diff --git a/engine/api/v2_workflow_run_craft.go b/engine/api/v2_workflow_run_craft.go index 3b633adc84..9af5846969 100644 --- a/engine/api/v2_workflow_run_craft.go +++ b/engine/api/v2_workflow_run_craft.go @@ -1282,7 +1282,10 @@ func getCDSversion(ctx context.Context, db gorp.SqlExecutor, vcsClient sdk.VCSAu if err := toml.Unmarshal([]byte(fileContent), &file); err != nil { return nil, false, sdk.NewErrorFrom(sdk.ErrWrongRequest, "unable to read poetry file: %v", err) } - fileVersion = file.Tool.Poetry.Version + fileVersion = file.Project.Version + if fileVersion == "" { + fileVersion = file.Tool.Poetry.Version + } case sdk.SemverTypeDebian: firsLine := strings.Split(fileContent, "\n")[0] r, _ := regexp.Compile(`.*\((.*)\).*`) // format: package (version) distribution; urgency=low diff --git a/engine/api/v2_workflow_run_craft_test.go b/engine/api/v2_workflow_run_craft_test.go index a588ae7f23..992b4545df 100644 --- a/engine/api/v2_workflow_run_craft_test.go +++ b/engine/api/v2_workflow_run_craft_test.go @@ -1485,6 +1485,177 @@ func TestCraftWorkflowRunCustomVersion_File(t *testing.T) { require.Equal(t, "6.6.6-1.sha.g"+wrDB.Contexts.Git.ShaShort, wrDB.Contexts.CDS.Version) } +func TestCraftWorkflowRunCustomVersion_PoetryProject(t *testing.T) { + api, db, _ := newTestAPI(t) + ctx := context.TODO() + + db.Exec("DELETE FROM rbac") + db.Exec("DELETE FROM region") + + reg := sdk.Region{Name: "build"} + require.NoError(t, region.Insert(ctx, db, ®)) + + proj := assets.InsertTestProject(t, db, api.Cache, sdk.RandomString(10), sdk.RandomString(10)) + admin, _ := assets.InsertAdminUser(t, db) + assets.InsertRBAcProject(t, db, sdk.ProjectRoleRead, proj.Key, *admin) + + vcsProject := assets.InsertTestVCSProject(t, db, proj.ID, "bitbucketserver", "bitbucketserver") + repo := assets.InsertTestProjectRepository(t, db, proj.Key, vcsProject.ID, "my/repo") + + wkName := sdk.RandomString(10) + wr := sdk.V2WorkflowRun{ + DeprecatedUserID: admin.ID, + ProjectKey: proj.Key, + Status: sdk.V2WorkflowRunStatusCrafting, + VCSServerID: vcsProject.ID, + RepositoryID: repo.ID, + RunNumber: 1, + RunAttempt: 0, + WorkflowRef: "refs/heads/master", + WorkflowSha: "123456789", + WorkflowName: wkName, + WorkflowData: sdk.V2WorkflowRunData{ + Workflow: sdk.V2Workflow{ + Name: wkName, + Semver: &sdk.WorkflowSemver{ + From: "poetry", + Path: "pyproject.toml", + ReleaseRefs: []string{"refs/heads/mai*"}, + }, + Jobs: map[string]sdk.V2Job{ + "job1": { + Name: "My super job", + If: "cds.workflow == 'toto'", + Region: "build", + RunsOn: sdk.V2JobRunsOn{ + Model: "myworker-model", + }, + Steps: []sdk.ActionStep{ + { + Run: "echo toto", + }, + }, + }, + }, + }, + }, + RunEvent: sdk.V2WorkflowRunEvent{ + HookType: sdk.WorkflowHookTypeRepository, + Payload: nil, + Ref: "refs/heads/main", + Sha: "123456789", + EventName: sdk.WorkflowHookEventNamePush, + }, + } + require.NoError(t, workflow_v2.InsertRun(ctx, db, &wr)) + + myWMEnt := sdk.Entity{ + ProjectKey: proj.Key, + ProjectRepositoryID: repo.ID, + Type: sdk.EntityTypeWorkerModel, + FilePath: ".cds/worker-models/myworker-model.yml", + Name: "myworker-model", + Ref: "refs/heads/master", + Commit: "123456789", + LastUpdate: time.Time{}, + Data: "name: myworkermodel", + } + require.NoError(t, entity.Insert(ctx, db, &myWMEnt)) + + // Mock VCS + s, _ := assets.InsertService(t, db, t.Name()+"_VCS", sdk.TypeVCS) + // Setup a mock for all services called by the API + ctrl := gomock.NewController(t) + defer ctrl.Finish() + servicesClients := mock_services.NewMockClient(ctrl) + services.NewClient = func(_ []sdk.Service) services.Client { + return servicesClients + } + defer func() { + _ = services.Delete(db, s) + services.NewClient = services.NewDefaultClient + }() + + servicesClients.EXPECT(). + DoJSONRequest(gomock.Any(), "GET", "/vcs/bitbucketserver/repos/my/repo/content/pyproject.toml?commit=123456789", gomock.Any(), gomock.Any(), gomock.Any()). + DoAndReturn(func(ctx context.Context, method, path string, in interface{}, out interface{}, _ interface{}) (http.Header, int, error) { + b := &sdk.VCSContent{ + IsFile: true, + Content: `[tool.poetry] +name = "poetry" +version = "2.0.0" +description = "Python dependency management and packaging made easy." +authors = [] +maintainers = [] +license = "MIT" +readme = "README.md" +[project] +name = "my-awesome-package" +version = "0.1.0" +description = "A short description" +authors = ["Jane Doe "] +dependencies = [ +"requests >=2.25.1", +]`, + } + *(out.(*sdk.VCSContent)) = *b + return nil, 200, nil + }).Times(2) + + servicesClients.EXPECT(). + DoJSONRequest(gomock.Any(), "GET", "/vcs/bitbucketserver/repos/my/repo", gomock.Any(), gomock.Any(), gomock.Any()). + DoAndReturn( + func(ctx context.Context, method, path string, in interface{}, out interface{}, _ interface{}) (http.Header, int, error) { + b := &sdk.VCSRepo{} + *(out.(*sdk.VCSRepo)) = *b + return nil, 200, nil + }, + ).Times(2) + + // Create hatchery + hatch := sdk.Hatchery{Name: sdk.RandomString(10), ModelType: ""} + require.NoError(t, hatchery.Insert(ctx, db, &hatch)) + + require.NoError(t, rbac.Insert(ctx, db, &sdk.RBAC{ + Name: sdk.RandomString(10), + Hatcheries: []sdk.RBACHatchery{ + { + RegionID: reg.ID, + HatcheryID: hatch.ID, + Role: sdk.HatcheryRoleSpawn, + }, + }, + })) + + require.NoError(t, api.craftWorkflowRunV2(ctx, wr.ID)) + + wrDB, err := workflow_v2.LoadRunByID(ctx, db, wr.ID) + require.NoError(t, err) + assert.Equal(t, wrDB.Status, sdk.V2WorkflowRunStatusBuilding) + wrInfos, err := workflow_v2.LoadRunInfosByRunID(ctx, db, wr.ID) + require.NoError(t, err) + require.Equal(t, 0, len(wrInfos), "Error found: %v", wrInfos) + + require.Equal(t, "0.1.0", wrDB.Contexts.CDS.Version) + + version, err := workflow_v2.LoadWorkflowVersion(ctx, db, wrDB.Contexts.CDS.ProjectKey, wrDB.Contexts.CDS.WorkflowVCSServer, wrDB.Contexts.CDS.WorkflowRepository, wrDB.Contexts.CDS.Workflow, "0.1.0") + require.NoError(t, err) + + require.NotNil(t, version) + + // Update the run and craft it again + wrDB.Status = sdk.V2WorkflowRunStatusCrafting + require.NoError(t, workflow_v2.UpdateRun(ctx, db, wrDB)) + require.NoError(t, api.craftWorkflowRunV2(ctx, wrDB.ID)) + + wrDB, err = workflow_v2.LoadRunByID(ctx, db, wr.ID) + require.NoError(t, err) + versions, err := workflow_v2.LoadAllVerionsByWorkflow(ctx, db, wrDB.Contexts.CDS.ProjectKey, wrDB.Contexts.CDS.WorkflowVCSServer, wrDB.Contexts.CDS.WorkflowRepository, wrDB.Contexts.CDS.Workflow) + require.NoError(t, err) + require.Equal(t, 1, len(versions)) + require.Equal(t, "0.1.0-1.sha.g"+wrDB.Contexts.Git.ShaShort, wrDB.Contexts.CDS.Version) +} + func TestCraftWorkflowRunCustomVersion_Poetry(t *testing.T) { api, db, _ := newTestAPI(t) ctx := context.TODO() diff --git a/sdk/v2_workflow_semver.go b/sdk/v2_workflow_semver.go index 1d31bd6e78..23c349748a 100644 --- a/sdk/v2_workflow_semver.go +++ b/sdk/v2_workflow_semver.go @@ -17,7 +17,11 @@ type SemverNpmYarnPackage struct { } type SemverPoetry struct { - Tool SemverPoetryTool `toml:"tool"` + Project SemverPoetryProject `toml:"project"` + Tool SemverPoetryTool `toml:"tool"` +} +type SemverPoetryProject struct { + Version string `toml:"version"` } type SemverPoetryTool struct { Poetry SemverPoetryToolPoetry `toml:"poetry"`