Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Artifactory Release Lifecycle Management - Add Export bundle command #2459

Merged
merged 31 commits into from
Mar 20, 2024
Merged
Show file tree
Hide file tree
Changes from 28 commits
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
712f159
Add rbe - release bundle export function
EyalDelarea Feb 29, 2024
a8ef281
Add rbe - release bundle export function
EyalDelarea Feb 29, 2024
07d6e34
remove destination flag
EyalDelarea Feb 29, 2024
f953caa
pull dev
EyalDelarea Feb 29, 2024
5b4f50b
fix go version
EyalDelarea Feb 29, 2024
8b5d434
fix static check
EyalDelarea Feb 29, 2024
e6e29b7
add rb export test
EyalDelarea Mar 3, 2024
924686f
update deps
EyalDelarea Mar 3, 2024
a6219e3
update deps
EyalDelarea Mar 3, 2024
fa617b8
verify downloaded exported file in tests and delete it afterward
EyalDelarea Mar 4, 2024
e7e5129
pull dev
EyalDelarea Mar 6, 2024
60974eb
CR
EyalDelarea Mar 10, 2024
f0d62c5
update deps
EyalDelarea Mar 10, 2024
bbbbd11
Merge branch 'dev' of https://github.com/jfrog/jfrog-cli into rb-expo…
EyalDelarea Mar 11, 2024
acdfc34
update deps
EyalDelarea Mar 11, 2024
f3d4ce5
change path mapping from distribution to artifactory
EyalDelarea Mar 11, 2024
f641b90
fix static check
EyalDelarea Mar 11, 2024
3b7eeec
Update repo flag
EyalDelarea Mar 11, 2024
c6557b7
Merge branch 'dev' into rb-export-import
EyalDelarea Mar 12, 2024
effd206
pull dev
EyalDelarea Mar 18, 2024
609f9f5
Merge branch 'rb-export-import' of https://github.com/EyalDelarea/jfr…
EyalDelarea Mar 18, 2024
bd802ae
update deps
EyalDelarea Mar 18, 2024
0093c2b
pull dev & update deps
EyalDelarea Mar 19, 2024
17c2db4
CR
EyalDelarea Mar 19, 2024
c0469a3
move target pattern to arg
EyalDelarea Mar 19, 2024
bf37e7f
update deps and verify downloaded file in test
EyalDelarea Mar 19, 2024
c1563f6
update deps
EyalDelarea Mar 19, 2024
42ffee1
Docs update
EyalDelarea Mar 19, 2024
2fd9a68
pull dev
EyalDelarea Mar 20, 2024
17b615e
CR
EyalDelarea Mar 20, 2024
50f7968
Update deps
EyalDelarea Mar 20, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
84 changes: 2 additions & 82 deletions artifactory/cli.go
Original file line number Diff line number Diff line change
Expand Up @@ -948,37 +948,6 @@ func GetCommands() []cli.Command {
})
}

func getSplitCount(c *cli.Context, defaultSplitCount, maxSplitCount int) (splitCount int, err error) {
splitCount = defaultSplitCount
err = nil
if c.String("split-count") != "" {
splitCount, err = strconv.Atoi(c.String("split-count"))
if err != nil {
err = errors.New("The '--split-count' option should have a numeric value. " + cliutils.GetDocumentationMessage())
}
if splitCount > maxSplitCount {
err = errors.New("The '--split-count' option value is limited to a maximum of " + strconv.Itoa(maxSplitCount) + ".")
}
if splitCount < 0 {
err = errors.New("the '--split-count' option cannot have a negative value")
}
}
return
}

func getMinSplit(c *cli.Context, defaultMinSplit int64) (minSplitSize int64, err error) {
minSplitSize = defaultMinSplit
if c.String(cliutils.MinSplit) != "" {
minSplitSize, err = strconv.ParseInt(c.String(cliutils.MinSplit), 10, 64)
if err != nil {
err = errors.New("The '--min-split' option should have a numeric value. " + cliutils.GetDocumentationMessage())
return 0, err
}
}

return minSplitSize, nil
}

func getRetries(c *cli.Context) (retries int, err error) {
retries = cliutils.Retries
if c.String("retries") != "" {
Expand Down Expand Up @@ -1238,7 +1207,7 @@ func downloadCmd(c *cli.Context) error {
return err
}
fixWinPathsForDownloadCmd(downloadSpec, c)
configuration, err := createDownloadConfiguration(c)
configuration, err := cliutils.CreateDownloadConfiguration(c)
if err != nil {
return err
}
Expand Down Expand Up @@ -1299,7 +1268,7 @@ func uploadCmd(c *cli.Context) (err error) {
return
}
cliutils.FixWinPathsForFileSystemSourcedCmds(uploadSpec, c)
configuration, err := createUploadConfiguration(c)
configuration, err := cliutils.CreateUploadConfiguration(c)
if err != nil {
return
}
Expand Down Expand Up @@ -2421,15 +2390,6 @@ func transferSettingsCmd(_ *cli.Context) error {
return commands.Exec(transferSettingsCmd)
}

func getDebFlag(c *cli.Context) (deb string, err error) {
deb = c.String("deb")
slashesCount := strings.Count(deb, "/") - strings.Count(deb, "\\/")
if deb != "" && slashesCount != 2 {
return "", errors.New("the --deb option should be in the form of distribution/component/architecture")
}
return deb, nil
}

func createDefaultCopyMoveSpec(c *cli.Context) (*spec.SpecFiles, error) {
offset, limit, err := getOffsetAndLimitValues(c)
if err != nil {
Expand Down Expand Up @@ -2635,25 +2595,6 @@ func createDefaultDownloadSpec(c *cli.Context) (*spec.SpecFiles, error) {
BuildSpec(), nil
}

func createDownloadConfiguration(c *cli.Context) (downloadConfiguration *utils.DownloadConfiguration, err error) {
downloadConfiguration = new(utils.DownloadConfiguration)
downloadConfiguration.MinSplitSize, err = getMinSplit(c, cliutils.DownloadMinSplitKb)
if err != nil {
return nil, err
}
downloadConfiguration.SplitCount, err = getSplitCount(c, cliutils.DownloadSplitCount, cliutils.DownloadMaxSplitCount)
if err != nil {
return nil, err
}
downloadConfiguration.Threads, err = cliutils.GetThreadsCount(c)
if err != nil {
return nil, err
}
downloadConfiguration.SkipChecksum = c.Bool("skip-checksum")
downloadConfiguration.Symlink = true
return
}

func setTransitiveInDownloadSpec(downloadSpec *spec.SpecFiles) {
transitive := os.Getenv(coreutils.TransitiveDownload)
if transitive == "" {
Expand Down Expand Up @@ -2713,27 +2654,6 @@ func fixWinPathsForDownloadCmd(uploadSpec *spec.SpecFiles, c *cli.Context) {
}
}

func createUploadConfiguration(c *cli.Context) (uploadConfiguration *utils.UploadConfiguration, err error) {
uploadConfiguration = new(utils.UploadConfiguration)
uploadConfiguration.MinSplitSizeMB, err = getMinSplit(c, cliutils.UploadMinSplitMb)
if err != nil {
return nil, err
}
uploadConfiguration.SplitCount, err = getSplitCount(c, cliutils.UploadSplitCount, cliutils.UploadMaxSplitCount)
if err != nil {
return nil, err
}
uploadConfiguration.Threads, err = cliutils.GetThreadsCount(c)
if err != nil {
return nil, err
}
uploadConfiguration.Deb, err = getDebFlag(c)
if err != nil {
return
}
return
}

func getOffsetAndLimitValues(c *cli.Context) (offset, limit int, err error) {
offset, err = cliutils.GetIntFlagValue(c, "offset", 0)
if err != nil {
Expand Down
2 changes: 1 addition & 1 deletion artifactory/cli_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -142,7 +142,7 @@ func TestCreateUploadConfiguration(t *testing.T) {
for _, testCase := range createUploadConfigurationCases {
t.Run(testCase.name, func(t *testing.T) {
context, _ := tests.CreateContext(t, testCase.flags, []string{})
uploadConfiguration, err := createUploadConfiguration(context)
uploadConfiguration, err := cliutils.CreateUploadConfiguration(context)
assert.NoError(t, err)
assert.Equal(t, testCase.expectedMinSplit, uploadConfiguration.MinSplitSizeMB)
assert.Equal(t, testCase.expectedSplitCount, uploadConfiguration.SplitCount)
Expand Down
24 changes: 24 additions & 0 deletions docs/lifecycle/export/help.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package export

var Usage = []string{"rbe <release bundle name> <release bundle version> [target pattern]"}

func GetDescription() string {
return "Triggers the Export process and downloads the Release Bundle archive"
}

func GetArguments() string {
EyalDelarea marked this conversation as resolved.
Show resolved Hide resolved
return ` release bundle name
Name of the Release Bundle to export.

release bundle version
Version of the Release Bundle to export.

target pattern
The third argument is optional and specifies the local file system target path.
If the target path ends with a slash, the path is assumed to be a directory.
For example, if you specify the target as "repo-name/a/b/", then "b" is assumed to be a directory into which files should be downloaded.
If there is no terminal slash, the target path is assumed to be a file to which the downloaded file should be renamed.
For example, if you specify the target as "a/b", the downloaded file is renamed to "b".
For flexibility in specifying the target path, you can include placeholders in the form of {1}, {2} which are replaced by corresponding
EyalDelarea marked this conversation as resolved.
Show resolved Hide resolved
tokens in the source path that are enclosed in parenthesis.`
}
4 changes: 2 additions & 2 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -130,9 +130,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 dev
replace github.com/jfrog/jfrog-cli-core/v2 => github.com/eyaldelarea/jfrog-cli-core/v2 v2.0.0-20240319144309-be480483bf30

// replace github.com/jfrog/jfrog-client-go => github.com/jfrog/jfrog-client-go dev
replace github.com/jfrog/jfrog-client-go => github.com/eyaldelarea/jfrog-client-go v1.28.4-0.20240319142726-22f1f4a74374

// replace github.com/jfrog/build-info-go => github.com/jfrog/build-info-go dev

Expand Down
8 changes: 4 additions & 4 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,10 @@ 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/eyaldelarea/jfrog-cli-core/v2 v2.0.0-20240319144309-be480483bf30 h1:OlUsUV0xqd6bAsnuwKBJyno5nfD5LBi7VRWeBQKkHvY=
github.com/eyaldelarea/jfrog-cli-core/v2 v2.0.0-20240319144309-be480483bf30/go.mod h1:w91LjZZIiaowz2eb+YPoBmycZDhafGQuqUXrrC1MXSc=
github.com/eyaldelarea/jfrog-client-go v1.28.4-0.20240319142726-22f1f4a74374 h1:nY/nIX8IL9obve912r1MsPYhOKGOvnS02biF/nzh+8o=
github.com/eyaldelarea/jfrog-client-go v1.28.4-0.20240319142726-22f1f4a74374/go.mod h1:MJmkLyB9YmdiRxwLO7j1PB/bEIrvZIpaS0MA58TOT9o=
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=
Expand Down Expand Up @@ -127,12 +131,8 @@ github.com/jfrog/gofrog v1.6.3 h1:F7He0+75HcgCe6SGTSHLFCBDxiE2Ja0tekvvcktW6wc=
github.com/jfrog/gofrog v1.6.3/go.mod h1:SZ1EPJUruxrVGndOzHd+LTiwWYKMlHqhKD+eu+v5Hqg=
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-core/v2 v2.49.0 h1:HhhwmenyAzRNXUY4KNHKmRH9fcaohCzvcWfzLx/Lt5M=
github.com/jfrog/jfrog-cli-core/v2 v2.49.0/go.mod h1:t7SigeX0Fbzsv0RIDGKkYnNQrwgf2cqIfoASoo5qZ2A=
github.com/jfrog/jfrog-cli-security v1.0.4 h1:wJwvpaozhzvMCwJA/puU5jQCnjFPqMUeZAntndgYuB0=
github.com/jfrog/jfrog-cli-security v1.0.4/go.mod h1:jtRSzr/E2s7LnwUzKX5w4vtJxHFHCKGmuo8qm8HSy2o=
github.com/jfrog/jfrog-client-go v1.38.0 h1:0QP4/dSmJe0oYUrAqzoPDpGdJHcrOeq9mycnb0pSxqQ=
github.com/jfrog/jfrog-client-go v1.38.0/go.mod h1:EHRLxpu0pIT7+ulYDNQ7IeieYBHMQeEPr8CoBHoJzQY=
github.com/jszwec/csvutil v1.10.0 h1:upMDUxhQKqZ5ZDCs/wy+8Kib8rZR8I8lOR34yJkdqhI=
github.com/jszwec/csvutil v1.10.0/go.mod h1:/E4ONrmGkwmWsk9ae9jpXnv9QT8pLHEPcCirMFhxG9I=
github.com/kevinburke/ssh_config v1.2.0 h1:x584FjTGwHzMwvHx18PXxbBVzfnxogHaAReU4gf13a4=
Expand Down
51 changes: 51 additions & 0 deletions lifecycle/cli.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,12 @@ import (
rbDeleteLocal "github.com/jfrog/jfrog-cli/docs/lifecycle/deletelocal"
rbDeleteRemote "github.com/jfrog/jfrog-cli/docs/lifecycle/deleteremote"
rbDistribute "github.com/jfrog/jfrog-cli/docs/lifecycle/distribute"
rbExport "github.com/jfrog/jfrog-cli/docs/lifecycle/export"
rbPromote "github.com/jfrog/jfrog-cli/docs/lifecycle/promote"
"github.com/jfrog/jfrog-cli/utils/cliutils"
"github.com/jfrog/jfrog-cli/utils/distribution"
artClientUtils "github.com/jfrog/jfrog-client-go/artifactory/services/utils"
"github.com/jfrog/jfrog-client-go/lifecycle/services"
"github.com/jfrog/jfrog-client-go/utils"
"github.com/jfrog/jfrog-client-go/utils/errorutils"
"github.com/urfave/cli"
Expand Down Expand Up @@ -63,6 +66,18 @@ func GetCommands() []cli.Command {
Category: lcCategory,
Action: distribute,
},
{
Name: "release-bundle-export",
Aliases: []string{"rbe"},
Flags: cliutils.GetCommandFlags(cliutils.ReleaseBundleExport),
Usage: rbExport.GetDescription(),
HelpName: coreCommon.CreateUsage("rbe", rbExport.GetDescription(), rbExport.Usage),
UsageText: rbExport.GetArguments(),
ArgsUsage: common.CreateEnvVars(),
BashComplete: coreCommon.CreateBashCompletionFunc(),
Category: lcCategory,
Action: export,
},
{
Name: "release-bundle-delete-local",
Aliases: []string{"rbdell"},
Expand Down Expand Up @@ -263,6 +278,24 @@ func deleteRemote(c *cli.Context) error {
return commands.Exec(deleteCmd)
}

func export(c *cli.Context) error {
lcDetails, err := createLifecycleDetailsByFlags(c)
if err != nil {
return err
}
exportCmd, modifications := initReleaseBundleExportCmd(c)
downloadConfig, err := cliutils.CreateDownloadConfiguration(c)
if err != nil {
return err
}
exportCmd.
SetServerDetails(lcDetails).
SetReleaseBundleExportModifications(modifications).
SetDownloadConfiguration(*downloadConfig)

return commands.Exec(exportCmd)
}

func validateDistributeCommand(c *cli.Context) error {
if err := distribution.ValidateReleaseBundleDistributeCmd(c); err != nil {
return err
Expand Down Expand Up @@ -308,3 +341,21 @@ func splitRepos(c *cli.Context, reposOptionKey string) []string {
}
return nil
}

func initReleaseBundleExportCmd(c *cli.Context) (command *lifecycle.ReleaseBundleExportCommand, modifications services.Modifications) {
command = lifecycle.NewReleaseBundleExportCommand().
SetReleaseBundleName(c.Args().Get(0)).
SetReleaseBundleVersion(c.Args().Get(1)).
SetTargetPath(c.Args().Get(2)).
SetProject(c.String(cliutils.Project))

modifications = services.Modifications{
PathMappings: []artClientUtils.PathMapping{
{
Input: c.String(cliutils.PathMappingPattern),
Output: c.String(cliutils.PathMappingTarget),
},
},
}
return
}
20 changes: 20 additions & 0 deletions lifecycle_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import (
"github.com/jfrog/jfrog-client-go/lifecycle/services"
clientUtils "github.com/jfrog/jfrog-client-go/utils"
"github.com/jfrog/jfrog-client-go/utils/errorutils"
"github.com/jfrog/jfrog-client-go/utils/io/fileutils"
clientTestUtils "github.com/jfrog/jfrog-client-go/utils/tests"
"github.com/stretchr/testify/assert"
"net/http"
Expand Down Expand Up @@ -138,6 +139,14 @@ func TestLifecycleFullFlow(t *testing.T) {
// Assert no artifacts were promoted to prod repo 2.
assertExpectedArtifacts(t, tests.SearchAllProdRepo2, []string{})

// Export release lifecycle bundle archive

tempDir, cleanUp := coreTests.CreateTempDirWithCallbackAndAssert(t)
defer cleanUp()

exportRb(t, tests.LcRbName2, number2, tempDir)
defer deleteExportedReleaseBundle(t, tests.LcRbName2)

// TODO Temporarily disabling till distribution on testing suite is stable.
/*
distributeRb(t)
Expand All @@ -149,6 +158,10 @@ func TestLifecycleFullFlow(t *testing.T) {

}

func deleteExportedReleaseBundle(t *testing.T, rbName string) {
assert.NoError(t, os.RemoveAll(rbName))
}

func assertExpectedArtifacts(t *testing.T, specFileName string, expected []string) {
searchProdSpec, err := tests.CreateSpec(specFileName)
assert.NoError(t, err)
Expand Down Expand Up @@ -193,6 +206,13 @@ func createRb(t *testing.T, specFilePath, sourceOption, rbName, rbVersion string
assert.NoError(t, lcCli.Exec(argsAndOptions...))
}

func exportRb(t *testing.T, rbName, rbVersion, targetPath string) {
lcCli.RunCliCmdWithOutput(t, "rbe", rbName, rbVersion, targetPath+"/")
exists, err := fileutils.IsDirExists(path.Join(targetPath, rbName), false)
assert.NoError(t, err)
assert.Equal(t, true, exists)
}

/*
func distributeRb(t *testing.T) {
distributionRulesPath := filepath.Join(tests.GetTestResourcesPath(), "distribution", tests.DistributionRules)
Expand Down
24 changes: 17 additions & 7 deletions utils/cliutils/commandsflags.go
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,7 @@ const (
ReleaseBundleDistribute = "release-bundle-distribute"
ReleaseBundleDeleteLocal = "release-bundle-delete-local"
ReleaseBundleDeleteRemote = "release-bundle-delete-remote"
ReleaseBundleExport = "release-bundle-export"

// Access Token Create commands keys
AccessTokenCreate = "access-token-create"
Expand Down Expand Up @@ -448,13 +449,14 @@ const (
deleteFromDist = "delete-from-dist"

// Common release-bundle-* v1&v2 flags
DistRules = "dist-rules"
site = "site"
city = "city"
countryCodes = "country-codes"
sync = "sync"
maxWaitMinutes = "max-wait-minutes"
CreateRepo = "create-repo"
DistRules = "dist-rules"
site = "site"
city = "city"
countryCodes = "country-codes"
sync = "sync"
maxWaitMinutes = "max-wait-minutes"
CreateRepo = "create-repo"
TargetDirectory = target + "-directory"
EyalDelarea marked this conversation as resolved.
Show resolved Hide resolved

// *** Xray Commands' flags ***
// Base flags
Expand Down Expand Up @@ -1715,6 +1717,10 @@ var flagsMap = map[string]cli.Flag{
Name: Reference,
Usage: "[Default: false] Generate a Reference Token (alias to Access Token) in addition to the full token (available from Artifactory 7.38.10)` `",
},
TargetDirectory: cli.StringFlag{
EyalDelarea marked this conversation as resolved.
Show resolved Hide resolved
Name: TargetDirectory,
Usage: "[Optional] Specify the destination PATH where the downloaded file will be saved. If not provided, the file will be saved in the current directory.` `",
},
}

var commandFlags = map[string][]string{
Expand Down Expand Up @@ -2019,6 +2025,10 @@ var commandFlags = map[string][]string{
platformUrl, user, password, accessToken, serverId, deleteQuiet, lcDryRun, DistRules, site, city, countryCodes,
lcSync, maxWaitMinutes, lcProject,
},
ReleaseBundleExport: {
platformUrl, user, password, accessToken, serverId, lcPathMappingTarget, lcPathMappingPattern, Project,
downloadMinSplit, downloadSplitCount,
},
// Mission Control's commands
McConfig: {
mcUrl, mcAccessToken, mcInteractive,
Expand Down
Loading
Loading