Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 05a32fa

Browse files
authored
feat(cdsctl): pipeline import --force to detach from repo (#5575)
* feat(cdsctl): pipeline import --force to detach from repo Signed-off-by: Yvonnick Esnault <[email protected]>
1 parent 4195f31 commit 05a32fa

File tree

5 files changed

+100
-9
lines changed

5 files changed

+100
-9
lines changed

cli/cdsctl/pipeline.go

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,12 @@ func pipelineExportRun(v cli.Values) error {
9797
var pipelineImportCmd = cli.Command{
9898
Name: "import",
9999
Short: "Import CDS pipeline",
100-
Long: "PATH: Path or URL of pipeline to import",
100+
Long: `PATH: Path or URL of pipeline to import
101+
102+
Without --force, CDS won't update an existing pipeline.
103+
With --force, CDS will allow you to update an existing pipeline. If this pipeline is managed 'as-code', CDS will
104+
override it. This pipeline will be detached from the repository, until it is re-imported again following a commit on the repo.
105+
`,
101106
Ctx: []cli.Arg{
102107
{Name: _ProjectKey},
103108
},

engine/api/pipeline.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -231,7 +231,7 @@ func (api *API) postPipelineRollbackHandler() service.Handler {
231231
}
232232
}(&msgList)
233233

234-
if err := pipeline.ImportUpdate(ctx, tx, *proj, audit.Pipeline, msgChan); err != nil {
234+
if err := pipeline.ImportUpdate(ctx, tx, *proj, audit.Pipeline, msgChan, pipeline.ImportOptions{}); err != nil {
235235
return sdk.WrapError(err, "cannot import pipeline")
236236
}
237237

engine/api/pipeline/pipeline_importer.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,14 +7,14 @@ import (
77
"github.com/go-gorp/gorp"
88

99
"github.com/ovh/cds/engine/api/action"
10-
"github.com/ovh/cds/engine/cache"
1110
"github.com/ovh/cds/engine/api/group"
11+
"github.com/ovh/cds/engine/cache"
1212
"github.com/ovh/cds/sdk"
1313
"github.com/ovh/cds/sdk/log"
1414
)
1515

1616
//ImportUpdate import and update the pipeline in the project
17-
func ImportUpdate(ctx context.Context, db gorp.SqlExecutor, proj sdk.Project, pip *sdk.Pipeline, msgChan chan<- sdk.Message) error {
17+
func ImportUpdate(ctx context.Context, db gorp.SqlExecutor, proj sdk.Project, pip *sdk.Pipeline, msgChan chan<- sdk.Message, opts ImportOptions) error {
1818
t := time.Now()
1919
log.Debug("ImportUpdate> Begin")
2020
defer log.Debug("ImportUpdate> End (%d ns)", time.Since(t).Nanoseconds())
@@ -26,7 +26,7 @@ func ImportUpdate(ctx context.Context, db gorp.SqlExecutor, proj sdk.Project, pi
2626
return sdk.WrapError(err, "Unable to load pipeline %s %s", proj.Key, pip.Name)
2727
}
2828

29-
if oldPipeline.FromRepository != "" && pip.FromRepository != oldPipeline.FromRepository {
29+
if !opts.Force && oldPipeline.FromRepository != "" && pip.FromRepository != oldPipeline.FromRepository {
3030
return sdk.WrapError(sdk.ErrPipelineAsCodeOverride, "unable to update as code pipeline %s/%s.", oldPipeline.FromRepository, pip.FromRepository)
3131
}
3232

engine/api/pipeline/pipeline_importer_test.go

Lines changed: 89 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,12 +8,12 @@ import (
88
"github.com/stretchr/testify/assert"
99

1010
"github.com/ovh/cds/engine/api/bootstrap"
11-
"github.com/ovh/cds/engine/cache"
1211
"github.com/ovh/cds/engine/api/event"
1312
"github.com/ovh/cds/engine/api/pipeline"
1413
"github.com/ovh/cds/engine/api/project"
1514
"github.com/ovh/cds/engine/api/test"
1615
"github.com/ovh/cds/engine/api/test/assets"
16+
"github.com/ovh/cds/engine/cache"
1717
"github.com/ovh/cds/sdk"
1818
"github.com/ovh/cds/sdk/log"
1919
)
@@ -22,6 +22,7 @@ type args struct {
2222
pkey string
2323
pip *sdk.Pipeline
2424
u *sdk.AuthentifiedUser
25+
opts pipeline.ImportOptions
2526
}
2627

2728
type testcase struct {
@@ -55,7 +56,7 @@ func testImportUpdate(t *testing.T, db gorp.SqlExecutor, store cache.Store, tt t
5556
proj, err := project.Load(context.TODO(), db, tt.args.pip.ProjectKey, nil)
5657
test.NoError(t, err)
5758

58-
if err := pipeline.ImportUpdate(context.TODO(), db, *proj, tt.args.pip, msgChan); (err != nil) != tt.wantErr {
59+
if err := pipeline.ImportUpdate(context.TODO(), db, *proj, tt.args.pip, msgChan, tt.args.opts); (err != nil) != tt.wantErr {
5960
t.Errorf("%q. ImportUpdate() error = %v, wantErr %v", tt.name, err, tt.wantErr)
6061
}
6162

@@ -651,8 +652,93 @@ func TestImportUpdate(t *testing.T) {
651652
},
652653
}
653654

655+
var test10 = testcase{
656+
name: "import an ascode pipeline with force update",
657+
wantErr: false,
658+
args: args{
659+
u: u,
660+
pkey: sdk.RandomString(7),
661+
pip: &sdk.Pipeline{},
662+
opts: pipeline.ImportOptions{Force: true},
663+
},
664+
setup: func(t *testing.T, args args) {
665+
proj := assets.InsertTestProject(t, db, cache, args.pkey, args.pkey)
666+
667+
pipExisting := sdk.Pipeline{
668+
Name: sdk.RandomString(10),
669+
ProjectID: proj.ID,
670+
FromRepository: "myrepofrom",
671+
}
672+
assert.NoError(t, pipeline.InsertPipeline(db, &pipExisting))
673+
674+
args.pip.Name = pipExisting.Name
675+
args.pip.ProjectID = proj.ID
676+
args.pip.ProjectKey = proj.Key
677+
args.pip.Stages = []sdk.Stage{
678+
{
679+
BuildOrder: 1,
680+
Enabled: true,
681+
Jobs: []sdk.Job{
682+
{
683+
Enabled: false,
684+
Action: sdk.Action{
685+
Name: "Job 1",
686+
Description: "This is the first job",
687+
},
688+
},
689+
},
690+
Name: "This is the first stage",
691+
},
692+
}
693+
},
694+
asserts: func(t *testing.T, pip sdk.Pipeline) {
695+
assert.Equal(t, 1, len(pip.Stages))
696+
assert.Equal(t, 1, len(pip.Stages[0].Jobs))
697+
},
698+
}
699+
700+
var test11 = testcase{
701+
name: "import an ascode pipeline without force update",
702+
wantErr: true,
703+
args: args{
704+
u: u,
705+
pkey: sdk.RandomString(7),
706+
pip: &sdk.Pipeline{},
707+
},
708+
setup: func(t *testing.T, args args) {
709+
proj := assets.InsertTestProject(t, db, cache, args.pkey, args.pkey)
710+
711+
pipExisting := sdk.Pipeline{
712+
Name: sdk.RandomString(10),
713+
ProjectID: proj.ID,
714+
FromRepository: "myrepofrom",
715+
}
716+
assert.NoError(t, pipeline.InsertPipeline(db, &pipExisting))
717+
718+
args.pip.Name = pipExisting.Name
719+
args.pip.ProjectID = proj.ID
720+
args.pip.ProjectKey = proj.Key
721+
args.pip.Stages = []sdk.Stage{
722+
{
723+
BuildOrder: 1,
724+
Enabled: true,
725+
Jobs: []sdk.Job{
726+
{
727+
Enabled: false,
728+
Action: sdk.Action{
729+
Name: "Job 1",
730+
Description: "This is the first job",
731+
},
732+
},
733+
},
734+
Name: "This is the first stage",
735+
},
736+
}
737+
},
738+
}
739+
654740
//Run the tests
655-
var tests = []testcase{test1, test2, test3, test4, test5, test6, test7, test8, test9}
741+
var tests = []testcase{test1, test2, test3, test4, test5, test6, test7, test8, test9, test10, test11}
656742
for _, tt := range tests {
657743
testImportUpdate(t, db, cache, tt)
658744
}

engine/api/pipeline/pipeline_parser.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ func ParseAndImport(ctx context.Context, db gorp.SqlExecutor, cache cache.Store,
6363
if exist && !opts.Force {
6464
return pip, nil, sdk.ErrPipelineAlreadyExists
6565
} else if exist {
66-
globalError = ImportUpdate(ctx, db, proj, pip, msgChan)
66+
globalError = ImportUpdate(ctx, db, proj, pip, msgChan, opts)
6767
} else {
6868
globalError = Import(ctx, db, cache, proj, pip, msgChan, u)
6969
}

0 commit comments

Comments
 (0)