From 57a59e31b87f058468bc60536e06ba32710c5beb Mon Sep 17 00:00:00 2001 From: Eran Turgeman Date: Sun, 25 Feb 2024 10:29:57 +0200 Subject: [PATCH] added SetArtifactoryAsResolutionServer for nuget projects --- artifactory/commands/dotnet/dotnetcommand.go | 68 +++++++++++++++++-- .../commands/dotnet/dotnetcommand_test.go | 4 +- go.mod | 6 +- go.sum | 8 +-- 4 files changed, 73 insertions(+), 13 deletions(-) diff --git a/artifactory/commands/dotnet/dotnetcommand.go b/artifactory/commands/dotnet/dotnetcommand.go index 60c79e4e0..d66cb1bb2 100644 --- a/artifactory/commands/dotnet/dotnetcommand.go +++ b/artifactory/commands/dotnet/dotnetcommand.go @@ -5,6 +5,7 @@ import ( "fmt" "github.com/jfrog/build-info-go/build" "github.com/jfrog/build-info-go/build/utils/dotnet" + "github.com/jfrog/build-info-go/utils" "github.com/jfrog/gofrog/io" commonBuild "github.com/jfrog/jfrog-cli-core/v2/common/build" "github.com/jfrog/jfrog-cli-core/v2/utils/config" @@ -15,6 +16,7 @@ import ( "net/url" "os" "path" + "path/filepath" "strings" ) @@ -27,6 +29,8 @@ Note that JFrog CLI does not restore dependencies during a 'dotnet test' command The initial error is: ` noRestoreFlag = "--no-restore" + + nugetConfigFileName = "NuGet.config" ) type DotnetCommand struct { @@ -237,7 +241,7 @@ func (dc *DotnetCommand) prepareConfigFileIfNeeded() (cleanup func() error, err return fileutils.RemoveTempDir(tempDirPath) } - configFile, err := InitNewConfig(tempDirPath, dc.repoName, dc.serverDetails, dc.useNugetV2) + configFile, err := InitNewConfig(tempDirPath, dc.repoName, "", dc.serverDetails, dc.useNugetV2) if err == nil { dc.argAndFlags = append(dc.argAndFlags, dc.GetToolchain().GetTypeFlagPrefix()+"configfile", configFile.Name()) } @@ -263,10 +267,15 @@ func getFlagValueIfExists(cmdFlag string, argAndFlags []string) (string, error) return "", nil } +// TODO ERAN fix test? // InitNewConfig is used when neither of the flags were provided, and we need to init our own config. -func InitNewConfig(configDirPath, repoName string, server *config.ServerDetails, useNugetV2 bool) (configFile *os.File, err error) { - // Initializing a new NuGet config file that NuGet will use into a temp file - configFile, err = os.CreateTemp(configDirPath, configFilePattern) +func InitNewConfig(configDirPath, repoName, configFileName string, server *config.ServerDetails, useNugetV2 bool) (configFile *os.File, err error) { + // Initializing a new NuGet config file to be used by NuGet commands + if configFileName == "" { + configFile, err = os.CreateTemp(configDirPath, configFilePattern) + } else { + configFile, err = os.OpenFile(configFileName, os.O_RDWR|os.O_CREATE|os.O_EXCL, 0600) + } if errorutils.CheckError(err) != nil { return } @@ -328,3 +337,54 @@ func getSourceDetails(details *config.ServerDetails, repoName string, useNugetV2 } return } + +// TODO ERAN add test + fix comments +// Configures an Artifactory server as a dependencies resolution registry by creating a configfile that is passed by a flag to the 'install' command +// dirPath is the directory in which we create the config file +// toolType is the dependencies management tool we use: .NET or NuGet +// canPassConfigFileDirectly tells us if we can pass the created config file directly with the flag --configfile. If not, in some cases, we must use +func SetArtifactoryAsResolutionServer(serverDetails *config.ServerDetails, depsRepo string, dirPath string, toolType dotnet.ToolchainType, canPassConfigFileDirectly bool) (installCommandArgs []string, clearResolutionServerFunc func() error, err error) { + log.Info(fmt.Sprintf("Resolving dependencies from '%s' from repo '%s'", serverDetails.Url, depsRepo)) + var configFile *os.File + if canPassConfigFileDirectly { + // If the command we wish to run after configuring the integration with an Artifactory server allow passing a config file directly using -configfile / --configfile flag + // We create a config file with a random name and send its path to the command + configFile, err = InitNewConfig(dirPath, depsRepo, "", serverDetails, false) + if err != nil { + err = fmt.Errorf("failed while attempting to generate a configuration file for setting up an Artifactory as a resolution registry") + return + } + installCommandArgs = append(installCommandArgs, toolType.GetTypeFlagPrefix()+"configfile", configFile.Name()) + + clearResolutionServerFunc = func() error { + return errors.Join(err, os.Remove(configFile.Name())) + } + } else { + // If the command we wish to run after configuring the integration with an Artifactory server doesn't allow passing a config file directly using -configfile / --configfile flag + // We create a config file with the default expected name, NuGet.config, since some commands doesn't support any other convention or able to recognize this file with any other name + + // If we already have NuGet.config in the directory we keep it in a temp dir before overriding it + var containerDir string + existingConfigFilePath := filepath.Join(dirPath, nugetConfigFileName) + if containerDir, err = utils.KeepFilesInTempDirIfExist([]string{existingConfigFilePath}); err != nil { + return + } + + configFile, err = InitNewConfig(dirPath, depsRepo, nugetConfigFileName, serverDetails, false) + if err != nil { + err = fmt.Errorf("failed while attempting to generate a configuration file for setting up an Artifactory as a resolution registry") + return + } + + clearResolutionServerFunc = func() error { + err = errors.Join(err, os.Remove(configFile.Name())) + if containerDir != "" { + oldConfigFilePath := filepath.Join(containerDir, nugetConfigFileName) + err = errors.Join(err, utils.CopyFile(dirPath, oldConfigFilePath)) + err = errors.Join(err, utils.RemoveTempDir(containerDir)) + } + return err + } + } + return +} diff --git a/artifactory/commands/dotnet/dotnetcommand_test.go b/artifactory/commands/dotnet/dotnetcommand_test.go index a89fade31..f6ee2e4b3 100644 --- a/artifactory/commands/dotnet/dotnetcommand_test.go +++ b/artifactory/commands/dotnet/dotnetcommand_test.go @@ -74,7 +74,7 @@ func TestInitNewConfig(t *testing.T) { User: "user", Password: "pass", } - configFile, err := InitNewConfig(tmpDir, repoName, server, false) + configFile, err := InitNewConfig(tmpDir, repoName, "", server, false) assert.NoError(t, err) f, err := os.Open(configFile.Name()) assert.NoError(t, err) @@ -98,7 +98,7 @@ func TestInitNewConfig(t *testing.T) { `, string(buf[:n])) server.Password = "" server.AccessToken = "abc123" - configFile, err = InitNewConfig(tmpDir, repoName, server, true) + configFile, err = InitNewConfig(tmpDir, repoName, "", server, true) assert.NoError(t, err) updatedConfigFile, err := os.Open(configFile.Name()) assert.NoError(t, err) diff --git a/go.mod b/go.mod index b2faee7a3..45b8c635d 100644 --- a/go.mod +++ b/go.mod @@ -12,7 +12,7 @@ require ( github.com/google/uuid v1.6.0 github.com/gookit/color v1.5.4 github.com/jedib0t/go-pretty/v6 v6.5.4 - github.com/jfrog/build-info-go v1.9.21 + github.com/jfrog/build-info-go v1.9.23 github.com/jfrog/gofrog v1.6.0 github.com/jfrog/jfrog-client-go v1.36.0 github.com/magiconair/properties v1.8.7 @@ -33,7 +33,7 @@ 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 @@ -98,6 +98,6 @@ require ( 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 +replace github.com/jfrog/build-info-go => github.com/eranturgeman/build-info-go v0.0.0-20240225082441-c0213bb4fbda // replace github.com/jfrog/gofrog => github.com/jfrog/gofrog v1.3.3-0.20231223133729-ef57bd08cedc diff --git a/go.sum b/go.sum index 2f8bea419..89b89b99e 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= @@ -49,6 +49,8 @@ github.com/dsnet/golib v0.0.0-20171103203638-1ea166775780/go.mod h1:Lj+Z9rebOhdf github.com/elazarl/goproxy v0.0.0-20230808193330-2592e75ae04a h1:mATvB/9r/3gvcejNsXKSkQ6lcIaNec2nyfOdlTBR2lU= github.com/emirpasic/gods v1.18.1 h1:FXtiHYKDGKCW2KzwZKx0iC0PQmdlorYgdFG9jPXJ1Bc= github.com/emirpasic/gods v1.18.1/go.mod h1:8tpGGwCnJ5H4r6BWwaV6OrWmMoPhUl5jm/FMNAnJvWQ= +github.com/eranturgeman/build-info-go v0.0.0-20240225082441-c0213bb4fbda h1:i1OkEeNXNee0WeeQnYJHB6dYeKrbWg+F/Crz+kChVjA= +github.com/eranturgeman/build-info-go v0.0.0-20240225082441-c0213bb4fbda/go.mod h1:QHcKuesY4MrBVBuEwwBz4uIsX6mwYuMEDV09ng4AvAU= github.com/forPelevin/gomoji v1.1.8 h1:JElzDdt0TyiUlecy6PfITDL6eGvIaxqYH1V52zrd0qQ= github.com/forPelevin/gomoji v1.1.8/go.mod h1:8+Z3KNGkdslmeGZBC3tCrwMrcPy5GRzAD+gL9NAwMXg= github.com/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHkI4W8= @@ -83,8 +85,6 @@ github.com/jedib0t/go-pretty/v6 v6.5.4 h1:gOGo0613MoqUcf0xCj+h/V3sHDaZasfv152G6/ 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.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.28.1-0.20240218093454-1c352a93c23d h1:59C2AOjdp5Wp/WoeQZkOGbAtKnhY1a9YhrnAdeVbVYs=