diff --git a/.github/workflows/xrayTests.yml b/.github/workflows/xrayTests.yml
index afb659a97..fdc8a691b 100644
--- a/.github/workflows/xrayTests.yml
+++ b/.github/workflows/xrayTests.yml
@@ -63,9 +63,9 @@ jobs:
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 }}
+ 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 }}
+ 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/testdata/go/simple-project/go.mod b/testdata/go/simple-project/go.mod
new file mode 100644
index 000000000..309e9d797
--- /dev/null
+++ b/testdata/go/simple-project/go.mod
@@ -0,0 +1,9 @@
+module github.com/you/hello
+
+go 1.20
+
+require rsc.io/quote v1.5.2
+
+require (
+ rsc.io/sampler v1.3.0 // indirect
+)
diff --git a/testdata/go/simple-project/go.sum b/testdata/go/simple-project/go.sum
new file mode 100644
index 000000000..4a8bcd704
--- /dev/null
+++ b/testdata/go/simple-project/go.sum
@@ -0,0 +1,6 @@
+golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c h1:qgOY6WgZOaTkIIMiVjBQcw93ERBE4m30iBm00nkL0i8=
+golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
+rsc.io/quote v1.5.2 h1:w5fcysjrx7yqtD/aO+QwRjYZOKnaM9Uh2b40tElTs3Y=
+rsc.io/quote v1.5.2/go.mod h1:LzX7hefJvL54yjefDEDHNONDjII0t9xZLPXsUe+TKr0=
+rsc.io/sampler v1.3.0 h1:7uVkIFmeBqHfdjD+gZwtXXI+RODJ2Wc4O7MPEh/QiW4=
+rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA=
diff --git a/testdata/go/simple-project/hello.go b/testdata/go/simple-project/hello.go
new file mode 100644
index 000000000..0a29866c4
--- /dev/null
+++ b/testdata/go/simple-project/hello.go
@@ -0,0 +1,11 @@
+package main
+
+import (
+ "fmt"
+
+ "rsc.io/quote"
+)
+
+func main() {
+ fmt.Println(quote.Hello())
+}
diff --git a/testdata/gradle/gradleproject/build.gradle b/testdata/gradle/gradleproject/build.gradle
index e1b9e8fd3..eeac79246 100644
--- a/testdata/gradle/gradleproject/build.gradle
+++ b/testdata/gradle/gradleproject/build.gradle
@@ -1,6 +1,10 @@
apply plugin: 'groovy'
apply plugin: 'idea'
+dependencies {
+ implementation "junit:junit:4.7"
+}
+
version = 1.0
task initProject(description: 'Initialize project directory structure.') {
doLast {
diff --git a/testdata/maven/mavenproject/pom.xml b/testdata/maven/mavenproject/pom.xml
index 17859af3a..502b78fba 100644
--- a/testdata/maven/mavenproject/pom.xml
+++ b/testdata/maven/mavenproject/pom.xml
@@ -37,5 +37,11 @@
4.11
test
+
+ commons-io
+ commons-io
+ 1.2
+ test
+
\ No newline at end of file
diff --git a/testdata/poetry/projecttomlproject/hello.py b/testdata/poetry/projecttomlproject/hello.py
new file mode 100644
index 000000000..e59e04407
--- /dev/null
+++ b/testdata/poetry/projecttomlproject/hello.py
@@ -0,0 +1,4 @@
+import numpy as np
+
+arr = np.array([1, 2, 3, 4, 5])
+print(arr)
diff --git a/testdata/poetry/projecttomlproject/pyproject.toml b/testdata/poetry/projecttomlproject/pyproject.toml
new file mode 100644
index 000000000..00c4eb5ae
--- /dev/null
+++ b/testdata/poetry/projecttomlproject/pyproject.toml
@@ -0,0 +1,13 @@
+[tool.poetry]
+name = "my-poetry-project"
+version = "1.1.0"
+description = ""
+authors = ["Severus Snape "]
+
+[tool.poetry.dependencies]
+python = "^3.10"
+numpy = "^1.23.0"
+
+[build-system]
+requires = ["poetry-core>=1.0.0"]
+build-backend = "poetry.core.masonry.api"
diff --git a/utils/tests/utils.go b/utils/tests/utils.go
index 00d738513..bf276700c 100644
--- a/utils/tests/utils.go
+++ b/utils/tests/utils.go
@@ -398,7 +398,7 @@ func GetNonVirtualRepositories() map[*string]string {
TestPip: {&PypiRemoteRepo},
TestPipenv: {&PipenvRemoteRepo},
TestPlugins: {&RtRepo1},
- TestXray: {&NpmRemoteRepo, &NugetRemoteRepo, &YarnRemoteRepo},
+ TestXray: {&NpmRemoteRepo, &NugetRemoteRepo, &YarnRemoteRepo, &GradleRemoteRepo, &MvnRemoteRepo, &GoRepo, &GoRemoteRepo, &PypiRemoteRepo},
TestAccess: {&RtRepo1},
TestTransfer: {&RtRepo1, &RtRepo2, &MvnRepo1, &MvnRemoteRepo, &DockerRemoteRepo},
TestLifecycle: {&RtDevRepo, &RtProdRepo},
@@ -422,7 +422,7 @@ func GetVirtualRepositories() map[*string]string {
TestPip: {&PypiVirtualRepo},
TestPipenv: {&PipenvVirtualRepo},
TestPlugins: {},
- TestXray: {},
+ TestXray: {&GoVirtualRepo},
TestAccess: {},
}
return getNeededRepositories(virtualReposMap)
diff --git a/xray_test.go b/xray_test.go
index 05182a09a..dc3935780 100644
--- a/xray_test.go
+++ b/xray_test.go
@@ -47,6 +47,13 @@ import (
"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
@@ -988,7 +995,45 @@ func TestDependencyResolutionFromArtifactory(t *testing.T) {
cacheRepoName: tests.YarnRemoteRepo,
projectType: artUtils.Yarn,
},
+ {
+ testProjectPath: []string{"gradle", "gradleproject"},
+ resolveRepoName: tests.GradleRemoteRepo,
+ cacheRepoName: tests.GradleRemoteRepo,
+ projectType: artUtils.Gradle,
+ },
+ {
+ testProjectPath: []string{"maven", "mavenproject"},
+ resolveRepoName: tests.MvnRemoteRepo,
+ cacheRepoName: tests.MvnRemoteRepo,
+ projectType: artUtils.Maven,
+ },
+ {
+ testProjectPath: []string{"go", "simple-project"},
+ resolveRepoName: tests.GoVirtualRepo,
+ cacheRepoName: tests.GoRemoteRepo,
+ projectType: artUtils.Go,
+ },
+ {
+ testProjectPath: []string{"pipenv", "pipenvproject"},
+ resolveRepoName: tests.PypiRemoteRepo,
+ cacheRepoName: tests.PypiRemoteRepo,
+ projectType: artUtils.Pipenv,
+ },
+ {
+ testProjectPath: []string{"pip", "setuppyproject"},
+ resolveRepoName: tests.PypiRemoteRepo,
+ cacheRepoName: tests.PypiRemoteRepo,
+ projectType: artUtils.Pip,
+ },
+ {
+ testProjectPath: []string{"poetry", "projecttomlproject"},
+ resolveRepoName: tests.PypiRemoteRepo,
+ cacheRepoName: tests.PypiRemoteRepo,
+ projectType: artUtils.Poetry,
+ },
}
+ createJfrogHomeConfig(t, true)
+ defer cleanTestsHomeEnv()
for _, testCase := range testCases {
t.Run(testCase.projectType.String(), func(t *testing.T) {
@@ -1008,27 +1053,71 @@ func testSingleTechDependencyResolution(t *testing.T, testProjectPartialPath []s
defer func() {
assert.NoError(t, os.Chdir(rootDir))
}()
- createJfrogHomeConfig(t, true)
- context := createContext(t, "repo-resolve="+resolveRepoName)
+
+ 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 = 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)
+ // 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()
+ }()
}
- // 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"))
+ // 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")
+ 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 artUtils.ProjectType) (callbackFunc func()) {
+ switch projectType {
+ case artUtils.Dotnet:
+ _, err := exec.Command("dotnet", "nuget", "locals", "all", "--clear").CombinedOutput()
+ assert.NoError(t, err)
+ case artUtils.Maven:
+ mavenCacheTempPath, createTempDirCallback := coretests.CreateTempDirWithCallbackAndAssert(t)
+ envVarCallbackFunc := clientTestUtils.SetEnvWithCallbackAndAssert(t, jvmLaunchEnvVar, mavenCacheRedirectionVal+mavenCacheTempPath)
+ callbackFunc = func() {
+ envVarCallbackFunc()
+ createTempDirCallback()
+ }
+ case artUtils.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 artUtils.Pip:
+ pipTempCachePath, createTempDirCallback := coretests.CreateTempDirWithCallbackAndAssert(t)
+ envVarCallbackFunc := clientTestUtils.SetEnvWithCallbackAndAssert(t, pipCacheEnvVar, pipTempCachePath)
+ callbackFunc = func() {
+ envVarCallbackFunc()
+ createTempDirCallback()
+ }
+ }
+ return
+}