Add setting to change workflow directory (#188)

Signed-off-by: Sanjula Ganepola <sanjulagane@gmail.com>
This commit is contained in:
Sanjula Ganepola
2025-03-23 18:27:30 -04:00
committed by GitHub
parent 412914d32a
commit e8f3f6c673
6 changed files with 74 additions and 33 deletions

View File

@@ -786,6 +786,11 @@
"type": "string",
"default": "act"
},
"githubLocalActions.workflowsDirectory": {
"markdownDescription": "The relative path to the directory containing your workflows. By default, this will be `.github/workflows`.",
"type": "string",
"default": ".github/workflows"
},
"githubLocalActions.dockerDesktopPath": {
"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`",
"type": "string",

View File

@@ -273,11 +273,12 @@ export class Act {
}
async runWorkflow(workspaceFolder: WorkspaceFolder, workflow: Workflow) {
const workflowsDirectory = WorkflowsManager.getWorkflowsDirectory();
return await this.runCommand({
path: workspaceFolder.uri.fsPath,
workflow: workflow,
options: [
`${Option.Workflows} "${WorkflowsManager.WORKFLOWS_DIRECTORY}/${path.parse(workflow.uri.fsPath).base}"`
`${Option.Workflows} "${workflowsDirectory}/${path.parse(workflow.uri.fsPath).base}"`
],
name: workflow.name,
extraHeader: [
@@ -287,11 +288,12 @@ export class Act {
}
async runJob(workspaceFolder: WorkspaceFolder, workflow: Workflow, job: Job) {
const workflowsDirectory = WorkflowsManager.getWorkflowsDirectory();
return await this.runCommand({
path: workspaceFolder.uri.fsPath,
workflow: workflow,
options: [
`${Option.Workflows} "${WorkflowsManager.WORKFLOWS_DIRECTORY}/${path.parse(workflow.uri.fsPath).base}"`,
`${Option.Workflows} "${workflowsDirectory}/${path.parse(workflow.uri.fsPath).base}"`,
`${Option.Job} "${job.id}"`
],
name: `${workflow.name}/${job.name}`,
@@ -304,7 +306,7 @@ export class Act {
async runEvent(workspaceFolder: WorkspaceFolder, event: Event) {
let eventExists: boolean = false;
const workflowsDirectory = WorkflowsManager.getWorkflowsDirectory();
const workflows = await this.workflowsManager.getWorkflows(workspaceFolder);
if (workflows.length > 0) {
for (const workflow of workflows) {
@@ -314,7 +316,7 @@ export class Act {
path: workspaceFolder.uri.fsPath,
workflow: workflow,
options: [
`${event} ${Option.Workflows} "${WorkflowsManager.WORKFLOWS_DIRECTORY}/${path.parse(workflow.uri.fsPath).base}"`
`${event} ${Option.Workflows} "${workflowsDirectory}/${path.parse(workflow.uri.fsPath).base}"`
],
name: `${workflow.name} (${event})`,
extraHeader: [

View File

@@ -1,5 +1,6 @@
import { ConfigurationTarget, workspace } from 'vscode';
import { Act } from './act';
import { WorkflowsManager } from './workflowsManager';
export enum Platform {
windows = 'win32',
@@ -9,6 +10,7 @@ export enum Platform {
export enum Section {
actCommand = 'actCommand',
workflowsDirectory = 'workflowsDirectory',
dockerDesktopPath = 'dockerDesktopPath'
}
@@ -17,6 +19,16 @@ export namespace ConfigurationManager {
export const searchPrefix: string = '@ext:sanjulaganepola.github-local-actions';
export async function initialize(): Promise<void> {
let actCommand = ConfigurationManager.get<string>(Section.actCommand);
if (!actCommand) {
await ConfigurationManager.set(Section.actCommand, Act.defaultActCommand);
}
let workflowsDirectory = ConfigurationManager.get<string>(Section.workflowsDirectory);
if (!workflowsDirectory) {
await ConfigurationManager.set(Section.workflowsDirectory, WorkflowsManager.defaultWorkflowsDirectory);
}
let dockerDesktopPath = ConfigurationManager.get<string>(Section.dockerDesktopPath);
if (!dockerDesktopPath) {
switch (process.platform) {
@@ -32,11 +44,6 @@ export namespace ConfigurationManager {
await ConfigurationManager.set(Section.dockerDesktopPath, dockerDesktopPath);
}
let actCommand = ConfigurationManager.get<string>(Section.actCommand);
if (!actCommand) {
await ConfigurationManager.set(Section.actCommand, Act.defaultActCommand);
}
}
export function getSearchTerm(section: Section): string {

View File

@@ -1,7 +1,6 @@
import * as vscode from 'vscode';
import { commands, env, TreeCheckboxChangeEvent, Uri, window, workspace } from 'vscode';
import { commands, env, ExtensionContext, TreeCheckboxChangeEvent, Uri, window, workspace } from 'vscode';
import { Act } from './act';
import { ConfigurationManager } from './configurationManager';
import { ConfigurationManager, Section } from './configurationManager';
import { IssueHandler } from './issueHandler';
import ComponentsTreeDataProvider from './views/components/componentsTreeDataProvider';
import { DecorationProvider } from './views/decorationProvider';
@@ -18,7 +17,7 @@ export let workflowsTreeDataProvider: WorkflowsTreeDataProvider;
export let historyTreeDataProvider: HistoryTreeDataProvider;
export let settingsTreeDataProvider: SettingsTreeDataProvider;
export function activate(context: vscode.ExtensionContext) {
export function activate(context: ExtensionContext) {
console.log('Congratulations, your extension "github-local-actions" is now active!');
act = new Act(context);
@@ -38,27 +37,29 @@ export function activate(context: vscode.ExtensionContext) {
});
// Create file watcher
const workflowsFileWatcher = workspace.createFileSystemWatcher(`**/${WorkflowsManager.WORKFLOWS_DIRECTORY}/*.{${WorkflowsManager.YML_EXTENSION},${WorkflowsManager.YAML_EXTENSION}}`);
workflowsFileWatcher.onDidCreate(() => {
workflowsTreeDataProvider.refresh();
settingsTreeDataProvider.refresh();
});
workflowsFileWatcher.onDidChange(() => {
workflowsTreeDataProvider.refresh();
settingsTreeDataProvider.refresh();
});
workflowsFileWatcher.onDidDelete(() => {
workflowsTreeDataProvider.refresh();
settingsTreeDataProvider.refresh();
});
let workflowsFileWatcher = setupFileWatcher(context);
// Initialize configurations
ConfigurationManager.initialize();
workspace.onDidChangeConfiguration(async event => {
if (event.affectsConfiguration(ConfigurationManager.group)) {
await ConfigurationManager.initialize();
if (event.affectsConfiguration(`${ConfigurationManager.group}.${Section.actCommand}`) ||
event.affectsConfiguration(`${ConfigurationManager.group}.${Section.dockerDesktopPath}`)) {
componentsTreeDataProvider.refresh();
}
if (event.affectsConfiguration(`${ConfigurationManager.group}.${Section.workflowsDirectory}`)) {
workflowsTreeDataProvider.refresh();
settingsTreeDataProvider.refresh();
if (workflowsFileWatcher) {
workflowsFileWatcher.dispose();
workflowsFileWatcher = setupFileWatcher(context);
}
}
}
});
context.subscriptions.push(
@@ -77,4 +78,23 @@ export function activate(context: vscode.ExtensionContext) {
);
}
function setupFileWatcher(context: ExtensionContext) {
const workflowsDirectory = WorkflowsManager.getWorkflowsDirectory();
const workflowsFileWatcher = workspace.createFileSystemWatcher(`**/${workflowsDirectory}/*.{${WorkflowsManager.ymlExtension},${WorkflowsManager.yamlExtension}}`);
workflowsFileWatcher.onDidCreate(() => {
workflowsTreeDataProvider.refresh();
settingsTreeDataProvider.refresh();
});
workflowsFileWatcher.onDidChange(() => {
workflowsTreeDataProvider.refresh();
settingsTreeDataProvider.refresh();
});
workflowsFileWatcher.onDidDelete(() => {
workflowsTreeDataProvider.refresh();
settingsTreeDataProvider.refresh();
});
return workflowsFileWatcher;
}
export function deactivate() { }

View File

@@ -61,7 +61,8 @@ export default class WorkflowsTreeDataProvider implements TreeDataProvider<Githu
if (activeTextEditor) {
const uri = activeTextEditor.document.uri;
const fileName = path.parse(uri.fsPath).base;
if (uri.path.match(`.*/${WorkflowsManager.WORKFLOWS_DIRECTORY}/.*\\.(${WorkflowsManager.YAML_EXTENSION}|${WorkflowsManager.YML_EXTENSION})`)) {
const workflowsDirectory = WorkflowsManager.getWorkflowsDirectory();
if (uri.path.match(`.*/${workflowsDirectory}/.*\\.(${WorkflowsManager.yamlExtension}|${WorkflowsManager.ymlExtension})`)) {
const workspaceFolder = workspace.getWorkspaceFolder(uri);
if (workspaceFolder) {
const workflows = await act.workflowsManager.getWorkflows(workspaceFolder);
@@ -69,7 +70,7 @@ export default class WorkflowsTreeDataProvider implements TreeDataProvider<Githu
if (workflow) {
await act.runWorkflow(workspaceFolder, workflow);
} else {
errorMessage = `Workflow not found in workflow directory (${WorkflowsManager.WORKFLOWS_DIRECTORY}).`;
errorMessage = `Workflow not found in workflow directory (${workflowsDirectory}).`;
}
} else {
errorMessage = `${fileName} must be opened in a workspace folder to be executed locally.`;

View File

@@ -2,6 +2,7 @@ import * as fs from "fs/promises";
import * as path from "path";
import { RelativePattern, Uri, workspace, WorkspaceFolder } from "vscode";
import * as yaml from "yaml";
import { ConfigurationManager, Section } from "./configurationManager";
export interface Workflow {
name: string,
@@ -17,14 +18,19 @@ export interface Job {
}
export class WorkflowsManager {
static WORKFLOWS_DIRECTORY: string = '.github/workflows';
static YAML_EXTENSION: string = 'yaml';
static YML_EXTENSION: string = 'yml';
static defaultWorkflowsDirectory: string = '.github/workflows';
static yamlExtension: string = 'yaml';
static ymlExtension: string = 'yml';
static getWorkflowsDirectory(): string {
return ConfigurationManager.get<string>(Section.workflowsDirectory) || WorkflowsManager.defaultWorkflowsDirectory;
}
async getWorkflows(workspaceFolder: WorkspaceFolder): Promise<Workflow[]> {
const workflows: Workflow[] = [];
const workflowFileUris = await workspace.findFiles(new RelativePattern(workspaceFolder, `${WorkflowsManager.WORKFLOWS_DIRECTORY}/*.{${WorkflowsManager.YAML_EXTENSION},${WorkflowsManager.YML_EXTENSION}}`));
const workflowsDirectory = WorkflowsManager.getWorkflowsDirectory();
const workflowFileUris = await workspace.findFiles(new RelativePattern(workspaceFolder, `${workflowsDirectory}/*.{${WorkflowsManager.yamlExtension},${WorkflowsManager.ymlExtension}}`));
for await (const workflowFileUri of workflowFileUris) {
let yamlContent: any | undefined;