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  }