diff --git a/artifactory/commands/dotnet/dotnetcommand.go b/artifactory/commands/dotnet/dotnetcommand.go index 435e2f45b..a51d62c2e 100644 --- a/artifactory/commands/dotnet/dotnetcommand.go +++ b/artifactory/commands/dotnet/dotnetcommand.go @@ -159,23 +159,8 @@ func changeWorkingDir(newWorkingDir string) (string, error) { return newWorkingDir, errorutils.CheckError(err) } -// Set Artifactory repo as source using the toolchain's `add source` command -func (dc *DotnetCommand) AddNugetAuthToConfig(cmdType dotnet.ToolchainType, configFile *os.File, sourceUrl, user, password string) error { - content := dotnet.ConfigFileTemplate - _, err := configFile.WriteString(content) - if err != nil { - return errorutils.CheckError(err) - } - // We need to close the config file to let the toolchain modify it. - err = configFile.Close() - if err != nil { - return errorutils.CheckError(err) - } - return addSourceToNugetConfig(cmdType, configFile.Name(), sourceUrl, user, password) -} - // Runs nuget sources add command -func addSourceToNugetConfig(cmdType dotnet.ToolchainType, configFileName, sourceUrl, user, password string) error { +func AddSourceToNugetConfig(cmdType dotnet.ToolchainType, configFileName, sourceUrl, user, password string) error { cmd, err := dotnet.CreateDotnetAddSourceCmd(cmdType, sourceUrl) if err != nil { return err diff --git a/artifactory/commands/golang/go.go b/artifactory/commands/golang/go.go index 4847855a5..6671589c7 100644 --- a/artifactory/commands/golang/go.go +++ b/artifactory/commands/golang/go.go @@ -10,7 +10,6 @@ import ( "github.com/jfrog/jfrog-cli-core/v2/common/project" "github.com/jfrog/jfrog-cli-core/v2/utils/config" "github.com/jfrog/jfrog-cli-core/v2/utils/coreutils" - goutils "github.com/jfrog/jfrog-cli-core/v2/utils/golang" "github.com/jfrog/jfrog-client-go/auth" "github.com/jfrog/jfrog-client-go/http/httpclient" rtutils "github.com/jfrog/jfrog-client-go/utils" @@ -18,6 +17,7 @@ import ( "github.com/jfrog/jfrog-client-go/utils/io/fileutils" "github.com/jfrog/jfrog-client-go/utils/log" "net/http" + "net/url" "os" "path" "path/filepath" @@ -135,7 +135,7 @@ func (gc *GoCommand) extractNoFallbackFromArgs() (cleanArgs []string, err error) } func (gc *GoCommand) run() (err error) { - err = goutils.LogGoVersion() + err = logGoVersion() if err != nil { return } @@ -154,7 +154,7 @@ func (gc *GoCommand) run() (err error) { return } // If noFallback=false, missing packages will be fetched directly from VCS - repoUrl, err := goutils.GetArtifactoryRemoteRepoUrl(resolverDetails, gc.resolverParams.TargetRepo(), goutils.GoProxyUrlParams{Direct: !gc.noFallback}) + repoUrl, err := getArtifactoryRemoteRepoUrl(resolverDetails, gc.resolverParams.TargetRepo(), GoProxyUrlParams{Direct: !gc.noFallback}) if err != nil { return } @@ -328,15 +328,15 @@ func buildPackageVersionRequest(name, branchName string) string { return path.Join(packageVersionRequest, "latest.info") } -func SetArtifactoryAsResolutionServer(serverDetails *config.ServerDetails, depsRepo string, goProxyParams goutils.GoProxyUrlParams) (err error) { +func SetArtifactoryAsResolutionServer(serverDetails *config.ServerDetails, depsRepo string, goProxyParams GoProxyUrlParams) (err error) { if err = setGoProxy(serverDetails, depsRepo, goProxyParams); 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, goProxyParams goutils.GoProxyUrlParams) error { - repoUrl, err := goutils.GetArtifactoryRemoteRepoUrl(server, remoteGoRepo, goProxyParams) +func setGoProxy(server *config.ServerDetails, remoteGoRepo string, goProxyParams GoProxyUrlParams) error { + repoUrl, err := getArtifactoryRemoteRepoUrl(server, remoteGoRepo, goProxyParams) if err != nil { return err } @@ -346,3 +346,78 @@ func setGoProxy(server *config.ServerDetails, remoteGoRepo string, goProxyParams func SetGoModCache(cacheFolder string) error { return os.Setenv("GOMODCACHE", cacheFolder) } + +func logGoVersion() error { + version, err := biutils.GetParsedGoVersion() + if err != nil { + return errorutils.CheckError(err) + } + log.Info("Using go:", version.GetVersion()) + return nil +} + +type GoProxyUrlParams struct { + // Fallback to retrieve the modules directly from the source if + // the module failed to be retrieved from the proxy. + // add |direct to the end of the url. + // example: https://gocenter.io|direct + Direct bool + // The path from baseUrl to the standard Go repository path + // URL structure: //api/go/ + EndpointPrefix string +} + +func (gdu *GoProxyUrlParams) BuildUrl(url *url.URL, repoName string) string { + url.Path = path.Join(url.Path, gdu.EndpointPrefix, "api/go/", repoName) + + return gdu.addDirect(url.String()) +} + +func (gdu *GoProxyUrlParams) addDirect(url string) string { + if gdu.Direct && !strings.HasSuffix(url, "|direct") { + return url + "|direct" + } + return url +} + +func getArtifactoryRemoteRepoUrl(serverDetails *config.ServerDetails, repo string, goProxyParams GoProxyUrlParams) (string, error) { + authServerDetails, err := serverDetails.CreateArtAuthConfig() + if err != nil { + return "", err + } + return getArtifactoryApiUrl(repo, authServerDetails, goProxyParams) +} + +// Gets the URL of the specified repository Go API in Artifactory. +// The URL contains credentials (username and access token or password). +func getArtifactoryApiUrl(repoName string, details auth.ServiceDetails, goProxyParams GoProxyUrlParams) (string, error) { + rtUrl, err := url.Parse(details.GetUrl()) + if err != nil { + return "", errorutils.CheckError(err) + } + + username := details.GetUser() + password := details.GetPassword() + + // Get credentials from access-token if exists. + if details.GetAccessToken() != "" { + log.Debug("Using proxy with access-token.") + if username == "" { + username = auth.ExtractUsernameFromAccessToken(details.GetAccessToken()) + } + password = details.GetAccessToken() + } + if password != "" { + rtUrl.User = url.UserPassword(username, password) + } + + return goProxyParams.BuildUrl(rtUrl, repoName), nil +} + +func GetModuleName(projectDir string) (string, error) { + path, err := biutils.GetModuleNameByDir(projectDir, log.Logger) + if err != nil { + return "", errorutils.CheckError(err) + } + return path, nil +} diff --git a/artifactory/commands/golang/go_test.go b/artifactory/commands/golang/go_test.go index 6aaf77d26..7949b3062 100644 --- a/artifactory/commands/golang/go_test.go +++ b/artifactory/commands/golang/go_test.go @@ -2,11 +2,14 @@ package golang import ( "fmt" + biutils "github.com/jfrog/build-info-go/utils" "github.com/jfrog/jfrog-cli-core/v2/utils/config" "github.com/jfrog/jfrog-cli-core/v2/utils/coreutils" - goutils "github.com/jfrog/jfrog-cli-core/v2/utils/golang" + "github.com/jfrog/jfrog-client-go/artifactory/auth" testsutils "github.com/jfrog/jfrog-client-go/utils/tests" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + "net/url" "os" "path/filepath" "strings" @@ -34,7 +37,7 @@ func TestBuildPackageVersionRequest(t *testing.T) { } func TestGetPackageFilesPath(t *testing.T) { - packageCachePath, err := goutils.GetGoModCachePath() + packageCachePath, err := biutils.GetGoModCachePath() assert.NoError(t, err) packageName := "github.com/golang/mock/mockgen" version := "v1.4.1" @@ -61,7 +64,7 @@ func TestSetArtifactoryAsResolutionServer(t *testing.T) { cleanup := testsutils.SetEnvWithCallbackAndAssert(t, "GOPROXY", "") defer cleanup() - assert.NoError(t, SetArtifactoryAsResolutionServer(server, repo, goutils.GoProxyUrlParams{Direct: true})) + assert.NoError(t, SetArtifactoryAsResolutionServer(server, repo, GoProxyUrlParams{Direct: true})) serverUrlWithoutHttp := strings.TrimPrefix(server.ArtifactoryUrl, "http://") expectedGoProxy := fmt.Sprintf("http://%s:%s@%sapi/go/%s|direct", server.User, server.Password, serverUrlWithoutHttp, repo) @@ -70,9 +73,95 @@ func TestSetArtifactoryAsResolutionServer(t *testing.T) { // Verify that the EndpointPrefix value is correctly added to the GOPROXY. // In this test case, the endpoint prefix is set to api/curation/audit/. // This parameter allows downloading dependencies from a custom API instead of the default one. - assert.NoError(t, SetArtifactoryAsResolutionServer(server, repo, goutils.GoProxyUrlParams{Direct: true, EndpointPrefix: coreutils.CurationPassThroughApi})) + assert.NoError(t, SetArtifactoryAsResolutionServer(server, repo, GoProxyUrlParams{Direct: true, EndpointPrefix: coreutils.CurationPassThroughApi})) serverUrlWithoutHttp = strings.TrimPrefix(server.ArtifactoryUrl, "http://") expectedGoProxy = fmt.Sprintf("http://%s:%s@%sapi/curation/audit/api/go/%s|direct", server.User, server.Password, serverUrlWithoutHttp, repo) assert.Equal(t, expectedGoProxy, os.Getenv("GOPROXY")) } + +func TestGetArtifactoryRemoteRepoUrl(t *testing.T) { + server := &config.ServerDetails{ + ArtifactoryUrl: "https://server.com/artifactory", + AccessToken: "eyJ0eXAiOiJKV1QifQ.eyJzdWIiOiJmYWtlXC91c2Vyc1wvdGVzdCJ9.MTIzNDU2Nzg5MA", + } + repoName := "test-repo" + repoUrl, err := getArtifactoryRemoteRepoUrl(server, repoName, GoProxyUrlParams{}) + assert.NoError(t, err) + assert.Equal(t, "https://test:eyJ0eXAiOiJKV1QifQ.eyJzdWIiOiJmYWtlXC91c2Vyc1wvdGVzdCJ9.MTIzNDU2Nzg5MA@server.com/artifactory/api/go/test-repo", repoUrl) +} + +func TestGetArtifactoryApiUrl(t *testing.T) { + details := auth.NewArtifactoryDetails() + details.SetUrl("https://test.com/artifactory/") + + // Test username and password + details.SetUser("frog") + details.SetPassword("passfrog") + url, err := getArtifactoryApiUrl("test-repo", details, GoProxyUrlParams{}) + assert.NoError(t, err) + assert.Equal(t, "https://frog:passfrog@test.com/artifactory/api/go/test-repo", url) + + // Test username and password with EndpointPrefix and direct + details.SetUser("frog") + details.SetPassword("passfrog") + url, err = getArtifactoryApiUrl("test-repo", details, GoProxyUrlParams{EndpointPrefix: "test", Direct: true}) + assert.NoError(t, err) + assert.Equal(t, "https://frog:passfrog@test.com/artifactory/test/api/go/test-repo|direct", url) + + // Test access token + // Set fake access token with username "test" + details.SetUser("") + details.SetAccessToken("eyJ0eXAiOiJKV1QifQ.eyJzdWIiOiJmYWtlXC91c2Vyc1wvdGVzdCJ9.MTIzNDU2Nzg5MA") + url, err = getArtifactoryApiUrl("test-repo", details, GoProxyUrlParams{}) + assert.NoError(t, err) + assert.Equal(t, "https://test:eyJ0eXAiOiJKV1QifQ.eyJzdWIiOiJmYWtlXC91c2Vyc1wvdGVzdCJ9.MTIzNDU2Nzg5MA@test.com/artifactory/api/go/test-repo", url) + + // Test access token with username + // Set fake access token with username "test" + // Expect username to be "frog" + details.SetUser("frog") + details.SetAccessToken("eyJ0eXAiOiJKV1QifQ.eyJzdWIiOiJmYWtlXC91c2Vyc1wvdGVzdCJ9.MTIzNDU2Nzg5MA") + url, err = getArtifactoryApiUrl("test-repo", details, GoProxyUrlParams{}) + assert.NoError(t, err) + assert.Equal(t, "https://frog:eyJ0eXAiOiJKV1QifQ.eyJzdWIiOiJmYWtlXC91c2Vyc1wvdGVzdCJ9.MTIzNDU2Nzg5MA@test.com/artifactory/api/go/test-repo", url) +} + +func TestGoProxyUrlParams_BuildUrl(t *testing.T) { + tests := []struct { + name string + RepoName string + Direct bool + EndpointPrefix string + ExpectedUrl string + }{ + { + name: "Url Without direct or Prefix", + RepoName: "go", + ExpectedUrl: "https://test/api/go/go", + }, + { + name: "Url With direct", + RepoName: "go", + Direct: true, + ExpectedUrl: "https://test/api/go/go|direct", + }, + { + name: "Url With Prefix", + RepoName: "go", + EndpointPrefix: "prefix", + ExpectedUrl: "https://test/prefix/api/go/go", + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + remoteUrl, err := url.Parse("https://test") + require.NoError(t, err) + gdu := &GoProxyUrlParams{ + Direct: tt.Direct, + EndpointPrefix: tt.EndpointPrefix, + } + assert.Equalf(t, tt.ExpectedUrl, gdu.BuildUrl(remoteUrl, tt.RepoName), "BuildUrl(%v, %v)", remoteUrl, tt.RepoName) + }) + } +} diff --git a/artifactory/commands/golang/gopublish.go b/artifactory/commands/golang/gopublish.go index 636067682..07160ee98 100644 --- a/artifactory/commands/golang/gopublish.go +++ b/artifactory/commands/golang/gopublish.go @@ -8,7 +8,6 @@ import ( "github.com/jfrog/jfrog-cli-core/v2/artifactory/utils" buildUtils "github.com/jfrog/jfrog-cli-core/v2/common/build" "github.com/jfrog/jfrog-cli-core/v2/common/project" - goutils "github.com/jfrog/jfrog-cli-core/v2/utils/golang" clientutils "github.com/jfrog/jfrog-client-go/utils" "github.com/jfrog/jfrog-client-go/utils/errorutils" ) @@ -58,7 +57,7 @@ func (gpc *GoPublishCommand) Run() error { return err } - err = goutils.LogGoVersion() + err = logGoVersion() if err != nil { return err } diff --git a/artifactory/commands/golang/publish.go b/artifactory/commands/golang/publish.go index 3de043a1d..30e7d799a 100644 --- a/artifactory/commands/golang/publish.go +++ b/artifactory/commands/golang/publish.go @@ -7,6 +7,7 @@ import ( "errors" "fmt" buildinfo "github.com/jfrog/build-info-go/entities" + "github.com/jfrog/build-info-go/utils" "github.com/jfrog/gofrog/crypto" "github.com/jfrog/gofrog/version" "io" @@ -17,7 +18,6 @@ import ( "time" "github.com/jfrog/jfrog-cli-core/v2/common/build" - goutils "github.com/jfrog/jfrog-cli-core/v2/utils/golang" "github.com/jfrog/jfrog-client-go/artifactory" _go "github.com/jfrog/jfrog-client-go/artifactory/services/go" servicesutils "github.com/jfrog/jfrog-client-go/artifactory/services/utils" @@ -28,13 +28,13 @@ import ( // Publish go project to Artifactory. func publishPackage(packageVersion, targetRepo, buildName, buildNumber, projectKey string, excludedPatterns []string, servicesManager artifactory.ArtifactoryServicesManager) (summary *servicesutils.OperationSummary, artifacts []buildinfo.Artifact, err error) { - projectPath, err := goutils.GetProjectRoot() + projectPath, err := getProjectRoot() if err != nil { return nil, nil, errorutils.CheckError(err) } // Read module name - moduleName, err := goutils.GetModuleName(projectPath) + moduleName, err := GetModuleName(projectPath) if err != nil { return nil, nil, err } @@ -238,3 +238,11 @@ type goInfo struct { Version string `json:"Version"` Time string `json:"Time"` } + +func getProjectRoot() (string, error) { + path, err := utils.GetProjectRoot() + if err != nil { + return "", errorutils.CheckError(err) + } + return path, nil +} diff --git a/artifactory/commands/gradle/gradle.go b/artifactory/commands/gradle/gradle.go index e849c7105..042214b79 100644 --- a/artifactory/commands/gradle/gradle.go +++ b/artifactory/commands/gradle/gradle.go @@ -1,6 +1,7 @@ package gradle import ( + "fmt" "github.com/jfrog/jfrog-cli-core/v2/artifactory/commands/generic" commandsutils "github.com/jfrog/jfrog-cli-core/v2/artifactory/commands/utils" "github.com/jfrog/jfrog-cli-core/v2/artifactory/utils" @@ -8,11 +9,18 @@ import ( "github.com/jfrog/jfrog-cli-core/v2/common/format" "github.com/jfrog/jfrog-cli-core/v2/common/project" "github.com/jfrog/jfrog-cli-core/v2/utils/config" - gradleutils "github.com/jfrog/jfrog-cli-core/v2/utils/gradle" + "github.com/jfrog/jfrog-cli-core/v2/utils/coreutils" + "github.com/jfrog/jfrog-cli-core/v2/utils/dependencies" "github.com/jfrog/jfrog-cli-core/v2/utils/ioutils" "github.com/jfrog/jfrog-client-go/utils/errorutils" "github.com/jfrog/jfrog-client-go/utils/io/fileutils" "github.com/spf13/viper" + "path/filepath" +) + +const ( + usePlugin = "useplugin" + useWrapper = "usewrapper" ) type GradleCommand struct { @@ -96,7 +104,7 @@ func (gc *GradleCommand) Run() error { if err != nil { return err } - err = gradleutils.RunGradle(vConfig, gc.tasks, gc.buildArtifactsDetailsFile, gc.configuration, gc.threads, gc.IsXrayScan()) + err = runGradle(vConfig, gc.tasks, gc.buildArtifactsDetailsFile, gc.configuration, gc.threads, gc.IsXrayScan()) if err != nil { return err } @@ -222,3 +230,72 @@ func (gc *GradleCommand) setResult(result *commandsutils.Result) *GradleCommand gc.result = result return gc } + +func runGradle(vConfig *viper.Viper, tasks []string, deployableArtifactsFile string, configuration *build.BuildConfiguration, threads int, disableDeploy bool) error { + buildInfoService := build.CreateBuildInfoService() + buildName, err := configuration.GetBuildName() + if err != nil { + return err + } + buildNumber, err := configuration.GetBuildNumber() + if err != nil { + return err + } + gradleBuild, err := buildInfoService.GetOrCreateBuildWithProject(buildName, buildNumber, configuration.GetProject()) + if err != nil { + return errorutils.CheckError(err) + } + gradleModule, err := gradleBuild.AddGradleModule("") + if err != nil { + return errorutils.CheckError(err) + } + props, wrapper, plugin, err := createGradleRunConfig(vConfig, deployableArtifactsFile, threads, disableDeploy) + if err != nil { + return err + } + dependencyLocalPath, err := getGradleDependencyLocalPath() + if err != nil { + return err + } + gradleModule.SetExtractorDetails(dependencyLocalPath, filepath.Join(coreutils.GetCliPersistentTempDirPath(), build.PropertiesTempPath), tasks, wrapper, plugin, dependencies.DownloadExtractor, props) + return coreutils.ConvertExitCodeError(gradleModule.CalcDependencies()) +} + +func getGradleDependencyLocalPath() (string, error) { + dependenciesPath, err := config.GetJfrogDependenciesPath() + if err != nil { + return "", err + } + return filepath.Join(dependenciesPath, "gradle"), nil +} + +func createGradleRunConfig(vConfig *viper.Viper, deployableArtifactsFile string, threads int, disableDeploy bool) (props map[string]string, wrapper, plugin bool, err error) { + wrapper = vConfig.GetBool(useWrapper) + if threads > 0 { + vConfig.Set(build.ForkCount, threads) + } + + if disableDeploy { + setDeployFalse(vConfig) + } + props, err = build.CreateBuildInfoProps(deployableArtifactsFile, vConfig, project.Gradle) + if err != nil { + return + } + if deployableArtifactsFile != "" { + // Save the path to a temp file, where buildinfo project will write the deployable artifacts details. + props[build.DeployableArtifacts] = fmt.Sprint(vConfig.Get(build.DeployableArtifacts)) + } + plugin = vConfig.GetBool(usePlugin) + return +} + +func setDeployFalse(vConfig *viper.Viper) { + vConfig.Set(build.DeployerPrefix+build.DeployArtifacts, "false") + if vConfig.GetString(build.DeployerPrefix+build.Url) == "" { + vConfig.Set(build.DeployerPrefix+build.Url, "http://empty_url") + } + if vConfig.GetString(build.DeployerPrefix+build.Repo) == "" { + vConfig.Set(build.DeployerPrefix+build.Repo, "empty_repo") + } +} diff --git a/artifactory/commands/mvn/mvn.go b/artifactory/commands/mvn/mvn.go index f7f85789f..62d2ebbe3 100644 --- a/artifactory/commands/mvn/mvn.go +++ b/artifactory/commands/mvn/mvn.go @@ -11,7 +11,6 @@ import ( "github.com/jfrog/jfrog-cli-core/v2/common/project" "github.com/jfrog/jfrog-cli-core/v2/utils/config" "github.com/jfrog/jfrog-cli-core/v2/utils/ioutils" - mvnutils "github.com/jfrog/jfrog-cli-core/v2/utils/mvn" "github.com/jfrog/jfrog-client-go/utils/errorutils" "github.com/jfrog/jfrog-client-go/utils/io/fileutils" "github.com/spf13/viper" @@ -141,7 +140,7 @@ func (mc *MvnCommand) Run() error { return err } - mvnParams := mvnutils.NewMvnUtils(). + mvnParams := NewMvnUtils(). SetConfig(vConfig). SetBuildArtifactsDetailsFile(mc.buildArtifactsDetailsFile). SetBuildConf(mc.configuration). @@ -149,7 +148,7 @@ func (mc *MvnCommand) Run() error { SetInsecureTls(mc.insecureTls). SetDisableDeploy(mc.deploymentDisabled). SetThreads(mc.threads) - if err = mvnutils.RunMvn(mvnParams); err != nil { + if err = RunMvn(mvnParams); err != nil { return err } diff --git a/utils/mvn/utils.go b/artifactory/commands/mvn/utils.go similarity index 99% rename from utils/mvn/utils.go rename to artifactory/commands/mvn/utils.go index 876344e17..96749e696 100644 --- a/utils/mvn/utils.go +++ b/artifactory/commands/mvn/utils.go @@ -1,4 +1,4 @@ -package mvnutils +package mvn import ( "io" diff --git a/artifactory/commands/python/poetry.go b/artifactory/commands/python/poetry.go index 33152c9cf..269935637 100644 --- a/artifactory/commands/python/poetry.go +++ b/artifactory/commands/python/poetry.go @@ -11,7 +11,6 @@ import ( "github.com/jfrog/jfrog-cli-core/v2/artifactory/utils" buildUtils "github.com/jfrog/jfrog-cli-core/v2/common/build" "github.com/jfrog/jfrog-cli-core/v2/utils/config" - python "github.com/jfrog/jfrog-cli-core/v2/utils/python" "github.com/jfrog/jfrog-client-go/utils/errorutils" "github.com/jfrog/jfrog-client-go/utils/log" "golang.org/x/exp/slices" @@ -21,16 +20,11 @@ import ( type PoetryCommand struct { PythonCommand - // The uniq Artifactory repository name for poetry config file. - poetryConfigRepoName string } -const baseConfigRepoName = "jfrog-server" - func NewPoetryCommand() *PoetryCommand { return &PoetryCommand{ - PythonCommand: *NewPythonCommand(pythonutils.Poetry), - poetryConfigRepoName: baseConfigRepoName, + PythonCommand: *NewPythonCommand(pythonutils.Poetry), } } @@ -90,7 +84,7 @@ func (pc *PoetryCommand) install(buildConfiguration *buildUtils.BuildConfigurati } func (pc *PoetryCommand) publish(buildConfiguration *buildUtils.BuildConfiguration, pythonBuildInfo *build.Build) error { - publishCmdArgs := append(slices.Clone(pc.args), "-r "+pc.poetryConfigRepoName) + publishCmdArgs := append(slices.Clone(pc.args), "-r "+pc.repository) // Collect build info by running the jf poetry install cmd pc.args = []string{} err := pc.install(buildConfiguration, pythonBuildInfo) @@ -126,16 +120,16 @@ func (pc *PoetryCommand) SetCommandName(commandName string) *PoetryCommand { } func (pc *PoetryCommand) SetPypiRepoUrlWithCredentials() error { - rtUrl, username, password, err := python.GetPypiRepoUrlWithCredentials(pc.serverDetails, pc.repository, false) + rtUrl, username, password, err := GetPypiRepoUrlWithCredentials(pc.serverDetails, pc.repository, false) if err != nil { return err } if password != "" { - return python.ConfigPoetryRepo( + return ConfigPoetryRepo( rtUrl.Scheme+"://"+rtUrl.Host+rtUrl.Path, username, password, - pc.poetryConfigRepoName) + pc.repository) } return nil } diff --git a/artifactory/commands/python/python.go b/artifactory/commands/python/python.go index 5e193040d..238ea074a 100644 --- a/artifactory/commands/python/python.go +++ b/artifactory/commands/python/python.go @@ -3,20 +3,35 @@ package python import ( "bytes" "errors" + "fmt" "github.com/jfrog/build-info-go/build" "github.com/jfrog/build-info-go/entities" buildInfoUtils "github.com/jfrog/build-info-go/utils" "github.com/jfrog/build-info-go/utils/pythonutils" + gofrogcmd "github.com/jfrog/gofrog/io" "github.com/jfrog/jfrog-cli-core/v2/artifactory/commands/python/dependencies" "github.com/jfrog/jfrog-cli-core/v2/artifactory/utils" buildUtils "github.com/jfrog/jfrog-cli-core/v2/common/build" "github.com/jfrog/jfrog-cli-core/v2/utils/config" - python "github.com/jfrog/jfrog-cli-core/v2/utils/python" + "github.com/jfrog/jfrog-cli-core/v2/utils/coreutils" + "github.com/jfrog/jfrog-client-go/auth" "github.com/jfrog/jfrog-client-go/utils/errorutils" "github.com/jfrog/jfrog-client-go/utils/log" + "github.com/spf13/viper" "io" + "net/url" "os" "os/exec" + "path/filepath" + "strings" +) + +const ( + pipenvRemoteRegistryFlag = "--pypi-mirror" + pipRemoteRegistryFlag = "-i" + poetryConfigAuthPrefix = "http-basic." + poetryConfigRepoPrefix = "repositories." + pyproject = "pyproject.toml" ) type PythonCommand struct { @@ -118,11 +133,11 @@ func (pc *PythonCommand) SetCommandName(commandName string) *PythonCommand { } func (pc *PythonCommand) SetPypiRepoUrlWithCredentials() error { - rtUrl, err := python.GetPypiRepoUrl(pc.serverDetails, pc.repository, false) + rtUrl, err := GetPypiRepoUrl(pc.serverDetails, pc.repository, false) if err != nil { return err } - pc.args = append(pc.args, python.GetPypiRemoteRegistryFlag(pc.pythonTool), rtUrl) + pc.args = append(pc.args, GetPypiRemoteRegistryFlag(pc.pythonTool), rtUrl) return nil } @@ -154,3 +169,111 @@ func (pc *PythonCommand) GetStdWriter() io.WriteCloser { func (pc *PythonCommand) GetErrWriter() io.WriteCloser { return nil } + +func GetPypiRepoUrlWithCredentials(serverDetails *config.ServerDetails, repository string, isCurationCmd bool) (*url.URL, string, string, error) { + rtUrl, err := url.Parse(serverDetails.GetArtifactoryUrl()) + if err != nil { + return nil, "", "", errorutils.CheckError(err) + } + + username := serverDetails.GetUser() + password := serverDetails.GetPassword() + + // Get credentials from access-token if exists. + if serverDetails.GetAccessToken() != "" { + if username == "" { + username = auth.ExtractUsernameFromAccessToken(serverDetails.GetAccessToken()) + } + password = serverDetails.GetAccessToken() + } + // In case of curation command, the download urls should be routed through a dedicated api. + if isCurationCmd { + rtUrl.Path += coreutils.CurationPassThroughApi + } + rtUrl.Path += "api/pypi/" + repository + "/simple" + return rtUrl, username, password, err +} + +func GetPypiRemoteRegistryFlag(tool pythonutils.PythonTool) string { + if tool == pythonutils.Pip { + return pipRemoteRegistryFlag + } + return pipenvRemoteRegistryFlag +} + +func GetPypiRepoUrl(serverDetails *config.ServerDetails, repository string, isCurationCmd bool) (string, error) { + rtUrl, username, password, err := GetPypiRepoUrlWithCredentials(serverDetails, repository, isCurationCmd) + if err != nil { + return "", err + } + if password != "" { + rtUrl.User = url.UserPassword(username, password) + } + return rtUrl.String(), err +} + +func ConfigPoetryRepo(url, username, password, configRepoName string) error { + // Add the poetry repository config + err := runPoetryConfigCommand([]string{poetryConfigRepoPrefix + configRepoName, url}, false) + if err != nil { + return err + } + + // Set the poetry repository credentials + err = runPoetryConfigCommand([]string{poetryConfigAuthPrefix + configRepoName, username, password}, true) + if err != nil { + return err + } + + // Add the repository config to the pyproject.toml + currentDir, err := os.Getwd() + if err != nil { + return errorutils.CheckError(err) + } + if err = addRepoToPyprojectFile(filepath.Join(currentDir, pyproject), configRepoName, url); err != nil { + return err + } + return poetryUpdate() +} + +func poetryUpdate() (err error) { + log.Info("Running Poetry update") + cmd := gofrogcmd.NewCommand("poetry", "update", []string{}) + err = gofrogcmd.RunCmd(cmd) + if err != nil { + return errorutils.CheckErrorf("Poetry config command failed with: %s", err.Error()) + } + return +} + +func runPoetryConfigCommand(args []string, maskArgs bool) error { + logMessage := "config " + if maskArgs { + logMessage += "***" + } else { + logMessage += strings.Join(args, " ") + } + log.Info(fmt.Sprintf("Running Poetry %s", logMessage)) + cmd := gofrogcmd.NewCommand("poetry", "config", args) + err := gofrogcmd.RunCmd(cmd) + if err != nil { + return errorutils.CheckErrorf("Poetry config command failed with: %s", err.Error()) + } + return nil +} + +func addRepoToPyprojectFile(filepath, poetryRepoName, repoUrl string) error { + viper.SetConfigType("toml") + viper.SetConfigFile(filepath) + err := viper.ReadInConfig() + if err != nil { + return errorutils.CheckErrorf("Failed to read pyproject.toml: %s", err.Error()) + } + viper.Set("tool.poetry.source", []map[string]string{{"name": poetryRepoName, "url": repoUrl}}) + err = viper.WriteConfig() + if err != nil { + return errorutils.CheckErrorf("Failed to add tool.poetry.source to pyproject.toml: %s", err.Error()) + } + log.Info(fmt.Sprintf("Added tool.poetry.source name:%q url:%q", poetryRepoName, repoUrl)) + return err +} diff --git a/artifactory/commands/utils/dockercmdutils.go b/artifactory/commands/utils/dockercmdutils.go deleted file mode 100644 index e198e1c17..000000000 --- a/artifactory/commands/utils/dockercmdutils.go +++ /dev/null @@ -1,35 +0,0 @@ -package utils - -import ( - "github.com/jfrog/jfrog-cli-core/v2/common/build" - "github.com/jfrog/jfrog-cli-core/v2/utils/config" - "github.com/jfrog/jfrog-cli-core/v2/utils/coreutils" -) - -// Remove all the none docker CLI flags from args. -func ExtractDockerOptionsFromArgs(args []string) (threads int, serverDetails *config.ServerDetails, detailedSummary, skipLogin bool, cleanArgs []string, buildConfig *build.BuildConfiguration, err error) { - cleanArgs = append([]string(nil), args...) - var serverId string - cleanArgs, serverId, err = coreutils.ExtractServerIdFromCommand(cleanArgs) - if err != nil { - return - } - serverDetails, err = config.GetSpecificConfig(serverId, true, true) - if err != nil { - return - } - cleanArgs, threads, err = coreutils.ExtractThreadsFromArgs(cleanArgs, 3) - if err != nil { - return - } - cleanArgs, detailedSummary, err = coreutils.ExtractDetailedSummaryFromArgs(cleanArgs) - if err != nil { - return - } - cleanArgs, skipLogin, err = coreutils.ExtractSkipLoginFromArgs(cleanArgs) - if err != nil { - return - } - cleanArgs, buildConfig, err = build.ExtractBuildDetailsFromArgs(cleanArgs) - return -} diff --git a/artifactory/commands/utils/yarnutils.go b/artifactory/commands/utils/yarnutils.go deleted file mode 100644 index 6d7880152..000000000 --- a/artifactory/commands/utils/yarnutils.go +++ /dev/null @@ -1,129 +0,0 @@ -package utils - -import ( - "encoding/json" - ioutils "github.com/jfrog/gofrog/io" - "io" - "strconv" - "strings" - - "github.com/jfrog/build-info-go/entities" - "github.com/jfrog/jfrog-cli-core/v2/common/build" - "github.com/jfrog/jfrog-cli-core/v2/common/format" - "github.com/jfrog/jfrog-cli-core/v2/utils/coreutils" - "github.com/jfrog/jfrog-client-go/artifactory" - "github.com/jfrog/jfrog-client-go/artifactory/services" - servicesUtils "github.com/jfrog/jfrog-client-go/artifactory/services/utils" - "github.com/jfrog/jfrog-client-go/utils/errorutils" - "github.com/jfrog/jfrog-client-go/utils/log" -) - -type aqlResult struct { - Results []*servicesUtils.ResultItem `json:"results,omitempty"` -} - -func GetDependenciesFromLatestBuild(servicesManager artifactory.ArtifactoryServicesManager, buildName string) (map[string]*entities.Dependency, error) { - buildDependencies := make(map[string]*entities.Dependency) - previousBuild, found, err := servicesManager.GetBuildInfo(services.BuildInfoParams{BuildName: buildName, BuildNumber: servicesUtils.LatestBuildNumberKey}) - if err != nil || !found { - return buildDependencies, err - } - for _, module := range previousBuild.BuildInfo.Modules { - for _, dependency := range module.Dependencies { - buildDependencies[dependency.Id] = &entities.Dependency{Id: dependency.Id, Type: dependency.Type, - Checksum: entities.Checksum{Md5: dependency.Md5, Sha1: dependency.Sha1}} - } - } - return buildDependencies, nil -} - -// Get dependency's checksum and type. -func getDependencyInfo(name, ver string, previousBuildDependencies map[string]*entities.Dependency, - servicesManager artifactory.ArtifactoryServicesManager) (checksum entities.Checksum, fileType string, err error) { - id := name + ":" + ver - if dep, ok := previousBuildDependencies[id]; ok { - // Get checksum from previous build. - checksum = dep.Checksum - fileType = dep.Type - return - } - - // Get info from Artifactory. - log.Debug("Fetching checksums for", id) - var stream io.ReadCloser - stream, err = servicesManager.Aql(servicesUtils.CreateAqlQueryForYarn(name, ver)) - if err != nil { - return - } - defer ioutils.Close(stream, &err) - var result []byte - result, err = io.ReadAll(stream) - if err != nil { - return - } - parsedResult := new(aqlResult) - if err = json.Unmarshal(result, parsedResult); err != nil { - return entities.Checksum{}, "", errorutils.CheckError(err) - } - if len(parsedResult.Results) == 0 { - log.Debug(id, "could not be found in Artifactory.") - return - } - if i := strings.LastIndex(parsedResult.Results[0].Name, "."); i != -1 { - fileType = parsedResult.Results[0].Name[i+1:] - } - log.Debug(id, "was found in Artifactory. Name:", parsedResult.Results[0].Name, - "SHA-1:", parsedResult.Results[0].Actual_Sha1, - "MD5:", parsedResult.Results[0].Actual_Md5) - - checksum = entities.Checksum{Sha1: parsedResult.Results[0].Actual_Sha1, Md5: parsedResult.Results[0].Actual_Md5, Sha256: parsedResult.Results[0].Sha256} - return -} - -func ExtractYarnOptionsFromArgs(args []string) (threads int, detailedSummary, xrayScan bool, scanOutputFormat format.OutputFormat, cleanArgs []string, buildConfig *build.BuildConfiguration, err error) { - threads = 3 - // Extract threads information from the args. - flagIndex, valueIndex, numOfThreads, err := coreutils.FindFlag("--threads", args) - if err != nil { - return - } - coreutils.RemoveFlagFromCommand(&args, flagIndex, valueIndex) - if numOfThreads != "" { - threads, err = strconv.Atoi(numOfThreads) - if err != nil { - err = errorutils.CheckError(err) - return - } - } - detailedSummary, xrayScan, scanOutputFormat, cleanArgs, buildConfig, err = ExtractNpmOptionsFromArgs(args) - return -} - -func PrintMissingDependencies(missingDependencies []string) { - if len(missingDependencies) == 0 { - return - } - - log.Warn(strings.Join(missingDependencies, "\n"), "\nThe npm dependencies above could not be found in Artifactory and therefore are not included in the build-info.\n"+ - "Deleting the local cache will force populating Artifactory with these dependencies.") -} - -func CreateCollectChecksumsFunc(previousBuildDependencies map[string]*entities.Dependency, servicesManager artifactory.ArtifactoryServicesManager, missingDepsChan chan string) func(dependency *entities.Dependency) (bool, error) { - return func(dependency *entities.Dependency) (bool, error) { - splitDepId := strings.SplitN(dependency.Id, ":", 2) - name := splitDepId[0] - ver := splitDepId[1] - - // Get dependency info. - checksum, fileType, err := getDependencyInfo(name, ver, previousBuildDependencies, servicesManager) - if err != nil || checksum.IsEmpty() { - missingDepsChan <- dependency.Id - return false, err - } - - // Update dependency. - dependency.Type = fileType - dependency.Checksum = checksum - return true, nil - } -} diff --git a/artifactory/commands/yarn/yarn.go b/artifactory/commands/yarn/yarn.go index 01db1771f..1a369d90e 100644 --- a/artifactory/commands/yarn/yarn.go +++ b/artifactory/commands/yarn/yarn.go @@ -4,9 +4,17 @@ import ( "bufio" "encoding/json" "errors" + "github.com/jfrog/build-info-go/entities" + gofrogio "github.com/jfrog/gofrog/io" + "github.com/jfrog/jfrog-cli-core/v2/common/format" + "github.com/jfrog/jfrog-client-go/artifactory" + "github.com/jfrog/jfrog-client-go/artifactory/services" + servicesUtils "github.com/jfrog/jfrog-client-go/artifactory/services/utils" + "io" "os" "os/exec" "path/filepath" + "strconv" "strings" "github.com/jfrog/build-info-go/build" @@ -78,7 +86,7 @@ func (yc *YarnCommand) Run() (err error) { } var filteredYarnArgs []string - yc.threads, _, _, _, filteredYarnArgs, yc.buildConfiguration, err = commandUtils.ExtractYarnOptionsFromArgs(yc.yarnArgs) + yc.threads, _, _, _, filteredYarnArgs, yc.buildConfiguration, err = extractYarnOptionsFromArgs(yc.yarnArgs) if err != nil { return } @@ -117,7 +125,7 @@ func (yc *YarnCommand) Run() (err error) { if yc.collectBuildInfo { close(missingDepsChan) - commandUtils.PrintMissingDependencies(missingDependencies) + printMissingDependencies(missingDependencies) } if err = RestoreConfigurationsFromBackup(backupEnvMap, restoreYarnrcFunc); err != nil { @@ -226,12 +234,12 @@ func (yc *YarnCommand) prepareBuildInfo() (missingDepsChan chan string, err erro if err != nil { return } - previousBuildDependencies, err := commandUtils.GetDependenciesFromLatestBuild(servicesManager, buildName) + previousBuildDependencies, err := getDependenciesFromLatestBuild(servicesManager, buildName) if err != nil { return } missingDepsChan = make(chan string) - collectChecksumsFunc := commandUtils.CreateCollectChecksumsFunc(previousBuildDependencies, servicesManager, missingDepsChan) + collectChecksumsFunc := createCollectChecksumsFunc(previousBuildDependencies, servicesManager, missingDepsChan) yc.buildInfoModule.SetTraverseDependenciesFunc(collectChecksumsFunc) yc.buildInfoModule.SetThreads(yc.threads) return @@ -376,3 +384,113 @@ func extractAuthValFromNpmAuth(npmAuth string) (authIndent, authToken string, er return "", "", errorutils.CheckErrorf("failed while retrieving npm auth details from Artifactory") } + +type aqlResult struct { + Results []*servicesUtils.ResultItem `json:"results,omitempty"` +} + +func getDependenciesFromLatestBuild(servicesManager artifactory.ArtifactoryServicesManager, buildName string) (map[string]*entities.Dependency, error) { + buildDependencies := make(map[string]*entities.Dependency) + previousBuild, found, err := servicesManager.GetBuildInfo(services.BuildInfoParams{BuildName: buildName, BuildNumber: servicesUtils.LatestBuildNumberKey}) + if err != nil || !found { + return buildDependencies, err + } + for _, module := range previousBuild.BuildInfo.Modules { + for _, dependency := range module.Dependencies { + buildDependencies[dependency.Id] = &entities.Dependency{Id: dependency.Id, Type: dependency.Type, + Checksum: entities.Checksum{Md5: dependency.Md5, Sha1: dependency.Sha1}} + } + } + return buildDependencies, nil +} + +// Get dependency's checksum and type. +func getDependencyInfo(name, ver string, previousBuildDependencies map[string]*entities.Dependency, + servicesManager artifactory.ArtifactoryServicesManager) (checksum entities.Checksum, fileType string, err error) { + id := name + ":" + ver + if dep, ok := previousBuildDependencies[id]; ok { + // Get checksum from previous build. + checksum = dep.Checksum + fileType = dep.Type + return + } + + // Get info from Artifactory. + log.Debug("Fetching checksums for", id) + var stream io.ReadCloser + stream, err = servicesManager.Aql(servicesUtils.CreateAqlQueryForYarn(name, ver)) + if err != nil { + return + } + defer gofrogio.Close(stream, &err) + var result []byte + result, err = io.ReadAll(stream) + if err != nil { + return + } + parsedResult := new(aqlResult) + if err = json.Unmarshal(result, parsedResult); err != nil { + return entities.Checksum{}, "", errorutils.CheckError(err) + } + if len(parsedResult.Results) == 0 { + log.Debug(id, "could not be found in Artifactory.") + return + } + if i := strings.LastIndex(parsedResult.Results[0].Name, "."); i != -1 { + fileType = parsedResult.Results[0].Name[i+1:] + } + log.Debug(id, "was found in Artifactory. Name:", parsedResult.Results[0].Name, + "SHA-1:", parsedResult.Results[0].Actual_Sha1, + "MD5:", parsedResult.Results[0].Actual_Md5) + + checksum = entities.Checksum{Sha1: parsedResult.Results[0].Actual_Sha1, Md5: parsedResult.Results[0].Actual_Md5, Sha256: parsedResult.Results[0].Sha256} + return +} + +func extractYarnOptionsFromArgs(args []string) (threads int, detailedSummary, xrayScan bool, scanOutputFormat format.OutputFormat, cleanArgs []string, buildConfig *buildUtils.BuildConfiguration, err error) { + threads = 3 + // Extract threads information from the args. + flagIndex, valueIndex, numOfThreads, err := coreutils.FindFlag("--threads", args) + if err != nil { + return + } + coreutils.RemoveFlagFromCommand(&args, flagIndex, valueIndex) + if numOfThreads != "" { + threads, err = strconv.Atoi(numOfThreads) + if err != nil { + err = errorutils.CheckError(err) + return + } + } + detailedSummary, xrayScan, scanOutputFormat, cleanArgs, buildConfig, err = commandUtils.ExtractNpmOptionsFromArgs(args) + return +} + +func printMissingDependencies(missingDependencies []string) { + if len(missingDependencies) == 0 { + return + } + + log.Warn(strings.Join(missingDependencies, "\n"), "\nThe npm dependencies above could not be found in Artifactory and therefore are not included in the build-info.\n"+ + "Deleting the local cache will force populating Artifactory with these dependencies.") +} + +func createCollectChecksumsFunc(previousBuildDependencies map[string]*entities.Dependency, servicesManager artifactory.ArtifactoryServicesManager, missingDepsChan chan string) func(dependency *entities.Dependency) (bool, error) { + return func(dependency *entities.Dependency) (bool, error) { + splitDepId := strings.SplitN(dependency.Id, ":", 2) + name := splitDepId[0] + ver := splitDepId[1] + + // Get dependency info. + checksum, fileType, err := getDependencyInfo(name, ver, previousBuildDependencies, servicesManager) + if err != nil || checksum.IsEmpty() { + missingDepsChan <- dependency.Id + return false, err + } + + // Update dependency. + dependency.Type = fileType + dependency.Checksum = checksum + return true, nil + } +} diff --git a/artifactory/utils/classworldsconf.go b/artifactory/utils/classworldsconf.go deleted file mode 100644 index 69a4c866c..000000000 --- a/artifactory/utils/classworldsconf.go +++ /dev/null @@ -1,10 +0,0 @@ -package utils - -const ClassworldsConf = `main is org.apache.maven.cli.MavenCli from plexus.core - -set maven.home default ${user.home}/m2 - -[plexus.core] -load ${maven.home}/lib/*.jar -load ${m3plugin.lib}/*.jar -` diff --git a/artifactory/utils/container/containermanager.go b/artifactory/utils/container/containermanager.go index e5139b5d5..8c16c6659 100644 --- a/artifactory/utils/container/containermanager.go +++ b/artifactory/utils/container/containermanager.go @@ -250,7 +250,7 @@ func (versionCmd *VersionCmd) RunCmd() (string, error) { func ValidateClientApiVersion() error { cmd := &VersionCmd{} - // 'docker version' may return 1 in case of errors from daemon. We should ignore this kind of errors. + // 'docker version' may return 1 in case of errors from daemon. We should ignore this kind of error. content, err := cmd.RunCmd() content = strings.TrimSpace(content) if !ApiVersionRegex.Match([]byte(content)) { diff --git a/artifactory/utils/container/localagent.go b/artifactory/utils/container/localagent.go index 9987dfc71..57c4ef573 100644 --- a/artifactory/utils/container/localagent.go +++ b/artifactory/utils/container/localagent.go @@ -14,7 +14,7 @@ import ( ) // Build-info builder for local agents tools such as: Docker or Podman. -type localAgentbuildInfoBuilder struct { +type localAgentBuildInfoBuilder struct { buildInfoBuilder *buildInfoBuilder // Name of the container CLI tool e.g. docker containerManager ContainerManager @@ -22,7 +22,7 @@ type localAgentbuildInfoBuilder struct { } // Create new build info builder container CLI tool -func NewLocalAgentBuildInfoBuilder(image *Image, repository, buildName, buildNumber, project string, serviceManager artifactory.ArtifactoryServicesManager, commandType CommandType, containerManager ContainerManager) (*localAgentbuildInfoBuilder, error) { +func NewLocalAgentBuildInfoBuilder(image *Image, repository, buildName, buildNumber, project string, serviceManager artifactory.ArtifactoryServicesManager, commandType CommandType, containerManager ContainerManager) (*localAgentBuildInfoBuilder, error) { imageSha2, err := containerManager.Id(image) if err != nil { return nil, err @@ -32,23 +32,23 @@ func NewLocalAgentBuildInfoBuilder(image *Image, repository, buildName, buildNum return nil, err } builder.setImageSha2(imageSha2) - return &localAgentbuildInfoBuilder{ + return &localAgentBuildInfoBuilder{ buildInfoBuilder: builder, containerManager: containerManager, commandType: commandType, }, err } -func (labib *localAgentbuildInfoBuilder) GetLayers() *[]utils.ResultItem { +func (labib *localAgentBuildInfoBuilder) GetLayers() *[]utils.ResultItem { return &labib.buildInfoBuilder.imageLayers } -func (labib *localAgentbuildInfoBuilder) SetSkipTaggingLayers(skipTaggingLayers bool) { +func (labib *localAgentBuildInfoBuilder) SetSkipTaggingLayers(skipTaggingLayers bool) { labib.buildInfoBuilder.skipTaggingLayers = skipTaggingLayers } // Create build-info for a docker image. -func (labib *localAgentbuildInfoBuilder) Build(module string) (*buildinfo.BuildInfo, error) { +func (labib *localAgentBuildInfoBuilder) Build(module string) (*buildinfo.BuildInfo, error) { // Search for image build-info. candidateLayers, manifest, err := labib.searchImage() if err != nil { @@ -63,7 +63,7 @@ func (labib *localAgentbuildInfoBuilder) Build(module string) (*buildinfo.BuildI } // Search an image in Artifactory and validate its sha2 with local image. -func (labib *localAgentbuildInfoBuilder) searchImage() (map[string]*utils.ResultItem, *manifest, error) { +func (labib *localAgentBuildInfoBuilder) searchImage() (map[string]*utils.ResultItem, *manifest, error) { longImageName, err := labib.buildInfoBuilder.image.GetImageLongNameWithTag() if err != nil { return nil, nil, err @@ -90,7 +90,7 @@ func (labib *localAgentbuildInfoBuilder) searchImage() (map[string]*utils.Result // Search image layers in artifactory by the provided image path in artifactory. // If fat-manifest is found, use it to find our image in Artifactory. -func (labib *localAgentbuildInfoBuilder) search(imagePathPattern string) (resultMap map[string]*utils.ResultItem, err error) { +func (labib *localAgentBuildInfoBuilder) search(imagePathPattern string) (resultMap map[string]*utils.ResultItem, err error) { resultMap, err = performSearch(imagePathPattern, labib.buildInfoBuilder.serviceManager) if err != nil { log.Debug("Failed to search marker layer. Error:", err.Error()) @@ -130,7 +130,7 @@ func (labib *localAgentbuildInfoBuilder) search(imagePathPattern string) (result } // Verify manifest by comparing sha256, which references to the image digest. If there is no match, return nil. -func (labib *localAgentbuildInfoBuilder) isVerifiedManifest(imageManifest *manifest) bool { +func (labib *localAgentBuildInfoBuilder) isVerifiedManifest(imageManifest *manifest) bool { if imageManifest.Config.Digest != labib.buildInfoBuilder.imageSha2 { log.Debug(`Found incorrect manifest.json file. Expects digest "` + labib.buildInfoBuilder.imageSha2 + `" found "` + imageManifest.Config.Digest) return false @@ -138,7 +138,7 @@ func (labib *localAgentbuildInfoBuilder) isVerifiedManifest(imageManifest *manif return true } -func (labib *localAgentbuildInfoBuilder) getImageDigestFromFatManifest(fatManifest utils.ResultItem) (string, error) { +func (labib *localAgentBuildInfoBuilder) getImageDigestFromFatManifest(fatManifest utils.ResultItem) (string, error) { var fatManifestContent *FatManifest if err := downloadLayer(fatManifest, &fatManifestContent, labib.buildInfoBuilder.serviceManager, labib.buildInfoBuilder.repositoryDetails.key); err != nil { log.Debug(`failed to unmarshal fat-manifest`) diff --git a/artifactory/utils/dotnet/solution/testdata/nugetproj/proj1/packages.config b/artifactory/utils/dotnet/solution/testdata/nugetproj/proj1/packages.config deleted file mode 100644 index 2d0891e8b..000000000 --- a/artifactory/utils/dotnet/solution/testdata/nugetproj/proj1/packages.config +++ /dev/null @@ -1,9 +0,0 @@ - - - - - - - - - \ No newline at end of file diff --git a/artifactory/utils/dotnet/solution/testdata/nugetproj/proj1/proj1.cs b/artifactory/utils/dotnet/solution/testdata/nugetproj/proj1/proj1.cs deleted file mode 100644 index 39deccf9e..000000000 --- a/artifactory/utils/dotnet/solution/testdata/nugetproj/proj1/proj1.cs +++ /dev/null @@ -1,6 +0,0 @@ -class Program -{ - static void Main() - { - } -} \ No newline at end of file diff --git a/artifactory/utils/dotnet/solution/testdata/nugetproj/proj1/proj1.csproj b/artifactory/utils/dotnet/solution/testdata/nugetproj/proj1/proj1.csproj deleted file mode 100644 index 8e89c8c9d..000000000 --- a/artifactory/utils/dotnet/solution/testdata/nugetproj/proj1/proj1.csproj +++ /dev/null @@ -1,28 +0,0 @@ - - - - - Debug - AnyCPU - {D1FFA0DC-0ACC-4108-ADC1-2A71122C09AF} - bin\$(Configuration)\ - v4.5 - - - - - - - - - - - - 4.0.0 - - - 2.14.0 - - - - \ No newline at end of file diff --git a/artifactory/utils/dotnet/solution/testdata/nugetproj/proj2/proj2.cs b/artifactory/utils/dotnet/solution/testdata/nugetproj/proj2/proj2.cs deleted file mode 100644 index 39deccf9e..000000000 --- a/artifactory/utils/dotnet/solution/testdata/nugetproj/proj2/proj2.cs +++ /dev/null @@ -1,6 +0,0 @@ -class Program -{ - static void Main() - { - } -} \ No newline at end of file diff --git a/artifactory/utils/dotnet/solution/testdata/nugetproj/proj2/proj2.csproj b/artifactory/utils/dotnet/solution/testdata/nugetproj/proj2/proj2.csproj deleted file mode 100644 index d7837ad9e..000000000 --- a/artifactory/utils/dotnet/solution/testdata/nugetproj/proj2/proj2.csproj +++ /dev/null @@ -1,28 +0,0 @@ - - - - - Debug - AnyCPU - {D1FFA0DC-0ACC-4108-ADC1-2A71122C09AF} - bin\$(Configuration)\ - v4.5 - - - - - - - - - - - - 11.0.2 - - - 2.14.0 - - - - \ No newline at end of file diff --git a/artifactory/utils/dotnet/solution/testdata/nugetproj/solutions/nugetproj.sln b/artifactory/utils/dotnet/solution/testdata/nugetproj/solutions/nugetproj.sln deleted file mode 100644 index b919df5d1..000000000 --- a/artifactory/utils/dotnet/solution/testdata/nugetproj/solutions/nugetproj.sln +++ /dev/null @@ -1,26 +0,0 @@ -Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 15 -VisualStudioVersion = 15.0.27428.2005 -MinimumVisualStudioVersion = 10.0.40219.1 -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "proj1", "../proj1/proj1.csproj", "{D1FFA0DC-0ACC-4108-ADC1-2A71122C09AF}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "proj2", "../proj2/proj2.csproj", "{D1FFA0DC-0ACC-4108-ADC1-2A71122C09AF}" -EndProject -Global - GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug|Any CPU = Debug|Any CPU - Release|Any CPU = Release|Any CPU - EndGlobalSection - GlobalSection(ProjectConfigurationPlatforms) = postSolution - {D1FFA0DC-0ACC-4108-ADC1-2A71122C09AF}.Debug|Any CPU.ActiveCfg = Debug|x86 - {D1FFA0DC-0ACC-4108-ADC1-2A71122C09AF}.Debug|Any CPU.Build.0 = Debug|x86 - {D1FFA0DC-0ACC-4108-ADC1-2A71122C09AF}.Release|Any CPU.ActiveCfg = Debug|x86 - {D1FFA0DC-0ACC-4108-ADC1-2A71122C09AF}.Release|Any CPU.Build.0 = Debug|x86 - EndGlobalSection - GlobalSection(SolutionProperties) = preSolution - HideSolutionNode = FALSE - EndGlobalSection - GlobalSection(ExtensibilityGlobals) = postSolution - SolutionGuid = {D6F2BF93-8FC0-422E-BED5-D352C69B81C0} - EndGlobalSection -EndGlobal diff --git a/artifactory/utils/dotnet/solution/testdata/nugetproj/solutions/proj2/packages.config b/artifactory/utils/dotnet/solution/testdata/nugetproj/solutions/proj2/packages.config deleted file mode 100644 index 2d0891e8b..000000000 --- a/artifactory/utils/dotnet/solution/testdata/nugetproj/solutions/proj2/packages.config +++ /dev/null @@ -1,9 +0,0 @@ - - - - - - - - - \ No newline at end of file diff --git a/utils/npm/cmd.go b/artifactory/utils/npm/cmd.go similarity index 97% rename from utils/npm/cmd.go rename to artifactory/utils/npm/cmd.go index 88f6cd060..9856d0fc4 100644 --- a/utils/npm/cmd.go +++ b/artifactory/utils/npm/cmd.go @@ -1,4 +1,4 @@ -package npmutils +package npm import ( "io" diff --git a/artifactory/utils/npm/config-get.go b/artifactory/utils/npm/config-get.go index eef86d3a7..5fff4649f 100644 --- a/artifactory/utils/npm/config-get.go +++ b/artifactory/utils/npm/config-get.go @@ -4,7 +4,6 @@ import ( "strings" gofrogcmd "github.com/jfrog/gofrog/io" - npmutils "github.com/jfrog/jfrog-cli-core/v2/utils/npm" "github.com/jfrog/jfrog-client-go/utils/errorutils" ) @@ -19,8 +18,8 @@ func ConfigGet(npmFlags []string, confName, executablePath string) (string, erro return confValue, nil } -func createConfigGetCmdConfig(executablePath, confName string, splitFlags []string) *npmutils.NpmConfig { - return &npmutils.NpmConfig{ +func createConfigGetCmdConfig(executablePath, confName string, splitFlags []string) *NpmConfig { + return &NpmConfig{ Npm: executablePath, Command: []string{"config", "get", confName}, CommandFlags: splitFlags, diff --git a/artifactory/utils/npm/config-list.go b/artifactory/utils/npm/config-list.go index d129ef53c..0eed30a61 100644 --- a/artifactory/utils/npm/config-list.go +++ b/artifactory/utils/npm/config-list.go @@ -3,7 +3,6 @@ package npm import ( "errors" gofrogcmd "github.com/jfrog/gofrog/io" - npmutils "github.com/jfrog/jfrog-cli-core/v2/utils/npm" "github.com/jfrog/jfrog-client-go/utils/errorutils" "io" ) @@ -34,8 +33,8 @@ func GetConfigList(npmFlags []string, executablePath string) (data []byte, err e return data, nil } -func createConfigListCmdConfig(executablePath string, splitFlags []string, pipeWriter *io.PipeWriter) *npmutils.NpmConfig { - return &npmutils.NpmConfig{ +func createConfigListCmdConfig(executablePath string, splitFlags []string, pipeWriter *io.PipeWriter) *NpmConfig { + return &NpmConfig{ Npm: executablePath, Command: []string{"c", "ls"}, CommandFlags: splitFlags, diff --git a/artifactory/utils/npm/pack.go b/artifactory/utils/npm/pack.go index 24ff8e289..04a340f41 100644 --- a/artifactory/utils/npm/pack.go +++ b/artifactory/utils/npm/pack.go @@ -6,7 +6,6 @@ import ( "strings" gofrogcmd "github.com/jfrog/gofrog/io" - npmutils "github.com/jfrog/jfrog-cli-core/v2/utils/npm" "github.com/jfrog/jfrog-client-go/utils/errorutils" ) @@ -23,8 +22,8 @@ func Pack(npmFlags []string, executablePath string) ([]string, error) { return getPackageFileNameFromOutput(output) } -func createPackCmdConfig(executablePath string, splitFlags []string) *npmutils.NpmConfig { - return &npmutils.NpmConfig{ +func createPackCmdConfig(executablePath string, splitFlags []string) *NpmConfig { + return &NpmConfig{ Npm: executablePath, Command: []string{"pack"}, CommandFlags: append(splitFlags, "--json=false"), diff --git a/common/cliutils/utils.go b/common/cliutils/utils.go index ce4d0d3a1..2eda96d1e 100644 --- a/common/cliutils/utils.go +++ b/common/cliutils/utils.go @@ -217,7 +217,8 @@ func CreateServerDetailsWithConfigOffer(createServerDetails func() (*config.Serv if err != nil { return nil, err } - + log.Debug(fmt.Sprintf("Using <%s> server-id configuration", confDetails.ServerId)) + // Take insecureTls value from options since it is not saved in config. confDetails.InsecureTls = details.InsecureTls confDetails.Url = clientUtils.AddTrailingSlashIfNeeded(confDetails.Url) diff --git a/general/invite/invite.go b/general/invite/invite.go deleted file mode 100644 index 84bdda983..000000000 --- a/general/invite/invite.go +++ /dev/null @@ -1,91 +0,0 @@ -package invite - -import ( - "fmt" - "github.com/jfrog/jfrog-cli-core/v2/artifactory/utils" - "github.com/jfrog/jfrog-client-go/access" - accessservices "github.com/jfrog/jfrog-client-go/access/services" - "github.com/jfrog/jfrog-client-go/artifactory/services" - clientutils "github.com/jfrog/jfrog-client-go/utils" - "github.com/jfrog/jfrog-client-go/utils/log" - "strings" - - "github.com/jfrog/jfrog-cli-core/v2/utils/config" -) - -const InviteCliSourceName = "cli" - -type InviteCommand struct { - invitedEmail string - serverDetails *config.ServerDetails -} - -func (ic *InviteCommand) SetInvitedEmail(invitedEmail string) *InviteCommand { - ic.invitedEmail = invitedEmail - return ic -} - -func (ic *InviteCommand) SetServerDetails(serverDetails *config.ServerDetails) *InviteCommand { - ic.serverDetails = serverDetails - return ic -} - -func (ic *InviteCommand) ServerDetails() (*config.ServerDetails, error) { - return ic.serverDetails, nil -} - -func (ic *InviteCommand) CommandName() string { - return "invite" -} - -func NewInviteCommand() *InviteCommand { - return &InviteCommand{} -} - -func (ic *InviteCommand) Run() (err error) { - servicesManager, err := utils.CreateServiceManager(ic.serverDetails, -1, 0, false) - if err != nil { - return err - } - userDetails := ic.createNewInvitedUser() - - log.Info(fmt.Sprintf("Sending invitation email to: %s...", userDetails.Name)) - params := new(services.UserParams) - params.UserDetails = *userDetails - params.ReplaceIfExists = false - // Inviting the new user - send a 'CreateUser' request to artifactory with the "shouldInvite=true" parameter. - err = servicesManager.CreateUser(*params) - if err != nil { - if strings.HasSuffix(err.Error(), "already exists") { - log.Debug(fmt.Sprintf("Re-sending invitation email to: %s...", userDetails.Name)) - var accessManager *access.AccessServicesManager - accessManager, err = utils.CreateAccessServiceManager(ic.serverDetails, false) - if err != nil { - return - } - // Re-inviting user - send an "Invite" request to access. - err = accessManager.InviteUser(params.UserDetails.Email, InviteCliSourceName) - if err != nil { - return - } - } - } - return -} - -func (ic *InviteCommand) createNewInvitedUser() *services.User { - userDetails := services.User{} - // Parameters "name" and "email" should both be with the email value for internal reasons in access. - userDetails.Email = ic.invitedEmail - userDetails.Name = ic.invitedEmail - // Random valid password - information won't be used in access. - userDetails.Password = "Password1!" - userDetails.Admin = clientutils.Pointer(true) - userDetails.ShouldInvite = clientutils.Pointer(true) - userDetails.Source = accessservices.InviteCliSourceName - - userDetails.ProfileUpdatable = clientutils.Pointer(true) - userDetails.DisableUIAccess = clientutils.Pointer(false) - userDetails.InternalPasswordDisabled = clientutils.Pointer(false) - return &userDetails -} diff --git a/go.mod b/go.mod index 1bfb134a3..ee98e29ff 100644 --- a/go.mod +++ b/go.mod @@ -11,7 +11,7 @@ require ( github.com/gocarina/gocsv v0.0.0-20240520201108-78e41c74b4b1 github.com/google/uuid v1.6.0 github.com/gookit/color v1.5.4 - github.com/jedib0t/go-pretty/v6 v6.5.9 + github.com/jedib0t/go-pretty/v6 v6.6.1 github.com/jfrog/build-info-go v1.10.3 github.com/jfrog/gofrog v1.7.6 github.com/jfrog/jfrog-client-go v1.47.4 @@ -20,13 +20,13 @@ require ( github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c github.com/spf13/viper v1.19.0 github.com/stretchr/testify v1.9.0 - github.com/urfave/cli v1.22.15 + github.com/urfave/cli v1.22.16 github.com/vbauerster/mpb/v8 v8.8.3 - golang.org/x/exp v0.0.0-20240909161429-701f63a606c0 + golang.org/x/exp v0.0.0-20241009180824-f66d83c29e7c golang.org/x/mod v0.21.0 golang.org/x/sync v0.8.0 - golang.org/x/term v0.24.0 - golang.org/x/text v0.18.0 + golang.org/x/term v0.25.0 + golang.org/x/text v0.19.0 gopkg.in/yaml.v3 v3.0.1 ) @@ -40,7 +40,7 @@ require ( github.com/acarl005/stripansi v0.0.0-20180116102854-5a71ef0e047d // indirect github.com/andybalholm/brotli v1.1.0 // indirect github.com/cloudflare/circl v1.3.7 // indirect - github.com/cpuguy83/go-md2man/v2 v2.0.4 // indirect + github.com/cpuguy83/go-md2man/v2 v2.0.5 // indirect github.com/cyphar/filepath-securejoin v0.2.4 // indirect github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect github.com/dsnet/compress v0.0.1 // indirect @@ -88,10 +88,10 @@ 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.27.0 // indirect - golang.org/x/net v0.29.0 // indirect - golang.org/x/sys v0.25.0 // indirect - golang.org/x/tools v0.25.0 // indirect + golang.org/x/crypto v0.28.0 // indirect + golang.org/x/net v0.30.0 // indirect + golang.org/x/sys v0.26.0 // indirect + golang.org/x/tools v0.26.0 // indirect gopkg.in/ini.v1 v1.67.0 // indirect gopkg.in/warnings.v0 v0.1.2 // indirect ) diff --git a/go.sum b/go.sum index 19c86c5f9..40df48faa 100644 --- a/go.sum +++ b/go.sum @@ -1,6 +1,5 @@ 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/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ= github.com/BurntSushi/toml v1.4.0 h1:kuoIxZQy2WRRk1pttg9asf+WVv6tWQuBNVmK8+nqPr0= github.com/BurntSushi/toml v1.4.0/go.mod h1:ukJfTF/6rtPPRCnwkur4qwRxa8vTRFBF0uk2lLoLwho= github.com/CycloneDX/cyclonedx-go v0.9.0 h1:inaif7qD8bivyxp7XLgxUYtOXWtDez7+j72qKTMQTb8= @@ -39,8 +38,8 @@ github.com/chzyer/test v1.0.0/go.mod h1:2JlltgoNkt4TW/z9V/IzDdFaMTM2JPIi26O1pF38 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.4 h1:wfIWP927BUkWJb2NmU/kNDYIBTh/ziUX91+lVfRxZq4= -github.com/cpuguy83/go-md2man/v2 v2.0.4/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= +github.com/cpuguy83/go-md2man/v2 v2.0.5 h1:ZtcqGrnekaHpVLArFSe4HK5DoKx1T0rq2DwVB0alcyc= +github.com/cpuguy83/go-md2man/v2 v2.0.5/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= github.com/cyphar/filepath-securejoin v0.2.4 h1:Ugdm7cg7i6ZK6x3xDF1oEu1nfkyfH53EtKeQYTC3kyg= github.com/cyphar/filepath-securejoin v0.2.4/go.mod h1:aPGpWjXOXUn2NCNjFvBE6aRxGGx79pTxQpKOJNYHHl4= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= @@ -88,8 +87,8 @@ 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.9 h1:ACteMBRrrmm1gMsXe9PSTOClQ63IXDUt03H5U+UV8OU= -github.com/jedib0t/go-pretty/v6 v6.5.9/go.mod h1:zbn98qrYlh95FIhwwsbIip0LYpwSG8SUOScs+v9/t0E= +github.com/jedib0t/go-pretty/v6 v6.6.1 h1:iJ65Xjb680rHcikRj6DSIbzCex2huitmc7bDtxYVWyc= +github.com/jedib0t/go-pretty/v6 v6.6.1/go.mod h1:zbn98qrYlh95FIhwwsbIip0LYpwSG8SUOScs+v9/t0E= github.com/jfrog/archiver/v3 v3.6.1 h1:LOxnkw9pOn45DzCbZNFV6K0+6dCsQ0L8mR3ZcujO5eI= github.com/jfrog/archiver/v3 v3.6.1/go.mod h1:VgR+3WZS4N+i9FaDwLZbq+jeU4B4zctXL+gL4EMzfLw= github.com/jfrog/build-info-go v1.10.3 h1:9nqBdZD6xkuxiOvxg+idZ79QLFWQNuucvKkl8Xb42kw= @@ -203,8 +202,8 @@ github.com/terminalstatic/go-xsd-validate v0.1.5/go.mod h1:18lsvYFofBflqCrvo1ump github.com/ulikunitz/xz v0.5.6/go.mod h1:2bypXElzHzzJZwzH67Y6wb67pO62Rzfn7BSiF4ABRW8= github.com/ulikunitz/xz v0.5.12 h1:37Nm15o69RwBkXM0J6A5OlE67RZTfzUxTj8fB3dfcsc= github.com/ulikunitz/xz v0.5.12/go.mod h1:nbz6k7qbPmH4IRqmfOplQw/tblSgqTqBwxkY0oWt/14= -github.com/urfave/cli v1.22.15 h1:nuqt+pdC/KqswQKhETJjo7pvn/k4xMUxgW6liI7XpnM= -github.com/urfave/cli v1.22.15/go.mod h1:wSan1hmo5zeyLGBjRJbzRTNk8gwoYa2B9n4q9dmRIc0= +github.com/urfave/cli v1.22.16 h1:MH0k6uJxdwdeWQTwhSO42Pwr4YLrNLwBtg1MRgTqPdQ= +github.com/urfave/cli v1.22.16/go.mod h1:EeJR6BKodywf4zciqrdw6hpCPk68JO9z5LazXZMn5Po= github.com/vbauerster/mpb/v8 v8.8.3 h1:dTOByGoqwaTJYPubhVz3lO5O6MK553XVgUo33LdnNsQ= github.com/vbauerster/mpb/v8 v8.8.3/go.mod h1:JfCCrtcMsJwP6ZwMn9e5LMnNyp3TVNpUWWkN+nd4EWk= github.com/xanzy/ssh-agent v0.3.3 h1:+/15pJfg/RsTxqYcX6fHqOXZwwMP+2VyYWJeWM2qQFM= @@ -229,10 +228,10 @@ golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5y golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= golang.org/x/crypto v0.3.1-0.20221117191849-2c476679df9a/go.mod h1:hebNnKkNXi2UzZN1eVRvBB7co0a+JxK6XbPiWVs/3J4= golang.org/x/crypto v0.7.0/go.mod h1:pYwdfH91IfpZVANVyUOhSIPZaFoJGxTFbZhFTx+dXZU= -golang.org/x/crypto v0.27.0 h1:GXm2NjJrPaiv/h1tb2UH8QfgC/hOf/+z0p6PT8o1w7A= -golang.org/x/crypto v0.27.0/go.mod h1:1Xngt8kV6Dvbssa53Ziq6Eqn0HqbZi5Z6R0ZpwQzt70= -golang.org/x/exp v0.0.0-20240909161429-701f63a606c0 h1:e66Fs6Z+fZTbFBAxKfP3PALWBtpfqks2bwGcexMxgtk= -golang.org/x/exp v0.0.0-20240909161429-701f63a606c0/go.mod h1:2TbTHSBQa924w8M6Xs1QcRcFwyucIwBGpK1p2f1YFFY= +golang.org/x/crypto v0.28.0 h1:GBDwsMXVQi34v5CCYUm2jkJvu4cbtru2U4TN2PSyQnw= +golang.org/x/crypto v0.28.0/go.mod h1:rmgy+3RHxRZMyY0jjAJShp2zgEdOqj2AO7U0pYmeQ7U= +golang.org/x/exp v0.0.0-20241009180824-f66d83c29e7c h1:7dEasQXItcW1xKJ2+gg5VOiBnqWrJc+rq0DPKyvvdbY= +golang.org/x/exp v0.0.0-20241009180824-f66d83c29e7c/go.mod h1:NQtJDoLvd6faHhE7m4T/1IY708gDefGGjR/iUW8yQQ8= 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.21.0 h1:vvrHzRwRfVKSiLrG+d4FMl/Qi4ukBCE6kZlTUkDYRT0= @@ -244,8 +243,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.29.0 h1:5ORfpBpCs4HzDYoodCDBbwHzdR5UrLBZ3sOnUJmFoHo= -golang.org/x/net v0.29.0/go.mod h1:gLkgy8jTGERgjzMic6DS9+SP0ajcu6Xu3Orq/SpETg0= +golang.org/x/net v0.30.0 h1:AcW1SDZMkb8IpzCdQUaIq2sP4sZ4zw+55h6ynffypl4= +golang.org/x/net v0.30.0/go.mod h1:2wGyMJ5iFasEhkwi13ChkO/t1ECNC4X4eBKkVFyYFlU= 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= @@ -277,15 +276,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.25.0 h1:r+8e+loiHxRqhXVl6ML1nO3l1+oFoWbnlu2Ehimmi34= -golang.org/x/sys v0.25.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.26.0 h1:KHjCJyddX0LoSTb3J+vWpupP9p0oznkqVk/IfjymZbo= +golang.org/x/sys v0.26.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.24.0 h1:Mh5cbb+Zk2hqqXNO7S1iTjEphVL+jb8ZWaqh/g+JWkM= -golang.org/x/term v0.24.0/go.mod h1:lOBK/LVxemqiMij05LGJ0tzNr8xlmwBRJ81PX6wVLH8= +golang.org/x/term v0.25.0 h1:WtHI/ltw4NvSUig5KARz9h521QvRC8RmF/cuYqifU24= +golang.org/x/term v0.25.0/go.mod h1:RPyXicDX+6vLxogjjRxjgD2TKtmAO6NZBsBRfrOLu7M= 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= @@ -293,14 +292,14 @@ golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/text v0.8.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= -golang.org/x/text v0.18.0 h1:XvMDiNzPAl0jr17s6W9lcaIhGUfUORdGCNsuLmPG224= -golang.org/x/text v0.18.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY= +golang.org/x/text v0.19.0 h1:kTxAhCbGbxhK0IwgSKiMO5awPoDQ0RpfiVYBfK860YM= +golang.org/x/text v0.19.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= 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.25.0 h1:oFU9pkj/iJgs+0DT+VMHrx+oBKs/LJMV+Uvg78sl+fE= -golang.org/x/tools v0.25.0/go.mod h1:/vtpO8WL1N9cQC3FN5zPqb//fRXskFHbLKk4OW1Q7rg= +golang.org/x/tools v0.26.0 h1:v/60pFQmzmT9ExmjDv2gGIfi3OqfKoEP6I5+umXlbnQ= +golang.org/x/tools v0.26.0/go.mod h1:TPVVj70c7JJ3WCazhD8OdXcZg/og+b9+tH/KxylGwH0= 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/utils/golang/utils.go b/utils/golang/utils.go deleted file mode 100644 index 645b23bad..000000000 --- a/utils/golang/utils.go +++ /dev/null @@ -1,144 +0,0 @@ -package goutils - -import ( - "github.com/jfrog/build-info-go/utils" - "github.com/jfrog/jfrog-cli-core/v2/utils/config" - "github.com/jfrog/jfrog-client-go/auth" - "github.com/jfrog/jfrog-client-go/utils/errorutils" - "github.com/jfrog/jfrog-client-go/utils/log" - "io" - "net/url" - "os/exec" - "path" - "strings" -) - -type GoCmdConfig struct { - Go string - Command []string - CommandFlags []string - Dir string - StrWriter io.WriteCloser - ErrWriter io.WriteCloser -} - -func NewGoCmdConfig() (*GoCmdConfig, error) { - execPath, err := exec.LookPath("go") - if err != nil { - return nil, errorutils.CheckError(err) - } - return &GoCmdConfig{Go: execPath}, nil -} - -func (config *GoCmdConfig) GetCmd() (cmd *exec.Cmd) { - var cmdStr []string - cmdStr = append(cmdStr, config.Go) - cmdStr = append(cmdStr, config.Command...) - cmdStr = append(cmdStr, config.CommandFlags...) - cmd = exec.Command(cmdStr[0], cmdStr[1:]...) - cmd.Dir = config.Dir - return -} - -func (config *GoCmdConfig) GetEnv() map[string]string { - return map[string]string{} -} - -func (config *GoCmdConfig) GetStdWriter() io.WriteCloser { - return config.StrWriter -} - -func (config *GoCmdConfig) GetErrWriter() io.WriteCloser { - return config.ErrWriter -} - -func LogGoVersion() error { - version, err := utils.GetParsedGoVersion() - if err != nil { - return errorutils.CheckError(err) - } - log.Info("Using go:", version.GetVersion()) - return nil -} - -func GetGoModCachePath() (string, error) { - path, err := utils.GetGoModCachePath() - if err != nil { - return "", errorutils.CheckError(err) - } - return path, nil -} - -func GetProjectRoot() (string, error) { - path, err := utils.GetProjectRoot() - if err != nil { - return "", errorutils.CheckError(err) - } - return path, nil -} - -func GetModuleName(projectDir string) (string, error) { - path, err := utils.GetModuleNameByDir(projectDir, log.Logger) - if err != nil { - return "", errorutils.CheckError(err) - } - return path, nil -} - -type GoProxyUrlParams struct { - // Fallback to retrieve the modules directly from the source if - // the module failed to be retrieved from the proxy. - // add |direct to the end of the url. - // example: https://gocenter.io|direct - Direct bool - // The path from baseUrl to the standard Go repository path - // URL structure: //api/go/ - EndpointPrefix string -} - -func (gdu *GoProxyUrlParams) BuildUrl(url *url.URL, repoName string) string { - url.Path = path.Join(url.Path, gdu.EndpointPrefix, "api/go/", repoName) - - return gdu.addDirect(url.String()) -} - -func (gdu *GoProxyUrlParams) addDirect(url string) string { - if gdu.Direct && !strings.HasSuffix(url, "|direct") { - return url + "|direct" - } - return url -} - -func GetArtifactoryRemoteRepoUrl(serverDetails *config.ServerDetails, repo string, goProxyParams GoProxyUrlParams) (string, error) { - authServerDetails, err := serverDetails.CreateArtAuthConfig() - if err != nil { - return "", err - } - return getArtifactoryApiUrl(repo, authServerDetails, goProxyParams) -} - -// Gets the URL of the specified repository Go API in Artifactory. -// The URL contains credentials (username and access token or password). -func getArtifactoryApiUrl(repoName string, details auth.ServiceDetails, goProxyParams GoProxyUrlParams) (string, error) { - rtUrl, err := url.Parse(details.GetUrl()) - if err != nil { - return "", errorutils.CheckError(err) - } - - username := details.GetUser() - password := details.GetPassword() - - // Get credentials from access-token if exists. - if details.GetAccessToken() != "" { - log.Debug("Using proxy with access-token.") - if username == "" { - username = auth.ExtractUsernameFromAccessToken(details.GetAccessToken()) - } - password = details.GetAccessToken() - } - if password != "" { - rtUrl.User = url.UserPassword(username, password) - } - - return goProxyParams.BuildUrl(rtUrl, repoName), nil -} diff --git a/utils/golang/utils_test.go b/utils/golang/utils_test.go deleted file mode 100644 index e6ec32041..000000000 --- a/utils/golang/utils_test.go +++ /dev/null @@ -1,96 +0,0 @@ -package goutils - -import ( - "github.com/jfrog/jfrog-cli-core/v2/utils/config" - "github.com/jfrog/jfrog-client-go/artifactory/auth" - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" - "net/url" - "testing" -) - -func TestGetArtifactoryRemoteRepoUrl(t *testing.T) { - server := &config.ServerDetails{ - ArtifactoryUrl: "https://server.com/artifactory", - AccessToken: "eyJ0eXAiOiJKV1QifQ.eyJzdWIiOiJmYWtlXC91c2Vyc1wvdGVzdCJ9.MTIzNDU2Nzg5MA", - } - repoName := "test-repo" - repoUrl, err := GetArtifactoryRemoteRepoUrl(server, repoName, GoProxyUrlParams{}) - assert.NoError(t, err) - assert.Equal(t, "https://test:eyJ0eXAiOiJKV1QifQ.eyJzdWIiOiJmYWtlXC91c2Vyc1wvdGVzdCJ9.MTIzNDU2Nzg5MA@server.com/artifactory/api/go/test-repo", repoUrl) -} - -func TestGetArtifactoryApiUrl(t *testing.T) { - details := auth.NewArtifactoryDetails() - details.SetUrl("https://test.com/artifactory/") - - // Test username and password - details.SetUser("frog") - details.SetPassword("passfrog") - url, err := getArtifactoryApiUrl("test-repo", details, GoProxyUrlParams{}) - assert.NoError(t, err) - assert.Equal(t, "https://frog:passfrog@test.com/artifactory/api/go/test-repo", url) - - // Test username and password with EndpointPrefix and direct - details.SetUser("frog") - details.SetPassword("passfrog") - url, err = getArtifactoryApiUrl("test-repo", details, GoProxyUrlParams{EndpointPrefix: "test", Direct: true}) - assert.NoError(t, err) - assert.Equal(t, "https://frog:passfrog@test.com/artifactory/test/api/go/test-repo|direct", url) - - // Test access token - // Set fake access token with username "test" - details.SetUser("") - details.SetAccessToken("eyJ0eXAiOiJKV1QifQ.eyJzdWIiOiJmYWtlXC91c2Vyc1wvdGVzdCJ9.MTIzNDU2Nzg5MA") - url, err = getArtifactoryApiUrl("test-repo", details, GoProxyUrlParams{}) - assert.NoError(t, err) - assert.Equal(t, "https://test:eyJ0eXAiOiJKV1QifQ.eyJzdWIiOiJmYWtlXC91c2Vyc1wvdGVzdCJ9.MTIzNDU2Nzg5MA@test.com/artifactory/api/go/test-repo", url) - - // Test access token with username - // Set fake access token with username "test" - // Expect username to be "frog" - details.SetUser("frog") - details.SetAccessToken("eyJ0eXAiOiJKV1QifQ.eyJzdWIiOiJmYWtlXC91c2Vyc1wvdGVzdCJ9.MTIzNDU2Nzg5MA") - url, err = getArtifactoryApiUrl("test-repo", details, GoProxyUrlParams{}) - assert.NoError(t, err) - assert.Equal(t, "https://frog:eyJ0eXAiOiJKV1QifQ.eyJzdWIiOiJmYWtlXC91c2Vyc1wvdGVzdCJ9.MTIzNDU2Nzg5MA@test.com/artifactory/api/go/test-repo", url) -} - -func TestGoProxyUrlParams_BuildUrl(t *testing.T) { - tests := []struct { - name string - RepoName string - Direct bool - EndpointPrefix string - ExpectedUrl string - }{ - { - name: "Url Without direct or Prefix", - RepoName: "go", - ExpectedUrl: "https://test/api/go/go", - }, - { - name: "Url With direct", - RepoName: "go", - Direct: true, - ExpectedUrl: "https://test/api/go/go|direct", - }, - { - name: "Url With Prefix", - RepoName: "go", - EndpointPrefix: "prefix", - ExpectedUrl: "https://test/prefix/api/go/go", - }, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - remoteUrl, err := url.Parse("https://test") - require.NoError(t, err) - gdu := &GoProxyUrlParams{ - Direct: tt.Direct, - EndpointPrefix: tt.EndpointPrefix, - } - assert.Equalf(t, tt.ExpectedUrl, gdu.BuildUrl(remoteUrl, tt.RepoName), "BuildUrl(%v, %v)", remoteUrl, tt.RepoName) - }) - } -} diff --git a/utils/gradle/utils.go b/utils/gradle/utils.go deleted file mode 100644 index cd019443c..000000000 --- a/utils/gradle/utils.go +++ /dev/null @@ -1,87 +0,0 @@ -package gradleutils - -import ( - "fmt" - "github.com/jfrog/jfrog-cli-core/v2/common/build" - "github.com/jfrog/jfrog-cli-core/v2/common/project" - "github.com/jfrog/jfrog-cli-core/v2/utils/config" - "github.com/jfrog/jfrog-cli-core/v2/utils/coreutils" - "github.com/jfrog/jfrog-cli-core/v2/utils/dependencies" - "github.com/jfrog/jfrog-client-go/utils/errorutils" - "github.com/spf13/viper" - "path/filepath" -) - -const ( - usePlugin = "useplugin" - useWrapper = "usewrapper" -) - -func RunGradle(vConfig *viper.Viper, tasks []string, deployableArtifactsFile string, configuration *build.BuildConfiguration, threads int, disableDeploy bool) error { - buildInfoService := build.CreateBuildInfoService() - buildName, err := configuration.GetBuildName() - if err != nil { - return err - } - buildNumber, err := configuration.GetBuildNumber() - if err != nil { - return err - } - gradleBuild, err := buildInfoService.GetOrCreateBuildWithProject(buildName, buildNumber, configuration.GetProject()) - if err != nil { - return errorutils.CheckError(err) - } - gradleModule, err := gradleBuild.AddGradleModule("") - if err != nil { - return errorutils.CheckError(err) - } - props, wrapper, plugin, err := createGradleRunConfig(vConfig, deployableArtifactsFile, threads, disableDeploy) - if err != nil { - return err - } - dependencyLocalPath, err := getGradleDependencyLocalPath() - if err != nil { - return err - } - gradleModule.SetExtractorDetails(dependencyLocalPath, filepath.Join(coreutils.GetCliPersistentTempDirPath(), build.PropertiesTempPath), tasks, wrapper, plugin, dependencies.DownloadExtractor, props) - return coreutils.ConvertExitCodeError(gradleModule.CalcDependencies()) -} - -func getGradleDependencyLocalPath() (string, error) { - dependenciesPath, err := config.GetJfrogDependenciesPath() - if err != nil { - return "", err - } - return filepath.Join(dependenciesPath, "gradle"), nil -} - -func createGradleRunConfig(vConfig *viper.Viper, deployableArtifactsFile string, threads int, disableDeploy bool) (props map[string]string, wrapper, plugin bool, err error) { - wrapper = vConfig.GetBool(useWrapper) - if threads > 0 { - vConfig.Set(build.ForkCount, threads) - } - - if disableDeploy { - setDeployFalse(vConfig) - } - props, err = build.CreateBuildInfoProps(deployableArtifactsFile, vConfig, project.Gradle) - if err != nil { - return - } - if deployableArtifactsFile != "" { - // Save the path to a temp file, where buildinfo project will write the deployable artifacts details. - props[build.DeployableArtifacts] = fmt.Sprint(vConfig.Get(build.DeployableArtifacts)) - } - plugin = vConfig.GetBool(usePlugin) - return -} - -func setDeployFalse(vConfig *viper.Viper) { - vConfig.Set(build.DeployerPrefix+build.DeployArtifacts, "false") - if vConfig.GetString(build.DeployerPrefix+build.Url) == "" { - vConfig.Set(build.DeployerPrefix+build.Url, "http://empty_url") - } - if vConfig.GetString(build.DeployerPrefix+build.Repo) == "" { - vConfig.Set(build.DeployerPrefix+build.Repo, "empty_repo") - } -} diff --git a/utils/python/utils.go b/utils/python/utils.go deleted file mode 100644 index 7a599b28a..000000000 --- a/utils/python/utils.go +++ /dev/null @@ -1,135 +0,0 @@ -package utils - -import ( - "fmt" - "github.com/jfrog/jfrog-cli-core/v2/utils/coreutils" - "net/url" - "os" - "path/filepath" - "strings" - - "github.com/jfrog/build-info-go/utils/pythonutils" - "github.com/jfrog/gofrog/io" - gofrogcmd "github.com/jfrog/gofrog/io" - "github.com/jfrog/jfrog-cli-core/v2/utils/config" - "github.com/jfrog/jfrog-client-go/auth" - "github.com/jfrog/jfrog-client-go/utils/errorutils" - "github.com/jfrog/jfrog-client-go/utils/log" - "github.com/spf13/viper" -) - -const ( - pipenvRemoteRegistryFlag = "--pypi-mirror" - pipRemoteRegistryFlag = "-i" - poetryConfigAuthPrefix = "http-basic." - poetryConfigRepoPrefix = "repositories." - pyproject = "pyproject.toml" -) - -func GetPypiRepoUrlWithCredentials(serverDetails *config.ServerDetails, repository string, isCurationCmd bool) (*url.URL, string, string, error) { - rtUrl, err := url.Parse(serverDetails.GetArtifactoryUrl()) - if err != nil { - return nil, "", "", errorutils.CheckError(err) - } - - username := serverDetails.GetUser() - password := serverDetails.GetPassword() - - // Get credentials from access-token if exists. - if serverDetails.GetAccessToken() != "" { - if username == "" { - username = auth.ExtractUsernameFromAccessToken(serverDetails.GetAccessToken()) - } - password = serverDetails.GetAccessToken() - } - // In case of curation command, the download urls should be routed through a dedicated api. - if isCurationCmd { - rtUrl.Path += coreutils.CurationPassThroughApi - } - rtUrl.Path += "api/pypi/" + repository + "/simple" - return rtUrl, username, password, err -} - -func GetPypiRemoteRegistryFlag(tool pythonutils.PythonTool) string { - if tool == pythonutils.Pip { - return pipRemoteRegistryFlag - } - return pipenvRemoteRegistryFlag -} - -func GetPypiRepoUrl(serverDetails *config.ServerDetails, repository string, isCurationCmd bool) (string, error) { - rtUrl, username, password, err := GetPypiRepoUrlWithCredentials(serverDetails, repository, isCurationCmd) - if err != nil { - return "", err - } - if password != "" { - rtUrl.User = url.UserPassword(username, password) - } - return rtUrl.String(), err -} - -func ConfigPoetryRepo(url, username, password, configRepoName string) error { - // Add the poetry repository config - err := runPoetryConfigCommand([]string{poetryConfigRepoPrefix + configRepoName, url}, false) - if err != nil { - return err - } - - // Set the poetry repository credentials - err = runPoetryConfigCommand([]string{poetryConfigAuthPrefix + configRepoName, username, password}, true) - if err != nil { - return err - } - - // Add the repository config to the pyproject.toml - currentDir, err := os.Getwd() - if err != nil { - return errorutils.CheckError(err) - } - if err = addRepoToPyprojectFile(filepath.Join(currentDir, pyproject), configRepoName, url); err != nil { - return err - } - return poetryUpdate() -} - -func poetryUpdate() (err error) { - log.Info("Running Poetry update") - cmd := io.NewCommand("poetry", "update", []string{}) - err = gofrogcmd.RunCmd(cmd) - if err != nil { - return errorutils.CheckErrorf("Poetry config command failed with: %s", err.Error()) - } - return -} - -func runPoetryConfigCommand(args []string, maskArgs bool) error { - logMessage := "config " - if maskArgs { - logMessage += "***" - } else { - logMessage += strings.Join(args, " ") - } - log.Info(fmt.Sprintf("Running Poetry %s", logMessage)) - cmd := io.NewCommand("poetry", "config", args) - err := gofrogcmd.RunCmd(cmd) - if err != nil { - return errorutils.CheckErrorf("Poetry config command failed with: %s", err.Error()) - } - return nil -} - -func addRepoToPyprojectFile(filepath, poetryRepoName, repoUrl string) error { - viper.SetConfigType("toml") - viper.SetConfigFile(filepath) - err := viper.ReadInConfig() - if err != nil { - return errorutils.CheckErrorf("Failed to read pyproject.toml: %s", err.Error()) - } - viper.Set("tool.poetry.source", []map[string]string{{"name": poetryRepoName, "url": repoUrl}}) - err = viper.WriteConfig() - if err != nil { - return errorutils.CheckErrorf("Failed to add tool.poetry.source to pyproject.toml: %s", err.Error()) - } - log.Info(fmt.Sprintf("Added tool.poetry.source name:%q url:%q", poetryRepoName, repoUrl)) - return err -} diff --git a/utils/python/utils_test.go b/utils/python/utils_test.go deleted file mode 100644 index 3ef8785c8..000000000 --- a/utils/python/utils_test.go +++ /dev/null @@ -1,61 +0,0 @@ -package utils - -import ( - "github.com/jfrog/jfrog-cli-core/v2/utils/config" - "github.com/jfrog/jfrog-cli-core/v2/utils/coreutils" - "github.com/stretchr/testify/require" - "path/filepath" - "strings" - "testing" - - "github.com/jfrog/jfrog-cli-core/v2/utils/tests" - "github.com/jfrog/jfrog-client-go/utils/io/fileutils" - "github.com/stretchr/testify/assert" -) - -func TestAddRepoToPyprojectFile(t *testing.T) { - poetryProjectPath, cleanUp := initPoetryTest(t) - defer cleanUp() - pyProjectPath := filepath.Join(poetryProjectPath, "pyproject.toml") - dummyRepoName := "test-repo-name" - dummyRepoURL := "https://ecosysjfrog.jfrog.io/" - - err := addRepoToPyprojectFile(pyProjectPath, dummyRepoName, dummyRepoURL) - assert.NoError(t, err) - // Validate pyproject.toml file content - content, err := fileutils.ReadFile(pyProjectPath) - assert.NoError(t, err) - assert.Contains(t, string(content), dummyRepoURL) -} - -func initPoetryTest(t *testing.T) (string, func()) { - // Create and change directory to test workspace - testAbs, err := filepath.Abs(filepath.Join("..", "..", "tests", "testdata", "poetry-project")) - assert.NoError(t, err) - poetryProjectPath, cleanUp := tests.CreateTestWorkspace(t, testAbs) - return poetryProjectPath, cleanUp -} - -func TestGetPypiRepoUrlWithCredentials(t *testing.T) { - tests := []struct { - name string - curationCmd bool - }{ - { - name: "test curation command true", - curationCmd: true, - }, - { - name: "test curation command false", - curationCmd: false, - }, - } - - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - url, _, _, err := GetPypiRepoUrlWithCredentials(&config.ServerDetails{}, "test", tt.curationCmd) - require.NoError(t, err) - assert.Equal(t, tt.curationCmd, strings.Contains(url.Path, coreutils.CurationPassThroughApi)) - }) - } -}