diff --git a/.github/workflows/analysis.yml b/.github/workflows/analysis.yml
index 5ca78123e..23a98a6e9 100644
--- a/.github/workflows/analysis.yml
+++ b/.github/workflows/analysis.yml
@@ -37,6 +37,7 @@ jobs:
go-version: 1.20.x
- name: Run Gosec Security Scanner
- uses: securego/gosec@master
+ # Temporarily set version 2.18.0 to workaround https://github.com/securego/gosec/issues/1046
+ uses: securego/gosec@v2.18.0
with:
args: -exclude G204,G301,G302,G304,G306 -tests -exclude-dir \.*test\.* ./...
diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml
index 4f356231f..a3026f842 100644
--- a/.github/workflows/test.yml
+++ b/.github/workflows/test.yml
@@ -21,7 +21,7 @@ jobs:
- uses: actions/checkout@v4
- name: Setup Python3
- uses: actions/setup-python@v4
+ uses: actions/setup-python@v5
with:
python-version: "3.x"
diff --git a/artifactory/commands/golang/go.go b/artifactory/commands/golang/go.go
index 87627aa31..b6950c50a 100644
--- a/artifactory/commands/golang/go.go
+++ b/artifactory/commands/golang/go.go
@@ -18,6 +18,7 @@ import (
"github.com/jfrog/jfrog-client-go/utils/io/fileutils"
"github.com/jfrog/jfrog-client-go/utils/log"
"net/http"
+ "os"
"path"
"path/filepath"
"strings"
@@ -328,3 +329,20 @@ func buildPackageVersionRequest(name, branchName string) string {
// No version was given to "go get" command, so the latest version should be requested
return path.Join(packageVersionRequest, "latest.info")
}
+
+func SetArtifactoryAsResolutionServer(serverDetails *config.ServerDetails, depsRepo string) (err error) {
+ err = setGoProxy(serverDetails, depsRepo)
+ if err != nil {
+ err = fmt.Errorf("failed while setting Artifactory as a dependencies resolution registry: %s", err.Error())
+ }
+ return
+}
+
+func setGoProxy(server *config.ServerDetails, remoteGoRepo string) error {
+ repoUrl, err := goutils.GetArtifactoryRemoteRepoUrl(server, remoteGoRepo)
+ if err != nil {
+ return err
+ }
+ repoUrl += "|direct"
+ return os.Setenv("GOPROXY", repoUrl)
+}
diff --git a/artifactory/commands/golang/go_test.go b/artifactory/commands/golang/go_test.go
index 974808889..ed899aad3 100644
--- a/artifactory/commands/golang/go_test.go
+++ b/artifactory/commands/golang/go_test.go
@@ -1,11 +1,14 @@
package golang
import (
+ "fmt"
+ "github.com/jfrog/jfrog-cli-core/v2/utils/config"
goutils "github.com/jfrog/jfrog-cli-core/v2/utils/golang"
testsutils "github.com/jfrog/jfrog-client-go/utils/tests"
"github.com/stretchr/testify/assert"
"os"
"path/filepath"
+ "strings"
"testing"
)
@@ -42,3 +45,24 @@ func TestGetPackageFilesPath(t *testing.T) {
assert.NoError(t, err)
assert.Equal(t, expectedPackagePath, actualPackagePath)
}
+
+func TestSetArtifactoryAsResolutionServer(t *testing.T) {
+ server := &config.ServerDetails{
+ Url: "http://localhost:8080/",
+ ArtifactoryUrl: "http://localhost:8080/artifactory/",
+ User: "myUser",
+ Password: "myPassword",
+ ServerId: "myServer",
+ }
+ repo := "myRepo"
+
+ // Setting the GOPROXY value to "" to ensure that the new value set in SetArtifactoryAsResolutionServer is correctly validated.
+ cleanup := testsutils.SetEnvWithCallbackAndAssert(t, "GOPROXY", "")
+ defer cleanup()
+
+ assert.NoError(t, SetArtifactoryAsResolutionServer(server, repo))
+
+ serverUrlWithoutHttp := strings.TrimPrefix(server.ArtifactoryUrl, "http://")
+ expectedGoProxy := fmt.Sprintf("http://%s:%s@%sapi/go/%s|direct", server.User, server.Password, serverUrlWithoutHttp, repo)
+ assert.Equal(t, expectedGoProxy, os.Getenv("GOPROXY"))
+}
diff --git a/artifactory/commands/repository/repository.go b/artifactory/commands/repository/repository.go
index d6c77206f..05e407872 100644
--- a/artifactory/commands/repository/repository.go
+++ b/artifactory/commands/repository/repository.go
@@ -116,7 +116,7 @@ var writersMap = map[string]ioutils.AnswerWriter{
YumRootDepth: ioutils.WriteIntAnswer,
DockerApiVersion: ioutils.WriteStringAnswer,
EnableFileListsIndexing: ioutils.WriteBoolAnswer,
- OptionalIndexCompressionFormats: ioutils.WriteStringAnswer,
+ OptionalIndexCompressionFormats: ioutils.WriteStringArrayAnswer,
Username: ioutils.WriteStringAnswer,
Password: ioutils.WriteStringAnswer,
Proxy: ioutils.WriteStringAnswer,
@@ -239,6 +239,8 @@ var localRepoHandlers = map[string]repoHandler{
Alpine: localAlpineHandler,
Generic: localGenericHandler,
Swift: localSwiftHandler,
+ Terraform: localTerraformHandler,
+ Cargo: localCargoHandler,
}
func localMavenHandler(servicesManager artifactory.ArtifactoryServicesManager, jsonConfig []byte, isUpdate bool) error {
@@ -620,6 +622,36 @@ func localSwiftHandler(servicesManager artifactory.ArtifactoryServicesManager, j
return err
}
+func localTerraformHandler(servicesManager artifactory.ArtifactoryServicesManager, jsonConfig []byte, isUpdate bool) error {
+ params := services.NewTerraformLocalRepositoryParams()
+ err := json.Unmarshal(jsonConfig, ¶ms)
+ if errorutils.CheckError(err) != nil {
+ return err
+ }
+
+ if isUpdate {
+ err = servicesManager.UpdateLocalRepository().Terraform(params)
+ } else {
+ err = servicesManager.CreateLocalRepository().Terraform(params)
+ }
+ return err
+}
+
+func localCargoHandler(servicesManager artifactory.ArtifactoryServicesManager, jsonConfig []byte, isUpdate bool) error {
+ params := services.NewCargoLocalRepositoryParams()
+ err := json.Unmarshal(jsonConfig, ¶ms)
+ if errorutils.CheckError(err) != nil {
+ return err
+ }
+
+ if isUpdate {
+ err = servicesManager.UpdateLocalRepository().Cargo(params)
+ } else {
+ err = servicesManager.CreateLocalRepository().Cargo(params)
+ }
+ return err
+}
+
func localGenericHandler(servicesManager artifactory.ArtifactoryServicesManager, jsonConfig []byte, isUpdate bool) error {
params := services.NewGenericLocalRepositoryParams()
err := json.Unmarshal(jsonConfig, ¶ms)
@@ -665,6 +697,8 @@ var remoteRepoHandlers = map[string]repoHandler{
Alpine: remoteAlpineHandler,
Generic: remoteGenericHandler,
Swift: remoteSwiftHandler,
+ Terraform: remoteTerraformHandler,
+ Cargo: remoteCargoHandler,
}
func remoteMavenHandler(servicesManager artifactory.ArtifactoryServicesManager, jsonConfig []byte, isUpdate bool) error {
@@ -1059,6 +1093,34 @@ func remoteSwiftHandler(servicesManager artifactory.ArtifactoryServicesManager,
return err
}
+func remoteCargoHandler(servicesManager artifactory.ArtifactoryServicesManager, jsonConfig []byte, isUpdate bool) error {
+ params := services.NewCargoRemoteRepositoryParams()
+ err := json.Unmarshal(jsonConfig, ¶ms)
+ if errorutils.CheckError(err) != nil {
+ return err
+ }
+ if isUpdate {
+ err = servicesManager.UpdateRemoteRepository().Cargo(params)
+ } else {
+ err = servicesManager.CreateRemoteRepository().Cargo(params)
+ }
+ return err
+}
+
+func remoteTerraformHandler(servicesManager artifactory.ArtifactoryServicesManager, jsonConfig []byte, isUpdate bool) error {
+ params := services.NewTerraformRemoteRepositoryParams()
+ err := json.Unmarshal(jsonConfig, ¶ms)
+ if errorutils.CheckError(err) != nil {
+ return err
+ }
+ if isUpdate {
+ err = servicesManager.UpdateRemoteRepository().Terraform(params)
+ } else {
+ err = servicesManager.CreateRemoteRepository().Terraform(params)
+ }
+ return err
+}
+
func remoteGenericHandler(servicesManager artifactory.ArtifactoryServicesManager, jsonConfig []byte, isUpdate bool) error {
params := services.NewGenericRemoteRepositoryParams()
err := json.Unmarshal(jsonConfig, ¶ms)
@@ -1102,6 +1164,8 @@ var federatedRepoHandlers = map[string]repoHandler{
Generic: federatedGenericHandler,
Yum: federatedYumHandler,
Swift: federatedSwiftHandler,
+ Terraform: federatedTerraformHandler,
+ Cargo: federatedCargoHandler,
}
func federatedMavenHandler(servicesManager artifactory.ArtifactoryServicesManager, jsonConfig []byte, isUpdate bool) error {
@@ -1430,6 +1494,30 @@ func federatedSwiftHandler(servicesManager artifactory.ArtifactoryServicesManage
return servicesManager.CreateFederatedRepository().Swift(params)
}
+func federatedTerraformHandler(servicesManager artifactory.ArtifactoryServicesManager, jsonConfig []byte, isUpdate bool) error {
+ params := services.NewTerraformFederatedRepositoryParams()
+ err := json.Unmarshal(jsonConfig, ¶ms)
+ if errorutils.CheckError(err) != nil {
+ return err
+ }
+ if isUpdate {
+ return servicesManager.UpdateFederatedRepository().Terraform(params)
+ }
+ return servicesManager.CreateFederatedRepository().Terraform(params)
+}
+
+func federatedCargoHandler(servicesManager artifactory.ArtifactoryServicesManager, jsonConfig []byte, isUpdate bool) error {
+ params := services.NewCargoFederatedRepositoryParams()
+ err := json.Unmarshal(jsonConfig, ¶ms)
+ if errorutils.CheckError(err) != nil {
+ return err
+ }
+ if isUpdate {
+ return servicesManager.UpdateFederatedRepository().Cargo(params)
+ }
+ return servicesManager.CreateFederatedRepository().Cargo(params)
+}
+
func federatedYumHandler(servicesManager artifactory.ArtifactoryServicesManager, jsonConfig []byte, isUpdate bool) error {
params := services.NewYumFederatedRepositoryParams()
err := json.Unmarshal(jsonConfig, ¶ms)
@@ -1443,31 +1531,32 @@ func federatedYumHandler(servicesManager artifactory.ArtifactoryServicesManager,
}
var virtualRepoHandlers = map[string]repoHandler{
- Maven: virtualMavenHandler,
- Gradle: virtualGradleHandler,
- Ivy: virtualIvyHandler,
- Sbt: virtualSbtHandler,
- Helm: virtualHelmHandler,
- Rpm: virtualRpmHandler,
- Nuget: virtualNugetHandler,
- Cran: virtualCranHandler,
- Gems: virtualGemsHandler,
- Npm: virtualNpmHandler,
- Bower: virtualBowerHandler,
- Debian: virtualDebianHandler,
- Pypi: virtualPypiHandler,
- Docker: virtualDockerHandler,
- Gitlfs: virtualGitLfsHandler,
- Go: virtualGoHandler,
- Yum: virtualYumHandler,
- Conan: virtualConanHandler,
- Chef: virtualChefHandler,
- Puppet: virtualPuppetHandler,
- Conda: virtualCondaHandler,
- P2: virtualP2Handler,
- Alpine: virtualAlpineHandler,
- Generic: virtualGenericHandler,
- Swift: virtualSwiftHandler,
+ Maven: virtualMavenHandler,
+ Gradle: virtualGradleHandler,
+ Ivy: virtualIvyHandler,
+ Sbt: virtualSbtHandler,
+ Helm: virtualHelmHandler,
+ Rpm: virtualRpmHandler,
+ Nuget: virtualNugetHandler,
+ Cran: virtualCranHandler,
+ Gems: virtualGemsHandler,
+ Npm: virtualNpmHandler,
+ Bower: virtualBowerHandler,
+ Debian: virtualDebianHandler,
+ Pypi: virtualPypiHandler,
+ Docker: virtualDockerHandler,
+ Gitlfs: virtualGitLfsHandler,
+ Go: virtualGoHandler,
+ Yum: virtualYumHandler,
+ Conan: virtualConanHandler,
+ Chef: virtualChefHandler,
+ Puppet: virtualPuppetHandler,
+ Conda: virtualCondaHandler,
+ P2: virtualP2Handler,
+ Alpine: virtualAlpineHandler,
+ Generic: virtualGenericHandler,
+ Swift: virtualSwiftHandler,
+ Terraform: virtualTerraformHandler,
}
func virtualMavenHandler(servicesManager artifactory.ArtifactoryServicesManager, jsonConfig []byte, isUpdate bool) error {
@@ -1806,6 +1895,20 @@ func virtualSwiftHandler(servicesManager artifactory.ArtifactoryServicesManager,
return err
}
+func virtualTerraformHandler(servicesManager artifactory.ArtifactoryServicesManager, jsonConfig []byte, isUpdate bool) error {
+ params := services.NewTerraformVirtualRepositoryParams()
+ err := json.Unmarshal(jsonConfig, ¶ms)
+ if errorutils.CheckError(err) != nil {
+ return err
+ }
+ if isUpdate {
+ err = servicesManager.UpdateVirtualRepository().Terraform(params)
+ } else {
+ err = servicesManager.CreateVirtualRepository().Terraform(params)
+ }
+ return err
+}
+
func virtualGenericHandler(servicesManager artifactory.ArtifactoryServicesManager, jsonConfig []byte, isUpdate bool) error {
params := services.NewGenericVirtualRepositoryParams()
err := json.Unmarshal(jsonConfig, ¶ms)
diff --git a/artifactory/commands/repository/template.go b/artifactory/commands/repository/template.go
index b19e59c9d..f046b1041 100644
--- a/artifactory/commands/repository/template.go
+++ b/artifactory/commands/repository/template.go
@@ -53,23 +53,24 @@ const (
BlockPushingSchema1 = "blockPushingSchema1"
// Mutual local and virtual repository configuration JSON keys
- DebianTrivialLayout = "debianTrivialLayout"
+ DebianTrivialLayout = "debianTrivialLayout"
+ OptionalIndexCompressionFormats = "optionalIndexCompressionFormats"
+ PrimaryKeyPairRef = "primaryKeyPairRef"
// Mutual remote and virtual repository configuration JSON keys
ExternalDependenciesEnabled = "externalDependenciesEnabled"
ExternalDependenciesPatterns = "externalDependenciesPatterns"
// Unique local repository configuration JSON keys
- ChecksumPolicyType = "checksumPolicyType"
- MaxUniqueTags = "maxUniqueTags"
- SnapshotVersionBehavior = "snapshotVersionBehavior"
- ArchiveBrowsingEnabled = "archiveBrowsingEnabled"
- CalculateYumMetadata = "calculateYumMetadata"
- YumRootDepth = "yumRootDepth"
- DockerApiVersion = "dockerApiVersion"
- EnableFileListsIndexing = "enableFileListsIndexing"
- OptionalIndexCompressionFormats = "optionalIndexCompressionFormats"
- ForceNugetAuthentication = "forceNugetAuthentication"
+ ChecksumPolicyType = "checksumPolicyType"
+ MaxUniqueTags = "maxUniqueTags"
+ SnapshotVersionBehavior = "snapshotVersionBehavior"
+ ArchiveBrowsingEnabled = "archiveBrowsingEnabled"
+ CalculateYumMetadata = "calculateYumMetadata"
+ YumRootDepth = "yumRootDepth"
+ DockerApiVersion = "dockerApiVersion"
+ EnableFileListsIndexing = "enableFileListsIndexing"
+ ForceNugetAuthentication = "forceNugetAuthentication"
// Unique remote repository configuration JSON keys
Url = "url"
@@ -158,6 +159,8 @@ const (
Conda = "conda"
P2 = "p2"
Swift = "swift"
+ Terraform = "terraform"
+ Cargo = "cargo"
// Repo layout Refs
BowerDefaultRepoLayout = "bower-default"
@@ -251,6 +254,7 @@ var optionalSuggestsMap = map[string]prompt.Suggest{
Username: {Text: Username},
Password: {Text: Password},
Proxy: {Text: Proxy},
+ PrimaryKeyPairRef: {Text: PrimaryKeyPairRef},
RemoteRepoChecksumPolicyType: {Text: RemoteRepoChecksumPolicyType},
HardFail: {Text: HardFail},
Offline: {Text: Offline},
@@ -306,7 +310,7 @@ var mavenGradleLocalRepoConfKeys = []string{
}
var rpmLocalRepoConfKeys = []string{
- YumRootDepth, CalculateYumMetadata, EnableFileListsIndexing,
+ YumRootDepth, CalculateYumMetadata, EnableFileListsIndexing, PrimaryKeyPairRef,
}
var nugetLocalRepoConfKeys = []string{
@@ -314,7 +318,7 @@ var nugetLocalRepoConfKeys = []string{
}
var debianLocalRepoConfKeys = []string{
- DebianTrivialLayout,
+ DebianTrivialLayout, PrimaryKeyPairRef,
}
var dockerLocalRepoConfKeys = []string{
@@ -388,7 +392,7 @@ var vcsRemoteRepoConfKeys = []string{
var baseVirtualRepoConfKeys = []string{
Repositories, Description, Notes, IncludePatterns, ExcludePatterns, RepoLayoutRef, ProjectKey, Environment, ArtifactoryRequestsCanRetrieveRemoteArtifacts,
- DefaultDeploymentRepo,
+ DefaultDeploymentRepo, OptionalIndexCompressionFormats, PrimaryKeyPairRef,
}
var mavenGradleVirtualRepoConfKeys = []string{
@@ -851,11 +855,12 @@ var questionMap = map[string]ioutils.QuestionInfo{
Msg: "Enter a comma separated list of values from " + strings.Join([]string{Bz2Compression, LzmaCompression, XzCompression}, ","),
Options: nil,
AllowVars: true,
- Writer: ioutils.WriteStringArrayAnswer,
+ Writer: ioutils.WriteStringAnswer,
},
- Username: ioutils.FreeStringQuestionInfo,
- Password: ioutils.FreeStringQuestionInfo,
- Proxy: ioutils.FreeStringQuestionInfo,
+ PrimaryKeyPairRef: ioutils.FreeStringQuestionInfo,
+ Username: ioutils.FreeStringQuestionInfo,
+ Password: ioutils.FreeStringQuestionInfo,
+ Proxy: ioutils.FreeStringQuestionInfo,
RemoteRepoChecksumPolicyType: {
Options: []prompt.Suggest{
{Text: GenerateIfAbsentPolicy},
diff --git a/artifactory/utils/repositoryutils.go b/artifactory/utils/repositoryutils.go
index 20efbdf7d..db8a46e69 100644
--- a/artifactory/utils/repositoryutils.go
+++ b/artifactory/utils/repositoryutils.go
@@ -65,16 +65,13 @@ func GetRepositories(artDetails *config.ServerDetails, repoTypes ...RepoType) ([
if err != nil {
return nil, err
}
- if len(repoTypes) == 0 {
- return GetFilteredRepositoriesByName(sm, nil, nil)
- }
repos := []string{}
for _, repoType := range repoTypes {
- repoKey, err := GetFilteredRepositoriesByNameAndType(sm, nil, nil, repoType)
+ filteredRepos, err := GetFilteredRepositoriesByNameAndType(sm, nil, nil, repoType)
if err != nil {
return repos, err
}
- repos = append(repos, repoKey...)
+ repos = append(repos, filteredRepos...)
}
return repos, nil
diff --git a/common/commands/configfile.go b/common/commands/configfile.go
index be265e761..a7e4518ba 100644
--- a/common/commands/configfile.go
+++ b/common/commands/configfile.go
@@ -152,27 +152,23 @@ func handleInteractiveConfigCreation(configFile *ConfigFile, confType project.Pr
}
switch confType {
case project.Go:
- err = configFile.configGo()
- case project.Pip:
- err = configFile.configPip()
- case project.Pipenv:
- err = configFile.configPipenv()
- case project.Poetry:
- err = configFile.configPoetry()
+ return configFile.setDeployerResolver()
+ case project.Pip, project.Pipenv, project.Poetry:
+ return configFile.setResolver(false)
case project.Yarn:
- err = configFile.configYarn()
+ return configFile.setResolver(false)
case project.Npm:
- err = configFile.configNpm()
+ return configFile.setDeployerResolver()
case project.Nuget, project.Dotnet:
- err = configFile.configDotnet()
+ return configFile.configDotnet()
case project.Maven:
- err = configFile.configMaven()
+ return configFile.configMaven()
case project.Gradle:
- err = configFile.configGradle()
+ return configFile.configGradle()
case project.Terraform:
- err = configFile.configTerraform()
+ return configFile.setResolver(false)
}
- return errorutils.CheckError(err)
+ return
}
func writeConfigFile(configFile *ConfigFile, destination string) (err error) {
@@ -394,32 +390,8 @@ func (configFile *ConfigFile) VerifyConfigFile(configFilePath string) error {
return errorutils.CheckError(os.Remove(configFilePath))
}
-func (configFile *ConfigFile) configGo() error {
- return configFile.setDeployerResolver()
-}
-
-func (configFile *ConfigFile) configPip() error {
- return configFile.setResolver()
-}
-
-func (configFile *ConfigFile) configPipenv() error {
- return configFile.setResolver()
-}
-
-func (configFile *ConfigFile) configPoetry() error {
- return configFile.setResolver()
-}
-
-func (configFile *ConfigFile) configYarn() error {
- return configFile.setResolver()
-}
-
-func (configFile *ConfigFile) configNpm() error {
- return configFile.setDeployerResolver()
-}
-
func (configFile *ConfigFile) configDotnet() error {
- if err := configFile.setResolver(); err != nil {
+ if err := configFile.setResolver(false); err != nil {
return err
}
if configFile.Resolver.ServerId != "" {
@@ -429,21 +401,10 @@ func (configFile *ConfigFile) configDotnet() error {
}
func (configFile *ConfigFile) configMaven() error {
- // Set resolution repositories
- if err := configFile.setResolverId(); err != nil {
- return err
- }
- if configFile.Resolver.ServerId != "" {
- configFile.setRepo(&configFile.Resolver.ReleaseRepo, "Set resolution repository for release dependencies", configFile.Resolver.ServerId, utils.Remote)
- configFile.setRepo(&configFile.Resolver.SnapshotRepo, "Set resolution repository for snapshot dependencies", configFile.Resolver.ServerId, utils.Remote)
- }
- // Set deployment repositories
- if err := configFile.setDeployerId(); err != nil {
+ if err := configFile.setDeployerResolverWithSnapshot(); err != nil {
return err
}
if configFile.Deployer.ServerId != "" {
- configFile.setRepo(&configFile.Deployer.ReleaseRepo, "Set repository for release artifacts deployment", configFile.Deployer.ServerId, utils.Local)
- configFile.setRepo(&configFile.Deployer.SnapshotRepo, "Set repository for snapshot artifacts deployment", configFile.Deployer.ServerId, utils.Local)
configFile.setIncludeExcludePatterns()
}
configFile.UseWrapper = coreutils.AskYesNo("Use Maven wrapper?", true)
@@ -494,11 +455,7 @@ func (configFile *ConfigFile) readGradleGlobalConfig() {
configFile.UseWrapper = coreutils.AskYesNo("Use Gradle wrapper?", true)
}
-func (configFile *ConfigFile) configTerraform() error {
- return configFile.setDeployer()
-}
-
-func (configFile *ConfigFile) setDeployer() error {
+func (configFile *ConfigFile) setDeployer(withSnapshot bool) error {
// Set deployer id
if err := configFile.setDeployerId(); err != nil {
return err
@@ -506,28 +463,57 @@ func (configFile *ConfigFile) setDeployer() error {
// Set deployment repository
if configFile.Deployer.ServerId != "" {
- configFile.setRepo(&configFile.Deployer.Repo, "Set repository for artifacts deployment", configFile.Deployer.ServerId, utils.Local)
+ deployerRepos, err := getRepositories(configFile.Deployer.ServerId, utils.Virtual, utils.Local)
+ if err != nil {
+ log.Error("failed getting repositories list: " + err.Error())
+ // Continue without auto complete.
+ deployerRepos = []string{}
+ }
+ if withSnapshot {
+ configFile.setRepo(&configFile.Deployer.SnapshotRepo, "Set repository for release artifacts deployment", deployerRepos)
+ configFile.setRepo(&configFile.Deployer.SnapshotRepo, "Set repository for snapshot artifacts deployment", deployerRepos)
+ } else {
+ configFile.setRepo(&configFile.Deployer.Repo, "Set repository for artifacts deployment", deployerRepos)
+ }
}
return nil
}
-func (configFile *ConfigFile) setResolver() error {
+func (configFile *ConfigFile) setResolver(withSnapshot bool) error {
// Set resolver id
if err := configFile.setResolverId(); err != nil {
return err
}
// Set resolution repository
if configFile.Resolver.ServerId != "" {
- configFile.setRepo(&configFile.Resolver.Repo, "Set repository for dependencies resolution", configFile.Resolver.ServerId, utils.Remote)
+ resolverRepos, err := getRepositories(configFile.Resolver.ServerId, utils.Virtual, utils.Remote)
+ if err != nil {
+ log.Error("failed getting repositories list: " + err.Error())
+ // Continue without auto complete.
+ resolverRepos = []string{}
+ }
+ if withSnapshot {
+ configFile.setRepo(&configFile.Resolver.SnapshotRepo, "Set resolution repository for release dependencies", resolverRepos)
+ configFile.setRepo(&configFile.Resolver.SnapshotRepo, "Set resolution repository for snapshot dependencies", resolverRepos)
+ } else {
+ configFile.setRepo(&configFile.Resolver.Repo, "Set resolution repository for dependencies resolution", resolverRepos)
+ }
}
return nil
}
func (configFile *ConfigFile) setDeployerResolver() error {
- if err := configFile.setResolver(); err != nil {
+ if err := configFile.setResolver(false); err != nil {
return err
}
- return configFile.setDeployer()
+ return configFile.setDeployer(false)
+}
+
+func (configFile *ConfigFile) setDeployerResolverWithSnapshot() error {
+ if err := configFile.setResolver(true); err != nil {
+ return err
+ }
+ return configFile.setDeployer(true)
}
func (configFile *ConfigFile) setResolverId() error {
@@ -544,9 +530,13 @@ func (configFile *ConfigFile) setServerId(serverId *string, useArtifactoryQuesti
return err
}
-func (configFile *ConfigFile) setRepo(repo *string, message string, serverId string, repoType utils.RepoType) {
+func (configFile *ConfigFile) setRepo(repo *string, promptPrefix string, availableRepos []string) {
if *repo == "" {
- *repo = readRepo(message+ioutils.PressTabMsg, serverId, repoType, utils.Virtual)
+ if len(availableRepos) > 0 {
+ *repo = ioutils.AskFromListWithMismatchConfirmation(promptPrefix, "Repository not found.", ioutils.ConvertToSuggests(availableRepos))
+ } else {
+ *repo = ioutils.AskString("", promptPrefix, false, false)
+ }
}
}
@@ -635,19 +625,6 @@ func readArtifactoryServer(useArtifactoryQuestion string) (string, error) {
return ioutils.AskFromList("", "Set Artifactory server ID", false, ioutils.ConvertToSuggests(serversIds), defaultServer), nil
}
-func readRepo(promptPrefix string, serverId string, repoTypes ...utils.RepoType) string {
- availableRepos, err := getRepositories(serverId, repoTypes...)
- if err != nil {
- log.Error("failed getting repositories list: " + err.Error())
- // Continue without auto complete.
- availableRepos = []string{}
- }
- if len(availableRepos) > 0 {
- return ioutils.AskFromListWithMismatchConfirmation(promptPrefix, "Repository not found.", ioutils.ConvertToSuggests(availableRepos))
- }
- return ioutils.AskString("", promptPrefix, false, false)
-}
-
func getServersIdAndDefault() ([]string, string, error) {
allConfigs, err := config.GetAllServersConfigs()
if err != nil {
diff --git a/common/project/projectconfig.go b/common/project/projectconfig.go
index 89bc25309..19422aea6 100644
--- a/common/project/projectconfig.go
+++ b/common/project/projectconfig.go
@@ -31,6 +31,7 @@ const (
Pipenv
Poetry
Npm
+ Pnpm
Yarn
Nuget
Maven
@@ -53,6 +54,7 @@ var ProjectTypes = []string{
"pipenv",
"poetry",
"npm",
+ "pnpm",
"yarn",
"nuget",
"maven",
diff --git a/go.mod b/go.mod
index 9977aad09..9110b805e 100644
--- a/go.mod
+++ b/go.mod
@@ -9,12 +9,12 @@ require (
github.com/chzyer/readline v1.5.1
github.com/forPelevin/gomoji v1.1.8
github.com/gocarina/gocsv v0.0.0-20231116093920-b87c2d0e983a
- github.com/google/uuid v1.4.0
+ github.com/google/uuid v1.6.0
github.com/gookit/color v1.5.4
- github.com/jedib0t/go-pretty/v6 v6.5.3
- github.com/jfrog/build-info-go v1.9.21
- github.com/jfrog/gofrog v1.5.1
- github.com/jfrog/jfrog-client-go v1.36.0
+ github.com/jedib0t/go-pretty/v6 v6.5.4
+ github.com/jfrog/build-info-go v1.9.22
+ github.com/jfrog/gofrog v1.6.0
+ github.com/jfrog/jfrog-client-go v1.37.0
github.com/magiconair/properties v1.8.7
github.com/manifoldco/promptui v0.9.0
github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c
@@ -22,10 +22,10 @@ require (
github.com/stretchr/testify v1.8.4
github.com/urfave/cli v1.22.14
github.com/vbauerster/mpb/v7 v7.5.3
- golang.org/x/exp v0.0.0-20240119083558-1b970713d09a
- golang.org/x/mod v0.14.0
+ golang.org/x/exp v0.0.0-20240213143201-ec583247a57a
+ golang.org/x/mod v0.15.0
golang.org/x/sync v0.6.0
- golang.org/x/term v0.16.0
+ golang.org/x/term v0.17.0
golang.org/x/text v0.14.0
gopkg.in/yaml.v3 v3.0.1
)
@@ -33,13 +33,13 @@ require (
require (
dario.cat/mergo v1.0.0 // indirect
github.com/BurntSushi/toml v1.3.2 // indirect
- github.com/CycloneDX/cyclonedx-go v0.7.2 // indirect
+ github.com/CycloneDX/cyclonedx-go v0.8.0 // indirect
github.com/Microsoft/go-winio v0.6.1 // 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.1.0 // indirect
- github.com/cloudflare/circl v1.3.3 // indirect
+ github.com/cloudflare/circl v1.3.7 // 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
@@ -88,15 +88,15 @@ 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.18.0 // indirect
- golang.org/x/net v0.20.0 // indirect
- golang.org/x/sys v0.16.0 // indirect
- golang.org/x/tools v0.17.0 // indirect
+ golang.org/x/crypto v0.19.0 // indirect
+ golang.org/x/net v0.21.0 // indirect
+ golang.org/x/sys v0.17.0 // indirect
+ golang.org/x/tools v0.18.0 // indirect
gopkg.in/ini.v1 v1.67.0 // indirect
gopkg.in/warnings.v0 v0.1.2 // indirect
)
-// 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.20240218093454-1c352a93c23d
// 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 185260231..d6555e914 100644
--- a/go.sum
+++ b/go.sum
@@ -2,8 +2,8 @@ dario.cat/mergo v1.0.0 h1:AGCNq9Evsj31mOgNPcLyXc+4PNABt905YmuqPYYpBWk=
dario.cat/mergo v1.0.0/go.mod h1:uNxQE+84aUszobStD9th8a29P2fMDhsBdgRYvZOxGmk=
github.com/BurntSushi/toml v1.3.2 h1:o7IhLm0Msx3BaB+n3Ag7L8EVlByGnpq14C4YWiu/gL8=
github.com/BurntSushi/toml v1.3.2/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ=
-github.com/CycloneDX/cyclonedx-go v0.7.2 h1:kKQ0t1dPOlugSIYVOMiMtFqeXI2wp/f5DBIdfux8gnQ=
-github.com/CycloneDX/cyclonedx-go v0.7.2/go.mod h1:K2bA+324+Og0X84fA8HhN2X066K7Bxz4rpMQ4ZhjtSk=
+github.com/CycloneDX/cyclonedx-go v0.8.0 h1:FyWVj6x6hoJrui5uRQdYZcSievw3Z32Z88uYzG/0D6M=
+github.com/CycloneDX/cyclonedx-go v0.8.0/go.mod h1:K2bA+324+Og0X84fA8HhN2X066K7Bxz4rpMQ4ZhjtSk=
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=
@@ -32,8 +32,9 @@ github.com/chzyer/readline v1.5.1/go.mod h1:Eh+b79XXUwfKfcPLepksvw2tcLE/Ct21YObk
github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU=
github.com/chzyer/test v1.0.0 h1:p3BQDXSxOhOG0P9z6/hGnII4LGiEPOYBhs8asl/fC04=
github.com/chzyer/test v1.0.0/go.mod h1:2JlltgoNkt4TW/z9V/IzDdFaMTM2JPIi26O1pF38GC8=
-github.com/cloudflare/circl v1.3.3 h1:fE/Qz0QdIGqeWfnwq0RE0R7MI51s0M2E4Ga9kq5AEMs=
github.com/cloudflare/circl v1.3.3/go.mod h1:5XYMA4rFBvNIrhs50XuiBJ15vF2pZn4nnUKZrLbUZFA=
+github.com/cloudflare/circl v1.3.7 h1:qlCDlTPz2n9fu58M0Nh1J/JzcFpfgkFHHX3O35r5vcU=
+github.com/cloudflare/circl v1.3.7/go.mod h1:sRTcRWXGLrKw6yIGJ+l7amYJFfAXbZG0kBSc8r4zxgA=
github.com/cpuguy83/go-md2man/v2 v2.0.2 h1:p1EgwI/C7NhT0JmVkwCD2ZBK8j4aeHQX2pMHHBfMQ6w=
github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
github.com/cyphar/filepath-securejoin v0.2.4 h1:Ugdm7cg7i6ZK6x3xDF1oEu1nfkyfH53EtKeQYTC3kyg=
@@ -70,24 +71,24 @@ github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da/go.mod h1:cIg4er
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.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
-github.com/google/uuid v1.4.0 h1:MtMxsa51/r9yyhkyLsVeVt0B+BGQZzpQiTQ4eHZ8bc4=
-github.com/google/uuid v1.4.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
+github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
+github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/gookit/color v1.5.4 h1:FZmqs7XOyGgCAxmWyPslpiok1k05wmY3SJTytgvYFs0=
github.com/gookit/color v1.5.4/go.mod h1:pZJOeOS8DM43rXbp4AZo1n9zCU2qjpcRko0b6/QJi9w=
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.5.3 h1:GIXn6Er/anHTkVUoufs7ptEvxdD6KIhR7Axa2wYCPF0=
-github.com/jedib0t/go-pretty/v6 v6.5.3/go.mod h1:5LQIxa52oJ/DlDSLv0HEkWOFMDGoWkJb9ss5KqPpJBg=
+github.com/jedib0t/go-pretty/v6 v6.5.4 h1:gOGo0613MoqUcf0xCj+h/V3sHDaZasfv152G6/5l91s=
+github.com/jedib0t/go-pretty/v6 v6.5.4/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-client-go v1.36.0 h1:iODLDjYSlK7rLH8/lEmAFHwYsboeBfaqxXybz6waraE=
-github.com/jfrog/jfrog-client-go v1.36.0/go.mod h1:y1WF6eiZ7V2DortiwjpMEicEH6NIJH+hOXI5QI2W3NU=
+github.com/jfrog/build-info-go v1.9.22 h1:+RPM8OJvgBvOo+PYPnVYkg+S3hl1JlyCJn/aGxLqRMI=
+github.com/jfrog/build-info-go v1.9.22/go.mod h1:QHcKuesY4MrBVBuEwwBz4uIsX6mwYuMEDV09ng4AvAU=
+github.com/jfrog/gofrog v1.6.0 h1:jOwb37nHY2PnxePNFJ6e6279Pgkr3di05SbQQw47Mq8=
+github.com/jfrog/gofrog v1.6.0/go.mod h1:SZ1EPJUruxrVGndOzHd+LTiwWYKMlHqhKD+eu+v5Hqg=
+github.com/jfrog/jfrog-client-go v1.37.0 h1:ULHMGfST0ONH8Ur4dkfMMVsuvxLWBHral7Y1Oi7ub0k=
+github.com/jfrog/jfrog-client-go v1.37.0/go.mod h1:kLlNc4BLpYtH2I0hHB5AcIwx6mEw1gQg65amvrY2DHM=
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/klauspost/compress v1.4.1/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A=
@@ -210,14 +211,14 @@ 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.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/crypto v0.19.0 h1:ENy+Az/9Y1vSrlrvBSyna3PITt4tiZLf7sgCjZBX7Wo=
+golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU=
+golang.org/x/exp v0.0.0-20240213143201-ec583247a57a h1:HinSgX1tJRX3KsL//Gxynpw5CTOAIPhgL4W8PNiIpVE=
+golang.org/x/exp v0.0.0-20240213143201-ec583247a57a/go.mod h1:CxmFvTBINI24O/j8iY7H1xHzx2i4OsyguNBmN/uPtqc=
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
-golang.org/x/mod v0.14.0 h1:dGoOF9QVLYng8IHTm7BAyWqCqSheQ5pYWGhzW00YJr0=
-golang.org/x/mod v0.14.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
+golang.org/x/mod v0.15.0 h1:SernR4v+D55NyBH2QiEQrlBAnj1ECL6AGrA5+dPaMY8=
+golang.org/x/mod v0.15.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
@@ -225,8 +226,8 @@ 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.20.0 h1:aCL9BSgETF1k+blQaYUBx9hJ9LOGP3gAVemcZlf1Kpo=
-golang.org/x/net v0.20.0/go.mod h1:z8BVo6PvndSri0LbOE3hAn0apkU+1YvI6E70E9jsnvY=
+golang.org/x/net v0.21.0 h1:AQyQV4dYCvJ7vGmJyKki9+PBdyvhkSd8EIx/qb0AYv4=
+golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44=
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-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
@@ -259,15 +260,15 @@ 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.16.0 h1:xWw16ngr6ZMtmxDyKyIgsE93KNKz5HKmMa3b8ALHidU=
-golang.org/x/sys v0.16.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
+golang.org/x/sys v0.17.0 h1:25cE3gD+tdBA7lp7QfhuV+rJiE9YXTcS3VG1SqssI/Y=
+golang.org/x/sys v0.17.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.16.0 h1:m+B6fahuftsE9qjo0VWp2FW0mB3MTJvR0BaMQrq0pmE=
-golang.org/x/term v0.16.0/go.mod h1:yn7UURbUtPyrVJPGPq404EukNFxcm/foM+bV/bfcDsY=
+golang.org/x/term v0.17.0 h1:mkTF7LCd6WGJNL3K1Ad7kwxNfYAW6a8a8QqtMblp/4U=
+golang.org/x/term v0.17.0/go.mod h1:lLRBjIVuehSbZlaOtGMbcMncT+aqLLLmKrsjNrUguwk=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
@@ -281,8 +282,8 @@ golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGm
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
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.17.0 h1:FvmRgNOcs3kOa+T20R1uhfP9F6HgG2mfxDv1vrx1Htc=
-golang.org/x/tools v0.17.0/go.mod h1:xsh6VxdV005rRVaS6SSAf9oiAqljS7UZUacMZ8Bnsps=
+golang.org/x/tools v0.18.0 h1:k8NLag8AGHnn+PHbl7g43CtqZAwG60vZkLqgyZgIHgQ=
+golang.org/x/tools v0.18.0/go.mod h1:GL7B4CwcLLeo59yx/9UWWuNOW1n3VZ4f5axWfML7Lcg=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
diff --git a/lifecycle/common.go b/lifecycle/common.go
index 55e7ef771..e185cb578 100644
--- a/lifecycle/common.go
+++ b/lifecycle/common.go
@@ -19,7 +19,8 @@ type releaseBundleCmd struct {
rbProjectKey string
}
-func (rbc *releaseBundleCmd) getPrerequisites() (servicesManager *lifecycle.LifecycleServicesManager, rbDetails services.ReleaseBundleDetails, params services.CreateOrPromoteReleaseBundleParams, err error) {
+func (rbc *releaseBundleCmd) getPrerequisites() (servicesManager *lifecycle.LifecycleServicesManager,
+ rbDetails services.ReleaseBundleDetails, queryParams services.CommonOptionalQueryParams, err error) {
servicesManager, err = utils.CreateLifecycleServiceManager(rbc.serverDetails, false)
if err != nil {
return
@@ -28,12 +29,9 @@ func (rbc *releaseBundleCmd) getPrerequisites() (servicesManager *lifecycle.Life
ReleaseBundleName: rbc.releaseBundleName,
ReleaseBundleVersion: rbc.releaseBundleVersion,
}
- params = services.CreateOrPromoteReleaseBundleParams{
- ReleaseBundleQueryParams: services.ReleaseBundleQueryParams{
- ProjectKey: rbc.rbProjectKey,
- Async: !rbc.sync,
- },
- SigningKeyName: rbc.signingKeyName,
+ queryParams = services.CommonOptionalQueryParams{
+ ProjectKey: rbc.rbProjectKey,
+ Async: !rbc.sync,
}
return
}
diff --git a/lifecycle/createcommon.go b/lifecycle/createcommon.go
index 5149a82a7..4d5fba599 100644
--- a/lifecycle/createcommon.go
+++ b/lifecycle/createcommon.go
@@ -67,13 +67,13 @@ func (rbc *ReleaseBundleCreateCommand) Run() error {
return err
}
- servicesManager, rbDetails, params, err := rbc.getPrerequisites()
+ servicesManager, rbDetails, queryParams, err := rbc.getPrerequisites()
if err != nil {
return err
}
if rbc.buildsSpecPath != "" {
- return rbc.createFromBuilds(servicesManager, rbDetails, params)
+ return rbc.createFromBuilds(servicesManager, rbDetails, queryParams)
}
- return rbc.createFromReleaseBundles(servicesManager, rbDetails, params)
+ return rbc.createFromReleaseBundles(servicesManager, rbDetails, queryParams)
}
diff --git a/lifecycle/createfrombuilds.go b/lifecycle/createfrombuilds.go
index f9a13ed2e..a955b997a 100644
--- a/lifecycle/createfrombuilds.go
+++ b/lifecycle/createfrombuilds.go
@@ -12,7 +12,7 @@ import (
)
func (rbc *ReleaseBundleCreateCommand) createFromBuilds(servicesManager *lifecycle.LifecycleServicesManager,
- rbDetails services.ReleaseBundleDetails, params services.CreateOrPromoteReleaseBundleParams) error {
+ rbDetails services.ReleaseBundleDetails, queryParams services.CommonOptionalQueryParams) error {
builds := CreateFromBuildsSpec{}
content, err := fileutils.ReadFile(rbc.buildsSpecPath)
@@ -31,13 +31,13 @@ func (rbc *ReleaseBundleCreateCommand) createFromBuilds(servicesManager *lifecyc
if err != nil {
return err
}
- return servicesManager.CreateReleaseBundleFromBuilds(rbDetails, params, buildsSource)
+ return servicesManager.CreateReleaseBundleFromBuilds(rbDetails, queryParams, rbc.signingKeyName, buildsSource)
}
func (rbc *ReleaseBundleCreateCommand) convertToBuildsSource(builds CreateFromBuildsSpec) (services.CreateFromBuildsSource, error) {
buildsSource := services.CreateFromBuildsSource{}
for _, build := range builds.Builds {
- buildSource := services.BuildSource{BuildName: build.Name}
+ buildSource := services.BuildSource{BuildName: build.Name, IncludeDependencies: build.IncludeDependencies}
buildNumber, err := rbc.getLatestBuildNumberIfEmpty(build.Name, build.Number, build.Project)
if err != nil {
return services.CreateFromBuildsSource{}, err
@@ -82,7 +82,8 @@ type CreateFromBuildsSpec struct {
}
type SourceBuildSpec struct {
- Name string `json:"name,omitempty"`
- Number string `json:"number,omitempty"`
- Project string `json:"project,omitempty"`
+ Name string `json:"name,omitempty"`
+ Number string `json:"number,omitempty"`
+ Project string `json:"project,omitempty"`
+ IncludeDependencies bool `json:"includeDependencies,omitempty"`
}
diff --git a/lifecycle/createfrombundles.go b/lifecycle/createfrombundles.go
index 872d76765..1e9253351 100644
--- a/lifecycle/createfrombundles.go
+++ b/lifecycle/createfrombundles.go
@@ -9,7 +9,7 @@ import (
)
func (rbc *ReleaseBundleCreateCommand) createFromReleaseBundles(servicesManager *lifecycle.LifecycleServicesManager,
- rbDetails services.ReleaseBundleDetails, params services.CreateOrPromoteReleaseBundleParams) error {
+ rbDetails services.ReleaseBundleDetails, queryParams services.CommonOptionalQueryParams) error {
bundles := CreateFromReleaseBundlesSpec{}
content, err := fileutils.ReadFile(rbc.releaseBundlesSpecPath)
@@ -25,7 +25,7 @@ func (rbc *ReleaseBundleCreateCommand) createFromReleaseBundles(servicesManager
}
releaseBundlesSource := rbc.convertToReleaseBundlesSource(bundles)
- return servicesManager.CreateReleaseBundleFromBundles(rbDetails, params, releaseBundlesSource)
+ return servicesManager.CreateReleaseBundleFromBundles(rbDetails, queryParams, rbc.signingKeyName, releaseBundlesSource)
}
func (rbc *ReleaseBundleCreateCommand) convertToReleaseBundlesSource(bundles CreateFromReleaseBundlesSpec) services.CreateFromReleaseBundlesSource {
diff --git a/lifecycle/promote.go b/lifecycle/promote.go
index 6958bae5a..0cf8b64d0 100644
--- a/lifecycle/promote.go
+++ b/lifecycle/promote.go
@@ -3,14 +3,16 @@ package lifecycle
import (
"encoding/json"
"github.com/jfrog/jfrog-cli-core/v2/utils/config"
+ "github.com/jfrog/jfrog-client-go/lifecycle/services"
"github.com/jfrog/jfrog-client-go/utils"
"github.com/jfrog/jfrog-client-go/utils/log"
)
type ReleaseBundlePromoteCommand struct {
releaseBundleCmd
- environment string
- overwrite bool
+ environment string
+ includeReposPatterns []string
+ excludeReposPatterns []string
}
func NewReleaseBundlePromoteCommand() *ReleaseBundlePromoteCommand {
@@ -52,8 +54,13 @@ func (rbp *ReleaseBundlePromoteCommand) SetEnvironment(environment string) *Rele
return rbp
}
-func (rbp *ReleaseBundlePromoteCommand) SetOverwrite(overwrite bool) *ReleaseBundlePromoteCommand {
- rbp.overwrite = overwrite
+func (rbp *ReleaseBundlePromoteCommand) SetIncludeReposPatterns(includeReposPatterns []string) *ReleaseBundlePromoteCommand {
+ rbp.includeReposPatterns = includeReposPatterns
+ return rbp
+}
+
+func (rbp *ReleaseBundlePromoteCommand) SetExcludeReposPatterns(excludeReposPatterns []string) *ReleaseBundlePromoteCommand {
+ rbp.excludeReposPatterns = excludeReposPatterns
return rbp
}
@@ -70,12 +77,18 @@ func (rbp *ReleaseBundlePromoteCommand) Run() error {
return err
}
- servicesManager, rbDetails, params, err := rbp.getPrerequisites()
+ servicesManager, rbDetails, queryParams, err := rbp.getPrerequisites()
if err != nil {
return err
}
- promotionResp, err := servicesManager.PromoteReleaseBundle(rbDetails, params, rbp.environment, rbp.overwrite)
+ promotionParams := services.RbPromotionParams{
+ Environment: rbp.environment,
+ IncludedRepositoryKeys: rbp.includeReposPatterns,
+ ExcludedRepositoryKeys: rbp.excludeReposPatterns,
+ }
+
+ promotionResp, err := servicesManager.PromoteReleaseBundle(rbDetails, queryParams, rbp.signingKeyName, promotionParams)
if err != nil {
return err
}
diff --git a/plugins/common/config.go b/plugins/common/config.go
index 8e22a2f3e..a906321ab 100644
--- a/plugins/common/config.go
+++ b/plugins/common/config.go
@@ -14,10 +14,9 @@ import (
// Any empty configuration could be later overridden by environment variables if set.
func CreateBuildConfiguration(c *components.Context) *build.BuildConfiguration {
buildConfiguration := new(build.BuildConfiguration)
- buildNameArg, buildNumberArg := c.Arguments[0], c.Arguments[1]
- if buildNameArg == "" || buildNumberArg == "" {
- buildNameArg = ""
- buildNumberArg = ""
+ var buildNameArg, buildNumberArg string
+ if len(c.Arguments) > 1 && c.Arguments[0] != "" && c.Arguments[1] != "" {
+ buildNameArg, buildNumberArg = c.Arguments[0], c.Arguments[1]
}
buildConfiguration.SetBuildName(buildNameArg).SetBuildNumber(buildNumberArg).SetProject(c.GetStringFlagValue("project")).SetModule(c.GetStringFlagValue("module"))
return buildConfiguration
diff --git a/tests/testdata/maven-example-with-many-types/pom.xml b/tests/testdata/maven-example-with-many-types/pom.xml
new file mode 100644
index 000000000..6d2096c96
--- /dev/null
+++ b/tests/testdata/maven-example-with-many-types/pom.xml
@@ -0,0 +1,53 @@
+
+ 4.0.0
+
+ org.jfrog
+ cli-test
+ 1.0
+ jar
+
+ cli-test
+ http://maven.apache.org
+
+
+ UTF-8
+ 1.8
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-compiler-plugin
+ 3.1
+
+
+ ${java.version}
+
+
+
+
+
+
+
+ junit
+ junit
+ 4.11
+ test
+
+
+ commons-io
+ commons-io
+ 1.2
+ test
+
+
+ org.webjars
+ lodash
+ 4.17.21
+ pom
+
+
+
\ No newline at end of file
diff --git a/utils/coreutils/techutils.go b/utils/coreutils/techutils.go
index 78e2321e6..ca63dc653 100644
--- a/utils/coreutils/techutils.go
+++ b/utils/coreutils/techutils.go
@@ -24,6 +24,7 @@ const (
Maven Technology = "maven"
Gradle Technology = "gradle"
Npm Technology = "npm"
+ Pnpm Technology = "pnpm"
Yarn Technology = "yarn"
Go Technology = "go"
Pip Technology = "pip"
@@ -77,7 +78,7 @@ var technologiesData = map[Technology]TechData{
},
Npm: {
indicators: []string{"package.json", "package-lock.json", "npm-shrinkwrap.json"},
- exclude: []string{".yarnrc.yml", "yarn.lock", ".yarn"},
+ exclude: []string{"pnpm-lock.yaml", ".yarnrc.yml", "yarn.lock", ".yarn"},
ciSetupSupport: true,
packageDescriptors: []string{"package.json"},
formal: string(Npm),
@@ -85,8 +86,16 @@ var technologiesData = map[Technology]TechData{
packageInstallationCommand: "install",
applicabilityScannable: true,
},
+ Pnpm: {
+ indicators: []string{"pnpm-lock.yaml"},
+ exclude: []string{".yarnrc.yml", "yarn.lock", ".yarn"},
+ packageDescriptors: []string{"package.json"},
+ packageVersionOperator: "@",
+ applicabilityScannable: true,
+ },
Yarn: {
indicators: []string{".yarnrc.yml", "yarn.lock", ".yarn", ".yarnrc"},
+ exclude: []string{"pnpm-lock.yaml"},
packageDescriptors: []string{"package.json"},
packageVersionOperator: "@",
applicabilityScannable: true,
diff --git a/utils/coreutils/techutils_test.go b/utils/coreutils/techutils_test.go
index 7d170b9da..c69d58ebe 100644
--- a/utils/coreutils/techutils_test.go
+++ b/utils/coreutils/techutils_test.go
@@ -17,6 +17,7 @@ func TestDetectTechnologiesByFilePaths(t *testing.T) {
}{
{"simpleMavenTest", []string{"pom.xml"}, map[Technology]bool{Maven: true}},
{"npmTest", []string{"../package.json"}, map[Technology]bool{Npm: true}},
+ {"pnpmTest", []string{"../package.json", "pnpm-lock.yaml"}, map[Technology]bool{Pnpm: true}},
{"yarnTest", []string{"./package.json", "./.yarn"}, map[Technology]bool{Yarn: true}},
{"windowsGradleTest", []string{"c:\\users\\test\\package\\build.gradle"}, map[Technology]bool{Gradle: true}},
{"windowsPipTest", []string{"c:\\users\\test\\package\\setup.py"}, map[Technology]bool{Pip: true}},
@@ -73,12 +74,19 @@ func TestMapFilesToRelevantWorkingDirectories(t *testing.T) {
},
expectedExcluded: noExclude,
},
+ {
+ name: "pnpmTest",
+ paths: []string{filepath.Join("dir", "package.json"), filepath.Join("dir", "pnpm-lock.yaml")},
+ requestedDescriptors: noRequest,
+ expectedWorkingDir: map[string][]string{"dir": {filepath.Join("dir", "package.json"), filepath.Join("dir", "pnpm-lock.yaml")}},
+ expectedExcluded: map[string][]Technology{"dir": {Npm, Yarn}},
+ },
{
name: "yarnTest",
paths: []string{filepath.Join("dir", "package.json"), filepath.Join("dir", ".yarn")},
requestedDescriptors: noRequest,
expectedWorkingDir: map[string][]string{"dir": {filepath.Join("dir", "package.json"), filepath.Join("dir", ".yarn")}},
- expectedExcluded: map[string][]Technology{"dir": {Npm}},
+ expectedExcluded: map[string][]Technology{"dir": {Npm, Pnpm}},
},
{
name: "golangTest",
@@ -138,13 +146,20 @@ func TestMapFilesToRelevantWorkingDirectories(t *testing.T) {
for _, test := range tests {
t.Run(test.name, func(t *testing.T) {
detectedWd, detectedExcluded := mapFilesToRelevantWorkingDirectories(test.paths, test.requestedDescriptors)
+ // Assert working directories
expectedKeys := maps.Keys(test.expectedWorkingDir)
actualKeys := maps.Keys(detectedWd)
assert.ElementsMatch(t, expectedKeys, actualKeys, "expected: %s, actual: %s", expectedKeys, actualKeys)
for key, value := range test.expectedWorkingDir {
assert.ElementsMatch(t, value, detectedWd[key], "expected: %s, actual: %s", value, detectedWd[key])
}
- assert.True(t, reflect.DeepEqual(test.expectedExcluded, detectedExcluded), "expected: %s, actual: %s", test.expectedExcluded, detectedExcluded)
+ // Assert excluded
+ expectedKeys = maps.Keys(test.expectedExcluded)
+ actualKeys = maps.Keys(detectedExcluded)
+ assert.ElementsMatch(t, expectedKeys, actualKeys, "expected: %s, actual: %s", expectedKeys, actualKeys)
+ for key, value := range test.expectedExcluded {
+ assert.ElementsMatch(t, value, detectedExcluded[key], "expected: %s, actual: %s", value, detectedExcluded[key])
+ }
})
}
}
@@ -178,6 +193,7 @@ func TestMapWorkingDirectoriesToTechnologies(t *testing.T) {
"dir": {filepath.Join("dir", "package.json"), filepath.Join("dir", "package-lock.json"), filepath.Join("dir", "build.gradle.kts"), filepath.Join("dir", "project.sln")},
"directory": {filepath.Join("directory", "npm-shrinkwrap.json")},
"dir3": {filepath.Join("dir3", "package.json"), filepath.Join("dir3", ".yarn")},
+ filepath.Join("dir3", "dir"): {filepath.Join("dir3", "dir", "package.json"), filepath.Join("dir3", "dir", "pnpm-lock.yaml")},
filepath.Join("dir", "dir2"): {filepath.Join("dir", "dir2", "go.mod")},
filepath.Join("users_dir", "test", "package"): {filepath.Join("users_dir", "test", "package", "setup.py")},
filepath.Join("users_dir", "test", "package2"): {filepath.Join("users_dir", "test", "package2", "requirements.txt")},
@@ -186,7 +202,8 @@ func TestMapWorkingDirectoriesToTechnologies(t *testing.T) {
},
excludedTechAtWorkingDir: map[string][]Technology{
filepath.Join("users", "test", "package"): {Pip},
- "dir3": {Npm},
+ "dir3": {Npm},
+ filepath.Join("dir3", "dir"): {Npm, Yarn},
},
requestedTechs: noRequestTech,
requestedDescriptors: noRequestSpecialDescriptors,
@@ -196,6 +213,7 @@ func TestMapWorkingDirectoriesToTechnologies(t *testing.T) {
"dir": {filepath.Join("dir", "package.json")},
"directory": {},
},
+ Pnpm: {filepath.Join("dir3", "dir"): {filepath.Join("dir3", "dir", "package.json")}},
Yarn: {"dir3": {filepath.Join("dir3", "package.json")}},
Go: {filepath.Join("dir", "dir2"): {filepath.Join("dir", "dir2", "go.mod")}},
Pip: {
@@ -354,6 +372,7 @@ func TestGetTechInformationFromWorkingDir(t *testing.T) {
"dir": {filepath.Join("dir", "package.json"), filepath.Join("dir", "package-lock.json"), filepath.Join("dir", "build.gradle.kts"), filepath.Join("dir", "project.sln"), filepath.Join("dir", "blabla.txt")},
"directory": {filepath.Join("directory", "npm-shrinkwrap.json")},
"dir3": {filepath.Join("dir3", "package.json"), filepath.Join("dir3", ".yarn")},
+ filepath.Join("dir3", "dir"): {filepath.Join("dir3", "dir", "package.json"), filepath.Join("dir3", "dir", "pnpm-lock.yaml")},
filepath.Join("dir", "dir2"): {filepath.Join("dir", "dir2", "go.mod")},
filepath.Join("users_dir", "test", "package"): {filepath.Join("users_dir", "test", "package", "setup.py")},
filepath.Join("users_dir", "test", "package2"): {filepath.Join("users_dir", "test", "package2", "requirements.txt")},
@@ -362,7 +381,8 @@ func TestGetTechInformationFromWorkingDir(t *testing.T) {
}
excludedTechAtWorkingDir := map[string][]Technology{
filepath.Join("users", "test", "package"): {Pip},
- "dir3": {Npm},
+ "dir3": {Npm, Pnpm},
+ filepath.Join("dir3", "dir"): {Npm, Yarn},
}
tests := []struct {
@@ -392,6 +412,12 @@ func TestGetTechInformationFromWorkingDir(t *testing.T) {
"directory": {},
},
},
+ {
+ name: "pnpmTest",
+ tech: Pnpm,
+ requestedDescriptors: map[Technology][]string{},
+ expected: map[string][]string{filepath.Join("dir3", "dir"): {filepath.Join("dir3", "dir", "package.json")}},
+ },
{
name: "yarnTest",
tech: Yarn,
diff --git a/utils/java/deptreemanager.go b/utils/java/deptreemanager.go
index 071e2192d..e323fad1e 100644
--- a/utils/java/deptreemanager.go
+++ b/utils/java/deptreemanager.go
@@ -5,7 +5,6 @@ import (
"os"
"strings"
- "github.com/jfrog/gofrog/datastructures"
"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/xray"
@@ -17,22 +16,20 @@ const (
GavPackageTypeIdentifier = "gav://"
)
-func BuildDependencyTree(serverDetails *config.ServerDetails, depsRepo string, useWrapper, isMavenDepTreeInstalled bool, tech coreutils.Technology) ([]*xrayUtils.GraphNode, []string, error) {
- depTreeParams := &DepTreeParams{
- UseWrapper: useWrapper,
- Server: serverDetails,
- DepsRepo: depsRepo,
- }
+func BuildDependencyTree(depTreeParams DepTreeParams, tech coreutils.Technology) ([]*xrayUtils.GraphNode, map[string][]string, error) {
if tech == coreutils.Maven {
- return buildMavenDependencyTree(depTreeParams, isMavenDepTreeInstalled)
+ return buildMavenDependencyTree(&depTreeParams)
}
- return buildGradleDependencyTree(depTreeParams)
+ return buildGradleDependencyTree(&depTreeParams)
}
type DepTreeParams struct {
- UseWrapper bool
- Server *config.ServerDetails
- DepsRepo string
+ UseWrapper bool
+ Server *config.ServerDetails
+ DepsRepo string
+ IsMavenDepTreeInstalled bool
+ IsCurationCmd bool
+ CurationCacheFolder string
}
type DepTreeManager struct {
@@ -47,36 +44,31 @@ func NewDepTreeManager(params *DepTreeParams) DepTreeManager {
// The structure of a dependency tree of a module in a Gradle/Maven project, as created by the gradle-dep-tree and maven-dep-tree plugins.
type moduleDepTree struct {
- Root string `json:"root"`
- Nodes map[string]depTreeNode `json:"nodes"`
-}
-
-type depTreeNode struct {
- Children []string `json:"children"`
+ Root string `json:"root"`
+ Nodes map[string]xray.DepTreeNode `json:"nodes"`
}
// Reads the output files of the gradle-dep-tree and maven-dep-tree plugins and returns them as a slice of GraphNodes.
// It takes the output of the plugin's run (which is a byte representation of a list of paths of the output files, separated by newlines) as input.
-func getGraphFromDepTree(outputFilePaths string) (depsGraph []*xrayUtils.GraphNode, uniqueDeps []string, err error) {
+func getGraphFromDepTree(outputFilePaths string) (depsGraph []*xrayUtils.GraphNode, uniqueDepsMap map[string][]string, err error) {
modules, err := parseDepTreeFiles(outputFilePaths)
if err != nil {
return
}
- allModulesUniqueDeps := datastructures.MakeSet[string]()
+ uniqueDepsMap = map[string][]string{}
for _, module := range modules {
moduleTree, moduleUniqueDeps := GetModuleTreeAndDependencies(module)
depsGraph = append(depsGraph, moduleTree)
- for _, depToAdd := range moduleUniqueDeps {
- allModulesUniqueDeps.Add(depToAdd)
+ for depToAdd, depTypes := range moduleUniqueDeps {
+ uniqueDepsMap[depToAdd] = depTypes
}
}
- uniqueDeps = allModulesUniqueDeps.ToSlice()
return
}
// Returns a dependency tree and a flat list of the module's dependencies for the given module
-func GetModuleTreeAndDependencies(module *moduleDepTree) (*xrayUtils.GraphNode, []string) {
- moduleTreeMap := make(map[string][]string)
+func GetModuleTreeAndDependencies(module *moduleDepTree) (*xrayUtils.GraphNode, map[string][]string) {
+ moduleTreeMap := make(map[string]xray.DepTreeNode)
moduleDeps := module.Nodes
for depName, dependency := range moduleDeps {
dependencyId := GavPackageTypeIdentifier + depName
@@ -85,8 +77,9 @@ func GetModuleTreeAndDependencies(module *moduleDepTree) (*xrayUtils.GraphNode,
childId := GavPackageTypeIdentifier + childName
childrenList = append(childrenList, childId)
}
- if len(childrenList) > 0 {
- moduleTreeMap[dependencyId] = childrenList
+ moduleTreeMap[dependencyId] = xray.DepTreeNode{
+ Types: dependency.Types,
+ Children: childrenList,
}
}
return xray.BuildXrayDependencyTree(moduleTreeMap, GavPackageTypeIdentifier+module.Root)
diff --git a/utils/java/gradle.go b/utils/java/gradle.go
index 013a2f3a6..57ceff8bd 100644
--- a/utils/java/gradle.go
+++ b/utils/java/gradle.go
@@ -56,7 +56,7 @@ type gradleDepTreeManager struct {
DepTreeManager
}
-func buildGradleDependencyTree(params *DepTreeParams) (dependencyTree []*xrayUtils.GraphNode, uniqueDeps []string, err error) {
+func buildGradleDependencyTree(params *DepTreeParams) (dependencyTree []*xrayUtils.GraphNode, uniqueDeps map[string][]string, err error) {
manager := &gradleDepTreeManager{DepTreeManager: NewDepTreeManager(params)}
outputFileContent, err := manager.runGradleDepTree()
if err != nil {
diff --git a/utils/java/mvn.go b/utils/java/mvn.go
index 56deee17c..5b38db6c0 100644
--- a/utils/java/mvn.go
+++ b/utils/java/mvn.go
@@ -7,6 +7,7 @@ import (
"net/url"
"os"
"os/exec"
+ "path"
"path/filepath"
"strings"
@@ -21,7 +22,7 @@ const (
mavenDepTreeJarFile = "maven-dep-tree.jar"
mavenDepTreeOutputFile = "mavendeptree.out"
// Changing this version also requires a change in MAVEN_DEP_TREE_VERSION within buildscripts/download_jars.sh
- mavenDepTreeVersion = "1.0.2"
+ mavenDepTreeVersion = "1.1.0"
settingsXmlFile = "settings.xml"
)
@@ -42,25 +43,31 @@ var mavenDepTreeJar []byte
type MavenDepTreeManager struct {
DepTreeManager
- isInstalled bool
- cmdName MavenDepTreeCmd
- settingsXmlPath string
+ isInstalled bool
+ // this flag its curation command, it will set dedicated cache and download url.
+ isCurationCmd bool
+ // path to the curation dedicated cache
+ curationCacheFolder string
+ cmdName MavenDepTreeCmd
+ settingsXmlPath string
}
-func NewMavenDepTreeManager(params *DepTreeParams, cmdName MavenDepTreeCmd, isDepTreeInstalled bool) *MavenDepTreeManager {
+func NewMavenDepTreeManager(params *DepTreeParams, cmdName MavenDepTreeCmd) *MavenDepTreeManager {
depTreeManager := NewDepTreeManager(&DepTreeParams{
Server: params.Server,
DepsRepo: params.DepsRepo,
})
return &MavenDepTreeManager{
- DepTreeManager: depTreeManager,
- isInstalled: isDepTreeInstalled,
- cmdName: cmdName,
+ DepTreeManager: depTreeManager,
+ isInstalled: params.IsMavenDepTreeInstalled,
+ cmdName: cmdName,
+ isCurationCmd: params.IsCurationCmd,
+ curationCacheFolder: params.CurationCacheFolder,
}
}
-func buildMavenDependencyTree(params *DepTreeParams, isDepTreeInstalled bool) (dependencyTree []*xrayUtils.GraphNode, uniqueDeps []string, err error) {
- manager := NewMavenDepTreeManager(params, Tree, isDepTreeInstalled)
+func buildMavenDependencyTree(params *DepTreeParams) (dependencyTree []*xrayUtils.GraphNode, uniqueDeps map[string][]string, err error) {
+ manager := NewMavenDepTreeManager(params, Tree)
outputFilePaths, clearMavenDepTreeRun, err := manager.RunMavenDepTree()
if err != nil {
if clearMavenDepTreeRun != nil {
@@ -68,11 +75,9 @@ func buildMavenDependencyTree(params *DepTreeParams, isDepTreeInstalled bool) (d
}
return
}
-
defer func() {
err = errors.Join(err, clearMavenDepTreeRun())
}()
-
dependencyTree, uniqueDeps, err = getGraphFromDepTree(outputFilePaths)
return
}
@@ -123,6 +128,9 @@ func (mdt *MavenDepTreeManager) execMavenDepTree(depTreeExecDir string) (string,
func (mdt *MavenDepTreeManager) runTreeCmd(depTreeExecDir string) (string, error) {
mavenDepTreePath := filepath.Join(depTreeExecDir, mavenDepTreeOutputFile)
goals := []string{"com.jfrog:maven-dep-tree:" + mavenDepTreeVersion + ":" + string(Tree), "-DdepsTreeOutputFile=" + mavenDepTreePath, "-B"}
+ if mdt.isCurationCmd {
+ goals = append(goals, "-Dmaven.repo.local="+mdt.curationCacheFolder)
+ }
if _, err := mdt.RunMvnCmd(goals); err != nil {
return "", err
}
@@ -199,16 +207,20 @@ func removeMavenConfig() (func() error, error) {
// Creates a new settings.xml file configured with the provided server and repository from the current MavenDepTreeManager instance.
// The settings.xml will be written to the given path.
-func (mdt *MavenDepTreeManager) createSettingsXmlWithConfiguredArtifactory(path string) error {
+func (mdt *MavenDepTreeManager) createSettingsXmlWithConfiguredArtifactory(settingsXmlPath string) error {
username, password, err := getArtifactoryAuthFromServer(mdt.server)
if err != nil {
return err
}
- remoteRepositoryFullPath, err := url.JoinPath(mdt.server.ArtifactoryUrl, mdt.depsRepo)
+ endPoint := mdt.depsRepo
+ if mdt.isCurationCmd {
+ endPoint = path.Join("api/curation/audit", endPoint)
+ }
+ remoteRepositoryFullPath, err := url.JoinPath(mdt.server.ArtifactoryUrl, endPoint)
if err != nil {
return err
}
- mdt.settingsXmlPath = filepath.Join(path, settingsXmlFile)
+ mdt.settingsXmlPath = filepath.Join(settingsXmlPath, settingsXmlFile)
settingsXmlContent := fmt.Sprintf(settingsXmlTemplate, username, password, remoteRepositoryFullPath)
return errorutils.CheckError(os.WriteFile(mdt.settingsXmlPath, []byte(settingsXmlContent), 0600))
diff --git a/utils/java/mvn_test.go b/utils/java/mvn_test.go
index fb141a3d9..b588806c4 100644
--- a/utils/java/mvn_test.go
+++ b/utils/java/mvn_test.go
@@ -1,11 +1,14 @@
package java
import (
+ "github.com/jfrog/build-info-go/utils"
"github.com/jfrog/jfrog-cli-core/v2/utils/config"
coreTests "github.com/jfrog/jfrog-cli-core/v2/utils/tests"
"github.com/jfrog/jfrog-client-go/utils/io/fileutils"
"github.com/jfrog/jfrog-client-go/utils/tests"
"github.com/stretchr/testify/assert"
+ "github.com/stretchr/testify/require"
+ "golang.org/x/exp/maps"
"os"
"path/filepath"
"strings"
@@ -32,6 +35,26 @@ const (
*
+`
+ //#nosec G101 - dummy token for testing
+ settingsXmlWithUsernameAndPasswordAndCurationDedicatedAPi = `
+
+
+
+ artifactory
+ testUser
+ testPass
+
+
+
+
+ artifactory
+ https://myartifactory.com/artifactory/api/curation/audit/testRepo
+ *
+
+
`
//#nosec G101 - dummy token for testing
settingsXmlWithUsernameAndToken = `
@@ -95,9 +118,9 @@ func TestMavenTreesMultiModule(t *testing.T) {
GavPackageTypeIdentifier + "hsqldb:hsqldb:1.8.0.10",
}
// Run getModulesDependencyTrees
- modulesDependencyTrees, uniqueDeps, err := buildMavenDependencyTree(&DepTreeParams{}, false)
+ modulesDependencyTrees, uniqueDeps, err := buildMavenDependencyTree(&DepTreeParams{})
if assert.NoError(t, err) && assert.NotEmpty(t, modulesDependencyTrees) {
- assert.ElementsMatch(t, uniqueDeps, expectedUniqueDeps, "First is actual, Second is Expected")
+ assert.ElementsMatch(t, maps.Keys(uniqueDeps), expectedUniqueDeps, "First is actual, Second is Expected")
// Check root module
multi := coreTests.GetAndAssertNode(t, modulesDependencyTrees, "org.jfrog.test:multi:3.7-SNAPSHOT")
if assert.NotNil(t, multi) {
@@ -145,9 +168,9 @@ func TestMavenWrapperTrees(t *testing.T) {
GavPackageTypeIdentifier + "javax.servlet:servlet-api:2.5",
}
- modulesDependencyTrees, uniqueDeps, err := buildMavenDependencyTree(&DepTreeParams{}, false)
+ modulesDependencyTrees, uniqueDeps, err := buildMavenDependencyTree(&DepTreeParams{})
if assert.NoError(t, err) && assert.NotEmpty(t, modulesDependencyTrees) {
- assert.ElementsMatch(t, uniqueDeps, expectedUniqueDeps, "First is actual, Second is Expected")
+ assert.ElementsMatch(t, maps.Keys(uniqueDeps), expectedUniqueDeps, "First is actual, Second is Expected")
// Check root module
multi := coreTests.GetAndAssertNode(t, modulesDependencyTrees, "org.jfrog.test:multi:3.7-SNAPSHOT")
if assert.NotNil(t, multi) {
@@ -166,6 +189,58 @@ func TestMavenWrapperTrees(t *testing.T) {
}
}
+func TestMavenWrapperTreesTypes(t *testing.T) {
+ // Create and change directory to test workspace
+ _, cleanUp := coreTests.CreateTestWorkspace(t, filepath.Join("..", "..", "tests", "testdata", "maven-example-with-many-types"))
+ defer cleanUp()
+ tree, uniqueDeps, err := buildMavenDependencyTree(&DepTreeParams{})
+ require.NoError(t, err)
+ // dependency of pom type
+ depWithPomType := uniqueDeps["gav://org.webjars:lodash:4.17.21"]
+ assert.NotEmpty(t, depWithPomType)
+ assert.Equal(t, depWithPomType[0], "pom")
+ existInTreePom := false
+ for _, node := range tree[0].Nodes {
+ if node.Id == "gav://org.webjars:lodash:4.17.21" {
+ nodeTypes := *node.Types
+ assert.Equal(t, nodeTypes[0], "pom")
+ existInTreePom = true
+ }
+ }
+ assert.True(t, existInTreePom)
+
+ // dependency of jar type
+ depWithJarType := uniqueDeps["gav://junit:junit:4.11"]
+ assert.NotEmpty(t, depWithJarType)
+ assert.Equal(t, depWithJarType[0], "jar")
+ existInTreeJar := false
+ for _, node := range tree[0].Nodes {
+ if node.Id == "gav://junit:junit:4.11" {
+ nodeTypes := *node.Types
+ assert.Equal(t, nodeTypes[0], "jar")
+ existInTreeJar = true
+ }
+ }
+ assert.True(t, existInTreeJar)
+}
+
+func TestDepTreeWithDedicatedCache(t *testing.T) {
+ // Create and change directory to test workspace
+ _, cleanUp := coreTests.CreateTestWorkspace(t, filepath.Join("..", "..", "tests", "testdata", "maven-example-with-wrapper"))
+ err := os.Chmod("mvnw", 0700)
+ defer cleanUp()
+ assert.NoError(t, err)
+ tempDir := t.TempDir()
+ defer assert.NoError(t, utils.RemoveTempDir(tempDir))
+ manager := NewMavenDepTreeManager(&DepTreeParams{IsCurationCmd: true, CurationCacheFolder: tempDir}, Tree)
+ _, err = manager.runTreeCmd(tempDir)
+ require.NoError(t, err)
+ // validate one of the jars exist in the dedicated cache for curation
+ fileExist, err := utils.IsFileExists(filepath.Join(tempDir, "org/slf4j/slf4j-api/1.7.36/slf4j-api-1.7.36.jar"), false)
+ require.NoError(t, err)
+ assert.True(t, fileExist)
+}
+
func TestGetMavenPluginInstallationArgs(t *testing.T) {
args := GetMavenPluginInstallationGoals("testPlugin")
assert.Equal(t, "org.apache.maven.plugins:maven-install-plugin:3.1.1:install-file", args[0])
@@ -196,6 +271,16 @@ func TestCreateSettingsXmlWithConfiguredArtifactory(t *testing.T) {
assert.NoError(t, err)
assert.Equal(t, settingsXmlWithUsernameAndPassword, string(actualContent))
+ // check curation command write a dedicated api for curation.
+ mdt.isCurationCmd = true
+ err = mdt.createSettingsXmlWithConfiguredArtifactory(tempDir)
+ require.NoError(t, err)
+ actualContent, err = os.ReadFile(settingsXmlPath)
+ actualContent = []byte(strings.ReplaceAll(string(actualContent), "\r\n", "\n"))
+ assert.NoError(t, err)
+ assert.Equal(t, settingsXmlWithUsernameAndPasswordAndCurationDedicatedAPi, string(actualContent))
+ mdt.isCurationCmd = false
+
mdt.server.Password = ""
// jfrog-ignore
mdt.server.AccessToken = dummyToken
@@ -223,7 +308,7 @@ func TestRunProjectsCmd(t *testing.T) {
// Create and change directory to test workspace
_, cleanUp := coreTests.CreateTestWorkspace(t, filepath.Join("..", "..", "tests", "testdata", "maven-example"))
defer cleanUp()
- mvnDepTreeManager := NewMavenDepTreeManager(&DepTreeParams{}, Projects, false)
+ mvnDepTreeManager := NewMavenDepTreeManager(&DepTreeParams{}, Projects)
output, clearMavenDepTreeRun, err := mvnDepTreeManager.RunMavenDepTree()
assert.NoError(t, err)
assert.NotNil(t, clearMavenDepTreeRun)
diff --git a/utils/lock/lock.go b/utils/lock/lock.go
index 0e8358809..57c5281af 100644
--- a/utils/lock/lock.go
+++ b/utils/lock/lock.go
@@ -10,6 +10,7 @@ import (
"strings"
"time"
+ "github.com/jfrog/jfrog-cli-core/v2/utils/osutils"
"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"
@@ -129,9 +130,9 @@ func (lock *Lock) removeOtherLockOrWait(otherLock Lock, filesList *[]string) err
log.Debug("Lock hasn't been acquired.")
// Check if the process is running.
- // There are two implementation of the 'isProcessRunning'.
+ // There are two implementation of the 'IsProcessRunning'.
// One for Windows and one for Unix based systems.
- running, err := isProcessRunning(otherLock.pid)
+ running, err := osutils.IsProcessRunning(otherLock.pid)
if err != nil {
return err
}
@@ -241,7 +242,7 @@ func GetLastLockTimestamp(lockDirPath string) (int64, error) {
lastLock := locks[len(locks)-1]
// If the lock isn't acquired by a running process, an unexpected error was occurred.
- running, err := isProcessRunning(lastLock.pid)
+ running, err := osutils.IsProcessRunning(lastLock.pid)
if err != nil {
return 0, err
}
diff --git a/utils/lock/utils_unix.go b/utils/osutils/utils_unix.go
similarity index 93%
rename from utils/lock/utils_unix.go
rename to utils/osutils/utils_unix.go
index 476ac23ce..c70c907e5 100644
--- a/utils/lock/utils_unix.go
+++ b/utils/osutils/utils_unix.go
@@ -1,19 +1,20 @@
//go:build linux || darwin || freebsd
// +build linux darwin freebsd
-package lock
+package osutils
import (
- "github.com/jfrog/jfrog-client-go/utils/log"
"os"
"syscall"
+
+ "github.com/jfrog/jfrog-client-go/utils/log"
)
// This file will be compiled only on unix systems.
// Checks if the process is running.
// If error occurs, check if the error is part of the OS permission errors. This means the process is running.
// Else means the process is not running.
-func isProcessRunning(pid int) (bool, error) {
+func IsProcessRunning(pid int) (bool, error) {
process, err := os.FindProcess(pid)
if err != nil {
return false, err
diff --git a/utils/lock/utils_windows.go b/utils/osutils/utils_windows.go
similarity index 93%
rename from utils/lock/utils_windows.go
rename to utils/osutils/utils_windows.go
index 504d1c97f..2711fcd1d 100644
--- a/utils/lock/utils_windows.go
+++ b/utils/osutils/utils_windows.go
@@ -1,15 +1,16 @@
-package lock
+package osutils
import (
- "github.com/jfrog/jfrog-client-go/utils/errorutils"
"syscall"
+
+ "github.com/jfrog/jfrog-client-go/utils/errorutils"
)
// This file will be compiled on Windows.
// Checks if the process can be reached.
// If an error occurs, check if the error is part of the invalid parameter. This means the process is not running.
// Else find the exit code. If the exit code 259 means the process is running.
-func isProcessRunning(pid int) (bool, error) {
+func IsProcessRunning(pid int) (bool, error) {
process, err := syscall.OpenProcess(syscall.PROCESS_QUERY_INFORMATION, true, uint32(pid))
if err != nil {
// Check if err is of type of syscall.Errno, which is a Windows error number.
diff --git a/utils/xray/xrayutils.go b/utils/xray/xrayutils.go
index 7f34d82a6..fc2f0f928 100644
--- a/utils/xray/xrayutils.go
+++ b/utils/xray/xrayutils.go
@@ -5,7 +5,6 @@ import (
clientconfig "github.com/jfrog/jfrog-client-go/config"
"github.com/jfrog/jfrog-client-go/xray"
xrayUtils "github.com/jfrog/jfrog-client-go/xray/services/utils"
- "golang.org/x/exp/maps"
)
func CreateXrayServiceManager(serviceDetails *config.ServerDetails) (*xray.XrayServicesManager, error) {
@@ -36,26 +35,46 @@ func CreateXrayServiceManagerAndGetVersion(serviceDetails *config.ServerDetails)
const maxUniqueAppearances = 10
-func BuildXrayDependencyTree(treeHelper map[string][]string, nodeId string) (*xrayUtils.GraphNode, []string) {
+type DepTreeNode struct {
+ Types *[]string `json:"types"`
+ Children []string `json:"children"`
+}
+
+func toNodeTypesMap(depMap map[string]DepTreeNode) map[string][]string {
+ mapOfTypes := map[string][]string{}
+ for nodId, value := range depMap {
+ mapOfTypes[nodId] = nil
+ if value.Types != nil {
+ mapOfTypes[nodId] = *value.Types
+ }
+ }
+ return mapOfTypes
+}
+
+func BuildXrayDependencyTree(treeHelper map[string]DepTreeNode, nodeId string) (*xrayUtils.GraphNode, map[string][]string) {
rootNode := &xrayUtils.GraphNode{
Id: nodeId,
Nodes: []*xrayUtils.GraphNode{},
}
dependencyAppearances := map[string]int8{}
- populateXrayDependencyTree(rootNode, treeHelper, &dependencyAppearances)
- return rootNode, maps.Keys(dependencyAppearances)
+ populateXrayDependencyTree(rootNode, treeHelper, dependencyAppearances)
+ return rootNode, toNodeTypesMap(treeHelper)
}
-func populateXrayDependencyTree(currNode *xrayUtils.GraphNode, treeHelper map[string][]string, dependencyAppearances *map[string]int8) {
- (*dependencyAppearances)[currNode.Id]++
+func populateXrayDependencyTree(currNode *xrayUtils.GraphNode, treeHelper map[string]DepTreeNode, dependencyAppearances map[string]int8) {
+ dependencyAppearances[currNode.Id]++
+ if _, ok := treeHelper[currNode.Id]; !ok {
+ treeHelper[currNode.Id] = DepTreeNode{}
+ }
// Recursively create & append all node's dependencies.
- for _, childDepId := range treeHelper[currNode.Id] {
+ for _, childDepId := range treeHelper[currNode.Id].Children {
childNode := &xrayUtils.GraphNode{
Id: childDepId,
Nodes: []*xrayUtils.GraphNode{},
Parent: currNode,
+ Types: treeHelper[childDepId].Types,
}
- if (*dependencyAppearances)[childDepId] >= maxUniqueAppearances || childNode.NodeHasLoop() {
+ if dependencyAppearances[childDepId] >= maxUniqueAppearances || childNode.NodeHasLoop() {
continue
}
currNode.Nodes = append(currNode.Nodes, childNode)