github.com/ouraigua/jenkins-library@v0.0.0-20231028010029-fbeaf2f3aa9b/src/com/sap/piper/Utils.groovy (about)

     1  package com.sap.piper
     2  
     3  import com.cloudbees.groovy.cps.NonCPS
     4  import com.sap.piper.analytics.Telemetry
     5  import groovy.text.GStringTemplateEngine
     6  
     7  import java.nio.charset.StandardCharsets
     8  import java.security.MessageDigest
     9  
    10  def stash(Map params) {
    11      if(params.includes == null) params.includes = '**/*.*'
    12      if(params.excludes == null) params.excludes = ''
    13      if(params.useDefaultExcludes == null) params.useDefaultExcludes = true
    14      if(params.allowEmpty == null) params.allowEmpty = false
    15      return stash(params.name, params.includes, params.excludes, params.useDefaultExcludes, params.allowEmpty)
    16  }
    17  
    18  def stash(String name, String includes = '**/*.*', String excludes = '', boolean useDefaultExcludes = true, boolean allowEmpty = false) {
    19      if(!name) throw new IllegalArgumentException("name must not be '$name'")
    20      echo "Stash content: ${name} (includes: ${includes}, excludes: ${excludes}, useDefaultExcludes: ${useDefaultExcludes}, allowEmpty: ${allowEmpty})"
    21  
    22      Map stashParams = [
    23          name    : name,
    24          includes: includes,
    25          excludes: excludes
    26      ]
    27      //only set the optional parameter if default excludes should not be applied
    28      if (!useDefaultExcludes) {
    29          stashParams.useDefaultExcludes = useDefaultExcludes
    30      }
    31      //only set the optional parameter if allow empty should be applied
    32      if (allowEmpty) {
    33          stashParams.allowEmpty = allowEmpty
    34      }
    35      steps.stash stashParams
    36  }
    37  
    38  def stashList(script, List stashes) {
    39      for (def stash : stashes) {
    40          def name = stash.name
    41          def includes = stash.includes
    42          def excludes = stash.excludes
    43  
    44          if (stash?.merge == true) {
    45              String lockingResourceGroup = script.commonPipelineEnvironment.projectName?:env.JOB_NAME
    46              String lockName = "${lockingResourceGroup}/${stash.name}"
    47              lock(lockName) {
    48                  unstash stash.name
    49                  echo "Stash content: ${name} (includes: ${includes}, excludes: ${excludes})"
    50                  steps.stash name: name, includes: includes, excludes: excludes, allowEmpty: true
    51              }
    52          } else {
    53              echo "Stash content: ${name} (includes: ${includes}, excludes: ${excludes})"
    54              steps.stash name: name, includes: includes, excludes: excludes, allowEmpty: true
    55          }
    56      }
    57  }
    58  
    59  def stashWithMessage(name, msg, include = '**/*.*', exclude = '', useDefaultExcludes = true) {
    60      try {
    61          stash(name, include, exclude, useDefaultExcludes)
    62      } catch (e) {
    63          echo msg + name + " (${e.getMessage()})"
    64      }
    65  }
    66  
    67  def stashStageFiles(Script script, String stageName) {
    68      List stashes = script.commonPipelineEnvironment.configuration.stageStashes?.get(stageName)?.stashes ?: []
    69  
    70      stashList(script, stashes)
    71  
    72      //NOTE: We do not delete the directory in case Jenkins runs on Kubernetes.
    73      // deleteDir() is not required in pods, but would be nice to have the same behaviour and leave a clean fileSystem.
    74      if (!isInsidePod(script)) {
    75          script.deleteDir()
    76      }
    77  }
    78  
    79  def unstashStageFiles(Script script, String stageName, List stashContent = []) {
    80      stashContent += script.commonPipelineEnvironment.configuration.stageStashes?.get(stageName)?.unstash ?: []
    81  
    82      script.deleteDir()
    83      unstashAll(stashContent)
    84  
    85      return stashContent
    86  }
    87  
    88  boolean isInsidePod(Script script) {
    89      return script.env.POD_NAME
    90  }
    91  
    92  def unstash(name, msg = "Unstash failed:") {
    93  
    94      def unstashedContent = []
    95      try {
    96          echo "Unstash content: ${name}"
    97          steps.unstash name
    98          unstashedContent += name
    99      } catch (e) {
   100          echo "$msg $name (${e.getMessage()})"
   101          if (e.getMessage().contains("JNLP4-connect")) {
   102              sleep(3) // Wait 3 seconds in case it has been a network hiccup
   103              try {
   104                  echo "[Retry JNLP4-connect issue] Unstashing content: ${name}"
   105                  steps.unstash name
   106                  unstashedContent += name
   107              } catch (errRetry) {
   108                  msg = "[Retry JNLP4-connect issue] Unstashing failed:"
   109                  echo "$msg $name (${errRetry.getMessage()})"
   110              }
   111          }
   112      }
   113      return unstashedContent
   114  }
   115  
   116  def unstashAll(stashContent) {
   117      def unstashedContent = []
   118      if (stashContent) {
   119          for (int i = 0; i < stashContent.size(); i++) {
   120              if (stashContent[i]) {
   121                  unstashedContent += unstash(stashContent[i])
   122              }
   123          }
   124      }
   125      return unstashedContent
   126  }
   127  
   128  @NonCPS
   129  def generateSha1(input) {
   130      return MessageDigest
   131          .getInstance("SHA-1")
   132          .digest(input.getBytes(StandardCharsets.UTF_8))
   133          .encodeHex().toString()
   134  }
   135  
   136  void pushToSWA(Map parameters, Map config) {
   137      try {
   138          parameters.actionName = parameters.get('actionName') ?: 'Piper Library OS'
   139          parameters.eventType = parameters.get('eventType') ?: 'library-os'
   140          parameters.jobUrlSha1 = generateSha1(env.JOB_URL ?: '')
   141          parameters.buildUrlSha1 = generateSha1(env.BUILD_URL ?: '')
   142  
   143          Telemetry.notify(this, config, parameters)
   144      } catch (ignore) {
   145          // some error occured in telemetry reporting. This should not break anything though.
   146          echo "[${parameters.step}] Telemetry Report failed: ${ignore.getMessage()}"
   147      }
   148  }
   149  
   150  @NonCPS
   151  static String fillTemplate(String templateText, Map binding) {
   152      def engine = new GStringTemplateEngine()
   153      String result = engine.createTemplate(templateText).make(binding)
   154      return result
   155  }
   156  
   157  static String downloadSettingsFromUrl(script, String url, String targetFile = 'settings.xml') {
   158      if (script.fileExists(targetFile)) {
   159          throw new RuntimeException("Trying to download settings file to ${targetFile}, but a file with this name already exists. Please specify a unique file name.")
   160      }
   161  
   162      def settings = script.httpRequest(url)
   163      script.writeFile(file: targetFile, text: settings.getContent())
   164      return targetFile
   165  }
   166  
   167  /*
   168   * Uses the Maven Help plugin to evaluate the given expression into the resolved values
   169   * that maven sees at / generates at runtime. This way, the exact Maven coordinates and
   170   * variables can be used.
   171   */
   172  static String evaluateFromMavenPom(Script script, String pomFileName, String pomPathExpression) {
   173  
   174      String resolvedExpression = script.mavenExecute(
   175          script: script,
   176          pomPath: pomFileName,
   177          goals: ['org.apache.maven.plugins:maven-help-plugin:3.1.0:evaluate'],
   178          defines: ["-Dexpression=$pomPathExpression", "-DforceStdout", "-q"],
   179          returnStdout: true
   180      )
   181      if (resolvedExpression.startsWith('null object or invalid expression')) {
   182          // There is no error indication (exit code or otherwise) from the
   183          // 'evaluate' Maven plugin, only this output to stdout. The calling
   184          // code assumes an empty string is returned when the property could
   185          // not be resolved.
   186          throw new RuntimeException("Cannot evaluate property value from '${pomFileName}', " +
   187              "missing property or invalid expression '${pomPathExpression}'.")
   188      }
   189      return resolvedExpression
   190  }
   191  
   192  static List appendParameterToStringList(List list, Map parameters, String paramName) {
   193      def value = parameters[paramName]
   194      List result = []
   195      result.addAll(list)
   196      if (value in CharSequence) {
   197          result.add(value)
   198      } else if (value in List) {
   199          result.addAll(value)
   200      }
   201      return result
   202  }