From 9c11690c89fd91c2d509b454a0d0d9a2817d3c1e Mon Sep 17 00:00:00 2001 From: Nicolas Date: Thu, 7 May 2026 18:47:00 +0200 Subject: [PATCH 1/4] fix(actions): ensure step status reflects individual task step status in workflow jobs --- services/convert/action_test.go | 59 +++++++++++++++++++++++++++++++++ services/convert/convert.go | 2 +- 2 files changed, 60 insertions(+), 1 deletion(-) diff --git a/services/convert/action_test.go b/services/convert/action_test.go index 9efc0e36a8395..35c79fab68ac9 100644 --- a/services/convert/action_test.go +++ b/services/convert/action_test.go @@ -9,6 +9,7 @@ import ( "testing" actions_model "code.gitea.io/gitea/models/actions" + db "code.gitea.io/gitea/models/db" repo_model "code.gitea.io/gitea/models/repo" "code.gitea.io/gitea/models/unit" "code.gitea.io/gitea/models/unittest" @@ -124,3 +125,61 @@ func TestToActionWorkflowRun_UsesTriggerEvent(t *testing.T) { require.NoError(t, err) assert.Equal(t, "schedule", apiRun.Event) } + +func TestToActionWorkflowJob_StepStatusIsIndependentOfJobStatus(t *testing.T) { + assert.NoError(t, unittest.PrepareTestDatabase()) + ctx := t.Context() + + run := &actions_model.ActionRun{ + ID: 9001, + RepoID: 2, + TriggerUserID: 1, + WorkflowID: "test.yaml", + Index: 9001, + Ref: "refs/heads/main", + CommitSHA: "c2d72f548424103f01ee1dc02889c1e2bff816b0", + Event: "push", + TriggerEvent: "push", + Status: actions_model.StatusFailure, + } + require.NoError(t, db.Insert(ctx, run)) + + task := &actions_model.ActionTask{ + ID: 9001, + JobID: 9001, + RepoID: 2, + Status: actions_model.StatusFailure, + TokenHash: "test_token_hash_9001_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", + TokenSalt: "testsalt", + TokenLastEight: "testlst1", + } + require.NoError(t, db.Insert(ctx, task)) + + job := &actions_model.ActionRunJob{ + ID: 9001, + RunID: 9001, + RepoID: 2, + Name: "test-job", + Attempt: 1, + JobID: "test-job", + TaskID: 9001, + Status: actions_model.StatusFailure, + } + require.NoError(t, db.Insert(ctx, job)) + + require.NoError(t, db.Insert(ctx, + &actions_model.ActionTaskStep{TaskID: 9001, RepoID: 2, Index: 0, Name: "step-success", Status: actions_model.StatusSuccess}, + &actions_model.ActionTaskStep{TaskID: 9001, RepoID: 2, Index: 1, Name: "step-failure", Status: actions_model.StatusFailure}, + )) + + repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 2}) + + apiJob, err := ToActionWorkflowJob(ctx, repo, task, job) + require.NoError(t, err) + require.Len(t, apiJob.Steps, 2) + + assert.Equal(t, "completed", apiJob.Steps[0].Status, "step 0 status") + assert.Equal(t, "success", apiJob.Steps[0].Conclusion, "step 0 conclusion (succeeded before the failure)") + assert.Equal(t, "completed", apiJob.Steps[1].Status, "step 1 status") + assert.Equal(t, "failure", apiJob.Steps[1].Conclusion, "step 1 conclusion") +} diff --git a/services/convert/convert.go b/services/convert/convert.go index 21fd1cadb403c..50ced869408ef 100644 --- a/services/convert/convert.go +++ b/services/convert/convert.go @@ -390,7 +390,7 @@ func ToActionWorkflowJob(ctx context.Context, repo *repo_model.Repository, task runnerName = runner.Name } for i, step := range task.Steps { - stepStatus, stepConclusion := ToActionsStatus(job.Status) + stepStatus, stepConclusion := ToActionsStatus(step.Status) steps = append(steps, &api.ActionWorkflowStep{ Name: step.Name, Number: int64(i), From 638305d3257cd7f17c8891d0fe0974ca38c20350 Mon Sep 17 00:00:00 2001 From: wxiaoguang Date: Fri, 8 May 2026 01:43:28 +0800 Subject: [PATCH 2/4] fix test --- services/convert/action_test.go | 28 +++++++++++----------------- 1 file changed, 11 insertions(+), 17 deletions(-) diff --git a/services/convert/action_test.go b/services/convert/action_test.go index 35c79fab68ac9..5d56d10a481ff 100644 --- a/services/convert/action_test.go +++ b/services/convert/action_test.go @@ -135,41 +135,35 @@ func TestToActionWorkflowJob_StepStatusIsIndependentOfJobStatus(t *testing.T) { RepoID: 2, TriggerUserID: 1, WorkflowID: "test.yaml", - Index: 9001, + Index: 12345, Ref: "refs/heads/main", - CommitSHA: "c2d72f548424103f01ee1dc02889c1e2bff816b0", - Event: "push", - TriggerEvent: "push", Status: actions_model.StatusFailure, } require.NoError(t, db.Insert(ctx, run)) task := &actions_model.ActionTask{ - ID: 9001, - JobID: 9001, - RepoID: 2, - Status: actions_model.StatusFailure, - TokenHash: "test_token_hash_9001_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", - TokenSalt: "testsalt", - TokenLastEight: "testlst1", + ID: 900102, + JobID: 9001, + RepoID: 2, + Status: actions_model.StatusFailure, } require.NoError(t, db.Insert(ctx, task)) job := &actions_model.ActionRunJob{ - ID: 9001, + ID: 90010203, RunID: 9001, + TaskID: 900102, RepoID: 2, - Name: "test-job", + Name: "test-job-name", Attempt: 1, - JobID: "test-job", - TaskID: 9001, + JobID: "test-job-id", Status: actions_model.StatusFailure, } require.NoError(t, db.Insert(ctx, job)) require.NoError(t, db.Insert(ctx, - &actions_model.ActionTaskStep{TaskID: 9001, RepoID: 2, Index: 0, Name: "step-success", Status: actions_model.StatusSuccess}, - &actions_model.ActionTaskStep{TaskID: 9001, RepoID: 2, Index: 1, Name: "step-failure", Status: actions_model.StatusFailure}, + &actions_model.ActionTaskStep{TaskID: task.ID, RepoID: 2, Index: 0, Name: "step-success", Status: actions_model.StatusSuccess}, + &actions_model.ActionTaskStep{TaskID: task.ID, RepoID: 2, Index: 1, Name: "step-failure", Status: actions_model.StatusFailure}, )) repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 2}) From 1a0066cb85e4178a5c4fa798d42fe0e9e5829f68 Mon Sep 17 00:00:00 2001 From: wxiaoguang Date: Fri, 8 May 2026 01:52:34 +0800 Subject: [PATCH 3/4] stricter switch-case --- services/convert/convert.go | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/services/convert/convert.go b/services/convert/convert.go index 50ced869408ef..9150001280ea1 100644 --- a/services/convert/convert.go +++ b/services/convert/convert.go @@ -314,33 +314,31 @@ func ToActionWorkflowRun(ctx context.Context, run *actions_model.ActionRun, atte }, nil } -func ToWorkflowRunAction(status actions_model.Status) string { - var action string +func ToWorkflowRunAction(status actions_model.Status) (action string) { switch status { case actions_model.StatusWaiting, actions_model.StatusBlocked: action = "requested" case actions_model.StatusRunning: action = "in_progress" - } - if status.IsDone() { - action = "completed" + default: + if status.IsDone() { + action = "completed" + } else { + setting.PanicInDevOrTesting("unknown action status: %v", status) + } } return action } -func ToActionsStatus(status actions_model.Status) (string, string) { - var action string - var conclusion string +func ToActionsStatus(status actions_model.Status) (action string, conclusion string) { switch status { - // This is a naming conflict of the webhook between Gitea and GitHub Actions case actions_model.StatusWaiting: - action = "queued" + action = "queued" // "waiting" is a naming conflict of the webhook between Gitea and GitHub Actions case actions_model.StatusBlocked: - action = "waiting" + action = "waiting" // naming conflict (as above) case actions_model.StatusRunning: action = "in_progress" - } - if status.IsDone() { + default: action = "completed" switch status { case actions_model.StatusSuccess: @@ -351,6 +349,8 @@ func ToActionsStatus(status actions_model.Status) (string, string) { conclusion = "failure" case actions_model.StatusSkipped: conclusion = "skipped" + default: + setting.PanicInDevOrTesting("unknown action status: %v", status) } } return action, conclusion From 128529932daa1014dd1fe3704dcdd2d6ba02f78b Mon Sep 17 00:00:00 2001 From: wxiaoguang Date: Fri, 8 May 2026 01:58:47 +0800 Subject: [PATCH 4/4] fix lint --- services/convert/convert.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/services/convert/convert.go b/services/convert/convert.go index 9150001280ea1..dae0587ec4bf5 100644 --- a/services/convert/convert.go +++ b/services/convert/convert.go @@ -330,7 +330,7 @@ func ToWorkflowRunAction(status actions_model.Status) (action string) { return action } -func ToActionsStatus(status actions_model.Status) (action string, conclusion string) { +func ToActionsStatus(status actions_model.Status) (action, conclusion string) { switch status { case actions_model.StatusWaiting: action = "queued" // "waiting" is a naming conflict of the webhook between Gitea and GitHub Actions