mirror of
https://github.com/go-gitea/gitea.git
synced 2026-09-26 06:33:42 +09:00
feat(actions): update actionslib, support self:, misc fixes (#39358)
Updates actionslib to https://gitea.com/gitea/actionslib/releases/tag/v1.2.1, moves workflow parsing into it and aligns behaviour with GitHub. 1. `uses:` supports `self:` (Gitea-only feature) and `$/` paths. 1. `strategy`, `matrix`, `max-parallel` and `fail-fast` accept expressions, including over `needs`. A job whose `name`, `runs-on` or `continue-on-error` reads `needs` is resolved once they finish. 1. A job `if:` may only read `github`, `needs`, `vars` and `inputs` and is decided before the matrix, as on github.com. 1. Matrix `fail-fast` cancels the other combinations, and `always()` jobs keep running when a run is cancelled. 1. Invalid workflow files, including a malformed `on:` and unknown or cyclic `needs`, show up on push as failed runs with the error. 1. A job whose `if:` or `concurrency:` fails to evaluate is skipped or failed with the error, instead of staying blocked. 1. Reusable workflows: a missing and an unreadable repository fail alike, public callers cannot use private workflows, nested jobs cannot exceed the caller's token permissions. 1. Runner labels match case-insensitively, and `runs-on` accepts an array from an expression. Runner PR: https://gitea.com/gitea/runner/pulls/1247 Docs PR: https://gitea.com/gitea/docs/pulls/553 Fixes: https://github.com/go-gitea/gitea/issues/38990 Fixes: https://github.com/go-gitea/gitea/issues/39382 Fixes: https://github.com/go-gitea/gitea/issues/32364 Fixes: https://github.com/go-gitea/gitea/issues/36077 Fixes: https://github.com/go-gitea/gitea/issues/23277 Fixes: https://github.com/go-gitea/gitea/issues/29020 Co-authored-by: Claude (Opus 5) <noreply@anthropic.com> Co-authored-by: Zettat123 <zettat123@gmail.com>
This commit is contained in:
@@ -17,9 +17,18 @@ import (
|
||||
|
||||
func TestParseRawOn(t *testing.T) {
|
||||
kases := []struct {
|
||||
input string
|
||||
result []*Event
|
||||
input string
|
||||
result []*Event
|
||||
wantErr bool
|
||||
}{
|
||||
{input: "on:\n push:\n branches:\n a: b", wantErr: true},
|
||||
{input: "on: [push, {pull_request: null}]", wantErr: true},
|
||||
{input: "on:", wantErr: true},
|
||||
{input: "on: 42", wantErr: true},
|
||||
{input: "jobs: {}", wantErr: true},
|
||||
{input: "on:\n schedule: []", wantErr: true},
|
||||
{input: "on:\n schedule:\n - {}", wantErr: true},
|
||||
{input: "on:\n schedule:\n - cron: nope", wantErr: true},
|
||||
{
|
||||
input: "on: issue_comment",
|
||||
result: []*Event{
|
||||
@@ -190,13 +199,14 @@ func TestParseRawOn(t *testing.T) {
|
||||
},
|
||||
},
|
||||
{
|
||||
input: "on:\n schedule:\n - cron: '20 6 * * *'",
|
||||
input: "on:\n schedule:\n - cron: '20 6 * * *'\n timezone: UTC",
|
||||
result: []*Event{
|
||||
{
|
||||
Name: "schedule",
|
||||
schedules: []map[string]string{
|
||||
{
|
||||
"cron": "20 6 * * *",
|
||||
"cron": "20 6 * * *",
|
||||
"timezone": "UTC",
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -228,28 +238,6 @@ func TestParseRawOn(t *testing.T) {
|
||||
result: []*Event{
|
||||
{
|
||||
Name: "workflow_dispatch",
|
||||
inputs: []WorkflowDispatchInput{
|
||||
{
|
||||
Name: "logLevel",
|
||||
Description: "Log level",
|
||||
Required: true,
|
||||
Default: "warning",
|
||||
Type: "choice",
|
||||
Options: []string{"info", "warning", "debug"},
|
||||
},
|
||||
{
|
||||
Name: "tags",
|
||||
Description: "Test scenario tags",
|
||||
Required: false,
|
||||
Type: "boolean",
|
||||
},
|
||||
{
|
||||
Name: "environment",
|
||||
Description: "Environment to run tests against",
|
||||
Type: "environment",
|
||||
Required: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "push",
|
||||
@@ -310,6 +298,10 @@ func TestParseRawOn(t *testing.T) {
|
||||
assert.NoError(t, err)
|
||||
|
||||
events, err := ParseRawOn(&origin.RawOn)
|
||||
if kase.wantErr {
|
||||
assert.Error(t, err)
|
||||
return
|
||||
}
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, kase.result, events, events)
|
||||
})
|
||||
@@ -467,51 +459,6 @@ func TestParseMappingNode(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestEvaluateJobIfExpressionMatrix(t *testing.T) {
|
||||
ifExprs := []string{
|
||||
`${{ contains(fromJSON('["linux","windows"]'), matrix.target) }}`,
|
||||
`${{ contains('["linux","windows"]', matrix.target) }}`,
|
||||
}
|
||||
|
||||
want := map[string]bool{
|
||||
"build (linux)": true,
|
||||
"build (windows)": true,
|
||||
"build (macos)": false,
|
||||
}
|
||||
|
||||
for _, ifExpr := range ifExprs {
|
||||
t.Run(ifExpr, func(t *testing.T) {
|
||||
content := fmt.Sprintf(`
|
||||
name: test
|
||||
on: push
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
if: %s
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
target: [linux, windows, macos]
|
||||
steps:
|
||||
- run: echo ${{ matrix.target }}
|
||||
`, ifExpr)
|
||||
|
||||
swfs, err := Parse([]byte(content))
|
||||
require.NoError(t, err)
|
||||
require.Len(t, swfs, 3)
|
||||
|
||||
got := make(map[string]bool, len(swfs))
|
||||
for _, swf := range swfs {
|
||||
id, job := swf.Job()
|
||||
shouldRun, err := EvaluateJobIfExpression(id, job, map[string]any{}, map[string]*JobResult{id: {}}, nil, nil, false)
|
||||
require.NoError(t, err)
|
||||
got[job.Name] = shouldRun
|
||||
}
|
||||
assert.Equal(t, want, got)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestEvaluateJobIfExpression(t *testing.T) {
|
||||
kases := []struct {
|
||||
name string
|
||||
@@ -567,9 +514,23 @@ jobs:
|
||||
"job1": {Result: kase.needResult},
|
||||
"job2": {Needs: []string{"job1"}},
|
||||
}
|
||||
got, err := EvaluateJobIfExpression("job2", job2, map[string]any{}, results, nil, nil, false)
|
||||
got, err := EvaluateJobIfExpression("job2", job2, map[string]any{}, results, nil, nil)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, kase.expected, got)
|
||||
})
|
||||
}
|
||||
|
||||
t.Run("stored unavailable context", func(t *testing.T) {
|
||||
for condition, wantErr := range map[string]string{
|
||||
"matrix.os == 'a'": "Unrecognized named-value: 'matrix'",
|
||||
"${{ strategy.fail-fast }}": "Unrecognized named-value: 'strategy'",
|
||||
"secrets.TOKEN != ''": "Unrecognized named-value: 'secrets'",
|
||||
"${{ matrix.os == }}": "Unexpected end of expression",
|
||||
} {
|
||||
_, job, err := ParseRawSingleWorkflow(fmt.Appendf(nil, "jobs: {job2: {if: %q, strategy: {matrix: {os: [a]}}}}", condition))
|
||||
require.NoError(t, err)
|
||||
_, err = EvaluateJobIfExpression("job2", job, map[string]any{}, map[string]*JobResult{"job2": {}}, nil, nil)
|
||||
assert.ErrorContains(t, err, wantErr, condition)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user