Keep the order of jobs in the workflow file when parsing ()

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