From 4666a58d84ba6cff6158e43f596a24d5a876bbcf Mon Sep 17 00:00:00 2001 From: Reshmi Date: Wed, 25 Feb 2026 15:21:15 +0530 Subject: [PATCH 1/2] add e2e test for conan --- conan_test.go | 366 ++++++++++++++++++++++++++++++++++++++++++++++++++ go.mod | 2 +- go.sum | 4 +- 3 files changed, 369 insertions(+), 3 deletions(-) diff --git a/conan_test.go b/conan_test.go index fc8bee20a..ba2cbeb49 100644 --- a/conan_test.go +++ b/conan_test.go @@ -1,6 +1,8 @@ package main import ( + "crypto/sha256" + "encoding/hex" "os" "os/exec" "path/filepath" @@ -10,6 +12,7 @@ import ( buildinfo "github.com/jfrog/build-info-go/entities" biutils "github.com/jfrog/build-info-go/utils" "github.com/jfrog/jfrog-cli-core/v2/artifactory/utils" + coreBuild "github.com/jfrog/jfrog-cli-core/v2/common/build" coretests "github.com/jfrog/jfrog-cli-core/v2/utils/tests" "github.com/jfrog/jfrog-cli/inttestutils" "github.com/jfrog/jfrog-cli/utils/tests" @@ -469,6 +472,369 @@ func cleanupConanRemote() { _ = exec.Command("conan", "remote", "remove", tests.ConanLocalRepo).Run() } +// TestConanCreateWithProjectKey tests that 'jf conan create --project=' stores build info +// in the correct local build dir (SHA includes the project key). +func TestConanCreateWithProjectKey(t *testing.T) { + initConanTest(t) + buildName := tests.ConanBuildName + "-project" + buildNumber := "1" + projectKey := "testprj" + + projectPath := createConanProject(t, "conan-create-project-test") + wd, err := os.Getwd() + require.NoError(t, err) + chdirCallback := clientTestUtils.ChangeDirWithCallback(t, wd, projectPath) + defer chdirCallback() + + configureConanRemote(t) + defer cleanupConanRemote() + + jfrogCli := coretests.NewJfrogCli(execMain, "jfrog", "") + createArgs := []string{ + "conan", "create", ".", + "--build=missing", + "--build-name=" + buildName, + "--build-number=" + buildNumber, + "--project=" + projectKey, + } + require.NoError(t, jfrogCli.Exec(createArgs...)) + + // Verify local build info was stored under the project-key-aware directory + builds, err := coreBuild.GetGeneratedBuildsInfo(buildName, buildNumber, projectKey) + require.NoError(t, err) + require.Len(t, builds, 1, "Expected 1 build info file stored with project key '%s'", projectKey) + assert.Equal(t, buildName, builds[0].Name) + assert.Equal(t, buildNumber, builds[0].Number) + + // Verify that the build is NOT found under the empty-project directory + buildsNoProject, err := coreBuild.GetGeneratedBuildsInfo(buildName, buildNumber, "") + assert.NoError(t, err) + assert.Empty(t, buildsNoProject, "Build info should NOT exist under empty project key directory") + + // Cleanup local build dir + assert.NoError(t, coreBuild.RemoveBuildDir(buildName, buildNumber, projectKey)) +} + +// TestConanCreateWithoutProjectKey verifies no regression: 'jf conan create' without --project +// still stores build info in the default (empty project) directory. +func TestConanCreateWithoutProjectKey(t *testing.T) { + initConanTest(t) + buildName := tests.ConanBuildName + "-noproject" + buildNumber := "1" + + projectPath := createConanProject(t, "conan-create-noproject-test") + wd, err := os.Getwd() + require.NoError(t, err) + chdirCallback := clientTestUtils.ChangeDirWithCallback(t, wd, projectPath) + defer chdirCallback() + + configureConanRemote(t) + defer cleanupConanRemote() + + jfrogCli := coretests.NewJfrogCli(execMain, "jfrog", "") + createArgs := []string{ + "conan", "create", ".", + "--build=missing", + "--build-name=" + buildName, + "--build-number=" + buildNumber, + } + require.NoError(t, jfrogCli.Exec(createArgs...)) + + // Verify local build info was stored under the empty project directory + builds, err := coreBuild.GetGeneratedBuildsInfo(buildName, buildNumber, "") + require.NoError(t, err) + require.Len(t, builds, 1, "Expected 1 build info file stored without project key") + assert.Equal(t, buildName, builds[0].Name) + + // Cleanup local build dir + assert.NoError(t, coreBuild.RemoveBuildDir(buildName, buildNumber, "")) +} + +// TestConanInstallWithProjectKey tests that 'jf conan install --project=' stores +// build info in the project-key-aware directory. +func TestConanInstallWithProjectKey(t *testing.T) { + initConanTest(t) + buildName := tests.ConanBuildName + "-install-project" + buildNumber := "1" + projectKey := "testprj" + + projectPath := createConanProject(t, "conan-install-project-test") + wd, err := os.Getwd() + require.NoError(t, err) + chdirCallback := clientTestUtils.ChangeDirWithCallback(t, wd, projectPath) + defer chdirCallback() + + configureConanRemote(t) + defer cleanupConanRemote() + + jfrogCli := coretests.NewJfrogCli(execMain, "jfrog", "") + installArgs := []string{ + "conan", "install", ".", + "--build=missing", + "-r", tests.ConanVirtualRepo, + "--build-name=" + buildName, + "--build-number=" + buildNumber, + "--project=" + projectKey, + } + require.NoError(t, jfrogCli.Exec(installArgs...)) + + // Verify local build info was stored with project key + builds, err := coreBuild.GetGeneratedBuildsInfo(buildName, buildNumber, projectKey) + require.NoError(t, err) + require.Len(t, builds, 1, "Expected 1 build info file stored with project key '%s'", projectKey) + + // Verify NOT stored under empty-project dir + buildsNoProject, err := coreBuild.GetGeneratedBuildsInfo(buildName, buildNumber, "") + assert.NoError(t, err) + assert.Empty(t, buildsNoProject, "Build info should NOT exist under empty project key directory") + + // Cleanup + assert.NoError(t, coreBuild.RemoveBuildDir(buildName, buildNumber, projectKey)) +} + +// TestConanUploadWithProjectKey tests that 'jf conan upload --project=' stores +// build info in the project-key-aware directory. +func TestConanUploadWithProjectKey(t *testing.T) { + initConanTest(t) + buildName := tests.ConanBuildName + "-upload-project" + buildNumber := "1" + projectKey := "testprj" + + projectPath := createConanProject(t, "conan-upload-project-test") + wd, err := os.Getwd() + require.NoError(t, err) + chdirCallback := clientTestUtils.ChangeDirWithCallback(t, wd, projectPath) + defer chdirCallback() + + configureConanRemote(t) + defer cleanupConanRemote() + + jfrogCli := coretests.NewJfrogCli(execMain, "jfrog", "") + + // First create the package so it can be uploaded + createArgs := []string{ + "conan", "create", ".", + "--build=missing", + "--build-name=" + buildName, + "--build-number=" + buildNumber, + "--project=" + projectKey, + } + require.NoError(t, jfrogCli.Exec(createArgs...)) + + // Upload with --project + uploadArgs := []string{ + "conan", "upload", "cli-test-package/*", + "-r", tests.ConanLocalRepo, + "--confirm", + "--build-name=" + buildName, + "--build-number=" + buildNumber, + "--project=" + projectKey, + } + require.NoError(t, jfrogCli.Exec(uploadArgs...)) + + // Verify local build info was stored with project key + builds, err := coreBuild.GetGeneratedBuildsInfo(buildName, buildNumber, projectKey) + require.NoError(t, err) + require.NotEmpty(t, builds, "Expected build info files stored with project key '%s'", projectKey) + + // Cleanup + assert.NoError(t, coreBuild.RemoveBuildDir(buildName, buildNumber, projectKey)) +} + +// TestConanBuildPublishWithProjectKey verifies that build info stored with --project +// is isolated from builds without --project. +func TestConanBuildPublishWithProjectKey(t *testing.T) { + initConanTest(t) + buildName := tests.ConanBuildName + "-bp-project" + buildNumber := "1" + projectKey := "testprj" + + projectPath := createConanProject(t, "conan-bp-project-test") + wd, err := os.Getwd() + require.NoError(t, err) + chdirCallback := clientTestUtils.ChangeDirWithCallback(t, wd, projectPath) + defer chdirCallback() + + configureConanRemote(t) + defer cleanupConanRemote() + + jfrogCli := coretests.NewJfrogCli(execMain, "jfrog", "") + + // Create with --project so build info is stored with project key in the dir hash + createArgs := []string{ + "conan", "create", ".", + "--build=missing", + "--build-name=" + buildName, + "--build-number=" + buildNumber, + "--project=" + projectKey, + } + require.NoError(t, jfrogCli.Exec(createArgs...)) + + // Verify the project-key-aware build dir has build info files + buildsInfo, err := coreBuild.GetGeneratedBuildsInfo(buildName, buildNumber, projectKey) + require.NoError(t, err) + assert.NotEmpty(t, buildsInfo, "Build info should exist in the project-key-aware build dir") + + // Verify the build dir WITHOUT project key does NOT have build info files + buildsInfoNoProject, err := coreBuild.GetGeneratedBuildsInfo(buildName, buildNumber, "") + require.NoError(t, err) + assert.Empty(t, buildsInfoNoProject, "Build info should NOT exist in the non-project build dir") + + // Cleanup + assert.NoError(t, coreBuild.RemoveBuildDir(buildName, buildNumber, projectKey)) + assert.NoError(t, coreBuild.RemoveBuildDir(buildName, buildNumber, "")) +} + +// TestConanProjectKeyBuildDirHash verifies the SHA256 directory name computation. +// With --project=vsm the local build dir should be SHA256("buildName_buildNumber_vsm"), +func TestConanProjectKeyBuildDirHash(t *testing.T) { + initConanTest(t) + buildName := tests.ConanBuildName + "-hash" + buildNumber := "1" + projectKey := "vsm" + + projectPath := createConanProject(t, "conan-hash-test") + wd, err := os.Getwd() + require.NoError(t, err) + chdirCallback := clientTestUtils.ChangeDirWithCallback(t, wd, projectPath) + defer chdirCallback() + + configureConanRemote(t) + defer cleanupConanRemote() + + jfrogCli := coretests.NewJfrogCli(execMain, "jfrog", "") + createArgs := []string{ + "conan", "create", ".", + "--build=missing", + "--build-name=" + buildName, + "--build-number=" + buildNumber, + "--project=" + projectKey, + } + require.NoError(t, jfrogCli.Exec(createArgs...)) + + // Compute expected directory names + expectedWithProject := sha256.Sum256([]byte(buildName + "_" + buildNumber + "_" + projectKey)) + expectedDirWithProject := hex.EncodeToString(expectedWithProject[:]) + buggyNoProject := sha256.Sum256([]byte(buildName + "_" + buildNumber + "_")) + buggyDirNoProject := hex.EncodeToString(buggyNoProject[:]) + + // Get the actual build dir path (should include project key) + buildDir, err := coreBuild.GetBuildDir(buildName, buildNumber, projectKey) + require.NoError(t, err) + actualDirName := filepath.Base(buildDir) + + assert.Equal(t, expectedDirWithProject, actualDirName, + "Build dir should be SHA256 of '%s_%s_%s'", buildName, buildNumber, projectKey) + assert.NotEqual(t, buggyDirNoProject, actualDirName, + "Build dir must NOT be SHA256 of '%s_%s_' (old bug)", buildName, buildNumber) + + // Verify build info file exists in that directory + builds, err := coreBuild.GetGeneratedBuildsInfo(buildName, buildNumber, projectKey) + require.NoError(t, err) + require.Len(t, builds, 1, "Expected build info to exist in the project-key-aware directory") + + assert.NoError(t, coreBuild.RemoveBuildDir(buildName, buildNumber, projectKey)) +} + +// TestConanMultipleProjectKeys tests that builds with different project keys +// are stored in separate directories and don't interfere with each other. +func TestConanMultipleProjectKeys(t *testing.T) { + initConanTest(t) + buildName := tests.ConanBuildName + "-multiproj" + buildNumber := "1" + projectKeys := []string{"proj1", "proj2", ""} + + projectPath := createConanProject(t, "conan-multi-project-test") + wd, err := os.Getwd() + require.NoError(t, err) + chdirCallback := clientTestUtils.ChangeDirWithCallback(t, wd, projectPath) + defer chdirCallback() + + configureConanRemote(t) + defer cleanupConanRemote() + + jfrogCli := coretests.NewJfrogCli(execMain, "jfrog", "") + + // Run create with different project keys + for _, pk := range projectKeys { + args := []string{ + "conan", "create", ".", + "--build=missing", + "--build-name=" + buildName, + "--build-number=" + buildNumber, + } + if pk != "" { + args = append(args, "--project="+pk) + } + require.NoError(t, jfrogCli.Exec(args...), "Failed for project key '%s'", pk) + } + + // Verify each project key has its own build info, isolated from the others + for _, pk := range projectKeys { + builds, err := coreBuild.GetGeneratedBuildsInfo(buildName, buildNumber, pk) + require.NoError(t, err) + require.Len(t, builds, 1, "Expected exactly 1 build info for project key '%s'", pk) + assert.Equal(t, buildName, builds[0].Name) + } + + // Verify all build dirs are distinct (different SHA) + dirs := make(map[string]string) + for _, pk := range projectKeys { + buildDir, err := coreBuild.GetBuildDir(buildName, buildNumber, pk) + require.NoError(t, err) + dirName := filepath.Base(buildDir) + existingPk, exists := dirs[dirName] + assert.False(t, exists, "Project keys '%s' and '%s' produced the same build dir %s", existingPk, pk, dirName) + dirs[dirName] = pk + } + + // Cleanup all + for _, pk := range projectKeys { + assert.NoError(t, coreBuild.RemoveBuildDir(buildName, buildNumber, pk)) + } +} + +// TestConanProjectKeySpaceSeparated tests that --project +// works the same as --project=. +func TestConanProjectKeySpaceSeparated(t *testing.T) { + initConanTest(t) + buildName := tests.ConanBuildName + "-space-project" + buildNumber := "1" + projectKey := "testprj" + + projectPath := createConanProject(t, "conan-space-project-test") + wd, err := os.Getwd() + require.NoError(t, err) + chdirCallback := clientTestUtils.ChangeDirWithCallback(t, wd, projectPath) + defer chdirCallback() + + configureConanRemote(t) + defer cleanupConanRemote() + + jfrogCli := coretests.NewJfrogCli(execMain, "jfrog", "") + // Note: --project testprj (space-separated, not --project=testprj) + createArgs := []string{ + "conan", "create", ".", + "--build=missing", + "--build-name=" + buildName, + "--build-number=" + buildNumber, + "--project", projectKey, + } + require.NoError(t, jfrogCli.Exec(createArgs...)) + + // Verify local build info was stored with project key + builds, err := coreBuild.GetGeneratedBuildsInfo(buildName, buildNumber, projectKey) + require.NoError(t, err) + require.Len(t, builds, 1, "Expected 1 build info file stored with space-separated --project") + + // Verify NOT stored under empty-project dir + buildsNoProject, err := coreBuild.GetGeneratedBuildsInfo(buildName, buildNumber, "") + assert.NoError(t, err) + assert.Empty(t, buildsNoProject, "Build info should NOT exist under empty project key directory") + + assert.NoError(t, coreBuild.RemoveBuildDir(buildName, buildNumber, projectKey)) +} + // TestConanBuildPublishWithCIVcsProps tests that CI VCS properties are set on Conan artifacts // when running build-publish in a CI environment (GitHub Actions). // Conan packages are published via Conan client; build-publish retrieves artifact paths diff --git a/go.mod b/go.mod index 9b3cc1f42..fc10a9045 100644 --- a/go.mod +++ b/go.mod @@ -256,7 +256,7 @@ replace github.com/gfleury/go-bitbucket-v1 => github.com/gfleury/go-bitbucket-v1 replace github.com/ktrysmt/go-bitbucket => github.com/ktrysmt/go-bitbucket v0.9.80 -//replace github.com/jfrog/jfrog-cli-core/v2 => ../jfrog-cli-core +replace github.com/jfrog/jfrog-cli-artifactory => github.com/reshmifrog/jfrog-cli-artifactory v0.0.0-20260224043243-64a372e78120 // replace github.com/jfrog/jfrog-cli-artifactory => github.com/fluxxBot/jfrog-cli-artifactory v0.0.0-20260130044429-464a5025d08a diff --git a/go.sum b/go.sum index c3bfa5ef5..8d2be218a 100644 --- a/go.sum +++ b/go.sum @@ -417,8 +417,6 @@ 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-application v1.0.2-0.20260216085810-1ade6c26b3df h1:raSyae8/h1y8HtzFLf7vZZj91fP/qD94AX+biwBJiqs= github.com/jfrog/jfrog-cli-application v1.0.2-0.20260216085810-1ade6c26b3df/go.mod h1:xum2HquWO5uExa/A7MQs3TgJJVEeoqTR+6Z4mfBr1Xw= -github.com/jfrog/jfrog-cli-artifactory v0.8.1-0.20260218070105-39c72c2c8214 h1:XFWrW8nmKheIs3jdiphozbagBXEgybafcb0eFatkKQ4= -github.com/jfrog/jfrog-cli-artifactory v0.8.1-0.20260218070105-39c72c2c8214/go.mod h1:qEUp3kyKkocqvf7xErppgAtkmudZR1TMaQUvDTGYCUI= github.com/jfrog/jfrog-cli-core/v2 v2.60.1-0.20260218080258-3bf55ed18973 h1:fOlWUGkCuujnIcE3166gpTdvicwv1wAZhLrfbm+f6rY= github.com/jfrog/jfrog-cli-core/v2 v2.60.1-0.20260218080258-3bf55ed18973/go.mod h1:GDveG1xAoiM12JlSx8RE0OcJ6Ov+xcmpmGv84we3pMA= github.com/jfrog/jfrog-cli-evidence v0.8.3-0.20260202100913-d9ee9476845a h1:lTOAhUjKcOmM/0Kbj4V+I/VHPlW7YNAhIEVpGnCM5mI= @@ -572,6 +570,8 @@ github.com/redis/go-redis/extra/redisotel/v9 v9.0.5 h1:EfpWLLCyXw8PSM2/XNJLjI3Pb github.com/redis/go-redis/extra/redisotel/v9 v9.0.5/go.mod h1:WZjPDy7VNzn77AAfnAfVjZNvfJTYfPetfZk5yoSTLaQ= github.com/redis/go-redis/v9 v9.17.2 h1:P2EGsA4qVIM3Pp+aPocCJ7DguDHhqrXNhVcEp4ViluI= github.com/redis/go-redis/v9 v9.17.2/go.mod h1:u410H11HMLoB+TP67dz8rL9s6QW2j76l0//kSOd3370= +github.com/reshmifrog/jfrog-cli-artifactory v0.0.0-20260224043243-64a372e78120 h1:yKzpFLB5k9QMhyIgDovYYKVk+RER6+SU8PAlpOpUvis= +github.com/reshmifrog/jfrog-cli-artifactory v0.0.0-20260224043243-64a372e78120/go.mod h1:qEUp3kyKkocqvf7xErppgAtkmudZR1TMaQUvDTGYCUI= github.com/rivo/uniseg v0.4.7 h1:WUdvkW8uEhrYfLC4ZzdpI2ztxP1I582+49Oc5Mq64VQ= github.com/rivo/uniseg v0.4.7/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88= github.com/robfig/cron/v3 v3.0.1 h1:WdRxkvbJztn8LMz/QEvLN5sBU+xKpSqwwUO1Pjr4qDs= From 93f028f652332ec834845aa8f736f9abcf7ec4d3 Mon Sep 17 00:00:00 2001 From: Reshmi Date: Tue, 3 Mar 2026 10:58:17 +0530 Subject: [PATCH 2/2] remove replace statement --- go.mod | 4 ++-- go.sum | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/go.mod b/go.mod index 2233bc071..51bddf168 100644 --- a/go.mod +++ b/go.mod @@ -19,7 +19,7 @@ require ( github.com/jfrog/build-info-go v1.13.1-0.20260216093441-40a4dc563294 github.com/jfrog/gofrog v1.7.6 github.com/jfrog/jfrog-cli-application v1.0.2-0.20260216085810-1ade6c26b3df - github.com/jfrog/jfrog-cli-artifactory v0.8.1-0.20260227101327-7478579b5f25 + github.com/jfrog/jfrog-cli-artifactory v0.8.1-0.20260303052518-917c005de223 github.com/jfrog/jfrog-cli-core/v2 v2.60.1-0.20260218080258-3bf55ed18973 github.com/jfrog/jfrog-cli-evidence v0.8.3-0.20260202100913-d9ee9476845a github.com/jfrog/jfrog-cli-platform-services v1.10.1-0.20260213131956-d1d39bf3a042 @@ -256,7 +256,7 @@ replace github.com/gfleury/go-bitbucket-v1 => github.com/gfleury/go-bitbucket-v1 replace github.com/ktrysmt/go-bitbucket => github.com/ktrysmt/go-bitbucket v0.9.80 -replace github.com/jfrog/jfrog-cli-artifactory => github.com/reshmifrog/jfrog-cli-artifactory v0.0.0-20260302170823-db801936b182 +// replace github.com/jfrog/jfrog-cli-artifactory => github.com/reshmifrog/jfrog-cli-artifactory v0.0.0-20260302170823-db801936b182 //replace github.com/jfrog/jfrog-cli-artifactory => github.com/naveenku-jfrog/jfrog-cli-artifactory v0.0.0-20260226133041-8d510cc4e5f6 diff --git a/go.sum b/go.sum index f3220d3da..76385b282 100644 --- a/go.sum +++ b/go.sum @@ -417,6 +417,8 @@ 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-application v1.0.2-0.20260216085810-1ade6c26b3df h1:raSyae8/h1y8HtzFLf7vZZj91fP/qD94AX+biwBJiqs= github.com/jfrog/jfrog-cli-application v1.0.2-0.20260216085810-1ade6c26b3df/go.mod h1:xum2HquWO5uExa/A7MQs3TgJJVEeoqTR+6Z4mfBr1Xw= +github.com/jfrog/jfrog-cli-artifactory v0.8.1-0.20260303052518-917c005de223 h1:amcFRt9xKmWZBsoT++amBoGrHiF28lTbWqr5yxHz+dI= +github.com/jfrog/jfrog-cli-artifactory v0.8.1-0.20260303052518-917c005de223/go.mod h1:P9ZywyTQzp+WsNmeb4IiMQOdVb++eQUD5oXd18LRVj8= github.com/jfrog/jfrog-cli-core/v2 v2.60.1-0.20260218080258-3bf55ed18973 h1:fOlWUGkCuujnIcE3166gpTdvicwv1wAZhLrfbm+f6rY= github.com/jfrog/jfrog-cli-core/v2 v2.60.1-0.20260218080258-3bf55ed18973/go.mod h1:GDveG1xAoiM12JlSx8RE0OcJ6Ov+xcmpmGv84we3pMA= github.com/jfrog/jfrog-cli-evidence v0.8.3-0.20260202100913-d9ee9476845a h1:lTOAhUjKcOmM/0Kbj4V+I/VHPlW7YNAhIEVpGnCM5mI= @@ -570,8 +572,6 @@ github.com/redis/go-redis/extra/redisotel/v9 v9.0.5 h1:EfpWLLCyXw8PSM2/XNJLjI3Pb github.com/redis/go-redis/extra/redisotel/v9 v9.0.5/go.mod h1:WZjPDy7VNzn77AAfnAfVjZNvfJTYfPetfZk5yoSTLaQ= github.com/redis/go-redis/v9 v9.17.2 h1:P2EGsA4qVIM3Pp+aPocCJ7DguDHhqrXNhVcEp4ViluI= github.com/redis/go-redis/v9 v9.17.2/go.mod h1:u410H11HMLoB+TP67dz8rL9s6QW2j76l0//kSOd3370= -github.com/reshmifrog/jfrog-cli-artifactory v0.0.0-20260302170823-db801936b182 h1:CmA/lkMdvMhvAy9U2WIoyf2H6NQ9myGHpQNOqKkGisA= -github.com/reshmifrog/jfrog-cli-artifactory v0.0.0-20260302170823-db801936b182/go.mod h1:P9ZywyTQzp+WsNmeb4IiMQOdVb++eQUD5oXd18LRVj8= github.com/rivo/uniseg v0.4.7 h1:WUdvkW8uEhrYfLC4ZzdpI2ztxP1I582+49Oc5Mq64VQ= github.com/rivo/uniseg v0.4.7/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88= github.com/robfig/cron/v3 v3.0.1 h1:WdRxkvbJztn8LMz/QEvLN5sBU+xKpSqwwUO1Pjr4qDs=