Keep the order of jobs in the workflow file when parsing (#33)
Keep the order of jobs in the workflow file when parsing, and it will make it possible for Gitea to show jobs in the original order on UI. Reviewed-on: https://gitea.com/gitea/act/pulls/33 Reviewed-by: Lunny Xiao <xiaolunwen@gmail.com>
This commit is contained in:
parent
568f053723
commit
342ad6a51a
5 changed files with 90 additions and 26 deletions
|
@ -36,7 +36,12 @@ func Parse(content []byte, options ...ParseOption) ([]*SingleWorkflow, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
var ret []*SingleWorkflow
|
var ret []*SingleWorkflow
|
||||||
for id, job := range workflow.Jobs {
|
ids, jobs, err := workflow.jobs()
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("invalid jobs: %w", err)
|
||||||
|
}
|
||||||
|
for i, id := range ids {
|
||||||
|
job := jobs[i]
|
||||||
for _, matrix := range getMatrixes(origin.GetJob(id)) {
|
for _, matrix := range getMatrixes(origin.GetJob(id)) {
|
||||||
job := job.Clone()
|
job := job.Clone()
|
||||||
if job.Name == "" {
|
if job.Name == "" {
|
||||||
|
@ -50,16 +55,18 @@ func Parse(content []byte, options ...ParseOption) ([]*SingleWorkflow, error) {
|
||||||
runsOn[i] = evaluator.Interpolate(v)
|
runsOn[i] = evaluator.Interpolate(v)
|
||||||
}
|
}
|
||||||
job.RawRunsOn = encodeRunsOn(runsOn)
|
job.RawRunsOn = encodeRunsOn(runsOn)
|
||||||
ret = append(ret, &SingleWorkflow{
|
swf := &SingleWorkflow{
|
||||||
Name: workflow.Name,
|
Name: workflow.Name,
|
||||||
RawOn: workflow.RawOn,
|
RawOn: workflow.RawOn,
|
||||||
Env: workflow.Env,
|
Env: workflow.Env,
|
||||||
Jobs: map[string]*Job{id: job},
|
|
||||||
Defaults: workflow.Defaults,
|
Defaults: workflow.Defaults,
|
||||||
})
|
}
|
||||||
|
if err := swf.setJob(id, job); err != nil {
|
||||||
|
return nil, fmt.Errorf("setJob: %w", err)
|
||||||
|
}
|
||||||
|
ret = append(ret, swf)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
sortWorkflows(ret)
|
|
||||||
return ret, nil
|
return ret, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -134,19 +141,3 @@ func matrixName(m map[string]interface{}) string {
|
||||||
|
|
||||||
return fmt.Sprintf("(%s)", strings.Join(vs, ", "))
|
return fmt.Sprintf("(%s)", strings.Join(vs, ", "))
|
||||||
}
|
}
|
||||||
|
|
||||||
func sortWorkflows(wfs []*SingleWorkflow) {
|
|
||||||
sort.Slice(wfs, func(i, j int) bool {
|
|
||||||
ki := ""
|
|
||||||
for k := range wfs[i].Jobs {
|
|
||||||
ki = k
|
|
||||||
break
|
|
||||||
}
|
|
||||||
kj := ""
|
|
||||||
for k := range wfs[j].Jobs {
|
|
||||||
kj = k
|
|
||||||
break
|
|
||||||
}
|
|
||||||
return ki < kj
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
|
@ -57,7 +57,10 @@ func TestParse(t *testing.T) {
|
||||||
}
|
}
|
||||||
encoder := yaml.NewEncoder(builder)
|
encoder := yaml.NewEncoder(builder)
|
||||||
encoder.SetIndent(2)
|
encoder.SetIndent(2)
|
||||||
_ = encoder.Encode(v)
|
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())
|
assert.Equal(t, string(want), builder.String())
|
||||||
})
|
})
|
||||||
|
|
|
@ -12,17 +12,63 @@ type SingleWorkflow struct {
|
||||||
Name string `yaml:"name,omitempty"`
|
Name string `yaml:"name,omitempty"`
|
||||||
RawOn yaml.Node `yaml:"on,omitempty"`
|
RawOn yaml.Node `yaml:"on,omitempty"`
|
||||||
Env map[string]string `yaml:"env,omitempty"`
|
Env map[string]string `yaml:"env,omitempty"`
|
||||||
Jobs map[string]*Job `yaml:"jobs,omitempty"`
|
RawJobs yaml.Node `yaml:"jobs,omitempty"`
|
||||||
Defaults Defaults `yaml:"defaults,omitempty"`
|
Defaults Defaults `yaml:"defaults,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (w *SingleWorkflow) Job() (string, *Job) {
|
func (w *SingleWorkflow) Job() (string, *Job) {
|
||||||
for k, v := range w.Jobs {
|
ids, jobs, _ := w.jobs()
|
||||||
return k, v
|
if len(ids) >= 1 {
|
||||||
|
return ids[0], jobs[0]
|
||||||
}
|
}
|
||||||
return "", nil
|
return "", nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (w *SingleWorkflow) jobs() ([]string, []*Job, error) {
|
||||||
|
var ids []string
|
||||||
|
var jobs []*Job
|
||||||
|
expectKey := true
|
||||||
|
for _, item := range w.RawJobs.Content {
|
||||||
|
if expectKey {
|
||||||
|
if item.Kind != yaml.ScalarNode {
|
||||||
|
return nil, nil, fmt.Errorf("invalid job id: %v", item.Value)
|
||||||
|
}
|
||||||
|
ids = append(ids, item.Value)
|
||||||
|
expectKey = false
|
||||||
|
} else {
|
||||||
|
job := &Job{}
|
||||||
|
if err := item.Decode(job); err != nil {
|
||||||
|
return nil, nil, fmt.Errorf("yaml.Unmarshal: %w", err)
|
||||||
|
}
|
||||||
|
jobs = append(jobs, job)
|
||||||
|
expectKey = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if len(ids) != len(jobs) {
|
||||||
|
return nil, nil, fmt.Errorf("invalid jobs: %v", w.RawJobs.Value)
|
||||||
|
}
|
||||||
|
return ids, jobs, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (w *SingleWorkflow) setJob(id string, job *Job) error {
|
||||||
|
m := map[string]*Job{
|
||||||
|
id: job,
|
||||||
|
}
|
||||||
|
out, err := yaml.Marshal(m)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
node := yaml.Node{}
|
||||||
|
if err := yaml.Unmarshal(out, &node); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if len(node.Content) != 1 || node.Content[0].Kind != yaml.MappingNode {
|
||||||
|
return fmt.Errorf("can not set job: %q", out)
|
||||||
|
}
|
||||||
|
w.RawJobs = *node.Content[0]
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
func (w *SingleWorkflow) Marshal() ([]byte, error) {
|
func (w *SingleWorkflow) Marshal() ([]byte, error) {
|
||||||
return yaml.Marshal(w)
|
return yaml.Marshal(w)
|
||||||
}
|
}
|
||||||
|
|
8
pkg/jobparser/testdata/multiple_jobs.in.yaml
vendored
8
pkg/jobparser/testdata/multiple_jobs.in.yaml
vendored
|
@ -1,5 +1,9 @@
|
||||||
name: test
|
name: test
|
||||||
jobs:
|
jobs:
|
||||||
|
zzz:
|
||||||
|
runs-on: linux
|
||||||
|
steps:
|
||||||
|
- run: echo zzz
|
||||||
job1:
|
job1:
|
||||||
runs-on: linux
|
runs-on: linux
|
||||||
steps:
|
steps:
|
||||||
|
@ -12,3 +16,7 @@ jobs:
|
||||||
runs-on: linux
|
runs-on: linux
|
||||||
steps:
|
steps:
|
||||||
- run: uname -a && go version
|
- run: uname -a && go version
|
||||||
|
aaa:
|
||||||
|
runs-on: linux
|
||||||
|
steps:
|
||||||
|
- run: uname -a && go version
|
||||||
|
|
16
pkg/jobparser/testdata/multiple_jobs.out.yaml
vendored
16
pkg/jobparser/testdata/multiple_jobs.out.yaml
vendored
|
@ -1,4 +1,12 @@
|
||||||
name: test
|
name: test
|
||||||
|
jobs:
|
||||||
|
zzz:
|
||||||
|
name: zzz
|
||||||
|
runs-on: linux
|
||||||
|
steps:
|
||||||
|
- run: echo zzz
|
||||||
|
---
|
||||||
|
name: test
|
||||||
jobs:
|
jobs:
|
||||||
job1:
|
job1:
|
||||||
name: job1
|
name: job1
|
||||||
|
@ -21,3 +29,11 @@ jobs:
|
||||||
runs-on: linux
|
runs-on: linux
|
||||||
steps:
|
steps:
|
||||||
- run: uname -a && go version
|
- run: uname -a && go version
|
||||||
|
---
|
||||||
|
name: test
|
||||||
|
jobs:
|
||||||
|
aaa:
|
||||||
|
name: aaa
|
||||||
|
runs-on: linux
|
||||||
|
steps:
|
||||||
|
- run: uname -a && go version
|
||||||
|
|
Loading…
Reference in a new issue