Skip to content
3 changes: 3 additions & 0 deletions apptrust/commands/flags.go
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ const (
OverwriteStrategyFlag = "overwrite-strategy"
TagFlag = "tag"
DraftFlag = "draft"
SkipUnassignedFlag = "skip-unassigned"
SourceTypeBuildsFlag = "source-type-builds"
SourceTypeReleaseBundlesFlag = "source-type-release-bundles"
SourceTypeApplicationVersionsFlag = "source-type-application-versions"
Expand Down Expand Up @@ -94,6 +95,7 @@ var flagsMap = map[string]components.Flag{
OverwriteStrategyFlag: components.NewStringFlag(OverwriteStrategyFlag, "Strategy for handling target artifacts with the same path but different checksum. Supported values: "+coreutils.ListToText(model.OverwriteStrategyValues)+".", func(f *components.StringFlag) { f.Mandatory = false }),
TagFlag: components.NewStringFlag(TagFlag, "A tag to associate with the version. Must contain only alphanumeric characters, hyphens (-), underscores (_), and dots (.).", func(f *components.StringFlag) { f.Mandatory = false }),
DraftFlag: components.NewBoolFlag(DraftFlag, "Create the application version as a draft.", components.WithBoolDefaultValueFalse()),
SkipUnassignedFlag: components.NewBoolFlag(SkipUnassignedFlag, "Automatically promote the new version to the first lifecycle stage when all of its source artifacts reside in repositories mapped to that stage. Otherwise the version is left unassigned and a message explaining why is returned.", components.WithBoolDefaultValueFalse()),
SourceTypeBuildsFlag: components.NewStringFlag(SourceTypeBuildsFlag, "List of semicolon-separated (;) builds in the form of 'name=buildName1, id=runID1[, include-deps=true][, repo-key=repo1][, started=2023-01-01T12:34:56.789+0100]; name=buildName2, id=runID2[, include-deps=true][, repo-key=repo2][, started=2023-01-01T12:34:56.789+0100]' to be included in the new version.", func(f *components.StringFlag) { f.Mandatory = false }),
SourceTypeReleaseBundlesFlag: components.NewStringFlag(SourceTypeReleaseBundlesFlag, "List of semicolon-separated (;) release bundles in the form of 'name=releaseBundleName1, version=version1[, project-key=project1][, repo-key=repo1]; name=releaseBundleName2, version=version2[, project-key=project2][, repo-key=repo2]' to be included in the new version.", func(f *components.StringFlag) { f.Mandatory = false }),
SourceTypeApplicationVersionsFlag: components.NewStringFlag(SourceTypeApplicationVersionsFlag, "List of semicolon-separated (;) application versions in the form of 'application-key=app1, version=version1; application-key=app2, version=version2' to be included in the new version.", func(f *components.StringFlag) { f.Mandatory = false }),
Expand All @@ -114,6 +116,7 @@ var commandFlags = map[string][]string{
SyncFlag,
TagFlag,
DraftFlag,
SkipUnassignedFlag,
SourceTypeBuildsFlag,
SourceTypeReleaseBundlesFlag,
SourceTypeApplicationVersionsFlag,
Expand Down
1 change: 1 addition & 0 deletions apptrust/commands/version/create_app_version_cmd.go
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,7 @@ func (cv *createAppVersionCommand) buildRequestPayload(ctx *components.Context)
Sources: sources,
Tag: ctx.GetStringFlagValue(commands.TagFlag),
Draft: ctx.GetBoolFlagValue(commands.DraftFlag),
SkipUnassigned: ctx.GetBoolFlagValue(commands.SkipUnassignedFlag),
Filters: filters,
}, nil
}
Expand Down
18 changes: 18 additions & 0 deletions apptrust/commands/version/create_app_version_cmd_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -173,6 +173,24 @@ func TestCreateAppVersionCommand_FlagsSuite(t *testing.T) {
},
},
},
{
name: "skip-unassigned flag",
ctxSetup: func(ctx *components.Context) {
ctx.Arguments = []string{"app-key", "1.0.0"}
ctx.AddBoolFlag(commands.SkipUnassignedFlag, true)
ctx.AddStringFlag(commands.SourceTypePackagesFlag, "type=npm,name=pkg1,version=1.0.0,repo-key=repo1")
},
expectsPayload: &model.CreateAppVersionRequest{
ApplicationKey: "app-key",
Version: "1.0.0",
SkipUnassigned: true,
Sources: &model.CreateVersionSources{
Packages: []model.CreateVersionPackage{
{Type: "npm", Name: "pkg1", Version: "1.0.0", Repository: "repo1"},
},
},
},
},
{
name: "spec only",
ctxSetup: func(ctx *components.Context) {
Expand Down
1 change: 1 addition & 0 deletions apptrust/common/keys.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ var OrderedAppVersionKeys = []string{
"status",
"current_stage",
"tag",
"message",
}

// OrderedAppKeys defines the display order for application table output
Expand Down
1 change: 1 addition & 0 deletions apptrust/model/create_app_version_request.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ type CreateAppVersionRequest struct {
Sources *CreateVersionSources `json:"sources,omitempty"`
Tag string `json:"tag,omitempty"`
Draft bool `json:"draft,omitempty"`
SkipUnassigned bool `json:"skip_unassigned,omitempty"`
Filters *CreateVersionFilters `json:"filters,omitempty"`
}

Expand Down
3 changes: 3 additions & 0 deletions e2e/application_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import (
)

func TestCreateApp(t *testing.T) {

projectKey := utils.GetTestProjectKey(t)
appKey := utils.GenerateUniqueKey("app-create")
appName := "Full Test Application"
Expand Down Expand Up @@ -49,6 +50,7 @@ func TestCreateApp(t *testing.T) {
}

func TestUpdateApp(t *testing.T) {

projectKey := utils.GetTestProjectKey(t)
appKey := utils.GenerateUniqueKey("app-update")

Expand Down Expand Up @@ -88,6 +90,7 @@ func TestUpdateApp(t *testing.T) {
}

func TestDeleteApp(t *testing.T) {

appKey := utils.GenerateUniqueKey("app-delete")
utils.CreateBasicApplication(t, appKey)

Expand Down
8 changes: 8 additions & 0 deletions e2e/format_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ func assertTableOutput(t *testing.T, output string, expectedFields ...string) {
}

func TestAppCreate_OutputFormat(t *testing.T) {

projectKey := utils.GetTestProjectKey(t)

runAppCreate := func(appKey string, formatArgs ...string) string {
Expand Down Expand Up @@ -63,6 +64,7 @@ func TestAppCreate_OutputFormat(t *testing.T) {
}

func TestAppUpdate_OutputFormat(t *testing.T) {

runAppUpdate := func(appKey string, formatArgs ...string) string {
args := []string{"app-update", appKey, "--application-name=Updated " + appKey}
args = append(args, formatArgs...)
Expand Down Expand Up @@ -94,6 +96,7 @@ func TestAppUpdate_OutputFormat(t *testing.T) {
}

func TestVersionUpdate_OutputFormat(t *testing.T) {

testPackage := utils.GetTestPackage(t)

prepareVersion := func(t *testing.T, suffix string) (appKey, version string, cleanup func()) {
Expand Down Expand Up @@ -138,6 +141,7 @@ func TestVersionUpdate_OutputFormat(t *testing.T) {
}

func TestVersionUpdateSources_OutputFormat(t *testing.T) {

testPackage := utils.GetTestPackage(t)
artifactPath := utils.GetTestArtifact(t)

Expand Down Expand Up @@ -182,6 +186,7 @@ func TestVersionUpdateSources_OutputFormat(t *testing.T) {
}

func TestVersionPromote_OutputFormat(t *testing.T) {

testPackage := utils.GetTestPackage(t)

prepareVersion := func(t *testing.T, suffix string) (appKey, version string, cleanup func()) {
Expand Down Expand Up @@ -225,6 +230,7 @@ func TestVersionPromote_OutputFormat(t *testing.T) {
}

func TestVersionRelease_OutputFormat(t *testing.T) {

testPackage := utils.GetTestPackage(t)

prepareVersion := func(t *testing.T, suffix string) (appKey, version string, cleanup func()) {
Expand Down Expand Up @@ -268,6 +274,7 @@ func TestVersionRelease_OutputFormat(t *testing.T) {
}

func TestVersionRollback_OutputFormat(t *testing.T) {

testPackage := utils.GetTestPackage(t)

preparePromoted := func(t *testing.T, suffix string) (appKey, version string, cleanup func()) {
Expand Down Expand Up @@ -312,6 +319,7 @@ func TestVersionRollback_OutputFormat(t *testing.T) {
}

func TestPackageBind_OutputFormat(t *testing.T) {

testPackage := utils.GetTestPackage(t)

prepareApp := func(t *testing.T, suffix string) (appKey string, cleanup func()) {
Expand Down
2 changes: 2 additions & 0 deletions e2e/package_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import (
)

func TestBindPackage(t *testing.T) {

// Prepare
appKey := utils.GenerateUniqueKey("package-bind")
utils.CreateBasicApplication(t, appKey)
Expand All @@ -35,6 +36,7 @@ func TestBindPackage(t *testing.T) {
}

func TestUnbindPackage(t *testing.T) {

// Prepare
appKey := utils.GenerateUniqueKey("package-unbind")
utils.CreateBasicApplication(t, appKey)
Expand Down
1 change: 1 addition & 0 deletions e2e/system_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import (
)

func TestPing(t *testing.T) {

output := utils.AppTrustCli.RunCliCmdWithOutput(t, "ping")
assert.Contains(t, output, "OK")
}
19 changes: 19 additions & 0 deletions e2e/utils/artifactory_utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,23 @@ func uploadPackageToArtifactory(t *testing.T, repoKey, buildName, buildNumber st
return artifactDetails.Checksums.Sha256
}

func CreateGenericRepoWithEnv(t *testing.T, suffix string, environments []string) string {
servicesManager := getArtifactoryServicesManager(t)
repoKey := GetTestProjectKey(t) + "-" + suffix
localRepoConfig := services.NewGenericLocalRepositoryParams()
localRepoConfig.ProjectKey = GetTestProjectKey(t)
localRepoConfig.Key = repoKey
localRepoConfig.Environments = environments
err := servicesManager.CreateLocalRepository().Generic(localRepoConfig)
require.NoError(t, err)
t.Cleanup(func() { _ = servicesManager.DeleteRepository(repoKey) })
return repoKey
}

func UploadTestArtifact(t *testing.T, repoKey, fileName string) string {
return uploadSimpleFileToArtifactory(t, repoKey, fileName)
}

func uploadSimpleFileToArtifactory(t *testing.T, repoKey, targetFileName string) string {
tmpFile, err := os.CreateTemp("", "e2e-artifact-*.txt")
require.NoError(t, err)
Expand All @@ -147,6 +164,8 @@ func uploadSimpleFileToArtifactory(t *testing.T, repoKey, targetFileName string)
err = summary.Close()
require.NoError(t, err)

reindexRepo(t, repoKey)

return targetPath
}

Expand Down
82 changes: 82 additions & 0 deletions e2e/version_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import (
)

func TestCreateVersion_Package(t *testing.T) {

// Prepare
appKey := utils.GenerateUniqueKey("app-version-create-package")
utils.CreateBasicApplication(t, appKey)
Expand All @@ -38,6 +39,7 @@ func TestCreateVersion_Package(t *testing.T) {
}

func TestCreateVersion_Artifact(t *testing.T) {

// Prepare
appKey := utils.GenerateUniqueKey("app-version-create-artifact")
utils.CreateBasicApplication(t, appKey)
Expand All @@ -59,6 +61,7 @@ func TestCreateVersion_Artifact(t *testing.T) {
}

func TestCreateVersion_ApplicationVersion(t *testing.T) {

// Prepare - create source application with a version
sourceAppKey := utils.GenerateUniqueKey("app-version-create-app-version")
utils.CreateBasicApplication(t, sourceAppKey)
Expand Down Expand Up @@ -92,6 +95,7 @@ func TestCreateVersion_ApplicationVersion(t *testing.T) {
}

func TestCreateVersion_ApplicationVersion_DryRun(t *testing.T) {

// Prepare - create source application with a version
sourceAppKey := utils.GenerateUniqueKey("app-version-create-app-version-dryrun")
utils.CreateBasicApplication(t, sourceAppKey)
Expand Down Expand Up @@ -124,6 +128,7 @@ func TestCreateVersion_ApplicationVersion_DryRun(t *testing.T) {
}

func TestCreateVersion_ReleaseBundle(t *testing.T) {

// Prepare
appKey := utils.GenerateUniqueKey("app-version-create-release-bundle")
utils.CreateBasicApplication(t, appKey)
Expand All @@ -150,6 +155,7 @@ func TestCreateVersion_ReleaseBundle(t *testing.T) {
}

func TestCreateVersion_Build(t *testing.T) {

// Prepare
appKey := utils.GenerateUniqueKey("app-version-create-build")
utils.CreateBasicApplication(t, appKey)
Expand Down Expand Up @@ -196,7 +202,77 @@ func TestCreateVersion_Draft(t *testing.T) {
assert.Equal(t, utils.StatusDraft, versionContent.Status)
}

type skipUnassignedResponse struct {
ApplicationKey string `json:"application_key"`
Version string `json:"version"`
Status string `json:"status"`
CurrentStage string `json:"current_stage"`
Message string `json:"message"`
}

func TestCreateVersion_SkipUnassigned(t *testing.T) {
appKey := utils.GenerateUniqueKey("app-version-skip-unassigned")
utils.CreateBasicApplication(t, appKey)
defer utils.DeleteApplication(t, appKey)

t.Run("auto-promotes when source repo is mapped to first stage", func(t *testing.T) {
version := utils.GenerateUniqueKey("skip-ua-ok")

testPackage := utils.GetTestPackage(t)
packageFlag := fmt.Sprintf("--source-type-packages=type=%s, name=%s, version=%s, repo-key=%s",
testPackage.PackageType, testPackage.PackageName, testPackage.PackageVersion, testPackage.RepoKey)
output := utils.AppTrustCli.RunCliCmdWithOutput(t, "version-create", appKey, version, packageFlag, "--skip-unassigned")
defer utils.DeleteApplicationVersion(t, appKey, version)

require.NotEmpty(t, output)

var response skipUnassignedResponse
err := json.Unmarshal([]byte(output), &response)
require.NoError(t, err, "failed to parse CLI output as JSON: %s", output)
assert.Equal(t, appKey, response.ApplicationKey)
assert.Equal(t, version, response.Version)

utils.WaitForVersionCreation(t, appKey, version, 30*time.Second, 2*time.Second)

versionContent, statusCode, err := utils.GetApplicationVersion(appKey, version)
require.NoError(t, err)
assert.Equal(t, http.StatusOK, statusCode)
require.NotNil(t, versionContent)
assert.Equal(t, utils.StatusCompleted, versionContent.Status)
assert.Equal(t, "DEV", versionContent.CurrentStage, "Version should be auto-promoted to DEV stage")
})

t.Run("stays unassigned with message when artifact not in first stage", func(t *testing.T) {
version := utils.GenerateUniqueKey("skip-ua-fail")

repoKey := utils.CreateGenericRepoWithEnv(t, "prod-only-local", []string{"PROD"})
artifactPath := utils.UploadTestArtifact(t, repoKey, "mismatch-artifact.txt")

artifactFlag := fmt.Sprintf("--source-type-artifacts=path=%s", artifactPath)
output := utils.AppTrustCli.RunCliCmdWithOutput(t, "version-create", appKey, version, artifactFlag, "--skip-unassigned")
defer utils.DeleteApplicationVersion(t, appKey, version)

require.NotEmpty(t, output)

var response skipUnassignedResponse
err := json.Unmarshal([]byte(output), &response)
require.NoError(t, err, "failed to parse CLI output as JSON: %s", output)
assert.Equal(t, appKey, response.ApplicationKey)
assert.Equal(t, version, response.Version)

utils.WaitForVersionCreation(t, appKey, version, 30*time.Second, 2*time.Second)

versionContent, statusCode, err := utils.GetApplicationVersion(appKey, version)
require.NoError(t, err)
assert.Equal(t, http.StatusOK, statusCode)
require.NotNil(t, versionContent)
assert.Equal(t, utils.StatusCompleted, versionContent.Status)
assert.Empty(t, versionContent.CurrentStage, "Version should stay unassigned when artifacts are not in first stage")
})
}

func TestCreateVersion_Async(t *testing.T) {

appKey := utils.GenerateUniqueKey("app-version-create-async")
utils.CreateBasicApplication(t, appKey)

Expand Down Expand Up @@ -237,6 +313,7 @@ func assertVersionContent(t *testing.T, expectedPackage *utils.TestPackageResour
}

func TestUpdateVersion(t *testing.T) {

// Prepare
appKey := utils.GenerateUniqueKey("app-version-update")
utils.CreateBasicApplication(t, appKey)
Expand Down Expand Up @@ -268,6 +345,7 @@ func TestUpdateVersion(t *testing.T) {
}

func TestUpdateDraftVersionSources(t *testing.T) {

appKey := utils.GenerateUniqueKey("app-version-update-sources")
utils.CreateBasicApplication(t, appKey)
defer utils.DeleteApplication(t, appKey)
Expand Down Expand Up @@ -313,6 +391,7 @@ func containsPath(paths []string, target string) bool {
}

func TestDeleteVersion(t *testing.T) {

// Prepare
appKey := utils.GenerateUniqueKey("app-version-delete")
utils.CreateBasicApplication(t, appKey)
Expand Down Expand Up @@ -345,6 +424,7 @@ func TestDeleteVersion(t *testing.T) {
}

func TestPromoteVersion(t *testing.T) {

// Prepare
appKey := utils.GenerateUniqueKey("app-version-promote")
utils.CreateBasicApplication(t, appKey)
Expand Down Expand Up @@ -376,6 +456,7 @@ func TestPromoteVersion(t *testing.T) {
}

func TestReleaseVersion(t *testing.T) {

// Prepare
appKey := utils.GenerateUniqueKey("app-version-release")
utils.CreateBasicApplication(t, appKey)
Expand Down Expand Up @@ -406,6 +487,7 @@ func TestReleaseVersion(t *testing.T) {
}

func TestRollbackVersion(t *testing.T) {

// Prepare
appKey := utils.GenerateUniqueKey("app-version-rollback")
utils.CreateBasicApplication(t, appKey)
Expand Down
Loading