1
0
mirror of https://github.com/SAP/jenkins-library.git synced 2024-12-12 10:55:20 +02:00

Merge pull request #155 from SAP/stashFiles

add steps for file stashing
This commit is contained in:
Thorsten Duda 2018-05-30 14:19:14 +02:00 committed by GitHub
commit 6e6e26f809
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
18 changed files with 828 additions and 39 deletions

20
pom.xml
View File

@ -109,6 +109,26 @@
<version>1.19</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>4.3.12.RELEASE</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context-support</artifactId>
<version>4.3.10.RELEASE</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>4.3.5.RELEASE</version>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<sourceDirectory>src</sourceDirectory>

View File

@ -14,18 +14,6 @@ steps:
docker:
filePath: 'Dockerfile'
versioningTemplate: '${version}-${timestamp}${commitId?"_"+commitId:""}'
mavenExecute:
dockerImage: 'maven:3.5-jdk-7'
influxWriteData:
influxServer: 'jenkins'
mtaBuild:
buildTarget: 'NEO'
mtaJarLocation: 'mta.jar'
neoDeploy:
deployMode: 'mta'
warAction: 'deploy'
vmSize: 'lite'
neoCredentialsId: 'CI_CREDENTIALS_ID'
checksPublishResults:
aggregation:
active: true
@ -85,6 +73,48 @@ steps:
fail:
high: '0'
archive: false
influxWriteData:
influxServer: 'jenkins'
mavenExecute:
dockerImage: 'maven:3.5-jdk-7'
mtaBuild:
buildTarget: 'NEO'
mtaJarLocation: 'mta.jar'
neoDeploy:
deployMode: 'mta'
warAction: 'deploy'
vmSize: 'lite'
neoCredentialsId: 'CI_CREDENTIALS_ID'
pipelineStashFilesAfterBuild:
stashIncludes:
checkmarx: '**/*.js, **/*.scala, **/*.py, **/*.go, **/*.xml, **/*.html'
classFiles: '**/target/classes/**/*.class, **/target/test-classes/**/*.class'
sonar: '**/jacoco*.exec, **/sonar-project.properties'
stashExcludes:
checkmarx: '**/*.mockserver.js, node_modules/**/*.js'
classFiles: ''
sonar: ''
pipelineStashFilesBeforeBuild:
stashIncludes:
buildDescriptor: '**/pom.xml, **/.mvn/**, **/assembly.xml, **/.swagger-codegen-ignore, **/package.json, **/requirements.txt, **/setup.py, **/whitesource_config.py, **/mta*.y*ml, **/.npmrc, **/whitesource.*.json, **/whitesource-fs-agent.config, .xmake.cfg, Dockerfile, **/VERSION, **/version.txt, **/build.sbt, **/sbtDescriptor.json, **/project/*'
deployDescriptor: '**/manifest*.y*ml, **/*.mtaext.y*ml, **/*.mtaext, **/xs-app.json, helm/**, *.y*ml'
git: '**/gitmetadata/**'
opa5: '**/*.*'
'opensource configuration': '**/srcclr.yml, **/vulas-custom.properties, **/.nsprc, **/.retireignore, **/.retireignore.json, **/'
pipelineConfigAndTests: '.pipeline/*.*'
securityDescriptor: '**/xs-security.json'
'snyk configuration': '**/.snyk'
tests: '**/pom.xml, **/*.json, **/*.xml, **/src/**, **/node_modules/**, **/specs/**, **/env/**, **/*.js'
stashExcludes:
buildDescriptor: '**/node_modules/**/package.json'
deployDescriptor: ''
git: ''
opa5: ''
'opensource configuration': ''
pipelineConfigAndTests: ''
securityDescriptor: ''
'snyk configuration': ''
tests: ''
testsPublishResults:
junit:
pattern: '**/target/surefire-reports/*.xml'

View File

@ -15,3 +15,39 @@ def getMandatoryParameter(Map map, paramName, defaultValue = null) {
return paramValue
}
def stash(name, include = '**/*.*', exclude = '') {
echo "Stash content: ${name} (include: ${include}, exclude: ${exclude})"
steps.stash name: name, includes: include, excludes: exclude
}
def stashWithMessage(name, msg, include = '**/*.*', exclude = '') {
try {
stash(name, include, exclude)
} catch (e) {
echo msg + name + " (${e.getMessage()})"
}
}
def unstash(name, msg = "Unstash failed:") {
def unstashedContent = []
try {
echo "Unstash content: ${name}"
steps.unstash name
unstashedContent += name
} catch (e) {
echo "$msg $name (${e.getMessage()})"
}
return unstashedContent
}
def unstashAll(stashContent) {
def unstashedContent = []
if (stashContent) {
for (i = 0; i < stashContent.size(); i++) {
unstashedContent += unstash(stashContent[i])
}
}
return unstashedContent
}

View File

@ -63,7 +63,7 @@ class InfluxWriteDataTest extends BasePipelineTest {
assertEquals('testInflux', stepMap.selectedTarget)
assertEquals(null, stepMap.customPrefix)
assertEquals([:], stepMap.customData)
assertEquals([pipeline_data:[:]], stepMap.customDataMap)
assertEquals([pipeline_data: [:], step_data: [:]], stepMap.customDataMap)
assertTrue(fileMap.containsKey('jenkins_data.json'))
assertTrue(fileMap.containsKey('pipeline_data.json'))

View File

@ -9,10 +9,11 @@ import com.lesfurets.jenkins.unit.BasePipelineTest
import static org.junit.Assert.assertEquals
import static org.junit.Assert.assertTrue
import util.BasePiperTest
import util.JenkinsShellCallRule
import util.Rules
class MavenExecuteTest extends BasePipelineTest {
class MavenExecuteTest extends BasePiperTest {
Map dockerParameters
@ -23,7 +24,6 @@ class MavenExecuteTest extends BasePipelineTest {
.around(jscr)
def mavenExecuteScript
def cpe
@Before
void init() {
@ -37,13 +37,12 @@ class MavenExecuteTest extends BasePipelineTest {
})
mavenExecuteScript = loadScript("mavenExecute.groovy").mavenExecute
cpe = loadScript('commonPipelineEnvironment.groovy').commonPipelineEnvironment
}
@Test
void testExecuteBasicMavenCommand() throws Exception {
mavenExecuteScript.call(script: [commonPipelineEnvironment: cpe], goals: 'clean install')
mavenExecuteScript.call(script: nullScript, goals: 'clean install')
assertEquals('maven:3.5-jdk-7', dockerParameters.dockerImage)
assert jscr.shell[0] == 'mvn clean install'
@ -53,7 +52,7 @@ class MavenExecuteTest extends BasePipelineTest {
void testExecuteMavenCommandWithParameter() throws Exception {
mavenExecuteScript.call(
script: [commonPipelineEnvironment: cpe],
script: nullScript,
dockerImage: 'maven:3.5-jdk-8-alpine',
goals: 'clean install',
globalSettingsFile: 'globalSettingsFile.xml',
@ -70,7 +69,7 @@ class MavenExecuteTest extends BasePipelineTest {
@Test
void testMavenCommandForwardsDockerOptions() throws Exception {
mavenExecuteScript.call(script: [commonPipelineEnvironment: cpe], goals: 'clean install')
mavenExecuteScript.call(script: nullScript, goals: 'clean install')
assertEquals('maven:3.5-jdk-7', dockerParameters.dockerImage)
assert jscr.shell[0] == 'mvn clean install'

View File

@ -0,0 +1,72 @@
import org.junit.Rule
import org.junit.Test
import org.junit.rules.RuleChain
import util.*
import static org.hamcrest.Matchers.containsString
import static org.junit.Assert.assertFalse
import static org.junit.Assert.assertThat
class PipelineStashFilesAfterBuildTest extends BasePiperTest {
JenkinsStepRule jsr = new JenkinsStepRule(this)
JenkinsLoggingRule jlr = new JenkinsLoggingRule(this)
JenkinsReadJsonRule jrj = new JenkinsReadJsonRule(this)
@Rule
public RuleChain rules = Rules
.getCommonRules(this)
.around(jrj)
.around(jlr)
.around(jsr)
@Test
void testStashAfterBuild() {
helper.registerAllowedMethod("fileExists", [String.class], {
searchTerm ->
return false
})
jsr.step.call(
script: nullScript,
juStabUtils: utils
)
// asserts
assertFalse(jlr.log.contains('Stash content: checkmarx'))
assertThat(jlr.log, containsString('Stash content: classFiles (include: **/target/classes/**/*.class, **/target/test-classes/**/*.class, exclude: )'))
assertThat(jlr.log, containsString('Stash content: sonar (include: **/jacoco*.exec, **/sonar-project.properties, exclude: )'))
assertFalse(jlr.log.contains('Stash content: postStagedFiles'))
}
@Test
void testStashAfterBuildWithCheckmarx() {
helper.registerAllowedMethod("fileExists", [String.class], {
searchTerm ->
return true
})
jsr.step.call(
script: nullScript,
juStabUtils: utils,
runCheckmarx: true
)
// asserts
assertThat(jlr.log, containsString('Stash content: checkmarx (include: **/*.js, **/*.scala, **/*.py, **/*.go, **/*.xml, **/*.html, exclude: **/*.mockserver.js, node_modules/**/*.js)'))
assertThat(jlr.log, containsString('Stash content: classFiles (include: **/target/classes/**/*.class, **/target/test-classes/**/*.class, exclude: )'))
assertThat(jlr.log, containsString('Stash content: sonar (include: **/jacoco*.exec, **/sonar-project.properties, exclude: )'))
}
@Test
void testStashAfterBuildWithCheckmarxConfig() {
helper.registerAllowedMethod("fileExists", [String.class], {
searchTerm ->
return true
})
jsr.step.call(
script: [commonPipelineEnvironment: [configuration: [steps: [executeCheckmarxScan: [checkmarxProject: 'TestProject']]]]],
juStabUtils: utils,
)
// asserts
assertThat(jlr.log, containsString('Stash content: checkmarx (include: **/*.js, **/*.scala, **/*.py, **/*.go, **/*.xml, **/*.html, exclude: **/*.mockserver.js, node_modules/**/*.js)'))
assertThat(jlr.log, containsString('Stash content: classFiles (include: **/target/classes/**/*.class, **/target/test-classes/**/*.class, exclude: )'))
assertThat(jlr.log, containsString('Stash content: sonar (include: **/jacoco*.exec, **/sonar-project.properties, exclude: )'))
}
}

View File

@ -0,0 +1,76 @@
import org.junit.Rule
import org.junit.Test
import org.junit.rules.RuleChain
import util.*
import static org.hamcrest.Matchers.containsString
import static org.junit.Assert.*
class PipelineStashFilesBeforeBuildTest extends BasePiperTest {
JenkinsStepRule jsr = new JenkinsStepRule(this)
JenkinsLoggingRule jlr = new JenkinsLoggingRule(this)
JenkinsShellCallRule jscr = new JenkinsShellCallRule(this)
//JenkinsReadJsonRule jrj = new JenkinsReadJsonRule(this)
@Rule
public RuleChain rules = Rules
.getCommonRules(this)
//.around(jrj)
.around(jlr)
.around(jscr)
.around(jsr)
@Test
void testStashBeforeBuildNoOpa() {
jsr.step.call(script: nullScript, juStabUtils: utils)
// asserts
assertEquals('mkdir -p gitmetadata', jscr.shell[0])
assertEquals('cp -rf .git/* gitmetadata', jscr.shell[1])
assertEquals('chmod -R u+w gitmetadata', jscr.shell[2])
assertFalse(jlr.log.contains('Stash content: opa5'))
assertThat(jlr.log, containsString('Stash content: git (include: **/gitmetadata/**, exclude: )'))
assertThat(jlr.log, containsString('Stash content: tests (include: **/pom.xml, **/*.json, **/*.xml, **/src/**, **/node_modules/**, **/specs/**, **/env/**, **/*.js, exclude: )'))
assertThat(jlr.log, containsString('Stash content: buildDescriptor (include: **/pom.xml, **/.mvn/**, **/assembly.xml, **/.swagger-codegen-ignore, **/package.json, **/requirements.txt, **/setup.py, **/whitesource_config.py, **/mta*.y*ml, **/.npmrc, **/whitesource.*.json, **/whitesource-fs-agent.config, .xmake.cfg, Dockerfile, **/VERSION, **/version.txt, **/build.sbt, **/sbtDescriptor.json, **/project/*, exclude: **/node_modules/**/package.json)'))
assertThat(jlr.log, containsString('Stash content: deployDescriptor (include: **/manifest*.y*ml, **/*.mtaext.y*ml, **/*.mtaext, **/xs-app.json, helm/**, *.y*ml, exclude: )'))
assertThat(jlr.log, containsString('Stash content: opensource configuration (include: **/srcclr.yml'))
assertThat(jlr.log, containsString('Stash content: snyk configuration (include: **/.snyk'))
assertThat(jlr.log, containsString('Stash content: pipelineConfigAndTests (include: .pipeline/*.*'))
assertThat(jlr.log, containsString('Stash content: securityDescriptor (include: **/xs-security.json'))
}
@Test
void testStashBeforeBuildOpa() {
jsr.step.call(script: nullScript, juStabUtils: utils, runOpaTests: true)
// asserts
assertThat(jlr.log, containsString('Stash content: opa5'))
assertThat(jlr.log, containsString('Stash content: git'))
assertThat(jlr.log, containsString('Stash content: tests'))
assertThat(jlr.log, containsString('Stash content: buildDescriptor'))
assertThat(jlr.log, containsString('Stash content: deployDescriptor'))
assertThat(jlr.log, containsString('Stash content: opensource configuration'))
assertThat(jlr.log, containsString('Stash content: snyk configuration'))
assertThat(jlr.log, containsString('Stash content: pipelineConfigAndTests'))
assertThat(jlr.log, containsString('Stash content: securityDescriptor'))
}
@Test
void testStashBeforeBuildOpaCompatibility() {
jsr.step.call(script: nullScript, juStabUtils: utils, runOpaTests: 'true')
// asserts
assertThat(jlr.log, containsString('Stash content: opa5'))
assertThat(jlr.log, containsString('Stash content: git'))
assertThat(jlr.log, containsString('Stash content: tests'))
assertThat(jlr.log, containsString('Stash content: buildDescriptor'))
assertThat(jlr.log, containsString('Stash content: deployDescriptor'))
assertThat(jlr.log, containsString('Stash content: opensource configuration'))
assertThat(jlr.log, containsString('Stash content: snyk configuration'))
assertThat(jlr.log, containsString('Stash content: pipelineConfigAndTests'))
assertThat(jlr.log, containsString('Stash content: securityDescriptor'))
}
}

View File

@ -6,13 +6,14 @@ import org.junit.Rule
import org.junit.Test
import org.junit.rules.ExpectedException
import org.junit.rules.RuleChain
import util.BasePiperTest
import util.JenkinsReadMavenPomRule
import util.JenkinsShellCallRule
import util.Rules
import static org.junit.Assert.assertEquals
class MavenArtifactVersioningTest extends BasePipelineTest{
class MavenArtifactVersioningTest extends BasePiperTest{
Map dockerParameters
def mavenExecuteScript
@ -21,10 +22,12 @@ class MavenArtifactVersioningTest extends BasePipelineTest{
MavenArtifactVersioning av
JenkinsShellCallRule jscr = new JenkinsShellCallRule(this)
ExpectedException thrown = ExpectedException.none()
@Rule
public RuleChain ruleChain = Rules.getCommonRules(this).around(jscr).around(thrown).around(new JenkinsReadMavenPomRule(this, 'test/resources/MavenArtifactVersioning'))
public RuleChain ruleChain = Rules
.getCommonRules(this)
.around(jscr)
.around(new JenkinsReadMavenPomRule(this, 'test/resources/MavenArtifactVersioning'))
@Before
void init() {
@ -35,16 +38,11 @@ class MavenArtifactVersioningTest extends BasePipelineTest{
dockerParameters = parameters
closure()
})
mavenExecuteScript = loadScript("mavenExecute.groovy").mavenExecute
commonPipelineEnvironment = loadScript('commonPipelineEnvironment.groovy').commonPipelineEnvironment
prepareObjectInterceptors(this)
}
@Test
void testVersioning() {
av = new MavenArtifactVersioning(this, [filePath: 'pom.xml'])
av = new MavenArtifactVersioning(nullScript, [filePath: 'pom.xml'])
assertEquals('1.2.3', av.getVersion())
av.setVersion('1.2.3-20180101')
assertEquals('mvn --file \'pom.xml\' versions:set -DnewVersion=1.2.3-20180101', jscr.shell[0])
@ -52,15 +50,9 @@ class MavenArtifactVersioningTest extends BasePipelineTest{
@Test
void testVersioningCustomFilePathSnapshot() {
av = new MavenArtifactVersioning(this, [filePath: 'snapshot/pom.xml'])
av = new MavenArtifactVersioning(nullScript, [filePath: 'snapshot/pom.xml'])
assertEquals('1.2.3', av.getVersion())
av.setVersion('1.2.3-20180101')
assertEquals('mvn --file \'snapshot/pom.xml\' versions:set -DnewVersion=1.2.3-20180101', jscr.shell[0])
}
void prepareObjectInterceptors(object) {
object.metaClass.invokeMethod = helper.getMethodInterceptor()
object.metaClass.static.invokeMethod = helper.getMethodInterceptor()
object.metaClass.methodMissing = helper.getMethodMissingInterceptor()
}
}

View File

@ -0,0 +1,52 @@
#!groovy
package util
import com.lesfurets.jenkins.unit.BasePipelineTest
import com.sap.piper.Utils
import org.junit.Before
import org.junit.runner.RunWith
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.test.context.ContextConfiguration
import org.springframework.test.context.TestExecutionListeners
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner
@RunWith(SpringJUnit4ClassRunner)
@ContextConfiguration(classes = [BasePiperTestContext.class])
@TestExecutionListeners(listeners = [LibraryLoadingTestExecutionListener.class], mergeMode = TestExecutionListeners.MergeMode.MERGE_WITH_DEFAULTS)
abstract class BasePiperTest extends BasePipelineTest {
@Autowired
MockHelper mockHelper
@Autowired
Script nullScript
@Autowired
Utils utils
@Override
@Before
void setUp() throws Exception {
helper = LibraryLoadingTestExecutionListener.singletonInstance
if(!isHelperInitialized()) {
super.setScriptRoots('.', 'vars')
super.setUp()
}
}
boolean isHelperInitialized() {
try {
helper.loadScript('dummy.groovy')
} catch (Exception e) {
if (e.getMessage().startsWith('GroovyScriptEngine is not initialized:'))
return false
}
return true
}
@Deprecated
void prepareObjectInterceptors(Object object) {
LibraryLoadingTestExecutionListener.prepareObjectInterceptors(object)
}
}

View File

@ -0,0 +1,37 @@
#!groovy
package util
import com.sap.piper.Utils
import org.codehaus.groovy.runtime.InvokerHelper
import org.springframework.context.annotation.Bean
import org.springframework.context.annotation.Configuration
@Configuration
class BasePiperTestContext {
@Bean
Script nullScript() {
def nullScript = InvokerHelper.createScript(null, new Binding())
nullScript.currentBuild = [:]
LibraryLoadingTestExecutionListener.prepareObjectInterceptors(nullScript)
return nullScript
}
@Bean
Utils mockUtils() {
def mockUtils = new Utils()
mockUtils.steps = [
stash : { m -> println "stash name = ${m.name}" },
unstash: { println "unstash called ..." }
]
LibraryLoadingTestExecutionListener.prepareObjectInterceptors(mockUtils)
return mockUtils
}
@Bean
MockHelper mockHelper() {
return new MockHelper()
}
}

View File

@ -21,6 +21,11 @@ class JenkinsEnvironmentRule implements TestRule {
@Override
void evaluate() throws Throwable {
env = testInstance.loadScript('commonPipelineEnvironment.groovy').commonPipelineEnvironment
try {
testInstance?.nullScript.commonPipelineEnvironment = env
} catch (MissingPropertyException e) {
//kept for backward compatibility before all tests inherit from BasePiperTest
}
base.evaluate()
}
}

View File

@ -0,0 +1,45 @@
package util
import com.lesfurets.jenkins.unit.BasePipelineTest
import groovy.json.JsonSlurper
import org.junit.rules.TestRule
import org.junit.runner.Description
import org.junit.runners.model.Statement
class JenkinsReadJsonRule implements TestRule {
final BasePipelineTest testInstance
final String testRoot
JenkinsReadJsonRule(BasePipelineTest testInstance, testRoot = '') {
this.testInstance = testInstance
this.testRoot = testRoot
}
@Override
Statement apply(Statement base, Description description) {
return statement(base)
}
private Statement statement(final Statement base) {
return new Statement() {
@Override
void evaluate() throws Throwable {
testInstance.helper.registerAllowedMethod("readJSON", [Map], { Map m ->
if(m.text) {
def js = new JsonSlurper()
return js.parseText(m.text)
} else if(m.file) {
def js = new JsonSlurper()
def reader = new BufferedReader(new FileReader( "${this.testRoot}${m.file}" ))
return js.parse(reader)
} else {
throw new IllegalArgumentException("Key 'text' is missing in map ${m}.")
}
})
base.evaluate()
}
}
}
}

View File

@ -0,0 +1,253 @@
package util
import com.lesfurets.jenkins.unit.InterceptingGCL
import com.lesfurets.jenkins.unit.MethodSignature
import com.lesfurets.jenkins.unit.PipelineTestHelper
import org.codehaus.groovy.control.CompilerConfiguration
import org.springframework.test.context.TestContext
import org.springframework.test.context.support.AbstractTestExecutionListener
import org.springframework.test.context.support.DependencyInjectionTestExecutionListener
import static com.lesfurets.jenkins.unit.MethodSignature.method
class LibraryLoadingTestExecutionListener extends AbstractTestExecutionListener {
static PipelineTestHelper singletonInstance
static CompilerConfiguration configuration
static GroovyClassLoader cLoader
static {
configuration = new CompilerConfiguration()
cLoader = new InterceptingGCL(singletonInstance, LibraryLoadingTestExecutionListener.class.getClassLoader(), configuration)
}
static List TRACKED_ON_CLASS = []
static List TRACKED_ON_METHODS = []
static HashMap RESTORE_ON_CLASS = [:]
static HashMap RESTORE_ON_METHODS = [:]
static boolean START_METHOD_TRACKING = false
static boolean START_CLASS_TRACKING = false
@Override
int getOrder() {
return 2500
}
static void setSingletonInstance(PipelineTestHelper helper) {
if(null != helper) {
helper.metaClass.invokeMethod = {
String name, Object[] args ->
if ((LibraryLoadingTestExecutionListener.START_METHOD_TRACKING || LibraryLoadingTestExecutionListener.START_CLASS_TRACKING)
&& name.equals("registerAllowedMethod")) {
List list
HashMap restore
if (LibraryLoadingTestExecutionListener.START_METHOD_TRACKING) {
list = LibraryLoadingTestExecutionListener.TRACKED_ON_METHODS
restore = LibraryLoadingTestExecutionListener.RESTORE_ON_METHODS
} else if (LibraryLoadingTestExecutionListener.START_CLASS_TRACKING) {
list = LibraryLoadingTestExecutionListener.TRACKED_ON_CLASS
restore = LibraryLoadingTestExecutionListener.RESTORE_ON_CLASS
}
Object methodName = args[0]
def key
if (args[1] instanceof List) {
List<Class> parameters = args[1]
key = method(methodName, parameters.toArray(new Class[parameters.size()]))
} else if (!(args[0] instanceof MethodSignature)) {
key = method(methodName, args[1])
}
if (null != key) {
list.add(key)
def existingValue = helper.removeAllowedMethodCallback(key)
if (!restore.containsKey(key)) {
restore.put(key, existingValue)
}
}
}
def m = delegate.metaClass.getMetaMethod(name, *args)
if( null != m)
return m.invoke(delegate, *args)
}
}
singletonInstance = helper
}
static PipelineTestHelper getSingletonInstance() {
if (singletonInstance == null) {
setSingletonInstance(new LibraryLoadingTestExecutionListener.PipelineTestHelperHook().helper)
}
return singletonInstance
}
@Override
void beforeTestClass(TestContext testContext) throws Exception {
super.beforeTestClass(testContext)
def helper = LibraryLoadingTestExecutionListener.getSingletonInstance()
registerDefaultAllowedMethods(helper)
LibraryLoadingTestExecutionListener.START_CLASS_TRACKING = true
}
@Override
void afterTestClass(TestContext testContext) throws Exception {
super.afterTestClass(testContext)
PipelineTestHelper helper = LibraryLoadingTestExecutionListener.getSingletonInstance()
helper.clearAllowedMethodCallbacks(LibraryLoadingTestExecutionListener.TRACKED_ON_CLASS)
LibraryLoadingTestExecutionListener.TRACKED_ON_CLASS.clear()
helper.putAllAllowedMethodCallbacks(LibraryLoadingTestExecutionListener.RESTORE_ON_CLASS)
LibraryLoadingTestExecutionListener.RESTORE_ON_CLASS.clear()
LibraryLoadingTestExecutionListener.START_CLASS_TRACKING = false
if (Boolean.TRUE.equals(testContext.getAttribute(DependencyInjectionTestExecutionListener.REINJECT_DEPENDENCIES_ATTRIBUTE))) {
LibraryLoadingTestExecutionListener.singletonInstance = null
PipelineTestHelper newHeiper = LibraryLoadingTestExecutionListener.getSingletonInstance()
def applicationContext = testContext.getApplicationContext()
def beanNames = applicationContext.getBeanDefinitionNames()
beanNames.each { name ->
LibraryLoadingTestExecutionListener.prepareObjectInterceptors(applicationContext.getBean(name))
}
}
}
@Override
void beforeTestMethod(TestContext testContext) throws Exception {
super.beforeTestMethod(testContext)
def testInstance = testContext.getTestInstance()
testInstance.binding.setVariable('currentBuild', [result: 'SUCCESS'])
PipelineTestHelper helper = LibraryLoadingTestExecutionListener.getSingletonInstance()
LibraryLoadingTestExecutionListener.START_METHOD_TRACKING = true
}
@Override
void afterTestMethod(TestContext testContext) throws Exception {
super.afterTestMethod(testContext)
def testInstance = testContext.getTestInstance()
PipelineTestHelper helper = LibraryLoadingTestExecutionListener.getSingletonInstance()
helper.clearCallStack()
helper.clearAllowedMethodCallbacks(LibraryLoadingTestExecutionListener.TRACKED_ON_METHODS)
LibraryLoadingTestExecutionListener.TRACKED_ON_METHODS.clear()
LibraryLoadingTestExecutionListener.START_METHOD_TRACKING = false
testInstance.getNullScript().commonPipelineEnvironment.reset()
}
def registerDefaultAllowedMethods(helper) {
helper.registerAllowedMethod("stage", [String.class, Closure.class], null)
helper.registerAllowedMethod("stage", [String.class, Closure.class], null)
helper.registerAllowedMethod("node", [String.class, Closure.class], null)
helper.registerAllowedMethod("node", [Closure.class], null)
helper.registerAllowedMethod( method('sh', Map.class), {m ->
println "sh-command: $m.script"
return ""
} )
helper.registerAllowedMethod( method('sh', String.class), {s ->
println "sh-command: $s"
return ""
} )
helper.registerAllowedMethod("checkout", [Map.class], null)
helper.registerAllowedMethod("echo", [String.class], null)
helper.registerAllowedMethod("timeout", [Map.class, Closure.class], null)
helper.registerAllowedMethod("step", [Map.class], null)
helper.registerAllowedMethod("input", [String.class], null)
helper.registerAllowedMethod("gitlabCommitStatus", [String.class, Closure.class], { String name, Closure c ->
c.delegate = delegate
helper.callClosure(c)
})
helper.registerAllowedMethod("gitlabBuilds", [Map.class, Closure.class], null)
helper.registerAllowedMethod("logRotator", [Map.class], null)
helper.registerAllowedMethod("buildDiscarder", [Object.class], null)
helper.registerAllowedMethod("pipelineTriggers", [List.class], null)
helper.registerAllowedMethod("properties", [List.class], null)
helper.registerAllowedMethod("dir", [String.class, Closure.class], null)
helper.registerAllowedMethod("archiveArtifacts", [Map.class], null)
helper.registerAllowedMethod("junit", [String.class], null)
helper.registerAllowedMethod("readFile", [String.class], null)
helper.registerAllowedMethod("disableConcurrentBuilds", [], null)
helper.registerAllowedMethod("gatlingArchive", [], null)
helper.registerAllowedMethod("unstash", [String.class], null)
helper.registerAllowedMethod("unstash", [Object.class, String.class], null)
helper.registerAllowedMethod("stash", [Map.class], null)
helper.registerAllowedMethod("echo", [String.class], null)
}
static def prepareObjectInterceptors(Object object) {
object.metaClass.invokeMethod = LibraryLoadingTestExecutionListener.singletonInstance.getMethodInterceptor()
object.metaClass.static.invokeMethod = LibraryLoadingTestExecutionListener.singletonInstance.getMethodInterceptor()
object.metaClass.methodMissing = LibraryLoadingTestExecutionListener.singletonInstance.getMethodMissingInterceptor()
}
static class PipelineTestHelperHook {
def helper = new PipelineTestHelper() {
def clearAllowedMethodCallbacks(Collection c = []) {
List itemsToRemove = []
c.each {
key ->
allowedMethodCallbacks.entrySet().each {
entry ->
if (entry?.getKey().equals(key))
itemsToRemove.add(entry.getKey())
}
}
allowedMethodCallbacks.keySet().removeAll(itemsToRemove)
}
def removeAllowedMethodCallback(Object key) {
def itemToRemove
allowedMethodCallbacks.entrySet().each {
entry ->
if (entry?.getKey().equals(key)) {
itemToRemove = entry.getKey()
}
}
if (null != itemToRemove) {
def itemValue = allowedMethodCallbacks.remove(itemToRemove)
return itemValue
}
return null
}
def putAllAllowedMethodCallbacks(HashMap m) {
m.entrySet().each {
entry ->
if(null != entry.getValue())
allowedMethodCallbacks.put(entry.getKey(), entry.getValue())
else
allowedMethodCallbacks.remove(entry.getKey())
}
}
protected void setGlobalVars(Binding binding) {
libLoader.libRecords.values().stream()
.flatMap { it.definedGlobalVars.entrySet().stream() }
.forEach { e ->
if (e.value instanceof Script) {
Script script = Script.cast(e.value)
// invoke setBinding from method to avoid interception
SCRIPT_SET_BINDING.invoke(script, binding)
LibraryLoadingTestExecutionListener.prepareObjectInterceptors(script)
script.metaClass.getMethods().findAll { it.name == 'call' }.forEach { m ->
LibraryLoadingTestExecutionListener.singletonInstance.registerAllowedMethod(method(e.value.class.name, m.getNativeParameterTypes()),
{ args ->
m.doMethodInvoke(e.value, args)
})
}
}
binding.setVariable(e.key, e.value)
}
}
}
}
}

View File

@ -13,8 +13,9 @@ public class Rules {
public static RuleChain getCommonRules(BasePipelineTest testCase, LibraryConfiguration libConfig) {
return RuleChain.outerRule(new JenkinsSetupRule(testCase, libConfig))
.around(new JenkinsReadYamlRule(testCase))
.around(new JenkinsResetDefaultCacheRule())
.around(new JenkinsErrorRule(testCase))
.around(new JenkinsReadYamlRule(testCase))
.around(new JenkinsResetDefaultCacheRule())
.around(new JenkinsErrorRule(testCase))
.around(new JenkinsEnvironmentRule(testCase))
}
}

View File

@ -15,12 +15,28 @@ class commonPipelineEnvironment implements Serializable {
Map defaultConfiguration = [:]
//each Map in influxCustomDataMap represents a measurement in Influx. Additional measurements can be added as a new Map entry of influxCustomDataMap
private Map influxCustomDataMap = [pipeline_data: [:]]
private Map influxCustomDataMap = [pipeline_data: [:], step_data: [:]]
//influxCustomData represents measurement jenkins_custom_data in Influx. Metrics can be written into this map
private Map influxCustomData = [:]
private String mtarFilePath
def reset() {
appContainerProperties = [:]
artifactVersion = null
configProperties = [:]
configuration = [:]
gitCommitId = null
gitSshUrl = null
influxCustomData = [:]
influxCustomDataMap = [pipeline_data: [:], step_data: [:]]
mtarFilePath = null
}
def setAppContainerProperty(property, value) {
appContainerProperties[property] = value
}

View File

@ -0,0 +1,7 @@
def call(Map parameters = [:], body) {
handlePipelineStepErrors (stepName: 'pipelineStashFiles', stepParameters: parameters) {
pipelineStashFilesBeforeBuild(parameters)
body() //execute build
pipelineStashFilesAfterBuild(parameters)
}
}

View File

@ -0,0 +1,51 @@
import com.sap.piper.Utils
import com.sap.piper.ConfigurationHelper
import groovy.transform.Field
@Field String STEP_NAME = 'pipelineStashFilesAfterBuild'
@Field Set STEP_CONFIG_KEYS = ['runCheckmarx', 'stashIncludes', 'stashExcludes']
@Field Set PARAMETER_KEYS = STEP_CONFIG_KEYS
def call(Map parameters = [:]) {
handlePipelineStepErrors (stepName: STEP_NAME, stepParameters: parameters, stepNameDoc: 'stashFiles') {
def utils = parameters.juStabUtils
if (utils == null) {
utils = new Utils()
}
def script = parameters.script
if (script == null)
script = [commonPipelineEnvironment: commonPipelineEnvironment]
//additional includes via passing e.g. stashIncludes: [opa5: '**/*.include']
//additional excludes via passing e.g. stashExcludes: [opa5: '**/*.exclude']
Map config = ConfigurationHelper
.loadStepDefaults(this)
.mixinGeneralConfig(script.commonPipelineEnvironment, STEP_CONFIG_KEYS)
.mixinStageConfig(script.commonPipelineEnvironment, parameters.stageName?:env.STAGE_NAME, STEP_CONFIG_KEYS)
.mixinStepConfig(script.commonPipelineEnvironment, STEP_CONFIG_KEYS)
.mixin(parameters, PARAMETER_KEYS)
.addIfEmpty('runCheckmarx', (script.commonPipelineEnvironment.configuration?.steps?.executeCheckmarxScan?.checkmarxProject != null && script.commonPipelineEnvironment.configuration.steps.executeCheckmarxScan.checkmarxProject.length()>0))
.use()
// store files to be checked with checkmarx
if (config.runCheckmarx) {
utils.stash('checkmarx', config.stashIncludes?.get('checkmarx')?config.stashIncludes.checkmarx:'**/*.js, **/*.scala, **/*.py, **/*.go, **/*.xml, **/*.html', config.stashExcludes?.get('checkmarx')?config.stashExcludes.checkmarx:'**/*.mockserver.js, node_modules/**/*.js')
}
utils.stashWithMessage(
'classFiles',
'[${STEP_NAME}] Failed to stash class files.',
config.stashIncludes.classFiles,
config.stashExcludes.classFiles
)
utils.stashWithMessage(
'sonar',
'[${STEP_NAME}] Failed to stash sonar files.',
config.stashIncludes.sonar,
config.stashExcludes.sonar
)
}
}

View File

@ -0,0 +1,97 @@
import com.sap.piper.Utils
import com.sap.piper.ConfigurationHelper
import groovy.transform.Field
@Field String STEP_NAME = 'pipelineStashFilesBeforeBuild'
@Field Set STEP_CONFIG_KEYS = ['runOpaTests', 'stashIncludes', 'stashExcludes']
@Field Set PARAMETER_KEYS = STEP_CONFIG_KEYS
def call(Map parameters = [:]) {
handlePipelineStepErrors (stepName: STEP_NAME, stepParameters: parameters, stepNameDoc: 'stashFiles') {
def utils = parameters.juStabUtils
if (utils == null) {
utils = new Utils()
}
def script = parameters.script
if (script == null)
script = [commonPipelineEnvironment: commonPipelineEnvironment]
//additional includes via passing e.g. stashIncludes: [opa5: '**/*.include']
//additional excludes via passing e.g. stashExcludes: [opa5: '**/*.exclude']
Map config = ConfigurationHelper
.loadStepDefaults(this)
.mixinGeneralConfig(script.commonPipelineEnvironment, STEP_CONFIG_KEYS)
.mixinStageConfig(script.commonPipelineEnvironment, parameters.stageName?:env.STAGE_NAME, STEP_CONFIG_KEYS)
.mixinStepConfig(script.commonPipelineEnvironment, STEP_CONFIG_KEYS)
.mixin(parameters, PARAMETER_KEYS)
.use()
if (config.runOpaTests){
utils.stash('opa5', config.stashIncludes?.get('opa5')?config.stashIncludes.opa5:'**/*.*', config.stashExcludes?.get('opa5')?config.stashExcludes.opa5:'')
}
//store git metadata for SourceClear agent
sh "mkdir -p gitmetadata"
sh "cp -rf .git/* gitmetadata"
sh "chmod -R u+w gitmetadata"
utils.stashWithMessage(
'git',
'[${STEP_NAME}] no git repo files detected: ',
config.stashIncludes.git,
config.stashExcludes.git
)
//store files required for tests, e.g. Gauge, SUT, ...
utils.stashWithMessage(
'tests',
'[${STEP_NAME}] no files for tests provided: ',
config.stashIncludes.tests,
config.stashExcludes.tests
)
//store build descriptor files depending on technology, e.g. pom.xml, package.json
utils.stash(
'buildDescriptor',
config.stashIncludes.buildDescriptor,
config.stashExcludes.buildDescriptor
)
//store deployment descriptor files depending on technology, e.g. *.mtaext.yml
utils.stashWithMessage(
'deployDescriptor',
'[${STEP_NAME}] no deployment descriptor files provided: ',
config.stashIncludes.deployDescriptor,
config.stashExcludes.deployDescriptor
)
//store nsp & retire exclusion file for future use
utils.stashWithMessage(
'opensource configuration',
'[${STEP_NAME}] no opensource configuration files provided: ',
config.stashIncludes.get('opensource configuration'),
config.stashExcludes.get('opensource configuration')
)
//store snyk config file for future use
utils.stashWithMessage(
'snyk configuration',
'[${STEP_NAME}] no snyk configuration files provided: ',
config.stashIncludes.get('snyk configuration'),
config.stashExcludes.get('snyk configuration')
)
//store pipeline configuration including additional groovy test scripts for future use
utils.stashWithMessage(
'pipelineConfigAndTests',
'[${STEP_NAME}] no pipeline configuration and test files found: ',
config.stashIncludes.pipelineConfigAndTests,
config.stashExcludes.pipelineConfigAndTests
)
utils.stashWithMessage(
'securityDescriptor',
'[${STEP_NAME}] no security descriptor found: ',
config.stashIncludes.securityDescriptor,
config.stashExcludes.securityDescriptor
)
}
}