How to get the git latest commit message and prevent the jenkins build if the commit message contains [ci skip]?
Asked Answered
D

5

28

I tried to get the git commit message in jenkinsfile and prevent the build based on commit message.

env.GIT_COMMIT doesn't return the commit details in jenkinsfile.

How to get the git latest commit message and prevent the jenkins build if the commit message contains [ci skip] in it?

Dud answered 14/12, 2016 at 10:28 Comment(3)
try sh "git log -1" and grep the relevant text.Hogue
@Amityo: Thanks it really helpful. I need one more query... how to prevent jenkins build in jenkinsfile, if the message contains [ci skip] content?Dud
issue has been created to provide GIT_COMMIT_MESSAGE you can vote to get it soon issues.jenkins-ci.org/browse/JENKINS-52490Rackrent
A
24

I had the same issue. I'm using pipelines. I solved this issue by implementing a shared library.

The code of the library is this:

// vars/ciSkip.groovy

def call(Map args) {
    if (args.action == 'check') {
        return check()
    }
    if (args.action == 'postProcess') {
        return postProcess()
    }
    error 'ciSkip has been called without valid arguments'
}

def check() {
    env.CI_SKIP = "false"
    result = sh (script: "git log -1 | grep '.*\\[ci skip\\].*'", returnStatus: true)
    if (result == 0) {
        env.CI_SKIP = "true"
        error "'[ci skip]' found in git commit message. Aborting."
    }
}

def postProcess() {
    if (env.CI_SKIP == "true") {
        currentBuild.result = 'NOT_BUILT'
    }
}

Then, in my Jenkinsfile:

pipeline {
  stages {
    stage('prepare') { steps { ciSkip action: 'check' } }
    // other stages here ...
  }
  post { always { ciSkip action: 'postProcess' } }
}

As you can see, the build is marked as NOT_BUILT. You can change it to ABORTED if you prefer, but it cannot be set to SUCCESS because a build result can only get worse

Aglaia answered 30/8, 2017 at 19:17 Comment(0)
H
19

The build will pass when [ci skip] is provided in the last git log, but will not run the actual build code (the replacement to the first echo statement)

node {
  checkout scm
  result = sh (script: "git log -1 | grep '\\[ci skip\\]'", returnStatus: true) 
  if (result != 0) {
    echo "performing build..."
  } else {
    echo "not running..."
  }
}
Hogue answered 15/12, 2016 at 10:25 Comment(1)
For more info on how to use sh: issues.jenkins-ci.org/browse/JENKINS-26133Pelotas
K
13

As for declarative pipeline one can use 'changelog' in 'when' directive to skip a stage:

when {
    not {
    changelog '.*^\\[ci skip\\] .+$'
    }
}

See: https://jenkins.io/doc/book/pipeline/syntax/#when

Kelda answered 6/6, 2019 at 18:53 Comment(6)
'^.*\[ci skip\].*$' or '.*\[ci skip\].*' may make more senseFerde
This won't work for 1st build as it would not have any changelogZiwot
Is there some way to limit this to the most recent commit message? Having tested this if the most recent commit message does not match, but the previous commit does this still skips.Progesterone
@Thor84no I have verified what you've reported as well. Unfortunately the changelog inside when does match more than just the latest commit message :-(Commit
I just tried this with Jenkins 2.303.3, and it works just fine. It did not look at previous commits.Septilateral
FWIW, this feature was created by this PR: github.com/jenkinsci/pipeline-model-definition-plugin/pull/178Septilateral
I
8

I think you could easily do that in multi branch pipeline job configuration Branch Sources > Additional Behaviours > Polling ignores commits with certain messages multi branch pipeline job configuration

Iyeyasu answered 15/12, 2016 at 13:2 Comment(3)
When using this approach, $CHANGE_ID is not available in the Jenkinsfile.Boggle
@Iyeyasu is this option available for multibranch as i am unable to find it?Rackrent
Do you have an updated version of this? It seems the "Advanced Behaviors" is no longer avaiable in the branch sources section in 2021. You can add behaviors, but none of the options seem to be related to commit messages. Any ideas?Cloverleaf
J
6

As of today, it's quite easy to achieve. The interesting line is the extension named MessageExclusion where excludedMessage accepts a regular expression.

checkout([ $class: 'GitSCM', 
  branches: [[name: '*/master']], 
  doGenerateSubmoduleConfigurations: false, 
  extensions: [[
    $class: 'MessageExclusion', excludedMessage: '.*skip-?ci.*'
  ]], 
  submoduleCfg: [], 
  userRemoteConfigs: [[
    credentialsId: 'xxx', url: '[email protected]:$ORG/$REPO.git'
  ]]
])
Jokester answered 5/6, 2018 at 18:57 Comment(2)
Are those built-in classes?Paulson
Interesting situation that I observe when using this; I'm unable to use git from within my Docker build. Not sure what one has to do with the other yet, but if I use the plain old 'checkout scm', it works. If I use this method, it doesn't.Paulson

© 2022 - 2024 — McMap. All rights reserved.