@@ -3,7 +3,7 @@ import { getClient } from "../api/api";
33import { getPAT } from "../auth/pat" ;
44import { Protocol } from "../external/protocol" ;
55import { getGitHubProtocol } from "../git/repository" ;
6- import { Workflow , WorkflowRun } from "../model" ;
6+ import { Workflow , WorkflowRun , WorkflowJob , WorkflowStep } from "../model" ;
77import { getWorkflowUri , usesRepositoryDispatch } from "../workflow/workflow" ;
88import { getIconForWorkflowRun } from "./icons" ;
99import Octokit = require( "@octokit/rest" ) ;
@@ -78,7 +78,12 @@ class WorkflowRunNode extends vscode.TreeItem {
7878 public readonly run : WorkflowRun ,
7979 public readonly client : Octokit
8080 ) {
81- super ( `#${ run . id } ` ) ;
81+ super (
82+ `#${ run . id } ` ,
83+ ( run . status === "completed" &&
84+ vscode . TreeItemCollapsibleState . Collapsed ) ||
85+ undefined
86+ ) ;
8287
8388 this . description = `${ run . event } (${ ( run . head_sha || "" ) . substr ( 0 , 7 ) } )` ;
8489
@@ -91,12 +96,33 @@ class WorkflowRunNode extends vscode.TreeItem {
9196 this . contextValue += " rerunnable" ;
9297 }
9398
99+ if ( this . run . status === "completed" ) {
100+ this . contextValue += "completed" ;
101+ }
102+
94103 this . command = {
95104 title : "Open run" ,
96105 command : "workflow.run.open"
97106 } ;
98107 }
99108
109+ hasJobs ( ) : boolean {
110+ return this . run . status === "completed" ;
111+ }
112+
113+ async getJobs ( ) : Promise < WorkflowJobNode [ ] > {
114+ const result = await this . client . actions . listJobsForWorkflowRun ( {
115+ owner : this . repo . owner ,
116+ repo : this . repo . repositoryName ,
117+ run_id : this . run . id
118+ } ) ;
119+
120+ const resp = result . data ;
121+ const jobs : WorkflowJob [ ] = ( resp as any ) . jobs ;
122+
123+ return jobs . map ( job => new WorkflowJobNode ( this . repo , job , this . client ) ) ;
124+ }
125+
100126 get tooltip ( ) : string {
101127 return `${ this . run . status } - ${ this . run . conclusion } ` ;
102128 }
@@ -106,11 +132,54 @@ class WorkflowRunNode extends vscode.TreeItem {
106132 }
107133}
108134
135+ class WorkflowJobNode extends vscode . TreeItem {
136+ constructor (
137+ public readonly repo : Protocol ,
138+ public readonly job : WorkflowJob ,
139+ public readonly client : Octokit
140+ ) {
141+ super (
142+ job . name ,
143+ ( job . steps &&
144+ job . steps . length > 0 &&
145+ vscode . TreeItemCollapsibleState . Collapsed ) ||
146+ undefined
147+ ) ;
148+ }
149+
150+ hasSteps ( ) : boolean {
151+ return this . job . steps && this . job . steps . length > 0 ;
152+ }
153+
154+ async getSteps ( ) : Promise < WorkflowStepNode [ ] > {
155+ return this . job . steps . map (
156+ s => new WorkflowStepNode ( this . repo , s , this . client )
157+ ) ;
158+ }
159+
160+ get iconPath ( ) {
161+ return getIconForWorkflowRun ( this . job ) ;
162+ }
163+ }
164+
165+ class WorkflowStepNode extends vscode . TreeItem {
166+ constructor (
167+ public readonly repo : Protocol ,
168+ public readonly step : WorkflowStep ,
169+ public readonly client : Octokit
170+ ) {
171+ super ( step . name ) ;
172+
173+ this . contextValue = "step" ;
174+ }
175+ }
176+
109177type ActionsExplorerNode =
110178 | AuthenticationNode
111179 | NoGitHubRepositoryNode
112180 | WorkflowNode
113- | WorkflowRunNode ;
181+ | WorkflowRunNode
182+ | WorkflowStepNode ;
114183
115184export class ActionsExplorerProvider
116185 implements vscode . TreeDataProvider < ActionsExplorerNode > {
@@ -132,6 +201,18 @@ export class ActionsExplorerProvider
132201 ) : Promise < ActionsExplorerNode [ ] > {
133202 if ( element && element instanceof WorkflowNode ) {
134203 return element . getRuns ( ) ;
204+ } else if (
205+ element &&
206+ element instanceof WorkflowRunNode &&
207+ element . hasJobs ( )
208+ ) {
209+ return element . getJobs ( ) ;
210+ } else if (
211+ element &&
212+ element instanceof WorkflowJobNode &&
213+ element . hasSteps ( )
214+ ) {
215+ return element . getSteps ( ) ;
135216 } else {
136217 // Root nodes
137218 const repo = await getGitHubProtocol ( ) ;
0 commit comments