From c335c5e25fecbd24456106b8096d05ad9317cd6a Mon Sep 17 00:00:00 2001 From: Brian DeHamer Date: Thu, 10 Jul 2025 11:46:09 -0700 Subject: [PATCH 1/4] include immutable field in release view Signed-off-by: Brian DeHamer --- pkg/cmd/release/shared/fetch.go | 2 ++ pkg/cmd/release/view/view.go | 1 + pkg/cmd/release/view/view_test.go | 4 ++++ 3 files changed, 7 insertions(+) diff --git a/pkg/cmd/release/shared/fetch.go b/pkg/cmd/release/shared/fetch.go index 322f33c17ce..d383d1d0fc1 100644 --- a/pkg/cmd/release/shared/fetch.go +++ b/pkg/cmd/release/shared/fetch.go @@ -30,6 +30,7 @@ var ReleaseFields = []string{ "id", "isDraft", "isPrerelease", + "isImmutable", "name", "publishedAt", "tagName", @@ -48,6 +49,7 @@ type Release struct { Body string `json:"body"` IsDraft bool `json:"draft"` IsPrerelease bool `json:"prerelease"` + IsImmutable bool `json:"immutable"` CreatedAt time.Time `json:"created_at"` PublishedAt *time.Time `json:"published_at"` diff --git a/pkg/cmd/release/view/view.go b/pkg/cmd/release/view/view.go index 59a19b4e5b0..4e88bf3aa9c 100644 --- a/pkg/cmd/release/view/view.go +++ b/pkg/cmd/release/view/view.go @@ -181,6 +181,7 @@ func renderReleasePlain(w io.Writer, release *shared.Release) error { fmt.Fprintf(w, "tag:\t%s\n", release.TagName) fmt.Fprintf(w, "draft:\t%v\n", release.IsDraft) fmt.Fprintf(w, "prerelease:\t%v\n", release.IsPrerelease) + fmt.Fprintf(w, "immutable:\t%v\n", release.IsImmutable) fmt.Fprintf(w, "author:\t%s\n", release.Author.Login) fmt.Fprintf(w, "created:\t%s\n", release.CreatedAt.Format(time.RFC3339)) if !release.IsDraft { diff --git a/pkg/cmd/release/view/view_test.go b/pkg/cmd/release/view/view_test.go index be345b186f8..95b00c6e261 100644 --- a/pkg/cmd/release/view/view_test.go +++ b/pkg/cmd/release/view/view_test.go @@ -31,6 +31,7 @@ func TestJSONFields(t *testing.T) { "id", "isDraft", "isPrerelease", + "isImmutable", "name", "publishedAt", "tagName", @@ -196,6 +197,7 @@ func Test_viewRun(t *testing.T) { tag: v1.2.3 draft: false prerelease: false + immutable: true author: MonaLisa created: 2020-08-31T15:44:24+02:00 published: 2020-08-31T15:44:24+02:00 @@ -220,6 +222,7 @@ func Test_viewRun(t *testing.T) { tag: v1.2.3 draft: false prerelease: false + immutable: true author: MonaLisa created: 2020-08-31T15:44:24+02:00 published: 2020-08-31T15:44:24+02:00 @@ -244,6 +247,7 @@ func Test_viewRun(t *testing.T) { shared.StubFetchRelease(t, fakeHTTP, "OWNER", "REPO", tt.opts.TagName, fmt.Sprintf(`{ "tag_name": "v1.2.3", "draft": false, + "immutable": true, "author": { "login": "MonaLisa" }, "body": "%[2]s", "created_at": "%[1]s", From 2ce3279ebc79982ca334c9244f09c7d55071595b Mon Sep 17 00:00:00 2001 From: "Babak K. Shandiz" Date: Wed, 16 Jul 2025 14:17:15 +0100 Subject: [PATCH 2/4] fix(run): add `IsSkipped` function Signed-off-by: Babak K. Shandiz --- pkg/cmd/run/shared/shared.go | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/pkg/cmd/run/shared/shared.go b/pkg/cmd/run/shared/shared.go index f085add4969..8c191846a1f 100644 --- a/pkg/cmd/run/shared/shared.go +++ b/pkg/cmd/run/shared/shared.go @@ -319,6 +319,10 @@ func IsFailureState(c Conclusion) bool { } } +func IsSkipped(c Conclusion) bool { + return c == Skipped +} + type RunsPayload struct { TotalCount int `json:"total_count"` WorkflowRuns []Run `json:"workflow_runs"` From 64d5d6c6c82b7454a9ff37ffdb372096df95404a Mon Sep 17 00:00:00 2001 From: "Babak K. Shandiz" Date: Wed, 16 Jul 2025 14:18:27 +0100 Subject: [PATCH 3/4] fix(run view): avoid looking for job log if its been skipped Signed-off-by: Babak K. Shandiz --- pkg/cmd/run/view/logs.go | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/pkg/cmd/run/view/logs.go b/pkg/cmd/run/view/logs.go index bd99830bb4e..8961381b3b0 100644 --- a/pkg/cmd/run/view/logs.go +++ b/pkg/cmd/run/view/logs.go @@ -91,6 +91,10 @@ func populateLogSegments(httpClient *http.Client, repo ghrepo.Interface, jobs [] apiLogFetcherCount := 0 for _, job := range jobs { + if shared.IsSkipped(job.Conclusion) { + continue + } + if onlyFailed && !shared.IsFailureState(job.Conclusion) { continue } From f67bd9a7d1ec6ddd11ec9b12e600d2e557853ed6 Mon Sep 17 00:00:00 2001 From: "Babak K. Shandiz" Date: Wed, 16 Jul 2025 14:19:13 +0100 Subject: [PATCH 4/4] test(run view): assert a skipped job does not cause error Signed-off-by: Babak K. Shandiz --- pkg/cmd/run/shared/test.go | 12 ++++++++++++ pkg/cmd/run/view/view_test.go | 23 +++++++++++++++++++++++ 2 files changed, 35 insertions(+) diff --git a/pkg/cmd/run/shared/test.go b/pkg/cmd/run/shared/test.go index 5a8a4584e3d..0920675230a 100644 --- a/pkg/cmd/run/shared/test.go +++ b/pkg/cmd/run/shared/test.go @@ -158,6 +158,18 @@ var LegacySuccessfulJobWithoutStepLogs Job = Job{ }, } +var SkippedJob Job = Job{ + ID: 13, + Status: Completed, + Conclusion: Skipped, + Name: "cool job", + StartedAt: TestRunStartTime, + CompletedAt: TestRunStartTime, + URL: "https://github.com/jobs/13", + RunID: 3, + Steps: []Step{}, +} + var FailedJob Job = Job{ ID: 20, Status: Completed, diff --git a/pkg/cmd/run/view/view_test.go b/pkg/cmd/run/view/view_test.go index 4c3a6a47172..5bcb587d19d 100644 --- a/pkg/cmd/run/view/view_test.go +++ b/pkg/cmd/run/view/view_test.go @@ -2254,6 +2254,29 @@ func TestViewRun(t *testing.T) { wantErr: true, errMsg: "job 20 is still in progress; logs will be available when it is complete", }, + { + name: "job log but job is skipped", + tty: false, + opts: &ViewOptions{ + JobID: "13", + Log: true, + }, + httpStubs: func(reg *httpmock.Registry) { + reg.Register( + httpmock.REST("GET", "repos/OWNER/REPO/actions/jobs/13"), + httpmock.JSONResponse(shared.SkippedJob)) + reg.Register( + httpmock.REST("GET", "repos/OWNER/REPO/actions/runs/3"), + httpmock.JSONResponse(shared.SuccessfulRun)) + reg.Register( + httpmock.REST("GET", "repos/OWNER/REPO/actions/runs/3/logs"), + httpmock.BinaryResponse(emptyZipArchive)) + reg.Register( + httpmock.REST("GET", "repos/OWNER/REPO/actions/workflows/123"), + httpmock.JSONResponse(shared.TestWorkflow)) + }, + wantOut: "", + }, { name: "noninteractive with job", opts: &ViewOptions{