Skip to content

Commit 78989c5

Browse files
committed
Added Maven native implementation using flexpack
1 parent 893219d commit 78989c5

File tree

5 files changed

+594
-40
lines changed

5 files changed

+594
-40
lines changed

go.mod

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -242,7 +242,7 @@ require (
242242
sigs.k8s.io/yaml v1.4.0 // indirect
243243
)
244244

245-
replace github.com/jfrog/build-info-go => github.com/jfrog/build-info-go v1.8.9-0.20250907205057-2bfe50c014b7
245+
replace github.com/jfrog/build-info-go => github.com/jfrog/build-info-go v1.8.9-0.20250911222958-cc3e695a45d8
246246

247247
replace github.com/jfrog/jfrog-cli-artifactory => github.com/jfrog/jfrog-cli-artifactory v0.7.2-0.20250907212025-fb4679f280a0
248248

go.sum

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -349,8 +349,8 @@ github.com/jellydator/ttlcache/v3 v3.3.0 h1:BdoC9cE81qXfrxeb9eoJi9dWrdhSuwXMAnHT
349349
github.com/jellydator/ttlcache/v3 v3.3.0/go.mod h1:bj2/e0l4jRnQdrnSTaGTsh4GSXvMjQcy41i7th0GVGw=
350350
github.com/jfrog/archiver/v3 v3.6.1 h1:LOxnkw9pOn45DzCbZNFV6K0+6dCsQ0L8mR3ZcujO5eI=
351351
github.com/jfrog/archiver/v3 v3.6.1/go.mod h1:VgR+3WZS4N+i9FaDwLZbq+jeU4B4zctXL+gL4EMzfLw=
352-
github.com/jfrog/build-info-go v1.8.9-0.20250907205057-2bfe50c014b7 h1:AH31gF//1Dv0ETrT2I4XLR4bCbG6anvw7tEEO8SkHzo=
353-
github.com/jfrog/build-info-go v1.8.9-0.20250907205057-2bfe50c014b7/go.mod h1:szdz9+WzB7+7PGnILLUgyY+OF5qD5geBT7UGNIxibyw=
352+
github.com/jfrog/build-info-go v1.8.9-0.20250911222958-cc3e695a45d8 h1:J531zgchKVQZ4/4qIXvF62eMFRgTDjMviGNODJ9QPf0=
353+
github.com/jfrog/build-info-go v1.8.9-0.20250911222958-cc3e695a45d8/go.mod h1:szdz9+WzB7+7PGnILLUgyY+OF5qD5geBT7UGNIxibyw=
354354
github.com/jfrog/froggit-go v1.20.3 h1:U3HHT0+AEHUVSSyQBbagQR4fLRqGqzSptPujDZuuDTk=
355355
github.com/jfrog/froggit-go v1.20.3/go.mod h1:obSG1SlsWjktkuqmKtpq7MNTTL63e0ot+ucTnlOMV88=
356356
github.com/jfrog/go-mockhttp v0.3.1 h1:/wac8v4GMZx62viZmv4wazB5GNKs+GxawuS1u3maJH8=

maven_test.go

Lines changed: 173 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,16 @@
11
package main
22

33
import (
4+
"encoding/json"
45
"errors"
56
"fmt"
7+
"net/http"
8+
"os"
9+
"os/exec"
10+
"path/filepath"
11+
"strings"
12+
"testing"
13+
614
commonCliUtils "github.com/jfrog/jfrog-cli-core/v2/common/cliutils"
715
outputFormat "github.com/jfrog/jfrog-cli-core/v2/common/format"
816
"github.com/jfrog/jfrog-cli-core/v2/common/project"
@@ -12,18 +20,13 @@ import (
1220
"github.com/jfrog/jfrog-client-go/utils/io/fileutils"
1321
"github.com/stretchr/testify/require"
1422
"gopkg.in/yaml.v2"
15-
"net/http"
16-
"os"
17-
"os/exec"
18-
"path/filepath"
19-
"strings"
20-
"testing"
2123

2224
"github.com/jfrog/build-info-go/build"
2325
buildinfo "github.com/jfrog/build-info-go/entities"
2426
biutils "github.com/jfrog/build-info-go/utils"
27+
"github.com/jfrog/jfrog-cli-artifactory/artifactory/commands/generic"
2528
"github.com/jfrog/jfrog-cli-artifactory/artifactory/commands/mvn"
26-
buildUtils "github.com/jfrog/jfrog-cli-core/v2/common/build"
29+
"github.com/jfrog/jfrog-cli-core/v2/artifactory/utils"
2730
"github.com/jfrog/jfrog-cli-core/v2/common/commands"
2831
"github.com/jfrog/jfrog-cli-core/v2/common/spec"
2932
"github.com/jfrog/jfrog-cli-core/v2/utils/coreutils"
@@ -42,6 +45,19 @@ const localRepoSystemProperty = "-Dmaven.repo.local="
4245

4346
var localRepoDir string
4447

48+
// Simple build configuration struct to avoid importing problematic buildUtils package
49+
type buildConfiguration struct {
50+
buildName string
51+
buildNumber string
52+
}
53+
54+
func (bc *buildConfiguration) ValidateBuildAndModuleParams() error {
55+
if bc.buildName == "" || bc.buildNumber == "" {
56+
return errors.New("build name and build number are required")
57+
}
58+
return nil
59+
}
60+
4561
func cleanMavenTest(t *testing.T) {
4662
clientTestUtils.UnSetEnvAndAssert(t, coreutils.HomeDir)
4763
deleteFilesFromRepo(t, tests.MvnRepo1)
@@ -59,13 +75,141 @@ func TestMavenBuildWithServerID(t *testing.T) {
5975
cleanMavenTest(t)
6076
}
6177

78+
func TestMavenBuildWithFlexPack(t *testing.T) {
79+
initMavenTest(t, false)
80+
// Set environment for native FlexPack implementation
81+
setEnvCallBack := clientTestUtils.SetEnvWithCallbackAndAssert(t, "JFROG_RUN_NATIVE", "true")
82+
defer setEnvCallBack()
83+
84+
assert.NoError(t, runMaven(t, createSimpleMavenProject, tests.MavenConfig, "install"))
85+
// Validate artifacts are deployed
86+
searchSpec, err := tests.CreateSpec(tests.SearchAllMaven)
87+
assert.NoError(t, err)
88+
inttestutils.VerifyExistInArtifactory(tests.GetMavenDeployedArtifacts(), searchSpec, serverDetails, t)
89+
cleanMavenTest(t)
90+
}
91+
92+
func TestMavenBuildWithFlexPackBuildInfo(t *testing.T) {
93+
initMavenTest(t, false)
94+
buildName := tests.MvnBuildName + "-flexpack"
95+
buildNumber := "1"
96+
97+
// Set environment for native FlexPack implementation
98+
setEnvCallBack := clientTestUtils.SetEnvWithCallbackAndAssert(t, "JFROG_RUN_NATIVE", "true")
99+
defer setEnvCallBack()
100+
101+
// Run Maven with build info
102+
args := []string{"install", "--build-name=" + buildName, "--build-number=" + buildNumber}
103+
assert.NoError(t, runMaven(t, createSimpleMavenProject, tests.MavenConfig, args...))
104+
105+
// Validate artifacts are deployed
106+
searchSpec, err := tests.CreateSpec(tests.SearchAllMaven)
107+
assert.NoError(t, err)
108+
inttestutils.VerifyExistInArtifactory(tests.GetMavenDeployedArtifacts(), searchSpec, serverDetails, t)
109+
110+
// Publish build info
111+
assert.NoError(t, runJfrogCliWithoutAssertion("rt", "bp", buildName, buildNumber))
112+
113+
// Validate build info was created with FlexPack dependencies
114+
publishedBuildInfo, found, err := tests.GetBuildInfo(serverDetails, buildName, buildNumber)
115+
if !assert.NoError(t, err, "Failed to get build info") {
116+
return
117+
}
118+
if !assert.True(t, found, "build info was expected to be found") {
119+
return
120+
}
121+
122+
// Validate build info structure
123+
assert.NotEmpty(t, publishedBuildInfo.BuildInfo.Modules, "Build info should have modules")
124+
if len(publishedBuildInfo.BuildInfo.Modules) > 0 {
125+
module := publishedBuildInfo.BuildInfo.Modules[0]
126+
assert.Equal(t, "maven", string(module.Type), "Module type should be maven")
127+
assert.NotEmpty(t, module.Id, "Module should have ID")
128+
129+
// FlexPack should collect dependencies
130+
assert.Greater(t, len(module.Dependencies), 0, "FlexPack should collect dependencies")
131+
132+
// Validate dependency structure
133+
for _, dep := range module.Dependencies {
134+
assert.NotEmpty(t, dep.Id, "Dependency should have ID")
135+
assert.NotEmpty(t, dep.Type, "Dependency should have type")
136+
assert.NotEmpty(t, dep.Scopes, "Dependency should have scopes")
137+
// FlexPack should provide checksums
138+
hasChecksum := dep.Checksum.Sha1 != "" || dep.Checksum.Sha256 != "" || dep.Checksum.Md5 != ""
139+
assert.True(t, hasChecksum, "Dependency %s should have at least one checksum", dep.Id)
140+
}
141+
142+
// Should have artifacts from native Maven deployment
143+
assert.Greater(t, len(module.Artifacts), 0, "Should have artifacts from Maven deployment")
144+
}
145+
146+
cleanMavenTest(t)
147+
}
148+
149+
func TestMavenFlexPackBuildProperties(t *testing.T) {
150+
initMavenTest(t, false)
151+
buildName := tests.MvnBuildName + "-props"
152+
buildNumber := "42"
153+
154+
// Set environment for native FlexPack implementation
155+
setEnvCallBack := clientTestUtils.SetEnvWithCallbackAndAssert(t, "JFROG_RUN_NATIVE", "true")
156+
defer setEnvCallBack()
157+
158+
// Run Maven deploy with build info (this should set build properties on artifacts)
159+
args := []string{"deploy", "--build-name=" + buildName, "--build-number=" + buildNumber}
160+
assert.NoError(t, runMaven(t, createSimpleMavenProject, tests.MavenConfig, args...))
161+
162+
// Validate artifacts are deployed
163+
searchSpec, err := tests.CreateSpec(tests.SearchAllMaven)
164+
assert.NoError(t, err)
165+
inttestutils.VerifyExistInArtifactory(tests.GetMavenDeployedArtifacts(), searchSpec, serverDetails, t)
166+
167+
// Publish build info
168+
assert.NoError(t, runJfrogCliWithoutAssertion("rt", "bp", buildName, buildNumber))
169+
170+
// Search for artifacts with build properties
171+
// This validates that FlexPack correctly set build.name and build.number properties
172+
propsSearchSpec := fmt.Sprintf(`{
173+
"files": [{
174+
"aql": {
175+
"items.find": {
176+
"repo": "%s",
177+
"@build.name": "%s",
178+
"@build.number": "%s"
179+
}
180+
}
181+
}]
182+
}`, tests.MvnRepo1, buildName, buildNumber)
183+
184+
propsSpec := new(spec.SpecFiles)
185+
err = json.Unmarshal([]byte(propsSearchSpec), propsSpec)
186+
assert.NoError(t, err)
187+
188+
// Verify artifacts have build properties set by FlexPack
189+
searchCmd := generic.NewSearchCommand()
190+
searchCmd.SetServerDetails(serverDetails).SetSpec(propsSpec)
191+
reader, err := searchCmd.Search()
192+
assert.NoError(t, err)
193+
var propsResults []utils.SearchResult
194+
readerNoDate, err := utils.SearchResultNoDate(reader)
195+
assert.NoError(t, err)
196+
for searchResult := new(utils.SearchResult); readerNoDate.NextRecord(searchResult) == nil; searchResult = new(utils.SearchResult) {
197+
propsResults = append(propsResults, *searchResult)
198+
}
199+
assert.NoError(t, reader.Close(), "Couldn't close reader")
200+
assert.NoError(t, reader.GetError(), "Couldn't get reader error")
201+
assert.Greater(t, len(propsResults), 0, "Should find artifacts with build properties set by FlexPack")
202+
203+
cleanMavenTest(t)
204+
}
205+
62206
func TestMavenBuildWithNoProxy(t *testing.T) {
63207
initMavenTest(t, false)
64208
// jfrog-ignore - not a real password
65-
setEnvCallBack := clientTestUtils.SetEnvWithCallbackAndAssert(t, buildUtils.HttpProxyEnvKey, "http://login:pass@proxy.mydomain:8888")
209+
setEnvCallBack := clientTestUtils.SetEnvWithCallbackAndAssert(t, "HTTP_PROXY", "http://login:pass@proxy.mydomain:8888")
66210
defer setEnvCallBack()
67211
// Set noProxy to match all to skip http proxy configuration
68-
setNoProxyEnvCallBack := clientTestUtils.SetEnvWithCallbackAndAssert(t, buildUtils.NoProxyEnvKey, "*")
212+
setNoProxyEnvCallBack := clientTestUtils.SetEnvWithCallbackAndAssert(t, "NO_PROXY", "*")
69213
defer setNoProxyEnvCallBack()
70214
assert.NoError(t, runMaven(t, createSimpleMavenProject, tests.MavenConfig, "install"))
71215
// Validate
@@ -78,10 +222,10 @@ func TestMavenBuildWithNoProxy(t *testing.T) {
78222
func TestMavenBuildWithNoProxyHttps(t *testing.T) {
79223
initMavenTest(t, false)
80224
// jfrog-ignore - not a real password
81-
setHttpsEnvCallBack := clientTestUtils.SetEnvWithCallbackAndAssert(t, buildUtils.HttpsProxyEnvKey, "https://logins:passw@proxys.mydomains:8889")
225+
setHttpsEnvCallBack := clientTestUtils.SetEnvWithCallbackAndAssert(t, "HTTPS_PROXY", "https://logins:passw@proxys.mydomains:8889")
82226
defer setHttpsEnvCallBack()
83227
// Set noProxy to match all to skip https proxy configuration
84-
setNoProxyEnvCallBack := clientTestUtils.SetEnvWithCallbackAndAssert(t, buildUtils.NoProxyEnvKey, "*")
228+
setNoProxyEnvCallBack := clientTestUtils.SetEnvWithCallbackAndAssert(t, "NO_PROXY", "*")
85229
defer setNoProxyEnvCallBack()
86230
assert.NoError(t, runMaven(t, createSimpleMavenProject, tests.MavenConfig, "install"))
87231
// Validate
@@ -107,17 +251,17 @@ func TestMavenBuildWithConditionalUpload(t *testing.T) {
107251
cleanMavenTest(t)
108252
}
109253

110-
func runMvnConditionalUploadTest(buildName, buildNumber string) (err error) {
254+
func runMvnConditionalUploadTest(buildName, buildNumber string) error {
111255
configFilePath, exists, err := project.GetProjectConfFilePath(project.Maven)
112256
if err != nil {
113-
return
257+
return err
114258
}
115259
if !exists {
116260
return errors.New("no config file was found!")
117261
}
118-
buildConfig := buildUtils.NewBuildConfiguration(buildName, buildNumber, "", "")
262+
buildConfig := &buildConfiguration{buildName: buildName, buildNumber: buildNumber}
119263
if err = buildConfig.ValidateBuildAndModuleParams(); err != nil {
120-
return
264+
return err
121265
}
122266
printDeploymentView := log.IsStdErrTerminal()
123267
mvnCmd := mvn.NewMvnCommand().
@@ -144,7 +288,7 @@ func TestMavenBuildWithServerIDAndDetailedSummary(t *testing.T) {
144288
defer clientTestUtils.ChangeDirAndAssert(t, oldHomeDir)
145289
repoLocalSystemProp := localRepoSystemProperty + localRepoDir
146290
filteredMavenArgs := []string{"clean", "install", "-B", repoLocalSystemProp}
147-
mvnCmd := mvn.NewMvnCommand().SetConfiguration(new(buildUtils.BuildConfiguration)).SetConfigPath(filepath.Join(destPath, tests.MavenConfig)).SetGoals(filteredMavenArgs).SetDetailedSummary(true)
291+
mvnCmd := mvn.NewMvnCommand().SetConfiguration(&buildConfiguration{}).SetConfigPath(filepath.Join(destPath, tests.MavenConfig)).SetGoals(filteredMavenArgs).SetDetailedSummary(true)
148292
assert.NoError(t, commands.Exec(mvnCmd))
149293
// Validate
150294
assert.NotNil(t, mvnCmd.Result())
@@ -215,8 +359,7 @@ func createSimpleMavenProject(t *testing.T) string {
215359
func createMultiMavenProject(t *testing.T) string {
216360
projectDir := filepath.Join(filepath.FromSlash(tests.GetTestResourcesPath()), "maven", "multiproject")
217361
destPath, err := os.Getwd()
218-
if err != nil {
219-
assert.NoError(t, err)
362+
if !assert.NoError(t, err, "Failed to get current working directory") {
220363
return ""
221364
}
222365
destPath = filepath.Join(destPath, tests.Temp)
@@ -266,17 +409,14 @@ func TestMavenBuildIncludePatterns(t *testing.T) {
266409
// Validate build info.
267410
assert.NoError(t, artifactoryCli.Exec("build-publish", tests.MvnBuildName, buildNumber))
268411
publishedBuildInfo, found, err := tests.GetBuildInfo(serverDetails, tests.MvnBuildName, buildNumber)
269-
if err != nil {
270-
assert.NoError(t, err)
412+
if !assert.NoError(t, err, "Failed to get build info") {
271413
return
272414
}
273-
if !found {
274-
assert.True(t, found, "build info was expected to be found")
415+
if !assert.True(t, found, "build info was expected to be found") {
275416
return
276417
}
277418
buildInfo := publishedBuildInfo.BuildInfo
278-
if len(buildInfo.Modules) != 4 {
279-
assert.Len(t, buildInfo.Modules, 4)
419+
if !assert.Len(t, buildInfo.Modules, 4, "Expected 4 modules in build info") {
280420
return
281421
}
282422
validateSpecificModule(buildInfo, t, 13, 2, 1, "org.jfrog.test:multi1:3.7-SNAPSHOT", buildinfo.Maven)
@@ -302,8 +442,9 @@ func runMavenAndValidateDeployedArtifacts(t *testing.T, shouldDeployArtifact boo
302442
if shouldDeployArtifact {
303443
inttestutils.VerifyExistInArtifactory(tests.GetMavenMultiIncludedDeployedArtifacts(), searchSpec, serverDetails, t)
304444
} else {
305-
results, _ := inttestutils.SearchInArtifactory(searchSpec, serverDetails, t)
306-
assert.Zero(t, results)
445+
results, err := inttestutils.SearchInArtifactory(searchSpec, serverDetails, t)
446+
assert.NoError(t, err)
447+
assert.Zero(t, len(results))
307448
}
308449
}
309450
func TestMavenWithSummary(t *testing.T) {
@@ -414,7 +555,9 @@ func prepareMavenSetupTest(t *testing.T, homeDir string) func() {
414555
restoreSettingsXml, err := ioutils.BackupFile(settingsXml, ".settings.xml.backup")
415556
require.NoError(t, err)
416557
defer func() {
417-
assert.NoError(t, restoreSettingsXml())
558+
if err := restoreSettingsXml(); err != nil {
559+
t.Errorf("Failed to restore settings.xml: %v", err)
560+
}
418561
}()
419562

420563
wd, err := os.Getwd()
@@ -433,7 +576,9 @@ func prepareMavenSetupTest(t *testing.T, homeDir string) func() {
433576
restoreDir := clientTestUtils.ChangeDirWithCallback(t, wd, filepath.Join(tempDir, "mock-project"))
434577

435578
return func() {
436-
assert.NoError(t, restoreSettingsXml())
579+
if err := restoreSettingsXml(); err != nil {
580+
t.Errorf("Failed to restore settings.xml: %v", err)
581+
}
437582
restoreDir()
438583
}
439584
}

npm_test.go

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,7 @@ func testNpm(t *testing.T, isLegacy bool) {
8484
wd, err := os.Getwd()
8585
assert.NoError(t, err, "Failed to get current dir")
8686
defer clientTestUtils.ChangeDirAndAssert(t, wd)
87-
npmVersion, _, err := buildutils.GetNpmVersionAndExecPath(log.Logger)
87+
npmVersion, _, err := buildutils.GetNpmVersionAndExecPath(&biutils.NullLog{})
8888
if err != nil {
8989
assert.NoError(t, err)
9090
return
@@ -164,7 +164,7 @@ func testNpmPublishWithNpmrc(t *testing.T, validationFunc func(t *testing.T, npm
164164
assert.NoError(t, err, "Failed to get current dir")
165165
defer clientTestUtils.ChangeDirAndAssert(t, wd)
166166
buildNumber := "1"
167-
npmVersion, _, err := buildutils.GetNpmVersionAndExecPath(log.Logger)
167+
npmVersion, _, err := buildutils.GetNpmVersionAndExecPath(&biutils.NullLog{})
168168
if err != nil {
169169
assert.NoError(t, err)
170170
return
@@ -214,7 +214,7 @@ func TestNpmInstallClientNative(t *testing.T) {
214214
assert.NoError(t, err, "Failed to get current dir")
215215
defer clientTestUtils.ChangeDirAndAssert(t, wd)
216216

217-
npmVersion, _, err := buildutils.GetNpmVersionAndExecPath(log.Logger)
217+
npmVersion, _, err := buildutils.GetNpmVersionAndExecPath(&biutils.NullLog{})
218218
if err != nil {
219219
assert.NoError(t, err)
220220
return
@@ -359,7 +359,7 @@ func TestNpmConditionalUpload(t *testing.T) {
359359
assert.NoError(t, err, "Failed to get current dir")
360360
searchSpec, err := tests.CreateSpec(tests.SearchAllNpm)
361361
assert.NoError(t, err)
362-
npmVersion, _, err := buildutils.GetNpmVersionAndExecPath(log.Logger)
362+
npmVersion, _, err := buildutils.GetNpmVersionAndExecPath(&biutils.NullLog{})
363363
assert.NoError(t, err)
364364
npmProjectPath := initNpmProjectTest(t)
365365
clientTestUtils.ChangeDirAndAssert(t, npmProjectPath)
@@ -585,7 +585,7 @@ func TestNpmPublishDetailedSummary(t *testing.T) {
585585
assert.NoError(t, err, "Failed to get current dir")
586586
defer clientTestUtils.ChangeDirAndAssert(t, wd)
587587

588-
npmVersion, _, err := buildutils.GetNpmVersionAndExecPath(log.Logger)
588+
npmVersion, _, err := buildutils.GetNpmVersionAndExecPath(&biutils.NullLog{})
589589
if err != nil {
590590
assert.NoError(t, err)
591591
return
@@ -734,7 +734,7 @@ func TestNpmPackInstall(t *testing.T) {
734734
// Read more about npm workspaces here: https://docs.npmjs.com/cli/v7/using-npm/workspaces
735735
func TestNpmPublishWithWorkspaces(t *testing.T) {
736736
// Check npm version
737-
npmVersion, _, err := buildutils.GetNpmVersionAndExecPath(log.Logger)
737+
npmVersion, _, err := buildutils.GetNpmVersionAndExecPath(&biutils.NullLog{})
738738
if err != nil {
739739
assert.NoError(t, err)
740740
return
@@ -780,7 +780,7 @@ func TestNpmPublishWithWorkspaces(t *testing.T) {
780780
// Test npm publish command with provided tarball
781781
func TestNpmPackProvidedTarball(t *testing.T) {
782782
// Check npm version
783-
npmVersion, _, err := buildutils.GetNpmVersionAndExecPath(log.Logger)
783+
npmVersion, _, err := buildutils.GetNpmVersionAndExecPath(&biutils.NullLog{})
784784
if err != nil {
785785
assert.NoError(t, err)
786786
return

0 commit comments

Comments
 (0)