1
0
mirror of https://github.com/SAP/jenkins-library.git synced 2024-12-14 11:03:09 +02:00
sap-jenkins-library/vars/piperPipelineStageInit.groovy

270 lines
12 KiB
Groovy
Raw Normal View History

import com.cloudbees.groovy.cps.NonCPS
import com.sap.piper.ConfigurationHelper
import com.sap.piper.GenerateStageDocumentation
import com.sap.piper.JenkinsUtils
import com.sap.piper.LegacyConfigurationCheckUtils
import com.sap.piper.StageNameProvider
import com.sap.piper.Utils
import com.sap.piper.k8s.ContainerMap
import groovy.transform.Field
import static com.sap.piper.Prerequisites.checkScript
@Field String STEP_NAME = getClass().getName()
@Field String TECHNICAL_STAGE_NAME = 'init'
@Field Set GENERAL_CONFIG_KEYS = [
/**
* Defines the build tool used.
* @possibleValues `docker`, `kaniko`, `maven`, `mta, ``npm`
*/
'buildTool',
/**
* Defines the library resource containing the container map.
*/
'containerMapResource',
/**
* Enable automatic inference of build tool (maven, npm, mta) based on existing project files.
* If this is set to true, it is not required to provide the `buildTool` parameter in the `general` section of the pipeline configuration.
*/
'inferBuildTool',
/**
* Enables automatic inference from the build descriptor in case projectName is not configured.
*/
'inferProjectName',
/**
* Toggle for initialization of the stash settings for Cloud SDK Pipeline.
* If this is set to true, the stashSettings parameter is **not** configurable.
*/
'initCloudSdkStashSettings',
/**
* Defines the library resource containing the legacy configuration definition.
*/
'legacyConfigSettings',
/**
* 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
*/
'productiveBranch',
/**
* Name of the project, e.g. used for the name of lockable resources.
*/
'projectName',
/**
* 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!**
*/
'stageConfigResource',
/**
* 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!**
*/
'stashSettings',
/**
* Whether verbose output should be produced.
* @possibleValues `true`, `false`
*/
'verbose'
]
@Field STAGE_STEP_KEYS = []
@Field Set STEP_CONFIG_KEYS = GENERAL_CONFIG_KEYS.plus(STAGE_STEP_KEYS)
@Field Set PARAMETER_KEYS = STEP_CONFIG_KEYS.plus([
/**
* Enables the use of technical stage names.
*/
'useTechnicalStageNames',
/**
* Optional path to the pipeline configuration file defining project specific settings.
*/
'configFile',
/**
* Optional list of file names which will be extracted from library resources and which serve as source for
* default values for the pipeline configuration. These are merged with and override built-in defaults, with
* a parameter supplied by the last resource file taking precedence over the same parameter supplied in an
* earlier resource file or built-in default.
*/
'customDefaults',
/**
* Optional list of file paths or URLs which must point to YAML content. These work exactly like
* `customDefaults`, but from local or remote files instead of library resources. They are merged with and
* take precedence over `customDefaults`.
*/
'customDefaultsFromFiles'
])
/**
* This stage initializes the pipeline run and prepares further execution.
*
* It will check out your repository and perform some steps to initialize your pipeline run.
*/
@GenerateStageDocumentation(defaultStageName = 'Init')
void call(Map parameters = [:]) {
def script = checkScript(this, parameters) ?: this
def utils = parameters.juStabUtils ?: new Utils()
if (parameters.useTechnicalStageNames) {
StageNameProvider.instance.useTechnicalStageNames = true
}
def stageName = StageNameProvider.instance.getStageName(script, parameters, this)
piperStageWrapper (script: script, stageName: stageName, stashContent: [], ordinal: 1, telemetryDisabled: true) {
def scmInfo = checkout scm
setupCommonPipelineEnvironment(script: script, customDefaults: parameters.customDefaults, gitUrl: scmInfo.GIT_URL,
configFile: parameters.configFile, customDefaultsFromFiles: parameters.customDefaultsFromFiles)
Map config = ConfigurationHelper.newInstance(this)
.loadStepDefaults()
.mixinGeneralConfig(script.commonPipelineEnvironment, GENERAL_CONFIG_KEYS)
.mixinStageConfig(script.commonPipelineEnvironment, stageName, STEP_CONFIG_KEYS)
.mixin(parameters, PARAMETER_KEYS)
.addIfEmpty('stageConfigResource', 'com.sap.piper/pipeline/stageDefaults.yml')
.addIfEmpty('stashSettings', 'com.sap.piper/pipeline/stashSettings.yml')
.addIfEmpty('buildTool', script.commonPipelineEnvironment.buildTool)
.withMandatoryProperty('buildTool')
.use()
if (config.legacyConfigSettings) {
Map legacyConfigSettings = readYaml(text: libraryResource(config.legacyConfigSettings))
LegacyConfigurationCheckUtils.checkConfiguration(script, legacyConfigSettings)
}
String buildTool = checkBuildTool(config)
script.commonPipelineEnvironment.projectName = config.projectName
if (!script.commonPipelineEnvironment.projectName && config.inferProjectName) {
script.commonPipelineEnvironment.projectName = inferProjectName(script, buildTool)
}
if (Boolean.valueOf(env.ON_K8S) && config.containerMapResource) {
ContainerMap.instance.initFromResource(script, config.containerMapResource, buildTool)
}
//perform stashing based on library resource piper-stash-settings.yml if not configured otherwise or Cloud SDK Pipeline is initialized
if (config.initCloudSdkStashSettings) {
switch (buildTool) {
case 'maven':
initStashConfiguration(script, "com.sap.piper/pipeline/cloudSdkJavaStashSettings.yml", config.verbose?: false)
break
case 'npm':
initStashConfiguration(script, "com.sap.piper/pipeline/cloudSdkJavascriptStashSettings.yml", config.verbose?: false)
break
case 'mta':
initStashConfiguration(script, "com.sap.piper/pipeline/cloudSdkMtaStashSettings.yml", config.verbose?: false)
break
default:
error "[${STEP_NAME}] No stash settings for build tool ${buildTool} can be found. With `initCloudSdkStashSettings` active, only Maven, MTA or NPM projects are supported."
break
}
} else {
initStashConfiguration(script, config.stashSettings, config.verbose?: false)
}
if (config.verbose) {
echo "piper-lib-os configuration: ${script.commonPipelineEnvironment.configuration}"
}
// telemetry reporting
utils.pushToSWA([step: STEP_NAME], config)
piperInitRunStageConfiguration script: script, stageConfigResource: config.stageConfigResource
// CHANGE_ID is set only for pull requests
if (env.CHANGE_ID) {
List prActions = []
//get trigger action from comment like /piper action
def jenkinsUtils = new JenkinsUtils()
def commentTriggerAction = jenkinsUtils.getIssueCommentTriggerAction()
if (commentTriggerAction != null) prActions.add(commentTriggerAction)
try {
prActions.addAll(pullRequest.getLabels().asList())
} catch (ex) {
echo "[${STEP_NAME}] GitHub labels could not be retrieved from Pull Request, please make sure that credentials are maintained on multi-branch job."
}
setPullRequestStageStepActivation(script, config, prActions)
}
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'
}
if (config.inferBuildTool && env.ON_K8S) {
// We set dockerImage: "" for the K8S case to avoid the execution of artifactPrepareVersion in a K8S Pod.
// In addition, a mvn executable is available on the Jenkins instance which can be used directly instead of executing the command in a container.
artifactPrepareVersion script: script, buildTool: buildTool, dockerImage: ""
} else if (config.inferBuildTool) {
artifactPrepareVersion script: script, buildTool: buildTool
} else {
artifactSetVersion script: script
}
}
pipelineStashFilesBeforeBuild script: script
}
}
private String inferProjectName(Script script, String buildTool) {
switch (buildTool) {
case 'maven':
def pom = script.readMavenPom file: 'pom.xml'
return "${pom.groupId}-${pom.artifactId}"
case 'npm':
Map packageJson = script.readJSON file: 'package.json'
return packageJson.name
case 'mta':
Map mta = script.readYaml file: 'mta.yaml'
return mta.ID
}
script.error "Cannot infer projectName. Project buildTool was none of the expected ones 'mta', 'maven', or 'npm'."
}
private String checkBuildTool(config) {
def buildDescriptorPattern = ''
String buildTool = config.buildTool
switch (buildTool) {
case 'maven':
buildDescriptorPattern = 'pom.xml'
break
case 'npm':
buildDescriptorPattern = 'package.json'
break
case 'mta':
buildDescriptorPattern = 'mta.yaml'
break
}
if (buildDescriptorPattern && !findFiles(glob: buildDescriptorPattern)) {
error "[${STEP_NAME}] buildTool configuration '${config.buildTool}' does not fit to your project, please set buildTool as genereal setting in your .pipeline/config.yml correctly, see also https://sap.github.io/jenkins-library/configuration/"
}
return buildTool
}
private void initStashConfiguration (script, stashSettings, verbose) {
Map stashConfiguration = readYaml(text: libraryResource(stashSettings))
if (verbose) echo "Stash config: ${stashConfiguration}"
script.commonPipelineEnvironment.configuration.stageStashes = stashConfiguration
}
private void setPullRequestStageStepActivation(script, config, List actions) {
if (script.commonPipelineEnvironment.configuration.runStep == null)
script.commonPipelineEnvironment.configuration.runStep = [:]
if (script.commonPipelineEnvironment.configuration.runStep[config.pullRequestStageName] == null)
script.commonPipelineEnvironment.configuration.runStep[config.pullRequestStageName] = [:]
actions.each {action ->
if (action.startsWith(config.labelPrefix))
action = action.minus(config.labelPrefix)
def stepName = config.stepMappings[action]
if (stepName) {
script.commonPipelineEnvironment.configuration.runStep."${config.pullRequestStageName}"."${stepName}" = true
}
}
}