Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
45 commits
Select commit Hold shift + click to select a range
85df682
Introduce e2e tests for lifecycle anotate command.
rimapol May 4, 2025
c14f9a8
Merge remote-tracking branch 'origin/dev' into v2
jfrog-ecosystem Jun 12, 2025
96c55b8
Support npm operations using native npm client with .npmrc via --run-…
fluxxBot May 14, 2025
906ca73
Add test case for multiple image tags in build-docker-create (#2957)
agrasth May 14, 2025
62da26d
Update dependencies
rimapol Jun 30, 2025
fae6645
Introduce e2e tests for create release bundle with multiple sources
rimapol May 18, 2025
375c9bb
Introduce support for create release bundle from multiple sources def…
rimapol May 22, 2025
3374fd1
Bump ver from 2.75.1 to 2.76.0 (#2974)
EyalDelarea May 18, 2025
c8f7fef
Update go version to `v1.23.9` (#2975)
EyalDelarea May 18, 2025
7f216e4
Update dependencies
rimapol May 22, 2025
0e11a9e
Update dependencies
rimapol May 22, 2025
e30bfa0
Update dependencies
rimapol May 22, 2025
f766ec3
Update dependency
rimapol May 22, 2025
ee8bb94
Fix lynt errors
rimapol May 22, 2025
e9caff0
Fix lynt errors
rimapol May 22, 2025
b8cc350
Fix lynt errors
rimapol May 22, 2025
91a8ad0
Revert format changes
rimapol May 22, 2025
733e96f
Remove unused
rimapol May 22, 2025
64cb12a
Bump ver from 2.76.0 to 2.76.1 (#2986)
EyalDelarea May 28, 2025
6f93bbe
Add tests for twine (#2985)
reshmifrog May 29, 2025
5c35371
Feature/docker validate sha (#2971)
agrasth May 30, 2025
df444ec
Fix for mismatching cpu type (#2993)
bhanurp Jun 9, 2025
b2658f1
Update tests after change source flags names
rimapol Jun 12, 2025
f9a4976
Update tests
rimapol Jun 12, 2025
641f670
Update dependencies
rimapol Jun 12, 2025
9f2c44e
Bump ver from 2.76.1 to 2.77.0 (#3001)
EyalDelarea Jun 12, 2025
2908326
Fix CheckError issue
rimapol Jun 12, 2025
6897b52
Update dependencies
rimapol Jun 12, 2025
2dc1d71
Update dependencies
rimapol Jun 12, 2025
ea5dafb
Update dependencies
rimapol Jun 13, 2025
3173ae1
Fix lint
rimapol Jun 13, 2025
c708430
Code review changes and update dependencies
rimapol Jun 17, 2025
5d05d07
Temp
rimapol Jun 17, 2025
e7e5a1d
ExportRb is commented
rimapol Jun 17, 2025
1663683
Revert useless small
rimapol Jun 18, 2025
8aacddc
Added Jenkins File and github workflow action's yaml file (#3004)
naveenku-jfrog Jun 19, 2025
cb4f7ee
Update dependencies
rimapol Jun 23, 2025
60ce88d
Update dependencies
rimapol Jun 23, 2025
1e61f85
Feature/adding parameters in jenkins job (#3007)
naveenku-jfrog Jun 24, 2025
bc0b7e6
Update dependencies
rimapol Jun 24, 2025
2c2eb26
Update dependencies
rimapol Jun 30, 2025
44eba8f
Update dependencies
rimapol Jun 30, 2025
a8359c9
Resolve conflicts
rimapol Jun 30, 2025
029998d
Merge branch 'jfrog:v2' into feature/support-multiple-sources
rimapol Jun 30, 2025
a5eb3f4
Merge branch 'dev' into feature/support-multiple-sources
rimapol Jul 1, 2025
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
6 changes: 3 additions & 3 deletions buildtools/cli.go
Original file line number Diff line number Diff line change
Expand Up @@ -1098,7 +1098,7 @@ func terraformCmd(c *cli.Context) error {
case "publish", "p":
return terraformPublishCmd(configFilePath, filteredArgs, c)
default:
return errorutils.CheckErrorf("Terraform command:\"" + cmdName + "\" is not supported. " + cliutils.GetDocumentationMessage())
return errorutils.CheckError(errors.New("Terraform command:\"" + cmdName + "\" is not supported. " + cliutils.GetDocumentationMessage()))
}
}

Expand Down Expand Up @@ -1128,7 +1128,7 @@ func getProjectConfigPathOrThrow(projectType project.ProjectType, cmdName, confi
return
}
if !exists {
return "", errorutils.CheckErrorf(getMissingConfigErrMsg(cmdName, configCmdName))
return "", errorutils.CheckError(errors.New(getMissingConfigErrMsg(cmdName, configCmdName)))
}
return
}
Expand Down Expand Up @@ -1179,5 +1179,5 @@ func getTwineConfigPath() (configFilePath string, err error) {
return
}
}
return "", errorutils.CheckErrorf(getMissingConfigErrMsg("twine", "pip-config OR pipenv-config"))
return "", errorutils.CheckError(errors.New(getMissingConfigErrMsg("twine", "pip-config OR pipenv-config")))
}
3 changes: 2 additions & 1 deletion config/cli.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package config

import (
"errors"
"fmt"
"github.com/jfrog/jfrog-cli-core/v2/general/token"
"os"
Expand Down Expand Up @@ -300,7 +301,7 @@ func validatePathsExist(paths ...string) error {
return err
}
if !exists {
return errorutils.CheckErrorf("file does not exit at " + path)
return errorutils.CheckError(errors.New("file does not exit at " + path))
}
}
}
Expand Down
8 changes: 4 additions & 4 deletions general/ai/cli.go
Original file line number Diff line number Diff line change
Expand Up @@ -175,12 +175,12 @@ func sendRestAPI(apiType ApiType, content interface{}) (response string, err err
if err = errorutils.CheckResponseStatus(resp, http.StatusOK); err != nil {
switch resp.StatusCode {
case http.StatusInternalServerError:
err = errorutils.CheckErrorf("JFrog CLI-AI model endpoint is not available. Please try again later.")
err = errorutils.CheckError(errors.New("JFrog CLI-AI model endpoint is not available. Please try again later"))
case http.StatusNotAcceptable:
err = errorutils.CheckErrorf("The system is currently handling multiple requests from other users\n" +
"Please try submitting your question again in a few minutes. Thank you for your patience!")
err = errorutils.CheckError(errors.New("The system is currently handling multiple requests from other users\n" +
"Please try submitting your question again in a few minutes. Thank you for your patience!"))
default:
err = errorutils.CheckErrorf("JFrog CLI-AI server is not available. Please check your network or try again later:\n" + err.Error())
err = errorutils.CheckError(errors.New("JFrog CLI-AI server is not available. Please check your network or try again later:\n" + err.Error()))
}
return
}
Expand Down
212 changes: 205 additions & 7 deletions lifecycle_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@ import (
"os"
"path"
"path/filepath"
"strconv"
"strings"
"testing"
"time"
)
Expand All @@ -45,6 +47,7 @@ const (
artifactoryLifecycleSetTagMinVersion = "7.111.0"
rbManifestName = "release-bundle.json.evd"
releaseBundlesV2 = "release-bundles-v2"
minMultiSourcesArtifactoryVersion = "7.114.0"
)

var (
Expand Down Expand Up @@ -94,6 +97,88 @@ func compareRbArtifacts(t *testing.T, actual services.ReleaseBundleSpecResponse,
assert.ElementsMatch(t, actualArtifactsPaths, expected)
}

func TestReleaseBundleCreationFromMultiBuildsUsingCommandFlag(t *testing.T) {

cleanCallback := initLifecycleTest(t, minMultiSourcesArtifactoryVersion)
defer cleanCallback()
lcManager := getLcServiceManager(t)

deleteBuilds := uploadBuilds(t)
defer deleteBuilds()

createRbFromMultiSourcesUsingCommandFlags(t, lcManager, createBuildsSource(), "", tests.LcRbName1, number1, "default", true)
defer deleteReleaseBundle(t, lcManager, tests.LcRbName1, number1)
assertStatusCompleted(t, lcManager, tests.LcRbName1, number1, "")
}

func TestReleaseBundleCreationFromMultiBundlesUsingCommandFlag(t *testing.T) {

cleanCallback := initLifecycleTest(t, minMultiSourcesArtifactoryVersion)
defer cleanCallback()
lcManager := getLcServiceManager(t)

deleteBuilds := uploadBuilds(t)
defer deleteBuilds()

createRbFromSpec(t, tests.LifecycleBuilds12, tests.LcRbName1, number1, true, true)
defer deleteReleaseBundle(t, lcManager, tests.LcRbName1, number1)

createRbFromSpec(t, tests.LifecycleBuilds3, tests.LcRbName2, number2, true, true)
defer deleteReleaseBundle(t, lcManager, tests.LcRbName2, number2)

createRbFromMultiSourcesUsingCommandFlags(t, lcManager, "", createReleaseBundlesSource(), tests.LcRbName3, number3, "default", true)
defer deleteReleaseBundle(t, lcManager, tests.LcRbName3, number3)
assertStatusCompleted(t, lcManager, tests.LcRbName3, number3, "")
}

func TestReleaseBundleCreationFromMultipleBuildsAndBundlesUsingCommandFlags(t *testing.T) {

cleanCallback := initLifecycleTest(t, minMultiSourcesArtifactoryVersion)
defer cleanCallback()
lcManager := getLcServiceManager(t)

deleteBuilds := uploadBuilds(t)
defer deleteBuilds()

createRbFromSpec(t, tests.LifecycleBuilds12, tests.LcRbName1, number1, true, true)
defer deleteReleaseBundle(t, lcManager, tests.LcRbName1, number1)

createRbFromSpec(t, tests.LifecycleBuilds3, tests.LcRbName2, number2, true, true)
defer deleteReleaseBundle(t, lcManager, tests.LcRbName2, number2)

createRbFromMultiSourcesUsingCommandFlags(t, lcManager, createBuildsSource(), createReleaseBundlesSource(), tests.LcRbName3, number3, "default", true)
defer deleteReleaseBundle(t, lcManager, tests.LcRbName3, number3)
assertStatusCompleted(t, lcManager, tests.LcRbName3, number3, "")
}

func TestReleaseBundleCreationFromMultipleSourcesUsingSpec(t *testing.T) {

cleanCallback := initLifecycleTest(t, minMultiSourcesArtifactoryVersion)
defer cleanCallback()
lcManager := getLcServiceManager(t)

deleteBuilds := uploadBuilds(t)
defer deleteBuilds()

createRbFromSpec(t, tests.LifecycleBuilds12, tests.LcRbName1, number1, true, true)
defer deleteReleaseBundle(t, lcManager, tests.LcRbName1, number1)

createRbFromSpec(t, tests.LifecycleBuilds3, tests.LcRbName2, number2, true, true)
defer deleteReleaseBundle(t, lcManager, tests.LcRbName2, number2)

createRbFromSpec(t, tests.LifecycleMultipleSources, tests.LcRbName3, number3, true, true)
defer deleteReleaseBundle(t, lcManager, tests.LcRbName3, number3)
assertStatusCompleted(t, lcManager, tests.LcRbName3, number3, "")
}

func createBuildsSource() string {
return fmt.Sprintf("name=%s, id=%s, include-deps=%s; name=%s, id=%s", tests.LcBuildName1, number1, "true", tests.LcBuildName2, number2)
}

func createReleaseBundlesSource() string {
return fmt.Sprintf("name=%s, version=%s; name=%s, version=%s", tests.LcRbName1, number1, tests.LcRbName2, number2)
}

func TestReleaseBundleCreationFromAql(t *testing.T) {
testReleaseBundleCreation(t, tests.UploadDevSpecA, tests.LifecycleAql, tests.GetExpectedLifecycleCreationByAql(), false)
}
Expand Down Expand Up @@ -157,12 +242,12 @@ func TestLifecycleFullFlow(t *testing.T) {
assertExpectedArtifacts(t, tests.SearchAllProdRepo2, []string{})

// Export release lifecycle bundle archive

tempDir, cleanUp := coreTests.CreateTempDirWithCallbackAndAssert(t)
// TODO Temporarily disabling till distribution on testing suite is stable.
/*tempDir, cleanUp := coreTests.CreateTempDirWithCallbackAndAssert(t)
defer cleanUp()

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

// TODO Temporarily disabling till distribution on testing suite is stable.
/*
Expand Down Expand Up @@ -202,9 +287,9 @@ func TestPromoteReleaseBundleWithPromotionTypeFlag(t *testing.T) {
assertStatusCompleted(t, lcManager, tests.LcRbName1, number1, "")
}

func deleteExportedReleaseBundle(t *testing.T, rbName string) {
/*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)
Expand Down Expand Up @@ -282,6 +367,119 @@ func TestCreateBundleWithoutSpecAndWithProject(t *testing.T) {
defer deleteReleaseBundleWithProject(t, lcManager, tests.LcRbName1, number1, tests.ProjectKey)
}

func createRbFromMultiSourcesUsingCommandFlags(t *testing.T, lcManager *lifecycle.LifecycleServicesManager, buildsSourcesOption, bundlesSourcesOption,
rbName, rbVersion, project string, sync bool) {
var sources []services.RbSource
sources = buildMultiSources(sources, buildsSourcesOption, bundlesSourcesOption, project)

rbDetails := services.ReleaseBundleDetails{
ReleaseBundleName: rbName,
ReleaseBundleVersion: rbVersion,
}
queryParams := services.CommonOptionalQueryParams{
Async: !sync,
ProjectKey: project,
}

_, err := lcManager.CreateReleaseBundlesFromMultipleSources(rbDetails, queryParams, gpgKeyPairName, sources)
assert.NoError(t, err)
}

func buildMultiSources(sources []services.RbSource, buildsSourcesStr, bundlesSourcesStr, projectKey string) []services.RbSource {
// Process Builds
if buildsSourcesStr != "" {
sources = buildMultiBuildSources(sources, buildsSourcesStr)
}

// Process Release Bundles
if bundlesSourcesStr != "" {
sources = buildMultiBundleSources(sources, bundlesSourcesStr, projectKey)
}

return sources
}

func buildMultiBundleSources(sources []services.RbSource, bundlesSourcesStr, projectKey string) []services.RbSource {
var releaseBundleSources []services.ReleaseBundleSource
bundleEntries := strings.Split(bundlesSourcesStr, ";")
for _, entry := range bundleEntries {
entry = strings.TrimSpace(entry)
if entry == "" {
continue
}
// Assuming the format "name=xxx, version=xxx"
components := strings.Split(entry, ",")
if len(components) != 2 {
continue
}
name := strings.TrimSpace(strings.Split(components[0], "=")[1])
version := strings.TrimSpace(strings.Split(components[1], "=")[1])

releaseBundleSources = append(releaseBundleSources, services.ReleaseBundleSource{
ProjectKey: projectKey,
ReleaseBundleName: name,
ReleaseBundleVersion: version,
})
}
if len(releaseBundleSources) > 0 {
sources = append(sources, services.RbSource{
SourceType: "release_bundles",
ReleaseBundles: releaseBundleSources,
})
}
return sources
}

func buildMultiBuildSources(sources []services.RbSource, sourcesStr string) []services.RbSource {
var buildSources []services.BuildSource
buildEntries := strings.Split(sourcesStr, ";")
for _, entry := range buildEntries {
entry = strings.TrimSpace(entry)
if entry == "" {
continue
}
// Assuming the format "name=xxx, number=xxx, include-dep=true"
components := strings.Split(entry, ",")
if len(components) < 2 {
continue
}

name := strings.TrimSpace(strings.Split(components[0], "=")[1])
number := strings.TrimSpace(strings.Split(components[1], "=")[1])

includeDepStr := "false"
if len(components) >= 3 {
parts := strings.Split(components[2], "=")
if len(parts) > 1 {
includeDepStr = strings.TrimSpace(parts[1])
}
}

includeDep, _ := strconv.ParseBool(includeDepStr)

buildSources = append(buildSources, services.BuildSource{
BuildRepository: getBuildInfoRepositoryByProject("default"),
BuildName: name,
BuildNumber: number,
IncludeDependencies: includeDep,
})
}
if len(buildSources) > 0 {
sources = append(sources, services.RbSource{
SourceType: "builds",
Builds: buildSources,
})
}
return sources
}

func getBuildInfoRepositoryByProject(projectKey string) string {
buildRepo := "artifactory"
if projectKey != "" && projectKey != "default" {
buildRepo = projectKey
}
return buildRepo + "-build-info"
}
func createRbWithFlags(t *testing.T, specFilePath, sourceOption, buildName, buildNumber, rbName, rbVersion, project string,
sync, withoutSigningKey bool) {
argsAndOptions := []string{
Expand Down Expand Up @@ -314,12 +512,12 @@ func createRbWithFlags(t *testing.T, specFilePath, sourceOption, buildName, buil
assert.NoError(t, lcCli.Exec(argsAndOptions...))
}

func exportRb(t *testing.T, rbName, rbVersion, targetPath string) {
/*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) {
Expand Down
2 changes: 1 addition & 1 deletion main.go
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,7 @@ func execMain() error {
cli.CommandHelpTemplate = commandHelpTemplate
cli.AppHelpTemplate = getAppHelpTemplate()
app.CommandNotFound = func(c *cli.Context, command string) {
_, err = fmt.Fprintf(c.App.Writer, "'"+c.App.Name+" "+command+"' is not a jf command. See --help\n")
_, err = fmt.Fprintf(c.App.Writer, "%s", `'`+c.App.Name+" "+command+"' is not a jf command. See --help\n")
if err != nil {
clientlog.Debug(err)
os.Exit(1)
Expand Down
3 changes: 2 additions & 1 deletion plugins/commands/uninstall.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package commands

import (
"errors"
"github.com/jfrog/jfrog-cli-core/v2/utils/coreutils"
"github.com/jfrog/jfrog-cli-core/v2/utils/plugins"
"github.com/jfrog/jfrog-cli/utils/cliutils"
Expand Down Expand Up @@ -50,5 +51,5 @@ func runUninstallCmd(requestedPlugin string) error {
}

func generateNoPluginFoundError(pluginName string) error {
return errorutils.CheckErrorf("plugin '" + pluginName + "' could not be found")
return errorutils.CheckError(errors.New("plugin '" + pluginName + "' could not be found"))
}
7 changes: 4 additions & 3 deletions plugins/commands/utils/utils.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package utils

import (
"errors"
"github.com/jfrog/jfrog-cli-core/v2/utils/config"
"github.com/jfrog/jfrog-client-go/utils/errorutils"
"github.com/jfrog/jfrog-client-go/utils/io/httputils"
Expand Down Expand Up @@ -119,11 +120,11 @@ func AssertPluginVersion(versionCmdOut string, expectedPluginVersion string) err
// Get the actual version which is after the last space. (expected output to -v for example: "plugin-name version v1.0.0")
split := strings.Split(strings.TrimSpace(versionCmdOut), " ")
if len(split) != 3 {
return errorutils.CheckErrorf("failed verifying plugin version. Unexpected plugin output for version command: '" + versionCmdOut + "'")
return errorutils.CheckError(errors.New("failed verifying plugin version. Unexpected plugin output for version command: '" + versionCmdOut + "'"))
}
if split[2] != expectedPluginVersion {
return errorutils.CheckErrorf("provided version does not match the plugin's actual version. " +
"Provided: '" + expectedPluginVersion + "', Actual: '" + split[2] + "'")
return errorutils.CheckError(errors.New("provided version does not match the plugin's actual version. " +
"Provided: '" + expectedPluginVersion + "', Actual: '" + split[2] + "'"))
}
return nil
}
Expand Down
Loading
Loading