From 86b4bb99561857310bf0bc3238d928a1e0af5d60 Mon Sep 17 00:00:00 2001 From: Andy Feller Date: Wed, 16 Oct 2024 19:38:10 -0400 Subject: [PATCH] Include startedAt, completedAt in run steps data This commit expands the `Step` structure used with GitHub Actions workflow runs to include fields indicating when steps start and complete. This information is already provided by the GitHub API, so this only involves expanding the structure, fields exported, and the associated tests. In the future, I could see `gh` including the duration calculation which is used when viewing workflow or workflow run. --- pkg/cmd/run/shared/shared.go | 32 ++++++++++++++++---------- pkg/cmd/run/shared/shared_test.go | 38 +++++++++++++++++++------------ 2 files changed, 44 insertions(+), 26 deletions(-) diff --git a/pkg/cmd/run/shared/shared.go b/pkg/cmd/run/shared/shared.go index e5f09dec968..90ab5a7fe0c 100644 --- a/pkg/cmd/run/shared/shared.go +++ b/pkg/cmd/run/shared/shared.go @@ -180,16 +180,22 @@ func (r *Run) ExportData(fields []string) map[string]interface{} { for _, j := range r.Jobs { steps := make([]interface{}, 0, len(j.Steps)) for _, s := range j.Steps { + var stepCompletedAt time.Time + if !s.CompletedAt.IsZero() { + stepCompletedAt = s.CompletedAt + } steps = append(steps, map[string]interface{}{ - "name": s.Name, - "status": s.Status, - "conclusion": s.Conclusion, - "number": s.Number, + "name": s.Name, + "status": s.Status, + "conclusion": s.Conclusion, + "number": s.Number, + "startedAt": s.StartedAt, + "completedAt": stepCompletedAt, }) } - var completedAt time.Time + var jobCompletedAt time.Time if !j.CompletedAt.IsZero() { - completedAt = j.CompletedAt + jobCompletedAt = j.CompletedAt } jobs = append(jobs, map[string]interface{}{ "databaseId": j.ID, @@ -198,7 +204,7 @@ func (r *Run) ExportData(fields []string) map[string]interface{} { "name": j.Name, "steps": steps, "startedAt": j.StartedAt, - "completedAt": completedAt, + "completedAt": jobCompletedAt, "url": j.URL, }) } @@ -225,11 +231,13 @@ type Job struct { } type Step struct { - Name string - Status Status - Conclusion Conclusion - Number int - Log *zip.File + Name string + Status Status + Conclusion Conclusion + Number int + StartedAt time.Time `json:"started_at"` + CompletedAt time.Time `json:"completed_at"` + Log *zip.File } type Steps []Step diff --git a/pkg/cmd/run/shared/shared_test.go b/pkg/cmd/run/shared/shared_test.go index 15663cd0a67..752ba2fc457 100644 --- a/pkg/cmd/run/shared/shared_test.go +++ b/pkg/cmd/run/shared/shared_test.go @@ -110,8 +110,12 @@ func TestRun_Duration(t *testing.T) { func TestRunExportData(t *testing.T) { oldestStartedAt, _ := time.Parse(time.RFC3339, "2022-07-20T11:20:13Z") + oldestStepStartedAt, _ := time.Parse(time.RFC3339, "2022-07-20T11:20:15Z") + oldestStepCompletedAt, _ := time.Parse(time.RFC3339, "2022-07-20T11:21:10Z") oldestCompletedAt, _ := time.Parse(time.RFC3339, "2022-07-20T11:21:16Z") newestStartedAt, _ := time.Parse(time.RFC3339, "2022-07-20T11:20:55Z") + newestStepStartedAt, _ := time.Parse(time.RFC3339, "2022-07-20T11:21:01Z") + newestStepCompletedAt, _ := time.Parse(time.RFC3339, "2022-07-20T11:23:10Z") newestCompletedAt, _ := time.Parse(time.RFC3339, "2022-07-20T11:23:16Z") tests := []struct { @@ -132,10 +136,12 @@ func TestRunExportData(t *testing.T) { Name: "macos", Steps: []Step{ { - Name: "Checkout", - Status: "completed", - Conclusion: "success", - Number: 1, + Name: "Checkout", + Status: "completed", + Conclusion: "success", + Number: 1, + StartedAt: oldestStepStartedAt, + CompletedAt: oldestStepCompletedAt, }, }, StartedAt: oldestStartedAt, @@ -144,7 +150,7 @@ func TestRunExportData(t *testing.T) { }, }, }, - output: `{"jobs":[{"completedAt":"2022-07-20T11:21:16Z","conclusion":"success","databaseId":123456,"name":"macos","startedAt":"2022-07-20T11:20:13Z","status":"completed","steps":[{"conclusion":"success","name":"Checkout","number":1,"status":"completed"}],"url":"https://example.com/OWNER/REPO/actions/runs/123456"}]}`, + output: `{"jobs":[{"completedAt":"2022-07-20T11:21:16Z","conclusion":"success","databaseId":123456,"name":"macos","startedAt":"2022-07-20T11:20:13Z","status":"completed","steps":[{"completedAt":"2022-07-20T11:21:10Z","conclusion":"success","name":"Checkout","number":1,"startedAt":"2022-07-20T11:20:15Z","status":"completed"}],"url":"https://example.com/OWNER/REPO/actions/runs/123456"}]}`, }, { name: "exports workflow run's multiple jobs", @@ -158,10 +164,12 @@ func TestRunExportData(t *testing.T) { Name: "macos", Steps: []Step{ { - Name: "Checkout", - Status: "completed", - Conclusion: "success", - Number: 1, + Name: "Checkout", + Status: "completed", + Conclusion: "success", + Number: 1, + StartedAt: oldestStepStartedAt, + CompletedAt: oldestStepCompletedAt, }, }, StartedAt: oldestStartedAt, @@ -175,10 +183,12 @@ func TestRunExportData(t *testing.T) { Name: "windows", Steps: []Step{ { - Name: "Checkout", - Status: "completed", - Conclusion: "error", - Number: 2, + Name: "Checkout", + Status: "completed", + Conclusion: "error", + Number: 2, + StartedAt: newestStepStartedAt, + CompletedAt: newestStepCompletedAt, }, }, StartedAt: newestStartedAt, @@ -187,7 +197,7 @@ func TestRunExportData(t *testing.T) { }, }, }, - output: `{"jobs":[{"completedAt":"2022-07-20T11:21:16Z","conclusion":"success","databaseId":123456,"name":"macos","startedAt":"2022-07-20T11:20:13Z","status":"completed","steps":[{"conclusion":"success","name":"Checkout","number":1,"status":"completed"}],"url":"https://example.com/OWNER/REPO/actions/runs/123456"},{"completedAt":"2022-07-20T11:23:16Z","conclusion":"error","databaseId":234567,"name":"windows","startedAt":"2022-07-20T11:20:55Z","status":"completed","steps":[{"conclusion":"error","name":"Checkout","number":2,"status":"completed"}],"url":"https://example.com/OWNER/REPO/actions/runs/234567"}]}`, + output: `{"jobs":[{"completedAt":"2022-07-20T11:21:16Z","conclusion":"success","databaseId":123456,"name":"macos","startedAt":"2022-07-20T11:20:13Z","status":"completed","steps":[{"completedAt":"2022-07-20T11:21:10Z","conclusion":"success","name":"Checkout","number":1,"startedAt":"2022-07-20T11:20:15Z","status":"completed"}],"url":"https://example.com/OWNER/REPO/actions/runs/123456"},{"completedAt":"2022-07-20T11:23:16Z","conclusion":"error","databaseId":234567,"name":"windows","startedAt":"2022-07-20T11:20:55Z","status":"completed","steps":[{"completedAt":"2022-07-20T11:23:10Z","conclusion":"error","name":"Checkout","number":2,"startedAt":"2022-07-20T11:21:01Z","status":"completed"}],"url":"https://example.com/OWNER/REPO/actions/runs/234567"}]}`, }, { name: "exports workflow run with attempt count",