github.com/ouraigua/jenkins-library@v0.0.0-20231028010029-fbeaf2f3aa9b/test/groovy/SetupCommonPipelineEnvironmentTest.groovy (about)

     1  import com.sap.piper.DefaultValueCache
     2  import com.sap.piper.Utils
     3  import com.sap.piper.GitUtils
     4  import org.junit.After
     5  import org.junit.Before
     6  import org.junit.Rule
     7  import org.junit.Test
     8  import org.junit.rules.ExpectedException
     9  import org.junit.rules.RuleChain
    10  import org.yaml.snakeyaml.Yaml
    11  import util.BasePiperTest
    12  import util.JenkinsLoggingRule
    13  import util.JenkinsReadFileRule
    14  import util.JenkinsShellCallRule
    15  import util.JenkinsStepRule
    16  import util.JenkinsWriteFileRule
    17  import util.Rules
    18  
    19  import static org.hamcrest.Matchers.is
    20  import static org.junit.Assert.assertEquals
    21  import static org.junit.Assert.assertNotNull
    22  import static org.junit.Assert.assertNull
    23  import static org.junit.Assert.assertThat
    24  
    25  class SetupCommonPipelineEnvironmentTest extends BasePiperTest {
    26  
    27      def usedConfigFile
    28      def pipelineAndTestStashIncludes
    29      def utilsMock
    30  
    31      private JenkinsStepRule stepRule = new JenkinsStepRule(this)
    32      private JenkinsWriteFileRule writeFileRule = new JenkinsWriteFileRule(this)
    33      private ExpectedException thrown = ExpectedException.none()
    34      private JenkinsShellCallRule shellRule = new JenkinsShellCallRule(this)
    35      private JenkinsReadFileRule readFileRule = new JenkinsReadFileRule(this, "./")
    36      private JenkinsLoggingRule loggingRule = new JenkinsLoggingRule(this)
    37  
    38      @Rule
    39      public RuleChain rules = Rules
    40          .getCommonRules(this)
    41          .around(stepRule)
    42          .around(writeFileRule)
    43          .around(thrown)
    44          .around(shellRule)
    45          .around(readFileRule)
    46          .around(loggingRule)
    47  
    48      @Before
    49      void init() {
    50  
    51          def examplePipelineConfig = new File('test/resources/test_pipeline_config.yml').text
    52  
    53          helper.registerAllowedMethod("libraryResource", [String], { fileName ->
    54              switch(fileName) {
    55                  case 'default_pipeline_environment.yml': return "default: 'config'"
    56                  case 'custom.yml': return "custom: 'myConfig'"
    57                  case 'notFound.yml': throw new hudson.AbortException('No such library resource notFound could be found')
    58                  default: return "the:'end'"
    59              }
    60          })
    61  
    62          helper.registerAllowedMethod("readYaml", [Map], { Map parameters ->
    63              Yaml yamlParser = new Yaml()
    64              if (parameters.text) {
    65                  return yamlParser.load(parameters.text)
    66              } else if (parameters.file) {
    67                  switch (parameters.file) {
    68                      case '.pipeline/default_pipeline_environment.yml':
    69                          return [default: 'config']
    70                      case '.pipeline/custom.yml':
    71                          return [custom: 'myConfig']
    72                      case 'pipeline_config.yml':
    73                          usedConfigFile = parameters.file
    74                          return [
    75                              general: [
    76                                  productiveBranch: 'main'
    77                              ],
    78                              steps: [
    79                                  mavenExecute: [
    80                                      dockerImage: 'my-custom-maven-docker']
    81                              ]
    82                          ]
    83                  }
    84              } else {
    85                  throw new IllegalArgumentException("Key 'text' and 'file' are both missing in map ${m}.")
    86              }
    87              usedConfigFile = parameters.file
    88              return yamlParser.load(examplePipelineConfig)
    89          })
    90          utilsMock = newUtilsMock()
    91      }
    92  
    93      Utils newUtilsMock() {
    94          def utilsMock = new Utils()
    95          utilsMock.steps = [
    96              stash  : { Map params -> pipelineAndTestStashIncludes = params.includes },
    97              unstash: {  }
    98          ]
    99          utilsMock.echo = { def m -> }
   100          return utilsMock
   101      }
   102  
   103      @Test
   104      void testIsYamlConfigurationAvailable() throws Exception {
   105  
   106          helper.registerAllowedMethod("fileExists", [String], { String path ->
   107              return path.endsWith('.pipeline/config.yml')
   108          })
   109  
   110          stepRule.step.setupCommonPipelineEnvironment(script: nullScript, utils: utilsMock)
   111  
   112          assertEquals('.pipeline/config.yml', usedConfigFile)
   113          assertNotNull(nullScript.commonPipelineEnvironment.configuration)
   114          assertEquals('develop', nullScript.commonPipelineEnvironment.configuration.general.productiveBranch)
   115          assertEquals('my-maven-docker', nullScript.commonPipelineEnvironment.configuration.steps.mavenExecute.dockerImage)
   116          assertEquals('.pipeline/**', pipelineAndTestStashIncludes)
   117      }
   118  
   119      @Test
   120      void testWorksAlsoWithYamlFileEnding() throws Exception {
   121  
   122          helper.registerAllowedMethod("fileExists", [String], { String path ->
   123              return path.endsWith('.pipeline/config.yaml')
   124          })
   125  
   126          stepRule.step.setupCommonPipelineEnvironment(script: nullScript, utils: utilsMock)
   127  
   128          assertEquals('.pipeline/config.yaml', usedConfigFile)
   129          assertNotNull(nullScript.commonPipelineEnvironment.configuration)
   130          assertEquals('develop', nullScript.commonPipelineEnvironment.configuration.general.productiveBranch)
   131          assertEquals('my-maven-docker', nullScript.commonPipelineEnvironment.configuration.steps.mavenExecute.dockerImage)
   132          assertEquals('.pipeline/**', pipelineAndTestStashIncludes)
   133      }
   134  
   135      @Test
   136      void testWorksAlsoWithCustomConfig() throws Exception {
   137  
   138          helper.registerAllowedMethod("fileExists", [String], { String path ->
   139              return path.endsWith('pipeline_config.yml')
   140          })
   141  
   142          stepRule.step.setupCommonPipelineEnvironment(script: nullScript, utils: utilsMock, configFile: 'pipeline_config.yml')
   143  
   144          assertEquals('pipeline_config.yml', usedConfigFile)
   145          assertNotNull(nullScript.commonPipelineEnvironment.configuration)
   146          assertEquals('main', nullScript.commonPipelineEnvironment.configuration.general.productiveBranch)
   147          assertEquals('my-custom-maven-docker', nullScript.commonPipelineEnvironment.configuration.steps.mavenExecute.dockerImage)
   148          assertEquals('.pipeline/**, pipeline_config.yml', pipelineAndTestStashIncludes)
   149      }
   150  
   151      @Test
   152      void testAttemptToLoadNonExistingConfigFile() {
   153  
   154          helper.registerAllowedMethod("fileExists", [String], { String path ->
   155              switch(path) {
   156                  case 'default_pipeline_environment.yml': return false
   157                  case 'custom.yml': return false
   158                  case 'notFound.yml': return false
   159                  case '': throw new RuntimeException('cannot call fileExists with empty path')
   160                  default: return true
   161              }
   162          })
   163  
   164          helper.registerAllowedMethod("handlePipelineStepErrors", [Map,Closure], { Map map, Closure closure ->
   165              closure()
   166          })
   167  
   168          // Behavior documented here based on reality check
   169          thrown.expect(hudson.AbortException.class)
   170          thrown.expectMessage('No such library resource notFound could be found')
   171  
   172          stepRule.step.setupCommonPipelineEnvironment(
   173              script: nullScript,
   174              utils: utilsMock,
   175              customDefaults: 'notFound.yml'
   176          )
   177      }
   178  
   179      @Test
   180      void testInvalidEntriesInCustomDefaults() {
   181  
   182          helper.registerAllowedMethod("fileExists", [String], { String path ->
   183              switch(path) {
   184                  case 'default_pipeline_environment.yml': return false
   185                  case '': throw new RuntimeException('cannot call fileExists with empty path')
   186                  default: return true
   187              }
   188          })
   189  
   190          helper.registerAllowedMethod("handlePipelineStepErrors", [Map,Closure], { Map map, Closure closure ->
   191              closure()
   192          })
   193  
   194          helper.registerAllowedMethod("readYaml", [Map], { Map parameters ->
   195              Yaml yamlParser = new Yaml()
   196              if (parameters.text) {
   197                  return yamlParser.load(parameters.text)
   198              } else if (parameters.file) {
   199                  if (parameters.file == '.pipeline/config-with-custom-defaults.yml') {
   200                      return [customDefaults: ['', true]]
   201                  }
   202              }
   203              throw new IllegalArgumentException("Unexpected invocation of readYaml step")
   204          })
   205  
   206          stepRule.step.setupCommonPipelineEnvironment(
   207              script: nullScript,
   208              utils: utilsMock,
   209              configFile: '.pipeline/config-with-custom-defaults.yml'
   210          )
   211  
   212          assertEquals('WARNING: Ignoring invalid entry in custom defaults from files: \'\' \n' +
   213              'WARNING: Ignoring invalid entry in custom defaults from files: \'true\' \n', loggingRule.getLog())
   214      }
   215  
   216      @Test
   217      void testAttemptToLoadFileFromURL() {
   218          helper.registerAllowedMethod("fileExists", [String], {String path ->
   219              switch (path) {
   220                  case 'default_pipeline_environment.yml': return false
   221                  case '': throw new RuntimeException('cannot call fileExists with empty path')
   222                  default: return true
   223              }
   224          })
   225  
   226          String customDefaultUrl = "https://url-to-my-config.com/my-config.yml"
   227          boolean urlRequested = false
   228  
   229          helper.registerAllowedMethod("httpRequest", [Map], {Map parameters ->
   230              switch (parameters.url) {
   231                  case customDefaultUrl:
   232                      urlRequested = true
   233                      return [status: 200, content: "custom: 'myRemoteConfig'"]
   234                  default:
   235                      throw new IllegalArgumentException('wrong URL requested')
   236              }
   237          })
   238  
   239          helper.registerAllowedMethod("readYaml", [Map], { Map parameters ->
   240              Yaml yamlParser = new Yaml()
   241              if (parameters.text) {
   242                  return yamlParser.load(parameters.text)
   243              } else if (parameters.file) {
   244                  if (parameters.file == '.pipeline/config-with-custom-defaults.yml') {
   245                      return [customDefaults: "${customDefaultUrl}"]
   246                  }
   247                  if (parameters.file == '.pipeline/custom_default_from_url_0.yml') {
   248                      return [custom: 'myRemoteConfig']
   249                  }
   250              }
   251              throw new IllegalArgumentException("Unexpected invocation of readYaml step")
   252          })
   253  
   254          stepRule.step.setupCommonPipelineEnvironment(
   255              script: nullScript,
   256              utils: utilsMock,
   257              customDefaults: 'custom.yml',
   258              configFile: '.pipeline/config-with-custom-defaults.yml',
   259          )
   260          assertEquals("custom: 'myRemoteConfig'", writeFileRule.files['.pipeline/custom_default_from_url_0.yml'])
   261          assertEquals('myRemoteConfig', DefaultValueCache.instance.defaultValues['custom'])
   262      }
   263  
   264  
   265      @Test
   266      void inferBuildToolMaven() {
   267          helper.registerAllowedMethod('fileExists', [String.class], { s ->
   268              return s == "pom.xml"
   269          })
   270          setupCommonPipelineEnvironment.inferBuildTool(nullScript, [inferBuildTool: true])
   271          assertEquals('maven', nullScript.commonPipelineEnvironment.buildTool)
   272      }
   273  
   274      @Test
   275      void inferBuildToolMTA() {
   276          helper.registerAllowedMethod('fileExists', [String.class], { s ->
   277              return s == "mta.yaml"
   278          })
   279          setupCommonPipelineEnvironment.inferBuildTool(nullScript, [inferBuildTool: true])
   280          assertEquals('mta', nullScript.commonPipelineEnvironment.buildTool)
   281      }
   282  
   283      @Test
   284      void inferBuildToolNpm() {
   285          helper.registerAllowedMethod('fileExists', [String.class], { s ->
   286              return s == "package.json"
   287          })
   288          setupCommonPipelineEnvironment.inferBuildTool(nullScript, [inferBuildTool: true])
   289          assertEquals('npm', nullScript.commonPipelineEnvironment.buildTool)
   290      }
   291  
   292      @Test
   293      void inferBuildToolNone() {
   294          helper.registerAllowedMethod('fileExists', [String.class], { s ->
   295              return false
   296          })
   297          setupCommonPipelineEnvironment.inferBuildTool(nullScript, [inferBuildTool: true])
   298          assertNull(nullScript.commonPipelineEnvironment.buildTool)
   299      }
   300  
   301      @Test
   302      void "Set scmInfo parameter sets commit id"() {
   303  
   304          def GitUtils gitUtils = new GitUtils() {
   305              boolean isMergeCommit(){
   306                  return false
   307              }
   308          }
   309  
   310          helper.registerAllowedMethod("fileExists", [String], { String path ->
   311              return path.endsWith('.pipeline/config.yml')
   312          })
   313  
   314          def dummyScmInfo = [GIT_COMMIT: 'dummy_git_commit_id', GIT_URL: 'https://github.com/testOrg/testRepo.git']
   315  
   316          stepRule.step.setupCommonPipelineEnvironment(script: nullScript, utils: utilsMock, scmInfo: dummyScmInfo, gitUtils: gitUtils)
   317          assertThat(nullScript.commonPipelineEnvironment.gitCommitId, is('dummy_git_commit_id'))
   318      }
   319  
   320      @Test
   321      void "Set scmInfo parameter sets git reference for branch"() {
   322  
   323          def GitUtils gitUtils = new GitUtils() {
   324              boolean isMergeCommit(){
   325                  return false
   326              }
   327          }
   328  
   329          helper.registerAllowedMethod("fileExists", [String], { String path ->
   330              return path.endsWith('.pipeline/config.yml')
   331          })
   332  
   333          def dummyScmInfo = [GIT_COMMIT: 'dummy_git_commit_id', GIT_BRANCH: 'origin/testbranch']
   334  
   335          stepRule.step.setupCommonPipelineEnvironment(script: nullScript, utils: utilsMock, scmInfo: dummyScmInfo, gitUtils: gitUtils)
   336          assertThat(nullScript.commonPipelineEnvironment.gitRef, is('refs/heads/testbranch'))
   337      }
   338  
   339      @Test
   340      void "Set scmInfo parameter sets git reference for branch with slashes in name, origin"() {
   341  
   342          def GitUtils gitUtils = new GitUtils() {
   343              boolean isMergeCommit(){
   344                  return false
   345              }
   346          }
   347  
   348          helper.registerAllowedMethod("fileExists", [String], { String path ->
   349              return path.endsWith('.pipeline/config.yml')
   350          })
   351  
   352          def dummyScmInfo = [GIT_COMMIT: 'dummy_git_commit_id', GIT_BRANCH: 'origin/testbranch/001']
   353  
   354          stepRule.step.setupCommonPipelineEnvironment(script: nullScript, utils: utilsMock, scmInfo: dummyScmInfo, gitUtils: gitUtils)
   355          assertThat(nullScript.commonPipelineEnvironment.gitRef, is('refs/heads/testbranch/001'))
   356      }
   357  
   358      @Test
   359      void "Set scmInfo parameter sets git reference for branch with slashes in name, not origin"() {
   360  
   361          def GitUtils gitUtils = new GitUtils() {
   362              boolean isMergeCommit(){
   363                  return false
   364              }
   365          }
   366  
   367          helper.registerAllowedMethod("fileExists", [String], { String path ->
   368              return path.endsWith('.pipeline/config.yml')
   369          })
   370  
   371          def dummyScmInfo = [GIT_COMMIT: 'dummy_git_commit_id', GIT_BRANCH: 'testbranch/001']
   372  
   373          stepRule.step.setupCommonPipelineEnvironment(script: nullScript, utils: utilsMock, scmInfo: dummyScmInfo, gitUtils: gitUtils)
   374          assertThat(nullScript.commonPipelineEnvironment.gitRef, is('refs/heads/testbranch/001'))
   375      }
   376  
   377      @Test
   378      void "sets gitReference and gitRemoteCommit for pull request, head strategy"() {
   379  
   380          def GitUtils gitUtils = new GitUtils() {
   381              boolean isMergeCommit(){
   382                  return false
   383              }
   384  
   385              String getMergeCommitSha(){
   386                  return "dummy_merge_git_commit_id"
   387              }
   388          }
   389  
   390          helper.registerAllowedMethod("fileExists", [String], { String path ->
   391              return path.endsWith('.pipeline/config.yml')
   392          })
   393  
   394          def dummyScmInfo = [GIT_COMMIT: 'dummy_git_commit_id', GIT_BRANCH: 'PR-42']
   395  
   396          stepRule.step.setupCommonPipelineEnvironment(script: nullScript, utils: utilsMock, scmInfo: dummyScmInfo, gitUtils: gitUtils)
   397          assertThat(nullScript.commonPipelineEnvironment.gitRef, is('refs/pull/42/head'))
   398          assertThat(nullScript.commonPipelineEnvironment.gitRemoteCommitId, is('dummy_git_commit_id'))
   399      }
   400  
   401      @Test
   402      void "sets gitReference and gitRemoteCommit for pull request, merge strategy"() {
   403  
   404          def GitUtils gitUtils = new GitUtils() {
   405              boolean isMergeCommit(){
   406                  return true
   407              }
   408  
   409              String getMergeCommitSha(){
   410                  return "dummy_merge_git_commit_id"
   411              }
   412          }
   413  
   414          helper.registerAllowedMethod("fileExists", [String], { String path ->
   415              return path.endsWith('.pipeline/config.yml')
   416          })
   417  
   418          def dummyScmInfo = [GIT_COMMIT: 'dummy_git_commit_id', GIT_BRANCH: 'PR-42']
   419  
   420          stepRule.step.setupCommonPipelineEnvironment(script: nullScript, utils: utilsMock, scmInfo: dummyScmInfo, gitUtils: gitUtils)
   421          assertThat(nullScript.commonPipelineEnvironment.gitRef, is('refs/pull/42/merge'))
   422          assertThat(nullScript.commonPipelineEnvironment.gitRemoteCommitId, is('dummy_merge_git_commit_id'))
   423      }
   424  
   425      @Test
   426      void "Set merge commit id as NA on exception"() {
   427  
   428          def GitUtils gitUtils = new GitUtils() {
   429              boolean isMergeCommit(){
   430                  return true
   431              }
   432  
   433              String getMergeCommitSha() throws MissingPropertyException{
   434                  throw new MissingPropertyException('pullRequest Context not found')
   435              }
   436          }
   437  
   438          helper.registerAllowedMethod("fileExists", [String], { String path ->
   439              return path.endsWith('.pipeline/config.yml')
   440          })
   441  
   442          def dummyScmInfo = [GIT_COMMIT: 'dummy_git_commit_id', GIT_BRANCH: 'PR-42']
   443  
   444          stepRule.step.setupCommonPipelineEnvironment(script: nullScript, utils: utilsMock, scmInfo: dummyScmInfo, gitUtils: gitUtils)
   445          assertThat(nullScript.commonPipelineEnvironment.gitRef, is('refs/pull/42/merge'))
   446          assertThat(nullScript.commonPipelineEnvironment.gitRemoteCommitId, is('NA'))
   447      }
   448  
   449      @Test
   450      void "No scmInfo passed as parameter yields empty git info"() {
   451          helper.registerAllowedMethod("fileExists", [String], { String path ->
   452              return path.endsWith('.pipeline/config.yml')
   453          })
   454  
   455          stepRule.step.setupCommonPipelineEnvironment(script: nullScript, utils: utilsMock)
   456          assertNull(nullScript.commonPipelineEnvironment.gitCommitId)
   457          assertNull(nullScript.commonPipelineEnvironment.getGitSshUrl())
   458          assertNull(nullScript.commonPipelineEnvironment.getGitHttpsUrl())
   459          assertNull(nullScript.commonPipelineEnvironment.getGithubOrg())
   460          assertNull(nullScript.commonPipelineEnvironment.getGithubRepo())
   461          assertNull(nullScript.commonPipelineEnvironment.getGitRef())
   462      }
   463  
   464      @Test
   465      void testSetScmInfoOnCommonPipelineEnvironment() {
   466          //currently supported formats
   467          def scmInfoTestList = [
   468              [GIT_URL: 'https://github.com/testOrg/testRepo.git', expectedSsh: 'git@github.com:testOrg/testRepo.git', expectedHttp: 'https://github.com/testOrg/testRepo.git', expectedOrg: 'testOrg', expectedRepo: 'testRepo'],
   469              [GIT_URL: 'https://github.com:7777/testOrg/testRepo.git', expectedSsh: 'git@github.com:testOrg/testRepo.git', expectedHttp: 'https://github.com:7777/testOrg/testRepo.git', expectedOrg: 'testOrg', expectedRepo: 'testRepo'],
   470              [GIT_URL: 'git@github.com:testOrg/testRepo.git', expectedSsh: 'git@github.com:testOrg/testRepo.git', expectedHttp: 'https://github.com/testOrg/testRepo.git', expectedOrg: 'testOrg', expectedRepo: 'testRepo'],
   471              [GIT_URL: 'ssh://git@github.com/testOrg/testRepo.git', expectedSsh: 'ssh://git@github.com/testOrg/testRepo.git', expectedHttp: 'https://github.com/testOrg/testRepo.git', expectedOrg: 'testOrg', expectedRepo: 'testRepo'],
   472              [GIT_URL: 'ssh://git@github.com:7777/testOrg/testRepo.git', expectedSsh: 'ssh://git@github.com:7777/testOrg/testRepo.git', expectedHttp: 'https://github.com/testOrg/testRepo.git', expectedOrg: 'testOrg', expectedRepo: 'testRepo'],
   473              [GIT_URL: 'ssh://git@github.com/path/to/testOrg/testRepo.git', expectedSsh: 'ssh://git@github.com/path/to/testOrg/testRepo.git', expectedHttp: 'https://github.com/path/to/testOrg/testRepo.git', expectedOrg: 'path/to/testOrg', expectedRepo: 'testRepo'],
   474              [GIT_URL: 'ssh://git@github.com/path/testOrg/testRepo.git', expectedSsh: 'ssh://git@github.com/path/testOrg/testRepo.git', expectedHttp: 'https://github.com/path/testOrg/testRepo.git', expectedOrg: 'path/testOrg', expectedRepo: 'testRepo'],
   475              [GIT_URL: 'ssh://git@github.com/testRepo.git', expectedSsh: 'ssh://git@github.com/testRepo.git', expectedHttp: 'https://github.com/testRepo.git', expectedOrg: 'N/A', expectedRepo: 'testRepo'],
   476          ]
   477  
   478          scmInfoTestList.each {scmInfoTest ->
   479              stepRule.step.setupCommonPipelineEnvironment.setGitUrlsOnCommonPipelineEnvironment(nullScript, scmInfoTest.GIT_URL)
   480              assertThat(nullScript.commonPipelineEnvironment.getGitSshUrl(), is(scmInfoTest.expectedSsh))
   481              assertThat(nullScript.commonPipelineEnvironment.getGitHttpsUrl(), is(scmInfoTest.expectedHttp))
   482              assertThat(nullScript.commonPipelineEnvironment.getGithubOrg(), is(scmInfoTest.expectedOrg))
   483              assertThat(nullScript.commonPipelineEnvironment.getGithubRepo(), is(scmInfoTest.expectedRepo))
   484          }
   485      }
   486  }