Skip to content

Commit

Permalink
Merge branch 'dev' of https://github.com/jfrog/jfrog-cli into dev-tests
Browse files Browse the repository at this point in the history
  • Loading branch information
sverdlov93 committed Feb 5, 2024
2 parents 4954ba0 + 23ece04 commit aae2358
Show file tree
Hide file tree
Showing 13 changed files with 128 additions and 97 deletions.
6 changes: 3 additions & 3 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ require (
github.com/nwaples/rardecode v1.1.3 // indirect
github.com/opencontainers/go-digest v1.0.0 // indirect
github.com/opencontainers/image-spec v1.1.0-rc5 // indirect
github.com/opencontainers/runc v1.1.5 // indirect
github.com/opencontainers/runc v1.1.12 // indirect
github.com/owenrumney/go-sarif/v2 v2.3.0 // indirect
github.com/pelletier/go-toml/v2 v2.1.0 // indirect
github.com/pierrec/lz4/v4 v4.1.21 // indirect
Expand Down Expand Up @@ -131,9 +131,9 @@ 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.20240122141213-a1db3c179c7e
replace github.com/jfrog/jfrog-cli-core/v2 => github.com/jfrog/jfrog-cli-core/v2 v2.31.1-0.20240204105703-557f7a17d7f9

// replace github.com/jfrog/jfrog-client-go => github.com/jfrog/jfrog-client-go v1.28.1-0.20240122123649-74f725715bbe
replace github.com/jfrog/jfrog-client-go => github.com/jfrog/jfrog-client-go v1.28.1-0.20240204105421-dd3f7041f3df

// replace github.com/jfrog/jfrog-cli-security => github.com/jfrog/jfrog-cli-security v0.0.0-20240122124933-edf9cb4ca3ac

Expand Down
44 changes: 6 additions & 38 deletions go.sum

Large diffs are not rendered by default.

11 changes: 10 additions & 1 deletion lifecycle/cli.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import (
"github.com/jfrog/jfrog-client-go/utils"
"github.com/jfrog/jfrog-client-go/utils/errorutils"
"github.com/urfave/cli"
"strings"
)

const lcCategory = "Lifecycle"
Expand Down Expand Up @@ -119,7 +120,8 @@ func promote(c *cli.Context) error {

createCmd := lifecycle.NewReleaseBundlePromoteCommand().SetServerDetails(lcDetails).SetReleaseBundleName(c.Args().Get(0)).
SetReleaseBundleVersion(c.Args().Get(1)).SetEnvironment(c.Args().Get(2)).SetSigningKeyName(c.String(cliutils.SigningKey)).
SetSync(c.Bool(cliutils.Sync)).SetReleaseBundleProject(cliutils.GetProject(c)).SetOverwrite(c.Bool(cliutils.Overwrite))
SetSync(c.Bool(cliutils.Sync)).SetReleaseBundleProject(cliutils.GetProject(c)).
SetIncludeReposPatterns(splitRepos(c, cliutils.IncludeRepos)).SetExcludeReposPatterns(splitRepos(c, cliutils.ExcludeRepos))
return commands.Exec(createCmd)
}

Expand Down Expand Up @@ -186,3 +188,10 @@ func PlatformToLifecycleUrls(lcDetails *coreConfig.ServerDetails) {
lcDetails.LifecycleUrl = utils.AddTrailingSlashIfNeeded(lcDetails.Url) + "lifecycle/"
lcDetails.Url = ""
}

func splitRepos(c *cli.Context, reposOptionKey string) []string {
if c.IsSet(reposOptionKey) {
return strings.Split(c.String(reposOptionKey), ";")
}
return nil
}
72 changes: 50 additions & 22 deletions lifecycle_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,8 @@ import (
"github.com/jfrog/jfrog-client-go/lifecycle"
"github.com/jfrog/jfrog-client-go/lifecycle/services"
clientUtils "github.com/jfrog/jfrog-client-go/utils"
"github.com/jfrog/jfrog-client-go/utils/distribution"
"github.com/jfrog/jfrog-client-go/utils/errorutils"
clientTestUtils "github.com/jfrog/jfrog-client-go/utils/tests"
"github.com/stretchr/testify/assert"
"net/http"
"os"
Expand All @@ -42,7 +42,8 @@ var (
)

func TestLifecycle(t *testing.T) {
initLifecycleTest(t)
cleanHomeDir := initLifecycleTest(t)
defer cleanHomeDir()
defer cleanLifecycleTests(t)
lcManager := getLcServiceManager(t)

Expand All @@ -54,7 +55,8 @@ func TestLifecycle(t *testing.T) {
createRb(t, buildsSpec12, cliutils.Builds, tests.LcRbName1, number1, true)
defer deleteReleaseBundle(t, lcManager, tests.LcRbName1, number1)

// Create release bundle from builds asynchronously and assert status.
// Create release bundle from a build asynchronously and assert status.
// This build has dependencies which are included in the release bundle.
createRb(t, buildsSpec3, cliutils.Builds, tests.LcRbName2, number2, false)
defer deleteReleaseBundle(t, lcManager, tests.LcRbName2, number2)
assertStatusCompleted(t, lcManager, tests.LcRbName2, number2, "")
Expand All @@ -63,27 +65,35 @@ func TestLifecycle(t *testing.T) {
createRb(t, releaseBundlesSpec, cliutils.ReleaseBundles, tests.LcRbName3, number3, true)
defer deleteReleaseBundle(t, lcManager, tests.LcRbName3, number3)

// Promote the last release bundle.
// Promote the last release bundle to prod repo 1.
promoteRb(t, lcManager, number3)

// Verify the artifacts of both the initial release bundles made it to the prod repo.
searchProdSpec, err := tests.CreateSpec(tests.SearchAllProdRepo)
assert.NoError(t, err)
inttestutils.VerifyExistInArtifactory(tests.GetExpectedLifecycleArtifacts(), searchProdSpec, serverDetails, t)
// Assert the artifacts of both the initial release bundles made it to prod repo 1.
assertExpectedArtifacts(t, tests.SearchAllProdRepo1, tests.GetExpectedLifecycleArtifacts())
// Assert no artifacts were promoted to prod repo 2.
assertExpectedArtifacts(t, tests.SearchAllProdRepo2, []string{})

// TODO Temporarily disabling till distribution on testing suite is stable.
/*
distributeRb(t)
defer remoteDeleteReleaseBundle(t, lcManager, tests.LcRbName3, number3)
distributeRb(t)
defer remoteDeleteReleaseBundle(t, lcManager, tests.LcRbName3, number3)
// Verify the artifacts were distributed correctly by the provided path mappings.
assertExpectedArtifacts(t, tests.SearchAllDevRepo, tests.GetExpectedLifecycleDistributedArtifacts())
*/

// Verify the artifacts were distributed correctly by the provided path mappings.
searchDevSpec, err := tests.CreateSpec(tests.SearchAllDevRepo)
}

func assertExpectedArtifacts(t *testing.T, specFileName string, expected []string) {
searchProdSpec, err := tests.CreateSpec(specFileName)
assert.NoError(t, err)
inttestutils.VerifyExistInArtifactory(tests.GetExpectedLifecycleDistributedArtifacts(), searchDevSpec, serverDetails, t)
inttestutils.VerifyExistInArtifactory(expected, searchProdSpec, serverDetails, t)
}

func uploadBuilds(t *testing.T) func() {
uploadBuild(t, tests.UploadDevSpecA, tests.LcBuildName1, number1)
uploadBuild(t, tests.UploadDevSpecB, tests.LcBuildName2, number2)
uploadBuild(t, tests.UploadDevSpecC, tests.LcBuildName3, number3)
uploadBuild(t, tests.UploadDevSpecA, tests.LcBuildName1, number1, false)
uploadBuild(t, tests.UploadDevSpecB, tests.LcBuildName2, number2, false)
uploadBuild(t, tests.UploadDevSpecC, tests.LcBuildName3, number3, true)
return func() {
inttestutils.DeleteBuild(serverDetails.ArtifactoryUrl, tests.LcBuildName1, artHttpDetails)
inttestutils.DeleteBuild(serverDetails.ArtifactoryUrl, tests.LcBuildName2, artHttpDetails)
Expand All @@ -108,6 +118,7 @@ func createRb(t *testing.T, specName, sourceOption, rbName, rbVersion string, sy
assert.NoError(t, lcCli.Exec(argsAndOptions...))
}

/*
func distributeRb(t *testing.T) {
distributionRulesPath := filepath.Join(tests.GetTestResourcesPath(), "distribution", tests.DistributionRules)
assert.NoError(t, lcCli.Exec(
Expand All @@ -119,6 +130,7 @@ func distributeRb(t *testing.T) {
// Wait after distribution before asserting. Can be removed once distribute supports sync.
time.Sleep(5 * time.Second)
}
*/

func getOption(option, value string) string {
return fmt.Sprintf("--%s=%s", option, value)
Expand All @@ -127,7 +139,7 @@ func getOption(option, value string) string {
func promoteRb(t *testing.T, lcManager *lifecycle.LifecycleServicesManager, rbVersion string) {
output := lcCli.RunCliCmdWithOutput(t, "rbp", tests.LcRbName3, rbVersion, prodEnvironment,
getOption(cliutils.SigningKey, gpgKeyPairName),
getOption(cliutils.Overwrite, "true"),
getOption(cliutils.IncludeRepos, tests.RtProdRepo1),
"--project=default")
var promotionResp services.RbPromotionResp
if !assert.NoError(t, json.Unmarshal([]byte(output), &promotionResp)) {
Expand Down Expand Up @@ -192,11 +204,12 @@ func deleteReleaseBundle(t *testing.T, lcManager *lifecycle.LifecycleServicesMan
ReleaseBundleVersion: rbVersion,
}

assert.NoError(t, lcManager.DeleteReleaseBundle(rbDetails, services.ReleaseBundleQueryParams{Async: false}))
assert.NoError(t, lcManager.DeleteReleaseBundle(rbDetails, services.CommonOptionalQueryParams{Async: false}))
// Wait after remote deleting. Can be removed once remote deleting supports sync.
time.Sleep(5 * time.Second)
}

/*
func remoteDeleteReleaseBundle(t *testing.T, lcManager *lifecycle.LifecycleServicesManager, rbName, rbVersion string) {
params := distribution.NewDistributeReleaseBundleParams(rbName, rbVersion)
rules := &distribution.DistributionCommonParams{
Expand All @@ -210,15 +223,22 @@ func remoteDeleteReleaseBundle(t *testing.T, lcManager *lifecycle.LifecycleServi
// Wait after remote deleting. Can be removed once remote deleting supports sync.
time.Sleep(5 * time.Second)
}
*/

func uploadBuild(t *testing.T, specFileName, buildName, buildNumber string) {
func uploadBuild(t *testing.T, specFileName, buildName, buildNumber string, uploadAsDependencies bool) {
specFile, err := tests.CreateSpec(specFileName)
assert.NoError(t, err)
runRt(t, "upload", "--spec="+specFile, "--build-name="+buildName, "--build-number="+buildNumber)

if uploadAsDependencies {
runRt(t, "upload", "--spec="+specFile)
assert.NoError(t, lcCli.WithoutCredentials().Exec("rt", "bad", buildName, buildNumber, tests.RtDevRepo+"/c*.in", "--from-rt"))
} else {
runRt(t, "upload", "--spec="+specFile, "--build-name="+buildName, "--build-number="+buildNumber)
}
runRt(t, "build-publish", buildName, buildNumber)
}

func initLifecycleTest(t *testing.T) {
func initLifecycleTest(t *testing.T) (cleanHomeDir func()) {
if !*tests.TestLifecycle {
t.Skip("Skipping lifecycle test. To run release bundle test add the '-test.lc=true' option.")
}
Expand All @@ -227,6 +247,13 @@ func initLifecycleTest(t *testing.T) {
if !isLifecycleSupported(t) {
t.Skip("Skipping lifecycle test because the functionality is not enabled on the provided JPD.")
}

// Populate cli config with 'default' server.
oldHomeDir, newHomeDir := prepareHomeDir(t)
return func() {
clientTestUtils.SetEnvAndAssert(t, coreutils.HomeDir, oldHomeDir)
clientTestUtils.RemoveAllAndAssert(t, newHomeDir)
}
}

func isLifecycleSupported(t *testing.T) (skip bool) {
Expand Down Expand Up @@ -264,7 +291,8 @@ func CleanLifecycleTests() {

func cleanLifecycleTests(t *testing.T) {
deleteFilesFromRepo(t, tests.RtDevRepo)
deleteFilesFromRepo(t, tests.RtProdRepo)
deleteFilesFromRepo(t, tests.RtProdRepo1)
deleteFilesFromRepo(t, tests.RtProdRepo2)
tests.CleanFileSystem()
}

Expand Down
7 changes: 0 additions & 7 deletions testdata/filespecs/search_all_prod_repo.json

This file was deleted.

7 changes: 7 additions & 0 deletions testdata/filespecs/search_all_prod_repo1.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"files": [
{
"pattern": "${PROD_REPO1}/*"
}
]
}
7 changes: 7 additions & 0 deletions testdata/filespecs/search_all_prod_repo2.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"files": [
{
"pattern": "${PROD_REPO2}/*"
}
]
}
3 changes: 2 additions & 1 deletion testdata/lifecycle/builds-spec-3.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@
"builds": [
{
"name": "${LC_BUILD_NAME3}",
"number": ""
"number": "",
"includeDependencies": true
}
]
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
"key": "${PROD_REPO}",
"key": "${PROD_REPO1}",
"rclass": "local",
"packageType": "generic",
"environments":["PROD"]
Expand Down
6 changes: 6 additions & 0 deletions testdata/prod_repo2_repository_config.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"key": "${PROD_REPO2}",
"rclass": "local",
"packageType": "generic",
"environments":["PROD"]
}
18 changes: 12 additions & 6 deletions utils/cliutils/commandsflags.go
Original file line number Diff line number Diff line change
Expand Up @@ -585,12 +585,13 @@ const (
lcReleaseBundles = lifecyclePrefix + ReleaseBundles
SigningKey = "signing-key"
lcSigningKey = lifecyclePrefix + SigningKey
lcOverwrite = lifecyclePrefix + Overwrite
PathMappingPattern = "mapping-pattern"
lcPathMappingPattern = lifecyclePrefix + PathMappingPattern
PathMappingTarget = "mapping-target"
lcPathMappingTarget = lifecyclePrefix + PathMappingTarget
lcDryRun = lifecyclePrefix + dryRun
lcIncludeRepos = lifecyclePrefix + IncludeRepos
lcExcludeRepos = lifecyclePrefix + ExcludeRepos
)

var flagsMap = map[string]cli.Flag{
Expand Down Expand Up @@ -1651,10 +1652,6 @@ var flagsMap = map[string]cli.Flag{
Name: SigningKey,
Usage: "[Mandatory] The GPG/RSA key-pair name given in Artifactory.` `",
},
lcOverwrite: cli.BoolFlag{
Name: Overwrite,
Usage: "[Default: false] Set to true to replace artifacts with the same name but a different checksum if such already exist at the promotion targets. By default, the promotion is stopped in a case of such conflict.` `",
},
lcPathMappingPattern: cli.StringFlag{
Name: PathMappingPattern,
Usage: "[Optional] Specify along with '" + PathMappingTarget + "' to distribute artifacts to a different path on the edge node. You can use wildcards to specify multiple artifacts.` `",
Expand All @@ -1673,6 +1670,15 @@ var flagsMap = map[string]cli.Flag{
Usage: "Default: false] [npm] when set, the Contextual Analysis scan also uses the code of the project dependencies to determine the applicability of the vulnerability.",
Hidden: true,
},
lcIncludeRepos: cli.StringFlag{
Name: IncludeRepos,
Usage: "[Optional] A list of semicolon-separated repositories to include in the promotion. If this property is left undefined, all repositories (except those specifically excluded) are included in the promotion. " +
"If one or more repositories are specifically included, all other repositories are excluded.` `",
},
lcExcludeRepos: cli.StringFlag{
Name: ExcludeRepos,
Usage: "[Optional] A list of semicolon-separated repositories to exclude from the promotion.` `",
},
atcProject: cli.StringFlag{
Name: Project,
Usage: "[Optional] The project for which this token is created. Enter the project name on which you want to apply this token.` `",
Expand Down Expand Up @@ -1999,7 +2005,7 @@ var commandFlags = map[string][]string{
lcUrl, user, password, accessToken, serverId, lcSigningKey, lcSync, lcProject, lcBuilds, lcReleaseBundles,
},
ReleaseBundlePromote: {
lcUrl, user, password, accessToken, serverId, lcSigningKey, lcSync, lcProject, lcOverwrite,
lcUrl, user, password, accessToken, serverId, lcSigningKey, lcSync, lcProject, lcIncludeRepos, lcExcludeRepos,
},
ReleaseBundleDistribute: {
lcUrl, user, password, accessToken, serverId, lcDryRun, DistRules, site, city, countryCodes,
Expand Down
29 changes: 16 additions & 13 deletions utils/tests/consts.go
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,8 @@ const (
SearchAllNpm = "search_all_npm.json"
SearchAllRepo1 = "search_all_repo1.json"
SearchAllDevRepo = "search_all_dev_repo.json"
SearchAllProdRepo = "search_all_prod_repo.json"
SearchAllProdRepo1 = "search_all_prod_repo1.json"
SearchAllProdRepo2 = "search_all_prod_repo2.json"
SearchDistRepoByInSuffix = "search_dist_repo_by_in_suffix.json"
SearchRepo1ByInSuffix = "search_repo1_by_in_suffix.json"
GoPublishRepoExcludes = "go_publish_repo_excludes.json"
Expand Down Expand Up @@ -150,7 +151,8 @@ const (
DockerVirtualRepositoryConfig = "docker_virtual_repository_config.json"
XrayEndpoint = "xray/"
DevRepoRepositoryConfig = "dev_repo_repository_config.json"
ProdRepoRepositoryConfig = "prod_repo_repository_config.json"
ProdRepo1RepositoryConfig = "prod_repo1_repository_config.json"
ProdRepo2RepositoryConfig = "prod_repo2_repository_config.json"
UploadDevSpecA = "upload_dev_spec_a.json"
UploadDevSpecB = "upload_dev_spec_b.json"
UploadDevSpecC = "upload_dev_spec_c.json"
Expand Down Expand Up @@ -187,8 +189,9 @@ var (
RtRepo2 = "cli-rt2"
RtVirtualRepo = "cli-rt-virtual"
// Repositories that are assigned to an environment.
RtDevRepo = "cli-rt-dev"
RtProdRepo = "cli-rt-prod"
RtDevRepo = "cli-rt-dev"
RtProdRepo1 = "cli-rt-prod1"
RtProdRepo2 = "cli-rt-prod2"
// These are not actual repositories. These patterns are meant to be used in both Repo1 and Repo2.
RtRepo1And2 = "cli-rt*"
RtRepo1And2Placeholder = "cli-rt(*)"
Expand Down Expand Up @@ -2088,15 +2091,15 @@ func GetTransferExpectedRepoSnapshot() []string {

func GetExpectedLifecycleArtifacts() []string {
return []string{
RtProdRepo + "/a1.in",
RtProdRepo + "/a2.in",
RtProdRepo + "/a3.in",
RtProdRepo + "/b1.in",
RtProdRepo + "/b2.in",
RtProdRepo + "/b3.in",
RtProdRepo + "/c1.in",
RtProdRepo + "/c2.in",
RtProdRepo + "/c3.in",
RtProdRepo1 + "/a1.in",
RtProdRepo1 + "/a2.in",
RtProdRepo1 + "/a3.in",
RtProdRepo1 + "/b1.in",
RtProdRepo1 + "/b2.in",
RtProdRepo1 + "/b3.in",
RtProdRepo1 + "/c1.in",
RtProdRepo1 + "/c2.in",
RtProdRepo1 + "/c3.in",
}
}

Expand Down
Loading

0 comments on commit aae2358

Please sign in to comment.