mirror of
https://gitea.com/gitea/act_runner.git
synced 2026-03-23 23:35:03 +01:00
feat: allow configuring gitea schema mode (#23)
* config entries for schema change * remove broken/unused syntetic nodejs action * specify desired schema in model struct that is read by unmarshal * replace params by config * allows gitea context + env names * act --gitea now parses a subset of gitea specific workflows Reviewed-on: https://gitea.com/actions-oss/act-cli/pulls/23 Co-authored-by: Christopher Homberger <christopher.homberger@web.de> Co-committed-by: Christopher Homberger <christopher.homberger@web.de>
This commit is contained in:
committed by
ChristopherHX
parent
faa252c8e9
commit
933c4a5bd5
@@ -83,13 +83,29 @@ type Action struct {
|
||||
Color string `yaml:"color"`
|
||||
Icon string `yaml:"icon"`
|
||||
} `yaml:"branding"`
|
||||
Definition string `yaml:"-"`
|
||||
Schema *schema.Schema `yaml:"-"`
|
||||
}
|
||||
|
||||
func (a *Action) GetDefinition() string {
|
||||
if a.Definition == "" {
|
||||
return "action-root"
|
||||
}
|
||||
return a.Definition
|
||||
}
|
||||
|
||||
func (a *Action) GetSchema() *schema.Schema {
|
||||
if a.Schema == nil {
|
||||
return schema.GetActionSchema()
|
||||
}
|
||||
return a.Schema
|
||||
}
|
||||
|
||||
func (a *Action) UnmarshalYAML(node *yaml.Node) error {
|
||||
// Validate the schema before deserializing it into our model
|
||||
if err := (&schema.Node{
|
||||
Definition: "action-root",
|
||||
Schema: schema.GetActionSchema(),
|
||||
Definition: a.GetDefinition(),
|
||||
Schema: a.GetSchema(),
|
||||
}).UnmarshalYAML(node); err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -110,9 +126,16 @@ type Output struct {
|
||||
Value string `yaml:"value"`
|
||||
}
|
||||
|
||||
type ActionConfig struct {
|
||||
Definition string
|
||||
Schema *schema.Schema
|
||||
}
|
||||
|
||||
// ReadAction reads an action from a reader
|
||||
func ReadAction(in io.Reader) (*Action, error) {
|
||||
func ReadAction(in io.Reader, config ActionConfig) (*Action, error) {
|
||||
a := new(Action)
|
||||
a.Schema = config.Schema
|
||||
a.Definition = config.Definition
|
||||
err := yaml.NewDecoder(in).Decode(a)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
||||
@@ -55,8 +55,13 @@ type WorkflowFiles struct {
|
||||
dirPath string
|
||||
}
|
||||
|
||||
type PlannerConfig struct {
|
||||
Recursive bool
|
||||
Workflow WorkflowConfig
|
||||
}
|
||||
|
||||
// NewWorkflowPlanner will load a specific workflow, all workflows from a directory or all workflows from a directory and its subdirectories
|
||||
func NewWorkflowPlanner(path string, noWorkflowRecurse, strict bool) (WorkflowPlanner, error) {
|
||||
func NewWorkflowPlanner(path string, config PlannerConfig) (WorkflowPlanner, error) {
|
||||
path, err := filepath.Abs(path)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -71,7 +76,7 @@ func NewWorkflowPlanner(path string, noWorkflowRecurse, strict bool) (WorkflowPl
|
||||
|
||||
if fi.IsDir() {
|
||||
log.Debugf("Loading workflows from '%s'", path)
|
||||
if noWorkflowRecurse {
|
||||
if !config.Recursive {
|
||||
files, err := os.ReadDir(path)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -124,7 +129,7 @@ func NewWorkflowPlanner(path string, noWorkflowRecurse, strict bool) (WorkflowPl
|
||||
}
|
||||
|
||||
log.Debugf("Reading workflow '%s'", f.Name())
|
||||
workflow, err := ReadWorkflow(f, strict)
|
||||
workflow, err := ReadWorkflow(f, config.Workflow)
|
||||
if err != nil {
|
||||
_ = f.Close()
|
||||
if err == io.EOF {
|
||||
@@ -157,11 +162,11 @@ func NewWorkflowPlanner(path string, noWorkflowRecurse, strict bool) (WorkflowPl
|
||||
return wp, nil
|
||||
}
|
||||
|
||||
func NewSingleWorkflowPlanner(name string, f io.Reader) (WorkflowPlanner, error) {
|
||||
func NewSingleWorkflowPlanner(name string, f io.Reader, config PlannerConfig) (WorkflowPlanner, error) {
|
||||
wp := new(workflowPlanner)
|
||||
|
||||
log.Debugf("Reading workflow %s", name)
|
||||
workflow, err := ReadWorkflow(f, false)
|
||||
workflow, err := ReadWorkflow(f, config.Workflow)
|
||||
if err != nil {
|
||||
if err == io.EOF {
|
||||
return nil, fmt.Errorf("unable to read workflow '%s': file is empty: %w", name, err)
|
||||
|
||||
@@ -31,7 +31,9 @@ func TestPlanner(t *testing.T) {
|
||||
assert.NoError(t, err, workdir)
|
||||
for _, table := range tables {
|
||||
fullWorkflowPath := filepath.Join(workdir, table.workflowPath)
|
||||
_, err = NewWorkflowPlanner(fullWorkflowPath, table.noWorkflowRecurse, false)
|
||||
_, err = NewWorkflowPlanner(fullWorkflowPath, PlannerConfig{
|
||||
Recursive: !table.noWorkflowRecurse,
|
||||
})
|
||||
if table.errorMessage == "" {
|
||||
assert.NoError(t, err, "WorkflowPlanner should exit without any error")
|
||||
} else {
|
||||
|
||||
@@ -17,12 +17,30 @@ import (
|
||||
|
||||
// Workflow is the structure of the files in .github/workflows
|
||||
type Workflow struct {
|
||||
File string
|
||||
Name string `yaml:"name"`
|
||||
RawOn yaml.Node `yaml:"on"`
|
||||
Env map[string]string `yaml:"env"`
|
||||
Jobs map[string]*Job `yaml:"jobs"`
|
||||
Defaults Defaults `yaml:"defaults"`
|
||||
File string
|
||||
Name string `yaml:"name"`
|
||||
RawOn yaml.Node `yaml:"on"`
|
||||
Env map[string]string `yaml:"env"`
|
||||
Jobs map[string]*Job `yaml:"jobs"`
|
||||
Defaults Defaults `yaml:"defaults"`
|
||||
Schema *schema.Schema `yaml:"-"`
|
||||
Definition string `yaml:"-"`
|
||||
}
|
||||
|
||||
// GetDefinition gets the schema definition name for the workflow
|
||||
func (w *Workflow) GetDefinition() string {
|
||||
if w.Definition == "" {
|
||||
return "workflow-root"
|
||||
}
|
||||
return w.Definition
|
||||
}
|
||||
|
||||
// GetSchema gets the schema for the workflow
|
||||
func (w *Workflow) GetSchema() *schema.Schema {
|
||||
if w.Schema == nil {
|
||||
return schema.GetWorkflowSchema()
|
||||
}
|
||||
return w.Schema
|
||||
}
|
||||
|
||||
// On events for the workflow
|
||||
@@ -74,27 +92,10 @@ func (w *Workflow) UnmarshalYAML(node *yaml.Node) error {
|
||||
}
|
||||
// Validate the schema before deserializing it into our model
|
||||
if err := (&schema.Node{
|
||||
Definition: "workflow-root",
|
||||
Schema: schema.GetWorkflowSchema(),
|
||||
Definition: w.GetDefinition(),
|
||||
Schema: w.GetSchema(),
|
||||
}).UnmarshalYAML(node); err != nil {
|
||||
return errors.Join(err, fmt.Errorf("actions YAML Schema Validation Error detected:\nFor more information, see: https://actions-oss.github.io/act-docs/usage/schema.html"))
|
||||
}
|
||||
type WorkflowDefault Workflow
|
||||
return node.Decode((*WorkflowDefault)(w))
|
||||
}
|
||||
|
||||
type WorkflowStrict Workflow
|
||||
|
||||
func (w *WorkflowStrict) UnmarshalYAML(node *yaml.Node) error {
|
||||
if err := resolveAliases(node); err != nil {
|
||||
return err
|
||||
}
|
||||
// Validate the schema before deserializing it into our model
|
||||
if err := (&schema.Node{
|
||||
Definition: "workflow-root-strict",
|
||||
Schema: schema.GetWorkflowSchema(),
|
||||
}).UnmarshalYAML(node); err != nil {
|
||||
return errors.Join(err, fmt.Errorf("actions YAML Strict Schema Validation Error detected:\nFor more information, see: https://nektosact.com/usage/schema.html"))
|
||||
return errors.Join(err, fmt.Errorf("actions YAML Schema Validation Error of definition '%s' detected:\nFor more information, see: https://actions-oss.github.io/act-docs/usage/schema.html", w.GetDefinition()))
|
||||
}
|
||||
type WorkflowDefault Workflow
|
||||
return node.Decode((*WorkflowDefault)(w))
|
||||
@@ -708,14 +709,20 @@ func (s *Step) Type() StepType {
|
||||
return StepTypeUsesActionRemote
|
||||
}
|
||||
|
||||
type WorkflowConfig struct {
|
||||
Definition string
|
||||
Schema *schema.Schema
|
||||
Strict bool
|
||||
}
|
||||
|
||||
// ReadWorkflow returns a list of jobs for a given workflow file reader
|
||||
func ReadWorkflow(in io.Reader, strict bool) (*Workflow, error) {
|
||||
if strict {
|
||||
w := new(WorkflowStrict)
|
||||
err := yaml.NewDecoder(in).Decode(w)
|
||||
return (*Workflow)(w), err
|
||||
}
|
||||
func ReadWorkflow(in io.Reader, config WorkflowConfig) (*Workflow, error) {
|
||||
w := new(Workflow)
|
||||
w.Schema = config.Schema
|
||||
w.Definition = config.Definition
|
||||
if config.Strict {
|
||||
w.Definition = "workflow-root-strict"
|
||||
}
|
||||
err := yaml.NewDecoder(in).Decode(w)
|
||||
return w, err
|
||||
}
|
||||
|
||||
@@ -21,7 +21,7 @@ jobs:
|
||||
- uses: ./actions/docker-url
|
||||
`
|
||||
|
||||
workflow, err := ReadWorkflow(strings.NewReader(yaml), false)
|
||||
workflow, err := ReadWorkflow(strings.NewReader(yaml), WorkflowConfig{})
|
||||
assert.NoError(t, err, "read workflow should succeed")
|
||||
|
||||
assert.Len(t, workflow.On(), 1)
|
||||
@@ -40,7 +40,7 @@ jobs:
|
||||
- uses: ./actions/docker-url
|
||||
`
|
||||
|
||||
workflow, err := ReadWorkflow(strings.NewReader(yaml), false)
|
||||
workflow, err := ReadWorkflow(strings.NewReader(yaml), WorkflowConfig{})
|
||||
assert.NoError(t, err, "read workflow should succeed")
|
||||
|
||||
assert.Len(t, workflow.On(), 2)
|
||||
@@ -66,7 +66,7 @@ jobs:
|
||||
- uses: ./actions/docker-url
|
||||
`
|
||||
|
||||
workflow, err := ReadWorkflow(strings.NewReader(yaml), false)
|
||||
workflow, err := ReadWorkflow(strings.NewReader(yaml), WorkflowConfig{})
|
||||
assert.NoError(t, err, "read workflow should succeed")
|
||||
assert.Len(t, workflow.On(), 2)
|
||||
assert.Contains(t, workflow.On(), "push")
|
||||
@@ -85,7 +85,7 @@ jobs:
|
||||
steps:
|
||||
- uses: ./actions/docker-url`
|
||||
|
||||
workflow, err := ReadWorkflow(strings.NewReader(yaml), false)
|
||||
workflow, err := ReadWorkflow(strings.NewReader(yaml), WorkflowConfig{})
|
||||
assert.NoError(t, err, "read workflow should succeed")
|
||||
assert.Equal(t, workflow.Jobs["test"].RunsOn(), []string{"ubuntu-latest"})
|
||||
}
|
||||
@@ -103,7 +103,7 @@ jobs:
|
||||
steps:
|
||||
- uses: ./actions/docker-url`
|
||||
|
||||
workflow, err := ReadWorkflow(strings.NewReader(yaml), false)
|
||||
workflow, err := ReadWorkflow(strings.NewReader(yaml), WorkflowConfig{})
|
||||
assert.NoError(t, err, "read workflow should succeed")
|
||||
assert.Equal(t, workflow.Jobs["test"].RunsOn(), []string{"ubuntu-latest", "linux"})
|
||||
}
|
||||
@@ -128,7 +128,7 @@ jobs:
|
||||
- uses: ./actions/docker-url
|
||||
`
|
||||
|
||||
workflow, err := ReadWorkflow(strings.NewReader(yaml), false)
|
||||
workflow, err := ReadWorkflow(strings.NewReader(yaml), WorkflowConfig{})
|
||||
assert.NoError(t, err, "read workflow should succeed")
|
||||
assert.Len(t, workflow.Jobs, 2)
|
||||
assert.Contains(t, workflow.Jobs["test"].Container().Image, "nginx:latest")
|
||||
@@ -158,7 +158,7 @@ jobs:
|
||||
- uses: ./actions/docker-url
|
||||
`
|
||||
|
||||
workflow, err := ReadWorkflow(strings.NewReader(yaml), false)
|
||||
workflow, err := ReadWorkflow(strings.NewReader(yaml), WorkflowConfig{})
|
||||
assert.NoError(t, err, "read workflow should succeed")
|
||||
assert.Len(t, workflow.Jobs, 1)
|
||||
|
||||
@@ -196,7 +196,7 @@ jobs:
|
||||
uses: ./some/path/to/workflow.yaml
|
||||
`
|
||||
|
||||
workflow, err := ReadWorkflow(strings.NewReader(yaml), false)
|
||||
workflow, err := ReadWorkflow(strings.NewReader(yaml), WorkflowConfig{})
|
||||
assert.NoError(t, err, "read workflow should succeed")
|
||||
assert.Len(t, workflow.Jobs, 6)
|
||||
|
||||
@@ -240,7 +240,7 @@ jobs:
|
||||
uses: some/path/to/workflow.yaml
|
||||
`
|
||||
|
||||
workflow, err := ReadWorkflow(strings.NewReader(yaml), false)
|
||||
workflow, err := ReadWorkflow(strings.NewReader(yaml), WorkflowConfig{})
|
||||
assert.NoError(t, err, "read workflow should succeed")
|
||||
assert.Len(t, workflow.Jobs, 4)
|
||||
|
||||
@@ -282,7 +282,7 @@ jobs:
|
||||
uses: ./local-action
|
||||
`
|
||||
|
||||
_, err := ReadWorkflow(strings.NewReader(yaml), false)
|
||||
_, err := ReadWorkflow(strings.NewReader(yaml), WorkflowConfig{})
|
||||
assert.Error(t, err, "read workflow should fail")
|
||||
}
|
||||
|
||||
@@ -314,7 +314,7 @@ jobs:
|
||||
echo "${{ needs.test1.outputs.some-b-key }}"
|
||||
`
|
||||
|
||||
workflow, err := ReadWorkflow(strings.NewReader(yaml), false)
|
||||
workflow, err := ReadWorkflow(strings.NewReader(yaml), WorkflowConfig{})
|
||||
assert.NoError(t, err, "read workflow should succeed")
|
||||
assert.Len(t, workflow.Jobs, 2)
|
||||
|
||||
@@ -329,7 +329,7 @@ jobs:
|
||||
}
|
||||
|
||||
func TestReadWorkflow_Strategy(t *testing.T) {
|
||||
w, err := NewWorkflowPlanner("testdata/strategy/push.yml", true, false)
|
||||
w, err := NewWorkflowPlanner("testdata/strategy/push.yml", PlannerConfig{})
|
||||
assert.NoError(t, err)
|
||||
|
||||
p, err := w.PlanJob("strategy-only-max-parallel")
|
||||
@@ -451,7 +451,7 @@ func TestReadWorkflow_WorkflowDispatchConfig(t *testing.T) {
|
||||
steps:
|
||||
- run: echo Test
|
||||
`
|
||||
workflow, err := ReadWorkflow(strings.NewReader(yaml), false)
|
||||
workflow, err := ReadWorkflow(strings.NewReader(yaml), WorkflowConfig{})
|
||||
assert.NoError(t, err, "read workflow should succeed")
|
||||
workflowDispatch := workflow.WorkflowDispatchConfig()
|
||||
assert.Nil(t, workflowDispatch)
|
||||
@@ -465,7 +465,7 @@ func TestReadWorkflow_WorkflowDispatchConfig(t *testing.T) {
|
||||
steps:
|
||||
- run: echo Test
|
||||
`
|
||||
workflow, err = ReadWorkflow(strings.NewReader(yaml), false)
|
||||
workflow, err = ReadWorkflow(strings.NewReader(yaml), WorkflowConfig{})
|
||||
assert.NoError(t, err, "read workflow should succeed")
|
||||
workflowDispatch = workflow.WorkflowDispatchConfig()
|
||||
assert.NotNil(t, workflowDispatch)
|
||||
@@ -480,7 +480,7 @@ func TestReadWorkflow_WorkflowDispatchConfig(t *testing.T) {
|
||||
steps:
|
||||
- run: echo Test
|
||||
`
|
||||
workflow, err = ReadWorkflow(strings.NewReader(yaml), false)
|
||||
workflow, err = ReadWorkflow(strings.NewReader(yaml), WorkflowConfig{})
|
||||
assert.NoError(t, err, "read workflow should succeed")
|
||||
workflowDispatch = workflow.WorkflowDispatchConfig()
|
||||
assert.Nil(t, workflowDispatch)
|
||||
@@ -494,7 +494,7 @@ func TestReadWorkflow_WorkflowDispatchConfig(t *testing.T) {
|
||||
steps:
|
||||
- run: echo Test
|
||||
`
|
||||
workflow, err = ReadWorkflow(strings.NewReader(yaml), false)
|
||||
workflow, err = ReadWorkflow(strings.NewReader(yaml), WorkflowConfig{})
|
||||
assert.NoError(t, err, "read workflow should succeed")
|
||||
workflowDispatch = workflow.WorkflowDispatchConfig()
|
||||
assert.NotNil(t, workflowDispatch)
|
||||
@@ -511,7 +511,7 @@ func TestReadWorkflow_WorkflowDispatchConfig(t *testing.T) {
|
||||
steps:
|
||||
- run: echo Test
|
||||
`
|
||||
workflow, err = ReadWorkflow(strings.NewReader(yaml), false)
|
||||
workflow, err = ReadWorkflow(strings.NewReader(yaml), WorkflowConfig{})
|
||||
assert.NoError(t, err, "read workflow should succeed")
|
||||
workflowDispatch = workflow.WorkflowDispatchConfig()
|
||||
assert.NotNil(t, workflowDispatch)
|
||||
@@ -528,7 +528,7 @@ func TestReadWorkflow_WorkflowDispatchConfig(t *testing.T) {
|
||||
steps:
|
||||
- run: echo Test
|
||||
`
|
||||
workflow, err = ReadWorkflow(strings.NewReader(yaml), false)
|
||||
workflow, err = ReadWorkflow(strings.NewReader(yaml), WorkflowConfig{})
|
||||
assert.NoError(t, err, "read workflow should succeed")
|
||||
workflowDispatch = workflow.WorkflowDispatchConfig()
|
||||
assert.Nil(t, workflowDispatch)
|
||||
@@ -555,7 +555,7 @@ func TestReadWorkflow_WorkflowDispatchConfig(t *testing.T) {
|
||||
steps:
|
||||
- run: echo Test
|
||||
`
|
||||
workflow, err = ReadWorkflow(strings.NewReader(yaml), false)
|
||||
workflow, err = ReadWorkflow(strings.NewReader(yaml), WorkflowConfig{})
|
||||
assert.NoError(t, err, "read workflow should succeed")
|
||||
workflowDispatch = workflow.WorkflowDispatchConfig()
|
||||
assert.NotNil(t, workflowDispatch)
|
||||
@@ -584,7 +584,7 @@ jobs:
|
||||
- uses: ./actions/docker-url
|
||||
`
|
||||
|
||||
_, err := ReadWorkflow(strings.NewReader(yaml), true)
|
||||
_, err := ReadWorkflow(strings.NewReader(yaml), WorkflowConfig{Strict: true})
|
||||
assert.Error(t, err, "read workflow should succeed")
|
||||
}
|
||||
|
||||
@@ -603,7 +603,7 @@ jobs:
|
||||
- uses: *checkout
|
||||
`
|
||||
|
||||
w, err := ReadWorkflow(strings.NewReader(yaml), true)
|
||||
w, err := ReadWorkflow(strings.NewReader(yaml), WorkflowConfig{Strict: true})
|
||||
assert.NoError(t, err, "read workflow should succeed")
|
||||
|
||||
for _, job := range w.Jobs {
|
||||
@@ -631,7 +631,7 @@ jobs:
|
||||
on: push #*trigger
|
||||
`
|
||||
|
||||
w, err := ReadWorkflow(strings.NewReader(yaml), false)
|
||||
w, err := ReadWorkflow(strings.NewReader(yaml), WorkflowConfig{})
|
||||
assert.NoError(t, err, "read workflow should succeed")
|
||||
|
||||
for _, job := range w.Jobs {
|
||||
|
||||
Reference in New Issue
Block a user