0
0
mirror of https://github.com/go-gitea/gitea.git synced 2026-02-22 11:05:42 +01:00

Fix workflow_run events not creating commit statuses

Workflows triggered by `workflow_run` events did not produce commit
statuses because `getCommitStatusEventNameAndCommitID` had no case for
`HookEventWorkflowRun`. The function returned empty strings, so
`CreateCommitStatusForRunJobs` silently skipped status creation.

Add a `workflow_run` case that walks up the parent run chain (up to 5
levels) to find the original triggering event's commit SHA and attaches
the status there. This makes chained `workflow_run` workflows visible
in the commit status popover alongside the root workflow.
This commit is contained in:
Davide 2026-02-13 16:58:12 +01:00
parent afcd11c77f
commit 177f114aa2
2 changed files with 173 additions and 2 deletions

View File

@ -34,7 +34,7 @@ func CreateCommitStatusForRunJobs(ctx context.Context, run *actions_model.Action
return
}
event, commitID, err := getCommitStatusEventNameAndCommitID(run)
event, commitID, err := getCommitStatusEventNameAndCommitID(ctx, run)
if err != nil {
log.Error("GetCommitStatusEventNameAndSHA: %v", err)
}
@ -81,7 +81,7 @@ func GetRunsFromCommitStatuses(ctx context.Context, statuses []*git_model.Commit
return runs, nil
}
func getCommitStatusEventNameAndCommitID(run *actions_model.ActionRun) (event, commitID string, _ error) {
func getCommitStatusEventNameAndCommitID(ctx context.Context, run *actions_model.ActionRun) (event, commitID string, _ error) {
switch run.Event {
case webhook_module.HookEventPush:
event = "push"
@ -118,6 +118,28 @@ func getCommitStatusEventNameAndCommitID(run *actions_model.ActionRun) (event, c
case webhook_module.HookEventRelease:
event = string(run.Event)
commitID = run.CommitSHA
case webhook_module.HookEventWorkflowRun:
event = "workflow_run"
currentRun := run
for range 5 {
payload, err := currentRun.GetWorkflowRunEventPayload()
if err != nil {
return "", "", fmt.Errorf("GetWorkflowRunEventPayload: %w", err)
}
if payload.WorkflowRun == nil {
return "", "", nil
}
parentRun, err := actions_model.GetRunByRepoAndID(ctx, currentRun.RepoID, payload.WorkflowRun.ID)
if err != nil {
return "", "", fmt.Errorf("GetRunByRepoAndID: %w", err)
}
if parentRun.Event != webhook_module.HookEventWorkflowRun {
_, commitID, err = getCommitStatusEventNameAndCommitID(ctx, parentRun)
return event, commitID, err
}
currentRun = parentRun
}
return "", "", nil
default: // do nothing, return empty
}
return event, commitID, nil

View File

@ -0,0 +1,149 @@
// Copyright 2026 The Gitea Authors. All rights reserved.
// SPDX-License-Identifier: MIT
package actions
import (
"testing"
actions_model "code.gitea.io/gitea/models/actions"
"code.gitea.io/gitea/models/db"
"code.gitea.io/gitea/models/unittest"
"code.gitea.io/gitea/modules/json"
api "code.gitea.io/gitea/modules/structs"
webhook_module "code.gitea.io/gitea/modules/webhook"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
func TestGetCommitStatusEventNameAndCommitID(t *testing.T) {
require.NoError(t, unittest.PrepareTestDatabase())
ctx := t.Context()
repoID := int64(1)
pushCommitSHA := "abc123def456abc123def456abc123def456abc1"
pushPayload, err := json.Marshal(&api.PushPayload{
HeadCommit: &api.PayloadCommit{ID: pushCommitSHA},
})
require.NoError(t, err)
nextIndex := func() int64 {
idx, err := db.GetNextResourceIndex(ctx, "action_run_index", repoID)
require.NoError(t, err)
return idx
}
pushRun := &actions_model.ActionRun{
Index: nextIndex(),
RepoID: repoID,
Event: webhook_module.HookEventPush,
EventPayload: string(pushPayload),
TriggerUserID: 1,
CommitSHA: pushCommitSHA,
Ref: "refs/heads/main",
WorkflowID: "push.yml",
Title: "push run",
}
require.NoError(t, db.Insert(ctx, pushRun))
t.Run("WorkflowRunWithPushParent", func(t *testing.T) {
wrPayload, err := json.Marshal(&api.WorkflowRunPayload{
WorkflowRun: &api.ActionWorkflowRun{
ID: pushRun.ID,
},
})
require.NoError(t, err)
wrRun := &actions_model.ActionRun{
Index: nextIndex(),
RepoID: repoID,
Event: webhook_module.HookEventWorkflowRun,
EventPayload: string(wrPayload),
TriggerUserID: 1,
CommitSHA: "default-branch-head-000000000000000000000",
Ref: "refs/heads/main",
WorkflowID: "wr.yml",
Title: "workflow_run run",
}
require.NoError(t, db.Insert(ctx, wrRun))
event, commitID, err := getCommitStatusEventNameAndCommitID(ctx, wrRun)
require.NoError(t, err)
assert.Equal(t, "workflow_run", event)
assert.Equal(t, pushCommitSHA, commitID)
})
t.Run("WorkflowRunChainedTwoLevels", func(t *testing.T) {
midPayload, err := json.Marshal(&api.WorkflowRunPayload{
WorkflowRun: &api.ActionWorkflowRun{
ID: pushRun.ID,
},
})
require.NoError(t, err)
midRun := &actions_model.ActionRun{
Index: nextIndex(),
RepoID: repoID,
Event: webhook_module.HookEventWorkflowRun,
EventPayload: string(midPayload),
TriggerUserID: 1,
CommitSHA: "default-branch-head-000000000000000000000",
Ref: "refs/heads/main",
WorkflowID: "mid.yml",
Title: "mid workflow_run",
}
require.NoError(t, db.Insert(ctx, midRun))
leafPayload, err := json.Marshal(&api.WorkflowRunPayload{
WorkflowRun: &api.ActionWorkflowRun{
ID: midRun.ID,
},
})
require.NoError(t, err)
leafRun := &actions_model.ActionRun{
Index: nextIndex(),
RepoID: repoID,
Event: webhook_module.HookEventWorkflowRun,
EventPayload: string(leafPayload),
TriggerUserID: 1,
CommitSHA: "default-branch-head-200000000000000000000",
Ref: "refs/heads/main",
WorkflowID: "leaf.yml",
Title: "leaf workflow_run",
}
require.NoError(t, db.Insert(ctx, leafRun))
event, commitID, err := getCommitStatusEventNameAndCommitID(ctx, leafRun)
require.NoError(t, err)
assert.Equal(t, "workflow_run", event)
assert.Equal(t, pushCommitSHA, commitID)
})
t.Run("WorkflowRunNilWorkflowRun", func(t *testing.T) {
payload, err := json.Marshal(&api.WorkflowRunPayload{
WorkflowRun: nil,
})
require.NoError(t, err)
run := &actions_model.ActionRun{
Index: nextIndex(),
RepoID: repoID,
Event: webhook_module.HookEventWorkflowRun,
EventPayload: string(payload),
TriggerUserID: 1,
CommitSHA: "some-sha-0000000000000000000000000000000",
Ref: "refs/heads/main",
WorkflowID: "nil.yml",
Title: "nil workflow_run",
}
require.NoError(t, db.Insert(ctx, run))
event, commitID, err := getCommitStatusEventNameAndCommitID(ctx, run)
require.NoError(t, err)
assert.Empty(t, event)
assert.Empty(t, commitID)
})
}