diff --git a/.github/workflows/scriptTests.yml b/.github/workflows/scriptTests.yml index 16856b439..11e8b6f47 100644 --- a/.github/workflows/scriptTests.yml +++ b/.github/workflows/scriptTests.yml @@ -78,7 +78,7 @@ jobs: - name: "Get latest release" id: latest-release run: | - export LATEST_RELEASE=`curl https://api.github.com/repos/jfrog/jfrog-cli/releases/latest -s --retry 10 | jq .name -r | cut -c 2-` + export LATEST_RELEASE=`curl https://api.github.com/repos/jfrog/jfrog-cli/releases/latest -s --retry 10 | jq .name -r | sed "s/^v//"` echo "LATEST_RELEASE=$LATEST_RELEASE" >> "$GITHUB_OUTPUT" shell: bash diff --git a/build/npm/v2-jf/package-lock.json b/build/npm/v2-jf/package-lock.json index 539e8404b..eece2630f 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.1", + "version": "2.52.3", "lockfileVersion": 1 } diff --git a/build/npm/v2-jf/package.json b/build/npm/v2-jf/package.json index f0d8f6ebd..6779ba92e 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.1", + "version": "2.52.3", "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 61137b0c8..43a9b01c5 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.1", + "version": "2.52.3", "lockfileVersion": 2 } diff --git a/build/npm/v2/package.json b/build/npm/v2/package.json index a47a8730c..b29216740 100644 --- a/build/npm/v2/package.json +++ b/build/npm/v2/package.json @@ -1,6 +1,6 @@ { "name": "jfrog-cli-v2", - "version": "2.52.1", + "version": "2.52.3", "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/go.mod b/go.mod index e57e0f700..dee921bbe 100644 --- a/go.mod +++ b/go.mod @@ -7,10 +7,10 @@ require ( github.com/buger/jsonparser v1.1.1 github.com/go-git/go-git/v5 v5.9.0 github.com/gocarina/gocsv v0.0.0-20230616125104-99d496ca653d - github.com/jfrog/build-info-go v1.9.16 + github.com/jfrog/build-info-go v1.9.17 github.com/jfrog/gofrog v1.3.2 - github.com/jfrog/jfrog-cli-core/v2 v2.47.2 - github.com/jfrog/jfrog-client-go v1.35.0 + github.com/jfrog/jfrog-cli-core/v2 v2.47.4 + github.com/jfrog/jfrog-client-go v1.35.1 github.com/jszwec/csvutil v1.8.0 github.com/mholt/archiver/v3 v3.5.1 github.com/stretchr/testify v1.8.4 @@ -132,7 +132,7 @@ require ( // replace github.com/jfrog/build-info-go => github.com/jfrog/build-info-go v1.8.9-0.20231130093251-25c79868c10c -// replace github.com/jfrog/jfrog-cli-core/v2 => github.com/jfrog/jfrog-cli-core/v2 v2.31.1-0.20231130101652-2aaa8c0c51ec +// replace github.com/jfrog/jfrog-cli-core/v2 => github.com/jfrog/jfrog-cli-core/v2 v2.31.1-0.20231207140254-799876947bac // replace github.com/jfrog/gofrog => github.com/jfrog/gofrog v1.3.2-0.20231130091721-6d742be8bc7a diff --git a/go.sum b/go.sum index e07c31904..305c790ad 100644 --- a/go.sum +++ b/go.sum @@ -237,16 +237,16 @@ github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 h1:BQSFePA1RWJOl github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99/go.mod h1:1lJo3i6rXxKeerYnT8Nvf0QmHCRC1n8sfWVwXF2Frvo= github.com/jedib0t/go-pretty/v6 v6.4.0 h1:YlI/2zYDrweA4MThiYMKtGRfT+2qZOO65ulej8GTcVI= github.com/jedib0t/go-pretty/v6 v6.4.0/go.mod h1:MgmISkTWDSFu0xOqiZ0mKNntMQ2mDgOcwOkwBEkMDJI= -github.com/jfrog/build-info-go v1.9.16 h1:zMNxUXve4CZndhlbaEGwgayWPY8CRyPzSobvTKYRPcg= -github.com/jfrog/build-info-go v1.9.16/go.mod h1:/5VZXH2Ud0IK3cOFwPykjwPOaEcHhzzbjnRiou+YKpM= +github.com/jfrog/build-info-go v1.9.17 h1:sUA6V3P8i+awYlK7dkwm4l6IuLE2W964F5Pb18x95HA= +github.com/jfrog/build-info-go v1.9.17/go.mod h1:/5VZXH2Ud0IK3cOFwPykjwPOaEcHhzzbjnRiou+YKpM= github.com/jfrog/gofrog v1.3.2 h1:TktKP+PdZdxjkYZxWWIq4DkTGSYtr9Slsy+egZpEhUY= github.com/jfrog/gofrog v1.3.2/go.mod h1:AQo5Fq0G9nDEF6icH7MYQK0iohR4HuEAXl8jaxRuT6Q= 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.2 h1:2tHkYY5ZdLkX3IsyGAfCDLQASMO4jrqd5WsNQP6d3PY= -github.com/jfrog/jfrog-cli-core/v2 v2.47.2/go.mod h1:RFQwrZ1qXAQ+X0xfuzxBBDIYuRnDsPy12xlyjuOpUog= -github.com/jfrog/jfrog-client-go v1.35.0 h1:VTyrR/jFlWInRdGYswa2fwFc1Thsh6eGMnHuqhDVh7s= -github.com/jfrog/jfrog-client-go v1.35.0/go.mod h1:cG0vdKXbyfupKgSYmwA5FZPco6zSfyJi3eEYOxuqm/k= +github.com/jfrog/jfrog-cli-core/v2 v2.47.4 h1:Wjim4UZxBZHs2LeSFe4+Ms3JJSzcUPv8D01DvEalkMQ= +github.com/jfrog/jfrog-cli-core/v2 v2.47.4/go.mod h1:6UImGTYUkxOxst/M4wSp6G7dnI24h0OkDW8BnXYhtCE= +github.com/jfrog/jfrog-client-go v1.35.1 h1:T5HXyRykSCx4cZ//9VCnvHs5rvsPCuNsTU4+CRvkVWk= +github.com/jfrog/jfrog-client-go v1.35.1/go.mod h1:XF/PXHuKILfB1sN3n903yWaWJKJX5VYofDGvO9cJ3+g= github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU= github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk= github.com/jszwec/csvutil v1.8.0 h1:G7vS2LGdpZZDH1HmHeNbxOaJ/ZnJlpwGFvOkTkJzzNk= diff --git a/main_test.go b/main_test.go index f9d4fb07b..4d42e6107 100644 --- a/main_test.go +++ b/main_test.go @@ -88,6 +88,9 @@ 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() } diff --git a/testdata/nuget/simple-dotnet/Class1.cs b/testdata/nuget/simple-dotnet/Class1.cs new file mode 100644 index 000000000..af05eece0 --- /dev/null +++ b/testdata/nuget/simple-dotnet/Class1.cs @@ -0,0 +1,6 @@ +namespace nuget1; + +public class Class1 +{ + +} diff --git a/testdata/nuget/simple-dotnet/nuget1.csproj b/testdata/nuget/simple-dotnet/nuget1.csproj new file mode 100644 index 000000000..0b5a60de8 --- /dev/null +++ b/testdata/nuget/simple-dotnet/nuget1.csproj @@ -0,0 +1,16 @@ + + + + net7.0 + enable + enable + + + + + + + + + + diff --git a/testdata/yarn_remote_repository_config.json b/testdata/yarn_remote_repository_config.json new file mode 100644 index 000000000..1474dc89d --- /dev/null +++ b/testdata/yarn_remote_repository_config.json @@ -0,0 +1,6 @@ +{ + "key": "${YARN_REMOTE_REPO}", + "rclass": "remote", + "packageType": "npm", + "url": "https://registry.npmjs.org" +} diff --git a/utils/cliutils/cli_consts.go b/utils/cliutils/cli_consts.go index 062dac18b..0f4e8b63e 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.1" + CliVersion = "2.52.3" ClientAgent = "jfrog-cli-go" // CLI base commands constants: diff --git a/utils/tests/consts.go b/utils/tests/consts.go index 8b3b93a6b..160ef87a3 100644 --- a/utils/tests/consts.go +++ b/utils/tests/consts.go @@ -78,6 +78,7 @@ const ( NpmLocalRepositoryConfig = "npm_local_repository_config.json" NpmRemoteRepositoryConfig = "npm_remote_repository_config.json" NugetRemoteRepositoryConfig = "nuget_remote_repository_config.json" + YarnRemoteRepositoryConfig = "yarn_remote_repository_config.json" Out = "out" PypiRemoteRepositoryConfig = "pypi_remote_repository_config.json" PypiVirtualRepositoryConfig = "pypi_virtual_repository_config.json" @@ -171,6 +172,7 @@ var ( NpmRepo = "cli-npm" NpmRemoteRepo = "cli-npm-remote" NugetRemoteRepo = "cli-nuget-remote" + YarnRemoteRepo = "cli-yarn-remote" PypiRemoteRepo = "cli-pypi-remote" PypiVirtualRepo = "cli-pypi-virtual" PipenvRemoteRepo = "cli-pipenv-pypi-remote" diff --git a/utils/tests/utils.go b/utils/tests/utils.go index b3eeb3950..00d738513 100644 --- a/utils/tests/utils.go +++ b/utils/tests/utils.go @@ -335,6 +335,7 @@ var reposConfigMap = map[*string]string{ &NpmRepo: NpmLocalRepositoryConfig, &NpmRemoteRepo: NpmRemoteRepositoryConfig, &NugetRemoteRepo: NugetRemoteRepositoryConfig, + &YarnRemoteRepo: YarnRemoteRepositoryConfig, &PypiRemoteRepo: PypiRemoteRepositoryConfig, &PypiVirtualRepo: PypiVirtualRepositoryConfig, &PipenvRemoteRepo: PipenvRemoteRepositoryConfig, @@ -397,7 +398,7 @@ func GetNonVirtualRepositories() map[*string]string { TestPip: {&PypiRemoteRepo}, TestPipenv: {&PipenvRemoteRepo}, TestPlugins: {&RtRepo1}, - TestXray: {}, + TestXray: {&NpmRemoteRepo, &NugetRemoteRepo, &YarnRemoteRepo}, TestAccess: {&RtRepo1}, TestTransfer: {&RtRepo1, &RtRepo2, &MvnRepo1, &MvnRemoteRepo, &DockerRemoteRepo}, TestLifecycle: {&RtDevRepo, &RtProdRepo}, @@ -488,6 +489,7 @@ func getSubstitutionMap() map[string]string { "${NPM_REPO}": NpmRepo, "${NPM_REMOTE_REPO}": NpmRemoteRepo, "${NUGET_REMOTE_REPO}": NugetRemoteRepo, + "${YARN_REMOTE_REPO}": YarnRemoteRepo, "${GO_REPO}": GoRepo, "${GO_REMOTE_REPO}": GoRemoteRepo, "${GO_VIRTUAL_REPO}": GoVirtualRepo, @@ -554,6 +556,7 @@ func AddTimestampToGlobalVars() { NpmRepo += uniqueSuffix NpmRemoteRepo += uniqueSuffix NugetRemoteRepo += uniqueSuffix + YarnRemoteRepo += uniqueSuffix PypiRemoteRepo += uniqueSuffix PypiVirtualRepo += uniqueSuffix PipenvRemoteRepo += uniqueSuffix diff --git a/xray_test.go b/xray_test.go index a0f024cf0..05182a09a 100644 --- a/xray_test.go +++ b/xray_test.go @@ -56,6 +56,14 @@ var ( func InitXrayTests() { initXrayCli() + initArtifactoryCli() + cleanUpOldRepositories() + tests.AddTimestampToGlobalVars() + createRequiredRepos() +} + +func CleanXrayTests() { + deleteCreatedRepos() } func authenticateXray() string { @@ -431,7 +439,7 @@ func TestXrayAuditMultiProjects(t *testing.T) { defer cleanTestsHomeEnv() output := xrayCli.WithoutCredentials().RunCliCmdWithOutput(t, "audit", "--format="+string(utils.SimpleJson), workingDirsFlag) verifySimpleJsonScanResults(t, output, 35, 0) - verifySimpleJsonJasResults(t, output, 3, 9, 7, 3) + verifySimpleJsonJasResults(t, output, 1, 9, 7, 3) } func TestXrayAuditPipJson(t *testing.T) { @@ -638,7 +646,7 @@ func TestXrayCurl(t *testing.T) { 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.xrayScan=true' and '-test.xray=true' options.") + 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() @@ -764,7 +772,7 @@ func TestXrayOfflineDBSyncV3(t *testing.T) { func TestXrayAuditJasSimpleJson(t *testing.T) { output := testXrayAuditJas(t, string(utils.SimpleJson), "jas-test") - verifySimpleJsonJasResults(t, output, 3, 9, 7, 2) + verifySimpleJsonJasResults(t, output, 1, 9, 7, 2) } func TestXrayAuditJasSimpleJsonWithConfig(t *testing.T) { @@ -950,3 +958,77 @@ func setStringFlags(flagSet *flag.FlagSet, flags ...string) []string { } 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 artUtils.ProjectType + }{ + { + testProjectPath: []string{"npm", "npmproject"}, + resolveRepoName: tests.NpmRemoteRepo, + cacheRepoName: tests.NpmRemoteRepo, + projectType: artUtils.Npm, + }, + { + testProjectPath: []string{"nuget", "simple-dotnet"}, + resolveRepoName: tests.NugetRemoteRepo, + cacheRepoName: tests.NugetRemoteRepo, + projectType: artUtils.Dotnet, + }, + { + testProjectPath: []string{"yarn", "yarnproject"}, + resolveRepoName: tests.YarnRemoteRepo, + cacheRepoName: tests.YarnRemoteRepo, + projectType: artUtils.Yarn, + }, + } + + 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 artUtils.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)) + }() + createJfrogHomeConfig(t, true) + context := createContext(t, "repo-resolve="+resolveRepoName) + err = artCmdUtils.CreateBuildConfig(context, projectType) + assert.NoError(t, err) + + artifactoryPathToSearch := cacheRepoName + "-cache/*" + output := artifactoryCli.RunCliCmdWithOutput(t, "s", artifactoryPathToSearch) + // Before the resolution from Artifactory, we verify whether the repository's cache is empty. + assert.Equal(t, "[]\n", output) + + if projectType == artUtils.Dotnet { + // In Nuget/Dotnet projects we need to clear local caches so we will resolve dependencies from Artifactory + _, err = exec.Command("dotnet", "nuget", "locals", "all", "--clear").CombinedOutput() + assert.NoError(t, err) + } + + // We execute 'audit' command on a project that hasn't been installed. With the Artifactory server and repository configuration, our expectation is that dependencies will be resolved from there + assert.NoError(t, xrayCli.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) +}