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:
@@ -7,8 +7,11 @@ import (
|
||||
"testing"
|
||||
|
||||
actions_model "gitea.dev/models/actions"
|
||||
repo_model "gitea.dev/models/repo"
|
||||
"gitea.dev/models/unittest"
|
||||
user_model "gitea.dev/models/user"
|
||||
"gitea.dev/modules/container"
|
||||
"gitea.dev/modules/test"
|
||||
"gitea.dev/modules/util"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
@@ -453,3 +456,52 @@ func TestCollectMatrixCollapse(t *testing.T) {
|
||||
assert.Empty(t, plan.matrixSiblingSkipTemplateIDs)
|
||||
})
|
||||
}
|
||||
|
||||
func TestRerunDecidesJobIf(t *testing.T) {
|
||||
require.NoError(t, unittest.PrepareTestDatabase())
|
||||
defer test.MockVariableValue(&EmitJobsIfReadyByRun, func(int64) error { return nil })()
|
||||
ctx := t.Context()
|
||||
|
||||
repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 4})
|
||||
variable, err := actions_model.InsertVariable(ctx, 0, repo.ID, "DEPLOY", "yes", "")
|
||||
require.NoError(t, err)
|
||||
|
||||
run := insertMaxParallelRun(t, `on: push
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- run: echo
|
||||
deploy:
|
||||
if: vars.DEPLOY == 'yes'
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- run: echo
|
||||
`, false)
|
||||
jobs := map[string]*actions_model.ActionRunJob{}
|
||||
for _, job := range runJobs(t, run.ID, run.LatestAttemptID) {
|
||||
require.Equal(t, actions_model.StatusWaiting, job.Status)
|
||||
job.Status = actions_model.StatusSuccess
|
||||
_, err = actions_model.UpdateRunJob(ctx, job, nil, "status")
|
||||
require.NoError(t, err)
|
||||
jobs[job.JobID] = job
|
||||
}
|
||||
run = unittest.AssertExistsAndLoadBean(t, &actions_model.ActionRun{ID: run.ID})
|
||||
|
||||
variable.Data = "no"
|
||||
_, err = actions_model.UpdateVariableCols(ctx, variable, "data")
|
||||
require.NoError(t, err)
|
||||
attempt, err := RerunWorkflowRunJobs(ctx, repo, run, &user_model.User{ID: 1}, []*actions_model.ActionRunJob{jobs["deploy"]})
|
||||
require.NoError(t, err)
|
||||
rerunJobs := map[string]*actions_model.ActionRunJob{}
|
||||
for _, job := range runJobs(t, run.ID, attempt.ID) {
|
||||
rerunJobs[job.JobID] = job
|
||||
}
|
||||
assert.Equal(t, actions_model.StatusSuccess, rerunJobs["build"].Status)
|
||||
assert.Equal(t, actions_model.StatusSkipped, rerunJobs["deploy"].Status)
|
||||
|
||||
attempt = unittest.AssertExistsAndLoadBean(t, &actions_model.ActionRunAttempt{ID: attempt.ID})
|
||||
assert.Equal(t, actions_model.StatusSuccess, attempt.Status)
|
||||
assert.NotZero(t, attempt.Stopped)
|
||||
assert.Equal(t, actions_model.StatusSuccess, unittest.AssertExistsAndLoadBean(t, &actions_model.ActionRun{ID: run.ID}).Status)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user