mirror of
https://github.com/go-gitea/gitea.git
synced 2026-10-01 20:59:45 +09:00
fix(actions): evaluate job-level if: before concurrency check (#39437)
Gitea doesn't evaluate a job's `if:` before checking the job's concurrency group, which causes a job that should have been skipped to incorrectly cancel other jobs in the same concurrency group. This PR makes Gitea decide `if:` for every job before it becomes waiting, including jobs without `needs` at insertion, on approval and on rerun. A skipped job therefore no longer takes part in job concurrency or holds a max-parallel slot, and a reusable caller whose `if:` is false is no longer expanded on approval or rerun. An invalid `if:` skips the job with an error summary. After this PR, Gitea decides all jobs' `if:` expressions and sends `if: always()` to the runner, so the runner no longer needs to evaluate a job's `if:` again ([gitea/runner `run_context.go`](https://gitea.com/gitea/runner/src/commit/81add274599355ec1838b6ebe45804890d40bab9/act/runner/run_context.go#L1195)). --------- Co-authored-by: silverwind <me@silverwind.io>
This commit is contained in:
@@ -14,10 +14,12 @@ import (
|
||||
actions_model "gitea.dev/models/actions"
|
||||
"gitea.dev/models/db"
|
||||
secret_model "gitea.dev/models/secret"
|
||||
"gitea.dev/modules/actions/jobparser"
|
||||
"gitea.dev/modules/graceful"
|
||||
"gitea.dev/modules/log"
|
||||
"gitea.dev/modules/setting"
|
||||
|
||||
"go.yaml.in/yaml/v4"
|
||||
"google.golang.org/protobuf/types/known/structpb"
|
||||
)
|
||||
|
||||
@@ -156,9 +158,14 @@ func buildRunnerTask(ctx context.Context, t *actions_model.ActionTask) (*runnerv
|
||||
return nil, nil, fmt.Errorf("generateTaskContext: %w", err)
|
||||
}
|
||||
|
||||
payload, err := runnerWorkflowPayload(job)
|
||||
if err != nil {
|
||||
return nil, nil, fmt.Errorf("runnerWorkflowPayload: %w", err)
|
||||
}
|
||||
|
||||
return &runnerv1.Task{
|
||||
Id: t.ID,
|
||||
WorkflowPayload: t.Job.WorkflowPayload,
|
||||
WorkflowPayload: payload,
|
||||
Context: taskContext,
|
||||
Secrets: secrets,
|
||||
Vars: vars,
|
||||
@@ -166,6 +173,19 @@ func buildRunnerTask(ctx context.Context, t *actions_model.ActionTask) (*runnerv
|
||||
}, job, nil
|
||||
}
|
||||
|
||||
// runnerWorkflowPayload sets the job `if:` to `always()`, as Gitea has decided it and a runner must not re-evaluate it.
|
||||
func runnerWorkflowPayload(job *actions_model.ActionRunJob) ([]byte, error) {
|
||||
swf, parsedJob, err := jobparser.ParseRawSingleWorkflow(job.WorkflowPayload)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
parsedJob.If = yaml.Node{Kind: yaml.ScalarNode, Value: "always()"}
|
||||
if err := swf.SetJob(job.JobID, parsedJob); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return swf.Marshal()
|
||||
}
|
||||
|
||||
func generateTaskContext(ctx context.Context, t *actions_model.ActionTask) (*structpb.Struct, error) {
|
||||
giteaRuntimeToken, err := CreateAuthorizationToken(t.ID, t.Job.RunID, t.JobID)
|
||||
if err != nil {
|
||||
|
||||
Reference in New Issue
Block a user