Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Next Next commit
Added e2e tests for create and update of a draft release bundle commands
  • Loading branch information
jongler committed Feb 1, 2026
commit 17ccb63e08284054b3c44aa0a5abdb23710304f2
6 changes: 3 additions & 3 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -16,15 +16,15 @@ require (
github.com/docker/docker v28.5.2+incompatible
github.com/gocarina/gocsv v0.0.0-20240520201108-78e41c74b4b1
github.com/jfrog/archiver/v3 v3.6.1
github.com/jfrog/build-info-go v1.13.1-0.20260107080257-82671efa69a2
github.com/jfrog/build-info-go v1.13.1-0.20260119231731-3cc4a0771bbd
github.com/jfrog/gofrog v1.7.6
github.com/jfrog/jfrog-cli-application v1.0.2-0.20251231144110-a68c3ac11c7a
github.com/jfrog/jfrog-cli-artifactory v0.8.1-0.20260107090044-56a45e5c560e
github.com/jfrog/jfrog-cli-artifactory v0.8.1-0.20260201084712-af3845a393d3
github.com/jfrog/jfrog-cli-core/v2 v2.60.1-0.20260106204841-744f3f71817b
github.com/jfrog/jfrog-cli-evidence v0.8.3-0.20251225153025-9d8ac181d615
github.com/jfrog/jfrog-cli-platform-services v1.10.1-0.20251205121610-171eb9b0000e
github.com/jfrog/jfrog-cli-security v1.25.0
github.com/jfrog/jfrog-client-go v1.55.1-0.20260107080024-ccd1f1de6614
github.com/jfrog/jfrog-client-go v1.55.1-0.20260201135506-ffd03518ef56
github.com/jszwec/csvutil v1.10.0
github.com/manifoldco/promptui v0.9.0
github.com/spf13/viper v1.21.0
Expand Down
12 changes: 6 additions & 6 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -1204,8 +1204,8 @@ github.com/jellydator/ttlcache/v3 v3.4.0 h1:YS4P125qQS0tNhtL6aeYkheEaB/m8HCqdMMP
github.com/jellydator/ttlcache/v3 v3.4.0/go.mod h1:Hw9EgjymziQD3yGsQdf1FqFdpp7YjFMd4Srg5EJlgD4=
github.com/jfrog/archiver/v3 v3.6.1 h1:LOxnkw9pOn45DzCbZNFV6K0+6dCsQ0L8mR3ZcujO5eI=
github.com/jfrog/archiver/v3 v3.6.1/go.mod h1:VgR+3WZS4N+i9FaDwLZbq+jeU4B4zctXL+gL4EMzfLw=
github.com/jfrog/build-info-go v1.13.1-0.20260107080257-82671efa69a2 h1:I3D+ApaOhHfICPkRlU8WwOY/IlHs4lfBIZC8NNHSDtQ=
github.com/jfrog/build-info-go v1.13.1-0.20260107080257-82671efa69a2/go.mod h1:+OCtMb22/D+u7Wne5lzkjJjaWr0LRZcHlDwTH86Mpwo=
github.com/jfrog/build-info-go v1.13.1-0.20260119231731-3cc4a0771bbd h1:rDAJA3RLhdjxgHjpYrPiYEl9RuGwDFODx+bvhU7J2LY=
github.com/jfrog/build-info-go v1.13.1-0.20260119231731-3cc4a0771bbd/go.mod h1:+OCtMb22/D+u7Wne5lzkjJjaWr0LRZcHlDwTH86Mpwo=
github.com/jfrog/froggit-go v1.20.6 h1:Xp7+LlEh0m1KGrQstb+u0aGfjRUtv1eh9xQBV3571jQ=
github.com/jfrog/froggit-go v1.20.6/go.mod h1:obSG1SlsWjktkuqmKtpq7MNTTL63e0ot+ucTnlOMV88=
github.com/jfrog/go-mockhttp v0.3.1 h1:/wac8v4GMZx62viZmv4wazB5GNKs+GxawuS1u3maJH8=
Expand All @@ -1216,8 +1216,8 @@ github.com/jfrog/jfrog-apps-config v1.0.1 h1:mtv6k7g8A8BVhlHGlSveapqf4mJfonwvXYL
github.com/jfrog/jfrog-apps-config v1.0.1/go.mod h1:8AIIr1oY9JuH5dylz2S6f8Ym2MaadPLR6noCBO4C22w=
github.com/jfrog/jfrog-cli-application v1.0.2-0.20251231144110-a68c3ac11c7a h1:XoJ3w2AFi7zniimALNK3idw9bzY9MwB/FM45TMgxYAY=
github.com/jfrog/jfrog-cli-application v1.0.2-0.20251231144110-a68c3ac11c7a/go.mod h1:xum2HquWO5uExa/A7MQs3TgJJVEeoqTR+6Z4mfBr1Xw=
github.com/jfrog/jfrog-cli-artifactory v0.8.1-0.20260107090044-56a45e5c560e h1:+qB6eWbzeSOh5i6Pc0sC9arG8r5f6GLZm722jDyQ6nI=
github.com/jfrog/jfrog-cli-artifactory v0.8.1-0.20260107090044-56a45e5c560e/go.mod h1:U/1q7jEO0YGSAWZEZiEmo0lZHI48xBorsFuL/F8C1fU=
github.com/jfrog/jfrog-cli-artifactory v0.8.1-0.20260201084712-af3845a393d3 h1:CGPRVKhCXuDAoK78RyACO04ohI0vvCDfnAk8FUheJJw=
github.com/jfrog/jfrog-cli-artifactory v0.8.1-0.20260201084712-af3845a393d3/go.mod h1:+3MYwa3NE2GR10uegJTdfKKvVXURXftN6N3/45OipRM=
github.com/jfrog/jfrog-cli-core/v2 v2.60.1-0.20260106204841-744f3f71817b h1:gGGmYXuYvcNns1BnLQI13lC+pgMxrmenx+ramtolQuA=
github.com/jfrog/jfrog-cli-core/v2 v2.60.1-0.20260106204841-744f3f71817b/go.mod h1:+Hnaikp/xCSPD/q7txxRy4Zc0wzjW/usrCSf+6uONSQ=
github.com/jfrog/jfrog-cli-evidence v0.8.3-0.20251225153025-9d8ac181d615 h1:y5an0bojHL00ipHP1QuBUrVcP+XK+yZHHOJ/r1I0RUM=
Expand All @@ -1226,8 +1226,8 @@ github.com/jfrog/jfrog-cli-platform-services v1.10.1-0.20251205121610-171eb9b000
github.com/jfrog/jfrog-cli-platform-services v1.10.1-0.20251205121610-171eb9b0000e/go.mod h1:qbu4iqBST9x8LgD8HhzUm91iOB3vHqtoGmaxOnmw0ok=
github.com/jfrog/jfrog-cli-security v1.25.0 h1:DM29QsMkFLRD6adKCWISe3uHFVaOodIN56NH7ThpKKU=
github.com/jfrog/jfrog-cli-security v1.25.0/go.mod h1:IV/+JhaLmyeMb8IAoJZYUq4gONW5BdrxgdT4w7SXgz0=
github.com/jfrog/jfrog-client-go v1.55.1-0.20260107080024-ccd1f1de6614 h1:8mjRuSJeJJ/mYPUXqJbT82hh2NxT2JvqWTvOtYsVa8g=
github.com/jfrog/jfrog-client-go v1.55.1-0.20260107080024-ccd1f1de6614/go.mod h1:sCE06+GngPoyrGO0c+vmhgMoVSP83UMNiZnIuNPzU8U=
github.com/jfrog/jfrog-client-go v1.55.1-0.20260201135506-ffd03518ef56 h1:MLbEex8JxLDj4bh62ZjQu16Qgfu8BPcKnlSTtizipe8=
github.com/jfrog/jfrog-client-go v1.55.1-0.20260201135506-ffd03518ef56/go.mod h1:sCE06+GngPoyrGO0c+vmhgMoVSP83UMNiZnIuNPzU8U=
github.com/jhump/protoreflect v1.17.0 h1:qOEr613fac2lOuTgWN4tPAtLL7fUSbuJL5X5XumQh94=
github.com/jhump/protoreflect v1.17.0/go.mod h1:h9+vUUL38jiBzck8ck+6G/aeMX8Z4QUY/NiJPwPNi+8=
github.com/jmespath/go-jmespath v0.4.1-0.20220621161143-b0104c826a24 h1:liMMTbpW34dhU4az1GN0pTPADwNmvoRSeoZ6PItiqnY=
Expand Down
129 changes: 121 additions & 8 deletions lifecycle_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -404,6 +404,76 @@ func TestPromoteReleaseBundleWithPromotionTypeFlag(t *testing.T) {
assertStatusCompleted(t, lcManager, tests.LcRbName1, number1, "")
}

func TestReleaseBundleCreationWithDraftFlag(t *testing.T) {
cleanCallback := initLifecycleTest(t, signingKeyOptionalArtifactoryMinVersion)
defer cleanCallback()
lcManager := getLcServiceManager(t)

deleteBuilds := uploadBuilds(t)
defer deleteBuilds()

// Test 1: Create draft bundle from spec
createRbFromSpecWithDraft(t, tests.LifecycleBuilds12, tests.LcRbName1, number1, true, true, true)
defer deleteReleaseBundle(t, lcManager, tests.LcRbName1, number1)
assertStatusDraft(t, lcManager, tests.LcRbName1, number1)

// Test 2: Create draft bundle using build-name/build-number flags
createRbWithFlags(t, "", "", tests.LcBuildName2, number2, tests.LcRbName2, number2, "default", true, true, true)
defer deleteReleaseBundle(t, lcManager, tests.LcRbName2, number2)
assertStatusDraft(t, lcManager, tests.LcRbName2, number2)
}

func TestReleaseBundleUpdateWithSpec(t *testing.T) {
cleanCallback := initLifecycleTest(t, signingKeyOptionalArtifactoryMinVersion)
defer cleanCallback()
lcManager := getLcServiceManager(t)

deleteBuilds := uploadBuilds(t)
defer deleteBuilds()

// Create a draft bundle from build 1
createRbWithFlags(t, "", "", tests.LcBuildName1, number1, tests.LcRbName1, number1, "default", true, true, true)
defer deleteReleaseBundle(t, lcManager, tests.LcRbName1, number1)
assertStatusDraft(t, lcManager, tests.LcRbName1, number1)
assertRbArtifacts(t, lcManager, tests.LcRbName1, number1, tests.GetExpectedLifecycleBuild1Artifacts())

// Update the draft bundle by adding build 3 (which includes dependencies) using spec file
updateSpecFile, err := tests.CreateSpec(tests.LifecycleBuilds3)
assert.NoError(t, err)
updateRbWithFlags(t, updateSpecFile, tests.LcRbName1, number1, "default", "", true)

// Verify the bundle is still in DRAFT status after update
assertStatusDraft(t, lcManager, tests.LcRbName1, number1)

// Verify the bundle now contains artifacts from both build 1 and build 3
assertRbArtifacts(t, lcManager, tests.LcRbName1, number1, tests.GetExpectedLifecycleUpdateArtifacts())
}

func TestReleaseBundleUpdateWithFlags(t *testing.T) {
cleanCallback := initLifecycleTest(t, signingKeyOptionalArtifactoryMinVersion)
defer cleanCallback()
lcManager := getLcServiceManager(t)

deleteBuilds := uploadBuilds(t)
defer deleteBuilds()

// Create a draft bundle from build 2
createRbWithFlags(t, "", "", tests.LcBuildName2, number2, tests.LcRbName2, number2, "default", true, true, true)
defer deleteReleaseBundle(t, lcManager, tests.LcRbName2, number2)
assertStatusDraft(t, lcManager, tests.LcRbName2, number2)
assertRbArtifacts(t, lcManager, tests.LcRbName2, number2, tests.GetExpectedLifecycleBuild2Artifacts())

// Update draft using --source-type-builds flag to add build 3
sourceBuildsFlag := fmt.Sprintf("name=%s,id=%s,include-deps=true", tests.LcBuildName3, number3)
updateRbWithFlags(t, "", tests.LcRbName2, number2, "default", sourceBuildsFlag, true)

// Verify the bundle is still in DRAFT status after update
assertStatusDraft(t, lcManager, tests.LcRbName2, number2)

// Verify the bundle now contains artifacts from both build 2 and build 3
assertRbArtifacts(t, lcManager, tests.LcRbName2, number2, tests.GetExpectedLifecycleUpdateBuild2Artifacts())
}

/*func deleteExportedReleaseBundle(t *testing.T, rbName string) {
assert.NoError(t, os.RemoveAll(rbName))
}*/
Expand Down Expand Up @@ -439,13 +509,19 @@ func uploadBuildsWithProject(t *testing.T) func() {
func createRbBackwardCompatible(t *testing.T, specName, sourceOption, rbName, rbVersion string, sync bool) {
specFile, err := getSpecFile(specName)
assert.NoError(t, err)
createRbWithFlags(t, specFile, sourceOption, "", "", rbName, rbVersion, "", sync, false)
createRbWithFlags(t, specFile, sourceOption, "", "", rbName, rbVersion, "", sync, false, false)
}

func createRbFromSpec(t *testing.T, specName, rbName, rbVersion string, sync bool, withoutSigningKey bool) {
specFile, err := tests.CreateSpec(specName)
assert.NoError(t, err)
createRbWithFlags(t, specFile, "spec", "", "", rbName, rbVersion, "", sync, withoutSigningKey)
createRbWithFlags(t, specFile, "spec", "", "", rbName, rbVersion, "", sync, withoutSigningKey, false)
}

func createRbFromSpecWithDraft(t *testing.T, specName, rbName, rbVersion string, sync, withoutSigningKey, draft bool) {
specFile, err := tests.CreateSpec(specName)
assert.NoError(t, err)
createRbWithFlags(t, specFile, "spec", "", "", rbName, rbVersion, "", sync, withoutSigningKey, draft)
}

func TestCreateBundleWithoutSpec(t *testing.T) {
Expand All @@ -457,11 +533,11 @@ func TestCreateBundleWithoutSpec(t *testing.T) {
deleteBuilds := uploadBuilds(t)
defer deleteBuilds()

createRbWithFlags(t, "", "", tests.LcBuildName1, number1, tests.LcRbName1, number1, "default", false, false)
createRbWithFlags(t, "", "", tests.LcBuildName1, number1, tests.LcRbName1, number1, "default", false, false, false)
assertStatusCompleted(t, lcManager, tests.LcRbName1, number1, "")
defer deleteReleaseBundle(t, lcManager, tests.LcRbName1, number1)

createRbWithFlags(t, "", "", tests.LcBuildName2, number2, tests.LcRbName2, number2, "default", false, true)
createRbWithFlags(t, "", "", tests.LcBuildName2, number2, tests.LcRbName2, number2, "default", false, true, false)
assertStatusCompleted(t, lcManager, tests.LcRbName2, number2, "")
defer deleteReleaseBundle(t, lcManager, tests.LcRbName2, number2)
}
Expand All @@ -481,13 +557,13 @@ func TestCreateBundleWithoutSpecAndWithProject(t *testing.T) {
deleteBuilds := uploadBuildsWithProject(t)
defer deleteBuilds()

createRbWithFlags(t, "", "", tests.LcBuildName1, number1, tests.LcRbName1, number1, tests.ProjectKey, false, false)
createRbWithFlags(t, "", "", tests.LcBuildName1, number1, tests.LcRbName1, number1, tests.ProjectKey, false, false, false)
assertStatusCompletedWithProject(t, lcManager, tests.LcRbName1, number1, "", tests.ProjectKey)
defer deleteReleaseBundleWithProject(t, lcManager, tests.LcRbName1, number1, tests.ProjectKey)
}

func createRbWithFlags(t *testing.T, specFilePath, sourceOption, buildName, buildNumber, rbName, rbVersion, project string,
sync, withoutSigningKey bool,
sync, withoutSigningKey, draft bool,
) {
argsAndOptions := []string{
"rbc",
Expand Down Expand Up @@ -516,6 +592,35 @@ func createRbWithFlags(t *testing.T, specFilePath, sourceOption, buildName, buil
argsAndOptions = append(argsAndOptions, getOption(cliutils.Project, project))
}

if draft {
argsAndOptions = append(argsAndOptions, getOption(cliutils.Draft, "true"))
}

assert.NoError(t, lcCli.Exec(argsAndOptions...))
}

func updateRbWithFlags(t *testing.T, specFilePath, rbName, rbVersion, project, sourceTypeBuilds string, sync bool) {
argsAndOptions := []string{
"rbu",
rbName,
rbVersion,
"--add", // Mandatory flag for rbu
}

if specFilePath != "" {
argsAndOptions = append(argsAndOptions, getOption("spec", specFilePath))
}

if sourceTypeBuilds != "" {
argsAndOptions = append(argsAndOptions, getOption("source-type-builds", sourceTypeBuilds))
}

if project != "" {
argsAndOptions = append(argsAndOptions, getOption(cliutils.Project, project))
}

argsAndOptions = append(argsAndOptions, getOption(cliutils.Sync, strconv.FormatBool(sync)))

assert.NoError(t, lcCli.Exec(argsAndOptions...))
}

Expand Down Expand Up @@ -580,6 +685,14 @@ func assertStatusCompleted(t *testing.T, lcManager *lifecycle.LifecycleServicesM
assert.Equal(t, services.Completed, resp.Status)
}

func assertStatusDraft(t *testing.T, lcManager *lifecycle.LifecycleServicesManager, rbName, rbVersion string) {
resp, err := getStatus(lcManager, rbName, rbVersion, "")
if !assert.NoError(t, err) {
return
}
assert.Equal(t, services.Draft, resp.Status)
}

// If createdMillis is provided, assert status for promotion. If blank, assert for creation.
func assertStatusCompletedWithProject(t *testing.T, lcManager *lifecycle.LifecycleServicesManager, rbName, rbVersion, createdMillis, projectKey string) {
resp, err := getStatusWithProject(lcManager, rbName, rbVersion, createdMillis, projectKey)
Expand Down Expand Up @@ -1117,13 +1230,13 @@ func TestReleaseBundlesSearchVersions(t *testing.T) {
}

// Create release bundles with project
createRbWithFlags(t, "", "", tests.LcBuildName1, number1, projectRbName, projectVersionA, tests.ProjectKey, true, false)
createRbWithFlags(t, "", "", tests.LcBuildName1, number1, projectRbName, projectVersionA, tests.ProjectKey, true, false, false)
defer deleteReleaseBundleWithProject(t, lcManager, projectRbName, projectVersionA, tests.ProjectKey)
assertStatusCompletedWithProject(t, lcManager, projectRbName, projectVersionA, "", tests.ProjectKey)

time.Sleep(1 * time.Second)

createRbWithFlags(t, "", "", tests.LcBuildName2, number2, projectRbName, projectVersionB, tests.ProjectKey, true, false)
createRbWithFlags(t, "", "", tests.LcBuildName2, number2, projectRbName, projectVersionB, tests.ProjectKey, true, false, false)
defer deleteReleaseBundleWithProject(t, lcManager, projectRbName, projectVersionB, tests.ProjectKey)
assertStatusCompletedWithProject(t, lcManager, projectRbName, projectVersionB, "", tests.ProjectKey)

Expand Down
1 change: 1 addition & 0 deletions utils/cliutils/commandsflags.go
Original file line number Diff line number Diff line change
Expand Up @@ -592,6 +592,7 @@ const (
SigningKey = "signing-key"
setupRepo = repo
PromotionType = "promotion-type"
Draft = "draft"
)

var flagsMap = map[string]cli.Flag{
Expand Down
40 changes: 40 additions & 0 deletions utils/tests/consts.go
Original file line number Diff line number Diff line change
Expand Up @@ -2156,6 +2156,46 @@ func GetExpectedLifecycleCreationByAql() []string {
}
}

// GetExpectedLifecycleBuild1Artifacts returns expected artifacts from build 1 only.
func GetExpectedLifecycleBuild1Artifacts() []string {
return []string{
RtDevRepo + "/a1.in",
RtDevRepo + "/a2.in",
RtDevRepo + "/a3.in",
}
}

// GetExpectedLifecycleUpdateArtifacts returns expected artifacts after updating a draft bundle
// that was created from build 1 (a1.in, a2.in, a3.in) with build 3 (dep-file as dependency).
func GetExpectedLifecycleUpdateArtifacts() []string {
return []string{
RtDevRepo + "/a1.in",
RtDevRepo + "/a2.in",
RtDevRepo + "/a3.in",
RtDevRepo + "/dep-file",
}
}

// GetExpectedLifecycleBuild2Artifacts returns expected artifacts from build 2 only.
func GetExpectedLifecycleBuild2Artifacts() []string {
return []string{
RtDevRepo + "/b1.in",
RtDevRepo + "/b2.in",
RtDevRepo + "/b3.in",
}
}

// GetExpectedLifecycleUpdateBuild2Artifacts returns expected artifacts after updating a draft bundle
// that was created from build 2 (b1.in, b2.in, b3.in) with build 3 (dep-file as dependency).
func GetExpectedLifecycleUpdateBuild2Artifacts() []string {
return []string{
RtDevRepo + "/b1.in",
RtDevRepo + "/b2.in",
RtDevRepo + "/b3.in",
RtDevRepo + "/dep-file",
}
}

func GetExpectedLifecycleArtifacts() []string {
return []string{
RtProdRepo1 + "/a1.in",
Expand Down