From af0b2edb4a5a6594d86848da8408644791b8b6a1 Mon Sep 17 00:00:00 2001 From: Sanjula Ganepola Date: Mon, 18 Nov 2024 18:23:07 -0500 Subject: [PATCH] Switch to use secret manager for secrets Signed-off-by: Sanjula Ganepola --- src/act.ts | 18 ++++----- src/secretManager.ts | 23 ++++++++++++ src/settingsManager.ts | 37 +++++++++++++++++-- src/views/settings/inputs.ts | 7 ++-- src/views/settings/runners.ts | 7 ++-- src/views/settings/secrets.ts | 7 ++-- src/views/settings/variables.ts | 7 ++-- src/views/settings/workspaceFolderSettings.ts | 15 +++----- 8 files changed, 83 insertions(+), 38 deletions(-) create mode 100644 src/secretManager.ts diff --git a/src/act.ts b/src/act.ts index 013f08f..50670f5 100644 --- a/src/act.ts +++ b/src/act.ts @@ -3,6 +3,7 @@ import { commands, ExtensionContext, ShellExecution, TaskGroup, TaskPanelKind, T import { ComponentsManager } from "./componentsManager"; import { componentsTreeDataProvider, historyTreeDataProvider } from './extension'; import { HistoryManager, HistoryStatus } from './historyManager'; +import { SecretManager } from "./secretManager"; import { SettingsManager } from './settingsManager'; import { StorageKey, StorageManager } from './storageManager'; import { Job, Workflow, WorkflowsManager } from "./workflowsManager"; @@ -62,6 +63,7 @@ export interface CommandArgs { export class Act { private static base: string = 'act'; storageManager: StorageManager; + secretManager: SecretManager; componentsManager: ComponentsManager; workflowsManager: WorkflowsManager; historyManager: HistoryManager; @@ -71,10 +73,11 @@ export class Act { constructor(context: ExtensionContext) { this.storageManager = new StorageManager(context); + this.secretManager = new SecretManager(context); this.componentsManager = new ComponentsManager(); this.workflowsManager = new WorkflowsManager(); this.historyManager = new HistoryManager(this.storageManager); - this.settingsManager = new SettingsManager(this.storageManager); + this.settingsManager = new SettingsManager(this.storageManager, this.secretManager); switch (process.platform) { case 'win32': @@ -272,15 +275,12 @@ export class Act { } // Build command with settings - const secrets = (await this.settingsManager.getSetting(workspaceFolder, SettingsManager.secretsRegExp, StorageKey.Secrets, true)).filter(secret => secret.selected); - const variables = (await this.settingsManager.getSetting(workspaceFolder, SettingsManager.variablesRegExp, StorageKey.Variables, false)).filter(variable => variable.selected); - const inputs = (await this.settingsManager.getSetting(workspaceFolder, SettingsManager.inputsRegExp, StorageKey.Inputs, false)).filter(input => input.selected && input.value); - const runners = (await this.settingsManager.getSetting(workspaceFolder, SettingsManager.runnersRegExp, StorageKey.Runners, false)).filter(runner => runner.selected && runner.value); + const settings = await this.settingsManager.getSettings(workspaceFolder, true); const command = `${Act.base} ${commandArgs.options}` + - (secrets.length > 0 ? ` ${Option.Secret} ${secrets.map(secret => (secret.value ? `${secret.key}=${secret.value}` : secret.key)).join(` ${Option.Secret} `)}` : ``) + - (variables.length > 0 ? ` ${Option.Variable} ${variables.map(variable => (variable.value ? `${variable.key}=${variable.value}` : variable.key)).join(` ${Option.Variable} `)}` : ``) + - (inputs.length > 0 ? ` ${Option.Input} ${inputs.map(input => `${input.key}=${input.value}`).join(` ${Option.Input} `)}` : ``) + - (runners.length > 0 ? ` ${Option.Platform} ${runners.map(runner => `${runner.key}=${runner.value}`).join(` ${Option.Platform} `)}` : ``); + (settings.secrets.length > 0 ? ` ${Option.Secret} ${settings.secrets.map(secret => (secret.value ? `${secret.key}=${secret.value}` : secret.key)).join(` ${Option.Secret} `)}` : ``) + + (settings.variables.length > 0 ? ` ${Option.Variable} ${settings.variables.map(variable => (variable.value ? `${variable.key}=${variable.value}` : variable.key)).join(` ${Option.Variable} `)}` : ``) + + (settings.inputs.length > 0 ? ` ${Option.Input} ${settings.inputs.map(input => `${input.key}=${input.value}`).join(` ${Option.Input} `)}` : ``) + + (settings.runners.length > 0 ? ` ${Option.Platform} ${settings.runners.map(runner => `${runner.key}=${runner.value}`).join(` ${Option.Platform} `)}` : ``); // Process task count suffix const historyIndex = this.historyManager.workspaceHistory[commandArgs.fsPath].length; diff --git a/src/secretManager.ts b/src/secretManager.ts new file mode 100644 index 0000000..b86b1d3 --- /dev/null +++ b/src/secretManager.ts @@ -0,0 +1,23 @@ +import { ExtensionContext, WorkspaceFolder } from "vscode"; +import { StorageKey } from "./storageManager"; + +export class SecretManager { + private context: ExtensionContext; + private extensionKey: string = 'githubLocalActions'; + + constructor(context: ExtensionContext) { + this.context = context; + } + + async get(workspaceFolder: WorkspaceFolder, storageKey: StorageKey, key: string): Promise { + return await this.context.secrets.get(`${this.extensionKey}.${workspaceFolder.uri.fsPath}.${storageKey}.${key}`); + } + + async store(workspaceFolder: WorkspaceFolder, storageKey: StorageKey, key: string, value: string): Promise { + await this.context.secrets.store(`${this.extensionKey}.${workspaceFolder.uri.fsPath}.${storageKey}.${key}`, value); + } + + async delete(workspaceFolder: WorkspaceFolder, storageKey: StorageKey, key: string): Promise { + return await this.context.secrets.delete(`${this.extensionKey}.${workspaceFolder.uri.fsPath}.${storageKey}.${key}`); + } +} \ No newline at end of file diff --git a/src/settingsManager.ts b/src/settingsManager.ts index a5cb15d..c3b2b94 100644 --- a/src/settingsManager.ts +++ b/src/settingsManager.ts @@ -1,5 +1,6 @@ import { WorkspaceFolder } from "vscode"; import { act } from "./extension"; +import { SecretManager } from "./secretManager"; import { StorageKey, StorageManager } from "./storageManager"; export interface Setting { @@ -11,13 +12,29 @@ export interface Setting { export class SettingsManager { storageManager: StorageManager; + secretManager: SecretManager; static secretsRegExp: RegExp = /\${{\s*secrets\.(.*?)\s*}}/g; static variablesRegExp: RegExp = /\${{\s*vars\.(.*?)(?:\s*==\s*(.*?))?\s*}}/g; static inputsRegExp: RegExp = /\${{\s*(?:inputs|github\.event\.inputs)\.(.*?)(?:\s*==\s*(.*?))?\s*}}/g; static runnersRegExp: RegExp = /runs-on:\s*(.+)/g; - constructor(storageManager: StorageManager) { + constructor(storageManager: StorageManager, secretManager: SecretManager) { this.storageManager = storageManager; + this.secretManager = secretManager; + } + + async getSettings(workspaceFolder: WorkspaceFolder, isUserSelected: boolean) { + const secrets = (await this.getSetting(workspaceFolder, SettingsManager.secretsRegExp, StorageKey.Secrets, true)).filter(secret => !isUserSelected || secret.selected); + const variables = (await this.getSetting(workspaceFolder, SettingsManager.variablesRegExp, StorageKey.Variables, false)).filter(variable => !isUserSelected || variable.selected); + const inputs = (await this.getSetting(workspaceFolder, SettingsManager.inputsRegExp, StorageKey.Inputs, false)).filter(input => !isUserSelected || (input.selected && input.value)); + const runners = (await this.getSetting(workspaceFolder, SettingsManager.runnersRegExp, StorageKey.Runners, false)).filter(runner => !isUserSelected || (runner.selected && runner.value)); + + return { + secrets: secrets, + variables: variables, + inputs: inputs, + runners: runners + } } async getSetting(workspaceFolder: WorkspaceFolder, regExp: RegExp, storageKey: StorageKey, password: boolean): Promise { @@ -43,9 +60,16 @@ export class SettingsManager { for (const [index, setting] of settings.entries()) { const existingSetting = existingSettings[workspaceFolder.uri.fsPath].find(existingSetting => existingSetting.key === setting.key); if (existingSetting) { + let value: string; + if (storageKey === StorageKey.Secrets) { + value = await this.secretManager.get(workspaceFolder, storageKey, setting.key) || ""; + } else { + value = existingSetting.value; + } + settings[index] = { key: setting.key, - value: existingSetting.value, + value: value, password: existingSetting.password, selected: existingSetting.selected }; @@ -59,8 +83,12 @@ export class SettingsManager { } async editSetting(workspaceFolder: WorkspaceFolder, newSetting: Setting, storageKey: StorageKey) { - const existingSettings = this.storageManager.get<{ [path: string]: Setting[] }>(storageKey) || {}; + const value = newSetting.value; + if (storageKey === StorageKey.Secrets) { + newSetting.value = ''; + } + const existingSettings = this.storageManager.get<{ [path: string]: Setting[] }>(storageKey) || {}; if (existingSettings[workspaceFolder.uri.fsPath]) { const index = existingSettings[workspaceFolder.uri.fsPath].findIndex(setting => setting.key === newSetting.key); if (index > -1) { @@ -73,6 +101,9 @@ export class SettingsManager { } await this.storageManager.update(storageKey, existingSettings); + if (storageKey === StorageKey.Secrets) { + await this.secretManager.store(workspaceFolder, storageKey, newSetting.key, value); + } } private findInWorkflow(content: string, regExp: RegExp, password: boolean) { diff --git a/src/views/settings/inputs.ts b/src/views/settings/inputs.ts index 5f8a600..19be59e 100644 --- a/src/views/settings/inputs.ts +++ b/src/views/settings/inputs.ts @@ -1,7 +1,6 @@ import { ThemeIcon, TreeItem, TreeItemCollapsibleState, WorkspaceFolder } from "vscode"; import { act } from "../../extension"; -import { Setting, SettingsManager } from "../../settingsManager"; -import { StorageKey } from "../../storageManager"; +import { Setting } from "../../settingsManager"; import { GithubLocalActionsTreeItem } from "../githubLocalActionsTreeItem"; import SettingTreeItem from "./setting"; @@ -18,8 +17,8 @@ export default class InputsTreeItem extends TreeItem implements GithubLocalActio async getChildren(): Promise { const items: GithubLocalActionsTreeItem[] = []; - const inputs = await act.settingsManager.getSetting(this.workspaceFolder, SettingsManager.inputsRegExp, StorageKey.Inputs, false); - for (const input of inputs) { + const settings = await act.settingsManager.getSettings(this.workspaceFolder, false); + for (const input of settings.inputs) { items.push(SettingTreeItem.getInputTreeItem(this.workspaceFolder, input)); } diff --git a/src/views/settings/runners.ts b/src/views/settings/runners.ts index f0841d1..e345410 100644 --- a/src/views/settings/runners.ts +++ b/src/views/settings/runners.ts @@ -1,7 +1,6 @@ import { ThemeIcon, TreeItem, TreeItemCollapsibleState, WorkspaceFolder } from "vscode"; import { act } from "../../extension"; -import { Setting, SettingsManager } from "../../settingsManager"; -import { StorageKey } from "../../storageManager"; +import { Setting } from "../../settingsManager"; import { GithubLocalActionsTreeItem } from "../githubLocalActionsTreeItem"; import SettingTreeItem from "./setting"; @@ -18,8 +17,8 @@ export default class RunnersTreeItem extends TreeItem implements GithubLocalActi async getChildren(): Promise { const items: GithubLocalActionsTreeItem[] = []; - const runners = await act.settingsManager.getSetting(this.workspaceFolder, SettingsManager.runnersRegExp, StorageKey.Runners, false); - for (const runner of runners) { + const settings = await act.settingsManager.getSettings(this.workspaceFolder, false); + for (const runner of settings.runners) { items.push(SettingTreeItem.getRunnerTreeItem(this.workspaceFolder, runner)); } diff --git a/src/views/settings/secrets.ts b/src/views/settings/secrets.ts index 8c12fdd..fb021b3 100644 --- a/src/views/settings/secrets.ts +++ b/src/views/settings/secrets.ts @@ -1,7 +1,6 @@ import { ThemeIcon, TreeItem, TreeItemCollapsibleState, WorkspaceFolder } from "vscode"; import { act } from "../../extension"; -import { Setting, SettingsManager } from "../../settingsManager"; -import { StorageKey } from "../../storageManager"; +import { Setting } from "../../settingsManager"; import { GithubLocalActionsTreeItem } from "../githubLocalActionsTreeItem"; import SettingTreeItem from "./setting"; @@ -18,8 +17,8 @@ export default class SecretsTreeItem extends TreeItem implements GithubLocalActi async getChildren(): Promise { const items: GithubLocalActionsTreeItem[] = []; - const secrets = await act.settingsManager.getSetting(this.workspaceFolder, SettingsManager.secretsRegExp, StorageKey.Secrets, true); - for (const secret of secrets) { + const settings = await act.settingsManager.getSettings(this.workspaceFolder, false); + for (const secret of settings.secrets) { items.push(SettingTreeItem.getSecretTreeItem(this.workspaceFolder, secret)); } diff --git a/src/views/settings/variables.ts b/src/views/settings/variables.ts index 6f308ab..6c43350 100644 --- a/src/views/settings/variables.ts +++ b/src/views/settings/variables.ts @@ -1,7 +1,6 @@ import { ThemeIcon, TreeItem, TreeItemCollapsibleState, WorkspaceFolder } from "vscode"; import { act } from "../../extension"; -import { Setting, SettingsManager } from "../../settingsManager"; -import { StorageKey } from "../../storageManager"; +import { Setting } from "../../settingsManager"; import { GithubLocalActionsTreeItem } from "../githubLocalActionsTreeItem"; import SettingTreeItem from "./setting"; @@ -18,8 +17,8 @@ export default class VariablesTreeItem extends TreeItem implements GithubLocalAc async getChildren(): Promise { const items: GithubLocalActionsTreeItem[] = []; - const variables = await act.settingsManager.getSetting(this.workspaceFolder, SettingsManager.variablesRegExp, StorageKey.Variables, false); - for (const variable of variables) { + const settings = await act.settingsManager.getSettings(this.workspaceFolder, false); + for (const variable of settings.variables) { items.push(SettingTreeItem.getVariableTreeItem(this.workspaceFolder, variable)); } diff --git a/src/views/settings/workspaceFolderSettings.ts b/src/views/settings/workspaceFolderSettings.ts index 181dcdb..9b068a0 100644 --- a/src/views/settings/workspaceFolderSettings.ts +++ b/src/views/settings/workspaceFolderSettings.ts @@ -1,7 +1,5 @@ import { ThemeIcon, TreeItem, TreeItemCollapsibleState, WorkspaceFolder } from "vscode"; import { act } from "../../extension"; -import { SettingsManager } from "../../settingsManager"; -import { StorageKey } from "../../storageManager"; import { GithubLocalActionsTreeItem } from "../githubLocalActionsTreeItem"; import InputsTreeItem from "./inputs"; import RunnersTreeItem from "./runners"; @@ -20,15 +18,12 @@ export default class WorkspaceFolderSettingsTreeItem extends TreeItem implements async getChildren(): Promise { const items: GithubLocalActionsTreeItem[] = []; - const secrets = await act.settingsManager.getSetting(this.workspaceFolder, SettingsManager.secretsRegExp, StorageKey.Secrets, true); - const variables = await act.settingsManager.getSetting(this.workspaceFolder, SettingsManager.variablesRegExp, StorageKey.Variables, false); - const inputs = await act.settingsManager.getSetting(this.workspaceFolder, SettingsManager.inputsRegExp, StorageKey.Inputs, false); - const runners = await act.settingsManager.getSetting(this.workspaceFolder, SettingsManager.runnersRegExp, StorageKey.Runners, false); + const settings = await act.settingsManager.getSettings(this.workspaceFolder, false); items.push(...[ - new SecretsTreeItem(this.workspaceFolder, secrets), - new VariablesTreeItem(this.workspaceFolder, variables), - new InputsTreeItem(this.workspaceFolder, inputs), - new RunnersTreeItem(this.workspaceFolder, runners) + new SecretsTreeItem(this.workspaceFolder, settings.secrets), + new VariablesTreeItem(this.workspaceFolder, settings.variables), + new InputsTreeItem(this.workspaceFolder, settings.inputs), + new RunnersTreeItem(this.workspaceFolder, settings.runners) ]); return items;