Skip to content

Commit

Permalink
Merge remote-tracking branch 'origin/dev' into main
Browse files Browse the repository at this point in the history
  • Loading branch information
JFrog Pipelines Step committed Mar 16, 2023
2 parents 3a63fa3 + a9f6b73 commit 9b6f2ec
Show file tree
Hide file tree
Showing 6 changed files with 164 additions and 47 deletions.
2 changes: 1 addition & 1 deletion build/gradle.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ const (
GradleExtractorFileName = "build-info-extractor-gradle-%s-uber.jar"
gradleInitScriptTemplate = "gradle.init"
GradleExtractorRemotePath = "org/jfrog/buildinfo/build-info-extractor-gradle/%s"
GradleExtractorDependencyVersion = "4.31.5"
GradleExtractorDependencyVersion = "4.31.7"
)

type GradleModule struct {
Expand Down
135 changes: 97 additions & 38 deletions build/maven.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ import (
"os"
"os/exec"
"path/filepath"
"runtime"
"strings"

"github.com/jfrog/build-info-go/utils"
Expand All @@ -20,7 +19,7 @@ const (
PropertiesTempfolderName = "properties"
MavenExtractorRemotePath = "org/jfrog/buildinfo/build-info-extractor-maven3/%s"
GeneratedBuildInfoTempPrefix = "generatedBuildInfo"
MavenExtractorDependencyVersion = "2.39.5"
MavenExtractorDependencyVersion = "2.39.7"

ClassworldsConf = `main is org.apache.maven.cli.MavenCli from plexus.core
Expand Down Expand Up @@ -55,6 +54,8 @@ type extractorDetails struct {
props map[string]string
// Local path to the configuration file.
propsDir string
// Use the maven wrapper to build the project.
useWrapper bool
}

// Add a new Maven module to a given build.
Expand All @@ -81,11 +82,12 @@ func newMavenModule(containingBuild *Build, srcPath string) (*MavenModule, error
}, err
}

func (mm *MavenModule) SetExtractorDetails(localdExtractorPath, extractorPropsdir string, goals []string, downloadExtractorFunc func(downloadTo, downloadFrom string) error, configProps map[string]string) *MavenModule {
mm.extractorDetails.localPath = localdExtractorPath
func (mm *MavenModule) SetExtractorDetails(localExtractorPath, extractorPropsdir string, goals []string, downloadExtractorFunc func(downloadTo, downloadFrom string) error, configProps map[string]string, useWrapper bool) *MavenModule {
mm.extractorDetails.localPath = localExtractorPath
mm.extractorDetails.propsDir = extractorPropsdir
mm.extractorDetails.downloadExtractorFunc = downloadExtractorFunc
mm.extractorDetails.goals = goals
mm.extractorDetails.useWrapper = useWrapper
if configProps != nil {
mm.extractorDetails.props = configProps
}
Expand Down Expand Up @@ -144,24 +146,30 @@ func (mm *MavenModule) createMvnRunConfig() (*mvnRunConfig, error) {
}

// Generates Maven build-info.
func (mm *MavenModule) CalcDependencies() error {
func (mm *MavenModule) CalcDependencies() (err error) {
if mm.srcPath == "" {
var err error
if mm.srcPath, err = os.Getwd(); err != nil {
return err
}
}

err := downloadMavenExtractor(mm.extractorDetails.localPath, mm.extractorDetails.downloadExtractorFunc, mm.containingBuild.logger)
if err != nil {
return err
if err = downloadMavenExtractor(mm.extractorDetails.localPath, mm.extractorDetails.downloadExtractorFunc, mm.containingBuild.logger); err != nil {
return
}
mvnRunConfig, err := mm.createMvnRunConfig()
if err != nil {
return err
return
}
defer func() {
fileExist, e := utils.IsFileExists(mvnRunConfig.buildInfoProperties, false)
if fileExist && e == nil {
e = os.Remove(mvnRunConfig.buildInfoProperties)
}
if err == nil {
err = e
}
}()

defer os.Remove(mvnRunConfig.buildInfoProperties)
mm.containingBuild.logger.Info("Running Mvn...")
return mvnRunConfig.runCmd()
}
Expand All @@ -172,42 +180,93 @@ func (mm *MavenModule) loadMavenHome() (mavenHome string, err error) {
if mavenHome == "" {
// The 'mavenHome' is not defined.
// Since Maven installation can be located in different locations,
// Depending on the installation type and the OS (for example: For Mac with brew install: /usr/local/Cellar/maven/{version}/libexec or Ubuntu with debian: /usr/share/maven),
// We need to grab the location using the mvn --version command

// depending on the installation type and the OS (for example: For Mac with brew install: /usr/local/Cellar/maven/{version}/libexec or Ubuntu with debian: /usr/share/maven),
// we need to grab the location using the mvn --version command.
// First we will try lo look for 'mvn' in PATH.
mvnPath, err := exec.LookPath("mvn")
if err != nil || mvnPath == "" {
return "", errors.New(err.Error() + "Hint: The mvn command may not be included in the PATH. Either add it to the path, or set the M2_HOME environment variable value to the maven installation directory, which is the directory which includes the bin and lib directories.")
maven, err := mm.getExecutableName()
if err != nil {
return maven, err
}
mm.containingBuild.logger.Debug(MavenHome, " is not defined. Retrieving Maven home using 'mvn --version' command.")
cmd := exec.Command("mvn", "--version")
var stdout bytes.Buffer
cmd.Stdout = &stdout
err = cmd.Run()
if !mm.extractorDetails.useWrapper {
mvnPath, err := mm.lookPath()
if err != nil {
return mvnPath, err
}
}
versionOutput, err := mm.execMavenVersion(maven)
if err != nil {
return "", err
}
output := strings.Split(strings.TrimSpace(stdout.String()), "\n")
// Finding the relevant "Maven home" line in command response.
for _, line := range output {
if strings.HasPrefix(line, "Maven home:") {
mavenHome = strings.Split(line, " ")[2]
if runtime.GOOS == "windows" {
mavenHome = strings.TrimSuffix(mavenHome, "\r")
}
mavenHome, err = filepath.Abs(mavenHome)
if err != nil {
return "", err
}
break
}
}
if mavenHome == "" {
return "", errors.New("Could not find the location of the maven home directory, by running 'mvn --version' command. The command output is:\n" + stdout.String() + "\nYou also have the option of setting the M2_HOME environment variable value to the maven installation directory, which is the directory which includes the bin and lib directories.")
mavenHome, err = mm.extractMavenPath(versionOutput)
if err != nil {
return "", err
}
}
mm.containingBuild.logger.Debug("Maven home location: ", mavenHome)

return
}

func (mm *MavenModule) lookPath() (mvnPath string, err error) {
mvnPath, err = exec.LookPath("mvn")
err = mm.determineError(mvnPath, "", err)
return
}

// This function generates an error with a clear message, based on the arguments it gets.
func (mm *MavenModule) determineError(mvnPath, versionOutput string, err error) error {
if err != nil {
if versionOutput == "" {
return errors.New(err.Error() + "\nHint: The mvn command may not be included in the PATH. Either add it to the path or set the M2_HOME environment variable value to the maven installation directory, which is the directory that includes the bin and lib directories.")
}
return errors.New(err.Error() + "Could not find the location of the maven home directory, by running 'mvn --version' command. The command versionOutput is:\n" + versionOutput + "\nYou also have the option of setting the M2_HOME environment variable value to the maven installation directory, which is the directory which includes the bin and lib directories.")
}
if mvnPath == "" {
if versionOutput == "" {
return errors.New("hint: The mvn command may not be included in the PATH. Either add it to the path or set the M2_HOME environment variable value to the maven installation directory, which is the directory that includes the bin and lib directories")
}
return errors.New("Could not find the location of the maven home directory, by running 'mvn --version' command. The command versionOutput is:\n" + versionOutput + "\nYou also have the option of setting the M2_HOME environment variable value to the maven installation directory, which is the directory which includes the bin and lib directories.")
}
return nil
}

func (mm *MavenModule) getExecutableName() (maven string, err error) {
maven = "mvn"
if mm.extractorDetails.useWrapper {
if utils.IsWindows() {
maven, err = filepath.Abs("mvnw.cmd")
} else {
maven = "./mvnw"
}
}
return
}

func (mm *MavenModule) execMavenVersion(maven string) (stdout bytes.Buffer, err error) {
mm.containingBuild.logger.Debug(MavenHome, " is not defined. Retrieving Maven home using 'mvn --version' command.")
cmd := exec.Command(maven, "--version")
cmd.Stdout = &stdout
err = cmd.Run()
err = mm.determineError("mvn", stdout.String(), err)
if err != nil {
return stdout, err
}

return stdout, nil
}

func (mm *MavenModule) extractMavenPath(mavenVersionOutput bytes.Buffer) (mavenHome string, err error) {
mavenVersionResultInArray := strings.Split(strings.TrimSpace(mavenVersionOutput.String()), "\n")
for _, line := range mavenVersionResultInArray {
if !strings.HasPrefix(line, "Maven home:") {
continue
}
mavenHome = strings.Split(line, " ")[2]
mavenHome = strings.TrimSpace(mavenHome)
mavenHome, err = filepath.Abs(mavenHome)
err = mm.determineError(mavenHome, mavenVersionOutput.String(), err)
}
return
}

Expand Down
60 changes: 60 additions & 0 deletions build/maven_test.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package build

import (
"bytes"
"encoding/json"
"fmt"
"os"
Expand Down Expand Up @@ -40,6 +41,7 @@ func TestGenerateBuildInfoForMavenProject(t *testing.T) {
defer func() {
assert.NoError(t, mavenBuild.Clean())
}()

testdataDir, err := filepath.Abs(filepath.Join("testdata"))
assert.NoError(t, err)
// Create maven project
Expand Down Expand Up @@ -72,3 +74,61 @@ func getExpectedMavenBuildInfo(t *testing.T, filePath string) entities.BuildInfo
assert.NoError(t, json.Unmarshal(data, &buildinfo))
return buildinfo
}

func TestExtractMavenPath(t *testing.T) {
service := NewBuildInfoService()
mavenBuild, err := service.GetOrCreateBuild("build-info-maven-test", "1")
assert.NoError(t, err)
defer assert.NoError(t, mavenBuild.Clean())

testdataDir, err := filepath.Abs(filepath.Join("testdata"))
assert.NoError(t, err)
// Create maven project
projectPath := filepath.Join(testdataDir, "maven", "project")
tmpProjectPath, cleanup := testdatautils.CreateTestProject(t, projectPath)
defer cleanup()
// Add maven project as module in build-info.
mavenModule, err := mavenBuild.AddMavenModule(tmpProjectPath)
assert.NoError(t, err)

allTests := []struct {
mavenVersionResultFirstLine string
mavenVersionResultSecondLine string
mavenVersionResultThirdLine string
}{
{"Maven home: /test/is/good", "Home: /test/is/not/good", "Mvn Home:= /test/is/not/good"},
{"Home: /test/is/not/good", "Maven home: /test/is/good", "Mvn Home:= /test/is/not/good"},
{"Mvn Home:= /test/is/not/good", "Home: /test/is/not/good", "Maven home: /test/is/good"},
}

for _, test := range allTests {
var mavenVersionFullResult []string
mavenVersionFullResult = append(mavenVersionFullResult, test.mavenVersionResultFirstLine, test.mavenVersionResultSecondLine, test.mavenVersionResultThirdLine)
data1 := bytes.Buffer{}
for _, i := range mavenVersionFullResult {
data1.WriteString(i)
data1.WriteString("\n")
}
mavenHome, err := mavenModule.extractMavenPath(data1)
assert.NoError(t, err)
if utils.IsWindows() {
assert.Equal(t, "D:\\test\\is\\good", mavenHome)
} else {
assert.Equal(t, "/test/is/good", mavenHome)
}
}
}

func TestGetExecutableName(t *testing.T) {
// Add maven project as module in build-info.
mavenModule := MavenModule{extractorDetails: &extractorDetails{useWrapper: true}}
mvnHome, err := mavenModule.getExecutableName()
assert.NoError(t, err)
if !utils.IsWindows() {
assert.Equal(t, "./mvnw", mvnHome)
} else {
result, err := filepath.Abs("mvnw.cmd")
assert.NoError(t, err)
assert.Equal(t, result, mvnHome)
}
}
2 changes: 1 addition & 1 deletion build/testdata/test_helpers.go
Original file line number Diff line number Diff line change
Expand Up @@ -71,5 +71,5 @@ func PrintBuildInfoMismatch(t *testing.T, expected, actual []entities.Module) {
assert.NoError(t, err)
actualStr, err := json.MarshalIndent(actual, "", " ")
assert.NoError(t, err)
t.Errorf("build-info don't match. want: \n %v\n got:\n%s\n", string(excpectedStr), string(actualStr))
t.Errorf("build-info don't match. want: \n%v\ngot:\n%s\n", string(excpectedStr), string(actualStr))
}
11 changes: 5 additions & 6 deletions build/utils/npm.go
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ func CalculateNpmDependenciesList(executablePath, srcPath, moduleId string, npmA
continue
}
if calculateChecksums {
dep.Md5, dep.Sha1, dep.Sha256, err = calculateChecksum(cacache, dep.Name, dep.Version, dep.Integrity, log)
dep.Md5, dep.Sha1, dep.Sha256, err = calculateChecksum(cacache, dep.Name, dep.Version, dep.Integrity)
if err != nil {
if dep.Optional {
missingOptionalDeps = append(missingOptionalDeps, dep.Id)
Expand Down Expand Up @@ -220,7 +220,7 @@ func parseDependencies(data []byte, pathToRoot []string, dependencies map[string
}
return errors.New("failed to parse '" + string(value) + "' from npm ls output.")
}
appendDependency(dependencies, npmLsDependency, pathToRoot, log)
appendDependency(dependencies, npmLsDependency, pathToRoot)
transitive, _, _, err := jsonparser.Get(value, "dependencies")
if err != nil && err.Error() != "Key path not found" {
return err
Expand Down Expand Up @@ -256,7 +256,7 @@ func npmLsDependencyParser(data []byte) (*npmLsDependency, error) {
return npmLsDependency, json.Unmarshal(data, &npmLsDependency)
}

func appendDependency(dependencies map[string]*dependencyInfo, dep *npmLsDependency, pathToRoot []string, log utils.Log) {
func appendDependency(dependencies map[string]*dependencyInfo, dep *npmLsDependency, pathToRoot []string) {
depId := dep.id()
scopes := dep.getScopes()
if dependencies[depId] == nil {
Expand All @@ -275,7 +275,7 @@ func appendDependency(dependencies map[string]*dependencyInfo, dep *npmLsDepende
}

// Lookup for a dependency's tarball in npm cache, and calculate checksum.
func calculateChecksum(cacache *cacache, name, version, integrity string, log utils.Log) (md5 string, sha1 string, sha256 string, err error) {
func calculateChecksum(cacache *cacache, name, version, integrity string) (md5 string, sha1 string, sha256 string, err error) {
if integrity == "" {
var info *cacacheInfo
info, err = cacache.GetInfo(name + "@" + version)
Expand Down Expand Up @@ -370,7 +370,6 @@ func GetNpmVersionAndExecPath(log utils.Log) (*version.Version, string, error) {
if err != nil {
return nil, "", err
}
log.Debug("Using npm version:", string(versionData))
return version.NewVersion(string(versionData)), npmExecPath, nil
}

Expand Down Expand Up @@ -462,5 +461,5 @@ func GetNpmConfigCache(srcPath, executablePath string, npmArgs []string, log uti
}

func printMissingDependenciesWarning(dependencyType string, dependencies []string, log utils.Log) {
log.Debug("The following dependencies will not be included in the build-info, because the 'npm ls' command did not return their integrity.\nThe reason why the version wasn't returned may be because the package is a '" + dependencyType + "', which was not manually installed.\n It is therefore okay to skip this dependency: " + strings.Join(dependencies, ","))
log.Debug("The following dependencies will not be included in the build-info, because the 'npm ls' command did not return their integrity.\nThe reason why the version wasn't returned may be because the package is a '" + dependencyType + "', which was not manually installed.\nIt is therefore okay to skip this dependency: " + strings.Join(dependencies, ","))
}
1 change: 0 additions & 1 deletion utils/pythonutils/poetryutils.go
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,6 @@ func extractProjectFromPyproject(pyprojectFilePath string) (project PoetryPackag
return
}
var pyprojectFile PyprojectToml

_, err = toml.Decode(string(content), &pyprojectFile)
if err != nil {
return
Expand Down

0 comments on commit 9b6f2ec

Please sign in to comment.