Skip to content

Commit 6eeefd0

Browse files
committed
Enhance download functionality to support RBV2
1 parent 539b80a commit 6eeefd0

File tree

5 files changed

+147
-9
lines changed

5 files changed

+147
-9
lines changed

artifactory/cli.go

Lines changed: 103 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,7 @@ import (
118118
buildinfocmd "github.com/jfrog/jfrog-client-go/artifactory/buildinfo"
119119
"github.com/jfrog/jfrog-client-go/artifactory/services"
120120
clientutils "github.com/jfrog/jfrog-client-go/utils"
121+
utilsForLC "github.com/jfrog/jfrog-client-go/utils"
121122
"github.com/jfrog/jfrog-client-go/utils/errorutils"
122123
"github.com/jfrog/jfrog-client-go/utils/log"
123124
"github.com/jszwec/csvutil"
@@ -133,6 +134,7 @@ const (
133134
userCategory = "User Management"
134135
transferCategory = "Transfer Between Artifactory Instances"
135136
otherCategory = "Other"
137+
releaseBundlesV2 = "release-bundles-v2"
136138
)
137139

138140
func GetCommands() []cli.Command {
@@ -1269,14 +1271,17 @@ func prepareDownloadCommand(c *cli.Context) (*spec.SpecFiles, error) {
12691271

12701272
var downloadSpec *spec.SpecFiles
12711273
var err error
1274+
12721275
if c.IsSet("spec") {
12731276
downloadSpec, err = cliutils.GetSpec(c, true, true)
12741277
} else {
12751278
downloadSpec, err = createDefaultDownloadSpec(c)
12761279
}
1280+
12771281
if err != nil {
12781282
return nil, err
12791283
}
1284+
12801285
setTransitiveInDownloadSpec(downloadSpec)
12811286
err = spec.ValidateSpec(downloadSpec.Files, false, true)
12821287
if err != nil {
@@ -1290,6 +1295,7 @@ func downloadCmd(c *cli.Context) error {
12901295
if err != nil {
12911296
return err
12921297
}
1298+
12931299
fixWinPathsForDownloadCmd(downloadSpec, c)
12941300
configuration, err := cliutils.CreateDownloadConfiguration(c)
12951301
if err != nil {
@@ -1330,6 +1336,54 @@ func downloadCmd(c *cli.Context) error {
13301336
return cliutils.GetCliError(err, result.SuccessCount(), result.FailCount(), cliutils.IsFailNoOp(c))
13311337
}
13321338

1339+
func checkRbExistenceInV2(c *cli.Context) (bool, error) {
1340+
bundleNameAndVersion := c.String("bundle")
1341+
parts := strings.Split(bundleNameAndVersion, "/")
1342+
rbName := parts[0]
1343+
rbVersion := parts[1]
1344+
1345+
lcDetails, err := createLifecycleDetailsByFlags(c)
1346+
if err != nil {
1347+
return false, err
1348+
}
1349+
1350+
lcServicesManager, err := utils.CreateLifecycleServiceManager(lcDetails, false)
1351+
if err != nil {
1352+
return false, err
1353+
}
1354+
1355+
return lcServicesManager.IsReleaseBundleExist(rbName, rbVersion, c.String("project"))
1356+
}
1357+
1358+
func createLifecycleDetailsByFlags(c *cli.Context) (*coreConfig.ServerDetails, error) {
1359+
lcDetails, err := cliutils.CreateServerDetailsWithConfigOffer(c, true, commonCliUtils.Platform)
1360+
if err != nil {
1361+
return nil, err
1362+
}
1363+
if lcDetails.Url == "" {
1364+
return nil, errors.New("platform URL is mandatory for lifecycle commands")
1365+
}
1366+
PlatformToLifecycleUrls(lcDetails)
1367+
return lcDetails, nil
1368+
}
1369+
1370+
func PlatformToLifecycleUrls(lcDetails *coreConfig.ServerDetails) {
1371+
// For tests only. in prod - this "if" will always return false
1372+
if strings.Contains(lcDetails.Url, "artifactory/") {
1373+
lcDetails.ArtifactoryUrl = utilsForLC.AddTrailingSlashIfNeeded(lcDetails.Url)
1374+
lcDetails.LifecycleUrl = strings.Replace(
1375+
utilsForLC.AddTrailingSlashIfNeeded(lcDetails.Url),
1376+
"artifactory/",
1377+
"lifecycle/",
1378+
1,
1379+
)
1380+
} else {
1381+
lcDetails.ArtifactoryUrl = utilsForLC.AddTrailingSlashIfNeeded(lcDetails.Url) + "artifactory/"
1382+
lcDetails.LifecycleUrl = utilsForLC.AddTrailingSlashIfNeeded(lcDetails.Url) + "lifecycle/"
1383+
}
1384+
lcDetails.Url = ""
1385+
}
1386+
13331387
func uploadCmd(c *cli.Context) (err error) {
13341388
if c.NArg() > 0 && c.IsSet("spec") {
13351389
return cliutils.PrintHelpAndReturnError("No arguments should be sent when the spec option is used.", c)
@@ -2648,8 +2702,9 @@ func createDefaultDownloadSpec(c *cli.Context) (*spec.SpecFiles, error) {
26482702
if err != nil {
26492703
return nil, err
26502704
}
2705+
26512706
return spec.NewBuilder().
2652-
Pattern(strings.TrimPrefix(c.Args().Get(0), "/")).
2707+
Pattern(getSourcePattern(c)).
26532708
Props(c.String("props")).
26542709
ExcludeProps(c.String("exclude-props")).
26552710
Build(c.String("build")).
@@ -2674,6 +2729,53 @@ func createDefaultDownloadSpec(c *cli.Context) (*spec.SpecFiles, error) {
26742729
BuildSpec(), nil
26752730
}
26762731

2732+
func getSourcePattern(c *cli.Context) string {
2733+
var source string
2734+
var isRbv2 bool
2735+
var err error
2736+
2737+
if c.IsSet("bundle") {
2738+
// If the bundle flag is set, we need to check if the bundle exists in rbv2
2739+
isRbv2, err = checkRbExistenceInV2(c)
2740+
if err != nil {
2741+
log.Error("Error occurred while checking if the bundle exists in rbv2:", err.Error())
2742+
}
2743+
}
2744+
2745+
if isRbv2 {
2746+
// RB2 will be downloaded like a regular artifact, path: projectKey-release-bundles-v2/rbName/rbVersion
2747+
source, err = buildSourceForRbv2(c)
2748+
if err != nil {
2749+
log.Error("Error occurred while building source path for rbv2:", err.Error())
2750+
return ""
2751+
}
2752+
} else {
2753+
source = strings.TrimPrefix(c.Args().Get(0), "/")
2754+
}
2755+
2756+
return source
2757+
}
2758+
2759+
func buildSourceForRbv2(c *cli.Context) (string, error) {
2760+
bundleNameAndVersion := c.String("bundle")
2761+
projectKey := c.String("project")
2762+
source := projectKey
2763+
2764+
// Reset bundle flag
2765+
err := c.Set("bundle", "")
2766+
if err != nil {
2767+
return "", err
2768+
}
2769+
2770+
// If projectKey is not empty, append "-" to it
2771+
if projectKey != "" {
2772+
source += "-"
2773+
}
2774+
// Build RB path: projectKey-release-bundles-v2/rbName/rbVersion/
2775+
source += releaseBundlesV2 + "/" + bundleNameAndVersion + "/"
2776+
return source, nil
2777+
}
2778+
26772779
func setTransitiveInDownloadSpec(downloadSpec *spec.SpecFiles) {
26782780
transitive := os.Getenv(coreutils.TransitiveDownload)
26792781
if transitive == "" {

artifactory_test.go

Lines changed: 35 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,8 @@ import (
6767
// https://jira.jfrog.org/browse/JA-2620
6868
// Minimum Artifactory version with Terraform support
6969
const terraformMinArtifactoryVersion = "7.38.4"
70+
const deleteReleaseBundleV1ApiUrl = "artifactory/api/release/bundles/"
71+
const deleteReleaseBundleV2ApiUrl = "lifecycle/api/v2/release_bundle/records/"
7072

7173
// JFrog CLI for Artifactory sub-commands (jfrog rt ...)
7274
var artifactoryCli *coretests.JfrogCli
@@ -223,10 +225,11 @@ func TestArtifactorySimpleUploadSpecUsingConfig(t *testing.T) {
223225
inttestutils.VerifyExistInArtifactory(tests.GetSimpleUploadExpectedRepo1(), searchFilePath, serverDetails, t)
224226
cleanArtifactoryTest()
225227
}
228+
226229
func TestReleaseBundleImportOnPrem(t *testing.T) {
227230
// Cleanup
228231
defer func() {
229-
deleteReceivedReleaseBundle(t, "cli-tests", "2")
232+
deleteReceivedReleaseBundle(t, deleteReleaseBundleV1ApiUrl, "cli-tests", "2")
230233
cleanArtifactoryTest()
231234
}()
232235
initArtifactoryTest(t, "")
@@ -240,6 +243,35 @@ func TestReleaseBundleImportOnPrem(t *testing.T) {
240243
assert.NoError(t, lcCli.Exec("rbi", testFilePath))
241244
}
242245

246+
func TestReleaseBundleV2Download(t *testing.T) {
247+
buildNumber := "5"
248+
defer func() {
249+
deleteReceivedReleaseBundle(t, deleteReleaseBundleV2ApiUrl, tests.LcRbName1, buildNumber)
250+
inttestutils.DeleteBuild(serverDetails.ArtifactoryUrl, tests.RtBuildName1, artHttpDetails)
251+
cleanArtifactoryTest()
252+
}()
253+
initArtifactoryTest(t, "")
254+
initLifecycleCli()
255+
256+
runRt(t, "upload", "testdata/a/a1.in", tests.RtRepo1, "--build-name="+tests.RtBuildName1, "--build-number="+buildNumber)
257+
runRt(t, "build-publish", tests.RtBuildName1, buildNumber)
258+
259+
// Create RBV2
260+
err := lcCli.Exec("rbc", tests.LcRbName1, buildNumber, "--build-name="+tests.RtBuildName1, "--build-number="+buildNumber)
261+
assert.NoError(t, err)
262+
263+
runRt(t, "download", "--bundle="+tests.LcRbName1+"/"+buildNumber)
264+
265+
wd, err := os.Getwd()
266+
assert.NoError(t, err, "Failed to get current dir")
267+
exists, err := fileutils.IsDirExists(filepath.Join(wd, tests.LcRbName1), false)
268+
269+
assert.NoError(t, err)
270+
assert.True(t, exists)
271+
272+
clientTestUtils.RemoveAllAndAssert(t, filepath.Join(wd, tests.LcRbName1))
273+
}
274+
243275
func TestArtifactoryUploadPathWithSpecialCharsAsNoRegex(t *testing.T) {
244276
initArtifactoryTest(t, "")
245277
filePath := getSpecialCharFilePath()
@@ -5654,10 +5686,10 @@ func sendArtifactoryTrustedPublicKey(t *testing.T, artHttpDetails httputils.Http
56545686
assert.NoError(t, err)
56555687
}
56565688

5657-
func deleteReceivedReleaseBundle(t *testing.T, bundleName, bundleVersion string) {
5689+
func deleteReceivedReleaseBundle(t *testing.T, url, bundleName, bundleVersion string) {
56585690
client, err := httpclient.ClientBuilder().Build()
56595691
assert.NoError(t, err)
5660-
deleteApi := path.Join("artifactory/api/release/bundles/", bundleName, bundleVersion)
5692+
deleteApi := path.Join(url, bundleName, bundleVersion)
56615693
_, _, err = client.SendDelete(*tests.JfrogUrl+deleteApi, []byte{}, artHttpDetails, "Deleting release bundle")
56625694
assert.NoError(t, err)
56635695
}

go.mod

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -179,3 +179,7 @@ require (
179179
// replace github.com/jfrog/build-info-go => github.com/jfrog/build-info-go v1.8.9-0.20241220065541-91828d43d8b9
180180

181181
// replace github.com/jfrog/gofrog => github.com/jfrog/gofrog dev
182+
183+
replace github.com/jfrog/jfrog-cli-core/v2 => github.com/jfrog/jfrog-cli-core/v2 v2.31.1-0.20250101110857-b26e9a6644c6
184+
185+
replace github.com/jfrog/jfrog-client-go => github.com/jfrog/jfrog-client-go v1.28.1-0.20250112155823-f3d607f5d854

go.sum

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -173,14 +173,14 @@ github.com/jfrog/jfrog-apps-config v1.0.1 h1:mtv6k7g8A8BVhlHGlSveapqf4mJfonwvXYL
173173
github.com/jfrog/jfrog-apps-config v1.0.1/go.mod h1:8AIIr1oY9JuH5dylz2S6f8Ym2MaadPLR6noCBO4C22w=
174174
github.com/jfrog/jfrog-cli-artifactory v0.1.11 h1:tYGQpkGZVHwYxApKhMXgY1V25QaLFaTbjsoq0l3Bf4w=
175175
github.com/jfrog/jfrog-cli-artifactory v0.1.11/go.mod h1:rVBTbanRnG9CXyAYRJ2O6h2fJMa+fsGB+3swUB/qEt0=
176-
github.com/jfrog/jfrog-cli-core/v2 v2.57.6 h1:kI5BqDW8Q4R5HkTUPSAObTqyIgQ9z7DqeFYGOEC1zPk=
177-
github.com/jfrog/jfrog-cli-core/v2 v2.57.6/go.mod h1:h5pzOZUb5ChGcGrXCYr3nPyXcTZjeGW2Rm1Zceo8Afg=
176+
github.com/jfrog/jfrog-cli-core/v2 v2.31.1-0.20250101110857-b26e9a6644c6 h1:/i1sIQS0q0gRN531ChVToQWcjaVZOKZ4KuGk7j7vDTc=
177+
github.com/jfrog/jfrog-cli-core/v2 v2.31.1-0.20250101110857-b26e9a6644c6/go.mod h1:LfKvCRXbvwgE0V6aX3/GabkzCedghXq0Y6lmsEuxr44=
178178
github.com/jfrog/jfrog-cli-platform-services v1.6.0 h1:2fBIDxnQaFWStZqMEUI2I3nkNjDmknxxHcmpeLxtocc=
179179
github.com/jfrog/jfrog-cli-platform-services v1.6.0/go.mod h1:u3lMRG7XC8MeUy/OPkHkZnsgCMIi0br4sjk2/W1Pm8I=
180180
github.com/jfrog/jfrog-cli-security v1.14.0 h1:mGm/ya0Qh0YdBS7ATgmQi1r8MEkbM8Hh/ml4UPkuu/4=
181181
github.com/jfrog/jfrog-cli-security v1.14.0/go.mod h1:KGfZVb4je4fiWm+OTNWdyi8V3c2TAkNDZHxsUUEM2GE=
182-
github.com/jfrog/jfrog-client-go v1.49.0 h1:NaTK6+LQBEJafL//6ntnS/eVx1dZMJnxydALwWHKORQ=
183-
github.com/jfrog/jfrog-client-go v1.49.0/go.mod h1:ohIfKpMBCQsE9kunrKQ1wvoExpqsPLaluRFO186B5EM=
182+
github.com/jfrog/jfrog-client-go v1.28.1-0.20250112155823-f3d607f5d854 h1:PlskEOWetCRH7NfEMbgC2/sOFPciXj42exbadxX3HT4=
183+
github.com/jfrog/jfrog-client-go v1.28.1-0.20250112155823-f3d607f5d854/go.mod h1:ohIfKpMBCQsE9kunrKQ1wvoExpqsPLaluRFO186B5EM=
184184
github.com/jszwec/csvutil v1.10.0 h1:upMDUxhQKqZ5ZDCs/wy+8Kib8rZR8I8lOR34yJkdqhI=
185185
github.com/jszwec/csvutil v1.10.0/go.mod h1:/E4ONrmGkwmWsk9ae9jpXnv9QT8pLHEPcCirMFhxG9I=
186186
github.com/k0kubun/colorstring v0.0.0-20150214042306-9440f1994b88/go.mod h1:3w7q1U84EfirKl04SVQ/s7nPm1ZPhiXd34z40TNz36k=

lifecycle_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ import (
3030

3131
const (
3232
artifactoryLifecycleMinVersion = "7.68.3"
33-
signingKeyOptionalArtifactoryMinVersion = "7.101.1"
33+
signingKeyOptionalArtifactoryMinVersion = "7.104.1"
3434
gpgKeyPairName = "lc-tests-key-pair"
3535
lcTestdataPath = "lifecycle"
3636
releaseBundlesSpec = "release-bundles-spec.json"

0 commit comments

Comments
 (0)