From 6e6ebbc981b633fc94045ce7be739a1ab9d60bc9 Mon Sep 17 00:00:00 2001 From: Earl Warren Date: Mon, 14 Jul 2025 20:46:51 +0000 Subject: [PATCH] fix: explain why a workflow cannot be used to run a job (#666) - report back to the Forgejo instance - log Forgejo runner side in debug mode - display the workflow with line number to facilitate matching with errors - split the error into multiple lines if possible ![image](/attachments/db376308-2ebc-4b63-831f-1ccd782107fb) Refs forgejo/act#170 Reviewed-on: https://code.forgejo.org/forgejo/runner/pulls/666 Reviewed-by: Michael Kriese Co-authored-by: Earl Warren Co-committed-by: Earl Warren --- internal/app/run/runner.go | 20 +++++++++++++++++++- internal/app/run/runner_test.go | 17 +++++++++++++++++ 2 files changed, 36 insertions(+), 1 deletion(-) diff --git a/internal/app/run/runner.go b/internal/app/run/runner.go index 3d081e88..05a02163 100644 --- a/internal/app/run/runner.go +++ b/internal/app/run/runner.go @@ -183,6 +183,22 @@ func (r *Runner) Run(ctx context.Context, task *runnerv1.Task) error { return nil } +func logAndReport(reporter *report.Reporter, message string, args ...any) { + log.Debugf(message, args...) + reporter.Logf(message, args...) +} + +func explainFailedGenerateWorkflow(task *runnerv1.Task, log func(message string, args ...any), err error) error { + for n, line := range strings.Split(string(task.WorkflowPayload), "\n") { + log("%d: %s", n+1, line) + } + log("Errors were found and although they tend to be cryptic the line number they refer to gives a hint as to where the problem might be.") + for _, line := range strings.Split(err.Error(), "\n") { + log("%s", line) + } + return fmt.Errorf("the workflow file is not usable") +} + func (r *Runner) run(ctx context.Context, task *runnerv1.Task, reporter *report.Reporter) (err error) { defer func() { if r := recover(); r != nil { @@ -194,7 +210,9 @@ func (r *Runner) run(ctx context.Context, task *runnerv1.Task, reporter *report. workflow, jobID, err := generateWorkflow(task) if err != nil { - return err + return explainFailedGenerateWorkflow(task, func(message string, args ...any) { + logAndReport(reporter, message, args...) + }, err) } plan, err := model.CombineWorkflowPlanner(workflow).PlanJob(jobID) diff --git a/internal/app/run/runner_test.go b/internal/app/run/runner_test.go index 09428944..78348fc2 100644 --- a/internal/app/run/runner_test.go +++ b/internal/app/run/runner_test.go @@ -2,13 +2,30 @@ package run import ( "context" + "errors" + "fmt" "testing" + runnerv1 "code.forgejo.org/forgejo/actions-proto/runner/v1" "runner.forgejo.org/internal/pkg/labels" "github.com/stretchr/testify/assert" ) +func TestExplainFailedGenerateWorkflow(t *testing.T) { + logged := "" + log := func(message string, args ...any) { + logged += fmt.Sprintf(message, args...) + "\n" + } + task := &runnerv1.Task{ + WorkflowPayload: []byte("on: [push]\njobs:\n"), + } + generateWorkflowError := errors.New("message 1\nmessage 2") + err := explainFailedGenerateWorkflow(task, log, generateWorkflowError) + assert.Error(t, err) + assert.Equal(t, "1: on: [push]\n2: jobs:\n3: \nErrors were found and although they tend to be cryptic the line number they refer to gives a hint as to where the problem might be.\nmessage 1\nmessage 2\n", logged) +} + func TestLabelUpdate(t *testing.T) { ctx := context.Background() ls := labels.Labels{}