aboutsummaryrefslogtreecommitdiffstats
path: root/routers/api/actions/runner
diff options
context:
space:
mode:
authorZettat123 <zettat123@gmail.com>2024-12-14 10:22:30 +0800
committerGitHub <noreply@github.com>2024-12-14 10:22:30 +0800
commit7269130d2878d51dcdf11f7081a591f85bd493e8 (patch)
treede667486f5951a3b34a0454686e8b2d1a7b7a183 /routers/api/actions/runner
parenta66c16dc1bca44d480317c6319144d33949bc724 (diff)
downloadgitea-7269130d2878d51dcdf11f7081a591f85bd493e8.tar.gz
gitea-7269130d2878d51dcdf11f7081a591f85bd493e8.zip
Fix missing outputs for jobs with matrix (#32823)
Fix #32795 If a job uses a matrix, multiple `ActionRunJobs` may have the same `JobID`. We need to merge the outputs of these jobs to make them available to the jobs that need them.
Diffstat (limited to 'routers/api/actions/runner')
-rw-r--r--routers/api/actions/runner/main_test.go14
-rw-r--r--routers/api/actions/runner/utils.go60
-rw-r--r--routers/api/actions/runner/utils_test.go28
3 files changed, 86 insertions, 16 deletions
diff --git a/routers/api/actions/runner/main_test.go b/routers/api/actions/runner/main_test.go
new file mode 100644
index 0000000000..1e80a4f5ca
--- /dev/null
+++ b/routers/api/actions/runner/main_test.go
@@ -0,0 +1,14 @@
+// Copyright 2024 The Gitea Authors. All rights reserved.
+// SPDX-License-Identifier: MIT
+
+package runner
+
+import (
+ "testing"
+
+ "code.gitea.io/gitea/models/unittest"
+)
+
+func TestMain(m *testing.M) {
+ unittest.MainTest(m)
+}
diff --git a/routers/api/actions/runner/utils.go b/routers/api/actions/runner/utils.go
index ff6ec5bd54..539be8d889 100644
--- a/routers/api/actions/runner/utils.go
+++ b/routers/api/actions/runner/utils.go
@@ -162,28 +162,56 @@ func findTaskNeeds(ctx context.Context, task *actions_model.ActionTask) (map[str
return nil, fmt.Errorf("FindRunJobs: %w", err)
}
- ret := make(map[string]*runnerv1.TaskNeed, len(needs))
+ jobIDJobs := make(map[string][]*actions_model.ActionRunJob)
for _, job := range jobs {
- if !needs.Contains(job.JobID) {
- continue
- }
- if job.TaskID == 0 || !job.Status.IsDone() {
- // it shouldn't happen, or the job has been rerun
+ jobIDJobs[job.JobID] = append(jobIDJobs[job.JobID], job)
+ }
+
+ ret := make(map[string]*runnerv1.TaskNeed, len(needs))
+ for jobID, jobsWithSameID := range jobIDJobs {
+ if !needs.Contains(jobID) {
continue
}
- outputs := make(map[string]string)
- got, err := actions_model.FindTaskOutputByTaskID(ctx, job.TaskID)
- if err != nil {
- return nil, fmt.Errorf("FindTaskOutputByTaskID: %w", err)
+ var jobOutputs map[string]string
+ for _, job := range jobsWithSameID {
+ if job.TaskID == 0 || !job.Status.IsDone() {
+ // it shouldn't happen, or the job has been rerun
+ continue
+ }
+ got, err := actions_model.FindTaskOutputByTaskID(ctx, job.TaskID)
+ if err != nil {
+ return nil, fmt.Errorf("FindTaskOutputByTaskID: %w", err)
+ }
+ outputs := make(map[string]string, len(got))
+ for _, v := range got {
+ outputs[v.OutputKey] = v.OutputValue
+ }
+ if len(jobOutputs) == 0 {
+ jobOutputs = outputs
+ } else {
+ jobOutputs = mergeTwoOutputs(outputs, jobOutputs)
+ }
}
- for _, v := range got {
- outputs[v.OutputKey] = v.OutputValue
- }
- ret[job.JobID] = &runnerv1.TaskNeed{
- Outputs: outputs,
- Result: runnerv1.Result(job.Status),
+ ret[jobID] = &runnerv1.TaskNeed{
+ Outputs: jobOutputs,
+ Result: runnerv1.Result(actions_model.AggregateJobStatus(jobsWithSameID)),
}
}
return ret, nil
}
+
+// mergeTwoOutputs merges two outputs from two different ActionRunJobs
+// Values with the same output name may be overridden. The user should ensure the output names are unique.
+// See https://docs.github.com/en/actions/writing-workflows/workflow-syntax-for-github-actions#using-job-outputs-in-a-matrix-job
+func mergeTwoOutputs(o1, o2 map[string]string) map[string]string {
+ ret := make(map[string]string, len(o1))
+ for k1, v1 := range o1 {
+ if len(v1) > 0 {
+ ret[k1] = v1
+ } else {
+ ret[k1] = o2[k1]
+ }
+ }
+ return ret
+}
diff --git a/routers/api/actions/runner/utils_test.go b/routers/api/actions/runner/utils_test.go
new file mode 100644
index 0000000000..d7a6f84550
--- /dev/null
+++ b/routers/api/actions/runner/utils_test.go
@@ -0,0 +1,28 @@
+// Copyright 2024 The Gitea Authors. All rights reserved.
+// SPDX-License-Identifier: MIT
+
+package runner
+
+import (
+ "context"
+ "testing"
+
+ actions_model "code.gitea.io/gitea/models/actions"
+ "code.gitea.io/gitea/models/unittest"
+
+ "github.com/stretchr/testify/assert"
+)
+
+func Test_findTaskNeeds(t *testing.T) {
+ assert.NoError(t, unittest.PrepareTestDatabase())
+
+ task := unittest.AssertExistsAndLoadBean(t, &actions_model.ActionTask{ID: 51})
+
+ ret, err := findTaskNeeds(context.Background(), task)
+ assert.NoError(t, err)
+ assert.Len(t, ret, 1)
+ assert.Contains(t, ret, "job1")
+ assert.Len(t, ret["job1"].Outputs, 2)
+ assert.Equal(t, "abc", ret["job1"].Outputs["output_a"])
+ assert.Equal(t, "bbb", ret["job1"].Outputs["output_b"])
+}