Skip to content
This repository was archived by the owner on Mar 28, 2023. It is now read-only.

Commit 3644fbc

Browse files
committed
Multi-repo logs
1 parent 5d8fd07 commit 3644fbc

7 files changed

Lines changed: 193 additions & 138 deletions

File tree

src/commands/openWorkflowFile.ts

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
import * as vscode from "vscode";
2+
import { Workflow } from "../model";
3+
import { getWorkflowUri } from "../workflow/workflow";
4+
5+
export function registerOpenWorkflowFile(context: vscode.ExtensionContext) {
6+
context.subscriptions.push(
7+
vscode.commands.registerCommand(
8+
"github-actions.explorer.openWorkflowFile",
9+
async (args) => {
10+
const wf: Workflow = args.wf;
11+
12+
const fileUri = getWorkflowUri(wf.path);
13+
if (fileUri) {
14+
const textDocument = await vscode.workspace.openTextDocument(fileUri);
15+
vscode.window.showTextDocument(textDocument);
16+
return;
17+
}
18+
19+
// File not found in workspace
20+
vscode.window.showErrorMessage(
21+
`Workflow ${wf.path} not found in current workspace`
22+
);
23+
}
24+
)
25+
);
26+
}

src/commands/openWorkflowRun.ts

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
import * as vscode from "vscode";
2+
import { WorkflowRun } from "../model";
3+
4+
export function registerOpenWorkflowRun(context: vscode.ExtensionContext) {
5+
context.subscriptions.push(
6+
vscode.commands.registerCommand(
7+
"github-actions.workflow.run.open",
8+
async (args) => {
9+
const run: WorkflowRun = args.run;
10+
const url = run.html_url;
11+
vscode.env.openExternal(vscode.Uri.parse(url));
12+
}
13+
)
14+
);
15+
}
Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
import * as vscode from "vscode";
2+
import { GitHubRepoContext } from "../git/repository";
3+
import { updateDecorations } from "../logs/formatProvider";
4+
import { getLogInfo } from "../logs/logInfoProvider";
5+
import { buildLogURI } from "../logs/scheme";
6+
import { WorkflowJob, WorkflowStep } from "../model";
7+
8+
export interface OpenWorkflowRunLogsCommandArgs {
9+
gitHubRepoContext: GitHubRepoContext;
10+
job: WorkflowJob;
11+
step?: WorkflowStep;
12+
}
13+
14+
export function registerOpenWorkflowRunLogs(context: vscode.ExtensionContext) {
15+
context.subscriptions.push(
16+
vscode.commands.registerCommand(
17+
"github-actions.workflow.logs",
18+
async (args: OpenWorkflowRunLogsCommandArgs) => {
19+
const gitHubRepoContext = args.gitHubRepoContext;
20+
const job = args.job;
21+
const step = args.step;
22+
const uri = buildLogURI(
23+
`%23${job.run_id} - ${job.name}`,
24+
gitHubRepoContext.owner,
25+
gitHubRepoContext.name,
26+
job.id
27+
);
28+
29+
const doc = await vscode.workspace.openTextDocument(uri);
30+
const editor = await vscode.window.showTextDocument(doc, {
31+
preview: false,
32+
});
33+
34+
const logInfo = getLogInfo(uri);
35+
if (!logInfo) {
36+
throw new Error("Could not get log info");
37+
}
38+
39+
// Custom formatting after the editor has been opened
40+
updateDecorations(editor, logInfo);
41+
42+
// Deep linking to steps
43+
if (step) {
44+
let matchingSection = logInfo.sections.find(
45+
(s) => s.name && s.name === step.name
46+
);
47+
if (!matchingSection) {
48+
// If we cannot match by name, see if we can try to match by number
49+
matchingSection = logInfo.sections[step.number - 1];
50+
}
51+
52+
if (matchingSection) {
53+
editor.revealRange(
54+
new vscode.Range(
55+
matchingSection.start,
56+
0,
57+
matchingSection.start,
58+
0
59+
),
60+
vscode.TextEditorRevealType.InCenter
61+
);
62+
}
63+
}
64+
}
65+
)
66+
);
67+
}

src/extension.ts

Lines changed: 20 additions & 92 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,12 @@
11
import * as vscode from "vscode";
2+
import { registerOpenWorkflowFile } from "./commands/openWorkflowFile";
3+
import { registerOpenWorkflowRun } from "./commands/openWorkflowRun";
4+
import { registerOpenWorkflowRunLogs } from "./commands/openWorkflowRunLogs";
25
import { getGitHubContext } from "./git/repository";
6+
import { LogScheme } from "./logs/constants";
7+
import { WorkflowStepLogProvider } from "./logs/fileProvider";
8+
import { WorkflowStepLogFoldingProvider } from "./logs/foldingProvider";
9+
import { WorkflowStepLogSymbolProvider } from "./logs/symbolProvider";
310
import { initWorkflowDocumentTracking } from "./tracker/workflowDocumentTracker";
411
import { initResources } from "./treeViews/icons";
512
import { SettingsTreeProvider } from "./treeViews/settings";
@@ -17,7 +24,10 @@ export function activate(context: vscode.ExtensionContext) {
1724
// Track workflow
1825
initWorkflowDocumentTracking(context);
1926

20-
// Actions Explorer
27+
//
28+
// Tree views
29+
//
30+
2131
const workflowTreeProvider = new WorkflowsTreeProvider();
2232
context.subscriptions.push(
2333
vscode.window.registerTreeDataProvider(
@@ -41,36 +51,15 @@ export function activate(context: vscode.ExtensionContext) {
4151
})
4252
);
4353

44-
/*
45-
context.subscriptions.push(
46-
vscode.commands.registerCommand(
47-
"github-actions.explorer.openRun",
48-
(args) => {
49-
const url = args.url || args;
50-
vscode.commands.executeCommand("vscode.open", vscode.Uri.parse(url));
51-
}
52-
)
53-
);
54-
context.subscriptions.push(
55-
vscode.commands.registerCommand(
56-
"github-actions.explorer.openWorkflowFile",
57-
async (args) => {
58-
const wf: Workflow = args.wf;
54+
//
55+
// Commands
56+
//
5957

60-
const fileUri = getWorkflowUri(wf.path);
61-
if (fileUri) {
62-
const textDocument = await vscode.workspace.openTextDocument(fileUri);
63-
vscode.window.showTextDocument(textDocument);
64-
return;
65-
}
58+
registerOpenWorkflowRun(context);
59+
registerOpenWorkflowFile(context);
60+
registerOpenWorkflowRunLogs(context);
6661

67-
// File not found in workspace
68-
vscode.window.showErrorMessage(
69-
`Workflow ${wf.path} not found in current workspace`
70-
);
71-
}
72-
)
73-
);
62+
/*
7463
context.subscriptions.push(
7564
vscode.commands.registerCommand(
7665
"github-actions.explorer.triggerRun",
@@ -224,69 +213,6 @@ export function activate(context: vscode.ExtensionContext) {
224213
)
225214
);
226215
227-
context.subscriptions.push(
228-
vscode.commands.registerCommand(
229-
"github-actions.workflow.run.open",
230-
async (args) => {
231-
const run: WorkflowRun = args.run;
232-
const url = run.html_url;
233-
vscode.env.openExternal(vscode.Uri.parse(url));
234-
}
235-
)
236-
);
237-
238-
context.subscriptions.push(
239-
vscode.commands.registerCommand(
240-
"github-actions.workflow.logs",
241-
async (args) => {
242-
const gitHubContext: GitHubContext = args.gitHubContext;
243-
const job: WorkflowJob = args.job;
244-
const step: WorkflowStep | undefined = args.step;
245-
const uri = buildLogURI(
246-
gitHubContext.owner,
247-
gitHubContext.name,
248-
job.id,
249-
step?.name
250-
);
251-
const doc = await vscode.workspace.openTextDocument(uri);
252-
const editor = await vscode.window.showTextDocument(doc, {
253-
preview: false,
254-
});
255-
256-
const logInfo = getLogInfo(uri);
257-
if (!logInfo) {
258-
throw new Error("Could not get log info");
259-
}
260-
261-
// Custom formatting after the editor has been opened
262-
updateDecorations(editor, logInfo);
263-
264-
// Deep linking
265-
if (step) {
266-
let matchingSection = logInfo.sections.find(
267-
(s) => s.name && s.name === step.name
268-
);
269-
if (!matchingSection) {
270-
// If we cannot match by name, see if we can try to match by number
271-
matchingSection = logInfo.sections[step.number - 1];
272-
}
273-
274-
if (matchingSection) {
275-
editor.revealRange(
276-
new vscode.Range(
277-
matchingSection.start,
278-
0,
279-
matchingSection.start,
280-
0
281-
),
282-
vscode.TextEditorRevealType.InCenter
283-
);
284-
}
285-
}
286-
}
287-
)
288-
);
289-
290216
context.subscriptions.push(
291217
vscode.commands.registerCommand(
292218
"github-actions.workflow.run.rerun",
@@ -467,6 +393,7 @@ export function activate(context: vscode.ExtensionContext) {
467393
}
468394
)
469395
);
396+
*/
470397

471398
//
472399
// Log providers
@@ -494,6 +421,7 @@ export function activate(context: vscode.ExtensionContext) {
494421
)
495422
);
496423

424+
/*
497425
//
498426
// Editing features
499427
//

src/git/repository.ts

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -148,3 +148,15 @@ export async function resetGitHubContext() {
148148
gitHubContext = undefined;
149149
await getGitHubContext();
150150
}
151+
152+
export async function getGitHubContextForRepo(
153+
owner: string,
154+
name: string
155+
): Promise<GitHubRepoContext | undefined> {
156+
const gitHubContext = await getGitHubContext();
157+
if (!gitHubContext) {
158+
return undefined;
159+
}
160+
161+
return gitHubContext.repos.find((r) => r.owner === owner && r.name === name);
162+
}

src/logs/fileProvider.ts

Lines changed: 39 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,8 @@
11
import * as vscode from "vscode";
2+
import { getGitHubContextForRepo } from "../git/repository";
3+
import { cacheLogInfo } from "./logInfoProvider";
4+
import { parseLog } from "./model";
5+
import { parseUri } from "./scheme";
26

37
export class WorkflowStepLogProvider
48
implements vscode.TextDocumentContentProvider
@@ -7,43 +11,40 @@ export class WorkflowStepLogProvider
711
onDidChange = this.onDidChangeEmitter.event;
812

913
async provideTextDocumentContent(uri: vscode.Uri): Promise<string> {
10-
// const { owner, repo, jobId } = parseUri(uri);
11-
12-
// const githubContext = await getGitHubContext();
13-
// if (!githubContext) {
14-
// throw new Error("Could not load logs");
15-
// }
16-
17-
// try {
18-
// const result = await githubContext?.client.actions.downloadJobLogsForWorkflowRun(
19-
// {
20-
// owner: owner,
21-
// repo: repo,
22-
// job_id: jobId,
23-
// }
24-
// );
25-
26-
// const log = result.data as any;
27-
28-
// const logInfo = parseLog(log);
29-
// cacheLogInfo(uri, logInfo);
30-
31-
// return logInfo.updatedLog;
32-
// } catch (e) {
33-
// if ("status" in e && e.status === 410) {
34-
// cacheLogInfo(uri, {
35-
// colorFormats: [],
36-
// sections: [],
37-
// updatedLog: "",
38-
// });
39-
40-
// return "Could not open logs, they are expired.";
41-
// }
42-
43-
// console.error("Error loading logs", e);
44-
// return `Could not open logs, unhandled error: ${e?.message || e}`;
45-
// }
46-
47-
return "IMPLEMENT ME";
14+
const { owner, repo, jobId } = parseUri(uri);
15+
16+
const githubRepoContext = await getGitHubContextForRepo(owner, repo);
17+
if (!githubRepoContext) {
18+
throw new Error("Could not load logs");
19+
}
20+
21+
try {
22+
const result =
23+
await githubRepoContext?.client.actions.downloadJobLogsForWorkflowRun({
24+
owner: owner,
25+
repo: repo,
26+
job_id: jobId,
27+
});
28+
29+
const log = result.data as any;
30+
31+
const logInfo = parseLog(log);
32+
cacheLogInfo(uri, logInfo);
33+
34+
return logInfo.updatedLog;
35+
} catch (e) {
36+
if ("status" in e && e.status === 410) {
37+
cacheLogInfo(uri, {
38+
colorFormats: [],
39+
sections: [],
40+
updatedLog: "",
41+
});
42+
43+
return "Could not open logs, they are expired.";
44+
}
45+
46+
console.error("Error loading logs", e);
47+
return `Could not open logs, unhandled error: ${e?.message || e}`;
48+
}
4849
}
4950
}

0 commit comments

Comments
 (0)