Skip to content

Commit 4d976ab

Browse files
authored
Added CI VCS props e2e tests for multiple package managers (#3332)
1 parent e5c4b62 commit 4d976ab

File tree

7 files changed

+667
-6
lines changed

7 files changed

+667
-6
lines changed

artifactory_test.go

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6885,3 +6885,80 @@ func validateSearchPatternWithAPI(t *testing.T, pattern string, recursive bool)
68856885
readerGetErrorAndAssert(t, readerNoDate)
68866886
readerCloseAndAssert(t, readerNoDate)
68876887
}
6888+
6889+
// TestUploadMultipleFilesWithCIVcsProps tests that CI VCS properties are set on multiple uploaded files.
6890+
// This test:
6891+
// - Creates 15 files dynamically during the test
6892+
// - Uploads all files using jf rt u
6893+
// - Verifies vcs.provider, vcs.org, vcs.repo properties are set on ALL 15 files
6894+
// - Fails if any property is missing on any file
6895+
func TestUploadMultipleFilesWithCIVcsProps(t *testing.T) {
6896+
initArtifactoryTest(t, "")
6897+
const numFiles = 15
6898+
6899+
// Setup GitHub Actions environment (uses real env vars on CI, mock values locally)
6900+
cleanupEnv, actualOrg, actualRepo := tests.SetupGitHubActionsEnv(t)
6901+
defer cleanupEnv()
6902+
6903+
// Create temp directory for test files
6904+
tmpDir, createTempDirCallback := coretests.CreateTempDirWithCallbackAndAssert(t)
6905+
defer createTempDirCallback()
6906+
6907+
// Create 15 files dynamically
6908+
var createdFiles []string
6909+
for i := 1; i <= numFiles; i++ {
6910+
fileName := fmt.Sprintf("civcs-test-file-%d.txt", i)
6911+
filePath := filepath.Join(tmpDir, fileName)
6912+
content := fmt.Sprintf("Test file %d for CI VCS properties verification. Timestamp: %d", i, time.Now().UnixNano())
6913+
err := os.WriteFile(filePath, []byte(content), 0644)
6914+
require.NoError(t, err, "Failed to create test file: %s", fileName)
6915+
createdFiles = append(createdFiles, fileName)
6916+
}
6917+
6918+
// Upload all files to Artifactory
6919+
uploadPattern := filepath.Join(tmpDir, "civcs-test-file-*.txt")
6920+
targetPath := tests.RtRepo1 + "/civcs-multi-upload/"
6921+
runRt(t, "upload", uploadPattern, targetPath, "--flat")
6922+
6923+
// Create service manager for getting artifact properties
6924+
serviceManager, err := utils.CreateServiceManager(serverDetails, 3, 1000, false)
6925+
require.NoError(t, err, "Failed to create service manager")
6926+
6927+
// Verify CI VCS properties on each uploaded file
6928+
validatedCount := 0
6929+
for _, fileName := range createdFiles {
6930+
fullPath := tests.RtRepo1 + "/civcs-multi-upload/" + fileName
6931+
6932+
props, err := serviceManager.GetItemProps(fullPath)
6933+
require.NoError(t, err, "Failed to get properties for file: %s", fullPath)
6934+
require.NotNil(t, props, "Properties are nil for file: %s", fullPath)
6935+
6936+
// Validate vcs.provider property
6937+
require.Contains(t, props.Properties, "vcs.provider",
6938+
"Missing vcs.provider property on file: %s", fileName)
6939+
require.Contains(t, props.Properties["vcs.provider"], "github",
6940+
"Wrong vcs.provider value on file: %s. Expected 'github', got: %v", fileName, props.Properties["vcs.provider"])
6941+
6942+
// Validate vcs.org property
6943+
require.Contains(t, props.Properties, "vcs.org",
6944+
"Missing vcs.org property on file: %s", fileName)
6945+
require.Contains(t, props.Properties["vcs.org"], actualOrg,
6946+
"Wrong vcs.org value on file: %s. Expected '%s', got: %v", fileName, actualOrg, props.Properties["vcs.org"])
6947+
6948+
// Validate vcs.repo property
6949+
require.Contains(t, props.Properties, "vcs.repo",
6950+
"Missing vcs.repo property on file: %s", fileName)
6951+
require.Contains(t, props.Properties["vcs.repo"], actualRepo,
6952+
"Wrong vcs.repo value on file: %s. Expected '%s', got: %v", fileName, actualRepo, props.Properties["vcs.repo"])
6953+
6954+
validatedCount++
6955+
}
6956+
6957+
// Ensure we validated exactly the expected number of files
6958+
require.Equal(t, numFiles, validatedCount,
6959+
"Expected to validate %d files, but validated %d", numFiles, validatedCount)
6960+
6961+
t.Logf("Successfully validated CI VCS properties on all %d files", validatedCount)
6962+
6963+
cleanArtifactoryTest()
6964+
}

conan_test.go

Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import (
99

1010
buildinfo "github.com/jfrog/build-info-go/entities"
1111
biutils "github.com/jfrog/build-info-go/utils"
12+
"github.com/jfrog/jfrog-cli-core/v2/artifactory/utils"
1213
coretests "github.com/jfrog/jfrog-cli-core/v2/utils/tests"
1314
"github.com/jfrog/jfrog-cli/inttestutils"
1415
"github.com/jfrog/jfrog-cli/utils/tests"
@@ -467,3 +468,104 @@ func cleanupConanRemote() {
467468
_ = exec.Command("conan", "remote", "remove", tests.ConanVirtualRepo).Run()
468469
_ = exec.Command("conan", "remote", "remove", tests.ConanLocalRepo).Run()
469470
}
471+
472+
// TestConanBuildPublishWithCIVcsProps tests that CI VCS properties are set on Conan artifacts
473+
// when running build-publish in a CI environment (GitHub Actions).
474+
// Conan packages are published via Conan client; build-publish retrieves artifact paths
475+
// from Build Info and applies properties via batch API.
476+
func TestConanBuildPublishWithCIVcsProps(t *testing.T) {
477+
initConanTest(t)
478+
479+
buildName := tests.ConanBuildName + "-civcs"
480+
buildNumber := "1"
481+
482+
// Setup GitHub Actions environment (uses real env vars on CI, mock values locally)
483+
cleanupEnv, actualOrg, actualRepo := tests.SetupGitHubActionsEnv(t)
484+
defer cleanupEnv()
485+
486+
// Clean old build
487+
inttestutils.DeleteBuild(serverDetails.ArtifactoryUrl, buildName, artHttpDetails)
488+
defer inttestutils.DeleteBuild(serverDetails.ArtifactoryUrl, buildName, artHttpDetails)
489+
490+
// Prepare project
491+
projectPath := createConanProject(t, "conan-civcs-test")
492+
wd, err := os.Getwd()
493+
require.NoError(t, err)
494+
chdirCallback := clientTestUtils.ChangeDirWithCallback(t, wd, projectPath)
495+
defer chdirCallback()
496+
497+
// Configure Conan remote
498+
configureConanRemote(t)
499+
defer cleanupConanRemote()
500+
501+
jfrogCli := coretests.NewJfrogCli(execMain, "jfrog", "")
502+
503+
// Run conan create
504+
createArgs := []string{
505+
"conan", "create", ".",
506+
"--build=missing",
507+
"--build-name=" + buildName,
508+
"--build-number=" + buildNumber,
509+
}
510+
assert.NoError(t, jfrogCli.Exec(createArgs...))
511+
512+
// Run conan upload
513+
uploadArgs := []string{
514+
"conan", "upload", "cli-test-package/*",
515+
"-r", tests.ConanLocalRepo,
516+
"--confirm",
517+
"--build-name=" + buildName,
518+
"--build-number=" + buildNumber,
519+
}
520+
assert.NoError(t, jfrogCli.Exec(uploadArgs...))
521+
522+
// Publish build info - should set CI VCS props on artifacts
523+
assert.NoError(t, artifactoryCli.Exec("bp", buildName, buildNumber))
524+
525+
// Get the published build info to find artifact paths
526+
publishedBuildInfo, found, err := tests.GetBuildInfo(serverDetails, buildName, buildNumber)
527+
require.NoError(t, err)
528+
require.True(t, found, "Build info was not found")
529+
530+
// Create service manager for getting artifact properties
531+
serviceManager, err := utils.CreateServiceManager(serverDetails, 3, 1000, false)
532+
require.NoError(t, err)
533+
534+
// Verify VCS properties on each artifact from build info
535+
// Note: Conan artifacts may not have OriginalDeploymentRepo set, so we use Path directly as fallback
536+
artifactCount := 0
537+
for _, module := range publishedBuildInfo.BuildInfo.Modules {
538+
for _, artifact := range module.Artifacts {
539+
// Use same fallback logic as CI VCS: OriginalDeploymentRepo + Path, or Path directly
540+
var fullPath string
541+
switch {
542+
case artifact.OriginalDeploymentRepo != "":
543+
fullPath = artifact.OriginalDeploymentRepo + "/" + artifact.Path
544+
case artifact.Path != "":
545+
fullPath = artifact.Path
546+
default:
547+
continue // Skip artifacts without any path info
548+
}
549+
550+
props, err := serviceManager.GetItemProps(fullPath)
551+
assert.NoError(t, err, "Failed to get properties for artifact: %s", fullPath)
552+
if props == nil {
553+
continue
554+
}
555+
556+
// Validate VCS properties
557+
assert.Contains(t, props.Properties, "vcs.provider", "Missing vcs.provider on %s", artifact.Name)
558+
assert.Contains(t, props.Properties["vcs.provider"], "github", "Wrong vcs.provider on %s", artifact.Name)
559+
560+
assert.Contains(t, props.Properties, "vcs.org", "Missing vcs.org on %s", artifact.Name)
561+
assert.Contains(t, props.Properties["vcs.org"], actualOrg, "Wrong vcs.org on %s", artifact.Name)
562+
563+
assert.Contains(t, props.Properties, "vcs.repo", "Missing vcs.repo on %s", artifact.Name)
564+
assert.Contains(t, props.Properties["vcs.repo"], actualRepo, "Wrong vcs.repo on %s", artifact.Name)
565+
566+
artifactCount++
567+
}
568+
}
569+
570+
assert.Greater(t, artifactCount, 0, "No artifacts were validated for CI VCS properties")
571+
}

go_test.go

Lines changed: 89 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,6 @@ package main
22

33
import (
44
"fmt"
5-
"github.com/jfrog/jfrog-client-go/http/httpclient"
6-
"github.com/stretchr/testify/require"
75
"net/http"
86
"os"
97
"os/exec"
@@ -12,20 +10,21 @@ import (
1210

1311
biutils "github.com/jfrog/build-info-go/utils"
1412

15-
coretests "github.com/jfrog/jfrog-cli-core/v2/utils/tests"
16-
clientTestUtils "github.com/jfrog/jfrog-client-go/utils/tests"
17-
1813
buildinfo "github.com/jfrog/build-info-go/entities"
1914
"github.com/jfrog/jfrog-cli-artifactory/artifactory/commands/golang"
15+
"github.com/jfrog/jfrog-cli-core/v2/artifactory/utils"
2016
"github.com/jfrog/jfrog-cli-core/v2/common/build"
2117
"github.com/jfrog/jfrog-cli-core/v2/common/commands"
2218
"github.com/jfrog/jfrog-cli-core/v2/common/spec"
19+
coretests "github.com/jfrog/jfrog-cli-core/v2/utils/tests"
2320
"github.com/jfrog/jfrog-cli/inttestutils"
24-
2521
"github.com/jfrog/jfrog-cli/utils/tests"
22+
"github.com/jfrog/jfrog-client-go/http/httpclient"
2623
"github.com/jfrog/jfrog-client-go/utils/io/fileutils"
2724
"github.com/jfrog/jfrog-client-go/utils/log"
25+
clientTestUtils "github.com/jfrog/jfrog-client-go/utils/tests"
2826
"github.com/stretchr/testify/assert"
27+
"github.com/stretchr/testify/require"
2928
)
3029

3130
func TestGoConfigWithModuleNameChange(t *testing.T) {
@@ -420,3 +419,87 @@ func TestSetupGoCommand(t *testing.T) {
420419
assert.Equal(t, http.StatusOK, res.StatusCode)
421420
}
422421
}
422+
423+
// TestGoBuildPublishWithCIVcsProps tests that CI VCS properties are set on Go artifacts
424+
// when running go-publish followed by build-publish in a CI environment (GitHub Actions).
425+
// Go supports direct upload via 'jf gp' which sets CI VCS properties during upload.
426+
func TestGoBuildPublishWithCIVcsProps(t *testing.T) {
427+
_, cleanUpFunc := initGoTest(t)
428+
defer cleanUpFunc()
429+
430+
buildName := tests.GoBuildName + "-civcs"
431+
buildNumber := "1"
432+
433+
// Setup GitHub Actions environment (uses real env vars on CI, mock values locally)
434+
cleanupEnv, actualOrg, actualRepo := tests.SetupGitHubActionsEnv(t)
435+
defer cleanupEnv()
436+
437+
// Clean old build
438+
inttestutils.DeleteBuild(serverDetails.ArtifactoryUrl, buildName, artHttpDetails)
439+
defer inttestutils.DeleteBuild(serverDetails.ArtifactoryUrl, buildName, artHttpDetails)
440+
441+
wd, err := os.Getwd()
442+
assert.NoError(t, err, "Failed to get current dir")
443+
444+
// Prepare and build the Go project
445+
prepareGoProject("project1", t, true)
446+
defer clientTestUtils.ChangeDirAndAssert(t, wd)
447+
448+
// Build the Go project with build info collection
449+
jfrogCli := coretests.NewJfrogCli(execMain, "jfrog", "")
450+
err = execGo(jfrogCli, "go", "build", "--mod=mod", "--build-name="+buildName, "--build-number="+buildNumber)
451+
assert.NoError(t, err)
452+
453+
// Publish the Go module to Artifactory with build info collection
454+
// This is where CI VCS properties should be set during direct upload
455+
err = execGo(jfrogCli, "gp", "--build-name="+buildName, "--build-number="+buildNumber, "v1.0.0")
456+
assert.NoError(t, err)
457+
458+
// Publish build info - should also set CI VCS props via batch update if not already set
459+
err = execGo(artifactoryCli, "bp", buildName, buildNumber)
460+
assert.NoError(t, err)
461+
462+
// Get the published build info to find artifact paths
463+
publishedBuildInfo, found, err := tests.GetBuildInfo(serverDetails, buildName, buildNumber)
464+
assert.NoError(t, err)
465+
assert.True(t, found, "Build info was not found")
466+
467+
// Create service manager for getting artifact properties
468+
serviceManager, err := utils.CreateServiceManager(serverDetails, 3, 1000, false)
469+
assert.NoError(t, err)
470+
471+
// Verify VCS properties on each artifact from build info
472+
// Use same fallback logic as CI VCS: OriginalDeploymentRepo + Path, or Path directly
473+
artifactCount := 0
474+
for _, module := range publishedBuildInfo.BuildInfo.Modules {
475+
for _, artifact := range module.Artifacts {
476+
var fullPath string
477+
switch {
478+
case artifact.OriginalDeploymentRepo != "":
479+
fullPath = artifact.OriginalDeploymentRepo + "/" + artifact.Path
480+
case artifact.Path != "":
481+
fullPath = artifact.Path
482+
default:
483+
continue // Skip artifacts without any path info
484+
}
485+
486+
props, err := serviceManager.GetItemProps(fullPath)
487+
assert.NoError(t, err, "Failed to get properties for artifact: %s", fullPath)
488+
assert.NotNil(t, props, "Properties are nil for artifact: %s", fullPath)
489+
490+
// Validate VCS properties
491+
assert.Contains(t, props.Properties, "vcs.provider", "Missing vcs.provider on %s", artifact.Name)
492+
assert.Contains(t, props.Properties["vcs.provider"], "github", "Wrong vcs.provider on %s", artifact.Name)
493+
494+
assert.Contains(t, props.Properties, "vcs.org", "Missing vcs.org on %s", artifact.Name)
495+
assert.Contains(t, props.Properties["vcs.org"], actualOrg, "Wrong vcs.org on %s", artifact.Name)
496+
497+
assert.Contains(t, props.Properties, "vcs.repo", "Missing vcs.repo on %s", artifact.Name)
498+
assert.Contains(t, props.Properties["vcs.repo"], actualRepo, "Wrong vcs.repo on %s", artifact.Name)
499+
500+
artifactCount++
501+
}
502+
}
503+
504+
assert.Greater(t, artifactCount, 0, "No artifacts were validated for CI VCS properties")
505+
}

0 commit comments

Comments
 (0)