diff --git a/pkg/jobparser/jobparser.go b/pkg/jobparser/jobparser.go index 33b900d..08557d3 100644 --- a/pkg/jobparser/jobparser.go +++ b/pkg/jobparser/jobparser.go @@ -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 - }) -} diff --git a/pkg/jobparser/jobparser_test.go b/pkg/jobparser/jobparser_test.go index 6872c29..ec8a980 100644 --- a/pkg/jobparser/jobparser_test.go +++ b/pkg/jobparser/jobparser_test.go @@ -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()) }) diff --git a/pkg/jobparser/model.go b/pkg/jobparser/model.go index 2d312ba..e63048a 100644 --- a/pkg/jobparser/model.go +++ b/pkg/jobparser/model.go @@ -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) } diff --git a/pkg/jobparser/testdata/multiple_jobs.in.yaml b/pkg/jobparser/testdata/multiple_jobs.in.yaml index 3474ce1..266ede8 100644 --- a/pkg/jobparser/testdata/multiple_jobs.in.yaml +++ b/pkg/jobparser/testdata/multiple_jobs.in.yaml @@ -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 \ No newline at end of file + - run: uname -a && go version + aaa: + runs-on: linux + steps: + - run: uname -a && go version diff --git a/pkg/jobparser/testdata/multiple_jobs.out.yaml b/pkg/jobparser/testdata/multiple_jobs.out.yaml index 2852d9d..ea22350 100644 --- a/pkg/jobparser/testdata/multiple_jobs.out.yaml +++ b/pkg/jobparser/testdata/multiple_jobs.out.yaml @@ -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