From 6b3dae604c9632c1f2abf1022ad04af26c887576 Mon Sep 17 00:00:00 2001 From: Eyal Ben Moshe Date: Mon, 28 Aug 2023 16:42:53 +0300 Subject: [PATCH 1/5] Update Frogbot workflows (#2166) --- .github/workflows/frogbot-scan-and-fix.yml | 8 ++++---- .github/workflows/frogbot-scan-pr.yml | 23 ++++++++++++++++++---- 2 files changed, 23 insertions(+), 8 deletions(-) diff --git a/.github/workflows/frogbot-scan-and-fix.yml b/.github/workflows/frogbot-scan-and-fix.yml index 5de072c16..875e275ca 100644 --- a/.github/workflows/frogbot-scan-and-fix.yml +++ b/.github/workflows/frogbot-scan-and-fix.yml @@ -15,10 +15,6 @@ jobs: # The repository scanning will be triggered periodically on the following branches. branch: [ "dev" ] steps: - - uses: actions/checkout@v3 - with: - ref: ${{ matrix.branch }} - # Install prerequisites - name: Setup Go uses: actions/setup-go@v3 @@ -40,3 +36,7 @@ jobs: JF_GIT_TOKEN: ${{ secrets.GITHUB_TOKEN }} JFROG_CLI_LOG_LEVEL: "DEBUG" + # [Mandatory] + # The name of the branch on which Frogbot will perform the scan + JF_GIT_BASE_BRANCH: ${{ matrix.branch }} + diff --git a/.github/workflows/frogbot-scan-pr.yml b/.github/workflows/frogbot-scan-pr.yml index 575d843e6..06147e3cd 100644 --- a/.github/workflows/frogbot-scan-pr.yml +++ b/.github/workflows/frogbot-scan-pr.yml @@ -12,10 +12,6 @@ jobs: # "frogbot" GitHub environment can approve the pull request to be scanned. environment: frogbot steps: - - uses: actions/checkout@v3 - with: - ref: ${{ github.event.pull_request.head.sha }} - # Install prerequisites - name: Setup Go uses: actions/setup-go@v3 @@ -36,3 +32,22 @@ jobs: # The GitHub token automatically generated for the job JF_GIT_TOKEN: ${{ secrets.GITHUB_TOKEN }} JFROG_CLI_LOG_LEVEL: "DEBUG" + + # [Optional] + # Configure the SMTP server to enable Frogbot to send emails with detected secrets in pull request scans. + # SMTP server URL including should the relevant port: (Example: smtp.server.com:8080) + JF_SMTP_SERVER: ${{ secrets.JF_SMTP_SERVER }} + + # [Mandatory if JF_SMTP_SERVER is set] + # The username required for authenticating with the SMTP server. + JF_SMTP_USER: ${{ secrets.JF_SMTP_USER }} + + # [Mandatory if JF_SMTP_SERVER is set] + # The password associated with the username required for authentication with the SMTP server. + JF_SMTP_PASSWORD: ${{ secrets.JF_SMTP_PASSWORD }} + + # [Optional] + # List of comma separated email addresses to receive email notifications about secrets + # detected during pull request scanning. The notification is also sent to the email set + # in the committer git profile regardless of whether this variable is set or not. + JF_EMAIL_RECEIVERS: "eco-system@jfrog.com" From 3b424360a982194b259eadfa227889e5b7408aba Mon Sep 17 00:00:00 2001 From: Assaf Attias <49212512+attiasas@users.noreply.github.com> Date: Mon, 28 Aug 2023 18:24:04 +0300 Subject: [PATCH 2/5] Upgrade client to 1.31.6 core to 2.41.3 (#2167) --- go.mod | 4 ++-- go.sum | 8 ++++---- inttestutils/buildinfo.go | 4 ++-- xray_test.go | 2 +- 4 files changed, 9 insertions(+), 9 deletions(-) diff --git a/go.mod b/go.mod index dc83f3523..be492e4d6 100644 --- a/go.mod +++ b/go.mod @@ -9,8 +9,8 @@ require ( github.com/gocarina/gocsv v0.0.0-20230616125104-99d496ca653d github.com/jfrog/build-info-go v1.9.8 github.com/jfrog/gofrog v1.3.0 - github.com/jfrog/jfrog-cli-core/v2 v2.41.2 - github.com/jfrog/jfrog-client-go v1.31.5 + github.com/jfrog/jfrog-cli-core/v2 v2.41.3 + github.com/jfrog/jfrog-client-go v1.31.6 github.com/jszwec/csvutil v1.8.0 github.com/mholt/archiver/v3 v3.5.1 github.com/stretchr/testify v1.8.4 diff --git a/go.sum b/go.sum index bd0657de8..676f79685 100644 --- a/go.sum +++ b/go.sum @@ -241,10 +241,10 @@ github.com/jfrog/build-info-go v1.9.8 h1:D8/ga+YgQpqp/CJj2zteS4/twmSy8zvm1v9lCd2 github.com/jfrog/build-info-go v1.9.8/go.mod h1:t31QRpH5xUJKw8XkQlAA+Aq7aanyS1rrzpcK8xSNVts= github.com/jfrog/gofrog v1.3.0 h1:o4zgsBZE4QyDbz2M7D4K6fXPTBJht+8lE87mS9bw7Gk= github.com/jfrog/gofrog v1.3.0/go.mod h1:IFMc+V/yf7rA5WZ74CSbXe+Lgf0iApEQLxRZVzKRUR0= -github.com/jfrog/jfrog-cli-core/v2 v2.41.2 h1:Gnp93JcDAnHHCN3SHqam2K/S9yJcytS4q+MQd6vv9Ck= -github.com/jfrog/jfrog-cli-core/v2 v2.41.2/go.mod h1:YqB9rEJF1P7uGLIPUvF5qdDDf1zM5f4DneIQNkqyAfs= -github.com/jfrog/jfrog-client-go v1.31.5 h1:dYVgIJzMwX+EU9GEELKPSHFLyfW6UrrjZWMEZtAyx6A= -github.com/jfrog/jfrog-client-go v1.31.5/go.mod h1:icb00ZJN/mMMNkQduHDkzpqsXH9Flwi3f3COYexq3Nc= +github.com/jfrog/jfrog-cli-core/v2 v2.41.3 h1:BkPjDdrjO2jTlrI0/9Wps1lGNZmSwlIKBPJA+Wd99pE= +github.com/jfrog/jfrog-cli-core/v2 v2.41.3/go.mod h1:h3VQ3fxXU8dzPCINAFfzOWMwkV34/iBTgLnXAMrIc0Y= +github.com/jfrog/jfrog-client-go v1.31.6 h1:uWuyT4BDm9s5ES6oDTBny9Gl6yf8iKFjcbmHSHQZrDc= +github.com/jfrog/jfrog-client-go v1.31.6/go.mod h1:icb00ZJN/mMMNkQduHDkzpqsXH9Flwi3f3COYexq3Nc= github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU= github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk= github.com/jszwec/csvutil v1.8.0 h1:G7vS2LGdpZZDH1HmHeNbxOaJ/ZnJlpwGFvOkTkJzzNk= diff --git a/inttestutils/buildinfo.go b/inttestutils/buildinfo.go index 954ca6987..3003172bf 100644 --- a/inttestutils/buildinfo.go +++ b/inttestutils/buildinfo.go @@ -11,8 +11,8 @@ import ( coreutils "github.com/jfrog/jfrog-cli-core/v2/artifactory/utils" - "github.com/jfrog/jfrog-client-go/artifactory/services/utils" "github.com/jfrog/jfrog-client-go/http/httpclient" + "github.com/jfrog/jfrog-client-go/utils" "github.com/jfrog/jfrog-client-go/utils/io/httputils" "github.com/jfrog/jfrog-client-go/utils/log" "github.com/stretchr/testify/assert" @@ -27,7 +27,7 @@ func DeleteBuild(artifactoryUrl, buildName string, artHttpDetails httputils.Http restApi := path.Join("api/build/", buildName) params := map[string]string{"deleteAll": "1"} - requestFullUrl, err := utils.BuildArtifactoryUrl(artifactoryUrl, restApi, params) + requestFullUrl, err := utils.BuildUrl(artifactoryUrl, restApi, params) if err != nil { log.Error(err) return diff --git a/xray_test.go b/xray_test.go index 857c8da1f..d1638b483 100644 --- a/xray_test.go +++ b/xray_test.go @@ -485,7 +485,7 @@ func validateXrayVersion(t *testing.T, minVersion string) { assert.NoError(t, err) return } - err = coreutils.ValidateMinimumVersion(coreutils.Xray, xrayVersion.GetVersion(), minVersion) + err = clientUtils.ValidateMinimumVersion(clientUtils.Xray, xrayVersion.GetVersion(), minVersion) if err != nil { t.Skip(err) } From d71026b0e7eed5403ffd58801c3ee440ffca21c4 Mon Sep 17 00:00:00 2001 From: Yahav Itzhak Date: Mon, 28 Aug 2023 20:26:22 +0300 Subject: [PATCH 3/5] Support Gradle version catalog, configuration cache and lazy tasks (#2161) --- .github/workflows/gradleTests.yml | 5 +++-- go.mod | 8 ++++---- go.sum | 8 ++++---- testdata/gradle/projectwithplugin/build.gradle | 16 +++++++++++++++- 4 files changed, 26 insertions(+), 11 deletions(-) diff --git a/.github/workflows/gradleTests.yml b/.github/workflows/gradleTests.yml index d361d9e9b..6feac8097 100644 --- a/.github/workflows/gradleTests.yml +++ b/.github/workflows/gradleTests.yml @@ -15,11 +15,12 @@ concurrency: jobs: Gradle-Tests: if: contains(github.event.pull_request.labels.*.name, 'safe to test') || github.event_name == 'push' - name: ${{ matrix.os }} + name: ${{ matrix.os }}-gradle-${{ matrix.gradle-version }} strategy: fail-fast: false matrix: os: [ubuntu-latest, macos-latest, windows-latest] + gradle-version: [5.6.4, 8.3] runs-on: ${{ matrix.os }} env: GRADLE_OPTS: -Dorg.gradle.daemon=false @@ -31,7 +32,7 @@ jobs: - name: Setup Gradle uses: gradle/gradle-build-action@v2 with: - gradle-version: 7.6 + gradle-version: ${{ matrix.gradle-version }} - name: Checkout code uses: actions/checkout@v3 with: diff --git a/go.mod b/go.mod index be492e4d6..225ba7f81 100644 --- a/go.mod +++ b/go.mod @@ -7,9 +7,9 @@ require ( github.com/buger/jsonparser v1.1.1 github.com/go-git/go-git/v5 v5.8.1 github.com/gocarina/gocsv v0.0.0-20230616125104-99d496ca653d - github.com/jfrog/build-info-go v1.9.8 + github.com/jfrog/build-info-go v1.9.9 github.com/jfrog/gofrog v1.3.0 - github.com/jfrog/jfrog-cli-core/v2 v2.41.3 + github.com/jfrog/jfrog-cli-core/v2 v2.41.4 github.com/jfrog/jfrog-client-go v1.31.6 github.com/jszwec/csvutil v1.8.0 github.com/mholt/archiver/v3 v3.5.1 @@ -122,9 +122,9 @@ require ( gopkg.in/yaml.v3 v3.0.1 // indirect ) -// replace github.com/jfrog/build-info-go => github.com/jfrog/build-info-go v1.8.9-0.20230820165857-52ff32c4d8eb +// replace github.com/jfrog/build-info-go => github.com/jfrog/build-info-go v1.8.9-0.20230828134416-f0db33dd9344 -// replace github.com/jfrog/jfrog-cli-core/v2 => github.com/eyalbe4/jfrog-cli-core/v2 v2.22.1-0.20230825095403-f5869e4264d6 +// replace github.com/jfrog/jfrog-cli-core/v2 => github.com/jfrog/jfrog-cli-core/v2 v2.31.1-0.20230828140932-e44caa02288e // replace github.com/jfrog/gofrog => github.com/jfrog/gofrog v1.2.6-0.20230418122323-2bf299dd6d27 diff --git a/go.sum b/go.sum index 676f79685..18ca77ea6 100644 --- a/go.sum +++ b/go.sum @@ -237,12 +237,12 @@ github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 h1:BQSFePA1RWJOl github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99/go.mod h1:1lJo3i6rXxKeerYnT8Nvf0QmHCRC1n8sfWVwXF2Frvo= github.com/jedib0t/go-pretty/v6 v6.4.6 h1:v6aG9h6Uby3IusSSEjHaZNXpHFhzqMmjXcPq1Rjl9Jw= github.com/jedib0t/go-pretty/v6 v6.4.6/go.mod h1:Ndk3ase2CkQbXLLNf5QDHoYb6J9WtVfmHZu9n8rk2xs= -github.com/jfrog/build-info-go v1.9.8 h1:D8/ga+YgQpqp/CJj2zteS4/twmSy8zvm1v9lCd2Kv1M= -github.com/jfrog/build-info-go v1.9.8/go.mod h1:t31QRpH5xUJKw8XkQlAA+Aq7aanyS1rrzpcK8xSNVts= +github.com/jfrog/build-info-go v1.9.9 h1:YMA9okHawBNL8SrCWzqULSf5M4W+YnWyUhmkWSjoXEE= +github.com/jfrog/build-info-go v1.9.9/go.mod h1:t31QRpH5xUJKw8XkQlAA+Aq7aanyS1rrzpcK8xSNVts= github.com/jfrog/gofrog v1.3.0 h1:o4zgsBZE4QyDbz2M7D4K6fXPTBJht+8lE87mS9bw7Gk= github.com/jfrog/gofrog v1.3.0/go.mod h1:IFMc+V/yf7rA5WZ74CSbXe+Lgf0iApEQLxRZVzKRUR0= -github.com/jfrog/jfrog-cli-core/v2 v2.41.3 h1:BkPjDdrjO2jTlrI0/9Wps1lGNZmSwlIKBPJA+Wd99pE= -github.com/jfrog/jfrog-cli-core/v2 v2.41.3/go.mod h1:h3VQ3fxXU8dzPCINAFfzOWMwkV34/iBTgLnXAMrIc0Y= +github.com/jfrog/jfrog-cli-core/v2 v2.41.4 h1:+V35NN+UaKl6ZFSjAyZFZ4VijCgsORnGsHug02DROdE= +github.com/jfrog/jfrog-cli-core/v2 v2.41.4/go.mod h1:Mi3WFUzG2CU6tlLpGsMNRaKkhH/tIMuci4tjnPZ9S3M= github.com/jfrog/jfrog-client-go v1.31.6 h1:uWuyT4BDm9s5ES6oDTBny9Gl6yf8iKFjcbmHSHQZrDc= github.com/jfrog/jfrog-client-go v1.31.6/go.mod h1:icb00ZJN/mMMNkQduHDkzpqsXH9Flwi3f3COYexq3Nc= github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU= diff --git a/testdata/gradle/projectwithplugin/build.gradle b/testdata/gradle/projectwithplugin/build.gradle index 7664f11cb..d06c9fa99 100644 --- a/testdata/gradle/projectwithplugin/build.gradle +++ b/testdata/gradle/projectwithplugin/build.gradle @@ -9,6 +9,8 @@ buildscript { apply plugin: 'groovy' apply plugin: 'idea' apply plugin: 'com.jfrog.artifactory' +apply plugin: 'maven-publish' + version = 1.0 task initProject(description: 'Initialize project directory structure.') { doLast { @@ -28,6 +30,18 @@ task initProject(description: 'Initialize project directory structure.') { } } +publishing { + publications { + mavenJava(MavenPublication) { + from components.java + } + } +} + +tasks.withType(GenerateModuleMetadata) { + enabled = false +} + artifactory { contextUrl = "${URL}" publish { @@ -40,7 +54,7 @@ artifactory { // Reference to Gradle publications defined in the build script. // This is how we tell the Artifactory Plugin which artifacts should be // published to Artifactory. - publishConfigs('archives', 'published') + publications('mavenJava') publishArtifacts = true // Properties to be attached to the published artifacts. properties = ['qa.level': 'basic', 'dev.team' : 'core'] From c72d7d84b95b8f87bda98925e5efcb2310262311 Mon Sep 17 00:00:00 2001 From: Robi Nino Date: Wed, 30 Aug 2023 16:20:39 +0300 Subject: [PATCH 4/5] Support Lifecycle Release Bundle Distribute (#2068) --- .github/workflows/lifecycleTests.yml | 44 +++++++++++++++ distribution/cli.go | 76 +++++++++----------------- distribution_test.go | 3 +- docs/lifecycle/distribute/help.go | 15 ++++++ go.mod | 4 +- go.sum | 8 +-- lifecycle/cli.go | 58 +++++++++++++++++++- lifecycle_test.go | 43 ++++++++++----- utils/cliutils/commandsflags.go | 81 ++++++++++++++++++---------- utils/distribution/distribute.go | 52 ++++++++++++++++++ utils/tests/consts.go | 14 +++++ utils/tests/utils.go | 2 +- 12 files changed, 297 insertions(+), 103 deletions(-) create mode 100644 .github/workflows/lifecycleTests.yml create mode 100644 docs/lifecycle/distribute/help.go create mode 100644 utils/distribution/distribute.go diff --git a/.github/workflows/lifecycleTests.yml b/.github/workflows/lifecycleTests.yml new file mode 100644 index 000000000..01613e0af --- /dev/null +++ b/.github/workflows/lifecycleTests.yml @@ -0,0 +1,44 @@ +name: Lifecycle Tests +on: + push: + branches: + - '**' + tags-ignore: + - '**' + # Triggers the workflow on labeled PRs only. + pull_request_target: + types: [labeled] +# Ensures that only the latest commit is running for each PR at a time. +concurrency: + group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.sha }}-${{ github.ref }} + cancel-in-progress: true +jobs: + Lifecycle-Tests: + if: contains(github.event.pull_request.labels.*.name, 'safe to test') || github.event_name == 'push' + name: ${{ matrix.os }} + strategy: + fail-fast: false + matrix: + os: [ubuntu-latest, macos-latest, windows-latest] + runs-on: ${{ matrix.os }} + steps: + - name: Install Go + uses: actions/setup-go@v3 + with: + go-version: 1.20.x + - name: Checkout code + uses: actions/checkout@v3 + with: + ref: ${{ github.event.pull_request.head.sha }} + - name: Go Cache + uses: actions/cache@v3 + with: + path: ~/go/pkg/mod + key: ${{ runner.os }}-go-${{ hashFiles('**/go.sum') }} + restore-keys: ${{ runner.os }}-go- + - name: Checkout code + uses: actions/checkout@v3 + with: + ref: ${{ github.event.pull_request.head.sha }} + - name: Run Lifecycle tests + run: go test -v github.com/jfrog/jfrog-cli --timeout 0 --test.lifecycle --jfrog.url=${{ secrets.PLATFORM_URL }} --jfrog.adminToken=${{ secrets.PLATFORM_ADMIN_TOKEN }} --jfrog.user=${{ secrets.PLATFORM_USER }} --ci.runId=${{ runner.os }}-lifecycle diff --git a/distribution/cli.go b/distribution/cli.go index 682156767..0a0664a29 100644 --- a/distribution/cli.go +++ b/distribution/cli.go @@ -2,10 +2,6 @@ package distribution import ( "errors" - "os" - "path/filepath" - "strings" - "github.com/jfrog/jfrog-cli-core/v2/common/commands" "github.com/jfrog/jfrog-cli-core/v2/common/spec" distributionCommands "github.com/jfrog/jfrog-cli-core/v2/distribution/commands" @@ -18,10 +14,14 @@ import ( "github.com/jfrog/jfrog-cli/docs/artifactory/releasebundleupdate" "github.com/jfrog/jfrog-cli/docs/common" "github.com/jfrog/jfrog-cli/utils/cliutils" + "github.com/jfrog/jfrog-cli/utils/distribution" distributionServices "github.com/jfrog/jfrog-client-go/distribution/services" distributionServicesUtils "github.com/jfrog/jfrog-client-go/distribution/services/utils" "github.com/jfrog/jfrog-client-go/utils/errorutils" "github.com/urfave/cli" + "os" + "path/filepath" + "strings" ) func GetCommands() []cli.Command { @@ -111,11 +111,11 @@ func releaseBundleCreateCmd(c *cli.Context) error { return err } releaseBundleCreateCmd := distributionCommands.NewReleaseBundleCreateCommand() - rtDetails, err := createArtifactoryDetailsByFlags(c) + dsDetails, err := createDistributionDetailsByFlags(c) if err != nil { return err } - releaseBundleCreateCmd.SetServerDetails(rtDetails).SetReleaseBundleCreateParams(params).SetSpec(releaseBundleCreateSpec).SetDryRun(c.Bool("dry-run")).SetDetailedSummary(c.Bool("detailed-summary")) + releaseBundleCreateCmd.SetServerDetails(dsDetails).SetReleaseBundleCreateParams(params).SetSpec(releaseBundleCreateSpec).SetDryRun(c.Bool("dry-run")).SetDetailedSummary(c.Bool("detailed-summary")) err = commands.Exec(releaseBundleCreateCmd) if releaseBundleCreateCmd.IsDetailedSummary() { @@ -153,11 +153,11 @@ func releaseBundleUpdateCmd(c *cli.Context) error { return err } releaseBundleUpdateCmd := distributionCommands.NewReleaseBundleUpdateCommand() - rtDetails, err := createArtifactoryDetailsByFlags(c) + dsDetails, err := createDistributionDetailsByFlags(c) if err != nil { return err } - releaseBundleUpdateCmd.SetServerDetails(rtDetails).SetReleaseBundleUpdateParams(params).SetSpec(releaseBundleUpdateSpec).SetDryRun(c.Bool("dry-run")).SetDetailedSummary(c.Bool("detailed-summary")) + releaseBundleUpdateCmd.SetServerDetails(dsDetails).SetReleaseBundleUpdateParams(params).SetSpec(releaseBundleUpdateSpec).SetDryRun(c.Bool("dry-run")).SetDetailedSummary(c.Bool("detailed-summary")) err = commands.Exec(releaseBundleUpdateCmd) if releaseBundleUpdateCmd.IsDetailedSummary() { @@ -177,11 +177,11 @@ func releaseBundleSignCmd(c *cli.Context) error { params.StoringRepository = c.String("repo") params.GpgPassphrase = c.String("passphrase") releaseBundleSignCmd := distributionCommands.NewReleaseBundleSignCommand() - rtDetails, err := createArtifactoryDetailsByFlags(c) + dsDetails, err := createDistributionDetailsByFlags(c) if err != nil { return err } - releaseBundleSignCmd.SetServerDetails(rtDetails).SetReleaseBundleSignParams(params).SetDetailedSummary(c.Bool("detailed-summary")) + releaseBundleSignCmd.SetServerDetails(dsDetails).SetReleaseBundleSignParams(params).SetDetailedSummary(c.Bool("detailed-summary")) err = commands.Exec(releaseBundleSignCmd) if releaseBundleSignCmd.IsDetailedSummary() { if summary := releaseBundleSignCmd.GetSummary(); summary != nil { @@ -192,37 +192,21 @@ func releaseBundleSignCmd(c *cli.Context) error { } func releaseBundleDistributeCmd(c *cli.Context) error { - if c.NArg() != 2 { - return cliutils.WrongNumberOfArgumentsHandler(c) - } - if c.IsSet("max-wait-minutes") && !c.IsSet("sync") { - return cliutils.PrintHelpAndReturnError("The --max-wait-minutes option can't be used without --sync", c) - } - var distributionRules *spec.DistributionRules - if c.IsSet("dist-rules") { - if c.IsSet("site") || c.IsSet("city") || c.IsSet("country-code") { - return cliutils.PrintHelpAndReturnError("The --dist-rules option can't be used with --site, --city or --country-code", c) - } - var err error - distributionRules, err = spec.CreateDistributionRulesFromFile(c.String("dist-rules")) - if err != nil { - return err - } - } else { - distributionRules = createDefaultDistributionRules(c) + if err := distribution.ValidateReleaseBundleDistributeCmd(c); err != nil { + return err } - params := distributionServices.NewDistributeReleaseBundleParams(c.Args().Get(0), c.Args().Get(1)) - releaseBundleDistributeCmd := distributionCommands.NewReleaseBundleDistributeCommand() - rtDetails, err := createArtifactoryDetailsByFlags(c) + dsDetails, err := createDistributionDetailsByFlags(c) if err != nil { return err } - maxWaitMinutes, err := cliutils.GetIntFlagValue(c, "max-wait-minutes", 60) + distributionRules, maxWaitMinutes, params, err := distribution.InitReleaseBundleDistributeCmd(c) if err != nil { return err } - releaseBundleDistributeCmd.SetServerDetails(rtDetails). + + distributeCmd := distributionCommands.NewReleaseBundleDistributeV1Command() + distributeCmd.SetServerDetails(dsDetails). SetDistributeBundleParams(params). SetDistributionRules(distributionRules). SetDryRun(c.Bool("dry-run")). @@ -230,7 +214,7 @@ func releaseBundleDistributeCmd(c *cli.Context) error { SetMaxWaitMinutes(maxWaitMinutes). SetAutoCreateRepo(c.Bool("create-repo")) - return commands.Exec(releaseBundleDistributeCmd) + return commands.Exec(distributeCmd) } func releaseBundleDeleteCmd(c *cli.Context) error { @@ -248,7 +232,7 @@ func releaseBundleDeleteCmd(c *cli.Context) error { return err } } else { - distributionRules = createDefaultDistributionRules(c) + distributionRules = distribution.CreateDefaultDistributionRules(c) } params := distributionServices.NewDeleteReleaseBundleParams(c.Args().Get(0), c.Args().Get(1)) @@ -260,11 +244,11 @@ func releaseBundleDeleteCmd(c *cli.Context) error { } params.MaxWaitMinutes = maxWaitMinutes distributeBundleCmd := distributionCommands.NewReleaseBundleDeleteParams() - rtDetails, err := createArtifactoryDetailsByFlags(c) + dsDetails, err := createDistributionDetailsByFlags(c) if err != nil { return err } - distributeBundleCmd.SetQuiet(cliutils.GetQuietValue(c)).SetServerDetails(rtDetails).SetDistributeBundleParams(params).SetDistributionRules(distributionRules).SetDryRun(c.Bool("dry-run")) + distributeBundleCmd.SetQuiet(cliutils.GetQuietValue(c)).SetServerDetails(dsDetails).SetDistributeBundleParams(params).SetDistributionRules(distributionRules).SetDryRun(c.Bool("dry-run")) return commands.Exec(distributeBundleCmd) } @@ -283,16 +267,6 @@ func createDefaultReleaseBundleSpec(c *cli.Context) *spec.SpecFiles { BuildSpec() } -func createDefaultDistributionRules(c *cli.Context) *spec.DistributionRules { - return &spec.DistributionRules{ - DistributionRules: []spec.DistributionRule{{ - SiteName: c.String("site"), - CityName: c.String("city"), - CountryCodes: cliutils.GetStringsArrFlagValue(c, "country-codes"), - }}, - } -} - func createReleaseBundleCreateUpdateParams(c *cli.Context, bundleName, bundleVersion string) (distributionServicesUtils.ReleaseBundleParams, error) { releaseBundleParams := distributionServicesUtils.NewReleaseBundleParams(bundleName, bundleVersion) releaseBundleParams.SignImmediately = c.Bool("sign") @@ -336,13 +310,13 @@ func populateReleaseNotesSyntax(c *cli.Context) (distributionServicesUtils.Relea return distributionServicesUtils.PlainText, nil } -func createArtifactoryDetailsByFlags(c *cli.Context) (*coreConfig.ServerDetails, error) { - artDetails, err := cliutils.CreateServerDetailsWithConfigOffer(c, true, cliutils.Ds) +func createDistributionDetailsByFlags(c *cli.Context) (*coreConfig.ServerDetails, error) { + dsDetails, err := cliutils.CreateServerDetailsWithConfigOffer(c, true, cliutils.Ds) if err != nil { return nil, err } - if artDetails.DistributionUrl == "" { + if dsDetails.DistributionUrl == "" { return nil, errors.New("the --dist-url option is mandatory") } - return artDetails, nil + return dsDetails, nil } diff --git a/distribution_test.go b/distribution_test.go index 9c23f7304..62cbea526 100644 --- a/distribution_test.go +++ b/distribution_test.go @@ -14,6 +14,7 @@ import ( distributionServices "github.com/jfrog/jfrog-client-go/distribution/services" clientDistUtils "github.com/jfrog/jfrog-client-go/distribution/services/utils" clientUtils "github.com/jfrog/jfrog-client-go/utils" + "github.com/jfrog/jfrog-client-go/utils/distribution" "github.com/jfrog/jfrog-client-go/utils/io/fileutils" "github.com/jfrog/jfrog-client-go/utils/io/httputils" "github.com/jfrog/jfrog-client-go/utils/log" @@ -566,7 +567,7 @@ func TestDistributeSyncTimeout(t *testing.T) { testServer, mockServerDetails, _ := coreTestUtils.CreateDsRestsMockServer(t, func(w http.ResponseWriter, r *http.Request) { if r.RequestURI == "/api/v1/distribution/"+tests.BundleName+"/"+bundleVersion { w.WriteHeader(http.StatusOK) - content, err := json.Marshal(distributionServices.DistributionResponseBody{TrackerId: json.Number(trackerId)}) + content, err := json.Marshal(distribution.DistributionResponseBody{TrackerId: json.Number(trackerId)}) assert.NoError(t, err) _, err = w.Write(content) assert.NoError(t, err) diff --git a/docs/lifecycle/distribute/help.go b/docs/lifecycle/distribute/help.go new file mode 100644 index 000000000..8a3c2d47f --- /dev/null +++ b/docs/lifecycle/distribute/help.go @@ -0,0 +1,15 @@ +package distribute + +var Usage = []string{"rbd [command options] "} + +func GetDescription() string { + return "Distribute a release bundle." +} + +func GetArguments() string { + return ` release bundle name + Name of the Release Bundle to distribute. + + release bundle version + Version of the Release Bundle to distribute.` +} diff --git a/go.mod b/go.mod index 225ba7f81..737d29c7d 100644 --- a/go.mod +++ b/go.mod @@ -124,8 +124,8 @@ require ( // replace github.com/jfrog/build-info-go => github.com/jfrog/build-info-go v1.8.9-0.20230828134416-f0db33dd9344 -// replace github.com/jfrog/jfrog-cli-core/v2 => github.com/jfrog/jfrog-cli-core/v2 v2.31.1-0.20230828140932-e44caa02288e +replace github.com/jfrog/jfrog-cli-core/v2 => github.com/jfrog/jfrog-cli-core/v2 v2.31.1-0.20230830130857-c5a2b11b52be // replace github.com/jfrog/gofrog => github.com/jfrog/gofrog v1.2.6-0.20230418122323-2bf299dd6d27 -// replace github.com/jfrog/jfrog-client-go => github.com/jfrog/jfrog-client-go v1.28.1-0.20230803140217-0a5f43783ae8 +replace github.com/jfrog/jfrog-client-go => github.com/jfrog/jfrog-client-go v1.28.1-0.20230830130057-df2d2a80b555 diff --git a/go.sum b/go.sum index 18ca77ea6..d00b21ab6 100644 --- a/go.sum +++ b/go.sum @@ -241,10 +241,10 @@ github.com/jfrog/build-info-go v1.9.9 h1:YMA9okHawBNL8SrCWzqULSf5M4W+YnWyUhmkWSj github.com/jfrog/build-info-go v1.9.9/go.mod h1:t31QRpH5xUJKw8XkQlAA+Aq7aanyS1rrzpcK8xSNVts= github.com/jfrog/gofrog v1.3.0 h1:o4zgsBZE4QyDbz2M7D4K6fXPTBJht+8lE87mS9bw7Gk= github.com/jfrog/gofrog v1.3.0/go.mod h1:IFMc+V/yf7rA5WZ74CSbXe+Lgf0iApEQLxRZVzKRUR0= -github.com/jfrog/jfrog-cli-core/v2 v2.41.4 h1:+V35NN+UaKl6ZFSjAyZFZ4VijCgsORnGsHug02DROdE= -github.com/jfrog/jfrog-cli-core/v2 v2.41.4/go.mod h1:Mi3WFUzG2CU6tlLpGsMNRaKkhH/tIMuci4tjnPZ9S3M= -github.com/jfrog/jfrog-client-go v1.31.6 h1:uWuyT4BDm9s5ES6oDTBny9Gl6yf8iKFjcbmHSHQZrDc= -github.com/jfrog/jfrog-client-go v1.31.6/go.mod h1:icb00ZJN/mMMNkQduHDkzpqsXH9Flwi3f3COYexq3Nc= +github.com/jfrog/jfrog-cli-core/v2 v2.31.1-0.20230830130857-c5a2b11b52be h1:MjbSKQy937o0WFBKCXtvkX4EUSPCaA1LIhGISJUjYbU= +github.com/jfrog/jfrog-cli-core/v2 v2.31.1-0.20230830130857-c5a2b11b52be/go.mod h1:kaFzB3X83/jdzMcuGOYOaqnlz5MVTnDYt/asrOsCv18= +github.com/jfrog/jfrog-client-go v1.28.1-0.20230830130057-df2d2a80b555 h1:yaF5J4LNk+ws5+j+BFMJ43NMqpKuCtF7dUfCeGLttl8= +github.com/jfrog/jfrog-client-go v1.28.1-0.20230830130057-df2d2a80b555/go.mod h1:icb00ZJN/mMMNkQduHDkzpqsXH9Flwi3f3COYexq3Nc= github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU= github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk= github.com/jszwec/csvutil v1.8.0 h1:G7vS2LGdpZZDH1HmHeNbxOaJ/ZnJlpwGFvOkTkJzzNk= diff --git a/lifecycle/cli.go b/lifecycle/cli.go index 8caa332d2..647963c10 100644 --- a/lifecycle/cli.go +++ b/lifecycle/cli.go @@ -8,8 +8,10 @@ import ( coreConfig "github.com/jfrog/jfrog-cli-core/v2/utils/config" "github.com/jfrog/jfrog-cli/docs/common" rbCreate "github.com/jfrog/jfrog-cli/docs/lifecycle/create" + rbDistribute "github.com/jfrog/jfrog-cli/docs/lifecycle/distribute" rbPromote "github.com/jfrog/jfrog-cli/docs/lifecycle/promote" "github.com/jfrog/jfrog-cli/utils/cliutils" + "github.com/jfrog/jfrog-cli/utils/distribution" "github.com/jfrog/jfrog-client-go/utils" "github.com/jfrog/jfrog-client-go/utils/errorutils" "github.com/urfave/cli" @@ -43,6 +45,19 @@ func GetCommands() []cli.Command { Category: lcCategory, Action: promote, }, + { + Name: "release-bundle-distribute", + Aliases: []string{"rbd"}, + Flags: cliutils.GetCommandFlags(cliutils.ReleaseBundleDistribute), + Usage: rbDistribute.GetDescription(), + HelpName: coreCommon.CreateUsage("rbd", rbDistribute.GetDescription(), rbDistribute.Usage), + UsageText: rbDistribute.GetArguments(), + ArgsUsage: common.CreateEnvVars(), + BashComplete: coreCommon.CreateBashCompletionFunc(), + Category: lcCategory, + Hidden: true, + Action: distribute, + }, }) } @@ -77,7 +92,7 @@ func create(c *cli.Context) (err error) { return } - createCmd := lifecycle.NewReleaseBundleCreate().SetServerDetails(lcDetails).SetReleaseBundleName(c.Args().Get(0)). + createCmd := lifecycle.NewReleaseBundleCreateCommand().SetServerDetails(lcDetails).SetReleaseBundleName(c.Args().Get(0)). SetReleaseBundleVersion(c.Args().Get(1)).SetSigningKeyName(c.String(cliutils.SigningKey)).SetSync(c.Bool(cliutils.Sync)). SetReleaseBundleProject(cliutils.GetProject(c)).SetBuildsSpecPath(c.String(cliutils.Builds)). SetReleaseBundlesSpecPath(c.String(cliutils.ReleaseBundles)) @@ -102,12 +117,51 @@ func promote(c *cli.Context) error { return err } - createCmd := lifecycle.NewReleaseBundlePromote().SetServerDetails(lcDetails).SetReleaseBundleName(c.Args().Get(0)). + createCmd := lifecycle.NewReleaseBundlePromoteCommand().SetServerDetails(lcDetails).SetReleaseBundleName(c.Args().Get(0)). SetReleaseBundleVersion(c.Args().Get(1)).SetEnvironment(c.Args().Get(2)).SetSigningKeyName(c.String(cliutils.SigningKey)). SetSync(c.Bool(cliutils.Sync)).SetReleaseBundleProject(cliutils.GetProject(c)).SetOverwrite(c.Bool(cliutils.Overwrite)) return commands.Exec(createCmd) } +func distribute(c *cli.Context) error { + if err := validateDistributeCommand(c); err != nil { + return err + } + + lcDetails, err := createLifecycleDetailsByFlags(c) + if err != nil { + return err + } + distributionRules, _, params, err := distribution.InitReleaseBundleDistributeCmd(c) + if err != nil { + return err + } + + distributeCmd := lifecycle.NewReleaseBundleDistributeCommand() + distributeCmd.SetServerDetails(lcDetails). + SetDistributeBundleParams(params). + SetDistributionRules(distributionRules). + SetDryRun(c.Bool("dry-run")). + SetAutoCreateRepo(c.Bool(cliutils.CreateRepo)). + SetPathMappingPattern(c.String(cliutils.PathMappingPattern)). + SetPathMappingTarget(c.String(cliutils.PathMappingTarget)) + return commands.Exec(distributeCmd) +} + +func validateDistributeCommand(c *cli.Context) error { + if err := distribution.ValidateReleaseBundleDistributeCmd(c); err != nil { + return err + } + + mappingPatternProvided := c.IsSet(cliutils.PathMappingPattern) + mappingTargetProvided := c.IsSet(cliutils.PathMappingTarget) + if (mappingPatternProvided && !mappingTargetProvided) || + (!mappingPatternProvided && mappingTargetProvided) { + return errorutils.CheckErrorf("the options --%s and --%s must be provided together", cliutils.PathMappingPattern, cliutils.PathMappingTarget) + } + return nil +} + func assertSigningKeyProvided(c *cli.Context) error { if c.String(cliutils.SigningKey) == "" { return errorutils.CheckErrorf("the --%s option is mandatory", cliutils.SigningKey) diff --git a/lifecycle_test.go b/lifecycle_test.go index 24980c734..c81e2beba 100644 --- a/lifecycle_test.go +++ b/lifecycle_test.go @@ -23,14 +23,14 @@ import ( ) const ( - rbMinVersion = "7.45.0" - gpgKeyPairName = "lc-tests-key-pair" - lcTestdataPath = "lifecycle" - releaseBundlesSpec = "release-bundles-spec.json" - buildsSpec12 = "builds-spec-1-2.json" - buildsSpec3 = "builds-spec-3.json" - prodEnvironment = "PROD" - number1, number2, number3 = "111", "222", "333" + artifactoryLifecycleMinVersion = "7.65.0" + gpgKeyPairName = "lc-tests-key-pair" + lcTestdataPath = "lifecycle" + releaseBundlesSpec = "release-bundles-spec.json" + buildsSpec12 = "builds-spec-1-2.json" + buildsSpec3 = "builds-spec-3.json" + prodEnvironment = "PROD" + number1, number2, number3 = "111", "222", "333" ) var ( @@ -47,11 +47,11 @@ func TestLifecycle(t *testing.T) { deleteBuilds := uploadBuilds(t) defer deleteBuilds() - // Create release bundles from builds synchronously. + // Create release bundle from builds synchronously. createRb(t, buildsSpec12, cliutils.Builds, tests.LcRbName1, number1, true) defer deleteReleaseBundle(t, lcManager, tests.LcRbName1, number1) - // Create release bundles from builds asynchronously and assert status. + // Create release bundle from builds asynchronously and assert status. createRb(t, buildsSpec3, cliutils.Builds, tests.LcRbName2, number2, false) defer deleteReleaseBundle(t, lcManager, tests.LcRbName2, number2) assertStatusCompleted(t, lcManager, tests.LcRbName2, number2, "") @@ -67,6 +67,11 @@ func TestLifecycle(t *testing.T) { searchSpec, err := tests.CreateSpec(tests.SearchAllProdRepo) assert.NoError(t, err) inttestutils.VerifyExistInArtifactory(tests.GetExpectedLifecycleArtifacts(), searchSpec, serverDetails, t) + + distributeRb(t) + // Verify the artifacts were distributed correctly by the provided path mappings. + expected := append(tests.GetExpectedLifecycleArtifacts(), tests.GetExpectedLifecycleMappingArtifacts()...) + inttestutils.VerifyExistInArtifactory(expected, searchSpec, serverDetails, t) } func uploadBuilds(t *testing.T) func() { @@ -80,13 +85,13 @@ func uploadBuilds(t *testing.T) func() { } } -func createRb(t *testing.T, specName, sourceOption, buildName, buildNumber string, sync bool) { +func createRb(t *testing.T, specName, sourceOption, rbName, rbVersion string, sync bool) { specFile, err := getSpecFile(specName) assert.NoError(t, err) argsAndOptions := []string{ "rbc", - buildName, - buildNumber, + rbName, + rbVersion, getOption(sourceOption, specFile), getOption(cliutils.SigningKey, gpgKeyPairName), } @@ -97,6 +102,16 @@ func createRb(t *testing.T, specName, sourceOption, buildName, buildNumber strin assert.NoError(t, lcCli.Exec(argsAndOptions...)) } +func distributeRb(t *testing.T) { + distributionRulesPath := filepath.Join(tests.GetTestResourcesPath(), "distribution", tests.DistributionRules) + assert.NoError(t, lcCli.Exec( + "rbd", tests.LcRbName3, number3, + getOption(cliutils.DistRules, distributionRulesPath), + getOption(cliutils.PathMappingPattern, tests.RtProdRepo+"/(*)"), + getOption(cliutils.PathMappingTarget, tests.RtProdRepo+"/target/{1}"), + )) +} + func getOption(option, value string) string { return fmt.Sprintf("--%s=%s", option, value) } @@ -183,7 +198,7 @@ func initLifecycleTest(t *testing.T) { if !*tests.TestLifecycle { t.Skip("Skipping lifecycle test. To run release bundle test add the '-test.lc=true' option.") } - validateArtifactoryVersion(t, rbMinVersion) + validateArtifactoryVersion(t, artifactoryLifecycleMinVersion) if !isLifecycleSupported(t) { t.Skip("Skipping lifecycle test because the functionality is not enabled on the provided JPD.") diff --git a/utils/cliutils/commandsflags.go b/utils/cliutils/commandsflags.go index 625841bc1..24bc36d46 100644 --- a/utils/cliutils/commandsflags.go +++ b/utils/cliutils/commandsflags.go @@ -131,8 +131,9 @@ const ( TransferInstall = "transfer-plugin-install" // Lifecycle commands keys - ReleaseBundleCreate = "release-bundle-create" - ReleaseBundlePromote = "release-bundle-promote" + ReleaseBundleCreate = "release-bundle-create" + ReleaseBundlePromote = "release-bundle-promote" + ReleaseBundleDistribute = "release-bundle-distribute" // *** Artifactory Commands' flags *** // Base flags @@ -424,14 +425,16 @@ const ( desc = "desc" releaseNotesPath = "release-notes-path" releaseNotesSyntax = "release-notes-syntax" - distRules = "dist-rules" - site = "site" - city = "city" - countryCodes = "country-codes" - sync = "sync" - maxWaitMinutes = "max-wait-minutes" deleteFromDist = "delete-from-dist" - createRepo = "create-repo" + + // Common release-bundle-* v1&v2 flags + DistRules = "dist-rules" + site = "site" + city = "city" + countryCodes = "country-codes" + sync = "sync" + maxWaitMinutes = "max-wait-minutes" + CreateRepo = "create-repo" // *** Xray Commands' flags *** // Base flags @@ -542,17 +545,22 @@ const ( InstallPluginHomeDir = "home-dir" // Unique lifecycle flags - lifecyclePrefix = "lc-" - lcUrl = lifecyclePrefix + url - lcSync = lifecyclePrefix + Sync - lcProject = lifecyclePrefix + project - Builds = "builds" - lcBuilds = lifecyclePrefix + Builds - ReleaseBundles = "release-bundles" - lcReleaseBundles = lifecyclePrefix + ReleaseBundles - SigningKey = "signing-key" - lcSigningKey = lifecyclePrefix + SigningKey - lcOverwrite = lifecyclePrefix + Overwrite + lifecyclePrefix = "lc-" + lcUrl = lifecyclePrefix + url + lcSync = lifecyclePrefix + Sync + lcProject = lifecyclePrefix + project + Builds = "builds" + lcBuilds = lifecyclePrefix + Builds + ReleaseBundles = "release-bundles" + lcReleaseBundles = lifecyclePrefix + ReleaseBundles + SigningKey = "signing-key" + lcSigningKey = lifecyclePrefix + SigningKey + lcOverwrite = lifecyclePrefix + Overwrite + PathMappingPattern = "mapping-pattern" + lcPathMappingPattern = lifecyclePrefix + PathMappingPattern + PathMappingTarget = "mapping-target" + lcPathMappingTarget = lifecyclePrefix + PathMappingTarget + lcDryRun = lifecyclePrefix + dryRun ) var flagsMap = map[string]cli.Flag{ @@ -1237,9 +1245,9 @@ var flagsMap = map[string]cli.Flag{ Name: repo, Usage: "[Optional] A repository name at source Artifactory to store release bundle artifacts in. If not provided, Artifactory will use the default one.` `", }, - distRules: cli.StringFlag{ - Name: distRules, - Usage: "Path to distribution rules.` `", + DistRules: cli.StringFlag{ + Name: DistRules, + Usage: "[Optional] Path to distribution rules.` `", }, site: cli.StringFlag{ Name: site, @@ -1509,8 +1517,8 @@ var flagsMap = map[string]cli.Flag{ Name: "format", Hidden: true, }, - createRepo: cli.BoolFlag{ - Name: createRepo, + CreateRepo: cli.BoolFlag{ + Name: CreateRepo, Usage: "[Default: false] Set to true to create the repository on the edge if it does not exist.` `", }, Filestore: cli.BoolFlag{ @@ -1613,6 +1621,19 @@ var flagsMap = map[string]cli.Flag{ Name: Overwrite, Usage: "[Default: false] Set to true to replace artifacts with the same name but a different checksum if such already exist at the promotion targets. By default, the promotion is stopped in a case of such conflict.` `", }, + lcPathMappingPattern: cli.StringFlag{ + Name: PathMappingPattern, + Usage: "[Optional] Specify along with '" + PathMappingTarget + "' to distribute artifacts to a different path on the edge node. You can use wildcards to specify multiple artifacts.` `", + }, + lcPathMappingTarget: cli.StringFlag{ + Name: PathMappingTarget, + Usage: "[Optional] The target path for distributed artifacts on the edge node. If not specified, the artifacts will have the same path and name on the edge node, as on the source Artifactory server. " + + "For flexibility in specifying the distribution path, you can include placeholders in the form of {1}, {2} which are replaced by corresponding tokens in the pattern path that are enclosed in parenthesis.` `", + }, + lcDryRun: cli.BoolFlag{ + Name: dryRun, + Usage: "[Default: false] Set to true to only simulate the distribution of the release bundle.` `", + }, } var commandFlags = map[string][]string{ @@ -1836,11 +1857,11 @@ var commandFlags = map[string][]string{ InsecureTls, rbDetailedSummary, }, ReleaseBundleV1Distribute: { - distUrl, user, password, accessToken, serverId, rbDryRun, distRules, - site, city, countryCodes, sync, maxWaitMinutes, InsecureTls, createRepo, + distUrl, user, password, accessToken, serverId, rbDryRun, DistRules, + site, city, countryCodes, sync, maxWaitMinutes, InsecureTls, CreateRepo, }, ReleaseBundleV1Delete: { - distUrl, user, password, accessToken, serverId, rbDryRun, distRules, + distUrl, user, password, accessToken, serverId, rbDryRun, DistRules, site, city, countryCodes, sync, maxWaitMinutes, InsecureTls, deleteFromDist, deleteQuiet, }, TemplateConsumer: { @@ -1897,6 +1918,10 @@ var commandFlags = map[string][]string{ ReleaseBundlePromote: { lcUrl, user, password, accessToken, serverId, lcSigningKey, lcSync, lcProject, lcOverwrite, }, + ReleaseBundleDistribute: { + lcUrl, user, password, accessToken, serverId, lcDryRun, DistRules, site, city, countryCodes, + InsecureTls, CreateRepo, lcPathMappingPattern, lcPathMappingTarget, + }, // Xray's commands OfflineUpdate: { licenseId, from, to, Version, target, Stream, Periodic, diff --git a/utils/distribution/distribute.go b/utils/distribution/distribute.go new file mode 100644 index 000000000..bbc82bae9 --- /dev/null +++ b/utils/distribution/distribute.go @@ -0,0 +1,52 @@ +package distribution + +import ( + "github.com/jfrog/jfrog-cli-core/v2/common/spec" + "github.com/jfrog/jfrog-cli/utils/cliutils" + distributionUtils "github.com/jfrog/jfrog-client-go/utils/distribution" + "github.com/urfave/cli" +) + +func CreateDefaultDistributionRules(c *cli.Context) *spec.DistributionRules { + return &spec.DistributionRules{ + DistributionRules: []spec.DistributionRule{{ + SiteName: c.String("site"), + CityName: c.String("city"), + CountryCodes: cliutils.GetStringsArrFlagValue(c, "country-codes"), + }}, + } +} + +func ValidateReleaseBundleDistributeCmd(c *cli.Context) error { + if c.NArg() != 2 { + return cliutils.WrongNumberOfArgumentsHandler(c) + } + if c.IsSet("max-wait-minutes") && !c.IsSet("sync") { + return cliutils.PrintHelpAndReturnError("The --max-wait-minutes option can't be used without --sync", c) + } + + if c.IsSet("dist-rules") && (c.IsSet("site") || c.IsSet("city") || c.IsSet("country-code")) { + return cliutils.PrintHelpAndReturnError("The --dist-rules option can't be used with --site, --city or --country-code", c) + } + + return nil +} + +func InitReleaseBundleDistributeCmd(c *cli.Context) (distributionRules *spec.DistributionRules, maxWaitMinutes int, params distributionUtils.DistributionParams, err error) { + if c.IsSet("dist-rules") { + distributionRules, err = spec.CreateDistributionRulesFromFile(c.String("dist-rules")) + if err != nil { + return + } + } else { + distributionRules = CreateDefaultDistributionRules(c) + } + + maxWaitMinutes, err = cliutils.GetIntFlagValue(c, "max-wait-minutes", 60) + if err != nil { + return + } + + params = distributionUtils.NewDistributeReleaseBundleParams(c.Args().Get(0), c.Args().Get(1)) + return +} diff --git a/utils/tests/consts.go b/utils/tests/consts.go index 8373be6d7..f415aa1f0 100644 --- a/utils/tests/consts.go +++ b/utils/tests/consts.go @@ -2099,6 +2099,20 @@ func GetExpectedLifecycleArtifacts() []string { } } +func GetExpectedLifecycleMappingArtifacts() []string { + return []string{ + RtProdRepo + "/target/a1.in", + RtProdRepo + "/target/a2.in", + RtProdRepo + "/target/a3.in", + RtProdRepo + "/target/b1.in", + RtProdRepo + "/target/b2.in", + RtProdRepo + "/target/b3.in", + RtProdRepo + "/target/c1.in", + RtProdRepo + "/target/c2.in", + RtProdRepo + "/target/c3.in", + } +} + func GetGoPublishWithExclusionsExpectedRepoGo() []string { var expected = []string{ GoRepo + "/github.com/jfrog/dependency/@v/v1.1.1.info", diff --git a/utils/tests/utils.go b/utils/tests/utils.go index d5ab82381..19540b144 100644 --- a/utils/tests/utils.go +++ b/utils/tests/utils.go @@ -106,7 +106,7 @@ func init() { TestXray = flag.Bool("test.xray", false, "Test Xray") TestAccess = flag.Bool("test.access", false, "Test Access") TestTransfer = flag.Bool("test.transfer", false, "Test files transfer") - TestLifecycle = flag.Bool("test.lc", false, "Test lifecycle") + TestLifecycle = flag.Bool("test.lifecycle", false, "Test lifecycle") ContainerRegistry = flag.String("test.containerRegistry", "localhost:8082", "Container registry") HideUnitTestLog = flag.Bool("test.hideUnitTestLog", false, "Hide unit tests logs and print it in a file") InstallDataTransferPlugin = flag.Bool("test.installDataTransferPlugin", false, "Install data-transfer plugin on the source Artifactory server") From bd082a1b70efa5163998eb5c665aca2b0e5d67fe Mon Sep 17 00:00:00 2001 From: Robi Nino Date: Wed, 30 Aug 2023 16:41:53 +0300 Subject: [PATCH 5/5] Skip lifecycle tests (#2173) --- lifecycle_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lifecycle_test.go b/lifecycle_test.go index c81e2beba..5a1516df8 100644 --- a/lifecycle_test.go +++ b/lifecycle_test.go @@ -23,7 +23,7 @@ import ( ) const ( - artifactoryLifecycleMinVersion = "7.65.0" + artifactoryLifecycleMinVersion = "7.68.3" gpgKeyPairName = "lc-tests-key-pair" lcTestdataPath = "lifecycle" releaseBundlesSpec = "release-bundles-spec.json"