diff --git a/package.json b/package.json index 9ab1500..b4fbd51 100644 --- a/package.json +++ b/package.json @@ -193,7 +193,7 @@ "category": "GitHub Local Actions", "command": "githubLocalActions.clearAll", "title": "Clear All", - "enablement": "!githubLocalActions:isRunning && !githubLocalActions:noWorkflows && workspaceFolderCount > 0", + "enablement": "!githubLocalActions:noHistory && !githubLocalActions:isRunning && !githubLocalActions:noWorkflows && workspaceFolderCount > 0", "icon": "$(clear-all)" }, { @@ -235,6 +235,36 @@ "command": "githubLocalActions.refreshSettings", "title": "Refresh", "icon": "$(refresh)" + }, + { + "category": "GitHub Local Actions", + "command": "githubLocalActions.editSecret", + "title": "Edit Secret", + "icon": "$(edit)" + }, + { + "category": "GitHub Local Actions", + "command": "githubLocalActions.editVariable", + "title": "Edit Variable", + "icon": "$(edit)" + }, + { + "category": "GitHub Local Actions", + "command": "githubLocalActions.editInput", + "title": "Edit Input", + "icon": "$(edit)" + }, + { + "category": "GitHub Local Actions", + "command": "githubLocalActions.addRunner", + "title": "Add Runner", + "icon": "$(add)" + }, + { + "category": "GitHub Local Actions", + "command": "githubLocalActions.editContainerEngine", + "title": "Edit Container Engine", + "icon": "$(edit)" } ], "menus": { @@ -306,6 +336,26 @@ { "command": "githubLocalActions.refreshSettings", "when": "never" + }, + { + "command": "githubLocalActions.editSecret", + "when": "never" + }, + { + "command": "githubLocalActions.editVariable", + "when": "never" + }, + { + "command": "githubLocalActions.editInput", + "when": "never" + }, + { + "command": "githubLocalActions.addRunner", + "when": "never" + }, + { + "command": "githubLocalActions.editContainerEngine", + "when": "never" } ], "view/title": [ @@ -395,6 +445,31 @@ "command": "githubLocalActions.remove", "when": "view == history && viewItem =~ /^githubLocalActions.history.*/", "group": "inline@3" + }, + { + "command": "githubLocalActions.editSecret", + "when": "view == settings && viewItem =~ /^githubLocalActions.secret(?!s).*/", + "group": "inline@0" + }, + { + "command": "githubLocalActions.editVariable", + "when": "view == settings && viewItem =~ /^githubLocalActions.variable(?!s).*/", + "group": "inline@0" + }, + { + "command": "githubLocalActions.editInput", + "when": "view == settings && viewItem =~ /^githubLocalActions.input(?!s).*/", + "group": "inline@0" + }, + { + "command": "githubLocalActions.addRunner", + "when": "view == settings && viewItem =~ /^githubLocalActions.runners.*/", + "group": "inline@0" + }, + { + "command": "githubLocalActions.editContainerEngine", + "when": "view == settings && viewItem =~ /^githubLocalActions.containerEngine(?!s).*/", + "group": "inline@0" } ] }, diff --git a/src/act.ts b/src/act.ts index a642429..99fbdd9 100644 --- a/src/act.ts +++ b/src/act.ts @@ -1,8 +1,9 @@ import * as child_process from 'child_process'; import * as path from "path"; -import { commands, CustomExecution, env, EventEmitter, ExtensionContext, Pseudoterminal, ShellExecution, TaskDefinition, TaskExecution, TaskGroup, TaskPanelKind, TaskRevealKind, tasks, TaskScope, TerminalDimensions, window, workspace, WorkspaceFolder } from "vscode"; +import { commands, CustomExecution, env, EventEmitter, ExtensionContext, Pseudoterminal, ShellExecution, TaskDefinition, TaskGroup, TaskPanelKind, TaskRevealKind, tasks, TaskScope, TerminalDimensions, window, workspace, WorkspaceFolder } from "vscode"; import { ComponentsManager } from "./componentsManager"; import { historyTreeDataProvider } from './extension'; +import { HistoryManager, HistoryStatus } from './historyManager'; import { SettingsManager } from './settingsManager'; import { StorageKey, StorageManager } from './storageManager'; import { Workflow, WorkflowsManager } from "./workflowsManager"; @@ -50,26 +51,6 @@ export enum Option { Json = "--json" } -export interface History { - index: number, - name: string, - status: HistoryStatus, - date?: { - start: string, - end: string, - } - output?: string, - taskExecution?: TaskExecution, - commandArgs: CommandArgs -} - -export enum HistoryStatus { - Running = 'Running', - Success = 'Success', - Failed = 'Failed', - Cancelled = 'Cancelled' -} - export interface CommandArgs { workspaceFolder: WorkspaceFolder, options: string, @@ -79,31 +60,20 @@ export interface CommandArgs { export class Act { private static base: string = 'act'; + storageManager: StorageManager; componentsManager: ComponentsManager; workflowsManager: WorkflowsManager; + historyManager: HistoryManager; settingsManager: SettingsManager; - storageManager: StorageManager; - workspaceHistory: { [path: string]: History[] }; installationCommands: { [packageManager: string]: string }; prebuiltExecutables: { [architecture: string]: string }; constructor(context: ExtensionContext) { + this.storageManager = new StorageManager(context); this.componentsManager = new ComponentsManager(); this.workflowsManager = new WorkflowsManager(); + this.historyManager = new HistoryManager(this.storageManager); this.settingsManager = new SettingsManager(); - this.storageManager = new StorageManager(context); - - const workspaceHistory = this.storageManager.get<{ [path: string]: History[] }>(StorageKey.WorkspaceHistory) || {}; - for (const [path, historyLogs] of Object.entries(workspaceHistory)) { - workspaceHistory[path] = historyLogs.map(history => { - if (history.status === HistoryStatus.Running) { - history.status = HistoryStatus.Cancelled; - } - - return history; - }); - } - this.workspaceHistory = workspaceHistory; switch (process.platform) { case 'win32': @@ -200,22 +170,13 @@ export class Act { return; } - if (!this.workspaceHistory[commandArgs.workspaceFolder.uri.fsPath]) { - this.workspaceHistory[commandArgs.workspaceFolder.uri.fsPath] = []; - this.storageManager.update(StorageKey.WorkspaceHistory, this.workspaceHistory); + if (!this.historyManager.workspaceHistory[commandArgs.workspaceFolder.uri.fsPath]) { + this.historyManager.workspaceHistory[commandArgs.workspaceFolder.uri.fsPath] = []; + this.storageManager.update(StorageKey.WorkspaceHistory, this.historyManager.workspaceHistory); } - const historyIndex = this.workspaceHistory[commandArgs.workspaceFolder.uri.fsPath].length; - this.workspaceHistory[commandArgs.workspaceFolder.uri.fsPath].unshift({ - index: historyIndex, - name: `${commandArgs.name} #${this.workspaceHistory[commandArgs.workspaceFolder.uri.fsPath].length + 1}`, - status: HistoryStatus.Running, - commandArgs: commandArgs - }); - historyTreeDataProvider.refresh(); - this.storageManager.update(StorageKey.WorkspaceHistory, this.workspaceHistory); - - this.workspaceHistory[commandArgs.workspaceFolder.uri.fsPath][historyIndex].taskExecution = await tasks.executeTask({ + const historyIndex = this.historyManager.workspaceHistory[commandArgs.workspaceFolder.uri.fsPath].length; + const taskExecution = await tasks.executeTask({ name: commandArgs.name, detail: 'Run workflow', definition: { type: 'GitHub Local Actions' }, @@ -239,46 +200,66 @@ export class Act { const closeEmitter = new EventEmitter(); writeEmitter.event(data => { - if (!this.workspaceHistory[commandArgs.workspaceFolder.uri.fsPath][historyIndex].output) { - this.workspaceHistory[commandArgs.workspaceFolder.uri.fsPath][historyIndex].output = data; + if (!this.historyManager.workspaceHistory[commandArgs.workspaceFolder.uri.fsPath][historyIndex].output) { + this.historyManager.workspaceHistory[commandArgs.workspaceFolder.uri.fsPath][historyIndex].output = data; } else { - this.workspaceHistory[commandArgs.workspaceFolder.uri.fsPath][historyIndex].output += data; + this.historyManager.workspaceHistory[commandArgs.workspaceFolder.uri.fsPath][historyIndex].output += data; } - this.storageManager.update(StorageKey.WorkspaceHistory, this.workspaceHistory); + this.storageManager.update(StorageKey.WorkspaceHistory, this.historyManager.workspaceHistory); }); const exec = child_process.spawn(command, { cwd: commandArgs.workspaceFolder.uri.fsPath, shell: env.shell }); const setDate = (actDate?: string) => { const date = actDate ? new Date(actDate).toString() : new Date().toString(); - if (!this.workspaceHistory[commandArgs.workspaceFolder.uri.fsPath][historyIndex].date) { - this.workspaceHistory[commandArgs.workspaceFolder.uri.fsPath][historyIndex].date = { + if (!this.historyManager.workspaceHistory[commandArgs.workspaceFolder.uri.fsPath][historyIndex].date) { + this.historyManager.workspaceHistory[commandArgs.workspaceFolder.uri.fsPath][historyIndex].date = { start: date, end: date, } } else { - this.workspaceHistory[commandArgs.workspaceFolder.uri.fsPath][historyIndex].date!.end = date; + this.historyManager.workspaceHistory[commandArgs.workspaceFolder.uri.fsPath][historyIndex].date!.end = date; } } const handleIO = (data: any) => { + if (typeof this.historyManager.workspaceHistory[commandArgs.workspaceFolder.uri.fsPath][historyIndex] === 'undefined') { + this.historyManager.workspaceHistory[commandArgs.workspaceFolder.uri.fsPath].push({ + index: historyIndex, + name: `${commandArgs.name} #${this.historyManager.workspaceHistory[commandArgs.workspaceFolder.uri.fsPath].length + 1}`, + status: HistoryStatus.Running, + taskExecution: taskExecution, + commandArgs: commandArgs + }); + historyTreeDataProvider.refresh(); + this.storageManager.update(StorageKey.WorkspaceHistory, this.historyManager.workspaceHistory); + } + const lines: string[] = data.toString().split('\n').filter((line: string) => line != ''); for (const line of lines) { - const jsonLine = JSON.parse(line); + let jsonLine: any; + try { + jsonLine = JSON.parse(line); + } catch (error) { + jsonLine = { + time: new Date().toString(), + msg: line + } + } setDate(jsonLine.time); if (jsonLine.jobResult) { switch (jsonLine.jobResult) { case 'success': - this.workspaceHistory[commandArgs.workspaceFolder.uri.fsPath][historyIndex].status = HistoryStatus.Success; + this.historyManager.workspaceHistory[commandArgs.workspaceFolder.uri.fsPath][historyIndex].status = HistoryStatus.Success; break; case 'failure': - this.workspaceHistory[commandArgs.workspaceFolder.uri.fsPath][historyIndex].status = HistoryStatus.Failed; + this.historyManager.workspaceHistory[commandArgs.workspaceFolder.uri.fsPath][historyIndex].status = HistoryStatus.Failed; break; } } historyTreeDataProvider.refresh(); - this.storageManager.update(StorageKey.WorkspaceHistory, this.workspaceHistory); + this.storageManager.update(StorageKey.WorkspaceHistory, this.historyManager.workspaceHistory); writeEmitter.fire(`${jsonLine.msg.trimEnd()}\r\n`); } } @@ -287,12 +268,12 @@ export class Act { exec.on('close', (code) => { setDate(); - if (this.workspaceHistory[commandArgs.workspaceFolder.uri.fsPath][historyIndex].status === HistoryStatus.Running) { - this.workspaceHistory[commandArgs.workspaceFolder.uri.fsPath][historyIndex].status = HistoryStatus.Failed; + if (this.historyManager.workspaceHistory[commandArgs.workspaceFolder.uri.fsPath][historyIndex].status === HistoryStatus.Running) { + this.historyManager.workspaceHistory[commandArgs.workspaceFolder.uri.fsPath][historyIndex].status = HistoryStatus.Failed; } historyTreeDataProvider.refresh(); - this.storageManager.update(StorageKey.WorkspaceHistory, this.workspaceHistory); + this.storageManager.update(StorageKey.WorkspaceHistory, this.historyManager.workspaceHistory); closeEmitter.fire(code || 0); }); @@ -313,12 +294,12 @@ export class Act { }, close: () => { - if (this.workspaceHistory[commandArgs.workspaceFolder.uri.fsPath][historyIndex].status === HistoryStatus.Running) { - this.workspaceHistory[commandArgs.workspaceFolder.uri.fsPath][historyIndex].status = HistoryStatus.Cancelled; + if (this.historyManager.workspaceHistory[commandArgs.workspaceFolder.uri.fsPath][historyIndex].status === HistoryStatus.Running) { + this.historyManager.workspaceHistory[commandArgs.workspaceFolder.uri.fsPath][historyIndex].status = HistoryStatus.Cancelled; } historyTreeDataProvider.refresh(); - this.storageManager.update(StorageKey.WorkspaceHistory, this.workspaceHistory); + this.storageManager.update(StorageKey.WorkspaceHistory, this.historyManager.workspaceHistory); exec.stdout.destroy(); exec.stdin.destroy(); @@ -328,7 +309,7 @@ export class Act { }; }) }); - this.storageManager.update(StorageKey.WorkspaceHistory, this.workspaceHistory); + this.storageManager.update(StorageKey.WorkspaceHistory, this.historyManager.workspaceHistory); } async install(packageManager: string) { @@ -357,34 +338,4 @@ export class Act { }); } } - - async clearAll() { - //TODO: Fix for multi workspace support - const workspaceFolders = workspace.workspaceFolders; - if (workspaceFolders && workspaceFolders.length > 0) { - for (const workspaceFolder of workspaceFolders) { - this.workspaceHistory[workspaceFolder.uri.fsPath] = []; - historyTreeDataProvider.refresh(); - this.storageManager.update(StorageKey.WorkspaceHistory, this.workspaceHistory); - } - } - } - - async viewOutput(history: History) { - await workspace.openTextDocument({ content: history.output }).then(async document => { - await window.showTextDocument(document); - }) - } - - async stop(history: History) { - history.taskExecution?.terminate(); - historyTreeDataProvider.refresh(); - } - - async remove(history: History) { - const historyIndex = this.workspaceHistory[history.commandArgs.workspaceFolder.uri.fsPath].findIndex(workspaceHistory => workspaceHistory.index === history.index) - this.workspaceHistory[history.commandArgs.workspaceFolder.uri.fsPath].splice(historyIndex, 1); - historyTreeDataProvider.refresh(); - this.storageManager.update(StorageKey.WorkspaceHistory, this.workspaceHistory); - } } \ No newline at end of file diff --git a/src/historyManager.ts b/src/historyManager.ts new file mode 100644 index 0000000..5437b61 --- /dev/null +++ b/src/historyManager.ts @@ -0,0 +1,76 @@ +import { TaskExecution, window, workspace } from "vscode"; +import { CommandArgs } from "./act"; +import { act, historyTreeDataProvider } from "./extension"; +import { StorageKey, StorageManager } from "./storageManager"; + +export interface History { + index: number, + name: string, + status: HistoryStatus, + date?: { + start: string, + end: string, + } + output?: string, + taskExecution?: TaskExecution, + commandArgs: CommandArgs +} + +export enum HistoryStatus { + Running = 'Running', + Success = 'Success', + Failed = 'Failed', + Cancelled = 'Cancelled' +} + +export class HistoryManager { + storageManager: StorageManager; + workspaceHistory: { [path: string]: History[] }; + + constructor(storageManager: StorageManager) { + this.storageManager = storageManager; + const workspaceHistory = this.storageManager.get<{ [path: string]: History[] }>(StorageKey.WorkspaceHistory) || {}; + for (const [path, historyLogs] of Object.entries(workspaceHistory)) { + workspaceHistory[path] = historyLogs.map(history => { + if (history.status === HistoryStatus.Running) { + history.status = HistoryStatus.Cancelled; + } + + return history; + }); + } + this.workspaceHistory = workspaceHistory; + } + + async clearAll() { + //TODO: Fix for multi workspace support + const workspaceFolders = workspace.workspaceFolders; + if (workspaceFolders && workspaceFolders.length > 0) { + for (const workspaceFolder of workspaceFolders) { + this.workspaceHistory[workspaceFolder.uri.fsPath] = []; + historyTreeDataProvider.refresh(); + this.storageManager.update(StorageKey.WorkspaceHistory, this.workspaceHistory); + } + } + } + + async viewOutput(history: History) { + await workspace.openTextDocument({ content: history.output }).then(async document => { + await window.showTextDocument(document); + }) + } + + async restart(history: History) { + await act.runCommand(history.commandArgs); + } + + async stop(history: History) { + history.taskExecution?.terminate(); + } + + async remove(history: History) { + const historyIndex = this.workspaceHistory[history.commandArgs.workspaceFolder.uri.fsPath].findIndex(workspaceHistory => workspaceHistory.index === history.index) + this.workspaceHistory[history.commandArgs.workspaceFolder.uri.fsPath].splice(historyIndex, 1); + this.storageManager.update(StorageKey.WorkspaceHistory, this.workspaceHistory); + } +} \ No newline at end of file diff --git a/src/settingsManager.ts b/src/settingsManager.ts index b42cd98..8fe3487 100644 --- a/src/settingsManager.ts +++ b/src/settingsManager.ts @@ -1,25 +1,77 @@ +import { WorkspaceFolder } from "vscode"; import { Workflow } from "./workflowsManager"; +export interface Settings { + environments: Environment[], + secrets: Secret[], + variables: Variable[], + inputs: Input[], + runners: Runner[], + containerEngines: ContainerEngine[] +} + export interface Environment { name: string } export interface Secret { key: string, - value?: string + value: string, + selected: boolean } export interface Variable { key: string, - value?: string + value: string, + selected: boolean } export interface Input { key: string, - value?: string + value: string, + selected: boolean +} + +export interface Runner { + key: string, + value: string, + selected: boolean +} + +export interface ContainerEngine { + key: string, + value: string, + selected: boolean } export class SettingsManager { + settings: { [path: string]: Settings } + + constructor() { + this.settings = {}; + } + + getSettings(workspaceFolder: WorkspaceFolder) { + if (!this.settings[workspaceFolder.uri.fsPath]) { + this.settings[workspaceFolder.uri.fsPath] = { + environments: [], + secrets: [], + variables: [], + inputs: [], + runners: [], + containerEngines: [ + { + key: 'DOCKER_HOST', + value: '', + selected: false + } + ] + } + } + + return this.settings[workspaceFolder.uri.fsPath]; + } + getEnvironments(workflow: Workflow): Environment[] { const environments: Environment[] = []; if (!workflow.yaml) { @@ -67,12 +119,32 @@ export class SettingsManager { return this.findInWorkflow(workflow.fileContent, /\${{\s*(?:inputs|github\.event\.inputs)\.(.*?)(?:\s*==\s*(.*?))?\s*}}/g); } + editSecret(workspaceFolder: WorkspaceFolder, secret: Secret, newValue: string) { + + } + + editVariable(workspaceFolder: WorkspaceFolder, variable: Variable, newValue: string) { + + } + + editInput(workspaceFolder: WorkspaceFolder, input: Input, newValue: string) { + + } + + addRunner(workspaceFolder: WorkspaceFolder, runner: Runner) { + + } + + editContainerEngine(workspaceFolder: WorkspaceFolder, containerEngine: ContainerEngine, newValue: string) { + + } + private findInWorkflow(content: string, regExp: RegExp) { const results: (Secret | Variable | Input)[] = []; const matches = content.matchAll(regExp); for (const match of matches) { - results.push({ key: match[1] }); + results.push({ key: match[1], value: '', selected: false }); } return results; diff --git a/src/views/githubLocalActionsTreeItem.ts b/src/views/githubLocalActionsTreeItem.ts index 7837b85..40644b1 100644 --- a/src/views/githubLocalActionsTreeItem.ts +++ b/src/views/githubLocalActionsTreeItem.ts @@ -1,6 +1,8 @@ -import { MarkdownString, TreeItem } from "vscode"; +import { MarkdownString, TreeItem, WorkspaceFolder } from "vscode"; export interface GithubLocalActionsTreeItem extends TreeItem { + workspaceFolder?: WorkspaceFolder; + getChildren: () => GithubLocalActionsTreeItem[] | Promise; getToolTip?: () => Promise; diff --git a/src/views/history/history.ts b/src/views/history/history.ts index 7bacc8d..fa514b1 100644 --- a/src/views/history/history.ts +++ b/src/views/history/history.ts @@ -1,13 +1,13 @@ -import { ThemeColor, ThemeIcon, TreeItem, TreeItemCollapsibleState } from "vscode"; -import { History, HistoryStatus } from "../../act"; +import { ThemeColor, ThemeIcon, TreeItem, TreeItemCollapsibleState, WorkspaceFolder } from "vscode"; import { DateUtils } from "../../dateUtils"; +import { History, HistoryStatus } from "../../historyManager"; import { GithubLocalActionsTreeItem } from "../githubLocalActionsTreeItem"; export default class HistoryTreeItem extends TreeItem implements GithubLocalActionsTreeItem { static contextValue = 'githubLocalActions.history'; history: History; - constructor(history: History) { + constructor(public workspaceFolder: WorkspaceFolder, history: History) { super(history.name, TreeItemCollapsibleState.None); this.history = history; diff --git a/src/views/history/historyTreeDataProvider.ts b/src/views/history/historyTreeDataProvider.ts index 5ab5fdd..3193fab 100644 --- a/src/views/history/historyTreeDataProvider.ts +++ b/src/views/history/historyTreeDataProvider.ts @@ -1,8 +1,9 @@ import { CancellationToken, commands, EventEmitter, ExtensionContext, extensions, TreeDataProvider, TreeItem, workspace } from "vscode"; -import { HistoryStatus } from "../../act"; import { act } from "../../extension"; +import { HistoryStatus } from "../../historyManager"; import { GithubLocalActionsTreeItem } from "../githubLocalActionsTreeItem"; import HistoryTreeItem from "./history"; +import WorkspaceFolderHistoryTreeItem from "./workspaceFolderHistory"; export default class HistoryTreeDataProvider implements TreeDataProvider { private _onDidChangeTreeData = new EventEmitter(); @@ -16,22 +17,24 @@ export default class HistoryTreeDataProvider implements TreeDataProvider { - await act.clearAll(); + await act.historyManager.clearAll(); }), commands.registerCommand('githubLocalActions.refreshHistory', async () => { this.refresh(); }), commands.registerCommand('githubLocalActions.viewOutput', async (historyTreeItem: HistoryTreeItem) => { - await act.viewOutput(historyTreeItem.history); + await act.historyManager.viewOutput(historyTreeItem.history); }), commands.registerCommand('githubLocalActions.restart', async (historyTreeItem: HistoryTreeItem) => { - await act.runCommand(historyTreeItem.history.commandArgs); + await act.historyManager.restart(historyTreeItem.history); }), commands.registerCommand('githubLocalActions.stop', async (historyTreeItem: HistoryTreeItem) => { - await act.stop(historyTreeItem.history); + await act.historyManager.stop(historyTreeItem.history); + this.refresh(); }), commands.registerCommand('githubLocalActions.remove', async (historyTreeItem: HistoryTreeItem) => { - await act.remove(historyTreeItem.history); + await act.historyManager.remove(historyTreeItem.history); + this.refresh(); }) ); } @@ -57,25 +60,24 @@ export default class HistoryTreeDataProvider implements TreeDataProvider 0) { - //TODO: Fix for multi workspace support - const workspaceHistory = act.workspaceHistory[workspaceFolders[0].uri.fsPath]; - if (workspaceHistory) { - for (const history of workspaceHistory) { - items.push(new HistoryTreeItem(history)); + if (workspaceFolders) { + for (const workspaceFolder of workspaceFolders) { + items.push(new WorkspaceFolderHistoryTreeItem(workspaceFolder)); - if (history.status === HistoryStatus.Running) { - isRunning = true; - } + const workspaceHistory = act.historyManager.workspaceHistory[workspaceFolders[0].uri.fsPath]; + if (workspaceHistory.length > 0) { + isRunning = act.historyManager.workspaceHistory[workspaceFolders[0].uri.fsPath].find(workspaceHistory => workspaceHistory.status === HistoryStatus.Running) !== undefined; + noHistory = false; } } } await commands.executeCommand('setContext', 'githubLocalActions:isRunning', isRunning); - await commands.executeCommand('setContext', 'githubLocalActions:noHistory', items.length == 0); + await commands.executeCommand('setContext', 'githubLocalActions:noHistory', noHistory); return items; } } diff --git a/src/views/history/workspaceFolderHistory.ts b/src/views/history/workspaceFolderHistory.ts new file mode 100644 index 0000000..df61031 --- /dev/null +++ b/src/views/history/workspaceFolderHistory.ts @@ -0,0 +1,26 @@ +import { ThemeIcon, TreeItem, TreeItemCollapsibleState, WorkspaceFolder } from "vscode"; +import { act } from "../../extension"; +import { GithubLocalActionsTreeItem } from "../githubLocalActionsTreeItem"; +import HistoryTreeItem from "./history"; + +export default class WorkspaceFolderHistoryTreeItem extends TreeItem implements GithubLocalActionsTreeItem { + static contextValue = 'githubLocalActions.workspaceFolderHistory'; + + constructor(public workspaceFolder: WorkspaceFolder) { + super(workspaceFolder.name, TreeItemCollapsibleState.Collapsed); + this.contextValue = WorkspaceFolderHistoryTreeItem.contextValue; + this.iconPath = new ThemeIcon('folder'); + } + + async getChildren(): Promise { + const items: GithubLocalActionsTreeItem[] = []; + + const workspaceHistory = act.historyManager.workspaceHistory[this.workspaceFolder.uri.fsPath]; + if (workspaceHistory) { + for (const history of workspaceHistory.slice().reverse()) { + items.push(new HistoryTreeItem(this.workspaceFolder, history)); + } + } + return items; + } +} \ No newline at end of file diff --git a/src/views/settings/containerEngine.ts b/src/views/settings/containerEngine.ts new file mode 100644 index 0000000..64ca3ba --- /dev/null +++ b/src/views/settings/containerEngine.ts @@ -0,0 +1,18 @@ +import { ThemeIcon, TreeItem, TreeItemCollapsibleState, WorkspaceFolder } from "vscode"; +import { ContainerEngine } from "../../settingsManager"; +import { GithubLocalActionsTreeItem } from "../githubLocalActionsTreeItem"; + +export default class ContainerEngineTreeItem extends TreeItem implements GithubLocalActionsTreeItem { + static contextValue = 'githubLocalActions.containerEngine'; + + constructor(public workspaceFolder: WorkspaceFolder, containerEngine: ContainerEngine) { + super(containerEngine.key, TreeItemCollapsibleState.None); + this.description = containerEngine.value; + this.contextValue = ContainerEngineTreeItem.contextValue; + this.iconPath = new ThemeIcon('code'); + } + + async getChildren(): Promise { + return []; + } +} \ No newline at end of file diff --git a/src/views/settings/containerEngines.ts b/src/views/settings/containerEngines.ts index 4b2c019..fcd9985 100644 --- a/src/views/settings/containerEngines.ts +++ b/src/views/settings/containerEngines.ts @@ -1,16 +1,25 @@ -import { ThemeIcon, TreeItem, TreeItemCollapsibleState } from "vscode"; +import { ThemeIcon, TreeItem, TreeItemCollapsibleState, WorkspaceFolder } from "vscode"; +import { act } from "../../extension"; import { GithubLocalActionsTreeItem } from "../githubLocalActionsTreeItem"; +import ContainerEngineTreeItem from "./containerEngine"; export default class ContainerEnginesTreeItem extends TreeItem implements GithubLocalActionsTreeItem { static contextValue = 'githubLocalActions.containerEngines'; - constructor() { + constructor(public workspaceFolder: WorkspaceFolder) { super('Container Engines', TreeItemCollapsibleState.Collapsed); this.contextValue = ContainerEnginesTreeItem.contextValue; this.iconPath = new ThemeIcon('server-process'); } async getChildren(): Promise { - return []; + const items: GithubLocalActionsTreeItem[] = []; + + const containerEngines = act.settingsManager.getSettings(this.workspaceFolder).containerEngines; + for (const containerEngine of containerEngines) { + items.push(new ContainerEngineTreeItem(this.workspaceFolder, containerEngine)); + } + + return items; } } \ No newline at end of file diff --git a/src/views/settings/environment.ts b/src/views/settings/environment.ts index c08f005..1fa654b 100644 --- a/src/views/settings/environment.ts +++ b/src/views/settings/environment.ts @@ -1,11 +1,11 @@ -import { ThemeIcon, TreeItem, TreeItemCollapsibleState } from "vscode"; +import { ThemeIcon, TreeItem, TreeItemCollapsibleState, WorkspaceFolder } from "vscode"; import { Environment } from "../../settingsManager"; import { GithubLocalActionsTreeItem } from "../githubLocalActionsTreeItem"; export default class EnvironmentTreeItem extends TreeItem implements GithubLocalActionsTreeItem { static contextValue = 'githubLocalActions.environment'; - constructor(environment: Environment) { + constructor(public workspaceFolder: WorkspaceFolder, environment: Environment) { super(environment.name, TreeItemCollapsibleState.None); this.contextValue = EnvironmentTreeItem.contextValue; this.iconPath = new ThemeIcon('server'); diff --git a/src/views/settings/environments.ts b/src/views/settings/environments.ts index 0e4b5a8..361873e 100644 --- a/src/views/settings/environments.ts +++ b/src/views/settings/environments.ts @@ -1,4 +1,4 @@ -import { ThemeIcon, TreeItem, TreeItemCollapsibleState } from "vscode"; +import { ThemeIcon, TreeItem, TreeItemCollapsibleState, WorkspaceFolder } from "vscode"; import { act } from "../../extension"; import { GithubLocalActionsTreeItem } from "../githubLocalActionsTreeItem"; import EnvironmentTreeItem from "./environment"; @@ -6,15 +6,15 @@ import EnvironmentTreeItem from "./environment"; export default class EnvironmentsTreeItem extends TreeItem implements GithubLocalActionsTreeItem { static contextValue = 'githubLocalActions.environments'; - constructor() { + constructor(public workspaceFolder: WorkspaceFolder) { super('Environments', TreeItemCollapsibleState.Collapsed); this.contextValue = EnvironmentsTreeItem.contextValue; this.iconPath = new ThemeIcon('server-environment'); } async getChildren(): Promise { - const workflows = await act.workflowsManager.getWorkflows(); + const workflows = await act.workflowsManager.getWorkflows(this.workspaceFolder); const environments = [...new Set(workflows.map(workflow => act.settingsManager.getEnvironments(workflow)).flat())]; - return environments.map(environment => new EnvironmentTreeItem(environment)); + return environments.map(environment => new EnvironmentTreeItem(this.workspaceFolder, environment)); } } \ No newline at end of file diff --git a/src/views/settings/input.ts b/src/views/settings/input.ts index 82a78aa..99d9d5b 100644 --- a/src/views/settings/input.ts +++ b/src/views/settings/input.ts @@ -1,11 +1,11 @@ -import { ThemeIcon, TreeItem, TreeItemCheckboxState, TreeItemCollapsibleState } from "vscode"; +import { ThemeIcon, TreeItem, TreeItemCheckboxState, TreeItemCollapsibleState, WorkspaceFolder } from "vscode"; import { Input } from "../../settingsManager"; import { GithubLocalActionsTreeItem } from "../githubLocalActionsTreeItem"; export default class InputTreeItem extends TreeItem implements GithubLocalActionsTreeItem { static contextValue = 'githubLocalActions.input'; - constructor(input: Input) { + constructor(public workspaceFolder: WorkspaceFolder, input: Input) { super(input.key, TreeItemCollapsibleState.None); this.description = input.value; this.contextValue = InputTreeItem.contextValue; diff --git a/src/views/settings/inputs.ts b/src/views/settings/inputs.ts index aee4011..3666f90 100644 --- a/src/views/settings/inputs.ts +++ b/src/views/settings/inputs.ts @@ -1,4 +1,4 @@ -import { ThemeIcon, TreeItem, TreeItemCollapsibleState } from "vscode"; +import { ThemeIcon, TreeItem, TreeItemCollapsibleState, WorkspaceFolder } from "vscode"; import { act } from "../../extension"; import { GithubLocalActionsTreeItem } from "../githubLocalActionsTreeItem"; import InputTreeItem from "./input"; @@ -6,15 +6,15 @@ import InputTreeItem from "./input"; export default class InputsTreeItem extends TreeItem implements GithubLocalActionsTreeItem { static contextValue = 'githubLocalActions.inputs'; - constructor() { + constructor(public workspaceFolder: WorkspaceFolder) { super('Inputs', TreeItemCollapsibleState.Collapsed); this.contextValue = InputsTreeItem.contextValue; this.iconPath = new ThemeIcon('record-keys'); } async getChildren(): Promise { - const workflows = await act.workflowsManager.getWorkflows(); + const workflows = await act.workflowsManager.getWorkflows(this.workspaceFolder); const inputs = [...new Set(workflows.map(workflow => act.settingsManager.getInputs(workflow)).flat())]; - return inputs.map(input => new InputTreeItem(input)); + return inputs.map(input => new InputTreeItem(this.workspaceFolder, input)); } } \ No newline at end of file diff --git a/src/views/settings/runners.ts b/src/views/settings/runners.ts index 328e74e..4b71906 100644 --- a/src/views/settings/runners.ts +++ b/src/views/settings/runners.ts @@ -1,10 +1,10 @@ -import { ThemeIcon, TreeItem, TreeItemCollapsibleState } from "vscode"; +import { ThemeIcon, TreeItem, TreeItemCollapsibleState, WorkspaceFolder } from "vscode"; import { GithubLocalActionsTreeItem } from "../githubLocalActionsTreeItem"; export default class RunnersTreeItem extends TreeItem implements GithubLocalActionsTreeItem { static contextValue = 'githubLocalActions.runners'; - constructor() { + constructor(public workspaceFolder: WorkspaceFolder) { super('Runners', TreeItemCollapsibleState.Collapsed); this.contextValue = RunnersTreeItem.contextValue; this.iconPath = new ThemeIcon('database'); diff --git a/src/views/settings/secret.ts b/src/views/settings/secret.ts index dea62fc..85bd83b 100644 --- a/src/views/settings/secret.ts +++ b/src/views/settings/secret.ts @@ -1,15 +1,13 @@ -import { ThemeIcon, TreeItem, TreeItemCheckboxState, TreeItemCollapsibleState } from "vscode"; +import { ThemeIcon, TreeItem, TreeItemCheckboxState, TreeItemCollapsibleState, WorkspaceFolder } from "vscode"; import { Secret } from "../../settingsManager"; import { GithubLocalActionsTreeItem } from "../githubLocalActionsTreeItem"; export default class SecretTreeItem extends TreeItem implements GithubLocalActionsTreeItem { static contextValue = 'githubLocalActions.secret'; - constructor(secret: Secret) { + constructor(public workspaceFolder: WorkspaceFolder, secret: Secret) { super(secret.key, TreeItemCollapsibleState.None); - if (secret.value) { - this.description = '••••••••' - } + this.description = secret.value ? '••••••••' : ''; this.contextValue = SecretTreeItem.contextValue; this.iconPath = new ThemeIcon('key'); this.checkboxState = TreeItemCheckboxState.Unchecked; diff --git a/src/views/settings/secrets.ts b/src/views/settings/secrets.ts index 123ca5e..76329f6 100644 --- a/src/views/settings/secrets.ts +++ b/src/views/settings/secrets.ts @@ -1,4 +1,4 @@ -import { ThemeIcon, TreeItem, TreeItemCollapsibleState } from "vscode"; +import { ThemeIcon, TreeItem, TreeItemCollapsibleState, WorkspaceFolder } from "vscode"; import { act } from "../../extension"; import { GithubLocalActionsTreeItem } from "../githubLocalActionsTreeItem"; import SecretTreeItem from "./secret"; @@ -6,15 +6,15 @@ import SecretTreeItem from "./secret"; export default class SecretsTreeItem extends TreeItem implements GithubLocalActionsTreeItem { static contextValue = 'githubLocalActions.secrets'; - constructor() { + constructor(public workspaceFolder: WorkspaceFolder) { super('Secrets', TreeItemCollapsibleState.Collapsed); this.contextValue = SecretsTreeItem.contextValue; this.iconPath = new ThemeIcon('lock'); } async getChildren(): Promise { - const workflows = await act.workflowsManager.getWorkflows(); + const workflows = await act.workflowsManager.getWorkflows(this.workspaceFolder); const secrets = [...new Set(workflows.map(workflow => act.settingsManager.getSecrets(workflow)).flat())]; - return secrets.map(secret => new SecretTreeItem(secret)); + return secrets.map(secret => new SecretTreeItem(this.workspaceFolder, secret)); } } \ No newline at end of file diff --git a/src/views/settings/settingsTreeDataProvider.ts b/src/views/settings/settingsTreeDataProvider.ts index 3373c91..ef6ba04 100644 --- a/src/views/settings/settingsTreeDataProvider.ts +++ b/src/views/settings/settingsTreeDataProvider.ts @@ -1,12 +1,12 @@ -import { CancellationToken, commands, EventEmitter, ExtensionContext, TreeDataProvider, TreeItem } from "vscode"; +import { CancellationToken, commands, EventEmitter, ExtensionContext, TreeDataProvider, TreeItem, workspace } from "vscode"; import { act } from "../../extension"; import { GithubLocalActionsTreeItem } from "../githubLocalActionsTreeItem"; -import ContainerEnginesTreeItem from "./containerEngines"; -import EnvironmentsTreeItem from "./environments"; -import InputsTreeItem from "./inputs"; +import ContainerEngineTreeItem from "./containerEngine"; +import InputTreeItem from "./input"; import RunnersTreeItem from "./runners"; -import SecretsTreeItem from "./secrets"; -import VariablesTreeItem from "./variables"; +import SecretTreeItem from "./secret"; +import VariableTreeItem from "./variable"; +import WorkspaceFolderSettingsTreeItem from "./workspaceFolderSettings"; export default class SettingsTreeDataProvider implements TreeDataProvider { private _onDidChangeTreeData = new EventEmitter(); @@ -17,6 +17,21 @@ export default class SettingsTreeDataProvider implements TreeDataProvider { this.refresh(); + }), + commands.registerCommand('githubLocalActions.editSecret', async (secretTreeItem: SecretTreeItem) => { + //TODO: Implement + }), + commands.registerCommand('githubLocalActions.editVariable', async (variableTreeItem: VariableTreeItem) => { + //TODO: Implement + }), + commands.registerCommand('githubLocalActions.editInput', async (inputTreeItem: InputTreeItem) => { + //TODO: Implement + }), + commands.registerCommand('githubLocalActions.addRunner', async (runnersTreeItem: RunnersTreeItem) => { + //TODO: Implement + }), + commands.registerCommand('githubLocalActions.editContainerEngine', async (containerEngineTreeItem: ContainerEngineTreeItem) => { + //TODO: Implement }) ); } @@ -42,20 +57,21 @@ export default class SettingsTreeDataProvider implements TreeDataProvider 0) { - items.push(...[ - new EnvironmentsTreeItem(), - new SecretsTreeItem(), - new VariablesTreeItem(), - new InputsTreeItem(), - new RunnersTreeItem(), - new ContainerEnginesTreeItem() - ]); + const workspaceFolders = workspace.workspaceFolders; + if (workspaceFolders) { + for (const workspaceFolder of workspaceFolders) { + items.push(new WorkspaceFolderSettingsTreeItem(workspaceFolder)); + + const workflows = await act.workflowsManager.getWorkflows(workspaceFolder); + if (workflows.length > 0) { + noSettings = false; + } + } } - await commands.executeCommand('setContext', 'githubLocalActions:noSettings', items.length == 0); + await commands.executeCommand('setContext', 'githubLocalActions:noSettings', noSettings); return items; } } diff --git a/src/views/settings/variable.ts b/src/views/settings/variable.ts index 15d586b..702f640 100644 --- a/src/views/settings/variable.ts +++ b/src/views/settings/variable.ts @@ -1,11 +1,11 @@ -import { ThemeIcon, TreeItem, TreeItemCheckboxState, TreeItemCollapsibleState } from "vscode"; +import { ThemeIcon, TreeItem, TreeItemCheckboxState, TreeItemCollapsibleState, WorkspaceFolder } from "vscode"; import { Variable } from "../../settingsManager"; import { GithubLocalActionsTreeItem } from "../githubLocalActionsTreeItem"; export default class VariableTreeItem extends TreeItem implements GithubLocalActionsTreeItem { static contextValue = 'githubLocalActions.variable'; - constructor(variable: Variable) { + constructor(public workspaceFolder: WorkspaceFolder, variable: Variable) { super(variable.key, TreeItemCollapsibleState.None); this.description = variable.value; this.contextValue = VariableTreeItem.contextValue; diff --git a/src/views/settings/variables.ts b/src/views/settings/variables.ts index 4a6d633..49debbe 100644 --- a/src/views/settings/variables.ts +++ b/src/views/settings/variables.ts @@ -1,4 +1,4 @@ -import { ThemeIcon, TreeItem, TreeItemCollapsibleState } from "vscode"; +import { ThemeIcon, TreeItem, TreeItemCollapsibleState, WorkspaceFolder } from "vscode"; import { act } from "../../extension"; import { GithubLocalActionsTreeItem } from "../githubLocalActionsTreeItem"; import VariableTreeItem from "./variable"; @@ -6,15 +6,15 @@ import VariableTreeItem from "./variable"; export default class VariablesTreeItem extends TreeItem implements GithubLocalActionsTreeItem { static contextValue = 'githubLocalActions.variables'; - constructor() { + constructor(public workspaceFolder: WorkspaceFolder) { super('Variables', TreeItemCollapsibleState.Collapsed); this.contextValue = VariablesTreeItem.contextValue; this.iconPath = new ThemeIcon('symbol-key'); } async getChildren(): Promise { - const workflows = await act.workflowsManager.getWorkflows(); + const workflows = await act.workflowsManager.getWorkflows(this.workspaceFolder); const variables = [...new Set(workflows.map(workflow => act.settingsManager.getVariables(workflow)).flat())]; - return variables.map(variable => new VariableTreeItem(variable)); + return variables.map(variable => new VariableTreeItem(this.workspaceFolder, variable)); } } \ No newline at end of file diff --git a/src/views/settings/workspaceFolderSettings.ts b/src/views/settings/workspaceFolderSettings.ts new file mode 100644 index 0000000..5bc746d --- /dev/null +++ b/src/views/settings/workspaceFolderSettings.ts @@ -0,0 +1,33 @@ +import { ThemeIcon, TreeItem, TreeItemCollapsibleState, WorkspaceFolder } from "vscode"; +import { GithubLocalActionsTreeItem } from "../githubLocalActionsTreeItem"; +import ContainerEnginesTreeItem from "./containerEngines"; +import EnvironmentsTreeItem from "./environments"; +import InputsTreeItem from "./inputs"; +import RunnersTreeItem from "./runners"; +import SecretsTreeItem from "./secrets"; +import VariablesTreeItem from "./variables"; + +export default class WorkspaceFolderSettingsTreeItem extends TreeItem implements GithubLocalActionsTreeItem { + static contextValue = 'githubLocalActions.workspaceFolderSettings'; + + constructor(public workspaceFolder: WorkspaceFolder) { + super(workspaceFolder.name, TreeItemCollapsibleState.Collapsed); + this.contextValue = WorkspaceFolderSettingsTreeItem.contextValue; + this.iconPath = new ThemeIcon('folder'); + } + + async getChildren(): Promise { + const items: GithubLocalActionsTreeItem[] = []; + + items.push(...[ + new EnvironmentsTreeItem(this.workspaceFolder), + new SecretsTreeItem(this.workspaceFolder), + new VariablesTreeItem(this.workspaceFolder), + new InputsTreeItem(this.workspaceFolder), + new RunnersTreeItem(this.workspaceFolder), + new ContainerEnginesTreeItem(this.workspaceFolder) + ]); + + return items; + } +} \ No newline at end of file diff --git a/src/views/workflows/job.ts b/src/views/workflows/job.ts index 6a71906..a4b15fd 100644 --- a/src/views/workflows/job.ts +++ b/src/views/workflows/job.ts @@ -1,4 +1,4 @@ -import { ThemeIcon, TreeItem, TreeItemCollapsibleState } from "vscode"; +import { ThemeIcon, TreeItem, TreeItemCollapsibleState, WorkspaceFolder } from "vscode"; import { Job, Workflow } from "../../workflowsManager"; import { GithubLocalActionsTreeItem } from "../githubLocalActionsTreeItem"; @@ -7,7 +7,7 @@ export default class JobTreeItem extends TreeItem implements GithubLocalActionsT job: Job; workflow: Workflow; - constructor(workflow: Workflow, job: Job) { + constructor(public workspaceFolder: WorkspaceFolder, workflow: Workflow, job: Job) { super(job.name, TreeItemCollapsibleState.None); this.workflow = workflow; this.job = job; diff --git a/src/views/workflows/workflow.ts b/src/views/workflows/workflow.ts index 63d1875..eaebc62 100644 --- a/src/views/workflows/workflow.ts +++ b/src/views/workflows/workflow.ts @@ -1,4 +1,4 @@ -import { ThemeIcon, TreeItem, TreeItemCollapsibleState, Uri } from "vscode"; +import { ThemeIcon, TreeItem, TreeItemCollapsibleState, Uri, WorkspaceFolder } from "vscode"; import { Workflow } from "../../workflowsManager"; import { GithubLocalActionsTreeItem } from "../githubLocalActionsTreeItem"; import JobTreeItem from "./job"; @@ -7,7 +7,7 @@ export default class WorkflowTreeItem extends TreeItem implements GithubLocalAct static contextValue = 'githubLocalActions.workflow'; workflow: Workflow; - constructor(workflow: Workflow) { + constructor(public workspaceFolder: WorkspaceFolder, workflow: Workflow) { super(workflow.name, workflow.error ? TreeItemCollapsibleState.None : TreeItemCollapsibleState.Collapsed); this.workflow = workflow; this.contextValue = WorkflowTreeItem.contextValue; @@ -27,7 +27,7 @@ export default class WorkflowTreeItem extends TreeItem implements GithubLocalAct const jobs = this.workflow.yaml.jobs; if (jobs) { for (const [key, value] of Object.entries(jobs)) { - items.push(new JobTreeItem(this.workflow, { name: value.name ? value.name : key, id: key })); + items.push(new JobTreeItem(this.workspaceFolder, this.workflow, { name: value.name ? value.name : key, id: key })); } } diff --git a/src/views/workflows/workflowsTreeDataProvider.ts b/src/views/workflows/workflowsTreeDataProvider.ts index 96bac6f..8cc6e1f 100644 --- a/src/views/workflows/workflowsTreeDataProvider.ts +++ b/src/views/workflows/workflowsTreeDataProvider.ts @@ -3,6 +3,7 @@ import { Event } from "../../act"; import { act } from "../../extension"; import { GithubLocalActionsTreeItem } from "../githubLocalActionsTreeItem"; import WorkflowTreeItem from "./workflow"; +import WorkspaceFolderWorkflowsTreeItem from "./workspaceFolderWorkflows"; export default class WorkflowsTreeDataProvider implements TreeDataProvider { private _onDidChangeTreeData = new EventEmitter(); @@ -63,13 +64,22 @@ export default class WorkflowsTreeDataProvider implements TreeDataProvider 0) { + noWorkflows = false; + } + } - const workflows = await act.workflowsManager.getWorkflows(); - for (const workflow of workflows) { - items.push(new WorkflowTreeItem(workflow)); } - await commands.executeCommand('setContext', 'githubLocalActions:noWorkflows', items.length == 0); + await commands.executeCommand('setContext', 'githubLocalActions:noWorkflows', noWorkflows); return items; } } diff --git a/src/views/workflows/workspaceFolderWorkflows.ts b/src/views/workflows/workspaceFolderWorkflows.ts new file mode 100644 index 0000000..eafaec1 --- /dev/null +++ b/src/views/workflows/workspaceFolderWorkflows.ts @@ -0,0 +1,25 @@ +import { ThemeIcon, TreeItem, TreeItemCollapsibleState, WorkspaceFolder } from "vscode"; +import { act } from "../../extension"; +import { GithubLocalActionsTreeItem } from "../githubLocalActionsTreeItem"; +import WorkflowTreeItem from "./workflow"; + +export default class WorkspaceFolderWorkflowsTreeItem extends TreeItem implements GithubLocalActionsTreeItem { + static contextValue = 'githubLocalActions.workspaceFolderWorkflows'; + + constructor(public workspaceFolder: WorkspaceFolder) { + super(workspaceFolder.name, TreeItemCollapsibleState.Collapsed); + this.contextValue = WorkspaceFolderWorkflowsTreeItem.contextValue; + this.iconPath = new ThemeIcon('folder'); + } + + async getChildren(): Promise { + const items: GithubLocalActionsTreeItem[] = []; + + const workflows = await act.workflowsManager.getWorkflows(this.workspaceFolder); + for (const workflow of workflows) { + items.push(new WorkflowTreeItem(this.workspaceFolder, workflow)); + } + + return items; + } +} \ No newline at end of file diff --git a/src/workflowsManager.ts b/src/workflowsManager.ts index 55e1202..5cc85b5 100644 --- a/src/workflowsManager.ts +++ b/src/workflowsManager.ts @@ -1,6 +1,6 @@ import * as fs from "fs/promises"; import * as path from "path"; -import { Uri, workspace } from "vscode"; +import { RelativePattern, Uri, workspace, WorkspaceFolder } from "vscode"; import * as yaml from "yaml"; export interface Workflow { @@ -17,33 +17,29 @@ export interface Job { } export class WorkflowsManager { - async getWorkflows(): Promise { + async getWorkflows(workspaceFolder: WorkspaceFolder): Promise { const workflows: Workflow[] = []; - const workspaceFolders = workspace.workspaceFolders; - if (workspaceFolders && workspaceFolders.length > 0) { - const workflowFileUris = await workspace.findFiles(`.github/workflows/*.{yml,yaml}`); + const workflowFileUris = await workspace.findFiles(new RelativePattern(workspaceFolder, `.github/workflows/*.{yml,yaml}`)); + for await (const workflowFileUri of workflowFileUris) { + let yamlContent: any | undefined; - for await (const workflowFileUri of workflowFileUris) { - let yamlContent: any | undefined; + try { + const fileContent = await fs.readFile(workflowFileUri.fsPath, 'utf8'); + yamlContent = yaml.parse(fileContent); - try { - const fileContent = await fs.readFile(workflowFileUri.fsPath, 'utf8'); - yamlContent = yaml.parse(fileContent); - - workflows.push({ - name: yamlContent.name || path.parse(workflowFileUri.fsPath).name, - uri: workflowFileUri, - fileContent: fileContent, - yaml: yaml.parse(fileContent) - }); - } catch (error) { - workflows.push({ - name: (yamlContent ? yamlContent.name : undefined) || path.parse(workflowFileUri.fsPath).name, - uri: workflowFileUri, - error: 'Failed to parse workflow file.' - }); - } + workflows.push({ + name: yamlContent.name || path.parse(workflowFileUri.fsPath).name, + uri: workflowFileUri, + fileContent: fileContent, + yaml: yaml.parse(fileContent) + }); + } catch (error) { + workflows.push({ + name: (yamlContent ? yamlContent.name : undefined) || path.parse(workflowFileUri.fsPath).name, + uri: workflowFileUri, + error: 'Failed to parse workflow file.' + }); } }