github.com/jaylevin/jenkins-library@v1.230.4/vars/checkForLegacyConfiguration.groovy (about) 1 import com.sap.piper.ConfigurationLoader 2 import com.sap.piper.DefaultValueCache 3 import com.sap.piper.MapUtils 4 import groovy.transform.Field 5 6 import static com.sap.piper.Prerequisites.checkScript 7 8 @Field String STEP_NAME = getClass().getName() 9 @Field Set GENERAL_CONFIG_KEYS = [] 10 @Field Set STEP_CONFIG_KEYS = [] 11 @Field Set PARAMETER_KEYS = STEP_CONFIG_KEYS 12 13 void call(Map parameters = [:]) { 14 List errors = [] 15 def script = checkScript(this, parameters) ?: this 16 def configChanges = parameters.legacyConfigSettings 17 18 if (configChanges?.removedOrReplacedConfigKeys) { 19 errors.addAll(checkForRemovedOrReplacedConfigKeys(script, configChanges.removedOrReplacedConfigKeys)) 20 } 21 22 if (configChanges?.requiredConfigKeys) { 23 errors.addAll(checkForMissingConfigKeys(script, configChanges.requiredConfigKeys)) 24 } 25 26 if (configChanges?.removedOrReplacedSteps) { 27 errors.addAll(checkForRemovedOrReplacedSteps(script, configChanges.removedOrReplacedSteps)) 28 } 29 30 if (configChanges?.removedOrReplacedStages) { 31 errors.addAll(checkForRemovedOrReplacedStages(script, configChanges.removedOrReplacedStages)) 32 } 33 34 if (configChanges?.parameterTypeChanged) { 35 errors.addAll(checkForParameterTypeChanged(script, configChanges.parameterTypeChanged)) 36 } 37 38 if (configChanges?.renamedNpmScript) { 39 errors.addAll(checkForRenamedNpmScripts(script, configChanges.renamedNpmScript)) 40 } 41 42 if (errors) { 43 String message = "" 44 if (errors.size() > 1) { 45 message += "Your pipeline configuration file contains the following errors:\n" 46 } 47 for (error in errors) { 48 message += error 49 message += "\n" 50 } 51 message += "Failing pipeline due to configuration errors. Please see log output above." 52 script.error(message) 53 } 54 } 55 56 static List checkForRemovedOrReplacedConfigKeys(Script script, Map configChanges) { 57 List errors = [] 58 configChanges.each { oldConfigKey, changes -> 59 List steps = changes?.steps ?: [] 60 List stages = changes?.stages ?: [] 61 Boolean general = changes?.general ?: false 62 Boolean postAction = changes?.postAction ?: false 63 64 Boolean warnInsteadOfError = changes?.warnInsteadOfError ?: false 65 String customMessage = changes?.customMessage ?: "" 66 String newConfigKey = changes?.newConfigKey ?: "" 67 68 if (newConfigKey) { 69 customMessage = "Please use the parameter ${newConfigKey} instead. " + customMessage 70 } 71 72 for (int i = 0; i < steps.size(); i++) { 73 Map config = loadEffectiveStepConfig(script, steps[i]) 74 if (config.containsKey(oldConfigKey)) { 75 String errorMessage = "Your pipeline configuration contains the configuration key ${oldConfigKey} for the step ${steps[i]}. " + 76 "This configuration option was removed. " + customMessage 77 if (warnInsteadOfError) { 78 addPipelineWarning(script, "Deprecated configuration key ${oldConfigKey}", errorMessage) 79 } else { 80 errors.add(errorMessage) 81 } 82 } 83 } 84 85 for (int i = 0; i < stages.size(); i++) { 86 Map config = loadEffectiveStageConfig(script, stages[i]) 87 if (config.containsKey(oldConfigKey)) { 88 String errorMessage = "Your pipeline configuration contains the configuration key ${oldConfigKey} for the stage ${stages[i]}. " + 89 "This configuration option was removed. " + customMessage 90 if (warnInsteadOfError) { 91 addPipelineWarning(script, "Deprecated configuration key ${oldConfigKey}", errorMessage) 92 } else { 93 errors.add(errorMessage) 94 } 95 } 96 } 97 98 if (general) { 99 Map config = loadEffectiveGeneralConfig(script) 100 if (config.containsKey(oldConfigKey)) { 101 String errorMessage = "Your pipeline configuration contains the configuration key ${oldConfigKey} in the general section. " + 102 "This configuration option was removed. " + customMessage 103 if (warnInsteadOfError) { 104 addPipelineWarning(script, "Deprecated configuration key ${oldConfigKey}", errorMessage) 105 } else { 106 errors.add(errorMessage) 107 } 108 } 109 } 110 111 if (postAction) { 112 Map config = loadEffectivePostActionConfig(script) 113 if (config.containsKey(oldConfigKey)) { 114 String errorMessage = "Your pipeline configuration contains the configuration key ${oldConfigKey} in the postActions section. " + 115 "This configuration option was removed. " + customMessage 116 if (warnInsteadOfError) { 117 addPipelineWarning(script, "Deprecated configuration key ${oldConfigKey}", errorMessage) 118 } else { 119 errors.add(errorMessage) 120 } 121 } 122 } 123 } 124 return errors 125 } 126 127 static List checkForMissingConfigKeys(Script script, Map configChanges) { 128 List errors = [] 129 configChanges.each { requiredConfigKey, changes -> 130 List steps = changes?.steps ?: [] 131 List stages = changes?.stages ?: [] 132 Boolean general = changes?.general ?: false 133 Boolean postAction = changes?.postAction ?: false 134 135 Boolean warnInsteadOfError = changes?.warnInsteadOfError ?: false 136 String customMessage = changes?.customMessage ?: "" 137 138 for (int i = 0; i < steps.size(); i++) { 139 Map config = loadEffectiveStepConfig(script, steps[i]) 140 if (!config.containsKey(requiredConfigKey)) { 141 String errorMessage = "Your pipeline configuration does not contain the configuration " + 142 "key ${requiredConfigKey} for the step ${steps[i]}. " + customMessage 143 if (warnInsteadOfError) { 144 addPipelineWarning(script, "Missing configuration key ${requiredConfigKey}", errorMessage) 145 } else { 146 errors.add(errorMessage) 147 } 148 } 149 } 150 151 for (int i = 0; i < stages.size(); i++) { 152 Map config = loadEffectiveStageConfig(script, stages[i]) 153 if (!config.containsKey(requiredConfigKey)) { 154 String errorMessage = "Your pipeline configuration does not contain the configuration " + 155 "key ${requiredConfigKey} for the stage ${stages[i]}. " + customMessage 156 if (warnInsteadOfError) { 157 addPipelineWarning(script, "Missing configuration key ${requiredConfigKey}", errorMessage) 158 } else { 159 errors.add(errorMessage) 160 } 161 } 162 } 163 164 if (general) { 165 Map config = loadEffectiveGeneralConfig(script) 166 if (!config.containsKey(requiredConfigKey)) { 167 String errorMessage = "Your pipeline configuration does not contain the configuration " + 168 "key ${requiredConfigKey} in the general section. " + customMessage 169 if (warnInsteadOfError) { 170 addPipelineWarning(script, "Missing configuration key ${requiredConfigKey}", errorMessage) 171 } else { 172 errors.add(errorMessage) 173 } 174 } 175 } 176 177 if (postAction) { 178 Map config = loadEffectivePostActionConfig(script) 179 if (!config.containsKey(requiredConfigKey)) { 180 String errorMessage = "Your pipeline configuration does not contain the configuration " + 181 "key ${requiredConfigKey} in the postActions section. " + customMessage 182 if (warnInsteadOfError) { 183 addPipelineWarning(script, "Missing configuration key ${requiredConfigKey}", errorMessage) 184 } else { 185 errors.add(errorMessage) 186 } 187 } 188 } 189 } 190 return errors 191 } 192 193 static List checkForRemovedOrReplacedSteps(Script script, Map configChanges) { 194 List errors = [] 195 configChanges.each { oldConfigKey, changes -> 196 Boolean onlyCheckProjectConfig = changes?.onlyCheckProjectConfig ?: false 197 String customMessage = changes?.customMessage ?: "" 198 String newStepName = changes?.newStepName ?: "" 199 200 if (newStepName) { 201 customMessage = "Please configure the step ${newStepName} instead. " + customMessage 202 } 203 204 Map config 205 if (onlyCheckProjectConfig) { 206 config = ConfigurationLoader.stepConfiguration(script, oldConfigKey) 207 } else { 208 config = loadEffectiveStepConfig(script, oldConfigKey) 209 } 210 211 if (config) { 212 errors.add("Your pipeline configuration contains configuration for the step ${oldConfigKey}. " + 213 "This step has been removed. " + customMessage) 214 } 215 } 216 return errors 217 } 218 219 static List checkForRemovedOrReplacedStages(Script script, Map configChanges) { 220 List errors = [] 221 configChanges.each { oldConfigKey, changes -> 222 String customMessage = changes?.customMessage ?: "" 223 String newStageName = changes?.newStageName ?: "" 224 225 if (newStageName) { 226 customMessage = "Please configure the stage ${newStageName} instead. " + customMessage 227 } 228 229 if (loadEffectiveStageConfig(script, oldConfigKey)) { 230 errors.add("Your pipeline configuration contains configuration for the stage ${oldConfigKey}. " + 231 "This stage has been removed. " + customMessage) 232 } 233 } 234 return errors 235 } 236 237 static List checkForParameterTypeChanged(Script script, Map configChanges) { 238 List errors = [] 239 configChanges.each { oldConfigKey, changes -> 240 String oldType = changes?.oldType ?: "" 241 String newType = changes?.newType ?: "" 242 List steps = changes?.steps ?: [] 243 List stages = changes?.stages ?: [] 244 Boolean general = changes?.general ?: false 245 String customMessage = changes?.customMessage ?: "" 246 247 if (oldType != "String") { 248 errors.add("Your legacy config settings contain an entry for parameterTypeChanged with the key ${oldConfigKey} with the unsupported type ${oldType}. " + 249 "Currently only the type 'String' is supported.") 250 return 251 } 252 253 for (int i = 0; i < steps.size(); i++) { 254 Map config = loadEffectiveStepConfig(script, steps[i]) 255 if (config.containsKey(oldConfigKey)) { 256 if (oldType == "String" && config.get(oldConfigKey) instanceof String) { 257 errors.add("Your pipeline configuration contains the configuration key ${oldConfigKey} for the step ${steps[i]}. " + 258 "The type of this configuration parameter was changed from ${oldType} to ${newType}. " + customMessage) 259 } 260 } 261 } 262 263 for (int i = 0; i < stages.size(); i++) { 264 Map config = loadEffectiveStageConfig(script, stages[i]) 265 if (config.containsKey(oldConfigKey)) { 266 if (oldType == "String" && config.get(oldConfigKey) instanceof String) { 267 errors.add("Your pipeline configuration contains the configuration key ${oldConfigKey} for the stage ${stages[i]}. " + 268 "The type of this configuration parameter was changed from ${oldType} to ${newType}. " + customMessage) 269 } 270 } 271 } 272 273 if (general) { 274 Map config = loadEffectiveGeneralConfig(script) 275 if (config.containsKey(oldConfigKey)) { 276 if (oldType == "String" && config.get(oldConfigKey) instanceof String) { 277 errors.add("Your pipeline configuration contains the configuration key ${oldConfigKey} in the general section. " + 278 "The type of this configuration parameter was changed from ${oldType} to ${newType}. " + customMessage) 279 } 280 } 281 } 282 } 283 return errors 284 } 285 286 static List checkForRenamedNpmScripts(Script script, Map configChanges) { 287 List errors = [] 288 configChanges.each { oldScriptName, changes -> 289 String newScriptName = changes?.newScriptName ?: "" 290 Boolean warnInsteadOfError = changes?.warnInsteadOfError ?: false 291 String customMessage = changes?.customMessage ?: "" 292 293 String packageJsonWithScript = findPackageWithScript(script, oldScriptName) 294 if (packageJsonWithScript) { 295 String errorMessage = "Your package.json file ${packageJsonWithScript} contains an npm script using the deprecated name ${oldScriptName}. " + 296 "Please rename the script to ${newScriptName}, since the script ${oldScriptName} will not be executed by the pipeline anymore. " + customMessage 297 if (warnInsteadOfError) { 298 addPipelineWarning(script, "Deprecated npm script ${oldScriptName}", errorMessage) 299 } else { 300 errors.add(errorMessage) 301 } 302 } 303 } 304 return errors 305 } 306 307 private static String findPackageWithScript(Script script, String scriptName) { 308 List packages = script.findFiles(glob: '**/package.json', excludes: '**/node_modules/**') 309 310 for (int i = 0; i < packages.size(); i++) { 311 String packageJsonPath = packages[i].path 312 Map packageJson = script.readJSON file: packageJsonPath 313 Map npmScripts = packageJson?.scripts ?: [:] 314 if (npmScripts.get(scriptName)) { 315 return packageJsonPath 316 } 317 } 318 return "" 319 } 320 321 private static Map loadEffectiveStepConfig(Script script, String stepName) { 322 return MapUtils.merge(ConfigurationLoader.defaultStepConfiguration(script, stepName), ConfigurationLoader.stepConfiguration(script, stepName)) 323 } 324 325 private static Map loadEffectiveStageConfig(Script script, String stageName) { 326 return MapUtils.merge(ConfigurationLoader.defaultStageConfiguration(script, stageName), ConfigurationLoader.stageConfiguration(script, stageName)) 327 } 328 329 private static Map loadEffectiveGeneralConfig(Script script) { 330 return MapUtils.merge(ConfigurationLoader.defaultGeneralConfiguration(script), ConfigurationLoader.generalConfiguration(script)) 331 } 332 333 private static Map loadEffectivePostActionConfig(Script script) { 334 Map defaultPostActionConfig = DefaultValueCache.getInstance()?.getDefaultValues()?.get("postActions") ?: [:] 335 Map projectPostActionConfig = script?.commonPipelineEnvironment?.configuration?.postActions ?: [:] 336 return MapUtils.merge(defaultPostActionConfig, projectPostActionConfig) 337 } 338 339 static void addPipelineWarning(Script script, String heading, String message) { 340 script.echo '[WARNING] ' + message 341 script.addBadge(icon: "warning.gif", text: message) 342 343 String html = 344 """ 345 <h2>$heading</h2> 346 <p>$message</p> 347 """ 348 349 script.createSummary(icon: "warning.gif", text: html) 350 }