任务 API
概述
Trae 任务 API 提供了强大的任务管理和执行系统,允许开发者定义、配置和运行各种类型的任务。任务系统支持构建脚本、测试运行、部署流程等自动化操作。
核心概念
任务定义
typescript
interface TaskDefinition {
readonly type: string;
readonly required?: string[];
readonly properties?: {
[property: string]: {
type: string;
description?: string;
default?: any;
enum?: any[];
};
};
}
interface Task {
readonly definition: TaskDefinition;
readonly scope: TaskScope;
readonly name?: string;
readonly source: string;
readonly execution?: TaskExecution;
readonly group?: TaskGroup;
readonly presentationOptions?: TaskPresentationOptions;
readonly problemMatchers?: string[];
readonly runOptions?: RunOptions;
readonly detail?: string;
}
enum TaskScope {
Global = 1,
Workspace = 2,
WorkspaceFolder = 3
}
interface TaskExecution {
// 基础执行接口
}
interface ShellExecution extends TaskExecution {
readonly commandLine?: string;
readonly command?: string | ShellQuotedString;
readonly args?: (string | ShellQuotedString)[];
readonly options?: ShellExecutionOptions;
}
interface ProcessExecution extends TaskExecution {
readonly process: string;
readonly args?: string[];
readonly options?: ProcessExecutionOptions;
}
interface CustomExecution extends TaskExecution {
readonly callback: (resolvedDefinition: TaskDefinition) => Thenable<Pseudoterminal>;
}任务组和呈现
typescript
interface TaskGroup {
readonly id: string;
readonly label?: string;
readonly isDefault?: boolean;
}
class TaskGroup {
static readonly Clean: TaskGroup;
static readonly Build: TaskGroup;
static readonly Rebuild: TaskGroup;
static readonly Test: TaskGroup;
}
interface TaskPresentationOptions {
readonly reveal?: TaskRevealKind;
readonly echo?: boolean;
readonly focus?: boolean;
readonly panel?: TaskPanelKind;
readonly showReuseMessage?: boolean;
readonly clear?: boolean;
readonly group?: string;
readonly close?: boolean;
}
enum TaskRevealKind {
Always = 1,
Silent = 2,
Never = 3
}
enum TaskPanelKind {
Shared = 1,
Dedicated = 2,
New = 3
}API 参考
任务管理
任务注册和执行
typescript
import { tasks, Task, TaskDefinition, ShellExecution } from '@trae/api';
// 注册任务提供者
const registerTaskProvider = (
type: string,
provider: TaskProvider
): Disposable => {
return tasks.registerTaskProvider(type, provider);
};
// 获取任务
const getTasks = async (filter?: TaskFilter): Promise<Task[]> => {
return await tasks.fetchTasks(filter);
};
// 执行任务
const executeTask = async (task: Task): Promise<TaskExecution> => {
return await tasks.executeTask(task);
};
// 终止任务
const terminateTask = async (execution: TaskExecution): Promise<void> => {
await tasks.terminateTask(execution);
};
// 获取活动任务
const getActiveTasks = (): TaskExecution[] => {
return tasks.taskExecutions;
};
// 监听任务事件
const onDidStartTask = (listener: (e: TaskStartEvent) => void): Disposable => {
return tasks.onDidStartTask(listener);
};
const onDidEndTask = (listener: (e: TaskEndEvent) => void): Disposable => {
return tasks.onDidEndTask(listener);
};
const onDidStartTaskProcess = (
listener: (e: TaskProcessStartEvent) => void
): Disposable => {
return tasks.onDidStartTaskProcess(listener);
};
const onDidEndTaskProcess = (
listener: (e: TaskProcessEndEvent) => void
): Disposable => {
return tasks.onDidEndTaskProcess(listener);
};任务提供者实现
typescript
interface TaskProvider {
provideTasks(token?: CancellationToken): ProviderResult<Task[]>;
resolveTask?(task: Task, token?: CancellationToken): ProviderResult<Task>;
}
class CustomTaskProvider implements TaskProvider {
private tasks: Task[] = [];
constructor() {
this.initializeTasks();
}
provideTasks(token?: CancellationToken): Task[] {
return this.tasks;
}
resolveTask(task: Task, token?: CancellationToken): Task | undefined {
// 解析任务的具体实现
const definition = task.definition;
if (definition.type === 'custom-build') {
return this.createBuildTask(definition);
}
if (definition.type === 'custom-test') {
return this.createTestTask(definition);
}
return undefined;
}
private initializeTasks(): void {
// 构建任务
this.tasks.push(this.createBuildTask({
type: 'custom-build',
target: 'production'
}));
// 测试任务
this.tasks.push(this.createTestTask({
type: 'custom-test',
suite: 'unit'
}));
// 清理任务
this.tasks.push(this.createCleanTask());
// 部署任务
this.tasks.push(this.createDeployTask());
}
private createBuildTask(definition: any): Task {
const execution = new ShellExecution(
'npm',
['run', 'build'],
{
cwd: workspace.rootPath,
env: {
NODE_ENV: definition.target || 'development'
}
}
);
const task = new Task(
definition,
TaskScope.Workspace,
'Build Project',
'custom-build',
execution,
['$tsc', '$eslint']
);
task.group = TaskGroup.Build;
task.presentationOptions = {
reveal: TaskRevealKind.Always,
echo: true,
focus: false,
panel: TaskPanelKind.Shared,
showReuseMessage: true,
clear: false
};
return task;
}
private createTestTask(definition: any): Task {
const args = ['test'];
if (definition.suite) {
args.push('--', '--grep', definition.suite);
}
const execution = new ShellExecution('npm', args, {
cwd: workspace.rootPath
});
const task = new Task(
definition,
TaskScope.Workspace,
`Run ${definition.suite || 'All'} Tests`,
'custom-test',
execution,
['$jest', '$mocha']
);
task.group = TaskGroup.Test;
task.presentationOptions = {
reveal: TaskRevealKind.Always,
echo: true,
focus: true,
panel: TaskPanelKind.Dedicated,
clear: true
};
return task;
}
private createCleanTask(): Task {
const execution = new ShellExecution('rm', ['-rf', 'dist', 'build'], {
cwd: workspace.rootPath
});
const task = new Task(
{ type: 'custom-clean' },
TaskScope.Workspace,
'Clean Build Artifacts',
'custom-clean',
execution
);
task.group = TaskGroup.Clean;
task.presentationOptions = {
reveal: TaskRevealKind.Silent,
echo: false
};
return task;
}
private createDeployTask(): Task {
const execution = new CustomExecution(async (definition) => {
return new DeploymentPseudoterminal(definition);
});
const task = new Task(
{ type: 'custom-deploy' },
TaskScope.Workspace,
'Deploy Application',
'custom-deploy',
execution
);
task.presentationOptions = {
reveal: TaskRevealKind.Always,
echo: true,
focus: true,
panel: TaskPanelKind.New
};
return task;
}
}自定义任务执行
伪终端实现
typescript
class DeploymentPseudoterminal implements Pseudoterminal {
private writeEmitter = new EventEmitter<string>();
private closeEmitter = new EventEmitter<number | void>();
onDidWrite: Event<string> = this.writeEmitter.event;
onDidClose: Event<number | void> = this.closeEmitter.event;
constructor(private definition: TaskDefinition) {}
open(initialDimensions: TerminalDimensions | undefined): void {
this.writeEmitter.fire('Starting deployment...\r\n');
this.deploy();
}
close(): void {
// 清理资源
}
handleInput(data: string): void {
// 处理用户输入
if (data === '\r') {
this.writeEmitter.fire('\r\n');
} else {
this.writeEmitter.fire(data);
}
}
setDimensions(dimensions: TerminalDimensions): void {
// 处理终端尺寸变化
}
private async deploy(): Promise<void> {
try {
// 步骤 1: 构建项目
this.writeEmitter.fire('Step 1: Building project...\r\n');
await this.runStep('npm run build', 'Build completed successfully');
// 步骤 2: 运行测试
this.writeEmitter.fire('Step 2: Running tests...\r\n');
await this.runStep('npm test', 'All tests passed');
// 步骤 3: 部署到服务器
this.writeEmitter.fire('Step 3: Deploying to server...\r\n');
await this.deployToServer();
this.writeEmitter.fire('\r\n✅ Deployment completed successfully!\r\n');
this.closeEmitter.fire(0);
} catch (error) {
this.writeEmitter.fire(`\r\n❌ Deployment failed: ${error.message}\r\n`);
this.closeEmitter.fire(1);
}
}
private async runStep(command: string, successMessage: string): Promise<void> {
return new Promise((resolve, reject) => {
const process = spawn(command, { shell: true });
process.stdout.on('data', (data) => {
this.writeEmitter.fire(data.toString());
});
process.stderr.on('data', (data) => {
this.writeEmitter.fire(data.toString());
});
process.on('close', (code) => {
if (code === 0) {
this.writeEmitter.fire(`${successMessage}\r\n`);
resolve();
} else {
reject(new Error(`Command failed with exit code ${code}`));
}
});
});
}
private async deployToServer(): Promise<void> {
// 模拟部署过程
const steps = [
'Connecting to server...',
'Uploading files...',
'Installing dependencies...',
'Restarting services...',
'Verifying deployment...'
];
for (const step of steps) {
this.writeEmitter.fire(`${step}\r\n`);
await new Promise(resolve => setTimeout(resolve, 1000));
}
}
}任务配置
tasks.json 配置
typescript
// .vscode/tasks.json 示例
{
"version": "2.0.0",
"tasks": [
{
"type": "shell",
"label": "Build Project",
"command": "npm",
"args": ["run", "build"],
"group": {
"kind": "build",
"isDefault": true
},
"presentation": {
"echo": true,
"reveal": "always",
"focus": false,
"panel": "shared",
"showReuseMessage": true,
"clear": false
},
"problemMatcher": ["$tsc", "$eslint"],
"options": {
"cwd": "${workspaceFolder}",
"env": {
"NODE_ENV": "production"
}
}
},
{
"type": "shell",
"label": "Run Tests",
"command": "npm",
"args": ["test"],
"group": "test",
"presentation": {
"echo": true,
"reveal": "always",
"focus": true,
"panel": "dedicated",
"clear": true
},
"problemMatcher": ["$jest"],
"runOptions": {
"runOn": "folderOpen"
}
},
{
"type": "process",
"label": "Watch Files",
"command": "node",
"args": ["scripts/watch.js"],
"isBackground": true,
"presentation": {
"reveal": "never"
},
"problemMatcher": {
"pattern": {
"regexp": "^(.*):(\\d+):(\\d+):\\s+(warning|error):\\s+(.*)$",
"file": 1,
"line": 2,
"column": 3,
"severity": 4,
"message": 5
},
"background": {
"activeOnStart": true,
"beginsPattern": "^\\[.*\\] Starting compilation",
"endsPattern": "^\\[.*\\] Compilation complete"
}
}
},
{
"type": "custom-deploy",
"label": "Deploy to Production",
"target": "production",
"options": {
"server": "prod.example.com",
"path": "/var/www/app"
},
"dependsOn": ["Build Project", "Run Tests"]
}
]
}
// 任务配置管理
class TaskConfigurationManager {
private configPath: string;
constructor(workspaceFolder: WorkspaceFolder) {
this.configPath = path.join(workspaceFolder.uri.fsPath, '.vscode', 'tasks.json');
}
async loadConfiguration(): Promise<TaskConfiguration> {
try {
const content = await workspace.fs.readFile(Uri.file(this.configPath));
return JSON.parse(content.toString());
} catch (error) {
return { version: '2.0.0', tasks: [] };
}
}
async saveConfiguration(config: TaskConfiguration): Promise<void> {
const content = JSON.stringify(config, null, 2);
await workspace.fs.writeFile(Uri.file(this.configPath), Buffer.from(content));
}
async addTask(task: TaskDefinitionConfig): Promise<void> {
const config = await this.loadConfiguration();
config.tasks.push(task);
await this.saveConfiguration(config);
}
async removeTask(label: string): Promise<void> {
const config = await this.loadConfiguration();
config.tasks = config.tasks.filter(task => task.label !== label);
await this.saveConfiguration(config);
}
async updateTask(label: string, updates: Partial<TaskDefinitionConfig>): Promise<void> {
const config = await this.loadConfiguration();
const taskIndex = config.tasks.findIndex(task => task.label === label);
if (taskIndex !== -1) {
config.tasks[taskIndex] = { ...config.tasks[taskIndex], ...updates };
await this.saveConfiguration(config);
}
}
}
interface TaskConfiguration {
version: string;
tasks: TaskDefinitionConfig[];
}
interface TaskDefinitionConfig {
type: string;
label: string;
command?: string;
args?: string[];
group?: string | { kind: string; isDefault?: boolean };
presentation?: TaskPresentationOptions;
problemMatcher?: string | string[];
options?: {
cwd?: string;
env?: Record<string, string>;
shell?: {
executable?: string;
args?: string[];
};
};
dependsOn?: string | string[];
runOptions?: {
runOn?: 'default' | 'folderOpen';
};
isBackground?: boolean;
[key: string]: any;
}问题匹配器
内置问题匹配器
typescript
// 常用问题匹配器
const problemMatchers = {
// TypeScript 编译器
'$tsc': {
owner: 'typescript',
fileLocation: 'relative',
pattern: {
regexp: '^([^\\s].*)\\((\\d+),(\\d+)\\):\\s+(error|warning|info)\\s+(TS\\d+)\\s*:\\s*(.*)$',
file: 1,
line: 2,
column: 3,
severity: 4,
code: 5,
message: 6
}
},
// ESLint
'$eslint-compact': {
owner: 'eslint',
fileLocation: 'relative',
pattern: {
regexp: '^(.+):\\s+line\\s+(\\d+),\\s+col\\s+(\\d+),\\s+(Error|Warning|Info)\\s+-\\s+(.+)\\s+\\((.+)\\)$',
file: 1,
line: 2,
column: 3,
severity: 4,
message: 5,
code: 6
}
},
// Jest 测试
'$jest': {
owner: 'jest',
fileLocation: 'relative',
pattern: [
{
regexp: '^\\s*FAIL\\s+(.*)$',
file: 1
},
{
regexp: '^\\s+●\\s+(.*)$',
message: 1
},
{
regexp: '^\\s+at\\s+.*\\s+\\((.*):(\\d+):(\\d+)\\)$',
file: 1,
line: 2,
column: 3,
loop: true
}
]
}
};
// 自定义问题匹配器
class CustomProblemMatcher {
static create(name: string, config: ProblemMatcherConfig): ProblemMatcher {
return {
name,
owner: config.owner,
fileLocation: config.fileLocation || 'relative',
pattern: config.pattern,
background: config.background,
watching: config.watching
};
}
static registerCustomMatchers(): void {
// 注册自定义构建工具的问题匹配器
const webpackMatcher = this.create('$webpack', {
owner: 'webpack',
fileLocation: 'relative',
pattern: {
regexp: '^ERROR in (.*)\\((\\d+),(\\d+)\\): (.*)$',
file: 1,
line: 2,
column: 3,
message: 4
}
});
// 注册 Sass 编译器问题匹配器
const sassMatcher = this.create('$sass', {
owner: 'sass',
fileLocation: 'relative',
pattern: {
regexp: '^Error: (.*)\\s+on line (\\d+) of (.*)$',
message: 1,
line: 2,
file: 3
}
});
}
}
interface ProblemMatcherConfig {
owner: string;
fileLocation?: 'absolute' | 'relative';
pattern: ProblemPattern | ProblemPattern[];
background?: BackgroundMatcher;
watching?: WatchingMatcher;
}
interface ProblemPattern {
regexp: string;
file?: number;
line?: number;
column?: number;
severity?: number;
message?: number;
code?: number;
loop?: boolean;
}
interface BackgroundMatcher {
activeOnStart?: boolean;
beginsPattern?: string;
endsPattern?: string;
}
interface WatchingMatcher {
activeOnStart?: boolean;
beginsPattern?: string;
endsPattern?: string;
}任务监控和管理
任务执行监控
typescript
class TaskMonitor {
private activeExecutions: Map<string, TaskExecutionInfo> = new Map();
private executionHistory: TaskExecutionInfo[] = [];
private disposables: Disposable[] = [];
constructor() {
this.setupEventListeners();
}
private setupEventListeners(): void {
this.disposables.push(
tasks.onDidStartTask(event => {
this.onTaskStarted(event);
}),
tasks.onDidEndTask(event => {
this.onTaskEnded(event);
}),
tasks.onDidStartTaskProcess(event => {
this.onTaskProcessStarted(event);
}),
tasks.onDidEndTaskProcess(event => {
this.onTaskProcessEnded(event);
})
);
}
private onTaskStarted(event: TaskStartEvent): void {
const info: TaskExecutionInfo = {
execution: event.execution,
task: event.execution.task,
startTime: Date.now(),
status: 'running',
processId: undefined,
exitCode: undefined
};
this.activeExecutions.set(this.getExecutionId(event.execution), info);
this.notifyTaskStarted(info);
}
private onTaskEnded(event: TaskEndEvent): void {
const executionId = this.getExecutionId(event.execution);
const info = this.activeExecutions.get(executionId);
if (info) {
info.endTime = Date.now();
info.duration = info.endTime - info.startTime;
info.status = 'completed';
this.activeExecutions.delete(executionId);
this.executionHistory.push(info);
// 保持历史记录在合理范围内
if (this.executionHistory.length > 100) {
this.executionHistory = this.executionHistory.slice(-50);
}
this.notifyTaskEnded(info);
}
}
private onTaskProcessStarted(event: TaskProcessStartEvent): void {
const executionId = this.getExecutionId(event.execution);
const info = this.activeExecutions.get(executionId);
if (info) {
info.processId = event.processId;
}
}
private onTaskProcessEnded(event: TaskProcessEndEvent): void {
const executionId = this.getExecutionId(event.execution);
const info = this.activeExecutions.get(executionId);
if (info) {
info.exitCode = event.exitCode;
}
}
private getExecutionId(execution: TaskExecution): string {
return `${execution.task.source}-${execution.task.name || execution.task.definition.type}`;
}
private notifyTaskStarted(info: TaskExecutionInfo): void {
window.showInformationMessage(
`Task started: ${info.task.name || info.task.definition.type}`,
'Show Terminal'
).then(action => {
if (action === 'Show Terminal') {
// 显示任务终端
}
});
}
private notifyTaskEnded(info: TaskExecutionInfo): void {
const duration = info.duration ? `(${info.duration}ms)` : '';
const message = `Task completed: ${info.task.name || info.task.definition.type} ${duration}`;
if (info.exitCode === 0) {
window.showInformationMessage(message);
} else {
window.showErrorMessage(`Task failed: ${info.task.name || info.task.definition.type}`);
}
}
getActiveExecutions(): TaskExecutionInfo[] {
return Array.from(this.activeExecutions.values());
}
getExecutionHistory(): TaskExecutionInfo[] {
return [...this.executionHistory];
}
getTaskStatistics(): TaskStatistics {
const total = this.executionHistory.length;
const successful = this.executionHistory.filter(info => info.exitCode === 0).length;
const failed = total - successful;
const durations = this.executionHistory
.filter(info => info.duration !== undefined)
.map(info => info.duration!);
const averageDuration = durations.length > 0
? durations.reduce((sum, duration) => sum + duration, 0) / durations.length
: 0;
return {
total,
successful,
failed,
averageDuration,
successRate: total > 0 ? (successful / total) * 100 : 0
};
}
dispose(): void {
this.disposables.forEach(d => d.dispose());
}
}
interface TaskExecutionInfo {
execution: TaskExecution;
task: Task;
startTime: number;
endTime?: number;
duration?: number;
status: 'running' | 'completed' | 'failed';
processId?: number;
exitCode?: number;
}
interface TaskStatistics {
total: number;
successful: number;
failed: number;
averageDuration: number;
successRate: number;
}任务模板和生成器
任务模板系统
typescript
class TaskTemplateManager {
private templates: Map<string, TaskTemplate> = new Map();
constructor() {
this.initializeBuiltinTemplates();
}
private initializeBuiltinTemplates(): void {
// Node.js 项目模板
this.registerTemplate('nodejs', {
name: 'Node.js Project',
description: 'Common tasks for Node.js projects',
tasks: [
{
type: 'shell',
label: 'npm: install',
command: 'npm',
args: ['install'],
group: 'build',
presentation: { reveal: 'always' }
},
{
type: 'shell',
label: 'npm: build',
command: 'npm',
args: ['run', 'build'],
group: { kind: 'build', isDefault: true },
problemMatcher: ['$tsc']
},
{
type: 'shell',
label: 'npm: test',
command: 'npm',
args: ['test'],
group: 'test',
problemMatcher: ['$jest']
},
{
type: 'shell',
label: 'npm: start',
command: 'npm',
args: ['start'],
isBackground: true,
problemMatcher: {
pattern: {
regexp: '^.*$'
},
background: {
activeOnStart: true,
beginsPattern: '^.*Server starting.*$',
endsPattern: '^.*Server started.*$'
}
}
}
]
});
// Python 项目模板
this.registerTemplate('python', {
name: 'Python Project',
description: 'Common tasks for Python projects',
tasks: [
{
type: 'shell',
label: 'pip: install requirements',
command: 'pip',
args: ['install', '-r', 'requirements.txt'],
group: 'build'
},
{
type: 'shell',
label: 'python: run tests',
command: 'python',
args: ['-m', 'pytest'],
group: 'test',
problemMatcher: {
pattern: {
regexp: '^(.*):(\\d+): (.*)$',
file: 1,
line: 2,
message: 3
}
}
},
{
type: 'shell',
label: 'python: lint',
command: 'flake8',
args: ['.'],
group: 'build',
problemMatcher: {
pattern: {
regexp: '^(.*):(\\d+):(\\d+): ([EW]\\d+) (.*)$',
file: 1,
line: 2,
column: 3,
code: 4,
message: 5
}
}
}
]
});
}
registerTemplate(id: string, template: TaskTemplate): void {
this.templates.set(id, template);
}
getTemplate(id: string): TaskTemplate | undefined {
return this.templates.get(id);
}
getAllTemplates(): TaskTemplate[] {
return Array.from(this.templates.values());
}
async generateTasksFromTemplate(
templateId: string,
workspaceFolder: WorkspaceFolder,
options: TemplateOptions = {}
): Promise<void> {
const template = this.getTemplate(templateId);
if (!template) {
throw new Error(`Template ${templateId} not found`);
}
const configManager = new TaskConfigurationManager(workspaceFolder);
const config = await configManager.loadConfiguration();
// 应用模板变量替换
const processedTasks = template.tasks.map(task =>
this.processTaskTemplate(task, options)
);
// 添加任务到配置
config.tasks.push(...processedTasks);
await configManager.saveConfiguration(config);
window.showInformationMessage(
`Generated ${processedTasks.length} tasks from ${template.name} template`
);
}
private processTaskTemplate(
task: TaskDefinitionConfig,
options: TemplateOptions
): TaskDefinitionConfig {
const processed = { ...task };
// 替换模板变量
if (typeof processed.command === 'string') {
processed.command = this.replaceVariables(processed.command, options);
}
if (processed.args) {
processed.args = processed.args.map(arg =>
this.replaceVariables(arg, options)
);
}
if (processed.label) {
processed.label = this.replaceVariables(processed.label, options);
}
return processed;
}
private replaceVariables(text: string, options: TemplateOptions): string {
let result = text;
// 替换内置变量
result = result.replace(/\${workspaceFolder}/g, '${workspaceFolder}');
result = result.replace(/\${workspaceFolderBasename}/g, '${workspaceFolderBasename}');
// 替换自定义变量
if (options.variables) {
for (const [key, value] of Object.entries(options.variables)) {
result = result.replace(new RegExp(`\\$\\{${key}\\}`, 'g'), value);
}
}
return result;
}
}
interface TaskTemplate {
name: string;
description: string;
tasks: TaskDefinitionConfig[];
variables?: TemplateVariable[];
}
interface TemplateVariable {
name: string;
description: string;
default?: string;
type: 'string' | 'boolean' | 'choice';
choices?: string[];
}
interface TemplateOptions {
variables?: Record<string, string>;
}最佳实践
任务组织
typescript
// 1. 任务分组和依赖
class TaskOrganizer {
static createBuildPipeline(): TaskDefinitionConfig[] {
return [
{
type: 'shell',
label: 'Clean',
command: 'rm',
args: ['-rf', 'dist'],
group: 'build',
presentation: { reveal: 'silent' }
},
{
type: 'shell',
label: 'Compile TypeScript',
command: 'tsc',
group: 'build',
dependsOn: 'Clean',
problemMatcher: '$tsc'
},
{
type: 'shell',
label: 'Bundle Assets',
command: 'webpack',
group: 'build',
dependsOn: 'Compile TypeScript',
problemMatcher: '$webpack'
},
{
type: 'shell',
label: 'Build All',
command: 'echo',
args: ['Build completed'],
group: { kind: 'build', isDefault: true },
dependsOn: ['Clean', 'Compile TypeScript', 'Bundle Assets'],
dependsOrder: 'sequence'
}
];
}
static createTestSuite(): TaskDefinitionConfig[] {
return [
{
type: 'shell',
label: 'Unit Tests',
command: 'npm',
args: ['run', 'test:unit'],
group: 'test',
problemMatcher: '$jest'
},
{
type: 'shell',
label: 'Integration Tests',
command: 'npm',
args: ['run', 'test:integration'],
group: 'test',
dependsOn: 'Unit Tests',
problemMatcher: '$jest'
},
{
type: 'shell',
label: 'E2E Tests',
command: 'npm',
args: ['run', 'test:e2e'],
group: 'test',
dependsOn: 'Integration Tests'
},
{
type: 'shell',
label: 'All Tests',
command: 'echo',
args: ['All tests completed'],
group: { kind: 'test', isDefault: true },
dependsOn: ['Unit Tests', 'Integration Tests', 'E2E Tests']
}
];
}
}
// 2. 环境特定任务
class EnvironmentTasks {
static createEnvironmentSpecificTasks(): TaskDefinitionConfig[] {
return [
{
type: 'shell',
label: 'Build (Development)',
command: 'npm',
args: ['run', 'build:dev'],
group: 'build',
options: {
env: {
NODE_ENV: 'development'
}
}
},
{
type: 'shell',
label: 'Build (Production)',
command: 'npm',
args: ['run', 'build:prod'],
group: 'build',
options: {
env: {
NODE_ENV: 'production'
}
}
},
{
type: 'shell',
label: 'Deploy (Staging)',
command: 'npm',
args: ['run', 'deploy:staging'],
dependsOn: 'Build (Development)'
},
{
type: 'shell',
label: 'Deploy (Production)',
command: 'npm',
args: ['run', 'deploy:prod'],
dependsOn: 'Build (Production)'
}
];
}
}错误处理和调试
typescript
// 任务错误处理
class TaskErrorHandler {
static setupErrorHandling(): void {
tasks.onDidEndTask(event => {
if (event.execution.task.group === TaskGroup.Build) {
this.handleBuildTaskEnd(event);
} else if (event.execution.task.group === TaskGroup.Test) {
this.handleTestTaskEnd(event);
}
});
}
private static handleBuildTaskEnd(event: TaskEndEvent): void {
// 检查构建任务的退出代码
tasks.onDidEndTaskProcess(processEvent => {
if (processEvent.execution === event.execution && processEvent.exitCode !== 0) {
window.showErrorMessage(
`Build failed: ${event.execution.task.name}`,
'Show Problems',
'Show Terminal'
).then(action => {
if (action === 'Show Problems') {
commands.executeCommand('workbench.panel.markers.view.focus');
} else if (action === 'Show Terminal') {
commands.executeCommand('workbench.panel.terminal.focus');
}
});
}
});
}
private static handleTestTaskEnd(event: TaskEndEvent): void {
// 处理测试任务结果
tasks.onDidEndTaskProcess(processEvent => {
if (processEvent.execution === event.execution) {
if (processEvent.exitCode === 0) {
window.showInformationMessage('All tests passed! ✅');
} else {
window.showErrorMessage(
'Some tests failed ❌',
'Show Test Results'
).then(action => {
if (action === 'Show Test Results') {
commands.executeCommand('workbench.view.testing.focus');
}
});
}
}
});
}
}相关 API
示例项目
查看 任务 API 示例 了解完整的实现示例。