Home > Mobile >  Jenkins: Modify the ChangeSet List to have changes since last successful build
Jenkins: Modify the ChangeSet List to have changes since last successful build

Time:07-12

I'm looking for a way to modify the changeset list in Jenkins to list all changes since last successful build instead of since last build regardless of the status.

Is there a way to do this for multibranch pipelines?

I need it to be in my changeSet because I need the jira plugin to pick up all those commits

This is what I have so far

@NonCPS
    def commitHashForBuild(build) {
      def scmAction = build?.actions.find { action -> action instanceof jenkins.scm.api.SCMRevisionAction }
      return scmAction?.revision?.hash
    }
    def getLastSuccessfulCommit() {
      def lastSuccessfulHash = null
      def lastSuccessfulBuild = currentBuild.rawBuild.getPreviousSuccessfulBuild()
      if ( lastSuccessfulBuild ) {
        lastSuccessfulHash = commitHashForBuild(lastSuccessfulBuild)
      }
      return lastSuccessfulHash 
    }
    def modifyChangeSets(commits){
        currentBuild.rawBuild.changeSets = commits
    }
    
    def call(Map config) {
        def lastSuccessfulCommit = getLastSuccessfulCommit()
        def currentCommit = commitHashForBuild(currentBuild.rawBuild)
        commits = sh(script: "git rev-list $currentCommit \"^$lastSuccessfulCommit\" --pretty=oneline --abbrev-commit  ", returnStdout: true).trim().split('\n').collect{it}
           
    
        modifyChangeSets(commits)
    }

There is no error in the console, but the changelist doesn't get generated at all and it breaks the status UI screen

CodePudding user response:

You can use the following Groovy code to get the changeSets from the last successful build.

def allChangeSetsFromLastSuccessfulBuild() {
    def job = Jenkins.instance.getItem("$JOB_NAME")
    def lastSuccessBuild = job.lastSuccessfulBuild.number as int
    def currentBuildId = "$BUILD_ID" as int
    
    def changeSets = []

    for(int i = lastSuccessBuild   1; i < currentBuildId; i  ) {
        echo "Getting Change Set for the Build ID : ${i}"
        def chageSet = job.getBuildByNumber(i).getChangeSets()
        changeSets.addAll(chageSet)
    }
     changeSets.addAll(currentBuild.changeSets) // Add the current Changeset
     return changeSets
}

Full Pipeline Example

The function getFilesChanged will return the list of files changed in all change sets.

pipeline {
    agent any
    stages {
        stage('Build') {
            steps {
                git (url: 'https://github.com/xxx/sample.git', branch: 'main')
                script {
                    def changeSets = allChangeSetsFromLastSuccessfulBuild()
                    echo "ChangeSet Size : ${changeSets.size()}"
                    echo "Files Changed : ${getFilesChanged(changeSets)}"
                }
            }
        }
    }
}

def allChangeSetsFromLastSuccessfulBuild() {
    def job = Jenkins.instance.getItem("$JOB_NAME")
    def lastSuccessBuild = job.lastSuccessfulBuild.number as int
    def currentBuildId = "$BUILD_ID" as int
    
    def changeSets = []

    for(int i = lastSuccessBuild   1; i < currentBuildId; i  ) {
        echo "Getting Change Set for the Build ID : ${i}"
        def chageSet = job.getBuildByNumber(i).getChangeSets()
        changeSets.addAll(chageSet)
    }
     changeSets.addAll(currentBuild.changeSets) // Add the current Changeset
     return changeSets
}

def getFilesChanged(chgSets) {
    def filesList = []
    def changeLogSets = chgSets
        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
}
  • Related