Skip to content

feat: support to convert YAML files with blob pattern #4

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Dec 13, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
51 changes: 43 additions & 8 deletions cmd/convert.go
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
package cmd

import (
"bytes"
"github.com/linuxsuren/github-action-workflow/pkg"
"github.com/spf13/cobra"
"golang.org/x/exp/maps"
"gopkg.in/yaml.v2"
"os"
"path/filepath"
"strings"
)

Expand All @@ -26,14 +28,50 @@ func newConvertCmd() (c *cobra.Command) {
}

func (o *convertOption) runE(cmd *cobra.Command, args []string) (err error) {
gh := &pkg.Workflow{}
var data []byte
if data, err = os.ReadFile(args[0]); err == nil {
if err = yaml.Unmarshal(data, gh); err != nil {
var result string
if result, err = o.convertWorkflowsFromFilePath(args[0]); err == nil {
cmd.Println(result)
}
return
}

func (o *convertOption) convertWorkflowsFromFilePath(targetPath string) (result string, err error) {
var ghs []*pkg.Workflow
var files []string
if files, err = filepath.Glob(targetPath); err == nil {
for _, file := range files {
var data []byte
if data, err = os.ReadFile(file); err == nil {
gh := &pkg.Workflow{}
if err = yaml.Unmarshal(data, gh); err == nil {
ghs = append(ghs, gh)
continue
}
}
return
}
result, err = o.convertWorkflows(ghs)
}
return
}

func (o *convertOption) convertWorkflows(ghs []*pkg.Workflow) (output string, err error) {
buf := bytes.Buffer{}

var result string
for i := range ghs {
if result, err = o.convert(ghs[i]); err != nil {
return
}

buf.WriteString("\n---\n")
buf.WriteString(strings.TrimSpace(result))
}
output = buf.String()
return
}

func (o *convertOption) convert(gh *pkg.Workflow) (output string, err error) {
for i, job := range gh.Jobs {
for j, step := range job.Steps {
if step.Env == nil {
Expand All @@ -44,10 +82,7 @@ func (o *convertOption) runE(cmd *cobra.Command, args []string) (err error) {
}
}

var result string
if result, err = gh.ConvertToArgoWorkflow(); err == nil {
cmd.Println(strings.TrimSpace(result))
}
output, err = gh.ConvertToArgoWorkflow()
return
}

Expand Down
261 changes: 261 additions & 0 deletions cmd/convert_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,261 @@
package cmd

import (
"bytes"
"fmt"
"github.com/linuxsuren/github-action-workflow/pkg"
"github.com/spf13/cobra"
"github.com/stretchr/testify/assert"
"os"
"testing"
)

func TestCmdConvert(t *testing.T) {
command := newConvertCmd()
assert.Equal(t, "convert", command.Use)
}

func Test_convertOption_convert(t *testing.T) {
type fields struct {
env map[string]string
}
type args struct {
gh *pkg.Workflow
}
tests := []struct {
name string
fields fields
args args
wantOutput string
wantErr bool
}{{
name: "simple",
args: args{
gh: &pkg.Workflow{
Name: "simple",
Jobs: map[string]pkg.Job{
"simple": {
Name: "test",
Steps: []pkg.Step{{
Name: "test",
Run: "echo 1",
}},
},
}},
},
wantOutput: "data/one-workflow.yaml",
}, {
name: "workflow with env",
args: args{
gh: &pkg.Workflow{
Name: "simple",
Jobs: map[string]pkg.Job{
"simple": {
Name: "test",
Steps: []pkg.Step{{
Name: "test",
Run: "echo 1",
Env: map[string]string{},
}},
},
}},
},
fields: fields{env: map[string]string{"key": "value"}},
wantOutput: "data/one-workflow-env.yaml",
}}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
o := &convertOption{
env: tt.fields.env,
}
gotOutput, err := o.convert(tt.args.gh)
if (err != nil) != tt.wantErr {
t.Errorf("convert() error = %v, wantErr %v", err, tt.wantErr)
return
}
if data, err := os.ReadFile(tt.wantOutput); err == nil {
tt.wantOutput = string(data)
}
assert.Equal(t, tt.wantOutput, gotOutput)
})
}
}

func Test_convertOption_convertWorkflows(t *testing.T) {
type fields struct {
env map[string]string
}
type args struct {
ghs []*pkg.Workflow
}
tests := []struct {
name string
fields fields
args args
wantOutput string
wantErr assert.ErrorAssertionFunc
}{{
name: "two workflows",
args: args{
ghs: []*pkg.Workflow{{
Name: "simple",
Jobs: map[string]pkg.Job{
"simple": {
Name: "test",
Steps: []pkg.Step{{
Name: "test",
Run: "echo 1",
Env: map[string]string{},
}},
},
}}, {
Name: "simple",
Jobs: map[string]pkg.Job{
"simple": {
Name: "test",
Steps: []pkg.Step{{
Name: "test",
Run: "echo 1",
Env: map[string]string{},
}},
},
}}},
},
wantOutput: "data/combine-workflow.yaml",
wantErr: func(t assert.TestingT, err error, i ...interface{}) bool {
return true
},
}}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
o := &convertOption{
env: tt.fields.env,
}
gotOutput, err := o.convertWorkflows(tt.args.ghs)
if !tt.wantErr(t, err, fmt.Sprintf("convertWorkflows(%v)", tt.args.ghs)) {
return
}
if data, err := os.ReadFile(tt.wantOutput); err == nil {
tt.wantOutput = string(data)
}
assert.Equal(t, tt.wantOutput, gotOutput)
})
}
}

func Test_convertOption_convertWorkflowsFromFilePath(t *testing.T) {
type fields struct {
env map[string]string
}
type args struct {
targetPath string
}
tests := []struct {
name string
fields fields
args args
wantResult string
wantErr assert.ErrorAssertionFunc
}{{
name: "one github workflow",
args: args{targetPath: "data/github-workflow-*.yaml"},
wantResult: simpleWorkflow,
wantErr: func(t assert.TestingT, err error, i ...interface{}) bool {
assert.Nil(t, err)
return true
},
}}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
o := &convertOption{
env: tt.fields.env,
}
gotResult, err := o.convertWorkflowsFromFilePath(tt.args.targetPath)
if !tt.wantErr(t, err, fmt.Sprintf("convertWorkflowsFromFilePath(%v)", tt.args.targetPath)) {
return
}
assert.Equalf(t, tt.wantResult, gotResult, "convertWorkflowsFromFilePath(%v)", tt.args.targetPath)
})
}
}

const simpleWorkflow = `
---
apiVersion: argoproj.io/v1alpha1
kind: WorkflowTemplate
metadata:
name: build
spec:
entrypoint: main
volumeClaimTemplates:
- metadata:
name: work
spec:
accessModes: ["ReadWriteOnce"]
resources:
requests:
storage: 64Mi

templates:
- name: main
dag:
tasks:
- name: test
template: test
- name: test
script:
image: alpine
command: [sh]
source: |
go test ./... -coverprofile coverage.out
volumeMounts:
- mountPath: /work
name: work
workingDir: /work`

func Test_convertOption_runE(t *testing.T) {
type fields struct {
env map[string]string
}
type args struct {
cmd *cobra.Command
args []string
}
tests := []struct {
name string
fields fields
args args
prepare func(c *cobra.Command) *bytes.Buffer
check func(t assert.TestingT, buf *bytes.Buffer)
wantErr assert.ErrorAssertionFunc
}{{
name: "simple",
args: args{
cmd: &cobra.Command{},
args: []string{"data/github-workflow-*.yaml"},
},
prepare: func(c *cobra.Command) *bytes.Buffer {
buf := bytes.Buffer{}
c.SetOut(&buf)
return &buf
},
check: func(t assert.TestingT, buf *bytes.Buffer) {
assert.Equal(t, simpleWorkflow+"\n", buf.String())
},
wantErr: func(t assert.TestingT, err error, i ...interface{}) bool {
assert.Nil(t, err)
return true
},
}}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
o := &convertOption{
env: tt.fields.env,
}
buf := tt.prepare(tt.args.cmd)
err := o.runE(tt.args.cmd, tt.args.args)
tt.check(t, buf)
tt.wantErr(t, err, fmt.Sprintf("runE(%v, %v)", tt.args.cmd, tt.args.args))
})
}
}
Loading