diff --git a/artifactory/cli.go b/artifactory/cli.go index 89a8aab0c..62639b3e8 100644 --- a/artifactory/cli.go +++ b/artifactory/cli.go @@ -133,6 +133,7 @@ const ( userCategory = "User Management" transferCategory = "Transfer Between Artifactory Instances" otherCategory = "Other" + releaseBundlesV2 = "release-bundles-v2" ) func GetCommands() []cli.Command { @@ -1259,7 +1260,15 @@ func pingCmd(c *cli.Context) error { return err } -func prepareDownloadCommand(c *cli.Context) (*spec.SpecFiles, error) { +func prepareDownloadCommandForRbv2(c *cli.Context) (*spec.SpecFiles, error) { + return prepareDownloadCommand(c, true) +} + +func prepareStandardDownloadCommand(c *cli.Context) (*spec.SpecFiles, error) { + return prepareDownloadCommand(c, false) +} + +func prepareDownloadCommand(c *cli.Context, isRbv2 bool) (*spec.SpecFiles, error) { if c.NArg() > 0 && c.IsSet("spec") { return nil, cliutils.PrintHelpAndReturnError("No arguments should be sent when the spec option is used.", c) } @@ -1272,7 +1281,7 @@ func prepareDownloadCommand(c *cli.Context) (*spec.SpecFiles, error) { if c.IsSet("spec") { downloadSpec, err = cliutils.GetSpec(c, true, true) } else { - downloadSpec, err = createDefaultDownloadSpec(c) + downloadSpec, err = createDefaultDownloadSpec(c, isRbv2) } if err != nil { return nil, err @@ -1286,10 +1295,23 @@ func prepareDownloadCommand(c *cli.Context) (*spec.SpecFiles, error) { } func downloadCmd(c *cli.Context) error { - downloadSpec, err := prepareDownloadCommand(c) + var isRbv2 bool + var err error + if c.IsSet("bundle") { + isRbv2, err = checkRbExistenceInV2(c) + } + //if the command contains --bundle and the bundle found in rbv2, we will download from rbv2 + downloadSpec := new(spec.SpecFiles) + if err == nil && isRbv2 == true { + downloadSpec, err = prepareDownloadCommandForRbv2(c) + } else { + downloadSpec, err = prepareStandardDownloadCommand(c) + } + if err != nil { return err } + fixWinPathsForDownloadCmd(downloadSpec, c) configuration, err := cliutils.CreateDownloadConfiguration(c) if err != nil { @@ -1330,6 +1352,26 @@ func downloadCmd(c *cli.Context) error { return cliutils.GetCliError(err, result.SuccessCount(), result.FailCount(), cliutils.IsFailNoOp(c)) } +func checkRbExistenceInV2(c *cli.Context) (bool, error) { + bundleNameAndVersion := c.String("bundle") + serverDetails, err := cliutils.CreateArtifactoryDetailsByFlags(c) + if err != nil { + return false, err + } + + servicesManager, err := utils.CreateServiceManager(serverDetails, -1, 0, false) + if err != nil { + return false, err + } + + projectName := c.String("project") + if projectName == "" { + projectName = "default" + } + + return servicesManager.IsRbv2(projectName, bundleNameAndVersion) +} + func uploadCmd(c *cli.Context) (err error) { if c.NArg() > 0 && c.IsSet("spec") { return cliutils.PrintHelpAndReturnError("No arguments should be sent when the spec option is used.", c) @@ -2643,13 +2685,21 @@ func createGitLfsCleanConfiguration(c *cli.Context) (gitLfsCleanConfiguration *g return } -func createDefaultDownloadSpec(c *cli.Context) (*spec.SpecFiles, error) { +func createDefaultDownloadSpec(c *cli.Context, isRbv2 bool) (*spec.SpecFiles, error) { offset, limit, err := getOffsetAndLimitValues(c) if err != nil { return nil, err } + var source string + if isRbv2 { + source = buildSourceForRbv2(c) + c.Set("bundle", "") + } else { + source = strings.TrimPrefix(c.Args().Get(0), "/") + } + return spec.NewBuilder(). - Pattern(strings.TrimPrefix(c.Args().Get(0), "/")). + Pattern(source). Props(c.String("props")). ExcludeProps(c.String("exclude-props")). Build(c.String("build")). @@ -2674,6 +2724,18 @@ func createDefaultDownloadSpec(c *cli.Context) (*spec.SpecFiles, error) { BuildSpec(), nil } +func buildSourceForRbv2(c *cli.Context) string { + bundleNameAndVersion := c.String("bundle") + projectKey := c.String("project") + source := projectKey + // If projectKey is not empty, append "-" to it + if projectKey != "" { + source += "-" + } + source += releaseBundlesV2 + "/" + bundleNameAndVersion + "/" + return source +} + func setTransitiveInDownloadSpec(downloadSpec *spec.SpecFiles) { transitive := os.Getenv(coreutils.TransitiveDownload) if transitive == "" { diff --git a/artifactory/cli_test.go b/artifactory/cli_test.go index 5ef5b0f85..4ebe14694 100644 --- a/artifactory/cli_test.go +++ b/artifactory/cli_test.go @@ -36,7 +36,7 @@ func TestPrepareSearchDownloadDeleteCommands(t *testing.T) { t.Run(test.name, func(t *testing.T) { context, buffer := tests.CreateContext(t, test.flags, test.args) funcArray := []func(c *cli.Context) (*spec.SpecFiles, error){ - prepareSearchCommand, prepareDownloadCommand, prepareDeleteCommand, + prepareSearchCommand, prepareStandardDownloadCommand, prepareDeleteCommand, } for _, prepareCommandFunc := range funcArray { specFiles, err := prepareCommandFunc(context) diff --git a/artifactory_test.go b/artifactory_test.go index 9ab9cd2b1..a1e5d312b 100644 --- a/artifactory_test.go +++ b/artifactory_test.go @@ -223,10 +223,11 @@ func TestArtifactorySimpleUploadSpecUsingConfig(t *testing.T) { inttestutils.VerifyExistInArtifactory(tests.GetSimpleUploadExpectedRepo1(), searchFilePath, serverDetails, t) cleanArtifactoryTest() } + func TestReleaseBundleImportOnPrem(t *testing.T) { // Cleanup defer func() { - deleteReceivedReleaseBundle(t, "cli-tests", "2") + deleteReceivedReleaseBundle(t, "artifactory/api/release/bundles/", "cli-tests", "2") cleanArtifactoryTest() }() initArtifactoryTest(t, "") @@ -240,6 +241,29 @@ func TestReleaseBundleImportOnPrem(t *testing.T) { assert.NoError(t, lcCli.Exec("rbi", testFilePath)) } +func TestReleaseBundleV2Download(t *testing.T) { + buildNumber := "5" + defer func() { + deleteReceivedReleaseBundle(t, "lifecycle/api/v2/release_bundle/records/", tests.LcRbName1, buildNumber) + cleanArtifactoryTest() + }() + initArtifactoryTest(t, "") + inttestutils.DeleteBuild(serverDetails.ArtifactoryUrl, tests.RtBuildName1, artHttpDetails) + initLifecycleCli() + + // Create and publish build + runRt(t, "upload", "testdata/a/a1.in", tests.RtRepo1, "--build-name="+tests.RtBuildName1, "--build-number="+buildNumber) + runRt(t, "build-publish", tests.RtBuildName1, buildNumber) + + // Create RBV2 + err := lcCli.Exec("rbc", tests.LcRbName1, buildNumber, "--build-name="+tests.RtBuildName1, "--build-number="+buildNumber) + assert.NoError(t, err) + + // Download RBV2 + err = artifactoryCli.Exec([]string{"download", "--bundle=" + tests.LcRbName1 + "/" + buildNumber}...) + assert.NoError(t, err) +} + func TestArtifactoryUploadPathWithSpecialCharsAsNoRegex(t *testing.T) { initArtifactoryTest(t, "") filePath := getSpecialCharFilePath() @@ -5654,10 +5678,10 @@ func sendArtifactoryTrustedPublicKey(t *testing.T, artHttpDetails httputils.Http assert.NoError(t, err) } -func deleteReceivedReleaseBundle(t *testing.T, bundleName, bundleVersion string) { +func deleteReceivedReleaseBundle(t *testing.T, url, bundleName, bundleVersion string) { client, err := httpclient.ClientBuilder().Build() assert.NoError(t, err) - deleteApi := path.Join("artifactory/api/release/bundles/", bundleName, bundleVersion) + deleteApi := path.Join(url, bundleName, bundleVersion) _, _, err = client.SendDelete(*tests.JfrogUrl+deleteApi, []byte{}, artHttpDetails, "Deleting release bundle") assert.NoError(t, err) } diff --git a/go.mod b/go.mod index 0c00fd2c7..a5af9ac85 100644 --- a/go.mod +++ b/go.mod @@ -168,6 +168,10 @@ require ( gopkg.in/yaml.v3 v3.0.1 // indirect ) +replace github.com/jfrog/jfrog-cli-core/v2 => ../jfrog-cli-core + +replace github.com/jfrog/jfrog-client-go => ../jfrog-client-go + // replace github.com/jfrog/jfrog-cli-core/v2 => github.com/jfrog/jfrog-cli-core/v2 v2.31.1-0.20241213094134-8e118077b14a // replace github.com/jfrog/jfrog-cli-security => github.com/EyalDelarea/jfrog-cli-security v0.0.0-20241121103043-02719f295f02 diff --git a/go.sum b/go.sum index 8ccbef25b..92d1270a0 100644 --- a/go.sum +++ b/go.sum @@ -171,14 +171,10 @@ 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-artifactory v0.1.11 h1:tYGQpkGZVHwYxApKhMXgY1V25QaLFaTbjsoq0l3Bf4w= github.com/jfrog/jfrog-cli-artifactory v0.1.11/go.mod h1:rVBTbanRnG9CXyAYRJ2O6h2fJMa+fsGB+3swUB/qEt0= -github.com/jfrog/jfrog-cli-core/v2 v2.57.3 h1:xqVHCIgcaJoRmLe79Qks1+9wIO7NigMjLFI9hRqL3sQ= -github.com/jfrog/jfrog-cli-core/v2 v2.57.3/go.mod h1:+43WrzRL8GIRde9YMwEQpXPzwZC1JZlZjO/K2ZsyJHc= github.com/jfrog/jfrog-cli-platform-services v1.4.0 h1:g6A30+tOfXd1h6VASeNwH+5mhs5bPQJ0MFzZs/4nlvs= github.com/jfrog/jfrog-cli-platform-services v1.4.0/go.mod h1:Ky4SDXuMeaiNP/5zMT1YSzIuXG+cNYYOl8BaEA7Awbc= github.com/jfrog/jfrog-cli-security v1.13.6 h1:gm8TnGTlprMJbRga0cujeoN2xal7Pagd2kDkUfclvrw= github.com/jfrog/jfrog-cli-security v1.13.6/go.mod h1:NarJyhl8Kh0HL6br74oeStIosLmCjA7atLYxZIFHJc4= -github.com/jfrog/jfrog-client-go v1.48.5 h1:q8v8oZ2HwwVw6+ZCwKbuIpUmxpWUeZzvTASQl/QKxKw= -github.com/jfrog/jfrog-client-go v1.48.5/go.mod h1:2ySOMva54L3EYYIlCBYBTcTgqfrrQ19gtpA/MWfA/ec= github.com/jszwec/csvutil v1.10.0 h1:upMDUxhQKqZ5ZDCs/wy+8Kib8rZR8I8lOR34yJkdqhI= github.com/jszwec/csvutil v1.10.0/go.mod h1:/E4ONrmGkwmWsk9ae9jpXnv9QT8pLHEPcCirMFhxG9I= github.com/k0kubun/colorstring v0.0.0-20150214042306-9440f1994b88/go.mod h1:3w7q1U84EfirKl04SVQ/s7nPm1ZPhiXd34z40TNz36k=