mirror of
https://github.com/go-gitea/gitea.git
synced 2026-08-06 20:56:05 +00:00
Backport #38495 by @Zettat123 Fix #38485 #37478 moved `if` evaluation from runner to server. But `NewInterpeter` always provides a nil `JobContext` for the evaluator, which makes [`cancelled()`](https://gitea.com/gitea/runner/src/commit/ad967330a8788c9b8ab723abbc1a86d53c3bc5e6/act/exprparser/functions.go#L299) panic on `Job.Status` because `Job` is a nil pointer. Co-authored-by: Zettat123 <zettat123@gmail.com>
This commit is contained in:
@@ -57,9 +57,14 @@ func NewInterpeter(
|
|||||||
}
|
}
|
||||||
|
|
||||||
ee := &exprparser.EvaluationEnvironment{
|
ee := &exprparser.EvaluationEnvironment{
|
||||||
Github: gitCtx,
|
Github: gitCtx,
|
||||||
Env: nil, // no need
|
Env: nil, // no need
|
||||||
Job: nil, // no need
|
// Job must be non-nil because cancelled() dereferences Job.Status unconditionally.
|
||||||
|
// See: https://gitea.com/gitea/runner/src/commit/ad967330a8788c9b8ab723abbc1a86d53c3bc5e6/act/exprparser/functions.go#L299
|
||||||
|
// TODO: The empty JobContext.Status is right for now because Gitea never checks `if` condition when the workflow run is cancelled.
|
||||||
|
// This is an implementation gap in Gitea Actions. When a workflow run is cancelled, Gitea should check the job's `if` condition,
|
||||||
|
// and if the condition is met (e.g. `if: ${{ cancelled() }}` ), the job should be executed rather than cancelled.
|
||||||
|
Job: &model.JobContext{},
|
||||||
Steps: nil, // no need
|
Steps: nil, // no need
|
||||||
Runner: nil, // no need
|
Runner: nil, // no need
|
||||||
Secrets: nil, // no need
|
Secrets: nil, // no need
|
||||||
|
|||||||
@@ -464,3 +464,61 @@ func TestParseMappingNode(t *testing.T) {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestEvaluateJobIfExpression(t *testing.T) {
|
||||||
|
kases := []struct {
|
||||||
|
name string
|
||||||
|
ifCond string
|
||||||
|
needResult string
|
||||||
|
expected bool
|
||||||
|
}{
|
||||||
|
{name: "empty need success", ifCond: "${{ 1 == 1 }}", needResult: "success", expected: true},
|
||||||
|
{name: "always", ifCond: "${{ always() }}", needResult: "failure", expected: true},
|
||||||
|
{name: "failure true", ifCond: "${{ failure() }}", needResult: "failure", expected: true},
|
||||||
|
{name: "failure false", ifCond: "${{ failure() }}", needResult: "success", expected: false},
|
||||||
|
{name: "success true", ifCond: "${{ success() }}", needResult: "success", expected: true},
|
||||||
|
// cancelled() is always false on the server: a cancelled run never evaluates a blocked job's `if:`
|
||||||
|
{name: "cancelled", ifCond: "${{ cancelled() }}", needResult: "success", expected: false},
|
||||||
|
{name: "not cancelled or failure", ifCond: "${{ !(cancelled() || failure()) }}", needResult: "success", expected: true},
|
||||||
|
{name: "not cancelled or failure, need failed", ifCond: "${{ !(cancelled() || failure()) }}", needResult: "failure", expected: false},
|
||||||
|
}
|
||||||
|
for _, kase := range kases {
|
||||||
|
t.Run(kase.name, func(t *testing.T) {
|
||||||
|
content := strings.ReplaceAll(`
|
||||||
|
name: test
|
||||||
|
on: push
|
||||||
|
jobs:
|
||||||
|
job1:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- run: echo job1
|
||||||
|
job2:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
needs: [job1]
|
||||||
|
if: IF_COND
|
||||||
|
steps:
|
||||||
|
- run: echo job2
|
||||||
|
`, "IF_COND", kase.ifCond)
|
||||||
|
|
||||||
|
workflows, err := Parse([]byte(content))
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
var job2 *Job
|
||||||
|
for _, wf := range workflows {
|
||||||
|
if id, job := wf.Job(); id == "job2" {
|
||||||
|
job2 = job
|
||||||
|
}
|
||||||
|
}
|
||||||
|
require.NotNil(t, job2)
|
||||||
|
|
||||||
|
// mirrors findJobNeedsAndFillJobResults: the needs' results plus a self entry carrying Needs
|
||||||
|
results := map[string]*JobResult{
|
||||||
|
"job1": {Result: kase.needResult},
|
||||||
|
"job2": {Needs: []string{"job1"}},
|
||||||
|
}
|
||||||
|
got, err := EvaluateJobIfExpression("job2", job2, map[string]any{}, results, nil, nil)
|
||||||
|
require.NoError(t, err)
|
||||||
|
assert.Equal(t, kase.expected, got)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user