mirror of
https://github.com/go-gitea/gitea.git
synced 2025-01-27 07:12:51 +00:00
fix(actions): fix nil errors and double list size
This commit is contained in:
parent
a9a9a1633a
commit
81c1662340
2
go.mod
2
go.mod
@ -102,6 +102,7 @@ require (
|
||||
github.com/prometheus/client_golang v1.20.5
|
||||
github.com/quasoft/websspi v1.1.2
|
||||
github.com/redis/go-redis/v9 v9.7.0
|
||||
github.com/rhysd/actionlint v1.7.3
|
||||
github.com/robfig/cron/v3 v3.0.1
|
||||
github.com/santhosh-tekuri/jsonschema/v5 v5.3.1
|
||||
github.com/sassoftware/go-rpmutils v0.4.0
|
||||
@ -271,7 +272,6 @@ require (
|
||||
github.com/prometheus/client_model v0.6.1 // indirect
|
||||
github.com/prometheus/common v0.60.1 // indirect
|
||||
github.com/prometheus/procfs v0.15.1 // indirect
|
||||
github.com/rhysd/actionlint v1.7.3 // indirect
|
||||
github.com/rivo/uniseg v0.4.7 // indirect
|
||||
github.com/rogpeppe/go-internal v1.13.1 // indirect
|
||||
github.com/rs/xid v1.6.0 // indirect
|
||||
|
@ -9,10 +9,10 @@ import (
|
||||
"gopkg.in/yaml.v3"
|
||||
)
|
||||
|
||||
// NewInterpeter returns an interpeter used in the server,
|
||||
// NewInterpreter returns an interpreter used in the server,
|
||||
// need github, needs, strategy, matrix, inputs context only,
|
||||
// see https://docs.github.com/en/actions/learn-github-actions/contexts#context-availability
|
||||
func NewInterpeter(
|
||||
func NewInterpreter(
|
||||
jobID string,
|
||||
job *model.Job,
|
||||
matrix map[string]any,
|
||||
@ -78,7 +78,7 @@ func NewInterpeter(
|
||||
return exprparser.NewInterpeter(ee, config)
|
||||
}
|
||||
|
||||
// JobResult is the minimum requirement of job results for Interpeter
|
||||
// JobResult is the minimum requirement of job results for Interpreter
|
||||
type JobResult struct {
|
||||
Needs []string
|
||||
Result string
|
||||
|
@ -54,7 +54,7 @@ func Parse(content []byte, options ...ParseOption) ([]*SingleWorkflow, error) {
|
||||
job.Name = id
|
||||
}
|
||||
job.Strategy.RawMatrix = encodeMatrix(matrix)
|
||||
evaluator := NewExpressionEvaluator(NewInterpeter(id, origin.GetJob(id), matrix, pc.gitContext, results, pc.vars))
|
||||
evaluator := NewExpressionEvaluator(NewInterpreter(id, origin.GetJob(id), matrix, pc.gitContext, results, pc.vars))
|
||||
job.Name = nameWithMatrix(job.Name, matrix, evaluator)
|
||||
runsOn := origin.GetJob(id).RunsOn()
|
||||
for i, v := range runsOn {
|
||||
|
@ -204,16 +204,19 @@ func (evt *Event) Acts() map[string][]string {
|
||||
// Helper to convert actionlint errors
|
||||
func acErrToError(acErrs []*actionlint.Error) []error {
|
||||
errs := make([]error, len(acErrs))
|
||||
for _, err := range acErrs {
|
||||
errs = append(errs, err)
|
||||
for i, err := range acErrs {
|
||||
errs[i] = err
|
||||
}
|
||||
return errs
|
||||
}
|
||||
|
||||
func acStringToString(strs []*actionlint.String) []string {
|
||||
if len(strs) == 0 {
|
||||
return nil
|
||||
}
|
||||
strings := make([]string, len(strs))
|
||||
for _, v := range strs {
|
||||
strings = append(strings, v.Value)
|
||||
for i, v := range strs {
|
||||
strings[i] = v.Value
|
||||
}
|
||||
return strings
|
||||
}
|
||||
@ -246,29 +249,39 @@ func GetEventsFromContent(content []byte) ([]*Event, error) {
|
||||
for _, acEvent := range wf.On {
|
||||
event := &Event{
|
||||
Name: acEvent.EventName(),
|
||||
acts: map[string][]string{},
|
||||
}
|
||||
switch e := acEvent.(type) {
|
||||
case *actionlint.ScheduledEvent:
|
||||
schedules := make([]map[string]string, len(e.Cron))
|
||||
for _, c := range e.Cron {
|
||||
schedules = append(schedules, map[string]string{"cron": c.Value})
|
||||
for i, c := range e.Cron {
|
||||
schedules[i] = map[string]string{"cron": c.Value}
|
||||
}
|
||||
event.schedules = schedules
|
||||
case *actionlint.WorkflowDispatchEvent:
|
||||
inputs := make([]WorkflowDispatchInput, len(e.Inputs))
|
||||
i := 0
|
||||
for keyword, v := range e.Inputs {
|
||||
inputs = append(inputs, WorkflowDispatchInput{
|
||||
Name: keyword,
|
||||
Required: v.Required.Value,
|
||||
Description: v.Description.Value,
|
||||
Default: v.Default.Value,
|
||||
Options: acStringToString(v.Options),
|
||||
Type: typeToString(v.Type),
|
||||
})
|
||||
wdi := WorkflowDispatchInput{
|
||||
Name: keyword,
|
||||
|
||||
Options: acStringToString(v.Options),
|
||||
Type: typeToString(v.Type),
|
||||
}
|
||||
if v.Required != nil {
|
||||
wdi.Required = v.Required.Value
|
||||
}
|
||||
if v.Description != nil {
|
||||
wdi.Description = v.Description.Value
|
||||
}
|
||||
if v.Default != nil {
|
||||
wdi.Default = v.Default.Value
|
||||
}
|
||||
inputs[i] = wdi
|
||||
i++
|
||||
}
|
||||
event.inputs = inputs
|
||||
case *actionlint.WebhookEvent:
|
||||
event.acts = map[string][]string{}
|
||||
if e.Branches != nil {
|
||||
event.acts[e.Branches.Name.Value] = acStringToString(e.Branches.Values)
|
||||
}
|
||||
@ -290,7 +303,6 @@ func GetEventsFromContent(content []byte) ([]*Event, error) {
|
||||
if e.Types != nil {
|
||||
event.acts["types"] = acStringToString(e.Types)
|
||||
}
|
||||
// if e.
|
||||
}
|
||||
events = append(events, event)
|
||||
}
|
||||
|
@ -9,270 +9,85 @@ import (
|
||||
|
||||
"github.com/nektos/act/pkg/model"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
"gopkg.in/yaml.v3"
|
||||
)
|
||||
|
||||
// func TestParseRawOn(t *testing.T) {
|
||||
// kases := []struct {
|
||||
// input string
|
||||
// result []*Event
|
||||
// }{
|
||||
// {
|
||||
// input: "on: issue_comment",
|
||||
// result: []*Event{
|
||||
// {
|
||||
// Name: "issue_comment",
|
||||
// },
|
||||
// },
|
||||
// },
|
||||
// {
|
||||
// input: "on:\n push",
|
||||
// result: []*Event{
|
||||
// {
|
||||
// Name: "push",
|
||||
// },
|
||||
// },
|
||||
// },
|
||||
func TestGetEvents(t *testing.T) {
|
||||
content := `
|
||||
name: My Workflow
|
||||
|
||||
// {
|
||||
// input: "on:\n - push\n - pull_request",
|
||||
// result: []*Event{
|
||||
// {
|
||||
// Name: "push",
|
||||
// },
|
||||
// {
|
||||
// Name: "pull_request",
|
||||
// },
|
||||
// },
|
||||
// },
|
||||
// {
|
||||
// input: "on:\n push:\n branches:\n - master",
|
||||
// result: []*Event{
|
||||
// {
|
||||
// Name: "push",
|
||||
// acts: map[string][]string{
|
||||
// "branches": {
|
||||
// "master",
|
||||
// },
|
||||
// },
|
||||
// },
|
||||
// },
|
||||
// },
|
||||
// {
|
||||
// input: "on:\n branch_protection_rule:\n types: [created, deleted]",
|
||||
// result: []*Event{
|
||||
// {
|
||||
// Name: "branch_protection_rule",
|
||||
// acts: map[string][]string{
|
||||
// "types": {
|
||||
// "created",
|
||||
// "deleted",
|
||||
// },
|
||||
// },
|
||||
// },
|
||||
// },
|
||||
// },
|
||||
// {
|
||||
// input: "on:\n project:\n types: [created, deleted]\n milestone:\n types: [opened, deleted]",
|
||||
// result: []*Event{
|
||||
// {
|
||||
// Name: "project",
|
||||
// acts: map[string][]string{
|
||||
// "types": {
|
||||
// "created",
|
||||
// "deleted",
|
||||
// },
|
||||
// },
|
||||
// },
|
||||
// {
|
||||
// Name: "milestone",
|
||||
// acts: map[string][]string{
|
||||
// "types": {
|
||||
// "opened",
|
||||
// "deleted",
|
||||
// },
|
||||
// },
|
||||
// },
|
||||
// },
|
||||
// },
|
||||
// {
|
||||
// input: "on:\n pull_request:\n types:\n - opened\n branches:\n - 'releases/**'",
|
||||
// result: []*Event{
|
||||
// {
|
||||
// Name: "pull_request",
|
||||
// acts: map[string][]string{
|
||||
// "types": {
|
||||
// "opened",
|
||||
// },
|
||||
// "branches": {
|
||||
// "releases/**",
|
||||
// },
|
||||
// },
|
||||
// },
|
||||
// },
|
||||
// },
|
||||
// {
|
||||
// input: "on:\n push:\n branches:\n - main\n pull_request:\n types:\n - opened\n branches:\n - '**'",
|
||||
// result: []*Event{
|
||||
// {
|
||||
// Name: "push",
|
||||
// acts: map[string][]string{
|
||||
// "branches": {
|
||||
// "main",
|
||||
// },
|
||||
// },
|
||||
// },
|
||||
// {
|
||||
// Name: "pull_request",
|
||||
// acts: map[string][]string{
|
||||
// "types": {
|
||||
// "opened",
|
||||
// },
|
||||
// "branches": {
|
||||
// "**",
|
||||
// },
|
||||
// },
|
||||
// },
|
||||
// },
|
||||
// },
|
||||
// {
|
||||
// input: "on:\n push:\n branches:\n - 'main'\n - 'releases/**'",
|
||||
// result: []*Event{
|
||||
// {
|
||||
// Name: "push",
|
||||
// acts: map[string][]string{
|
||||
// "branches": {
|
||||
// "main",
|
||||
// "releases/**",
|
||||
// },
|
||||
// },
|
||||
// },
|
||||
// },
|
||||
// },
|
||||
// {
|
||||
// input: "on:\n push:\n tags:\n - v1.**",
|
||||
// result: []*Event{
|
||||
// {
|
||||
// Name: "push",
|
||||
// acts: map[string][]string{
|
||||
// "tags": {
|
||||
// "v1.**",
|
||||
// },
|
||||
// },
|
||||
// },
|
||||
// },
|
||||
// },
|
||||
// {
|
||||
// input: "on: [pull_request, workflow_dispatch]",
|
||||
// result: []*Event{
|
||||
// {
|
||||
// Name: "pull_request",
|
||||
// },
|
||||
// {
|
||||
// Name: "workflow_dispatch",
|
||||
// },
|
||||
// },
|
||||
// },
|
||||
// {
|
||||
// input: "on:\n schedule:\n - cron: '20 6 * * *'",
|
||||
// result: []*Event{
|
||||
// {
|
||||
// Name: "schedule",
|
||||
// schedules: []map[string]string{
|
||||
// {
|
||||
// "cron": "20 6 * * *",
|
||||
// },
|
||||
// },
|
||||
// },
|
||||
// },
|
||||
// },
|
||||
// {
|
||||
// input: `on:
|
||||
// workflow_dispatch:
|
||||
// inputs:
|
||||
// logLevel:
|
||||
// description: 'Log level'
|
||||
// required: true
|
||||
// default: 'warning'
|
||||
// type: choice
|
||||
// options:
|
||||
// - info
|
||||
// - warning
|
||||
// - debug
|
||||
// tags:
|
||||
// description: 'Test scenario tags'
|
||||
// required: false
|
||||
// type: boolean
|
||||
// environment:
|
||||
// description: 'Environment to run tests against'
|
||||
// type: environment
|
||||
// required: true
|
||||
// push:
|
||||
// `,
|
||||
// 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",
|
||||
// },
|
||||
// },
|
||||
// },
|
||||
// }
|
||||
// for _, kase := range kases {
|
||||
// t.Run(kase.input, func(t *testing.T) {
|
||||
// origin, err := model.ReadWorkflow(strings.NewReader(kase.input))
|
||||
// assert.NoError(t, err)
|
||||
on:
|
||||
push:
|
||||
branches: [main]
|
||||
schedule:
|
||||
- cron: '0 0 * * *'
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
my_variable1:
|
||||
description: 'first variable'
|
||||
required: true
|
||||
type: string
|
||||
my_variable2:
|
||||
description: 'second variable'
|
||||
required: false
|
||||
type: number
|
||||
default: 4
|
||||
|
||||
// events, err := ParseRawOn(&origin.RawOn)
|
||||
// assert.NoError(t, err)
|
||||
// assert.EqualValues(t, kase.result, events, fmt.Sprintf("%#v", events))
|
||||
// })
|
||||
// }
|
||||
// }
|
||||
jobs:
|
||||
example:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- run: exit 0
|
||||
`
|
||||
expected := make([]*Event, 3)
|
||||
expected[0] = &Event{acts: map[string][]string{"branches": {"main"}}, Name: "push"}
|
||||
expected[1] = &Event{Name: "schedule", schedules: []map[string]string{{"cron": "0 0 * * *"}}}
|
||||
expected[2] = &Event{
|
||||
Name: "workflow_dispatch",
|
||||
inputs: []WorkflowDispatchInput{
|
||||
{
|
||||
Name: "my_variable1",
|
||||
Description: "first variable",
|
||||
Required: true,
|
||||
Type: "string",
|
||||
},
|
||||
{
|
||||
Name: "my_variable2",
|
||||
Type: "number",
|
||||
Description: "second variable",
|
||||
Default: "4",
|
||||
},
|
||||
},
|
||||
}
|
||||
actual, err := GetEventsFromContent([]byte(content))
|
||||
require.NoError(t, err)
|
||||
assert.Len(t, actual, 3)
|
||||
assert.Equal(t, expected, actual)
|
||||
//Toggler
|
||||
}
|
||||
|
||||
// func TestSingleWorkflow_SetJob(t *testing.T) {
|
||||
// t.Run("erase needs", func(t *testing.T) {
|
||||
// content := ReadTestdata(t, "erase_needs.in.yaml")
|
||||
// want := ReadTestdata(t, "erase_needs.out.yaml")
|
||||
// swf, err := Parse(content)
|
||||
// require.NoError(t, err)
|
||||
// builder := &strings.Builder{}
|
||||
// for _, v := range swf {
|
||||
// id, job := v.Job()
|
||||
// require.NoError(t, v.SetJob(id, job.EraseNeeds()))
|
||||
func TestSingleWorkflow_SetJob(t *testing.T) {
|
||||
t.Run("erase needs", func(t *testing.T) {
|
||||
content := ReadTestdata(t, "erase_needs.in.yaml")
|
||||
want := ReadTestdata(t, "erase_needs.out.yaml")
|
||||
swf, err := Parse(content)
|
||||
require.NoError(t, err)
|
||||
builder := &strings.Builder{}
|
||||
for _, v := range swf {
|
||||
id, job := v.Job()
|
||||
require.NoError(t, v.SetJob(id, job.EraseNeeds()))
|
||||
|
||||
// if builder.Len() > 0 {
|
||||
// builder.WriteString("---\n")
|
||||
// }
|
||||
// encoder := yaml.NewEncoder(builder)
|
||||
// encoder.SetIndent(2)
|
||||
// require.NoError(t, encoder.Encode(v))
|
||||
// }
|
||||
// assert.Equal(t, string(want), builder.String())
|
||||
// })
|
||||
// }
|
||||
if builder.Len() > 0 {
|
||||
builder.WriteString("---\n")
|
||||
}
|
||||
encoder := yaml.NewEncoder(builder)
|
||||
encoder.SetIndent(2)
|
||||
require.NoError(t, encoder.Encode(v))
|
||||
}
|
||||
assert.Equal(t, string(want), builder.String())
|
||||
})
|
||||
}
|
||||
|
||||
func TestParseMappingNode(t *testing.T) {
|
||||
tests := []struct {
|
||||
|
Loading…
Reference in New Issue
Block a user