chore: initialize Gitea v1.27.2 fork
giteabot backport / giteabot (push) Canceled after 0s
giteabot / giteabot (push) Canceled after 0s
release-nightly / nightly-binary (push) Canceled after 0s
release-nightly / nightly-container (push) Canceled after 0s
cache-seeder / gobuild (push) Canceled after 0s
cache-seeder / lint (bindata, lint-backend) (push) Canceled after 0s
release-nightly-snapcraft / build-and-publish (push) Canceled after 0s
giteabot backport / giteabot (push) Canceled after 0s
giteabot / giteabot (push) Canceled after 0s
release-nightly / nightly-binary (push) Canceled after 0s
release-nightly / nightly-container (push) Canceled after 0s
cache-seeder / gobuild (push) Canceled after 0s
cache-seeder / lint (bindata, lint-backend) (push) Canceled after 0s
release-nightly-snapcraft / build-and-publish (push) Canceled after 0s
Includes direct password setup links in registration emails. Assisted-by: Codex:GPT-5
This commit is contained in:
@@ -0,0 +1,149 @@
|
||||
// Copyright 2026 The Gitea Authors. All rights reserved.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
package jobparser
|
||||
|
||||
import (
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"gitea.com/gitea/runner/act/model"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
"go.yaml.in/yaml/v4"
|
||||
)
|
||||
|
||||
func TestParse(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
options []ParseOption
|
||||
wantErr bool
|
||||
}{
|
||||
{
|
||||
name: "multiple_jobs",
|
||||
options: nil,
|
||||
wantErr: false,
|
||||
},
|
||||
{
|
||||
name: "multiple_matrix",
|
||||
options: nil,
|
||||
wantErr: false,
|
||||
},
|
||||
{
|
||||
name: "has_needs",
|
||||
options: nil,
|
||||
wantErr: false,
|
||||
},
|
||||
{
|
||||
name: "has_with",
|
||||
options: nil,
|
||||
wantErr: false,
|
||||
},
|
||||
{
|
||||
name: "has_secrets",
|
||||
options: nil,
|
||||
wantErr: false,
|
||||
},
|
||||
{
|
||||
name: "empty_step",
|
||||
options: nil,
|
||||
wantErr: false,
|
||||
},
|
||||
{
|
||||
name: "job_name_with_matrix",
|
||||
options: nil,
|
||||
wantErr: false,
|
||||
},
|
||||
{
|
||||
name: "prefixed_newline",
|
||||
options: nil,
|
||||
wantErr: false,
|
||||
},
|
||||
{
|
||||
name: "continue_on_error_expr",
|
||||
options: nil,
|
||||
wantErr: false,
|
||||
},
|
||||
}
|
||||
invalidFileTests := []struct {
|
||||
name string
|
||||
}{
|
||||
{name: "null_job_implicit"},
|
||||
{name: "null_job_explicit"},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
content := ReadTestdata(t, tt.name+".in.yaml")
|
||||
want := ReadTestdata(t, tt.name+".out.yaml")
|
||||
got, err := Parse(content, tt.options...)
|
||||
if tt.wantErr {
|
||||
require.Error(t, err)
|
||||
}
|
||||
require.NoError(t, err)
|
||||
|
||||
builder := &strings.Builder{}
|
||||
for _, v := range got {
|
||||
if builder.Len() > 0 {
|
||||
builder.WriteString("---\n")
|
||||
}
|
||||
encoder := yaml.NewEncoder(builder)
|
||||
encoder.SetIndent(2)
|
||||
require.NoError(t, encoder.Encode(v))
|
||||
id, job := v.Job()
|
||||
assert.NotEmpty(t, id)
|
||||
assert.NotNil(t, job)
|
||||
}
|
||||
assert.Equal(t, string(want), builder.String())
|
||||
})
|
||||
}
|
||||
|
||||
for _, tt := range invalidFileTests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
content := ReadTestdata(t, tt.name+".in.yaml")
|
||||
require.NotPanics(t, func() {
|
||||
_, err := Parse(content)
|
||||
require.Error(t, err)
|
||||
})
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestParseInterpolatesRunName(t *testing.T) {
|
||||
workflow := func(runName string) []byte {
|
||||
return []byte("name: t\nrun-name: \"" + runName + "\"\non: push\njobs:\n build:\n runs-on: ubuntu-latest\n steps: [{run: echo}]\n")
|
||||
}
|
||||
|
||||
for _, tt := range []struct{ name, runName, want string }{
|
||||
{"bool", "${{ true }}", "true"},
|
||||
{"int", "${{ 1 }}", "1"},
|
||||
{"float", "${{ 1.0 }}", "1"},
|
||||
{"null", "${{ null }}", ""},
|
||||
{"object", `${{ fromJSON('{\"a\":1}') }}`, "Object"},
|
||||
{"array", "${{ fromJSON('[1,2]') }}", "Array"},
|
||||
{"context", "${{ github }}", "Object"},
|
||||
{"surrounding literals", "run ${{ 1 }} now", "run 1 now"},
|
||||
{"two expressions", "${{ 1 }}-${{ true }}", "1-true"},
|
||||
{"closing brace inside a string", "${{ 'a}}b' }}", "a}}b"},
|
||||
{"incomplete expression stays literal", "${{ 1", "${{ 1"},
|
||||
} {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
result, err := Parse(workflow(tt.runName), WithGitContext(&model.GithubContext{EventName: "push"}))
|
||||
require.NoError(t, err)
|
||||
require.Len(t, result, 1)
|
||||
assert.Equal(t, tt.want, result[0].RunName)
|
||||
})
|
||||
}
|
||||
|
||||
// a malformed part must not restructure the surrounding expression
|
||||
for _, runName := range []string{"${{ 1) && (2 }}", "run ${{ 1) && (2 }} now", "${{ 'a' }} ${{ b", "${{ 'a }}"} {
|
||||
_, err := Parse(workflow(runName), WithGitContext(&model.GithubContext{EventName: "push"}))
|
||||
assert.ErrorContains(t, err, "interpolate run-name")
|
||||
}
|
||||
|
||||
// callers such as commit status parse without a git context, leaving `github` a nil pointer
|
||||
result, err := Parse(workflow("${{ github }}"))
|
||||
require.NoError(t, err)
|
||||
require.Len(t, result, 1)
|
||||
assert.Empty(t, result[0].RunName)
|
||||
}
|
||||
Reference in New Issue
Block a user