feat: Add Gitea workflow support (.gitea/workflows) - Support for both .github/workflows and .gitea/workflows directories - Fixed workflow execution path resolution - Cleaned up debugging code - Updated to version 1.2.5
Some checks failed
Test Gitea Workflow / test (push) Has been cancelled

This commit is contained in:
2025-08-03 23:00:22 +07:00
parent bc25f97d70
commit adf88e431c
8 changed files with 4699 additions and 1318 deletions

View File

@@ -0,0 +1,21 @@
name: Test Gitea Workflow
run-name: Test Gitea Workflow
on:
push:
branches: [main]
pull_request:
branches: [main]
jobs:
test:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Run tests
run: echo "Testing Gitea workflow"
- name: Build
run: echo "Building project"

2935
src/Extension Host.log Normal file

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -1,22 +1,21 @@
import { ConfigurationTarget, workspace } from 'vscode';
import { Act } from './act';
import { WorkflowsManager } from './workflowsManager';
import { ConfigurationTarget, workspace } from "vscode";
import { Act } from "./act";
export enum Platform {
windows = 'win32',
mac = 'darwin',
linux = 'linux'
windows = "win32",
mac = "darwin",
linux = "linux",
}
export enum Section {
actCommand = 'actCommand',
workflowsDirectory = 'workflowsDirectory',
dockerDesktopPath = 'dockerDesktopPath'
actCommand = "actCommand",
dockerDesktopPath = "dockerDesktopPath",
}
export namespace ConfigurationManager {
export const group: string = 'githubLocalActions';
export const searchPrefix: string = '@ext:sanjulaganepola.github-local-actions';
export const group: string = "githubLocalActions";
export const searchPrefix: string =
"@ext:sanjulaganepola.github-local-actions";
export async function initialize(): Promise<void> {
let actCommand = ConfigurationManager.get<string>(Section.actCommand);
@@ -24,25 +23,32 @@ export namespace ConfigurationManager {
await ConfigurationManager.set(Section.actCommand, Act.defaultActCommand);
}
let workflowsDirectory = ConfigurationManager.get<string>(Section.workflowsDirectory);
if (!workflowsDirectory) {
await ConfigurationManager.set(Section.workflowsDirectory, WorkflowsManager.defaultWorkflowsDirectory);
}
// Don't set a default workflows directory to allow multi-directory support
// let workflowsDirectory = ConfigurationManager.get<string>(Section.workflowsDirectory);
// if (!workflowsDirectory) {
// await ConfigurationManager.set(Section.workflowsDirectory, WorkflowsManager.defaultWorkflowsDirectory);
// }
let dockerDesktopPath = ConfigurationManager.get<string>(Section.dockerDesktopPath);
let dockerDesktopPath = ConfigurationManager.get<string>(
Section.dockerDesktopPath
);
if (!dockerDesktopPath) {
switch (process.platform) {
case Platform.windows:
dockerDesktopPath = 'C:/Program Files/Docker/Docker/Docker Desktop.exe';
dockerDesktopPath =
"C:/Program Files/Docker/Docker/Docker Desktop.exe";
break;
case Platform.mac:
dockerDesktopPath = '/Applications/Docker.app';
dockerDesktopPath = "/Applications/Docker.app";
break;
default:
return;
}
await ConfigurationManager.set(Section.dockerDesktopPath, dockerDesktopPath);
await ConfigurationManager.set(
Section.dockerDesktopPath,
dockerDesktopPath
);
}
}
@@ -51,10 +57,14 @@ export namespace ConfigurationManager {
}
export function get<T>(section: Section): T | undefined {
return workspace.getConfiguration(ConfigurationManager.group).get(section) as T;
return workspace
.getConfiguration(ConfigurationManager.group)
.get(section) as T;
}
export async function set(section: Section, value: any): Promise<void> {
return await workspace.getConfiguration(ConfigurationManager.group).update(section, value, ConfigurationTarget.Global);
return await workspace
.getConfiguration(ConfigurationManager.group)
.update(section, value, ConfigurationTarget.Global);
}
}

View File

@@ -1,15 +1,23 @@
import { commands, env, ExtensionContext, TreeCheckboxChangeEvent, Uri, window, workspace } from 'vscode';
import { Act } from './act';
import { ConfigurationManager, Section } from './configurationManager';
import { IssueHandler } from './issueHandler';
import ComponentsTreeDataProvider from './views/components/componentsTreeDataProvider';
import { DecorationProvider } from './views/decorationProvider';
import { GithubLocalActionsTreeItem } from './views/githubLocalActionsTreeItem';
import HistoryTreeDataProvider from './views/history/historyTreeDataProvider';
import SettingTreeItem from './views/settings/setting';
import SettingsTreeDataProvider from './views/settings/settingsTreeDataProvider';
import WorkflowsTreeDataProvider from './views/workflows/workflowsTreeDataProvider';
import { WorkflowsManager } from './workflowsManager';
import {
commands,
env,
ExtensionContext,
TreeCheckboxChangeEvent,
Uri,
window,
workspace,
} from "vscode";
import { Act } from "./act";
import { ConfigurationManager, Section } from "./configurationManager";
import { IssueHandler } from "./issueHandler";
import ComponentsTreeDataProvider from "./views/components/componentsTreeDataProvider";
import { DecorationProvider } from "./views/decorationProvider";
import { GithubLocalActionsTreeItem } from "./views/githubLocalActionsTreeItem";
import HistoryTreeDataProvider from "./views/history/historyTreeDataProvider";
import SettingTreeItem from "./views/settings/setting";
import SettingsTreeDataProvider from "./views/settings/settingsTreeDataProvider";
import WorkflowsTreeDataProvider from "./views/workflows/workflowsTreeDataProvider";
import { WorkflowsManager } from "./workflowsManager";
export let act: Act;
export let componentsTreeDataProvider: ComponentsTreeDataProvider;
@@ -18,47 +26,63 @@ export let historyTreeDataProvider: HistoryTreeDataProvider;
export let settingsTreeDataProvider: SettingsTreeDataProvider;
export function activate(context: ExtensionContext) {
console.log('Congratulations, your extension "github-local-actions" is now active!');
console.log(
'Congratulations, your extension "github-local-actions" is now active!'
);
act = new Act(context);
// Create tree views
const decorationProvider = new DecorationProvider();
componentsTreeDataProvider = new ComponentsTreeDataProvider(context);
const componentsTreeView = window.createTreeView(ComponentsTreeDataProvider.VIEW_ID, { treeDataProvider: componentsTreeDataProvider, showCollapseAll: true });
const componentsTreeView = window.createTreeView(
ComponentsTreeDataProvider.VIEW_ID,
{ treeDataProvider: componentsTreeDataProvider, showCollapseAll: true }
);
workflowsTreeDataProvider = new WorkflowsTreeDataProvider(context);
const workflowsTreeView = window.createTreeView(WorkflowsTreeDataProvider.VIEW_ID, { treeDataProvider: workflowsTreeDataProvider, showCollapseAll: true });
const workflowsTreeView = window.createTreeView(
WorkflowsTreeDataProvider.VIEW_ID,
{ treeDataProvider: workflowsTreeDataProvider, showCollapseAll: true }
);
historyTreeDataProvider = new HistoryTreeDataProvider(context);
const historyTreeView = window.createTreeView(HistoryTreeDataProvider.VIEW_ID, { treeDataProvider: historyTreeDataProvider, showCollapseAll: true });
const historyTreeView = window.createTreeView(
HistoryTreeDataProvider.VIEW_ID,
{ treeDataProvider: historyTreeDataProvider, showCollapseAll: true }
);
settingsTreeDataProvider = new SettingsTreeDataProvider(context);
const settingsTreeView = window.createTreeView(SettingsTreeDataProvider.VIEW_ID, { treeDataProvider: settingsTreeDataProvider, showCollapseAll: true });
settingsTreeView.onDidChangeCheckboxState(async (event: TreeCheckboxChangeEvent<GithubLocalActionsTreeItem>) => {
await settingsTreeDataProvider.onDidChangeCheckboxState(event as TreeCheckboxChangeEvent<SettingTreeItem>);
});
const settingsTreeView = window.createTreeView(
SettingsTreeDataProvider.VIEW_ID,
{ treeDataProvider: settingsTreeDataProvider, showCollapseAll: true }
);
settingsTreeView.onDidChangeCheckboxState(
async (event: TreeCheckboxChangeEvent<GithubLocalActionsTreeItem>) => {
await settingsTreeDataProvider.onDidChangeCheckboxState(
event as TreeCheckboxChangeEvent<SettingTreeItem>
);
}
);
// Create file watcher
let workflowsFileWatcher = setupFileWatcher(context);
// Initialize configurations
ConfigurationManager.initialize();
workspace.onDidChangeConfiguration(async event => {
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}`)) {
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);
}
}
}
});
@@ -69,18 +93,31 @@ export function activate(context: ExtensionContext) {
settingsTreeView,
window.registerFileDecorationProvider(decorationProvider),
workflowsFileWatcher,
commands.registerCommand('githubLocalActions.viewDocumentation', async () => {
await env.openExternal(Uri.parse('https://sanjulaganepola.github.io/github-local-actions-docs'));
}),
commands.registerCommand('githubLocalActions.reportAnIssue', async () => {
commands.registerCommand(
"githubLocalActions.viewDocumentation",
async () => {
await env.openExternal(
Uri.parse(
"https://sanjulaganepola.github.io/github-local-actions-docs"
)
);
}
),
commands.registerCommand("githubLocalActions.reportAnIssue", async () => {
await IssueHandler.openBugReport(context);
}),
})
);
}
function setupFileWatcher(context: ExtensionContext) {
const workflowsDirectory = WorkflowsManager.getWorkflowsDirectory();
const workflowsFileWatcher = workspace.createFileSystemWatcher(`**/${workflowsDirectory}/*.{${WorkflowsManager.ymlExtension},${WorkflowsManager.yamlExtension}}`);
const workflowsDirectories = WorkflowsManager.getWorkflowsDirectories();
const fileWatchers: any[] = [];
for (const workflowsDirectory of workflowsDirectories) {
const workflowsFileWatcher = workspace.createFileSystemWatcher(
`**/${workflowsDirectory}/*.{${WorkflowsManager.ymlExtension},${WorkflowsManager.yamlExtension}}`
);
workflowsFileWatcher.onDidCreate(() => {
workflowsTreeDataProvider.refresh();
settingsTreeDataProvider.refresh();
@@ -94,7 +131,15 @@ function setupFileWatcher(context: ExtensionContext) {
settingsTreeDataProvider.refresh();
});
return workflowsFileWatcher;
fileWatchers.push(workflowsFileWatcher);
}
// Return a disposable that disposes all watchers
return {
dispose: () => {
fileWatchers.forEach((watcher) => watcher.dispose());
},
};
}
export function deactivate() {}

View File

@@ -1,5 +1,14 @@
import * as path from "path";
import { CancellationToken, commands, EventEmitter, ExtensionContext, TreeDataProvider, TreeItem, window, workspace } from "vscode";
import {
CancellationToken,
commands,
EventEmitter,
ExtensionContext,
TreeDataProvider,
TreeItem,
window,
workspace,
} from "vscode";
import { Event } from "../../act";
import { act } from "../../extension";
import { Utils } from "../../utils";
@@ -9,51 +18,88 @@ import JobTreeItem from "./job";
import WorkflowTreeItem from "./workflow";
import WorkspaceFolderWorkflowsTreeItem from "./workspaceFolderWorkflows";
export default class WorkflowsTreeDataProvider implements TreeDataProvider<GithubLocalActionsTreeItem> {
private _onDidChangeTreeData = new EventEmitter<GithubLocalActionsTreeItem | undefined | null | void>();
export default class WorkflowsTreeDataProvider
implements TreeDataProvider<GithubLocalActionsTreeItem>
{
private _onDidChangeTreeData = new EventEmitter<
GithubLocalActionsTreeItem | undefined | null | void
>();
readonly onDidChangeTreeData = this._onDidChangeTreeData.event;
static VIEW_ID = 'workflows';
static VIEW_ID = "workflows";
constructor(context: ExtensionContext) {
context.subscriptions.push(
commands.registerCommand('githubLocalActions.runAllWorkflows', async (workspaceFolderWorkflowsTreeItem?: WorkspaceFolderWorkflowsTreeItem) => {
const workspaceFolder = await Utils.getWorkspaceFolder(workspaceFolderWorkflowsTreeItem?.workspaceFolder);
commands.registerCommand(
"githubLocalActions.runAllWorkflows",
async (
workspaceFolderWorkflowsTreeItem?: WorkspaceFolderWorkflowsTreeItem
) => {
const workspaceFolder = await Utils.getWorkspaceFolder(
workspaceFolderWorkflowsTreeItem?.workspaceFolder
);
if (workspaceFolder) {
await act.runAllWorkflows(workspaceFolder);
}
}),
commands.registerCommand('githubLocalActions.runEvent', async (workspaceFolderWorkflowsTreeItem?: WorkspaceFolderWorkflowsTreeItem) => {
const workspaceFolder = await Utils.getWorkspaceFolder(workspaceFolderWorkflowsTreeItem?.workspaceFolder);
}
),
commands.registerCommand(
"githubLocalActions.runEvent",
async (
workspaceFolderWorkflowsTreeItem?: WorkspaceFolderWorkflowsTreeItem
) => {
const workspaceFolder = await Utils.getWorkspaceFolder(
workspaceFolderWorkflowsTreeItem?.workspaceFolder
);
if (workspaceFolder) {
const event = await window.showQuickPick(Object.values(Event), {
title: 'Select the event to run',
placeHolder: 'Event'
title: "Select the event to run",
placeHolder: "Event",
});
if (event) {
await act.runEvent(workspaceFolder, event as Event);
}
}
}),
commands.registerCommand('githubLocalActions.refreshWorkflows', async () => {
}
),
commands.registerCommand(
"githubLocalActions.refreshWorkflows",
async () => {
this.refresh();
}),
commands.registerCommand('githubLocalActions.openWorkflow', async (workflowTreeItem: WorkflowTreeItem) => {
}
),
commands.registerCommand(
"githubLocalActions.openWorkflow",
async (workflowTreeItem: WorkflowTreeItem) => {
try {
const document = await workspace.openTextDocument(workflowTreeItem.workflow.uri);
const document = await workspace.openTextDocument(
workflowTreeItem.workflow.uri
);
await window.showTextDocument(document);
} catch (error: any) {
try {
await workspace.fs.stat(workflowTreeItem.workflow.uri);
window.showErrorMessage(`Failed to open workflow. Error: ${error}`);
window.showErrorMessage(
`Failed to open workflow. Error: ${error}`
);
} catch (error: any) {
window.showErrorMessage(`Workflow ${path.parse(workflowTreeItem.workflow.uri.fsPath).base} not found.`);
window.showErrorMessage(
`Workflow ${
path.parse(workflowTreeItem.workflow.uri.fsPath).base
} not found.`
);
}
}
}),
commands.registerCommand('githubLocalActions.runWorkflow', async (workflowTreeItem: WorkflowTreeItem) => {
}
),
commands.registerCommand(
"githubLocalActions.runWorkflow",
async (workflowTreeItem: WorkflowTreeItem) => {
if (workflowTreeItem) {
await act.runWorkflow(workflowTreeItem.workspaceFolder, workflowTreeItem.workflow);
await act.runWorkflow(
workflowTreeItem.workspaceFolder,
workflowTreeItem.workflow
);
} else {
let errorMessage: string | undefined;
@@ -61,12 +107,21 @@ export default class WorkflowsTreeDataProvider implements TreeDataProvider<Githu
if (activeTextEditor) {
const uri = activeTextEditor.document.uri;
const fileName = path.parse(uri.fsPath).base;
const workflowsDirectory = WorkflowsManager.getWorkflowsDirectory();
if (uri.path.match(`.*/${workflowsDirectory}/.*\\.(${WorkflowsManager.yamlExtension}|${WorkflowsManager.ymlExtension})`)) {
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);
const workflow = workflows.find(workflow => workflow.uri.fsPath === uri.fsPath);
const workflows = await act.workflowsManager.getWorkflows(
workspaceFolder
);
const workflow = workflows.find(
(workflow) => workflow.uri.fsPath === uri.fsPath
);
if (workflow) {
await act.runWorkflow(workspaceFolder, workflow);
} else {
@@ -79,57 +134,91 @@ export default class WorkflowsTreeDataProvider implements TreeDataProvider<Githu
errorMessage = `${fileName} is not a workflow that can be executed locally.`;
}
} else {
errorMessage = 'No workflow opened to execute locally.';
errorMessage = "No workflow opened to execute locally.";
}
if (errorMessage) {
window.showErrorMessage(errorMessage, 'View Workflows').then(async value => {
if (value === 'View Workflows') {
await commands.executeCommand('workflows.focus');
window
.showErrorMessage(errorMessage, "View Workflows")
.then(async (value) => {
if (value === "View Workflows") {
await commands.executeCommand("workflows.focus");
}
});
}
}
}),
commands.registerCommand('githubLocalActions.runJob', async (jobTreeItem: JobTreeItem) => {
await act.runJob(jobTreeItem.workspaceFolder, jobTreeItem.workflow, jobTreeItem.job);
}),
commands.registerCommand('githubLocalActions.runWorkflowEvent', async (workflowTreeItem: WorkflowTreeItem) => {
}
),
commands.registerCommand(
"githubLocalActions.runJob",
async (jobTreeItem: JobTreeItem) => {
await act.runJob(
jobTreeItem.workspaceFolder,
jobTreeItem.workflow,
jobTreeItem.job
);
}
),
commands.registerCommand(
"githubLocalActions.runWorkflowEvent",
async (workflowTreeItem: WorkflowTreeItem) => {
// Filter to only events that are registered on the workflow
const registeredEventsOnWorkflow = Object.keys(workflowTreeItem.workflow.yaml.on);
const registeredEventsOnWorkflow = Object.keys(
workflowTreeItem.workflow.yaml.on
);
if (registeredEventsOnWorkflow.length === 0) {
window.showErrorMessage(`No events registered on the workflow (${workflowTreeItem.workflow.name}). Add an event to the \`on\` section of the workflow to trigger it.`);
window.showErrorMessage(
`No events registered on the workflow (${workflowTreeItem.workflow.name}). Add an event to the \`on\` section of the workflow to trigger it.`
);
return;
}
const event = await window.showQuickPick(registeredEventsOnWorkflow, {
title: 'Select the event to run',
placeHolder: 'Event',
title: "Select the event to run",
placeHolder: "Event",
});
if (event) {
await act.runEvent(workflowTreeItem.workspaceFolder, event as Event, { workflow: workflowTreeItem.workflow });
await act.runEvent(
workflowTreeItem.workspaceFolder,
event as Event,
{ workflow: workflowTreeItem.workflow }
);
}
}),
commands.registerCommand('githubLocalActions.runJobEvent', async (jobTreeItem: JobTreeItem) => {
}
),
commands.registerCommand(
"githubLocalActions.runJobEvent",
async (jobTreeItem: JobTreeItem) => {
// Filter to only events that are registered on the job's parent workflow
const registeredEventsOnJobParentWorkflow = Object.keys(jobTreeItem.workflow.yaml.on);
const registeredEventsOnJobParentWorkflow = Object.keys(
jobTreeItem.workflow.yaml.on
);
if (registeredEventsOnJobParentWorkflow.length === 0) {
window.showErrorMessage(`No events registered on the workflow (${jobTreeItem.workflow.name}). Add an event to the \`on\` section of the workflow to trigger it.`);
window.showErrorMessage(
`No events registered on the workflow (${jobTreeItem.workflow.name}). Add an event to the \`on\` section of the workflow to trigger it.`
);
return;
}
const event = await window.showQuickPick(registeredEventsOnJobParentWorkflow, {
title: 'Select the event to run',
placeHolder: 'Event'
});
const event = await window.showQuickPick(
registeredEventsOnJobParentWorkflow,
{
title: "Select the event to run",
placeHolder: "Event",
}
);
if (event) {
await act.runEvent(jobTreeItem.workspaceFolder, event as Event, { workflow: jobTreeItem.workflow, job: jobTreeItem.job });
await act.runEvent(jobTreeItem.workspaceFolder, event as Event, {
workflow: jobTreeItem.workflow,
job: jobTreeItem.job,
});
}
})
}
)
);
}
@@ -137,11 +226,17 @@ export default class WorkflowsTreeDataProvider implements TreeDataProvider<Githu
this._onDidChangeTreeData.fire(element);
}
getTreeItem(element: GithubLocalActionsTreeItem): GithubLocalActionsTreeItem | Thenable<GithubLocalActionsTreeItem> {
getTreeItem(
element: GithubLocalActionsTreeItem
): GithubLocalActionsTreeItem | Thenable<GithubLocalActionsTreeItem> {
return element;
}
async resolveTreeItem(item: TreeItem, element: GithubLocalActionsTreeItem, token: CancellationToken): Promise<GithubLocalActionsTreeItem> {
async resolveTreeItem(
item: TreeItem,
element: GithubLocalActionsTreeItem,
token: CancellationToken
): Promise<GithubLocalActionsTreeItem> {
if (element.getToolTip) {
element.tooltip = await element.getToolTip();
}
@@ -149,7 +244,9 @@ export default class WorkflowsTreeDataProvider implements TreeDataProvider<Githu
return element;
}
async getChildren(element?: GithubLocalActionsTreeItem): Promise<GithubLocalActionsTreeItem[]> {
async getChildren(
element?: GithubLocalActionsTreeItem
): Promise<GithubLocalActionsTreeItem[]> {
if (element) {
return element.getChildren();
} else {
@@ -159,9 +256,15 @@ export default class WorkflowsTreeDataProvider implements TreeDataProvider<Githu
const workspaceFolders = workspace.workspaceFolders;
if (workspaceFolders) {
if (workspaceFolders.length === 1) {
items.push(...await new WorkspaceFolderWorkflowsTreeItem(workspaceFolders[0]).getChildren());
items.push(
...(await new WorkspaceFolderWorkflowsTreeItem(
workspaceFolders[0]
).getChildren())
);
const workflows = await act.workflowsManager.getWorkflows(workspaceFolders[0]);
const workflows = await act.workflowsManager.getWorkflows(
workspaceFolders[0]
);
if (workflows && workflows.length > 0) {
noWorkflows = false;
}
@@ -169,7 +272,9 @@ export default class WorkflowsTreeDataProvider implements TreeDataProvider<Githu
for (const workspaceFolder of workspaceFolders) {
items.push(new WorkspaceFolderWorkflowsTreeItem(workspaceFolder));
const workflows = await act.workflowsManager.getWorkflows(workspaceFolder);
const workflows = await act.workflowsManager.getWorkflows(
workspaceFolder
);
if (workflows && workflows.length > 0) {
noWorkflows = false;
}
@@ -177,7 +282,11 @@ export default class WorkflowsTreeDataProvider implements TreeDataProvider<Githu
}
}
await commands.executeCommand('setContext', 'githubLocalActions:noWorkflows', noWorkflows);
await commands.executeCommand(
"setContext",
"githubLocalActions:noWorkflows",
noWorkflows
);
return items;
}
}

View File

@@ -2,56 +2,83 @@ 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,
uri: Uri,
fileContent?: string,
yaml?: any,
error?: string
name: string;
uri: Uri;
fileContent?: string;
yaml?: any;
error?: string;
}
export interface Job {
name: string
id: string
name: string;
id: string;
}
export class WorkflowsManager {
static defaultWorkflowsDirectory: string = '.github/workflows';
static yamlExtension: string = 'yaml';
static ymlExtension: string = 'yml';
static defaultWorkflowsDirectory: string = ".github/workflows";
static giteaWorkflowsDirectory: string = ".gitea/workflows";
static yamlExtension: string = "yaml";
static ymlExtension: string = "yml";
static getWorkflowsDirectories(): string[] {
const directories = [
WorkflowsManager.defaultWorkflowsDirectory,
WorkflowsManager.giteaWorkflowsDirectory,
];
return directories;
}
static getWorkflowsDirectory(): string {
return ConfigurationManager.get<string>(Section.workflowsDirectory) || WorkflowsManager.defaultWorkflowsDirectory;
return WorkflowsManager.defaultWorkflowsDirectory;
}
async getWorkflows(workspaceFolder: WorkspaceFolder): Promise<Workflow[]> {
const workflows: Workflow[] = [];
const workflowsDirectory = WorkflowsManager.getWorkflowsDirectory();
const workflowFileUris = await workspace.findFiles(new RelativePattern(workspaceFolder, `${workflowsDirectory}/*.{${WorkflowsManager.yamlExtension},${WorkflowsManager.ymlExtension}}`));
const workflowsDirectories = WorkflowsManager.getWorkflowsDirectories();
for (const workflowsDirectory of workflowsDirectories) {
try {
const workflowFileUris = await workspace.findFiles(
new RelativePattern(
workspaceFolder,
`${workflowsDirectory}/*.{${WorkflowsManager.yamlExtension},${WorkflowsManager.ymlExtension}}`
)
);
for await (const workflowFileUri of workflowFileUris) {
let yamlContent: any | undefined;
try {
const fileContent = await fs.readFile(workflowFileUri.fsPath, 'utf8');
const fileContent = await fs.readFile(
workflowFileUri.fsPath,
"utf8"
);
yamlContent = yaml.parse(fileContent);
workflows.push({
name: yamlContent.name || path.parse(workflowFileUri.fsPath).name,
uri: workflowFileUri,
fileContent: fileContent,
yaml: yaml.parse(fileContent)
yaml: yaml.parse(fileContent),
});
} catch (error: any) {
workflows.push({
name: (yamlContent ? yamlContent.name : undefined) || path.parse(workflowFileUri.fsPath).name,
name:
(yamlContent ? yamlContent.name : undefined) ||
path.parse(workflowFileUri.fsPath).name,
uri: workflowFileUri,
error: 'Failed to parse workflow'
error: "Failed to parse workflow",
});
}
}
} catch (error) {
// Directory doesn't exist, skip it
continue;
}
}
return workflows;
}