From 2f5e5210b4865711380c289837b91d58f4886078 Mon Sep 17 00:00:00 2001 From: Sanjula Ganepola Date: Wed, 20 Nov 2024 20:52:16 -0500 Subject: [PATCH] Add configuration manager and setting for docker desktop path Signed-off-by: Sanjula Ganepola --- package.json | 12 +++++++ src/componentsManager.ts | 55 ++++++++++++++++++++++--------- src/configurationManager.ts | 46 ++++++++++++++++++++++++++ src/extension.ts | 9 +++++ src/views/components/component.ts | 1 + 5 files changed, 108 insertions(+), 15 deletions(-) create mode 100644 src/configurationManager.ts diff --git a/package.json b/package.json index e8c93ae..398763a 100644 --- a/package.json +++ b/package.json @@ -499,6 +499,18 @@ } ] }, + "configuration": { + "title": "GitHub Local Actions", + "properties": { + "githubLocalActions.dockerDesktopPath": { + "type": "string", + "markdownDescription": "The path to your Docker Desktop executable (used for Windows and MacOS). To start Docker Engine from the `Components` view, this application will be launched. Refer to the default path based on OS:\n\n* **Windows**: `C:/Program Files/Docker/Docker/Docker Desktop.exe`\n\n* **MacOS**: `/Applications/Docker.app`\n\n* **Linux**: Not Required", + "items": { + "type": "string" + } + } + } + }, "colors": [ { "id": "GitHubLocalActions.green", diff --git a/src/componentsManager.ts b/src/componentsManager.ts index 80e1d4c..d3400e2 100644 --- a/src/componentsManager.ts +++ b/src/componentsManager.ts @@ -1,11 +1,14 @@ import * as childProcess from "child_process"; -import { env, extensions, QuickPickItemKind, ShellExecution, TaskGroup, TaskPanelKind, TaskRevealKind, tasks, TaskScope, ThemeIcon, Uri, window } from "vscode"; +import { commands, env, extensions, QuickPickItemKind, ShellExecution, TaskGroup, TaskPanelKind, TaskRevealKind, tasks, TaskScope, ThemeIcon, Uri, window } from "vscode"; +import { ConfigurationManager, Platform, Section } from "./configurationManager"; import { act, componentsTreeDataProvider } from "./extension"; +import ComponentsTreeDataProvider from "./views/components/componentsTreeDataProvider"; export interface Component { name: string, icon: string, version?: string, + path?: string, status: T, required: boolean, information: string, @@ -121,10 +124,12 @@ export class ComponentsManager { }); const dockerCliInfo = await this.getCliInfo('docker version', /Client:\n.+\n\sVersion:\s+(.+)/, true, true); + const dockerDesktopPath = ConfigurationManager.get(Section.dockerDesktopPath); components.push({ name: 'Docker Engine', icon: 'dashboard', version: dockerCliInfo.version, + path: dockerDesktopPath, status: dockerCliInfo.status, required: true, information: 'https://docs.docker.com/engine', @@ -132,15 +137,11 @@ export class ComponentsManager { await env.openExternal(Uri.parse('https://docs.docker.com/engine/install')); }, start: async () => { - //TODO: Make the below win32 and darwin paths customizable - switch (process.platform) { - case 'win32': - await env.openExternal(Uri.parse('C:/Program Files/Docker/Docker/Docker Desktop.exe')); - break; - case 'darwin': - await env.openExternal(Uri.parse('/Applications/Docker.app')); - break; - case 'linux': + const dockerDesktopPath = ConfigurationManager.get(Section.dockerDesktopPath); + if (dockerDesktopPath) { + await env.openExternal(Uri.parse(dockerDesktopPath)); + } else { + if (process.platform === Platform.linux) { await tasks.executeTask({ name: 'Docker Engine', detail: 'Start Docker Engine', @@ -162,15 +163,39 @@ export class ComponentsManager { group: TaskGroup.Build, execution: new ShellExecution('sudo dockerd') }); - break; - default: - window.showErrorMessage(`Invalid environment: ${process.platform}`); + } else { + window.showErrorMessage(`Invalid environment: ${process.platform}`, 'Report an Issue').then(async value => { + if (value === 'Report an Issue') { + await commands.executeCommand('githubLocalActions.reportAnIssue'); + } + }); return; + } } - window.showInformationMessage('Once Docker Engine is successfully started (this could take a few seconds), refresh the components view.', 'Refresh').then(async value => { - if (value === 'Refresh') { + window.withProgress({ location: { viewId: ComponentsTreeDataProvider.VIEW_ID } }, async () => { + // Delay 4 seconds for Docker Desktop to be started + const delay = (ms: number) => new Promise(resolve => setTimeout(resolve, ms)); + await delay(4000); + + // Check again for docker status + const newDockerCliInfo = await this.getCliInfo('docker version', /Client:\n.+\n\sVersion:\s+(.+)/, true, true); + if (dockerCliInfo.status !== newDockerCliInfo.status) { componentsTreeDataProvider.refresh(); + } else { + const verificationMessage = process.platform === Platform.linux ? + 'If it failed to start, start it manually.' : + 'If it failed to start, configure your Docker Desktop path or start it manually.'; + const options = process.platform === Platform.linux ? + ['Refresh'] : + ['Refresh', 'Configure Docker Desktop Path']; + window.showInformationMessage(`Once Docker Engine is successfully started, refresh the components view. ${verificationMessage}`, ...options).then(async value => { + if (value === 'Refresh') { + componentsTreeDataProvider.refresh(); + } else if (value === 'Configure Docker Desktop Path') { + await commands.executeCommand('workbench.action.openSettings', ConfigurationManager.getSearchTerm(Section.dockerDesktopPath)); + } + }); } }); } diff --git a/src/configurationManager.ts b/src/configurationManager.ts new file mode 100644 index 0000000..bf047bc --- /dev/null +++ b/src/configurationManager.ts @@ -0,0 +1,46 @@ +import { ConfigurationTarget, workspace } from 'vscode'; + +export enum Platform { + windows = 'win32', + mac = 'darwin', + linux = 'linux' +} + +export enum Section { + dockerDesktopPath = 'dockerDesktopPath' +} + +export namespace ConfigurationManager { + export const group: string = 'githubLocalActions'; + export const searchPrefix: string = '@ext:sanjulaganepola.github-local-actions'; + + export function initialize(): void { + let dockerDesktopPath = ConfigurationManager.get(Section.dockerDesktopPath); + if (!dockerDesktopPath) { + switch (process.platform) { + case Platform.windows: + dockerDesktopPath = 'C:/Program Files/Docker/Docker/Docker Desktop.exe'; + break; + case Platform.mac: + dockerDesktopPath = '/Applications/Docker.app'; + break; + default: + return; + } + + ConfigurationManager.set(Section.dockerDesktopPath, dockerDesktopPath); + } + } + + export function getSearchTerm(section: Section): string { + return `${ConfigurationManager.searchPrefix} ${ConfigurationManager.group}.${section}`; + } + + export function get(section: Section): T | undefined { + return workspace.getConfiguration(ConfigurationManager.group).get(section) as T; + } + + export async function set(section: Section, value: any): Promise { + return await workspace.getConfiguration(ConfigurationManager.group).update(section, value, ConfigurationTarget.Global); + } +} \ No newline at end of file diff --git a/src/extension.ts b/src/extension.ts index 01644a1..c39afb8 100644 --- a/src/extension.ts +++ b/src/extension.ts @@ -1,6 +1,7 @@ import * as vscode from 'vscode'; import { commands, env, TreeCheckboxChangeEvent, Uri, window, workspace } from 'vscode'; import { Act } from './act'; +import { ConfigurationManager } from './configurationManager'; import ComponentsTreeDataProvider from './views/components/componentsTreeDataProvider'; import { DecorationProvider } from './views/decorationProvider'; import { GithubLocalActionsTreeItem } from './views/githubLocalActionsTreeItem'; @@ -49,6 +50,14 @@ export function activate(context: vscode.ExtensionContext) { settingsTreeDataProvider.refresh(); }); + // Initialize configurations + ConfigurationManager.initialize(); + workspace.onDidChangeConfiguration(async event => { + if (event.affectsConfiguration(ConfigurationManager.group)) { + ConfigurationManager.initialize(); + } + }); + context.subscriptions.push( componentsTreeView, workflowsTreeView, diff --git a/src/views/components/component.ts b/src/views/components/component.ts index 490e9e9..bf5ae24 100644 --- a/src/views/components/component.ts +++ b/src/views/components/component.ts @@ -14,6 +14,7 @@ export default class ComponentTreeItem extends TreeItem implements GithubLocalAc this.iconPath = new ThemeIcon(component.icon); this.resourceUri = Uri.parse(`${ComponentTreeItem.contextValue}:${component.name}?status=${component.status}&required=${component.required}`, true); this.tooltip = `Name: ${component.name}\n` + + (component.path ? `Path: ${component.path}\n` : ``) + `Status: ${component.status}\n` + `Required: ${component.required ? 'Yes' : 'No'}\n` + (component.message ? `Message: ${component.message}` : ``);