diff --git a/conan_test.go b/conan_test.go index ba2cbeb49..9f3283ea7 100644 --- a/conan_test.go +++ b/conan_test.go @@ -454,6 +454,18 @@ func createConanProject(t *testing.T, outputFolder string) string { return projectPath } +func createConanProjectSubdir(t *testing.T, outputFolder string) string { + projectSrc := filepath.Join(filepath.FromSlash(tests.GetTestResourcesPath()), "conan", "conanproject-subdir") + tmpDir, cleanupCallback := coretests.CreateTempDirWithCallbackAndAssert(t) + + projectPath := filepath.Join(tmpDir, outputFolder) + require.NoError(t, biutils.CopyDir(projectSrc, projectPath, true, nil)) + + t.Cleanup(cleanupCallback) + + return projectPath +} + func configureConanRemote(t *testing.T) { // Remove existing remote if any _ = exec.Command("conan", "remote", "remove", tests.ConanVirtualRepo).Run() @@ -472,6 +484,167 @@ func cleanupConanRemote() { _ = exec.Command("conan", "remote", "remove", tests.ConanLocalRepo).Run() } +// TestConanInstallRequiresNoRecipe tests 'jf conan install --requires' without any conanfile. +func TestConanInstallRequiresNoRecipe(t *testing.T) { + initConanTest(t) + buildNumber := "1" + + // Create empty project dir (no conanfile) + tmpDir, cleanupCallback := coretests.CreateTempDirWithCallbackAndAssert(t) + t.Cleanup(cleanupCallback) + projectPath := filepath.Join(tmpDir, "no-recipe-test") + require.NoError(t, os.MkdirAll(projectPath, 0755)) + + 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", "") + args := []string{ + "conan", "install", + "--requires", "zlib/1.3.1", + "--build", "missing", + "-r", tests.ConanVirtualRepo, + "--build-name=" + tests.ConanBuildName, + "--build-number=" + buildNumber, + } + require.NoError(t, jfrogCli.Exec(args...), "conan install --requires should succeed without a conanfile") + + require.NoError(t, artifactoryCli.Exec("bp", tests.ConanBuildName, buildNumber)) + defer inttestutils.DeleteBuild(serverDetails.ArtifactoryUrl, tests.ConanBuildName, artHttpDetails) + + 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") + assert.GreaterOrEqual(t, len(buildInfoModules[0].Dependencies), 1, "Expected at least 1 dependency (zlib)") +} + +// TestConanInstallRecipeInSubdir tests 'jf conan install ' where the recipe is not in cwd. +func TestConanInstallRecipeInSubdir(t *testing.T) { + initConanTest(t) + buildNumber := "1" + + projectPath := createConanProjectSubdir(t, "conan-subdir-install-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", "") + args := []string{ + "conan", "install", "recipes/mylib", + "--build=missing", + "-r", tests.ConanVirtualRepo, + "--build-name=" + tests.ConanBuildName, + "--build-number=" + buildNumber, + } + require.NoError(t, jfrogCli.Exec(args...), "conan install with recipe in subdirectory should succeed") + + require.NoError(t, artifactoryCli.Exec("bp", tests.ConanBuildName, buildNumber)) + defer inttestutils.DeleteBuild(serverDetails.ArtifactoryUrl, tests.ConanBuildName, artHttpDetails) + + 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) + assert.Equal(t, buildinfo.Conan, buildInfoModules[0].Type) + assert.Equal(t, "cli-test-subdir-package:1.0.0", buildInfoModules[0].Id, + "Module ID should come from the subdirectory's conanfile.py") + assert.GreaterOrEqual(t, len(buildInfoModules[0].Dependencies), 1) +} + +// TestConanCreateRecipeInSubdir tests 'jf conan create ' where the recipe is not in cwd. +func TestConanCreateRecipeInSubdir(t *testing.T) { + initConanTest(t) + buildNumber := "1" + + projectPath := createConanProjectSubdir(t, "conan-subdir-create-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", "recipes/mylib", + "--build=missing", + "--build-name=" + tests.ConanBuildName, + "--build-number=" + buildNumber, + } + require.NoError(t, jfrogCli.Exec(createArgs...), "conan create with recipe in subdirectory should succeed") + + require.NoError(t, artifactoryCli.Exec("bp", tests.ConanBuildName, buildNumber)) + defer inttestutils.DeleteBuild(serverDetails.ArtifactoryUrl, tests.ConanBuildName, artHttpDetails) + + 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) + assert.Equal(t, "cli-test-subdir-package:1.0.0", buildInfoModules[0].Id) + assert.GreaterOrEqual(t, len(buildInfoModules[0].Dependencies), 1) +} + +// TestConanInstallMultipleRequires tests --requires with multiple dependencies. +func TestConanInstallMultipleRequires(t *testing.T) { + initConanTest(t) + buildNumber := "1" + + tmpDir, cleanupCallback := coretests.CreateTempDirWithCallbackAndAssert(t) + t.Cleanup(cleanupCallback) + projectPath := filepath.Join(tmpDir, "multi-requires-test") + require.NoError(t, os.MkdirAll(projectPath, 0755)) + + 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", "") + args := []string{ + "conan", "install", + "--requires", "zlib/1.3.1", + "--requires", "bzip2/1.0.8", + "--build", "missing", + "-r", tests.ConanVirtualRepo, + "--build-name=" + tests.ConanBuildName, + "--build-number=" + buildNumber, + } + require.NoError(t, jfrogCli.Exec(args...)) + + require.NoError(t, artifactoryCli.Exec("bp", tests.ConanBuildName, buildNumber)) + defer inttestutils.DeleteBuild(serverDetails.ArtifactoryUrl, tests.ConanBuildName, artHttpDetails) + + 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) + assert.GreaterOrEqual(t, len(buildInfoModules[0].Dependencies), 2, + "Expected at least 2 dependencies (zlib + bzip2)") +} + // 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) { diff --git a/go.mod b/go.mod index e929c9cc0..5ba2a820b 100644 --- a/go.mod +++ b/go.mod @@ -255,9 +255,9 @@ replace github.com/ktrysmt/go-bitbucket => github.com/ktrysmt/go-bitbucket v0.9. //replace github.com/jfrog/jfrog-cli-core/v2 => ../jfrog-cli-core -// replace github.com/jfrog/jfrog-cli-artifactory => github.com/fluxxBot/jfrog-cli-artifactory v0.0.0-20260130044429-464a5025d08a +replace github.com/jfrog/jfrog-cli-artifactory => github.com/reshmifrog/jfrog-cli-artifactory v0.0.0-20260303084642-b208fbba798b -//replace github.com/jfrog/build-info-go => github.com/fluxxBot/build-info-go v1.10.10-0.20260105070825-d3f36f619ba5 +replace github.com/jfrog/build-info-go => github.com/reshmifrog/build-info-go v1.10.11-0.20260303032831-71878c7210bf //replace github.com/jfrog/jfrog-cli-core/v2 => github.com/fluxxBot/jfrog-cli-core/v2 v2.58.1-0.20260105065921-c6488910f44c diff --git a/go.sum b/go.sum index 3bd696dc1..78eb6fe0e 100644 --- a/go.sum +++ b/go.sum @@ -407,8 +407,6 @@ 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.3 h1:hkAmPjBw393tPmQ07JknLNWFNZjXdy2xFEnOW9wwOxI= github.com/jfrog/archiver/v3 v3.6.3/go.mod h1:5V9l+Fte30Y4qe9dUOAd3yNTf8lmtVNuhKNrvI8PMhg= -github.com/jfrog/build-info-go v1.13.1-0.20260216093441-40a4dc563294 h1:7aJGdrjibtWT1VPLH+GYyoZsAsoca8/fMrvGIvkZ8Fs= -github.com/jfrog/build-info-go v1.13.1-0.20260216093441-40a4dc563294/go.mod h1:+OCtMb22/D+u7Wne5lzkjJjaWr0LRZcHlDwTH86Mpwo= github.com/jfrog/froggit-go v1.21.0 h1:OFz5eqK1zgqrzXtPdyStVKSMqNJg96RNqRKmXSXOHsk= github.com/jfrog/froggit-go v1.21.0/go.mod h1:obSG1SlsWjktkuqmKtpq7MNTTL63e0ot+ucTnlOMV88= github.com/jfrog/go-mockhttp v0.3.1 h1:/wac8v4GMZx62viZmv4wazB5GNKs+GxawuS1u3maJH8= @@ -419,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.20260303081233-aefbc2d40c47 h1:sVnpvQhg+jGkd8Vvww3+z+DZS3UBFi+0qCUKl6jKOmk= -github.com/jfrog/jfrog-cli-artifactory v0.8.1-0.20260303081233-aefbc2d40c47/go.mod h1:IRUe9nYwCUq8V2WRDUd4bddwiXXdkxvNQ36+0U0uHqI= 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= @@ -576,6 +572,10 @@ 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/build-info-go v1.10.11-0.20260303032831-71878c7210bf h1:MP+2sbP5rU66EXEG471hyk3VOSIBkm564EWFNhCCCIs= +github.com/reshmifrog/build-info-go v1.10.11-0.20260303032831-71878c7210bf/go.mod h1:+OCtMb22/D+u7Wne5lzkjJjaWr0LRZcHlDwTH86Mpwo= +github.com/reshmifrog/jfrog-cli-artifactory v0.0.0-20260303084642-b208fbba798b h1:ZLKQgpBEM5ah5JfP9+iUaRStDbuJF4q86eKOW8A/G0Q= +github.com/reshmifrog/jfrog-cli-artifactory v0.0.0-20260303084642-b208fbba798b/go.mod h1:Iii9Mej7avjeYfYwKxCGbRM6lNf1lhHn3M5LmDOiHkE= 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= diff --git a/testdata/conan/conanproject-subdir/recipes/mylib/conanfile.py b/testdata/conan/conanproject-subdir/recipes/mylib/conanfile.py new file mode 100644 index 000000000..bbe090795 --- /dev/null +++ b/testdata/conan/conanproject-subdir/recipes/mylib/conanfile.py @@ -0,0 +1,13 @@ +from conan import ConanFile + + +class TestConan(ConanFile): + name = "cli-test-subdir-package" + version = "1.0.0" + requires = "zlib/1.3.1" + + def build(self): + self.output.info("Building test package from subdirectory") + + def package(self): + pass