<p>You might try installing the <a href="https://plugins.jenkins.io/github-pullrequest/" rel="nofollow noreferrer">GitHub Integration</a> plugin. Reading <a href="https://github.com/KostyaSha/github-integration-plugin/blob/master/docs/Configuration.adoc" rel="nofollow noreferrer">their documentation</a>, they provide a number of environment variables you can use for your purpose.</p>

<ol>
<li><code>GITHUB_PR_STATE</code> can be <code>OPEN</code>, <code>CLOSE</code></li>
<li><code>GITHUB_PR_SOURCE_BRANCH</code> for the source branch (e.g., <code>hotfix/foo</code>)</li>
<li><code>GITHUB_PR_TARGET_BRANCH</code> or <code>master</code></li>
</ol>

<p>Using the when condition, you can run a job/stage when it's a closed PR merging into the <code>master</code> branch using:</p>

<pre><code>when { 
  allOf { 
    expression { env.GITHUB_PR_STATE == "CLOSE" }
    expression { env.GITHUB_PR_TARGET_BRANCH == "master" }
    expression { env.GITHUB_PR_SOURCE_BRANCH == "hotfix/foo" }
  } 
}
</code></pre>

CC BY-SA 4.0
2020-06-16T15:32:42.020Z
Thanks, but this only shows the env vars of a PR 'branch', ie the job that's created when you pull a PR. As I mentioned i know how to find the values of the source/target branch. What i'm looking for is some way to tell if the `master` build that's happening is a result of a PR merge/closure, or just a regular ol' push to master (which is discouraged, but could happen - in which case I don't want to tag).

I've tried to use `currentBuild.getBuildCauses()` but it only shows "push even to master", which i think applies to _any_ merge to master. I'm only looking for PR merges.
Max Cascone
CC BY-SA 4.0
2020-06-16T17:16:01.600Z
Just wanted to clarify something before I provide another possible solution -- checking that the `env.GITHUB_PR_STATE` is `CLOSE` is not sufficient to detect that's it's a closed PR?
Argyle
CC BY-SA 4.0
2020-06-16T17:20:22.420Z
Can you try including the following line in your pipeline: `def build_cause = JSONArray.toList(currentBuild.getBuildCauses())` What is the value of `build_cause._class[0]` when the job is triggered from GitHub?
Argyle
CC BY-SA 4.0
2020-06-27T04:17:34.563Z
i'm sorry i haven't done exactly this yet but i can tell you from the json of the build, that the PR build contains `"actions": [
{
"_class": "hudson.model.CauseAction",
"causes": [
{
"_class": "jenkins.branch.BranchEventCause",
"shortDescription": "Pull request #27 updated"
}
]`, but the branch build only has `"actions": [
{
"_class": "hudson.model.CauseAction",
"causes": [
{
"_class": "jenkins.branch.BranchEventCause",
"shortDescription": "Push event to branch PLATDEV-6356-pipe-template-2"
}
]
},`  These are the same as shown at the very top of the build console output.
Max Cascone
CC BY-SA 4.0
2021-01-07T11:18:42.333Z
Late to the discussion, have you solved this? What about checking the number of parents of the current commit in git? This assumes any direct push to master contains only commits directly committed to master. Don't know if this is easy to check from a Jenkins pipeline, though.
José González
CC BY-SA 4.0
2020-06-16T08:55:45.223Z
2020-06-16T08:55:45.223Z
Argyle
<p>I've solved this!</p>
<p>I can't find the stackoverflow question that helped me, but they gave me the idea.</p>
<p><code>git log --format=format:%s -1</code></p>
<p>Specifically, I have a bash file that does the following as part of my jenkins pipeline.</p>
<p><code>echo &quot;COMMIT MESSAGE&quot; `git log --format=format:%s -1`;</code></p>
<p>In my PR build, it prints the following:</p>
<p><code>2021-10-07 12:56:43  COMMIT MESSAGE prints</code></p>
<p>In the master build, it prints the following:</p>
<p><code>2021-10-07 12:58:11  COMMIT MESSAGE more print statements (#1948)</code></p>
<p>And then you can use some bash kung fu to do what you need to do from there!</p>
<p>I noticed this when manually scanning the JSON payload that GitHub sends to Jenkins and noticed that GitHub was adding the PR # at the tail end of the git commit message (but only for master for some reason).</p>

CC BY-SA 4.0
2021-10-07T17:03:10.417Z
2021-10-07T17:03:10.417Z
Daniel Wyleczuk-Stern
<p>You are not building the wrong thing this is a topic that is coming up more and more frequently as people create more and more advanced pipelines. You can see people discussing the need for it <a href="https://github.com/jenkinsci/ghprb-plugin/issues/651" rel="nofollow noreferrer">here</a>.</p>
<p>The reason is doesn't come up a ton is most people can just trigger their tag job on any change to master. Which is much simpler to setup. I often want to tear down something like a environment when a new feature is merged.</p>
<p>Pretty much your best bet is too follow this <a href="https://bit-basics-backup.netlify.app/2019/september/jenkins-job-github-pullrequest/" rel="nofollow noreferrer">guide</a>. Basically you use the <a href="https://plugins.jenkins.io/generic-webhook-trigger/" rel="nofollow noreferrer">generic-webhook-trigger</a> plugin. It allows you to extract parts of a JSON payload into environment variables injected into the job. Once you have done that you just follow <a href="https://devops.stackexchange.com/a/11828/4427">Argyle's</a> answer.</p>

CC BY-SA 4.0
2021-09-21T15:56:10.857Z
I wish I could explain how good it feels to hear "you are not building the wrong thing."  I have evolved away from this particular use case but it is nice to hear.
Max Cascone
CC BY-SA 4.0
2021-06-14T20:26:42.347Z
2021-06-14T20:26:42.347Z
Levi
<p>Check if the <a href="https://plugins.jenkins.io/git/#commit-variables" rel="nofollow noreferrer">GIT_COMMIT</a> is a merge commit using <a href="https://stackoverflow.com/a/64080225/150884"><code>git rev-parse</code></a>:</p>
<pre class="lang-java prettyprint-override"><code>when {
  branch 'master'
  expression {
    isMergeCommit(env.GIT_COMMIT)
  }
}

def isMergeCommit(String commit) {
  isSimpleCommit = sh(returnStdout: true,
      script: &quot;set +e; git rev-parse --verify -q $commit^2 &gt; /dev/null; echo \$?&quot;).trim()
  return isSimpleCommit == &quot;0&quot;
}
</code></pre>
<p><a href="https://www.jenkins.io/doc/pipeline/steps/workflow-durable-task-step/#sh-shell-script" rel="nofollow noreferrer"><code>set +e</code> is needed</a> because the script returns a non-zero exit code if the commit is a simple (non-merge) commit.</p>

CC BY-SA 4.0
2021-09-17T04:33:55.140Z
This is interesting, but is there a way to figure out which branch it was merged from? I am using the former branch name to create an environment and I need the branch name again to spin it back down upon deletion.
justin.m.chase
CC BY-SA 4.0
2021-06-14T12:30:42.403Z
2021-06-14T12:30:42.403Z
hertzsprung
<p>Wow, this has garnered a ton of views. For what it's worth, I've ended up building a much simpler solution since I posted this.</p>
<p>Ultimately, we've stopped using PRs for much of anything pipeline-related other than build success. It's just too complicated to get data out of them reliably, and there's too much hand-waving and magic happening for the average developer who's not inside this stuff all day to really <em>get</em> it.
In fact, I am able to identify PR branches at a basic level by checking for <code>env.CHANGE_ID != null</code>, and just skip wholesale or hardcode a lot of stuff that's not important to us for PRs, like versioning and archiving. I can always come back to it later if we decide we want to actually use the PR builds for anything.</p>
<p>What we have currently is a process implementing basic Semantic Versioning, where we only tag on <code>develop</code> builds, <code>develop</code> being our de-facto mainline. We don't do a great job of merging to <code>master</code> after releases, but we are pretty solid on always only deploying from <code>develop</code>. (Why keep <code>main</code> around, then? We ask ourselves that often. It comes down to priorities of process changes; it's not really hurting anything to have it, so we focus on other stuff.)</p>
<p>I recently integrated <a href="https://gitversion.net" rel="nofollow noreferrer">gitversion</a> into the pipe, and have it configured to automatically bump the <code>PATCH</code> version on any commit-build to <code>develop</code>. If a bump of <code>MINOR</code> or <code>MAJOR</code> is required, the <a href="https://gitversion.net/docs/reference/version-increments?Manually-incrementing-the-version" rel="nofollow noreferrer">commit-message phrases</a> can be used.</p>
<p>Gitversion is nice because it removes the need for a file in the repo to be updated manually; it's based entirely on <code>git tags</code> and commits. It even updates the <code>assembly*.cs</code> etc files in the repo automatically. The downside is it took me quite a while to feel like I understood it well enough to use it; its configurability makes it complicated to grok at first. There are other tools out there that do the same thing, this is the one that was suggested to me and the docs made me comfortable enough to jump into it.</p>

CC BY-SA 4.0
2021-09-21T15:54:39.490Z
2021-09-21T15:54:39.490Z
Max Cascone
<p>I think i've scoured every post on this topic but haven't found my specific scenario. (Maybe that means I'm building the wrong thing OR i've built something unique and new? The former is far more likely) </p>

<p>I have a multibranch pipeline in Jenkins being triggered by webhooks from GitHub. I want to automatically tag the repo being built only when a PR from <code>develop|release|hotfix</code> branches are closed and merged to <code>master</code>. </p>

<p>What I want to drill in on is how to identify when a <code>master</code> branch build is triggered by the merge from a PR, and not from anything else. I <em>don't</em> want to tag if <code>master</code> builds due to a non-PR merge. (This would allow updating readmes and code comments without generating a new tag.)</p>

<p>I'm getting the tag string from a file in the repo, and I know how to use the PR builder to identify the source and target of a pull request for <code>when</code> conditions. I know how to get the JSON build information and pull data out, but what I want doesn't seem to be there. </p>

<p><code>when { changeRequest target: 'master' }</code> only identifies the PR build, not the <code>master</code> build that results when the PR is closed and merged. </p>

<p><code>when { branch 'master' }</code> obviously identifies a <code>master</code> branch build, but how can I limit it to only build when the build is triggered the merge from a closed PR?</p>

<jenkins><github>
How to determine if a Jenkins build is triggered by a Pull Request merged to Master
Max Cascone
# How to determine if a Jenkins build is triggered by a Pull Request merged to Master

(Asked by: username_0 on 2020-06-16)

I think i've scoured every post on this topic but haven't found my specific scenario. (Maybe that means I'm building the wrong thing OR i've built something unique and new? The former is far more likely)

I have a multibranch pipeline in Jenkins being triggered by webhooks from GitHub. I want to automatically tag the repo being built only when a PR from `develop|release|hotfix` branches are closed and merged to `master`.

What I want to drill in on is how to identify when a `master` branch build is triggered by the merge from a PR, and not from anything else. I *don't* want to tag if `master` builds due to a non-PR merge. (This would allow updating readmes and code comments without generating a new tag.)

I'm getting the tag string from a file in the repo, and I know how to use the PR builder to identify the source and target of a pull request for `when` conditions. I know how to get the JSON build information and pull data out, but what I want doesn't seem to be there.

`when { changeRequest target: 'master' }` only identifies the PR build, not the `master` build that results when the PR is closed and merged.

`when { branch 'master' }` obviously identifies a `master` branch build, but how can I limit it to only build when the build is triggered the merge from a closed PR?

**Tags:** jenkins, github


---

## 5 answers

### Answer by username_1 on 2020-06-16. Score: 3

You might try installing the GitHub Integration plugin. Reading their documentation, they provide a number of environment variables you can use for your purpose.

GITHUB_PR_STATE can be OPEN, CLOSE
GITHUB_PR_SOURCE_BRANCH for the source branch (e.g., hotfix/foo)
GITHUB_PR_TARGET_BRANCH or master

Using the when condition, you can run a job/stage when it's a closed PR merging into the master branch using:
when { 
  allOf { 
    expression { env.GITHUB_PR_STATE == "CLOSE" }
    expression { env.GITHUB_PR_TARGET_BRANCH == "master" }
    expression { env.GITHUB_PR_SOURCE_BRANCH == "hotfix/foo" }
  } 
}

> **Comments:**
> **username_0**: Thanks, but this only shows the env vars of a PR 'branch', ie the job that's created when you pull a PR. As I mentioned i know how to find the values of the source/target branch. What i'm looking for is some way to tell if the `master` build that's happening is a result of a PR merge/closure, or just a regular ol' push to master (which is discouraged, but could happen - in which case I don't want to tag).  I've tried to use `currentBuild.getBuildCauses()` but it only shows "push even to master", which i think applies to _any_ merge to master. I'm only looking for PR merges.  
> **username_1**: Just wanted to clarify something before I provide another possible solution -- checking that the `env.GITHUB_PR_STATE` is `CLOSE` is not sufficient to detect that's it's a closed PR?  
> **username_1**: Can you try including the following line in your pipeline: `def build_cause = JSONArray.toList(currentBuild.getBuildCauses())` What is the value of `build_cause._class[0]` when the job is triggered from GitHub?  
> **username_0**: i'm sorry i haven't done exactly this yet but i can tell you from the json of the build, that the PR build contains `"actions": [ { "_class": "hudson.model.CauseAction", "causes": [ { "_class": "jenkins.branch.BranchEventCause", "shortDescription": "Pull request #27 updated" } ]`, but the branch build only has `"actions": [ { "_class": "hudson.model.CauseAction", "causes": [ { "_class": "jenkins.branch.BranchEventCause", "shortDescription": "Push event to branch PLATDEV-6356-pipe-template-2" } ] },`  These are the same as shown at the very top of the build console output.  
> **username_2**: Late to the discussion, have you solved this? What about checking the number of parents of the current commit in git? This assumes any direct push to master contains only commits directly committed to master. Don't know if this is easy to check from a Jenkins pipeline, though.  

---

### Answer by username_3 on 2021-10-07. Score: 2

I've solved this!

I can't find the stackoverflow question that helped me, but they gave me the idea.

`git log --format=format:%s -1`

Specifically, I have a bash file that does the following as part of my jenkins pipeline.

`echo "COMMIT MESSAGE" `git log --format=format:%s -1`;`

In my PR build, it prints the following:

`2021-10-07 12:56:43 COMMIT MESSAGE prints`

In the master build, it prints the following:

`2021-10-07 12:58:11 COMMIT MESSAGE more print statements (#1948)`

And then you can use some bash kung fu to do what you need to do from there!

I noticed this when manually scanning the JSON payload that GitHub sends to Jenkins and noticed that GitHub was adding the PR # at the tail end of the git commit message (but only for master for some reason).


---

### Answer by username_4 on 2021-06-14. Score: 1

You are not building the wrong thing this is a topic that is coming up more and more frequently as people create more and more advanced pipelines. You can see people discussing the need for it [here](https://github.com/jenkinsci/ghprb-plugin/issues/651).

The reason is doesn't come up a ton is most people can just trigger their tag job on any change to master. Which is much simpler to setup. I often want to tear down something like a environment when a new feature is merged.

Pretty much your best bet is too follow this [guide](https://bit-basics-backup.netlify.app/2019/september/jenkins-job-github-pullrequest/). Basically you use the [generic-webhook-trigger](https://plugins.jenkins.io/generic-webhook-trigger/) plugin. It allows you to extract parts of a JSON payload into environment variables injected into the job. Once you have done that you just follow [username_1's](https://devops.stackexchange.com/a/11828/4427) answer.

> **Comments:**
> **username_0**: I wish I could explain how good it feels to hear "you are not building the wrong thing."  I have evolved away from this particular use case but it is nice to hear.  

---

### Answer by username_5 on 2021-06-14. Score: 0

Check if the GIT_COMMIT is a merge commit using git rev-parse:
when {
  branch 'master'
  expression {
    isMergeCommit(env.GIT_COMMIT)
  }
}

def isMergeCommit(String commit) {
  isSimpleCommit = sh(returnStdout: true,
      script: "set +e; git rev-parse --verify -q $commit^2 > /dev/null; echo \$?").trim()
  return isSimpleCommit == "0"
}

set +e is needed because the script returns a non-zero exit code if the commit is a simple (non-merge) commit.

> **Comments:**
> **username_6**: This is interesting, but is there a way to figure out which branch it was merged from? I am using the former branch name to create an environment and I need the branch name again to spin it back down upon deletion.  

---

### Answer by username_0 on 2021-09-21. Score: 0

Wow, this has garnered a ton of views. For what it's worth, I've ended up building a much simpler solution since I posted this.

Ultimately, we've stopped using PRs for much of anything pipeline-related other than build success. It's just too complicated to get data out of them reliably, and there's too much hand-waving and magic happening for the average developer who's not inside this stuff all day to really *get* it.
In fact, I am able to identify PR branches at a basic level by checking for `env.CHANGE_ID != null`, and just skip wholesale or hardcode a lot of stuff that's not important to us for PRs, like versioning and archiving. I can always come back to it later if we decide we want to actually use the PR builds for anything.

What we have currently is a process implementing basic Semantic Versioning, where we only tag on `develop` builds, `develop` being our de-facto mainline. We don't do a great job of merging to `master` after releases, but we are pretty solid on always only deploying from `develop`. (Why keep `main` around, then? We ask ourselves that often. It comes down to priorities of process changes; it's not really hurting anything to have it, so we focus on other stuff.)

I recently integrated [gitversion](https://gitversion.net) into the pipe, and have it configured to automatically bump the `PATCH` version on any commit-build to `develop`. If a bump of `MINOR` or `MAJOR` is required, the [commit-message phrases](https://gitversion.net/docs/reference/version-increments?Manually-incrementing-the-version) can be used.

Gitversion is nice because it removes the need for a file in the repo to be updated manually; it's based entirely on `git tags` and commits. It even updates the `assembly*.cs` etc files in the repo automatically. The downside is it took me quite a while to feel like I understood it well enough to use it; its configurability makes it complicated to grok at first. There are other tools out there that do the same thing, this is the one that was suggested to me and the docs made me comfortable enough to jump into it.


---

