Skip to content

Commit

Permalink
feat: support retry event binding (#14)
Browse files Browse the repository at this point in the history
  • Loading branch information
LinuxSuRen authored Jan 16, 2023
1 parent 4594789 commit 8adac60
Show file tree
Hide file tree
Showing 29 changed files with 439 additions and 309 deletions.
2 changes: 2 additions & 0 deletions .github/pre-commit
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
#!/bin/sh
make pre-commit
3 changes: 2 additions & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@ build:
test:
go test ./...
pre-commit: test build

install-pre-commit:
cp .github/pre-commit .git/hooks/pre-commit
copy: build
cp bin/gaw /usr/local/bin
test-gh:
Expand Down
3 changes: 2 additions & 1 deletion cmd/convert_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"bytes"
"fmt"
"os"
"strings"
"testing"

"github.com/linuxsuren/github-action-workflow/pkg"
Expand Down Expand Up @@ -284,7 +285,7 @@ func Test_convertOption_preRunE(t *testing.T) {
}{{
name: "simple",
check: func(t *testing.T, opt *convertOption) {
assert.Contains(t, opt.gitRepository, "LinuxSuRen/github-action-workflow")
assert.Contains(t, strings.ToLower(opt.gitRepository), "linuxsuren/github-action-workflow")
},
wantErr: func(t assert.TestingT, err error, i ...interface{}) bool {
assert.Nil(t, err)
Expand Down
237 changes: 16 additions & 221 deletions pkg/argo-workflow.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,10 @@ func (w *Workflow) GetWorkflowBindings() (wfbs []WorkflowEventBinding) {
}

for _, e := range w.GetEvent() {
projectSelector := fmt.Sprintf(`payload.project.path_with_namespace endsWith "%s"`, projectName)

binding := WorkflowEventBinding{
Selector: fmt.Sprintf(`payload.object_kind == "%s" && payload.project.path_with_namespace endsWith "%s"`, e, projectName),
Selector: fmt.Sprintf(`payload.object_kind == "%s" && %s`, e, projectSelector),
Ref: w.Name,
Name: fmt.Sprintf("%s-%s", w.Name, e),
Parameters: map[string]string{},
Expand All @@ -49,6 +51,10 @@ func (w *Workflow) GetWorkflowBindings() (wfbs []WorkflowEventBinding) {
binding.Parameters["branch"] = "payload.object_attributes.source_branch"
binding.Parameters["pr"] = "payload.object_attributes.iid"
binding.Selector = binding.Selector + ` && payload.object_attributes.state == "opened"`
case "retry":
binding.Parameters["branch"] = "payload.object_attributes.source_branch"
binding.Parameters["pr"] = "payload.merge_request.iid"
binding.Selector = fmt.Sprintf(`payload.event_type == "note" && payload.merge_request.state == "opened" && payload.object_attributes.note == "/retry" && %s`, projectSelector)
default:
continue
}
Expand Down Expand Up @@ -145,6 +151,15 @@ fi`, w.GitRepository)
}
}

if len(w.GetWorkflowBindings()) > 0 {
output = output + "\n---\n" + strings.TrimSpace(eventBindingRole)
output = output + "\n---\n" + strings.TrimSpace(eventBindingGitHubServiceAccount)
output = output + "\n---\n" + strings.TrimSpace(eventBindingGitHubRoleBinding)
output = output + "\n---\n" + strings.TrimSpace(eventBindingGitlabServiceAccount)
output = output + "\n---\n" + strings.TrimSpace(eventBindingGitlabRoleBinding)
output = output + "\n---\n" + strings.TrimSpace(eventBindingSecret)
}

// generate cronWorkflow
var schedules []Schedule
schedules, err = w.GetSchedules()
Expand All @@ -167,223 +182,3 @@ type WorkflowEventBinding struct {
Selector string
Parameters map[string]string
}

var argoworkflowEventBinding = `
apiVersion: argoproj.io/v1alpha1
kind: WorkflowEventBinding
metadata:
name: {{.Name}}
spec:
event:
selector: {{.Selector}}
submit:
workflowTemplateRef:
name: {{.Ref}}
{{- if .Parameters}}
arguments:
parameters:
{{- range $key, $val := .Parameters}}
- name: {{$key}}
valueFrom:
event: "{{$val}}"
{{- end}}
{{- end}}
---
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: submit-workflow-template
rules:
- apiGroups:
- argoproj.io
resources:
- workfloweventbindings
verbs:
- list
- apiGroups:
- argoproj.io
resources:
- workflowtemplates
verbs:
- get
- apiGroups:
- argoproj.io
resources:
- workflows
verbs:
- create
---
apiVersion: v1
kind: ServiceAccount
metadata:
name: github.com
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: github.com
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: Role
name: submit-workflow-template
subjects:
- kind: ServiceAccount
name: github.com
namespace: default
---
apiVersion: v1
kind: ServiceAccount
metadata:
name: gitlab.com
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: gitlab.com
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: Role
name: submit-workflow-template
subjects:
- kind: ServiceAccount
name: gitlab.com
namespace: default
---
kind: Secret
apiVersion: v1
metadata:
name: argo-workflows-webhook-clients
stringData:
bitbucket.org: |
type: bitbucket
bitbucketserver: |
type: bitbucketserver
github.com: |
type: github
gitlab.com: |
type: gitlab`

var cronWorkflowTemplate = `
apiVersion: argoproj.io/v1alpha1
kind: CronWorkflow
metadata:
name: {{.Name}}
spec:
schedule: "{{.Cron}}"
concurrencyPolicy: "Replace"
startingDeadlineSeconds: 0
workflowSpec:
entrypoint: main
templates:
- name: main
dag:
tasks:
{{- range $key, $job := .Jobs}}
{{- range $i, $step := $job.Steps}}
{{- if $step.Image}}
- name: {{$step.Name}}
template: {{$step.Name}}
{{- if $step.Depends}}
depends: {{$step.Depends}}
{{- end}}
{{- end}}
{{- end}}
{{- end}}
{{- range $key, $job := .Jobs}}
{{- range $i, $step := $job.Steps}}
{{- if $step.Image}}
- name: {{$step.Name}}
script:
image: {{$step.Image}}
command: [sh]
{{- if $step.Env}}
env:
{{- range $k, $v := $step.Env}}
- name: {{$k}}
value: {{$v}}
{{- end}}
{{- end}}
source: |
{{indent 12 $step.Run}}
{{- end}}
{{- end}}
{{- end}}`

var argoworkflowTemplate = `
apiVersion: argoproj.io/v1alpha1
kind: WorkflowTemplate
metadata:
name: {{.Name}}
spec:
entrypoint: main
arguments:
parameters:
- name: branch
default: master
- name: pr
default: -1
volumeClaimTemplates:
- metadata:
name: work
spec:
accessModes: ["ReadWriteOnce"]
resources:
requests:
storage: 64Mi
{{- if .Concurrency}}
synchronization:
mutex:
name: {{.Concurrency}}
{{- end}}
templates:
- name: main
dag:
tasks:
{{- range $key, $job := .Jobs}}
{{- range $i, $step := $job.Steps}}
{{- if $step.Image}}
- name: {{$step.Name}}
template: {{$step.Name}}
{{- if $step.Depends}}
depends: {{$step.Depends}}
{{- end}}
{{- end}}
{{- end}}
{{- end}}
{{- range $key, $job := .Jobs}}
{{- range $i, $step := $job.Steps}}
{{- if $step.Image}}
- name: {{$step.Name}}
{{- if $step.Secret}}
volumes:
- name: {{$step.Secret}}
secret:
defaultMode: 0400
secretName: {{$step.Secret}}
{{- end}}
script:
image: {{$step.Image}}
command: [sh]
{{- if $step.Env}}
env:
{{- range $k, $v := $step.Env}}
- name: {{$k}}
value: {{$v}}
{{- end}}
{{- end}}
source: |
{{indent 10 $step.Run}}
volumeMounts:
- mountPath: /work
name: work
{{- if $step.Secret}}
- mountPath: /root/.ssh/
name: {{$step.Secret}}
{{- end}}
workingDir: /work
{{- end}}
{{- end}}
{{- end}}
`
26 changes: 15 additions & 11 deletions pkg/argo-workflow_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,24 +16,28 @@ func TestWorkflow_ConvertToArgoWorkflow(t *testing.T) {
wantErr bool
}{{
name: "simple",
githubActions: "data/github-actions.yaml",
argoWorkflows: "data/argo-workflows.yaml",
githubActions: "testdata/github-actions.yaml",
argoWorkflows: "testdata/argo-workflows.yaml",
}, {
name: "with image",
githubActions: "data/github-action-image.yaml",
argoWorkflows: "data/argo-workflows-image.yaml",
githubActions: "testdata/github-action-image.yaml",
argoWorkflows: "testdata/argo-workflows-image.yaml",
}, {
name: "complex event",
githubActions: "data/github-action-complex-event.yaml",
argoWorkflows: "data/argo-workflows-complex-event.yaml",
githubActions: "testdata/github-action-complex-event.yaml",
argoWorkflows: "testdata/argo-workflows-complex-event.yaml",
}, {
name: "with concurrency",
githubActions: "data/github-actions-concurrency.yaml",
argoWorkflows: "data/argo-workflows-concurrency.yaml",
githubActions: "testdata/github-actions-concurrency.yaml",
argoWorkflows: "testdata/argo-workflows-concurrency.yaml",
}, {
name: "with schedule",
githubActions: "data/github-actions-schedule.yaml",
argoWorkflows: "data/argo-workflows-schedule.yaml",
githubActions: "testdata/github-actions-schedule.yaml",
argoWorkflows: "testdata/argo-workflows-schedule.yaml",
}, {
name: "with retry event",
githubActions: "testdata/github-actions-retry-event.yaml",
argoWorkflows: "testdata/argo-workflows-retry-event.yaml",
}}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
Expand All @@ -51,7 +55,7 @@ func TestWorkflow_ConvertToArgoWorkflow(t *testing.T) {

wantData, err := os.ReadFile(tt.argoWorkflows)
assert.Nil(t, err)
assert.Equal(t, string(wantData), gotOutput)
assert.Equalf(t, string(wantData), gotOutput, gotOutput)
})
}

Expand Down
46 changes: 46 additions & 0 deletions pkg/data/cronWorkflow.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@

apiVersion: argoproj.io/v1alpha1
kind: CronWorkflow
metadata:
name: {{.Name}}
spec:
schedule: "{{.Cron}}"
concurrencyPolicy: "Replace"
startingDeadlineSeconds: 0
workflowSpec:
entrypoint: main
templates:
- name: main
dag:
tasks:
{{- range $key, $job := .Jobs}}
{{- range $i, $step := $job.Steps}}
{{- if $step.Image}}
- name: {{$step.Name}}
template: {{$step.Name}}
{{- if $step.Depends}}
depends: {{$step.Depends}}
{{- end}}
{{- end}}
{{- end}}
{{- end}}

{{- range $key, $job := .Jobs}}
{{- range $i, $step := $job.Steps}}
{{- if $step.Image}}
- name: {{$step.Name}}
script:
image: {{$step.Image}}
command: [sh]
{{- if $step.Env}}
env:
{{- range $k, $v := $step.Env}}
- name: {{$k}}
value: {{$v}}
{{- end}}
{{- end}}
source: |
{{indent 12 $step.Run}}
{{- end}}
{{- end}}
{{- end}}
Loading

0 comments on commit 8adac60

Please sign in to comment.