Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
8ef998e
chore: bump jfrog-cli-artifactory for local git VCS fallback
attiasas Jun 14, 2026
edabc01
test: add local git VCS e2e helpers and fixtures
attiasas Jun 14, 2026
25ba219
test: e2e local git VCS props on rt upload flows
attiasas Jun 14, 2026
1e1ef7e
test: e2e local git VCS props on go and gradle publish
attiasas Jun 14, 2026
7d5ab43
test: e2e local git VCS props on build-publish
attiasas Jun 14, 2026
91b95ec
format, fix static
attiasas Jun 14, 2026
b18e7a9
fix tests
attiasas Jun 14, 2026
2242fc6
update deps
attiasas Jun 14, 2026
dfe1021
update dep
attiasas Jun 15, 2026
0946bdc
fix tests
attiasas Jun 15, 2026
5852836
fix tests for gradle fix
attiasas Jun 15, 2026
722af11
update dep to expend_vsc_detection
attiasas Jun 15, 2026
8cd321d
fix tests in CI
attiasas Jun 16, 2026
b0a82a6
test: add shared local-git VCS validation for build-info artifacts
attiasas Jun 16, 2026
9b97e22
test: e2e local git VCS props on conan upload
attiasas Jun 16, 2026
16767d2
test: e2e local git VCS props on maven build-publish
attiasas Jun 16, 2026
f7dc24f
test: e2e local git VCS props on Gradle FlexPack publish
attiasas Jun 16, 2026
447593b
test: e2e local git VCS props on npm publish
attiasas Jun 16, 2026
093068e
test: e2e local git VCS props on pnpm publish
attiasas Jun 16, 2026
d956944
test: e2e local git VCS props on twine publish
attiasas Jun 16, 2026
eee0ded
test: e2e local git VCS props on uv publish
attiasas Jun 16, 2026
c3b15bc
test: e2e local git VCS props on docker push
attiasas Jun 16, 2026
d582695
test: e2e local git VCS props on helm push
attiasas Jun 16, 2026
5ba23a3
test: e2e local git VCS props on nix copy
attiasas Jun 16, 2026
295cefd
test: e2e local git VCS props on huggingface upload
attiasas Jun 16, 2026
91ca785
test: e2e local git VCS props on terraform publish
attiasas Jun 16, 2026
2da7cdd
fix(tests): correct maven repo constant and UV artifact path resolution
attiasas Jun 16, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
186 changes: 186 additions & 0 deletions artifactory_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -6922,6 +6922,51 @@ func terraformPublishModulesAndBuildInfo(t *testing.T, trPublishArgs []string) {
assert.Len(t, buildInfo.Modules[0].Artifacts, 3)
}

func TestTerraformPublishWithLocalGitVcsProps(t *testing.T) {
initArtifactoryTest(t, terraformMinArtifactoryVersion)
defer cleanArtifactoryTest()
createJfrogHomeConfig(t, true)

buildNumber := "local-git-1"
buildName := tests.RtBuildName1 + "-local-git"

cleanupEnv := tests.SetupLocalGitVcsEnv(t)
defer cleanupEnv()

inttestutils.DeleteBuild(serverDetails.ArtifactoryUrl, buildName, artHttpDetails)
defer inttestutils.DeleteBuild(serverDetails.ArtifactoryUrl, buildName, artHttpDetails)

projectPath := prepareTerraformProject("terraformproject", t, true)
tests.CopyGitFixtureIntoProject(t, projectPath)

wd, err := os.Getwd()
require.NoError(t, err)
awsDir := filepath.Join(projectPath, "aws")
chdirCallback := clientTestUtils.ChangeDirWithCallback(t, wd, awsDir)
defer chdirCallback()

trPublishArgs := []string{
"terraform", "publish",
"--namespace=namespace", "--provider=provider", "--tag=tag",
"--exclusions=*test*",
"--build-name=" + buildName, "--build-number=" + buildNumber,
"--module=my-tr-module-local-git",
}
require.NoError(t, platformCli.WithoutCredentials().Exec(trPublishArgs...))
require.NoError(t, artifactoryCli.Exec("bp", buildName, buildNumber))

publishedBuildInfo, found, err := tests.GetBuildInfo(serverDetails, buildName, buildNumber)
require.NoError(t, err)
require.True(t, found)

serviceManager, err := utils.CreateServiceManager(serverDetails, 3, 1000, false)
require.NoError(t, err)

count := tests.ValidateLocalGitVcsPropsOnBuildInfoArtifacts(t, serviceManager, publishedBuildInfo, tests.TerraformRepo,
tests.VcsFixtureMainURL, tests.VcsFixtureMainRevision, tests.VcsFixtureMainBranch)
assert.Greater(t, count, 0)
}

func prepareTerraformProject(projectName string, t *testing.T, copyDirs bool) string {
projectPath := filepath.Join(tests.GetTestResourcesPath(), "terraform", projectName)
testdataTarget := filepath.Join(tests.Out, "terraformProject")
Expand Down Expand Up @@ -7181,3 +7226,144 @@ func TestUploadMultipleFilesWithCIVcsProps(t *testing.T) {

cleanArtifactoryTest()
}

// TestUploadWithLocalGitVcsProps verifies civcs local git fallback on rt upload
// when CI VCS env vars are absent but VCS collection is enabled.
func TestUploadWithLocalGitVcsProps(t *testing.T) {
initArtifactoryTest(t, "")

cleanupEnv := tests.SetupLocalGitVcsEnv(t)
defer cleanupEnv()

testDir := tests.CopyVcsGitFixture(t, tests.Temp)
targetPath := tests.RtRepo1 + "/local-git-vcs/"

runRt(t, "upload", filepath.Join(testDir, "*.in"), targetPath, "--flat=true")

resultItems := searchItemsInArtifactory(t, tests.SearchRepo1ByInSuffix)
assert.NotZero(t, len(resultItems))

var uploaded []rtutils.ResultItem
for _, item := range resultItems {
if item.Name == "a1.in" || item.Name == "a2.in" {
uploaded = append(uploaded, item)
}
}
assert.Len(t, uploaded, 2)

tests.ValidateLocalGitVcsPropsOnArtifacts(t, uploaded,
tests.VcsFixtureMainURL, tests.VcsFixtureMainRevision, tests.VcsFixtureMainBranch)

cleanArtifactoryTest()
}

// TestUploadWithLocalGitVcsPropsNestedRepo verifies upload from a subdirectory
// resolves the nearest .git (OtherGit), not the parent repo.
func TestUploadWithLocalGitVcsPropsNestedRepo(t *testing.T) {
initArtifactoryTest(t, "")

cleanupEnv := tests.SetupLocalGitVcsEnv(t)
defer cleanupEnv()

testDir := tests.CopyVcsGitFixture(t, tests.Temp)
targetPath := tests.RtRepo1 + "/local-git-vcs-nested/"

runRt(t, "upload", filepath.Join(testDir, "OtherGit", "*.in"), targetPath, "--flat=true")

resultItems := searchItemsInArtifactory(t, tests.SearchRepo1ByInSuffix)
var uploaded []rtutils.ResultItem
for _, item := range resultItems {
if item.Name == "b1.in" || item.Name == "b2.in" {
uploaded = append(uploaded, item)
}
}
assert.Len(t, uploaded, 2)

tests.ValidateLocalGitVcsPropsOnArtifacts(t, uploaded,
tests.VcsFixtureOtherURL, tests.VcsFixtureOtherRevision, tests.VcsFixtureOtherBranch)

cleanArtifactoryTest()
}

func TestUploadUserPropsOverrideLocalGitVcs(t *testing.T) {
initArtifactoryTest(t, "")

cleanupEnv := tests.SetupLocalGitVcsEnv(t)
defer cleanupEnv()

testDir := tests.CopyVcsGitFixture(t, tests.Temp)
targetPath := tests.RtRepo1 + "/local-git-vcs-user-override/"
userProps := "vcs.url=https://example.com/custom.git;vcs.revision=deadbeef;vcs.branch=feature-x"

runRt(t, "upload", filepath.Join(testDir, "a1.in"), targetPath, "--flat=true", "--target-props="+userProps)

serviceManager, err := utils.CreateServiceManager(serverDetails, 3, 1000, false)
require.NoError(t, err)

props, err := serviceManager.GetItemProps(targetPath + "a1.in")
require.NoError(t, err)
require.Contains(t, props.Properties["vcs.url"], "https://example.com/custom.git")
require.Contains(t, props.Properties["vcs.revision"], "deadbeef")
require.Contains(t, props.Properties["vcs.branch"], "feature-x")
require.NotContains(t, props.Properties["vcs.url"], tests.VcsFixtureMainURL)
require.NotContains(t, props.Properties["vcs.revision"], tests.VcsFixtureMainRevision)

cleanArtifactoryTest()
}

// TestUploadCIPlusLocalGitVcsProps verifies CI provides provider/org/repo
// while local git fills url/revision/branch when CI env lacks them.
func TestUploadCIPlusLocalGitVcsProps(t *testing.T) {
initArtifactoryTest(t, "")

cleanupEnv, actualOrg, actualRepo := tests.SetupGitHubActionsEnvForLocalGitMerge(t)
defer cleanupEnv()

testDir := tests.CopyVcsGitFixture(t, tests.Temp)
targetPath := tests.RtRepo1 + "/local-git-vcs-ci-merge/"

runRt(t, "upload", filepath.Join(testDir, "a1.in"), targetPath, "--flat=true")

serviceManager, err := utils.CreateServiceManager(serverDetails, 3, 1000, false)
require.NoError(t, err)

props, err := serviceManager.GetItemProps(targetPath + "a1.in")
require.NoError(t, err)

require.Contains(t, props.Properties["vcs.provider"], "github")
require.Contains(t, props.Properties["vcs.org"], actualOrg)
require.Contains(t, props.Properties["vcs.repo"], actualRepo)
require.Contains(t, props.Properties["vcs.url"], tests.VcsFixtureMainURL)
require.Contains(t, props.Properties["vcs.revision"], tests.VcsFixtureMainRevision)
require.Contains(t, props.Properties["vcs.branch"], tests.VcsFixtureMainBranch)

cleanArtifactoryTest()
}

func TestUploadNoLocalGitVcsWhenNoGitRepo(t *testing.T) {
initArtifactoryTest(t, "")

cleanupEnv := tests.SetupLocalGitVcsEnv(t)
defer cleanupEnv()

tmpDir, cleanupTmp := coretests.CreateTempDirWithCallbackAndAssert(t)
defer cleanupTmp()

filePath := filepath.Join(tmpDir, "no-git.txt")
require.NoError(t, os.WriteFile(filePath, []byte("no git here"), 0644))

targetPath := tests.RtRepo1 + "/local-git-vcs-none/"
runRt(t, "upload", filePath, targetPath, "--flat=true")

resultItems := searchItemsInArtifactory(t, tests.SearchAllRepo1)
var uploaded []rtutils.ResultItem
for _, item := range resultItems {
if item.Name == "no-git.txt" {
uploaded = append(uploaded, item)
}
}
require.Len(t, uploaded, 1)
tests.ValidateNoLocalGitVcsPropsOnArtifacts(t, uploaded)

cleanArtifactoryTest()
}
36 changes: 36 additions & 0 deletions buildinfo_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1234,6 +1234,42 @@ func TestBuildPublishWithCIVcsProps(t *testing.T) {
cleanArtifactoryTest()
}

// TestBuildPublishWithLocalGitVcsProps verifies build-publish sets local git VCS props
// when CI env is absent but VCS collection is enabled.
func TestBuildPublishWithLocalGitVcsProps(t *testing.T) {
initArtifactoryTest(t, "")
buildName := tests.RtBuildName1 + "-local-git"
buildNumber := "1"

cleanupEnv := tests.SetupLocalGitVcsEnv(t)
defer cleanupEnv()

inttestutils.DeleteBuild(serverDetails.ArtifactoryUrl, buildName, artHttpDetails)
defer inttestutils.DeleteBuild(serverDetails.ArtifactoryUrl, buildName, artHttpDetails)

testDir := tests.CopyVcsGitFixture(t, tests.Temp)
runRt(t, "upload", filepath.Join(testDir, "a1.in"), tests.RtRepo1+"/local-git-bp/", "--flat=true",
"--build-name="+buildName, "--build-number="+buildNumber)

runRt(t, "build-publish", buildName, buildNumber, "--dot-git-path", testDir)

resultItems := getResultItemsFromArtifactory(tests.SearchAllRepo1, t)
require.Greater(t, len(resultItems), 0)

var uploaded []rtutils.ResultItem
for _, item := range resultItems {
if item.Name == "a1.in" {
uploaded = append(uploaded, item)
}
}
require.NotEmpty(t, uploaded)

tests.ValidateLocalGitVcsPropsOnArtifacts(t, uploaded,
tests.VcsFixtureMainURL, tests.VcsFixtureMainRevision, tests.VcsFixtureMainBranch)

cleanArtifactoryTest()
}

// TestBuildPublishWithoutCI tests that CI VCS properties are NOT set on artifacts
// when running build-publish outside of a CI environment.
func TestBuildPublishWithoutCI(t *testing.T) {
Expand Down
45 changes: 45 additions & 0 deletions conan_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1162,3 +1162,48 @@ func TestConanBuildPublishWithCIVcsProps(t *testing.T) {

assert.Greater(t, artifactCount, 0, "No artifacts were validated for CI VCS properties")
}

// TestConanUploadWithLocalGitVcsProps verifies civcs local git fallback on conan upload.
func TestConanUploadWithLocalGitVcsProps(t *testing.T) {
initConanTest(t)

buildName := tests.ConanBuildName + "-local-git"
buildNumber := "1"

cleanupEnv := tests.SetupLocalGitVcsEnv(t)
defer cleanupEnv()

inttestutils.DeleteBuild(serverDetails.ArtifactoryUrl, buildName, artHttpDetails)
defer inttestutils.DeleteBuild(serverDetails.ArtifactoryUrl, buildName, artHttpDetails)

projectPath := createConanProject(t, "conan-local-git")
tests.CopyGitFixtureIntoProject(t, projectPath)

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", "")
require.NoError(t, jfrogCli.Exec("conan", "create", ".", "--build=missing",
"--build-name="+buildName, "--build-number="+buildNumber))
require.NoError(t, jfrogCli.Exec("conan", "upload", "cli-test-package/*",
"-r", tests.ConanLocalRepo, "--confirm",
"--build-name="+buildName, "--build-number="+buildNumber))

require.NoError(t, artifactoryCli.Exec("bp", buildName, buildNumber))

publishedBuildInfo, found, err := tests.GetBuildInfo(serverDetails, buildName, buildNumber)
require.NoError(t, err)
require.True(t, found)

serviceManager, err := utils.CreateServiceManager(serverDetails, 3, 1000, false)
require.NoError(t, err)

count := tests.ValidateLocalGitVcsPropsOnBuildInfoArtifacts(t, serviceManager, publishedBuildInfo, tests.ConanLocalRepo,
tests.VcsFixtureMainURL, tests.VcsFixtureMainRevision, tests.VcsFixtureMainBranch)
assert.Greater(t, count, 0)
}
49 changes: 49 additions & 0 deletions docker_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1574,6 +1574,55 @@ CMD ["echo", "Hello from CI VCS test"]`, baseImage)
assert.Greater(t, artifactCount, 0, "No artifacts in build info")
}

// TestDockerPushWithLocalGitVcsProps verifies local git VCS props on Docker artifacts
// when running build-publish with VCS collection enabled and no CI env.
func TestDockerPushWithLocalGitVcsProps(t *testing.T) {
cleanup := initDockerBuildTest(t)
defer cleanup()

buildName := "docker-local-git-test"
buildNumber := "1"

cleanupEnv := tests.SetupLocalGitVcsEnv(t)
defer cleanupEnv()

inttestutils.DeleteBuild(serverDetails.ArtifactoryUrl, buildName, artHttpDetails)
defer inttestutils.DeleteBuild(serverDetails.ArtifactoryUrl, buildName, artHttpDetails)

registryHost := *tests.ContainerRegistry
if parsedURL, err := url.Parse(registryHost); err == nil && parsedURL.Host != "" {
registryHost = parsedURL.Host
}
imageName := path.Join(registryHost, tests.OciLocalRepo, "test-local-git-docker")
imageTag := imageName + ":v1"

workspace, err := filepath.Abs(tests.Out)
require.NoError(t, err)
require.NoError(t, fileutils.CreateDirIfNotExist(workspace))
tests.CopyGitFixtureIntoProject(t, workspace)

baseImage := path.Join(registryHost, tests.OciRemoteRepo, "alpine:latest")
dockerfileContent := fmt.Sprintf("FROM %s\nCMD [\"echo\", \"local git vcs test\"]", baseImage)
dockerfilePath := filepath.Join(workspace, "Dockerfile")
require.NoError(t, os.WriteFile(dockerfilePath, []byte(dockerfileContent), 0o644)) //#nosec G703 -- test code, path built from test workspace

runJfrogCli(t, "rt", "bc", buildName, buildNumber)
runJfrogCli(t, "docker", "build", "-t", imageTag, "--push", "-f", dockerfilePath,
"--build-name="+buildName, "--build-number="+buildNumber, workspace)
runRt(t, "build-publish", buildName, buildNumber)

publishedBuildInfo, found, err := tests.GetBuildInfo(serverDetails, buildName, buildNumber)
require.NoError(t, err)
require.True(t, found)

serviceManager, err := utils.CreateServiceManager(serverDetails, 3, 1000, false)
require.NoError(t, err)

count := tests.ValidateLocalGitVcsPropsOnBuildInfoArtifacts(t, serviceManager, publishedBuildInfo, tests.OciLocalRepo,
tests.VcsFixtureMainURL, tests.VcsFixtureMainRevision, tests.VcsFixtureMainBranch)
assert.Greater(t, count, 0)
}

// TestSetupDockerCommand verifies `jf setup docker --url ...` end-to-end.
//
// Guards RTECO-1352: configureContainer (in jfrog-cli-artifactory) used to read
Expand Down
6 changes: 5 additions & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ require (
github.com/jfrog/build-info-go v1.13.1-0.20260610071651-260ad6720e0d
github.com/jfrog/gofrog v1.7.6
github.com/jfrog/jfrog-cli-application v1.0.2-0.20260608074325-4de652aef752
github.com/jfrog/jfrog-cli-artifactory v0.8.1-0.20260610074911-82ce7d90edbd
github.com/jfrog/jfrog-cli-artifactory v0.8.1-0.20260610130201-b879889dc96a
github.com/jfrog/jfrog-cli-core/v2 v2.60.1-0.20260609101026-df3091b39d06
github.com/jfrog/jfrog-cli-evidence v0.9.5-0.20260601141509-8df6c9a4bc9b
github.com/jfrog/jfrog-cli-platform-services v1.10.1-0.20260601140139-4cefb6add7b7
Expand Down Expand Up @@ -242,6 +242,10 @@ require (
sigs.k8s.io/yaml v1.6.0 // indirect
)

// attiasas:local_git_detection
// attiasas:expend_vsc_detection
replace github.com/jfrog/jfrog-cli-artifactory => github.com/attiasas/jfrog-cli-artifactory v0.0.0-20260615121012-628b7b6f896e

//replace github.com/gfleury/go-bitbucket-v1 => github.com/gfleury/go-bitbucket-v1 v0.0.0-20230825095122-9bc1711434ab

//replace github.com/ktrysmt/go-bitbucket => github.com/ktrysmt/go-bitbucket v0.9.80
Expand Down
4 changes: 2 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,8 @@ github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5 h1:0CwZNZbxp69SHPd
github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkYZB8zMSxRWpUBQtwG5a7fFgvEO+odwuTv2gs=
github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2 h1:DklsrG3dyBCFEj5IhUbnKptjxatkF07cF2ak3yi77so=
github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2/go.mod h1:WaHUgvxTVq04UNunO+XhnAqY/wQc+bxr74GqbsZ/Jqw=
github.com/attiasas/jfrog-cli-artifactory v0.0.0-20260615121012-628b7b6f896e h1:LuzFnMNs6Sp1f757MFqKXtyz43YZkteWtZKPKKZJZgo=
github.com/attiasas/jfrog-cli-artifactory v0.0.0-20260615121012-628b7b6f896e/go.mod h1:VqV0Bed11HoBlugAEGa3RumbwnDVslEf0gKocTzLs9s=
github.com/aws/aws-sdk-go-v2 v1.41.7 h1:DWpAJt66FmnnaRIOT/8ASTucrvuDPZASqhhLey6tLY8=
github.com/aws/aws-sdk-go-v2 v1.41.7/go.mod h1:4LAfZOPHNVNQEckOACQx60Y8pSRjIkNZQz1w92xpMJc=
github.com/aws/aws-sdk-go-v2/config v1.32.17 h1:FpL4/758/diKwqbytU0prpuiu60fgXKUWCpDJtApclU=
Expand Down Expand Up @@ -406,8 +408,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.20260608074325-4de652aef752 h1:Fcb54+kmZjEuBbGstzerLz37Lk6SutfMF7CxLqgXRlE=
github.com/jfrog/jfrog-cli-application v1.0.2-0.20260608074325-4de652aef752/go.mod h1:EeLKgLeJfKcS7671H52bfCgj1xK8wyJJGBRD5a+vJMc=
github.com/jfrog/jfrog-cli-artifactory v0.8.1-0.20260610074911-82ce7d90edbd h1:1AKWhJehl5Z8X69ibX7Azjt70x2L4PnBdnrGiVzdWxY=
github.com/jfrog/jfrog-cli-artifactory v0.8.1-0.20260610074911-82ce7d90edbd/go.mod h1:VqV0Bed11HoBlugAEGa3RumbwnDVslEf0gKocTzLs9s=
github.com/jfrog/jfrog-cli-core/v2 v2.60.1-0.20260609101026-df3091b39d06 h1:A8hWKHyvqzGXfWmh+8lXv3waAkim4xiucBfGhl7ZOeQ=
github.com/jfrog/jfrog-cli-core/v2 v2.60.1-0.20260609101026-df3091b39d06/go.mod h1:9R90mhbczGXwW5EGlDs7F08ejQU/xdoDhYHMvzBiqgE=
github.com/jfrog/jfrog-cli-evidence v0.9.5-0.20260601141509-8df6c9a4bc9b h1:V0FxnU3xh29y8yJHWymm6rPr1MrjG1DdPQlr3ckImwk=
Expand Down
Loading
Loading