diff --git a/package.json b/package.json index 54a7e16..8fb7c41 100644 --- a/package.json +++ b/package.json @@ -242,10 +242,16 @@ }, { "category": "GitHub Local Actions", - "command": "githubLocalActions.addSecretFiles", - "title": "Add Secret Files", + "command": "githubLocalActions.createSecretFile", + "title": "Create Secret File", "icon": "$(add)" }, + { + "category": "GitHub Local Actions", + "command": "githubLocalActions.locateSecretFiles", + "title": "Locate Secret Files", + "icon": "$(search)" + }, { "category": "GitHub Local Actions", "command": "githubLocalActions.show", @@ -260,22 +266,34 @@ }, { "category": "GitHub Local Actions", - "command": "githubLocalActions.addVariableFiles", - "title": "Add Variable Files", + "command": "githubLocalActions.createVariableFile", + "title": "Create Variable File", "icon": "$(add)" }, + { + "category": "GitHub Local Actions", + "command": "githubLocalActions.locateVariableFiles", + "title": "Locate Variable Files", + "icon": "$(search)" + }, + { + "category": "GitHub Local Actions", + "command": "githubLocalActions.createInputFile", + "title": "Create Input File", + "icon": "$(add)" + }, + { + "category": "GitHub Local Actions", + "command": "githubLocalActions.locateInputFiles", + "title": "Locate Input Files", + "icon": "$(search)" + }, { "category": "GitHub Local Actions", "command": "githubLocalActions.importFromGithub", "title": "Import from GitHub", "icon": "$(github)" }, - { - "category": "GitHub Local Actions", - "command": "githubLocalActions.addInputFiles", - "title": "Add Input Files", - "icon": "$(add)" - }, { "category": "GitHub Local Actions", "command": "githubLocalActions.openSettingFile", @@ -389,7 +407,11 @@ "when": "never" }, { - "command": "githubLocalActions.addSecretFiles", + "command": "githubLocalActions.createSecretFile", + "when": "never" + }, + { + "command": "githubLocalActions.locateSecretFiles", "when": "never" }, { @@ -401,17 +423,25 @@ "when": "never" }, { - "command": "githubLocalActions.addVariableFiles", + "command": "githubLocalActions.createVariableFile", + "when": "never" + }, + { + "command": "githubLocalActions.locateVariableFiles", + "when": "never" + }, + { + "command": "githubLocalActions.createInputFile", + "when": "never" + }, + { + "command": "githubLocalActions.locateInputFiles", "when": "never" }, { "command": "githubLocalActions.importFromGithub", "when": "never" }, - { - "command": "githubLocalActions.addInputFiles", - "when": "never" - }, { "command": "githubLocalActions.openSettingFile", "when": "never" @@ -556,10 +586,15 @@ "group": "inline@3" }, { - "command": "githubLocalActions.addSecretFiles", + "command": "githubLocalActions.createSecretFile", "when": "view == settings && viewItem =~ /^githubLocalActions.secrets.*/", "group": "inline@0" }, + { + "command": "githubLocalActions.locateSecretFiles", + "when": "view == settings && viewItem =~ /^githubLocalActions.secrets.*/", + "group": "inline@1" + }, { "command": "githubLocalActions.show", "when": "view == settings && viewItem =~ /^githubLocalActions.secret(?!s)_hide.*/", @@ -571,20 +606,30 @@ "group": "inline@0" }, { - "command": "githubLocalActions.addVariableFiles", + "command": "githubLocalActions.createVariableFile", "when": "view == settings && viewItem =~ /^githubLocalActions.variables.*/", "group": "inline@0" }, { - "command": "githubLocalActions.importFromGithub", + "command": "githubLocalActions.locateVariableFiles", "when": "view == settings && viewItem =~ /^githubLocalActions.variables.*/", "group": "inline@1" }, { - "command": "githubLocalActions.addInputFiles", + "command": "githubLocalActions.createInputFile", "when": "view == settings && viewItem =~ /^githubLocalActions.inputs.*/", "group": "inline@0" }, + { + "command": "githubLocalActions.locateInputFiles", + "when": "view == settings && viewItem =~ /^githubLocalActions.inputs.*/", + "group": "inline@1" + }, + { + "command": "githubLocalActions.importFromGithub", + "when": "view == settings && viewItem =~ /^githubLocalActions.variables.*/", + "group": "inline@2" + }, { "command": "githubLocalActions.openSettingFile", "when": "view == settings && viewItem =~ /^githubLocalActions.(secret|variable|input)File.*/", diff --git a/src/act.ts b/src/act.ts index d9e3379..c2fce97 100644 --- a/src/act.ts +++ b/src/act.ts @@ -309,11 +309,11 @@ export class Act { `set -o pipefail; ` + `${Act.base} ${commandArgs.options}` + (settings.secrets.length > 0 ? ` ${Option.Secret} ${settings.secrets.map(secret => secret.key).join(` ${Option.Secret} `)}` : ``) + - (settings.secretFiles.length > 0 ? ` ${Option.SecretFile} ${settings.secretFiles.map(secretFile => `"${secretFile.path}"`).join(` ${Option.SecretFile} `)}` : ``) + + (settings.secretFiles.length > 0 ? ` ${Option.SecretFile} ${settings.secretFiles[0].path}` : ` ${Option.SecretFile} ""`) + (settings.variables.length > 0 ? ` ${Option.Variable} ${settings.variables.map(variable => (variable.value ? `${variable.key}=${variable.value}` : variable.key)).join(` ${Option.Variable} `)}` : ``) + - (settings.variableFiles.length > 0 ? ` ${Option.VariableFile} ${settings.variableFiles.map(variableFile => `"${variableFile.path}"`).join(` ${Option.VariableFile} `)}` : ``) + + (settings.variableFiles.length > 0 ? ` ${Option.VariableFile} ${settings.variableFiles[0].path}` : ` ${Option.VariableFile} ""`) + (settings.inputs.length > 0 ? ` ${Option.Input} ${settings.inputs.map(input => `${input.key}=${input.value}`).join(` ${Option.Input} `)}` : ``) + - (settings.inputFiles.length > 0 ? ` ${Option.InputFile} ${settings.inputFiles.map(inputFile => `"${inputFile.path}"`).join(` ${Option.InputFile} `)}` : ``) + + (settings.inputFiles.length > 0 ? ` ${Option.InputFile} ${settings.inputFiles[0].path}` : ` ${Option.InputFile} ""`) + (settings.runners.length > 0 ? ` ${Option.Platform} ${settings.runners.map(runner => `${runner.key}=${runner.value}`).join(` ${Option.Platform} `)}` : ``) + ` 2>&1 | tee "${logPath}"`; diff --git a/src/settingsManager.ts b/src/settingsManager.ts index 7cdd7a8..6f71337 100644 --- a/src/settingsManager.ts +++ b/src/settingsManager.ts @@ -1,3 +1,4 @@ +import * as path from "path"; import { Uri, window, workspace, WorkspaceFolder } from "vscode"; import { act } from "./extension"; import { GitHubManager } from "./githubManager"; @@ -34,6 +35,12 @@ export enum Visibility { hide = 'hide' } +export enum SettingFileName { + secretFile = '.secrets', + variableFile = '.env', + inputFile = '.input' +} + export class SettingsManager { storageManager: StorageManager; secretManager: SecretManager; @@ -153,6 +160,48 @@ export class SettingsManager { return environments; } + async createSettingFile(workspaceFolder: WorkspaceFolder, storageKey: StorageKey, settingFileName: string) { + const settingFileUri = Uri.file(path.join(workspaceFolder.uri.fsPath, settingFileName)); + + try { + await workspace.fs.stat(settingFileUri); + window.showErrorMessage(`A file or folder named ${settingFileName} already exists at ${workspaceFolder.uri.fsPath}. Please choose another name.`); + } catch (error: any) { + try { + await workspace.fs.writeFile(settingFileUri, new TextEncoder().encode('')); + await this.locateSettingFile(workspaceFolder, storageKey, [settingFileUri]); + const document = await workspace.openTextDocument(settingFileUri); + await window.showTextDocument(document); + } catch (error: any) { + window.showErrorMessage(`Failed to create ${settingFileName}. Error: ${error}`) + } + } + } + + async locateSettingFile(workspaceFolder: WorkspaceFolder, storageKey: StorageKey, settingFilesUris: Uri[]) { + const settingFilesPaths = (await act.settingsManager.getSettingFiles(workspaceFolder, storageKey)).map(settingFile => settingFile.path); + const existingSettingFileNames: string[] = []; + + for await (const uri of settingFilesUris) { + const settingFileName = path.parse(uri.fsPath).name; + + if (settingFilesPaths.includes(uri.fsPath)) { + existingSettingFileNames.push(settingFileName); + } else { + const newSettingFile: SettingFile = { + name: path.parse(uri.fsPath).base, + path: uri.fsPath, + selected: false + }; + await act.settingsManager.editSettingFile(workspaceFolder, newSettingFile, storageKey); + } + } + + if (existingSettingFileNames.length > 0) { + window.showErrorMessage(`The following file(s) have already been added: ${existingSettingFileNames.join(', ')}`); + } + } + async editSettingFile(workspaceFolder: WorkspaceFolder, newSettingFile: SettingFile, storageKey: StorageKey) { const existingSettingFiles = this.storageManager.get<{ [path: string]: SettingFile[] }>(storageKey) || {}; if (existingSettingFiles[workspaceFolder.uri.fsPath]) { diff --git a/src/views/settings/inputs.ts b/src/views/settings/inputs.ts index ce36b7d..6c1deb9 100644 --- a/src/views/settings/inputs.ts +++ b/src/views/settings/inputs.ts @@ -14,7 +14,7 @@ export default class InputsTreeItem extends TreeItem implements GithubLocalActio super('Inputs', TreeItemCollapsibleState.Collapsed); const selectedInputFiles = inputFiles.filter(inputFile => inputFile.selected); this.description = `${inputs.filter(input => input.selected).length}/${inputs.length}` + - (selectedInputFiles.length > 0 ? ` + ${selectedInputFiles.length} input file(s)` : ``); + (selectedInputFiles.length > 0 ? ` + ${selectedInputFiles[0].name}` : ``); this.contextValue = InputsTreeItem.contextValue; this.iconPath = new ThemeIcon('record-keys'); } diff --git a/src/views/settings/secrets.ts b/src/views/settings/secrets.ts index 8f1be60..8259532 100644 --- a/src/views/settings/secrets.ts +++ b/src/views/settings/secrets.ts @@ -14,7 +14,7 @@ export default class SecretsTreeItem extends TreeItem implements GithubLocalActi super('Secrets', TreeItemCollapsibleState.Collapsed); const selectedSecretFiles = secretFiles.filter(secretFile => secretFile.selected); this.description = `${secrets.filter(secret => secret.selected).length}/${secrets.length}` + - (selectedSecretFiles.length > 0 ? ` + ${selectedSecretFiles.length} secret file(s)` : ``); + (selectedSecretFiles.length > 0 ? ` + ${selectedSecretFiles[0].name}` : ``); this.contextValue = SecretsTreeItem.contextValue; this.iconPath = new ThemeIcon('lock'); } diff --git a/src/views/settings/settingsTreeDataProvider.ts b/src/views/settings/settingsTreeDataProvider.ts index 4a3a546..1de0022 100644 --- a/src/views/settings/settingsTreeDataProvider.ts +++ b/src/views/settings/settingsTreeDataProvider.ts @@ -1,7 +1,6 @@ -import * as path from "path"; import { CancellationToken, commands, EventEmitter, ExtensionContext, QuickPickItem, QuickPickItemKind, ThemeIcon, TreeCheckboxChangeEvent, TreeDataProvider, TreeItem, TreeItemCheckboxState, window, workspace } from "vscode"; import { act } from "../../extension"; -import { SettingFile, Visibility } from "../../settingsManager"; +import { SettingFileName, Visibility } from "../../settingsManager"; import { StorageKey } from "../../storageManager"; import { GithubLocalActionsTreeItem } from "../githubLocalActionsTreeItem"; import InputsTreeItem from "./inputs"; @@ -21,48 +20,83 @@ export default class SettingsTreeDataProvider implements TreeDataProvider { this.refresh(); }), - commands.registerCommand('githubLocalActions.addSettingFiles', async (treeItem: SecretsTreeItem | VariablesTreeItem | InputsTreeItem, title: string) => { - const settingFilesUris = await window.showOpenDialog({ - title: title, - canSelectFiles: true, - canSelectFolders: false, - canSelectMany: true, - defaultUri: treeItem.workspaceFolder.uri + commands.registerCommand('githubLocalActions.createSecretFile', async (secretsTreeItem: SecretsTreeItem) => { + const secretFileName = await window.showInputBox({ + prompt: `Enter the name for the secret file`, + placeHolder: `Secret File Name`, + value: SettingFileName.secretFile }); - if (settingFilesUris) { - const settingFilesPaths = (await act.settingsManager.getSettingFiles(treeItem.workspaceFolder, treeItem.storageKey)).map(settingFile => settingFile.path); - const existingSettingFileNames: string[] = []; - - for await (const uri of settingFilesUris) { - const settingFileName = path.parse(uri.fsPath).name; - - if (settingFilesPaths.includes(uri.fsPath)) { - existingSettingFileNames.push(settingFileName); - } else { - const newSettingFile: SettingFile = { - name: path.parse(uri.fsPath).base, - path: uri.fsPath, - selected: false - }; - await act.settingsManager.editSettingFile(treeItem.workspaceFolder, newSettingFile, treeItem.storageKey); - } - } - - if (existingSettingFileNames.length > 0) { - window.showErrorMessage(`The following file(s) have already been added: ${existingSettingFileNames.join(', ')}`); - } + if (secretFileName) { + await act.settingsManager.createSettingFile(secretsTreeItem.workspaceFolder, secretsTreeItem.storageKey, secretFileName); this.refresh(); } }), - commands.registerCommand('githubLocalActions.addSecretFiles', async (secretsTreeItem: SecretsTreeItem) => { - await commands.executeCommand('githubLocalActions.addSettingFiles', secretsTreeItem, 'Add Secret File'); + commands.registerCommand('githubLocalActions.locateSecretFiles', async (secretsTreeItem: SecretsTreeItem) => { + const secretFilesUris = await window.showOpenDialog({ + title: 'Locate Secret Files', + canSelectFiles: true, + canSelectFolders: false, + canSelectMany: true, + defaultUri: secretsTreeItem.workspaceFolder.uri + }); + + if (secretFilesUris) { + await act.settingsManager.locateSettingFile(secretsTreeItem.workspaceFolder, secretsTreeItem.storageKey, secretFilesUris); + this.refresh(); + } }), - commands.registerCommand('githubLocalActions.addVariableFiles', async (variablesTreeItem: VariablesTreeItem) => { - await commands.executeCommand('githubLocalActions.addSettingFiles', variablesTreeItem, 'Add Variable File'); + commands.registerCommand('githubLocalActions.createVariableFile', async (variablesTreeItem: VariablesTreeItem) => { + const variableFileName = await window.showInputBox({ + prompt: `Enter the name for the variable file`, + placeHolder: `Variable File Name`, + value: SettingFileName.variableFile + }); + + if (variableFileName) { + await act.settingsManager.createSettingFile(variablesTreeItem.workspaceFolder, variablesTreeItem.storageKey, variableFileName); + this.refresh(); + } }), - commands.registerCommand('githubLocalActions.addInputFiles', async (inputsTreeItem: InputsTreeItem) => { - await commands.executeCommand('githubLocalActions.addSettingFiles', inputsTreeItem, 'Add Input File'); + commands.registerCommand('githubLocalActions.locateVariableFiles', async (variablesTreeItem: VariablesTreeItem) => { + const variableFilesUris = await window.showOpenDialog({ + title: 'Locate Variable Files', + canSelectFiles: true, + canSelectFolders: false, + canSelectMany: true, + defaultUri: variablesTreeItem.workspaceFolder.uri + }); + + if (variableFilesUris) { + await act.settingsManager.locateSettingFile(variablesTreeItem.workspaceFolder, variablesTreeItem.storageKey, variableFilesUris); + this.refresh(); + } + }), + commands.registerCommand('githubLocalActions.createInputFile', async (inputsTreeItem: InputsTreeItem) => { + const inputFileName = await window.showInputBox({ + prompt: `Enter the name for the input file`, + placeHolder: `Input File Name`, + value: SettingFileName.inputFile + }); + + if (inputFileName) { + await act.settingsManager.createSettingFile(inputsTreeItem.workspaceFolder, inputsTreeItem.storageKey, inputFileName); + this.refresh(); + } + }), + commands.registerCommand('githubLocalActions.locateInputFiles', async (inputsTreeItem: InputsTreeItem) => { + const inputFilesUris = await window.showOpenDialog({ + title: 'Locate Variable Files', + canSelectFiles: true, + canSelectFolders: false, + canSelectMany: true, + defaultUri: inputsTreeItem.workspaceFolder.uri + }); + + if (inputFilesUris) { + await act.settingsManager.locateSettingFile(inputsTreeItem.workspaceFolder, inputsTreeItem.storageKey, inputFilesUris); + this.refresh(); + } }), commands.registerCommand('githubLocalActions.openSettingFile', async (settingFileTreeItem: SettingFileTreeItem) => { const document = await workspace.openTextDocument(settingFileTreeItem.settingFile.path); diff --git a/src/views/settings/variables.ts b/src/views/settings/variables.ts index b8b0d28..da6e4a9 100644 --- a/src/views/settings/variables.ts +++ b/src/views/settings/variables.ts @@ -14,7 +14,7 @@ export default class VariablesTreeItem extends TreeItem implements GithubLocalAc super('Variables', TreeItemCollapsibleState.Collapsed); const selectedVariableFiles = variableFiles.filter(variableFile => variableFile.selected); this.description = `${variables.filter(variable => variable.selected).length}/${variables.length}` + - (selectedVariableFiles.length > 0 ? ` + ${selectedVariableFiles.length} variable file(s)` : ``); + (selectedVariableFiles.length > 0 ? ` + ${selectedVariableFiles[0].name} variable file(s)` : ``); this.contextValue = VariablesTreeItem.contextValue; this.iconPath = new ThemeIcon('symbol-key'); }