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

Added support for old "interceptor API" for extensions

This is part of the effort to get rid of the "runAsStage" step in the SDK pipeline, and use piperStageWrapper directly. The SDK pipeline currently needs to support for loading "old" extensions where the call() method had different parameters. The support for the exact API can and should be removed, however, having a mechanism for supporting old extension APIs seems beneficial in general.

Another crucial change is the deleteDir() call before unstashing at the beginning of the stage. Without this, the SDK pipeline fails to unstash, since apparently the workspace may not always be clean at that point.
This commit is contained in:
Stephan Aßmus 2020-01-20 15:58:57 +01:00
parent f59d9f9d49
commit ddd10683c4

View File

@ -1,3 +1,4 @@
import com.cloudbees.groovy.cps.NonCPS
import com.sap.piper.Utils
import com.sap.piper.ConfigurationHelper
import com.sap.piper.ConfigurationLoader
@ -13,12 +14,12 @@ void call(Map parameters = [:], body) {
final script = checkScript(this, parameters) ?: this
def utils = parameters.juStabUtils ?: new Utils()
def stageName = parameters.stageName?:env.STAGE_NAME
def stageName = parameters.stageName ?: env.STAGE_NAME
// load default & individual configuration
Map config = ConfigurationHelper.newInstance(this)
.loadStepDefaults()
.mixin(ConfigurationLoader.defaultStageConfiguration(this, stageName))
.mixin(ConfigurationLoader.defaultStageConfiguration(script, stageName))
.mixinGeneralConfig(script.commonPipelineEnvironment)
.mixinStageConfig(script.commonPipelineEnvironment, stageName)
.mixin(parameters)
@ -62,6 +63,7 @@ private void executeStage(script, originalStage, stageName, config, utils) {
//Add general stage stashes to config.stashContent
config.stashContent += script.commonPipelineEnvironment.configuration.stageStashes?.get(stageName)?.unstash ?: []
deleteDir()
utils.unstashAll(config.stashContent)
/* Defining the sources where to look for a project extension and a repository extension.
@ -76,20 +78,19 @@ private void executeStage(script, originalStage, stageName, config, utils) {
// First, check if a global extension exists via a dedicated repository
if (globalExtensions) {
Script globalInterceptorScript = load(globalInterceptorFile)
echo "[${STEP_NAME}] Found global interceptor '${globalInterceptorFile}' for ${stageName}."
// If we call the global interceptor, we will pass on originalStage as parameter
body = {
globalInterceptorScript(script: script, originalStage: body, stageName: stageName, config: config)
callInterceptor(script, globalInterceptorFile, originalStage, stageName, config)
}
}
// Second, check if a project extension (within the same repository) exists
if (projectExtensions) {
Script projectInterceptorScript = load(projectInterceptorFile)
echo "[${STEP_NAME}] Running project interceptor '${projectInterceptorFile}' for ${stageName}."
// If we call the project interceptor, we will pass on body as parameter which contains either originalStage or the repository interceptor
projectInterceptorScript(script: script, originalStage: body, stageName: stageName, config: config)
callInterceptor(script, projectInterceptorFile, body, stageName, config)
} else {
//TODO: assign projectInterceptorScript to body as done for globalInterceptorScript, currently test framework does not seem to support this case. Further investigations needed.
body()
@ -122,3 +123,42 @@ private void executeStage(script, originalStage, stageName, config, utils) {
], config)
}
}
private void callInterceptor(Script script, String extensionFileName, Closure originalStage, String stageName, Map configuration) {
Script interceptor = load(extensionFileName)
if (isOldInterceptorInterfaceUsed(interceptor)) {
echo("[Warning] The interface to implement extensions has changed. " +
"The extension $extensionFileName has to implement a method named 'call' with exactly one parameter of type Map. " +
"This map will have the properties script, originalStage, stageName, config. " +
"For example: def call(Map parameters) { ... }")
interceptor.call(originalStage, stageName, configuration, configuration)
} else {
validateInterceptor(interceptor, extensionFileName)
interceptor.call([
script : script,
originalStage: originalStage,
stageName : stageName,
config : configuration
])
}
}
@NonCPS
private boolean isInterceptorValid(Script interceptor) {
MetaMethod method = interceptor.metaClass.pickMethod("call", [Map.class] as Class[])
return method != null
}
private void validateInterceptor(Script interceptor, String extensionFileName) {
if (!isInterceptorValid(interceptor)) {
error("The extension $extensionFileName has to implement a method named 'call' with exactly one parameter of type Map. " +
"This map will have the properties script, originalStage, stageName, config. " +
"For example: def call(Map parameters) { ... }")
}
}
@NonCPS
private boolean isOldInterceptorInterfaceUsed(Script interceptor) {
MetaMethod method = interceptor.metaClass.pickMethod("call", [Closure.class, String.class, Map.class, Map.class] as Class[])
return method != null
}