简体   繁体   中英

Jenkins - Commit an update in the PR build

I have a jenkins job for my puppet stuff and really all those jobs do are validation and deployment to puppet. The question I have is that as part of that build I'd like to force an update via bundle which will update the puppetfile which needs to then be checked in as part of that PR.

One of the concerns I have is that the commit to the PR will end up triggering another build, which will trigger another update... so on and so forth.

The only thing I was able to find in regards to this was that you can control to some extent how the jobs run (restart/stop and new from new commits) but those seem to be blanket settings and not specific to the job instance and no way that I could find via the pipeline stuff to control that.

I have to imagine this is something that people do and that there is a method to this but my google foo is failing or I'm searching on the wrong terms.

Also, if it matters we're using github enterprise onsite.

Disclaimer : There might be a better way than what I am about to describe (it seems heavy handed) but we also found the built-in Jenkins exclusion settings insufficient. Primarily because it only applied to triggered builds not scheduled Multi-branch pipeline scans. Also this only applies to Pipeline Groovy DSL jobs; not to freestyle jobs or declarative Pipeline jobs.

Summary

Best explained in pseudocode

if git changed files since last run == 0 then
  no need to change puppetfile
  end build
endif

if 1 file changed and it is puppetfile then
  if the contents of the change is just the auto-changed puppetfile stuff
    no need to change puppetfile again
    end build
  endif
endif

if we get here then more stuff changed so do the auto-change puppetfile stuff

Details

For a concrete implementation I will use a Javascript project's package.json as an example but it's exactly the same situation as the puppetfile . Just replace package.json with puppetfile and version: with whatever content change you auto-generate that should not trigger another build.

First we need some utility methods:

/**
 * Utility method to run git and handle splitting its output
 */
def git( command ) {
  def output = []
  outputRaw = sh(
    script: "git $command",
    returnStdout: true
  )
  if ( !outputRaw.empty ) {
    output = outputRaw.split('\n')
  }
  return output
}

/**
 * The names of files changed since the last successful build
 */
def getFilesChangedSinceLastSuccessfulBuild() {
  def filesChanged = []
  if (lastSuccessfulCommit) {
    filesChanged = git "diff --name-only $currentCommit '^$lastSuccessfulCommit'"
  }
  echo "DEBUG: Files changed $filesChanged (size ${filesChanged.size()})"
  return filesChanged
}

/**
 * Get changes as a list without context
 */
def getContextFreeChanges() {
  def contentsChanged = []
  if (lastSuccessfulCommit) {
    contentsChanged = git "diff --unified=0 $lastSuccessfulCommit $currentCommit | egrep '^\\+ ' || exit 0"
  }
  echo "DEBUG: Contents changed: $contentsChanged (size ${contentsChanged.size()})"
  return contentsChanged

}

Then we take those and create needToBumpVersion() (rename as appropriate) which ties it all together to figure out of any auto-generate changes need to happen:

/**
 * Do we need to actually increment version in package.json
 */
def needToBumpVersion() {
  def filesChanged = getFilesChangedSinceLastSuccessfulBuild()
  if (filesChanged.size() == 0) {
    echo "INFO: No files changed, no need to bump version"
    return false
  }
  if (filesChanged.size() == 1 && filesChanged[0] == 'package.json') {
    def contentsChanged = getContextFreeChanges()
    if (contentsChanged.size() == 1 && contentsChanged[0] =~ /"version":/) {
      echo "INFO: Don't need to bump version, it has already been done"
      return false
    }
  }
  echo "INFO: We do need to bump the version, more than just package.json version string changed"
  return true
}

and finally you can then use this method to figure out whether to make the auto-generated changes and commit them:

if (needToBumpVersion()) {
  // Do bump here
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM