diff --git a/buildtools/cli.go b/buildtools/cli.go index f7fe94ce4..e3b9482eb 100644 --- a/buildtools/cli.go +++ b/buildtools/cli.go @@ -3,6 +3,7 @@ package buildtools import ( "errors" "fmt" + conancommand "github.com/jfrog/jfrog-cli-artifactory/artifactory/commands/conan" "os" "os/exec" "path/filepath" @@ -1486,18 +1487,19 @@ func ConanCmd(c *cli.Context) error { } args := cliutils.ExtractCommand(c) - cmdName, conanArgs := getCommandName(args) - // Execute native conan command directly - log.Info(fmt.Sprintf("Running Conan %s.", cmdName)) - conanCmd := exec.Command("conan", append([]string{cmdName}, conanArgs...)...) - conanCmd.Stdout = os.Stdout - conanCmd.Stderr = os.Stderr - if err := conanCmd.Run(); err != nil { - return fmt.Errorf("conan %s failed: %w", cmdName, err) + // Extract build flags (--build-name, --build-number) before passing to Conan + filteredArgs, buildConfiguration, err := build.ExtractBuildDetailsFromArgs(args) + if err != nil { + return err } - return nil + cmdName, conanArgs := getCommandName(filteredArgs) + + // Use jfrog-cli-artifactory Conan command with build info support + conanCommand := conancommand.NewConanCommand().SetCommandName(cmdName).SetArgs(conanArgs).SetBuildConfiguration(buildConfiguration) + + return commands.Exec(conanCommand) } func pythonCmd(c *cli.Context, projectType project.ProjectType) error { diff --git a/conan_test.go b/conan_test.go new file mode 100644 index 000000000..324c462cd --- /dev/null +++ b/conan_test.go @@ -0,0 +1,469 @@ +package main + +import ( + "os" + "os/exec" + "path/filepath" + "strconv" + "testing" + + buildinfo "github.com/jfrog/build-info-go/entities" + biutils "github.com/jfrog/build-info-go/utils" + coretests "github.com/jfrog/jfrog-cli-core/v2/utils/tests" + "github.com/jfrog/jfrog-cli/inttestutils" + "github.com/jfrog/jfrog-cli/utils/tests" + clientTestUtils "github.com/jfrog/jfrog-client-go/utils/tests" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" +) + +// TestConanInstall tests 'jf conan install' command with build info collection. +// This is Scenario 1: Install + Build Publish (dependencies only) +func TestConanInstall(t *testing.T) { + initConanTest(t) + buildNumber := "1" + + // Prepare project + projectPath := createConanProject(t, "conan-install-test") + wd, err := os.Getwd() + require.NoError(t, err) + chdirCallback := clientTestUtils.ChangeDirWithCallback(t, wd, projectPath) + defer chdirCallback() + + // Configure Conan remote + configureConanRemote(t) + defer cleanupConanRemote() + + // Run conan install with build info + jfrogCli := coretests.NewJfrogCli(execMain, "jfrog", "") + args := []string{ + "conan", "install", ".", + "--build=missing", + "-r", tests.ConanVirtualRepo, + "--build-name=" + tests.ConanBuildName, + "--build-number=" + buildNumber, + } + require.NoError(t, jfrogCli.Exec(args...)) + + // Publish build info + require.NoError(t, artifactoryCli.Exec("bp", tests.ConanBuildName, buildNumber)) + defer inttestutils.DeleteBuild(serverDetails.ArtifactoryUrl, tests.ConanBuildName, artHttpDetails) + + // Validate build info + publishedBuildInfo, found, err := tests.GetBuildInfo(serverDetails, tests.ConanBuildName, buildNumber) + require.NoError(t, err) + require.True(t, found, "build info was expected to be found") + + buildInfoModules := publishedBuildInfo.BuildInfo.Modules + require.Len(t, buildInfoModules, 1, "Expected 1 module") + assert.Equal(t, buildinfo.Conan, buildInfoModules[0].Type, "Module type should be conan") + + // Should have dependencies (at least zlib) + assert.GreaterOrEqual(t, len(buildInfoModules[0].Dependencies), 1, "Expected at least 1 dependency (zlib)") + + // No artifacts should be present (only install was run, no upload) + assert.Len(t, buildInfoModules[0].Artifacts, 0, "No artifacts expected for install-only scenario") +} + +// TestConanInstallCreate tests 'jf conan install' + 'jf conan create' command flow. +// This is Scenario 2: Install + Create + Build Publish (dependencies only) +func TestConanInstallCreate(t *testing.T) { + initConanTest(t) + buildNumber := "1" + + // Prepare project + projectPath := createConanProject(t, "conan-install-create-test") + wd, err := os.Getwd() + require.NoError(t, err) + chdirCallback := clientTestUtils.ChangeDirWithCallback(t, wd, projectPath) + defer chdirCallback() + + // Configure Conan remote + configureConanRemote(t) + defer cleanupConanRemote() + + jfrogCli := coretests.NewJfrogCli(execMain, "jfrog", "") + + // Run conan install + installArgs := []string{ + "conan", "install", ".", + "--build=missing", + "-r", tests.ConanVirtualRepo, + "--build-name=" + tests.ConanBuildName, + "--build-number=" + buildNumber, + } + assert.NoError(t, jfrogCli.Exec(installArgs...)) + + // Run conan create + createArgs := []string{ + "conan", "create", ".", + "--build=missing", + "--build-name=" + tests.ConanBuildName, + "--build-number=" + buildNumber, + } + assert.NoError(t, jfrogCli.Exec(createArgs...)) + + // Publish build info + assert.NoError(t, artifactoryCli.Exec("bp", tests.ConanBuildName, buildNumber)) + defer inttestutils.DeleteBuild(serverDetails.ArtifactoryUrl, tests.ConanBuildName, artHttpDetails) + + // Validate build info + publishedBuildInfo, found, err := tests.GetBuildInfo(serverDetails, tests.ConanBuildName, buildNumber) + require.NoError(t, err) + require.True(t, found, "build info was expected to be found") + + buildInfoModules := publishedBuildInfo.BuildInfo.Modules + assert.Len(t, buildInfoModules, 1, "Expected 1 module") + + // Should have dependencies + assert.GreaterOrEqual(t, len(buildInfoModules[0].Dependencies), 1, "Expected at least 1 dependency") + + // No artifacts without upload + assert.Len(t, buildInfoModules[0].Artifacts, 0, "No artifacts expected without upload") +} + +// TestConanFullFlow tests the complete flow: install + create + upload + build publish. +// This is Scenario 3: Install + Create + Upload + Build Publish (deps + artifacts) +func TestConanFullFlow(t *testing.T) { + initConanTest(t) + buildNumber := "1" + + // Prepare project + projectPath := createConanProject(t, "conan-full-flow-test") + wd, err := os.Getwd() + require.NoError(t, err) + chdirCallback := clientTestUtils.ChangeDirWithCallback(t, wd, projectPath) + defer chdirCallback() + + // Configure Conan remote + configureConanRemote(t) + defer cleanupConanRemote() + + jfrogCli := coretests.NewJfrogCli(execMain, "jfrog", "") + + // Run conan install + installArgs := []string{ + "conan", "install", ".", + "--build=missing", + "-r", tests.ConanVirtualRepo, + "--build-name=" + tests.ConanBuildName, + "--build-number=" + buildNumber, + } + assert.NoError(t, jfrogCli.Exec(installArgs...)) + + // Run conan create + createArgs := []string{ + "conan", "create", ".", + "--build=missing", + "--build-name=" + tests.ConanBuildName, + "--build-number=" + buildNumber, + } + assert.NoError(t, jfrogCli.Exec(createArgs...)) + + // Run conan upload + uploadArgs := []string{ + "conan", "upload", "cli-test-package/*", + "-r", tests.ConanLocalRepo, + "--confirm", + "--build-name=" + tests.ConanBuildName, + "--build-number=" + buildNumber, + } + assert.NoError(t, jfrogCli.Exec(uploadArgs...)) + + // Publish build info + assert.NoError(t, artifactoryCli.Exec("bp", tests.ConanBuildName, buildNumber)) + defer inttestutils.DeleteBuild(serverDetails.ArtifactoryUrl, tests.ConanBuildName, artHttpDetails) + + // Validate build info + publishedBuildInfo, found, err := tests.GetBuildInfo(serverDetails, tests.ConanBuildName, buildNumber) + require.NoError(t, err) + require.True(t, found, "build info was expected to be found") + + buildInfoModules := publishedBuildInfo.BuildInfo.Modules + assert.Len(t, buildInfoModules, 1, "Expected 1 module") + + // Should have both dependencies and artifacts + assert.GreaterOrEqual(t, len(buildInfoModules[0].Dependencies), 1, "Expected at least 1 dependency") + assert.GreaterOrEqual(t, len(buildInfoModules[0].Artifacts), 1, "Expected at least 1 artifact after upload") + + // Validate artifacts have checksums + for _, artifact := range buildInfoModules[0].Artifacts { + assert.NotEmpty(t, artifact.Sha1, "Artifact %s should have SHA1", artifact.Name) + } +} + +// TestConanCreateUpload tests create + upload flow without install. +// This is Scenario 4: Create + Upload + Build Publish (deps + artifacts) +func TestConanCreateUpload(t *testing.T) { + initConanTest(t) + buildNumber := "1" + + // Prepare project + projectPath := createConanProject(t, "conan-create-upload-test") + wd, err := os.Getwd() + require.NoError(t, err) + chdirCallback := clientTestUtils.ChangeDirWithCallback(t, wd, projectPath) + defer chdirCallback() + + // Configure Conan remote + configureConanRemote(t) + defer cleanupConanRemote() + + jfrogCli := coretests.NewJfrogCli(execMain, "jfrog", "") + + // Run conan create (this also installs dependencies) + createArgs := []string{ + "conan", "create", ".", + "--build=missing", + "--build-name=" + tests.ConanBuildName, + "--build-number=" + buildNumber, + } + assert.NoError(t, jfrogCli.Exec(createArgs...)) + + // Run conan upload + uploadArgs := []string{ + "conan", "upload", "cli-test-package/*", + "-r", tests.ConanLocalRepo, + "--confirm", + "--build-name=" + tests.ConanBuildName, + "--build-number=" + buildNumber, + } + assert.NoError(t, jfrogCli.Exec(uploadArgs...)) + + // Publish build info + assert.NoError(t, artifactoryCli.Exec("bp", tests.ConanBuildName, buildNumber)) + defer inttestutils.DeleteBuild(serverDetails.ArtifactoryUrl, tests.ConanBuildName, artHttpDetails) + + // Validate build info + publishedBuildInfo, found, err := tests.GetBuildInfo(serverDetails, tests.ConanBuildName, buildNumber) + require.NoError(t, err) + require.True(t, found, "build info was expected to be found") + + buildInfoModules := publishedBuildInfo.BuildInfo.Modules + assert.Len(t, buildInfoModules, 1, "Expected 1 module") + + // Should have both dependencies and artifacts + assert.GreaterOrEqual(t, len(buildInfoModules[0].Dependencies), 1, "Expected at least 1 dependency") + assert.GreaterOrEqual(t, len(buildInfoModules[0].Artifacts), 1, "Expected at least 1 artifact after upload") +} + +// TestConanAutoLogin tests that auto-login works for Artifactory remotes. +func TestConanAutoLogin(t *testing.T) { + initConanTest(t) + + // Prepare project + projectPath := createConanProject(t, "conan-auto-login-test") + wd, err := os.Getwd() + require.NoError(t, err) + chdirCallback := clientTestUtils.ChangeDirWithCallback(t, wd, projectPath) + defer chdirCallback() + + // Configure Conan remote (without manual login) + configureConanRemote(t) + defer cleanupConanRemote() + + // Run conan install - auto-login should happen + jfrogCli := coretests.NewJfrogCli(execMain, "jfrog", "") + args := []string{ + "conan", "install", ".", + "--build=missing", + "-r", tests.ConanVirtualRepo, + } + + // If auto-login works, this should not fail with authentication error + err = jfrogCli.Exec(args...) + assert.NoError(t, err, "Conan install with auto-login should succeed") +} + +// TestConanBuildInfoModuleFromProject tests that module ID is derived from the conanfile.py project info. +func TestConanBuildInfoModuleFromProject(t *testing.T) { + initConanTest(t) + buildNumber := "1" + + // Prepare project + projectPath := createConanProject(t, "conan-module-test") + wd, err := os.Getwd() + require.NoError(t, err) + chdirCallback := clientTestUtils.ChangeDirWithCallback(t, wd, projectPath) + defer chdirCallback() + + // Configure Conan remote + configureConanRemote(t) + defer cleanupConanRemote() + + // Run conan install + jfrogCli := coretests.NewJfrogCli(execMain, "jfrog", "") + args := []string{ + "conan", "install", ".", + "--build=missing", + "-r", tests.ConanVirtualRepo, + "--build-name=" + tests.ConanBuildName, + "--build-number=" + buildNumber, + } + assert.NoError(t, jfrogCli.Exec(args...)) + + // Publish build info + assert.NoError(t, artifactoryCli.Exec("bp", tests.ConanBuildName, buildNumber)) + defer inttestutils.DeleteBuild(serverDetails.ArtifactoryUrl, tests.ConanBuildName, artHttpDetails) + + // Validate build info module ID comes from conanfile.py (name:version) + publishedBuildInfo, found, err := tests.GetBuildInfo(serverDetails, tests.ConanBuildName, buildNumber) + require.NoError(t, err) + require.True(t, found, "build info was expected to be found") + + buildInfoModules := publishedBuildInfo.BuildInfo.Modules + assert.Len(t, buildInfoModules, 1, "Expected 1 module") + // Module ID should be derived from conanfile.py: "cli-test-package:1.0.0" + assert.Equal(t, "cli-test-package:1.0.0", buildInfoModules[0].Id, "Module ID should be derived from conanfile.py") +} + +// TestConanMultipleBuilds tests that multiple Conan builds don't interfere with each other. +func TestConanMultipleBuilds(t *testing.T) { + initConanTest(t) + + // Prepare project + projectPath := createConanProject(t, "conan-multi-build-test") + wd, err := os.Getwd() + require.NoError(t, err) + chdirCallback := clientTestUtils.ChangeDirWithCallback(t, wd, projectPath) + defer chdirCallback() + + // Configure Conan remote + configureConanRemote(t) + defer cleanupConanRemote() + + jfrogCli := coretests.NewJfrogCli(execMain, "jfrog", "") + + // Run multiple builds + for i := 1; i <= 3; i++ { + buildNumber := strconv.Itoa(i) + + args := []string{ + "conan", "install", ".", + "--build=missing", + "-r", tests.ConanVirtualRepo, + "--build-name=" + tests.ConanBuildName, + "--build-number=" + buildNumber, + } + assert.NoError(t, jfrogCli.Exec(args...)) + + // Publish each build + assert.NoError(t, artifactoryCli.Exec("bp", tests.ConanBuildName, buildNumber)) + } + + // Cleanup all builds + defer func() { + for i := 1; i <= 3; i++ { + inttestutils.DeleteBuild(serverDetails.ArtifactoryUrl, tests.ConanBuildName, artHttpDetails) + } + }() + + // Verify all builds exist + for i := 1; i <= 3; i++ { + buildNumber := strconv.Itoa(i) + publishedBuildInfo, found, err := tests.GetBuildInfo(serverDetails, tests.ConanBuildName, buildNumber) + require.NoError(t, err) + require.True(t, found, "build info %s/%s was expected to be found", tests.ConanBuildName, buildNumber) + assert.Len(t, publishedBuildInfo.BuildInfo.Modules, 1) + } +} + +// TestConanDependencyChecksums tests that dependencies have proper checksums. +func TestConanDependencyChecksums(t *testing.T) { + initConanTest(t) + buildNumber := "1" + + // Prepare project + projectPath := createConanProject(t, "conan-checksum-test") + wd, err := os.Getwd() + require.NoError(t, err) + chdirCallback := clientTestUtils.ChangeDirWithCallback(t, wd, projectPath) + defer chdirCallback() + + // Configure Conan remote + configureConanRemote(t) + defer cleanupConanRemote() + + // Run conan install + jfrogCli := coretests.NewJfrogCli(execMain, "jfrog", "") + args := []string{ + "conan", "install", ".", + "--build=missing", + "-r", tests.ConanVirtualRepo, + "--build-name=" + tests.ConanBuildName, + "--build-number=" + buildNumber, + } + assert.NoError(t, jfrogCli.Exec(args...)) + + // Publish build info + assert.NoError(t, artifactoryCli.Exec("bp", tests.ConanBuildName, buildNumber)) + defer inttestutils.DeleteBuild(serverDetails.ArtifactoryUrl, tests.ConanBuildName, artHttpDetails) + + // Validate checksums + publishedBuildInfo, found, err := tests.GetBuildInfo(serverDetails, tests.ConanBuildName, buildNumber) + require.NoError(t, err) + require.True(t, found, "build info was expected to be found") + + buildInfoModules := publishedBuildInfo.BuildInfo.Modules + require.Len(t, buildInfoModules, 1) + + checksumCount := 0 + for _, dep := range buildInfoModules[0].Dependencies { + if dep.Sha1 != "" || dep.Sha256 != "" { + checksumCount++ + t.Logf("Dependency %s has checksums: SHA1=%s, SHA256=%s", dep.Id, dep.Sha1, dep.Sha256) + } + } + + assert.Greater(t, checksumCount, 0, "At least some dependencies should have checksums") +} + +// Helper functions + +func initConanTest(t *testing.T) { + if !*tests.TestConan { + t.Skip("Skipping Conan test. To run Conan test add the '-test.conan=true' option.") + } + // Ensure Conan is installed + _, err := exec.LookPath("conan") + require.NoError(t, err, "Conan must be installed to run Conan tests") + // Ensure Conan default profile exists (required for conan install/create) + _ = exec.Command("conan", "profile", "detect").Run() + // Initialize CLI if not already done + if artifactoryCli == nil { + initArtifactoryCli() + } + // Set up home directory configuration + createJfrogHomeConfig(t, true) +} + +func createConanProject(t *testing.T, outputFolder string) string { + projectSrc := filepath.Join(filepath.FromSlash(tests.GetTestResourcesPath()), "conan", "conanproject") + tmpDir, cleanupCallback := coretests.CreateTempDirWithCallbackAndAssert(t) + + projectPath := filepath.Join(tmpDir, outputFolder) + require.NoError(t, biutils.CopyDir(projectSrc, projectPath, true, nil)) + + // Register cleanup to run at the end of the test + t.Cleanup(cleanupCallback) + + return projectPath +} + +func configureConanRemote(t *testing.T) { + // Remove existing remote if any + _ = exec.Command("conan", "remote", "remove", tests.ConanVirtualRepo).Run() + _ = exec.Command("conan", "remote", "remove", tests.ConanLocalRepo).Run() + // Add Conan remotes pointing to Artifactory + virtualUrl := serverDetails.ArtifactoryUrl + "api/conan/" + tests.ConanVirtualRepo + localUrl := serverDetails.ArtifactoryUrl + "api/conan/" + tests.ConanLocalRepo + addVirtualCmd := exec.Command("conan", "remote", "add", tests.ConanVirtualRepo, virtualUrl) + require.NoError(t, addVirtualCmd.Run(), "Failed to add Conan virtual remote") + addLocalCmd := exec.Command("conan", "remote", "add", tests.ConanLocalRepo, localUrl) + require.NoError(t, addLocalCmd.Run(), "Failed to add Conan local remote") +} + +func cleanupConanRemote() { + _ = exec.Command("conan", "remote", "remove", tests.ConanVirtualRepo).Run() + _ = exec.Command("conan", "remote", "remove", tests.ConanLocalRepo).Run() +} diff --git a/go.mod b/go.mod index fe61700ea..cb4be4817 100644 --- a/go.mod +++ b/go.mod @@ -1,6 +1,6 @@ module github.com/jfrog/jfrog-cli -go 1.25.4 +go 1.25.5 replace ( // Should not be updated to 0.2.6 due to a bug (https://github.com/jfrog/jfrog-cli-core/pull/372) @@ -16,15 +16,15 @@ require ( github.com/docker/docker v28.5.2+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.12.5-0.20251209171349-eb030db986f9 + github.com/jfrog/build-info-go v1.13.0 github.com/jfrog/gofrog v1.7.6 github.com/jfrog/jfrog-cli-application v1.0.2-0.20251210075951-519050602a7f - github.com/jfrog/jfrog-cli-artifactory v0.8.1-0.20251222102341-20b9565387e0 - github.com/jfrog/jfrog-cli-core/v2 v2.60.1-0.20251219102726-2cbe70d57403 + github.com/jfrog/jfrog-cli-artifactory v0.8.1-0.20251223103502-890237031ed7 + github.com/jfrog/jfrog-cli-core/v2 v2.60.1-0.20251223102649-e659f6937251 github.com/jfrog/jfrog-cli-evidence v0.8.3-0.20251204144808-73fa744851c0 github.com/jfrog/jfrog-cli-platform-services v1.10.1-0.20251205121610-171eb9b0000e github.com/jfrog/jfrog-cli-security v1.24.1 - github.com/jfrog/jfrog-client-go v1.55.1-0.20251218135123-ebfdf494c72d + github.com/jfrog/jfrog-client-go v1.55.1-0.20251223130919-74f030039d45 github.com/jszwec/csvutil v1.10.0 github.com/manifoldco/promptui v0.9.0 github.com/spf13/viper v1.21.0 @@ -282,8 +282,6 @@ replace github.com/docker/docker => github.com/docker/docker v27.5.1+incompatibl replace github.com/gfleury/go-bitbucket-v1 => github.com/gfleury/go-bitbucket-v1 v0.0.0-20230825095122-9bc1711434ab -// replace github.com/jfrog/build-info-go => github.com/jfrog/build-info-go v1.8.9-0.20251118093509-ebe86db606fa - //replace github.com/jfrog/jfrog-cli-artifactory => github.com/naveenku-jfrog/jfrog-cli-artifactory v0.0.0-20251210184507-0c8d138690cb //replace github.com/jfrog/build-info-go => github.com/jfrog/build-info-go v1.8.9-0.20251006061821-8b1be6a65215 diff --git a/go.sum b/go.sum index 41cf9dbb3..cf34708bd 100644 --- a/go.sum +++ b/go.sum @@ -1204,8 +1204,8 @@ github.com/jellydator/ttlcache/v3 v3.4.0 h1:YS4P125qQS0tNhtL6aeYkheEaB/m8HCqdMMP github.com/jellydator/ttlcache/v3 v3.4.0/go.mod h1:Hw9EgjymziQD3yGsQdf1FqFdpp7YjFMd4Srg5EJlgD4= 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.12.5-0.20251209171349-eb030db986f9 h1:CL7lp7Y7srwQ1vy1btX66t4wbztzEGQbqi/9tdEz7xk= -github.com/jfrog/build-info-go v1.12.5-0.20251209171349-eb030db986f9/go.mod h1:9W4U440fdTHwW1HiB/R0VQvz/5q8ZHsms9MWcq+JrdY= +github.com/jfrog/build-info-go v1.13.0 h1:bHedp1Gl+a8eR71xxP5JvkqwDj2X3r6e5NiIwNcIwRM= +github.com/jfrog/build-info-go v1.13.0/go.mod h1:+OCtMb22/D+u7Wne5lzkjJjaWr0LRZcHlDwTH86Mpwo= github.com/jfrog/froggit-go v1.20.6 h1:Xp7+LlEh0m1KGrQstb+u0aGfjRUtv1eh9xQBV3571jQ= github.com/jfrog/froggit-go v1.20.6/go.mod h1:obSG1SlsWjktkuqmKtpq7MNTTL63e0ot+ucTnlOMV88= github.com/jfrog/go-mockhttp v0.3.1 h1:/wac8v4GMZx62viZmv4wazB5GNKs+GxawuS1u3maJH8= @@ -1216,18 +1216,18 @@ 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.20251210075951-519050602a7f h1:YHwPNF13Gmt65J618kEGn/4SGewXqyYuAdcyYWYdrBA= github.com/jfrog/jfrog-cli-application v1.0.2-0.20251210075951-519050602a7f/go.mod h1:xum2HquWO5uExa/A7MQs3TgJJVEeoqTR+6Z4mfBr1Xw= -github.com/jfrog/jfrog-cli-artifactory v0.8.1-0.20251222102341-20b9565387e0 h1:hQscFu/t9G5A/2PuL4G4t8K5VUIxBubcB9+iYenATDE= -github.com/jfrog/jfrog-cli-artifactory v0.8.1-0.20251222102341-20b9565387e0/go.mod h1:oIq7MEnqzAjA9ZbamJPvdgTpHcmlPBMo05KBxZ3fykE= -github.com/jfrog/jfrog-cli-core/v2 v2.60.1-0.20251219102726-2cbe70d57403 h1:Hnw9eOCdybMBAh1pUt9FCs74CTDOUh0M79ZCQ3VKPc4= -github.com/jfrog/jfrog-cli-core/v2 v2.60.1-0.20251219102726-2cbe70d57403/go.mod h1:BMoGi2rG0udCCeaghqlNgiW3fTmT+TNnfTnBoWFYgcg= +github.com/jfrog/jfrog-cli-artifactory v0.8.1-0.20251223103502-890237031ed7 h1:kO+iONXxQ2xY5RJJbna2xHylBUL1NUpIlSgSWpB7+KQ= +github.com/jfrog/jfrog-cli-artifactory v0.8.1-0.20251223103502-890237031ed7/go.mod h1:S379fjRgPPiQDqBU2fGzPWmAt2Yu30syWQnXaGCtLiE= +github.com/jfrog/jfrog-cli-core/v2 v2.60.1-0.20251223102649-e659f6937251 h1:WTyDOaYJUwY6zQujZuL9JQ9Q9+QWj9p31tLb4bJnu4U= +github.com/jfrog/jfrog-cli-core/v2 v2.60.1-0.20251223102649-e659f6937251/go.mod h1:REkU0OfnLYZbQIjD2Cg85DAVP0SRZuV/PxiDfCJiJOc= github.com/jfrog/jfrog-cli-evidence v0.8.3-0.20251204144808-73fa744851c0 h1:8S1vE1PeVtrzWkKL0N39cX6XLLNV0It+f6xjRKjw7Ug= github.com/jfrog/jfrog-cli-evidence v0.8.3-0.20251204144808-73fa744851c0/go.mod h1:Ijx7tkTp6uDxgmQW+zQKLNztMrz6dcQAoVNXHL7spsU= github.com/jfrog/jfrog-cli-platform-services v1.10.1-0.20251205121610-171eb9b0000e h1:0BDeb5lD8qgQMOZJ08E35jUMTlt2Hb0K7Wu0SqO6MrI= github.com/jfrog/jfrog-cli-platform-services v1.10.1-0.20251205121610-171eb9b0000e/go.mod h1:qbu4iqBST9x8LgD8HhzUm91iOB3vHqtoGmaxOnmw0ok= github.com/jfrog/jfrog-cli-security v1.24.1 h1:NF8SE9uzUgqvqYjuuqbduXBqj+fwE4CmkMeVKtcLkyI= github.com/jfrog/jfrog-cli-security v1.24.1/go.mod h1:3FXD5IkKtdQOm9CZk6cR7q0iC6PaGMnjqzZqRcQp2r0= -github.com/jfrog/jfrog-client-go v1.55.1-0.20251218135123-ebfdf494c72d h1:AUavZ6icGpYiUXpTeya+3QhoG1Ja74pO71CtPr2h8iI= -github.com/jfrog/jfrog-client-go v1.55.1-0.20251218135123-ebfdf494c72d/go.mod h1:WQ5Y+oKYyHFAlCbHN925bWhnShTd2ruxZ6YTpb76fpU= +github.com/jfrog/jfrog-client-go v1.55.1-0.20251223130919-74f030039d45 h1:+XaOwUs5u8fZihlaVL4Pc1yIEiB8lVEczBW0QQBqNqg= +github.com/jfrog/jfrog-client-go v1.55.1-0.20251223130919-74f030039d45/go.mod h1:/rOoTsgWLr0aw90pBV70+GnULp1jc/LT/2J+iphWY9E= github.com/jhump/protoreflect v1.17.0 h1:qOEr613fac2lOuTgWN4tPAtLL7fUSbuJL5X5XumQh94= github.com/jhump/protoreflect v1.17.0/go.mod h1:h9+vUUL38jiBzck8ck+6G/aeMX8Z4QUY/NiJPwPNi+8= github.com/jmespath/go-jmespath v0.4.1-0.20220621161143-b0104c826a24 h1:liMMTbpW34dhU4az1GN0pTPADwNmvoRSeoZ6PItiqnY= diff --git a/main_test.go b/main_test.go index 4d396585e..60ae5bf54 100644 --- a/main_test.go +++ b/main_test.go @@ -60,7 +60,7 @@ func setupIntegrationTests() { InitArtifactoryTests() } - if *tests.TestNpm || *tests.TestGradle || *tests.TestMaven || *tests.TestGo || *tests.TestNuget || *tests.TestPip || *tests.TestPipenv || *tests.TestPoetry || *tests.TestHelm || (*tests.TestArtifactory && !*tests.TestArtifactoryProxy) || *tests.TestArtifactoryProject { + if *tests.TestNpm || *tests.TestGradle || *tests.TestMaven || *tests.TestGo || *tests.TestNuget || *tests.TestPip || *tests.TestPipenv || *tests.TestPoetry || *tests.TestConan || *tests.TestHelm || (*tests.TestArtifactory && !*tests.TestArtifactoryProxy) || *tests.TestArtifactoryProject { InitBuildToolsTests() } if *tests.TestDocker || *tests.TestPodman || *tests.TestDockerScan { @@ -93,7 +93,7 @@ func tearDownIntegrationTests() { if (*tests.TestArtifactory && !*tests.TestArtifactoryProxy) || *tests.TestArtifactoryProject { CleanArtifactoryTests() } - if *tests.TestNpm || *tests.TestGradle || *tests.TestMaven || *tests.TestGo || *tests.TestNuget || *tests.TestPip || *tests.TestPipenv || *tests.TestPoetry || *tests.TestHelm || *tests.TestDocker || *tests.TestPodman || *tests.TestDockerScan || (*tests.TestArtifactory && !*tests.TestArtifactoryProxy) || *tests.TestArtifactoryProject { + if *tests.TestNpm || *tests.TestGradle || *tests.TestMaven || *tests.TestGo || *tests.TestNuget || *tests.TestPip || *tests.TestPipenv || *tests.TestPoetry || *tests.TestConan || *tests.TestHelm || *tests.TestDocker || *tests.TestPodman || *tests.TestDockerScan || (*tests.TestArtifactory && !*tests.TestArtifactoryProxy) || *tests.TestArtifactoryProject { CleanBuildToolsTests() } if *tests.TestDistribution { diff --git a/testdata/conan/conanproject/conanfile.py b/testdata/conan/conanproject/conanfile.py new file mode 100644 index 000000000..b6013ae20 --- /dev/null +++ b/testdata/conan/conanproject/conanfile.py @@ -0,0 +1,13 @@ +from conan import ConanFile + + +class TestConan(ConanFile): + name = "cli-test-package" + version = "1.0.0" + requires = "zlib/1.3.1" + + def build(self): + self.output.info("Building test package") + + def package(self): + pass diff --git a/testdata/conan_local_repository_config.json b/testdata/conan_local_repository_config.json new file mode 100644 index 000000000..0048746e8 --- /dev/null +++ b/testdata/conan_local_repository_config.json @@ -0,0 +1,5 @@ +{ + "key": "${CONAN_LOCAL_REPO}", + "rclass": "local", + "packageType": "conan" +} diff --git a/testdata/conan_remote_repository_config.json b/testdata/conan_remote_repository_config.json new file mode 100644 index 000000000..9d8948511 --- /dev/null +++ b/testdata/conan_remote_repository_config.json @@ -0,0 +1,6 @@ +{ + "key": "${CONAN_REMOTE_REPO}", + "rclass": "remote", + "packageType": "conan", + "url": "https://center2.conan.io" +} diff --git a/testdata/conan_virtual_repository_config.json b/testdata/conan_virtual_repository_config.json new file mode 100644 index 000000000..778d14d84 --- /dev/null +++ b/testdata/conan_virtual_repository_config.json @@ -0,0 +1,6 @@ +{ + "key": "${CONAN_VIRTUAL_REPO}", + "rclass": "virtual", + "packageType": "conan", + "repositories": ["${CONAN_LOCAL_REPO}", "${CONAN_REMOTE_REPO}"] +} diff --git a/utils/tests/consts.go b/utils/tests/consts.go index 999aeadaa..8910cf920 100644 --- a/utils/tests/consts.go +++ b/utils/tests/consts.go @@ -108,6 +108,9 @@ const ( PoetryLocalRepositoryConfig = "poetry_local_repository_config.json" PoetryRemoteRepositoryConfig = "poetry_remote_repository_config.json" PoetryVirtualRepositoryConfig = "poetry_virtual_repository_config.json" + ConanLocalRepositoryConfig = "conan_local_repository_config.json" + ConanRemoteRepositoryConfig = "conan_remote_repository_config.json" + ConanVirtualRepositoryConfig = "conan_virtual_repository_config.json" HelmLocalRepositoryConfig = "helm_local_repository_config.json" ReplicationTempCreate = "replication_push_create.json" Repo1RepositoryConfig = "repo1_repository_config.json" @@ -205,6 +208,9 @@ var ( PoetryLocalRepo = "cli-poetry-local" PoetryRemoteRepo = "cli-poetry-remote" PoetryVirtualRepo = "cli-poetry-virtual" + ConanLocalRepo = "cli-conan-local" + ConanRemoteRepo = "cli-conan-remote" + ConanVirtualRepo = "cli-conan-virtual" HelmLocalRepo = "cli-helm-local" DockerLocalRepo = "cli-docker-local" DockerLocalPromoteRepo = "cli-docker-local-promote" @@ -239,6 +245,7 @@ var ( PipBuildName = "cli-pip-build" PipenvBuildName = "cli-pipenv-build" PoetryBuildName = "cli-poetry-build" + ConanBuildName = "cli-conan-build" HelmBuildName = "cli-helm-build" RtBuildName1 = "cli-rt-build1" RtBuildName2 = "cli-rt-build2" diff --git a/utils/tests/utils.go b/utils/tests/utils.go index 17c9745d5..2245a5562 100644 --- a/utils/tests/utils.go +++ b/utils/tests/utils.go @@ -68,6 +68,7 @@ var ( TestPip *bool TestPipenv *bool TestPoetry *bool + TestConan *bool TestHelm *bool TestPlugins *bool TestXray *bool @@ -106,6 +107,7 @@ func init() { TestPip = flag.Bool("test.pip", false, "Test Pip") TestPipenv = flag.Bool("test.pipenv", false, "Test Pipenv") TestPoetry = flag.Bool("test.poetry", false, "Test Poetry") + TestConan = flag.Bool("test.conan", false, "Test Conan") TestHelm = flag.Bool("test.helm", false, "Test Helm") TestPlugins = flag.Bool("test.plugins", false, "Test Plugins") TestXray = flag.Bool("test.xray", false, "Test Xray") @@ -281,6 +283,9 @@ var reposConfigMap = map[*string]string{ &PoetryLocalRepo: PoetryLocalRepositoryConfig, &PoetryRemoteRepo: PoetryRemoteRepositoryConfig, &PoetryVirtualRepo: PoetryVirtualRepositoryConfig, + &ConanLocalRepo: ConanLocalRepositoryConfig, + &ConanRemoteRepo: ConanRemoteRepositoryConfig, + &ConanVirtualRepo: ConanVirtualRepositoryConfig, &HelmLocalRepo: HelmLocalRepositoryConfig, &RtDebianRepo: DebianTestRepositoryConfig, &RtLfsRepo: GitLfsTestRepositoryConfig, @@ -346,6 +351,7 @@ func GetNonVirtualRepositories() map[*string]string { TestPip: {&PypiLocalRepo, &PypiRemoteRepo}, TestPipenv: {&PipenvRemoteRepo}, TestPoetry: {&PoetryLocalRepo, &PoetryRemoteRepo}, + TestConan: {&ConanLocalRepo, &ConanRemoteRepo}, TestHelm: {&HelmLocalRepo}, TestPlugins: {&RtRepo1}, TestXray: {&NpmRemoteRepo, &NugetRemoteRepo, &YarnRemoteRepo, &GradleRemoteRepo, &MvnRemoteRepo, &GoRepo, &GoRemoteRepo, &PypiRemoteRepo}, @@ -373,6 +379,7 @@ func GetVirtualRepositories() map[*string]string { TestPip: {&PypiVirtualRepo}, TestPipenv: {&PipenvVirtualRepo}, TestPoetry: {&PoetryVirtualRepo}, + TestConan: {&ConanVirtualRepo}, TestHelm: {}, TestPlugins: {}, TestXray: {&GoVirtualRepo}, @@ -411,6 +418,7 @@ func GetBuildNames() []string { TestPip: {&PipBuildName}, TestPipenv: {&PipenvBuildName}, TestPoetry: {&PoetryBuildName}, + TestConan: {&ConanBuildName}, TestHelm: {&HelmBuildName}, TestPlugins: {}, TestXray: {}, @@ -468,6 +476,9 @@ func getSubstitutionMap() map[string]string { "${POETRY_LOCAL_REPO}": PoetryLocalRepo, "${POETRY_REMOTE_REPO}": PoetryRemoteRepo, "${POETRY_VIRTUAL_REPO}": PoetryVirtualRepo, + "${CONAN_LOCAL_REPO}": ConanLocalRepo, + "${CONAN_REMOTE_REPO}": ConanRemoteRepo, + "${CONAN_VIRTUAL_REPO}": ConanVirtualRepo, "${HELM_REPO}": HelmLocalRepo, "${BUILD_NAME1}": RtBuildName1, "${BUILD_NAME2}": RtBuildName2, @@ -534,6 +545,9 @@ func AddTimestampToGlobalVars() { PoetryLocalRepo += uniqueSuffix PoetryRemoteRepo += uniqueSuffix PoetryVirtualRepo += uniqueSuffix + ConanLocalRepo += uniqueSuffix + ConanRemoteRepo += uniqueSuffix + ConanVirtualRepo += uniqueSuffix HelmLocalRepo += uniqueSuffix RtDebianRepo += uniqueSuffix RtLfsRepo += uniqueSuffix @@ -560,6 +574,7 @@ func AddTimestampToGlobalVars() { PipBuildName += uniqueSuffix PipenvBuildName += uniqueSuffix PoetryBuildName += uniqueSuffix + ConanBuildName += uniqueSuffix HelmBuildName += uniqueSuffix RtBuildName1 += uniqueSuffix RtBuildName2 += uniqueSuffix