From 296600d31ae3ad300c35d0d9eba457a35bdb8850 Mon Sep 17 00:00:00 2001 From: oshratz Date: Thu, 14 Nov 2024 13:27:59 +0200 Subject: [PATCH 1/9] Turn the signing key to be optional in RBC --- lifecycle/cli.go | 4 ---- lifecycle/cli_test.go | 2 +- 2 files changed, 1 insertion(+), 5 deletions(-) diff --git a/lifecycle/cli.go b/lifecycle/cli.go index 92a7a5d0e..d45068b4e 100644 --- a/lifecycle/cli.go +++ b/lifecycle/cli.go @@ -127,10 +127,6 @@ func validateCreateReleaseBundleContext(c *cli.Context) error { return cliutils.WrongNumberOfArgumentsHandler(c) } - if err := assertSigningKeyProvided(c); err != nil { - return err - } - return assertValidCreationMethod(c) } diff --git a/lifecycle/cli_test.go b/lifecycle/cli_test.go index 65b911958..a09ac6e91 100644 --- a/lifecycle/cli_test.go +++ b/lifecycle/cli_test.go @@ -21,7 +21,7 @@ func TestValidateCreateReleaseBundleContext(t *testing.T) { {"extraArgs", []string{"one", "two", "three", "four"}, []string{}, true}, {"bothSources", []string{"one", "two", "three"}, []string{cliutils.Builds + "=/path/to/file", cliutils.ReleaseBundles + "=/path/to/file"}, true}, {"noSources", []string{"one", "two", "three"}, []string{}, true}, - {"builds without signing key", []string{"name", "version"}, []string{cliutils.Builds + "=/path/to/file"}, true}, + {"builds without signing key", []string{"name", "version"}, []string{cliutils.Builds + "=/path/to/file"}, false}, {"builds correct", []string{"name", "version"}, []string{ cliutils.Builds + "=/path/to/file", cliutils.SigningKey + "=key"}, false}, {"releaseBundles without signing key", []string{"name", "version", "env"}, []string{cliutils.ReleaseBundles + "=/path/to/file"}, true}, From 7ac19f5f3f1737448683a8c6d89af1a2da6bc769 Mon Sep 17 00:00:00 2001 From: oshratz Date: Thu, 14 Nov 2024 17:36:40 +0200 Subject: [PATCH 2/9] Turn the signing key to be optional in RBC --- lifecycle_test.go | 32 ++++++++++++++++++++------------ 1 file changed, 20 insertions(+), 12 deletions(-) diff --git a/lifecycle_test.go b/lifecycle_test.go index 455f035d8..c566793e3 100644 --- a/lifecycle_test.go +++ b/lifecycle_test.go @@ -87,14 +87,18 @@ func compareRbArtifacts(t *testing.T, actual services.ReleaseBundleSpecResponse, } func TestReleaseBundleCreationFromAql(t *testing.T) { - testReleaseBundleCreation(t, tests.UploadDevSpecA, tests.LifecycleAql, tests.GetExpectedLifecycleCreationByAql()) + testReleaseBundleCreation(t, tests.UploadDevSpecA, tests.LifecycleAql, tests.GetExpectedLifecycleCreationByAql(), false) } func TestReleaseBundleCreationFromArtifacts(t *testing.T) { - testReleaseBundleCreation(t, tests.UploadDevSpec, tests.LifecycleArtifacts, tests.GetExpectedLifecycleCreationByArtifacts()) + testReleaseBundleCreation(t, tests.UploadDevSpec, tests.LifecycleArtifacts, tests.GetExpectedLifecycleCreationByArtifacts(), false) } -func testReleaseBundleCreation(t *testing.T, uploadSpec, creationSpec string, expected []string) { +func TestReleaseBundleCreationFromArtifactsWithoutSigningKey(t *testing.T) { + testReleaseBundleCreation(t, tests.UploadDevSpec, tests.LifecycleArtifacts, tests.GetExpectedLifecycleCreationByArtifacts(), true) +} + +func testReleaseBundleCreation(t *testing.T, uploadSpec, creationSpec string, expected []string, withoutKey bool) { cleanCallback := initLifecycleTest(t) defer cleanCallback() lcManager := getLcServiceManager(t) @@ -103,7 +107,7 @@ func testReleaseBundleCreation(t *testing.T, uploadSpec, creationSpec string, ex assert.NoError(t, err) runRt(t, "upload", "--spec="+specFile) - createRbFromSpec(t, creationSpec, tests.LcRbName1, number1, true) + createRbFromSpec(t, creationSpec, tests.LcRbName1, number1, true, withoutKey) defer deleteReleaseBundle(t, lcManager, tests.LcRbName1, number1) assertRbArtifacts(t, lcManager, tests.LcRbName1, number1, expected) @@ -119,17 +123,17 @@ func TestLifecycleFullFlow(t *testing.T) { defer deleteBuilds() // Create release bundle from builds synchronously. - createRbFromSpec(t, tests.LifecycleBuilds12, tests.LcRbName1, number1, true) + createRbFromSpec(t, tests.LifecycleBuilds12, tests.LcRbName1, number1, true, false) defer deleteReleaseBundle(t, lcManager, tests.LcRbName1, number1) // Create release bundle from a build asynchronously and assert status. // This build has dependencies which are included in the release bundle. - createRbFromSpec(t, tests.LifecycleBuilds3, tests.LcRbName2, number2, false) + createRbFromSpec(t, tests.LifecycleBuilds3, tests.LcRbName2, number2, false, false) defer deleteReleaseBundle(t, lcManager, tests.LcRbName2, number2) assertStatusCompleted(t, lcManager, tests.LcRbName2, number2, "") // Create a combined release bundle from the two previous release bundle. - createRbFromSpec(t, tests.LifecycleReleaseBundles, tests.LcRbName3, number3, true) + createRbFromSpec(t, tests.LifecycleReleaseBundles, tests.LcRbName3, number3, true, false) defer deleteReleaseBundle(t, lcManager, tests.LcRbName3, number3) // Promote the last release bundle to prod repo 1. @@ -195,23 +199,27 @@ func uploadBuilds(t *testing.T) func() { func createRbBackwardCompatible(t *testing.T, specName, sourceOption, rbName, rbVersion string, sync bool) { specFile, err := getSpecFile(specName) assert.NoError(t, err) - createRb(t, specFile, sourceOption, rbName, rbVersion, sync) + createRb(t, specFile, sourceOption, rbName, rbVersion, sync, false) } -func createRbFromSpec(t *testing.T, specName, rbName, rbVersion string, sync bool) { +func createRbFromSpec(t *testing.T, specName, rbName, rbVersion string, sync bool, withoutKey bool) { specFile, err := tests.CreateSpec(specName) assert.NoError(t, err) - createRb(t, specFile, "spec", rbName, rbVersion, sync) + createRb(t, specFile, "spec", rbName, rbVersion, sync, withoutKey) } -func createRb(t *testing.T, specFilePath, sourceOption, rbName, rbVersion string, sync bool) { +func createRb(t *testing.T, specFilePath, sourceOption, rbName, rbVersion string, sync bool, withoutKey bool) { argsAndOptions := []string{ "rbc", rbName, rbVersion, getOption(sourceOption, specFilePath), - getOption(cliutils.SigningKey, gpgKeyPairName), } + + if !withoutKey { + argsAndOptions = append(argsAndOptions, getOption(cliutils.SigningKey, gpgKeyPairName)) + } + // Add the --sync option only if requested, to test the default value. if sync { argsAndOptions = append(argsAndOptions, getOption(cliutils.Sync, "true")) From 7ecf2d443273317756830350f67e299ad0e4e556 Mon Sep 17 00:00:00 2001 From: oshratz Date: Sun, 17 Nov 2024 11:38:37 +0200 Subject: [PATCH 3/9] Turn the signing key to be optional in RBC --- lifecycle/cli_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lifecycle/cli_test.go b/lifecycle/cli_test.go index a09ac6e91..8f5aefe8b 100644 --- a/lifecycle/cli_test.go +++ b/lifecycle/cli_test.go @@ -24,7 +24,7 @@ func TestValidateCreateReleaseBundleContext(t *testing.T) { {"builds without signing key", []string{"name", "version"}, []string{cliutils.Builds + "=/path/to/file"}, false}, {"builds correct", []string{"name", "version"}, []string{ cliutils.Builds + "=/path/to/file", cliutils.SigningKey + "=key"}, false}, - {"releaseBundles without signing key", []string{"name", "version", "env"}, []string{cliutils.ReleaseBundles + "=/path/to/file"}, true}, + {"releaseBundles without signing key", []string{"name", "version"}, []string{cliutils.ReleaseBundles + "=/path/to/file"}, false}, {"releaseBundles correct", []string{"name", "version"}, []string{ cliutils.ReleaseBundles + "=/path/to/file", cliutils.SigningKey + "=key"}, false}, {"spec without signing key", []string{"name", "version", "env"}, []string{"spec=/path/to/file"}, true}, From f5041031ba8d454529f1ed18b915d192711fbb2a Mon Sep 17 00:00:00 2001 From: oshratz Date: Sun, 17 Nov 2024 13:57:54 +0200 Subject: [PATCH 4/9] Turn the signing key to be optional in RBP --- lifecycle/cli.go | 4 ---- 1 file changed, 4 deletions(-) diff --git a/lifecycle/cli.go b/lifecycle/cli.go index 366ba25cf..ce0e32bbb 100644 --- a/lifecycle/cli.go +++ b/lifecycle/cli.go @@ -184,10 +184,6 @@ func promote(c *cli.Context) error { return cliutils.WrongNumberOfArgumentsHandler(c) } - if err := assertSigningKeyProvided(c); err != nil { - return err - } - lcDetails, err := createLifecycleDetailsByFlags(c) if err != nil { return err From 5c10b966da968d29ad8c20b31790fc1d4c095464 Mon Sep 17 00:00:00 2001 From: oshratz Date: Sun, 17 Nov 2024 13:57:54 +0200 Subject: [PATCH 5/9] Turn the signing key to be optional in RBP --- lifecycle/cli.go | 7 ------- 1 file changed, 7 deletions(-) diff --git a/lifecycle/cli.go b/lifecycle/cli.go index ce0e32bbb..da6c3d7d7 100644 --- a/lifecycle/cli.go +++ b/lifecycle/cli.go @@ -350,13 +350,6 @@ func validateDistributeCommand(c *cli.Context) error { return nil } -func assertSigningKeyProvided(c *cli.Context) error { - if c.String(cliutils.SigningKey) == "" { - return errorutils.CheckErrorf("the --%s option is mandatory", cliutils.SigningKey) - } - return nil -} - func createLifecycleDetailsByFlags(c *cli.Context) (*coreConfig.ServerDetails, error) { lcDetails, err := cliutils.CreateServerDetailsWithConfigOffer(c, true, commonCliUtils.Platform) if err != nil { From cbf2b008f64cc4e55e16661c50f62f657eb51b08 Mon Sep 17 00:00:00 2001 From: Eyal Ben Moshe Date: Tue, 19 Nov 2024 11:27:06 +0200 Subject: [PATCH 6/9] Bump ver from 2.71.4 to 2.71.5 (#2764) --- build/npm/v2-jf/package-lock.json | 2 +- build/npm/v2-jf/package.json | 2 +- build/npm/v2/package-lock.json | 2 +- build/npm/v2/package.json | 2 +- go.mod | 2 +- go.sum | 4 ++-- utils/cliutils/cli_consts.go | 2 +- 7 files changed, 8 insertions(+), 8 deletions(-) diff --git a/build/npm/v2-jf/package-lock.json b/build/npm/v2-jf/package-lock.json index 24ded68fe..8cb87ed8b 100644 --- a/build/npm/v2-jf/package-lock.json +++ b/build/npm/v2-jf/package-lock.json @@ -1,5 +1,5 @@ { "name": "jfrog-cli-v2-jf", - "version": "2.71.4", + "version": "2.71.5", "lockfileVersion": 1 } diff --git a/build/npm/v2-jf/package.json b/build/npm/v2-jf/package.json index a0087a689..8e6ef7991 100644 --- a/build/npm/v2-jf/package.json +++ b/build/npm/v2-jf/package.json @@ -1,6 +1,6 @@ { "name": "jfrog-cli-v2-jf", - "version": "2.71.4", + "version": "2.71.5", "description": "🐸 Command-line interface for JFrog Artifactory, Xray, Distribution, Pipelines and Mission Control 🐸", "homepage": "https://github.com/jfrog/jfrog-cli", "preferGlobal": true, diff --git a/build/npm/v2/package-lock.json b/build/npm/v2/package-lock.json index 146af32a6..1728225c8 100644 --- a/build/npm/v2/package-lock.json +++ b/build/npm/v2/package-lock.json @@ -1,5 +1,5 @@ { "name": "jfrog-cli-v2", - "version": "2.71.4", + "version": "2.71.5", "lockfileVersion": 2 } diff --git a/build/npm/v2/package.json b/build/npm/v2/package.json index c7242fab1..c1e06522e 100644 --- a/build/npm/v2/package.json +++ b/build/npm/v2/package.json @@ -1,6 +1,6 @@ { "name": "jfrog-cli-v2", - "version": "2.71.4", + "version": "2.71.5", "description": "🐸 Command-line interface for JFrog Artifactory, Xray, Distribution, Pipelines and Mission Control 🐸", "homepage": "https://github.com/jfrog/jfrog-cli", "preferGlobal": true, diff --git a/go.mod b/go.mod index ed6801ee3..5791e80aa 100644 --- a/go.mod +++ b/go.mod @@ -18,7 +18,7 @@ require ( github.com/jfrog/archiver/v3 v3.6.1 github.com/jfrog/build-info-go v1.10.5 github.com/jfrog/gofrog v1.7.6 - github.com/jfrog/jfrog-cli-artifactory v0.1.6 + github.com/jfrog/jfrog-cli-artifactory v0.1.7 github.com/jfrog/jfrog-cli-core/v2 v2.56.8 github.com/jfrog/jfrog-cli-platform-services v1.4.0 github.com/jfrog/jfrog-cli-security v1.12.5 diff --git a/go.sum b/go.sum index 1d9edb8f8..f3263fde9 100644 --- a/go.sum +++ b/go.sum @@ -169,8 +169,8 @@ github.com/jfrog/gofrog v1.7.6 h1:QmfAiRzVyaI7JYGsB7cxfAJePAZTzFz0gRWZSE27c6s= github.com/jfrog/gofrog v1.7.6/go.mod h1:ntr1txqNOZtHplmaNd7rS4f8jpA5Apx8em70oYEe7+4= github.com/jfrog/jfrog-apps-config v1.0.1 h1:mtv6k7g8A8BVhlHGlSveapqf4mJfonwvXYLipdsOFMY= github.com/jfrog/jfrog-apps-config v1.0.1/go.mod h1:8AIIr1oY9JuH5dylz2S6f8Ym2MaadPLR6noCBO4C22w= -github.com/jfrog/jfrog-cli-artifactory v0.1.6 h1:bMfJsrLQJw0dZp4nqUf1xOmtY0rpCatW/I5q88x+fhQ= -github.com/jfrog/jfrog-cli-artifactory v0.1.6/go.mod h1:jbNb22ebtupcjdhrdGq0VBew2vWG6VUK04xxGNDfynE= +github.com/jfrog/jfrog-cli-artifactory v0.1.7 h1:/PBDO6nS6cf3PK+GRkd6BJtZnvYasi1PrQhRiayirso= +github.com/jfrog/jfrog-cli-artifactory v0.1.7/go.mod h1:M5pZTHnsYNDmml/FAnoxxt4QiHOIUHPx91th30AtwfM= github.com/jfrog/jfrog-cli-core/v2 v2.56.8 h1:UexulAwRVN20VmYACijkTFYKqtUq5myE4okEgmUrorw= github.com/jfrog/jfrog-cli-core/v2 v2.56.8/go.mod h1:RY74eDpw1WBxruSfZ0HO1ax7c1NAj+rbBgA/hVOJNME= github.com/jfrog/jfrog-cli-platform-services v1.4.0 h1:g6A30+tOfXd1h6VASeNwH+5mhs5bPQJ0MFzZs/4nlvs= diff --git a/utils/cliutils/cli_consts.go b/utils/cliutils/cli_consts.go index a9ed95e61..325ead011 100644 --- a/utils/cliutils/cli_consts.go +++ b/utils/cliutils/cli_consts.go @@ -4,7 +4,7 @@ import "time" const ( // General CLI constants - CliVersion = "2.71.4" + CliVersion = "2.71.5" ClientAgent = "jfrog-cli-go" // CLI base commands constants: From bb3329f5777a9e39d92682415fffaceef0246c6d Mon Sep 17 00:00:00 2001 From: Oshrat Zairi <159787052+oshratZairi@users.noreply.github.com> Date: Thu, 21 Nov 2024 06:41:12 +0200 Subject: [PATCH 7/9] Make the signing key optinal `jf release-bundle-create` (#2762) --- lifecycle_test.go | 55 +++++++++++++++++++-------------- utils/cliutils/commandsflags.go | 2 +- 2 files changed, 32 insertions(+), 25 deletions(-) diff --git a/lifecycle_test.go b/lifecycle_test.go index c566793e3..ac66bcec5 100644 --- a/lifecycle_test.go +++ b/lifecycle_test.go @@ -29,14 +29,16 @@ import ( ) const ( - artifactoryLifecycleMinVersion = "7.68.3" - gpgKeyPairName = "lc-tests-key-pair" - lcTestdataPath = "lifecycle" - releaseBundlesSpec = "release-bundles-spec.json" - buildsSpec12 = "builds-spec-1-2.json" - buildsSpec3 = "builds-spec-3.json" - prodEnvironment = "PROD" - number1, number2, number3 = "111", "222", "333" + artifactoryLifecycleMinVersion = "7.68.3" + signingKeyOptionalArtifactoryMinVersion = "7.101.1" + gpgKeyPairName = "lc-tests-key-pair" + lcTestdataPath = "lifecycle" + releaseBundlesSpec = "release-bundles-spec.json" + buildsSpec12 = "builds-spec-1-2.json" + buildsSpec3 = "builds-spec-3.json" + prodEnvironment = "PROD" + number1, number2, number3 = "111", "222", "333" + withoutSigningKey = true ) var ( @@ -45,7 +47,7 @@ var ( ) func TestBackwardCompatibleReleaseBundleCreation(t *testing.T) { - cleanCallback := initLifecycleTest(t) + cleanCallback := initLifecycleTest(t, artifactoryLifecycleMinVersion) defer cleanCallback() lcManager := getLcServiceManager(t) @@ -95,26 +97,31 @@ func TestReleaseBundleCreationFromArtifacts(t *testing.T) { } func TestReleaseBundleCreationFromArtifactsWithoutSigningKey(t *testing.T) { - testReleaseBundleCreation(t, tests.UploadDevSpec, tests.LifecycleArtifacts, tests.GetExpectedLifecycleCreationByArtifacts(), true) + testReleaseBundleCreation(t, tests.UploadDevSpec, tests.LifecycleArtifacts, tests.GetExpectedLifecycleCreationByArtifacts(), withoutSigningKey) } -func testReleaseBundleCreation(t *testing.T, uploadSpec, creationSpec string, expected []string, withoutKey bool) { - cleanCallback := initLifecycleTest(t) - defer cleanCallback() - lcManager := getLcServiceManager(t) +func testReleaseBundleCreation(t *testing.T, uploadSpec, creationSpec string, expected []string, withoutSigningKey bool) { + if withoutSigningKey { + cleanCallback := initLifecycleTest(t, signingKeyOptionalArtifactoryMinVersion) + defer cleanCallback() + } else { + cleanCallback := initLifecycleTest(t, artifactoryLifecycleMinVersion) + defer cleanCallback() + } + lcManager := getLcServiceManager(t) specFile, err := tests.CreateSpec(uploadSpec) assert.NoError(t, err) runRt(t, "upload", "--spec="+specFile) - createRbFromSpec(t, creationSpec, tests.LcRbName1, number1, true, withoutKey) + createRbFromSpec(t, creationSpec, tests.LcRbName1, number1, true, withoutSigningKey) defer deleteReleaseBundle(t, lcManager, tests.LcRbName1, number1) assertRbArtifacts(t, lcManager, tests.LcRbName1, number1, expected) } func TestLifecycleFullFlow(t *testing.T) { - cleanCallback := initLifecycleTest(t) + cleanCallback := initLifecycleTest(t, signingKeyOptionalArtifactoryMinVersion) defer cleanCallback() lcManager := getLcServiceManager(t) @@ -165,7 +172,7 @@ func TestLifecycleFullFlow(t *testing.T) { // Import bundles only work on onPerm platforms func TestImportReleaseBundle(t *testing.T) { - cleanCallback := initLifecycleTest(t) + cleanCallback := initLifecycleTest(t, artifactoryLifecycleMinVersion) defer cleanCallback() wd, err := os.Getwd() assert.NoError(t, err) @@ -202,13 +209,13 @@ func createRbBackwardCompatible(t *testing.T, specName, sourceOption, rbName, rb createRb(t, specFile, sourceOption, rbName, rbVersion, sync, false) } -func createRbFromSpec(t *testing.T, specName, rbName, rbVersion string, sync bool, withoutKey bool) { +func createRbFromSpec(t *testing.T, specName, rbName, rbVersion string, sync bool, withoutSigningKey bool) { specFile, err := tests.CreateSpec(specName) assert.NoError(t, err) - createRb(t, specFile, "spec", rbName, rbVersion, sync, withoutKey) + createRb(t, specFile, "spec", rbName, rbVersion, sync, withoutSigningKey) } -func createRb(t *testing.T, specFilePath, sourceOption, rbName, rbVersion string, sync bool, withoutKey bool) { +func createRb(t *testing.T, specFilePath, sourceOption, rbName, rbVersion string, sync bool, withoutSigningKey bool) { argsAndOptions := []string{ "rbc", rbName, @@ -216,10 +223,9 @@ func createRb(t *testing.T, specFilePath, sourceOption, rbName, rbVersion string getOption(sourceOption, specFilePath), } - if !withoutKey { + if !withoutSigningKey { argsAndOptions = append(argsAndOptions, getOption(cliutils.SigningKey, gpgKeyPairName)) } - // Add the --sync option only if requested, to test the default value. if sync { argsAndOptions = append(argsAndOptions, getOption(cliutils.Sync, "true")) @@ -371,11 +377,12 @@ func uploadBuildWithDeps(t *testing.T, buildName, buildNumber string) { runRt(t, "build-publish", buildName, buildNumber) } -func initLifecycleTest(t *testing.T) (cleanCallback func()) { +func initLifecycleTest(t *testing.T, minVersion string) (cleanCallback func()) { if !*tests.TestLifecycle { t.Skip("Skipping lifecycle test. To run release bundle test add the '-test.lc=true' option.") } - validateArtifactoryVersion(t, artifactoryLifecycleMinVersion) + + validateArtifactoryVersion(t, minVersion) if !isLifecycleSupported(t) { t.Skip("Skipping lifecycle test because the functionality is not enabled on the provided JPD.") diff --git a/utils/cliutils/commandsflags.go b/utils/cliutils/commandsflags.go index 446f84eff..0157f6c13 100644 --- a/utils/cliutils/commandsflags.go +++ b/utils/cliutils/commandsflags.go @@ -1650,7 +1650,7 @@ var flagsMap = map[string]cli.Flag{ }, lcSigningKey: cli.StringFlag{ Name: SigningKey, - Usage: "[Mandatory] The GPG/RSA key-pair name given in Artifactory.` `", + Usage: "[Optional] The GPG/RSA key-pair name given in Artifactory. If the key isn't provided, the command creates or uses the default key.` `", }, lcPathMappingPattern: cli.StringFlag{ Name: PathMappingPattern, From 7c23a97f11594bc1a2a9630009cf556ce4dd43d7 Mon Sep 17 00:00:00 2001 From: Eyal Delarea Date: Thu, 21 Nov 2024 20:24:29 +0200 Subject: [PATCH 8/9] `NuGet` - Allow to set `allowInsecureConnections` package source attribute (#2758) --- buildtools/cli.go | 20 ++++++-- go.mod | 6 +-- go.sum | 12 ++--- nuget_test.go | 17 +++++-- utils/cliutils/commandsflags.go | 9 +++- utils/cliutils/utils.go | 12 +++++ utils/cliutils/utils_test.go | 85 +++++++++++++++++++++++++++++++++ 7 files changed, 144 insertions(+), 17 deletions(-) diff --git a/buildtools/cli.go b/buildtools/cli.go index fa7d87993..02eee938a 100644 --- a/buildtools/cli.go +++ b/buildtools/cli.go @@ -566,9 +566,18 @@ func NugetCmd(c *cli.Context) error { return err } + allowInsecureConnection, err := cliutils.ExtractBoolFlagFromArgs(&filteredNugetArgs, "allow-insecure-connections") + if err != nil { + return err + } + nugetCmd := dotnet.NewNugetCommand() - nugetCmd.SetServerDetails(rtDetails).SetRepoName(targetRepo).SetBuildConfiguration(buildConfiguration). - SetBasicCommand(filteredNugetArgs[0]).SetUseNugetV2(useNugetV2) + nugetCmd.SetServerDetails(rtDetails). + SetRepoName(targetRepo). + SetBuildConfiguration(buildConfiguration). + SetBasicCommand(filteredNugetArgs[0]). + SetUseNugetV2(useNugetV2). + SetAllowInsecureConnections(allowInsecureConnection) // Since we are using the values of the command's arguments and flags along the buildInfo collection process, // we want to separate the actual NuGet basic command (restore/build...) from the arguments and flags if len(filteredNugetArgs) > 1 { @@ -604,10 +613,15 @@ func DotnetCmd(c *cli.Context) error { return err } + allowInsecureConnection, err := cliutils.ExtractBoolFlagFromArgs(&filteredDotnetArgs, "allow-insecure-connections") + if err != nil { + return err + } + // Run command. dotnetCmd := dotnet.NewDotnetCoreCliCommand() dotnetCmd.SetServerDetails(rtDetails).SetRepoName(targetRepo).SetBuildConfiguration(buildConfiguration). - SetBasicCommand(filteredDotnetArgs[0]).SetUseNugetV2(useNugetV2) + SetBasicCommand(filteredDotnetArgs[0]).SetUseNugetV2(useNugetV2).SetAllowInsecureConnections(allowInsecureConnection) // Since we are using the values of the command's arguments and flags along the buildInfo collection process, // we want to separate the actual .NET basic command (restore/build...) from the arguments and flags if len(filteredDotnetArgs) > 1 { diff --git a/go.mod b/go.mod index 5791e80aa..cfab56ecb 100644 --- a/go.mod +++ b/go.mod @@ -167,12 +167,12 @@ require ( gopkg.in/yaml.v3 v3.0.1 // indirect ) -// replace github.com/jfrog/jfrog-cli-core/v2 => github.com/jfrog/jfrog-cli-core/v2 v2.31.1-0.20241113152357-24197a744331 +replace github.com/jfrog/jfrog-cli-core/v2 => github.com/jfrog/jfrog-cli-core/v2 v2.31.1-0.20241121163158-04daeb8132c3 -// replace github.com/jfrog/jfrog-cli-security => github.com/jfrog/jfrog-cli-security v1.12.5-0.20241107141149-42cf964808a1 +replace github.com/jfrog/jfrog-cli-security => github.com/EyalDelarea/jfrog-cli-security v0.0.0-20241121103043-02719f295f02 // replace github.com/jfrog/jfrog-client-go => github.com/jfrog/jfrog-client-go v1.28.1-0.20240918081224-1c584cc334c7 -// replace github.com/jfrog/build-info-go => github.com/jfrog/build-info-go v1.8.9-0.20240918150101-ad5b10435a12 +replace github.com/jfrog/build-info-go => github.com/jfrog/build-info-go v1.8.9-0.20241121100855-e7a75ceee2bd // replace github.com/jfrog/gofrog => github.com/jfrog/gofrog dev diff --git a/go.sum b/go.sum index f3263fde9..9692db858 100644 --- a/go.sum +++ b/go.sum @@ -10,6 +10,8 @@ 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= github.com/CycloneDX/cyclonedx-go v0.9.0/go.mod h1:NE/EWvzELOFlG6+ljX/QeMlVt9VKcTwu8u0ccsACEsw= +github.com/EyalDelarea/jfrog-cli-security v0.0.0-20241121103043-02719f295f02 h1:oyTvu0FWw+qlEcinSd/8/U+JWR00uQSSa9y0fO+ZVAo= +github.com/EyalDelarea/jfrog-cli-security v0.0.0-20241121103043-02719f295f02/go.mod h1:5LBGwth7TXkEH8MO0JJXvpoRktMAV2BK7Q5nQePNrv4= github.com/Microsoft/go-winio v0.5.2/go.mod h1:WpS1mjBmmwHBEWmogvA2mj8546UReBk4v8QkMxJ6pZY= github.com/Microsoft/go-winio v0.6.2 h1:F2VQgta7ecxGYO8k3ZZz3RS8fVIXVxONVUPlNERoyfY= github.com/Microsoft/go-winio v0.6.2/go.mod h1:yd8OoFMLzJbo9gZq8j5qaps8bJ9aShtEA8Ipt1oGCvU= @@ -161,8 +163,8 @@ github.com/jedib0t/go-pretty/v6 v6.6.1 h1:iJ65Xjb680rHcikRj6DSIbzCex2huitmc7bDtx 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.5 h1:cW03JlPlKv7RMUU896uLUxyLWXAmCgR5Y5QX0fwgz0Q= -github.com/jfrog/build-info-go v1.10.5/go.mod h1:JcISnovFXKx3wWf3p1fcMmlPdt6adxScXvoJN4WXqIE= +github.com/jfrog/build-info-go v1.8.9-0.20241121100855-e7a75ceee2bd h1:PzxnJ1mjHIL4bAC4RPm87WnJ1TZXFBicyOhtIHRQH6g= +github.com/jfrog/build-info-go v1.8.9-0.20241121100855-e7a75ceee2bd/go.mod h1:JcISnovFXKx3wWf3p1fcMmlPdt6adxScXvoJN4WXqIE= github.com/jfrog/froggit-go v1.16.2 h1:F//S83iXH14qsCwYzv0zB2JtjS2pJVEsUoEmYA+37dQ= github.com/jfrog/froggit-go v1.16.2/go.mod h1:5VpdQfAcbuyFl9x/x8HGm7kVk719kEtW/8YJFvKcHPA= github.com/jfrog/gofrog v1.7.6 h1:QmfAiRzVyaI7JYGsB7cxfAJePAZTzFz0gRWZSE27c6s= @@ -171,12 +173,10 @@ github.com/jfrog/jfrog-apps-config v1.0.1 h1:mtv6k7g8A8BVhlHGlSveapqf4mJfonwvXYL github.com/jfrog/jfrog-apps-config v1.0.1/go.mod h1:8AIIr1oY9JuH5dylz2S6f8Ym2MaadPLR6noCBO4C22w= github.com/jfrog/jfrog-cli-artifactory v0.1.7 h1:/PBDO6nS6cf3PK+GRkd6BJtZnvYasi1PrQhRiayirso= github.com/jfrog/jfrog-cli-artifactory v0.1.7/go.mod h1:M5pZTHnsYNDmml/FAnoxxt4QiHOIUHPx91th30AtwfM= -github.com/jfrog/jfrog-cli-core/v2 v2.56.8 h1:UexulAwRVN20VmYACijkTFYKqtUq5myE4okEgmUrorw= -github.com/jfrog/jfrog-cli-core/v2 v2.56.8/go.mod h1:RY74eDpw1WBxruSfZ0HO1ax7c1NAj+rbBgA/hVOJNME= +github.com/jfrog/jfrog-cli-core/v2 v2.31.1-0.20241121163158-04daeb8132c3 h1:cJSPTMflqE+ucC/h2/BB6BkVxz3BG8PnivCb00Dxt/Y= +github.com/jfrog/jfrog-cli-core/v2 v2.31.1-0.20241121163158-04daeb8132c3/go.mod h1:zVyWxMkBpZwy/AvTohefIlaZzYKBMFje+gKKKlkunNo= github.com/jfrog/jfrog-cli-platform-services v1.4.0 h1:g6A30+tOfXd1h6VASeNwH+5mhs5bPQJ0MFzZs/4nlvs= github.com/jfrog/jfrog-cli-platform-services v1.4.0/go.mod h1:Ky4SDXuMeaiNP/5zMT1YSzIuXG+cNYYOl8BaEA7Awbc= -github.com/jfrog/jfrog-cli-security v1.12.5 h1:2JHPyapXuHQw/qEaElGxBUGrJCZlVFLXDdxkqhf10vE= -github.com/jfrog/jfrog-cli-security v1.12.5/go.mod h1:5LBGwth7TXkEH8MO0JJXvpoRktMAV2BK7Q5nQePNrv4= github.com/jfrog/jfrog-client-go v1.48.0 h1:hx5B7+Wnobmzq4aFVZtALtbEVDFcjpn0Wb4q2m6H4KU= github.com/jfrog/jfrog-client-go v1.48.0/go.mod h1:1a7bmQHkRmPEza9wva2+WVrYzrGbosrMymq57kyG5gU= github.com/jszwec/csvutil v1.10.0 h1:upMDUxhQKqZ5ZDCs/wy+8Kib8rZR8I8lOR34yJkdqhI= diff --git a/nuget_test.go b/nuget_test.go index e8b42d2bb..bf1235a37 100644 --- a/nuget_test.go +++ b/nuget_test.go @@ -107,6 +107,7 @@ func TestNuGetWithGlobalConfig(t *testing.T) { assert.NoError(t, err) err = createConfigFileForTest([]string{jfrogHomeDir}, tests.NugetRemoteRepo, "", t, project.Nuget, true) assert.NoError(t, err) + // allow insecure connection for testings to work with localhost server testNugetCmd(t, projectPath, tests.NuGetBuildName, "1", []string{"packagesconfig"}, []string{"nuget", "restore"}, []int{6}) cleanTestsHomeEnv() @@ -117,7 +118,10 @@ func testNugetCmd(t *testing.T, projectPath, buildName, buildNumber string, expe assert.NoError(t, err, "Failed to get current dir") chdirCallback := clientTestUtils.ChangeDirWithCallback(t, wd, projectPath) defer chdirCallback() + + allowInsecureConnectionForTests(&args) args = append(args, "--build-name="+buildName, "--build-number="+buildNumber) + err = runNuGet(t, args...) if err != nil { return @@ -152,6 +156,12 @@ func testNugetCmd(t *testing.T, projectPath, buildName, buildNumber string, expe inttestutils.DeleteBuild(serverDetails.ArtifactoryUrl, buildName, artHttpDetails) } +// Add allow insecure connection for testings to work with localhost server +func allowInsecureConnectionForTests(args *[]string) *[]string { + *args = append(*args, "--allow-insecure-connections") + return args +} + func assertNugetDependencies(t *testing.T, module buildInfo.Module, moduleName string) { for _, dependency := range module.Dependencies { switch dependency.Id { @@ -224,10 +234,11 @@ func runInitNewConfig(t *testing.T, testSuite testInitNewConfigDescriptor, baseR params := &dotnet.DotnetCommand{} server := &config.ServerDetails{ArtifactoryUrl: baseRtUrl, User: "user", Password: "password"} params.SetServerDetails(server). - SetUseNugetV2(testSuite.useNugetV2) - // Prepare the config file with NuGet authentication + SetUseNugetV2(testSuite.useNugetV2). + SetAllowInsecureConnections(true) - configFile, err := dotnet.InitNewConfig(tempDirPath, "", server, testSuite.useNugetV2) + // Prepare the config file with NuGet authentication + configFile, err := dotnet.InitNewConfig(tempDirPath, "", server, testSuite.useNugetV2, true) if err != nil { assert.NoError(t, err) return diff --git a/utils/cliutils/commandsflags.go b/utils/cliutils/commandsflags.go index 0157f6c13..1ad558d3c 100644 --- a/utils/cliutils/commandsflags.go +++ b/utils/cliutils/commandsflags.go @@ -376,7 +376,8 @@ const ( npmDetailedSummary = npmPrefix + detailedSummary // Unique nuget/dotnet config flags - nugetV2 = "nuget-v2" + nugetV2 = "nuget-v2" + allowInsecureConnections = "allow-insecure-connections" // Unique go flags noFallback = "no-fallback" @@ -1161,6 +1162,10 @@ var flagsMap = map[string]cli.Flag{ Name: nugetV2, Usage: "[Default: false] Set to true if you'd like to use the NuGet V2 protocol when restoring packages from Artifactory.` `", }, + allowInsecureConnections: cli.BoolFlag{ + Name: allowInsecureConnections, + Usage: "[Default: false] Set to true if you wish to configure NuGet sources with unsecured connections. This is recommended for testing purposes only. ` `", + }, noFallback: cli.BoolTFlag{ Name: noFallback, Usage: "[Default: false] Set to true to avoid downloading packages from the VCS, if they are missing in Artifactory.` `", @@ -1882,7 +1887,7 @@ var commandFlags = map[string][]string{ global, serverIdResolve, repoResolve, nugetV2, }, Nuget: { - buildName, buildNumber, module, Project, + buildName, buildNumber, module, Project, allowInsecureConnections, }, DotnetConfig: { global, serverIdResolve, repoResolve, nugetV2, diff --git a/utils/cliutils/utils.go b/utils/cliutils/utils.go index 17781fe50..ac43b25a8 100644 --- a/utils/cliutils/utils.go +++ b/utils/cliutils/utils.go @@ -809,3 +809,15 @@ func getDebFlag(c *cli.Context) (deb string, err error) { } return deb, nil } + +// ExtractBoolFlagFromArgs Extracts a boolean flag from the args and removes it from the slice. +func ExtractBoolFlagFromArgs(filteredArgs *[]string, flagName string) (value bool, err error) { + var flagIndex int + var boolFlag bool + flagIndex, boolFlag, err = coreutils.FindBooleanFlag("--"+flagName, *filteredArgs) + if err != nil { + return false, err + } + coreutils.RemoveFlagFromCommand(filteredArgs, flagIndex, flagIndex) + return boolFlag, nil +} diff --git a/utils/cliutils/utils_test.go b/utils/cliutils/utils_test.go index f9bf32b2e..e67ec46c7 100644 --- a/utils/cliutils/utils_test.go +++ b/utils/cliutils/utils_test.go @@ -140,3 +140,88 @@ func TestShouldCheckLatestCliVersion(t *testing.T) { assert.NoError(t, err) assert.True(t, shouldCheck) } + +func TestExtractBoolFlagFromArgs(t *testing.T) { + testCases := []struct { + name string + args []string + flagName string + expectedValue bool + expectedErr bool + expectedArgs []string + }{ + { + name: "Flag present as --flagName (implied true)", + args: []string{"somecmd", "--flagName", "otherarg"}, + flagName: "flagName", + expectedValue: true, + expectedErr: false, + expectedArgs: []string{"somecmd", "otherarg"}, + }, + { + name: "Flag present as --flagName=true", + args: []string{"somecmd", "--flagName=true", "otherarg"}, + flagName: "flagName", + expectedValue: true, + expectedErr: false, + expectedArgs: []string{"somecmd", "otherarg"}, + }, + { + name: "Flag present as --flagName=false", + args: []string{"somecmd", "--flagName=false", "otherarg"}, + flagName: "flagName", + expectedValue: false, + expectedErr: false, + expectedArgs: []string{"somecmd", "otherarg"}, + }, + { + name: "Flag not present", + args: []string{"somecmd", "otherarg"}, + flagName: "flagName", + expectedValue: false, + expectedErr: false, + expectedArgs: []string{"somecmd", "otherarg"}, + }, + { + name: "Flag present with invalid value", + args: []string{"somecmd", "--flagName=invalid", "otherarg"}, + flagName: "flagName", + expectedValue: false, + expectedErr: true, + expectedArgs: []string{"somecmd", "--flagName=invalid", "otherarg"}, + }, + { + name: "Flag present as -flagName (should not be found)", + args: []string{"somecmd", "-flagName", "otherarg"}, + flagName: "flagName", + expectedValue: false, + expectedErr: false, + expectedArgs: []string{"somecmd", "-flagName", "otherarg"}, + }, + { + name: "Flag present multiple times", + args: []string{"somecmd", "--flagName", "--flagName=false", "otherarg"}, + flagName: "flagName", + expectedValue: true, + expectedErr: false, + expectedArgs: []string{"somecmd", "--flagName=false", "otherarg"}, + }, + } + + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + // Make a copy to avoid modifying the original + argsCopy := append([]string(nil), tc.args...) + value, err := ExtractBoolFlagFromArgs(&argsCopy, tc.flagName) + + if tc.expectedErr { + assert.Error(t, err) + } else { + assert.NoError(t, err) + } + + assert.Equal(t, tc.expectedValue, value) + assert.Equal(t, tc.expectedArgs, argsCopy) + }) + } +} From fd666deee5e4b5c2bc757c2d62bf60b69b068799 Mon Sep 17 00:00:00 2001 From: oshratz Date: Wed, 20 Nov 2024 10:02:51 +0200 Subject: [PATCH 9/9] RBC command - Turn spec flag optional, adding support in buildName and buildNumber --- go.mod | 14 +++--- go.sum | 16 +++---- lifecycle/cli.go | 80 +++++++++++++++++++++++++++++---- lifecycle/cli_test.go | 71 +++++++++++++++++++++++++++++ lifecycle_test.go | 39 +++++++++++++--- utils/cliutils/commandsflags.go | 60 ++++++++++++------------- 6 files changed, 220 insertions(+), 60 deletions(-) diff --git a/go.mod b/go.mod index cfab56ecb..763e8ef87 100644 --- a/go.mod +++ b/go.mod @@ -16,13 +16,13 @@ require ( github.com/docker/docker v27.3.1+incompatible github.com/gocarina/gocsv v0.0.0-20240520201108-78e41c74b4b1 github.com/jfrog/archiver/v3 v3.6.1 - github.com/jfrog/build-info-go v1.10.5 + github.com/jfrog/build-info-go v1.10.6 github.com/jfrog/gofrog v1.7.6 github.com/jfrog/jfrog-cli-artifactory v0.1.7 - github.com/jfrog/jfrog-cli-core/v2 v2.56.8 + github.com/jfrog/jfrog-cli-core/v2 v2.57.1 github.com/jfrog/jfrog-cli-platform-services v1.4.0 - github.com/jfrog/jfrog-cli-security v1.12.5 - github.com/jfrog/jfrog-client-go v1.48.0 + github.com/jfrog/jfrog-cli-security v1.13.4 + github.com/jfrog/jfrog-client-go v1.48.3 github.com/jszwec/csvutil v1.10.0 github.com/manifoldco/promptui v0.9.0 github.com/stretchr/testify v1.9.0 @@ -167,12 +167,12 @@ require ( gopkg.in/yaml.v3 v3.0.1 // indirect ) -replace github.com/jfrog/jfrog-cli-core/v2 => github.com/jfrog/jfrog-cli-core/v2 v2.31.1-0.20241121163158-04daeb8132c3 +// replace github.com/jfrog/jfrog-cli-core/v2 => github.com/jfrog/jfrog-cli-core/v2 v2.31.1-0.20241121163158-04daeb8132c3 -replace github.com/jfrog/jfrog-cli-security => github.com/EyalDelarea/jfrog-cli-security v0.0.0-20241121103043-02719f295f02 +// replace github.com/jfrog/jfrog-cli-security => github.com/EyalDelarea/jfrog-cli-security v0.0.0-20241121103043-02719f295f02 // replace github.com/jfrog/jfrog-client-go => github.com/jfrog/jfrog-client-go v1.28.1-0.20240918081224-1c584cc334c7 -replace github.com/jfrog/build-info-go => github.com/jfrog/build-info-go v1.8.9-0.20241121100855-e7a75ceee2bd +// replace github.com/jfrog/build-info-go => github.com/jfrog/build-info-go v1.8.9-0.20241121100855-e7a75ceee2bd // replace github.com/jfrog/gofrog => github.com/jfrog/gofrog dev diff --git a/go.sum b/go.sum index 9692db858..704d43c11 100644 --- a/go.sum +++ b/go.sum @@ -10,8 +10,6 @@ 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= github.com/CycloneDX/cyclonedx-go v0.9.0/go.mod h1:NE/EWvzELOFlG6+ljX/QeMlVt9VKcTwu8u0ccsACEsw= -github.com/EyalDelarea/jfrog-cli-security v0.0.0-20241121103043-02719f295f02 h1:oyTvu0FWw+qlEcinSd/8/U+JWR00uQSSa9y0fO+ZVAo= -github.com/EyalDelarea/jfrog-cli-security v0.0.0-20241121103043-02719f295f02/go.mod h1:5LBGwth7TXkEH8MO0JJXvpoRktMAV2BK7Q5nQePNrv4= github.com/Microsoft/go-winio v0.5.2/go.mod h1:WpS1mjBmmwHBEWmogvA2mj8546UReBk4v8QkMxJ6pZY= github.com/Microsoft/go-winio v0.6.2 h1:F2VQgta7ecxGYO8k3ZZz3RS8fVIXVxONVUPlNERoyfY= github.com/Microsoft/go-winio v0.6.2/go.mod h1:yd8OoFMLzJbo9gZq8j5qaps8bJ9aShtEA8Ipt1oGCvU= @@ -163,8 +161,8 @@ github.com/jedib0t/go-pretty/v6 v6.6.1 h1:iJ65Xjb680rHcikRj6DSIbzCex2huitmc7bDtx 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.8.9-0.20241121100855-e7a75ceee2bd h1:PzxnJ1mjHIL4bAC4RPm87WnJ1TZXFBicyOhtIHRQH6g= -github.com/jfrog/build-info-go v1.8.9-0.20241121100855-e7a75ceee2bd/go.mod h1:JcISnovFXKx3wWf3p1fcMmlPdt6adxScXvoJN4WXqIE= +github.com/jfrog/build-info-go v1.10.6 h1:zH1ZhXlVfi5DlFyunygHjrdOcnv5qxfeLqmsfD4+lc4= +github.com/jfrog/build-info-go v1.10.6/go.mod h1:JcISnovFXKx3wWf3p1fcMmlPdt6adxScXvoJN4WXqIE= github.com/jfrog/froggit-go v1.16.2 h1:F//S83iXH14qsCwYzv0zB2JtjS2pJVEsUoEmYA+37dQ= github.com/jfrog/froggit-go v1.16.2/go.mod h1:5VpdQfAcbuyFl9x/x8HGm7kVk719kEtW/8YJFvKcHPA= github.com/jfrog/gofrog v1.7.6 h1:QmfAiRzVyaI7JYGsB7cxfAJePAZTzFz0gRWZSE27c6s= @@ -173,12 +171,14 @@ github.com/jfrog/jfrog-apps-config v1.0.1 h1:mtv6k7g8A8BVhlHGlSveapqf4mJfonwvXYL github.com/jfrog/jfrog-apps-config v1.0.1/go.mod h1:8AIIr1oY9JuH5dylz2S6f8Ym2MaadPLR6noCBO4C22w= github.com/jfrog/jfrog-cli-artifactory v0.1.7 h1:/PBDO6nS6cf3PK+GRkd6BJtZnvYasi1PrQhRiayirso= github.com/jfrog/jfrog-cli-artifactory v0.1.7/go.mod h1:M5pZTHnsYNDmml/FAnoxxt4QiHOIUHPx91th30AtwfM= -github.com/jfrog/jfrog-cli-core/v2 v2.31.1-0.20241121163158-04daeb8132c3 h1:cJSPTMflqE+ucC/h2/BB6BkVxz3BG8PnivCb00Dxt/Y= -github.com/jfrog/jfrog-cli-core/v2 v2.31.1-0.20241121163158-04daeb8132c3/go.mod h1:zVyWxMkBpZwy/AvTohefIlaZzYKBMFje+gKKKlkunNo= +github.com/jfrog/jfrog-cli-core/v2 v2.57.1 h1:YVuiSoavDisE8Dc9TOhYo5fE3d2C4/BrXuLDO/SZpJo= +github.com/jfrog/jfrog-cli-core/v2 v2.57.1/go.mod h1:e95/VWV6LL+UUxSNTJZ+sLmqJhCO5lDRhhLUQMV8WK4= github.com/jfrog/jfrog-cli-platform-services v1.4.0 h1:g6A30+tOfXd1h6VASeNwH+5mhs5bPQJ0MFzZs/4nlvs= github.com/jfrog/jfrog-cli-platform-services v1.4.0/go.mod h1:Ky4SDXuMeaiNP/5zMT1YSzIuXG+cNYYOl8BaEA7Awbc= -github.com/jfrog/jfrog-client-go v1.48.0 h1:hx5B7+Wnobmzq4aFVZtALtbEVDFcjpn0Wb4q2m6H4KU= -github.com/jfrog/jfrog-client-go v1.48.0/go.mod h1:1a7bmQHkRmPEza9wva2+WVrYzrGbosrMymq57kyG5gU= +github.com/jfrog/jfrog-cli-security v1.13.4 h1:GF6KfBZLi2ztwKJgOvHdXYVUFIvLjZRMWTy152cbJ7Y= +github.com/jfrog/jfrog-cli-security v1.13.4/go.mod h1:GNf/qXZuSsYXfGBH9qobE6Vz5glaGqNpRgU3LWnBrAQ= +github.com/jfrog/jfrog-client-go v1.48.3 h1:HJpKGul0f/S2i7Uf7K/GwS1EUGiirt1LWXL1lanKNhU= +github.com/jfrog/jfrog-client-go v1.48.3/go.mod h1:1a7bmQHkRmPEza9wva2+WVrYzrGbosrMymq57kyG5gU= github.com/jszwec/csvutil v1.10.0 h1:upMDUxhQKqZ5ZDCs/wy+8Kib8rZR8I8lOR34yJkdqhI= github.com/jszwec/csvutil v1.10.0/go.mod h1:/E4ONrmGkwmWsk9ae9jpXnv9QT8pLHEPcCirMFhxG9I= github.com/k0kubun/colorstring v0.0.0-20150214042306-9440f1994b88/go.mod h1:3w7q1U84EfirKl04SVQ/s7nPm1ZPhiXd34z40TNz36k= diff --git a/lifecycle/cli.go b/lifecycle/cli.go index da6c3d7d7..246c2e524 100644 --- a/lifecycle/cli.go +++ b/lifecycle/cli.go @@ -2,9 +2,11 @@ package lifecycle import ( "errors" + "fmt" commonCliUtils "github.com/jfrog/jfrog-cli-core/v2/common/cliutils" "github.com/jfrog/jfrog-cli-core/v2/common/commands" "github.com/jfrog/jfrog-cli-core/v2/common/spec" + speccore "github.com/jfrog/jfrog-cli-core/v2/common/spec" coreCommon "github.com/jfrog/jfrog-cli-core/v2/docs/common" "github.com/jfrog/jfrog-cli-core/v2/lifecycle" coreConfig "github.com/jfrog/jfrog-cli-core/v2/utils/config" @@ -24,6 +26,7 @@ import ( "github.com/jfrog/jfrog-client-go/utils" "github.com/jfrog/jfrog-client-go/utils/errorutils" "github.com/urfave/cli" + "os" "strings" ) @@ -131,21 +134,56 @@ func validateCreateReleaseBundleContext(c *cli.Context) error { } func assertValidCreationMethod(c *cli.Context) error { + // Determine the methods provided methods := []bool{ - c.IsSet("spec"), c.IsSet(cliutils.Builds), c.IsSet(cliutils.ReleaseBundles)} - if coreutils.SumTrueValues(methods) > 1 { - return errorutils.CheckErrorf("exactly one creation source must be supplied: --%s, --%s or --%s.\n"+ - "Opt to use the --%s option as the --%s and --%s are deprecated", + c.IsSet("spec"), + c.IsSet(cliutils.Builds), + c.IsSet(cliutils.ReleaseBundles), + } + methodCount := coreutils.SumTrueValues(methods) + + // Validate that only one creation method is provided + if err := validateSingleCreationMethod(methodCount); err != nil { + return err + } + + if err := validateCreationValuesPresence(c, methodCount); err != nil { + return err + } + return nil +} + +func validateSingleCreationMethod(methodCount int) error { + if methodCount > 1 { + return errorutils.CheckErrorf( + "exactly one creation source must be supplied: --%s, --%s, or --%s.\n"+ + "Opt to use the --%s option as the --%s and --%s are deprecated", + "spec", cliutils.Builds, cliutils.ReleaseBundles, "spec", cliutils.Builds, cliutils.ReleaseBundles, - "spec", cliutils.Builds, cliutils.ReleaseBundles) + ) } - // If the user did not provide a source, we suggest only the recommended spec approach. - if coreutils.SumTrueValues(methods) == 0 { - return errorutils.CheckErrorf("the --spec option is mandatory") + return nil +} + +func validateCreationValuesPresence(c *cli.Context, methodCount int) error { + if methodCount == 0 { + if !areBuildFlagsSet(c) && !areBuildEnvVarsSet() { + return errorutils.CheckErrorf("Either --build-name or JFROG_CLI_BUILD_NAME, and --build-number or JFROG_CLI_BUILD_NUMBER must be defined") + } } return nil } +// areBuildFlagsSet checks if build-name or build-number flags are set. +func areBuildFlagsSet(c *cli.Context) bool { + return c.IsSet(cliutils.BuildName) || c.IsSet(cliutils.BuildNumber) +} + +// areBuildEnvVarsSet checks if build environment variables are set. +func areBuildEnvVarsSet() bool { + return os.Getenv("JFROG_CLI_BUILD_NUMBER") != "" && os.Getenv("JFROG_CLI_BUILD_NAME") != "" +} + func create(c *cli.Context) (err error) { if err = validateCreateReleaseBundleContext(c); err != nil { return err @@ -169,10 +207,34 @@ func create(c *cli.Context) (err error) { } func getReleaseBundleCreationSpec(c *cli.Context) (*spec.SpecFiles, error) { + // לֹhecking if the "builds" or "release-bundles" flags are set - if so, the spec flag should be ignored + if c.IsSet(cliutils.Builds) || c.IsSet(cliutils.ReleaseBundles) { + return nil, nil + } + + // Check if the "spec" flag is set - if so, return the spec if c.IsSet("spec") { return cliutils.GetSpec(c, true, false) } - return nil, nil + + // Else - create a spec from the buildName and buildnumber flags or env vars + buildName := getStringFlagOrEnv(c, cliutils.BuildName, coreutils.BuildName) + buildNumber := getStringFlagOrEnv(c, cliutils.BuildNumber, coreutils.BuildNumber) + + if buildName != "" && buildNumber != "" { + return speccore.CreateSpecFromBuildNameAndNumber(buildName, buildNumber) + } + + return nil, fmt.Errorf("either the --spec flag must be provided, " + + "or both --build-name and --build-number flags (or their corresponding environment variables " + + "JFROG_CLI_BUILD_NAME and JFROG_CLI_BUILD_NUMBER) must be set") +} + +func getStringFlagOrEnv(c *cli.Context, flag string, envVar string) string { + if c.IsSet(flag) { + return c.String(flag) + } + return os.Getenv(envVar) } func promote(c *cli.Context) error { diff --git a/lifecycle/cli_test.go b/lifecycle/cli_test.go index 8f5aefe8b..55317a63a 100644 --- a/lifecycle/cli_test.go +++ b/lifecycle/cli_test.go @@ -4,6 +4,7 @@ import ( "github.com/jfrog/jfrog-cli/utils/cliutils" "github.com/jfrog/jfrog-cli/utils/tests" "github.com/stretchr/testify/assert" + "os" "path/filepath" "testing" ) @@ -56,3 +57,73 @@ func TestCreateReleaseBundleSpecWithProject(t *testing.T) { creationSpec.Get(0).Project = "" assert.Equal(t, projectKey, cliutils.GetProject(context)) } + +func TestGetReleaseBundleCreationSpec(t *testing.T) { + + t.Run("Spec Flag Set", func(t *testing.T) { + specFile := filepath.Join("testdata", "specfile.json") + ctx, _ := tests.CreateContext(t, []string{"spec=" + specFile}, []string{}) + + spec, err := getReleaseBundleCreationSpec(ctx) + + assert.NoError(t, err) + assert.NotNil(t, spec) + }) + + t.Run("Build Name and Number Set via Flags", func(t *testing.T) { + ctx, _ := tests.CreateContext(t, []string{"build-name=Common-builds", "build-number=1.0.0"}, []string{}) + + spec, err := getReleaseBundleCreationSpec(ctx) + + assert.NoError(t, err) + assert.NotNil(t, spec) + assert.Equal(t, "Common-builds/1.0.0", spec.Files[0].Build) + }) + + t.Run("Build Name and Number Set via Env Variables", func(t *testing.T) { + t.Setenv("JFROG_CLI_BUILD_NAME", "Common-builds") + t.Setenv("JFROG_CLI_BUILD_NUMBER", "2.0.0") + + ctx, _ := tests.CreateContext(t, []string{}, []string{}) + + spec, err := getReleaseBundleCreationSpec(ctx) + + assert.NoError(t, err) + assert.NotNil(t, spec) + assert.Equal(t, "Common-builds/2.0.0", spec.Files[0].Build) + os.Unsetenv("JFROG_CLI_BUILD_NAME") + os.Unsetenv("JFROG_CLI_BUILD_NUMBER") + }) + + t.Run("Missing Build Name and Number", func(t *testing.T) { + ctx, _ := tests.CreateContext(t, []string{}, []string{}) + + spec, err := getReleaseBundleCreationSpec(ctx) + + assert.Error(t, err) + assert.Nil(t, spec) + assert.EqualError(t, err, "either the --spec flag must be provided, or both --build-name and --build-number flags (or their corresponding environment variables JFROG_CLI_BUILD_NAME and JFROG_CLI_BUILD_NUMBER) must be set") + }) + + t.Run("Only One Build Variable Set", func(t *testing.T) { + ctx, _ := tests.CreateContext(t, []string{"build-name=Common-builds"}, []string{}) + + spec, err := getReleaseBundleCreationSpec(ctx) + + assert.Error(t, err) + assert.Nil(t, spec) + assert.EqualError(t, err, "either the --spec flag must be provided, or both --build-name and --build-number flags (or their corresponding environment variables JFROG_CLI_BUILD_NAME and JFROG_CLI_BUILD_NUMBER) must be set") + }) + + t.Run("One Env Variable One Flag", func(t *testing.T) { + ctx, _ := tests.CreateContext(t, []string{"build-name=Common-builds"}, []string{}) + t.Setenv("JFROG_CLI_BUILD_NUMBER", "2.0.0") + + spec, err := getReleaseBundleCreationSpec(ctx) + + assert.NoError(t, err) + assert.NotNil(t, spec) + assert.Equal(t, "Common-builds/2.0.0", spec.Files[0].Build) + os.Unsetenv("JFROG_CLI_BUILD_NUMBER") + }) +} diff --git a/lifecycle_test.go b/lifecycle_test.go index ac66bcec5..4913d5f91 100644 --- a/lifecycle_test.go +++ b/lifecycle_test.go @@ -167,7 +167,6 @@ func TestLifecycleFullFlow(t *testing.T) { // Verify the artifacts were distributed correctly by the provided path mappings. assertExpectedArtifacts(t, tests.SearchAllDevRepo, tests.GetExpectedLifecycleDistributedArtifacts()) */ - } // Import bundles only work on onPerm platforms @@ -206,30 +205,58 @@ func uploadBuilds(t *testing.T) func() { func createRbBackwardCompatible(t *testing.T, specName, sourceOption, rbName, rbVersion string, sync bool) { specFile, err := getSpecFile(specName) assert.NoError(t, err) - createRb(t, specFile, sourceOption, rbName, rbVersion, sync, false) + createRbWithFlags(t, specFile, sourceOption, "", "", rbName, rbVersion, sync, false) } func createRbFromSpec(t *testing.T, specName, rbName, rbVersion string, sync bool, withoutSigningKey bool) { specFile, err := tests.CreateSpec(specName) assert.NoError(t, err) - createRb(t, specFile, "spec", rbName, rbVersion, sync, withoutSigningKey) + createRbWithFlags(t, specFile, "spec", "", "", rbName, rbVersion, sync, withoutSigningKey) } -func createRb(t *testing.T, specFilePath, sourceOption, rbName, rbVersion string, sync bool, withoutSigningKey bool) { +func TestCreateBundleWithoutSpec(t *testing.T) { + cleanCallback := initLifecycleTest(t, signingKeyOptionalArtifactoryMinVersion) + defer cleanCallback() + + lcManager := getLcServiceManager(t) + + deleteBuilds := uploadBuilds(t) + defer deleteBuilds() + + createRbWithFlags(t, "", "", tests.LcBuildName1, number1, tests.LcRbName1, number1, false, false) + assertStatusCompleted(t, lcManager, tests.LcRbName1, number1, "") + defer deleteReleaseBundle(t, lcManager, tests.LcRbName1, number1) + + createRbWithFlags(t, "", "", tests.LcBuildName2, number2, tests.LcRbName2, number2, false, true) + assertStatusCompleted(t, lcManager, tests.LcRbName2, number2, "") + defer deleteReleaseBundle(t, lcManager, tests.LcRbName2, number2) +} + +func createRbWithFlags(t *testing.T, specFilePath, sourceOption, buildName, buildNumber, rbName, rbVersion string, + sync, withoutSigningKey bool) { argsAndOptions := []string{ "rbc", rbName, rbVersion, - getOption(sourceOption, specFilePath), + } + + if specFilePath != "" { + argsAndOptions = append(argsAndOptions, getOption(sourceOption, specFilePath)) + } + + if buildName != "" && buildNumber != "" { + argsAndOptions = append(argsAndOptions, getOption(cliutils.BuildName, buildName)) + argsAndOptions = append(argsAndOptions, getOption(cliutils.BuildNumber, buildNumber)) } if !withoutSigningKey { argsAndOptions = append(argsAndOptions, getOption(cliutils.SigningKey, gpgKeyPairName)) } - // Add the --sync option only if requested, to test the default value. + if sync { argsAndOptions = append(argsAndOptions, getOption(cliutils.Sync, "true")) } + assert.NoError(t, lcCli.Exec(argsAndOptions...)) } diff --git a/utils/cliutils/commandsflags.go b/utils/cliutils/commandsflags.go index 1ad558d3c..8005a28a7 100644 --- a/utils/cliutils/commandsflags.go +++ b/utils/cliutils/commandsflags.go @@ -164,8 +164,8 @@ const ( specVars = "spec-vars" // Build info flags - buildName = "build-name" - buildNumber = "build-number" + BuildName = "build-name" + BuildNumber = "build-number" module = "module" // Generic commands flags @@ -664,12 +664,12 @@ var flagsMap = map[string]cli.Flag{ Name: specVars, Usage: "[Optional] List of semicolon-separated(;) variables in the form of \"key1=value1;key2=value2;...\" (wrapped by quotes) to be replaced in the File Spec. In the File Spec, the variables should be used as follows: ${key1}.` `", }, - buildName: cli.StringFlag{ - Name: buildName, + BuildName: cli.StringFlag{ + Name: BuildName, Usage: "[Optional] Providing this option will collect and record build info for this build name. Build number option is mandatory when this option is provided.` `", }, - buildNumber: cli.StringFlag{ - Name: buildNumber, + BuildNumber: cli.StringFlag{ + Name: BuildNumber, Usage: "[Optional] Providing this option will collect and record build info for this build number. Build name option is mandatory when this option is provided.` `", }, module: cli.StringFlag{ @@ -1739,14 +1739,14 @@ var commandFlags = map[string][]string{ }, Upload: { url, user, password, accessToken, sshPassphrase, sshKeyPath, serverId, ClientCertPath, uploadTargetProps, - ClientCertKeyPath, specFlag, specVars, buildName, buildNumber, module, uploadExclusions, deb, + ClientCertKeyPath, specFlag, specVars, BuildName, BuildNumber, module, uploadExclusions, deb, uploadRecursive, uploadFlat, uploadRegexp, retries, retryWaitTime, dryRun, uploadExplode, symlinks, includeDirs, failNoOp, threads, uploadSyncDeletes, syncDeletesQuiet, InsecureTls, detailedSummary, Project, uploadAnt, uploadArchive, uploadMinSplit, uploadSplitCount, ChunkSize, }, Download: { url, user, password, accessToken, sshPassphrase, sshKeyPath, serverId, ClientCertPath, - ClientCertKeyPath, specFlag, specVars, buildName, buildNumber, module, exclusions, sortBy, + ClientCertKeyPath, specFlag, specVars, BuildName, BuildNumber, module, exclusions, sortBy, sortOrder, limit, offset, downloadRecursive, downloadFlat, build, includeDeps, excludeArtifacts, downloadMinSplit, downloadSplitCount, retries, retryWaitTime, dryRun, downloadExplode, bypassArchiveInspection, validateSymlinks, bundle, publicGpgKey, includeDirs, downloadProps, downloadExcludeProps, failNoOp, threads, archiveEntries, downloadSyncDeletes, syncDeletesQuiet, InsecureTls, detailedSummary, Project, @@ -1800,11 +1800,11 @@ var commandFlags = map[string][]string{ Project, }, BuildDockerCreate: { - buildName, buildNumber, module, url, user, password, accessToken, sshPassphrase, sshKeyPath, + BuildName, BuildNumber, module, url, user, password, accessToken, sshPassphrase, sshKeyPath, serverId, imageFile, Project, }, OcStartBuild: { - buildName, buildNumber, module, Project, serverId, ocStartBuildRepo, + BuildName, BuildNumber, module, Project, serverId, ocStartBuildRepo, }, BuildScanLegacy: { url, user, password, accessToken, sshPassphrase, sshKeyPath, serverId, fail, InsecureTls, @@ -1836,21 +1836,21 @@ var commandFlags = map[string][]string{ deployIvyDesc, ivyDescPattern, ivyArtifactsPattern, }, Mvn: { - buildName, buildNumber, deploymentThreads, InsecureTls, Project, detailedSummary, xrayScan, xrOutput, + BuildName, BuildNumber, deploymentThreads, InsecureTls, Project, detailedSummary, xrayScan, xrOutput, }, Gradle: { - buildName, buildNumber, deploymentThreads, Project, detailedSummary, xrayScan, xrOutput, + BuildName, BuildNumber, deploymentThreads, Project, detailedSummary, xrayScan, xrOutput, }, Docker: { - buildName, buildNumber, module, Project, + BuildName, BuildNumber, module, Project, serverId, skipLogin, threads, detailedSummary, watches, repoPath, licenses, xrOutput, fail, ExtendedTable, BypassArchiveLimits, MinSeverity, FixableOnly, vuln, }, DockerPush: { - buildName, buildNumber, module, Project, + BuildName, BuildNumber, module, Project, serverId, skipLogin, threads, detailedSummary, }, DockerPull: { - buildName, buildNumber, module, Project, + BuildName, BuildNumber, module, Project, serverId, skipLogin, }, DockerPromote: { @@ -1858,21 +1858,21 @@ var commandFlags = map[string][]string{ serverId, }, ContainerPush: { - buildName, buildNumber, module, url, user, password, accessToken, sshPassphrase, sshKeyPath, + BuildName, BuildNumber, module, url, user, password, accessToken, sshPassphrase, sshKeyPath, serverId, skipLogin, threads, Project, detailedSummary, }, ContainerPull: { - buildName, buildNumber, module, url, user, password, accessToken, sshPassphrase, sshKeyPath, + BuildName, BuildNumber, module, url, user, password, accessToken, sshPassphrase, sshKeyPath, serverId, skipLogin, Project, }, NpmConfig: { global, serverIdResolve, serverIdDeploy, repoResolve, repoDeploy, }, NpmInstallCi: { - buildName, buildNumber, module, Project, + BuildName, BuildNumber, module, Project, }, NpmPublish: { - buildName, buildNumber, module, Project, npmDetailedSummary, xrayScan, xrOutput, + BuildName, BuildNumber, module, Project, npmDetailedSummary, xrayScan, xrOutput, }, PnpmConfig: { global, serverIdResolve, repoResolve, @@ -1881,38 +1881,38 @@ var commandFlags = map[string][]string{ global, serverIdResolve, repoResolve, }, Yarn: { - buildName, buildNumber, module, Project, + BuildName, BuildNumber, module, Project, }, NugetConfig: { global, serverIdResolve, repoResolve, nugetV2, }, Nuget: { - buildName, buildNumber, module, Project, allowInsecureConnections, + BuildName, BuildNumber, module, Project, allowInsecureConnections, }, DotnetConfig: { global, serverIdResolve, repoResolve, nugetV2, }, Dotnet: { - buildName, buildNumber, module, Project, + BuildName, BuildNumber, module, Project, }, GoConfig: { global, serverIdResolve, serverIdDeploy, repoResolve, repoDeploy, }, GoPublish: { - url, user, password, accessToken, buildName, buildNumber, module, Project, detailedSummary, goPublishExclusions, + url, user, password, accessToken, BuildName, BuildNumber, module, Project, detailedSummary, goPublishExclusions, }, Go: { - buildName, buildNumber, module, Project, noFallback, + BuildName, BuildNumber, module, Project, noFallback, }, TerraformConfig: { global, serverIdDeploy, repoDeploy, }, Terraform: { namespace, provider, tag, exclusions, - buildName, buildNumber, module, Project, + BuildName, BuildNumber, module, Project, }, Twine: { - buildName, buildNumber, module, Project, + BuildName, BuildNumber, module, Project, }, TransferConfig: { Force, Verbose, IncludeRepos, ExcludeRepos, SourceWorkingDir, TargetWorkingDir, PreChecks, @@ -1931,19 +1931,19 @@ var commandFlags = map[string][]string{ global, serverIdResolve, serverIdDeploy, repoResolve, repoDeploy, }, PipInstall: { - buildName, buildNumber, module, Project, + BuildName, BuildNumber, module, Project, }, PipenvConfig: { global, serverIdResolve, serverIdDeploy, repoResolve, repoDeploy, }, PipenvInstall: { - buildName, buildNumber, module, Project, + BuildName, BuildNumber, module, Project, }, PoetryConfig: { global, serverIdResolve, repoResolve, }, Poetry: { - buildName, buildNumber, module, Project, + BuildName, BuildNumber, module, Project, }, ReleaseBundleV1Create: { distUrl, user, password, accessToken, serverId, specFlag, specVars, targetProps, @@ -2020,7 +2020,7 @@ var commandFlags = map[string][]string{ }, ReleaseBundleCreate: { platformUrl, user, password, accessToken, serverId, lcSigningKey, lcSync, lcProject, lcBuilds, lcReleaseBundles, - specFlag, specVars, + specFlag, specVars, BuildName, BuildNumber, }, ReleaseBundlePromote: { platformUrl, user, password, accessToken, serverId, lcSigningKey, lcSync, lcProject, lcIncludeRepos, lcExcludeRepos,