Skip to content

Commit

Permalink
Merge pull request #95 from SanjulaGanepola/feature/step-and-job-leve…
Browse files Browse the repository at this point in the history
…l-output

Add support for job and step level execution status
  • Loading branch information
SanjulaGanepola authored Dec 6, 2024
2 parents 8ec4788 + 726049c commit c80671b
Show file tree
Hide file tree
Showing 9 changed files with 414 additions and 98 deletions.
28 changes: 25 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -240,6 +240,11 @@
"enablement": "viewItem =~ /^githubLocalActions.history_(Success|Failed|Cancelled).*/",
"icon": "$(close)"
},
{
"category": "GitHub Local Actions",
"command": "githubLocalActions.focusTask",
"title": "Focus Task"
},
{
"category": "GitHub Local Actions",
"command": "githubLocalActions.refreshSettings",
Expand Down Expand Up @@ -436,6 +441,10 @@
"command": "githubLocalActions.remove",
"when": "never"
},
{
"command": "githubLocalActions.focusTask",
"when": "never"
},
{
"command": "githubLocalActions.refreshSettings",
"when": "never"
Expand Down Expand Up @@ -640,6 +649,11 @@
"when": "view == history && viewItem =~ /^githubLocalActions.history.*/",
"group": "inline@3"
},
{
"command": "githubLocalActions.focusTask",
"when": "view == history && viewItem =~ /^githubLocalActions.history.*/",
"group": "0_focus@0"
},
{
"command": "githubLocalActions.createSecretFile",
"when": "view == settings && viewItem =~ /^githubLocalActions.secrets.*/",
Expand Down Expand Up @@ -745,23 +759,31 @@
"colors": [
{
"id": "GitHubLocalActions.green",
"description": "Color for green in GitHub Local Actions extension",
"description": "Color for green in the GitHub Local Actions extension",
"defaults": {
"dark": "#89d185",
"light": "#89d185"
}
},
{
"id": "GitHubLocalActions.yellow",
"description": "Color for yellow in GitHub Local Actions extension",
"description": "Color for yellow in the GitHub Local Actions extension",
"defaults": {
"dark": "#cca700",
"light": "#cca700"
}
},
{
"id": "GitHubLocalActions.purple",
"description": "Color for purple in the GitHub Local Actions extension",
"defaults": {
"dark": "#d6bcfa",
"light": "#d6bcfa"
}
},
{
"id": "GitHubLocalActions.red",
"description": "Color for red in GitHub Local Actions extension",
"description": "Color for red in the GitHub Local Actions extension",
"defaults": {
"dark": "#f48771",
"light": "#f48771"
Expand Down
297 changes: 237 additions & 60 deletions src/act.ts

Large diffs are not rendered by default.

64 changes: 58 additions & 6 deletions src/historyManager.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { TaskExecution, Uri, window, workspace, WorkspaceFolder } from "vscode";
import { TaskExecution, ThemeColor, ThemeIcon, Uri, window, workspace, WorkspaceFolder } from "vscode";
import { CommandArgs } from "./act";
import { act, historyTreeDataProvider } from "./extension";
import { StorageKey, StorageManager } from "./storageManager";
Expand All @@ -12,16 +12,38 @@ export interface History {
start: string,
end?: string,
},
taskExecution?: TaskExecution,
commandArgs: CommandArgs,
logPath: string
logPath: string,
taskExecution?: TaskExecution,
jobs?: Job[],
}

export interface Job {
name: string,
status: HistoryStatus,
date: {
start: string,
end?: string,
},
steps?: Step[]
}

export interface Step {
id: string,
name: string,
status: HistoryStatus,
date: {
start: string,
end?: string,
}
}

export enum HistoryStatus {
Running = 'Running',
Success = 'Success',
Failed = 'Failed',
Cancelled = 'Cancelled'
Cancelled = 'Cancelled',
Unknown = 'Unknown'
}

export class HistoryManager {
Expand All @@ -33,6 +55,21 @@ export class HistoryManager {
const workspaceHistory = this.storageManager.get<{ [path: string]: History[] }>(StorageKey.WorkspaceHistory) || {};
for (const [path, historyLogs] of Object.entries(workspaceHistory)) {
workspaceHistory[path] = historyLogs.map(history => {
history.jobs?.forEach((job, jobIndex) => {
history.jobs![jobIndex].steps?.forEach((step, stepIndex) => {
// Update status of all running steps
if (step.status === HistoryStatus.Running) {
history.jobs![jobIndex].steps![stepIndex].status = HistoryStatus.Cancelled;
}
});

// Update status of all running jobs
if (job.status === HistoryStatus.Running) {
history.jobs![jobIndex].status = HistoryStatus.Cancelled;
}
});

// Update history status
if (history.status === HistoryStatus.Running) {
history.status = HistoryStatus.Cancelled;
}
Expand All @@ -53,7 +90,7 @@ export class HistoryManager {

this.workspaceHistory[workspaceFolder.uri.fsPath] = [];
historyTreeDataProvider.refresh();
this.storageManager.update(StorageKey.WorkspaceHistory, this.workspaceHistory);
await this.storageManager.update(StorageKey.WorkspaceHistory, this.workspaceHistory);
}

async viewOutput(history: History) {
Expand All @@ -77,11 +114,26 @@ export class HistoryManager {
const historyIndex = this.workspaceHistory[history.commandArgs.path].findIndex(workspaceHistory => workspaceHistory.index === history.index);
if (historyIndex > -1) {
this.workspaceHistory[history.commandArgs.path].splice(historyIndex, 1);
this.storageManager.update(StorageKey.WorkspaceHistory, this.workspaceHistory);
await this.storageManager.update(StorageKey.WorkspaceHistory, this.workspaceHistory);

try {
await workspace.fs.delete(Uri.file(history.logPath));
} catch (error: any) { }
}
}

static statusToIcon(status: HistoryStatus) {
switch (status) {
case HistoryStatus.Running:
return new ThemeIcon('loading~spin');
case HistoryStatus.Success:
return new ThemeIcon('pass', new ThemeColor('GitHubLocalActions.green'));
case HistoryStatus.Failed:
return new ThemeIcon('error', new ThemeColor('GitHubLocalActions.red'));
case HistoryStatus.Cancelled:
return new ThemeIcon('circle-slash', new ThemeColor('GitHubLocalActions.yellow'));
case HistoryStatus.Unknown:
return new ThemeIcon('question', new ThemeColor('GitHubLocalActions.purple'));
}
}
}
8 changes: 4 additions & 4 deletions src/settingsManager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ export interface Settings {
runners: Setting[];
payloadFiles: CustomSetting[];
options: CustomSetting[];
environments: Setting[];
// environments: Setting[];
}

export interface Setting {
Expand Down Expand Up @@ -74,7 +74,7 @@ export class SettingsManager {
const runners = (await this.getSetting(workspaceFolder, SettingsManager.runnersRegExp, StorageKey.Runners, false, Visibility.show)).filter(runner => !isUserSelected || (runner.selected && runner.value));
const payloadFiles = (await this.getCustomSettings(workspaceFolder, StorageKey.PayloadFiles)).filter(payloadFile => !isUserSelected || payloadFile.selected);
const options = (await this.getCustomSettings(workspaceFolder, StorageKey.Options)).filter(option => !isUserSelected || (option.selected && (option.path || option.notEditable)));
const environments = await this.getEnvironments(workspaceFolder);
// const environments = await this.getEnvironments(workspaceFolder);

return {
secrets: secrets,
Expand All @@ -86,7 +86,7 @@ export class SettingsManager {
runners: runners,
payloadFiles: payloadFiles,
options: options,
environments: environments
// environments: environments
};
}

Expand Down Expand Up @@ -131,7 +131,7 @@ export class SettingsManager {
}
}
existingSettings[workspaceFolder.uri.fsPath] = settings;
this.storageManager.update(storageKey, existingSettings);
await this.storageManager.update(storageKey, existingSettings);

return settings;
}
Expand Down
29 changes: 6 additions & 23 deletions src/views/history/history.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,16 @@
import * as path from "path";
import { ThemeColor, ThemeIcon, TreeItem, TreeItemCollapsibleState, WorkspaceFolder } from "vscode";
import { History, HistoryStatus } from "../../historyManager";
import { TreeItem, TreeItemCollapsibleState, WorkspaceFolder } from "vscode";
import { History, HistoryManager, HistoryStatus } from "../../historyManager";
import { Utils } from "../../utils";
import { GithubLocalActionsTreeItem } from "../githubLocalActionsTreeItem";
import JobTreeItem from "./job";

export default class HistoryTreeItem extends TreeItem implements GithubLocalActionsTreeItem {
static contextValue = 'githubLocalActions.history';
history: History;

constructor(public workspaceFolder: WorkspaceFolder, history: History) {
super(`${history.name} #${history.count}`, TreeItemCollapsibleState.None);
super(`${history.name} #${history.count}`, TreeItemCollapsibleState.Collapsed);
this.history = history;

let endTime: string | undefined;
Expand All @@ -24,20 +25,7 @@ export default class HistoryTreeItem extends TreeItem implements GithubLocalActi

this.description = totalDuration;
this.contextValue = `${HistoryTreeItem.contextValue}_${history.status}`;
switch (history.status) {
case HistoryStatus.Running:
this.iconPath = new ThemeIcon('loading~spin');
break;
case HistoryStatus.Success:
this.iconPath = new ThemeIcon('pass', new ThemeColor('GitHubLocalActions.green'));
break;
case HistoryStatus.Failed:
this.iconPath = new ThemeIcon('error', new ThemeColor('GitHubLocalActions.red'));
break;
case HistoryStatus.Cancelled:
this.iconPath = new ThemeIcon('circle-slash', new ThemeColor('GitHubLocalActions.yellow'));
break;
}
this.iconPath = HistoryManager.statusToIcon(history.status);
this.tooltip = `Name: ${history.name} #${history.count}\n` +
`${history.commandArgs.extraHeader.map(header => `${header.key}: ${header.value}`).join('\n')}\n` +
`Path: ${history.commandArgs.path}\n` +
Expand All @@ -46,14 +34,9 @@ export default class HistoryTreeItem extends TreeItem implements GithubLocalActi
`Started: ${Utils.getDateString(history.date.start)}\n` +
`Ended: ${endTime ? Utils.getDateString(endTime) : 'N/A'}\n` +
`Total Duration: ${totalDuration ? totalDuration : 'N/A'}`;
this.command = {
title: 'Focus Task',
command: 'githubLocalActions.focusTask',
arguments: [this]
};
}

async getChildren(): Promise<GithubLocalActionsTreeItem[]> {
return [];
return this.history.jobs?.map(job => new JobTreeItem(this.workspaceFolder, job)) || [];
}
}
7 changes: 7 additions & 0 deletions src/views/history/historyTreeDataProvider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,15 @@ export default class HistoryTreeDataProvider implements TreeDataProvider<GithubL
for (const terminal of terminals) {
if (terminal.creationOptions.name === `${historyTreeItem.history.name} #${historyTreeItem.history.count}`) {
terminal.show();
return;
}
}

window.showErrorMessage(`${historyTreeItem.history.name} #${historyTreeItem.history.count} task is no longer open.`, 'View Output').then(async value => {
if (value === 'View Output') {
await commands.executeCommand('githubLocalActions.viewOutput', historyTreeItem);
}
});
}),
commands.registerCommand('githubLocalActions.viewOutput', async (historyTreeItem: HistoryTreeItem) => {
await act.historyManager.viewOutput(historyTreeItem.history);
Expand Down
38 changes: 38 additions & 0 deletions src/views/history/job.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import { TreeItem, TreeItemCollapsibleState, WorkspaceFolder } from "vscode";
import { HistoryManager, HistoryStatus, Job } from "../../historyManager";
import { Utils } from "../../utils";
import { GithubLocalActionsTreeItem } from "../githubLocalActionsTreeItem";
import StepTreeItem from "./step";

export default class JobTreeItem extends TreeItem implements GithubLocalActionsTreeItem {
static contextValue = 'githubLocalActions.job';
job: Job;

constructor(public workspaceFolder: WorkspaceFolder, job: Job) {
super(job.name, TreeItemCollapsibleState.Expanded);
this.job = job;

let endTime: string | undefined;
let totalDuration: string | undefined;
if (job.date.end) {
endTime = job.date.end;
totalDuration = Utils.getTimeDuration(job.date.start, endTime);
} else if (job.status === HistoryStatus.Running) {
endTime = new Date().toString();
totalDuration = Utils.getTimeDuration(job.date.start, endTime);
}

this.description = totalDuration;
this.contextValue = `${JobTreeItem.contextValue}_${job.status}`;
this.iconPath = HistoryManager.statusToIcon(job.status);
this.tooltip = `Name: ${job.name}\n` +
`Status: ${job.status}\n` +
`Started: ${Utils.getDateString(job.date.start)}\n` +
`Ended: ${endTime ? Utils.getDateString(endTime) : 'N/A'}\n` +
`Total Duration: ${totalDuration ? totalDuration : 'N/A'}`;
}

async getChildren(): Promise<GithubLocalActionsTreeItem[]> {
return this.job.steps?.map(step => new StepTreeItem(this.workspaceFolder, step)) || [];
}
}
37 changes: 37 additions & 0 deletions src/views/history/step.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import { TreeItem, TreeItemCollapsibleState, WorkspaceFolder } from "vscode";
import { HistoryManager, HistoryStatus, Step } from "../../historyManager";
import { Utils } from "../../utils";
import { GithubLocalActionsTreeItem } from "../githubLocalActionsTreeItem";

export default class StepTreeItem extends TreeItem implements GithubLocalActionsTreeItem {
static contextValue = 'githubLocalActions.step';
step: Step;

constructor(public workspaceFolder: WorkspaceFolder, step: Step) {
super(step.name, TreeItemCollapsibleState.None);
this.step = step;

let endTime: string | undefined;
let totalDuration: string | undefined;
if (step.date.end) {
endTime = step.date.end;
totalDuration = Utils.getTimeDuration(step.date.start, endTime);
} else if (step.status === HistoryStatus.Running) {
endTime = new Date().toString();
totalDuration = Utils.getTimeDuration(step.date.start, endTime);
}

this.description = totalDuration;
this.contextValue = `${StepTreeItem.contextValue}_${step.status}`;
this.iconPath = HistoryManager.statusToIcon(step.status);
this.tooltip = `Name: ${step.name}\n` +
`Status: ${step.status}\n` +
`Started: ${Utils.getDateString(step.date.start)}\n` +
`Ended: ${endTime ? Utils.getDateString(endTime) : 'N/A'}\n` +
`Total Duration: ${totalDuration ? totalDuration : 'N/A'}`;
}

async getChildren(): Promise<GithubLocalActionsTreeItem[]> {
return [];
}
}
4 changes: 2 additions & 2 deletions src/views/settings/settingsTreeDataProvider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -307,9 +307,9 @@ export default class SettingsTreeDataProvider implements TreeDataProvider<Github
];

options.forEach((option, index) => {
options[index].label = options[index].label.slice(2)
options[index].label = options[index].label.slice(2);
options[index].iconPath = new ThemeIcon('symbol-property');
})
});

const settings = await act.settingsManager.getSettings(optionsTreeItem.workspaceFolder, false);
const optionNames = settings.options.map(option => option.name);
Expand Down

0 comments on commit c80671b

Please sign in to comment.