8000 feat(api,ui): init a template from an existing workflow (#3875) · ovh/cds@2617273 · GitHub
[go: up one dir, main page]
More Web Proxy on the site http://driver.im/
Skip to content

Commit 2617273

Browse files
authored
feat(api,ui): init a template from an existing workflow (#3875)
1 parent 0724686 commit 2617273

File tree

19 files changed

+384
-225
lines changed
  • assets/i18n
  • 19 files changed

    +384
    -225
    lines changed

    cli/cdsctl/workflow_as_code.go

    Lines changed: 2 additions & 2 deletions
    Original file line numberDiff line numberDiff line change
    @@ -332,7 +332,7 @@ func workflowInitRun(c cli.Values) error {
    332332
    return fmt.Errorf("Unable to write application file format: %v", err)
    333333
    }
    334334

    335-
    appFilePath := filepath.Join(dotCDS, appName+".app.yml")
    335+
    appFilePath := filepath.Join(dotCDS, fmt.Sprintf(exportentities.PullApplicationName, appName))
    336336
    if err := ioutil.WriteFile(appFilePath, b, os.FileMode(0644)); err != nil {
    337337
    return fmt.Errorf("Unable to write application file: %v", err)
    338338
    }
    @@ -363,7 +363,7 @@ func workflowInitRun(c cli.Values) error {
    363363
    return fmt.Errorf("Unable to write pipeline file format: %v", err)
    364364
    }
    365365

    366-
    pipFilePath := filepath.Join(dotCDS, pipName+".pip.yml")
    366+
    pipFilePath := filepath.Join(dotCDS, fmt.Sprintf(exportentities.PullPipelineName, pipName))
    367367
    if err := ioutil.WriteFile(pipFilePath, b, os.FileMode(0644)); err != nil {
    368368
    return fmt.Errorf("Unable to write application file: %v", err)
    369369
    }

    engine/api/group/dao.go

    Lines changed: 1 addition & 1 deletion
    Original file line numberDiff line numberDiff line change
    @@ -14,7 +14,7 @@ func GetAllByIDs(db gorp.SqlExecutor, ids []int64) ([]sdk.Group, error) {
    1414
    `SELECT * FROM "group" WHERE id = ANY(string_to_array($1, ',')::int[])`,
    1515
    gorpmapping.IDsToQueryString(ids),
    1616
    ); err != nil {
    17-
    return nil, sdk.WrapError(err, "Cannot get groups")
    17+
    return nil, sdk.WrapError(err, "cannot get groups")
    1818
    }
    1919

    2020
    return gs, nil

    engine/api/workflow/as_code.go

    Lines changed: 7 additions & 2 deletions
    Original file line numberDiff line numberDiff line change
    @@ -42,11 +42,16 @@ func UpdateAsCode(ctx context.Context, db *gorp.DbMap, store cache.Store, proj *
    4242
    }
    4343

    4444
    // Export workflow
    45-
    buf := new(bytes.Buffer)
    46-
    if err := Pull(ctx, db, store, proj, wf.Name, exportentities.FormatYAML, encryptFunc, u, buf, exportentities.WorkflowSkipIfOnlyOneRepoWebhook); err != nil {
    45+
    pull, err := Pull(ctx, db, store, proj, wf.Name, exportentities.FormatYAML, encryptFunc, u, exportentities.WorkflowSkipIfOnlyOneRepoWebhook)
    46+
    if err != nil {
    4747
    return nil, sdk.WrapError(err, "cannot pull workflow")
    4848
    }
    4949

    50+
    buf := new(bytes.Buffer)
    51+
    if err := pull.Tar(buf); err != nil {
    52+
    return nil, sdk.WrapError(err, "cannot tar pulled workflow")
    53+
    }
    54+
    5055
    var vcsStrategy = app.RepositoryStrategy
    5156

    5257
    if vcsStrategy.SSHKey != "" {
    Lines changed: 38 additions & 83 deletions
    Original file line numberDiff line numberDiff line change
    @@ -1,10 +1,9 @@
    11
    package workflow
    22

    33
    import (
    4-
    "archive/tar"
    54
    "bytes"
    65
    "context"
    7-
    "fmt"
    6+
    "encoding/base64"
    87
    "io"
    98
    "reflect"
    109

    @@ -19,7 +18,6 @@ import (
    1918
    "github.com/ovh/cds/engine/api/workflowtemplate"
    2019
    "github.com/ovh/cds/sdk"
    2120
    "github.com/ovh/cds/sdk/exportentities"
    22-
    "github.com/ovh/cds/sdk/log"
    2321
    )
    2422

    2523
    // Export a workflow
    @@ -61,29 +59,32 @@ func exportWorkflow(wf sdk.Workflow, f exportentities.Format, w io.Writer, opts
    6159
    }
    6260

    6361
    // Pull a workflow with all it dependencies; it writes a tar buffer in the writer
    64-
    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 {
    62+
    func Pull(ctx context.Context, db gorp.SqlExecutor, cache cache.Store, proj *sdk.Project, name string, f exportentities.Format,
    63+
    encryptFunc sdk.EncryptFunc, u *sdk.User, opts ...exportentities.WorkflowOptions) (exportentities.WorkflowPulled, error) {
    6564
    ctx, end := observability.Span(ctx, "workflow.Pull")
    6665
    defer end()
    6766

    67+
    var wp exportentities.WorkflowPulled
    68+
    6869
    options := LoadOptions{
    6970
    DeepPipeline: true,
    7071
    }
    7172
    wf, errload := Load(ctx, db, cache, proj, name, u, options)
    7273
    if errload != nil {
    73-
    return sdk.WrapError(errload, "Cannot load workflow %s", name)
    74+
    return wp, sdk.WrapError(errload, "cannot load workflow %s", name)
    7475
    }
    7576

    7677
    i, err := workflowtemplate.GetInstanceByWorkflowID(db, wf.ID)
    7778
    if err != nil {
    78-
    return err
    79+
    return wp, err
    7980
    }
    8081
    if i != nil {
    8182
    wf.Template, err = workflowtemplate.GetByID(db, i.WorkflowTemplateID)
    8283
    if err != nil {
    83-
    return err
    84+
    return wp, err
    8485
    }
    8586
    if err := group.AggregateOnWorkflowTemplate(db, wf.Template); err != nil {
    86-
    return err
    87+
    return wp, err
    8788
    }
    8889
    }
    8990

    @@ -96,12 +97,12 @@ func Pull(ctx context.Context, db gorp.SqlExecutor, cache cache.Store, proj *sdk
    9697
    app := &apps[i]
    9798
    vars, errv := application.GetAllVariable(db, proj.Key, app.Name, application.WithClearPassword())
    9899
    if errv != nil {
    99-
    return sdk.WrapError(errv, "Cannot load application variables %s", app.Name)
    100+
    return wp, sdk.WrapError(errv, "cannot load application variables %s", app.Name)
    100101
    }
    101102
    app.Variable = vars
    102103

    103-
    if errk := application.LoadAllDecryptedKeys(db, app); errk != nil {
    104-
    return sdk.WrapError(errk, "Cannot load application keys %s", app.Name)
    104+
    if err := application.LoadAllDecryptedKeys(db, app); err != nil {
    105+
    return wp, sdk.WrapError(err, "cannot load application keys %s", app.Name)
    105106
    }
    106107
    }
    107108

    @@ -110,39 +111,21 @@ func Pull(ctx context.Context, db gorp.SqlExecutor, cache cache.Store, proj *sdk
    110111
    env := &envs[i]
    111112
    vars, errv := environment.GetAllVariable(db, proj.Key, env.Name, environment.WithClearPassword())
    112113
    if errv != nil {
    113-
    return sdk.WrapError(errv, "Cannot load environment variables %s", env.Name)
    114+
    return wp, sdk.WrapError(errv, "cannot load environment variables %s", env.Name)
    114115
    }
    115116
    env.Variable = vars
    116117

    117-
    if errk := environment.LoadAllDecryptedKeys(db, env); errk != nil {
    118-
    return sdk.WrapError(errk, "Cannot load environment keys %s", env.Name)
    118+
    if err := environment.LoadAllDecryptedKeys(db, env); err != nil {
    119+
    return wp, sdk.WrapError(err, "cannot load environment keys %s", env.Name)
    119120
    }
    120121
    }
    121122

    122-
    tw := tar.NewWriter(w)
    123-
    defer func() {
    124-
    if err := tw.Close(); err != nil {
    125-
    log.Error("%v", sdk.WrapError(err, "Unable to close tar writer"))
    126-
    }
    127-
    }()
    128-
    129123
    buffw := new(bytes.Buffer)
    130-
    size, errw := exportWorkflow(*wf, f, buffw, opts...)
    131-
    if errw != nil {
    132-
    return sdk.WrapError(errw, "Unable to export workflow")
    133-
    }
    134-
    135-
    hdr := &tar.Header{
    136-
    Name: fmt.Sprintf("%s.yml", wf.Name),
    137-
    Mode: 0644,
    138-
    Size: int64(size),
    139-
    }
    140-
    if err := tw.WriteHeader(hdr); err != nil {
    141-
    return sdk.WrapError(err, "Unable to write workflow header %+v", hdr)
    142-
    }
    143-
    if _, err := io.Copy(tw, buffw); err != nil {
    144-
    return sdk.WrapError(err, "Unable to copy workflow buffer")
    124+
    if _, err := exportWorkflow(*wf, f, buffw, opts...); err != nil {
    125+
    return wp, sdk.WrapError(err, "unable to export workflow")
    145126
    }
    127+
    wp.Workflow.Name = wf.Name
    128+
    wp.Workflow.Value = base64.StdEncoding.EncodeToString(buffw.Bytes())
    146129

    147130
    var withPermissions bool
    148131
    for _, f := range opts {
    @@ -151,63 +134,35 @@ func Pull(ctx context.Context, db gorp.SqlExecutor, cache cache.Store, proj *sdk
    151134
    }
    152135
    }
    153136

    154-
    for _, a := range apps {
    137+
    wp.Applications = make([]exportentities.WorkflowPulledItem, len(apps))
    138+
    for i, a := range apps {
    155139
    buff := new(bytes.Buffer)
    156-
    size, err := application.ExportApplication(db, a, f, withPermissions, encryptFunc, buff)
    157-
    if err != nil {
    158-
    return sdk.WrapError(err, "Unable to export app %s", a.Name)
    159-
    }
    160-
    hdr := &tar.Header{
    161-
    Name: fmt.Sprintf("%s.app.yml", a.Name),
    162-
    Mode: 0644,
    163-
    Size: int64(size),
    164-
    }
    165-
    if err := tw.WriteHeader(hdr); err != nil {
    166-
    return sdk.WrapError(err, "Unable to write app header %+v", hdr)
    167-
    }
    168-
    if _, err := io.Copy(tw, buff); err != nil {
    169-
    return sdk.WrapError(err, "Unable to copy app buffer")
    140+
    if _, err := application.ExportApplication(db, a, f, withPermissions, encryptFunc, buff); err != nil {
    141+
    return wp, sdk.WrapError(err, "unable to export app %s", a.Name)
    170142
    }
    143+
    wp.Applications[i].Name = a.Name
    144+
    wp.Applications[i].Value = base64.StdEncoding.EncodeToString(buff.Bytes())
    171145
    }
    172146

    173-
    for _, e := range envs {
    147+
    wp.Environments = make([]exportentities.WorkflowPulledItem, len(envs))
    148+
    for i, e := range envs {
    174149
    buff := new(bytes.Buffer)
    175-
    size, err := environment.ExportEnvironment(db, e, f, withPermissions, encryptFunc, buff)
    176-
    if err != nil {
    177-
    return sdk.WrapError(err, "Unable to export env %s", e.Name)
    178-
    }
    179-
    180-
    hdr := &tar.Header{
    181-
    Name: fmt.Sprintf("%s.env.yml", e.Name),
    182-
    Mode: 0644,
    183-
    Size: int64(size),
    184-
    }
    185-
    if err := tw.WriteHeader(hdr); err != nil {
    186-
    return sdk.WrapError(err, "Unable to write env header %+v", hdr)
    187-
    }
    188-
    if _, err := io.Copy(tw, buff); err != nil {
    189-
    return sdk.WrapError(err, "Unable to copy env buffer")
    150+
    if _, err := environment.ExportEnvironment(db, e, f, withPermissions, encryptFunc, buff); err != nil {
    151+
    return wp, sdk.WrapError(err, "unable to export env %s", e.Name)
    190152
    }
    153+
    wp.Environments[i].Name = e.Name
    154+
    wp.Environments[i].Value = base64.StdEncoding.EncodeToString(buff.Bytes())
    191155
    }
    192156

    193-
    for _, p := range pips {
    157+
    wp.Pipelines = make([]exportentities.WorkflowPulledItem, len(pips))
    158+
    for i, p := range pips {
    194159
    buff := new(bytes.Buffer)
    195-
    size, err := pipeline.ExportPipeline(p, f, withPermissions, buff)
    196-
    if err != nil {
    197-
    return sdk.WrapError(err, "Unable to export pipeline %s", p.Name)
    198-
    }
    199-
    hdr := &tar.Header{
    200-
    Name: fmt.Sprintf("%s.pip.yml", p.Name),
    201-
    Mode: 0644,
    202-
    Size: int64(size),
    203-
    }
    204-
    if err := tw.WriteHeader(hdr); err != nil {
    205-
    return sdk.WrapError(err, "Unable to write pipeline header %+v", hdr)
    206-
    }
    207-
    if _, err := io.Copy(tw, buff); err != nil {
    208-
    return sdk.WrapError(err, "Unable to copy pip buffer")
    160+
    if _, err := pipeline.ExportPipeline(p, f, withPermissions, buff); err != nil {
    161+
    return wp, sdk.WrapError(err, "unable to export pipeline %s", p.Name)
    209162
    }
    163+
    wp.Pipelines[i].Name = p.Name
    164+
    wp.Pipelines[i].Value = base64.StdEncoding.EncodeToString(buff.Bytes())
    210165
    }
    211166

    212-
    return nil
    167+
    return wp, nil
    213168
    }

    engine/api/workflow/workflow_exporter_test.go

    Lines changed: 4 additions & 1 deletion
    Original file line numberDiff line numberDiff line change
    @@ -132,8 +132,11 @@ func TestPull(t *testing.T) {
    132132
    test.Equal(t, w.Metadata, w1.Metadata)
    133133
    test.Equal(t, w.PurgeTags, w1.PurgeTags)
    134134

    135+
    pull, err := workflow.Pull(context.TODO(), db, cache, proj, w1.Name, exportentities.FormatYAML, project.EncryptWithBuiltinKey, u)
    136+
    test.NoError(t, err)
    137+
    135138
    buff := new(bytes.Buffer)
    136-
    test.NoError(t, workflow.Pull(context.TODO(), db, cache, proj, w1.Name, exportentities.FormatYAML, project.EncryptWithBuiltinKey, u, buff))
    139+
    test.NoError(t, pull.Tar(buff))
    137140

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

    engine/api/workflow_export.go

    Lines changed: 14 additions & 4 deletions
    Original file line numberDiff line numberDiff line change
    @@ -68,14 +68,24 @@ func (api *API) getWorkflowPullHandler() service.Handler {
    6868
    return sdk.WrapError(err, "unable to load projet")
    6969
    }
    7070

    71+
    pull, err := workflow.Pull(ctx, api.mustDB(), api.Cache, proj, name, exportentities.FormatYAML, project.EncryptWithBuiltinKey, deprecatedGetUser(ctx), opts...)
    72+
    if err != nil {
    73+
    return err
    74+
    }
    75+
    76+
    // early returns as json if param set
    77+
    if FormBool(r, "json") {
    78+
    return service.WriteJSON(w, pull, http.StatusOK)
    79+
    }
    80+
    7181
    buf := new(bytes.Buffer)
    72-
    if err := workflow.Pull(ctx, api.mustDB(), api.Cache, proj, name, exportentities.FormatYAML, project.EncryptWithBuiltinKey, deprecatedGetUser(ctx), buf, opts...); err != nil {
    73-
    return sdk.WrapError(err, "getWorkflowPullHandler")
    82+
    if err := pull.Tar(buf); err != nil {
    83+
    return err
    7484
    }
    7585

    7686
    w.Header().Add("Content-Type", "application/tar")
    7787
    w.WriteHeader(http.StatusOK)
    78-
    _, errC := io.Copy(w, buf)
    79-
    return sdk.WrapError(errC, "getWorkflowPullHandler> Unable to copy content buffer in the response writer")
    88+
    _, err = io.Copy(w, buf)
    89+
    return sdk.WrapError(err, "unable to copy content buffer in the response writer")
    8090
    }
    8191
    }

    engine/api/workflowtemplate/dao.go

    Lines changed: 2 additions & 2 deletions
    Original file line numberDiff line numberDiff line change
    @@ -57,7 +57,7 @@ func GetByID(db gorp.SqlExecutor, id int64) (*sdk.WorkflowTemplate, error) {
    5757
    if err == sql.ErrNoRows {
    5858
    return nil, nil
    5959
    }
    60-
    return nil, sdk.WrapError(err, "Cannot get workflow template")
    60+
    return nil, sdk.WrapError(err, "cannot get workflow template")
    6161
    }
    6262

    6363
    return &w, nil
    @@ -207,7 +207,7 @@ func GetInstanceByWorkflowID(db gorp.SqlExecutor, workflowID int64) (*sdk.Workfl
    207207
    if err == sql.ErrNoRows {
    208208
    return nil, nil
    209209
    }
    210-
    return nil, sdk.WrapError(err, "Cannot get workflow template instance")
    210+
    return nil, sdk.WrapError(err, "cannot get workflow template instance")
    211211
    }
    212212

    213213
    return &wti, nil

    engine/api/workflowtemplate/execute.go

    Lines changed: 4 additions & 4 deletions
    Original file line numberDiff line numberDiff line change
    @@ -229,7 +229,7 @@ func Tar(wt *sdk.WorkflowTemplate, res sdk.WorkflowTemplateResult, w io.Writer)
    229229
    return err
    230230
    }
    231231
    if err := tw.WriteHeader(&tar.Header{
    232-
    Name: fmt.Sprintf("%s.yml", wor.Name),
    232+
    Name: fmt.Sprintf(exportentities.PullWorkflowName, wor.Name),
    233233
    Mode: 0644,
    234234
    Size: int64(len(bs)),
    235235
    }); err != nil {
    @@ -254,7 +254,7 @@ func Tar(wt *sdk.WorkflowTemplate, res sdk.WorkflowTemplateResult, w io.Writer)
    254254
    return err
    255255
    }
    256256
    if err := tw.WriteHeader(&tar.Header{
    257-
    Name: fmt.Sprintf("%s.pip.yml", pip.Name),
    257+
    Name: fmt.Sprintf(exportentities.PullPipelineName, pip.Name),
    258258
    Mode: 0644,
    259259
    Size: int64(len(bs)),
    260260
    }); err != nil {
    @@ -280,7 +280,7 @@ func Tar(wt *sdk.WorkflowTemplate, res sdk.WorkflowTemplateResult, w io.Writer)
    280280
    return err
    281281
    }
    282282
    if err := tw.WriteHeader(&tar.Header{
    283-
    Name: fmt.Sprintf("%s.app.yml", app.Name),
    283+
    Name: fmt.Sprintf(exportentities.PullApplicationName, app.Name),
    284284
    Mode: 0644,
    285285
    Size: int64(len(bs)),
    286286
    }); err != nil {
    @@ -306,7 +306,7 @@ func Tar(wt *sdk.WorkflowTemplate, res sdk.WorkflowTemplateResult, w io.Writer)
    306306
    return err
    307307
    }
    308308
    if err := tw.WriteHeader(&tar.Header{
    309-
    Name: fmt.Sprintf("%s.env.yml", env.Name),
    309+
    Name: fmt.Sprintf(exportentities.PullEnvironmentName, env.Name),
    310310
    Mode: 0644,
    311311
    Size: int64(len(bs)),
    312312
    }); err != nil {

    engine/api/workflowtemplate/export.go

    Lines changed: 1 addition & 1 deletion
    Original file line numberDiff line numberDiff line change
    @@ -46,7 +46,7 @@ func Pull(wt *sdk.WorkflowTemplate, f exportentities.Format, w io.Writer) error
    4646
    return sdk.WrapError(errw, "Unable to export template")
    4747
    }
    4848
    hdr := &tar.Header{
    49-
    Name: fmt.Sprintf("%s.yml", wt.Slug),
    49+
    Name: fmt.Sprintf(exportentities.PullWorkflowName, wt.Slug),
    5050
    Mode: 0644,
    5151
    Size: int64(size),
    5252
    }

    0 commit comments

    Comments
     (0)
    0