Write to filesystem for non-secret StorageKey values (#191)

This commit is contained in:
atoko
2025-04-05 14:49:59 -07:00
committed by GitHub
parent eebee47f40
commit bc25f97d70
8 changed files with 139 additions and 67 deletions

View File

@@ -26,5 +26,6 @@ Thanks so much to everyone [who has contributed](https://github.com/SanjulaGanep
* [@SanjulaGanepola](https://github.com/SanjulaGanepola)
* [@ChristopherHX](https://github.com/ChristopherHX)
* [@a11rew](https://github.com/a11rew)
* [@atoko](https://github.com/atoko)
Want to see your name on this list? Join us and contribute!

View File

@@ -664,17 +664,18 @@ export class Act {
}
// Initialize history for workspace
if (!this.historyManager.workspaceHistory[commandArgs.path]) {
this.historyManager.workspaceHistory[commandArgs.path] = [];
await this.storageManager.update(StorageKey.WorkspaceHistory, this.historyManager.workspaceHistory);
const workspaceHistory = await this.historyManager.getWorkspaceHistory();
if (workspaceHistory[commandArgs.path] === undefined) {
workspaceHistory[commandArgs.path] = [];
await this.storageManager.update(StorageKey.WorkspaceHistory, workspaceHistory);
}
// Process task count suffix
const historyIndex = this.historyManager.workspaceHistory[commandArgs.path].length;
const matchingTasks = this.historyManager.workspaceHistory[commandArgs.path]
const historyIndex = (workspaceHistory[commandArgs.path] ?? []).length;
const matchingTasks = (workspaceHistory[commandArgs.path] ?? [])
.filter(history => history.name === commandArgs.name)
.sort((a, b) => b.count - a.count);
const count = matchingTasks && matchingTasks.length > 0 ? matchingTasks[0].count + 1 : 1;
const count = matchingTasks.length > 0 ? matchingTasks[0].count + 1 : 1;
// Process log file and path
const start = new Date();
@@ -753,6 +754,7 @@ export class Act {
lastline = lines.pop() || "";
}
const workspaceHistory = (await this.historyManager.getWorkspaceHistory());
for await (const line of lines) {
const dateString = new Date().toString();
@@ -796,11 +798,13 @@ export class Act {
jobName = `${jobName} (${matrixValues})`;
}
let jobIndex = this.historyManager.workspaceHistory[commandArgs.path][historyIndex].jobs!
const jobHistory = workspaceHistory[commandArgs.path][historyIndex];
const jobs = jobHistory.jobs ?? [];
let jobIndex = jobs
.findIndex(job => job.name === jobName);
if (jobIndex < 0) {
// Add new job with setup step
this.historyManager.workspaceHistory[commandArgs.path][historyIndex].jobs!.push({
jobs.push({
name: jobName,
status: HistoryStatus.Running,
date: {
@@ -808,13 +812,17 @@ export class Act {
},
steps: []
});
jobIndex = this.historyManager.workspaceHistory[commandArgs.path][historyIndex].jobs!.length - 1;
jobIndex = jobs.length - 1;
}
// Update step status in workspace history
const job = jobs[jobIndex];
if (parsedMessage.stepID) {
let stepName: string;
const stepId: string = parsedMessage.stepID[0];
const steps = job.steps ?? [];
if (parsedMessage.stage !== 'Main') {
stepName = `${parsedMessage.stage} ${parsedMessage.step}`;
} else {
@@ -822,20 +830,20 @@ export class Act {
// TODO: This forcefully sets any pre step to success. To be fixed with https://github.com/nektos/act/issues/2551
const preStepName = `Pre ${parsedMessage.step}`;
let preStepIndex = this.historyManager.workspaceHistory[commandArgs.path][historyIndex].jobs![jobIndex].steps!
let preStepIndex = steps
.findIndex(step => step.id === stepId && step.name === preStepName);
if (preStepIndex > -1 && this.historyManager.workspaceHistory[commandArgs.path][historyIndex].jobs![jobIndex].steps![preStepIndex].status === HistoryStatus.Running) {
this.historyManager.workspaceHistory[commandArgs.path][historyIndex].jobs![jobIndex].steps![preStepIndex].status = HistoryStatus.Success;
this.historyManager.workspaceHistory[commandArgs.path][historyIndex].jobs![jobIndex].steps![preStepIndex].date.end = dateString;
const prestep = (job.steps! ?? [])[preStepIndex];
if (preStepIndex > -1 && prestep?.status === HistoryStatus.Running) {
prestep.status = HistoryStatus.Success;
prestep.date.end = dateString;
}
}
let stepIndex = this.historyManager.workspaceHistory[commandArgs.path][historyIndex].jobs![jobIndex].steps!
let stepIndex = steps
.findIndex(step => step.id === stepId && step.name === stepName);
if (stepIndex < 0) {
// Add new step
this.historyManager.workspaceHistory[commandArgs.path][historyIndex].jobs![jobIndex].steps!.push({
steps.push({
id: stepId,
name: stepName,
status: HistoryStatus.Running,
@@ -843,21 +851,24 @@ export class Act {
start: dateString
}
});
stepIndex = this.historyManager.workspaceHistory[commandArgs.path][historyIndex].jobs![jobIndex].steps!.length - 1;
stepIndex = steps.length - 1;
}
if (parsedMessage.stepResult) {
this.historyManager.workspaceHistory[commandArgs.path][historyIndex].jobs![jobIndex].steps![stepIndex].status =
HistoryManager.stepResultToHistoryStatus(parsedMessage.stepResult);
this.historyManager.workspaceHistory[commandArgs.path][historyIndex].jobs![jobIndex].steps![stepIndex].date.end = dateString;
const step = steps[stepIndex];
if (step) {
step.status = HistoryManager.stepResultToHistoryStatus(parsedMessage.stepResult);
step.date.end = dateString;
}
}
}
if (parsedMessage.jobResult) {
this.historyManager.workspaceHistory[commandArgs.path][historyIndex].jobs![jobIndex].status =
HistoryManager.stepResultToHistoryStatus(parsedMessage.jobResult);
this.historyManager.workspaceHistory[commandArgs.path][historyIndex].jobs![jobIndex].date.end =
dateString;
if (job) {
job.status = HistoryManager.stepResultToHistoryStatus(parsedMessage.jobResult);
job.date.end = dateString;
}
}
}
}
@@ -872,7 +883,7 @@ export class Act {
writeEmitter.fire(`${message.trimEnd()}\r\n`);
historyTreeDataProvider.refresh();
}
await this.storageManager.update(StorageKey.WorkspaceHistory, this.historyManager.workspaceHistory);
await this.storageManager.update(StorageKey.WorkspaceHistory, workspaceHistory);
};
};
@@ -920,36 +931,47 @@ export class Act {
const dateString = new Date().toString();
// Set execution status and end time in workspace history
if (this.historyManager.workspaceHistory[commandArgs.path][historyIndex].status === HistoryStatus.Running) {
const workspaceHistory = (await this.historyManager.getWorkspaceHistory());
if (workspaceHistory[commandArgs.path][historyIndex].status === HistoryStatus.Running) {
const jobAndStepStatus = (!code && code !== 0) ? HistoryStatus.Cancelled : HistoryStatus.Unknown;
this.historyManager.workspaceHistory[commandArgs.path][historyIndex].jobs?.forEach((job, jobIndex) => {
this.historyManager.workspaceHistory[commandArgs.path][historyIndex].jobs![jobIndex].steps?.forEach((step, stepIndex) => {
workspaceHistory[commandArgs.path][historyIndex].jobs?.forEach((job, jobIndex) => {
workspaceHistory[commandArgs.path][historyIndex].jobs![jobIndex].steps?.forEach((step, stepIndex) => {
if (step.status === HistoryStatus.Running) {
// Update status of all running steps
this.historyManager.workspaceHistory[commandArgs.path][historyIndex].jobs![jobIndex].steps![stepIndex].status = jobAndStepStatus;
this.historyManager.workspaceHistory[commandArgs.path][historyIndex].jobs![jobIndex].steps![stepIndex].date.end = dateString;
const step = workspaceHistory[commandArgs.path][historyIndex].jobs![jobIndex].steps![stepIndex];
if (step) {
step.status = jobAndStepStatus;
step.date.end = dateString;
}
}
});
if (job.status === HistoryStatus.Running) {
// Update status of all running jobs
this.historyManager.workspaceHistory[commandArgs.path][historyIndex].jobs![jobIndex].status = jobAndStepStatus;
this.historyManager.workspaceHistory[commandArgs.path][historyIndex].jobs![jobIndex].date.end = dateString;
const step = workspaceHistory[commandArgs.path][historyIndex].jobs![jobIndex];
if (step) {
step.status = jobAndStepStatus;
step.date.end = dateString;
}
}
});
// Update history status
if (code === 0) {
this.historyManager.workspaceHistory[commandArgs.path][historyIndex].status = HistoryStatus.Success;
workspaceHistory[commandArgs.path][historyIndex].status = HistoryStatus.Success;
} else if (!code) {
this.historyManager.workspaceHistory[commandArgs.path][historyIndex].status = HistoryStatus.Cancelled;
workspaceHistory[commandArgs.path][historyIndex].status = HistoryStatus.Cancelled;
} else {
this.historyManager.workspaceHistory[commandArgs.path][historyIndex].status = HistoryStatus.Failed;
workspaceHistory[commandArgs.path][historyIndex].status = HistoryStatus.Failed;
}
}
this.historyManager.workspaceHistory[commandArgs.path][historyIndex].date.end = dateString;
const step = workspaceHistory[commandArgs.path][historyIndex];
if (step) {
step.date.end = dateString;
}
historyTreeDataProvider.refresh();
await this.storageManager.update(StorageKey.WorkspaceHistory, this.historyManager.workspaceHistory);
await this.storageManager.update(StorageKey.WorkspaceHistory, workspaceHistory);
if (signal === 'SIGINT') {
writeEmitter.fire(`\r\n${commandArgs.name} #${count} was interrupted.\r\n`);
@@ -987,7 +1009,7 @@ export class Act {
});
// Add new entry to workspace history
this.historyManager.workspaceHistory[commandArgs.path].push({
workspaceHistory[commandArgs.path].push({
index: historyIndex,
count: count,
name: `${commandArgs.name}`,
@@ -1001,7 +1023,7 @@ export class Act {
jobs: []
});
historyTreeDataProvider.refresh();
await this.storageManager.update(StorageKey.WorkspaceHistory, this.historyManager.workspaceHistory);
await this.storageManager.update(StorageKey.WorkspaceHistory, workspaceHistory);
}
async install(packageManager: string) {

View File

@@ -49,11 +49,26 @@ export enum HistoryStatus {
export class HistoryManager {
storageManager: StorageManager;
workspaceHistory: { [path: string]: History[] };
private workspaceHistory: { [path: string]: History[] };
constructor(storageManager: StorageManager) {
this.storageManager = storageManager;
const workspaceHistory = this.storageManager.get<{ [path: string]: History[] }>(StorageKey.WorkspaceHistory) || {};
this.workspaceHistory = {};
this.syncHistory();
}
async getWorkspaceHistory() {
if (!this.workspaceHistory) {
await this.syncHistory();
}
return this.workspaceHistory;
}
async syncHistory() {
const workspaceHistory = await 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) => {
@@ -79,22 +94,27 @@ export class HistoryManager {
});
}
this.workspaceHistory = workspaceHistory;
}
};
async clearAll(workspaceFolder: WorkspaceFolder) {
const existingHistory = this.workspaceHistory[workspaceFolder.uri.fsPath];
await this.syncHistory();
const existingHistory = this.workspaceHistory?.[workspaceFolder.uri.fsPath] ?? [];
for (const history of existingHistory) {
try {
await workspace.fs.delete(Uri.file(history.logPath));
} catch (error: any) { }
}
this.workspaceHistory[workspaceFolder.uri.fsPath] = [];
if (this.workspaceHistory) {
this.workspaceHistory[workspaceFolder.uri.fsPath] = [];
}
historyTreeDataProvider.refresh();
await this.storageManager.update(StorageKey.WorkspaceHistory, this.workspaceHistory);
}
async viewOutput(history: History) {
await this.syncHistory();
try {
const document = await workspace.openTextDocument(history.logPath);
await window.showTextDocument(document);
@@ -112,9 +132,10 @@ export class HistoryManager {
}
async remove(history: History) {
const historyIndex = this.workspaceHistory[history.commandArgs.path].findIndex(workspaceHistory => workspaceHistory.index === history.index);
await this.syncHistory();
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.workspaceHistory?.[history.commandArgs.path] ?? []).splice(historyIndex, 1);
await this.storageManager.update(StorageKey.WorkspaceHistory, this.workspaceHistory);
try {

View File

@@ -118,8 +118,8 @@ export namespace IssueHandler {
});
}
const workflowHistory = act.historyManager.workspaceHistory[workspaceFolder.uri.fsPath]?.filter(history => history.commandArgs.workflow?.uri.fsPath === workflow.uri.fsPath);
if (workflowHistory && workflowHistory.length > 0) {
const workflowHistory = ((await act.historyManager.getWorkspaceHistory())[workspaceFolder.uri.fsPath] ?? []).filter(history => history.commandArgs.workflow?.uri.fsPath === workflow.uri.fsPath);
if (workflowHistory.length > 0) {
// Get last act command
const settings = await act.settingsManager.getSettings(workspaceFolder, true);
const history = workflowHistory[workflowHistory.length - 1];

View File

@@ -124,7 +124,7 @@ export class SettingsManager {
}
}
const existingSettings = this.storageManager.get<{ [path: string]: Setting[] }>(storageKey) || {};
const existingSettings = await this.storageManager.get<{ [path: string]: Setting[] }>(storageKey) || {};
if (existingSettings[workspaceFolder.uri.fsPath]) {
for (const [index, setting] of settings.entries()) {
const existingSetting = existingSettings[workspaceFolder.uri.fsPath].find(existingSetting => existingSetting.key === setting.key);
@@ -154,7 +154,7 @@ export class SettingsManager {
}
async getCustomSettings(workspaceFolder: WorkspaceFolder, storageKey: StorageKey): Promise<CustomSetting[]> {
const existingCustomSettings = this.storageManager.get<{ [path: string]: CustomSetting[] }>(storageKey) || {};
const existingCustomSettings = await this.storageManager.get<{ [path: string]: CustomSetting[] }>(storageKey) || {};
return existingCustomSettings[workspaceFolder.uri.fsPath] || [];
}
@@ -233,7 +233,7 @@ export class SettingsManager {
}
async editCustomSetting(workspaceFolder: WorkspaceFolder, newCustomSetting: CustomSetting, storageKey: StorageKey, forceAppend: boolean = false) {
const existingCustomSettings = this.storageManager.get<{ [path: string]: CustomSetting[] }>(storageKey) || {};
const existingCustomSettings = await this.storageManager.get<{ [path: string]: CustomSetting[] }>(storageKey) || {};
if (existingCustomSettings[workspaceFolder.uri.fsPath]) {
const index = existingCustomSettings[workspaceFolder.uri.fsPath]
.findIndex(customSetting =>
@@ -254,7 +254,7 @@ export class SettingsManager {
}
async removeCustomSetting(workspaceFolder: WorkspaceFolder, existingCustomSetting: CustomSetting, storageKey: StorageKey) {
const existingCustomSettings = this.storageManager.get<{ [path: string]: CustomSetting[] }>(storageKey) || {};
const existingCustomSettings = await this.storageManager.get<{ [path: string]: CustomSetting[] }>(storageKey) || {};
if (existingCustomSettings[workspaceFolder.uri.fsPath]) {
const index = existingCustomSettings[workspaceFolder.uri.fsPath].findIndex(customSetting =>
storageKey === StorageKey.Options ?
@@ -289,7 +289,7 @@ export class SettingsManager {
newSetting.value = '';
}
const existingSettings = this.storageManager.get<{ [path: string]: Setting[] }>(storageKey) || {};
const existingSettings = await this.storageManager.get<{ [path: string]: Setting[] }>(storageKey) || {};
if (existingSettings[workspaceFolder.uri.fsPath]) {
const index = existingSettings[workspaceFolder.uri.fsPath].findIndex(setting => setting.key === newSetting.key);
if (index > -1) {

View File

@@ -1,4 +1,4 @@
import { ExtensionContext } from "vscode";
import { ExtensionContext, Uri, workspace } from "vscode";
export enum StorageKey {
WorkspaceHistory = 'workspaceHistory',
@@ -9,7 +9,7 @@ export enum StorageKey {
Inputs = 'inputs',
InputFiles = 'inputFiles',
Runners = 'runners',
PayloadFiles = 'PayloadFiles',
PayloadFiles = 'payloadFiles',
Options = 'options'
}
@@ -21,15 +21,43 @@ export class StorageManager {
this.context = context;
}
keys(): readonly string[] {
return this.context.globalState.keys();
private async getStorageDirectory(): Promise<Uri> {
const storageDirectory = Uri.joinPath(this.context.storageUri ?? this.context.globalStorageUri, "storageManager");
await workspace.fs.createDirectory(storageDirectory).then(undefined, () => void 0);
return storageDirectory;
}
get<T>(storageKey: StorageKey): T | undefined {
return this.context.globalState.get<T>(`${this.extensionKey}.${storageKey}`);
private async getStorageFile(storageKey: StorageKey): Promise<Uri> {
const storageDirectory = await this.getStorageDirectory();
return Uri.joinPath(storageDirectory, `${storageKey}.json`);
}
async get<T>(storageKey: StorageKey): Promise<T | undefined> {
if ([StorageKey.Secrets, StorageKey.SecretFiles].includes(storageKey)) {
return this.context.globalState.get<T>(`${this.extensionKey}.${storageKey}`);
}
const storageFile = await this.getStorageFile(storageKey);
return workspace.fs.readFile(storageFile).then(data => {
if (data) {
return JSON.parse(data.toString()) as T;
}
return undefined;
}, (error) => {
if (error.code === 'FileNotFound') {
return undefined;
}
});
}
async update(storageKey: StorageKey, value: any): Promise<void> {
await this.context.globalState.update(`${this.extensionKey}.${storageKey}`, value);
if ([StorageKey.Secrets, StorageKey.SecretFiles].includes(storageKey)) {
await this.context.globalState.update(`${this.extensionKey}.${storageKey}`, value);
return;
}
const data = JSON.stringify(value, null, 2);
const storageFile = await this.getStorageFile(storageKey);
await workspace.fs.writeFile(storageFile, Buffer.from(data));
}
}

View File

@@ -87,18 +87,18 @@ export default class HistoryTreeDataProvider implements TreeDataProvider<GithubL
if (workspaceFolders.length === 1) {
items.push(...await new WorkspaceFolderHistoryTreeItem(workspaceFolders[0]).getChildren());
const workspaceHistory = act.historyManager.workspaceHistory[workspaceFolders[0].uri.fsPath];
if (workspaceHistory && workspaceHistory.length > 0) {
isRunning = act.historyManager.workspaceHistory[workspaceFolders[0].uri.fsPath].find(workspaceHistory => workspaceHistory.status === HistoryStatus.Running) !== undefined;
const workspaceHistory = (await act.historyManager.getWorkspaceHistory())[workspaceFolders[0].uri.fsPath] ?? [];
if (workspaceHistory.length > 0) {
isRunning = workspaceHistory.find(workspaceHistory => workspaceHistory.status === HistoryStatus.Running) !== undefined;
noHistory = false;
}
} else if (workspaceFolders.length > 1) {
for (const workspaceFolder of workspaceFolders) {
items.push(new WorkspaceFolderHistoryTreeItem(workspaceFolder));
const workspaceHistory = act.historyManager.workspaceHistory[workspaceFolder.uri.fsPath];
if (workspaceHistory && workspaceHistory.length > 0) {
isRunning = act.historyManager.workspaceHistory[workspaceFolder.uri.fsPath].find(workspaceHistory => workspaceHistory.status === HistoryStatus.Running) !== undefined;
const workspaceHistory = (await act.historyManager.getWorkspaceHistory())[workspaceFolder.uri.fsPath] ?? [];
if (workspaceHistory.length > 0) {
isRunning = workspaceHistory.find(workspaceHistory => workspaceHistory.status === HistoryStatus.Running) !== undefined;
noHistory = false;
}
}

View File

@@ -15,7 +15,7 @@ export default class WorkspaceFolderHistoryTreeItem extends TreeItem implements
async getChildren(): Promise<GithubLocalActionsTreeItem[]> {
const items: GithubLocalActionsTreeItem[] = [];
const workspaceHistory = act.historyManager.workspaceHistory[this.workspaceFolder.uri.fsPath];
const workspaceHistory = (await act.historyManager.getWorkspaceHistory())[this.workspaceFolder.uri.fsPath];
if (workspaceHistory) {
for (const history of workspaceHistory.slice().reverse()) {
items.push(new HistoryTreeItem(this.workspaceFolder, history));