You've already forked sap-jenkins-library
mirror of
https://github.com/SAP/jenkins-library.git
synced 2025-09-16 09:26:22 +02:00
Fix maven parameter handling (#1493)
Avoid maven error `Unknown lifecycle phase \"-\"` when the value of a define contains `-`. Don't split and trim maven arguments. Expect they come in as a list, keep them as list. This is a breaking change compared to the old Groovy implementation which relied on using a shell for calling maven. As an example, consider this diff: ```diff - goals: 'org.apache.maven.plugins:maven-help-plugin:3.1.0:evaluate', - defines: "-Dexpression=$pomPathExpression -DforceStdout -q", + goals: ['org.apache.maven.plugins:maven-help-plugin:3.1.0:evaluate'], + defines: ["-Dexpression=$pomPathExpression", "-DforceStdout", "-q"], ```
This commit is contained in:
@@ -4,12 +4,13 @@ import (
|
|||||||
"github.com/SAP/jenkins-library/pkg/command"
|
"github.com/SAP/jenkins-library/pkg/command"
|
||||||
"github.com/SAP/jenkins-library/pkg/log"
|
"github.com/SAP/jenkins-library/pkg/log"
|
||||||
"github.com/SAP/jenkins-library/pkg/maven"
|
"github.com/SAP/jenkins-library/pkg/maven"
|
||||||
sliceUtils "github.com/SAP/jenkins-library/pkg/piperutils"
|
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
|
|
||||||
"github.com/SAP/jenkins-library/pkg/telemetry"
|
"github.com/SAP/jenkins-library/pkg/telemetry"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
var writeFile = ioutil.WriteFile
|
||||||
|
|
||||||
func mavenExecute(config mavenExecuteOptions, _ *telemetry.CustomData) {
|
func mavenExecute(config mavenExecuteOptions, _ *telemetry.CustomData) {
|
||||||
runner := command.Command{}
|
runner := command.Command{}
|
||||||
err := runMavenExecute(config, &runner)
|
err := runMavenExecute(config, &runner)
|
||||||
@@ -24,22 +25,16 @@ func runMavenExecute(config mavenExecuteOptions, runner execRunner) error {
|
|||||||
ProjectSettingsFile: config.ProjectSettingsFile,
|
ProjectSettingsFile: config.ProjectSettingsFile,
|
||||||
GlobalSettingsFile: config.GlobalSettingsFile,
|
GlobalSettingsFile: config.GlobalSettingsFile,
|
||||||
M2Path: config.M2Path,
|
M2Path: config.M2Path,
|
||||||
Goals: splitAndTrimParams(config.Goals),
|
Goals: config.Goals,
|
||||||
Defines: splitAndTrimParams(config.Defines),
|
Defines: config.Defines,
|
||||||
Flags: splitAndTrimParams(config.Flags),
|
Flags: config.Flags,
|
||||||
LogSuccessfulMavenTransfers: config.LogSuccessfulMavenTransfers,
|
LogSuccessfulMavenTransfers: config.LogSuccessfulMavenTransfers,
|
||||||
ReturnStdout: config.ReturnStdout,
|
ReturnStdout: config.ReturnStdout,
|
||||||
}
|
}
|
||||||
|
|
||||||
output, err := maven.Execute(&options, runner)
|
output, err := maven.Execute(&options, runner)
|
||||||
if err == nil && config.ReturnStdout {
|
if err == nil && config.ReturnStdout {
|
||||||
err = ioutil.WriteFile(".pipeline/maven_output.txt", []byte(output), 0644)
|
err = writeFile(".pipeline/maven_output.txt", []byte(output), 0644)
|
||||||
}
|
}
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
// We *must not* deduplicate the parameters here as this will break commands such as `mvn -pl a -pl b`,
|
|
||||||
// which would become `mvn -pl a b` which is invalid
|
|
||||||
func splitAndTrimParams(params []string) []string {
|
|
||||||
return sliceUtils.SplitAndTrim(params, " ")
|
|
||||||
}
|
|
||||||
|
@@ -3,33 +3,87 @@ package cmd
|
|||||||
import (
|
import (
|
||||||
"github.com/SAP/jenkins-library/pkg/mock"
|
"github.com/SAP/jenkins-library/pkg/mock"
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
|
"os"
|
||||||
"testing"
|
"testing"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestMavenExecute(t *testing.T) {
|
func TestMavenExecute(t *testing.T) {
|
||||||
t.Run("mavenExecute should cleanup the parameters", func(t *testing.T) {
|
t.Run("mavenExecute should write output file", func(t *testing.T) {
|
||||||
mockRunner := mock.ExecMockRunner{}
|
// init
|
||||||
|
|
||||||
config := mavenExecuteOptions{
|
config := mavenExecuteOptions{
|
||||||
Flags: []string{"--errors --fail-fast "},
|
Goals: []string{"goal"},
|
||||||
Defines: []string{" -DoutputFile=mvnDependencyTree.txt"},
|
LogSuccessfulMavenTransfers: true,
|
||||||
Goals: []string{" dependency:tree"},
|
ReturnStdout: true,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
mockRunner := mock.ExecMockRunner{}
|
||||||
|
mockRunner.StdoutReturn = map[string]string{}
|
||||||
|
mockRunner.StdoutReturn[""] = "test output"
|
||||||
|
|
||||||
|
var outputFile string
|
||||||
|
var output []byte
|
||||||
|
|
||||||
|
oldWriteFile := writeFile
|
||||||
|
writeFile = func(filename string, data []byte, perm os.FileMode) error {
|
||||||
|
outputFile = filename
|
||||||
|
output = data
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
defer func() { writeFile = oldWriteFile }()
|
||||||
|
|
||||||
|
// test
|
||||||
err := runMavenExecute(config, &mockRunner)
|
err := runMavenExecute(config, &mockRunner)
|
||||||
|
|
||||||
|
// assert
|
||||||
expectedParams := []string{
|
expectedParams := []string{
|
||||||
"--errors",
|
"--batch-mode", "goal",
|
||||||
"--fail-fast",
|
|
||||||
"-DoutputFile=mvnDependencyTree.txt",
|
|
||||||
"-Dorg.slf4j.simpleLogger.log.org.apache.maven.cli.transfer.Slf4jMavenTransferListener=warn",
|
|
||||||
"--batch-mode",
|
|
||||||
"dependency:tree",
|
|
||||||
}
|
}
|
||||||
|
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
assert.Equal(t, "mvn", mockRunner.Calls[0].Exec)
|
if assert.Equal(t, 1, len(mockRunner.Calls)) {
|
||||||
assert.Equal(t, expectedParams, mockRunner.Calls[0].Params)
|
assert.Equal(t, "mvn", mockRunner.Calls[0].Exec)
|
||||||
|
assert.Equal(t, expectedParams, mockRunner.Calls[0].Params)
|
||||||
|
}
|
||||||
|
assert.Equal(t, "test output", string(output))
|
||||||
|
assert.Equal(t, ".pipeline/maven_output.txt", outputFile)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
t.Run("mavenExecute should NOT write output file", func(t *testing.T) {
|
||||||
|
// init
|
||||||
|
config := mavenExecuteOptions{
|
||||||
|
Goals: []string{"goal"},
|
||||||
|
LogSuccessfulMavenTransfers: true,
|
||||||
|
}
|
||||||
|
|
||||||
|
mockRunner := mock.ExecMockRunner{}
|
||||||
|
mockRunner.StdoutReturn = map[string]string{}
|
||||||
|
mockRunner.StdoutReturn[""] = "test output"
|
||||||
|
|
||||||
|
var outputFile string
|
||||||
|
var output []byte
|
||||||
|
|
||||||
|
oldWriteFile := writeFile
|
||||||
|
writeFile = func(filename string, data []byte, perm os.FileMode) error {
|
||||||
|
outputFile = filename
|
||||||
|
output = data
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
defer func() { writeFile = oldWriteFile }()
|
||||||
|
|
||||||
|
// test
|
||||||
|
err := runMavenExecute(config, &mockRunner)
|
||||||
|
|
||||||
|
// assert
|
||||||
|
expectedParams := []string{
|
||||||
|
"--batch-mode", "goal",
|
||||||
|
}
|
||||||
|
|
||||||
|
assert.NoError(t, err)
|
||||||
|
if assert.Equal(t, 1, len(mockRunner.Calls)) {
|
||||||
|
assert.Equal(t, "mvn", mockRunner.Calls[0].Exec)
|
||||||
|
assert.Equal(t, expectedParams, mockRunner.Calls[0].Params)
|
||||||
|
}
|
||||||
|
assert.Equal(t, "", string(output))
|
||||||
|
assert.Equal(t, "", outputFile)
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
17
cmd/piper.go
17
cmd/piper.go
@@ -178,7 +178,7 @@ func PrepareConfig(cmd *cobra.Command, metadata *config.StepData, stepName strin
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
stepConfig.Config = convertTypes(stepConfig.Config, options)
|
stepConfig.Config = checkTypes(stepConfig.Config, options)
|
||||||
confJSON, _ := json.Marshal(stepConfig.Config)
|
confJSON, _ := json.Marshal(stepConfig.Config)
|
||||||
_ = json.Unmarshal(confJSON, &options)
|
_ = json.Unmarshal(confJSON, &options)
|
||||||
|
|
||||||
@@ -194,7 +194,7 @@ func PrepareConfig(cmd *cobra.Command, metadata *config.StepData, stepName strin
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func convertTypes(config map[string]interface{}, options interface{}) map[string]interface{} {
|
func checkTypes(config map[string]interface{}, options interface{}) map[string]interface{} {
|
||||||
optionsType := getStepOptionsStructType(options)
|
optionsType := getStepOptionsStructType(options)
|
||||||
|
|
||||||
for paramName := range config {
|
for paramName := range config {
|
||||||
@@ -205,7 +205,7 @@ func convertTypes(config map[string]interface{}, options interface{}) map[string
|
|||||||
|
|
||||||
paramValueType := reflect.ValueOf(config[paramName])
|
paramValueType := reflect.ValueOf(config[paramName])
|
||||||
if paramValueType.Kind() != reflect.String {
|
if paramValueType.Kind() != reflect.String {
|
||||||
// We can only convert from strings at the moment
|
// Type check is limited to strings at the moment
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -214,14 +214,15 @@ func convertTypes(config map[string]interface{}, options interface{}) map[string
|
|||||||
|
|
||||||
switch optionsField.Type.Kind() {
|
switch optionsField.Type.Kind() {
|
||||||
case reflect.String:
|
case reflect.String:
|
||||||
// Types already match, ignore
|
// Types match, ignore
|
||||||
logWarning = false
|
logWarning = false
|
||||||
case reflect.Slice, reflect.Array:
|
case reflect.Slice, reflect.Array:
|
||||||
if optionsField.Type.Elem().Kind() == reflect.String {
|
// Could do automatic conversion for those types in theory,
|
||||||
config[paramName] = []string{paramValue}
|
// but that might obscure what really happens in error cases.
|
||||||
logWarning = false
|
log.Entry().Fatalf("Type mismatch in configuration for option '%s'. Expected type to be a list (or slice, or array) but got %s.", paramName, paramValueType.Kind())
|
||||||
}
|
|
||||||
case reflect.Bool:
|
case reflect.Bool:
|
||||||
|
// Sensible to convert strings "true"/"false" to respective boolean values as it is
|
||||||
|
// common practice to write booleans as string in yaml files.
|
||||||
paramValue = strings.ToLower(paramValue)
|
paramValue = strings.ToLower(paramValue)
|
||||||
if paramValue == "true" {
|
if paramValue == "true" {
|
||||||
config[paramName] = true
|
config[paramName] = true
|
||||||
|
@@ -3,6 +3,7 @@ package cmd
|
|||||||
import (
|
import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"github.com/SAP/jenkins-library/pkg/log"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
@@ -131,36 +132,52 @@ func TestGetProjectConfigFile(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestConvertTypes(t *testing.T) {
|
func TestConvertTypes(t *testing.T) {
|
||||||
// Init
|
t.Run("Converts strings to booleans", func(t *testing.T) {
|
||||||
options := struct {
|
// Init
|
||||||
Foo []string `json:"foo,omitempty"`
|
options := struct {
|
||||||
Bar bool `json:"bar,omitempty"`
|
Foo bool `json:"foo,omitempty"`
|
||||||
Baz string `json:"baz,omitempty"`
|
Bar bool `json:"bar,omitempty"`
|
||||||
Bla int `json:"bla,omitempty"`
|
}{}
|
||||||
}{}
|
options.Foo = true
|
||||||
|
options.Bar = false
|
||||||
|
|
||||||
stepConfig := map[string]interface{}{}
|
stepConfig := map[string]interface{}{}
|
||||||
stepConfig["baz"] = "ignore"
|
stepConfig["foo"] = "False"
|
||||||
stepConfig["foo"] = "element"
|
stepConfig["bar"] = "True"
|
||||||
stepConfig["bar"] = "True"
|
|
||||||
stepConfig["bla"] = "42"
|
|
||||||
|
|
||||||
// Test
|
// Test
|
||||||
stepConfig = convertTypes(stepConfig, options)
|
stepConfig = checkTypes(stepConfig, options)
|
||||||
|
|
||||||
confJSON, _ := json.Marshal(stepConfig)
|
confJSON, _ := json.Marshal(stepConfig)
|
||||||
_ = json.Unmarshal(confJSON, &options)
|
_ = json.Unmarshal(confJSON, &options)
|
||||||
|
|
||||||
// Assert
|
// Assert
|
||||||
assert.Equal(t, []string{"element"}, stepConfig["foo"])
|
assert.Equal(t, false, stepConfig["foo"])
|
||||||
assert.Equal(t, true, stepConfig["bar"])
|
assert.Equal(t, true, stepConfig["bar"])
|
||||||
|
assert.Equal(t, false, options.Foo)
|
||||||
|
assert.Equal(t, true, options.Bar)
|
||||||
|
})
|
||||||
|
t.Run("Exits on unsupported type mismatch", func(t *testing.T) {
|
||||||
|
// Init
|
||||||
|
hasFailed := false
|
||||||
|
|
||||||
assert.Equal(t, []string{"element"}, options.Foo)
|
exitFunc := log.Entry().Logger.ExitFunc
|
||||||
assert.Equal(t, true, options.Bar)
|
log.Entry().Logger.ExitFunc = func(int) {
|
||||||
|
hasFailed = true
|
||||||
|
}
|
||||||
|
defer func() { log.Entry().Logger.ExitFunc = exitFunc }()
|
||||||
|
|
||||||
assert.Equal(t, "ignore", stepConfig["baz"])
|
options := struct {
|
||||||
assert.Equal(t, "42", stepConfig["bla"])
|
Foo []string `json:"foo,omitempty"`
|
||||||
|
}{}
|
||||||
|
|
||||||
assert.Equal(t, "ignore", options.Baz)
|
stepConfig := map[string]interface{}{}
|
||||||
assert.Equal(t, 0, options.Bla)
|
stepConfig["foo"] = "entry"
|
||||||
|
|
||||||
|
// Test
|
||||||
|
stepConfig = checkTypes(stepConfig, options)
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
assert.True(t, hasFailed, "Expected checkTypes() to exit via logging framework")
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
@@ -4,6 +4,23 @@
|
|||||||
|
|
||||||
## ${docGenParameters}
|
## ${docGenParameters}
|
||||||
|
|
||||||
|
!!! note "Breaking change in `goals`, `defines` and `flags` parameters"
|
||||||
|
The `goals`, `defines` and `flags` parameters of the step need to be lists of strings with each element being one item.
|
||||||
|
|
||||||
|
As an example consider this diff, showing the old api deleted and the new api inserted:
|
||||||
|
|
||||||
|
```diff
|
||||||
|
-goals: 'org.apache.maven.plugins:maven-help-plugin:3.1.0:evaluate',
|
||||||
|
-defines: "-Dexpression=$pomPathExpression -DforceStdout -q",
|
||||||
|
+goals: ['org.apache.maven.plugins:maven-help-plugin:3.1.0:evaluate'],
|
||||||
|
+defines: ["-Dexpression=$pomPathExpression", "-DforceStdout", "-q"],
|
||||||
|
```
|
||||||
|
|
||||||
|
Additionally please note that in the parameters _must not_ be [shell quoted/escaped](https://www.tldp.org/LDP/Bash-Beginners-Guide/html/sect_03_03.html).
|
||||||
|
What you pass in is literally passed to Maven without any shell interpreter inbetween.
|
||||||
|
|
||||||
|
The old behavior is still available in version `v1.23.0` and before of project "Piper".
|
||||||
|
|
||||||
## ${docGenConfiguration}
|
## ${docGenConfiguration}
|
||||||
|
|
||||||
## ${docJenkinsPluginDependencies}
|
## ${docJenkinsPluginDependencies}
|
||||||
@@ -15,5 +32,5 @@ None
|
|||||||
## Example
|
## Example
|
||||||
|
|
||||||
```groovy
|
```groovy
|
||||||
mavenExecute script: this, goals: 'clean install'
|
mavenExecute script: this, goals: ['clean', 'install']
|
||||||
```
|
```
|
||||||
|
@@ -155,6 +155,7 @@ func getParametersFromOptions(options *ExecuteOptions, utils mavenUtils) ([]stri
|
|||||||
parameters = append(parameters, "--batch-mode")
|
parameters = append(parameters, "--batch-mode")
|
||||||
|
|
||||||
parameters = append(parameters, options.Goals...)
|
parameters = append(parameters, options.Goals...)
|
||||||
|
|
||||||
return parameters, nil
|
return parameters, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -81,7 +81,8 @@ func TestExecute(t *testing.T) {
|
|||||||
Flags: []string{"-q"}, LogSuccessfulMavenTransfers: true,
|
Flags: []string{"-q"}, LogSuccessfulMavenTransfers: true,
|
||||||
ReturnStdout: false}
|
ReturnStdout: false}
|
||||||
expectedParameters := []string{"--global-settings", "anotherSettings.xml", "--settings", "settings.xml",
|
expectedParameters := []string{"--global-settings", "anotherSettings.xml", "--settings", "settings.xml",
|
||||||
"-Dmaven.repo.local=.m2/", "--file", "pom.xml", "-q", "-Da=b", "--batch-mode", "flatten", "install"}
|
"-Dmaven.repo.local=.m2/", "--file", "pom.xml", "-q", "-Da=b", "--batch-mode",
|
||||||
|
"flatten", "install"}
|
||||||
|
|
||||||
mavenOutput, _ := Execute(&opts, &execMockRunner)
|
mavenOutput, _ := Execute(&opts, &execMockRunner)
|
||||||
|
|
||||||
|
@@ -2,11 +2,13 @@ package com.sap.piper
|
|||||||
|
|
||||||
class BashUtils implements Serializable {
|
class BashUtils implements Serializable {
|
||||||
static final long serialVersionUID = 1L
|
static final long serialVersionUID = 1L
|
||||||
|
public static final String ESCAPED_SINGLE_QUOTE = "'\"'\"'"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Put string in single quotes and escape contained single quotes by putting them into a double quoted string
|
||||||
|
*/
|
||||||
static String quoteAndEscape(String str) {
|
static String quoteAndEscape(String str) {
|
||||||
// put string in single quotes and escape contained single quotes by putting them into a double quoted string
|
def escapedString = str.replace("'", ESCAPED_SINGLE_QUOTE)
|
||||||
|
|
||||||
def escapedString = str.replace("'", "'\"'\"'")
|
|
||||||
return "'${escapedString}'"
|
return "'${escapedString}'"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -159,8 +159,8 @@ static String evaluateFromMavenPom(Script script, String pomFileName, String pom
|
|||||||
String resolvedExpression = script.mavenExecute(
|
String resolvedExpression = script.mavenExecute(
|
||||||
script: script,
|
script: script,
|
||||||
pomPath: pomFileName,
|
pomPath: pomFileName,
|
||||||
goals: 'org.apache.maven.plugins:maven-help-plugin:3.1.0:evaluate',
|
goals: ['org.apache.maven.plugins:maven-help-plugin:3.1.0:evaluate'],
|
||||||
defines: "-Dexpression=$pomPathExpression -DforceStdout -q",
|
defines: ["-Dexpression=$pomPathExpression", "-DforceStdout", "-q"],
|
||||||
returnStdout: true
|
returnStdout: true
|
||||||
)
|
)
|
||||||
if (resolvedExpression.startsWith('null object or invalid expression')) {
|
if (resolvedExpression.startsWith('null object or invalid expression')) {
|
||||||
|
@@ -16,6 +16,9 @@ class MavenArtifactVersioning extends ArtifactVersioning {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
def setVersion(version) {
|
def setVersion(version) {
|
||||||
script.mavenExecute script: script, goals: 'org.codehaus.mojo:versions-maven-plugin:2.7:set', defines: "-DnewVersion=${version} -DgenerateBackupPoms=false", pomPath: configuration.filePath
|
script.mavenExecute script: script,
|
||||||
|
goals: ['org.codehaus.mojo:versions-maven-plugin:2.7:set'],
|
||||||
|
defines: ["-DnewVersion=${version}", "-DgenerateBackupPoms=false"],
|
||||||
|
pomPath: configuration.filePath
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -89,14 +89,14 @@ class ArtifactSetVersionTest extends BasePiperTest {
|
|||||||
|
|
||||||
mvnExecuteRule.setReturnValue([
|
mvnExecuteRule.setReturnValue([
|
||||||
'pomPath': 'pom.xml',
|
'pomPath': 'pom.xml',
|
||||||
'goals': 'org.apache.maven.plugins:maven-help-plugin:3.1.0:evaluate',
|
'goals': ['org.apache.maven.plugins:maven-help-plugin:3.1.0:evaluate'],
|
||||||
'defines': '-Dexpression=project.version -DforceStdout -q',
|
'defines': ['-Dexpression=project.version', '-DforceStdout', '-q'],
|
||||||
], version)
|
], version)
|
||||||
|
|
||||||
mvnExecuteRule.setReturnValue([
|
mvnExecuteRule.setReturnValue([
|
||||||
'pomPath': 'snapshot/pom.xml',
|
'pomPath': 'snapshot/pom.xml',
|
||||||
'goals': 'org.apache.maven.plugins:maven-help-plugin:3.1.0:evaluate',
|
'goals': ['org.apache.maven.plugins:maven-help-plugin:3.1.0:evaluate'],
|
||||||
'defines': '-Dexpression=project.version -DforceStdout -q',
|
'defines': ['-Dexpression=project.version', '-DforceStdout', '-q'],
|
||||||
], version)
|
], version)
|
||||||
|
|
||||||
shellRule.setReturnValue("date --utc +'%Y%m%d%H%M%S'", '20180101010203')
|
shellRule.setReturnValue("date --utc +'%Y%m%d%H%M%S'", '20180101010203')
|
||||||
@@ -114,8 +114,8 @@ class ArtifactSetVersionTest extends BasePiperTest {
|
|||||||
|
|
||||||
assertEquals(new JenkinsMavenExecuteRule.Execution([
|
assertEquals(new JenkinsMavenExecuteRule.Execution([
|
||||||
pomPath: 'pom.xml',
|
pomPath: 'pom.xml',
|
||||||
goals: 'org.codehaus.mojo:versions-maven-plugin:2.7:set',
|
goals: ['org.codehaus.mojo:versions-maven-plugin:2.7:set'],
|
||||||
defines: '-DnewVersion=1.2.3-20180101010203_testCommitId -DgenerateBackupPoms=false'
|
defines: ['-DnewVersion=1.2.3-20180101010203_testCommitId', '-DgenerateBackupPoms=false']
|
||||||
]), mvnExecuteRule.executions[1])
|
]), mvnExecuteRule.executions[1])
|
||||||
|
|
||||||
assertThat(shellRule.shell.join(), stringContainsInOrder([
|
assertThat(shellRule.shell.join(), stringContainsInOrder([
|
||||||
@@ -158,8 +158,8 @@ class ArtifactSetVersionTest extends BasePiperTest {
|
|||||||
|
|
||||||
assertEquals(new JenkinsMavenExecuteRule.Execution([
|
assertEquals(new JenkinsMavenExecuteRule.Execution([
|
||||||
pomPath: 'pom.xml',
|
pomPath: 'pom.xml',
|
||||||
goals: 'org.codehaus.mojo:versions-maven-plugin:2.7:set',
|
goals: ['org.codehaus.mojo:versions-maven-plugin:2.7:set'],
|
||||||
defines: '-DnewVersion=1.2.3-20180101010203_testCommitId -DgenerateBackupPoms=false'
|
defines: ['-DnewVersion=1.2.3-20180101010203_testCommitId', '-DgenerateBackupPoms=false']
|
||||||
]), mvnExecuteRule.executions[1])
|
]), mvnExecuteRule.executions[1])
|
||||||
assertThat(((Iterable)shellRule.shell).join(), stringContainsInOrder([
|
assertThat(((Iterable)shellRule.shell).join(), stringContainsInOrder([
|
||||||
"git add .",
|
"git add .",
|
||||||
@@ -282,8 +282,8 @@ class ArtifactSetVersionTest extends BasePiperTest {
|
|||||||
assertEquals('1.2.3-20180101010203_testCommitId', environmentRule.env.getArtifactVersion())
|
assertEquals('1.2.3-20180101010203_testCommitId', environmentRule.env.getArtifactVersion())
|
||||||
assertEquals(new JenkinsMavenExecuteRule.Execution([
|
assertEquals(new JenkinsMavenExecuteRule.Execution([
|
||||||
pomPath: 'pom.xml',
|
pomPath: 'pom.xml',
|
||||||
goals: 'org.codehaus.mojo:versions-maven-plugin:2.7:set',
|
goals: ['org.codehaus.mojo:versions-maven-plugin:2.7:set'],
|
||||||
defines: '-DnewVersion=1.2.3-20180101010203_testCommitId -DgenerateBackupPoms=false'
|
defines: ['-DnewVersion=1.2.3-20180101010203_testCommitId', '-DgenerateBackupPoms=false']
|
||||||
]), mvnExecuteRule.executions[1])
|
]), mvnExecuteRule.executions[1])
|
||||||
assertThat(shellRule.shell, not(hasItem(containsString('commit'))))
|
assertThat(shellRule.shell, not(hasItem(containsString('commit'))))
|
||||||
}
|
}
|
||||||
|
@@ -40,14 +40,14 @@ class MavenArtifactVersioningTest extends BasePiperTest{
|
|||||||
|
|
||||||
mvnExecuteRule.setReturnValue([
|
mvnExecuteRule.setReturnValue([
|
||||||
'pomPath': 'pom.xml',
|
'pomPath': 'pom.xml',
|
||||||
'goals': 'org.apache.maven.plugins:maven-help-plugin:3.1.0:evaluate',
|
'goals': ['org.apache.maven.plugins:maven-help-plugin:3.1.0:evaluate'],
|
||||||
'defines': '-Dexpression=project.version -DforceStdout -q',
|
'defines': ['-Dexpression=project.version', '-DforceStdout', '-q'],
|
||||||
], version)
|
], version)
|
||||||
|
|
||||||
mvnExecuteRule.setReturnValue([
|
mvnExecuteRule.setReturnValue([
|
||||||
'pomPath': 'snapshot/pom.xml',
|
'pomPath': 'snapshot/pom.xml',
|
||||||
'goals': 'org.apache.maven.plugins:maven-help-plugin:3.1.0:evaluate',
|
'goals': ['org.apache.maven.plugins:maven-help-plugin:3.1.0:evaluate'],
|
||||||
'defines': '-Dexpression=project.version -DforceStdout -q',
|
'defines': ['-Dexpression=project.version', '-DforceStdout', '-q'],
|
||||||
], version)
|
], version)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -60,13 +60,13 @@ class MavenArtifactVersioningTest extends BasePiperTest{
|
|||||||
assertEquals(2, mvnExecuteRule.executions.size())
|
assertEquals(2, mvnExecuteRule.executions.size())
|
||||||
assertEquals(new JenkinsMavenExecuteRule.Execution([
|
assertEquals(new JenkinsMavenExecuteRule.Execution([
|
||||||
pomPath: 'pom.xml',
|
pomPath: 'pom.xml',
|
||||||
goals: 'org.apache.maven.plugins:maven-help-plugin:3.1.0:evaluate',
|
goals: ['org.apache.maven.plugins:maven-help-plugin:3.1.0:evaluate'],
|
||||||
defines: '-Dexpression=project.version -DforceStdout -q'
|
defines: ['-Dexpression=project.version', '-DforceStdout', '-q']
|
||||||
]), mvnExecuteRule.executions[0])
|
]), mvnExecuteRule.executions[0])
|
||||||
assertEquals(new JenkinsMavenExecuteRule.Execution([
|
assertEquals(new JenkinsMavenExecuteRule.Execution([
|
||||||
pomPath: 'pom.xml',
|
pomPath: 'pom.xml',
|
||||||
goals: 'org.codehaus.mojo:versions-maven-plugin:2.7:set',
|
goals: ['org.codehaus.mojo:versions-maven-plugin:2.7:set'],
|
||||||
defines: '-DnewVersion=1.2.3-20180101 -DgenerateBackupPoms=false'
|
defines: ['-DnewVersion=1.2.3-20180101', '-DgenerateBackupPoms=false']
|
||||||
]), mvnExecuteRule.executions[1])
|
]), mvnExecuteRule.executions[1])
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -79,13 +79,13 @@ class MavenArtifactVersioningTest extends BasePiperTest{
|
|||||||
assertEquals(2, mvnExecuteRule.executions.size())
|
assertEquals(2, mvnExecuteRule.executions.size())
|
||||||
assertEquals(new JenkinsMavenExecuteRule.Execution([
|
assertEquals(new JenkinsMavenExecuteRule.Execution([
|
||||||
pomPath: 'snapshot/pom.xml',
|
pomPath: 'snapshot/pom.xml',
|
||||||
goals : 'org.apache.maven.plugins:maven-help-plugin:3.1.0:evaluate',
|
goals: ['org.apache.maven.plugins:maven-help-plugin:3.1.0:evaluate'],
|
||||||
defines: '-Dexpression=project.version -DforceStdout -q'
|
defines: ['-Dexpression=project.version', '-DforceStdout', '-q']
|
||||||
]), mvnExecuteRule.executions[0])
|
]), mvnExecuteRule.executions[0])
|
||||||
assertEquals(new JenkinsMavenExecuteRule.Execution([
|
assertEquals(new JenkinsMavenExecuteRule.Execution([
|
||||||
pomPath: 'snapshot/pom.xml',
|
pomPath: 'snapshot/pom.xml',
|
||||||
goals : 'org.codehaus.mojo:versions-maven-plugin:2.7:set',
|
goals: ['org.codehaus.mojo:versions-maven-plugin:2.7:set'],
|
||||||
defines: '-DnewVersion=1.2.3-20180101 -DgenerateBackupPoms=false'
|
defines: ['-DnewVersion=1.2.3-20180101', '-DgenerateBackupPoms=false']
|
||||||
]), mvnExecuteRule.executions[1])
|
]), mvnExecuteRule.executions[1])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -10,5 +10,6 @@ void call(Map parameters = [:]) {
|
|||||||
List credentials = [ ]
|
List credentials = [ ]
|
||||||
final script = checkScript(this, parameters) ?: this
|
final script = checkScript(this, parameters) ?: this
|
||||||
parameters = DownloadCacheUtils.injectDownloadCacheInMavenParameters(script, parameters)
|
parameters = DownloadCacheUtils.injectDownloadCacheInMavenParameters(script, parameters)
|
||||||
|
|
||||||
piperExecuteBin(parameters, STEP_NAME, METADATA_FILE, credentials)
|
piperExecuteBin(parameters, STEP_NAME, METADATA_FILE, credentials)
|
||||||
}
|
}
|
||||||
|
@@ -1,6 +1,6 @@
|
|||||||
import com.sap.piper.DownloadCacheUtils
|
import com.sap.piper.DownloadCacheUtils
|
||||||
|
import com.sap.piper.BashUtils
|
||||||
import groovy.transform.Field
|
import groovy.transform.Field
|
||||||
|
|
||||||
import static com.sap.piper.Prerequisites.checkScript
|
import static com.sap.piper.Prerequisites.checkScript
|
||||||
|
|
||||||
@Field def STEP_NAME = getClass().getName()
|
@Field def STEP_NAME = getClass().getName()
|
||||||
@@ -10,7 +10,15 @@ def call(Map parameters = [:]) {
|
|||||||
final script = checkScript(this, parameters) ?: this
|
final script = checkScript(this, parameters) ?: this
|
||||||
parameters = DownloadCacheUtils.injectDownloadCacheInMavenParameters(script, parameters)
|
parameters = DownloadCacheUtils.injectDownloadCacheInMavenParameters(script, parameters)
|
||||||
|
|
||||||
List credentials = [ ]
|
validateParameter(parameters.defines, 'defines')
|
||||||
|
validateParameter(parameters.flags, 'flags')
|
||||||
|
validateParameter(parameters.goals, 'goals')
|
||||||
|
validateStringParameter(parameters.pomPath)
|
||||||
|
validateStringParameter(parameters.projectSettingsFile)
|
||||||
|
validateStringParameter(parameters.globalSettingsFile)
|
||||||
|
validateStringParameter(parameters.m2Path)
|
||||||
|
|
||||||
|
List credentials = []
|
||||||
piperExecuteBin(parameters, STEP_NAME, METADATA_FILE, credentials)
|
piperExecuteBin(parameters, STEP_NAME, METADATA_FILE, credentials)
|
||||||
|
|
||||||
String output = ''
|
String output = ''
|
||||||
@@ -25,3 +33,46 @@ def call(Map parameters = [:]) {
|
|||||||
}
|
}
|
||||||
return output
|
return output
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void validateParameter(parameter, name) {
|
||||||
|
if (!parameter) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
String errorMessage = "Expected parameter ${name} with value ${parameter} to be of type List, but it is ${parameter.class}. "
|
||||||
|
|
||||||
|
// Specifically check for string-like types as the old step (v1.23.0 and before) allowed that as input
|
||||||
|
if (parameter in CharSequence) {
|
||||||
|
errorMessage += "This is a breaking change for mavenExecute in library version v1.24.0 which allowed strings as input for defines, flags and goals before. " +
|
||||||
|
"To fix that, please update the interface to pass in lists, or use v1.23.0 which is the last version with the old interface. "
|
||||||
|
|
||||||
|
if (parameter.contains(BashUtils.ESCAPED_SINGLE_QUOTE)) {
|
||||||
|
errorMessage += "It looks like your input contains shell escaped quotes. "
|
||||||
|
}
|
||||||
|
|
||||||
|
error errorMessage + "Note that *no* shell escaping is allowed."
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!parameter in List) {
|
||||||
|
error errorMessage + "Note that *no* shell escaping is allowed."
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < parameter.size(); i++) {
|
||||||
|
String element = parameter[i]
|
||||||
|
validateStringParameter(element)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void validateStringParameter(String element) {
|
||||||
|
if (!element) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if (element =~ /-D.*='.*'/) {
|
||||||
|
echo "[$STEP_NAME WARNING] It looks like you passed a define in the form -Dmy.key='this is my value' in $element. Please note that the quotes might cause issues. Correct form: -Dmy.key=this is my value"
|
||||||
|
}
|
||||||
|
|
||||||
|
if (element.length() >= 2 && element.startsWith("'") && element.endsWith("'")) {
|
||||||
|
echo "[$STEP_NAME WARNING] It looks like $element is quoted but it should not be quoted."
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@@ -49,6 +49,8 @@ void call(Map parameters = [:], stepName, metadataFile, List credentialInfo, fai
|
|||||||
String defaultConfigArgs = getCustomDefaultConfigsArg()
|
String defaultConfigArgs = getCustomDefaultConfigsArg()
|
||||||
String customConfigArg = getCustomConfigArg(script)
|
String customConfigArg = getCustomConfigArg(script)
|
||||||
|
|
||||||
|
echo "PIPER_parametersJSON: ${groovy.json.JsonOutput.toJson(stepParameters)}"
|
||||||
|
|
||||||
// get context configuration
|
// get context configuration
|
||||||
Map config = readJSON(text: sh(returnStdout: true, script: "./piper getConfig --contextConfig --stepMetadata '.pipeline/tmp/${metadataFile}'${defaultConfigArgs}${customConfigArg}"))
|
Map config = readJSON(text: sh(returnStdout: true, script: "./piper getConfig --contextConfig --stepMetadata '.pipeline/tmp/${metadataFile}'${defaultConfigArgs}${customConfigArg}"))
|
||||||
echo "Context Config: ${config}"
|
echo "Context Config: ${config}"
|
||||||
|
Reference in New Issue
Block a user