Search code examples
jenkinsgroovycontinuous-integrationjenkins-pipelinejenkins-groovy

Jenkins CI/CD for Helm Package and cm-push


At present I'm having 20+ Helm chart in a single GitLab repo and I want to do Jenkins ci/cd like, when I changes any resource files in the Helm chart and push it to git. A job should be run for that particular folder and do helm package and helm cm-push of that folder name.

I want to create a Jenkins pipeline such a way that it should fetch the folder name in which files are changed from commit and use the folder name as a variable in Helm package and helm cm-push cmd

Note: There will be change's in multiple folders or 2 or 3 folders in a single "Commit" So Jobs should fetch the folder's name and run Job in series One by one Making folder names as a Variable one by one. (in-loop)

I have found this Script but this Script in fetching File names from Git commit I try to setup this script in my CI/CD but It does not work according to my needs. AND, One more thing this script fetch file name and if a single folder contain 2 file changes it will show 2 like this

 [node-app/Chart.yaml, node-app-backend/configmap.yaml, node-app-backend/deployment.yaml]

but in our case it should be fetch folder name and count as a single folder and run job one time for common or same name folder

pipeline {
agent any
stages { 
    stage('clone') {
            steps {
                  git branch: 'main', url: 'https://github.com/xxx/sample.git'
            }
    }
    stage('build') {
            steps {
                script {
                      println(getFilesChanged())
                      // Do your cleanup here and then execute the SH block
                }
            }
    }
 }
}

def getFilesChanged() {
  def filesList = []
  def changeLogSets = currentBuild.changeSets
                  for (int i = 0; i < changeLogSets.size(); i++) {
                      def entries = changeLogSets[i].items
                      for (int j = 0; j < entries.length; j++) {
                          def entry = entries[j]
                          def files = new ArrayList(entry.affectedFiles)
                              for (int k = 0; k < files.size(); k++) {
                              def file = files[k]
                              filesList.add(file.path)
              } 
          }
      }
  return filesList
}

Solution

  • You can filter the fileList to just have the unique folders. Something like below.

    fileList.collect {entry -> return entry.split('/')[0]}.unique()
    

    Full function

    def getFilesChanged() {
      def filesList = []
      def changeLogSets = currentBuild.changeSets
                      for (int i = 0; i < changeLogSets.size(); i++) {
                          def entries = changeLogSets[i].items
                          for (int j = 0; j < entries.length; j++) {
                              def entry = entries[j]
                              def files = new ArrayList(entry.affectedFiles)
                                  for (int k = 0; k < files.size(); k++) {
                                  def file = files[k]
                                  filesList.add(file.path)
                  } 
              }
          }
      return filesList.collect {entry -> return entry.split('/')[0]}.unique()
    }
    

    Note: The above code assumes you don't have any files in the root directory and if not changes will not be made in those files. Otherwise, you may have to handle that case as well.