From b30fc76de52348fceb2aba85265d8a26e94fc42f Mon Sep 17 00:00:00 2001 From: Sanjula Ganepola Date: Sun, 29 Sep 2024 11:28:03 -0400 Subject: [PATCH] Add settings view Signed-off-by: Sanjula Ganepola --- src/settingsManager.ts | 69 +++++++++++++++++-- src/views/settings/environment.ts | 17 +++++ src/views/settings/environments.ts | 6 +- src/views/settings/input.ts | 18 +++++ src/views/settings/inputs.ts | 20 ++++++ src/views/settings/secret.ts | 18 +++++ src/views/settings/secrets.ts | 6 +- .../settings/settingsTreeDataProvider.ts | 4 +- src/views/settings/variable.ts | 18 +++++ src/views/settings/variables.ts | 6 +- src/workflowsManager.ts | 6 +- 11 files changed, 178 insertions(+), 10 deletions(-) create mode 100644 src/views/settings/environment.ts create mode 100644 src/views/settings/input.ts create mode 100644 src/views/settings/inputs.ts create mode 100644 src/views/settings/secret.ts create mode 100644 src/views/settings/variable.ts diff --git a/src/settingsManager.ts b/src/settingsManager.ts index f532e9c..b42cd98 100644 --- a/src/settingsManager.ts +++ b/src/settingsManager.ts @@ -1,5 +1,7 @@ -export interface Environment { +import { Workflow } from "./workflowsManager"; +export interface Environment { + name: string } export interface Secret { @@ -12,8 +14,67 @@ export interface Variable { value?: string } +export interface Input { + key: string, + value?: string +} + export class SettingsManager { - environments: Environment[] = []; - secrets: Secret[] = []; - variables: Variable[] = []; + getEnvironments(workflow: Workflow): Environment[] { + const environments: Environment[] = []; + if (!workflow.yaml) { + return environments; + } + + const jobs = workflow.yaml?.jobs; + if (jobs) { + for (const details of Object.values(jobs)) { + if (details.environment) { + environments.push({ + name: details.environment + }); + } + } + } + + return environments; + } + + getSecrets(workflow: Workflow): Secret[] { + const secrets: Secret[] = []; + if (!workflow.fileContent) { + return secrets; + } + + return this.findInWorkflow(workflow.fileContent, /\${{\s*secrets\.(.*?)\s*}}/g); + } + + getVariables(workflow: Workflow): Variable[] { + const variables: Variable[] = []; + if (!workflow.fileContent) { + return variables; + } + + return this.findInWorkflow(workflow.fileContent, /\${{\s*vars\.(.*?)(?:\s*==\s*(.*?))?\s*}}/g); + } + + getInputs(workflow: Workflow): Input[] { + const inputs: Variable[] = []; + if (!workflow.fileContent) { + return inputs; + } + + return this.findInWorkflow(workflow.fileContent, /\${{\s*(?:inputs|github\.event\.inputs)\.(.*?)(?:\s*==\s*(.*?))?\s*}}/g); + } + + 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] }); + } + + return results; + } } \ No newline at end of file diff --git a/src/views/settings/environment.ts b/src/views/settings/environment.ts new file mode 100644 index 0000000..c08f005 --- /dev/null +++ b/src/views/settings/environment.ts @@ -0,0 +1,17 @@ +import { ThemeIcon, TreeItem, TreeItemCollapsibleState } 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) { + super(environment.name, TreeItemCollapsibleState.None); + this.contextValue = EnvironmentTreeItem.contextValue; + this.iconPath = new ThemeIcon('server'); + } + + async getChildren(): Promise { + return []; + } +} \ No newline at end of file diff --git a/src/views/settings/environments.ts b/src/views/settings/environments.ts index 90498f1..0e4b5a8 100644 --- a/src/views/settings/environments.ts +++ b/src/views/settings/environments.ts @@ -1,5 +1,7 @@ import { ThemeIcon, TreeItem, TreeItemCollapsibleState } from "vscode"; +import { act } from "../../extension"; import { GithubLocalActionsTreeItem } from "../githubLocalActionsTreeItem"; +import EnvironmentTreeItem from "./environment"; export default class EnvironmentsTreeItem extends TreeItem implements GithubLocalActionsTreeItem { static contextValue = 'githubLocalActions.environments'; @@ -11,6 +13,8 @@ export default class EnvironmentsTreeItem extends TreeItem implements GithubLoca } async getChildren(): Promise { - return []; + const workflows = await act.workflowsManager.getWorkflows(); + const environments = [...new Set(workflows.map(workflow => act.settingsManager.getEnvironments(workflow)).flat())]; + return environments.map(environment => new EnvironmentTreeItem(environment)); } } \ No newline at end of file diff --git a/src/views/settings/input.ts b/src/views/settings/input.ts new file mode 100644 index 0000000..4c59562 --- /dev/null +++ b/src/views/settings/input.ts @@ -0,0 +1,18 @@ +import { ThemeIcon, TreeItem, TreeItemCollapsibleState } 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) { + super(input.key, TreeItemCollapsibleState.None); + this.description = input.value; + this.contextValue = InputTreeItem.contextValue; + this.iconPath = new ThemeIcon('symbol-parameter'); + } + + async getChildren(): Promise { + return []; + } +} \ No newline at end of file diff --git a/src/views/settings/inputs.ts b/src/views/settings/inputs.ts new file mode 100644 index 0000000..aee4011 --- /dev/null +++ b/src/views/settings/inputs.ts @@ -0,0 +1,20 @@ +import { ThemeIcon, TreeItem, TreeItemCollapsibleState } from "vscode"; +import { act } from "../../extension"; +import { GithubLocalActionsTreeItem } from "../githubLocalActionsTreeItem"; +import InputTreeItem from "./input"; + +export default class InputsTreeItem extends TreeItem implements GithubLocalActionsTreeItem { + static contextValue = 'githubLocalActions.inputs'; + + constructor() { + super('Inputs', TreeItemCollapsibleState.Collapsed); + this.contextValue = InputsTreeItem.contextValue; + this.iconPath = new ThemeIcon('record-keys'); + } + + async getChildren(): Promise { + const workflows = await act.workflowsManager.getWorkflows(); + const inputs = [...new Set(workflows.map(workflow => act.settingsManager.getInputs(workflow)).flat())]; + return inputs.map(input => new InputTreeItem(input)); + } +} \ No newline at end of file diff --git a/src/views/settings/secret.ts b/src/views/settings/secret.ts new file mode 100644 index 0000000..092d650 --- /dev/null +++ b/src/views/settings/secret.ts @@ -0,0 +1,18 @@ +import { ThemeIcon, TreeItem, TreeItemCollapsibleState } 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) { + super(secret.key, TreeItemCollapsibleState.None); + this.description = secret.value; + this.contextValue = SecretTreeItem.contextValue; + this.iconPath = new ThemeIcon('key'); + } + + async getChildren(): Promise { + return []; + } +} \ No newline at end of file diff --git a/src/views/settings/secrets.ts b/src/views/settings/secrets.ts index 95765e5..123ca5e 100644 --- a/src/views/settings/secrets.ts +++ b/src/views/settings/secrets.ts @@ -1,5 +1,7 @@ import { ThemeIcon, TreeItem, TreeItemCollapsibleState } from "vscode"; +import { act } from "../../extension"; import { GithubLocalActionsTreeItem } from "../githubLocalActionsTreeItem"; +import SecretTreeItem from "./secret"; export default class SecretsTreeItem extends TreeItem implements GithubLocalActionsTreeItem { static contextValue = 'githubLocalActions.secrets'; @@ -11,6 +13,8 @@ export default class SecretsTreeItem extends TreeItem implements GithubLocalActi } async getChildren(): Promise { - return []; + const workflows = await act.workflowsManager.getWorkflows(); + const secrets = [...new Set(workflows.map(workflow => act.settingsManager.getSecrets(workflow)).flat())]; + return secrets.map(secret => new SecretTreeItem(secret)); } } \ No newline at end of file diff --git a/src/views/settings/settingsTreeDataProvider.ts b/src/views/settings/settingsTreeDataProvider.ts index a2589e4..8633f16 100644 --- a/src/views/settings/settingsTreeDataProvider.ts +++ b/src/views/settings/settingsTreeDataProvider.ts @@ -1,6 +1,7 @@ import { CancellationToken, commands, EventEmitter, ExtensionContext, TreeDataProvider, TreeItem } from "vscode"; import { GithubLocalActionsTreeItem } from "../githubLocalActionsTreeItem"; import EnvironmentsTreeItem from "./environments"; +import InputsTreeItem from "./inputs"; import SecretsTreeItem from "./secrets"; import VariablesTreeItem from "./variables"; @@ -40,7 +41,8 @@ export default class SettingsTreeDataProvider implements TreeDataProvider { + return []; + } +} \ No newline at end of file diff --git a/src/views/settings/variables.ts b/src/views/settings/variables.ts index 7d350dd..4a6d633 100644 --- a/src/views/settings/variables.ts +++ b/src/views/settings/variables.ts @@ -1,5 +1,7 @@ import { ThemeIcon, TreeItem, TreeItemCollapsibleState } from "vscode"; +import { act } from "../../extension"; import { GithubLocalActionsTreeItem } from "../githubLocalActionsTreeItem"; +import VariableTreeItem from "./variable"; export default class VariablesTreeItem extends TreeItem implements GithubLocalActionsTreeItem { static contextValue = 'githubLocalActions.variables'; @@ -11,6 +13,8 @@ export default class VariablesTreeItem extends TreeItem implements GithubLocalAc } async getChildren(): Promise { - return []; + const workflows = await act.workflowsManager.getWorkflows(); + const variables = [...new Set(workflows.map(workflow => act.settingsManager.getVariables(workflow)).flat())]; + return variables.map(variable => new VariableTreeItem(variable)); } } \ No newline at end of file diff --git a/src/workflowsManager.ts b/src/workflowsManager.ts index ed27503..5fb15d4 100644 --- a/src/workflowsManager.ts +++ b/src/workflowsManager.ts @@ -6,7 +6,8 @@ import * as yaml from "yaml"; export interface Workflow { name: string, uri: Uri, - content?: any, + fileContent?: string, + yaml?: any, error?: string } @@ -65,7 +66,8 @@ export class WorkflowsManager { workflows.push({ name: yamlContent.name || path.parse(workflowFileUri.fsPath).name, uri: workflowFileUri, - content: yaml.parse(fileContent) + fileContent: fileContent, + yaml: yaml.parse(fileContent) }); } catch (error) { workflows.push({