mirror of
https://github.com/go-gitea/gitea.git
synced 2026-09-16 09:53:24 +09:00
chore(deps): update actionslib to v1.0.0 (#39295)
Co-authored-by: bircni <bircni@icloud.com>
This commit is contained in:
@@ -24,8 +24,10 @@ func NewInterpeter(
|
||||
) exprparser.Interpreter {
|
||||
strategy := make(map[string]any)
|
||||
if job.Strategy != nil {
|
||||
strategy["fail-fast"] = job.Strategy.FailFast
|
||||
strategy["max-parallel"] = job.Strategy.MaxParallel
|
||||
strategy["fail-fast"] = job.Strategy.GetFailFast()
|
||||
if limit, declared, err := job.Strategy.ParseMaxParallel(); declared && err == nil {
|
||||
strategy["max-parallel"] = limit
|
||||
}
|
||||
}
|
||||
|
||||
run := &model.Run{
|
||||
|
||||
@@ -14,7 +14,6 @@ import (
|
||||
"gitea.dev/actionslib/pkg/exprparser"
|
||||
"gitea.dev/actionslib/pkg/model"
|
||||
|
||||
"github.com/rhysd/actionlint"
|
||||
"go.yaml.in/yaml/v4"
|
||||
)
|
||||
|
||||
@@ -60,13 +59,13 @@ func ParseRawSingleWorkflow(payload []byte) (*SingleWorkflow, *Job, error) {
|
||||
// those too would replace their combinations with one placeholder and change the commit status
|
||||
// contexts the run publishes, which a repository's required checks are configured against.
|
||||
func expressionReadsNeeds(value string) bool {
|
||||
return expressionReadsContext(value, "needs")
|
||||
return expreval.ReadsContext(value, "needs")
|
||||
}
|
||||
|
||||
// ExpressionReadsMatrix reports whether a job's `if:` reads the matrix context.
|
||||
// A deferred-matrix placeholder has no combination yet, so such an expression cannot be decided.
|
||||
func ExpressionReadsMatrix(ifValue string) bool {
|
||||
return expressionReadsContext(asIfExpression(ifValue), "matrix")
|
||||
return expreval.ReadsContext(asIfExpression(ifValue), "matrix")
|
||||
}
|
||||
|
||||
// ExpressionIgnoresNeedResults reports whether a job's `if:` calls always(), failure() or cancelled(),
|
||||
@@ -86,14 +85,6 @@ func asIfExpression(ifValue string) string {
|
||||
return "${{ " + ifValue + " }}"
|
||||
}
|
||||
|
||||
// expressionReadsContext reports whether value holds a ${{ }} expression reading the named context.
|
||||
func expressionReadsContext(value, contextName string) bool {
|
||||
return expreval.Match(value, func(node actionlint.ExprNode) bool {
|
||||
variable, ok := node.(*actionlint.VariableNode)
|
||||
return ok && strings.EqualFold(variable.Name, contextName)
|
||||
})
|
||||
}
|
||||
|
||||
func Parse(content []byte, options ...ParseOption) ([]*SingleWorkflow, error) {
|
||||
// The workflow is split into one document per job below, which would strand an alias whose
|
||||
// anchor lands in another one.
|
||||
|
||||
@@ -177,7 +177,6 @@ func TestParseInterpolatesRunName(t *testing.T) {
|
||||
{"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"}))
|
||||
@@ -187,6 +186,11 @@ func TestParseInterpolatesRunName(t *testing.T) {
|
||||
})
|
||||
}
|
||||
|
||||
t.Run("unclosed expression errors", func(t *testing.T) {
|
||||
_, err := Parse(workflow("${{ 1"), WithGitContext(&model.GithubContext{EventName: "push"}))
|
||||
require.ErrorContains(t, err, "unclosed expression")
|
||||
})
|
||||
|
||||
// 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"}))
|
||||
@@ -252,14 +256,14 @@ func TestExpandMatrixWithNeeds(t *testing.T) {
|
||||
})
|
||||
|
||||
// GitHub rejects a matrix that yields no combinations instead of running the job unparameterized.
|
||||
for _, tt := range []struct{ name, matrix string }{
|
||||
{"empty vector", "\n version: ${{ fromJson(needs.setup.outputs.empty) }}\n"},
|
||||
{"empty include", "\n include: ${{ fromJson(needs.setup.outputs.empty) }}\n"},
|
||||
{"whole matrix not a mapping", " ${{ fromJson(needs.setup.outputs.empty) }}\n"},
|
||||
for _, tt := range []struct{ name, matrix, errHas string }{
|
||||
{"empty vector", "\n version: ${{ fromJson(needs.setup.outputs.empty) }}\n", `Matrix vector "version" does not contain any values`},
|
||||
{"empty include", "\n include: ${{ fromJson(needs.setup.outputs.empty) }}\n", "Matrix must define at least one vector"},
|
||||
{"whole matrix not a mapping", " ${{ fromJson(needs.setup.outputs.empty) }}\n", `Matrix "" is not a map of matrix keys to values`},
|
||||
} {
|
||||
t.Run(tt.name+" errors", func(t *testing.T) {
|
||||
_, err := expand(t, tt.matrix)
|
||||
require.ErrorContains(t, err, "matrix must define at least one vector")
|
||||
require.ErrorContains(t, err, tt.errHas)
|
||||
})
|
||||
}
|
||||
|
||||
@@ -331,10 +335,10 @@ jobs:
|
||||
}{
|
||||
// The canonical GitHub dynamic-matrix idiom. validateMatrixFilters rejects the still-scalar expression outright.
|
||||
{name: "include expression", matrix: "include: ${{ fromJson(needs.setup.outputs.m) }}", parseErrHas: "must be a list of mappings"},
|
||||
// A static vector crossed with the unevaluated expression: one workflow per static value.
|
||||
{name: "static vector and expression", matrix: "os: [a, b]\n version: ${{ fromJson(needs.setup.outputs.m) }}", parseCount: 2},
|
||||
// The single-key case the feature shipped with happens to survive Parse, so it must keep working.
|
||||
{name: "single expression vector", matrix: "version: ${{ fromJson(needs.setup.outputs.m) }}", parseCount: 1},
|
||||
// An unevaluated expression is a scalar where a vector is required, rather than one
|
||||
// combination holding the literal `${{ }}` text.
|
||||
{name: "static vector and expression", matrix: "os: [a, b]\n version: ${{ fromJson(needs.setup.outputs.m) }}", parseErrHas: `Matrix vector "version" is not a list of values`},
|
||||
{name: "single expression vector", matrix: "version: ${{ fromJson(needs.setup.outputs.m) }}", parseErrHas: `Matrix vector "version" is not a list of values`},
|
||||
} {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
planned, err := Parse(fmt.Appendf(nil, workflow, tt.matrix))
|
||||
|
||||
@@ -175,12 +175,23 @@ func (j *Job) RunsOn() []string {
|
||||
return (&model.Job{RawRunsOn: j.RawRunsOn}).RunsOn()
|
||||
}
|
||||
|
||||
// BlockSafeString works around https://github.com/yaml/go-yaml/issues/399, quoting a value whose
|
||||
// leading newline would cost a literal block scalar its indentation indicator.
|
||||
type BlockSafeString string
|
||||
|
||||
func (s BlockSafeString) MarshalYAML() (any, error) {
|
||||
if !strings.HasPrefix(string(s), "\n") {
|
||||
return string(s), nil
|
||||
}
|
||||
return &yaml.Node{Kind: yaml.ScalarNode, Tag: "!!str", Style: yaml.DoubleQuotedStyle, Value: string(s)}, nil
|
||||
}
|
||||
|
||||
type Step struct {
|
||||
ID string `yaml:"id,omitempty"`
|
||||
If yaml.Node `yaml:"if,omitempty"`
|
||||
Name string `yaml:"name,omitempty"`
|
||||
Name BlockSafeString `yaml:"name,omitempty"`
|
||||
Uses string `yaml:"uses,omitempty"`
|
||||
Run string `yaml:"run,omitempty"`
|
||||
Run BlockSafeString `yaml:"run,omitempty"`
|
||||
WorkingDirectory string `yaml:"working-directory,omitempty"`
|
||||
Shell string `yaml:"shell,omitempty"`
|
||||
Env yaml.Node `yaml:"env,omitempty"`
|
||||
@@ -208,9 +219,9 @@ func (s *Step) String() string {
|
||||
}
|
||||
return (&model.Step{
|
||||
ID: s.ID,
|
||||
Name: s.Name,
|
||||
Name: string(s.Name),
|
||||
Uses: s.Uses,
|
||||
Run: s.Run,
|
||||
Run: string(s.Run),
|
||||
}).String()
|
||||
}
|
||||
|
||||
@@ -287,8 +298,6 @@ func EvaluateConcurrency(rc *model.RawConcurrency, jobID string, job *Job, gitCt
|
||||
MaxParallelString: job.Strategy.MaxParallelString,
|
||||
RawMatrix: job.Strategy.RawMatrix,
|
||||
}
|
||||
actJob.Strategy.FailFast = actJob.Strategy.GetFailFast()
|
||||
actJob.Strategy.MaxParallel = actJob.Strategy.GetMaxParallel()
|
||||
}
|
||||
|
||||
matrix := make(map[string]any)
|
||||
|
||||
@@ -48,7 +48,7 @@ jobs:
|
||||
_, origJob := sws[0].Job()
|
||||
require.Len(t, origJob.Steps, 1)
|
||||
const wantRun = "\n\necho start\necho done\n"
|
||||
require.Equal(t, wantRun, origJob.Steps[0].Run)
|
||||
require.Equal(t, wantRun, string(origJob.Steps[0].Run))
|
||||
|
||||
payload, err := sws[0].Marshal()
|
||||
require.NoError(t, err)
|
||||
@@ -63,7 +63,7 @@ jobs:
|
||||
// the round-trip must preserve the run block byte-for-byte
|
||||
_, gotJob := roundTripped[0].Job()
|
||||
require.Len(t, gotJob.Steps, 1)
|
||||
require.Equal(t, wantRun, gotJob.Steps[0].Run, "round-trip must preserve run content; got payload:\n%s", payload)
|
||||
require.Equal(t, wantRun, string(gotJob.Steps[0].Run), "round-trip must preserve run content; got payload:\n%s", payload)
|
||||
}
|
||||
|
||||
// Typing a step's continue-on-error as a bool used to reject the whole `jobs:` node.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
name: Step with leading new line
|
||||
"on":
|
||||
'on':
|
||||
push:
|
||||
jobs:
|
||||
test:
|
||||
@@ -7,9 +7,5 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- id: extract_tag
|
||||
name: |2-
|
||||
|
||||
Extract tag for variant
|
||||
run: |2
|
||||
|
||||
echo Test
|
||||
name: "\nExtract tag for variant"
|
||||
run: "\necho Test\n"
|
||||
|
||||
@@ -88,7 +88,7 @@ labels:
|
||||
b: bb
|
||||
`,
|
||||
tmpl: &IssueTemplate{},
|
||||
wantErr: "yaml: unmarshal errors:\n line 3: cannot unmarshal !!map into IssueTemplateStringSlice",
|
||||
wantErr: "yaml: construct errors: line 3: cannot unmarshal !!map into IssueTemplateStringSlice",
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
|
||||
Reference in New Issue
Block a user