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/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 0b5ae975a..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) { @@ -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) +}