From 686a55c8a9c4e1fd6304d6df6d820c7ba3a5ba2a Mon Sep 17 00:00:00 2001 From: Bhanu Reddy Date: Thu, 29 Jan 2026 19:56:48 +0530 Subject: [PATCH 1/8] Added e2e tests for multiple package managers --- conan_test.go | 96 ++++++++++++++++++++++++++++++ go_test.go | 89 ++++++++++++++++++++++++++-- helm_test.go | 155 +++++++++++++++++++++++++++++++++++++++++++++++++ nuget_test.go | 58 ++++++++++++++++++ pip_test.go | 83 ++++++++++++++++++++++++++ poetry_test.go | 90 ++++++++++++++++++++++++++++ 6 files changed, 565 insertions(+), 6 deletions(-) diff --git a/conan_test.go b/conan_test.go index 324c462cd..b674bd68f 100644 --- a/conan_test.go +++ b/conan_test.go @@ -9,6 +9,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" coretests "github.com/jfrog/jfrog-cli-core/v2/utils/tests" "github.com/jfrog/jfrog-cli/inttestutils" "github.com/jfrog/jfrog-cli/utils/tests" @@ -467,3 +468,98 @@ func cleanupConanRemote() { _ = exec.Command("conan", "remote", "remove", tests.ConanVirtualRepo).Run() _ = exec.Command("conan", "remote", "remove", tests.ConanLocalRepo).Run() } + +// 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 +// from Build Info and applies properties via batch API. +func TestConanBuildPublishWithCIVcsProps(t *testing.T) { + initConanTest(t) + + buildName := tests.ConanBuildName + "-civcs" + buildNumber := "1" + + // Setup GitHub Actions environment (uses real env vars on CI, mock values locally) + cleanupEnv, actualOrg, actualRepo := tests.SetupGitHubActionsEnv(t) + defer cleanupEnv() + + // Clean old build + inttestutils.DeleteBuild(serverDetails.ArtifactoryUrl, buildName, artHttpDetails) + defer inttestutils.DeleteBuild(serverDetails.ArtifactoryUrl, buildName, artHttpDetails) + + // Prepare project + projectPath := createConanProject(t, "conan-civcs-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 + createArgs := []string{ + "conan", "create", ".", + "--build=missing", + "--build-name=" + buildName, + "--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=" + buildName, + "--build-number=" + buildNumber, + } + assert.NoError(t, jfrogCli.Exec(uploadArgs...)) + + // Publish build info - should set CI VCS props on artifacts + assert.NoError(t, artifactoryCli.Exec("bp", buildName, buildNumber)) + + // Get the published build info to find artifact paths + publishedBuildInfo, found, err := tests.GetBuildInfo(serverDetails, buildName, buildNumber) + require.NoError(t, err) + require.True(t, found, "Build info was not found") + + // Create service manager for getting artifact properties + serviceManager, err := utils.CreateServiceManager(serverDetails, 3, 1000, false) + require.NoError(t, err) + + // Verify VCS properties on each artifact from build info + artifactCount := 0 + for _, module := range publishedBuildInfo.BuildInfo.Modules { + for _, artifact := range module.Artifacts { + if artifact.OriginalDeploymentRepo == "" { + continue // Skip artifacts without deployment repo info + } + fullPath := artifact.OriginalDeploymentRepo + "/" + artifact.Path + + props, err := serviceManager.GetItemProps(fullPath) + if err != nil { + t.Logf("Skipping artifact %s: could not get properties", fullPath) + continue + } + if props == nil { + continue + } + + // Validate VCS properties + if _, ok := props.Properties["vcs.provider"]; ok { + assert.Contains(t, props.Properties["vcs.provider"], "github", "Wrong vcs.provider on %s", artifact.Name) + assert.Contains(t, props.Properties["vcs.org"], actualOrg, "Wrong vcs.org on %s", artifact.Name) + assert.Contains(t, props.Properties["vcs.repo"], actualRepo, "Wrong vcs.repo on %s", artifact.Name) + artifactCount++ + } + } + } + + // Log summary + t.Logf("Conan build info created with CI VCS properties validated on %d artifacts", artifactCount) + t.Logf("CI VCS environment validated: org=%s, repo=%s", actualOrg, actualRepo) +} diff --git a/go_test.go b/go_test.go index a9e593cc7..23d134e7b 100644 --- a/go_test.go +++ b/go_test.go @@ -2,8 +2,6 @@ package main import ( "fmt" - "github.com/jfrog/jfrog-client-go/http/httpclient" - "github.com/stretchr/testify/require" "net/http" "os" "os/exec" @@ -12,20 +10,21 @@ import ( biutils "github.com/jfrog/build-info-go/utils" - coretests "github.com/jfrog/jfrog-cli-core/v2/utils/tests" - clientTestUtils "github.com/jfrog/jfrog-client-go/utils/tests" - buildinfo "github.com/jfrog/build-info-go/entities" "github.com/jfrog/jfrog-cli-artifactory/artifactory/commands/golang" + "github.com/jfrog/jfrog-cli-core/v2/artifactory/utils" "github.com/jfrog/jfrog-cli-core/v2/common/build" "github.com/jfrog/jfrog-cli-core/v2/common/commands" "github.com/jfrog/jfrog-cli-core/v2/common/spec" + coretests "github.com/jfrog/jfrog-cli-core/v2/utils/tests" "github.com/jfrog/jfrog-cli/inttestutils" - "github.com/jfrog/jfrog-cli/utils/tests" + "github.com/jfrog/jfrog-client-go/http/httpclient" "github.com/jfrog/jfrog-client-go/utils/io/fileutils" "github.com/jfrog/jfrog-client-go/utils/log" + clientTestUtils "github.com/jfrog/jfrog-client-go/utils/tests" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" ) func TestGoConfigWithModuleNameChange(t *testing.T) { @@ -420,3 +419,81 @@ func TestSetupGoCommand(t *testing.T) { assert.Equal(t, http.StatusOK, res.StatusCode) } } + +// TestGoBuildPublishWithCIVcsProps tests that CI VCS properties are set on Go artifacts +// when running go-publish followed by build-publish in a CI environment (GitHub Actions). +// Go supports direct upload via 'jf gp' which sets CI VCS properties during upload. +func TestGoBuildPublishWithCIVcsProps(t *testing.T) { + _, cleanUpFunc := initGoTest(t) + defer cleanUpFunc() + + buildName := tests.GoBuildName + "-civcs" + buildNumber := "1" + + // Setup GitHub Actions environment (uses real env vars on CI, mock values locally) + cleanupEnv, actualOrg, actualRepo := tests.SetupGitHubActionsEnv(t) + defer cleanupEnv() + + // Clean old build + inttestutils.DeleteBuild(serverDetails.ArtifactoryUrl, buildName, artHttpDetails) + defer inttestutils.DeleteBuild(serverDetails.ArtifactoryUrl, buildName, artHttpDetails) + + wd, err := os.Getwd() + assert.NoError(t, err, "Failed to get current dir") + + // Prepare and build the Go project + prepareGoProject("project1", t, true) + defer clientTestUtils.ChangeDirAndAssert(t, wd) + + // Build the Go project with build info collection + jfrogCli := coretests.NewJfrogCli(execMain, "jfrog", "") + err = execGo(jfrogCli, "go", "build", "--mod=mod", "--build-name="+buildName, "--build-number="+buildNumber) + assert.NoError(t, err) + + // Publish the Go module to Artifactory with build info collection + // This is where CI VCS properties should be set during direct upload + err = execGo(jfrogCli, "gp", "--build-name="+buildName, "--build-number="+buildNumber, "v1.0.0") + assert.NoError(t, err) + + // Publish build info - should also set CI VCS props via batch update if not already set + err = execGo(artifactoryCli, "bp", buildName, buildNumber) + assert.NoError(t, err) + + // Get the published build info to find artifact paths + publishedBuildInfo, found, err := tests.GetBuildInfo(serverDetails, buildName, buildNumber) + assert.NoError(t, err) + assert.True(t, found, "Build info was not found") + + // Create service manager for getting artifact properties + serviceManager, err := utils.CreateServiceManager(serverDetails, 3, 1000, false) + assert.NoError(t, err) + + // Verify VCS properties on each artifact from build info + artifactCount := 0 + for _, module := range publishedBuildInfo.BuildInfo.Modules { + for _, artifact := range module.Artifacts { + if artifact.OriginalDeploymentRepo == "" { + continue // Skip artifacts without deployment repo info + } + fullPath := artifact.OriginalDeploymentRepo + "/" + artifact.Path + + props, err := serviceManager.GetItemProps(fullPath) + assert.NoError(t, err, "Failed to get properties for artifact: %s", fullPath) + assert.NotNil(t, props, "Properties are nil for artifact: %s", fullPath) + + // Validate VCS properties + assert.Contains(t, props.Properties, "vcs.provider", "Missing vcs.provider on %s", artifact.Name) + assert.Contains(t, props.Properties["vcs.provider"], "github", "Wrong vcs.provider on %s", artifact.Name) + + assert.Contains(t, props.Properties, "vcs.org", "Missing vcs.org on %s", artifact.Name) + assert.Contains(t, props.Properties["vcs.org"], actualOrg, "Wrong vcs.org on %s", artifact.Name) + + assert.Contains(t, props.Properties, "vcs.repo", "Missing vcs.repo on %s", artifact.Name) + assert.Contains(t, props.Properties["vcs.repo"], actualRepo, "Wrong vcs.repo on %s", artifact.Name) + + artifactCount++ + } + } + + assert.Greater(t, artifactCount, 0, "No artifacts were validated for CI VCS properties") +} diff --git a/helm_test.go b/helm_test.go index f2a2c549e..a1014d157 100644 --- a/helm_test.go +++ b/helm_test.go @@ -16,9 +16,11 @@ import ( "time" buildinfo "github.com/jfrog/build-info-go/entities" + "github.com/jfrog/jfrog-cli-core/v2/artifactory/utils" "github.com/jfrog/jfrog-cli-core/v2/utils/config" "github.com/jfrog/jfrog-cli-core/v2/utils/coreutils" 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" @@ -803,6 +805,159 @@ func TestHelmPackageAndPushWithBuildInfo(t *testing.T) { validateHelmBuildInfo(t, publishedBuildInfo.BuildInfo, buildName, true, true) } +// TestHelmBuildPublishWithCIVcsProps tests that CI VCS properties are set on Helm artifacts +// when running build-publish in a CI environment (GitHub Actions). +// Helm charts are published via Helm client; build-publish retrieves artifact paths +// from Build Info and applies CI VCS properties via optimized batch SetProps API call. +func TestHelmBuildPublishWithCIVcsProps(t *testing.T) { + initHelmTest(t) + defer cleanHelmTest(t) + + buildName := tests.HelmBuildName + "-civcs" + buildNumber := "1" + + // Setup GitHub Actions environment (uses real env vars on CI, mock values locally) + cleanupEnv, actualOrg, actualRepo := tests.SetupGitHubActionsEnv(t) + defer cleanupEnv() + + // Clean old build + inttestutils.DeleteBuild(serverDetails.ArtifactoryUrl, buildName, artHttpDetails) + defer inttestutils.DeleteBuild(serverDetails.ArtifactoryUrl, buildName, artHttpDetails) + + chartDir := createTestHelmChartWithDependencies(t, "test-chart-civcs", "0.1.0") + defer func() { + if err := os.RemoveAll(chartDir); err != nil { + t.Logf("Warning: Failed to remove test chart directory %s: %v", chartDir, err) + } + }() + + originalDir, err := os.Getwd() + require.NoError(t, err) + defer func() { + if err := os.Chdir(originalDir); err != nil { + t.Logf("Warning: Failed to change back to original directory: %v", err) + } + }() + + err = os.Chdir(chartDir) + require.NoError(t, err) + + // Run helm dependency update + helmCmd := exec.Command("helm", "dependency", "update") + helmCmd.Dir = chartDir + err = helmCmd.Run() + require.NoError(t, err, "helm dependency update should succeed") + + // Run helm package with build info (collects dependencies) + jfrogCli := coreTests.NewJfrogCli(execMain, "jfrog", "") + args := []string{ + "helm", "package", ".", + "--build-name=" + buildName, + "--build-number=" + buildNumber, + } + err = jfrogCli.Exec(args...) + require.NoError(t, err, "helm package should succeed") + + // Get the packaged chart file + chartFiles, err := filepath.Glob(filepath.Join(chartDir, "*.tgz")) + require.NoError(t, err) + require.Greater(t, len(chartFiles), 0, "Chart package file should be created") + chartFile := filepath.Base(chartFiles[0]) + + // Setup registry for push + parsedURL, err := url.Parse(serverDetails.ArtifactoryUrl) + require.NoError(t, err) + registryHost := parsedURL.Host + registryURL := fmt.Sprintf("oci://%s/%s", registryHost, tests.HelmLocalRepo) + + if !isRepoExist(tests.HelmLocalRepo) { + t.Skipf("Repository %s does not exist. Skipping test.", tests.HelmLocalRepo) + } + + err = loginHelmRegistry(t, registryHost) + if err != nil { + errorMsg := strings.ToLower(err.Error()) + if strings.Contains(errorMsg, "account temporarily locked") { + t.Skip("Artifactory account is temporarily locked. Skipping test.") + } + if strings.Contains(errorMsg, "http response to https") || + strings.Contains(errorMsg, "tls: first record does not look like a tls handshake") { + t.Skip("Helm registry login failed due to HTTPS/HTTP mismatch. Skipping test.") + } + } + require.NoError(t, err, "helm registry login should succeed") + + // Run helm push with the same build name/number (adds artifacts to existing build info) + args = []string{ + "helm", "push", chartFile, + registryURL, + "--build-name=" + buildName, + "--build-number=" + buildNumber, + } + err = jfrogCli.Exec(args...) + if err != nil { + errorMsg := strings.ToLower(err.Error()) + if strings.Contains(errorMsg, "404") || + strings.Contains(errorMsg, "not found") || + strings.Contains(errorMsg, "exit status 1") { + t.Skip("OCI registry API not accessible (404). Skipping test.") + } + } + require.NoError(t, err, "helm push should succeed") + + // Publish build info - should set CI VCS props on artifacts + assert.NoError(t, artifactoryCli.Exec("bp", buildName, buildNumber)) + + // Get the published build info + publishedBuildInfo, found, err := tests.GetBuildInfo(serverDetails, buildName, buildNumber) + require.NoError(t, err, "Failed to get build info") + require.True(t, found, "build info should be found") + + // Verify build info has artifacts + require.Greater(t, len(publishedBuildInfo.BuildInfo.Modules), 0, "Build info should have modules") + + // Create service manager for getting artifact properties + serviceManager, err := utils.CreateServiceManager(serverDetails, 3, 1000, false) + require.NoError(t, err) + + // Verify VCS properties on each artifact from build info + artifactCount := 0 + propsValidatedCount := 0 + for _, module := range publishedBuildInfo.BuildInfo.Modules { + for _, artifact := range module.Artifacts { + artifactCount++ + if artifact.OriginalDeploymentRepo == "" { + continue // Skip artifacts without deployment repo info + } + fullPath := artifact.OriginalDeploymentRepo + "/" + artifact.Path + + props, err := serviceManager.GetItemProps(fullPath) + if err != nil { + t.Logf("Skipping artifact %s: could not get properties: %v", fullPath, err) + continue + } + if props == nil { + continue + } + + // Validate VCS properties if present + if _, ok := props.Properties["vcs.provider"]; ok { + assert.Contains(t, props.Properties["vcs.provider"], "github", "Wrong vcs.provider on %s", artifact.Name) + assert.Contains(t, props.Properties["vcs.org"], actualOrg, "Wrong vcs.org on %s", artifact.Name) + assert.Contains(t, props.Properties["vcs.repo"], actualRepo, "Wrong vcs.repo on %s", artifact.Name) + propsValidatedCount++ + } + } + } + + t.Logf("Helm build info: %d artifacts, %d with CI VCS properties validated", artifactCount, propsValidatedCount) + t.Logf("CI VCS environment: org=%s, repo=%s", actualOrg, actualRepo) + + // Validate that build info was created successfully + assert.NotEmpty(t, publishedBuildInfo.BuildInfo.Started, "Build info should have start time") + assert.Equal(t, buildName, publishedBuildInfo.BuildInfo.Name, "Build name should match") +} + // InitHelmTests initializes Helm tests func InitHelmTests() { initArtifactoryCli() diff --git a/nuget_test.go b/nuget_test.go index b54965706..7598a4797 100644 --- a/nuget_test.go +++ b/nuget_test.go @@ -475,3 +475,61 @@ func TestDotnetRequestedByDeterminism(t *testing.T) { t.Logf("Successfully verified RequestedBy determinism across %d runs", numRuns) cleanTestsHomeEnv() } + +// TestNugetBuildPublishWithCIVcsProps tests that CI VCS properties are set on NuGet artifacts +// when running build-publish in a CI environment (GitHub Actions). +// NuGet relies on build-publish to set CI VCS properties via batch AQL query. +// Note: NuGet packages are uploaded without properties; build-publish identifies +// artifacts from Build Info and applies properties in a single batch request. +func TestNugetBuildPublishWithCIVcsProps(t *testing.T) { + initNugetTest(t) + defer cleanTestsHomeEnv() + + buildName := tests.NuGetBuildName + "-civcs" + buildNumber := "1" + + // Setup GitHub Actions environment (uses real env vars on CI, mock values locally) + cleanupEnv, actualOrg, actualRepo := tests.SetupGitHubActionsEnv(t) + defer cleanupEnv() + + // Clean old build + inttestutils.DeleteBuild(serverDetails.ArtifactoryUrl, buildName, artHttpDetails) + defer inttestutils.DeleteBuild(serverDetails.ArtifactoryUrl, buildName, artHttpDetails) + + // Create NuGet project and config + projectPath := createNugetProject(t, "reference") + err := createConfigFileForTest([]string{projectPath}, tests.NugetRemoteRepo, "", t, project.Nuget, false) + require.NoError(t, err) + + wd, err := os.Getwd() + require.NoError(t, err) + chdirCallback := clientTestUtils.ChangeDirWithCallback(t, wd, projectPath) + defer chdirCallback() + + // Run NuGet restore with build info collection + args := []string{dotnetUtils.Nuget.String(), "restore"} + allowInsecureConnectionForTests(&args) + args = append(args, "--build-name="+buildName, "--build-number="+buildNumber) + + err = runNuGet(t, args...) + require.NoError(t, err) + + // Publish build info - should set CI VCS props on artifacts + require.NoError(t, artifactoryCli.Exec("bp", buildName, buildNumber)) + + // Get the published build info + publishedBuildInfo, found, err := tests.GetBuildInfo(serverDetails, buildName, buildNumber) + require.NoError(t, err) + require.True(t, found, "Build info was not found") + + // NuGet restore only has dependencies, not artifacts + // Verify build info was created successfully + require.NotEmpty(t, publishedBuildInfo.BuildInfo.Modules, "Build info should have modules") + require.Greater(t, len(publishedBuildInfo.BuildInfo.Modules[0].Dependencies), 0, "Build info should have dependencies") + + // Note: For NuGet, CI VCS properties are only applicable when there are artifacts (e.g., nuget push) + // This test verifies the build-info collection works correctly in CI environment + // The CI VCS properties will be set on artifacts when they are uploaded via build-publish + t.Logf("NuGet build info created with %d dependencies", len(publishedBuildInfo.BuildInfo.Modules[0].Dependencies)) + t.Logf("CI VCS environment validated: org=%s, repo=%s", actualOrg, actualRepo) +} diff --git a/pip_test.go b/pip_test.go index 5ba4af1ba..5c30c6f39 100644 --- a/pip_test.go +++ b/pip_test.go @@ -688,3 +688,86 @@ func TestSetupPipCommand(t *testing.T) { assert.Equal(t, http.StatusOK, res.StatusCode) } } + +// TestTwineBuildPublishWithCIVcsProps tests that CI VCS properties are set on Twine artifacts +// when running build-publish in a CI environment (GitHub Actions). +// Twine relies on build-publish to set CI VCS properties via batch AQL query. +func TestTwineBuildPublishWithCIVcsProps(t *testing.T) { + initPipTest(t) + + buildName := tests.PipBuildName + "-civcs" + buildNumber := "1" + + // Setup GitHub Actions environment (uses real env vars on CI, mock values locally) + cleanupEnv, actualOrg, actualRepo := tests.SetupGitHubActionsEnv(t) + defer cleanupEnv() + + // Populate cli config with 'default' server. + oldHomeDir, newHomeDir := prepareHomeDir(t) + defer func() { + clientTestUtils.SetEnvAndAssert(t, coreutils.HomeDir, oldHomeDir) + clientTestUtils.RemoveAllAndAssert(t, newHomeDir) + }() + + cleanVirtualEnv, err := prepareVirtualEnv(t) + assert.NoError(t, err) + defer cleanVirtualEnv() + + // Clean old build + inttestutils.DeleteBuild(serverDetails.ArtifactoryUrl, buildName, artHttpDetails) + defer inttestutils.DeleteBuild(serverDetails.ArtifactoryUrl, buildName, artHttpDetails) + + projectPath := createPypiProject(t, "twine-civcs", "pyproject", "twine") + + wd, err := os.Getwd() + assert.NoError(t, err, "Failed to get current dir") + chdirCallback := clientTestUtils.ChangeDirWithCallback(t, wd, projectPath) + defer chdirCallback() + + // Run twine upload with build info collection + jfrogCli := coretests.NewJfrogCli(execMain, "jfrog", "") + args := []string{"twine", "upload", "dist/*", "--build-name=" + buildName, "--build-number=" + buildNumber} + err = jfrogCli.Exec(args...) + assert.NoError(t, err, "Failed executing twine upload command") + + // Publish build info - should set CI VCS props on artifacts + assert.NoError(t, artifactoryCli.Exec("bp", buildName, buildNumber)) + + // Get the published build info to find artifact paths + publishedBuildInfo, found, err := tests.GetBuildInfo(serverDetails, buildName, buildNumber) + assert.NoError(t, err) + assert.True(t, found, "Build info was not found") + + // Create service manager for getting artifact properties + serviceManager, err := utils.CreateServiceManager(serverDetails, 3, 1000, false) + assert.NoError(t, err) + + // Verify VCS properties on each artifact from build info + artifactCount := 0 + for _, module := range publishedBuildInfo.BuildInfo.Modules { + for _, artifact := range module.Artifacts { + if artifact.OriginalDeploymentRepo == "" { + continue // Skip artifacts without deployment repo info + } + fullPath := artifact.OriginalDeploymentRepo + "/" + artifact.Path + + props, err := serviceManager.GetItemProps(fullPath) + assert.NoError(t, err, "Failed to get properties for artifact: %s", fullPath) + assert.NotNil(t, props, "Properties are nil for artifact: %s", fullPath) + + // Validate VCS properties + assert.Contains(t, props.Properties, "vcs.provider", "Missing vcs.provider on %s", artifact.Name) + assert.Contains(t, props.Properties["vcs.provider"], "github", "Wrong vcs.provider on %s", artifact.Name) + + assert.Contains(t, props.Properties, "vcs.org", "Missing vcs.org on %s", artifact.Name) + assert.Contains(t, props.Properties["vcs.org"], actualOrg, "Wrong vcs.org on %s", artifact.Name) + + assert.Contains(t, props.Properties, "vcs.repo", "Missing vcs.repo on %s", artifact.Name) + assert.Contains(t, props.Properties["vcs.repo"], actualRepo, "Wrong vcs.repo on %s", artifact.Name) + + artifactCount++ + } + } + + assert.Greater(t, artifactCount, 0, "No artifacts were validated for CI VCS properties") +} diff --git a/poetry_test.go b/poetry_test.go index 2c871c660..b50556d2c 100644 --- a/poetry_test.go +++ b/poetry_test.go @@ -12,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" "github.com/jfrog/jfrog-cli-core/v2/utils/coreutils" coretests "github.com/jfrog/jfrog-cli-core/v2/utils/tests" "github.com/jfrog/jfrog-client-go/http/httpclient" @@ -629,3 +630,92 @@ func TestPoetryFlexPackFeatures(t *testing.T) { inttestutils.DeleteBuild(serverDetails.ArtifactoryUrl, "poetry-checksum-test", artHttpDetails) }) } + +// TestPoetryBuildPublishWithCIVcsProps tests that CI VCS properties are set on Poetry artifacts +// when running build-publish in a CI environment (GitHub Actions). +// Poetry relies on build-publish to set CI VCS properties via batch AQL query. +func TestPoetryBuildPublishWithCIVcsProps(t *testing.T) { + initPoetryTest(t) + + buildName := tests.PoetryBuildName + "-civcs" + buildNumber := "1" + + // Setup GitHub Actions environment (uses real env vars on CI, mock values locally) + cleanupEnv, actualOrg, actualRepo := tests.SetupGitHubActionsEnv(t) + defer cleanupEnv() + + // Populate cli config with 'default' server + oldHomeDir, newHomeDir := prepareHomeDir(t) + defer func() { + clientTestUtils.SetEnvAndAssert(t, coreutils.HomeDir, oldHomeDir) + clientTestUtils.RemoveAllAndAssert(t, newHomeDir) + }() + + // Clean old build + inttestutils.DeleteBuild(serverDetails.ArtifactoryUrl, buildName, artHttpDetails) + defer inttestutils.DeleteBuild(serverDetails.ArtifactoryUrl, buildName, artHttpDetails) + + projectPath := createPoetryProject(t, "poetry-civcs", "poetryproject") + + wd, err := os.Getwd() + assert.NoError(t, err) + chdirCallback := clientTestUtils.ChangeDirWithCallback(t, wd, projectPath) + defer chdirCallback() + + // Build the package first + buildCmd := exec.Command("poetry", "build") + buildCmd.Dir = projectPath + assert.NoError(t, buildCmd.Run(), "Failed to build Poetry package") + + // Run poetry publish with build info collection + jfrogCli := coretests.NewJfrogCli(execMain, "jfrog", "") + args := []string{ + "poetry", "publish", + "--build-name=" + buildName, + "--build-number=" + buildNumber, + "--repository=" + tests.PoetryLocalRepo, + } + err = jfrogCli.Exec(args...) + assert.NoError(t, err, "Failed executing poetry publish command") + + // Publish build info - should set CI VCS props on artifacts + assert.NoError(t, artifactoryCli.Exec("bp", buildName, buildNumber)) + + // Get the published build info to find artifact paths + publishedBuildInfo, found, err := tests.GetBuildInfo(serverDetails, buildName, buildNumber) + assert.NoError(t, err) + assert.True(t, found, "Build info was not found") + + // Create service manager for getting artifact properties + serviceManager, err := utils.CreateServiceManager(serverDetails, 3, 1000, false) + assert.NoError(t, err) + + // Verify VCS properties on each artifact from build info + artifactCount := 0 + for _, module := range publishedBuildInfo.BuildInfo.Modules { + for _, artifact := range module.Artifacts { + if artifact.OriginalDeploymentRepo == "" { + continue // Skip artifacts without deployment repo info + } + fullPath := artifact.OriginalDeploymentRepo + "/" + artifact.Path + + props, err := serviceManager.GetItemProps(fullPath) + assert.NoError(t, err, "Failed to get properties for artifact: %s", fullPath) + assert.NotNil(t, props, "Properties are nil for artifact: %s", fullPath) + + // Validate VCS properties + assert.Contains(t, props.Properties, "vcs.provider", "Missing vcs.provider on %s", artifact.Name) + assert.Contains(t, props.Properties["vcs.provider"], "github", "Wrong vcs.provider on %s", artifact.Name) + + assert.Contains(t, props.Properties, "vcs.org", "Missing vcs.org on %s", artifact.Name) + assert.Contains(t, props.Properties["vcs.org"], actualOrg, "Wrong vcs.org on %s", artifact.Name) + + assert.Contains(t, props.Properties, "vcs.repo", "Missing vcs.repo on %s", artifact.Name) + assert.Contains(t, props.Properties["vcs.repo"], actualRepo, "Wrong vcs.repo on %s", artifact.Name) + + artifactCount++ + } + } + + assert.Greater(t, artifactCount, 0, "No artifacts were validated for CI VCS properties") +} From 41128b43b9e666587c05e699807802b415c66ec5 Mon Sep 17 00:00:00 2001 From: Bhanu Reddy Date: Sun, 1 Feb 2026 20:50:01 +0530 Subject: [PATCH 2/8] Updated tests for CI VCS properties --- conan_test.go | 25 ++++++++++++------------- go.mod | 4 +++- go.sum | 8 ++++---- helm_test.go | 34 ++++++++++++++-------------------- nuget_test.go | 31 ++++++++++++++++--------------- 5 files changed, 49 insertions(+), 53 deletions(-) diff --git a/conan_test.go b/conan_test.go index b674bd68f..6017c71e2 100644 --- a/conan_test.go +++ b/conan_test.go @@ -541,25 +541,24 @@ func TestConanBuildPublishWithCIVcsProps(t *testing.T) { fullPath := artifact.OriginalDeploymentRepo + "/" + artifact.Path props, err := serviceManager.GetItemProps(fullPath) - if err != nil { - t.Logf("Skipping artifact %s: could not get properties", fullPath) - continue - } + assert.NoError(t, err, "Failed to get properties for artifact: %s", fullPath) if props == nil { continue } // Validate VCS properties - if _, ok := props.Properties["vcs.provider"]; ok { - assert.Contains(t, props.Properties["vcs.provider"], "github", "Wrong vcs.provider on %s", artifact.Name) - assert.Contains(t, props.Properties["vcs.org"], actualOrg, "Wrong vcs.org on %s", artifact.Name) - assert.Contains(t, props.Properties["vcs.repo"], actualRepo, "Wrong vcs.repo on %s", artifact.Name) - artifactCount++ - } + assert.Contains(t, props.Properties, "vcs.provider", "Missing vcs.provider on %s", artifact.Name) + assert.Contains(t, props.Properties["vcs.provider"], "github", "Wrong vcs.provider on %s", artifact.Name) + + assert.Contains(t, props.Properties, "vcs.org", "Missing vcs.org on %s", artifact.Name) + assert.Contains(t, props.Properties["vcs.org"], actualOrg, "Wrong vcs.org on %s", artifact.Name) + + assert.Contains(t, props.Properties, "vcs.repo", "Missing vcs.repo on %s", artifact.Name) + assert.Contains(t, props.Properties["vcs.repo"], actualRepo, "Wrong vcs.repo on %s", artifact.Name) + + artifactCount++ } } - // Log summary - t.Logf("Conan build info created with CI VCS properties validated on %d artifacts", artifactCount) - t.Logf("CI VCS environment validated: org=%s, repo=%s", actualOrg, actualRepo) + assert.Greater(t, artifactCount, 0, "No artifacts were validated for CI VCS properties") } diff --git a/go.mod b/go.mod index 756aa3ca5..da4c97902 100644 --- a/go.mod +++ b/go.mod @@ -24,7 +24,7 @@ require ( github.com/jfrog/jfrog-cli-evidence v0.8.3-0.20251225153025-9d8ac181d615 github.com/jfrog/jfrog-cli-platform-services v1.10.1-0.20251205121610-171eb9b0000e github.com/jfrog/jfrog-cli-security v1.26.0 - github.com/jfrog/jfrog-client-go v1.55.1-0.20260121110006-56e09db08899 + github.com/jfrog/jfrog-client-go v1.55.1-0.20260128141727-bd34d78a3e48 github.com/jszwec/csvutil v1.10.0 github.com/manifoldco/promptui v0.9.0 github.com/spf13/viper v1.21.0 @@ -293,3 +293,5 @@ replace github.com/gfleury/go-bitbucket-v1 => github.com/gfleury/go-bitbucket-v1 // replace github.com/jfrog/jfrog-cli-security => github.com/jfrog/jfrog-cli-security dev // replace github.com/jfrog/build-info-go => github.com/reshmifrog/build-info-go v1.8.9-0.20260106113011-c7f131cea484 + +replace github.com/jfrog/jfrog-cli-artifactory => github.com/bhanurp/jfrog-cli-artifactory v0.1.12-0.20260201151210-3c89ffbf853f diff --git a/go.sum b/go.sum index dc7d41e82..32409cbb1 100644 --- a/go.sum +++ b/go.sum @@ -729,6 +729,8 @@ github.com/beevik/etree v1.6.0 h1:u8Kwy8pp9D9XeITj2Z0XtA5qqZEmtJtuXZRQi+j03eE= github.com/beevik/etree v1.6.0/go.mod h1:bh4zJxiIr62SOf9pRzN7UUYaEDa9HEKafK25+sLc0Gc= github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= +github.com/bhanurp/jfrog-cli-artifactory v0.1.12-0.20260201151210-3c89ffbf853f h1:umzXy09/0SW8SKqSGjtKoiLoeKxp7V58Qgi7D2kLC9M= +github.com/bhanurp/jfrog-cli-artifactory v0.1.12-0.20260201151210-3c89ffbf853f/go.mod h1:+3MYwa3NE2GR10uegJTdfKKvVXURXftN6N3/45OipRM= github.com/blang/semver v3.5.1+incompatible h1:cQNTCjp13qL8KC3Nbxr/y2Bqb63oX6wdnnjpJbkM4JQ= github.com/blang/semver v3.5.1+incompatible/go.mod h1:kRBLl5iJ+tD4TcOOxsy/0fnwebNt5EWlYSAyrTnjyyk= github.com/boombuler/barcode v1.0.0/go.mod h1:paBWMcWSl3LHKBqUq+rly7CNSldXjb2rDl3JlRe0mD8= @@ -1216,8 +1218,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.20260107143435-b30ede954432 h1:6eOOs+326IrWLVA+ghDDudJmN3Nt8lxPl11eOu8vtPE= github.com/jfrog/jfrog-cli-application v1.0.2-0.20260107143435-b30ede954432/go.mod h1:xum2HquWO5uExa/A7MQs3TgJJVEeoqTR+6Z4mfBr1Xw= -github.com/jfrog/jfrog-cli-artifactory v0.8.1-0.20260129054930-035e3ed7e30d h1:jyBD9kqAL8eHerZvGmxiTZECA+sYuH3TpodGnnpnPSs= -github.com/jfrog/jfrog-cli-artifactory v0.8.1-0.20260129054930-035e3ed7e30d/go.mod h1:ANFZOB4AX+Voo24l1BO8bVvN76m3ZViR1QaK5u3QDgE= github.com/jfrog/jfrog-cli-core/v2 v2.60.1-0.20260112010739-87fc7275623c h1:K9anqOZ7ASxlsijsl9u4jh92wqqIvJA4kTYfXrcOmJA= github.com/jfrog/jfrog-cli-core/v2 v2.60.1-0.20260112010739-87fc7275623c/go.mod h1:+Hnaikp/xCSPD/q7txxRy4Zc0wzjW/usrCSf+6uONSQ= github.com/jfrog/jfrog-cli-evidence v0.8.3-0.20251225153025-9d8ac181d615 h1:y5an0bojHL00ipHP1QuBUrVcP+XK+yZHHOJ/r1I0RUM= @@ -1226,8 +1226,8 @@ github.com/jfrog/jfrog-cli-platform-services v1.10.1-0.20251205121610-171eb9b000 github.com/jfrog/jfrog-cli-platform-services v1.10.1-0.20251205121610-171eb9b0000e/go.mod h1:qbu4iqBST9x8LgD8HhzUm91iOB3vHqtoGmaxOnmw0ok= github.com/jfrog/jfrog-cli-security v1.26.0 h1:FcLshS1Ahm0++nV5q7UluFTCVRxH2wEIbqO7ZBag++I= github.com/jfrog/jfrog-cli-security v1.26.0/go.mod h1:r9E0BdlNy6mq6gkRGslZRZaYe6WeGhLkpUm8+oEUOvU= -github.com/jfrog/jfrog-client-go v1.55.1-0.20260121110006-56e09db08899 h1:b6DzkI3qCVUHiErnFDajICW6k1RAuXVe69AsGq2AunE= -github.com/jfrog/jfrog-client-go v1.55.1-0.20260121110006-56e09db08899/go.mod h1:sCE06+GngPoyrGO0c+vmhgMoVSP83UMNiZnIuNPzU8U= +github.com/jfrog/jfrog-client-go v1.55.1-0.20260128141727-bd34d78a3e48 h1:HY4b9DsUe0Lox1rScYHKmfIZY9PQvy0kfkOefqc/QdQ= +github.com/jfrog/jfrog-client-go v1.55.1-0.20260128141727-bd34d78a3e48/go.mod h1:sCE06+GngPoyrGO0c+vmhgMoVSP83UMNiZnIuNPzU8U= 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/helm_test.go b/helm_test.go index a1014d157..e7fdc36b3 100644 --- a/helm_test.go +++ b/helm_test.go @@ -824,7 +824,7 @@ func TestHelmBuildPublishWithCIVcsProps(t *testing.T) { inttestutils.DeleteBuild(serverDetails.ArtifactoryUrl, buildName, artHttpDetails) defer inttestutils.DeleteBuild(serverDetails.ArtifactoryUrl, buildName, artHttpDetails) - chartDir := createTestHelmChartWithDependencies(t, "test-chart-civcs", "0.1.0") + chartDir := createTestHelmChartWithDependencies(t, "test-chart-civcs", "0.2.0") defer func() { if err := os.RemoveAll(chartDir); err != nil { t.Logf("Warning: Failed to remove test chart directory %s: %v", chartDir, err) @@ -922,40 +922,34 @@ func TestHelmBuildPublishWithCIVcsProps(t *testing.T) { // Verify VCS properties on each artifact from build info artifactCount := 0 - propsValidatedCount := 0 for _, module := range publishedBuildInfo.BuildInfo.Modules { for _, artifact := range module.Artifacts { - artifactCount++ if artifact.OriginalDeploymentRepo == "" { continue // Skip artifacts without deployment repo info } fullPath := artifact.OriginalDeploymentRepo + "/" + artifact.Path props, err := serviceManager.GetItemProps(fullPath) - if err != nil { - t.Logf("Skipping artifact %s: could not get properties: %v", fullPath, err) - continue - } + assert.NoError(t, err, "Failed to get properties for artifact: %s", fullPath) if props == nil { continue } - // Validate VCS properties if present - if _, ok := props.Properties["vcs.provider"]; ok { - assert.Contains(t, props.Properties["vcs.provider"], "github", "Wrong vcs.provider on %s", artifact.Name) - assert.Contains(t, props.Properties["vcs.org"], actualOrg, "Wrong vcs.org on %s", artifact.Name) - assert.Contains(t, props.Properties["vcs.repo"], actualRepo, "Wrong vcs.repo on %s", artifact.Name) - propsValidatedCount++ - } + // Validate VCS properties + assert.Contains(t, props.Properties, "vcs.provider", "Missing vcs.provider on %s", artifact.Name) + assert.Contains(t, props.Properties["vcs.provider"], "github", "Wrong vcs.provider on %s", artifact.Name) + + assert.Contains(t, props.Properties, "vcs.org", "Missing vcs.org on %s", artifact.Name) + assert.Contains(t, props.Properties["vcs.org"], actualOrg, "Wrong vcs.org on %s", artifact.Name) + + assert.Contains(t, props.Properties, "vcs.repo", "Missing vcs.repo on %s", artifact.Name) + assert.Contains(t, props.Properties["vcs.repo"], actualRepo, "Wrong vcs.repo on %s", artifact.Name) + + artifactCount++ } } - t.Logf("Helm build info: %d artifacts, %d with CI VCS properties validated", artifactCount, propsValidatedCount) - t.Logf("CI VCS environment: org=%s, repo=%s", actualOrg, actualRepo) - - // Validate that build info was created successfully - assert.NotEmpty(t, publishedBuildInfo.BuildInfo.Started, "Build info should have start time") - assert.Equal(t, buildName, publishedBuildInfo.BuildInfo.Name, "Build name should match") + assert.Greater(t, artifactCount, 0, "No artifacts were validated for CI VCS properties") } // InitHelmTests initializes Helm tests diff --git a/nuget_test.go b/nuget_test.go index 7598a4797..bc500c0e8 100644 --- a/nuget_test.go +++ b/nuget_test.go @@ -476,11 +476,11 @@ func TestDotnetRequestedByDeterminism(t *testing.T) { cleanTestsHomeEnv() } -// TestNugetBuildPublishWithCIVcsProps tests that CI VCS properties are set on NuGet artifacts -// when running build-publish in a CI environment (GitHub Actions). -// NuGet relies on build-publish to set CI VCS properties via batch AQL query. -// Note: NuGet packages are uploaded without properties; build-publish identifies -// artifacts from Build Info and applies properties in a single batch request. +// TestNugetBuildPublishWithCIVcsProps tests that CI VCS properties integration works +// with NuGet in a CI environment (GitHub Actions). +// Note: NuGet restore only has dependencies (not artifacts), so this test validates +// that build-info collection works correctly in CI environment. CI VCS properties +// are set on artifacts via build-publish when packages are pushed (nuget push). func TestNugetBuildPublishWithCIVcsProps(t *testing.T) { initNugetTest(t) defer cleanTestsHomeEnv() @@ -514,7 +514,7 @@ func TestNugetBuildPublishWithCIVcsProps(t *testing.T) { err = runNuGet(t, args...) require.NoError(t, err) - // Publish build info - should set CI VCS props on artifacts + // Publish build info require.NoError(t, artifactoryCli.Exec("bp", buildName, buildNumber)) // Get the published build info @@ -522,14 +522,15 @@ func TestNugetBuildPublishWithCIVcsProps(t *testing.T) { require.NoError(t, err) require.True(t, found, "Build info was not found") - // NuGet restore only has dependencies, not artifacts - // Verify build info was created successfully + // Validate build info was created correctly require.NotEmpty(t, publishedBuildInfo.BuildInfo.Modules, "Build info should have modules") - require.Greater(t, len(publishedBuildInfo.BuildInfo.Modules[0].Dependencies), 0, "Build info should have dependencies") - - // Note: For NuGet, CI VCS properties are only applicable when there are artifacts (e.g., nuget push) - // This test verifies the build-info collection works correctly in CI environment - // The CI VCS properties will be set on artifacts when they are uploaded via build-publish - t.Logf("NuGet build info created with %d dependencies", len(publishedBuildInfo.BuildInfo.Modules[0].Dependencies)) - t.Logf("CI VCS environment validated: org=%s, repo=%s", actualOrg, actualRepo) + assert.Greater(t, len(publishedBuildInfo.BuildInfo.Modules[0].Dependencies), 0, "Build info should have dependencies") + assert.Equal(t, buildName, publishedBuildInfo.BuildInfo.Name, "Build name should match") + assert.Equal(t, buildNumber, publishedBuildInfo.BuildInfo.Number, "Build number should match") + + // Verify CI environment was detected (for nuget push scenarios, CI VCS props would be set) + assert.NotEmpty(t, actualOrg, "CI org should be detected") + assert.NotEmpty(t, actualRepo, "CI repo should be detected") + t.Logf("NuGet build info created with %d dependencies in CI environment (org=%s, repo=%s)", + len(publishedBuildInfo.BuildInfo.Modules[0].Dependencies), actualOrg, actualRepo) } From 3b7bf61b0314fc93df12e2fcdb92d2811b6db515 Mon Sep 17 00:00:00 2001 From: Bhanu Reddy Date: Sun, 1 Feb 2026 20:55:19 +0530 Subject: [PATCH 3/8] UPdated dependencies --- go.sum | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/go.sum b/go.sum index 1131ac520..6e5fdaaed 100644 --- a/go.sum +++ b/go.sum @@ -1218,12 +1218,12 @@ github.com/jfrog/gofrog v1.7.6 h1:QmfAiRzVyaI7JYGsB7cxfAJePAZTzFz0gRWZSE27c6s= github.com/jfrog/gofrog v1.7.6/go.mod h1:ntr1txqNOZtHplmaNd7rS4f8jpA5Apx8em70oYEe7+4= 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-application v1.0.2-0.20260107143435-b30ede954432 h1:6eOOs+326IrWLVA+ghDDudJmN3Nt8lxPl11eOu8vtPE= -github.com/jfrog/jfrog-cli-application v1.0.2-0.20260107143435-b30ede954432/go.mod h1:xum2HquWO5uExa/A7MQs3TgJJVEeoqTR+6Z4mfBr1Xw= -github.com/jfrog/jfrog-cli-core/v2 v2.60.1-0.20260112010739-87fc7275623c h1:K9anqOZ7ASxlsijsl9u4jh92wqqIvJA4kTYfXrcOmJA= -github.com/jfrog/jfrog-cli-core/v2 v2.60.1-0.20260112010739-87fc7275623c/go.mod h1:+Hnaikp/xCSPD/q7txxRy4Zc0wzjW/usrCSf+6uONSQ= -github.com/jfrog/jfrog-cli-evidence v0.8.3-0.20251225153025-9d8ac181d615 h1:y5an0bojHL00ipHP1QuBUrVcP+XK+yZHHOJ/r1I0RUM= -github.com/jfrog/jfrog-cli-evidence v0.8.3-0.20251225153025-9d8ac181d615/go.mod h1:Ijx7tkTp6uDxgmQW+zQKLNztMrz6dcQAoVNXHL7spsU= +github.com/jfrog/jfrog-cli-application v1.0.2-0.20260127112223-c5078af84b5a h1:Yvl7XuMoI1cXk3jzB1oWcZvFy5K3aUAIin9o5GRaqzE= +github.com/jfrog/jfrog-cli-application v1.0.2-0.20260127112223-c5078af84b5a/go.mod h1:xum2HquWO5uExa/A7MQs3TgJJVEeoqTR+6Z4mfBr1Xw= +github.com/jfrog/jfrog-cli-core/v2 v2.60.1-0.20260128134755-624b659a398e h1:jGtYjWMMfCINDl1JbRtvAijtVwD+j+yvR5BuYMZvRrA= +github.com/jfrog/jfrog-cli-core/v2 v2.60.1-0.20260128134755-624b659a398e/go.mod h1:+Hnaikp/xCSPD/q7txxRy4Zc0wzjW/usrCSf+6uONSQ= +github.com/jfrog/jfrog-cli-evidence v0.8.3-0.20260125120022-1c6f4f382dbb h1:4nGzxRxVcXxkFg95jr+zMjESisZGqSYecXfHsA37rpA= +github.com/jfrog/jfrog-cli-evidence v0.8.3-0.20260125120022-1c6f4f382dbb/go.mod h1:+nU35Jkm9EZfRSP/cgZMVnGI7+BLXn9CeUlnxEx052I= 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.26.0 h1:FcLshS1Ahm0++nV5q7UluFTCVRxH2wEIbqO7ZBag++I= From 73a8934271743181628b13bf01d4866becb209e4 Mon Sep 17 00:00:00 2001 From: Bhanu Reddy Date: Mon, 2 Feb 2026 13:13:56 +0530 Subject: [PATCH 4/8] Fixed conan and other test to mirror CI VCS prop setting logic --- conan_test.go | 12 +++++++++--- go.mod | 2 +- go.sum | 4 ++-- go_test.go | 11 ++++++++--- helm_test.go | 11 ++++++++--- pip_test.go | 11 ++++++++--- poetry_test.go | 11 ++++++++--- 7 files changed, 44 insertions(+), 18 deletions(-) diff --git a/conan_test.go b/conan_test.go index 6017c71e2..34e66c851 100644 --- a/conan_test.go +++ b/conan_test.go @@ -532,13 +532,19 @@ func TestConanBuildPublishWithCIVcsProps(t *testing.T) { require.NoError(t, err) // Verify VCS properties on each artifact from build info + // Note: Conan artifacts may not have OriginalDeploymentRepo set, so we use Path directly as fallback artifactCount := 0 for _, module := range publishedBuildInfo.BuildInfo.Modules { for _, artifact := range module.Artifacts { - if artifact.OriginalDeploymentRepo == "" { - continue // Skip artifacts without deployment repo info + // Use same fallback logic as CI VCS: OriginalDeploymentRepo + Path, or Path directly + var fullPath string + if artifact.OriginalDeploymentRepo != "" { + fullPath = artifact.OriginalDeploymentRepo + "/" + artifact.Path + } else if artifact.Path != "" { + fullPath = artifact.Path + } else { + continue // Skip artifacts without any path info } - fullPath := artifact.OriginalDeploymentRepo + "/" + artifact.Path props, err := serviceManager.GetItemProps(fullPath) assert.NoError(t, err, "Failed to get properties for artifact: %s", fullPath) diff --git a/go.mod b/go.mod index ea6309926..468167aa8 100644 --- a/go.mod +++ b/go.mod @@ -294,4 +294,4 @@ replace github.com/gfleury/go-bitbucket-v1 => github.com/gfleury/go-bitbucket-v1 // replace github.com/jfrog/build-info-go => github.com/reshmifrog/build-info-go v1.8.9-0.20260106113011-c7f131cea484 -replace github.com/jfrog/jfrog-cli-artifactory => github.com/bhanurp/jfrog-cli-artifactory v0.1.12-0.20260201151210-3c89ffbf853f +replace github.com/jfrog/jfrog-cli-artifactory => github.com/bhanurp/jfrog-cli-artifactory v0.1.12-0.20260202074034-d6aeb3259fcd diff --git a/go.sum b/go.sum index 6e5fdaaed..4b7dd19de 100644 --- a/go.sum +++ b/go.sum @@ -731,8 +731,8 @@ github.com/beevik/etree v1.6.0 h1:u8Kwy8pp9D9XeITj2Z0XtA5qqZEmtJtuXZRQi+j03eE= github.com/beevik/etree v1.6.0/go.mod h1:bh4zJxiIr62SOf9pRzN7UUYaEDa9HEKafK25+sLc0Gc= github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= -github.com/bhanurp/jfrog-cli-artifactory v0.1.12-0.20260201151210-3c89ffbf853f h1:umzXy09/0SW8SKqSGjtKoiLoeKxp7V58Qgi7D2kLC9M= -github.com/bhanurp/jfrog-cli-artifactory v0.1.12-0.20260201151210-3c89ffbf853f/go.mod h1:+3MYwa3NE2GR10uegJTdfKKvVXURXftN6N3/45OipRM= +github.com/bhanurp/jfrog-cli-artifactory v0.1.12-0.20260202074034-d6aeb3259fcd h1:197DmaDhMAVfdv0tI14dcsSAMhUH+X2ShWvN7rlaa94= +github.com/bhanurp/jfrog-cli-artifactory v0.1.12-0.20260202074034-d6aeb3259fcd/go.mod h1:+3MYwa3NE2GR10uegJTdfKKvVXURXftN6N3/45OipRM= github.com/blang/semver v3.5.1+incompatible h1:cQNTCjp13qL8KC3Nbxr/y2Bqb63oX6wdnnjpJbkM4JQ= github.com/blang/semver v3.5.1+incompatible/go.mod h1:kRBLl5iJ+tD4TcOOxsy/0fnwebNt5EWlYSAyrTnjyyk= github.com/boombuler/barcode v1.0.0/go.mod h1:paBWMcWSl3LHKBqUq+rly7CNSldXjb2rDl3JlRe0mD8= diff --git a/go_test.go b/go_test.go index 23d134e7b..91b191792 100644 --- a/go_test.go +++ b/go_test.go @@ -469,13 +469,18 @@ func TestGoBuildPublishWithCIVcsProps(t *testing.T) { assert.NoError(t, err) // Verify VCS properties on each artifact from build info + // Use same fallback logic as CI VCS: OriginalDeploymentRepo + Path, or Path directly artifactCount := 0 for _, module := range publishedBuildInfo.BuildInfo.Modules { for _, artifact := range module.Artifacts { - if artifact.OriginalDeploymentRepo == "" { - continue // Skip artifacts without deployment repo info + var fullPath string + if artifact.OriginalDeploymentRepo != "" { + fullPath = artifact.OriginalDeploymentRepo + "/" + artifact.Path + } else if artifact.Path != "" { + fullPath = artifact.Path + } else { + continue // Skip artifacts without any path info } - fullPath := artifact.OriginalDeploymentRepo + "/" + artifact.Path props, err := serviceManager.GetItemProps(fullPath) assert.NoError(t, err, "Failed to get properties for artifact: %s", fullPath) diff --git a/helm_test.go b/helm_test.go index e7fdc36b3..0171ef278 100644 --- a/helm_test.go +++ b/helm_test.go @@ -921,13 +921,18 @@ func TestHelmBuildPublishWithCIVcsProps(t *testing.T) { require.NoError(t, err) // Verify VCS properties on each artifact from build info + // Use same fallback logic as CI VCS: OriginalDeploymentRepo + Path, or Path directly artifactCount := 0 for _, module := range publishedBuildInfo.BuildInfo.Modules { for _, artifact := range module.Artifacts { - if artifact.OriginalDeploymentRepo == "" { - continue // Skip artifacts without deployment repo info + var fullPath string + if artifact.OriginalDeploymentRepo != "" { + fullPath = artifact.OriginalDeploymentRepo + "/" + artifact.Path + } else if artifact.Path != "" { + fullPath = artifact.Path + } else { + continue // Skip artifacts without any path info } - fullPath := artifact.OriginalDeploymentRepo + "/" + artifact.Path props, err := serviceManager.GetItemProps(fullPath) assert.NoError(t, err, "Failed to get properties for artifact: %s", fullPath) diff --git a/pip_test.go b/pip_test.go index 5c30c6f39..ad0bd0497 100644 --- a/pip_test.go +++ b/pip_test.go @@ -743,13 +743,18 @@ func TestTwineBuildPublishWithCIVcsProps(t *testing.T) { assert.NoError(t, err) // Verify VCS properties on each artifact from build info + // Use same fallback logic as CI VCS: OriginalDeploymentRepo + Path, or Path directly artifactCount := 0 for _, module := range publishedBuildInfo.BuildInfo.Modules { for _, artifact := range module.Artifacts { - if artifact.OriginalDeploymentRepo == "" { - continue // Skip artifacts without deployment repo info + var fullPath string + if artifact.OriginalDeploymentRepo != "" { + fullPath = artifact.OriginalDeploymentRepo + "/" + artifact.Path + } else if artifact.Path != "" { + fullPath = artifact.Path + } else { + continue // Skip artifacts without any path info } - fullPath := artifact.OriginalDeploymentRepo + "/" + artifact.Path props, err := serviceManager.GetItemProps(fullPath) assert.NoError(t, err, "Failed to get properties for artifact: %s", fullPath) diff --git a/poetry_test.go b/poetry_test.go index b50556d2c..7a7a874d7 100644 --- a/poetry_test.go +++ b/poetry_test.go @@ -691,13 +691,18 @@ func TestPoetryBuildPublishWithCIVcsProps(t *testing.T) { assert.NoError(t, err) // Verify VCS properties on each artifact from build info + // Use same fallback logic as CI VCS: OriginalDeploymentRepo + Path, or Path directly artifactCount := 0 for _, module := range publishedBuildInfo.BuildInfo.Modules { for _, artifact := range module.Artifacts { - if artifact.OriginalDeploymentRepo == "" { - continue // Skip artifacts without deployment repo info + var fullPath string + if artifact.OriginalDeploymentRepo != "" { + fullPath = artifact.OriginalDeploymentRepo + "/" + artifact.Path + } else if artifact.Path != "" { + fullPath = artifact.Path + } else { + continue // Skip artifacts without any path info } - fullPath := artifact.OriginalDeploymentRepo + "/" + artifact.Path props, err := serviceManager.GetItemProps(fullPath) assert.NoError(t, err, "Failed to get properties for artifact: %s", fullPath) From 7fcee13f99fb633df93a0912a3b6090aff35176d Mon Sep 17 00:00:00 2001 From: Bhanu Reddy Date: Mon, 2 Feb 2026 13:21:23 +0530 Subject: [PATCH 5/8] Fixed static violations --- conan_test.go | 7 ++++--- go.mod | 2 -- go_test.go | 7 ++++--- helm_test.go | 7 ++++--- 4 files changed, 12 insertions(+), 11 deletions(-) diff --git a/conan_test.go b/conan_test.go index 34e66c851..fc8bee20a 100644 --- a/conan_test.go +++ b/conan_test.go @@ -538,11 +538,12 @@ func TestConanBuildPublishWithCIVcsProps(t *testing.T) { for _, artifact := range module.Artifacts { // Use same fallback logic as CI VCS: OriginalDeploymentRepo + Path, or Path directly var fullPath string - if artifact.OriginalDeploymentRepo != "" { + switch { + case artifact.OriginalDeploymentRepo != "": fullPath = artifact.OriginalDeploymentRepo + "/" + artifact.Path - } else if artifact.Path != "" { + case artifact.Path != "": fullPath = artifact.Path - } else { + default: continue // Skip artifacts without any path info } diff --git a/go.mod b/go.mod index 468167aa8..7e7d44c68 100644 --- a/go.mod +++ b/go.mod @@ -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/jfrog-cli-core/v2 => ../jfrog-cli-core - //replace github.com/jfrog/build-info-go => github.com/fluxxBot/build-info-go v1.10.10-0.20260105070825-d3f36f619ba5 //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_test.go b/go_test.go index 91b191792..1c9a2e304 100644 --- a/go_test.go +++ b/go_test.go @@ -474,11 +474,12 @@ func TestGoBuildPublishWithCIVcsProps(t *testing.T) { for _, module := range publishedBuildInfo.BuildInfo.Modules { for _, artifact := range module.Artifacts { var fullPath string - if artifact.OriginalDeploymentRepo != "" { + switch { + case artifact.OriginalDeploymentRepo != "": fullPath = artifact.OriginalDeploymentRepo + "/" + artifact.Path - } else if artifact.Path != "" { + case artifact.Path != "": fullPath = artifact.Path - } else { + default: continue // Skip artifacts without any path info } diff --git a/helm_test.go b/helm_test.go index 0171ef278..279e4f069 100644 --- a/helm_test.go +++ b/helm_test.go @@ -926,11 +926,12 @@ func TestHelmBuildPublishWithCIVcsProps(t *testing.T) { for _, module := range publishedBuildInfo.BuildInfo.Modules { for _, artifact := range module.Artifacts { var fullPath string - if artifact.OriginalDeploymentRepo != "" { + switch { + case artifact.OriginalDeploymentRepo != "": fullPath = artifact.OriginalDeploymentRepo + "/" + artifact.Path - } else if artifact.Path != "" { + case artifact.Path != "": fullPath = artifact.Path - } else { + default: continue // Skip artifacts without any path info } From 2273195319c8dde9b53928a5e9e548f080cdef78 Mon Sep 17 00:00:00 2001 From: Bhanu Reddy Date: Mon, 2 Feb 2026 13:53:01 +0530 Subject: [PATCH 6/8] Fixed static violations --- pip_test.go | 7 ++++--- poetry_test.go | 7 ++++--- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/pip_test.go b/pip_test.go index ad0bd0497..4ee8ac9d6 100644 --- a/pip_test.go +++ b/pip_test.go @@ -748,11 +748,12 @@ func TestTwineBuildPublishWithCIVcsProps(t *testing.T) { for _, module := range publishedBuildInfo.BuildInfo.Modules { for _, artifact := range module.Artifacts { var fullPath string - if artifact.OriginalDeploymentRepo != "" { + switch { + case artifact.OriginalDeploymentRepo != "": fullPath = artifact.OriginalDeploymentRepo + "/" + artifact.Path - } else if artifact.Path != "" { + case artifact.Path != "": fullPath = artifact.Path - } else { + default: continue // Skip artifacts without any path info } diff --git a/poetry_test.go b/poetry_test.go index 7a7a874d7..0c6c54e37 100644 --- a/poetry_test.go +++ b/poetry_test.go @@ -696,11 +696,12 @@ func TestPoetryBuildPublishWithCIVcsProps(t *testing.T) { for _, module := range publishedBuildInfo.BuildInfo.Modules { for _, artifact := range module.Artifacts { var fullPath string - if artifact.OriginalDeploymentRepo != "" { + switch { + case artifact.OriginalDeploymentRepo != "": fullPath = artifact.OriginalDeploymentRepo + "/" + artifact.Path - } else if artifact.Path != "" { + case artifact.Path != "": fullPath = artifact.Path - } else { + default: continue // Skip artifacts without any path info } From cdd6951df7c87b3597600e76b00e01cae063a4b2 Mon Sep 17 00:00:00 2001 From: Bhanu Reddy Date: Wed, 4 Feb 2026 16:15:12 +0530 Subject: [PATCH 7/8] Updated dependencies --- go.mod | 6 ++---- go.sum | 8 ++++---- 2 files changed, 6 insertions(+), 8 deletions(-) diff --git a/go.mod b/go.mod index 7e7d44c68..315665469 100644 --- a/go.mod +++ b/go.mod @@ -19,12 +19,12 @@ require ( github.com/jfrog/build-info-go v1.13.1-0.20260130140656-2d0d5593fccf github.com/jfrog/gofrog v1.7.6 github.com/jfrog/jfrog-cli-application v1.0.2-0.20260127112223-c5078af84b5a - github.com/jfrog/jfrog-cli-artifactory v0.8.1-0.20260129054930-035e3ed7e30d + github.com/jfrog/jfrog-cli-artifactory v0.8.1-0.20260204081838-6bfbb967f10c github.com/jfrog/jfrog-cli-core/v2 v2.60.1-0.20260128134755-624b659a398e github.com/jfrog/jfrog-cli-evidence v0.8.3-0.20260125120022-1c6f4f382dbb github.com/jfrog/jfrog-cli-platform-services v1.10.1-0.20251205121610-171eb9b0000e github.com/jfrog/jfrog-cli-security v1.26.0 - github.com/jfrog/jfrog-client-go v1.55.1-0.20260128141727-bd34d78a3e48 + github.com/jfrog/jfrog-client-go v1.55.1-0.20260201135506-ffd03518ef56 github.com/jszwec/csvutil v1.10.0 github.com/manifoldco/promptui v0.9.0 github.com/spf13/viper v1.21.0 @@ -291,5 +291,3 @@ replace github.com/gfleury/go-bitbucket-v1 => github.com/gfleury/go-bitbucket-v1 // replace github.com/jfrog/jfrog-cli-security => github.com/jfrog/jfrog-cli-security dev // replace github.com/jfrog/build-info-go => github.com/reshmifrog/build-info-go v1.8.9-0.20260106113011-c7f131cea484 - -replace github.com/jfrog/jfrog-cli-artifactory => github.com/bhanurp/jfrog-cli-artifactory v0.1.12-0.20260202074034-d6aeb3259fcd diff --git a/go.sum b/go.sum index 4b7dd19de..083ae23a7 100644 --- a/go.sum +++ b/go.sum @@ -731,8 +731,6 @@ github.com/beevik/etree v1.6.0 h1:u8Kwy8pp9D9XeITj2Z0XtA5qqZEmtJtuXZRQi+j03eE= github.com/beevik/etree v1.6.0/go.mod h1:bh4zJxiIr62SOf9pRzN7UUYaEDa9HEKafK25+sLc0Gc= github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= -github.com/bhanurp/jfrog-cli-artifactory v0.1.12-0.20260202074034-d6aeb3259fcd h1:197DmaDhMAVfdv0tI14dcsSAMhUH+X2ShWvN7rlaa94= -github.com/bhanurp/jfrog-cli-artifactory v0.1.12-0.20260202074034-d6aeb3259fcd/go.mod h1:+3MYwa3NE2GR10uegJTdfKKvVXURXftN6N3/45OipRM= github.com/blang/semver v3.5.1+incompatible h1:cQNTCjp13qL8KC3Nbxr/y2Bqb63oX6wdnnjpJbkM4JQ= github.com/blang/semver v3.5.1+incompatible/go.mod h1:kRBLl5iJ+tD4TcOOxsy/0fnwebNt5EWlYSAyrTnjyyk= github.com/boombuler/barcode v1.0.0/go.mod h1:paBWMcWSl3LHKBqUq+rly7CNSldXjb2rDl3JlRe0mD8= @@ -1220,6 +1218,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.20260127112223-c5078af84b5a h1:Yvl7XuMoI1cXk3jzB1oWcZvFy5K3aUAIin9o5GRaqzE= github.com/jfrog/jfrog-cli-application v1.0.2-0.20260127112223-c5078af84b5a/go.mod h1:xum2HquWO5uExa/A7MQs3TgJJVEeoqTR+6Z4mfBr1Xw= +github.com/jfrog/jfrog-cli-artifactory v0.8.1-0.20260204081838-6bfbb967f10c h1:u7zOF0Ph9VTjnqjK939tziDSQoinK8VZK/05MEmLZFs= +github.com/jfrog/jfrog-cli-artifactory v0.8.1-0.20260204081838-6bfbb967f10c/go.mod h1:DkLAN+AvZ4v6jcuUStufi9DuhAS1dvSRJhILJyRa9kg= github.com/jfrog/jfrog-cli-core/v2 v2.60.1-0.20260128134755-624b659a398e h1:jGtYjWMMfCINDl1JbRtvAijtVwD+j+yvR5BuYMZvRrA= github.com/jfrog/jfrog-cli-core/v2 v2.60.1-0.20260128134755-624b659a398e/go.mod h1:+Hnaikp/xCSPD/q7txxRy4Zc0wzjW/usrCSf+6uONSQ= github.com/jfrog/jfrog-cli-evidence v0.8.3-0.20260125120022-1c6f4f382dbb h1:4nGzxRxVcXxkFg95jr+zMjESisZGqSYecXfHsA37rpA= @@ -1228,8 +1228,8 @@ github.com/jfrog/jfrog-cli-platform-services v1.10.1-0.20251205121610-171eb9b000 github.com/jfrog/jfrog-cli-platform-services v1.10.1-0.20251205121610-171eb9b0000e/go.mod h1:qbu4iqBST9x8LgD8HhzUm91iOB3vHqtoGmaxOnmw0ok= github.com/jfrog/jfrog-cli-security v1.26.0 h1:FcLshS1Ahm0++nV5q7UluFTCVRxH2wEIbqO7ZBag++I= github.com/jfrog/jfrog-cli-security v1.26.0/go.mod h1:r9E0BdlNy6mq6gkRGslZRZaYe6WeGhLkpUm8+oEUOvU= -github.com/jfrog/jfrog-client-go v1.55.1-0.20260128141727-bd34d78a3e48 h1:HY4b9DsUe0Lox1rScYHKmfIZY9PQvy0kfkOefqc/QdQ= -github.com/jfrog/jfrog-client-go v1.55.1-0.20260128141727-bd34d78a3e48/go.mod h1:sCE06+GngPoyrGO0c+vmhgMoVSP83UMNiZnIuNPzU8U= +github.com/jfrog/jfrog-client-go v1.55.1-0.20260201135506-ffd03518ef56 h1:MLbEex8JxLDj4bh62ZjQu16Qgfu8BPcKnlSTtizipe8= +github.com/jfrog/jfrog-client-go v1.55.1-0.20260201135506-ffd03518ef56/go.mod h1:sCE06+GngPoyrGO0c+vmhgMoVSP83UMNiZnIuNPzU8U= 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= From ade84fa2800a26d1777c885e9402ece490525b90 Mon Sep 17 00:00:00 2001 From: Bhanu Reddy Date: Tue, 10 Feb 2026 14:56:12 +0530 Subject: [PATCH 8/8] Added multi file upload test case --- artifactory_test.go | 77 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 77 insertions(+) diff --git a/artifactory_test.go b/artifactory_test.go index 9ba575230..1e0468518 100644 --- a/artifactory_test.go +++ b/artifactory_test.go @@ -6885,3 +6885,80 @@ func validateSearchPatternWithAPI(t *testing.T, pattern string, recursive bool) readerGetErrorAndAssert(t, readerNoDate) readerCloseAndAssert(t, readerNoDate) } + +// TestUploadMultipleFilesWithCIVcsProps tests that CI VCS properties are set on multiple uploaded files. +// This test: +// - Creates 15 files dynamically during the test +// - Uploads all files using jf rt u +// - Verifies vcs.provider, vcs.org, vcs.repo properties are set on ALL 15 files +// - Fails if any property is missing on any file +func TestUploadMultipleFilesWithCIVcsProps(t *testing.T) { + initArtifactoryTest(t, "") + const numFiles = 15 + + // Setup GitHub Actions environment (uses real env vars on CI, mock values locally) + cleanupEnv, actualOrg, actualRepo := tests.SetupGitHubActionsEnv(t) + defer cleanupEnv() + + // Create temp directory for test files + tmpDir, createTempDirCallback := coretests.CreateTempDirWithCallbackAndAssert(t) + defer createTempDirCallback() + + // Create 15 files dynamically + var createdFiles []string + for i := 1; i <= numFiles; i++ { + fileName := fmt.Sprintf("civcs-test-file-%d.txt", i) + filePath := filepath.Join(tmpDir, fileName) + content := fmt.Sprintf("Test file %d for CI VCS properties verification. Timestamp: %d", i, time.Now().UnixNano()) + err := os.WriteFile(filePath, []byte(content), 0644) + require.NoError(t, err, "Failed to create test file: %s", fileName) + createdFiles = append(createdFiles, fileName) + } + + // Upload all files to Artifactory + uploadPattern := filepath.Join(tmpDir, "civcs-test-file-*.txt") + targetPath := tests.RtRepo1 + "/civcs-multi-upload/" + runRt(t, "upload", uploadPattern, targetPath, "--flat") + + // Create service manager for getting artifact properties + serviceManager, err := utils.CreateServiceManager(serverDetails, 3, 1000, false) + require.NoError(t, err, "Failed to create service manager") + + // Verify CI VCS properties on each uploaded file + validatedCount := 0 + for _, fileName := range createdFiles { + fullPath := tests.RtRepo1 + "/civcs-multi-upload/" + fileName + + props, err := serviceManager.GetItemProps(fullPath) + require.NoError(t, err, "Failed to get properties for file: %s", fullPath) + require.NotNil(t, props, "Properties are nil for file: %s", fullPath) + + // Validate vcs.provider property + require.Contains(t, props.Properties, "vcs.provider", + "Missing vcs.provider property on file: %s", fileName) + require.Contains(t, props.Properties["vcs.provider"], "github", + "Wrong vcs.provider value on file: %s. Expected 'github', got: %v", fileName, props.Properties["vcs.provider"]) + + // Validate vcs.org property + require.Contains(t, props.Properties, "vcs.org", + "Missing vcs.org property on file: %s", fileName) + require.Contains(t, props.Properties["vcs.org"], actualOrg, + "Wrong vcs.org value on file: %s. Expected '%s', got: %v", fileName, actualOrg, props.Properties["vcs.org"]) + + // Validate vcs.repo property + require.Contains(t, props.Properties, "vcs.repo", + "Missing vcs.repo property on file: %s", fileName) + require.Contains(t, props.Properties["vcs.repo"], actualRepo, + "Wrong vcs.repo value on file: %s. Expected '%s', got: %v", fileName, actualRepo, props.Properties["vcs.repo"]) + + validatedCount++ + } + + // Ensure we validated exactly the expected number of files + require.Equal(t, numFiles, validatedCount, + "Expected to validate %d files, but validated %d", numFiles, validatedCount) + + t.Logf("Successfully validated CI VCS properties on all %d files", validatedCount) + + cleanArtifactoryTest() +}