diff --git a/.github/workflows/accessTests.yml b/.github/workflows/accessTests.yml index f1f9d450f..2fd90cf55 100644 --- a/.github/workflows/accessTests.yml +++ b/.github/workflows/accessTests.yml @@ -27,13 +27,13 @@ jobs: with: go-version: 1.20.x - name: Go Cache - uses: actions/cache@v3 + uses: actions/cache@v4 with: path: ~/go/pkg/mod key: ${{ runner.os }}-go-${{ hashFiles('**/go.sum') }} restore-keys: ${{ runner.os }}-go- - name: Checkout code - uses: actions/checkout@v3 + uses: actions/checkout@v4 with: ref: ${{ github.event.pull_request.head.sha }} - name: Run Access tests diff --git a/.github/workflows/analysis.yml b/.github/workflows/analysis.yml index ccc237c65..c8f6e67b4 100644 --- a/.github/workflows/analysis.yml +++ b/.github/workflows/analysis.yml @@ -23,11 +23,11 @@ jobs: with: go-version: 1.20.x - name: Checkout code - uses: actions/checkout@v3 + uses: actions/checkout@v4 with: ref: ${{ github.event.pull_request.head.sha }} - name: Go Cache - uses: actions/cache@v3 + uses: actions/cache@v4 with: path: ~/go/pkg/mod key: ${{ runner.os }}-go-${{ hashFiles('**/go.sum') }} @@ -40,7 +40,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout Source - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: Install Go uses: actions/setup-go@v3 with: @@ -56,7 +56,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout Source - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: Install Go uses: actions/setup-go@v3 with: @@ -71,7 +71,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout Source - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: Run ShellCheck uses: ludeeus/action-shellcheck@master diff --git a/.github/workflows/artifactoryTests.yml b/.github/workflows/artifactoryTests.yml index 440323b26..37ffed60b 100644 --- a/.github/workflows/artifactoryTests.yml +++ b/.github/workflows/artifactoryTests.yml @@ -28,11 +28,11 @@ jobs: with: go-version: 1.20.x - name: Checkout code - uses: actions/checkout@v3 + uses: actions/checkout@v4 with: ref: ${{ github.event.pull_request.head.sha }} - name: Go Cache - uses: actions/cache@v3 + uses: actions/cache@v4 with: path: ~/go/pkg/mod key: ${{ runner.os }}-go-${{ hashFiles('**/go.sum') }} diff --git a/.github/workflows/distributionTests.yml b/.github/workflows/distributionTests.yml index 7804ad677..80670b423 100644 --- a/.github/workflows/distributionTests.yml +++ b/.github/workflows/distributionTests.yml @@ -27,13 +27,13 @@ jobs: with: go-version: 1.20.x - name: Go Cache - uses: actions/cache@v3 + uses: actions/cache@v4 with: path: ~/go/pkg/mod key: ${{ runner.os }}-go-${{ hashFiles('**/go.sum') }} restore-keys: ${{ runner.os }}-go- - name: Checkout code - uses: actions/checkout@v3 + uses: actions/checkout@v4 with: ref: ${{ github.event.pull_request.head.sha }} - name: Run Distribution tests diff --git a/.github/workflows/dockerTests.yml b/.github/workflows/dockerTests.yml index 1a30ece44..0d218b16f 100644 --- a/.github/workflows/dockerTests.yml +++ b/.github/workflows/dockerTests.yml @@ -23,11 +23,11 @@ jobs: with: go-version: 1.20.x - name: Checkout code - uses: actions/checkout@v3 + uses: actions/checkout@v4 with: ref: ${{ github.event.pull_request.head.sha }} - name: Go Cache - uses: actions/cache@v3 + uses: actions/cache@v4 with: path: ~/go/pkg/mod key: ${{ runner.os }}-go-${{ hashFiles('**/go.sum') }} diff --git a/.github/workflows/goTests.yml b/.github/workflows/goTests.yml index 1a74d2221..3384b039d 100644 --- a/.github/workflows/goTests.yml +++ b/.github/workflows/goTests.yml @@ -28,11 +28,11 @@ jobs: with: go-version: 1.20.x - name: Checkout code - uses: actions/checkout@v3 + uses: actions/checkout@v4 with: ref: ${{ github.event.pull_request.head.sha }} - name: Go Cache - uses: actions/cache@v3 + uses: actions/cache@v4 with: path: ~/go/pkg/mod key: ${{ runner.os }}-go-${{ hashFiles('**/go.sum') }} diff --git a/.github/workflows/gradleTests.yml b/.github/workflows/gradleTests.yml index edb2c50f9..4c0f0dff2 100644 --- a/.github/workflows/gradleTests.yml +++ b/.github/workflows/gradleTests.yml @@ -34,11 +34,11 @@ jobs: with: gradle-version: ${{ matrix.gradle-version }} - name: Checkout code - uses: actions/checkout@v3 + uses: actions/checkout@v4 with: ref: ${{ github.event.pull_request.head.sha }} - name: Go Cache - uses: actions/cache@v3 + uses: actions/cache@v4 with: path: ~/go/pkg/mod key: ${{ runner.os }}-go-${{ hashFiles('**/go.sum') }} diff --git a/.github/workflows/lifecycleTests.yml b/.github/workflows/lifecycleTests.yml index 0f073b2bd..491b7a618 100644 --- a/.github/workflows/lifecycleTests.yml +++ b/.github/workflows/lifecycleTests.yml @@ -27,17 +27,17 @@ jobs: with: go-version: 1.20.x - name: Checkout code - uses: actions/checkout@v3 + uses: actions/checkout@v4 with: ref: ${{ github.event.pull_request.head.sha }} - name: Go Cache - uses: actions/cache@v3 + uses: actions/cache@v4 with: path: ~/go/pkg/mod key: ${{ runner.os }}-go-${{ hashFiles('**/go.sum') }} restore-keys: ${{ runner.os }}-go- - name: Checkout code - uses: actions/checkout@v3 + uses: actions/checkout@v4 with: ref: ${{ github.event.pull_request.head.sha }} - name: Run Lifecycle tests diff --git a/.github/workflows/mavenTests.yml b/.github/workflows/mavenTests.yml index a7f55587c..a4ff959fc 100644 --- a/.github/workflows/mavenTests.yml +++ b/.github/workflows/mavenTests.yml @@ -27,11 +27,11 @@ jobs: with: go-version: 1.20.x - name: Checkout code - uses: actions/checkout@v3 + uses: actions/checkout@v4 with: ref: ${{ github.event.pull_request.head.sha }} - name: Go Cache - uses: actions/cache@v3 + uses: actions/cache@v4 with: path: ~/go/pkg/mod key: ${{ runner.os }}-go-${{ hashFiles('**/go.sum') }} diff --git a/.github/workflows/npmTests.yml b/.github/workflows/npmTests.yml index 6d0b79663..3c0ae0d87 100644 --- a/.github/workflows/npmTests.yml +++ b/.github/workflows/npmTests.yml @@ -31,11 +31,11 @@ jobs: with: node-version: "16" - name: Checkout code - uses: actions/checkout@v3 + uses: actions/checkout@v4 with: ref: ${{ github.event.pull_request.head.sha }} - name: Go Cache - uses: actions/cache@v3 + uses: actions/cache@v4 with: path: ~/go/pkg/mod key: ${{ runner.os }}-go-${{ hashFiles('**/go.sum') }} diff --git a/.github/workflows/nugetTests.yml b/.github/workflows/nugetTests.yml index 262dabb50..dcc4d245e 100644 --- a/.github/workflows/nugetTests.yml +++ b/.github/workflows/nugetTests.yml @@ -31,15 +31,15 @@ jobs: with: nuget-version: 6.x - name: Install dotnet - uses: actions/setup-dotnet@v3 + uses: actions/setup-dotnet@v4 with: dotnet-version: "6.x" - name: Checkout code - uses: actions/checkout@v3 + uses: actions/checkout@v4 with: ref: ${{ github.event.pull_request.head.sha }} - name: Go Cache - uses: actions/cache@v3 + uses: actions/cache@v4 with: path: ~/go/pkg/mod key: ${{ runner.os }}-go-${{ hashFiles('**/go.sum') }} diff --git a/.github/workflows/pluginsTests.yml b/.github/workflows/pluginsTests.yml index a91275a45..b8aa9523b 100644 --- a/.github/workflows/pluginsTests.yml +++ b/.github/workflows/pluginsTests.yml @@ -27,11 +27,11 @@ jobs: with: go-version: 1.20.x - name: Checkout code - uses: actions/checkout@v3 + uses: actions/checkout@v4 with: ref: ${{ github.event.pull_request.head.sha }} - name: Go Cache - uses: actions/cache@v3 + uses: actions/cache@v4 with: path: ~/go/pkg/mod key: ${{ runner.os }}-go-${{ hashFiles('**/go.sum') }} diff --git a/.github/workflows/podmanTests.yml b/.github/workflows/podmanTests.yml index 87b6244f3..35386f228 100644 --- a/.github/workflows/podmanTests.yml +++ b/.github/workflows/podmanTests.yml @@ -23,11 +23,11 @@ jobs: with: go-version: 1.20.x - name: Checkout code - uses: actions/checkout@v3 + uses: actions/checkout@v4 with: ref: ${{ github.event.pull_request.head.sha }} - name: Go Cache - uses: actions/cache@v3 + uses: actions/cache@v4 with: path: ~/go/pkg/mod key: ${{ runner.os }}-go-${{ hashFiles('**/go.sum') }} diff --git a/.github/workflows/pythonTests.yml b/.github/workflows/pythonTests.yml index d9aed44fa..692f261bc 100644 --- a/.github/workflows/pythonTests.yml +++ b/.github/workflows/pythonTests.yml @@ -36,11 +36,11 @@ jobs: if: ${{ matrix.suite == 'pipenv' }} run: python -m pip install pipenv - name: Checkout code - uses: actions/checkout@v3 + uses: actions/checkout@v4 with: ref: ${{ github.event.pull_request.head.sha }} - name: Go Cache - uses: actions/cache@v3 + uses: actions/cache@v4 with: path: ~/go/pkg/mod key: ${{ runner.os }}-go-${{ hashFiles('**/go.sum') }} diff --git a/.github/workflows/scriptTests.yml b/.github/workflows/scriptTests.yml index 11e8b6f47..b579a6c6c 100644 --- a/.github/workflows/scriptTests.yml +++ b/.github/workflows/scriptTests.yml @@ -15,26 +15,33 @@ jobs: name: Script tests (${{ matrix.suite.os }}) defaults: run: - shell: bash + shell: sh strategy: fail-fast: false matrix: suite: - - os: "ubuntu" + - os: "ubuntu-latest" + + - os: "ubuntu-20.04" + + - os: "macos-latest" - - os: "macos" + - os: "macos-11" + + - os: "windows-latest" + osSuffix: ".exe" - - os: "windows" + - os: "windows-2019" osSuffix: ".exe" - runs-on: ${{ matrix.suite.os }}-latest + runs-on: ${{ matrix.suite.os }} steps: - name: Checkout code - uses: actions/checkout@v3 + uses: actions/checkout@v4 with: ref: ${{ github.event.pull_request.head.sha }} - name: Go Cache - uses: actions/cache@v3 + uses: actions/cache@v4 with: path: ~/go/pkg/mod key: ${{ runner.os }}-go-${{ hashFiles('**/go.sum') }} @@ -64,13 +71,13 @@ jobs: run: | sh build/build.sh ./jf${{ matrix.suite.osSuffix }} --version - if: ${{ matrix.suite.os != 'windows' }} + if: contains( matrix.suite.os, 'windows') - name: Test Build CLI - bat run: | build/build.bat ./jf${{ matrix.suite.osSuffix }} --version - if: ${{ matrix.suite.os == 'windows' }} + if: contains( matrix.suite.os, 'windows') # Prior to the release, we set the new version in the package.json files, introducing the prereleased version. # This adjustment may result in an attempt to download a version that hasn't been published to releases.jfrog.io yet. diff --git a/.github/workflows/transferTests.yml b/.github/workflows/transferTests.yml index 044c6a2e2..9029fe737 100644 --- a/.github/workflows/transferTests.yml +++ b/.github/workflows/transferTests.yml @@ -23,7 +23,7 @@ jobs: runs-on: ${{ matrix.os }}-latest steps: - name: Checkout code - uses: actions/checkout@v3 + uses: actions/checkout@v4 with: ref: ${{ github.event.pull_request.head.sha }} - name: Install Go @@ -31,7 +31,7 @@ jobs: with: go-version: 1.20.x - name: Go Cache - uses: actions/cache@v3 + uses: actions/cache@v4 with: path: ~/go/pkg/mod key: ${{ runner.os }}-go-${{ hashFiles('**/go.sum') }} @@ -53,7 +53,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout code - uses: actions/checkout@v3 + uses: actions/checkout@v4 with: ref: ${{ github.event.pull_request.head.sha }} - name: Install Go @@ -61,7 +61,7 @@ jobs: with: go-version: 1.20.x - name: Go Cache - uses: actions/cache@v3 + uses: actions/cache@v4 with: path: ~/go/pkg/mod key: ${{ runner.os }}-go-${{ hashFiles('**/go.sum') }} diff --git a/.github/workflows/xrayTests.yml b/.github/workflows/xrayTests.yml deleted file mode 100644 index fdc8a691b..000000000 --- a/.github/workflows/xrayTests.yml +++ /dev/null @@ -1,71 +0,0 @@ -name: Xray 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: - CLI-Tests: - if: contains(github.event.pull_request.labels.*.name, 'safe to test') || github.event_name == 'push' - name: Xray tests (${{ matrix.os }}) - strategy: - fail-fast: false - matrix: - os: [ ubuntu, windows, macos ] - runs-on: ${{ matrix.os }}-latest - env: - GRADLE_OPTS: -Dorg.gradle.daemon=false - steps: - - name: Install Go - uses: actions/setup-go@v3 - with: - go-version: 1.20.x - - name: Install npm - uses: actions/setup-node@v3 - with: - node-version: "16" - - name: Install Java - uses: actions/setup-java@v3 - with: - java-version: "11" - distribution: "adopt" - - name: Install NuGet - uses: nuget/setup-nuget@v1 - with: - nuget-version: 6.x - - name: Install dotnet - uses: actions/setup-dotnet@v3 - with: - dotnet-version: "6.x" - - name: Setup Python3 - uses: actions/setup-python@v4 - with: - python-version: "3.x" - - name: Setup Pipenv - run: python -m pip install pipenv - - name: Setup Poetry - run: python -m pip install poetry - - name: Setup Gradle - uses: gradle/gradle-build-action@v2 - with: - gradle-version: 7.6 - - name: Checkout code - uses: actions/checkout@v3 - with: - ref: ${{ github.event.pull_request.head.sha }} - - - name: Run Xray tests (without Docker Scan) - run: go test -v github.com/jfrog/jfrog-cli --timeout 0 --test.xray --jfrog.url=${{ secrets.PLATFORM_URL }} --jfrog.adminToken=${{ secrets.PLATFORM_ADMIN_TOKEN }} --jfrog.user=${{ secrets.PLATFORM_USER }} --test.containerRegistry=${{ secrets.CONTAINER_REGISTRY }} --ci.runId=${{ runner.os }}-xray - if: ${{ matrix.os != 'ubuntu' }} - - - name: Run Xray tests (with Docker Scan, only on Ubuntu) - run: go test -v github.com/jfrog/jfrog-cli --timeout 0 --test.xray --test.dockerScan --jfrog.url=${{ secrets.PLATFORM_URL }} --jfrog.adminToken=${{ secrets.PLATFORM_ADMIN_TOKEN }} --test.containerRegistry=${{ secrets.CONTAINER_REGISTRY }} --ci.runId=${{ runner.os }}-xray - if: ${{ matrix.os == 'ubuntu' }} diff --git a/Jenkinsfile b/Jenkinsfile index 35e124208..b17de8cce 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -25,10 +25,6 @@ node("docker") { masterBranch = 'v2' devBranch = 'dev' - if (BRANCH?.trim() == 'v1') { - masterBranch = 'v1' - devBranch = 'dev-v1' - } releaseVersion = '' diff --git a/access_test.go b/access_test.go index ba092b1d1..8374c5b65 100644 --- a/access_test.go +++ b/access_test.go @@ -23,7 +23,7 @@ import ( var ( accessDetails *config.ServerDetails - accessCli *tests.JfrogCli + accessCli *coreTests.JfrogCli accessHttpDetails httputils.HttpClientDetails ) @@ -37,7 +37,7 @@ func initAccessCli() { if accessCli != nil { return } - accessCli = tests.NewJfrogCli(execMain, "jfrog", authenticateAccess()) + accessCli = coreTests.NewJfrogCli(execMain, "jfrog", authenticateAccess()) } func InitAccessTests() { @@ -115,7 +115,7 @@ func TestRefreshableAccessTokens(t *testing.T) { defer deleteServerConfig(t) // Upload a file and assert the refreshable tokens were generated. - artifactoryCommandExecutor := tests.NewJfrogCli(execMain, "jfrog rt", "") + artifactoryCommandExecutor := coreTests.NewJfrogCli(execMain, "jfrog rt", "") uploadedFiles := 1 err = uploadWithSpecificServerAndVerify(t, artifactoryCommandExecutor, "testdata/a/a1.in", uploadedFiles) if !assert.NoError(t, err) { @@ -260,7 +260,7 @@ func TestAccessTokenCreate(t *testing.T) { assertNotEmptyIfExpected(t, test.expectedReference, token.ReferenceToken) // Try pinging Artifactory with the new token. - assert.NoError(t, tests.NewJfrogCli(execMain, "jfrog rt", + assert.NoError(t, coreTests.NewJfrogCli(execMain, "jfrog rt", "--url="+*tests.JfrogUrl+tests.ArtifactoryEndpoint+" --access-token="+token.AccessToken).Exec("ping")) }) } diff --git a/artifactory/cli.go b/artifactory/cli.go index bc8a7fded..ef9ce9081 100644 --- a/artifactory/cli.go +++ b/artifactory/cli.go @@ -31,13 +31,14 @@ import ( "github.com/jfrog/jfrog-cli-core/v2/artifactory/utils" containerutils "github.com/jfrog/jfrog-cli-core/v2/artifactory/utils/container" "github.com/jfrog/jfrog-cli-core/v2/common/build" + commonCliUtils "github.com/jfrog/jfrog-cli-core/v2/common/cliutils" "github.com/jfrog/jfrog-cli-core/v2/common/commands" + "github.com/jfrog/jfrog-cli-core/v2/common/progressbar" "github.com/jfrog/jfrog-cli-core/v2/common/project" "github.com/jfrog/jfrog-cli-core/v2/common/spec" corecommon "github.com/jfrog/jfrog-cli-core/v2/docs/common" coreConfig "github.com/jfrog/jfrog-cli-core/v2/utils/config" "github.com/jfrog/jfrog-cli-core/v2/utils/coreutils" - "github.com/jfrog/jfrog-cli-core/v2/utils/ioutils" "github.com/jfrog/jfrog-cli/buildtools" "github.com/jfrog/jfrog-cli/docs/artifactory/accesstokencreate" "github.com/jfrog/jfrog-cli/docs/artifactory/buildadddependencies" @@ -110,7 +111,6 @@ import ( "github.com/jfrog/jfrog-cli/docs/artifactory/yarnconfig" "github.com/jfrog/jfrog-cli/docs/common" "github.com/jfrog/jfrog-cli/utils/cliutils" - "github.com/jfrog/jfrog-cli/utils/progressbar" buildinfocmd "github.com/jfrog/jfrog-client-go/artifactory/buildinfo" "github.com/jfrog/jfrog-client-go/artifactory/services" clientutils "github.com/jfrog/jfrog-client-go/utils" @@ -1823,6 +1823,9 @@ func gitLfsCleanCmd(c *cli.Context) error { } func curlCmd(c *cli.Context) error { + if show, err := cliutils.ShowCmdHelpIfNeeded(c, c.Args()); show || err != nil { + return err + } if c.NArg() < 1 { return cliutils.WrongNumberOfArgumentsHandler(c) } @@ -2679,23 +2682,11 @@ func createDefaultBuildAddDependenciesSpec(c *cli.Context) *spec.SpecFiles { func fixWinPathsForDownloadCmd(uploadSpec *spec.SpecFiles, c *cli.Context) { if coreutils.IsWindows() { for i, file := range uploadSpec.Files { - uploadSpec.Files[i].Target = fixWinPathBySource(file.Target, c.IsSet("spec")) + uploadSpec.Files[i].Target = commonCliUtils.FixWinPathBySource(file.Target, c.IsSet("spec")) } } } -func fixWinPathBySource(path string, fromSpec bool) string { - if strings.Count(path, "/") > 0 { - // Assuming forward slashes - not doubling backslash to allow regexp escaping - return ioutils.UnixToWinPathSeparator(path) - } - if fromSpec { - // Doubling backslash only for paths from spec files (that aren't forward slashed) - return ioutils.DoubleWinPathSeparator(path) - } - return path -} - func createUploadConfiguration(c *cli.Context) (uploadConfiguration *utils.UploadConfiguration, err error) { uploadConfiguration = new(utils.UploadConfiguration) uploadConfiguration.Threads, err = cliutils.GetThreadsCount(c) diff --git a/artifactory_test.go b/artifactory_test.go index 028321b80..bbcd133c9 100644 --- a/artifactory_test.go +++ b/artifactory_test.go @@ -30,9 +30,11 @@ import ( "github.com/jfrog/gofrog/version" "github.com/jfrog/jfrog-cli-core/v2/artifactory/commands/generic" "github.com/jfrog/jfrog-cli-core/v2/artifactory/utils" + commonCliUtils "github.com/jfrog/jfrog-cli-core/v2/common/cliutils" "github.com/jfrog/jfrog-cli-core/v2/common/commands" "github.com/jfrog/jfrog-cli-core/v2/common/project" "github.com/jfrog/jfrog-cli-core/v2/common/spec" + commontests "github.com/jfrog/jfrog-cli-core/v2/common/tests" "github.com/jfrog/jfrog-cli-core/v2/utils/config" "github.com/jfrog/jfrog-cli-core/v2/utils/coreutils" "github.com/jfrog/jfrog-cli-core/v2/utils/dependencies" @@ -68,13 +70,13 @@ import ( const terraformMinArtifactoryVersion = "7.38.4" // JFrog CLI for Artifactory sub-commands (jfrog rt ...) -var artifactoryCli *tests.JfrogCli +var artifactoryCli *coretests.JfrogCli // JFrog CLI for Platform commands (jfrog ...) -var platformCli *tests.JfrogCli +var platformCli *coretests.JfrogCli // JFrog CLI for config command only (doesn't pass the --ssh-passphrase flag) -var configCli *tests.JfrogCli +var configCli *coretests.JfrogCli var serverDetails *config.ServerDetails var artAuth auth.ServiceDetails @@ -126,11 +128,11 @@ func authenticate(configCli bool) string { // A Jfrog CLI to be used to execute a config task. // Removed the ssh-passphrase flag that cannot be passed to with a config command -func createConfigJfrogCLI(cred string) *tests.JfrogCli { +func createConfigJfrogCLI(cred string) *coretests.JfrogCli { if strings.Contains(cred, " --ssh-passphrase=") { cred = strings.ReplaceAll(cred, " --ssh-passphrase="+*tests.JfrogSshPassphrase, "") } - return tests.NewJfrogCli(execMain, "jfrog config", cred) + return coretests.NewJfrogCli(execMain, "jfrog config", cred) } func getArtifactoryTestCredentials() string { @@ -212,7 +214,7 @@ func TestArtifactorySimpleUploadSpecUsingConfig(t *testing.T) { passphrase, err := createServerConfigAndReturnPassphrase(t) defer deleteServerConfig(t) assert.NoError(t, err) - artifactoryCommandExecutor := tests.NewJfrogCli(execMain, "jfrog rt", "") + artifactoryCommandExecutor := coretests.NewJfrogCli(execMain, "jfrog rt", "") specFile, err := tests.CreateSpec(tests.UploadFlatRecursive) assert.NoError(t, err) assert.NoError(t, artifactoryCommandExecutor.Exec("upload", "--spec="+specFile, "--server-id="+tests.ServerId, passphrase)) @@ -349,7 +351,7 @@ func TestArtifactoryDownloadFromVirtual(t *testing.T) { func TestArtifactoryDownloadAndUploadWithProgressBar(t *testing.T) { initArtifactoryTest(t, "") - callback := tests.MockProgressInitialization() + callback := commontests.MockProgressInitialization() defer callback() runRt(t, "upload", "testdata/a/*", tests.RtRepo1, "--flat=false") @@ -793,7 +795,7 @@ func verifyUsersExistInArtifactory(csvFilePath string, t *testing.T) { break } user, password := record[0], record[1] - err = tests.NewJfrogCli(execMain, "jfrog rt", "--url="+serverDetails.ArtifactoryUrl+" --user="+user+" --password="+password).Exec("ping") + err = coretests.NewJfrogCli(execMain, "jfrog rt", "--url="+serverDetails.ArtifactoryUrl+" --user="+user+" --password="+password).Exec("ping") assert.NoError(t, err) } @@ -1805,7 +1807,7 @@ func TestXrayScanBuild(t *testing.T) { initArtifactoryTest(t, "") xrayServerPort := xray.StartXrayMockServer() serverUrl := "--url=http://localhost:" + strconv.Itoa(xrayServerPort) - artifactoryCommandExecutor := tests.NewJfrogCli(execMain, "jfrog rt", serverUrl+getArtifactoryTestCredentials()) + artifactoryCommandExecutor := coretests.NewJfrogCli(execMain, "jfrog rt", serverUrl+getArtifactoryTestCredentials()) assert.NoError(t, artifactoryCommandExecutor.Exec("build-scan", xray.CleanScanBuildName, "3")) cleanArtifactoryTest() @@ -3090,7 +3092,7 @@ func prepareDownloadByBuildWithDependenciesTests(t *testing.T) { runRt(t, "upload", "--spec="+specFileB) // Add build dependencies. - artifactoryCliNoCreds := tests.NewJfrogCli(execMain, "jfrog rt", "") + artifactoryCliNoCreds := coretests.NewJfrogCli(execMain, "jfrog rt", "") assert.NoError(t, artifactoryCliNoCreds.Exec("bad", "--spec="+specFileB, tests.RtBuildName1, buildNumber)) // Publish build. @@ -4222,7 +4224,7 @@ func TestUploadDetailedSummary(t *testing.T) { func createUploadConfiguration() *utils.UploadConfiguration { uploadConfiguration := new(utils.UploadConfiguration) - uploadConfiguration.Threads = cliutils.Threads + uploadConfiguration.Threads = commonCliUtils.Threads return uploadConfiguration } @@ -5098,9 +5100,9 @@ func TestConfigEncryption(t *testing.T) { assert.NoError(t, configCli.Exec("add", "server-2")) // Expect no error after reading it - assert.NoError(t, tests.NewJfrogCli(execMain, "jfrog config", "").Exec("show")) - assert.NoError(t, tests.NewJfrogCli(execMain, "jfrog rt", "--server-id=server-1").Exec("ping")) - assert.NoError(t, tests.NewJfrogCli(execMain, "jfrog rt", "--server-id=server-2").Exec("ping")) + assert.NoError(t, coretests.NewJfrogCli(execMain, "jfrog config", "").Exec("show")) + assert.NoError(t, coretests.NewJfrogCli(execMain, "jfrog rt", "--server-id=server-1").Exec("ping")) + assert.NoError(t, coretests.NewJfrogCli(execMain, "jfrog rt", "--server-id=server-2").Exec("ping")) } func TestConfigEncryptionMissingKey(t *testing.T) { @@ -5194,7 +5196,7 @@ func pipeStdinSecret(t *testing.T, secret string) func() { func TestArtifactoryReplicationCreate(t *testing.T) { initArtifactoryTest(t, "") // Configure server with dummy credentials - err := tests.NewJfrogCli(execMain, "jfrog config", "").Exec("add", tests.ServerId, "--artifactory-url="+*tests.JfrogUrl+tests.ArtifactoryEndpoint, "--user=admin", "--password=password", "--enc-password=false") + err := coretests.NewJfrogCli(execMain, "jfrog config", "").Exec("add", tests.ServerId, "--artifactory-url="+*tests.JfrogUrl+tests.ArtifactoryEndpoint, "--user=admin", "--password=password", "--enc-password=false") defer deleteServerConfig(t) assert.NoError(t, err) @@ -5244,7 +5246,7 @@ func TestArtifactoryAccessTokenCreate(t *testing.T) { *tests.JfrogAccessToken = origAccessToken }() *tests.JfrogAccessToken = "" - err := tests.NewJfrogCli(execMain, "jfrog rt", authenticate(false)).Exec("atc") + err := coretests.NewJfrogCli(execMain, "jfrog rt", authenticate(false)).Exec("atc") assert.NoError(t, err) } else { runRt(t, "atc") @@ -5273,7 +5275,7 @@ func checkAccessToken(t *testing.T, buffer *bytes.Buffer) { assert.NoError(t, err) // Try ping with the new token - err = tests.NewJfrogCli(execMain, "jfrog rt", "--url="+*tests.JfrogUrl+tests.ArtifactoryEndpoint+" --access-token="+token).Exec("ping") + err = coretests.NewJfrogCli(execMain, "jfrog rt", "--url="+*tests.JfrogUrl+tests.ArtifactoryEndpoint+" --access-token="+token).Exec("ping") assert.NoError(t, err) } @@ -5290,7 +5292,7 @@ func TestRefreshableArtifactoryTokens(t *testing.T) { assert.NoError(t, err) // Upload a file and assert the refreshable tokens were generated. - artifactoryCommandExecutor := tests.NewJfrogCli(execMain, "jfrog rt", "") + artifactoryCommandExecutor := coretests.NewJfrogCli(execMain, "jfrog rt", "") uploadedFiles := 1 err = uploadWithSpecificServerAndVerify(t, artifactoryCommandExecutor, "testdata/a/a1.in", uploadedFiles) if err != nil { @@ -5415,7 +5417,7 @@ func assertTokensChanged(t *testing.T, curAccessToken, curRefreshToken string) ( return newAccessToken, newRefreshToken, nil } -func uploadWithSpecificServerAndVerify(t *testing.T, cli *tests.JfrogCli, source string, expectedResults int) error { +func uploadWithSpecificServerAndVerify(t *testing.T, cli *coretests.JfrogCli, source string, expectedResults int) error { err := cli.Exec("upload", source, tests.RtRepo1, "--server-id="+tests.ServerId) if err != nil { assert.NoError(t, err) diff --git a/build/bump-version.sh b/build/bump-version.sh index 03a00bae4..a26781f96 100755 --- a/build/bump-version.sh +++ b/build/bump-version.sh @@ -3,7 +3,9 @@ # Function to get fromVersion from a file populateFromVersion() { build/build.sh - fromVersion=$(./jf -v | tr -d 'jfrog version' | tr -d '\n') + local versionString + versionString=$(./jf -v) + fromVersion=${versionString//[^0-9.+]/} } # Function to validate arguments @@ -32,17 +34,18 @@ validateVersions() { exit 1 fi - echo Bumping version from $fromVersion to $toVersion + echo "Bumping version from $fromVersion to $toVersion" } createBranch() { - branchName=bump-ver-from-$fromVersion-to-$toVersion + branchName="bump-ver-from-$fromVersion-to-$toVersion" + git remote rm upstream git remote add upstream https://github.com/jfrog/jfrog-cli.git git checkout dev git fetch upstream dev - git pull upstream dev + git reset --hard upstream/dev git push - git checkout -b $branchName + git checkout -b "$branchName" } # Function to replace version in file @@ -83,7 +86,7 @@ replaceVersion() { } ## Validate the argument was received. -validateArg +validateArg "$@" ## Read the script argument into the toVersion variable toVersion=$1 @@ -108,4 +111,5 @@ replaceVersion "build/npm/v2-jf/package.json" "\"version\": \"$fromVersion\"," " echo "Version bumped successfully." ## Push the new branch, with the version bump -git push --set-upstream origin $branchName +git commit -m "Bump version from $fromVersion to $toVersion" +git push --set-upstream origin "$branchName" diff --git a/build/getcli/jf.sh b/build/getcli/jf.sh index 7b1f5eeff..752b82191 100644 --- a/build/getcli/jf.sh +++ b/build/getcli/jf.sh @@ -1,29 +1,31 @@ -#!/bin/bash +#!/bin/sh +set -u + +# This script is downloading the OS-specific JFrog CLI binary with the name - 'jf' CLI_OS="na" CLI_MAJOR_VER="v2-jf" VERSION="[RELEASE]" +FILE_NAME="jf" -if [ $# -eq 1 ] -then +if [ $# -eq 1 ]; then VERSION=$1 echo "Downloading version $VERSION of JFrog CLI..." else echo "Downloading the latest version of JFrog CLI..." fi -if echo "${OSTYPE}" | grep -q msys; then +if uname -s | grep -q -E -i "(cygwin|mingw|msys|windows)"; then CLI_OS="windows" - URL="https://releases.jfrog.io/artifactory/jfrog-cli/${CLI_MAJOR_VER}/${VERSION}/jfrog-cli-windows-amd64/jf.exe" - FILE_NAME="jf.exe" -elif echo "${OSTYPE}" | grep -q darwin; then + ARCH="amd64" + FILE_NAME="${FILE_NAME}.exe" +elif uname -s | grep -q -i "darwin"; then CLI_OS="mac" - if [[ $(uname -m) == 'arm64' ]]; then - URL="https://releases.jfrog.io/artifactory/jfrog-cli/${CLI_MAJOR_VER}/${VERSION}/jfrog-cli-mac-arm64/jf" + if [ "$(uname -m)" = "arm64" ]; then + ARCH="arm64" else - URL="https://releases.jfrog.io/artifactory/jfrog-cli/${CLI_MAJOR_VER}/${VERSION}/jfrog-cli-mac-386/jf" + ARCH="386" fi - FILE_NAME="jf" else CLI_OS="linux" MACHINE_TYPE="$(uname -m)" @@ -54,9 +56,9 @@ else exit 1 ;; esac - URL="https://releases.jfrog.io/artifactory/jfrog-cli/${CLI_MAJOR_VER}/${VERSION}/jfrog-cli-${CLI_OS}-${ARCH}/jf" - FILE_NAME="jf" fi +URL="https://releases.jfrog.io/artifactory/jfrog-cli/${CLI_MAJOR_VER}/${VERSION}/jfrog-cli-${CLI_OS}-${ARCH}/${FILE_NAME}" +echo "Downloading from: $URL" curl -XGET "$URL" -L -k -g > $FILE_NAME -chmod u+x $FILE_NAME +chmod +x $FILE_NAME diff --git a/build/getcli/jfrog.sh b/build/getcli/jfrog.sh index 1debb922e..8cef09787 100644 --- a/build/getcli/jfrog.sh +++ b/build/getcli/jfrog.sh @@ -1,29 +1,31 @@ -#!/bin/bash +#!/bin/sh +set -u + +# This script is downloading the OS-specific JFrog CLI binary with the name - 'jfrog' CLI_OS="na" CLI_MAJOR_VER="v2" VERSION="[RELEASE]" +FILE_NAME="jfrog" -if [ $# -eq 1 ] -then +if [ $# -eq 1 ]; then VERSION=$1 echo "Downloading version $VERSION of JFrog CLI..." else echo "Downloading the latest version of JFrog CLI..." fi -if echo "${OSTYPE}" | grep -q msys; then +if uname -s | grep -q -E -i "(cygwin|mingw|msys|windows)"; then CLI_OS="windows" - URL="https://releases.jfrog.io/artifactory/jfrog-cli/${CLI_MAJOR_VER}/${VERSION}/jfrog-cli-windows-amd64/jfrog.exe" - FILE_NAME="jfrog.exe" -elif echo "${OSTYPE}" | grep -q darwin; then + ARCH="amd64" + FILE_NAME="${FILE_NAME}.exe" +elif uname -s | grep -q -i "darwin"; then CLI_OS="mac" - if [[ $(uname -m) == 'arm64' ]]; then - URL="https://releases.jfrog.io/artifactory/jfrog-cli/${CLI_MAJOR_VER}/${VERSION}/jfrog-cli-mac-arm64/jfrog" + if [ "$(uname -m)" = "arm64" ]; then + ARCH="arm64" else - URL="https://releases.jfrog.io/artifactory/jfrog-cli/${CLI_MAJOR_VER}/${VERSION}/jfrog-cli-mac-386/jfrog" + ARCH="386" fi - FILE_NAME="jfrog" else CLI_OS="linux" MACHINE_TYPE="$(uname -m)" @@ -54,9 +56,9 @@ else exit 1 ;; esac - URL="https://releases.jfrog.io/artifactory/jfrog-cli/${CLI_MAJOR_VER}/${VERSION}/jfrog-cli-${CLI_OS}-${ARCH}/jfrog" - FILE_NAME="jfrog" fi +URL="https://releases.jfrog.io/artifactory/jfrog-cli/${CLI_MAJOR_VER}/${VERSION}/jfrog-cli-${CLI_OS}-${ARCH}/${FILE_NAME}" +echo "Downloading from: $URL" curl -XGET "$URL" -L -k -g > $FILE_NAME -chmod u+x $FILE_NAME \ No newline at end of file +chmod +x $FILE_NAME \ No newline at end of file diff --git a/build/installcli/jf.sh b/build/installcli/jf.sh index 4619708d4..c8c15a13b 100755 --- a/build/installcli/jf.sh +++ b/build/installcli/jf.sh @@ -1,11 +1,14 @@ -#!/bin/bash +#!/bin/sh +set -u + +# This script is downloading the OS-specific JFrog CLI binary with the name - 'jf', and adds it to PATH CLI_OS="na" CLI_MAJOR_VER="v2-jf" VERSION="[RELEASE]" +FILE_NAME="jf" -if [ $# -eq 1 ] -then +if [ $# -eq 1 ]; then VERSION=$1 echo "Downloading version $VERSION of JFrog CLI..." else @@ -13,18 +16,17 @@ else fi echo "" -if echo "${OSTYPE}" | grep -q msys; then +if uname -s | grep -q -E -i "(cygwin|mingw|msys|windows)"; then CLI_OS="windows" - URL="https://releases.jfrog.io/artifactory/jfrog-cli/${CLI_MAJOR_VER}/${VERSION}/jfrog-cli-windows-amd64/jf.exe" - FILE_NAME="jf.exe" -elif echo "${OSTYPE}" | grep -q darwin; then + ARCH="amd64" + FILE_NAME="${FILE_NAME}.exe" +elif uname -s | grep -q -i "darwin"; then CLI_OS="mac" - if [[ $(uname -m) == 'arm64' ]]; then - URL="https://releases.jfrog.io/artifactory/jfrog-cli/${CLI_MAJOR_VER}/${VERSION}/jfrog-cli-mac-arm64/jf" + if [ "$(uname -m)" = "arm64" ]; then + ARCH="arm64" else - URL="https://releases.jfrog.io/artifactory/jfrog-cli/${CLI_MAJOR_VER}/${VERSION}/jfrog-cli-mac-386/jf" + ARCH="386" fi - FILE_NAME="jf" else CLI_OS="linux" MACHINE_TYPE="$(uname -m)" @@ -55,12 +57,12 @@ else exit 1 ;; esac - URL="https://releases.jfrog.io/artifactory/jfrog-cli/${CLI_MAJOR_VER}/${VERSION}/jfrog-cli-${CLI_OS}-${ARCH}/jf" - FILE_NAME="jf" fi +URL="https://releases.jfrog.io/artifactory/jfrog-cli/${CLI_MAJOR_VER}/${VERSION}/jfrog-cli-${CLI_OS}-${ARCH}/${FILE_NAME}" +echo "Downloading from: $URL" curl -XGET "$URL" -L -k -g > $FILE_NAME -chmod u+x $FILE_NAME +chmod +x $FILE_NAME # Move executable to a destination in path. # Order is by destination priority. diff --git a/build/installcli/jfrog.sh b/build/installcli/jfrog.sh index 80ec7c3f3..bda6b22eb 100755 --- a/build/installcli/jfrog.sh +++ b/build/installcli/jfrog.sh @@ -1,11 +1,14 @@ -#!/bin/bash +#!/bin/sh +set -u + +# This script is downloading the OS-specific JFrog CLI binary with the name - 'jfrog', and adds it to PATH CLI_OS="na" CLI_MAJOR_VER="v2" VERSION="[RELEASE]" +FILE_NAME="jfrog" -if [ $# -eq 1 ] -then +if [ $# -eq 1 ]; then VERSION=$1 echo "Downloading version $VERSION of JFrog CLI..." else @@ -13,18 +16,17 @@ else fi echo "" -if echo "${OSTYPE}" | grep -q msys; then +if uname -s | grep -q -E -i "(cygwin|mingw|msys|windows)"; then CLI_OS="windows" - URL="https://releases.jfrog.io/artifactory/jfrog-cli/${CLI_MAJOR_VER}/${VERSION}/jfrog-cli-windows-amd64/jfrog.exe" - FILE_NAME="jfrog.exe" -elif echo "${OSTYPE}" | grep -q darwin; then + ARCH="amd64" + FILE_NAME="${FILE_NAME}.exe" +elif uname -s | grep -q -i "darwin"; then CLI_OS="mac" - if [[ $(uname -m) == 'arm64' ]]; then - URL="https://releases.jfrog.io/artifactory/jfrog-cli/${CLI_MAJOR_VER}/${VERSION}/jfrog-cli-mac-arm64/jfrog" + if [ "$(uname -m)" = "arm64" ]; then + ARCH="arm64" else - URL="https://releases.jfrog.io/artifactory/jfrog-cli/${CLI_MAJOR_VER}/${VERSION}/jfrog-cli-mac-386/jfrog" + ARCH="386" fi - FILE_NAME="jfrog" else CLI_OS="linux" MACHINE_TYPE="$(uname -m)" @@ -55,12 +57,12 @@ else exit 1 ;; esac - URL="https://releases.jfrog.io/artifactory/jfrog-cli/${CLI_MAJOR_VER}/${VERSION}/jfrog-cli-${CLI_OS}-${ARCH}/jfrog" - FILE_NAME="jfrog" fi +URL="https://releases.jfrog.io/artifactory/jfrog-cli/${CLI_MAJOR_VER}/${VERSION}/jfrog-cli-${CLI_OS}-${ARCH}/${FILE_NAME}" +echo "Downloading from: $URL" curl -XGET "$URL" -L -k -g > $FILE_NAME -chmod u+x $FILE_NAME +chmod +x $FILE_NAME # Move executable to a destination in path. # Order is by destination priority. diff --git a/build/npm/v2-jf/package-lock.json b/build/npm/v2-jf/package-lock.json index 239796521..0fcbf29be 100644 --- a/build/npm/v2-jf/package-lock.json +++ b/build/npm/v2-jf/package-lock.json @@ -1,5 +1,5 @@ { "name": "jfrog-cli-v2-jf", - "version": "2.52.9", + "version": "2.52.10", "lockfileVersion": 1 } diff --git a/build/npm/v2-jf/package.json b/build/npm/v2-jf/package.json index bcbaab171..1c8214687 100644 --- a/build/npm/v2-jf/package.json +++ b/build/npm/v2-jf/package.json @@ -1,6 +1,6 @@ { "name": "jfrog-cli-v2-jf", - "version": "2.52.9", + "version": "2.52.10", "description": "🐸 Command-line interface for JFrog Artifactory, Xray, Distribution, Pipelines and Mission Control 🐸", "homepage": "https://github.com/jfrog/jfrog-cli", "preferGlobal": true, diff --git a/build/npm/v2/package-lock.json b/build/npm/v2/package-lock.json index bd4b3db87..8e7416344 100644 --- a/build/npm/v2/package-lock.json +++ b/build/npm/v2/package-lock.json @@ -1,5 +1,5 @@ { "name": "jfrog-cli-v2", - "version": "2.52.9", + "version": "2.52.10", "lockfileVersion": 2 } diff --git a/build/npm/v2/package.json b/build/npm/v2/package.json index 0cf3008e4..6f9c756dc 100644 --- a/build/npm/v2/package.json +++ b/build/npm/v2/package.json @@ -1,6 +1,6 @@ { "name": "jfrog-cli-v2", - "version": "2.52.9", + "version": "2.52.10", "description": "🐸 Command-line interface for JFrog Artifactory, Xray, Distribution, Pipelines and Mission Control 🐸", "homepage": "https://github.com/jfrog/jfrog-cli", "preferGlobal": true, diff --git a/build/setupcli/jf.sh b/build/setupcli/jf.sh index ecf68f0cc..6adcd7af3 100755 --- a/build/setupcli/jf.sh +++ b/build/setupcli/jf.sh @@ -1,8 +1,12 @@ -#!/bin/bash +#!/bin/sh +set -u + +# This script is downloading the OS-specific JFrog CLI binary with the name - 'jf', adds it to PATH and prints greeting message CLI_OS="na" CLI_MAJOR_VER="v2-jf" VERSION="[RELEASE]" +FILE_NAME="jf" SETUP_COMMAND="jf setup" GREEN_COLOR='\033[0;32m' REMOVE_COLOR='\033[0m' @@ -11,24 +15,22 @@ print_installation_greeting () { echo "${GREEN_COLOR}Thank you for installing JFrog CLI! 🐸 ${REMOVE_COLOR}" } -if [ $# -eq 1 ] -then +if [ $# -eq 1 ]; then SETUP_COMMAND="$SETUP_COMMAND $1" fi echo "Downloading the latest version of JFrog CLI..." -if echo "${OSTYPE}" | grep -q msys; then +if uname -s | grep -q -E -i "(cygwin|mingw|msys|windows)"; then CLI_OS="windows" - URL="https://releases.jfrog.io/artifactory/jfrog-cli/${CLI_MAJOR_VER}/${VERSION}/jfrog-cli-windows-amd64/jf.exe" - FILE_NAME="jf.exe" -elif echo "${OSTYPE}" | grep -q darwin; then + ARCH="amd64" + FILE_NAME="${FILE_NAME}.exe" +elif uname -s | grep -q -i "darwin"; then CLI_OS="mac" - if [[ $(uname -m) == 'arm64' ]]; then - URL="https://releases.jfrog.io/artifactory/jfrog-cli/${CLI_MAJOR_VER}/${VERSION}/jfrog-cli-mac-arm64/jf" + if [ "$(uname -m)" = "arm64" ]; then + ARCH="arm64" else - URL="https://releases.jfrog.io/artifactory/jfrog-cli/${CLI_MAJOR_VER}/${VERSION}/jfrog-cli-mac-386/jf" + ARCH="386" fi - FILE_NAME="jf" else CLI_OS="linux" MACHINE_TYPE="$(uname -m)" @@ -59,12 +61,12 @@ else exit 1 ;; esac - URL="https://releases.jfrog.io/artifactory/jfrog-cli/${CLI_MAJOR_VER}/${VERSION}/jfrog-cli-${CLI_OS}-${ARCH}/jf" - FILE_NAME="jf" fi +URL="https://releases.jfrog.io/artifactory/jfrog-cli/${CLI_MAJOR_VER}/${VERSION}/jfrog-cli-${CLI_OS}-${ARCH}/${FILE_NAME}" +echo "Downloading from: $URL" curl -XGET "$URL" -L -k -g > $FILE_NAME -chmod u+x $FILE_NAME +chmod +x $FILE_NAME # Move executable to a destination in path. # Order is by destination priority. diff --git a/buildinfo_test.go b/buildinfo_test.go index a86de6eb9..b783aa706 100644 --- a/buildinfo_test.go +++ b/buildinfo_test.go @@ -161,7 +161,7 @@ func TestBuildAddDependenciesDryRun(t *testing.T) { chdirCallback := clientTestUtils.ChangeDirWithCallback(t, wd, "testdata") defer chdirCallback() - noCredsCli := tests.NewJfrogCli(execMain, "jfrog rt", "") + noCredsCli := coretests.NewJfrogCli(execMain, "jfrog rt", "") // Execute the bad command on the local file system assert.NoError(t, noCredsCli.Exec("bad", tests.RtBuildName1, "1", "a/*", "--dry-run=true")) buildDir, err := build.GetBuildDir(tests.RtBuildName1, "1", "") @@ -660,7 +660,7 @@ func TestBuildAddGitEnvBuildNameAndNumber(t *testing.T) { func testBuildAddGit(t *testing.T, useEnvBuildNameAndNumber bool) { initArtifactoryTest(t, "") - gitCollectCliRunner := tests.NewJfrogCli(execMain, "jfrog rt", "") + gitCollectCliRunner := coretests.NewJfrogCli(execMain, "jfrog rt", "") buildNumber := "13" // Populate cli config with 'default' server @@ -843,7 +843,7 @@ func TestModuleName(t *testing.T) { } func collectDepsAndPublishBuild(badTest buildAddDepsBuildInfoTestParams, useEnvBuildNameAndNumber bool, t *testing.T) { - noCredsCli := tests.NewJfrogCli(execMain, "jfrog rt", "") + noCredsCli := coretests.NewJfrogCli(execMain, "jfrog rt", "") // Remove old tests data from fs if exists err := build.RemoveBuildDir(badTest.buildName, badTest.buildNumber, "") assert.NoError(t, err) diff --git a/buildtools/cli.go b/buildtools/cli.go index 082d79d2f..019b5425c 100644 --- a/buildtools/cli.go +++ b/buildtools/cli.go @@ -19,12 +19,17 @@ import ( "github.com/jfrog/jfrog-cli-core/v2/artifactory/commands/yarn" containerutils "github.com/jfrog/jfrog-cli-core/v2/artifactory/utils/container" "github.com/jfrog/jfrog-cli-core/v2/common/build" + commonCliUtils "github.com/jfrog/jfrog-cli-core/v2/common/cliutils" "github.com/jfrog/jfrog-cli-core/v2/common/commands" outputFormat "github.com/jfrog/jfrog-cli-core/v2/common/format" "github.com/jfrog/jfrog-cli-core/v2/common/project" corecommon "github.com/jfrog/jfrog-cli-core/v2/docs/common" + "github.com/jfrog/jfrog-cli-core/v2/plugins/components" coreConfig "github.com/jfrog/jfrog-cli-core/v2/utils/config" "github.com/jfrog/jfrog-cli-core/v2/utils/coreutils" + securityCLI "github.com/jfrog/jfrog-cli-security/cli" + securityDocs "github.com/jfrog/jfrog-cli-security/cli/docs" + "github.com/jfrog/jfrog-cli-security/commands/scan" terraformdocs "github.com/jfrog/jfrog-cli/docs/artifactory/terraform" "github.com/jfrog/jfrog-cli/docs/artifactory/terraformconfig" "github.com/jfrog/jfrog-cli/docs/buildtools/docker" @@ -50,7 +55,6 @@ import ( yarndocs "github.com/jfrog/jfrog-cli/docs/buildtools/yarn" "github.com/jfrog/jfrog-cli/docs/buildtools/yarnconfig" "github.com/jfrog/jfrog-cli/docs/common" - "github.com/jfrog/jfrog-cli/scan" "github.com/jfrog/jfrog-cli/utils/cliutils" "github.com/jfrog/jfrog-client-go/utils/errorutils" "github.com/jfrog/jfrog-client-go/utils/log" @@ -410,6 +414,9 @@ func MvnCmd(c *cli.Context) (err error) { if err != nil { return err } + if xrayScan { + commandsUtils.ConditionalUploadScanFunc = scan.ConditionalUploadDefaultScanFunc + } filteredMavenArgs, format, err := coreutils.ExtractXrayOutputFormatFromArgs(filteredMavenArgs) if err != nil { return err @@ -463,6 +470,9 @@ func GradleCmd(c *cli.Context) (err error) { if err != nil { return err } + if xrayScan { + commandsUtils.ConditionalUploadScanFunc = scan.ConditionalUploadDefaultScanFunc + } filteredGradleArgs, format, err := coreutils.ExtractXrayOutputFormatFromArgs(filteredGradleArgs) if err != nil { return err @@ -602,7 +612,7 @@ func extractThreadsFlag(args []string) (cleanArgs []string, threadsCount int, er cleanArgs = append([]string(nil), args...) threadsFlagIndex, threadsValueIndex, threads, err := coreutils.FindFlag("--threads", cleanArgs) if err != nil || threadsFlagIndex < 0 { - threadsCount = cliutils.Threads + threadsCount = commonCliUtils.Threads return } coreutils.RemoveFlagFromCommand(&cleanArgs, threadsFlagIndex, threadsValueIndex) @@ -686,7 +696,7 @@ func dockerCmd(c *cli.Context) error { case "push": err = pushCmd(c, image) case "scan": - return scan.DockerScan(c, image) + return dockerScanCmd(c, image) default: err = dockerNativeCmd(c) } @@ -744,6 +754,14 @@ func pushCmd(c *cli.Context, image string) (err error) { return } +func dockerScanCmd(c *cli.Context, imageTag string) error { + convertedCtx, err := components.ConvertContext(c, securityDocs.GetCommandFlags(securityDocs.DockerScan)...) + if err != nil { + return err + } + return securityCLI.DockerScan(convertedCtx, imageTag) +} + func dockerNativeCmd(c *cli.Context) error { if show, err := cliutils.ShowCmdHelpIfNeeded(c, c.Args()); show || err != nil { return err @@ -826,6 +844,9 @@ func NpmPublishCmd(c *cli.Context) (err error) { if err = npmCmd.Init(); err != nil { return err } + if npmCmd.GetXrayScan() { + commandsUtils.ConditionalUploadScanFunc = scan.ConditionalUploadDefaultScanFunc + } printDeploymentView, detailedSummary := log.IsStdErrTerminal(), npmCmd.IsDetailedSummary() if !detailedSummary { npmCmd.SetDetailedSummary(printDeploymentView) diff --git a/buildtools/help.go b/buildtools/help.go index 472dce3b0..2b2f3b092 100644 --- a/buildtools/help.go +++ b/buildtools/help.go @@ -4,7 +4,6 @@ import ( corecommon "github.com/jfrog/jfrog-cli-core/v2/docs/common" "github.com/jfrog/jfrog-cli/docs/buildtools/dockerpull" "github.com/jfrog/jfrog-cli/docs/buildtools/dockerpush" - "github.com/jfrog/jfrog-cli/docs/buildtools/dockerscan" "github.com/jfrog/jfrog-cli/docs/buildtools/npmci" "github.com/jfrog/jfrog-cli/docs/buildtools/npminstall" "github.com/jfrog/jfrog-cli/docs/buildtools/npmpublish" @@ -35,15 +34,6 @@ func GetBuildToolsHelpCommands() []cli.Command { ArgsUsage: common.CreateEnvVars(), Hidden: true, }, - { - Name: "dockerscanhelp", - Flags: cliutils.GetCommandFlags(cliutils.DockerScan), - Usage: dockerscan.GetDescription(), - HelpName: corecommon.CreateUsage("docker scan", dockerscan.GetDescription(), dockerscan.Usage), - UsageText: dockerscan.GetArguments(), - ArgsUsage: common.CreateEnvVars(), - Hidden: true, - }, { Name: "npminstallhelp", Flags: cliutils.GetCommandFlags(cliutils.NpmInstallCi), diff --git a/completion_test.go b/completion_test.go index 944b94fcc..040e9125d 100644 --- a/completion_test.go +++ b/completion_test.go @@ -3,6 +3,7 @@ package main import ( "testing" + coreTests "github.com/jfrog/jfrog-cli-core/v2/utils/tests" "github.com/jfrog/jfrog-cli/completion/shells/bash" "github.com/jfrog/jfrog-cli/completion/shells/zsh" "github.com/jfrog/jfrog-cli/utils/tests" @@ -10,21 +11,21 @@ import ( ) func TestBashCompletion(t *testing.T) { - jfrogCli := tests.NewJfrogCli(execMain, "jfrog", "") + jfrogCli := coreTests.NewJfrogCli(execMain, "jfrog", "") content, err := tests.GetCmdOutput(t, jfrogCli, "completion", "bash") assert.NoError(t, err) assert.Equal(t, bash.BashAutocomplete, string(content)) } func TestZshCompletion(t *testing.T) { - jfrogCli := tests.NewJfrogCli(execMain, "jfrog", "") + jfrogCli := coreTests.NewJfrogCli(execMain, "jfrog", "") content, err := tests.GetCmdOutput(t, jfrogCli, "completion", "zsh") assert.NoError(t, err) assert.Equal(t, zsh.ZshAutocomplete, string(content)) } func TestFishCompletion(t *testing.T) { - jfrogCli := tests.NewJfrogCli(execMain, "jfrog", "") + jfrogCli := coreTests.NewJfrogCli(execMain, "jfrog", "") content, err := tests.GetCmdOutput(t, jfrogCli, "completion", "fish") assert.NoError(t, err) assert.Contains(t, string(content), "complete -c") diff --git a/distribution/cli.go b/distribution/cli.go index 0a0664a29..bc118b1e3 100644 --- a/distribution/cli.go +++ b/distribution/cli.go @@ -2,6 +2,7 @@ package distribution import ( "errors" + commonCliUtils "github.com/jfrog/jfrog-cli-core/v2/common/cliutils" "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" @@ -311,7 +312,7 @@ func populateReleaseNotesSyntax(c *cli.Context) (distributionServicesUtils.Relea } func createDistributionDetailsByFlags(c *cli.Context) (*coreConfig.ServerDetails, error) { - dsDetails, err := cliutils.CreateServerDetailsWithConfigOffer(c, true, cliutils.Ds) + dsDetails, err := cliutils.CreateServerDetailsWithConfigOffer(c, true, commonCliUtils.Ds) if err != nil { return nil, err } diff --git a/distribution_test.go b/distribution_test.go index 5c5d12869..c1d5751a7 100644 --- a/distribution_test.go +++ b/distribution_test.go @@ -36,7 +36,7 @@ var ( distAuth auth.ServiceDetails distHttpDetails httputils.HttpClientDetails // JFrog CLI for Distribution commands - distributionCli *tests.JfrogCli + distributionCli *coreTests.JfrogCli ) func InitDistributionTests() { @@ -80,7 +80,7 @@ func initDistributionCli() { return } cred := authenticateDistribution() - distributionCli = tests.NewJfrogCli(execMain, "jfrog ds", cred) + distributionCli = coreTests.NewJfrogCli(execMain, "jfrog ds", cred) } func initDistributionTest(t *testing.T) { @@ -610,7 +610,7 @@ func TestDistributeSyncTimeout(t *testing.T) { maxWaitMinutes := 1 distributionRulesPath := filepath.Join(tests.GetTestResourcesPath(), "distribution", tests.DistributionRules) - mockDsCli := tests.NewJfrogCli(execMain, "jfrog ds", "--url="+mockServerDetails.DistributionUrl) + mockDsCli := coreTests.NewJfrogCli(execMain, "jfrog ds", "--url="+mockServerDetails.DistributionUrl) err := mockDsCli.Exec("rbd", tests.BundleName, bundleVersion, "--dist-rules="+distributionRulesPath, "--sync", "--max-wait-minutes="+strconv.Itoa(maxWaitMinutes), "--create-repo") assert.ErrorContains(t, err, "executor timeout after") assert.ErrorAs(t, err, &clientUtils.RetryExecutorTimeoutError{}) diff --git a/docker_test.go b/docker_test.go index 28a9b79e9..154dd78e7 100644 --- a/docker_test.go +++ b/docker_test.go @@ -19,7 +19,9 @@ import ( "github.com/jfrog/jfrog-cli-core/v2/artifactory/utils/container" "github.com/jfrog/jfrog-cli-core/v2/common/build" "github.com/jfrog/jfrog-cli-core/v2/common/spec" + commonTests "github.com/jfrog/jfrog-cli-core/v2/common/tests" "github.com/jfrog/jfrog-cli-core/v2/utils/coreutils" + coreTests "github.com/jfrog/jfrog-cli-core/v2/utils/tests" "github.com/jfrog/jfrog-cli/inttestutils" "github.com/jfrog/jfrog-cli/utils/tests" "github.com/jfrog/jfrog-client-go/auth" @@ -105,7 +107,7 @@ func TestContainerPushWithDetailedSummary(t *testing.T) { func() { imageTag, err := inttestutils.BuildTestImage(imageName+":1", "", repo, containerManager) assert.NoError(t, err) - defer inttestutils.DeleteTestImage(t, imageTag, containerManager) + defer commonTests.DeleteTestImage(t, imageTag, containerManager) // Testing detailed summary without build-info pushCommand := coreContainer.NewPushCommand(containerManager) pushCommand.SetThreads(1).SetDetailedSummary(true).SetCmdParams([]string{"push", imageTag}).SetBuildConfiguration(new(build.BuildConfiguration)).SetRepo(tests.DockerLocalRepo).SetServerDetails(serverDetails).SetImageTag(imageTag) @@ -159,7 +161,7 @@ func TestContainerPushWithMultipleSlash(t *testing.T) { func runPushTest(containerManager container.ContainerManagerType, imageName, module string, withModule bool, t *testing.T, repo string) { imageTag, err := inttestutils.BuildTestImage(imageName+":1", "", repo, containerManager) assert.NoError(t, err) - defer inttestutils.DeleteTestImage(t, imageTag, containerManager) + defer commonTests.DeleteTestImage(t, imageTag, containerManager) buildNumber := "1" if withModule { @@ -290,7 +292,7 @@ func TestContainerPushBuildNameNumberFromEnv(t *testing.T) { func() { imageTag, err := inttestutils.BuildTestImage(tests.DockerImageName+":1", "", tests.DockerLocalRepo, containerManager) assert.NoError(t, err) - defer inttestutils.DeleteTestImage(t, imageTag, containerManager) + defer commonTests.DeleteTestImage(t, imageTag, containerManager) buildNumber := "1" setEnvCallBack := clientTestUtils.SetEnvWithCallbackAndAssert(t, coreutils.BuildName, tests.DockerBuildName) defer setEnvCallBack() @@ -313,7 +315,7 @@ func TestContainerPull(t *testing.T) { func() { imageName, err := inttestutils.BuildTestImage(tests.DockerImageName+":1", "", tests.DockerLocalRepo, containerManager) assert.NoError(t, err) - defer inttestutils.DeleteTestImage(t, imageName, containerManager) + defer commonTests.DeleteTestImage(t, imageName, containerManager) for _, repo := range []string{tests.DockerVirtualRepo, tests.DockerLocalRepo} { // Push container image @@ -353,7 +355,7 @@ func TestContainerFatManifestPull(t *testing.T) { func() { // Pull container image imageTag := path.Join(*tests.ContainerRegistry, dockerRepo, imageName+":2.2") - defer inttestutils.DeleteTestImage(t, imageTag, containerManager) + defer commonTests.DeleteTestImage(t, imageTag, containerManager) runCmdWithRetries(t, jfrogRtCliTask(containerManager.String()+"-pull", imageTag, dockerRepo, "--build-name="+tests.DockerBuildName, "--build-number="+buildNumber)) runRt(t, "build-publish", tests.DockerBuildName, buildNumber) @@ -383,7 +385,7 @@ func TestDockerPromote(t *testing.T) { // Build and push image imageName, err := inttestutils.BuildTestImage(tests.DockerImageName+":1", "", tests.DockerLocalRepo, container.DockerClient) assert.NoError(t, err) - defer inttestutils.DeleteTestImage(t, imageName, container.DockerClient) + defer commonTests.DeleteTestImage(t, imageName, container.DockerClient) // Push image runCmdWithRetries(t, jfrogRtCliTask("docker-push", imageName, tests.DockerLocalRepo)) @@ -517,13 +519,13 @@ func TestNativeDockerPushPull(t *testing.T) { runRt(t, "build-publish", tests.DockerBuildName, pushBuildNumber) imagePath := path.Join(tests.DockerLocalRepo, tests.DockerImageName, pushBuildNumber) + "/" validateContainerBuild(tests.DockerBuildName, pushBuildNumber, imagePath, module, 7, 5, 7, t) - inttestutils.DeleteTestImage(t, image, container.DockerClient) + commonTests.DeleteTestImage(t, image, container.DockerClient) runCmdWithRetries(t, jfCliTask("docker", "-D", "pull", image, "--build-name="+tests.DockerBuildName, "--build-number="+pullBuildNumber, "--module="+module)) runRt(t, "build-publish", tests.DockerBuildName, pullBuildNumber) imagePath = path.Join(tests.DockerLocalRepo, tests.DockerImageName, pullBuildNumber) + "/" validateContainerBuild(tests.DockerBuildName, pullBuildNumber, imagePath, module, 0, 7, 0, t) - inttestutils.DeleteTestImage(t, image, container.DockerClient) + commonTests.DeleteTestImage(t, image, container.DockerClient) inttestutils.ContainerTestCleanup(t, serverDetails, artHttpDetails, tests.DockerImageName, tests.DockerBuildName, tests.DockerLocalRepo) } @@ -557,7 +559,7 @@ func jfrogRtCliTask(args ...string) func() error { func jfCliTask(args ...string) func() error { return func() error { - return tests.NewJfrogCli(execMain, "jf", "").WithoutCredentials().Exec(args...) + return coreTests.NewJfrogCli(execMain, "jf", "").WithoutCredentials().Exec(args...) } } diff --git a/docs/buildtools/dockerscan/help.go b/docs/buildtools/dockerscan/help.go deleted file mode 100644 index 52baa8422..000000000 --- a/docs/buildtools/dockerscan/help.go +++ /dev/null @@ -1,12 +0,0 @@ -package dockerscan - -var Usage = []string{"docker scan "} - -func GetDescription() string { - return "Scan local docker image using the docker client and Xray." -} - -func GetArguments() string { - return ` docker scan args - The docker scan args to run docker scan.` -} diff --git a/docs/xray/auditgo/help.go b/docs/xray/auditgo/help.go deleted file mode 100644 index e03d10d4a..000000000 --- a/docs/xray/auditgo/help.go +++ /dev/null @@ -1,7 +0,0 @@ -package auditgo - -var Usage = []string{"xr audit-go [command options]"} - -func GetDescription() string { - return "Execute an audit Go command, using the configured Xray details." -} diff --git a/docs/xray/auditgradle/help.go b/docs/xray/auditgradle/help.go deleted file mode 100644 index df90fe765..000000000 --- a/docs/xray/auditgradle/help.go +++ /dev/null @@ -1,7 +0,0 @@ -package auditgradle - -var Usage = []string{"xr audit-gradle [command options]"} - -func GetDescription() string { - return "Execute an audit Gradle command, using the configured Xray details." -} diff --git a/docs/xray/auditmvn/help.go b/docs/xray/auditmvn/help.go deleted file mode 100644 index 3b489af4e..000000000 --- a/docs/xray/auditmvn/help.go +++ /dev/null @@ -1,7 +0,0 @@ -package auditmvn - -var Usage = []string{"xr audit-mvn [command options]"} - -func GetDescription() string { - return "Execute an audit Maven command, using the configured Xray details." -} diff --git a/docs/xray/auditnpm/help.go b/docs/xray/auditnpm/help.go deleted file mode 100644 index 3ad981fb4..000000000 --- a/docs/xray/auditnpm/help.go +++ /dev/null @@ -1,7 +0,0 @@ -package auditnpm - -var Usage = []string{"xr audit-npm [command options]"} - -func GetDescription() string { - return "Execute an audit Npm command, using the configured Xray details." -} diff --git a/docs/xray/auditpip/help.go b/docs/xray/auditpip/help.go deleted file mode 100644 index 64892bbb4..000000000 --- a/docs/xray/auditpip/help.go +++ /dev/null @@ -1,7 +0,0 @@ -package auditpip - -var Usage = []string{"xr audit-pip [command options]"} - -func GetDescription() string { - return "Execute an audit Pip command, using the configured Xray details." -} diff --git a/docs/xray/curl/help.go b/docs/xray/curl/help.go deleted file mode 100644 index 2b81957e3..000000000 --- a/docs/xray/curl/help.go +++ /dev/null @@ -1,12 +0,0 @@ -package curl - -var Usage = []string{"xr curl [command options] "} - -func GetDescription() string { - return "Execute a cUrl command, using the configured Xray details." -} - -func GetArguments() string { - return ` curl command - cUrl command to run.` -} diff --git a/docs/xray/offlineupdate/help.go b/docs/xray/offlineupdate/help.go deleted file mode 100644 index cdd5acb63..000000000 --- a/docs/xray/offlineupdate/help.go +++ /dev/null @@ -1,7 +0,0 @@ -package offlineupdate - -var Usage = []string{"xr offline-update --license-id= [command options]"} - -func GetDescription() string { - return "Download Xray offline updates." -} diff --git a/docs/xray/scan/help.go b/docs/xray/scan/help.go deleted file mode 100644 index b141eef7a..000000000 --- a/docs/xray/scan/help.go +++ /dev/null @@ -1,15 +0,0 @@ -package scan - -var Usage = []string{"xr scan [command options] ", - "xr scan [command options] --spec= "} - -func GetDescription() string { - return "Scan files located on the local file-system with Xray." -} - -func GetArguments() string { - return ` source pattern - Specifies the local file system path of the files to be scanned. - You can specify multiple files by using wildcards, Ant pattern or a regular expression. - If you have specified that you are using regular expressions, then the first one used in the argument must be enclosed in parenthesis.` -} diff --git a/general/envsetup/envsetup.go b/general/envsetup/envsetup.go index 2a261f463..db6cee91b 100644 --- a/general/envsetup/envsetup.go +++ b/general/envsetup/envsetup.go @@ -1,10 +1,10 @@ package envsetup import ( + "github.com/jfrog/jfrog-cli-core/v2/common/progressbar" "github.com/jfrog/jfrog-cli-core/v2/general/envsetup" "github.com/jfrog/jfrog-cli-core/v2/utils/coreutils" "github.com/jfrog/jfrog-cli/utils/cliutils" - "github.com/jfrog/jfrog-cli/utils/progressbar" "github.com/jfrog/jfrog-client-go/utils/log" "github.com/urfave/cli" ) diff --git a/general/token/cli.go b/general/token/cli.go index 748a0f0a1..bb35fd983 100644 --- a/general/token/cli.go +++ b/general/token/cli.go @@ -3,6 +3,7 @@ package token import ( "errors" "fmt" + commonCliUtils "github.com/jfrog/jfrog-cli-core/v2/common/cliutils" "github.com/jfrog/jfrog-cli-core/v2/common/commands" generic "github.com/jfrog/jfrog-cli-core/v2/general/token" coreConfig "github.com/jfrog/jfrog-cli-core/v2/utils/config" @@ -67,7 +68,7 @@ func AccessTokenCreateCmd(c *cli.Context) error { } func createPlatformDetailsByFlags(c *cli.Context) (*coreConfig.ServerDetails, error) { - platformDetails, err := cliutils.CreateServerDetailsWithConfigOffer(c, true, cliutils.Platform) + platformDetails, err := cliutils.CreateServerDetailsWithConfigOffer(c, true, commonCliUtils.Platform) if err != nil { return nil, err } diff --git a/go.mod b/go.mod index bdcf6cde4..2a25c9d11 100644 --- a/go.mod +++ b/go.mod @@ -7,47 +7,45 @@ require ( github.com/buger/jsonparser v1.1.1 github.com/go-git/go-git/v5 v5.11.0 github.com/gocarina/gocsv v0.0.0-20231116093920-b87c2d0e983a - github.com/jfrog/build-info-go v1.9.20 - github.com/jfrog/gofrog v1.4.1 - github.com/jfrog/jfrog-cli-core/v2 v2.47.10 - github.com/jfrog/jfrog-client-go v1.35.6 - github.com/jszwec/csvutil v1.8.0 + github.com/jfrog/build-info-go v1.9.21 + github.com/jfrog/gofrog v1.5.1 + github.com/jfrog/jfrog-cli-core/v2 v2.47.11 + github.com/jfrog/jfrog-cli-security v0.0.0-20240122124933-edf9cb4ca3ac + github.com/jfrog/jfrog-client-go v1.36.0 + github.com/jszwec/csvutil v1.9.0 github.com/mholt/archiver/v3 v3.5.1 github.com/stretchr/testify v1.8.4 github.com/testcontainers/testcontainers-go v0.23.0 github.com/urfave/cli v1.22.14 - github.com/vbauerster/mpb/v7 v7.5.3 github.com/xeipuuv/gojsonschema v1.2.0 - golang.org/x/exp v0.0.0-20231226003508-02704c960a9b - golang.org/x/term v0.15.0 + golang.org/x/exp v0.0.0-20240119083558-1b970713d09a + golang.org/x/term v0.16.0 gopkg.in/yaml.v2 v2.4.0 ) -require github.com/jedib0t/go-pretty/v6 v6.4.0 // indirect; Should not be updated to v6.4.1+ due to a bug (https://github.com/jfrog/jfrog-cli-core/pull/1045) - require ( dario.cat/mergo v1.0.0 // indirect github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1 // indirect github.com/BurntSushi/toml v1.3.2 // indirect github.com/CycloneDX/cyclonedx-go v0.7.2 // indirect github.com/Microsoft/go-winio v0.6.1 // indirect - github.com/Microsoft/hcsshim v0.11.1 // indirect - github.com/ProtonMail/go-crypto v0.0.0-20230923063757-afb1ddc0824c // indirect + github.com/Microsoft/hcsshim v0.11.4 // indirect + github.com/ProtonMail/go-crypto v1.0.0 // indirect github.com/VividCortex/ewma v1.2.0 // indirect github.com/acarl005/stripansi v0.0.0-20180116102854-5a71ef0e047d // indirect - github.com/andybalholm/brotli v1.0.1 // indirect + github.com/andybalholm/brotli v1.1.0 // indirect github.com/c-bata/go-prompt v0.2.5 // indirect github.com/cenkalti/backoff/v4 v4.2.1 // indirect github.com/chzyer/readline v1.5.1 // indirect github.com/cloudflare/circl v1.3.3 // indirect - github.com/containerd/containerd v1.7.7 // indirect + github.com/containerd/containerd v1.7.11 // indirect github.com/containerd/log v0.1.0 // indirect github.com/cpuguy83/dockercfg v0.3.1 // indirect github.com/cpuguy83/go-md2man/v2 v2.0.2 // indirect github.com/cyphar/filepath-securejoin v0.2.4 // indirect github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect github.com/docker/distribution v2.8.2+incompatible // indirect - github.com/docker/docker v24.0.6+incompatible // indirect + github.com/docker/docker v24.0.7+incompatible // indirect github.com/docker/go-connections v0.4.0 // indirect github.com/docker/go-units v0.5.0 // indirect github.com/dsnet/compress v0.0.2-0.20210315054119-f66993602bf5 // indirect @@ -60,22 +58,23 @@ require ( github.com/golang-jwt/jwt/v4 v4.5.0 // indirect github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect github.com/golang/protobuf v1.5.3 // indirect - github.com/golang/snappy v0.0.2 // indirect + github.com/golang/snappy v0.0.4 // indirect github.com/google/uuid v1.5.0 // indirect github.com/gookit/color v1.5.4 // indirect github.com/hashicorp/hcl v1.0.0 // indirect github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 // indirect - github.com/jfrog/archiver/v3 v3.5.3 // indirect + github.com/jedib0t/go-pretty/v6 v6.5.3 // indirect + github.com/jfrog/archiver/v3 v3.6.0 // indirect github.com/jfrog/jfrog-apps-config v1.0.1 // indirect github.com/kevinburke/ssh_config v1.2.0 // indirect - github.com/klauspost/compress v1.17.0 // indirect + github.com/klauspost/compress v1.17.4 // indirect github.com/klauspost/cpuid/v2 v2.2.3 // indirect - github.com/klauspost/pgzip v1.2.5 // indirect + github.com/klauspost/pgzip v1.2.6 // indirect github.com/magiconair/properties v1.8.7 // indirect github.com/manifoldco/promptui v0.9.0 // indirect github.com/mattn/go-colorable v0.1.13 // indirect github.com/mattn/go-isatty v0.0.17 // indirect - github.com/mattn/go-runewidth v0.0.13 // indirect + github.com/mattn/go-runewidth v0.0.15 // indirect github.com/mattn/go-tty v0.0.3 // indirect github.com/minio/sha256-simd v1.0.1 // indirect github.com/mitchellh/mapstructure v1.5.0 // indirect @@ -83,15 +82,15 @@ require ( github.com/moby/sys/sequential v0.5.0 // indirect github.com/moby/term v0.5.0 // indirect github.com/morikuni/aec v1.0.0 // indirect - github.com/nwaples/rardecode v1.1.0 // indirect + github.com/nwaples/rardecode v1.1.3 // indirect github.com/opencontainers/go-digest v1.0.0 // indirect github.com/opencontainers/image-spec v1.1.0-rc5 // indirect github.com/opencontainers/runc v1.1.5 // indirect github.com/owenrumney/go-sarif/v2 v2.3.0 // indirect github.com/pelletier/go-toml/v2 v2.1.0 // indirect - github.com/pierrec/lz4/v4 v4.1.2 // indirect + github.com/pierrec/lz4/v4 v4.1.21 // indirect github.com/pjbgf/sha1cd v0.3.0 // indirect - github.com/pkg/browser v0.0.0-20210911075715-681adbf594b8 // indirect + github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c // indirect github.com/pkg/errors v0.9.1 // indirect github.com/pkg/term v1.1.0 // indirect github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect @@ -108,7 +107,8 @@ require ( github.com/spf13/pflag v1.0.5 // indirect github.com/spf13/viper v1.18.2 // indirect github.com/subosito/gotenv v1.6.0 // indirect - github.com/ulikunitz/xz v0.5.9 // indirect + github.com/ulikunitz/xz v0.5.11 // indirect + github.com/vbauerster/mpb/v7 v7.5.3 // indirect github.com/xanzy/ssh-agent v0.3.3 // indirect github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb // indirect github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 // indirect @@ -116,13 +116,13 @@ require ( github.com/xo/terminfo v0.0.0-20210125001918-ca9a967f8778 // indirect go.uber.org/atomic v1.9.0 // indirect go.uber.org/multierr v1.9.0 // indirect - golang.org/x/crypto v0.17.0 // indirect + golang.org/x/crypto v0.18.0 // indirect golang.org/x/mod v0.14.0 // indirect - golang.org/x/net v0.19.0 // indirect - golang.org/x/sync v0.5.0 // indirect - golang.org/x/sys v0.15.0 // indirect + golang.org/x/net v0.20.0 // indirect + golang.org/x/sync v0.6.0 // indirect + golang.org/x/sys v0.16.0 // indirect golang.org/x/text v0.14.0 // indirect - golang.org/x/tools v0.16.0 // indirect + golang.org/x/tools v0.17.0 // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20231120223509-83a465c0220f // indirect google.golang.org/grpc v1.59.0 // indirect google.golang.org/protobuf v1.31.0 // indirect @@ -131,9 +131,11 @@ require ( gopkg.in/yaml.v3 v3.0.1 // indirect ) -// replace github.com/jfrog/jfrog-cli-core/v2 => github.com/jfrog/jfrog-cli-core/v2 v2.31.1-0.20240104095135-8e243b03531d +// replace github.com/jfrog/jfrog-cli-core/v2 => github.com/jfrog/jfrog-cli-core/v2 v2.31.1-0.20240122141213-a1db3c179c7e + +// replace github.com/jfrog/jfrog-client-go => github.com/jfrog/jfrog-client-go v1.28.1-0.20240122123649-74f725715bbe -// replace github.com/jfrog/jfrog-client-go => github.com/jfrog/jfrog-client-go v1.28.1-0.20231220105505-e62769dde9da +// replace github.com/jfrog/jfrog-cli-security => github.com/jfrog/jfrog-cli-security v0.0.0-20240122124933-edf9cb4ca3ac // replace github.com/jfrog/build-info-go => github.com/jfrog/build-info-go v1.8.9-0.20231220102935-c8776c613ad8 diff --git a/go.sum b/go.sum index fbf201b69..2d978b28b 100644 --- a/go.sum +++ b/go.sum @@ -11,18 +11,19 @@ github.com/CycloneDX/cyclonedx-go v0.7.2/go.mod h1:K2bA+324+Og0X84fA8HhN2X066K7B github.com/Microsoft/go-winio v0.5.2/go.mod h1:WpS1mjBmmwHBEWmogvA2mj8546UReBk4v8QkMxJ6pZY= github.com/Microsoft/go-winio v0.6.1 h1:9/kr64B9VUZrLm5YYwbGtUJnMgqWVOdUAXu6Migciow= github.com/Microsoft/go-winio v0.6.1/go.mod h1:LRdKpFKfdobln8UmuiYcKPot9D2v6svN5+sAH+4kjUM= -github.com/Microsoft/hcsshim v0.11.1 h1:hJ3s7GbWlGK4YVV92sO88BQSyF4ZLVy7/awqOlPxFbA= -github.com/Microsoft/hcsshim v0.11.1/go.mod h1:nFJmaO4Zr5Y7eADdFOpYswDDlNVbvcIJJNJLECr5JQg= -github.com/ProtonMail/go-crypto v0.0.0-20230923063757-afb1ddc0824c h1:kMFnB0vCcX7IL/m9Y5LO+KQYv+t1CQOiFe6+SV2J7bE= -github.com/ProtonMail/go-crypto v0.0.0-20230923063757-afb1ddc0824c/go.mod h1:EjAoLdwvbIOoOQr3ihjnSoLZRtE8azugULFRteWMNc0= +github.com/Microsoft/hcsshim v0.11.4 h1:68vKo2VN8DE9AdN4tnkWnmdhqdbpUFM8OF3Airm7fz8= +github.com/Microsoft/hcsshim v0.11.4/go.mod h1:smjE4dvqPX9Zldna+t5FG3rnoHhaB7QYxPRqGcpAD9w= +github.com/ProtonMail/go-crypto v1.0.0 h1:LRuvITjQWX+WIfr930YHG2HNfjR1uOfyf5vE0kC2U78= +github.com/ProtonMail/go-crypto v1.0.0/go.mod h1:EjAoLdwvbIOoOQr3ihjnSoLZRtE8azugULFRteWMNc0= github.com/VividCortex/ewma v1.2.0 h1:f58SaIzcDXrSy3kWaHNvuJgJ3Nmz59Zji6XoJR/q1ow= github.com/VividCortex/ewma v1.2.0/go.mod h1:nz4BbCtbLyFDeC9SUHbtcT5644juEuWfUAUnGx7j5l4= github.com/acarl005/stripansi v0.0.0-20180116102854-5a71ef0e047d h1:licZJFw2RwpHMqeKTCYkitsPqHNxTmd4SNR5r94FGM8= github.com/acarl005/stripansi v0.0.0-20180116102854-5a71ef0e047d/go.mod h1:asat636LX7Bqt5lYEZ27JNDcqxfjdBQuJ/MM4CN/Lzo= github.com/agnivade/levenshtein v1.1.1 h1:QY8M92nrzkmr798gCo3kmMyqXFzdQVpxLlGPRBij0P8= github.com/agnivade/levenshtein v1.1.1/go.mod h1:veldBMzWxcCG2ZvUTKD2kJNRdCk5hVbJomOvKkmgYbo= -github.com/andybalholm/brotli v1.0.1 h1:KqhlKozYbRtJvsPrrEeXcO+N2l6NYT5A2QAFmSULpEc= github.com/andybalholm/brotli v1.0.1/go.mod h1:loMXtMfwqflxFJPmdbJO0a3KNoPuLBgiu3qAvBg8x/Y= +github.com/andybalholm/brotli v1.1.0 h1:eLKJA0d02Lf0mVpIDgYnqXcUn0GqVmEFny3VuID1U3M= +github.com/andybalholm/brotli v1.1.0/go.mod h1:sms7XGricyQI9K10gOSf56VKKWS4oLer58Q+mhRPtnY= github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be h1:9AeTilPcZAjCFIImctFaOjnTIavg87rW78vTPkQqLI8= github.com/apparentlymart/go-textseg/v13 v13.0.0/go.mod h1:ZK2fH7c4NqDTLtiYLvIkEghdlcqw7yxLeM89kiTRPUo= github.com/arbovm/levenshtein v0.0.0-20160628152529-48b4e1c0c4d0 h1:jfIu9sQUG6Ig+0+Ap1h4unLjW6YQJpKZVmUzxsD4E/Q= @@ -50,8 +51,8 @@ github.com/cilium/ebpf v0.7.0/go.mod h1:/oI2+1shJiTGAMgl6/RgJr36Eo1jzrRcAWbcXO2u github.com/cloudflare/circl v1.3.3 h1:fE/Qz0QdIGqeWfnwq0RE0R7MI51s0M2E4Ga9kq5AEMs= github.com/cloudflare/circl v1.3.3/go.mod h1:5XYMA4rFBvNIrhs50XuiBJ15vF2pZn4nnUKZrLbUZFA= github.com/containerd/console v1.0.3/go.mod h1:7LqA/THxQ86k76b8c/EMSiaJ3h1eZkMkXar0TQ1gf3U= -github.com/containerd/containerd v1.7.7 h1:QOC2K4A42RQpcrZyptP6z9EJZnlHfHJUfZrAAHe15q4= -github.com/containerd/containerd v1.7.7/go.mod h1:3c4XZv6VeT9qgf9GMTxNTMFxGJrGpI2vz1yk4ye+YY8= +github.com/containerd/containerd v1.7.11 h1:lfGKw3eU35sjV0aG2eYZTiwFEY1pCzxdzicHP3SZILw= +github.com/containerd/containerd v1.7.11/go.mod h1:5UluHxHTX2rdvYuZ5OJTC5m/KJNs0Zs9wVoJm9zf5ZE= github.com/containerd/log v0.1.0 h1:TCJt7ioM2cr/tfR8GPbGf9/VRAX8D2B4PjzCpfX540I= github.com/containerd/log v0.1.0/go.mod h1:VRRf09a7mHDIRezVKTRCrOq78v577GXq3bSa3EhrzVo= github.com/coreos/go-systemd/v22 v22.3.2/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= @@ -72,8 +73,8 @@ github.com/dgryski/trifles v0.0.0-20200323201526-dd97f9abfb48 h1:fRzb/w+pyskVMQ+ github.com/dgryski/trifles v0.0.0-20200323201526-dd97f9abfb48/go.mod h1:if7Fbed8SFyPtHLHbg49SI7NAdJiC5WIA09pe59rfAA= github.com/docker/distribution v2.8.2+incompatible h1:T3de5rq0dB1j30rp0sA2rER+m322EBzniBPB6ZIzuh8= github.com/docker/distribution v2.8.2+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w= -github.com/docker/docker v24.0.6+incompatible h1:hceabKCtUgDqPu+qm0NgsaXf28Ljf4/pWFL7xjWWDgE= -github.com/docker/docker v24.0.6+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= +github.com/docker/docker v24.0.7+incompatible h1:Wo6l37AuwP3JaMnZa226lzVXGA3F9Ig1seQen0cKYlM= +github.com/docker/docker v24.0.7+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= github.com/docker/go-connections v0.4.0 h1:El9xVISelRB7BuFusrZozjnkIM5YnzCViNKohAFqRJQ= github.com/docker/go-connections v0.4.0/go.mod h1:Gbd7IOopHjR8Iph03tsViu4nIes5XhDvyHbTtUxmeec= github.com/docker/go-units v0.4.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk= @@ -114,8 +115,9 @@ github.com/golang/protobuf v1.3.4/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaW github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg= github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= -github.com/golang/snappy v0.0.2 h1:aeE13tS0IiQgFjYdoL8qN3K1N2bXXtI6Vi51/y7BpMw= github.com/golang/snappy v0.0.2/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= +github.com/golang/snappy v0.0.4 h1:yAGX7huGHXlcLOEtBnF4w7FQwA26wojNCwOYAEhLjQM= +github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= @@ -128,35 +130,38 @@ github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4= github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 h1:BQSFePA1RWJOlocH6Fxy8MmwDt+yVQYULKfN0RoTN8A= github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99/go.mod h1:1lJo3i6rXxKeerYnT8Nvf0QmHCRC1n8sfWVwXF2Frvo= -github.com/jedib0t/go-pretty/v6 v6.4.0 h1:YlI/2zYDrweA4MThiYMKtGRfT+2qZOO65ulej8GTcVI= -github.com/jedib0t/go-pretty/v6 v6.4.0/go.mod h1:MgmISkTWDSFu0xOqiZ0mKNntMQ2mDgOcwOkwBEkMDJI= -github.com/jfrog/archiver/v3 v3.5.3 h1:Udz6+z/YIhTFmcEp1TeW2DEwNyo7JSAnrGUsrbL2FZI= -github.com/jfrog/archiver/v3 v3.5.3/go.mod h1:/MbmBhPzkliu9PtweAg9lCYHGcKdapwMMZS/QS09T5c= -github.com/jfrog/build-info-go v1.9.20 h1:tQF6EMjt/EEX8syTrgpL/c7FjhlBSjtv848jNvxpMp8= -github.com/jfrog/build-info-go v1.9.20/go.mod h1:Vxv6zmx4e1NWsx40OHaDWCCYDeYAq2yXzpJ4nsDChbE= -github.com/jfrog/gofrog v1.4.1 h1:jz4kXBdsvVCNRDVkGLRiZIQ+uTO6/DSxQ9LjfvmLfoY= -github.com/jfrog/gofrog v1.4.1/go.mod h1:wQqagqq2VpuCWRPlq/65GbH9gsRz+7Bgc1Q+PKD4Y+k= +github.com/jedib0t/go-pretty/v6 v6.5.3 h1:GIXn6Er/anHTkVUoufs7ptEvxdD6KIhR7Axa2wYCPF0= +github.com/jedib0t/go-pretty/v6 v6.5.3/go.mod h1:5LQIxa52oJ/DlDSLv0HEkWOFMDGoWkJb9ss5KqPpJBg= +github.com/jfrog/archiver/v3 v3.6.0 h1:OVZ50vudkIQmKMgA8mmFF9S0gA47lcag22N13iV3F1w= +github.com/jfrog/archiver/v3 v3.6.0/go.mod h1:fCAof46C3rAXgZurS8kNRNdSVMKBbZs+bNNhPYxLldI= +github.com/jfrog/build-info-go v1.9.21 h1:bcD0SEC2lEilhjE+aDB3xlvA8zsr4Kw/bFzvr9Tcj9I= +github.com/jfrog/build-info-go v1.9.21/go.mod h1:Vxv6zmx4e1NWsx40OHaDWCCYDeYAq2yXzpJ4nsDChbE= +github.com/jfrog/gofrog v1.5.1 h1:2AXL8hHu1jJFMIoCqTp2OyRUfEqEp4nC7J8fwn6KtwE= +github.com/jfrog/gofrog v1.5.1/go.mod h1:SZ1EPJUruxrVGndOzHd+LTiwWYKMlHqhKD+eu+v5Hqg= github.com/jfrog/jfrog-apps-config v1.0.1 h1:mtv6k7g8A8BVhlHGlSveapqf4mJfonwvXYLipdsOFMY= github.com/jfrog/jfrog-apps-config v1.0.1/go.mod h1:8AIIr1oY9JuH5dylz2S6f8Ym2MaadPLR6noCBO4C22w= -github.com/jfrog/jfrog-cli-core/v2 v2.47.10 h1:14d6nQBU4zVV2c6ieH7pc/efDKybIgW0RnoXcsaU28A= -github.com/jfrog/jfrog-cli-core/v2 v2.47.10/go.mod h1:ZcyEfF9CuSsLCx1XiVd1xbwUdHlLH6Y6zvuXVipn+SE= -github.com/jfrog/jfrog-client-go v1.35.6 h1:nVS94x6cwSRkhtj8OM3elbUcGgQhqsK8YMPvC/gf5sk= -github.com/jfrog/jfrog-client-go v1.35.6/go.mod h1:V+XKC27k6GA5OcWIAItpnxZAZnCigg8xCkpXKP905Fk= -github.com/jszwec/csvutil v1.8.0 h1:G7vS2LGdpZZDH1HmHeNbxOaJ/ZnJlpwGFvOkTkJzzNk= -github.com/jszwec/csvutil v1.8.0/go.mod h1:/E4ONrmGkwmWsk9ae9jpXnv9QT8pLHEPcCirMFhxG9I= +github.com/jfrog/jfrog-cli-core/v2 v2.47.11 h1:2oHyITZjnjuuwU/LEVedlA3NkJz3PbaXdBT2Y1kt21o= +github.com/jfrog/jfrog-cli-core/v2 v2.47.11/go.mod h1:RVn4pIkR5fPUnr8gFXt61ou3pCNrrDdRQUpcolP4lhw= +github.com/jfrog/jfrog-cli-security v0.0.0-20240122124933-edf9cb4ca3ac h1:tNn3TQXaIJZ9Fu5jiVB9lWpJAKkEGWNjz/6WzHhHePI= +github.com/jfrog/jfrog-cli-security v0.0.0-20240122124933-edf9cb4ca3ac/go.mod h1:X4rz1639L8vWKJgpLxpO3ddkIW7KaCaQjbwani7FPf4= +github.com/jfrog/jfrog-client-go v1.36.0 h1:iODLDjYSlK7rLH8/lEmAFHwYsboeBfaqxXybz6waraE= +github.com/jfrog/jfrog-client-go v1.36.0/go.mod h1:y1WF6eiZ7V2DortiwjpMEicEH6NIJH+hOXI5QI2W3NU= +github.com/jszwec/csvutil v1.9.0 h1:iTmq9G1P0e+AUq/MkFg6tetJ+1BH3fOX8Xi0RAcwiGc= +github.com/jszwec/csvutil v1.9.0/go.mod h1:/E4ONrmGkwmWsk9ae9jpXnv9QT8pLHEPcCirMFhxG9I= github.com/kevinburke/ssh_config v1.2.0 h1:x584FjTGwHzMwvHx18PXxbBVzfnxogHaAReU4gf13a4= github.com/kevinburke/ssh_config v1.2.0/go.mod h1:CT57kijsi8u/K/BOFA39wgDQJ9CxiF4nAY/ojJ6r6mM= github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= github.com/klauspost/compress v1.4.1/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A= github.com/klauspost/compress v1.11.4/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs= -github.com/klauspost/compress v1.17.0 h1:Rnbp4K9EjcDuVuHtd0dgA4qNuv9yKDYKK1ulpJwgrqM= -github.com/klauspost/compress v1.17.0/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE= +github.com/klauspost/compress v1.17.4 h1:Ej5ixsIri7BrIjBkRZLTo6ghwrEtHFk7ijlczPW4fZ4= +github.com/klauspost/compress v1.17.4/go.mod h1:/dCuZOvVtNoHsyb+cuJD3itjs3NbnF6KH9zAO4BDxPM= github.com/klauspost/cpuid v1.2.0/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek= github.com/klauspost/cpuid/v2 v2.2.3 h1:sxCkb+qR91z4vsqw4vGGZlDgPz3G7gjaLyK3V8y70BU= github.com/klauspost/cpuid/v2 v2.2.3/go.mod h1:RVVoqg1df56z8g3pUjL/3lE5UfnlrJX8tyFgg4nqhuY= -github.com/klauspost/pgzip v1.2.5 h1:qnWYvvKqedOF2ulHpMG72XQol4ILEJ8k2wwRl/Km8oE= github.com/klauspost/pgzip v1.2.5/go.mod h1:Ch1tH69qFZu15pkjo5kYi6mth2Zzwzt50oCQKQE9RUs= +github.com/klauspost/pgzip v1.2.6 h1:8RXeL5crjEUFnR2/Sn6GJNWtSQ3Dk8pq4CL3jvdDyjU= +github.com/klauspost/pgzip v1.2.6/go.mod h1:Ch1tH69qFZu15pkjo5kYi6mth2Zzwzt50oCQKQE9RUs= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= @@ -179,8 +184,9 @@ github.com/mattn/go-isatty v0.0.17 h1:BTarxUcIeDqL27Mc+vyvdWYSL28zpIhv3RoTdsLMPn github.com/mattn/go-isatty v0.0.17/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= github.com/mattn/go-runewidth v0.0.6/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI= github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI= -github.com/mattn/go-runewidth v0.0.13 h1:lTGmDsbAYt5DmK6OnoV7EuIF1wEIFAcxld6ypU4OSgU= github.com/mattn/go-runewidth v0.0.13/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= +github.com/mattn/go-runewidth v0.0.15 h1:UNAjwbU9l54TA3KzvqLGxwWjHmMgBUVhBiTjelZgg3U= +github.com/mattn/go-runewidth v0.0.15/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= github.com/mattn/go-tty v0.0.3 h1:5OfyWorkyO7xP52Mq7tB36ajHDG5OHrmBGIS/DtakQI= github.com/mattn/go-tty v0.0.3/go.mod h1:ihxohKRERHTVzN+aSVRwACLCeqIoZAWpoICkkvrWyR0= github.com/mholt/archiver/v3 v3.5.1 h1:rDjOBX9JSF5BvoJGvjqK479aL70qh9DIpZCl+k7Clwo= @@ -199,8 +205,9 @@ github.com/moby/term v0.5.0/go.mod h1:8FzsFHVUBGZdbDsJw/ot+X+d5HLUbvklYLJ9uGfcI3 github.com/morikuni/aec v1.0.0 h1:nP9CBfwrvYnBRgY6qfDQkygYDmYwOilePFkwzv4dU8A= github.com/morikuni/aec v1.0.0/go.mod h1:BbKIizmSmc5MMPqRYbxO4ZU0S0+P200+tUnFx7PXmsc= github.com/mrunalp/fileutils v0.5.0/go.mod h1:M1WthSahJixYnrXQl/DFQuteStB1weuxD2QJNHXfbSQ= -github.com/nwaples/rardecode v1.1.0 h1:vSxaY8vQhOcVr4mm5e8XllHWTiM4JF507A0Katqw7MQ= github.com/nwaples/rardecode v1.1.0/go.mod h1:5DzqNKiOdpKKBH87u8VlvAnPZMXcGRhxWkRpHbbfGS0= +github.com/nwaples/rardecode v1.1.3 h1:cWCaZwfM5H7nAD6PyEdcVnczzV8i/JtotnyW/dD9lEc= +github.com/nwaples/rardecode v1.1.3/go.mod h1:5DzqNKiOdpKKBH87u8VlvAnPZMXcGRhxWkRpHbbfGS0= github.com/onsi/gomega v1.27.10 h1:naR28SdDFlqrG6kScpT8VWpu1xWY5nJRCF3XaYyBjhI= github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U= github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM= @@ -215,15 +222,15 @@ github.com/owenrumney/go-sarif/v2 v2.3.0 h1:wP5yEpI53zr0v5cBmagXzLbHZp9Oylyo3AJD github.com/owenrumney/go-sarif/v2 v2.3.0/go.mod h1:MSqMMx9WqlBSY7pXoOZWgEsVB4FDNfhcaXDA1j6Sr+w= github.com/pelletier/go-toml/v2 v2.1.0 h1:FnwAJ4oYMvbT/34k9zzHuZNrhlz48GB3/s6at6/MHO4= github.com/pelletier/go-toml/v2 v2.1.0/go.mod h1:tJU2Z3ZkXwnxa4DPO899bsyIoywizdUvyaeZurnPPDc= -github.com/pierrec/lz4/v4 v4.1.2 h1:qvY3YFXRQE/XB8MlLzJH7mSzBs74eA2gg52YTk6jUPM= github.com/pierrec/lz4/v4 v4.1.2/go.mod h1:gZWDp/Ze/IJXGXf23ltt2EXimqmTUXEy0GFuRQyBid4= +github.com/pierrec/lz4/v4 v4.1.21 h1:yOVMLb6qSIDP67pl/5F7RepeKYu/VmTyEXvuMI5d9mQ= +github.com/pierrec/lz4/v4 v4.1.21/go.mod h1:gZWDp/Ze/IJXGXf23ltt2EXimqmTUXEy0GFuRQyBid4= github.com/pjbgf/sha1cd v0.3.0 h1:4D5XXmUUBUl/xQ6IjCkEAbqXskkq/4O7LmGn0AqMDs4= github.com/pjbgf/sha1cd v0.3.0/go.mod h1:nZ1rrWOcGJ5uZgEEVL1VUM9iRQiZvWdbZjkKyFzPPsI= -github.com/pkg/browser v0.0.0-20210911075715-681adbf594b8 h1:KoWmjvw+nsYOo29YJK9vDA65RGE3NrOnUtO7a+RF9HU= -github.com/pkg/browser v0.0.0-20210911075715-681adbf594b8/go.mod h1:HKlIX3XHQyzLZPlr7++PzdhaXEj94dEiJgZDTsxEqUI= +github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c h1:+mdjkGKdHQG3305AYmdv1U2eRNDiU2ErMBj1gwrq8eQ= +github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c/go.mod h1:7rwL4CYBLnjLxUqIJNnCWiEdr3bn6IUYi15bNlnbCCU= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= -github.com/pkg/profile v1.6.0/go.mod h1:qBsxPvzyUincmltOk6iyRVxHYg4adc0OFOv72ZdLa18= github.com/pkg/term v1.1.0 h1:xIAAdCMh3QIAy+5FrE8Ad8XoDhEU4ufwbaSozViP9kk= github.com/pkg/term v1.1.0/go.mod h1:E25nymQcrSllhX42Ok8MRm1+hyBdHY0dCeiKZ9jpNGw= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= @@ -268,7 +275,6 @@ github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UV github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -github.com/stretchr/testify v1.7.4/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= @@ -279,8 +285,9 @@ github.com/terminalstatic/go-xsd-validate v0.1.5 h1:RqpJnf6HGE2CB/lZB1A8BYguk8uR github.com/testcontainers/testcontainers-go v0.23.0 h1:ERYTSikX01QczBLPZpqsETTBO7lInqEP349phDOVJVs= github.com/testcontainers/testcontainers-go v0.23.0/go.mod h1:3gzuZfb7T9qfcH2pHpV4RLlWrPjeWNQah6XlYQ32c4I= github.com/ulikunitz/xz v0.5.8/go.mod h1:nbz6k7qbPmH4IRqmfOplQw/tblSgqTqBwxkY0oWt/14= -github.com/ulikunitz/xz v0.5.9 h1:RsKRIA2MO8x56wkkcd3LbtcE/uMszhb6DpRf+3uwa3I= github.com/ulikunitz/xz v0.5.9/go.mod h1:nbz6k7qbPmH4IRqmfOplQw/tblSgqTqBwxkY0oWt/14= +github.com/ulikunitz/xz v0.5.11 h1:kpFauv27b6ynzBNT/Xy+1k+fK4WswhN/6PN5WhFAGw8= +github.com/ulikunitz/xz v0.5.11/go.mod h1:nbz6k7qbPmH4IRqmfOplQw/tblSgqTqBwxkY0oWt/14= github.com/urfave/cli v1.22.1/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0= github.com/urfave/cli v1.22.14 h1:ebbhrRiGK2i4naQJr+1Xj92HXZCrK7MsyTS/ob3HnAk= github.com/urfave/cli v1.22.14/go.mod h1:X0eDS6pD6Exaclxm99NJ3FiCDRED7vIHpx2mDOHLvkA= @@ -318,10 +325,10 @@ golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5y golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= golang.org/x/crypto v0.3.1-0.20221117191849-2c476679df9a/go.mod h1:hebNnKkNXi2UzZN1eVRvBB7co0a+JxK6XbPiWVs/3J4= golang.org/x/crypto v0.7.0/go.mod h1:pYwdfH91IfpZVANVyUOhSIPZaFoJGxTFbZhFTx+dXZU= -golang.org/x/crypto v0.17.0 h1:r8bRNjWL3GshPW3gkd+RpvzWrZAwPS49OmTGZ/uhM4k= -golang.org/x/crypto v0.17.0/go.mod h1:gCAAfMLgwOJRpTjQ2zCCt2OcSfYMTeZVSRtQlPC7Nq4= -golang.org/x/exp v0.0.0-20231226003508-02704c960a9b h1:kLiC65FbiHWFAOu+lxwNPujcsl8VYyTYYEZnsOO1WK4= -golang.org/x/exp v0.0.0-20231226003508-02704c960a9b/go.mod h1:iRJReGqOEeBhDZGkGbynYwcHlctCvnjTYIamk7uXpHI= +golang.org/x/crypto v0.18.0 h1:PGVlW0xEltQnzFZ55hkuX5+KLyrMYhHld1YHO4AKcdc= +golang.org/x/crypto v0.18.0/go.mod h1:R0j02AL6hcrfOiy9T4ZYp/rcWeMxM3L6QYxlOuEG1mg= +golang.org/x/exp v0.0.0-20240119083558-1b970713d09a h1:Q8/wZp0KX97QFTc2ywcOE0YRjZPVIx+MXInMzdvQqcA= +golang.org/x/exp v0.0.0-20240119083558-1b970713d09a/go.mod h1:idGWGoKP1toJGkd5/ig9ZLuPcZBC3ewk7SzmH0uou08= golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= @@ -341,15 +348,15 @@ golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug golang.org/x/net v0.2.0/go.mod h1:KqCZLdyyvdV855qA2rE3GC2aiw5xGR5TEjj8smXukLY= golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= golang.org/x/net v0.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc= -golang.org/x/net v0.19.0 h1:zTwKpTd2XuCqf8huc7Fo2iSy+4RHPd10s4KzeTnVr1c= -golang.org/x/net v0.19.0/go.mod h1:CfAk/cbD4CthTvqiEl8NpboMuiuOYsAr/7NOjZJtv1U= +golang.org/x/net v0.20.0 h1:aCL9BSgETF1k+blQaYUBx9hJ9LOGP3gAVemcZlf1Kpo= +golang.org/x/net v0.20.0/go.mod h1:z8BVo6PvndSri0LbOE3hAn0apkU+1YvI6E70E9jsnvY= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.5.0 h1:60k92dhOjHxJkrqnwsfl8KuaHbn/5dl0lUPUklKo3qE= -golang.org/x/sync v0.5.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= +golang.org/x/sync v0.6.0 h1:5BMeUDZ7vkXGfEr1x9B4bRcTH4lpkTkpdh0T/J+qjbQ= +golang.org/x/sync v0.6.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sys v0.0.0-20181122145206-62eef0e2fa9b/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -368,7 +375,6 @@ golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210616045830-e2b7044e8c71/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210906170528-6f6e22806c34/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20211025201205-69cdffdb9359/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= @@ -380,19 +386,20 @@ golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220909162455-aba9fc2a8ff2/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.3.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.15.0 h1:h48lPFYpsTvQJZF4EKyI4aLHaev3CxivZmv7yZig9pc= -golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.16.0 h1:xWw16ngr6ZMtmxDyKyIgsE93KNKz5HKmMa3b8ALHidU= +golang.org/x/sys v0.16.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.2.0/go.mod h1:TVmDHMZPmdnySmBfhjOoOdhjzdE1h4u1VwSiw2l1Nuc= golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= golang.org/x/term v0.6.0/go.mod h1:m6U89DPEgQRMq3DNkDClhWw02AUbt2daBVO4cn4Hv9U= -golang.org/x/term v0.15.0 h1:y/Oo/a/q3IXu26lQgl04j/gjuBDOBlx7X6Om1j2CPW4= -golang.org/x/term v0.15.0/go.mod h1:BDl952bC7+uMoWR75FIrCDx79TPU9oHkTZ9yRbYOrX0= +golang.org/x/term v0.16.0 h1:m+B6fahuftsE9qjo0VWp2FW0mB3MTJvR0BaMQrq0pmE= +golang.org/x/term v0.16.0/go.mod h1:yn7UURbUtPyrVJPGPq404EukNFxcm/foM+bV/bfcDsY= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= @@ -411,8 +418,8 @@ golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roY golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= -golang.org/x/tools v0.16.0 h1:GO788SKMRunPIBCXiQyo2AaexLstOrVhuAL5YwsckQM= -golang.org/x/tools v0.16.0/go.mod h1:kYVVN6I1mBNoB1OX+noeBjbRk4IUEPa7JJ+TJMEooJ0= +golang.org/x/tools v0.17.0 h1:FvmRgNOcs3kOa+T20R1uhfP9F6HgG2mfxDv1vrx1Htc= +golang.org/x/tools v0.17.0/go.mod h1:xsh6VxdV005rRVaS6SSAf9oiAqljS7UZUacMZ8Bnsps= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= diff --git a/go_test.go b/go_test.go index 153892df6..77bfff423 100644 --- a/go_test.go +++ b/go_test.go @@ -52,7 +52,7 @@ func TestGoGetSpecificVersion(t *testing.T) { runGo(t, "", tests.GoBuildName, buildNumber, 4, 0, "go", "build", "--mod=mod", "--build-name="+tests.GoBuildName, "--build-number="+buildNumber) // Go get one of the known dependencies - jfrogCli := tests.NewJfrogCli(execMain, "jfrog", "") + jfrogCli := coretests.NewJfrogCli(execMain, "jfrog", "") err = execGo(jfrogCli, "go", "get", "rsc.io/quote@v1.5.2", "--build-name="+tests.GoBuildName, "--build-number="+buildNumber) if err != nil { assert.NoError(t, err) @@ -90,7 +90,7 @@ func TestGoGetNestedPackage(t *testing.T) { wd, err := os.Getwd() assert.NoError(t, err, "Failed to get current dir") prepareGoProject("project1", t, true) - jfrogCli := tests.NewJfrogCli(execMain, "jfrog", "") + jfrogCli := coretests.NewJfrogCli(execMain, "jfrog", "") // Download 'mockgen', which is a nested package inside 'github.com/golang/mock@v1.4.1'. Then validate it was downloaded correctly. err = execGo(jfrogCli, "go", "get", "github.com/golang/mock/mockgen@v1.4.1") @@ -152,7 +152,7 @@ func TestGoPublishWithDetailedSummary(t *testing.T) { // Publish with detailed summary and buildinfo. // Build project buildNumber := "1" - jfrogCli := tests.NewJfrogCli(execMain, "jfrog", "") + jfrogCli := coretests.NewJfrogCli(execMain, "jfrog", "") assert.NoError(t, execGo(jfrogCli, "go", "build", "--mod=mod", "--build-name="+tests.GoBuildName, "--build-number="+buildNumber, "--module="+ModuleNameJFrogTest)) // GoPublish with detailed summary without buildinfo. @@ -193,7 +193,7 @@ func TestGoPublishWithDeploymentView(t *testing.T) { wd, err := os.Getwd() assert.NoError(t, err, "Failed to get current dir") prepareGoProject("project1", t, true) - jfrogCli := tests.NewJfrogCli(execMain, "jf", "") + jfrogCli := coretests.NewJfrogCli(execMain, "jf", "") err = execGo(jfrogCli, "gp", "v1.1.1") if err != nil { assert.NoError(t, err) @@ -224,7 +224,7 @@ func TestGoPublishWithExclusions(t *testing.T) { } for _, test := range testData { prepareGoProject("project4", t, true) - jfrogCli := tests.NewJfrogCli(execMain, "jf", "") + jfrogCli := coretests.NewJfrogCli(execMain, "jf", "") err = execGo(jfrogCli, "gp", "v1.1.1", "--exclusions", test.exclusions) assert.NoError(t, err) @@ -263,7 +263,7 @@ func TestGoVcsFallback(t *testing.T) { assert.NoError(t, err, "Failed to get current dir") _ = prepareGoProject("vcsfallback", t, false) - jfrogCli := tests.NewJfrogCli(execMain, "jfrog", "") + jfrogCli := coretests.NewJfrogCli(execMain, "jfrog", "") // Run "go get github.com/octocat/Hello-World" with --no-fallback. // This package is not a Go package, and therefore we'd expect the command to fail. err = execGo(jfrogCli, "go", "get", "github.com/octocat/Hello-World", "--no-fallback") @@ -341,7 +341,7 @@ func createGoProject(t *testing.T, projectName string, includeDirs bool) string // runGo runs 'jfrog' command with the given args, publishes a build info, validates it and finally deletes it. func runGo(t *testing.T, module, buildName, buildNumber string, expectedDependencies, expectedArtifacts int, args ...string) { - jfrogCli := tests.NewJfrogCli(execMain, "jfrog", "") + jfrogCli := coretests.NewJfrogCli(execMain, "jfrog", "") err := execGo(jfrogCli, args...) if err != nil { assert.NoError(t, err) @@ -372,7 +372,7 @@ func runGo(t *testing.T, module, buildName, buildNumber string, expectedDependen validateBuildInfo(buildInfo, t, expectedDependencies, expectedArtifacts, module, buildinfo.Go) } -func execGo(cli *tests.JfrogCli, args ...string) error { +func execGo(cli *coretests.JfrogCli, args ...string) error { return cli.WithoutCredentials().Exec(args...) } diff --git a/gradle_test.go b/gradle_test.go index 37cd28e42..a1ffed56d 100644 --- a/gradle_test.go +++ b/gradle_test.go @@ -1,17 +1,24 @@ package main import ( + "errors" "os" "path/filepath" "strings" "testing" + "github.com/jfrog/jfrog-cli/utils/cliutils" + "github.com/jfrog/jfrog-client-go/utils/log" + clientTestUtils "github.com/jfrog/jfrog-client-go/utils/tests" buildinfo "github.com/jfrog/build-info-go/entities" "github.com/jfrog/jfrog-cli-core/v2/artifactory/commands/gradle" "github.com/jfrog/jfrog-cli-core/v2/common/build" + commonCliUtils "github.com/jfrog/jfrog-cli-core/v2/common/cliutils" "github.com/jfrog/jfrog-cli-core/v2/common/commands" + outputFormat "github.com/jfrog/jfrog-cli-core/v2/common/format" + "github.com/jfrog/jfrog-cli-core/v2/common/project" "github.com/jfrog/jfrog-cli-core/v2/common/spec" "github.com/jfrog/jfrog-cli-core/v2/utils/coreutils" @@ -45,12 +52,37 @@ func TestGradleBuildConditionalUpload(t *testing.T) { oldHomeDir := changeWD(t, filepath.Dir(buildGradlePath)) defer clientTestUtils.ChangeDirAndAssert(t, oldHomeDir) execFunc := func() error { - return runJfrogCliWithoutAssertion("gradle", "clean", "artifactoryPublish", "-b"+buildGradlePath, "--scan") + return runGradleConditionalUploadTest(buildGradlePath) } testConditionalUpload(t, execFunc, searchSpec, tests.GetGradleDeployedArtifacts()...) cleanGradleTest(t) } +func runGradleConditionalUploadTest(buildGradlePath string) (err error) { + configFilePath, exists, err := project.GetProjectConfFilePath(project.Gradle) + if err != nil { + return err + } + if !exists { + return errors.New("no config file was found!") + } + buildConfig := build.NewBuildConfiguration("", "", "", "") + if err = buildConfig.ValidateBuildAndModuleParams(); err != nil { + return + } + printDeploymentView := log.IsStdErrTerminal() + gradleCmd := gradle.NewGradleCommand(). + SetTasks([]string{"clean", "artifactoryPublish", "-b" + buildGradlePath}). + SetConfiguration(buildConfig). + SetXrayScan(true).SetScanOutputFormat(outputFormat.Table). + SetDetailedSummary(printDeploymentView).SetConfigPath(configFilePath).SetThreads(commonCliUtils.Threads) + err = commands.Exec(gradleCmd) + result := gradleCmd.Result() + defer cliutils.CleanupResult(result, &err) + err = cliutils.PrintCommandSummary(gradleCmd.Result(), false, printDeploymentView, false, err) + return +} + func TestGradleWithDeploymentView(t *testing.T) { initGradleTest(t) buildGradlePath := createGradleProject(t, "gradleproject") diff --git a/inttestutils/distribution.go b/inttestutils/distribution.go index 8e13aab6b..90b1bfde0 100644 --- a/inttestutils/distribution.go +++ b/inttestutils/distribution.go @@ -11,8 +11,8 @@ import ( "time" "github.com/jfrog/jfrog-cli-core/v2/common/spec" - "github.com/jfrog/jfrog-cli-core/v2/utils/coreutils" + coreTests "github.com/jfrog/jfrog-cli-core/v2/utils/tests" "github.com/buger/jsonparser" "github.com/jfrog/jfrog-cli-core/v2/utils/config" @@ -220,7 +220,7 @@ func getLocalBundle(t *testing.T, bundleName, bundleVersion string, distHttpDeta return resp, body } -func CleanUpOldBundles(distHttpDetails httputils.HttpClientDetails, bundleVersion string, distributionCli *tests.JfrogCli) { +func CleanUpOldBundles(distHttpDetails httputils.HttpClientDetails, bundleVersion string, distributionCli *coreTests.JfrogCli) { getActualItems := func() ([]string, error) { return ListAllBundlesNames(distHttpDetails) } deleteItem := func(bundleName string) { err := distributionCli.Exec("rbdel", bundleName, bundleVersion, "--site=*", "--delete-from-dist", "--quiet") diff --git a/inttestutils/docker.go b/inttestutils/docker.go index 5b537d2db..5fdc2d946 100644 --- a/inttestutils/docker.go +++ b/inttestutils/docker.go @@ -1,8 +1,6 @@ package inttestutils import ( - "io" - "os/exec" "path" "path/filepath" "strings" @@ -14,6 +12,7 @@ import ( "github.com/jfrog/jfrog-cli-core/v2/artifactory/commands/generic" "github.com/jfrog/jfrog-cli-core/v2/artifactory/utils" "github.com/jfrog/jfrog-cli-core/v2/artifactory/utils/container" + commonTests "github.com/jfrog/jfrog-cli-core/v2/common/tests" "github.com/jfrog/jfrog-cli-core/v2/utils/config" "github.com/jfrog/jfrog-cli/utils/tests" "github.com/jfrog/jfrog-client-go/utils/io/httputils" @@ -21,194 +20,14 @@ import ( "github.com/stretchr/testify/assert" ) -// Image get parent image id command -type BuildDockerImage struct { - // The build command builds images from a Dockerfile and a context. - // A build's context is the set of files located in the specified PATH. - // The build process can refer to any of the files in the context. - // For example, The build can use a COPY instruction to reference a file in the context. - buildContext string - dockerFileName string - imageName string - containerManager container.ContainerManagerType -} - -func NewBuildDockerImage(imageTag, dockerFilePath string, containerManager container.ContainerManagerType) *BuildDockerImage { - return &BuildDockerImage{imageName: imageTag, buildContext: dockerFilePath, containerManager: containerManager} -} - -func (image *BuildDockerImage) SetDockerFileName(name string) *BuildDockerImage { - image.dockerFileName = name - return image -} - -func (image *BuildDockerImage) GetCmd() *exec.Cmd { - var cmd []string - cmd = append(cmd, "build") - cmd = append(cmd, "--tag", image.imageName) - if image.dockerFileName != "" { - cmd = append(cmd, "--file", path.Join(image.buildContext, image.dockerFileName)) - - } - cmd = append(cmd, image.buildContext) - return exec.Command(image.containerManager.String(), cmd...) -} - -func (image *BuildDockerImage) GetEnv() map[string]string { - return map[string]string{} -} - -func (image *BuildDockerImage) GetStdWriter() io.WriteCloser { - return nil -} - -func (image *BuildDockerImage) GetErrWriter() io.WriteCloser { - return nil -} - -// The ExecDockerImage command runs a new command in a running container. -type ExecDockerImage struct { - Args []string - errCloser io.WriteCloser - stdWriter io.WriteCloser - containerManager container.ContainerManagerType -} - -func NewExecDockerImage(containerManager container.ContainerManagerType, args ...string) *ExecDockerImage { - return &ExecDockerImage{Args: args, containerManager: containerManager} -} - -func (e *ExecDockerImage) GetCmd() *exec.Cmd { - var cmd []string - cmd = append(cmd, "exec") - cmd = append(cmd, e.Args...) - return exec.Command(e.containerManager.String(), cmd...) -} - -func (e *ExecDockerImage) GetEnv() map[string]string { - return map[string]string{} -} - -func (e *ExecDockerImage) GetStdWriter() io.WriteCloser { - return e.stdWriter -} - -func (e *ExecDockerImage) SetStdWriter(writer io.WriteCloser) { - e.stdWriter = writer -} - -func (e *ExecDockerImage) GetErrWriter() io.WriteCloser { - return e.errCloser -} - -func (e *ExecDockerImage) SetErrWriter(writer io.WriteCloser) { - e.errCloser = writer -} - -type RunDockerImage struct { - Args []string - containerManager container.ContainerManagerType -} - -func NewRunDockerImage(containerManager container.ContainerManagerType, args ...string) *RunDockerImage { - return &RunDockerImage{Args: args, containerManager: containerManager} -} - -func (run *RunDockerImage) GetCmd() *exec.Cmd { - var cmd []string - cmd = append(cmd, "run") - cmd = append(cmd, run.Args...) - return exec.Command(run.containerManager.String(), cmd...) -} - -func (run *RunDockerImage) GetEnv() map[string]string { - return map[string]string{} -} - -func (run *RunDockerImage) GetStdWriter() io.WriteCloser { - return nil -} - -func (run *RunDockerImage) GetErrWriter() io.WriteCloser { - return nil -} - -type DeleteDockerImage struct { - imageTag string - containerManager container.ContainerManagerType -} - -func NewDeleteDockerImage(imageTag string, containerManager container.ContainerManagerType) *DeleteDockerImage { - return &DeleteDockerImage{imageTag: imageTag, containerManager: containerManager} -} - -func (image *DeleteDockerImage) GetCmd() *exec.Cmd { - var cmd []string - cmd = append(cmd, "image") - cmd = append(cmd, "rm") - cmd = append(cmd, image.imageTag) - return exec.Command(image.containerManager.String(), cmd...) -} - -func (image *DeleteDockerImage) GetEnv() map[string]string { - return map[string]string{} -} - -func (image *DeleteDockerImage) GetStdWriter() io.WriteCloser { - return nil -} - -func (image *DeleteDockerImage) GetErrWriter() io.WriteCloser { - return nil -} - -type DeleteContainer struct { - containerName string - containerManager container.ContainerManagerType -} - -func NewDeleteContainer(containerName string, containerManager container.ContainerManagerType) *DeleteContainer { - return &DeleteContainer{containerName: containerName, containerManager: containerManager} -} - -func (image *DeleteContainer) GetCmd() *exec.Cmd { - var cmd []string - cmd = append(cmd, "rm") - cmd = append(cmd, "--force") - cmd = append(cmd, image.containerName) - return exec.Command(image.containerManager.String(), cmd...) -} - -func (image *DeleteContainer) GetEnv() map[string]string { - return map[string]string{} -} - -func (image *DeleteContainer) GetStdWriter() io.WriteCloser { - return nil -} - -func (image *DeleteContainer) GetErrWriter() io.WriteCloser { - return nil -} - func BuildTestImage(imageName, dockerfileName, repo string, containerManagerType container.ContainerManagerType) (string, error) { log.Info("Building image", imageName, "with", containerManagerType.String()) imageName = path.Join(*tests.ContainerRegistry, repo, imageName) dockerFilePath := filepath.Join(filepath.FromSlash(tests.GetTestResourcesPath()), "docker") - imageBuilder := NewBuildDockerImage(imageName, dockerFilePath, containerManagerType).SetDockerFileName(dockerfileName) + imageBuilder := commonTests.NewBuildDockerImage(imageName, dockerFilePath, containerManagerType).SetDockerFileName(dockerfileName) return imageName, gofrogcmd.RunCmd(imageBuilder) } -func DeleteTestImage(t *testing.T, imageTag string, containerManagerType container.ContainerManagerType) { - imageBuilder := NewDeleteDockerImage(imageTag, containerManagerType) - assert.NoError(t, gofrogcmd.RunCmd(imageBuilder)) -} - -func DeleteTestContainer(t *testing.T, containerName string, containerManagerType container.ContainerManagerType) { - containerDelete := NewDeleteContainer(containerName, containerManagerType) - assert.NoError(t, gofrogcmd.RunCmd(containerDelete)) -} - func ContainerTestCleanup(t *testing.T, serverDetails *config.ServerDetails, artHttpDetails httputils.HttpClientDetails, imageName, buildName, repo string) { // Remove build from Artifactory DeleteBuild(serverDetails.ArtifactoryUrl, buildName, artHttpDetails) diff --git a/inttestutils/transfer.go b/inttestutils/transfer.go index 1422d5649..53338bed6 100644 --- a/inttestutils/transfer.go +++ b/inttestutils/transfer.go @@ -13,6 +13,7 @@ import ( "github.com/jfrog/jfrog-cli-core/v2/common/spec" "github.com/jfrog/jfrog-cli-core/v2/utils/config" "github.com/jfrog/jfrog-cli-core/v2/utils/coreutils" + coreTests "github.com/jfrog/jfrog-cli-core/v2/utils/tests" "github.com/jfrog/jfrog-cli/utils/tests" clientutils "github.com/jfrog/jfrog-client-go/utils" "github.com/jfrog/jfrog-client-go/utils/io/httputils" @@ -27,7 +28,7 @@ const ( // Create test repositories in the target Artifactory // targetArtifactoryCli - Target Artifactory CLI -func CreateTargetRepos(targetArtifactoryCli *tests.JfrogCli) { +func CreateTargetRepos(targetArtifactoryCli *coreTests.JfrogCli) { log.Info("Creating repositories in target Artifactory...") for _, template := range tests.CreatedNonVirtualRepositories { repoTemplate := filepath.Join("testdata", template) @@ -39,7 +40,7 @@ func CreateTargetRepos(targetArtifactoryCli *tests.JfrogCli) { // Delete test repositories in the target Artifactory // targetArtifactoryCli - Target Artifactory CLI -func DeleteTargetRepos(targetArtifactoryCli *tests.JfrogCli) { +func DeleteTargetRepos(targetArtifactoryCli *coreTests.JfrogCli) { for repoKey := range tests.CreatedNonVirtualRepositories { coreutils.ExitOnErr(targetArtifactoryCli.Exec("repo-delete", *repoKey)) } @@ -47,7 +48,7 @@ func DeleteTargetRepos(targetArtifactoryCli *tests.JfrogCli) { // Clean test repositories content in the target Artifactory // targetArtifactoryCli - Target Artifactory CLI -func CleanTargetRepos(targetArtifactoryCli *tests.JfrogCli) { +func CleanTargetRepos(targetArtifactoryCli *coreTests.JfrogCli) { for repoKey := range tests.CreatedNonVirtualRepositories { coreutils.ExitOnErr(targetArtifactoryCli.Exec("del", *repoKey)) } @@ -73,7 +74,7 @@ func AuthenticateTarget() (string, *config.ServerDetails, *httputils.HttpClientD // sourceArtifactoryCli - Source Artifactory CLI // serverDetails - Source server details // t - The testing object -func UploadTransferTestFilesAndAssert(sourceArtifactoryCli *tests.JfrogCli, serverDetails *config.ServerDetails, t *testing.T) (string, string) { +func UploadTransferTestFilesAndAssert(sourceArtifactoryCli *coreTests.JfrogCli, serverDetails *config.ServerDetails, t *testing.T) (string, string) { // Upload files assert.NoError(t, sourceArtifactoryCli.Exec("upload", "testdata/a/*", tests.RtRepo1)) assert.NoError(t, sourceArtifactoryCli.Exec("upload", "testdata/a/b/*", tests.RtRepo2)) @@ -130,7 +131,7 @@ func WaitForCreationInArtifactory(pattern string, serverDetails *config.ServerDe // wg - Wait group to update when done // filesTransferFinished - Changes to true when the file transfer process finished // t - The testing object -func AsyncExecTransferFiles(artifactoryCli *tests.JfrogCli, wg *sync.WaitGroup, filesTransferFinished *bool, t *testing.T) { +func AsyncExecTransferFiles(artifactoryCli *coreTests.JfrogCli, wg *sync.WaitGroup, filesTransferFinished *bool, t *testing.T) { wg.Add(1) go func() { defer func() { diff --git a/lifecycle/cli.go b/lifecycle/cli.go index eaf201222..e4b29edbd 100644 --- a/lifecycle/cli.go +++ b/lifecycle/cli.go @@ -2,6 +2,7 @@ package lifecycle import ( "errors" + commonCliUtils "github.com/jfrog/jfrog-cli-core/v2/common/cliutils" "github.com/jfrog/jfrog-cli-core/v2/common/commands" coreCommon "github.com/jfrog/jfrog-cli-core/v2/docs/common" "github.com/jfrog/jfrog-cli-core/v2/lifecycle" @@ -169,7 +170,7 @@ func assertSigningKeyProvided(c *cli.Context) error { } func createLifecycleDetailsByFlags(c *cli.Context) (*coreConfig.ServerDetails, error) { - lcDetails, err := cliutils.CreateServerDetailsWithConfigOffer(c, true, cliutils.Platform) + lcDetails, err := cliutils.CreateServerDetailsWithConfigOffer(c, true, commonCliUtils.Platform) if err != nil { return nil, err } diff --git a/lifecycle_test.go b/lifecycle_test.go index 719834409..1519f0197 100644 --- a/lifecycle_test.go +++ b/lifecycle_test.go @@ -6,6 +6,7 @@ import ( "github.com/jfrog/jfrog-cli-core/v2/artifactory/utils" configUtils "github.com/jfrog/jfrog-cli-core/v2/utils/config" "github.com/jfrog/jfrog-cli-core/v2/utils/coreutils" + coreTests "github.com/jfrog/jfrog-cli-core/v2/utils/tests" "github.com/jfrog/jfrog-cli/inttestutils" lifecycleCli "github.com/jfrog/jfrog-cli/lifecycle" "github.com/jfrog/jfrog-cli/utils/cliutils" @@ -37,7 +38,7 @@ const ( var ( lcDetails *configUtils.ServerDetails - lcCli *tests.JfrogCli + lcCli *coreTests.JfrogCli ) func TestLifecycle(t *testing.T) { @@ -254,7 +255,7 @@ func initLifecycleCli() { if lcCli != nil { return } - lcCli = tests.NewJfrogCli(execMain, "jfrog", authenticateLifecycle()) + lcCli = coreTests.NewJfrogCli(execMain, "jfrog", authenticateLifecycle()) } func CleanLifecycleTests() { diff --git a/main.go b/main.go index 8cf9155c0..78aa9d6ce 100644 --- a/main.go +++ b/main.go @@ -2,12 +2,19 @@ package main import ( "fmt" + "os" + "runtime" + "sort" + "strings" + "github.com/agnivade/levenshtein" corecommon "github.com/jfrog/jfrog-cli-core/v2/docs/common" setupcore "github.com/jfrog/jfrog-cli-core/v2/general/envsetup" + "github.com/jfrog/jfrog-cli-core/v2/plugins/components" coreconfig "github.com/jfrog/jfrog-cli-core/v2/utils/config" "github.com/jfrog/jfrog-cli-core/v2/utils/coreutils" "github.com/jfrog/jfrog-cli-core/v2/utils/log" + securityCLI "github.com/jfrog/jfrog-cli-security/cli" "github.com/jfrog/jfrog-cli/artifactory" "github.com/jfrog/jfrog-cli/buildtools" "github.com/jfrog/jfrog-cli/completion" @@ -27,18 +34,12 @@ import ( "github.com/jfrog/jfrog-cli/pipelines" "github.com/jfrog/jfrog-cli/plugins" "github.com/jfrog/jfrog-cli/plugins/utils" - "github.com/jfrog/jfrog-cli/scan" "github.com/jfrog/jfrog-cli/utils/cliutils" - "github.com/jfrog/jfrog-cli/xray" clientutils "github.com/jfrog/jfrog-client-go/utils" "github.com/jfrog/jfrog-client-go/utils/io/fileutils" clientlog "github.com/jfrog/jfrog-client-go/utils/log" "github.com/urfave/cli" "golang.org/x/exp/slices" - "os" - "runtime" - "sort" - "strings" ) const commandHelpTemplate string = `{{.HelpName}}{{if .UsageText}} @@ -70,6 +71,8 @@ OPTIONS: {{end}} ` +const jfrogAppName = "jf" + func main() { log.SetDefaultLogger() err := execMain() @@ -84,13 +87,19 @@ func execMain() error { clientutils.SetUserAgent(coreutils.GetCliUserAgent()) app := cli.NewApp() - app.Name = "jf" + app.Name = jfrogAppName app.Usage = "See https://github.com/jfrog/jfrog-cli for usage instructions." app.Version = cliutils.GetVersion() args := os.Args cliutils.SetCliExecutableName(args[0]) app.EnableBashCompletion = true - app.Commands = getCommands() + commands, err := getCommands() + if err != nil { + clientlog.Error(err) + os.Exit(1) + } + sort.Slice(commands, func(i, j int) bool { return commands[i].Name < commands[j].Name }) + app.Commands = commands cli.CommandHelpTemplate = commandHelpTemplate cli.AppHelpTemplate = getAppHelpTemplate() cli.SubcommandHelpTemplate = subcommandHelpTemplate @@ -127,7 +136,7 @@ func execMain() error { } return nil } - err := app.Run(args) + err = app.Run(args) return err } @@ -168,7 +177,7 @@ func searchSimilarCmds(cmds []cli.Command, toCompare string) (bestSimilarity []s const otherCategory = "Other" -func getCommands() []cli.Command { +func getCommands() ([]cli.Command, error) { cliNameSpaces := []cli.Command{ { Name: cliutils.CmdArtifactory, @@ -182,12 +191,6 @@ func getCommands() []cli.Command { Subcommands: missioncontrol.GetCommands(), Category: otherCategory, }, - { - Name: cliutils.CmdXray, - Usage: "Xray commands.", - Subcommands: xray.GetCommands(), - Category: otherCategory, - }, { Name: cliutils.CmdDistribution, Usage: "Distribution commands.", @@ -289,11 +292,31 @@ func getCommands() []cli.Command { Action: token.AccessTokenCreateCmd, }, } - allCommands := append(slices.Clone(cliNameSpaces), utils.GetPlugins()...) - allCommands = append(allCommands, scan.GetCommands()...) + + securityCmds, err := ConvertEmbeddedPlugin(securityCLI.GetJfrogCliSecurityApp()) + if err != nil { + return nil, err + } + allCommands := append(slices.Clone(cliNameSpaces), securityCmds...) + allCommands = append(allCommands, utils.GetPlugins()...) allCommands = append(allCommands, buildtools.GetCommands()...) allCommands = append(allCommands, lifecycle.GetCommands()...) - return append(allCommands, buildtools.GetBuildToolsHelpCommands()...) + return append(allCommands, buildtools.GetBuildToolsHelpCommands()...), nil +} + +// Embedded plugins are CLI plugins that are embedded in the JFrog CLI and not require any installation. +// This function converts an embedded plugin to a cli.Command slice to be registered as commands of the cli. +func ConvertEmbeddedPlugin(jfrogPlugin components.App) (converted []cli.Command, err error) { + for i := range jfrogPlugin.Subcommands { + // commands name-space without category are considered as 'other' category + if jfrogPlugin.Subcommands[i].Category == "" { + jfrogPlugin.Subcommands[i].Category = otherCategory + } + } + if converted, err = components.ConvertAppCommands(jfrogPlugin); err != nil { + err = fmt.Errorf("failed adding '%s' embedded plugin commands. Last error: %s", jfrogPlugin.Name, err.Error()) + } + return } func getAppHelpTemplate() string { diff --git a/main_test.go b/main_test.go index ca2f51214..f0f8859a8 100644 --- a/main_test.go +++ b/main_test.go @@ -68,9 +68,6 @@ func setupIntegrationTests() { if *tests.TestPlugins { InitPluginsTests() } - if *tests.TestXray { - InitXrayTests() - } if *tests.TestAccess { InitAccessTests() } @@ -89,9 +86,6 @@ func tearDownIntegrationTests() { if *tests.TestNpm || *tests.TestGradle || *tests.TestMaven || *tests.TestGo || *tests.TestNuget || *tests.TestPip || *tests.TestPipenv || *tests.TestDocker || *tests.TestPodman || *tests.TestDockerScan { CleanBuildToolsTests() } - if *tests.TestXray { - CleanXrayTests() - } if *tests.TestDistribution { CleanDistributionTests() } @@ -133,11 +127,11 @@ func createJfrogHomeConfig(t *testing.T, encryptPassword bool) { // Delete the default server if exist config, err := commands.GetConfig("default", false) if err == nil && config.ServerId != "" { - err = tests.NewJfrogCli(execMain, "jfrog config", "").Exec("rm", "default", "--quiet") + err = coreTests.NewJfrogCli(execMain, "jfrog config", "").Exec("rm", "default", "--quiet") assert.NoError(t, err) } *tests.JfrogUrl = utils.AddTrailingSlashIfNeeded(*tests.JfrogUrl) - err = tests.NewJfrogCli(execMain, "jfrog config", credentials).Exec("add", "default", "--interactive=false", "--url="+*tests.JfrogUrl, "--enc-password="+strconv.FormatBool(encryptPassword)) + err = coreTests.NewJfrogCli(execMain, "jfrog config", credentials).Exec("add", "default", "--interactive=false", "--url="+*tests.JfrogUrl, "--enc-password="+strconv.FormatBool(encryptPassword)) assert.NoError(t, err) } @@ -185,11 +179,11 @@ func initArtifactoryCli() { return } *tests.JfrogUrl = utils.AddTrailingSlashIfNeeded(*tests.JfrogUrl) - artifactoryCli = tests.NewJfrogCli(execMain, "jfrog rt", authenticate(false)) + artifactoryCli = coreTests.NewJfrogCli(execMain, "jfrog rt", authenticate(false)) if (*tests.TestArtifactory && !*tests.TestArtifactoryProxy) || *tests.TestPlugins || *tests.TestArtifactoryProject || *tests.TestAccess || *tests.TestTransfer || *tests.TestLifecycle { configCli = createConfigJfrogCLI(authenticate(true)) - platformCli = tests.NewJfrogCli(execMain, "jfrog", authenticate(false)) + platformCli = coreTests.NewJfrogCli(execMain, "jfrog", authenticate(false)) } } @@ -239,7 +233,7 @@ func runJfrogCli(t *testing.T, args ...string) { } func runJfrogCliWithoutAssertion(args ...string) error { - jfrogCli := tests.NewJfrogCli(execMain, "jfrog", "") + jfrogCli := coreTests.NewJfrogCli(execMain, "jfrog", "") return jfrogCli.Exec(args...) } @@ -261,7 +255,12 @@ func createConfigFile(inDir, configFilePath string, t *testing.T) { // Validate that all CLI commands' aliases are unique, and that two commands don't use the same alias. func validateCmdAliasesUniqueness() { - for _, command := range getCommands() { + cmds, err := getCommands() + if err != nil { + clientlog.Error(err) + os.Exit(1) + } + for _, command := range cmds { subcommands := command.Subcommands aliasesMap := map[string]bool{} for _, subcommand := range subcommands { @@ -295,14 +294,16 @@ func testConditionalUpload(t *testing.T, execFunc func() error, searchSpec strin } func TestSearchSimilarCmds(t *testing.T) { + cmds, err := getCommands() + assert.NoError(t, err) testData := []struct { badCmdSyntax string searchIn []cli.Command expectedRes []string }{ - {"rtt", getCommands(), []string{"rt"}}, - {"bp", getCommands(), []string{"rt bp"}}, - {"asdfewrwqfaxf", getCommands(), []string{}}, + {"rtt", cmds, []string{"rt"}}, + {"bp", cmds, []string{"rt bp"}}, + {"asdfewrwqfaxf", cmds, []string{}}, {"bpp", artifactory.GetCommands(), []string{"bpr", "bp", "pp"}}, {"uplid", artifactory.GetCommands(), []string{"upload"}}, {"downlo", artifactory.GetCommands(), []string{"download"}}, diff --git a/maven_test.go b/maven_test.go index 7d3958ca1..e993ac8e7 100644 --- a/maven_test.go +++ b/maven_test.go @@ -1,7 +1,12 @@ package main import ( + "errors" "fmt" + commonCliUtils "github.com/jfrog/jfrog-cli-core/v2/common/cliutils" + outputFormat "github.com/jfrog/jfrog-cli-core/v2/common/format" + "github.com/jfrog/jfrog-cli-core/v2/common/project" + "github.com/jfrog/jfrog-cli/utils/cliutils" "os" "path/filepath" "strings" @@ -83,7 +88,9 @@ func TestMavenBuildWithConditionalUpload(t *testing.T) { buildNumber := "505" execFunc := func() error { - return runMaven(t, createSimpleMavenProject, tests.MavenConfig, "install", "--scan", "--build-name="+buildName, "--build-number="+buildNumber) + oldHomeDir := changeWD(t, beforeRunMaven(t, createSimpleMavenProject, tests.MavenConfig)) + defer clientTestUtils.ChangeDirAndAssert(t, oldHomeDir) + return runMvnConditionalUploadTest(buildName, buildNumber) } searchSpec, err := tests.CreateSpec(tests.SearchAllMaven) assert.NoError(t, err) @@ -91,6 +98,30 @@ func TestMavenBuildWithConditionalUpload(t *testing.T) { cleanMavenTest(t) } +func runMvnConditionalUploadTest(buildName, buildNumber string) (err error) { + configFilePath, exists, err := project.GetProjectConfFilePath(project.Maven) + if err != nil { + return + } + if !exists { + return errors.New("no config file was found!") + } + buildConfig := buildUtils.NewBuildConfiguration(buildName, buildNumber, "", "") + if err = buildConfig.ValidateBuildAndModuleParams(); err != nil { + return + } + printDeploymentView := log.IsStdErrTerminal() + mvnCmd := mvn.NewMvnCommand(). + SetGoals([]string{"clean", "install", "-B", localRepoSystemProperty + localRepoDir}). + SetConfiguration(buildConfig). + SetXrayScan(true).SetScanOutputFormat(outputFormat.Table). + SetConfigPath(configFilePath).SetDetailedSummary(printDeploymentView).SetThreads(commonCliUtils.Threads) + err = commands.Exec(mvnCmd) + result := mvnCmd.Result() + defer cliutils.CleanupResult(result, &err) + return cliutils.PrintCommandSummary(mvnCmd.Result(), false, printDeploymentView, false, err) +} + func TestMavenBuildWithServerIDAndDetailedSummary(t *testing.T) { initMavenTest(t, false) pomDir := createSimpleMavenProject(t) @@ -148,7 +179,7 @@ func TestInsecureTlsMavenBuild(t *testing.T) { oldHomeDir := changeWD(t, pomDir) defer clientTestUtils.ChangeDirAndAssert(t, oldHomeDir) - jfrogCli := tests.NewJfrogCli(execMain, "jfrog", "") + jfrogCli := coreTests.NewJfrogCli(execMain, "jfrog", "") // First, try to run without the insecure-tls flag, failure is expected. err = jfrogCli.Exec("mvn", "clean", "install", "-B", repoLocalSystemProp) @@ -311,12 +342,7 @@ func deleteDeployedArtifacts(t *testing.T) { } func runMaven(t *testing.T, createProjectFunction func(*testing.T) string, configFileName string, args ...string) error { - projDir := createProjectFunction(t) - configFilePath := filepath.Join(filepath.FromSlash(tests.GetTestResourcesPath()), "buildspecs", configFileName) - destPath := filepath.Join(projDir, ".jfrog", "projects") - createConfigFile(destPath, configFilePath, t) - assert.NoError(t, os.Rename(filepath.Join(destPath, configFileName), filepath.Join(destPath, "maven.yaml"))) - oldHomeDir := changeWD(t, projDir) + oldHomeDir := changeWD(t, beforeRunMaven(t, createProjectFunction, configFileName)) defer clientTestUtils.ChangeDirAndAssert(t, oldHomeDir) repoLocalSystemProp := localRepoSystemProperty + localRepoDir @@ -324,3 +350,12 @@ func runMaven(t *testing.T, createProjectFunction func(*testing.T) string, confi args = append(args, "-B", repoLocalSystemProp) return runJfrogCliWithoutAssertion(args...) } + +func beforeRunMaven(t *testing.T, createProjectFunction func(*testing.T) string, configFileName string) string { + projDir := createProjectFunction(t) + configFilePath := filepath.Join(filepath.FromSlash(tests.GetTestResourcesPath()), "buildspecs", configFileName) + destPath := filepath.Join(projDir, ".jfrog", "projects") + createConfigFile(destPath, configFilePath, t) + assert.NoError(t, os.Rename(filepath.Join(destPath, configFileName), filepath.Join(destPath, "maven.yaml"))) + return projDir +} diff --git a/missioncontrol/cli.go b/missioncontrol/cli.go index 4e7a6341a..d086d1832 100644 --- a/missioncontrol/cli.go +++ b/missioncontrol/cli.go @@ -3,6 +3,7 @@ package missioncontrol import ( "strconv" + commonCliUtils "github.com/jfrog/jfrog-cli-core/v2/common/cliutils" coreCommonCommands "github.com/jfrog/jfrog-cli-core/v2/common/commands" corecommon "github.com/jfrog/jfrog-cli-core/v2/docs/common" "github.com/jfrog/jfrog-cli-core/v2/missioncontrol/commands" @@ -140,7 +141,7 @@ func licenseRelease(c *cli.Context) error { } func offerConfig(c *cli.Context) (*config.ServerDetails, error) { - confirmed, err := cliutils.ShouldOfferConfig() + confirmed, err := commonCliUtils.ShouldOfferConfig() if !confirmed || err != nil { return nil, err } diff --git a/npm_test.go b/npm_test.go index 55e6bc843..3c0cf1474 100644 --- a/npm_test.go +++ b/npm_test.go @@ -15,6 +15,8 @@ import ( biutils "github.com/jfrog/build-info-go/utils" "github.com/jfrog/gofrog/version" coretests "github.com/jfrog/jfrog-cli-core/v2/utils/tests" + "github.com/jfrog/jfrog-cli/utils/cliutils" + "github.com/jfrog/jfrog-client-go/utils/errorutils" "github.com/jfrog/jfrog-client-go/utils/log" clientTestUtils "github.com/jfrog/jfrog-client-go/utils/tests" @@ -204,11 +206,34 @@ func TestNpmConditionalUpload(t *testing.T) { buildNumber := "505" runJfrogCli(t, []string{"npm", "install", "--build-name=" + buildName, "--build-number=" + buildNumber}...) execFunc := func() error { - return runJfrogCliWithoutAssertion([]string{"npm", "publish", "--scan", "--build-name=" + buildName, "--build-number=" + buildNumber}...) + return runNpmConditionalUploadTest(buildName, buildNumber) } testConditionalUpload(t, execFunc, searchSpec, tests.GetNpmDeployedArtifacts(isNpm7(npmVersion))...) } +func runNpmConditionalUploadTest(buildName, buildNumber string) (err error) { + configFilePath, exists, err := project.GetProjectConfFilePath(project.Npm) + if err != nil { + return + } else if !exists { + return errorutils.CheckErrorf("no config file was found!") + } + npmCmd := npm.NewNpmPublishCommand() + npmCmd.SetConfigFilePath(configFilePath).SetArgs([]string{"--scan", "--build-name=" + buildName, "--build-number=" + buildNumber}) + if err = npmCmd.Init(); err != nil { + return err + } + printDeploymentView, detailedSummary := log.IsStdErrTerminal(), npmCmd.IsDetailedSummary() + if !detailedSummary { + npmCmd.SetDetailedSummary(printDeploymentView) + } + err = commands.Exec(npmCmd) + result := npmCmd.Result() + defer cliutils.CleanupResult(result, &err) + err = cliutils.PrintCommandSummary(npmCmd.Result(), detailedSummary, printDeploymentView, false, err) + return +} + func validateNpmrcFileInfo(t *testing.T, npmTest npmTestParams, npmrcFileInfo, postTestNpmrcFileInfo os.FileInfo, err, postTestFileInfoErr error) { if postTestFileInfoErr != nil && !os.IsNotExist(postTestFileInfoErr) { assert.Fail(t, postTestFileInfoErr.Error()) @@ -353,7 +378,7 @@ func prepareArtifactoryForNpmBuild(t *testing.T, workingDirectory string) { caches := ioutils.DoubleWinPathSeparator(filepath.Join(workingDirectory, "caches")) // Run install with -cache argument to download the artifacts from Artifactory // This done to be sure the artifacts exists in Artifactory - jfrogCli := tests.NewJfrogCli(execMain, "jfrog", "") + jfrogCli := coretests.NewJfrogCli(execMain, "jfrog", "") assert.NoError(t, jfrogCli.Exec("npm", "install", "-cache="+caches)) clientTestUtils.RemoveAllAndAssert(t, filepath.Join(workingDirectory, "node_modules")) @@ -508,7 +533,7 @@ func TestYarn(t *testing.T) { assert.NoError(t, yarn.ConfigSet("unsafeHttpWhitelist", origWhitelist, yarnExecPath, true)) }() - jfrogCli := tests.NewJfrogCli(execMain, "jfrog", "") + jfrogCli := coretests.NewJfrogCli(execMain, "jfrog", "") assert.NoError(t, jfrogCli.Exec("yarn", "--build-name="+tests.YarnBuildName, "--build-number=1", "--module="+ModuleNameJFrogTest)) validateNpmLocalBuildInfo(t, tests.YarnBuildName, "1", ModuleNameJFrogTest) @@ -563,7 +588,7 @@ func TestGenericNpm(t *testing.T) { chdirCallBack := clientTestUtils.ChangeDirWithCallback(t, wd, npmPath) defer chdirCallBack() - jfrogCli := tests.NewJfrogCli(execMain, "jfrog", "") + jfrogCli := coretests.NewJfrogCli(execMain, "jfrog", "") args := []string{"npm", "version"} output := jfrogCli.WithoutCredentials().RunCliCmdWithOutput(t, args...) assert.Contains(t, output, "'jfrog-cli-tests': 'v1.0.0'") @@ -573,6 +598,6 @@ func TestGenericNpm(t *testing.T) { } func runGenericNpm(t *testing.T, args ...string) { - jfCli := tests.NewJfrogCli(execMain, "jf", "") + jfCli := coretests.NewJfrogCli(execMain, "jf", "") assert.NoError(t, jfCli.WithoutCredentials().Exec(args...)) } diff --git a/nuget_test.go b/nuget_test.go index c8bf733d2..e8b42d2bb 100644 --- a/nuget_test.go +++ b/nuget_test.go @@ -184,7 +184,7 @@ func assertNugetMultiPackagesConfigDependencies(t *testing.T, module buildInfo.M } func runNuGet(t *testing.T, args ...string) error { - artifactoryNuGetCli := tests.NewJfrogCli(execMain, "jfrog", "") + artifactoryNuGetCli := coreTests.NewJfrogCli(execMain, "jfrog", "") err := artifactoryNuGetCli.Exec(args...) assert.NoError(t, err) return err diff --git a/pip_test.go b/pip_test.go index 70772e6ec..34267df70 100644 --- a/pip_test.go +++ b/pip_test.go @@ -4,7 +4,7 @@ import ( biutils "github.com/jfrog/build-info-go/utils" "github.com/jfrog/jfrog-cli-core/v2/utils/coreutils" coretests "github.com/jfrog/jfrog-cli-core/v2/utils/tests" - "github.com/jfrog/jfrog-cli-core/v2/xray/commands/audit/sca/python" + "github.com/jfrog/jfrog-cli-security/commands/audit/sca/python" clientTestUtils "github.com/jfrog/jfrog-client-go/utils/tests" "os" "path/filepath" @@ -112,7 +112,7 @@ func testPipCmd(t *testing.T, projectPath, buildNumber, module string, expectedD args = append(args, "--build-number="+buildNumber) - jfrogCli := tests.NewJfrogCli(execMain, "jfrog", "") + jfrogCli := coretests.NewJfrogCli(execMain, "jfrog", "") err = jfrogCli.Exec(args...) if err != nil { assert.Fail(t, "Failed executing pip install command", err.Error()) diff --git a/pipenv_test.go b/pipenv_test.go index f5b7b9bc6..807690135 100644 --- a/pipenv_test.go +++ b/pipenv_test.go @@ -9,6 +9,7 @@ import ( buildinfo "github.com/jfrog/build-info-go/entities" "github.com/jfrog/jfrog-cli-core/v2/utils/coreutils" + coreTests "github.com/jfrog/jfrog-cli-core/v2/utils/tests" "github.com/jfrog/jfrog-cli/inttestutils" "github.com/jfrog/jfrog-cli/utils/tests" "github.com/jfrog/jfrog-client-go/utils/io/fileutils" @@ -66,7 +67,7 @@ func testPipenvCmd(t *testing.T, projectPath, buildNumber, module string, args [ args = append(args, "--build-number="+buildNumber) - jfrogCli := tests.NewJfrogCli(execMain, "jfrog", "") + jfrogCli := coreTests.NewJfrogCli(execMain, "jfrog", "") err = jfrogCli.WithoutCredentials().Exec(args...) if err != nil { assert.Fail(t, "Failed executing pipenv-install command", err.Error()) diff --git a/plugins/commands/install.go b/plugins/commands/install.go index e1bd7e70d..913d043a4 100644 --- a/plugins/commands/install.go +++ b/plugins/commands/install.go @@ -14,9 +14,9 @@ import ( commandsUtils "github.com/jfrog/jfrog-cli/plugins/commands/utils" clientUtils "github.com/jfrog/jfrog-client-go/utils" + "github.com/jfrog/jfrog-cli-core/v2/common/progressbar" "github.com/jfrog/jfrog-cli-core/v2/utils/coreutils" "github.com/jfrog/jfrog-cli/utils/cliutils" - "github.com/jfrog/jfrog-cli/utils/progressbar" "github.com/jfrog/jfrog-client-go/http/httpclient" "github.com/jfrog/jfrog-client-go/utils/errorutils" "github.com/jfrog/jfrog-client-go/utils/io/fileutils" diff --git a/plugins/commands/publish.go b/plugins/commands/publish.go index 8d740b62c..9bb76dc78 100644 --- a/plugins/commands/publish.go +++ b/plugins/commands/publish.go @@ -6,6 +6,7 @@ import ( "github.com/jfrog/jfrog-cli-core/v2/artifactory/commands/generic" commandsutils "github.com/jfrog/jfrog-cli-core/v2/artifactory/commands/utils" rtutils "github.com/jfrog/jfrog-cli-core/v2/artifactory/utils" + commonCliUtils "github.com/jfrog/jfrog-cli-core/v2/common/cliutils" "github.com/jfrog/jfrog-cli-core/v2/common/spec" "github.com/jfrog/jfrog-cli-core/v2/utils/config" "github.com/jfrog/jfrog-cli-core/v2/utils/coreutils" @@ -303,6 +304,6 @@ func createResourcesUploadSpec(source, target string) *spec.SpecFiles { func createUploadConfiguration() *rtutils.UploadConfiguration { uploadConfiguration := new(rtutils.UploadConfiguration) - uploadConfiguration.Threads = cliutils.Threads + uploadConfiguration.Threads = commonCliUtils.Threads return uploadConfiguration } diff --git a/plugins_test.go b/plugins_test.go index dcbe0e187..d0cd684c0 100644 --- a/plugins_test.go +++ b/plugins_test.go @@ -11,6 +11,7 @@ import ( clientTestUtils "github.com/jfrog/jfrog-client-go/utils/tests" "github.com/buger/jsonparser" + commonTests "github.com/jfrog/jfrog-cli-core/v2/common/tests" "github.com/jfrog/jfrog-cli-core/v2/plugins" "github.com/jfrog/jfrog-cli-core/v2/utils/coreutils" pluginsutils "github.com/jfrog/jfrog-cli-core/v2/utils/plugins" @@ -47,7 +48,7 @@ func TestPluginInstallUninstallOfficialRegistry(t *testing.T) { clientTestUtils.SetEnvAndAssert(t, utils.PluginsRepoEnv, oldRepo) }() clientTestUtils.SetEnvAndAssert(t, utils.PluginsRepoEnv, "") - jfrogCli := tests.NewJfrogCli(execMain, "jfrog", "") + jfrogCli := coreTests.NewJfrogCli(execMain, "jfrog", "") // Try installing a plugin with specific version. err = installAndAssertPlugin(t, jfrogCli, officialPluginVersion) @@ -76,7 +77,7 @@ func TestPluginInstallUninstallOfficialRegistry(t *testing.T) { func TestPluginInstallWithProgressBar(t *testing.T) { initPluginsTest(t) - callback := tests.MockProgressInitialization() + callback := commonTests.MockProgressInitialization() defer callback() // Create temp jfrog home @@ -97,7 +98,7 @@ func TestPluginInstallWithProgressBar(t *testing.T) { clientTestUtils.SetEnvAndAssert(t, utils.PluginsRepoEnv, oldRepo) }() clientTestUtils.SetEnvAndAssert(t, utils.PluginsRepoEnv, "") - jfrogCli := tests.NewJfrogCli(execMain, "jfrog", "") + jfrogCli := coreTests.NewJfrogCli(execMain, "jfrog", "") // Try installing a plugin with specific version. err = installAndAssertPlugin(t, jfrogCli, officialPluginVersion) @@ -112,7 +113,7 @@ func TestPluginInstallWithProgressBar(t *testing.T) { } } -func installAndAssertPlugin(t *testing.T, jfrogCli *tests.JfrogCli, pluginVersion string) error { +func installAndAssertPlugin(t *testing.T, jfrogCli *coreTests.JfrogCli, pluginVersion string) error { // If version required, concat to plugin name identifier := officialPluginForTest if pluginVersion != "" { @@ -138,7 +139,7 @@ func installAndAssertPlugin(t *testing.T, jfrogCli *tests.JfrogCli, pluginVersio return verifyPluginVersion(t, jfrogCli, pluginVersion) } -func verifyPluginSignature(t *testing.T, jfrogCli *tests.JfrogCli) error { +func verifyPluginSignature(t *testing.T, jfrogCli *coreTests.JfrogCli) error { // Get signature from plugin. content, err := tests.GetCmdOutput(t, jfrogCli, officialPluginForTest, plugins.SignatureCommandName) if err != nil { @@ -163,7 +164,7 @@ func verifyPluginSignature(t *testing.T, jfrogCli *tests.JfrogCli) error { return nil } -func verifyPluginVersion(t *testing.T, jfrogCli *tests.JfrogCli, expectedVersion string) error { +func verifyPluginVersion(t *testing.T, jfrogCli *coreTests.JfrogCli, expectedVersion string) error { // Run plugin's -v command. content, err := tests.GetCmdOutput(t, jfrogCli, officialPluginForTest, "-v") if err != nil { @@ -264,7 +265,7 @@ func TestPublishInstallCustomServer(t *testing.T) { func testPublishAndInstall(t *testing.T, resources bool) { // Publish the CLI as a plugin to the registry. - jfrogCli := tests.NewJfrogCli(execMain, "jfrog", "") + jfrogCli := coreTests.NewJfrogCli(execMain, "jfrog", "") err := jfrogCli.Exec("plugin", "p", customPluginName, cliutils.GetVersion()) if err != nil { assert.NoError(t, err) diff --git a/scan/cli.go b/scan/cli.go deleted file mode 100644 index 43301312c..000000000 --- a/scan/cli.go +++ /dev/null @@ -1,477 +0,0 @@ -package scan - -import ( - "github.com/jfrog/jfrog-cli-core/v2/xray/commands/curation" - xrutils "github.com/jfrog/jfrog-cli-core/v2/xray/utils" - curationdocs "github.com/jfrog/jfrog-cli/docs/scan/curation" - "os" - "strings" - - "github.com/jfrog/jfrog-cli/utils/progressbar" - - "github.com/jfrog/jfrog-cli-core/v2/common/commands" - outputFormat "github.com/jfrog/jfrog-cli-core/v2/common/format" - "github.com/jfrog/jfrog-cli-core/v2/common/spec" - corecommondocs "github.com/jfrog/jfrog-cli-core/v2/docs/common" - coreconfig "github.com/jfrog/jfrog-cli-core/v2/utils/config" - "github.com/jfrog/jfrog-cli-core/v2/utils/coreutils" - "github.com/jfrog/jfrog-cli-core/v2/xray/commands/audit" - "github.com/jfrog/jfrog-cli-core/v2/xray/commands/scan" - "github.com/jfrog/jfrog-cli/docs/common" - auditdocs "github.com/jfrog/jfrog-cli/docs/scan/audit" - auditgodocs "github.com/jfrog/jfrog-cli/docs/scan/auditgo" - auditgradledocs "github.com/jfrog/jfrog-cli/docs/scan/auditgradle" - "github.com/jfrog/jfrog-cli/docs/scan/auditmvn" - auditnpmdocs "github.com/jfrog/jfrog-cli/docs/scan/auditnpm" - auditpipdocs "github.com/jfrog/jfrog-cli/docs/scan/auditpip" - auditpipenvdocs "github.com/jfrog/jfrog-cli/docs/scan/auditpipenv" - buildscandocs "github.com/jfrog/jfrog-cli/docs/scan/buildscan" - scandocs "github.com/jfrog/jfrog-cli/docs/scan/scan" - "github.com/jfrog/jfrog-cli/utils/cliutils" - "github.com/urfave/cli" - - "github.com/jfrog/jfrog-client-go/utils/errorutils" -) - -const auditScanCategory = "Audit & Scan" - -func GetCommands() []cli.Command { - return cliutils.GetSortedCommands(cli.CommandsByName{ - { - Name: "curation-audit", - Category: auditScanCategory, - Flags: cliutils.GetCommandFlags(cliutils.CurationAudit), - Aliases: []string{"ca"}, - Usage: curationdocs.GetDescription(), - HelpName: corecommondocs.CreateUsage("curation-audit", curationdocs.GetDescription(), curationdocs.Usage), - ArgsUsage: common.CreateEnvVars(), - BashComplete: corecommondocs.CreateBashCompletionFunc(), - Action: CurationCmd, - }, - { - Name: "audit", - Category: auditScanCategory, - Flags: cliutils.GetCommandFlags(cliutils.Audit), - Aliases: []string{"aud"}, - Usage: auditdocs.GetDescription(), - HelpName: corecommondocs.CreateUsage("audit", auditdocs.GetDescription(), auditdocs.Usage), - ArgsUsage: common.CreateEnvVars(), - BashComplete: corecommondocs.CreateBashCompletionFunc(), - Action: AuditCmd, - }, - { - Name: "audit-mvn", - Category: auditScanCategory, - Flags: cliutils.GetCommandFlags(cliutils.AuditMvn), - Aliases: []string{"am"}, - Usage: auditmvn.GetDescription(), - HelpName: corecommondocs.CreateUsage("audit-mvn", auditmvn.GetDescription(), auditmvn.Usage), - ArgsUsage: common.CreateEnvVars(), - BashComplete: corecommondocs.CreateBashCompletionFunc(), - Action: func(c *cli.Context) error { - return AuditSpecificCmd(c, coreutils.Maven) - }, - Hidden: true, - }, - { - Name: "audit-gradle", - Category: auditScanCategory, - Flags: cliutils.GetCommandFlags(cliutils.AuditGradle), - Aliases: []string{"ag"}, - Usage: auditgradledocs.GetDescription(), - HelpName: corecommondocs.CreateUsage("audit-gradle", auditgradledocs.GetDescription(), auditgradledocs.Usage), - ArgsUsage: common.CreateEnvVars(), - BashComplete: corecommondocs.CreateBashCompletionFunc(), - Action: func(c *cli.Context) error { - return AuditSpecificCmd(c, coreutils.Gradle) - }, - Hidden: true, - }, - { - Name: "audit-npm", - Category: auditScanCategory, - Flags: cliutils.GetCommandFlags(cliutils.AuditNpm), - Aliases: []string{"an"}, - Usage: auditnpmdocs.GetDescription(), - HelpName: corecommondocs.CreateUsage("audit-npm", auditnpmdocs.GetDescription(), auditnpmdocs.Usage), - ArgsUsage: common.CreateEnvVars(), - BashComplete: corecommondocs.CreateBashCompletionFunc(), - Action: func(c *cli.Context) error { - return AuditSpecificCmd(c, coreutils.Npm) - }, - Hidden: true, - }, - { - Name: "audit-go", - Category: auditScanCategory, - Flags: cliutils.GetCommandFlags(cliutils.AuditGo), - Aliases: []string{"ago"}, - Usage: auditgodocs.GetDescription(), - HelpName: corecommondocs.CreateUsage("audit-go", auditgodocs.GetDescription(), auditgodocs.Usage), - ArgsUsage: common.CreateEnvVars(), - BashComplete: corecommondocs.CreateBashCompletionFunc(), - Action: func(c *cli.Context) error { - return AuditSpecificCmd(c, coreutils.Go) - }, - Hidden: true, - }, - { - Name: "audit-pip", - Category: auditScanCategory, - Flags: cliutils.GetCommandFlags(cliutils.AuditPip), - Aliases: []string{"ap"}, - Usage: auditpipdocs.GetDescription(), - HelpName: corecommondocs.CreateUsage("audit-pip", auditpipdocs.GetDescription(), auditpipdocs.Usage), - ArgsUsage: common.CreateEnvVars(), - BashComplete: corecommondocs.CreateBashCompletionFunc(), - Action: func(c *cli.Context) error { - return AuditSpecificCmd(c, coreutils.Pip) - }, - Hidden: true, - }, - { - Name: "audit-pipenv", - Category: auditScanCategory, - Flags: cliutils.GetCommandFlags(cliutils.AuditPipenv), - Aliases: []string{"ape"}, - Usage: auditpipenvdocs.GetDescription(), - HelpName: corecommondocs.CreateUsage("audit-pipenv", auditpipenvdocs.GetDescription(), auditpipenvdocs.Usage), - ArgsUsage: common.CreateEnvVars(), - BashComplete: corecommondocs.CreateBashCompletionFunc(), - Action: func(c *cli.Context) error { - return AuditSpecificCmd(c, coreutils.Pipenv) - }, - Hidden: true, - }, - { - Name: "scan", - Category: auditScanCategory, - Flags: cliutils.GetCommandFlags(cliutils.XrScan), - Aliases: []string{"s"}, - Usage: scandocs.GetDescription(), - HelpName: corecommondocs.CreateUsage("scan", scandocs.GetDescription(), scandocs.Usage), - UsageText: scandocs.GetArguments(), - ArgsUsage: common.CreateEnvVars(), - BashComplete: corecommondocs.CreateBashCompletionFunc(), - Action: ScanCmd, - }, - { - Name: "build-scan", - Category: auditScanCategory, - Flags: cliutils.GetCommandFlags(cliutils.BuildScan), - Aliases: []string{"bs"}, - Usage: buildscandocs.GetDescription(), - UsageText: buildscandocs.GetArguments(), - HelpName: corecommondocs.CreateUsage("build-scan", buildscandocs.GetDescription(), buildscandocs.Usage), - ArgsUsage: common.CreateEnvVars(), - BashComplete: corecommondocs.CreateBashCompletionFunc(), - Action: BuildScan, - }, - }) -} - -func AuditCmd(c *cli.Context) error { - auditCmd, err := createAuditCmd(c) - if err != nil { - return err - } - - // Check if user used specific technologies flags - allTechnologies := coreutils.GetAllTechnologiesList() - technologies := []string{} - for _, tech := range allTechnologies { - var techExists bool - if tech == coreutils.Maven { - // On Maven we use '--mvn' flag - techExists = c.Bool("mvn") - } else { - techExists = c.Bool(tech.String()) - } - if techExists { - technologies = append(technologies, tech.String()) - } - } - auditCmd.SetTechnologies(technologies) - return progressbar.ExecWithProgress(auditCmd) -} - -func AuditSpecificCmd(c *cli.Context, technology coreutils.Technology) error { - cliutils.LogNonGenericAuditCommandDeprecation(c.Command.Name) - auditCmd, err := createAuditCmd(c) - if err != nil { - return err - } - technologies := []string{string(technology)} - auditCmd.SetTechnologies(technologies) - return progressbar.ExecWithProgress(auditCmd) -} - -func CurationCmd(c *cli.Context) error { - threads, err := curation.DetectNumOfThreads(c.Int("threads")) - if err != nil { - return err - } - curationAuditCommand := curation.NewCurationAuditCommand(). - SetWorkingDirs(splitByCommaAndTrim(c.String("working-dirs"))). - SetParallelRequests(threads) - - serverDetails, err := cliutils.CreateServerDetailsWithConfigOffer(c, true, "rt") - if err != nil { - return err - } - format, err := curation.GetCurationOutputFormat(c.String("format")) - if err != nil { - return err - } - curationAuditCommand.SetServerDetails(serverDetails). - SetExcludeTestDependencies(c.Bool(cliutils.ExcludeTestDeps)). - SetOutputFormat(format). - SetUseWrapper(c.BoolT(cliutils.UseWrapper)). - SetInsecureTls(c.Bool(cliutils.InsecureTls)). - SetNpmScope(c.String(cliutils.DepType)). - SetPipRequirementsFile(c.String(cliutils.RequirementsFile)) - return progressbar.ExecWithProgress(curationAuditCommand) -} - -func createAuditCmd(c *cli.Context) (*audit.AuditCommand, error) { - auditCmd := audit.NewGenericAuditCommand() - serverDetails, err := createServerDetailsWithConfigOffer(c) - if err != nil { - return nil, err - } - err = validateXrayContext(c, serverDetails) - if err != nil { - return nil, err - } - format, err := outputFormat.GetOutputFormat(c.String("format")) - if err != nil { - return nil, err - } - minSeverity, err := xrutils.GetSeveritiesFormat(c.String(cliutils.MinSeverity)) - if err != nil { - return nil, err - } - auditCmd.SetTargetRepoPath(addTrailingSlashToRepoPathIfNeeded(c)). - SetProject(c.String("project")). - SetIncludeVulnerabilities(shouldIncludeVulnerabilities(c)). - SetIncludeLicenses(c.Bool("licenses")). - SetFail(c.BoolT("fail")). - SetPrintExtendedTable(c.Bool(cliutils.ExtendedTable)). - SetMinSeverityFilter(minSeverity). - SetFixableOnly(c.Bool(cliutils.FixableOnly)). - SetThirdPartyApplicabilityScan(c.Bool(cliutils.ThirdPartyContextualAnalysis)). - SetExclusions(cliutils.GetStringsArrFlagValue(c, "exclusions")) - - if c.String("watches") != "" { - auditCmd.SetWatches(splitByCommaAndTrim(c.String("watches"))) - } - - if c.String("working-dirs") != "" { - auditCmd.SetWorkingDirs(splitByCommaAndTrim(c.String("working-dirs"))) - } - auditCmd.SetServerDetails(serverDetails). - SetExcludeTestDependencies(c.Bool(cliutils.ExcludeTestDeps)). - SetOutputFormat(format). - SetUseWrapper(c.BoolT(cliutils.UseWrapper)). - SetInsecureTls(c.Bool(cliutils.InsecureTls)). - SetNpmScope(c.String(cliutils.DepType)). - SetPipRequirementsFile(c.String(cliutils.RequirementsFile)) - return auditCmd, err -} - -func ScanCmd(c *cli.Context) error { - if c.NArg() == 0 && !c.IsSet("spec") { - return cliutils.PrintHelpAndReturnError("providing either a argument or the 'spec' option is mandatory", c) - } - serverDetails, err := createServerDetailsWithConfigOffer(c) - if err != nil { - return err - } - err = validateXrayContext(c, serverDetails) - if err != nil { - return err - } - var specFile *spec.SpecFiles - if c.IsSet("spec") { - specFile, err = cliutils.GetFileSystemSpec(c) - if err != nil { - return err - } - } else { - specFile = createDefaultScanSpec(c, addTrailingSlashToRepoPathIfNeeded(c)) - } - err = spec.ValidateSpec(specFile.Files, false, false) - if err != nil { - return err - } - threads, err := cliutils.GetThreadsCount(c) - if err != nil { - return err - } - format, err := outputFormat.GetOutputFormat(c.String("format")) - if err != nil { - return err - } - cliutils.FixWinPathsForFileSystemSourcedCmds(specFile, c) - minSeverity, err := xrutils.GetSeveritiesFormat(c.String(cliutils.MinSeverity)) - if err != nil { - return err - } - scanCmd := scan.NewScanCommand(). - SetServerDetails(serverDetails). - SetThreads(threads). - SetSpec(specFile). - SetOutputFormat(format). - SetProject(c.String("project")). - SetIncludeVulnerabilities(shouldIncludeVulnerabilities(c)). - SetIncludeLicenses(c.Bool("licenses")). - SetFail(c.BoolT("fail")). - SetPrintExtendedTable(c.Bool(cliutils.ExtendedTable)). - SetBypassArchiveLimits(c.Bool(cliutils.BypassArchiveLimits)). - SetFixableOnly(c.Bool(cliutils.FixableOnly)). - SetMinSeverityFilter(minSeverity) - if c.String("watches") != "" { - scanCmd.SetWatches(splitByCommaAndTrim(c.String("watches"))) - } - return commands.Exec(scanCmd) -} - -// Scan published builds with Xray -func BuildScan(c *cli.Context) error { - if c.NArg() > 2 { - return cliutils.WrongNumberOfArgumentsHandler(c) - } - buildConfiguration := cliutils.CreateBuildConfiguration(c) - if err := buildConfiguration.ValidateBuildParams(); err != nil { - return err - } - serverDetails, err := createServerDetailsWithConfigOffer(c) - if err != nil { - return err - } - err = validateXrayContext(c, serverDetails) - if err != nil { - return err - } - format, err := outputFormat.GetOutputFormat(c.String("format")) - if err != nil { - return err - } - buildScanCmd := scan.NewBuildScanCommand(). - SetServerDetails(serverDetails). - SetFailBuild(c.BoolT("fail")). - SetBuildConfiguration(buildConfiguration). - SetOutputFormat(format). - SetPrintExtendedTable(c.Bool(cliutils.ExtendedTable)). - SetRescan(c.Bool("rescan")) - if format != outputFormat.Sarif { - // Sarif shouldn't include the additional all-vulnerabilities info that received by adding the vuln flag - buildScanCmd.SetIncludeVulnerabilities(c.Bool("vuln")) - } - return commands.Exec(buildScanCmd) -} - -func DockerScan(c *cli.Context, image string) error { - if show, err := cliutils.ShowGenericCmdHelpIfNeeded(c, c.Args(), "dockerscanhelp"); show || err != nil { - return err - } - if image == "" { - return cli.ShowCommandHelp(c, "dockerscanhelp") - } - serverDetails, err := createServerDetailsWithConfigOffer(c) - if err != nil { - return err - } - err = validateXrayContext(c, serverDetails) - if err != nil { - return err - } - containerScanCommand := scan.NewDockerScanCommand() - format, err := outputFormat.GetOutputFormat(c.String("format")) - if err != nil { - return err - } - minSeverity, err := xrutils.GetSeveritiesFormat(c.String(cliutils.MinSeverity)) - if err != nil { - return err - } - containerScanCommand.SetImageTag(image). - SetTargetRepoPath(addTrailingSlashToRepoPathIfNeeded(c)). - SetServerDetails(serverDetails). - SetOutputFormat(format). - SetProject(c.String("project")). - SetIncludeVulnerabilities(shouldIncludeVulnerabilities(c)). - SetIncludeLicenses(c.Bool("licenses")). - SetFail(c.BoolT("fail")). - SetPrintExtendedTable(c.Bool(cliutils.ExtendedTable)). - SetBypassArchiveLimits(c.Bool(cliutils.BypassArchiveLimits)). - SetFixableOnly(c.Bool(cliutils.FixableOnly)). - SetMinSeverityFilter(minSeverity) - if c.String("watches") != "" { - containerScanCommand.SetWatches(splitByCommaAndTrim(c.String("watches"))) - } - return progressbar.ExecWithProgress(containerScanCommand) -} - -func addTrailingSlashToRepoPathIfNeeded(c *cli.Context) string { - repoPath := c.String("repo-path") - if repoPath != "" && !strings.Contains(repoPath, "/") { - // In case only repo name was provided (no path) we are adding a trailing slash. - repoPath += "/" - } - return repoPath -} - -func createDefaultScanSpec(c *cli.Context, defaultTarget string) *spec.SpecFiles { - return spec.NewBuilder(). - Pattern(c.Args().Get(0)). - Target(defaultTarget). - Recursive(c.BoolT("recursive")). - Exclusions(cliutils.GetStringsArrFlagValue(c, "exclusions")). - Regexp(c.Bool("regexp")). - Ant(c.Bool("ant")). - IncludeDirs(c.Bool("include-dirs")). - BuildSpec() -} - -func createServerDetailsWithConfigOffer(c *cli.Context) (*coreconfig.ServerDetails, error) { - return cliutils.CreateServerDetailsWithConfigOffer(c, true, "xr") -} - -func shouldIncludeVulnerabilities(c *cli.Context) bool { - // If no context was provided by the user, no Violations will be triggered by Xray, so include general vulnerabilities in the command output - return c.String("watches") == "" && !isProjectProvided(c) && c.String("repo-path") == "" -} - -func validateXrayContext(c *cli.Context, serverDetails *coreconfig.ServerDetails) error { - if serverDetails.XrayUrl == "" { - return errorutils.CheckErrorf("JFrog Xray URL must be provided in order run this command. Use the 'jf c add' command to set the Xray server details.") - } - contextFlag := 0 - if c.String("watches") != "" { - contextFlag++ - } - if isProjectProvided(c) { - contextFlag++ - } - if c.String("repo-path") != "" { - contextFlag++ - } - if contextFlag > 1 { - return errorutils.CheckErrorf("only one of the following flags can be supplied: --watches, --project or --repo-path") - } - return nil -} - -func isProjectProvided(c *cli.Context) bool { - return c.String("project") != "" || os.Getenv(coreutils.Project) != "" -} - -func splitByCommaAndTrim(paramValue string) (res []string) { - args := strings.Split(paramValue, ",") - res = make([]string, len(args)) - for i, arg := range args { - res[i] = strings.TrimSpace(arg) - } - return -} diff --git a/transfer_test.go b/transfer_test.go index 943476aa5..592dc9ea3 100644 --- a/transfer_test.go +++ b/transfer_test.go @@ -37,7 +37,7 @@ import ( var targetArtHttpDetails *httputils.HttpClientDetails var targetServerDetails *config.ServerDetails -var targetArtifactoryCli *tests.JfrogCli +var targetArtifactoryCli *coretests.JfrogCli func InitTransferTests() { initArtifactoryCli() @@ -47,7 +47,7 @@ func InitTransferTests() { createRequiredRepos() var creds string creds, targetServerDetails, targetArtHttpDetails = inttestutils.AuthenticateTarget() - targetArtifactoryCli = tests.NewJfrogCli(execMain, "jfrog rt", creds) + targetArtifactoryCli = coretests.NewJfrogCli(execMain, "jfrog rt", creds) inttestutils.CreateTargetRepos(targetArtifactoryCli) } @@ -77,7 +77,7 @@ func initTransferTest(t *testing.T) func() { assert.NoError(t, err) } *tests.JfrogUrl = utils.AddTrailingSlashIfNeeded(*tests.JfrogUrl) - err = tests.NewJfrogCli(execMain, "jfrog config", "--access-token="+*tests.JfrogTargetAccessToken).Exec("add", inttestutils.TargetServerId, "--interactive=false", "--url="+*tests.JfrogTargetUrl) + err = coretests.NewJfrogCli(execMain, "jfrog config", "--access-token="+*tests.JfrogTargetAccessToken).Exec("add", inttestutils.TargetServerId, "--interactive=false", "--url="+*tests.JfrogTargetUrl) assert.NoError(t, err) if *tests.InstallDataTransferPlugin { diff --git a/utils/cliutils/cli_consts.go b/utils/cliutils/cli_consts.go index 6cd1a2f8d..a142f81f3 100644 --- a/utils/cliutils/cli_consts.go +++ b/utils/cliutils/cli_consts.go @@ -4,7 +4,7 @@ import "time" const ( // General CLI constants - CliVersion = "2.52.9" + CliVersion = "2.52.10" ClientAgent = "jfrog-cli-go" // CLI base commands constants: @@ -27,15 +27,13 @@ const ( // Common Retries = 3 RetryWaitMilliSecs = 0 - Threads = 3 ArtifactoryTokenExpiry = 3600 DefaultLicenseCount = 1 LatestCliVersionCheckInterval = time.Hour * 6 // Env - BuildUrl = "JFROG_CLI_BUILD_URL" - EnvExclude = "JFROG_CLI_ENV_EXCLUDE" - UserAgent = "JFROG_CLI_USER_AGENT" - JfrogCliAvoidDeprecationWarnings = "JFROG_CLI_AVOID_DEPRECATION_WARNINGS" - JfrogCliAvoidNewVersionWarning = "JFROG_CLI_AVOID_NEW_VERSION_WARNING" + BuildUrl = "JFROG_CLI_BUILD_URL" + EnvExclude = "JFROG_CLI_ENV_EXCLUDE" + UserAgent = "JFROG_CLI_USER_AGENT" + JfrogCliAvoidNewVersionWarning = "JFROG_CLI_AVOID_NEW_VERSION_WARNING" ) diff --git a/utils/cliutils/codegangstautils.go b/utils/cliutils/codegangstautils.go index 5df4443b0..036936332 100644 --- a/utils/cliutils/codegangstautils.go +++ b/utils/cliutils/codegangstautils.go @@ -1,12 +1,12 @@ package cliutils import ( - "errors" "golang.org/x/exp/slices" "sort" "strconv" "strings" + commonCliUtils "github.com/jfrog/jfrog-cli-core/v2/common/cliutils" "github.com/jfrog/jfrog-client-go/utils" "github.com/urfave/cli" ) @@ -28,15 +28,7 @@ func GetStringsArrFlagValue(c *cli.Context, flagName string) (resultArray []stri } func GetThreadsCount(c *cli.Context) (threads int, err error) { - threads = Threads - if c.String("threads") != "" { - threads, err = strconv.Atoi(c.String("threads")) - if err != nil || threads < 1 { - err = errors.New("the '--threads' option should have a numeric positive value") - return 0, err - } - } - return threads, nil + return commonCliUtils.GetThreadsCount(c.String("threads")) } func ExtractCommand(c *cli.Context) []string { diff --git a/utils/cliutils/commandsflags.go b/utils/cliutils/commandsflags.go index 3607aafd9..30a9b2b5f 100644 --- a/utils/cliutils/commandsflags.go +++ b/utils/cliutils/commandsflags.go @@ -5,8 +5,8 @@ import ( "sort" "strconv" + commonCliUtils "github.com/jfrog/jfrog-cli-core/v2/common/cliutils" "github.com/jfrog/jfrog-cli-core/v2/utils/coreutils" - "github.com/jfrog/jfrog-cli-core/v2/xray/commands/offlineupdate" "github.com/jfrog/jfrog-client-go/utils/log" "github.com/urfave/cli" @@ -711,7 +711,7 @@ var flagsMap = map[string]cli.Flag{ threads: cli.StringFlag{ Name: threads, Value: "", - Usage: "[Default: " + strconv.Itoa(Threads) + "] Number of working threads.` `", + Usage: "[Default: " + strconv.Itoa(commonCliUtils.Threads) + "] Number of working threads.` `", }, retries: cli.StringFlag{ Name: retries, @@ -1140,7 +1140,7 @@ var flagsMap = map[string]cli.Flag{ deploymentThreads: cli.StringFlag{ Name: threads, Value: "", - Usage: "[Default: " + strconv.Itoa(Threads) + "] Number of threads for uploading build artifacts.` `", + Usage: "[Default: " + strconv.Itoa(commonCliUtils.Threads) + "] Number of threads for uploading build artifacts.` `", }, skipLogin: cli.BoolFlag{ Name: skipLogin, @@ -1325,10 +1325,6 @@ var flagsMap = map[string]cli.Flag{ Name: licenseId, Usage: "[Mandatory] Xray license ID.` `", }, - Stream: cli.StringFlag{ - Name: Stream, - Usage: fmt.Sprintf("[Optional] Xray DBSync V3 stream, Possible values are: %s.` `", offlineupdate.NewValidStreams().GetValidStreamsString()), - }, from: cli.StringFlag{ Name: from, Usage: "[Optional] From update date in YYYY-MM-DD format.` `", @@ -2009,49 +2005,6 @@ var commandFlags = map[string][]string{ 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, - }, - XrCurl: { - serverId, - }, - CurationAudit: { - curationOutput, workingDirs, curationThreads, - }, - Audit: { - xrUrl, user, password, accessToken, serverId, InsecureTls, Project, watches, repoPath, licenses, xrOutput, ExcludeTestDeps, - useWrapperAudit, DepType, RequirementsFile, fail, ExtendedTable, workingDirs, ExclusionsAudit, Mvn, Gradle, Npm, Yarn, Go, Nuget, Pip, Pipenv, Poetry, MinSeverity, FixableOnly, ThirdPartyContextualAnalysis, - }, - AuditMvn: { - xrUrl, user, password, accessToken, serverId, InsecureTls, Project, ExclusionsAudit, watches, repoPath, licenses, xrOutput, fail, ExtendedTable, useWrapperAudit, - }, - AuditGradle: { - xrUrl, user, password, accessToken, serverId, ExcludeTestDeps, ExclusionsAudit, useWrapperAudit, Project, watches, repoPath, licenses, xrOutput, fail, ExtendedTable, - }, - AuditNpm: { - xrUrl, user, password, accessToken, serverId, DepType, Project, ExclusionsAudit, watches, repoPath, licenses, xrOutput, fail, ExtendedTable, - }, - AuditGo: { - xrUrl, user, password, accessToken, serverId, Project, ExclusionsAudit, watches, repoPath, licenses, xrOutput, fail, ExtendedTable, - }, - AuditPip: { - xrUrl, user, password, accessToken, serverId, RequirementsFile, Project, ExclusionsAudit, watches, repoPath, licenses, xrOutput, fail, ExtendedTable, - }, - AuditPipenv: { - xrUrl, user, password, accessToken, serverId, Project, ExclusionsAudit, watches, repoPath, licenses, xrOutput, ExtendedTable, - }, - XrScan: { - xrUrl, user, password, accessToken, serverId, specFlag, threads, scanRecursive, scanRegexp, scanAnt, - Project, watches, repoPath, licenses, xrOutput, fail, ExtendedTable, BypassArchiveLimits, MinSeverity, FixableOnly, - }, - DockerScan: { - // Flags added here should be also added to Docker command - serverId, Project, watches, repoPath, licenses, xrOutput, fail, ExtendedTable, BypassArchiveLimits, MinSeverity, FixableOnly, - }, - BuildScan: { - xrUrl, user, password, accessToken, serverId, Project, vuln, xrOutput, fail, ExtendedTable, rescan, - }, // Mission Control's commands McConfig: { mcUrl, mcAccessToken, mcInteractive, diff --git a/utils/cliutils/utils.go b/utils/cliutils/utils.go index fe9b7f32e..7cff55dc9 100644 --- a/utils/cliutils/utils.go +++ b/utils/cliutils/utils.go @@ -4,8 +4,6 @@ import ( "encoding/json" "errors" "fmt" - "github.com/jfrog/gofrog/version" - "github.com/jfrog/jfrog-client-go/utils/log" "io" "net/http" "os" @@ -14,17 +12,21 @@ import ( "strings" "time" + "github.com/jfrog/gofrog/version" + "github.com/jfrog/jfrog-client-go/utils/log" + corecontainercmds "github.com/jfrog/jfrog-cli-core/v2/artifactory/commands/container" commandUtils "github.com/jfrog/jfrog-cli-core/v2/artifactory/commands/utils" artifactoryUtils "github.com/jfrog/jfrog-cli-core/v2/artifactory/utils" containerutils "github.com/jfrog/jfrog-cli-core/v2/artifactory/utils/container" buildUtils "github.com/jfrog/jfrog-cli-core/v2/common/build" - coreCommonCommands "github.com/jfrog/jfrog-cli-core/v2/common/commands" + "github.com/jfrog/jfrog-cli-core/v2/common/cliutils" + commonCliUtils "github.com/jfrog/jfrog-cli-core/v2/common/cliutils" + commonCommands "github.com/jfrog/jfrog-cli-core/v2/common/commands" "github.com/jfrog/jfrog-cli-core/v2/common/project" speccore "github.com/jfrog/jfrog-cli-core/v2/common/spec" coreConfig "github.com/jfrog/jfrog-cli-core/v2/utils/config" "github.com/jfrog/jfrog-cli-core/v2/utils/coreutils" - "github.com/jfrog/jfrog-cli-core/v2/utils/ioutils" "github.com/jfrog/jfrog-cli/utils/summary" clientutils "github.com/jfrog/jfrog-client-go/utils" "github.com/jfrog/jfrog-client-go/utils/errorutils" @@ -32,15 +34,6 @@ import ( "github.com/urfave/cli" ) -type CommandDomain string - -const ( - Rt CommandDomain = "rt" - Ds CommandDomain = "ds" - Xr CommandDomain = "xr" - Platform CommandDomain = "platform" -) - // Error modes (how should the application behave when the CheckError function is invoked): type OnError string @@ -261,16 +254,11 @@ func CreateBuildInfoSummaryReportString(success, failed int, sha256 string, err } func PrintHelpAndReturnError(msg string, context *cli.Context) error { - log.Error(msg + " " + GetDocumentationMessage()) - err := cli.ShowCommandHelp(context, context.Command.Name) - if err != nil { - msg = msg + ". " + err.Error() - } - return errors.New(msg) + return commonCliUtils.PrintHelpAndReturnError(msg, GetPrintCurrentCmdHelp(context)) } func WrongNumberOfArgumentsHandler(context *cli.Context) error { - return PrintHelpAndReturnError(fmt.Sprintf("Wrong number of arguments (%d).", context.NArg()), context) + return commonCliUtils.WrongNumberOfArgumentsHandler(context.NArg(), GetPrintCurrentCmdHelp(context)) } // This function indicates whether the command should be executed without @@ -335,31 +323,6 @@ func getOrDefaultEnv(arg, envKey string) string { return os.Getenv(envKey) } -func ShouldOfferConfig() (bool, error) { - exists, err := coreConfig.IsServerConfExists() - if err != nil || exists { - return false, err - } - var ci bool - if ci, err = clientutils.GetBoolEnvValue(coreutils.CI, false); err != nil { - return false, err - } - if ci { - return false, nil - } - - msg := fmt.Sprintf("To avoid this message in the future, set the %s environment variable to true.\n"+ - "The CLI commands require the URL and authentication details\n"+ - "Configuring JFrog CLI with these parameters now will save you having to include them as command options.\n"+ - "You can also configure these parameters later using the 'jfrog c' command.\n"+ - "Configure now?", coreutils.CI) - confirmed := coreutils.AskYesNo(msg, false) - if !confirmed { - return false, nil - } - return true, nil -} - func CreateServerDetailsFromFlags(c *cli.Context) (details *coreConfig.ServerDetails, err error) { details = new(coreConfig.ServerDetails) details.Url = clientutils.AddTrailingSlashIfNeeded(c.String(url)) @@ -390,34 +353,7 @@ func CreateServerDetailsFromFlags(c *cli.Context) (details *coreConfig.ServerDet } func handleSecretInput(c *cli.Context, stringFlag, stdinFlag string) (secret string, err error) { - secret = c.String(stringFlag) - isStdinSecret := c.Bool(stdinFlag) - if isStdinSecret && secret != "" { - err = errorutils.CheckErrorf("providing both %s and %s flags is not supported", stringFlag, stdinFlag) - return - } - - if isStdinSecret { - var stat os.FileInfo - stat, err = os.Stdin.Stat() - if err != nil { - return - } - if (stat.Mode() & os.ModeCharDevice) == 0 { - var rawSecret []byte - rawSecret, err = io.ReadAll(os.Stdin) - if err != nil { - return - } - secret = strings.TrimSpace(string(rawSecret)) - if secret != "" { - log.Debug("Using", stringFlag, "provided via Stdin") - return - } - } - err = errorutils.CheckErrorf("no %s provided via Stdin", stringFlag) - } - return + return commonCliUtils.HandleSecretInput(stringFlag, c.String(stringFlag), stdinFlag, c.Bool(stdinFlag)) } func GetSpec(c *cli.Context, isDownload bool) (specFiles *speccore.SpecFiles, err error) { @@ -435,6 +371,19 @@ func GetSpec(c *cli.Context, isDownload bool) (specFiles *speccore.SpecFiles, er return } +func GetFileSystemSpec(c *cli.Context) (fsSpec *speccore.SpecFiles, err error) { + fsSpec, err = speccore.CreateSpecFromFile(c.String("spec"), coreutils.SpecVarsStringToMap(c.String("spec-vars"))) + if err != nil { + return + } + // Override spec with CLI options + for i := 0; i < len(fsSpec.Files); i++ { + fsSpec.Get(i).Target = strings.TrimPrefix(fsSpec.Get(i).Target, "/") + OverrideFieldsIfSet(fsSpec.Get(i), c) + } + return +} + // If `fieldName` exist in the cli args, read it to `field` as a string. func overrideStringIfSet(field *string, c *cli.Context, fieldName string) { if c.IsSet(fieldName) { @@ -456,81 +405,25 @@ func overrideIntIfSet(field *int, c *cli.Context, fieldName string) { } } -func offerConfig(c *cli.Context, domain CommandDomain) (*coreConfig.ServerDetails, error) { - confirmed, err := ShouldOfferConfig() - if !confirmed || err != nil { - return nil, err - } - details, err := createServerDetailsFromFlags(c, domain) - if err != nil { - return nil, err - } - configCmd := coreCommonCommands.NewConfigCommand(coreCommonCommands.AddOrEdit, details.ServerId).SetDefaultDetails(details).SetInteractive(true).SetEncPassword(true) - err = configCmd.Run() - if err != nil { - return nil, err - } - - return configCmd.ServerDetails() -} - // Exclude refreshable tokens parameter should be true when working with external tools (build tools, curl, etc) // or when sending requests not via ArtifactoryHttpClient. -func CreateServerDetailsWithConfigOffer(c *cli.Context, excludeRefreshableTokens bool, domain CommandDomain) (*coreConfig.ServerDetails, error) { - createdDetails, err := offerConfig(c, domain) - if err != nil { - return nil, err - } - if createdDetails != nil { - return createdDetails, err - } - - details, err := createServerDetailsFromFlags(c, domain) - if err != nil { - return nil, err - } - // If urls or credentials were passed as options, use options as they are. - // For security reasons, we'd like to avoid using part of the connection details from command options and the rest from the config. - // Either use command options only or config only. - if credentialsChanged(details) { - return details, nil - } - - // Else, use details from config for requested serverId, or for default server if empty. - confDetails, err := coreCommonCommands.GetConfig(details.ServerId, excludeRefreshableTokens) - if err != nil { - return nil, err - } - - // Take insecureTls value from options since it is not saved in config. - confDetails.InsecureTls = details.InsecureTls - confDetails.Url = clientutils.AddTrailingSlashIfNeeded(confDetails.Url) - confDetails.DistributionUrl = clientutils.AddTrailingSlashIfNeeded(confDetails.DistributionUrl) - - // Create initial access token if needed. - if !excludeRefreshableTokens { - err = coreConfig.CreateInitialRefreshableTokensIfNeeded(confDetails) - if err != nil { - return nil, err - } - } - - return confDetails, nil +func CreateServerDetailsWithConfigOffer(c *cli.Context, excludeRefreshableTokens bool, domain cliutils.CommandDomain) (*coreConfig.ServerDetails, error) { + return cliutils.CreateServerDetailsWithConfigOffer(func() (*coreConfig.ServerDetails, error) { return createServerDetailsFromFlags(c, domain) }, excludeRefreshableTokens) } -func createServerDetailsFromFlags(c *cli.Context, domain CommandDomain) (details *coreConfig.ServerDetails, err error) { +func createServerDetailsFromFlags(c *cli.Context, domain cliutils.CommandDomain) (details *coreConfig.ServerDetails, err error) { details, err = CreateServerDetailsFromFlags(c) if err != nil { return } switch domain { - case Rt: + case cliutils.Rt: details.ArtifactoryUrl = details.Url - case Xr: + case cliutils.Xr: details.XrayUrl = details.Url - case Ds: + case cliutils.Ds: details.DistributionUrl = details.Url - case Platform: + case cliutils.Platform: return } details.Url = "" @@ -538,24 +431,17 @@ func createServerDetailsFromFlags(c *cli.Context, domain CommandDomain) (details return } -func credentialsChanged(details *coreConfig.ServerDetails) bool { - return details.Url != "" || details.ArtifactoryUrl != "" || details.DistributionUrl != "" || details.XrayUrl != "" || - details.User != "" || details.Password != "" || details.SshKeyPath != "" || details.SshPassphrase != "" || details.AccessToken != "" || - details.ClientCertKeyPath != "" || details.ClientCertPath != "" +func GetPrintCurrentCmdHelp(c *cli.Context) func() error { + return func() error { + return cli.ShowCommandHelp(c, c.Command.Name) + } } // This function checks whether the command received --help as a single option. // If it did, the command's help is shown and true is returned. // This function should be used iff the SkipFlagParsing option is used. func ShowCmdHelpIfNeeded(c *cli.Context, args []string) (bool, error) { - if len(args) != 1 { - return false, nil - } - if args[0] == "--help" || args[0] == "-h" { - err := cli.ShowCommandHelp(c, c.Command.Name) - return true, err - } - return false, nil + return commonCliUtils.ShowCmdHelpIfNeeded(args, GetPrintCurrentCmdHelp(c)) } // This function checks whether the command received --help as a single option. @@ -574,19 +460,6 @@ func ShowGenericCmdHelpIfNeeded(c *cli.Context, args []string, cmdName string) ( return false, nil } -func GetFileSystemSpec(c *cli.Context) (fsSpec *speccore.SpecFiles, err error) { - fsSpec, err = speccore.CreateSpecFromFile(c.String("spec"), coreutils.SpecVarsStringToMap(c.String("spec-vars"))) - if err != nil { - return - } - // Override spec with CLI options - for i := 0; i < len(fsSpec.Files); i++ { - fsSpec.Get(i).Target = strings.TrimPrefix(fsSpec.Get(i).Target, "/") - OverrideFieldsIfSet(fsSpec.Get(i), c) - } - return -} - func OverrideFieldsIfSet(spec *speccore.File, c *cli.Context) { overrideArrayIfSet(&spec.Exclusions, c, "exclusions") overrideArrayIfSet(&spec.SortBy, c, "sort-by") @@ -614,38 +487,18 @@ func OverrideFieldsIfSet(spec *speccore.File, c *cli.Context) { } func FixWinPathsForFileSystemSourcedCmds(uploadSpec *speccore.SpecFiles, c *cli.Context) { - if coreutils.IsWindows() { - for i, file := range uploadSpec.Files { - uploadSpec.Files[i].Pattern = fixWinPathBySource(file.Pattern, c.IsSet("spec")) - for j, exclusion := range uploadSpec.Files[i].Exclusions { - // If exclusions are set, they override the spec value - uploadSpec.Files[i].Exclusions[j] = fixWinPathBySource(exclusion, c.IsSet("spec") && !c.IsSet("exclusions")) - } - } - } -} - -func fixWinPathBySource(path string, fromSpec bool) string { - if strings.Count(path, "/") > 0 { - // Assuming forward slashes - not doubling backslash to allow regexp escaping - return ioutils.UnixToWinPathSeparator(path) - } - if fromSpec { - // Doubling backslash only for paths from spec files (that aren't forward slashed) - return ioutils.DoubleWinPathSeparator(path) - } - return path + commonCliUtils.FixWinPathsForFileSystemSourcedCmds(uploadSpec, c.IsSet("spec"), c.IsSet("exclusions")) } func CreateConfigCmd(c *cli.Context, confType project.ProjectType) error { if c.NArg() != 0 { return WrongNumberOfArgumentsHandler(c) } - return coreCommonCommands.CreateBuildConfig(c, confType) + return commonCommands.CreateBuildConfig(c, confType) } func RunNativeCmdWithDeprecationWarning(cmdName string, projectType project.ProjectType, c *cli.Context, cmd func(c *cli.Context) error) error { - if shouldLogWarning() { + if cliutils.ShouldLogWarning() { LogNativeCommandDeprecation(cmdName, projectType.String()) } return cmd(c) @@ -684,42 +537,16 @@ func NotSupportedNativeDockerCommand(oldCmdName string) error { func RunConfigCmdWithDeprecationWarning(cmdName, oldSubcommand string, confType project.ProjectType, c *cli.Context, cmd func(c *cli.Context, confType project.ProjectType) error) error { - logNonNativeCommandDeprecation(cmdName, oldSubcommand) + commonCliUtils.LogNonNativeCommandDeprecation(cmdName, oldSubcommand) return cmd(c, confType) } func RunCmdWithDeprecationWarning(cmdName, oldSubcommand string, c *cli.Context, cmd func(c *cli.Context) error) error { - logNonNativeCommandDeprecation(cmdName, oldSubcommand) + commonCliUtils.LogNonNativeCommandDeprecation(cmdName, oldSubcommand) return cmd(c) } -func logNonNativeCommandDeprecation(cmdName, oldSubcommand string) { - if shouldLogWarning() { - log.Warn( - `You are using a deprecated syntax of the command. - Instead of: - $ ` + coreutils.GetCliExecutableName() + ` ` + oldSubcommand + ` ` + cmdName + ` ... - Use: - $ ` + coreutils.GetCliExecutableName() + ` ` + cmdName + ` ...`) - } -} - -func LogNonGenericAuditCommandDeprecation(cmdName string) { - if shouldLogWarning() { - log.Warn( - `You are using a deprecated syntax of the command. - Instead of: - $ ` + coreutils.GetCliExecutableName() + ` ` + cmdName + ` ... - Use: - $ ` + coreutils.GetCliExecutableName() + ` audit ...`) - } -} - -func shouldLogWarning() bool { - return strings.ToLower(os.Getenv(JfrogCliAvoidDeprecationWarnings)) != "true" -} - func SetCliExecutableName(executablePath string) { coreutils.SetCliExecutableName(filepath.Base(executablePath)) } @@ -747,7 +574,7 @@ func CreateBuildConfigurationWithModule(c *cli.Context) (buildConfigConfiguratio } func CreateArtifactoryDetailsByFlags(c *cli.Context) (*coreConfig.ServerDetails, error) { - artDetails, err := CreateServerDetailsWithConfigOffer(c, false, Rt) + artDetails, err := CreateServerDetailsWithConfigOffer(c, false, cliutils.Rt) if err != nil { return nil, err } diff --git a/utils/progressbar/filesprogressbar.go b/utils/progressbar/filesprogressbar.go deleted file mode 100644 index 5046c7058..000000000 --- a/utils/progressbar/filesprogressbar.go +++ /dev/null @@ -1,338 +0,0 @@ -package progressbar - -import ( - "github.com/jfrog/jfrog-cli-core/v2/utils/coreutils" - "net/url" - "os" - "strings" - "sync" - "sync/atomic" - "time" - - "github.com/jfrog/jfrog-cli-core/v2/common/commands" - corelog "github.com/jfrog/jfrog-cli-core/v2/utils/log" - "github.com/jfrog/jfrog-cli-core/v2/utils/progressbar" - ioUtils "github.com/jfrog/jfrog-client-go/utils/io" - "github.com/jfrog/jfrog-client-go/utils/log" - - "github.com/vbauerster/mpb/v7" - "github.com/vbauerster/mpb/v7/decor" -) - -var terminalWidth int - -type filesProgressBarManager struct { - // A list of progress bar objects. - bars []progressBar - // A wait group for all progress bars. - barsWg *sync.WaitGroup - // A container of all external mpb bar objects to be displayed. - container *mpb.Progress - // A synchronization lock object. - barsRWMutex sync.RWMutex - // A general work indicator spinner. - headlineBar *mpb.Bar - // A general tasks completion indicator. - generalProgressBar *mpb.Bar - // A cumulative amount of tasks - tasksCount int64 - // The log file - logFile *os.File -} - -type progressBarUnit struct { - bar *mpb.Bar - incrChannel chan int - description string -} - -type progressBar interface { - ioUtils.Progress - getProgressBarUnit() *progressBarUnit -} - -func (p *filesProgressBarManager) InitProgressReaders() { - p.newHeadlineBar(" Working") - p.tasksCount = 0 - p.newGeneralProgressBar() -} - -// Initializes a new reader progress indicator for a new file transfer. -// Input: 'total' - file size. -// -// 'label' - the title of the operation. -// 'path' - the path of the file being processed. -// -// Output: progress indicator id -func (p *filesProgressBarManager) NewProgressReader(total int64, label, path string) (bar ioUtils.Progress) { - // Write Lock when appending a new bar to the slice - p.barsRWMutex.Lock() - defer p.barsRWMutex.Unlock() - p.barsWg.Add(1) - newBar := p.container.New(total, - mpb.BarStyle().Lbound("|").Filler("🟩").Tip("🟩").Padding("⬛").Refiller("").Rbound("|"), - mpb.BarRemoveOnComplete(), - mpb.AppendDecorators( - // Extra chars length is the max length of the KibiByteCounter - decor.Name(buildProgressDescription(label, path, 17)), - decor.CountersKibiByte("%3.1f/%3.1f"), - ), - ) - - // Add bar to bars array - unit := initNewBarUnit(newBar, path) - barId := len(p.bars) + 1 - readerProgressBar := ReaderProgressBar{progressBarUnit: unit, Id: barId} - p.bars = append(p.bars, &readerProgressBar) - return &readerProgressBar -} - -// Changes progress indicator state and acts accordingly. -func (p *filesProgressBarManager) SetProgressState(id int, state string) { - if state == "Merging" { - p.addNewMergingSpinner(id) - } -} - -// Initializes a new progress bar, that replaces the progress bar with the given replacedBarId -func (p *filesProgressBarManager) addNewMergingSpinner(replacedBarId int) { - // Write Lock when appending a new bar to the slice - p.barsRWMutex.Lock() - defer p.barsRWMutex.Unlock() - replacedBar := p.bars[replacedBarId-1].getProgressBarUnit() - p.bars[replacedBarId-1].Abort() - newBar := p.container.New(1, - mpb.SpinnerStyle(createSpinnerFramesArray()...).PositionLeft(), - mpb.AppendDecorators( - decor.Name(buildProgressDescription(" Merging ", replacedBar.description, 0)), - ), - ) - // Bar replacement is a simple spinner and thus does not implement any read functionality - unit := &progressBarUnit{bar: newBar, description: replacedBar.description} - progressBar := SimpleProgressBar{progressBarUnit: unit, Id: replacedBarId} - p.bars[replacedBarId-1] = &progressBar -} - -func buildProgressDescription(label, path string, extraCharsLen int) string { - separator := " | " - // Max line length after decreasing bar width (*2 in case unicode chars with double width are used) and the extra chars - descMaxLength := terminalWidth - (progressbar.ProgressBarWidth*2 + extraCharsLen) - return buildDescByLimits(descMaxLength, " "+label+separator, shortenUrl(path), separator) -} - -func shortenUrl(path string) string { - if _, err := url.ParseRequestURI(path); err != nil { - return path - } - - semicolonIndex := strings.Index(path, ";") - if semicolonIndex == -1 { - return path - } - return path[:semicolonIndex] -} - -func buildDescByLimits(descMaxLength int, prefix, path, suffix string) string { - desc := prefix + path + suffix - - // Verify that the whole description doesn't exceed the max length - if len(desc) <= descMaxLength { - return desc - } - - // If it does exceed, check if shortening the path will help (+3 is for "...") - if len(desc)-len(path)+3 > descMaxLength { - // Still exceeds, do not display desc - return "" - } - - // Shorten path from the beginning - path = "..." + path[len(desc)-descMaxLength+3:] - return prefix + path + suffix -} - -func initNewBarUnit(bar *mpb.Bar, path string) *progressBarUnit { - ch := make(chan int, 1000) - unit := &progressBarUnit{bar: bar, incrChannel: ch, description: path} - go incrBarFromChannel(unit) - return unit -} - -func incrBarFromChannel(unit *progressBarUnit) { - // Increase bar while channel is open - for n := range unit.incrChannel { - unit.bar.IncrBy(n) - } -} - -func createSpinnerFramesArray() []string { - black := "⬛" - green := "🟩" - spinnerFramesArray := make([]string, progressbar.ProgressBarWidth) - for i := 1; i < progressbar.ProgressBarWidth-1; i++ { - cur := "|" + strings.Repeat(black, i-1) + green + strings.Repeat(black, progressbar.ProgressBarWidth-2-i) + "|" - spinnerFramesArray[i] = cur - } - return spinnerFramesArray -} - -// Aborts a progress bar. -// Should be called even if bar completed successfully. -// The progress component's Abort method has no effect if bar has already completed, so can always be safely called anyway -func (p *filesProgressBarManager) RemoveProgress(id int) { - p.barsRWMutex.RLock() - defer p.barsWg.Done() - defer p.barsRWMutex.RUnlock() - p.bars[id-1].Abort() -} - -// Increases general progress bar by 1 -func (p *filesProgressBarManager) IncrementGeneralProgress() { - p.generalProgressBar.Increment() -} - -// Quits the progress bar while aborting the initial bars. -func (p *filesProgressBarManager) Quit() (err error) { - if p.headlineBar != nil { - p.headlineBar.Abort(true) - p.barsWg.Done() - p.headlineBar = nil - } - if p.generalProgressBar != nil { - p.generalProgressBar.Abort(true) - p.barsWg.Done() - p.generalProgressBar = nil - } - // Wait a refresh rate to make sure all aborts have finished - time.Sleep(progressbar.ProgressRefreshRate) - p.container.Wait() - // Close the created log file (once) - if p.logFile != nil { - err = corelog.CloseLogFile(p.logFile) - p.logFile = nil - // Set back the default logger - corelog.SetDefaultLogger() - } - return -} - -func (p *filesProgressBarManager) GetProgress(id int) ioUtils.Progress { - return p.bars[id-1] -} - -// Initializes progress bar if possible (all conditions in 'shouldInitProgressBar' are met). -// Returns nil, nil, err if failed. -func InitFilesProgressBarIfPossible(showLogFilePath bool) (ioUtils.ProgressMgr, error) { - shouldInit, err := progressbar.ShouldInitProgressBar() - if !shouldInit || err != nil { - return nil, err - } - - logFile, err := corelog.CreateLogFile() - if err != nil { - return nil, err - } - if showLogFilePath { - log.Info("Log path:", logFile.Name()) - } - log.SetLogger(log.NewLogger(corelog.GetCliLogLevel(), logFile)) - - newProgressBar := &filesProgressBarManager{} - newProgressBar.barsWg = new(sync.WaitGroup) - - // Initialize the progressBar container with wg, to create a single joint point - newProgressBar.container = mpb.New( - mpb.WithOutput(os.Stderr), - mpb.WithWaitGroup(newProgressBar.barsWg), - mpb.WithWidth(progressbar.ProgressBarWidth), - mpb.WithRefreshRate(progressbar.ProgressRefreshRate)) - - newProgressBar.logFile = logFile - - return newProgressBar, nil -} - -// Initializes a new progress bar for general progress indication -func (p *filesProgressBarManager) newGeneralProgressBar() { - p.barsWg.Add(1) - p.generalProgressBar = p.container.New(p.tasksCount, - mpb.BarStyle().Lbound("|").Filler("⬜").Tip("⬜").Padding("⬛").Refiller("").Rbound("|"), - mpb.BarRemoveOnComplete(), - mpb.AppendDecorators( - decor.Name(" Tasks: "), - decor.CountersNoUnit("%d/%d"), - ), - ) -} - -// Initializes a new progress bar for headline, with a spinner -func (p *filesProgressBarManager) newHeadlineBar(headline string) { - p.barsWg.Add(1) - p.headlineBar = p.container.New(1, - mpb.SpinnerStyle("∙∙∙∙∙∙", "●∙∙∙∙∙", "∙●∙∙∙∙", "∙∙●∙∙∙", "∙∙∙●∙∙", "∙∙∙∙●∙", "∙∙∙∙∙●", "∙∙∙∙∙∙").PositionLeft(), - mpb.BarRemoveOnComplete(), - mpb.PrependDecorators( - decor.Name(headline), - ), - ) -} - -func (p *filesProgressBarManager) SetHeadlineMsg(msg string) { - if p.headlineBar != nil { - current := p.headlineBar - p.barsRWMutex.RLock() - // First abort, then mark progress as done and finally release the lock. - defer p.barsRWMutex.RUnlock() - defer p.barsWg.Done() - defer current.Abort(true) - } - // Remove emojis from non-supported terminals - msg = coreutils.RemoveEmojisIfNonSupportedTerminal(msg) - p.newHeadlineBar(msg) -} - -func (p *filesProgressBarManager) ClearHeadlineMsg() { - if p.headlineBar != nil { - p.barsRWMutex.RLock() - p.headlineBar.Abort(true) - p.barsWg.Done() - p.barsRWMutex.RUnlock() - // Wait a refresh rate to make sure the abort has finished - time.Sleep(progressbar.ProgressRefreshRate) - } - p.headlineBar = nil -} - -// IncGeneralProgressTotalBy increments the general progress bar total count by given n. -func (p *filesProgressBarManager) IncGeneralProgressTotalBy(n int64) { - atomic.AddInt64(&p.tasksCount, n) - if p.generalProgressBar != nil { - p.generalProgressBar.SetTotal(p.tasksCount, false) - } -} - -type CommandWithProgress interface { - commands.Command - SetProgress(ioUtils.ProgressMgr) -} - -func ExecWithProgress(cmd CommandWithProgress) (err error) { - // Show log file path on all progress bars except 'setup' command - showLogFilePath := cmd.CommandName() != "setup" - // Init progress bar. - progressBar, err := InitFilesProgressBarIfPossible(showLogFilePath) - if err != nil { - return err - } - if progressBar != nil { - cmd.SetProgress(progressBar) - defer func() { - e := progressBar.Quit() - if err == nil { - err = e - } - }() - } - err = commands.Exec(cmd) - return -} diff --git a/utils/progressbar/filesprogressbar_test.go b/utils/progressbar/filesprogressbar_test.go deleted file mode 100644 index 0f9c6fea3..000000000 --- a/utils/progressbar/filesprogressbar_test.go +++ /dev/null @@ -1,50 +0,0 @@ -package progressbar - -import ( - "github.com/jfrog/jfrog-cli-core/v2/utils/progressbar" - "testing" -) - -func TestBuildProgressDescription(t *testing.T) { - // Set an arbitrary terminal width - terminalWidth = 100 - tests := getTestCases() - for _, test := range tests { - t.Run(test.name, func(t *testing.T) { - desc := buildProgressDescription(test.prefix, test.path, test.extraCharsLen) - - // Validate result - if desc != test.expectedDesc { - t.Errorf("Expected value of: \"%s\", got: \"%s\".", test.expectedDesc, desc) - } - }) - } -} - -func getTestCases() []testCase { - prefix := " downloading" - path := "/a/path/to/a/file" - separator := " | " - - fullDesc := " " + prefix + separator + path + separator - emptyPathDesc := " " + prefix + separator + "..." + separator - shortenedDesc := " " + prefix + separator + "...ggggg/path/to/a/file" + separator - - widthMinusProgress := terminalWidth - progressbar.ProgressBarWidth*2 - return []testCase{ - {"commonUseCase", prefix, path, 17, fullDesc}, - {"zeroExtraChars", prefix, path, 0, fullDesc}, - {"minDescLength", prefix, path, widthMinusProgress - len(emptyPathDesc), emptyPathDesc}, - {"longPath", prefix, "/a/longggggggggggggggggggggg/path/to/a/file", 17, shortenedDesc}, - {"longPrefix", "longggggggggggggggggggggggggg prefix", path, 17, ""}, - {"manyExtraChars", prefix, path, widthMinusProgress - len(emptyPathDesc) + 1, ""}, - } -} - -type testCase struct { - name string - prefix string - path string - extraCharsLen int - expectedDesc string -} diff --git a/utils/progressbar/readerprogressbar.go b/utils/progressbar/readerprogressbar.go deleted file mode 100644 index 0ccef8190..000000000 --- a/utils/progressbar/readerprogressbar.go +++ /dev/null @@ -1,75 +0,0 @@ -package progressbar - -import ( - "io" -) - -type ReaderProgressBar struct { - *progressBarUnit - Id int -} - -// Wraps an io.Reader for bytes reading tracking -type proxyReader struct { - unit *progressBarUnit - io.ReadCloser -} - -// Used to update the progress bar progress. -func (p *ReaderProgressBar) ActionWithProgress(reader io.Reader) (results io.Reader) { - return p.readWithProgress(reader) -} - -// Abort aborts a progress indicator. Called on both successful and unsuccessful operations -func (p *ReaderProgressBar) Abort() { - close(p.incrChannel) - p.bar.Abort(true) -} - -// GetId Returns the ProgressBar ID -// -//nolint:gocritic -func (p *ReaderProgressBar) GetId() (Id int) { - return p.Id -} - -func (p *ReaderProgressBar) getProgressBarUnit() (unit *progressBarUnit) { - return p.progressBarUnit -} - -// Wraps a body of a response (io.Reader) and increments bar accordingly -func (p *ReaderProgressBar) readWithProgress(reader io.Reader) (wrappedReader io.Reader) { - wrappedReader = initProxyReader(p.progressBarUnit, reader) - return wrappedReader -} - -func initProxyReader(unit *progressBarUnit, reader io.Reader) io.ReadCloser { - if reader == nil { - return nil - } - rc, ok := reader.(io.ReadCloser) - if !ok { - rc = io.NopCloser(reader) - } - return &proxyReader{unit, rc} -} - -// Overrides the Read method of the original io.Reader. -func (pr *proxyReader) Read(p []byte) (n int, err error) { - n, err = pr.ReadCloser.Read(p) - if n > 0 && (err == nil || err == io.EOF) { - pr.incrChannel(n) - } - return -} - -func (pr *proxyReader) incrChannel(n int) { - // When an upload / download error occurs (for example, a bad HTTP error code), - // The progress bar's Abort method is invoked and closes the channel. - // Therefore, the channel may be already closed at this stage, which leads to a panic. - // We therefore need to recover if that happens. - defer func() { - _ = recover() - }() - pr.unit.incrChannel <- n -} diff --git a/utils/progressbar/simpleprogressbar.go b/utils/progressbar/simpleprogressbar.go deleted file mode 100644 index a6695acf3..000000000 --- a/utils/progressbar/simpleprogressbar.go +++ /dev/null @@ -1,32 +0,0 @@ -package progressbar - -import ( - "io" -) - -type SimpleProgressBar struct { - *progressBarUnit - Id int -} - -// Used to update the progress bar progress. -func (p *SimpleProgressBar) ActionWithProgress(reader io.Reader) (results io.Reader) { - p.bar.Increment() - return nil -} - -// Abort aborts a progress indicator. Called on both successful and unsuccessful operations -func (p *SimpleProgressBar) Abort() { - p.bar.Abort(true) -} - -// GetId Returns the ProgressBar ID -// -//nolint:gocritic -func (p *SimpleProgressBar) GetId() (Id int) { - return p.Id -} - -func (p *SimpleProgressBar) getProgressBarUnit() (unit *progressBarUnit) { - return p.progressBarUnit -} diff --git a/utils/tests/utils.go b/utils/tests/utils.go index bf276700c..d113ddcff 100644 --- a/utils/tests/utils.go +++ b/utils/tests/utils.go @@ -24,16 +24,16 @@ import ( commandutils "github.com/jfrog/jfrog-cli-core/v2/artifactory/commands/utils" artUtils "github.com/jfrog/jfrog-cli-core/v2/artifactory/utils" "github.com/jfrog/jfrog-cli-core/v2/common/spec" + commonCliUtils "github.com/jfrog/jfrog-cli-core/v2/common/tests" "github.com/jfrog/jfrog-cli-core/v2/utils/config" "github.com/jfrog/jfrog-cli-core/v2/utils/coreutils" corelog "github.com/jfrog/jfrog-cli-core/v2/utils/log" - "github.com/jfrog/jfrog-cli-core/v2/utils/progressbar" + coreTests "github.com/jfrog/jfrog-cli-core/v2/utils/tests" "github.com/jfrog/jfrog-cli/utils/summary" "github.com/jfrog/jfrog-client-go/artifactory/services" "github.com/jfrog/jfrog-client-go/artifactory/services/utils" "github.com/jfrog/jfrog-client-go/auth" clientutils "github.com/jfrog/jfrog-client-go/utils" - "github.com/jfrog/jfrog-client-go/utils/errorutils" "github.com/jfrog/jfrog-client-go/utils/io/fileutils" "github.com/jfrog/jfrog-client-go/utils/log" "github.com/jfrog/jfrog-client-go/utils/tests" @@ -216,83 +216,6 @@ type PackageSearchResultItem struct { Published bool } -type JfrogCli struct { - main func() error - prefix string - credentials string -} - -func NewJfrogCli(mainFunc func() error, prefix, credentials string) *JfrogCli { - return &JfrogCli{mainFunc, prefix, credentials} -} - -func (cli *JfrogCli) SetPrefix(prefix string) *JfrogCli { - cli.prefix = prefix - return cli -} - -func (cli *JfrogCli) Exec(args ...string) error { - spaceSplit := " " - os.Args = strings.Split(cli.prefix, spaceSplit) - output := strings.Split(cli.prefix, spaceSplit) - for _, v := range args { - if v == "" { - continue - } - args := strings.Split(v, spaceSplit) - os.Args = append(os.Args, v) - output = append(output, args...) - } - if cli.credentials != "" { - args := strings.Split(cli.credentials, spaceSplit) - os.Args = append(os.Args, args...) - } - - log.Info("[Command]", strings.Join(output, " ")) - return cli.main() -} - -// Run `jfrog` command, redirect the stdout and return the output -func (cli *JfrogCli) RunCliCmdWithOutput(t *testing.T, args ...string) string { - newStdout, stdWriter, previousStdout := RedirectStdOutToPipe() - previousLog := log.Logger - log.SetLogger(log.NewLogger(corelog.GetCliLogLevel(), nil)) - // Restore previous stdout when the function returns - defer func() { - os.Stdout = previousStdout - log.SetLogger(previousLog) - assert.NoError(t, newStdout.Close()) - }() - go func() { - err := cli.Exec(args...) - assert.NoError(t, err) - // Closing the temp stdout in order to be able to read it's content. - assert.NoError(t, stdWriter.Close()) - }() - content, err := io.ReadAll(newStdout) - assert.NoError(t, err) - log.Debug(string(content)) - return string(content) -} - -func (cli *JfrogCli) LegacyBuildToolExec(args ...string) error { - spaceSplit := " " - os.Args = strings.Split(cli.prefix, spaceSplit) - os.Args = append(os.Args, args...) - - log.Info("[Command]", os.Args) - - if cli.credentials != "" { - args := strings.Split(cli.credentials, spaceSplit) - os.Args = append(os.Args, args...) - } - return cli.main() -} - -func (cli *JfrogCli) WithoutCredentials() *JfrogCli { - return &JfrogCli{cli.main, cli.prefix, ""} -} - func DeleteFiles(deleteSpec *spec.SpecFiles, serverDetails *config.ServerDetails) (successCount, failCount int, err error) { deleteCommand := generic.NewDeleteCommand() deleteCommand.SetThreads(3).SetSpec(deleteSpec).SetServerDetails(serverDetails).SetDryRun(false) @@ -613,33 +536,7 @@ func AddTimestampToGlobalVars() { // path - Path to the input file. // destPath - Path to the output file. If empty, the output file will be under ${CWD}/tmp/. func ReplaceTemplateVariables(path, destPath string) (string, error) { - content, err := os.ReadFile(path) - if err != nil { - return "", errorutils.CheckError(err) - } - - for name, value := range getSubstitutionMap() { - content = bytes.ReplaceAll(content, []byte(name), []byte(value)) - } - if destPath == "" { - destPath, err = os.Getwd() - if err != nil { - return "", errorutils.CheckError(err) - } - destPath = filepath.Join(destPath, Temp) - } - err = os.MkdirAll(destPath, 0700) - if err != nil { - return "", errorutils.CheckError(err) - } - specPath := filepath.Join(destPath, filepath.Base(path)) - log.Info("Creating spec file at:", specPath) - err = os.WriteFile(specPath, content, 0700) - if err != nil { - return "", errorutils.CheckError(err) - } - - return specPath, nil + return commonCliUtils.ReplaceTemplateVariables(path, destPath, getSubstitutionMap()) } func CreateSpec(fileName string) (string, error) { @@ -700,15 +597,6 @@ func CleanUpOldItems(baseItemNames []string, getActualItems func() ([]string, er } } -// Redirect stdout to new temp, os.pipe -// Caller is responsible to close the pipe and to set the old stdout back. -func RedirectStdOutToPipe() (reader *os.File, writer *os.File, previousStdout *os.File) { - previousStdout = os.Stdout - reader, writer, _ = os.Pipe() - os.Stdout = writer - return -} - // Set new logger with output redirection to a null logger. This is useful for negative tests. // Caller is responsible to set the old log back. func RedirectLogOutputToNil() (previousLog log.Log) { @@ -720,21 +608,10 @@ func RedirectLogOutputToNil() (previousLog log.Log) { return previousLog } -// Set progressbar.ShouldInitProgressBar func to always return true -// so the progress bar library will be initialized and progress will be displayed. -// The returned callback sets the original func back. -func MockProgressInitialization() func() { - originFunc := progressbar.ShouldInitProgressBar - progressbar.ShouldInitProgressBar = func() (bool, error) { return true, nil } - return func() { - progressbar.ShouldInitProgressBar = originFunc - } -} - // Redirect output to a file, execute the command and read output. // The reason for redirecting to a file and not to a buffer is the limited // size of the buffer while using os.Pipe. -func GetCmdOutput(t *testing.T, jfrogCli *JfrogCli, cmd ...string) ([]byte, error) { +func GetCmdOutput(t *testing.T, jfrogCli *coreTests.JfrogCli, cmd ...string) ([]byte, error) { oldStdout := os.Stdout temp, err := os.CreateTemp("", "output") assert.NoError(t, err) diff --git a/xray/cli.go b/xray/cli.go deleted file mode 100644 index cb766bd7c..000000000 --- a/xray/cli.go +++ /dev/null @@ -1,222 +0,0 @@ -package xray - -import ( - "time" - - "github.com/jfrog/jfrog-cli-core/v2/utils/coreutils" - - corecommon "github.com/jfrog/jfrog-cli-core/v2/common/commands" - corecommondocs "github.com/jfrog/jfrog-cli-core/v2/docs/common" - "github.com/jfrog/jfrog-cli-core/v2/xray/commands/curl" - "github.com/jfrog/jfrog-cli-core/v2/xray/commands/offlineupdate" - "github.com/jfrog/jfrog-cli/docs/common" - auditgodocs "github.com/jfrog/jfrog-cli/docs/xray/auditgo" - "github.com/jfrog/jfrog-cli/docs/xray/auditgradle" - "github.com/jfrog/jfrog-cli/docs/xray/auditmvn" - auditnpmdocs "github.com/jfrog/jfrog-cli/docs/xray/auditnpm" - auditpipdocs "github.com/jfrog/jfrog-cli/docs/xray/auditpip" - curldocs "github.com/jfrog/jfrog-cli/docs/xray/curl" - offlineupdatedocs "github.com/jfrog/jfrog-cli/docs/xray/offlineupdate" - scandocs "github.com/jfrog/jfrog-cli/docs/xray/scan" - "github.com/jfrog/jfrog-cli/scan" - "github.com/jfrog/jfrog-cli/utils/cliutils" - "github.com/jfrog/jfrog-client-go/utils/errorutils" - "github.com/urfave/cli" -) - -const DateFormat = "2006-01-02" - -func GetCommands() []cli.Command { - return cliutils.GetSortedCommands(cli.CommandsByName{ - { - Name: "curl", - Flags: cliutils.GetCommandFlags(cliutils.XrCurl), - Aliases: []string{"cl"}, - Usage: curldocs.GetDescription(), - HelpName: corecommondocs.CreateUsage("xr curl", curldocs.GetDescription(), curldocs.Usage), - UsageText: curldocs.GetArguments(), - ArgsUsage: common.CreateEnvVars(), - BashComplete: corecommondocs.CreateBashCompletionFunc(), - SkipFlagParsing: true, - Action: curlCmd, - }, - { - Name: "audit-mvn", - Flags: cliutils.GetCommandFlags(cliutils.AuditMvn), - Aliases: []string{"am"}, - Usage: auditmvn.GetDescription(), - HelpName: corecommondocs.CreateUsage("xr audit-mvn", auditmvn.GetDescription(), auditmvn.Usage), - ArgsUsage: common.CreateEnvVars(), - BashComplete: corecommondocs.CreateBashCompletionFunc(), - Action: func(c *cli.Context) error { - return scan.AuditSpecificCmd(c, coreutils.Maven) - }, - }, - { - Name: "audit-gradle", - Flags: cliutils.GetCommandFlags(cliutils.AuditGradle), - Aliases: []string{"ag"}, - Usage: auditgradle.GetDescription(), - HelpName: corecommondocs.CreateUsage("xr audit-gradle", auditgradle.GetDescription(), auditgradle.Usage), - ArgsUsage: common.CreateEnvVars(), - BashComplete: corecommondocs.CreateBashCompletionFunc(), - Action: func(c *cli.Context) error { - return scan.AuditSpecificCmd(c, coreutils.Gradle) - }, - }, - { - Name: "audit-npm", - Flags: cliutils.GetCommandFlags(cliutils.AuditNpm), - Aliases: []string{"an"}, - Usage: auditnpmdocs.GetDescription(), - HelpName: corecommondocs.CreateUsage("xr audit-npm", auditnpmdocs.GetDescription(), auditnpmdocs.Usage), - ArgsUsage: common.CreateEnvVars(), - BashComplete: corecommondocs.CreateBashCompletionFunc(), - Action: func(c *cli.Context) error { - return scan.AuditSpecificCmd(c, coreutils.Npm) - }, - }, - { - Name: "audit-go", - Flags: cliutils.GetCommandFlags(cliutils.AuditGo), - Aliases: []string{"ago"}, - Usage: auditgodocs.GetDescription(), - HelpName: corecommondocs.CreateUsage("xr audit-go", auditgodocs.GetDescription(), auditgodocs.Usage), - ArgsUsage: common.CreateEnvVars(), - BashComplete: corecommondocs.CreateBashCompletionFunc(), - Action: func(c *cli.Context) error { - return scan.AuditSpecificCmd(c, coreutils.Go) - }, - }, - { - Name: "audit-pip", - Flags: cliutils.GetCommandFlags(cliutils.AuditPip), - Aliases: []string{"ap"}, - Usage: auditpipdocs.GetDescription(), - HelpName: corecommondocs.CreateUsage("xr audit-pip", auditpipdocs.GetDescription(), auditpipdocs.Usage), - ArgsUsage: common.CreateEnvVars(), - BashComplete: corecommondocs.CreateBashCompletionFunc(), - Action: func(c *cli.Context) error { - return scan.AuditSpecificCmd(c, coreutils.Pip) - }, - }, - { - Name: "scan", - Flags: cliutils.GetCommandFlags(cliutils.XrScan), - Aliases: []string{"s"}, - Usage: scandocs.GetDescription(), - UsageText: scandocs.GetArguments(), - HelpName: corecommondocs.CreateUsage("xr scan", scandocs.GetDescription(), scandocs.Usage), - ArgsUsage: common.CreateEnvVars(), - BashComplete: corecommondocs.CreateBashCompletionFunc(), - Action: func(c *cli.Context) error { - return cliutils.RunCmdWithDeprecationWarning("scan", "xr", c, scan.ScanCmd) - }, - }, - { - Name: "offline-update", - Usage: offlineupdatedocs.GetDescription(), - HelpName: corecommondocs.CreateUsage("xr offline-update", offlineupdatedocs.GetDescription(), offlineupdatedocs.Usage), - ArgsUsage: common.CreateEnvVars(), - Flags: cliutils.GetCommandFlags(cliutils.OfflineUpdate), - Aliases: []string{"ou"}, - BashComplete: corecommondocs.CreateBashCompletionFunc(), - Action: offlineUpdates, - }, - }) -} - -func getOfflineUpdatesFlag(c *cli.Context) (flags *offlineupdate.OfflineUpdatesFlags, err error) { - flags = new(offlineupdate.OfflineUpdatesFlags) - flags.Version = c.String("version") - flags.License = c.String("license-id") - flags.Target = c.String("target") - if len(flags.License) < 1 { - return nil, errorutils.CheckErrorf("the --license-id option is mandatory") - } - // Handle V3 flags - stream := c.String(cliutils.Stream) - flags.IsPeriodicUpdate = c.Bool(cliutils.Periodic) - // If a 'stream' flag was provided - validate its value and return. - if stream != "" { - flags.Stream, err = validateStream(stream) - return - } - if flags.IsPeriodicUpdate { - return nil, errorutils.CheckErrorf("the %s option is only valid with %s", cliutils.Periodic, cliutils.Stream) - } - // Handle V1 flags - from := c.String("from") - to := c.String("to") - if len(to) > 0 && len(from) < 1 { - return nil, errorutils.CheckErrorf("the --from option is mandatory, when the --to option is sent") - } - if len(from) > 0 && len(to) < 1 { - return nil, errorutils.CheckErrorf("the --to option is mandatory, when the --from option is sent") - } - if len(from) > 0 && len(to) > 0 { - flags.From, err = dateToMilliseconds(from) - err = errorutils.CheckError(err) - if err != nil { - return - } - flags.To, err = dateToMilliseconds(to) - err = errorutils.CheckError(err) - } - return -} - -// Verify that the given string is a valid optional stream. -func validateStream(stream string) (string, error) { - streams := offlineupdate.NewValidStreams() - if streams.StreamsMap[stream] { - return stream, nil - } - return "", errorutils.CheckErrorf("Invalid stream type: %s, Possible values are: %v", stream, streams.GetValidStreamsString()) -} - -func dateToMilliseconds(date string) (dateInMillisecond int64, err error) { - t, err := time.Parse(DateFormat, date) - if errorutils.CheckError(err) != nil { - return - } - dateInMillisecond = t.UnixNano() / (int64(time.Millisecond) / int64(time.Nanosecond)) - return -} - -func offlineUpdates(c *cli.Context) error { - offlineUpdateFlags, err := getOfflineUpdatesFlag(c) - if err != nil { - return err - } - return offlineupdate.OfflineUpdate(offlineUpdateFlags) -} - -func curlCmd(c *cli.Context) error { - if show, err := cliutils.ShowCmdHelpIfNeeded(c, c.Args()); show || err != nil { - return err - } - if c.NArg() < 1 { - return cliutils.WrongNumberOfArgumentsHandler(c) - } - xrCurlCmd, err := newXrCurlCommand(c) - if err != nil { - return err - } - return corecommon.Exec(xrCurlCmd) -} - -func newXrCurlCommand(c *cli.Context) (*curl.XrCurlCommand, error) { - curlCommand := corecommon.NewCurlCommand().SetArguments(cliutils.ExtractCommand(c)) - xrCurlCommand := curl.NewXrCurlCommand(*curlCommand) - xrDetails, err := xrCurlCommand.GetServerDetails() - if err != nil { - return nil, err - } - if xrDetails.XrayUrl == "" { - return nil, errorutils.CheckErrorf("No Xray servers configured. Use the 'jf c add' command to set the Xray server details.") - } - xrCurlCommand.SetServerDetails(xrDetails) - xrCurlCommand.SetUrl(xrDetails.XrayUrl) - return xrCurlCommand, err -} diff --git a/xray/cli_test.go b/xray/cli_test.go deleted file mode 100644 index c88f2e21b..000000000 --- a/xray/cli_test.go +++ /dev/null @@ -1,39 +0,0 @@ -package xray - -import ( - "github.com/jfrog/jfrog-cli-core/v2/xray/commands/offlineupdate" - "reflect" - "testing" -) - -func TestValidateStream(t *testing.T) { - streams := offlineupdate.NewValidStreams() - type args struct { - streams string - } - tests := []struct { - name string - args args - want string - wantErr bool - }{ - {"empty array", args{streams: ""}, "", true}, - {"PublicData", args{streams: streams.GetPublicDataStream()}, streams.GetPublicDataStream(), false}, - {"ContextualAnalysis", args{streams: streams.GetContextualAnalysisStream()}, streams.GetContextualAnalysisStream(), false}, - {"Exposures", args{streams: streams.GetExposuresStream()}, streams.GetExposuresStream(), false}, - {"invalid elements", args{streams: "bad_stream"}, "", true}, - {"array", args{streams: streams.GetPublicDataStream() + ";" + streams.GetContextualAnalysisStream()}, "", true}, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - got, err := validateStream(tt.args.streams) - if (err != nil) != tt.wantErr { - t.Errorf("validateStream() error = %v, wantErr %v", err, tt.wantErr) - return - } - if !reflect.DeepEqual(got, tt.want) { - t.Errorf("validateStream() got = %v, want %v", got, tt.want) - } - }) - } -} diff --git a/xray_test.go b/xray_test.go deleted file mode 100644 index 0581b383c..000000000 --- a/xray_test.go +++ /dev/null @@ -1,1126 +0,0 @@ -package main - -import ( - "encoding/json" - "errors" - "flag" - "fmt" - "net/http" - "net/http/httptest" - "os" - "os/exec" - "path" - "path/filepath" - "strconv" - "strings" - "sync" - "testing" - "time" - - biutils "github.com/jfrog/build-info-go/utils" - "github.com/jfrog/jfrog-cli-core/v2/xray/scangraph" - - "github.com/jfrog/gofrog/version" - coreContainer "github.com/jfrog/jfrog-cli-core/v2/artifactory/commands/container" - "github.com/jfrog/jfrog-cli-core/v2/artifactory/utils/container" - "github.com/jfrog/jfrog-cli-core/v2/common/build" - coreCmd "github.com/jfrog/jfrog-cli-core/v2/common/commands" - "github.com/jfrog/jfrog-cli-core/v2/common/format" - "github.com/jfrog/jfrog-cli-core/v2/common/project" - commontests "github.com/jfrog/jfrog-cli-core/v2/common/tests" - "github.com/jfrog/jfrog-cli-core/v2/utils/config" - "github.com/jfrog/jfrog-cli-core/v2/utils/coreutils" - "github.com/jfrog/jfrog-cli-core/v2/utils/dependencies" - coretests "github.com/jfrog/jfrog-cli-core/v2/utils/tests" - coreCuration "github.com/jfrog/jfrog-cli-core/v2/xray/commands/curation" - "github.com/jfrog/jfrog-cli-core/v2/xray/commands/scan" - "github.com/jfrog/jfrog-cli-core/v2/xray/formats" - "github.com/jfrog/jfrog-cli-core/v2/xray/utils" - "github.com/jfrog/jfrog-cli/inttestutils" - "github.com/jfrog/jfrog-cli/utils/cliutils" - "github.com/jfrog/jfrog-cli/utils/tests" - "github.com/jfrog/jfrog-client-go/auth" - clientUtils "github.com/jfrog/jfrog-client-go/utils" - "github.com/jfrog/jfrog-client-go/utils/io/fileutils" - clientTestUtils "github.com/jfrog/jfrog-client-go/utils/tests" - "github.com/jfrog/jfrog-client-go/xray/services" - xrayUtils "github.com/jfrog/jfrog-client-go/xray/services/utils" - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" - "github.com/urfave/cli" -) - -const ( - jvmLaunchEnvVar = "MAVEN_OPTS" - mavenCacheRedirectionVal = "-Dmaven.repo.local=" - goCacheEnvVar = "GOMODCACHE" - pipCacheEnvVar = "PIP_CACHE_DIR" -) - -var ( - xrayDetails *config.ServerDetails - xrayAuth auth.ServiceDetails - // JFrog CLI for Xray commands - xrayCli *tests.JfrogCli -) - -func InitXrayTests() { - initXrayCli() - initArtifactoryCli() - cleanUpOldRepositories() - tests.AddTimestampToGlobalVars() - createRequiredRepos() -} - -func CleanXrayTests() { - deleteCreatedRepos() -} - -func authenticateXray() string { - *tests.JfrogUrl = clientUtils.AddTrailingSlashIfNeeded(*tests.JfrogUrl) - xrayDetails = &config.ServerDetails{XrayUrl: *tests.JfrogUrl + tests.XrayEndpoint} - cred := fmt.Sprintf("--url=%s", xrayDetails.XrayUrl) - if *tests.JfrogAccessToken != "" { - xrayDetails.AccessToken = *tests.JfrogAccessToken - cred += fmt.Sprintf(" --access-token=%s", xrayDetails.AccessToken) - } else { - xrayDetails.User = *tests.JfrogUser - xrayDetails.Password = *tests.JfrogPassword - cred += fmt.Sprintf(" --user=%s --password=%s", xrayDetails.User, xrayDetails.Password) - } - - var err error - if xrayAuth, err = xrayDetails.CreateXrayAuthConfig(); err != nil { - coreutils.ExitOnErr(errors.New("Failed while attempting to authenticate with Xray: " + err.Error())) - } - xrayDetails.XrayUrl = xrayAuth.GetUrl() - return cred -} - -func initXrayCli() { - if xrayCli != nil { - return - } - cred := authenticateXray() - xrayCli = tests.NewJfrogCli(execMain, "jfrog", cred) -} - -// Tests basic binary scan by providing pattern (path to testdata binaries) and --licenses flag -// and asserts any error. -func TestXrayBinaryScanJson(t *testing.T) { - output := testXrayBinaryScan(t, string(format.Json)) - verifyJsonScanResults(t, output, 0, 1, 1) -} - -func TestXrayBinaryScanSimpleJson(t *testing.T) { - output := testXrayBinaryScan(t, string(format.SimpleJson)) - verifySimpleJsonScanResults(t, output, 1, 1) -} - -func TestXrayBinaryScanJsonWithProgress(t *testing.T) { - callback := tests.MockProgressInitialization() - defer callback() - output := testXrayBinaryScan(t, string(format.Json)) - verifyJsonScanResults(t, output, 0, 1, 1) -} - -func TestXrayBinaryScanSimpleJsonWithProgress(t *testing.T) { - callback := tests.MockProgressInitialization() - defer callback() - output := testXrayBinaryScan(t, string(format.SimpleJson)) - verifySimpleJsonScanResults(t, output, 1, 1) -} - -func testXrayBinaryScan(t *testing.T, format string) string { - initXrayTest(t, scangraph.GraphScanMinXrayVersion) - binariesPath := filepath.Join(filepath.FromSlash(tests.GetTestResourcesPath()), "xray", "binaries", "*") - return xrayCli.RunCliCmdWithOutput(t, "scan", binariesPath, "--licenses", "--format="+format) -} - -func TestXrayBinaryScanWithBypassArchiveLimits(t *testing.T) { - initXrayTest(t, scan.BypassArchiveLimitsMinXrayVersion) - unsetEnv := clientTestUtils.SetEnvWithCallbackAndAssert(t, "JF_INDEXER_COMPRESS_MAXENTITIES", "10") - defer unsetEnv() - binariesPath := filepath.Join(filepath.FromSlash(tests.GetTestResourcesPath()), "xray", "binaries", "*") - scanArgs := []string{"scan", binariesPath, "--format=json", "--licenses"} - // Run without bypass flag and expect scan to fail - err := xrayCli.Exec(scanArgs...) - // Expect error - assert.Error(t, err) - - // Run with bypass flag and expect it to find vulnerabilities - scanArgs = append(scanArgs, "--bypass-archive-limits") - output := xrayCli.RunCliCmdWithOutput(t, scanArgs...) - verifyJsonScanResults(t, output, 0, 1, 1) -} - -// Tests npm audit by providing simple npm project and asserts any error. -func TestXrayAuditNpmJson(t *testing.T) { - output := testXrayAuditNpm(t, string(format.Json)) - verifyJsonScanResults(t, output, 0, 1, 1) -} - -func TestXrayAuditNpmSimpleJson(t *testing.T) { - output := testXrayAuditNpm(t, string(format.SimpleJson)) - verifySimpleJsonScanResults(t, output, 1, 1) -} - -func testXrayAuditNpm(t *testing.T, format string) string { - initXrayTest(t, scangraph.GraphScanMinXrayVersion) - tempDirPath, createTempDirCallback := coretests.CreateTempDirWithCallbackAndAssert(t) - defer createTempDirCallback() - npmProjectPath := filepath.Join(filepath.FromSlash(tests.GetTestResourcesPath()), "xray", "npm") - // Copy the npm project from the testdata to a temp dir - assert.NoError(t, biutils.CopyDir(npmProjectPath, tempDirPath, true, nil)) - prevWd := changeWD(t, tempDirPath) - defer clientTestUtils.ChangeDirAndAssert(t, prevWd) - // Run npm install before executing jfrog xr npm-audit - assert.NoError(t, exec.Command("npm", "install").Run()) - // Add dummy descriptor file to check that we run only specific audit - addDummyPackageDescriptor(t, true) - return xrayCli.RunCliCmdWithOutput(t, "audit", "--npm", "--licenses", "--format="+format) -} - -func TestXrayAuditYarnV2Json(t *testing.T) { - testXrayAuditYarn(t, "yarn-v2", func() { - output := runXrayAuditYarnWithOutput(t, string(format.Json)) - verifyJsonScanResults(t, output, 0, 1, 1) - }) -} - -func TestXrayAuditYarnV2SimpleJson(t *testing.T) { - testXrayAuditYarn(t, "yarn-v2", func() { - output := runXrayAuditYarnWithOutput(t, string(format.SimpleJson)) - verifySimpleJsonScanResults(t, output, 1, 1) - }) -} - -func TestXrayAuditYarnV1Json(t *testing.T) { - testXrayAuditYarn(t, "yarn-v1", func() { - output := runXrayAuditYarnWithOutput(t, string(format.Json)) - verifyJsonScanResults(t, output, 0, 1, 1) - }) -} - -func TestXrayAuditYarnV1JsonWithoutDevDependencies(t *testing.T) { - unsetEnv := clientTestUtils.SetEnvWithCallbackAndAssert(t, "NODE_ENV", "production") - defer unsetEnv() - testXrayAuditYarn(t, "yarn-v1", func() { - output := runXrayAuditYarnWithOutput(t, string(format.Json)) - var results []services.ScanResponse - err := json.Unmarshal([]byte(output), &results) - assert.NoError(t, err) - assert.Len(t, results[0].Vulnerabilities, 0) - }) -} - -func TestXrayAuditYarnV1SimpleJson(t *testing.T) { - testXrayAuditYarn(t, "yarn-v1", func() { - output := runXrayAuditYarnWithOutput(t, string(format.SimpleJson)) - verifySimpleJsonScanResults(t, output, 1, 1) - }) -} - -func testXrayAuditYarn(t *testing.T, projectDirName string, yarnCmd func()) { - initXrayTest(t, scangraph.GraphScanMinXrayVersion) - tempDirPath, createTempDirCallback := coretests.CreateTempDirWithCallbackAndAssert(t) - defer createTempDirCallback() - yarnProjectPath := filepath.Join(filepath.FromSlash(tests.GetTestResourcesPath()), "xray", projectDirName) - // Copy the Yarn project from the testdata to a temp directory - assert.NoError(t, biutils.CopyDir(yarnProjectPath, tempDirPath, true, nil)) - prevWd := changeWD(t, tempDirPath) - defer clientTestUtils.ChangeDirAndAssert(t, prevWd) - // Run yarn install before executing jf audit --yarn. Return error to assert according to test. - assert.NoError(t, exec.Command("yarn").Run()) - // Add dummy descriptor file to check that we run only specific audit - addDummyPackageDescriptor(t, true) - yarnCmd() -} - -func runXrayAuditYarnWithOutput(t *testing.T, format string) string { - return xrayCli.RunCliCmdWithOutput(t, "audit", "--yarn", "--licenses", "--format="+format) -} - -// Tests NuGet audit by providing simple NuGet project + multi-project NuGet project and asserts any error. -func TestXrayAuditNugetJson(t *testing.T) { - var testdata = []struct { - projectName string - format string - restoreTech string - minVulnerabilities int - minLicences int - }{ - { - projectName: "single4.0", - format: string(format.Json), - restoreTech: "nuget", - minVulnerabilities: 2, - minLicences: 0, - }, - { - projectName: "single5.0", - format: string(format.Json), - restoreTech: "dotnet", - minVulnerabilities: 3, - minLicences: 2, - }, - { - projectName: "single5.0", - format: string(format.Json), - restoreTech: "", - minVulnerabilities: 3, - minLicences: 2, - }, - { - projectName: "multi", - format: string(format.Json), - restoreTech: "dotnet", - minVulnerabilities: 4, - minLicences: 3, - }, - { - projectName: "multi", - format: string(format.Json), - restoreTech: "", - minVulnerabilities: 4, - minLicences: 3, - }, - } - for _, test := range testdata { - runInstallCommand := test.restoreTech != "" - t.Run(fmt.Sprintf("projectName:%s,runInstallCommand:%t", test.projectName, runInstallCommand), - func(t *testing.T) { - output := testXrayAuditNuget(t, test.projectName, test.format, test.restoreTech) - verifyJsonScanResults(t, output, 0, test.minVulnerabilities, test.minLicences) - }) - } -} - -func TestXrayAuditNugetSimpleJson(t *testing.T) { - var testdata = []struct { - projectName string - format string - restoreTech string - minVulnerabilities int - minLicences int - }{ - { - projectName: "single4.0", - format: string(format.SimpleJson), - restoreTech: "nuget", - minVulnerabilities: 2, - minLicences: 0, - }, - { - projectName: "single5.0", - format: string(format.SimpleJson), - restoreTech: "dotnet", - minVulnerabilities: 3, - minLicences: 2, - }, - { - projectName: "single5.0", - format: string(format.SimpleJson), - restoreTech: "", - minVulnerabilities: 3, - minLicences: 2, - }, - } - for _, test := range testdata { - runInstallCommand := test.restoreTech != "" - t.Run(fmt.Sprintf("projectName:%s,runInstallCommand:%t", test.projectName, runInstallCommand), - func(t *testing.T) { - output := testXrayAuditNuget(t, test.projectName, test.format, test.restoreTech) - verifySimpleJsonScanResults(t, output, test.minVulnerabilities, test.minLicences) - }) - } -} - -func testXrayAuditNuget(t *testing.T, projectName, format string, restoreTech string) string { - initXrayTest(t, scangraph.GraphScanMinXrayVersion) - tempDirPath, createTempDirCallback := coretests.CreateTempDirWithCallbackAndAssert(t) - defer createTempDirCallback() - projectPath := filepath.Join(filepath.FromSlash(tests.GetTestResourcesPath()), "xray", "nuget", projectName) - - assert.NoError(t, biutils.CopyDir(projectPath, tempDirPath, true, nil)) - prevWd := changeWD(t, tempDirPath) - defer clientTestUtils.ChangeDirAndAssert(t, prevWd) - // Add dummy descriptor file to check that we run only specific audit - addDummyPackageDescriptor(t, false) - // Run NuGet/Dotnet restore before executing jfrog xr audit (NuGet) - if restoreTech != "" { - _, err := exec.Command(restoreTech, "restore").CombinedOutput() - assert.NoError(t, err) - } - return xrayCli.RunCliCmdWithOutput(t, "audit", "--nuget", "--format="+format, "--licenses") -} - -func TestXrayAuditGradleJson(t *testing.T) { - output := testXrayAuditGradle(t, string(format.Json)) - verifyJsonScanResults(t, output, 0, 3, 3) -} - -func TestXrayAuditGradleSimpleJson(t *testing.T) { - output := testXrayAuditGradle(t, string(format.SimpleJson)) - verifySimpleJsonScanResults(t, output, 3, 3) -} - -func testXrayAuditGradle(t *testing.T, format string) string { - initXrayTest(t, scangraph.GraphScanMinXrayVersion) - tempDirPath, createTempDirCallback := coretests.CreateTempDirWithCallbackAndAssert(t) - defer createTempDirCallback() - gradleProjectPath := filepath.Join(filepath.FromSlash(tests.GetTestResourcesPath()), "xray", "gradle") - // Copy the gradle project from the testdata to a temp dir - assert.NoError(t, biutils.CopyDir(gradleProjectPath, tempDirPath, true, nil)) - prevWd := changeWD(t, tempDirPath) - defer clientTestUtils.ChangeDirAndAssert(t, prevWd) - // Add dummy descriptor file to check that we run only specific audit - addDummyPackageDescriptor(t, false) - return xrayCli.RunCliCmdWithOutput(t, "audit", "--gradle", "--licenses", "--format="+format) -} - -func TestXrayAuditMavenJson(t *testing.T) { - output := testXrayAuditMaven(t, string(format.Json)) - verifyJsonScanResults(t, output, 0, 1, 1) -} - -func TestXrayAuditMavenSimpleJson(t *testing.T) { - output := testXrayAuditMaven(t, string(format.SimpleJson)) - verifySimpleJsonScanResults(t, output, 1, 1) -} - -func testXrayAuditMaven(t *testing.T, format string) string { - initXrayTest(t, scangraph.GraphScanMinXrayVersion) - tempDirPath, createTempDirCallback := coretests.CreateTempDirWithCallbackAndAssert(t) - defer createTempDirCallback() - mvnProjectPath := filepath.Join(filepath.FromSlash(tests.GetTestResourcesPath()), "xray", "maven") - // Copy the maven project from the testdata to a temp dir - assert.NoError(t, biutils.CopyDir(mvnProjectPath, tempDirPath, true, nil)) - prevWd := changeWD(t, tempDirPath) - defer clientTestUtils.ChangeDirAndAssert(t, prevWd) - // Add dummy descriptor file to check that we run only specific audit - addDummyPackageDescriptor(t, false) - return xrayCli.RunCliCmdWithOutput(t, "audit", "--mvn", "--licenses", "--format="+format) -} - -func TestXrayAuditNoTech(t *testing.T) { - initXrayTest(t, scangraph.GraphScanMinXrayVersion) - tempDirPath, createTempDirCallback := coretests.CreateTempDirWithCallbackAndAssert(t) - defer createTempDirCallback() - prevWd := changeWD(t, tempDirPath) - defer clientTestUtils.ChangeDirAndAssert(t, prevWd) - // Run audit on empty folder, expect an error - err := xrayCli.Exec("audit") - assert.NoError(t, err) -} - -func TestXrayAuditDetectTech(t *testing.T) { - initXrayTest(t, scangraph.GraphScanMinXrayVersion) - tempDirPath, createTempDirCallback := coretests.CreateTempDirWithCallbackAndAssert(t) - defer createTempDirCallback() - mvnProjectPath := filepath.Join(filepath.FromSlash(tests.GetTestResourcesPath()), "xray", "maven") - // Copy the maven project from the testdata to a temp dir - assert.NoError(t, biutils.CopyDir(mvnProjectPath, tempDirPath, true, nil)) - prevWd := changeWD(t, tempDirPath) - defer clientTestUtils.ChangeDirAndAssert(t, prevWd) - // Run generic audit on mvn project with a vulnerable dependency - output := xrayCli.RunCliCmdWithOutput(t, "audit", "--licenses", "--format="+string(format.SimpleJson)) - var results formats.SimpleJsonResults - err := json.Unmarshal([]byte(output), &results) - assert.NoError(t, err) - // Expects the ImpactedPackageType of the known vulnerability to be maven - assert.Equal(t, strings.ToLower(results.Vulnerabilities[0].ImpactedDependencyType), "maven") -} - -func TestXrayAuditMultiProjects(t *testing.T) { - initXrayTest(t, scangraph.GraphScanMinXrayVersion) - tempDirPath, createTempDirCallback := coretests.CreateTempDirWithCallbackAndAssert(t) - defer createTempDirCallback() - multiProject := filepath.Join(filepath.FromSlash(tests.GetTestResourcesPath()), "xray") - // Copy the multi project from the testdata to a temp dir - assert.NoError(t, biutils.CopyDir(multiProject, tempDirPath, true, nil)) - prevWd := changeWD(t, tempDirPath) - defer clientTestUtils.ChangeDirAndAssert(t, prevWd) - workingDirsFlag := fmt.Sprintf("--working-dirs=%s, %s ,%s, %s", - filepath.Join(tempDirPath, "maven"), filepath.Join(tempDirPath, "nuget", "single4.0"), - filepath.Join(tempDirPath, "python", "pip"), filepath.Join(tempDirPath, "jas-test")) - // Configure a new server named "default" - createJfrogHomeConfig(t, true) - defer cleanTestsHomeEnv() - output := xrayCli.WithoutCredentials().RunCliCmdWithOutput(t, "audit", "--format="+string(format.SimpleJson), workingDirsFlag) - verifySimpleJsonScanResults(t, output, 35, 0) - verifySimpleJsonJasResults(t, output, 1, 9, 7, 3) -} - -func TestXrayAuditPipJson(t *testing.T) { - output := testXrayAuditPip(t, string(format.Json), "") - verifyJsonScanResults(t, output, 0, 3, 1) -} - -func TestXrayAuditPipSimpleJson(t *testing.T) { - output := testXrayAuditPip(t, string(format.SimpleJson), "") - verifySimpleJsonScanResults(t, output, 3, 1) -} - -func TestXrayAuditPipJsonWithRequirementsFile(t *testing.T) { - output := testXrayAuditPip(t, string(format.Json), "requirements.txt") - verifyJsonScanResults(t, output, 0, 2, 0) -} - -func TestXrayAuditPipSimpleJsonWithRequirementsFile(t *testing.T) { - output := testXrayAuditPip(t, string(format.SimpleJson), "requirements.txt") - verifySimpleJsonScanResults(t, output, 2, 0) -} - -func testXrayAuditPip(t *testing.T, format, requirementsFile string) string { - initXrayTest(t, scangraph.GraphScanMinXrayVersion) - tempDirPath, createTempDirCallback := coretests.CreateTempDirWithCallbackAndAssert(t) - defer createTempDirCallback() - pipProjectPath := filepath.Join(filepath.FromSlash(tests.GetTestResourcesPath()), "xray", "python", "pip") - // Copy the pip project from the testdata to a temp dir - assert.NoError(t, biutils.CopyDir(pipProjectPath, tempDirPath, true, nil)) - prevWd := changeWD(t, tempDirPath) - defer clientTestUtils.ChangeDirAndAssert(t, prevWd) - // Add dummy descriptor file to check that we run only specific audit - addDummyPackageDescriptor(t, false) - args := []string{"audit", "--pip", "--licenses", "--format=" + format} - if requirementsFile != "" { - args = append(args, "--requirements-file="+requirementsFile) - - } - return xrayCli.RunCliCmdWithOutput(t, args...) -} - -func TestXrayAuditPipenvJson(t *testing.T) { - output := testXrayAuditPipenv(t, string(format.Json)) - verifyJsonScanResults(t, output, 0, 3, 1) -} - -func TestXrayAuditPipenvSimpleJson(t *testing.T) { - output := testXrayAuditPipenv(t, string(format.SimpleJson)) - verifySimpleJsonScanResults(t, output, 3, 1) -} - -func testXrayAuditPipenv(t *testing.T, format string) string { - initXrayTest(t, scangraph.GraphScanMinXrayVersion) - tempDirPath, createTempDirCallback := coretests.CreateTempDirWithCallbackAndAssert(t) - defer createTempDirCallback() - pipenvProjectPath := filepath.Join(filepath.FromSlash(tests.GetTestResourcesPath()), "xray", "python", "pipenv") - // Copy the pipenv project from the testdata to a temp dir - assert.NoError(t, biutils.CopyDir(pipenvProjectPath, tempDirPath, true, nil)) - prevWd := changeWD(t, tempDirPath) - defer clientTestUtils.ChangeDirAndAssert(t, prevWd) - // Add dummy descriptor file to check that we run only specific audit - addDummyPackageDescriptor(t, false) - return xrayCli.RunCliCmdWithOutput(t, "audit", "--pipenv", "--licenses", "--format="+format) -} - -func TestDownloadAnalyzerManagerIfNeeded(t *testing.T) { - initXrayTest(t, "") - - // Configure a new JFrog CLI home dir. - tempDirPath, createTempDirCallback := coretests.CreateTempDirWithCallbackAndAssert(t) - defer createTempDirCallback() - setEnvCallBack := clientTestUtils.SetEnvWithCallbackAndAssert(t, coreutils.HomeDir, tempDirPath) - defer setEnvCallBack() - - // Download - err := dependencies.DownloadAnalyzerManagerIfNeeded() - assert.NoError(t, err) - - // Validate Analyzer manager app & checksum.sh2 file exist - path, err := utils.GetAnalyzerManagerDirAbsolutePath() - assert.NoError(t, err) - amPath := filepath.Join(path, utils.GetAnalyzerManagerExecutableName()) - exists, err := fileutils.IsFileExists(amPath, false) - assert.NoError(t, err) - assert.True(t, exists) - checksumPath := filepath.Join(path, dependencies.ChecksumFileName) - exists, err = fileutils.IsFileExists(checksumPath, false) - assert.NoError(t, err) - assert.True(t, exists) - checksumFileStat, err := os.Stat(checksumPath) - assert.NoError(t, err) - assert.True(t, checksumFileStat.Size() > 0) - - // Validate no second download occurred - firstFileStat, err := os.Stat(amPath) - assert.NoError(t, err) - err = dependencies.DownloadAnalyzerManagerIfNeeded() - assert.NoError(t, err) - secondFileStat, err := os.Stat(amPath) - assert.NoError(t, err) - assert.Equal(t, firstFileStat.ModTime(), secondFileStat.ModTime()) -} - -func TestXrayAuditPoetryJson(t *testing.T) { - output := testXrayAuditPoetry(t, string(format.Json)) - verifyJsonScanResults(t, output, 0, 3, 1) -} - -func TestXrayAuditPoetrySimpleJson(t *testing.T) { - output := testXrayAuditPoetry(t, string(format.SimpleJson)) - verifySimpleJsonScanResults(t, output, 3, 1) -} - -func testXrayAuditPoetry(t *testing.T, format string) string { - initXrayTest(t, scangraph.GraphScanMinXrayVersion) - tempDirPath, createTempDirCallback := coretests.CreateTempDirWithCallbackAndAssert(t) - defer createTempDirCallback() - poetryProjectPath := filepath.Join(filepath.FromSlash(tests.GetTestResourcesPath()), "xray", "python", "poetry") - // Copy the poetry project from the testdata to a temp dir - assert.NoError(t, biutils.CopyDir(poetryProjectPath, tempDirPath, true, nil)) - prevWd := changeWD(t, tempDirPath) - defer clientTestUtils.ChangeDirAndAssert(t, prevWd) - // Add dummy descriptor file to check that we run only specific audit - addDummyPackageDescriptor(t, false) - return xrayCli.RunCliCmdWithOutput(t, "audit", "--poetry", "--licenses", "--format="+format) -} - -func addDummyPackageDescriptor(t *testing.T, hasPackageJson bool) { - descriptor := "package.json" - if hasPackageJson { - descriptor = "pom.xml" - } - dummyFile, err := os.Create(descriptor) - assert.NoError(t, err) - assert.NoError(t, dummyFile.Close()) -} - -func initXrayTest(t *testing.T, minVersion string) { - if !*tests.TestXray { - t.Skip("Skipping Xray test. To run Xray test add the '-test.xray=true' option.") - } - validateXrayVersion(t, minVersion) -} - -func validateXrayVersion(t *testing.T, minVersion string) { - xrayVersion, err := getXrayVersion() - if err != nil { - assert.NoError(t, err) - return - } - err = clientUtils.ValidateMinimumVersion(clientUtils.Xray, xrayVersion.GetVersion(), minVersion) - if err != nil { - t.Skip(err) - } -} - -func getXrayVersion() (version.Version, error) { - xrayVersion, err := xrayAuth.GetVersion() - return *version.NewVersion(xrayVersion), err -} - -func verifyJsonScanResults(t *testing.T, content string, minViolations, minVulnerabilities, minLicenses int) { - var results []services.ScanResponse - err := json.Unmarshal([]byte(content), &results) - if assert.NoError(t, err) { - var violations []services.Violation - var vulnerabilities []services.Vulnerability - var licenses []services.License - for _, result := range results { - violations = append(violations, result.Violations...) - vulnerabilities = append(vulnerabilities, result.Vulnerabilities...) - licenses = append(licenses, result.Licenses...) - } - assert.True(t, len(violations) >= minViolations, fmt.Sprintf("Expected at least %d violations in scan results, but got %d violations.", minViolations, len(violations))) - assert.True(t, len(vulnerabilities) >= minVulnerabilities, fmt.Sprintf("Expected at least %d vulnerabilities in scan results, but got %d vulnerabilities.", minVulnerabilities, len(vulnerabilities))) - assert.True(t, len(licenses) >= minLicenses, fmt.Sprintf("Expected at least %d Licenses in scan results, but got %d Licenses.", minLicenses, len(licenses))) - } -} - -func verifySimpleJsonScanResults(t *testing.T, content string, minVulnerabilities, minLicenses int) { - var results formats.SimpleJsonResults - err := json.Unmarshal([]byte(content), &results) - if assert.NoError(t, err) { - assert.GreaterOrEqual(t, len(results.Vulnerabilities), minVulnerabilities) - assert.GreaterOrEqual(t, len(results.Licenses), minLicenses) - } -} - -func TestXrayCurl(t *testing.T) { - initXrayTest(t, "") - // Configure a new server named "default". - createJfrogHomeConfig(t, true) - defer cleanTestsHomeEnv() - // Check curl command with the default configured server. - err := xrayCli.WithoutCredentials().Exec("xr", "curl", "-XGET", "/api/v1/system/version") - assert.NoError(t, err) - // Check curl command with '--server-id' flag - err = xrayCli.WithoutCredentials().Exec("xr", "curl", "-XGET", "/api/system/version", "--server-id=default") - assert.NoError(t, err) - // Check curl command with invalid server id - should get an error. - err = xrayCli.WithoutCredentials().Exec("xr", "curl", "-XGET", "/api/system/version", "--server-id=not_configured_name") - assert.EqualError(t, err, "Server ID 'not_configured_name' does not exist.") -} - -func initNativeDockerWithXrayTest(t *testing.T) func() { - if !*tests.TestDockerScan || !*tests.TestXray { - t.Skip("Skipping Docker scan test. To run Xray Docker test add the '-test.dockerScan=true' and '-test.xray=true' options.") - } - oldHomeDir := os.Getenv(coreutils.HomeDir) - initXrayCli() - validateXrayVersion(t, scan.DockerScanMinXrayVersion) - // Create server config to use with the command. - createJfrogHomeConfig(t, true) - return func() { - clientTestUtils.SetEnvAndAssert(t, coreutils.HomeDir, oldHomeDir) - } -} - -func TestDockerScan(t *testing.T) { - cleanup := initNativeDockerWithXrayTest(t) - defer cleanup() - - watchName, deleteWatch := createTestWatch(t) - defer deleteWatch() - - imagesToScan := []string{ - // Simple image with vulnerabilities - "bitnami/minio:2022", - - // Image with RPM with vulnerabilities - "redhat/ubi8-micro:8.4", - } - for _, imageName := range imagesToScan { - runDockerScan(t, imageName, watchName, 3, 3, 3) - } - - // On Xray 3.40.3 there is a bug whereby xray fails to scan docker image with 0 vulnerabilities, - // So we skip it for now till the next version will be released - validateXrayVersion(t, "3.41.0") - - // Image with 0 vulnerabilities - runDockerScan(t, "busybox:1.35", "", 0, 0, 0) -} - -func TestDockerScanWithProgressBar(t *testing.T) { - callback := tests.MockProgressInitialization() - defer callback() - TestDockerScan(t) -} - -func runDockerScan(t *testing.T, imageName, watchName string, minViolations, minVulnerabilities, minLicenses int) { - // Pull image from docker repo - imageTag := path.Join(*tests.ContainerRegistry, tests.DockerVirtualRepo, imageName) - dockerPullCommand := coreContainer.NewPullCommand(container.DockerClient) - dockerPullCommand.SetCmdParams([]string{"pull", imageTag}).SetImageTag(imageTag).SetRepo(tests.DockerVirtualRepo).SetServerDetails(serverDetails).SetBuildConfiguration(new(build.BuildConfiguration)) - if assert.NoError(t, dockerPullCommand.Run()) { - defer inttestutils.DeleteTestImage(t, imageTag, container.DockerClient) - - args := []string{"docker", "scan", imageTag, "--server-id=default", "--licenses", "--format=json", "--fail=false", "--min-severity=low", "--fixable-only"} - - // Run docker scan on image - output := xrayCli.WithoutCredentials().RunCliCmdWithOutput(t, args...) - if assert.NotEmpty(t, output) { - verifyJsonScanResults(t, output, 0, minVulnerabilities, minLicenses) - } - - // Run docker scan on image with watch - if watchName != "" { - args = append(args, "--watches="+watchName) - output = xrayCli.WithoutCredentials().RunCliCmdWithOutput(t, args...) - if assert.NotEmpty(t, output) { - verifyJsonScanResults(t, output, minViolations, 0, 0) - } - } - } -} - -func createTestWatch(t *testing.T) (string, func()) { - xrayManager, err := utils.CreateXrayServiceManager(xrayDetails) - assert.NoError(t, err) - // Create new default policy. - policyParams := xrayUtils.PolicyParams{ - Name: fmt.Sprintf("%s-%s", "docker-policy", strconv.FormatInt(time.Now().Unix(), 10)), - Type: xrayUtils.Security, - Rules: []xrayUtils.PolicyRule{{ - Name: "sec_rule", - Criteria: *xrayUtils.CreateSeverityPolicyCriteria(xrayUtils.Low), - Priority: 1, - Actions: &xrayUtils.PolicyAction{ - FailBuild: clientUtils.Pointer(true), - }, - }}, - } - if !assert.NoError(t, xrayManager.CreatePolicy(policyParams)) { - return "", func() {} - } - // Create new default watch. - watchParams := xrayUtils.NewWatchParams() - watchParams.Name = fmt.Sprintf("%s-%s", "docker-watch", strconv.FormatInt(time.Now().Unix(), 10)) - watchParams.Active = true - watchParams.Builds.Type = xrayUtils.WatchBuildAll - watchParams.Policies = []xrayUtils.AssignedPolicy{ - { - Name: policyParams.Name, - Type: "security", - }, - } - assert.NoError(t, xrayManager.CreateWatch(watchParams)) - return watchParams.Name, func() { - assert.NoError(t, xrayManager.DeleteWatch(watchParams.Name)) - assert.NoError(t, xrayManager.DeletePolicy(policyParams.Name)) - } -} - -func TestXrayOfflineDBSyncV3(t *testing.T) { - initXrayTest(t, "") - - // Validate license-id - err := xrayCli.WithoutCredentials().Exec("xr", "ou") - assert.EqualError(t, err, "the --license-id option is mandatory") - // Periodic valid only with stream - err = xrayCli.WithoutCredentials().Exec("xr", "ou", "--license-id=123", "--periodic") - assert.EqualError(t, err, fmt.Sprintf("the %s option is only valid with %s", cliutils.Periodic, cliutils.Stream)) - err = xrayCli.WithoutCredentials().Exec("xr", "ou", "--license-id=123", "--stream=", "--periodic") - assert.EqualError(t, err, fmt.Sprintf("the %s option is only valid with %s", cliutils.Periodic, cliutils.Stream)) - // Invalid stream - err = xrayCli.WithoutCredentials().Exec("xr", "ou", "--license-id=123", "--stream=bad_name") - assert.ErrorContains(t, err, "Invalid stream type") -} - -func TestXrayAuditJasSimpleJson(t *testing.T) { - output := testXrayAuditJas(t, string(format.SimpleJson), "jas-test") - verifySimpleJsonJasResults(t, output, 1, 9, 7, 2) -} - -func TestXrayAuditJasSimpleJsonWithConfig(t *testing.T) { - output := testXrayAuditJas(t, string(format.SimpleJson), "jas-config") - verifySimpleJsonJasResults(t, output, 0, 0, 1, 2) -} - -func TestXrayAuditJasNoViolationsSimpleJson(t *testing.T) { - output := testXrayAuditJas(t, string(format.SimpleJson), "npm") - verifySimpleJsonScanResults(t, output, 1, 0) - verifySimpleJsonJasResults(t, output, 0, 0, 0, 0) -} - -func testXrayAuditJas(t *testing.T, format string, project string) string { - initXrayTest(t, scangraph.GraphScanMinXrayVersion) - tempDirPath, createTempDirCallback := coretests.CreateTempDirWithCallbackAndAssert(t) - defer createTempDirCallback() - projectDir := filepath.Join(filepath.FromSlash(tests.GetTestResourcesPath()), filepath.Join("xray", project)) - // Copy the multi project from the testdata to a temp dir - assert.NoError(t, biutils.CopyDir(projectDir, tempDirPath, true, nil)) - // Configure a new server named "default" - createJfrogHomeConfig(t, true) - defer cleanTestsHomeEnv() - baseWd, err := os.Getwd() - assert.NoError(t, err) - chdirCallback := clientTestUtils.ChangeDirWithCallback(t, baseWd, tempDirPath) - defer chdirCallback() - return xrayCli.WithoutCredentials().RunCliCmdWithOutput(t, "audit", "--format="+format) -} - -func verifySimpleJsonJasResults(t *testing.T, content string, minSastViolations, minIacViolations, minSecrets, minApplicable int) { - var results formats.SimpleJsonResults - err := json.Unmarshal([]byte(content), &results) - if assert.NoError(t, err) { - assert.GreaterOrEqual(t, len(results.Sast), minSastViolations, "Found less sast then expected") - assert.GreaterOrEqual(t, len(results.Secrets), minSecrets, "Found less secrets then expected") - assert.GreaterOrEqual(t, len(results.Iacs), minIacViolations, "Found less IaC then expected") - var applicableResults, notApplicableResults int - for _, vuln := range results.Vulnerabilities { - if vuln.Applicable == string(utils.NotApplicable) { - notApplicableResults++ - } else if vuln.Applicable == string(utils.Applicable) { - applicableResults++ - } - } - assert.GreaterOrEqual(t, applicableResults, minApplicable, "Found less applicableResults then expected") - assert.GreaterOrEqual(t, notApplicableResults, 1, "Found less notApplicableResults then expected") - } -} - -func TestCurationAudit(t *testing.T) { - initXrayTest(t, "") - tempDirPath, createTempDirCallback := coretests.CreateTempDirWithCallbackAndAssert(t) - defer createTempDirCallback() - multiProject := filepath.Join(filepath.FromSlash(tests.GetTestResourcesPath()), "xray") - assert.NoError(t, biutils.CopyDir(multiProject, tempDirPath, true, nil)) - rootDir, err := os.Getwd() - require.NoError(t, err) - defer func() { - assert.NoError(t, os.Chdir(rootDir)) - }() - require.NoError(t, os.Chdir(filepath.Join(tempDirPath, "npm"))) - expectedRequest := map[string]bool{ - "/api/npm/npms/json/-/json-9.0.6.tgz": false, - "/api/npm/npms/xml/-/xml-1.0.1.tgz": false, - } - requestToFail := map[string]bool{ - "/api/npm/npms/xml/-/xml-1.0.1.tgz": false, - } - serverMock, config := curationServer(t, expectedRequest, requestToFail) - - cleanUpJfrogHome, err := coretests.SetJfrogHome() - assert.NoError(t, err) - defer cleanUpJfrogHome() - - config.User = "admin" - config.Password = "password" - config.ServerId = "test" - configCmd := coreCmd.NewConfigCommand(coreCmd.AddOrEdit, "test").SetDetails(config).SetUseBasicAuthOnly(true).SetInteractive(false) - assert.NoError(t, configCmd.Run()) - - defer serverMock.Close() - // Create build config - resolutionServerId := "server-id-resolve" - deploymentServerId := "server-id-deploy" - resolutionRepo := "repo-resolve" - deploymentRepo := "repo-deploy" - context := createContext(t, resolutionServerId+"="+config.ServerId, resolutionRepo+"=npms", deploymentServerId+"="+config.ServerId, deploymentRepo+"=npm-local", "global=false") - err = coreCmd.CreateBuildConfig(context, project.Npm) - assert.NoError(t, err) - - localXrayCli := xrayCli.WithoutCredentials() - workingDirsFlag := fmt.Sprintf("--working-dirs=%s", filepath.Join(tempDirPath, "npm")) - output := localXrayCli.RunCliCmdWithOutput(t, "curation-audit", "--format="+string(format.Json), workingDirsFlag) - expectedResp := getCurationExpectedResponse(config) - var got []coreCuration.PackageStatus - bracketIndex := strings.Index(output, "[") - require.Less(t, 0, bracketIndex, "Unexpected Curation output with missing '['") - err = json.Unmarshal([]byte(output[bracketIndex:]), &got) - assert.NoError(t, err) - assert.Equal(t, expectedResp, got) - for k, v := range expectedRequest { - assert.Truef(t, v, "didn't receive expected GET request for package url %s", k) - } -} - -func getCurationExpectedResponse(config *config.ServerDetails) []coreCuration.PackageStatus { - expectedResp := []coreCuration.PackageStatus{ - { - Action: "blocked", - PackageName: "xml", - PackageVersion: "1.0.1", - BlockedPackageUrl: config.ArtifactoryUrl + "api/npm/npms/xml/-/xml-1.0.1.tgz", - BlockingReason: coreCuration.BlockingReasonPolicy, - ParentName: "xml", - ParentVersion: "1.0.1", - DepRelation: "direct", - PkgType: "npm", - Policy: []coreCuration.Policy{ - { - Policy: "pol1", - Condition: "cond1", - Explanation: "explanation", - Recommendation: "recommendation", - }, - { - Policy: "pol2", - Condition: "cond2", - Explanation: "explanation2", - Recommendation: "recommendation2", - }, - }, - }, - } - return expectedResp -} - -func curationServer(t *testing.T, expectedRequest map[string]bool, requestToFail map[string]bool) (*httptest.Server, *config.ServerDetails) { - mapLockReadWrite := sync.Mutex{} - serverMock, config, _ := commontests.CreateRtRestsMockServer(t, func(w http.ResponseWriter, r *http.Request) { - if r.Method == http.MethodHead { - mapLockReadWrite.Lock() - if _, exist := expectedRequest[r.RequestURI]; exist { - expectedRequest[r.RequestURI] = true - } - mapLockReadWrite.Unlock() - if _, exist := requestToFail[r.RequestURI]; exist { - w.WriteHeader(http.StatusForbidden) - } - } - if r.Method == http.MethodGet { - if r.RequestURI == "/api/system/version" { - _, err := w.Write([]byte(`{"version": "7.0.0"}`)) - require.NoError(t, err) - w.WriteHeader(http.StatusOK) - return - } - - if _, exist := requestToFail[r.RequestURI]; exist { - w.WriteHeader(http.StatusForbidden) - _, err := w.Write([]byte("{\n \"errors\": [\n {\n \"status\": 403,\n " + - "\"message\": \"Package download was blocked by JFrog Packages " + - "Curation service due to the following policies violated {pol1, cond1, explanation, recommendation}, {pol2, cond2, explanation2, recommendation2}\"\n }\n ]\n}")) - require.NoError(t, err) - } - } - }) - return serverMock, config -} - -func createContext(t *testing.T, stringFlags ...string) *cli.Context { - flagSet := flag.NewFlagSet("TestFlagSet", flag.ContinueOnError) - flags := setStringFlags(flagSet, stringFlags...) - assert.NoError(t, flagSet.Parse(flags)) - return cli.NewContext(nil, flagSet, nil) -} - -func setStringFlags(flagSet *flag.FlagSet, flags ...string) []string { - cmdFlags := []string{} - for _, stringFlag := range flags { - flagSet.String(strings.Split(stringFlag, "=")[0], "", "") - cmdFlags = append(cmdFlags, "--"+stringFlag) - } - return cmdFlags -} - -// We perform validation on dependency resolution from an Artifactory server during the construction of the dependency tree during 'audit' flow. -// This process involves resolving all dependencies required by the project. -func TestDependencyResolutionFromArtifactory(t *testing.T) { - initXrayTest(t, "") - - testCases := []struct { - testProjectPath []string - resolveRepoName string - cacheRepoName string - projectType project.ProjectType - }{ - { - testProjectPath: []string{"npm", "npmproject"}, - resolveRepoName: tests.NpmRemoteRepo, - cacheRepoName: tests.NpmRemoteRepo, - projectType: project.Npm, - }, - { - testProjectPath: []string{"nuget", "simple-dotnet"}, - resolveRepoName: tests.NugetRemoteRepo, - cacheRepoName: tests.NugetRemoteRepo, - projectType: project.Dotnet, - }, - { - testProjectPath: []string{"yarn", "yarnproject"}, - resolveRepoName: tests.YarnRemoteRepo, - cacheRepoName: tests.YarnRemoteRepo, - projectType: project.Yarn, - }, - { - testProjectPath: []string{"gradle", "gradleproject"}, - resolveRepoName: tests.GradleRemoteRepo, - cacheRepoName: tests.GradleRemoteRepo, - projectType: project.Gradle, - }, - { - testProjectPath: []string{"maven", "mavenproject"}, - resolveRepoName: tests.MvnRemoteRepo, - cacheRepoName: tests.MvnRemoteRepo, - projectType: project.Maven, - }, - { - testProjectPath: []string{"go", "simple-project"}, - resolveRepoName: tests.GoVirtualRepo, - cacheRepoName: tests.GoRemoteRepo, - projectType: project.Go, - }, - { - testProjectPath: []string{"pipenv", "pipenvproject"}, - resolveRepoName: tests.PypiRemoteRepo, - cacheRepoName: tests.PypiRemoteRepo, - projectType: project.Pipenv, - }, - { - testProjectPath: []string{"pip", "setuppyproject"}, - resolveRepoName: tests.PypiRemoteRepo, - cacheRepoName: tests.PypiRemoteRepo, - projectType: project.Pip, - }, - { - testProjectPath: []string{"poetry", "projecttomlproject"}, - resolveRepoName: tests.PypiRemoteRepo, - cacheRepoName: tests.PypiRemoteRepo, - projectType: project.Poetry, - }, - } - createJfrogHomeConfig(t, true) - defer cleanTestsHomeEnv() - - for _, testCase := range testCases { - t.Run(testCase.projectType.String(), func(t *testing.T) { - testSingleTechDependencyResolution(t, testCase.testProjectPath, testCase.resolveRepoName, testCase.cacheRepoName, testCase.projectType) - }) - } -} - -func testSingleTechDependencyResolution(t *testing.T, testProjectPartialPath []string, resolveRepoName string, cacheRepoName string, projectType project.ProjectType) { - tempDirPath, createTempDirCallback := coretests.CreateTempDirWithCallbackAndAssert(t) - defer createTempDirCallback() - testProjectPath := filepath.Join(append([]string{filepath.FromSlash(tests.GetTestResourcesPath())}, testProjectPartialPath...)...) - assert.NoError(t, biutils.CopyDir(testProjectPath, tempDirPath, true, nil)) - rootDir, err := os.Getwd() - assert.NoError(t, err) - assert.NoError(t, os.Chdir(tempDirPath)) - defer func() { - assert.NoError(t, os.Chdir(rootDir)) - }() - - server := &config.ServerDetails{ - Url: *tests.JfrogUrl, - ArtifactoryUrl: *tests.JfrogUrl + tests.ArtifactoryEndpoint, - XrayUrl: *tests.JfrogUrl + tests.XrayEndpoint, - AccessToken: *tests.JfrogAccessToken, - ServerId: tests.ServerId, - } - configCmd := coreCmd.NewConfigCommand(coreCmd.AddOrEdit, tests.ServerId).SetDetails(server).SetUseBasicAuthOnly(true).SetInteractive(false) - assert.NoError(t, configCmd.Run()) - - context := createContext(t, "repo-resolve="+resolveRepoName, "server-id-resolve="+server.ServerId) - err = coreCmd.CreateBuildConfig(context, projectType) - assert.NoError(t, err) - - artifactoryPathToSearch := cacheRepoName + "-cache/*" - // To ensure a clean state between test cases, we need to verify that the cache remains clear for remote directories shared across multiple test cases. - assert.NoError(t, artifactoryCli.Exec("del", artifactoryPathToSearch)) - - callbackFunc := clearOrRedirectLocalCacheIfNeeded(t, projectType) - if callbackFunc != nil { - defer func() { - callbackFunc() - }() - } - - // Executing the 'audit' command on an uninstalled project, we anticipate the resolution of dependencies from the configured Artifactory server and repository. - assert.NoError(t, xrayCli.WithoutCredentials().Exec("audit")) - - // Following resolution from Artifactory, we anticipate the repository's cache to contain data. - output := artifactoryCli.RunCliCmdWithOutput(t, "s", artifactoryPathToSearch, "--fail-no-op") - // After the resolution from Artifactory, we verify whether the repository's cache is filled with artifacts. - assert.NotEqual(t, "[]\n", output) -} - -// To guarantee that dependencies are resolved from Artifactory, certain package managers may need their local cache to be cleared. -func clearOrRedirectLocalCacheIfNeeded(t *testing.T, projectType project.ProjectType) (callbackFunc func()) { - switch projectType { - case project.Dotnet: - _, err := exec.Command("dotnet", "nuget", "locals", "all", "--clear").CombinedOutput() - assert.NoError(t, err) - case project.Maven: - mavenCacheTempPath, createTempDirCallback := coretests.CreateTempDirWithCallbackAndAssert(t) - envVarCallbackFunc := clientTestUtils.SetEnvWithCallbackAndAssert(t, jvmLaunchEnvVar, mavenCacheRedirectionVal+mavenCacheTempPath) - callbackFunc = func() { - envVarCallbackFunc() - createTempDirCallback() - } - case project.Go: - goTempCachePath, createTempDirCallback := coretests.CreateTempDirWithCallbackAndAssert(t) - envVarCallbackFunc := clientTestUtils.SetEnvWithCallbackAndAssert(t, goCacheEnvVar, goTempCachePath) - - callbackFunc = func() { - envVarCallbackFunc() - // To remove the temporary cache in Go and all its contents, appropriate deletion permissions are required. - assert.NoError(t, coreutils.SetPermissionsRecursively(goTempCachePath, 0755)) - createTempDirCallback() - } - case project.Pip: - pipTempCachePath, createTempDirCallback := coretests.CreateTempDirWithCallbackAndAssert(t) - envVarCallbackFunc := clientTestUtils.SetEnvWithCallbackAndAssert(t, pipCacheEnvVar, pipTempCachePath) - callbackFunc = func() { - envVarCallbackFunc() - createTempDirCallback() - } - } - return -}