support list/map/scalar for on and needs
Signed-off-by: Casey Lee <cplee@nektos.com>
This commit is contained in:
@@ -3,7 +3,7 @@ package model
|
||||
import (
|
||||
"io"
|
||||
|
||||
"gopkg.in/yaml.v2"
|
||||
"gopkg.in/yaml.v3"
|
||||
)
|
||||
|
||||
// ActionRunsUsing is the type of runner for the action
|
||||
|
@@ -88,8 +88,10 @@ type workflowPlanner struct {
|
||||
func (wp *workflowPlanner) PlanEvent(eventName string) *Plan {
|
||||
plan := new(Plan)
|
||||
for _, w := range wp.workflows {
|
||||
if w.On == eventName {
|
||||
plan.mergeStages(createStages(w, w.GetJobIDs()...))
|
||||
for _, e := range w.On() {
|
||||
if e == eventName {
|
||||
plan.mergeStages(createStages(w, w.GetJobIDs()...))
|
||||
}
|
||||
}
|
||||
}
|
||||
return plan
|
||||
@@ -110,14 +112,19 @@ func (wp *workflowPlanner) GetEvents() []string {
|
||||
for _, w := range wp.workflows {
|
||||
found := false
|
||||
for _, e := range events {
|
||||
if e == w.On {
|
||||
found = true
|
||||
for _, we := range w.On() {
|
||||
if e == we {
|
||||
found = true
|
||||
break
|
||||
}
|
||||
}
|
||||
if found {
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
if !found {
|
||||
events = append(events, w.On)
|
||||
events = append(events, w.On()...)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -163,8 +170,8 @@ func createStages(w *Workflow, jobIDs ...string) []*Stage {
|
||||
// make sure we haven't visited this job yet
|
||||
if _, ok := jobDependencies[jID]; !ok {
|
||||
if job := w.GetJob(jID); job != nil {
|
||||
jobDependencies[jID] = job.Needs
|
||||
newJobIDs = append(newJobIDs, job.Needs...)
|
||||
jobDependencies[jID] = job.Needs()
|
||||
newJobIDs = append(newJobIDs, job.Needs()...)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -6,21 +6,45 @@ import (
|
||||
"regexp"
|
||||
"strings"
|
||||
|
||||
"gopkg.in/yaml.v2"
|
||||
"gopkg.in/yaml.v3"
|
||||
)
|
||||
|
||||
// Workflow is the structure of the files in .github/workflows
|
||||
type Workflow struct {
|
||||
Name string `yaml:"name"`
|
||||
On string `yaml:"on"`
|
||||
Env map[string]string `yaml:"env"`
|
||||
Jobs map[string]*Job `yaml:"jobs"`
|
||||
Name string `yaml:"name"`
|
||||
RawOn yaml.Node `yaml:"on"`
|
||||
Env map[string]string `yaml:"env"`
|
||||
Jobs map[string]*Job `yaml:"jobs"`
|
||||
}
|
||||
|
||||
// On events for the workflow
|
||||
func (w *Workflow) On() []string {
|
||||
|
||||
switch w.RawOn.Kind {
|
||||
case yaml.ScalarNode:
|
||||
var val string
|
||||
w.RawOn.Decode(&val)
|
||||
return []string{val}
|
||||
case yaml.SequenceNode:
|
||||
var val []string
|
||||
w.RawOn.Decode(&val)
|
||||
return val
|
||||
case yaml.MappingNode:
|
||||
var val map[string]interface{}
|
||||
w.RawOn.Decode(&val)
|
||||
var keys []string
|
||||
for k := range val {
|
||||
keys = append(keys, k)
|
||||
}
|
||||
return keys
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Job is the structure of one job in a workflow
|
||||
type Job struct {
|
||||
Name string `yaml:"name"`
|
||||
Needs []string `yaml:"needs"`
|
||||
RawNeeds yaml.Node `yaml:"needs"`
|
||||
RunsOn string `yaml:"runs-on"`
|
||||
Env map[string]string `yaml:"env"`
|
||||
If string `yaml:"if"`
|
||||
@@ -30,6 +54,22 @@ type Job struct {
|
||||
Services map[string]*ContainerSpec `yaml:"services"`
|
||||
}
|
||||
|
||||
// Needs list for Job
|
||||
func (j *Job) Needs() []string {
|
||||
|
||||
switch j.RawNeeds.Kind {
|
||||
case yaml.ScalarNode:
|
||||
var val string
|
||||
j.RawNeeds.Decode(&val)
|
||||
return []string{val}
|
||||
case yaml.SequenceNode:
|
||||
var val []string
|
||||
j.RawNeeds.Decode(&val)
|
||||
return val
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// ContainerSpec is the specification of the container to use for the job
|
||||
type ContainerSpec struct {
|
||||
Image string `yaml:"image"`
|
||||
|
68
pkg/model/workflow_test.go
Normal file
68
pkg/model/workflow_test.go
Normal file
@@ -0,0 +1,68 @@
|
||||
package model
|
||||
|
||||
import (
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"gotest.tools/assert"
|
||||
)
|
||||
|
||||
func TestReadWorkflow_StringEvent(t *testing.T) {
|
||||
yaml := `
|
||||
name: local-action-docker-url
|
||||
on: push
|
||||
|
||||
jobs:
|
||||
test:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: ./actions/docker-url
|
||||
`
|
||||
|
||||
workflow, err := ReadWorkflow(strings.NewReader(yaml))
|
||||
assert.NilError(t, err, "read workflow should succeed")
|
||||
|
||||
assert.DeepEqual(t, workflow.On(), []string{"push"})
|
||||
}
|
||||
|
||||
func TestReadWorkflow_ListEvent(t *testing.T) {
|
||||
yaml := `
|
||||
name: local-action-docker-url
|
||||
on: [push, pull_request]
|
||||
|
||||
jobs:
|
||||
test:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: ./actions/docker-url
|
||||
`
|
||||
|
||||
workflow, err := ReadWorkflow(strings.NewReader(yaml))
|
||||
assert.NilError(t, err, "read workflow should succeed")
|
||||
|
||||
assert.DeepEqual(t, workflow.On(), []string{"push", "pull_request"})
|
||||
}
|
||||
|
||||
func TestReadWorkflow_MapEvent(t *testing.T) {
|
||||
yaml := `
|
||||
name: local-action-docker-url
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
pull_request:
|
||||
branches:
|
||||
- master
|
||||
|
||||
jobs:
|
||||
test:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: ./actions/docker-url
|
||||
`
|
||||
|
||||
workflow, err := ReadWorkflow(strings.NewReader(yaml))
|
||||
assert.NilError(t, err, "read workflow should succeed")
|
||||
|
||||
assert.DeepEqual(t, workflow.On(), []string{"push", "pull_request"})
|
||||
}
|
Reference in New Issue
Block a user