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:
Jason Song 2023-03-28 11:38:40 +08:00
parent 568f053723
commit 342ad6a51a
5 changed files with 90 additions and 26 deletions

View file

@ -36,7 +36,12 @@ func Parse(content []byte, options ...ParseOption) ([]*SingleWorkflow, error) {
}
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)) {
job := job.Clone()
if job.Name == "" {
@ -50,16 +55,18 @@ func Parse(content []byte, options ...ParseOption) ([]*SingleWorkflow, error) {
runsOn[i] = evaluator.Interpolate(v)
}
job.RawRunsOn = encodeRunsOn(runsOn)
ret = append(ret, &SingleWorkflow{
swf := &SingleWorkflow{
Name: workflow.Name,
RawOn: workflow.RawOn,
Env: workflow.Env,
Jobs: map[string]*Job{id: job},
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
}
@ -134,19 +141,3 @@ func matrixName(m map[string]interface{}) string {
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
})
}

View file

@ -57,7 +57,10 @@ func TestParse(t *testing.T) {
}
encoder := yaml.NewEncoder(builder)
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())
})

View file

@ -12,17 +12,63 @@ type SingleWorkflow struct {
Name string `yaml:"name,omitempty"`
RawOn yaml.Node `yaml:"on,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"`
}
func (w *SingleWorkflow) Job() (string, *Job) {
for k, v := range w.Jobs {
return k, v
ids, jobs, _ := w.jobs()
if len(ids) >= 1 {
return ids[0], jobs[0]
}
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) {
return yaml.Marshal(w)
}

View file

@ -1,5 +1,9 @@
name: test
jobs:
zzz:
runs-on: linux
steps:
- run: echo zzz
job1:
runs-on: linux
steps:
@ -11,4 +15,8 @@ jobs:
job3:
runs-on: linux
steps:
- run: uname -a && go version
- run: uname -a && go version
aaa:
runs-on: linux
steps:
- run: uname -a && go version

View file

@ -1,4 +1,12 @@
name: test
jobs:
zzz:
name: zzz
runs-on: linux
steps:
- run: echo zzz
---
name: test
jobs:
job1:
name: job1
@ -21,3 +29,11 @@ jobs:
runs-on: linux
steps:
- run: uname -a && go version
---
name: test
jobs:
aaa:
name: aaa
runs-on: linux
steps:
- run: uname -a && go version