|
| 1 | +import * as vscode from "vscode"; |
| 2 | + |
| 3 | +import {canReachGitHubAPI} from "../api/canReachGitHubAPI"; |
| 4 | +import {getGitHubContext} from "../git/repository"; |
| 5 | +import {logDebug, logError} from "../log"; |
| 6 | +import {RunStore} from "../store/store"; |
| 7 | +import {AttemptNode} from "./shared/attemptNode"; |
| 8 | +import {AuthenticationNode} from "./shared/authenticationNode"; |
| 9 | +import {ErrorNode} from "./shared/errorNode"; |
| 10 | +import {GitHubAPIUnreachableNode} from "./shared/gitHubApiUnreachableNode"; |
| 11 | +import {NoWorkflowJobsNode} from "./shared/noWorkflowJobsNode"; |
| 12 | +import {PreviousAttemptsNode} from "./shared/previousAttemptsNode"; |
| 13 | +import {WorkflowJobNode} from "./shared/workflowJobNode"; |
| 14 | +import {WorkflowRunNode} from "./shared/workflowRunNode"; |
| 15 | +import {WorkflowRunTreeDataProvider} from "./workflowRunTreeDataProvider"; |
| 16 | + |
| 17 | +type CombinedWorkflowsTreeNode = |
| 18 | + | AuthenticationNode |
| 19 | + | WorkflowRunNode |
| 20 | + | PreviousAttemptsNode |
| 21 | + | AttemptNode |
| 22 | + | WorkflowJobNode |
| 23 | + | NoWorkflowJobsNode |
| 24 | + | GitHubAPIUnreachableNode; |
| 25 | + |
| 26 | +export class CombinedWorkflowsTreeProvider |
| 27 | + extends WorkflowRunTreeDataProvider |
| 28 | + implements vscode.TreeDataProvider<CombinedWorkflowsTreeNode> |
| 29 | +{ |
| 30 | + private _onDidChangeTreeData = new vscode.EventEmitter<CombinedWorkflowsTreeNode | null>(); |
| 31 | + readonly onDidChangeTreeData = this._onDidChangeTreeData.event; |
| 32 | + |
| 33 | + constructor(store: RunStore) { |
| 34 | + super(store); |
| 35 | + } |
| 36 | + |
| 37 | + protected _updateNode(node: WorkflowRunNode): void { |
| 38 | + this._onDidChangeTreeData.fire(node); |
| 39 | + } |
| 40 | + |
| 41 | + async refresh(): Promise<void> { |
| 42 | + if (await canReachGitHubAPI()) { |
| 43 | + this._onDidChangeTreeData.fire(null); |
| 44 | + } else { |
| 45 | + await vscode.window.showWarningMessage("Unable to refresh, could not reach GitHub API"); |
| 46 | + } |
| 47 | + } |
| 48 | + |
| 49 | + getTreeItem(element: CombinedWorkflowsTreeNode): vscode.TreeItem | Thenable<vscode.TreeItem> { |
| 50 | + return element; |
| 51 | + } |
| 52 | + |
| 53 | + async getChildren(element?: CombinedWorkflowsTreeNode | undefined): Promise<CombinedWorkflowsTreeNode[]> { |
| 54 | + if (!element) { |
| 55 | + logDebug("Getting combined workflow runs from all repos"); |
| 56 | + |
| 57 | + try { |
| 58 | + const gitHubContext = await getGitHubContext(); |
| 59 | + if (!gitHubContext) { |
| 60 | + logDebug("could not get github context for combined workflows"); |
| 61 | + return [new GitHubAPIUnreachableNode()]; |
| 62 | + } |
| 63 | + |
| 64 | + if (gitHubContext.repos.length === 0) { |
| 65 | + return []; |
| 66 | + } |
| 67 | + |
| 68 | + const allRuns: WorkflowRunNode[] = []; |
| 69 | + |
| 70 | + for (const repo of gitHubContext.repos) { |
| 71 | + try { |
| 72 | + const result = await repo.client.actions.listWorkflowRunsForRepo({ |
| 73 | + owner: repo.owner, |
| 74 | + repo: repo.name, |
| 75 | + per_page: 20 |
| 76 | + }); |
| 77 | + |
| 78 | + const runs = this.runNodes(repo, result.data.workflow_runs, true); |
| 79 | + allRuns.push(...runs); |
| 80 | + } catch (e) { |
| 81 | + logError(e as Error, `Failed to fetch runs for ${repo.owner}/${repo.name}`); |
| 82 | + } |
| 83 | + } |
| 84 | + |
| 85 | + allRuns.sort((a, b) => { |
| 86 | + const aTime = new Date(a.run.run.created_at).getTime(); |
| 87 | + const bTime = new Date(b.run.run.created_at).getTime(); |
| 88 | + return bTime - aTime; |
| 89 | + }); |
| 90 | + |
| 91 | + return allRuns; |
| 92 | + } catch (e) { |
| 93 | + logError(e as Error, "Failed to get GitHub context"); |
| 94 | + |
| 95 | + if ((e as Error).message.startsWith("Could not get token from the GitHub authentication provider.")) { |
| 96 | + return [new AuthenticationNode()]; |
| 97 | + } |
| 98 | + |
| 99 | + return [new ErrorNode(`An error has occurred: ${(e as Error).message}`)]; |
| 100 | + } |
| 101 | + } |
| 102 | + |
| 103 | + if (element instanceof WorkflowRunNode) { |
| 104 | + return element.getJobs(); |
| 105 | + } else if (element instanceof PreviousAttemptsNode) { |
| 106 | + return element.getAttempts(); |
| 107 | + } else if (element instanceof AttemptNode) { |
| 108 | + return element.getJobs(); |
| 109 | + } else if (element instanceof WorkflowJobNode) { |
| 110 | + return element.getSteps(); |
| 111 | + } |
| 112 | + |
| 113 | + return []; |
| 114 | + } |
| 115 | +} |
0 commit comments