8000 fix(api): workflow as code improvements (#3423) · ovh/cds@4d80334 · GitHub
[go: up one dir, main page]
More Web Proxy on the site http://driver.im/
Skip to content

Commit 4d80334

Browse files
authored
fix(api): workflow as code improvements (#3423)
* Since a hook is mandatory for workflow as code, do not export it * Do not export default VCS payload closes #3239
1 parent dad6098 commit 4d80334

17 files changed

+211
-46
lines changed

cli/cdsctl/workflow_export.go

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,11 @@ package main
22

33
import (
44
"fmt"
5+
"net/http"
56
"reflect"
67

78
"github.com/ovh/cds/cli"
9+
"github.com/ovh/cds/sdk/cdsclient"
810
)
911

1012
var workflowExportCmd = cli.Command{
@@ -31,7 +33,24 @@ var workflowExportCmd = cli.Command{
3133
}
3234

3335
func workflowExportRun(c cli.Values) error {
34-
btes, err := client.WorkflowExport(c.GetString(_ProjectKey), c.GetString(_WorkflowName), c.GetBool("with-permissions"), c.GetString("format"))
36+
mods := []cdsclient.RequestModifier{
37+
func(r *http.Request) {
38+
q := r.URL.Query()
39+
q.Set("format", c.GetString("format"))
40+
r.URL.RawQuery = q.Encode()
41+
},
42+
}
43+
if c.GetBool("with-permissions") {
44+
mods = append(mods,
45+
func(r *http.Request) {
46+
q := r.URL.Query()
47+
q.Set("withPermissions", "true")
48+
r.URL.RawQuery = q.Encode()
49+
},
50+
)
51+
}
52+
53+
btes, err := client.WorkflowExport(c.GetString(_ProjectKey), c.GetString(_WorkflowName), mods...)
3554
if err != nil {
3655
return err
3756
}

cli/cdsctl/workflow_pull.go

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,14 @@ import (
44
"archive/tar"
55
"fmt"
66
"io"
7+
"net/http"
78
"os"
89
"path/filepath"
910
"reflect"
1011
"strings"
1112

1213
"github.com/ovh/cds/cli"
14+
"github.com/ovh/cds/sdk/cdsclient"
1315
)
1416

1517
var workflowPullCmd = cli.Command{
@@ -57,7 +59,18 @@ func workflowPullRun(c cli.Values) error {
5759
return fmt.Errorf("Unable to create directory %s: %v", c.GetString("output-dir"), err)
5860
}
5961

60-
tr, err := client.WorkflowPull(c.GetString(_ProjectKey), c.GetString(_WorkflowName), c.GetBool("with-permissions"))
62+
mods := []cdsclient.RequestModifier{}
63+
if c.GetBool("with-permissions") {
64+
mods = append(mods,
65+
func(r *http.Request) {
66+
q := r.URL.Query()
67+
q.Set("withPermissions", "true")
68+
r.URL.RawQuery = q.Encode()
69+
},
70+
)
71+
}
72+
73+
tr, err := client.WorkflowPull(c.GetString(_ProjectKey), c.GetString(_WorkflowName), mods...)
6174
if err != nil {
6275
return err
6376
}

engine/api/workflow/audit.go

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ func (a addWorkflowAudit) Compute(db gorp.SqlExecutor, e sdk.Event) error {
6363
}
6464

6565
buffer := bytes.NewBufferString("")
66-
_, errE := exportWorkflow(wEvent.Workflow, exportentities.FormatYAML, false, buffer)
66+
_, errE := exportWorkflow(wEvent.Workflow, exportentities.FormatYAML, buffer)
6767
if errE != nil {
6868
return sdk.WrapError(errE, "addWorkflowAudit.Compute> Unable to export workflow")
6969
}
@@ -88,12 +88,12 @@ func (u updateWorkflowAudit) Compute(db gorp.SqlExecutor, e sdk.Event) error {
8888
}
8989

9090
oldWorkflowBuffer := bytes.NewBufferString("")
91-
_, errE := exportWorkflow(wEvent.OldWorkflow, exportentities.FormatYAML, false, oldWorkflowBuffer)
91+
_, errE := exportWorkflow(wEvent.OldWorkflow, exportentities.FormatYAML, oldWorkflowBuffer)
9292
if errE != nil {
9393
return sdk.WrapError(errE, "updateWorkflowAudit.Compute> Unable to export workflow")
9494
}
9595
newWorkflowBuffer := bytes.NewBufferString("")
96-
_, errN := exportWorkflow(wEvent.NewWorkflow, exportentities.FormatYAML, false, newWorkflowBuffer)
96+
_, errN := exportWorkflow(wEvent.NewWorkflow, exportentities.FormatYAML, newWorkflowBuffer)
9797
if errN != nil {
9898
return sdk.WrapError(errN, "updateWorkflowAudit.Compute> Unable to export workflow")
9999
}
@@ -119,7 +119,7 @@ func (d deleteWorkflowAudit) Compute(db gorp.SqlExecutor, e sdk.Event) error {
119119
}
120120

121121
oldWorkflowBuffer := bytes.NewBufferString("")
122-
_, errE := exportWorkflow(wEvent.Workflow, exportentities.FormatYAML, false, oldWorkflowBuffer)
122+
_, errE := exportWorkflow(wEvent.Workflow, exportentities.FormatYAML, oldWorkflowBuffer)
123123
if errE != nil {
124124
return sdk.WrapError(errE, "deleteWorkflowAudit.Compute> Unable to export workflow")
125125
}

engine/api/workflow/dao.go

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1040,6 +1040,22 @@ func Push(ctx context.Context, db *gorp.DbMap, store cache.Store, proj *sdk.Proj
10401040
dryRun = opts.DryRun
10411041
}
10421042

1043+
// In workflow as code context, if we only have the repowebhook, we skip it
1044+
// because it will be automatically recreated later with the proper configuration
1045+
if opts != nil && opts.FromRepository != "" {
1046+
if len(wrkflw.Workflow) == 0 {
1047+
if len(wrkflw.PipelineHooks) == 1 && wrkflw.PipelineHooks[0].Model == sdk.RepositoryWebHookModelName {
1048+
wrkflw.PipelineHooks = nil
1049+
}
1050+
} else {
1051+
for node, hooks := range wrkflw.Hooks {
1052+
if len(hooks) == 1 && hooks[0].Model == sdk.RepositoryWebHookModelName {
1053+
wrkflw.Hooks[node] = nil
1054+
}
1055+
}
1056+
}
1057+
}
1058+
10431059
wf, msgList, err := ParseAndImport(ctx, tx, store, proj, &wrkflw, u, ImportOptions{DryRun: dryRun, Force: true})
10441060
if err != nil {
10451061
log.Error("Push> Unable to import workflow: %v", err)

engine/api/workflow/dao_node_run_vulnerability.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -205,6 +205,7 @@ func loadLatestRunVulnerabilityReport(db gorp.SqlExecutor, nr *sdk.WorkflowNodeR
205205
return dbReport.Report.Summary, nil
206206
}
207207

208+
// InsertVulnerabilityReport inserts vulnerability report
208209
func InsertVulnerabilityReport(db gorp.SqlExecutor, report sdk.WorkflowNodeRunVulnerabilityReport) error {
209210
dbReport := dbNodeRunVulenrabilitiesReport(report)
210211
if err := db.Insert(&dbReport); err != nil {

engine/api/workflow/dao_test.go

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,7 @@ func TestInsertSimpleWorkflowAndExport(t *testing.T) {
8080
test.NoError(t, err)
8181
assert.Equal(t, 1, len(ws))
8282

83-
exp, err := exportentities.NewWorkflow(*w1, false)
83+
exp, err := exportentities.NewWorkflow(*w1)
8484
test.NoError(t, err)
8585
btes, err := exportentities.Marshal(exp, exportentities.FormatYAML)
8686
test.NoError(t, err)
@@ -311,7 +311,7 @@ func TestInsertComplexeWorkflowAndExport(t *testing.T) {
311311

312312
assertEqualNode(t, w.Root, w1.Root)
313313

314-
exp, err := exportentities.NewWorkflow(w, false)
314+
exp, err := exportentities.NewWorkflow(w)
315315
test.NoError(t, err)
316316
btes, err := exportentities.Marshal(exp, exportentities.FormatYAML)
317317
test.NoError(t, err)
@@ -789,7 +789,7 @@ func TestInsertComplexeWorkflowWithJoinsAndExport(t *testing.T) {
789789
}, w1.Joins[0].SourceNodeIDs)
790790
assert.Equal(t, pip5.Name, w.Joins[0].Triggers[0].WorkflowDestNode.PipelineName)
791791

792-
exp, err := exportentities.NewWorkflow(*w1, false)
792+
exp, err := exportentities.NewWorkflow(*w1)
793793
test.NoError(t, err)
794794
btes, err := exportentities.Marshal(exp, exportentities.FormatYAML)
795795
test.NoError(t, err)
@@ -1250,7 +1250,7 @@ func TestInsertSimpleWorkflowWithHookAndExport(t *testing.T) {
12501250
assert.Len(t, w.Root.Hooks, 1)
12511251
t.Log(w.Root.Hooks)
12521252

1253-
exp, err := exportentities.NewWorkflow(*w1, false)
1253+
exp, err := exportentities.NewWorkflow(*w1)
12541254
test.NoError(t, err)
12551255
btes, err := exportentities.Marshal(exp, exportentities.FormatYAML)
12561256
test.NoError(t, err)

engine/api/workflow/hook.go

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -295,8 +295,17 @@ func mergeAndDiffHook(oldHooks map[string]sdk.WorkflowNodeHook, newHooks map[str
295295

296296
// DefaultPayload returns the default payload for the workflow root
297297
func DefaultPayload(ctx context.Context, db gorp.SqlExecutor, store cache.Store, p *sdk.Project, u *sdk.User, wf *sdk.Workflow) (interface{}, error) {
298+
if wf.Root.Context == nil {
299+
return nil, nil
300+
}
301+
302+
if wf.Root.Context.Application == nil {
303+
return wf.Root.Context.DefaultPayload, nil
304+
}
305+
298306
var defaultPayload interface{}
299-
if wf.Root.Context == nil || wf.Root.Context.Application == nil || wf.Root.Context.Application.ID == 0 {
307+
// Load application if not available
308+
if wf.Root.Context != nil && wf.Root.Context.Application == nil && wf.Root.Context.ApplicationID != 0 {
300309
app, errLa := application.LoadByID(db, store, wf.Root.Context.ApplicationID, u)
301310
if errLa != nil {
302311
return wf.Root.Context.DefaultPayload, sdk.WrapError(errLa, "DefaultPayload> unable to load application by id %d", wf.Root.Context.ApplicationID)
@@ -328,10 +337,14 @@ func DefaultPayload(ctx context.Context, db gorp.SqlExecutor, store cache.Store,
328337

329338
defaultPayload = wf.Root.Context.DefaultPayload
330339
if !wf.Root.Context.HasDefaultPayload() {
331-
defaultPayload = sdk.WorkflowNodeContextDefaultPayloadVCS{
340+
structuredDefaultPayload := sdk.WorkflowNodeContextDefaultPayloadVCS{
332341
GitBranch: defaultBranch,
333342
GitRepository: wf.Root.Context.Application.RepositoryFullname,
334343
}
344+
defaultPayloadBtes, _ := json.Marshal(structuredDefaultPayload)
345+
if err := json.Unmarshal(defaultPayloadBtes, &defaultPayload); err != nil {
346+
return nil, err
347+
}
335348
} else if defaultPayloadMap, err := wf.Root.Context.DefaultPayloadToMap(); err == nil && defaultPayloadMap["git.branch"] == "" {
336349
defaultPayloadMap["git.branch"] = defaultBranch
337350
defaultPayloadMap["git.repository"] = wf.Root.Context.Application.RepositoryFullname

engine/api/workflow/workflow_exporter.go

Lines changed: 19 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import (
66
"context"
77
"fmt"
88
"io"
9+
"reflect"
910

1011
"github.com/go-gorp/gorp"
1112

@@ -19,7 +20,7 @@ import (
1920
)
2021

2122
// Export a workflow
22-
func Export(ctx context.Context, db gorp.SqlExecutor, cache cache.Store, proj *sdk.Project, name string, f exportentities.Format, withPermissions bool, u *sdk.User, w io.Writer) (int, error) {
23+
func Export(ctx context.Context, db gorp.SqlExecutor, cache cache.Store, proj *sdk.Project, name string, f exportentities.Format, u *sdk.User, w io.Writer, opts ...exportentities.WorkflowOptions) (int, error) {
2324
ctx, end := observability.Span(ctx, "workflow.Export")
2425
defer end()
2526

@@ -28,11 +29,16 @@ func Export(ctx context.Context, db gorp.SqlExecutor, cache cache.Store, proj *s
2829
return 0, sdk.WrapError(errload, "workflow.Export> Cannot load workflow %s", name)
2930
}
3031

31-
return exportWorkflow(*wf, f, withPermissions, w)
32+
// If repo is from as-code do not export WorkflowSkipIfOnlyOneRepoWebhook
33+
if wf.FromRepository != "" {
34+
opts = append(opts, exportentities.WorkflowSkipIfOnlyOneRepoWebhook)
35+
}
36+
37+
return exportWorkflow(*wf, f, w, opts...)
3238
}
3339

34-
func exportWorkflow(wf sdk.Workflow, f exportentities.Format, withPermissions bool, w io.Writer) (int, error) {
35-
e, err := exportentities.NewWorkflow(wf, withPermissions)
40+
func exportWorkflow(wf sdk.Workflow, f exportentities.Format, w io.Writer, opts ...exportentities.WorkflowOptions) (int, error) {
41+
e, err := exportentities.NewWorkflow(wf, opts...)
3642
if err != nil {
3743
return 0, err
3844
}
@@ -52,7 +58,7 @@ func exportWorkflow(wf sdk.Workflow, f exportentities.Format, withPermissions bo
5258
}
5359

5460
// Pull a workflow with all it dependencies; it writes a tar buffer in the writer
55-
func Pull(ctx context.Context, db gorp.SqlExecutor, cache cache.Store, proj *sdk.Project, name string, f exportentities.Format, withPermissions bool, encryptFunc sdk.EncryptFunc, u *sdk.User, w io.Writer) error {
61+
func Pull(ctx context.Context, db gorp.SqlExecutor, cache cache.Store, proj *sdk.Project, name string, f exportentities.Format, encryptFunc sdk.EncryptFunc, u *sdk.User, w io.Writer, opts ...exportentities.WorkflowOptions) error {
5662
ctx, end := observability.Span(ctx, "workflow.Pull")
5763
defer end()
5864

@@ -99,7 +105,7 @@ func Pull(ctx context.Context, db gorp.SqlExecutor, cache cache.Store, proj *sdk
99105
tw := tar.NewWriter(w)
100106

101107
buffw := new(bytes.Buffer)
102-
size, errw := exportWorkflow(*wf, f, withPermissions, buffw)
108+
size, errw := exportWorkflow(*wf, f, buffw, opts...)
103109
if errw != nil {
104110
tw.Close()
105111
return sdk.WrapError(errw, "workflow.Pull> Unable to export workflow")
@@ -119,6 +125,13 @@ func Pull(ctx context.Context, db gorp.SqlExecutor, cache cache.Store, proj *sdk
119125
return sdk.WrapError(err, "workflow.Pull> Unable to copy workflow buffer")
120126
}
121127

128+
var withPermissions bool
129+
for _, f := range opts {
130+
if reflect.ValueOf(f).Pointer() == reflect.ValueOf(exportentities.WorkflowWithPermissions).Pointer() {
131+
withPermissions = true
132+
}
133+
}
134+
122135
for _, a := range apps {
123136
buff := new(bytes.Buffer)
124137
size, err := application.ExportApplication(db, a, f, withPermissions, encryptFunc, buff)

engine/api/workflow/workflow_exporter_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -123,7 +123,7 @@ func TestPull(t *testing.T) {
123123
test.Equal(t, w.PurgeTags, w1.PurgeTags)
124124

125125
buff := new(bytes.Buffer)
126-
test.NoError(t, workflow.Pull(context.TODO(), db, cache, proj, w1.Name, exportentities.FormatYAML, false, project.EncryptWithBuiltinKey, u, buff))
126+
test.NoError(t, workflow.Pull(context.TODO(), db, cache, proj, w1.Name, exportentities.FormatYAML, project.EncryptWithBuiltinKey, u, buff))
127127

128128
// Open the tar archive for reading.
129129
r := bytes.NewReader(buff.Bytes())

engine/api/workflow/workflow_importer.go

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,15 @@ func Import(ctx context.Context, db gorp.SqlExecutor, store cache.Store, proj *s
117117
return sdk.WrapError(errE, "Import> Cannot check if workflow exists")
118118
}
119119

120+
//Manage default payload
121+
var err error
122+
if w.Root.Context == nil {
123+
w.Root.Context = &sdk.WorkflowNodeContext{}
124+
}
125+
if w.Root.Context.DefaultPayload, err = DefaultPayload(ctx, db, store, proj, u, w); err != nil {
126+
log.Warning("workflow.Import> Cannot set default payload : %v", err)
127+
}
128+
120129
if !doUpdate {
121130
if err := Insert(db, store, w, proj, u); err != nil {
122131
return sdk.WrapError(err, "Import> Unable to insert workflow")

0 commit comments

Comments
 (0)
0