From f0f9f0c8ab4bbbbcbe5ce8843e6624caaa197417 Mon Sep 17 00:00:00 2001 From: ChristopherHX Date: Sun, 22 Feb 2026 14:56:09 +0000 Subject: [PATCH] fix: composite action log result reported as step result (#801) Act logs an array of stepID to signal that this is an partial step result within an composite actions, this is the case for years and act_runner never handled it correctly. Ref: Reviewed-on: https://gitea.com/gitea/act_runner/pulls/801 Reviewed-by: silverwind --- internal/pkg/report/reporter.go | 14 +++++++++++++- internal/pkg/report/reporter_test.go | 17 ++++++++++++++++- 2 files changed, 29 insertions(+), 2 deletions(-) diff --git a/internal/pkg/report/reporter.go b/internal/pkg/report/reporter.go index eb6026ed..5efcfd62 100644 --- a/internal/pkg/report/reporter.go +++ b/internal/pkg/report/reporter.go @@ -96,6 +96,18 @@ func appendIfNotNil[T any](s []*T, v *T) []*T { return s } +// isJobStepEntry is used to not report composite step results incorrectly as step result +// returns true if the logentry is on job level +// returns false for composite action step messages +func isJobStepEntry(entry *log.Entry) bool { + if v, ok := entry.Data["stepID"]; ok { + if v, ok := v.([]string); ok && len(v) > 1 { + return false + } + } + return true +} + func (r *Reporter) Fire(entry *log.Entry) error { r.stateMu.Lock() defer r.stateMu.Unlock() @@ -166,7 +178,7 @@ func (r *Reporter) Fire(entry *log.Entry) error { } else if !r.duringSteps() { r.logRows = appendIfNotNil(r.logRows, r.parseLogRow(entry)) } - if v, ok := entry.Data["stepResult"]; ok { + if v, ok := entry.Data["stepResult"]; ok && isJobStepEntry(entry) { if stepResult, ok := r.parseResult(v); ok { if step.LogLength == 0 { step.LogIndex = int64(r.logOffset + len(r.logRows)) diff --git a/internal/pkg/report/reporter_test.go b/internal/pkg/report/reporter_test.go index 2381b521..b7221341 100644 --- a/internal/pkg/report/reporter_test.go +++ b/internal/pkg/report/reporter_test.go @@ -196,8 +196,23 @@ func TestReporter_Fire(t *testing.T) { assert.NoError(t, reporter.Fire(&log.Entry{Message: "::debug::debug log line", Data: dataStep0})) assert.NoError(t, reporter.Fire(&log.Entry{Message: "::debug::debug log line", Data: dataStep0})) assert.NoError(t, reporter.Fire(&log.Entry{Message: "regular log line", Data: dataStep0})) + assert.NoError(t, reporter.Fire(&log.Entry{Message: "composite step result", Data: map[string]interface{}{ + "stage": "Main", + "stepID": []string{"0", "0"}, + "stepNumber": 0, + "raw_output": true, + "stepResult": "failure", + }})) + assert.Equal(t, runnerv1.Result_RESULT_UNSPECIFIED, reporter.state.Steps[0].Result) + assert.NoError(t, reporter.Fire(&log.Entry{Message: "step result", Data: map[string]interface{}{ + "stage": "Main", + "stepNumber": 0, + "raw_output": true, + "stepResult": "success", + }})) + assert.Equal(t, runnerv1.Result_RESULT_SUCCESS, reporter.state.Steps[0].Result) - assert.Equal(t, int64(3), reporter.state.Steps[0].LogLength) + assert.Equal(t, int64(5), reporter.state.Steps[0].LogLength) }) }