1
0
mirror of https://github.com/SAP/jenkins-library.git synced 2025-01-20 05:19:40 +02:00

New step mavenExecuteIntegration (#1829)

Co-authored-by: Florian Wilhelm <florian.wilhelm02@sap.com>
This commit is contained in:
Stephan Aßmus 2020-07-29 19:51:27 +02:00 committed by GitHub
parent 77028bf50c
commit a61798ccbf
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
17 changed files with 691 additions and 29 deletions

View File

@ -0,0 +1,106 @@
package cmd
import (
"fmt"
"github.com/SAP/jenkins-library/pkg/command"
"github.com/SAP/jenkins-library/pkg/log"
"github.com/SAP/jenkins-library/pkg/maven"
"github.com/SAP/jenkins-library/pkg/piperutils"
"github.com/SAP/jenkins-library/pkg/telemetry"
"io"
"path/filepath"
"strconv"
"strings"
"unicode"
)
type mavenExecuteIntegrationUtils interface {
Stdout(out io.Writer)
Stderr(err io.Writer)
RunExecutable(e string, p ...string) error
FileExists(filename string) (bool, error)
}
type mavenExecuteIntegrationUtilsBundle struct {
*command.Command
*piperutils.Files
}
func newMavenExecuteIntegrationUtils() mavenExecuteIntegrationUtils {
utils := mavenExecuteIntegrationUtilsBundle{
Command: &command.Command{},
Files: &piperutils.Files{},
}
utils.Stdout(log.Writer())
utils.Stderr(log.Writer())
return &utils
}
func mavenExecuteIntegration(config mavenExecuteIntegrationOptions, _ *telemetry.CustomData) {
utils := newMavenExecuteIntegrationUtils()
err := runMavenExecuteIntegration(&config, utils)
if err != nil {
log.Entry().WithError(err).Fatal("step execution failed")
}
}
func runMavenExecuteIntegration(config *mavenExecuteIntegrationOptions, utils mavenExecuteIntegrationUtils) error {
pomPath := filepath.Join("integration-tests", "pom.xml")
hasIntegrationTestsModule, _ := utils.FileExists(pomPath)
if !hasIntegrationTestsModule {
return fmt.Errorf("maven module 'integration-tests' does not exist in project structure")
}
if err := validateForkCount(config.ForkCount); err != nil {
return err
}
retryDefine := fmt.Sprintf("-Dsurefire.rerunFailingTestsCount=%v", config.Retry)
forkCountDefine := fmt.Sprintf("-Dsurefire.forkCount=%v", config.ForkCount)
mavenOptions := maven.ExecuteOptions{
PomPath: pomPath,
M2Path: config.M2Path,
ProjectSettingsFile: config.ProjectSettingsFile,
GlobalSettingsFile: config.GlobalSettingsFile,
Goals: []string{"org.jacoco:jacoco-maven-plugin:prepare-agent", "test"},
Defines: []string{retryDefine, forkCountDefine},
}
_, err := maven.Execute(&mavenOptions, utils)
return err
}
func validateForkCount(value string) error {
var err error
if strings.HasSuffix(value, "C") {
value := strings.TrimSuffix(value, "C")
for _, c := range value {
if !unicode.IsDigit(c) && c != '.' {
err = fmt.Errorf("only integers or floats allowed with 'C' suffix")
break
}
}
if err == nil {
_, err = strconv.ParseFloat(value, 64)
}
} else {
for _, c := range value {
if !unicode.IsDigit(c) {
err = fmt.Errorf("only integers allowed without 'C' suffix")
break
}
}
if err == nil {
_, err = strconv.ParseInt(value, 10, 64)
}
}
if err != nil {
return fmt.Errorf("invalid forkCount parameter '%v': %w, please see https://maven.apache.org/surefire/maven-surefire-plugin/test-mojo.html#forkCount for details", value, err)
}
return nil
}

View File

@ -0,0 +1,153 @@
// Code generated by piper's step-generator. DO NOT EDIT.
package cmd
import (
"fmt"
"os"
"time"
"github.com/SAP/jenkins-library/pkg/config"
"github.com/SAP/jenkins-library/pkg/log"
"github.com/SAP/jenkins-library/pkg/telemetry"
"github.com/spf13/cobra"
)
type mavenExecuteIntegrationOptions struct {
Retry int `json:"retry,omitempty"`
ForkCount string `json:"forkCount,omitempty"`
ProjectSettingsFile string `json:"projectSettingsFile,omitempty"`
GlobalSettingsFile string `json:"globalSettingsFile,omitempty"`
M2Path string `json:"m2Path,omitempty"`
LogSuccessfulMavenTransfers bool `json:"logSuccessfulMavenTransfers,omitempty"`
}
// MavenExecuteIntegrationCommand This step will execute backend integration tests via the Jacoco Maven-plugin.
func MavenExecuteIntegrationCommand() *cobra.Command {
const STEP_NAME = "mavenExecuteIntegration"
metadata := mavenExecuteIntegrationMetadata()
var stepConfig mavenExecuteIntegrationOptions
var startTime time.Time
var createMavenExecuteIntegrationCmd = &cobra.Command{
Use: STEP_NAME,
Short: "This step will execute backend integration tests via the Jacoco Maven-plugin.",
Long: `If the project contains a Maven module named "integration-tests", this step will execute
the integration tests via the Jacoco Maven-plugin.`,
PreRunE: func(cmd *cobra.Command, _ []string) error {
startTime = time.Now()
log.SetStepName(STEP_NAME)
log.SetVerbose(GeneralConfig.Verbose)
path, _ := os.Getwd()
fatalHook := &log.FatalHook{CorrelationID: GeneralConfig.CorrelationID, Path: path}
log.RegisterHook(fatalHook)
err := PrepareConfig(cmd, &metadata, STEP_NAME, &stepConfig, config.OpenPiperFile)
if err != nil {
log.SetErrorCategory(log.ErrorConfiguration)
return err
}
if len(GeneralConfig.HookConfig.SentryConfig.Dsn) > 0 {
sentryHook := log.NewSentryHook(GeneralConfig.HookConfig.SentryConfig.Dsn, GeneralConfig.CorrelationID)
log.RegisterHook(&sentryHook)
}
return nil
},
Run: func(_ *cobra.Command, _ []string) {
telemetryData := telemetry.CustomData{}
telemetryData.ErrorCode = "1"
handler := func() {
telemetryData.Duration = fmt.Sprintf("%v", time.Since(startTime).Milliseconds())
telemetry.Send(&telemetryData)
}
log.DeferExitHandler(handler)
defer handler()
telemetry.Initialize(GeneralConfig.NoTelemetry, STEP_NAME)
mavenExecuteIntegration(stepConfig, &telemetryData)
telemetryData.ErrorCode = "0"
log.Entry().Info("SUCCESS")
},
}
addMavenExecuteIntegrationFlags(createMavenExecuteIntegrationCmd, &stepConfig)
return createMavenExecuteIntegrationCmd
}
func addMavenExecuteIntegrationFlags(cmd *cobra.Command, stepConfig *mavenExecuteIntegrationOptions) {
cmd.Flags().IntVar(&stepConfig.Retry, "retry", 1, "The number of times that integration tests will be retried before failing the step. Note: This will consume more time for the step execution.")
cmd.Flags().StringVar(&stepConfig.ForkCount, "forkCount", `1C`, "The number of JVM processes that are spawned to run the tests in parallel in case of using a maven based project structure. For more details visit the Surefire documentation at https://maven.apache.org/surefire/maven-surefire-plugin/test-mojo.html#forkCount.")
cmd.Flags().StringVar(&stepConfig.ProjectSettingsFile, "projectSettingsFile", os.Getenv("PIPER_projectSettingsFile"), "Path to the mvn settings file that should be used as project settings file.")
cmd.Flags().StringVar(&stepConfig.GlobalSettingsFile, "globalSettingsFile", os.Getenv("PIPER_globalSettingsFile"), "Path to the mvn settings file that should be used as global settings file.")
cmd.Flags().StringVar(&stepConfig.M2Path, "m2Path", os.Getenv("PIPER_m2Path"), "Path to the location of the local repository that should be used.")
cmd.Flags().BoolVar(&stepConfig.LogSuccessfulMavenTransfers, "logSuccessfulMavenTransfers", false, "Configures maven to log successful downloads. This is set to `false` by default to reduce the noise in build logs.")
}
// retrieve step metadata
func mavenExecuteIntegrationMetadata() config.StepData {
var theMetaData = config.StepData{
Metadata: config.StepMetadata{
Name: "mavenExecuteIntegration",
Aliases: []config.Alias{{Name: "mavenExecute", Deprecated: false}},
},
Spec: config.StepSpec{
Inputs: config.StepInputs{
Parameters: []config.StepParameters{
{
Name: "retry",
ResourceRef: []config.ResourceReference{},
Scope: []string{"PARAMETERS", "STEPS", "STAGES"},
Type: "int",
Mandatory: false,
Aliases: []config.Alias{},
},
{
Name: "forkCount",
ResourceRef: []config.ResourceReference{},
Scope: []string{"PARAMETERS", "STEPS", "STAGES"},
Type: "string",
Mandatory: false,
Aliases: []config.Alias{},
},
{
Name: "projectSettingsFile",
ResourceRef: []config.ResourceReference{},
Scope: []string{"GENERAL", "STEPS", "STAGES", "PARAMETERS"},
Type: "string",
Mandatory: false,
Aliases: []config.Alias{{Name: "maven/projectSettingsFile"}},
},
{
Name: "globalSettingsFile",
ResourceRef: []config.ResourceReference{},
Scope: []string{"GENERAL", "STEPS", "STAGES", "PARAMETERS"},
Type: "string",
Mandatory: false,
Aliases: []config.Alias{{Name: "maven/globalSettingsFile"}},
},
{
Name: "m2Path",
ResourceRef: []config.ResourceReference{},
Scope: []string{"GENERAL", "STEPS", "STAGES", "PARAMETERS"},
Type: "string",
Mandatory: false,
Aliases: []config.Alias{{Name: "maven/m2Path"}},
},
{
Name: "logSuccessfulMavenTransfers",
ResourceRef: []config.ResourceReference{},
Scope: []string{"GENERAL", "STEPS", "STAGES", "PARAMETERS"},
Type: "bool",
Mandatory: false,
Aliases: []config.Alias{{Name: "maven/logSuccessfulMavenTransfers"}},
},
},
},
},
}
return theMetaData
}

View File

@ -0,0 +1,16 @@
package cmd
import (
"testing"
"github.com/stretchr/testify/assert"
)
func TestMavenExecuteIntegrationCommand(t *testing.T) {
testCmd := MavenExecuteIntegrationCommand()
// only high level testing performed - details are tested in step generation procudure
assert.Equal(t, "mavenExecuteIntegration", testCmd.Use, "command name incorrect")
}

View File

@ -0,0 +1,133 @@
package cmd
import (
"github.com/SAP/jenkins-library/pkg/mock"
"github.com/stretchr/testify/assert"
"testing"
)
type mavenExecuteIntegrationTestUtilsBundle struct {
*mock.ExecMockRunner
*mock.FilesMock
}
func TestIntegrationTestModuleDoesNotExist(t *testing.T) {
utils := newMavenIntegrationTestsUtilsBundle()
config := mavenExecuteIntegrationOptions{}
err := runMavenExecuteIntegration(&config, utils)
assert.EqualError(t, err, "maven module 'integration-tests' does not exist in project structure")
}
func TestHappyPathIntegrationTests(t *testing.T) {
utils := newMavenIntegrationTestsUtilsBundle()
utils.FilesMock.AddFile("integration-tests/pom.xml", []byte(`<project> </project>`))
config := mavenExecuteIntegrationOptions{
Retry: 2,
ForkCount: "1C",
}
err := runMavenExecuteIntegration(&config, utils)
if err != nil {
t.Fatalf("Error %s", err)
}
expectedParameters1 := []string{
"--file",
"integration-tests/pom.xml",
"-Dsurefire.rerunFailingTestsCount=2",
"-Dsurefire.forkCount=1C",
"-Dorg.slf4j.simpleLogger.log.org.apache.maven.cli.transfer.Slf4jMavenTransferListener=warn",
"--batch-mode",
"org.jacoco:jacoco-maven-plugin:prepare-agent",
"test",
}
assert.Equal(t, mock.ExecCall{Exec: "mvn", Params: expectedParameters1}, utils.ExecMockRunner.Calls[0])
}
func TestInvalidForkCountParam(t *testing.T) {
// init
utils := newMavenIntegrationTestsUtilsBundle()
utils.FilesMock.AddFile("integration-tests/pom.xml", []byte(`<project> </project>`))
// test
err := runMavenExecuteIntegration(&mavenExecuteIntegrationOptions{ForkCount: "4.2"}, utils)
// assert
if assert.Error(t, err) {
assert.Contains(t, err.Error(), "invalid forkCount parameter")
}
}
func TestValidateForkCount(t *testing.T) {
t.Parallel()
testCases := []struct {
name string
testValue string
expectedError string
}{
{
name: "valid integer",
testValue: "2",
expectedError: "",
},
{
name: "zero is valid",
testValue: "0",
expectedError: "",
},
{
name: "valid floating point",
testValue: "2.5C",
expectedError: "",
},
{
name: "valid integer with C",
testValue: "2C",
expectedError: "",
},
{
name: "invalid floating point",
testValue: "1.2",
expectedError: "invalid forkCount parameter",
},
{
name: "invalid",
testValue: "C1",
expectedError: "invalid forkCount parameter",
},
{
name: "another invalid",
testValue: "1 C",
expectedError: "invalid forkCount parameter",
},
{
name: "invalid float",
testValue: "1..2C",
expectedError: "invalid forkCount parameter",
},
}
for _, testCase := range testCases {
t.Run(testCase.name, func(t *testing.T) {
err := validateForkCount(testCase.testValue)
if testCase.expectedError == "" {
assert.NoError(t, err)
} else if assert.Error(t, err) {
assert.Contains(t, err.Error(), testCase.expectedError)
}
})
}
}
func newMavenIntegrationTestsUtilsBundle() mavenExecuteIntegrationTestUtilsBundle {
utilsBundle := mavenExecuteIntegrationTestUtilsBundle{
ExecMockRunner: &mock.ExecMockRunner{},
FilesMock: &mock.FilesMock{},
}
return utilsBundle
}

View File

@ -81,6 +81,7 @@ func Execute() {
rootCmd.AddCommand(MavenExecuteCommand())
rootCmd.AddCommand(CloudFoundryCreateServiceKeyCommand())
rootCmd.AddCommand(MavenBuildCommand())
rootCmd.AddCommand(MavenExecuteIntegrationCommand())
rootCmd.AddCommand(MavenExecuteStaticCodeChecksCommand())
rootCmd.AddCommand(NexusUploadCommand())
rootCmd.AddCommand(AbapEnvironmentRunATCCheckCommand())

View File

@ -0,0 +1,7 @@
# ${docGenStepName}
## ${docGenDescription}
## ${docGenParameters}
## ${docGenConfiguration}

View File

@ -24,6 +24,16 @@ func TestMavenBuildCloudSdkSpringProject(t *testing.T) {
container.assertHasOutput(t, "BUILD SUCCESS")
container.assertHasFile(t, "/project/application/target/cloud-sdk-spring-archetype-application.jar")
container.assertHasFile(t, "/tmp/.m2/repository")
err = container.whenRunningPiperCommand("mavenExecuteIntegration", "")
if err != nil {
t.Fatalf("Calling piper command filed %s", err)
}
container.assertHasOutput(t, "INFO mydemo.HelloWorldControllerTest - Starting HelloWorldControllerTest")
container.assertHasOutput(t, "Tests run: 1, Failures: 0, Errors: 0, Skipped: 0")
container.assertHasFile(t, "/project/integration-tests/target/coverage-reports/jacoco.exec")
}
func TestMavenBuildCloudSdkTomeeProject(t *testing.T) {
@ -44,4 +54,14 @@ func TestMavenBuildCloudSdkTomeeProject(t *testing.T) {
container.assertHasFile(t, "/project/application/target/cloud-sdk-tomee-archetype-application-classes.jar")
container.assertHasFile(t, "/project/application/target/cloud-sdk-tomee-archetype-application.war")
container.assertHasFile(t, "/tmp/.m2/repository")
err = container.whenRunningPiperCommand("mavenExecuteIntegration", "")
if err != nil {
t.Fatalf("Calling piper command filed %s", err)
}
container.assertHasOutput(t, "(prepare-agent) @ cloud-sdk-tomee-archetype-integration-tests")
container.assertHasOutput(t, "Tests run: 1, Failures: 0, Errors: 0, Skipped: 0")
container.assertHasFile(t, "/project/integration-tests/target/coverage-reports/jacoco.exec")
}

View File

@ -1,5 +1,5 @@
general:
steps:
mavenBuild:
maven:
globalSettingsFile: settings.xml
steps:
stages:

View File

@ -1,5 +1,5 @@
general:
steps:
mavenBuild:
maven:
globalSettingsFile: settings.xml
steps:
stages:

View File

@ -0,0 +1,85 @@
metadata:
name: mavenExecuteIntegration
aliases:
- name: mavenExecute
deprecated: false
description: "This step will execute backend integration tests via the Jacoco Maven-plugin."
longDescription: |
If the project contains a Maven module named "integration-tests", this step will execute
the integration tests via the Jacoco Maven-plugin.
spec:
inputs:
params:
- name: retry
type: int
description: "The number of times that integration tests will be retried before failing the step.
Note: This will consume more time for the step execution."
scope:
- PARAMETERS
- STEPS
- STAGES
default: 1
- name: forkCount
type: string
description: "The number of JVM processes that are spawned to run the tests in parallel in case of
using a maven based project structure.
For more details visit the Surefire documentation at
https://maven.apache.org/surefire/maven-surefire-plugin/test-mojo.html#forkCount."
scope:
- PARAMETERS
- STEPS
- STAGES
default: "1C"
# Global maven settings, should be added to all maven steps
- name: projectSettingsFile
type: string
description: "Path to the mvn settings file that should be used as project settings file."
scope:
- GENERAL
- STEPS
- STAGES
- PARAMETERS
aliases:
- name: maven/projectSettingsFile
- name: globalSettingsFile
type: string
description: "Path to the mvn settings file that should be used as global settings file."
scope:
- GENERAL
- STEPS
- STAGES
- PARAMETERS
aliases:
- name: maven/globalSettingsFile
- name: m2Path
type: string
description: "Path to the location of the local repository that should be used."
scope:
- GENERAL
- STEPS
- STAGES
- PARAMETERS
aliases:
- name: maven/m2Path
- name: logSuccessfulMavenTransfers
type: bool
description: "Configures maven to log successful downloads.
This is set to `false` by default to reduce the noise in build logs."
scope:
- GENERAL
- STEPS
- STAGES
- PARAMETERS
default: false
aliases:
- name: maven/logSuccessfulMavenTransfers
containers:
- name: mvn
image: maven:3.6-jdk-8
imagePullPolicy: Never
# This declaration is necessary in order to return any sidecar configuration in the context config.
sidecars:
- name: ''

View File

@ -4,31 +4,33 @@ package com.sap.piper
class DownloadCacheUtils {
static Map injectDownloadCacheInParameters(Script script, Map parameters, BuildTool buildTool) {
if (DownloadCacheUtils.isEnabled(script)) {
if (!isEnabled(script)) {
return parameters
}
if (!parameters.dockerOptions) {
parameters.dockerOptions = []
}
if (parameters.dockerOptions instanceof CharSequence) {
parameters.dockerOptions = [parameters.dockerOptions]
if (!parameters.dockerOptions) {
parameters.dockerOptions = []
}
if (parameters.dockerOptions instanceof CharSequence) {
parameters.dockerOptions = [parameters.dockerOptions]
}
if (!(parameters.dockerOptions instanceof List)) {
throw new IllegalArgumentException("Unexpected type for dockerOptions. Expected was either a list or a string. Actual type was: '${parameters.dockerOptions.getClass()}'")
}
parameters.dockerOptions.add(getDockerOptions(script))
if (buildTool == BuildTool.MAVEN || buildTool == BuildTool.MTA) {
String globalSettingsFile = getGlobalMavenSettingsForDownloadCache(script)
if (parameters.globalSettingsFile && parameters.globalSettingsFile != globalSettingsFile) {
throw new IllegalArgumentException("You can not specify the parameter globalSettingsFile if the download cache is active")
}
if (!(parameters.dockerOptions instanceof List)) {
throw new IllegalArgumentException("Unexpected type for dockerOptions. Expected was either a list or a string. Actual type was: '${parameters.dockerOptions.getClass()}'")
}
parameters.dockerOptions.add(DownloadCacheUtils.getDockerOptions(script))
parameters.globalSettingsFile = globalSettingsFile
}
if (buildTool == BuildTool.MAVEN || buildTool == BuildTool.MTA) {
if (parameters.globalSettingsFile) {
throw new IllegalArgumentException("You can not specify the parameter globalSettingsFile if the download cache is active")
}
parameters.globalSettingsFile = DownloadCacheUtils.getGlobalMavenSettingsForDownloadCache(script)
}
if (buildTool == BuildTool.NPM || buildTool == buildTool.MTA) {
parameters['defaultNpmRegistry'] = DownloadCacheUtils.getNpmRegistryUri(script)
}
if (buildTool == BuildTool.NPM || buildTool == BuildTool.MTA) {
parameters['defaultNpmRegistry'] = getNpmRegistryUri(script)
}
return parameters
@ -47,6 +49,15 @@ class DownloadCacheUtils {
return false
}
// Do not enable the DL-cache when a sidecar image is specified.
// This is necessary because it is currently not possible to connect a container to multiple networks.
// Can be removed when docker plugin supports multiple networks and jenkins-library implemented that feature
// See also https://github.com/SAP/jenkins-library/issues/1864
if (script.env.SIDECAR_IMAGE) {
script.echo "Download cache disabled while running with sidecar image (${script.env.SIDECAR_IMAGE})"
return false
}
return (networkName() && hostname())
}

View File

@ -134,6 +134,7 @@ public class CommonStepsTest extends BasePiperTest{
'malwareExecuteScan', //implementing new golang pattern without fields
'mavenBuild', //implementing new golang pattern without fields
'mavenExecute', //implementing new golang pattern without fields
'mavenExecuteIntegration', //implementing new golang pattern without fields
'mavenExecuteStaticCodeChecks', //implementing new golang pattern without fields
'mtaBuild', //implementing new golang pattern without fields
'nexusUpload', //implementing new golang pattern without fields

View File

@ -0,0 +1,72 @@
import groovy.json.JsonSlurper
import org.junit.Before
import org.junit.Rule
import org.junit.Test
import org.junit.rules.ExpectedException
import org.junit.rules.RuleChain
import util.*
import static org.hamcrest.Matchers.*
import static org.junit.Assert.assertThat
class MavenExecuteIntegrationTest extends BasePiperTest {
private ExpectedException exception = ExpectedException.none()
private JenkinsCredentialsRule credentialsRule = new JenkinsCredentialsRule(this)
private JenkinsShellCallRule shellCallRule = new JenkinsShellCallRule(this)
private JenkinsStepRule stepRule = new JenkinsStepRule(this)
private JenkinsWriteFileRule writeFileRule = new JenkinsWriteFileRule(this)
private List withEnvArgs = []
@Rule
public RuleChain rules = Rules
.getCommonRules(this)
.around(exception)
.around(new JenkinsReadYamlRule(this))
.around(credentialsRule)
.around(new JenkinsReadJsonRule(this))
.around(shellCallRule)
.around(stepRule)
.around(writeFileRule)
.around(new JenkinsFileExistsRule(this, []))
@Before
void init() {
helper.registerAllowedMethod("readJSON", [Map], { m ->
if (m.text instanceof String)
return new JsonSlurper().parseText(m.text as String)
})
helper.registerAllowedMethod("withEnv", [List, Closure], { arguments, closure ->
arguments.each {arg ->
withEnvArgs.add(arg.toString())
}
return closure()
})
shellCallRule.setReturnValue(
'./piper getConfig --contextConfig --stepMetadata \'.pipeline/tmp/metadata/mavenExecuteIntegration.yaml\'',
'{"verbose": false}'
)
helper.registerAllowedMethod('fileExists', [String], {return true})
helper.registerAllowedMethod('findFiles', [Map], {return null})
helper.registerAllowedMethod('testsPublishResults', [Map], {return null})
}
@Test
void testWithSidecar() {
stepRule.step.mavenExecuteIntegration(
juStabUtils: utils,
jenkinsUtilsStub: jenkinsUtils,
testParam: 'This is test content',
sidecarImage: 'some/image',
script: nullScript,
)
// asserts
assertThat(writeFileRule.files['.pipeline/tmp/metadata/mavenExecuteIntegration.yaml'] as String,
containsString('name: mavenExecuteIntegration'))
assertThat(withEnvArgs[0], allOf(startsWith('PIPER_parametersJSON'),
containsString('"testParam":"This is test content"')))
assertThat(shellCallRule.shell[1] as String, is('./piper mavenExecuteIntegration'))
}
}

View File

@ -316,6 +316,14 @@ boolean isContainerDefined(config) {
return false
}
if (env.SIDECAR_IMAGE != config.sidecarImage) {
// If a sidecar image has been configured for the current stage,
// then piperStageWrapper will have set the env.SIDECAR_IMAGE variable.
// If the current step overrides the stage's sidecar image,
// then a new Pod needs to be spawned.
return false
}
return containerMap.get(env.POD_NAME).containsKey(config.dockerImage)
}

View File

@ -0,0 +1,31 @@
import com.sap.piper.BuildTool
import com.sap.piper.DownloadCacheUtils
import groovy.transform.Field
import static com.sap.piper.Prerequisites.checkScript
@Field String STEP_NAME = getClass().getName()
@Field String METADATA_FILE = 'metadata/mavenExecuteIntegration.yaml'
@Field Set GENERAL_CONFIG_KEYS = []
@Field Set STEP_CONFIG_KEYS = GENERAL_CONFIG_KEYS
@Field Set PARAMETER_KEYS = STEP_CONFIG_KEYS.plus([
/**
* Specify a glob pattern where test result files will be located.
*/
'reportLocationPattern',
])
//Metadata maintained in file project://resources/metadata/mavenExecuteIntegration.yaml
void call(Map parameters = [:]) {
final script = checkScript(this, parameters) ?: this
parameters = DownloadCacheUtils.injectDownloadCacheInParameters(script, parameters, BuildTool.MAVEN)
try {
List credentials = []
piperExecuteBin(parameters, STEP_NAME, METADATA_FILE, credentials)
} finally {
testsPublishResults(script: script, junit: [allowEmptyResults: true, pattern: parameters.reportLocationPattern])
}
}

View File

@ -48,7 +48,7 @@ void call(Map parameters = [:], String stepName, String metadataFile, List crede
}
// prepare stashes
// first eliminate empty stahes
// first eliminate empty stashes
config.stashContent = utils.unstashAll(config.stashContent)
// then make sure that commonPipelineEnvironment, config, ... is also available when step stashing is active
if (config.stashContent?.size() > 0) {

View File

@ -31,20 +31,38 @@ void call(Map parameters = [:], body) {
stageLocking(config) {
def containerMap = ContainerMap.instance.getMap().get(stageName) ?: [:]
List environment = []
if (config.sidecarImage) {
echo "sidecarImage configured for stage '${stageName}': '${config.sidecarImage}'"
environment.add("SIDECAR_IMAGE=${config.sidecarImage}")
}
if (Boolean.valueOf(env.ON_K8S) && (containerMap.size() > 0 || config.runStageInPod)) {
withEnv(["POD_NAME=${stageName}"]) {
environment.add("POD_NAME=${stageName}")
withEnv(environment) {
dockerExecuteOnKubernetes(script: script, containerMap: containerMap, stageName: stageName) {
executeStage(script, body, stageName, config, utils, parameters.telemetryDisabled)
}
}
} else {
node(config.nodeLabel) {
executeStage(script, body, stageName, config, utils, parameters.telemetryDisabled)
withEnvWrapper(environment) {
node(config.nodeLabel) {
executeStage(script, body, stageName, config, utils, parameters.telemetryDisabled)
}
}
}
}
}
private void withEnvWrapper(List environment, Closure body) {
if (environment) {
withEnv(environment) {
body()
}
} else {
body()
}
}
private void stageLocking(Map config, Closure body) {
if (config.stageLocking) {
String resource = config.lockingResourceGroup?:env.JOB_NAME