From 397543c3fe3361340de6e6db29144022abe30199 Mon Sep 17 00:00:00 2001 From: Andrew Watkins Date: Thu, 7 May 2026 11:58:17 -0500 Subject: [PATCH] fix(ci): link status attempts to workflow view --- pkg/cmd/ci/status.go | 22 ++++++++++++++++++++-- pkg/cmd/ci/status_test.go | 3 ++- 2 files changed, 22 insertions(+), 3 deletions(-) diff --git a/pkg/cmd/ci/status.go b/pkg/cmd/ci/status.go index 2f1bcdf6..a071f53f 100644 --- a/pkg/cmd/ci/status.go +++ b/pkg/cmd/ci/status.go @@ -2,6 +2,8 @@ package ci import ( "fmt" + "net/url" + "strings" "github.com/depot/cli/pkg/config" "github.com/depot/cli/pkg/helpers" @@ -81,7 +83,7 @@ func NewCmdStatus() *cobra.Command { if canDownloadLogExport(attempt.Status) { fmt.Printf(" Download: depot ci logs %s --output-file %s%s\n", attempt.AttemptId, logDownloadFilename, orgFlag) } - fmt.Printf(" View: https://depot.dev/orgs/%s/workflows/%s\n", resp.OrgId, attempt.AttemptId) + fmt.Printf(" View: %s\n", statusAttemptViewURL(resp.OrgId, workflow.WorkflowId, job.JobId, attempt.AttemptId)) if attempt.GetSandboxId() != "" && statusIsRunning(attempt.GetStatus()) { fmt.Printf(" SSH: depot ci ssh %s --job %s%s\n", resp.RunId, job.JobKey, orgFlag) } @@ -172,7 +174,7 @@ func statusToJSON(resp *civ1.GetRunStatusResponse, orgFlag string) statusJSON { SessionID: attempt.GetSessionId(), LogsCommand: fmt.Sprintf("depot ci logs %s%s", attempt.GetAttemptId(), orgFlag), DownloadAvailable: canDownloadLogExport(attempt.GetStatus()), - ViewURL: fmt.Sprintf("https://depot.dev/orgs/%s/workflows/%s", resp.GetOrgId(), attempt.GetAttemptId()), + ViewURL: statusAttemptViewURL(resp.GetOrgId(), workflow.GetWorkflowId(), job.GetJobId(), attempt.GetAttemptId()), SSHAvailable: attempt.GetSandboxId() != "" && statusIsRunning(attempt.GetStatus()), } if a.DownloadAvailable { @@ -194,3 +196,19 @@ func statusToJSON(resp *civ1.GetRunStatusResponse, orgFlag string) statusJSON { func statusIsRunning(status string) bool { return status != "finished" && status != "failed" && status != "cancelled" } + +func statusAttemptViewURL(orgID, workflowID, jobID, attemptID string) string { + path := fmt.Sprintf("https://depot.dev/orgs/%s/workflows/%s", url.PathEscape(orgID), url.PathEscape(workflowID)) + + var params []string + if jobID != "" { + params = append(params, "job="+url.QueryEscape(jobID)) + } + if attemptID != "" { + params = append(params, "attempt="+url.QueryEscape(attemptID)) + } + if len(params) == 0 { + return path + } + return path + "?" + strings.Join(params, "&") +} diff --git a/pkg/cmd/ci/status_test.go b/pkg/cmd/ci/status_test.go index b72bc20a..e8a1f72f 100644 --- a/pkg/cmd/ci/status_test.go +++ b/pkg/cmd/ci/status_test.go @@ -74,6 +74,7 @@ func TestStatusHumanOutputShowsDownloadForFinishedAttemptsOnly(t *testing.T) { for _, want := range []string{ "Logs: depot ci logs att-finished --org org-123", "Download: depot ci logs att-finished --output-file logs.txt --org org-123", + "View: https://depot.dev/orgs/org-123/workflows/workflow-1?job=job-1&attempt=att-finished", "Logs: depot ci logs att-running --org org-123", "Logs: depot ci logs att-failed --org org-123", } { @@ -159,7 +160,7 @@ func TestStatusJSONOutput(t *testing.T) { if !attempts[0].DownloadAvailable || attempts[0].DownloadCommand != "depot ci logs att-finished --output-file logs.txt --org org-123" { t.Fatalf("unexpected finished download affordance: %+v", attempts[0]) } - if attempts[0].ViewURL != "https://depot.dev/orgs/org-123/workflows/att-finished" { + if attempts[0].ViewURL != "https://depot.dev/orgs/org-123/workflows/workflow-1?job=job-1&attempt=att-finished" { t.Fatalf("finished view url = %q", attempts[0].ViewURL) } if !attempts[1].SSHAvailable || attempts[1].SSHCommand != "depot ci ssh run-1 --job ci.yml:build --org org-123" {