diff --git a/models/actions/run_job.go b/models/actions/run_job.go index c7ab93d2c6..edd1170072 100644 --- a/models/actions/run_job.go +++ b/models/actions/run_job.go @@ -66,7 +66,14 @@ func (job *ActionRunJob) HTMLURL(ctx context.Context) (string, error) { return "", fmt.Errorf("action_run_job: unable to find job on run: %d", job.ID) } - return fmt.Sprintf("%s/actions/runs/%d/jobs/%d/attempt/%d", job.Run.Repo.HTMLURL(), job.Run.Index, jobIndex, job.Attempt), nil + attempt := job.Attempt + // If a job has never been fetched by a runner yet, it will have attempt 0 -- but this attempt will never have a + // valid UI since attempt is incremented to 1 if it is picked up by a runner. + if attempt == 0 { + attempt = 1 + } + + return fmt.Sprintf("%s/actions/runs/%d/jobs/%d/attempt/%d", job.Run.Repo.HTMLURL(), job.Run.Index, jobIndex, attempt), nil } func (job *ActionRunJob) Duration() time.Duration { diff --git a/models/fixtures/action_run_job.yml b/models/fixtures/action_run_job.yml index 00f9998ba9..911e99c076 100644 --- a/models/fixtures/action_run_job.yml +++ b/models/fixtures/action_run_job.yml @@ -136,7 +136,7 @@ commit_sha: 985f0301dba5e7b34be866819cd15ad3d8f508ee is_fork_pull_request: 0 name: job_2 - attempt: 1 + attempt: 0 job_id: job_2 task_id: null status: 5 diff --git a/routers/web/repo/actions/view_test.go b/routers/web/repo/actions/view_test.go index b94e57591a..e3f72e9e37 100644 --- a/routers/web/repo/actions/view_test.go +++ b/routers/web/repo/actions/view_test.go @@ -386,6 +386,8 @@ func TestActionsViewRedirectToLatestAttempt(t *testing.T) { jobIndex int64 expectedCode int expectedURL string + userID int64 + repoID int64 }{ { name: "no job index", @@ -420,13 +422,31 @@ func TestActionsViewRedirectToLatestAttempt(t *testing.T) { jobIndex: 500, expectedURL: "https://try.gitea.io/user2/repo1/actions/runs/187/jobs/0/attempt/1", }, + // This ActionRunJob has Attempt: 0 and TaskID: null, which indicates its first run is pending pickup by a + // runner. Should redirect to the attempt/1 since that's what it will be when it is running. + { + name: "redirect to non-picked task", + userID: 2, + repoID: 4, + runIndex: 190, + jobIndex: 0, + expectedURL: "https://try.gitea.io/user5/repo4/actions/runs/190/jobs/0/attempt/1", + }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { ctx, resp := contexttest.MockContext(t, "user2/repo1/actions/runs/0") - contexttest.LoadUser(t, ctx, 2) - contexttest.LoadRepo(t, ctx, 1) + if tt.userID == 0 { + contexttest.LoadUser(t, ctx, 2) + } else { + contexttest.LoadUser(t, ctx, tt.userID) + } + if tt.repoID == 0 { + contexttest.LoadRepo(t, ctx, 1) + } else { + contexttest.LoadRepo(t, ctx, tt.repoID) + } ctx.SetParams(":run", fmt.Sprintf("%d", tt.runIndex)) if tt.jobIndex != -1 { ctx.SetParams(":job", fmt.Sprintf("%d", tt.jobIndex))