github.com/xgoffin/jenkins-library@v1.154.0/vars/piperPipelineStageInit.groovy (about) 1 import com.sap.piper.ConfigurationHelper 2 import com.sap.piper.GenerateStageDocumentation 3 import com.sap.piper.JenkinsUtils 4 import com.sap.piper.StageNameProvider 5 import com.sap.piper.Utils 6 import com.sap.piper.k8s.ContainerMap 7 import groovy.transform.Field 8 9 import static com.sap.piper.Prerequisites.checkScript 10 11 @Field String STEP_NAME = getClass().getName() 12 @Field String TECHNICAL_STAGE_NAME = 'init' 13 14 @Field Set GENERAL_CONFIG_KEYS = [ 15 /** 16 * Defines the build tool used. 17 * @possibleValues `docker`, `kaniko`, `maven`, `mta, ``npm` 18 */ 19 'buildTool', 20 /** 21 * Defines the library resource containing the container map. 22 */ 23 'containerMapResource', 24 /** 25 * Enable automatic inference of build tool (maven, npm, mta) based on existing project files. 26 * If this is set to true, it is not required to provide the `buildTool` parameter in the `general` section of the pipeline configuration. 27 */ 28 'inferBuildTool', 29 /** 30 * Enables automatic inference from the build descriptor in case projectName is not configured. 31 */ 32 'inferProjectName', 33 /** 34 * Defines the library resource containing the legacy configuration definition. 35 */ 36 'legacyConfigSettings', 37 /** 38 * Defines the main branch for your pipeline. **Typically this is the `master` branch, which does not need to be set explicitly.** Only change this in exceptional cases 39 */ 40 'productiveBranch', 41 /** 42 * Name of the project, e.g. used for the name of lockable resources. 43 */ 44 'projectName', 45 /** 46 * Specify to execute artifact versioning in a kubernetes pod. 47 * @possibleValues `true`, `false` 48 */ 49 'runArtifactVersioningOnPod', 50 /** 51 * Defines the library resource containing stage/step initialization settings. Those define conditions when certain steps/stages will be activated. **Caution: changing the default will break the standard behavior of the pipeline - thus only relevant when including `Init` stage into custom pipelines!** 52 */ 53 'stageConfigResource', 54 /** 55 * Defines the library resource containing the stash settings to be performed before and after each stage. **Caution: changing the default will break the standard behavior of the pipeline - thus only relevant when including `Init` stage into custom pipelines!** 56 */ 57 'stashSettings', 58 /** 59 * Works as the stashSettings parameter, but allows the use of a stash settings file that is not available as a library resource. 60 */ 61 'customStashSettings', 62 /** 63 * Whether verbose output should be produced. 64 * @possibleValues `true`, `false` 65 */ 66 'verbose' 67 ] 68 @Field STAGE_STEP_KEYS = [ 69 /** 70 * Sets the build version. 71 * @possibleValues `true`, `false` 72 */ 73 'artifactPrepareVersion' 74 ] 75 @Field Set STEP_CONFIG_KEYS = GENERAL_CONFIG_KEYS.plus(STAGE_STEP_KEYS) 76 @Field Set PARAMETER_KEYS = STEP_CONFIG_KEYS.plus([ 77 /** 78 * Enables the use of technical stage names. 79 */ 80 'useTechnicalStageNames', 81 /** 82 * Provides a clone from the specified repository. 83 * This map contains attributes, such as, `branches`, `extensions`, `userRemoteConfigs` etc. 84 * Example: `[$class: 'GitSCM', branches: [[name: <branch_to_be_cloned>]], userRemoteConfigs: [[credentialsId: <credential_to_access_repository>, url: <repository_url>]]]`. 85 */ 86 'checkoutMap', 87 /** 88 * The map returned from a Jenkins git checkout. Used to set the git information in the 89 * common pipeline environment. 90 */ 91 'scmInfo', 92 /** 93 * Optional skip of checkout if checkout was done before this step already. 94 * @possibleValues `true`, `false` 95 */ 96 'skipCheckout', 97 /** 98 * Mandatory if you skip the checkout. Then you need to unstash your workspace to get the e.g. configuration. 99 */ 100 'stashContent', 101 /** 102 * Optional path to the pipeline configuration file defining project specific settings. 103 */ 104 'configFile', 105 /** 106 * Optional list of file names which will be extracted from library resources and which serve as source for 107 * default values for the pipeline configuration. These are merged with and override built-in defaults, with 108 * a parameter supplied by the last resource file taking precedence over the same parameter supplied in an 109 * earlier resource file or built-in default. 110 */ 111 'customDefaults', 112 /** 113 * Optional list of file paths or URLs which must point to YAML content. These work exactly like 114 * `customDefaults`, but from local or remote files instead of library resources. They are merged with and 115 * take precedence over `customDefaults`. 116 */ 117 'customDefaultsFromFiles' 118 ]) 119 120 /** 121 * This stage initializes the pipeline run and prepares further execution. 122 * 123 * It will check out your repository and perform some steps to initialize your pipeline run. 124 */ 125 @GenerateStageDocumentation(defaultStageName = 'Init') 126 void call(Map parameters = [:]) { 127 128 def script = checkScript(this, parameters) ?: this 129 def utils = parameters.juStabUtils ?: new Utils() 130 131 if (parameters.useTechnicalStageNames) { 132 StageNameProvider.instance.useTechnicalStageNames = true 133 } 134 135 def stageName = StageNameProvider.instance.getStageName(script, parameters, this) 136 137 piperStageWrapper (script: script, stageName: stageName, stashContent: [], ordinal: 1, telemetryDisabled: true) { 138 def skipCheckout = parameters.skipCheckout 139 if (skipCheckout != null && !(skipCheckout instanceof Boolean)) { 140 error "[${STEP_NAME}] Parameter skipCheckout has to be of type boolean. Instead got '${skipCheckout.class.getName()}'" 141 } 142 def scmInfo = parameters.scmInfo 143 if (skipCheckout && !scmInfo) { 144 error "[${STEP_NAME}] Need am scmInfo map retrieved from a checkout. " + 145 "If you want to skip the checkout the scm info needs to be provided by you with parameter scmInfo, " + 146 "for example as follows:\n" + 147 " def scmInfo = checkout scm\n" + 148 " piperPipelineStageInit script:this, skipCheckout: true, scmInfo: scmInfo" 149 } 150 if (!skipCheckout) { 151 scmInfo = checkout(parameters.checkoutMap ?: scm) 152 } 153 else { 154 def stashContent = parameters.stashContent 155 if(stashContent == null || stashContent.size() == 0) { 156 error "[${STEP_NAME}] needs stashes if you skip checkout" 157 } 158 utils.unstashAll(stashContent) 159 } 160 161 setupCommonPipelineEnvironment(script: script, customDefaults: parameters.customDefaults, scmInfo: scmInfo, 162 configFile: parameters.configFile, customDefaultsFromFiles: parameters.customDefaultsFromFiles) 163 164 Map config = ConfigurationHelper.newInstance(this) 165 .loadStepDefaults() 166 .mixinGeneralConfig(script.commonPipelineEnvironment, GENERAL_CONFIG_KEYS) 167 .mixinStageConfig(script.commonPipelineEnvironment, stageName, STEP_CONFIG_KEYS) 168 .mixin(parameters, PARAMETER_KEYS) 169 .addIfEmpty('stageConfigResource', 'com.sap.piper/pipeline/stageDefaults.yml') 170 .addIfEmpty('stashSettings', 'com.sap.piper/pipeline/stashSettings.yml') 171 .addIfEmpty('buildTool', script.commonPipelineEnvironment.buildTool) 172 .withMandatoryProperty('buildTool') 173 .use() 174 175 if (config.legacyConfigSettings) { 176 Map legacyConfigSettings = readYaml(text: libraryResource(config.legacyConfigSettings)) 177 checkForLegacyConfiguration(script: script, legacyConfigSettings: legacyConfigSettings) 178 } 179 180 String buildTool = config.buildTool 181 String buildToolDesc = inferBuildToolDesc(script, config.buildTool) 182 183 checkBuildTool(buildTool, buildToolDesc) 184 185 script.commonPipelineEnvironment.projectName = config.projectName 186 187 if (!script.commonPipelineEnvironment.projectName && config.inferProjectName) { 188 script.commonPipelineEnvironment.projectName = inferProjectName(script, buildTool, buildToolDesc) 189 } 190 191 if (Boolean.valueOf(env.ON_K8S) && config.containerMapResource) { 192 ContainerMap.instance.initFromResource(script, config.containerMapResource, buildTool) 193 } 194 195 initStashConfiguration(script, config.stashSettings, config.customStashSettings, config.verbose ?: false) 196 197 if (config.verbose) { 198 echo "piper-lib-os configuration: ${script.commonPipelineEnvironment.configuration}" 199 } 200 201 // telemetry reporting 202 utils.pushToSWA([step: STEP_NAME], config) 203 204 piperInitRunStageConfiguration script: script, stageConfigResource: config.stageConfigResource 205 206 // CHANGE_ID is set only for pull requests 207 if (env.CHANGE_ID) { 208 List prActions = [] 209 210 //get trigger action from comment like /piper action 211 def jenkinsUtils = new JenkinsUtils() 212 def commentTriggerAction = jenkinsUtils.getIssueCommentTriggerAction() 213 214 if (commentTriggerAction != null) prActions.add(commentTriggerAction) 215 216 try { 217 prActions.addAll(pullRequest.getLabels().asList()) 218 } catch (ex) { 219 echo "[${STEP_NAME}] GitHub labels could not be retrieved from Pull Request, please make sure that credentials are maintained on multi-branch job." 220 } 221 222 setPullRequestStageStepActivation(script, config, prActions) 223 } 224 225 if (env.BRANCH_NAME == config.productiveBranch) { 226 if (parameters.script.commonPipelineEnvironment.configuration.runStep?.get('Init')?.slackSendNotification) { 227 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' 228 } 229 230 config.artifactPrepareVersion = true 231 } 232 233 if (config.artifactPrepareVersion) { 234 Map prepareVersionParams = [script: script] 235 if (config.inferBuildTool) { 236 prepareVersionParams.buildTool = buildTool 237 } 238 if(buildToolDesc) { 239 prepareVersionParams.filePath = buildToolDesc 240 } 241 if (env.ON_K8S && !config.runArtifactVersioningOnPod) { 242 // We force dockerImage: "" for the K8S case to avoid the execution of artifactPrepareVersion in a K8S Pod. 243 // Since artifactPrepareVersion may need the ".git" folder in order to push a tag, it would need to be part of the stashing. 244 // There are however problems with tar-ing this folder, which results in a failure to copy the stash back -- without a failure of the pipeline. 245 // This then also has the effect that any changes made to the build descriptors by the step (updated version) are not visible in the relevant stashes. 246 // In addition, a mvn executable is available on the Jenkins instance which can be used directly instead of executing the command in a container. 247 prepareVersionParams.dockerImage = "" 248 } 249 artifactPrepareVersion prepareVersionParams 250 } 251 pipelineStashFilesBeforeBuild script: script 252 } 253 } 254 255 // Infer build tool descriptor (maven, npm, mta) 256 private static String inferBuildToolDesc(script, buildTool) { 257 258 String buildToolDesc = null 259 260 switch (buildTool) { 261 case 'maven': 262 Map configBuild = script.commonPipelineEnvironment.getStepConfiguration('mavenBuild', 'Build') 263 buildToolDesc = configBuild.pomPath? configBuild.pomPath : 'pom.xml' 264 break 265 case 'npm': // no parameter for the descriptor path 266 buildToolDesc = 'package.json' 267 break 268 case 'mta': 269 Map configBuild = script.commonPipelineEnvironment.getStepConfiguration('mtaBuild', 'Build') 270 buildToolDesc = configBuild.source? configBuild.source + '/mta.yaml' : 'mta.yaml' 271 break 272 default: 273 break; 274 } 275 276 return buildToolDesc 277 } 278 279 private String inferProjectName(Script script, String buildTool, String buildToolDesc) { 280 switch (buildTool) { 281 case 'maven': 282 def pom = script.readMavenPom file: buildToolDesc 283 return "${pom.groupId}-${pom.artifactId}" 284 case 'npm': 285 Map packageJson = script.readJSON file: buildToolDesc 286 return packageJson.name 287 case 'mta': 288 Map mta = script.readYaml file: buildToolDesc 289 return mta.ID 290 } 291 292 script.error "Cannot infer projectName. Project buildTool was none of the expected ones 'mta', 'maven', or 'npm'." 293 } 294 295 private checkBuildTool(String buildTool, String buildDescriptorPattern) { 296 if (buildDescriptorPattern && !findFiles(glob: buildDescriptorPattern)) { 297 error "[${STEP_NAME}] buildTool configuration '${buildTool}' does not fit to your project (buildDescriptorPattern: '${buildDescriptorPattern}'), please set buildTool as general setting in your .pipeline/config.yml correctly, see also https://sap.github.io/jenkins-library/configuration/" 298 } 299 } 300 301 private void initStashConfiguration (script, stashSettings, customStashSettings, verbose) { 302 Map stashConfiguration = null 303 if (customStashSettings){ 304 stashConfiguration = readYaml(file: customStashSettings) 305 }else{ 306 stashConfiguration = readYaml(text: libraryResource(stashSettings)) 307 } 308 if (verbose) echo "Stash config: ${stashConfiguration}" 309 script.commonPipelineEnvironment.configuration.stageStashes = stashConfiguration 310 } 311 312 private void setPullRequestStageStepActivation(script, config, List actions) { 313 314 if (script.commonPipelineEnvironment.configuration.runStep == null) 315 script.commonPipelineEnvironment.configuration.runStep = [:] 316 if (script.commonPipelineEnvironment.configuration.runStep[config.pullRequestStageName] == null) 317 script.commonPipelineEnvironment.configuration.runStep[config.pullRequestStageName] = [:] 318 319 actions.each {action -> 320 if (action.startsWith(config.labelPrefix)) 321 action = action.minus(config.labelPrefix) 322 323 def stepName = config.stepMappings[action] 324 if (stepName) { 325 script.commonPipelineEnvironment.configuration.runStep."${config.pullRequestStageName}"."${stepName}" = true 326 } 327 } 328 }