Add run workflow support
Signed-off-by: Sanjula Ganepola <sanjulagane@gmail.com>
This commit is contained in:
38
package.json
38
package.json
@@ -50,12 +50,12 @@
|
|||||||
{
|
{
|
||||||
"id": "workflows",
|
"id": "workflows",
|
||||||
"name": "Workflows",
|
"name": "Workflows",
|
||||||
"icon": "$(remote-explorer)"
|
"icon": "$(layers)"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "settings",
|
"id": "settings",
|
||||||
"name": "Settings",
|
"name": "Settings",
|
||||||
"icon": "$(server-environment)"
|
"icon": "$(gear)"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
@@ -66,6 +66,12 @@
|
|||||||
"title": "Refresh",
|
"title": "Refresh",
|
||||||
"icon": "$(refresh)"
|
"icon": "$(refresh)"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"category": "GitHub Local Actions",
|
||||||
|
"command": "githubLocalActions.runAllWorkflows",
|
||||||
|
"title": "Run All Workflows",
|
||||||
|
"icon": "$(run-all)"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"category": "GitHub Local Actions",
|
"category": "GitHub Local Actions",
|
||||||
"command": "githubLocalActions.refreshWorkflows",
|
"command": "githubLocalActions.refreshWorkflows",
|
||||||
@@ -78,6 +84,12 @@
|
|||||||
"title": "Open Workflow",
|
"title": "Open Workflow",
|
||||||
"icon": "$(go-to-file)"
|
"icon": "$(go-to-file)"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"category": "GitHub Local Actions",
|
||||||
|
"command": "githubLocalActions.runWorkflow",
|
||||||
|
"title": "Run Workflow",
|
||||||
|
"icon": "$(debug-start)"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"category": "GitHub Local Actions",
|
"category": "GitHub Local Actions",
|
||||||
"command": "githubLocalActions.refreshSettings",
|
"command": "githubLocalActions.refreshSettings",
|
||||||
@@ -91,6 +103,10 @@
|
|||||||
"command": "githubLocalActions.refreshComponents",
|
"command": "githubLocalActions.refreshComponents",
|
||||||
"when": "never"
|
"when": "never"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"command": "githubLocalActions.runAllWorkflows",
|
||||||
|
"when": "never"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"command": "githubLocalActions.refreshWorkflows",
|
"command": "githubLocalActions.refreshWorkflows",
|
||||||
"when": "never"
|
"when": "never"
|
||||||
@@ -99,6 +115,10 @@
|
|||||||
"command": "githubLocalActions.openWorkflow",
|
"command": "githubLocalActions.openWorkflow",
|
||||||
"when": "never"
|
"when": "never"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"command": "githubLocalActions.runWorkflow",
|
||||||
|
"when": "never"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"command": "githubLocalActions.refreshSettings",
|
"command": "githubLocalActions.refreshSettings",
|
||||||
"when": "never"
|
"when": "never"
|
||||||
@@ -111,10 +131,15 @@
|
|||||||
"group": "navigation@0"
|
"group": "navigation@0"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"command": "githubLocalActions.refreshWorkflows",
|
"command": "githubLocalActions.runAllWorkflows",
|
||||||
"when": "view == workflows",
|
"when": "view == workflows",
|
||||||
"group": "navigation@0"
|
"group": "navigation@0"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"command": "githubLocalActions.refreshWorkflows",
|
||||||
|
"when": "view == workflows",
|
||||||
|
"group": "navigation@1"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"command": "githubLocalActions.refreshSettings",
|
"command": "githubLocalActions.refreshSettings",
|
||||||
"when": "view == settings",
|
"when": "view == settings",
|
||||||
@@ -124,8 +149,13 @@
|
|||||||
"view/item/context": [
|
"view/item/context": [
|
||||||
{
|
{
|
||||||
"command": "githubLocalActions.openWorkflow",
|
"command": "githubLocalActions.openWorkflow",
|
||||||
"when": "view == workflows && viewItem =~ /^workflow.*/",
|
"when": "view == workflows && viewItem =~ /^githubLocalActions.workflow.*/",
|
||||||
"group": "inline@0"
|
"group": "inline@0"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"command": "githubLocalActions.runWorkflow",
|
||||||
|
"when": "view == workflows && viewItem =~ /^githubLocalActions.workflow.*/",
|
||||||
|
"group": "inline@1"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
|||||||
55
src/act.ts
Normal file
55
src/act.ts
Normal file
@@ -0,0 +1,55 @@
|
|||||||
|
import * as path from "path";
|
||||||
|
import { commands, ShellExecution, TaskGroup, TaskPanelKind, TaskRevealKind, tasks, window, workspace } from "vscode";
|
||||||
|
import { ComponentManager } from "./componentManager";
|
||||||
|
import { Workflow } from "./workflowManager";
|
||||||
|
|
||||||
|
export enum Options {
|
||||||
|
Workflows = '-W'
|
||||||
|
}
|
||||||
|
|
||||||
|
export class Act {
|
||||||
|
private static base: string = 'act';
|
||||||
|
|
||||||
|
static async runAllWorkflows() {
|
||||||
|
// TODO: Implement
|
||||||
|
}
|
||||||
|
|
||||||
|
static async runWorkflow(workflow: Workflow) {
|
||||||
|
return await Act.runCommand(workflow, `${Act.base} ${Options.Workflows} '.github/workflows/${path.parse(workflow.uri.fsPath).base}'`);
|
||||||
|
}
|
||||||
|
|
||||||
|
static async runCommand(workflow: Workflow, command: string) {
|
||||||
|
|
||||||
|
const unreadyComponents = await ComponentManager.getUnreadyComponents();
|
||||||
|
if (unreadyComponents.length > 0) {
|
||||||
|
window.showErrorMessage(`The following required components are not ready: ${unreadyComponents.map(component => component.name).join(', ')}`, 'Fix...').then(async value => {
|
||||||
|
if (value === 'Fix...') {
|
||||||
|
await commands.executeCommand('components.focus');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
await tasks.executeTask({
|
||||||
|
name: workflow.name,
|
||||||
|
detail: 'Run workflow',
|
||||||
|
definition: { type: 'GitHub Local Actions' },
|
||||||
|
source: 'GitHub Local Actions',
|
||||||
|
scope: workspace.getWorkspaceFolder(workflow.uri),
|
||||||
|
isBackground: true,
|
||||||
|
presentationOptions: {
|
||||||
|
reveal: TaskRevealKind.Always,
|
||||||
|
focus: false,
|
||||||
|
clear: false,
|
||||||
|
close: false,
|
||||||
|
echo: true,
|
||||||
|
panel: TaskPanelKind.Dedicated,
|
||||||
|
showReuseMessage: false
|
||||||
|
},
|
||||||
|
problemMatchers: [],
|
||||||
|
runOptions: {},
|
||||||
|
group: TaskGroup.Build,
|
||||||
|
execution: new ShellExecution(command)
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,7 +1,8 @@
|
|||||||
export interface Component {
|
export interface Component {
|
||||||
name: string,
|
name: string,
|
||||||
status: Status,
|
|
||||||
icon: string,
|
icon: string,
|
||||||
|
status: Status,
|
||||||
|
required: boolean
|
||||||
message?: string
|
message?: string
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -12,32 +13,39 @@ export enum Status {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export class ComponentManager {
|
export class ComponentManager {
|
||||||
components: Component[] = [
|
static async getComponents(): Promise<Component[]> {
|
||||||
{
|
return [
|
||||||
name: 'nektos/act',
|
{
|
||||||
status: Status.Enabled,
|
name: 'nektos/act',
|
||||||
icon: 'package'
|
icon: 'package',
|
||||||
},
|
status: Status.Enabled,
|
||||||
{
|
required: true
|
||||||
name: 'Docker Engine',
|
},
|
||||||
status: Status.Disabled,
|
{
|
||||||
icon: 'dashboard'
|
name: 'Docker Engine',
|
||||||
},
|
icon: 'dashboard',
|
||||||
{
|
status: Status.Enabled,
|
||||||
name: 'GitHub Actions Extension',
|
required: true
|
||||||
status: Status.Warning,
|
},
|
||||||
icon: 'extensions',
|
{
|
||||||
message: 'GitHub Actions extension is not required but is recommended to take advantage of workflow editor features'
|
name: 'GitHub Actions Extension',
|
||||||
},
|
icon: 'extensions',
|
||||||
{
|
status: Status.Warning,
|
||||||
name: 'GitHub CLI',
|
required: false,
|
||||||
status: Status.Warning,
|
message: 'GitHub Actions extension is not required, but is recommended to take advantage of workflow editor features.'
|
||||||
icon: 'terminal',
|
},
|
||||||
message: 'GitHub CLI is not required but is recommended if you plan to use it to retrieve GitHub tokens'
|
{
|
||||||
}
|
name: 'GitHub CLI',
|
||||||
];
|
icon: 'terminal',
|
||||||
|
status: Status.Warning,
|
||||||
|
required: false,
|
||||||
|
message: 'GitHub CLI is not required, but is recommended if you plan to use it to retrieve GitHub tokens.'
|
||||||
|
}
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
async getComponents(): Promise<Component[]> {
|
static async getUnreadyComponents(): Promise<Component[]> {
|
||||||
return this.components;
|
const components = await ComponentManager.getComponents();
|
||||||
|
return components.filter(component => component.required && component.status !== Status.Enabled);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,9 +1,9 @@
|
|||||||
import { ThemeIcon, TreeItem, TreeItemCollapsibleState, Uri } from "vscode";
|
import { ThemeIcon, TreeItem, TreeItemCollapsibleState, Uri } from "vscode";
|
||||||
import { GithubLocalActionsTreeItem } from "../githubLocalActionsTreeItem";
|
|
||||||
import { Component } from "../../componentManager";
|
import { Component } from "../../componentManager";
|
||||||
|
import { GithubLocalActionsTreeItem } from "../githubLocalActionsTreeItem";
|
||||||
|
|
||||||
export default class ComponentTreeItem extends TreeItem implements GithubLocalActionsTreeItem {
|
export default class ComponentTreeItem extends TreeItem implements GithubLocalActionsTreeItem {
|
||||||
static contextValue = 'component';
|
static contextValue = 'githubLocalActions.component';
|
||||||
component: Component;
|
component: Component;
|
||||||
|
|
||||||
constructor(component: Component) {
|
constructor(component: Component) {
|
||||||
|
|||||||
@@ -6,12 +6,9 @@ import ComponentTreeItem from "./component";
|
|||||||
export default class ComponentsTreeDataProvider implements TreeDataProvider<GithubLocalActionsTreeItem> {
|
export default class ComponentsTreeDataProvider implements TreeDataProvider<GithubLocalActionsTreeItem> {
|
||||||
private _onDidChangeTreeData = new EventEmitter<GithubLocalActionsTreeItem | undefined | null | void>();
|
private _onDidChangeTreeData = new EventEmitter<GithubLocalActionsTreeItem | undefined | null | void>();
|
||||||
readonly onDidChangeTreeData = this._onDidChangeTreeData.event;
|
readonly onDidChangeTreeData = this._onDidChangeTreeData.event;
|
||||||
public static VIEW_ID = 'components';
|
static VIEW_ID = 'components';
|
||||||
private componentManager: ComponentManager;
|
|
||||||
|
|
||||||
constructor(context: ExtensionContext) {
|
constructor(context: ExtensionContext) {
|
||||||
this.componentManager = new ComponentManager();
|
|
||||||
|
|
||||||
context.subscriptions.push(
|
context.subscriptions.push(
|
||||||
commands.registerCommand('githubLocalActions.refreshComponents', async () => {
|
commands.registerCommand('githubLocalActions.refreshComponents', async () => {
|
||||||
this.refresh();
|
this.refresh();
|
||||||
@@ -39,7 +36,7 @@ export default class ComponentsTreeDataProvider implements TreeDataProvider<Gith
|
|||||||
if (element) {
|
if (element) {
|
||||||
return element.getChildren();
|
return element.getChildren();
|
||||||
} else {
|
} else {
|
||||||
const components = await this.componentManager.getComponents();
|
const components = await ComponentManager.getComponents();
|
||||||
return components.map(component => new ComponentTreeItem(component));
|
return components.map(component => new ComponentTreeItem(component));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import { CancellationToken, Event, FileDecoration, FileDecorationProvider, ProviderResult, ThemeColor, Uri } from "vscode";
|
import { CancellationToken, Event, FileDecoration, FileDecorationProvider, ProviderResult, ThemeColor, Uri } from "vscode";
|
||||||
import { Status } from "../types";
|
import { Status } from "../componentManager";
|
||||||
import ComponentTreeItem from "./components/component";
|
import ComponentTreeItem from "./components/component";
|
||||||
import WorkflowTreeItem from "./workflows/workflow";
|
import WorkflowTreeItem from "./workflows/workflow";
|
||||||
|
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ import { ThemeIcon, TreeItem, TreeItemCollapsibleState } from "vscode";
|
|||||||
import { GithubLocalActionsTreeItem } from "../githubLocalActionsTreeItem";
|
import { GithubLocalActionsTreeItem } from "../githubLocalActionsTreeItem";
|
||||||
|
|
||||||
export default class EnvironmentsTreeItem extends TreeItem implements GithubLocalActionsTreeItem {
|
export default class EnvironmentsTreeItem extends TreeItem implements GithubLocalActionsTreeItem {
|
||||||
static contextValue = 'environments';
|
static contextValue = 'githubLocalActions.environments';
|
||||||
|
|
||||||
constructor() {
|
constructor() {
|
||||||
super('Environments', TreeItemCollapsibleState.Collapsed);
|
super('Environments', TreeItemCollapsibleState.Collapsed);
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ import { ThemeIcon, TreeItem, TreeItemCollapsibleState } from "vscode";
|
|||||||
import { GithubLocalActionsTreeItem } from "../githubLocalActionsTreeItem";
|
import { GithubLocalActionsTreeItem } from "../githubLocalActionsTreeItem";
|
||||||
|
|
||||||
export default class SecretsTreeItem extends TreeItem implements GithubLocalActionsTreeItem {
|
export default class SecretsTreeItem extends TreeItem implements GithubLocalActionsTreeItem {
|
||||||
static contextValue = 'secrets';
|
static contextValue = 'githubLocalActions.secrets';
|
||||||
|
|
||||||
constructor() {
|
constructor() {
|
||||||
super('Secrets', TreeItemCollapsibleState.Collapsed);
|
super('Secrets', TreeItemCollapsibleState.Collapsed);
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ import VariablesTreeItem from "./variables";
|
|||||||
export default class SettingsTreeDataProvider implements TreeDataProvider<GithubLocalActionsTreeItem> {
|
export default class SettingsTreeDataProvider implements TreeDataProvider<GithubLocalActionsTreeItem> {
|
||||||
private _onDidChangeTreeData = new EventEmitter<GithubLocalActionsTreeItem | undefined | null | void>();
|
private _onDidChangeTreeData = new EventEmitter<GithubLocalActionsTreeItem | undefined | null | void>();
|
||||||
readonly onDidChangeTreeData = this._onDidChangeTreeData.event;
|
readonly onDidChangeTreeData = this._onDidChangeTreeData.event;
|
||||||
public static VIEW_ID = 'settings';
|
static VIEW_ID = 'settings';
|
||||||
|
|
||||||
constructor(context: ExtensionContext) {
|
constructor(context: ExtensionContext) {
|
||||||
context.subscriptions.push(
|
context.subscriptions.push(
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ import { ThemeIcon, TreeItem, TreeItemCollapsibleState } from "vscode";
|
|||||||
import { GithubLocalActionsTreeItem } from "../githubLocalActionsTreeItem";
|
import { GithubLocalActionsTreeItem } from "../githubLocalActionsTreeItem";
|
||||||
|
|
||||||
export default class VariablesTreeItem extends TreeItem implements GithubLocalActionsTreeItem {
|
export default class VariablesTreeItem extends TreeItem implements GithubLocalActionsTreeItem {
|
||||||
static contextValue = 'variables';
|
static contextValue = 'githubLocalActions.variables';
|
||||||
|
|
||||||
constructor() {
|
constructor() {
|
||||||
super('Variables', TreeItemCollapsibleState.Collapsed);
|
super('Variables', TreeItemCollapsibleState.Collapsed);
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ import { Workflow } from "../../workflowManager";
|
|||||||
import { GithubLocalActionsTreeItem } from "../githubLocalActionsTreeItem";
|
import { GithubLocalActionsTreeItem } from "../githubLocalActionsTreeItem";
|
||||||
|
|
||||||
export default class WorkflowTreeItem extends TreeItem implements GithubLocalActionsTreeItem {
|
export default class WorkflowTreeItem extends TreeItem implements GithubLocalActionsTreeItem {
|
||||||
static contextValue = 'workflow';
|
static contextValue = 'githubLocalActions.workflow';
|
||||||
workflow: Workflow;
|
workflow: Workflow;
|
||||||
|
|
||||||
constructor(workflow: Workflow) {
|
constructor(workflow: Workflow) {
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
import { CancellationToken, commands, EventEmitter, ExtensionContext, TreeDataProvider, TreeItem, window, workspace } from "vscode";
|
import { CancellationToken, commands, EventEmitter, ExtensionContext, TreeDataProvider, TreeItem, window, workspace } from "vscode";
|
||||||
|
import { Act } from "../../act";
|
||||||
import { WorkflowManager } from "../../workflowManager";
|
import { WorkflowManager } from "../../workflowManager";
|
||||||
import { GithubLocalActionsTreeItem } from "../githubLocalActionsTreeItem";
|
import { GithubLocalActionsTreeItem } from "../githubLocalActionsTreeItem";
|
||||||
import WorkflowTreeItem from "./workflow";
|
import WorkflowTreeItem from "./workflow";
|
||||||
@@ -6,13 +7,13 @@ import WorkflowTreeItem from "./workflow";
|
|||||||
export default class WorkflowsTreeDataProvider implements TreeDataProvider<GithubLocalActionsTreeItem> {
|
export default class WorkflowsTreeDataProvider implements TreeDataProvider<GithubLocalActionsTreeItem> {
|
||||||
private _onDidChangeTreeData = new EventEmitter<GithubLocalActionsTreeItem | undefined | null | void>();
|
private _onDidChangeTreeData = new EventEmitter<GithubLocalActionsTreeItem | undefined | null | void>();
|
||||||
readonly onDidChangeTreeData = this._onDidChangeTreeData.event;
|
readonly onDidChangeTreeData = this._onDidChangeTreeData.event;
|
||||||
public static VIEW_ID = 'workflows';
|
static VIEW_ID = 'workflows';
|
||||||
private workflowManager: WorkflowManager;
|
|
||||||
|
|
||||||
constructor(context: ExtensionContext) {
|
constructor(context: ExtensionContext) {
|
||||||
this.workflowManager = new WorkflowManager();
|
|
||||||
|
|
||||||
context.subscriptions.push(
|
context.subscriptions.push(
|
||||||
|
commands.registerCommand('githubLocalActions.runAllWorkflows', async () => {
|
||||||
|
await Act.runAllWorkflows();
|
||||||
|
}),
|
||||||
commands.registerCommand('githubLocalActions.refreshWorkflows', async () => {
|
commands.registerCommand('githubLocalActions.refreshWorkflows', async () => {
|
||||||
this.refresh();
|
this.refresh();
|
||||||
}),
|
}),
|
||||||
@@ -21,7 +22,7 @@ export default class WorkflowsTreeDataProvider implements TreeDataProvider<Githu
|
|||||||
await window.showTextDocument(document);
|
await window.showTextDocument(document);
|
||||||
}),
|
}),
|
||||||
commands.registerCommand('githubLocalActions.runWorkflow', async (workflowTreeItem: WorkflowTreeItem) => {
|
commands.registerCommand('githubLocalActions.runWorkflow', async (workflowTreeItem: WorkflowTreeItem) => {
|
||||||
|
await Act.runWorkflow(workflowTreeItem.workflow);
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -46,7 +47,7 @@ export default class WorkflowsTreeDataProvider implements TreeDataProvider<Githu
|
|||||||
if (element) {
|
if (element) {
|
||||||
return element.getChildren();
|
return element.getChildren();
|
||||||
} else {
|
} else {
|
||||||
const workflows = await this.workflowManager.getWorkflows();
|
const workflows = await WorkflowManager.getWorkflows();
|
||||||
return workflows.map(workflow => new WorkflowTreeItem(workflow));
|
return workflows.map(workflow => new WorkflowTreeItem(workflow));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ export interface Workflow {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export class WorkflowManager {
|
export class WorkflowManager {
|
||||||
async getWorkflows(): Promise<Workflow[]> {
|
static async getWorkflows(): Promise<Workflow[]> {
|
||||||
const workflows: Workflow[] = [];
|
const workflows: Workflow[] = [];
|
||||||
|
|
||||||
const workspaceFolders = workspace.workspaceFolders;
|
const workspaceFolders = workspace.workspaceFolders;
|
||||||
|
|||||||
Reference in New Issue
Block a user