From 8a55e25f7204b82ee1e8fa1e7381c37fc595cee1 Mon Sep 17 00:00:00 2001 From: Christopher Fenner Date: Fri, 10 May 2019 06:47:44 +0200 Subject: [PATCH] add Slack notification to Init and Post stage (#691) * add Slack notification to post stage * add Slack notification to init stage * add trigger condition for Slack notification * fix whitespaces * use capital stage name * add tests for init stage * remove unused import * add tests for post stage * minor changes * fix typo --- .../com.sap.piper/pipeline/stageDefaults.yml | 8 ++ test/groovy/PiperPipelineStageInitTest.groovy | 122 ++++++++++++++++++ test/groovy/PiperPipelineStagePostTest.groovy | 69 ++++++++++ vars/piperPipelineStageInit.groovy | 5 +- vars/piperPipelineStagePost.groovy | 6 + 5 files changed, 208 insertions(+), 2 deletions(-) create mode 100644 test/groovy/PiperPipelineStageInitTest.groovy create mode 100644 test/groovy/PiperPipelineStagePostTest.groovy diff --git a/resources/com.sap.piper/pipeline/stageDefaults.yml b/resources/com.sap.piper/pipeline/stageDefaults.yml index 18e79ce58..f61775fd4 100644 --- a/resources/com.sap.piper/pipeline/stageDefaults.yml +++ b/resources/com.sap.piper/pipeline/stageDefaults.yml @@ -1,4 +1,8 @@ stages: + Init: + stepConditions: + slackSendNotification: + config: 'channel' 'Pull-Request Voting': {} Build: {} 'Additional Unit Tests': {} @@ -18,3 +22,7 @@ stages: Compliance: {} Promote: {} Release: {} + 'Post Actions': + stepConditions: + slackSendNotification: + config: 'channel' diff --git a/test/groovy/PiperPipelineStageInitTest.groovy b/test/groovy/PiperPipelineStageInitTest.groovy new file mode 100644 index 000000000..b5e18b39f --- /dev/null +++ b/test/groovy/PiperPipelineStageInitTest.groovy @@ -0,0 +1,122 @@ +#!groovy +package stages + +import org.junit.Before +import org.junit.Rule +import org.junit.Test +import org.junit.rules.ExpectedException +import org.junit.rules.RuleChain +import util.BasePiperTest +import util.JenkinsLoggingRule +import util.JenkinsReadYamlRule +import util.JenkinsStepRule +import util.Rules + +import static org.hamcrest.Matchers.* +import static org.junit.Assert.assertThat + +class PiperPipelineStageInitTest extends BasePiperTest { + private JenkinsStepRule jsr = new JenkinsStepRule(this) + private JenkinsLoggingRule jlr = new JenkinsLoggingRule(this) + private ExpectedException thrown = ExpectedException.none() + + @Rule + public RuleChain rules = Rules + .getCommonRules(this) + .around(new JenkinsReadYamlRule(this)) + .around(thrown) + .around(jlr) + .around(jsr) + + private List stepsCalled = [] + + @Before + void init() { + binding.variables.env.STAGE_NAME = 'Init' + binding.setVariable('scm', {}) + + helper.registerAllowedMethod('deleteDir', [], null) + helper.registerAllowedMethod("findFiles", [Map.class], { map -> + switch (map.glob) { + case 'pom.xml': + return [new File('pom.xml')].toArray() + default: + return [].toArray() + } + }) + helper.registerAllowedMethod('piperStageWrapper', [Map.class, Closure.class], {m, body -> + assertThat(m.stageName, is('Init')) + return body() + }) + helper.registerAllowedMethod('checkout', [Closure.class], {c -> + stepsCalled.add('checkout') + return [ + GIT_COMMIT: 'abcdef12345', + GIT_URL: 'some.url' + ] + }) + helper.registerAllowedMethod('setupCommonPipelineEnvironment', [Map.class], {m -> stepsCalled.add('setupCommonPipelineEnvironment')}) + helper.registerAllowedMethod('piperInitRunStageConfiguration', [Map.class], {m -> stepsCalled.add('piperInitRunStageConfiguration')}) + helper.registerAllowedMethod('slackSendNotification', [Map.class], {m -> stepsCalled.add('slackSendNotification')}) + helper.registerAllowedMethod('artifactSetVersion', [Map.class], {m -> stepsCalled.add('artifactSetVersion')}) + helper.registerAllowedMethod('pipelineStashFilesBeforeBuild', [Map.class], {m -> stepsCalled.add('pipelineStashFilesBeforeBuild')}) + } + + @Test + void testInitNoBuildTool() { + thrown.expectMessage('ERROR - NO VALUE AVAILABLE FOR buildTool') + jsr.step.piperPipelineStageInit(script: nullScript, juStabUtils: utils) + } + + @Test + void testInitBuildToolDoesNotMatchProject() { + thrown.expect(hudson.AbortException) + thrown.expectMessage(containsString("buildTool configuration 'npm' does not fit to your project")) + jsr.step.piperPipelineStageInit(script: nullScript, juStabUtils: utils, buildTool: 'npm') + } + + @Test + void testInitDefault() { + jsr.step.piperPipelineStageInit(script: nullScript, juStabUtils: utils, buildTool: 'maven') + + assertThat(stepsCalled, hasItems( + 'checkout', + 'setupCommonPipelineEnvironment', + 'piperInitRunStageConfiguration', + 'artifactSetVersion', + 'pipelineStashFilesBeforeBuild' + )) + assertThat(stepsCalled, not(hasItems('slackSendNotification'))) + } + + @Test + void testInitNotOnProductiveBranch() { + binding.variables.env.BRANCH_NAME = 'anyOtherBranch' + + jsr.step.piperPipelineStageInit(script: nullScript, juStabUtils: utils, buildTool: 'maven') + + assertThat(stepsCalled, hasItems( + 'checkout', + 'setupCommonPipelineEnvironment', + 'piperInitRunStageConfiguration', + 'pipelineStashFilesBeforeBuild' + )) + assertThat(stepsCalled, not(hasItems('artifactSetVersion'))) + } + + @Test + void testInitWithSlackNotification() { + nullScript.commonPipelineEnvironment.configuration = [runStep: [Init: [slackSendNotification: true]]] + + jsr.step.piperPipelineStageInit(script: nullScript, juStabUtils: utils, buildTool: 'maven') + + assertThat(stepsCalled, hasItems( + 'checkout', + 'setupCommonPipelineEnvironment', + 'piperInitRunStageConfiguration', + 'artifactSetVersion', + 'slackSendNotification', + 'pipelineStashFilesBeforeBuild' + )) + } +} diff --git a/test/groovy/PiperPipelineStagePostTest.groovy b/test/groovy/PiperPipelineStagePostTest.groovy new file mode 100644 index 000000000..b0266c7da --- /dev/null +++ b/test/groovy/PiperPipelineStagePostTest.groovy @@ -0,0 +1,69 @@ +#!groovy +package stages + +import org.junit.Before +import org.junit.Rule +import org.junit.Test +import org.junit.rules.ExpectedException +import org.junit.rules.RuleChain +import util.BasePiperTest +import util.JenkinsReadYamlRule +import util.JenkinsStepRule +import util.Rules + +import static org.hamcrest.Matchers.* +import static org.junit.Assert.assertThat + +class PiperPipelineStagePostTest extends BasePiperTest { + private JenkinsStepRule jsr = new JenkinsStepRule(this) + private ExpectedException thrown = ExpectedException.none() + + @Rule + public RuleChain rules = Rules + .getCommonRules(this) + .around(new JenkinsReadYamlRule(this)) + .around(thrown) + .around(jsr) + + private List stepsCalled = [] + + @Before + void init() { + binding.variables.env.STAGE_NAME = 'Release' + + helper.registerAllowedMethod('piperStageWrapper', [Map.class, Closure.class], {m, body -> + assertThat(m.stageName, is('Release')) + return body() + }) + helper.registerAllowedMethod('influxWriteData', [Map.class], {m -> stepsCalled.add('influxWriteData')}) + helper.registerAllowedMethod('slackSendNotification', [Map.class], {m -> stepsCalled.add('slackSendNotification')}) + helper.registerAllowedMethod('mailSendNotification', [Map.class], {m -> stepsCalled.add('mailSendNotification')}) + } + + @Test + void testPostDefault() { + jsr.step.piperPipelineStagePost(script: nullScript, juStabUtils: utils) + + assertThat(stepsCalled, hasItems('influxWriteData','mailSendNotification')) + assertThat(stepsCalled, not(hasItems('slackSendNotification'))) + } + + @Test + void testPostNotOnProductiveBranch() { + binding.variables.env.BRANCH_NAME = 'anyOtherBranch' + + jsr.step.piperPipelineStagePost(script: nullScript, juStabUtils: utils) + + assertThat(stepsCalled, hasItems('influxWriteData','mailSendNotification')) + assertThat(stepsCalled, not(hasItems('slackSendNotification'))) + } + + @Test + void testPostWithSlackNotification() { + nullScript.commonPipelineEnvironment.configuration = [runStep: ['Post Actions': [slackSendNotification: true]]] + + jsr.step.piperPipelineStagePost(script: nullScript, juStabUtils: utils) + + assertThat(stepsCalled, hasItems('influxWriteData','mailSendNotification','slackSendNotification')) + } +} diff --git a/vars/piperPipelineStageInit.groovy b/vars/piperPipelineStageInit.groovy index 8016e4ff3..fc703f61a 100644 --- a/vars/piperPipelineStageInit.groovy +++ b/vars/piperPipelineStageInit.groovy @@ -55,11 +55,12 @@ void call(Map parameters = [:]) { piperInitRunStageConfiguration script: script, stageConfigResource: config.stageConfigResource if (env.BRANCH_NAME == config.productiveBranch) { + if (parameters.script.commonPipelineEnvironment.configuration.runStep?.get('Init')?.slackSendNotification) { + slackSendNotification script: script, message: "STARTED: Job <${env.BUILD_URL}|${URLDecoder.decode(env.JOB_NAME, java.nio.charset.StandardCharsets.UTF_8.name())} ${env.BUILD_DISPLAY_NAME}>", color: 'WARNING' + } artifactSetVersion script: script } - pipelineStashFilesBeforeBuild script: script - } } diff --git a/vars/piperPipelineStagePost.groovy b/vars/piperPipelineStagePost.groovy index 3bd1be082..03036921c 100644 --- a/vars/piperPipelineStagePost.groovy +++ b/vars/piperPipelineStagePost.groovy @@ -40,6 +40,12 @@ void call(Map parameters = [:]) { utils.pushToSWA([step: STEP_NAME], config) influxWriteData script: script + + if(env.BRANCH_NAME == parameters.script.commonPipelineEnvironment.getStepConfiguration('', '').productiveBranch) { + if(parameters.script.commonPipelineEnvironment.configuration.runStep?.get('Post Actions')?.slackSendNotification) { + slackSendNotification script: parameters.script + } + } mailSendNotification script: script } }