@@ -14,30 +14,48 @@ struct Check {
1414 workflow string
1515}
1616
17+ struct GhRun {
18+ database_id i64 @[json: databaseId]
19+ workflow_name string @[json: workflowName]
20+ }
21+
22+ struct GhJob {
23+ name string
24+ status string
25+ conclusion string
26+ url string
27+ database_id i64 @[json: databaseId]
28+ }
29+
30+ struct GhRunView {
31+ jobs []GhJob
32+ workflow_name string @[json: workflowName]
33+ }
34+
1735fn main () {
1836 unbuffer_stdout ()
1937 if os.args.len != 2 {
20- println ('Usage: v run gh_restart_failed.v <PR_NUMBER>' )
21- return
22- }
23- pr_number := os.args[1 ].int ()
24- println (c (tg, 'Fetching checks for PR ${m (pr_number )}...' ))
25- // Fetch checks using gh CLI
26- cmd := 'gh pr checks ${pr_number } --json name,bucket,state,link,workflow'
27- res := os.execute (cmd)
28- if res.exit_code != 0 {
29- println ('Error fetching checks: ${res .output }' )
38+ println ('Usage: v run gh_restart_failed.v <PR_NUMBER|REF>' )
3039 return
3140 }
32- checks := json.decode ([]Check, res.output) or {
33- println ('Failed to decode JSON: ${err }' )
34- return
41+ arg := os.args[1 ]
42+ mut is_pr := true
43+ if arg.len > 5 {
44+ is_pr = false
45+ } else {
46+ for r in arg {
47+ if ! r.is_digit () {
48+ is_pr = false
49+ break
50+ }
51+ }
3552 }
3653 mut failed := []Check{}
3754 mut cancelled := []Check{}
3855 mut succeeded := 0
3956 mut in_progress := 0
4057 mut total := 0
58+ checks := if is_pr { get_checks_for_pr (arg.int ()) } else { get_checks_for_commit (arg) }
4159 for check in checks {
4260 total++
4361 match check.bucket {
@@ -137,3 +155,65 @@ fn main() {
137155fn m (metric int ) string {
138156 return c (tb, metric.str ())
139157}
158+
159+ fn get_checks_for_pr (pr_number int ) []Check {
160+ mut checks := []Check{}
161+ println (c (tg, 'Fetching checks for PR ${m (pr_number )}...' ))
162+ cmd := 'gh pr checks ${pr_number } --json name,bucket,state,link,workflow'
163+ res := os.execute (cmd)
164+ if res.exit_code != 0 {
165+ println ('Error fetching checks: ${res .output }' )
166+ exit (1 )
167+ }
168+ checks = json.decode ([]Check, res.output) or {
169+ println ('Failed to decode JSON: ${err }' )
170+ exit (1 )
171+ }
172+ return checks
173+ }
174+
175+ fn get_checks_for_commit (commit string ) []Check {
176+ mut checks := []Check{}
177+ println (c (tg, 'Fetching checks for ref ${c (tb , commit )}...' ))
178+ runs_res := os.execute ('gh run list --commit ${commit } --limit 100 --json databaseId,workflowName' )
179+ if runs_res.exit_code != 0 {
180+ println ('Error fetching runs: ${runs_res .output }' )
181+ exit (1 )
182+ }
183+ runs := json.decode ([]GhRun, runs_res.output) or {
184+ println ('Failed to decode runs JSON: ${err }' )
185+ exit (1 )
186+ }
187+ for run in runs {
188+ view_res := os.execute ('gh run view ${run .database_id } --json jobs,workflowName' )
189+ if view_res.exit_code != 0 {
190+ continue
191+ }
192+ view := json.decode (GhRunView, view_res.output) or { continue }
193+ for job in view.jobs {
194+ mut bucket := 'pass'
195+ mut state := job.conclusion.to_upper ()
196+ if state == '' {
197+ state = job.status.to_upper ()
198+ }
199+ if job.conclusion == 'failure' {
200+ bucket = 'fail'
201+ } else if job.conclusion == 'cancelled' {
202+ bucket = 'cancel'
203+ } else if job.status in ['in_progress' , 'queued' , 'waiting' ] {
204+ bucket = 'pending'
205+ if state == '' {
206+ state = 'PENDING'
207+ }
208+ }
209+ checks << Check{
210+ name: job.name
211+ bucket: bucket
212+ state: state
213+ link: job.url
214+ workflow: view.workflow_name
215+ }
216+ }
217+ }
218+ return checks
219+ }
0 commit comments