{
    "componentChunkName": "component---src-templates-blog-post-tsx",
    "path": "/blog/2020-05-26-github-actions-pull_request/",
    "result": {"data":{"blogPost":{"title":"Github Actions: a deep dive into pull_request","slug":"/blog/2020-05-26-github-actions-pull_request/","authorNodes":[{"name":"Min Kim","slug":"/people/min-kim/"}],"markdown":{"html":"<p>Github Actions is an exciting feature that enables teams to construct workflows based on webhook events. It unlocks new possibilities for teams that neatly integrate it into their development flow.</p>\n<p>For example, you can use Github Actions to automatically run tests, generate a preview app, and send a follow-up notification every time somebody opens a pull request. Presuming you're familiar with writing <a href=\"https://help.github.com/en/actions/configuring-and-managing-workflows\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">Github Actions workflows</a>, let’s take a closer look at some aspects of that process.</p>\n<p>At Frontside we use Github Actions extensively to make the development process of our clients both simpler and more inclusive for non-technical stakeholders. This is possible because Github Actions offers a rich API that allows us to build flexible and highly-specific workflows.</p>\n<p>In this article, we have put together specific behaviors and information that you’ll need to use <code class=\"language-text\">pull_request</code> as a trigger for your Github Actions workflow. First we’ll take a look at how the workflow is actually triggered <code class=\"language-text\">on: pull_request</code>; then we’ll examine the information provided to the workflow when triggered by a <code class=\"language-text\">pull_request</code>; and finally we’ll look at how <code class=\"language-text\">@actions/checkout</code> reacts to <code class=\"language-text\">pull_request</code>.</p>\n<nav class=\"table-of-contents\">\n  <h2>All you need to know about pull_request:</h2>\n  <ul>\n      <li>\n          <a href='#how-do-workflows-trigger-on-pull_request'>Activities that trigger pull_request</a>\n      </li>\n      <li>\n          <a href='#what-information-is-available-from-a-workflow'>Information available to the workflow</a>\n      </li>\n      <li>\n          <a href='#how-does-pull_request-affect-actionscheckout'>Effects on @action/checkout</a>\n      </li>\n  </ul>\n</nav>\n<h2 id=\"how-do-workflows-trigger-on-pull_request\" style=\"position:relative;\"><a href=\"#how-do-workflows-trigger-on-pull_request\" aria-label=\"how do workflows trigger on pull_request permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>How do workflows trigger on <code class=\"language-text\">pull_request</code>?</h2>\n<p>When a Github Actions workflow is configured to run on pull requests, by default it will be triggered on three different types of activities: <code class=\"language-text\">opened</code>, <code class=\"language-text\">synchronize</code>, and <code class=\"language-text\">reopened</code>.</p>\n<div class=\"gatsby-highlight\" data-language=\"yaml\"><pre class=\"language-yaml\"><code class=\"language-yaml\"><span class=\"token key atrule\">name</span><span class=\"token punctuation\">:</span> Pull Request Workflow\n<span class=\"token key atrule\">on</span><span class=\"token punctuation\">:</span> pull_request</code></pre></div>\n<p class=\"blog-post--caption\">Basic <code class=\"language-text\">pull_request</code> usage.</p>\n<p>If you need your workflow to run on any of the other types you will need to specify them. And if you wish to run those types in addition to the default types, you will need to manually add those too because once you configure <code class=\"language-text\">types</code> the default values are no longer provided:</p>\n<div class=\"gatsby-highlight\" data-language=\"yaml\"><pre class=\"language-yaml\"><code class=\"language-yaml\"><span class=\"token key atrule\">name</span><span class=\"token punctuation\">:</span> Pull Request Workflow\n<span class=\"token key atrule\">on</span><span class=\"token punctuation\">:</span>\n  <span class=\"token key atrule\">pull_request</span><span class=\"token punctuation\">:</span>\n    <span class=\"token key atrule\">types</span><span class=\"token punctuation\">:</span> <span class=\"token punctuation\">[</span> assigned<span class=\"token punctuation\">,</span> opened<span class=\"token punctuation\">,</span> synchronize<span class=\"token punctuation\">,</span> reopened <span class=\"token punctuation\">]</span></code></pre></div>\n<p class=\"blog-post--caption\">We have to explicitely set every action type if we customize them. <br /> The defaults will not be preserved automatically.</p>\n<p>Although the names of these types are pretty self-explanatory, we have gone ahead and double-checked each one of them to confirm our assumptions:</p>\n<table>\n<thead>\n<tr>\n<th>Type</th>\n<th>Description</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td><code class=\"language-text\">assigned</code></td>\n<td>a user is assigned to the pull request</td>\n</tr>\n<tr>\n<td><code class=\"language-text\">unassigned</code></td>\n<td>a user is unassigned from the pull request</td>\n</tr>\n<tr>\n<td><code class=\"language-text\">labeled</code></td>\n<td>a label is applied to the pull request</td>\n</tr>\n<tr>\n<td><code class=\"language-text\">unlabeled</code></td>\n<td>a label is removed from the pull request</td>\n</tr>\n<tr>\n<td><code class=\"language-text\">opened</code></td>\n<td>pull request is created</td>\n</tr>\n<tr>\n<td><code class=\"language-text\">edited</code></td>\n<td>title, body, or the base branch of the PR is modified</td>\n</tr>\n<tr>\n<td><code class=\"language-text\">closed</code></td>\n<td>pull request is closed (as opposed to merged)</td>\n</tr>\n<tr>\n<td><code class=\"language-text\">reopened</code></td>\n<td>closed pull request is reopened</td>\n</tr>\n<tr>\n<td><code class=\"language-text\">synchronize</code></td>\n<td>commit(s) pushed to the pull request</td>\n</tr>\n<tr>\n<td><code class=\"language-text\">ready_for_review</code></td>\n<td>pull request is taken out from draft mode</td>\n</tr>\n<tr>\n<td><code class=\"language-text\">locked</code></td>\n<td>pull request is locked</td>\n</tr>\n<tr>\n<td><code class=\"language-text\">unlocked</code></td>\n<td>pull request is unlocked</td>\n</tr>\n<tr>\n<td><code class=\"language-text\">review_requested</code></td>\n<td>request a user for review</td>\n</tr>\n<tr>\n<td><code class=\"language-text\">review_request_removed</code></td>\n<td>remove request from user for review</td>\n</tr>\n</tbody>\n</table>\n<p class=\"blog-post--caption\">For a complete list of activity types, checkout <a href=\"https://help.github.com/en/actions/reference/events-that-trigger-workflows\" target=\"_blank\" rel=\"nofollow\">Github's Events-that-trigger-workflows page</a>.</p>\n<p>One thing to note is that when you configure your <code class=\"language-text\">pull_request</code> workflow to be triggered on <code class=\"language-text\">labeled</code> or <code class=\"language-text\">unlabeled</code> and you add/remove multiple labels at the same time, the event of each label will trigger its own workflow run. It also works the same way for <code class=\"language-text\">assigned</code>/<code class=\"language-text\">unassigned</code> and <code class=\"language-text\">review_requested</code>/<code class=\"language-text\">review_request_removed</code>.</p>\n<h2 id=\"what-information-is-available-from-a-workflow\" style=\"position:relative;\"><a href=\"#what-information-is-available-from-a-workflow\" aria-label=\"what information is available from a workflow permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>What information is available from a workflow?</h2>\n<p>You can find the payload of each run of a workflow inside <code class=\"language-text\">workflow/event.json</code> which is accessible with the <code class=\"language-text\">github_event_path</code> environment variable. The payload contains the POST data of the webhook event that triggered the workflow, such as the action type, the commit before and after the action was triggered, the sender, etc.</p>\n<p>Here is an example of a payload from a workflow triggered by <code class=\"language-text\">pull_request</code> on <code class=\"language-text\">synchronize</code>:</p>\n<div class=\"gatsby-highlight\" data-language=\"js\"><pre class=\"language-js\"><code class=\"language-js\"><span class=\"token punctuation\">{</span>\n  <span class=\"token string-property property\">\"action\"</span><span class=\"token operator\">:</span> <span class=\"token string\">\"synchronize\"</span><span class=\"token punctuation\">,</span>\n  <span class=\"token string-property property\">\"after\"</span><span class=\"token operator\">:</span> <span class=\"token string\">\"abcdefg\"</span><span class=\"token punctuation\">,</span> <span class=\"token comment\">// most recent commit of this push</span>\n  <span class=\"token string-property property\">\"before\"</span><span class=\"token operator\">:</span> <span class=\"token string\">\"1234567\"</span><span class=\"token punctuation\">,</span> <span class=\"token comment\">// latest commit prior to this push</span>\n  <span class=\"token string-property property\">\"number\"</span><span class=\"token operator\">:</span> <span class=\"token number\">12</span><span class=\"token punctuation\">,</span> <span class=\"token comment\">// pull request number</span>\n  <span class=\"token string-property property\">\"pull_request\"</span><span class=\"token operator\">:</span> <span class=\"token punctuation\">{</span>\n\t<span class=\"token comment\">// pull request metadata</span>\n  <span class=\"token punctuation\">}</span><span class=\"token punctuation\">,</span>\n  <span class=\"token string-property property\">\"repository\"</span><span class=\"token operator\">:</span> <span class=\"token punctuation\">{</span>\n\t<span class=\"token comment\">// owner, description, git_url ...</span>\n  <span class=\"token punctuation\">}</span><span class=\"token punctuation\">,</span>\n  <span class=\"token string-property property\">\"sender\"</span><span class=\"token operator\">:</span> <span class=\"token punctuation\">{</span>\n\t<span class=\"token comment\">// information of user who triggered this event</span>\n  <span class=\"token punctuation\">}</span>\n<span class=\"token punctuation\">}</span></code></pre></div>\n<p>You can do all sorts of useful things with the data provided from this payload. For example, you could compare the <code class=\"language-text\">repo.url</code> property of <code class=\"language-text\">pull_request.head</code> and <code class=\"language-text\">pull_request.base</code> to determine if the pull request was created from a forked repository against the original, and if so you could <code class=\"language-text\">console.log(\"Thank you for your interest in our open source project!\")</code>.</p>\n<p>The information in the payload will vary depending on the webhook event and the activity type which caused the trigger. By way of comparison, here’s the payload from a <code class=\"language-text\">push</code> webhook workflow triggered by the same commit as the example above (note that the actual payload will have more information):</p>\n<div class=\"gatsby-highlight\" data-language=\"js\"><pre class=\"language-js\"><code class=\"language-js\"><span class=\"token punctuation\">{</span>\n  <span class=\"token string-property property\">\"after\"</span><span class=\"token operator\">:</span> <span class=\"token string\">\"abcdefg\"</span><span class=\"token punctuation\">,</span>\n  <span class=\"token string-property property\">\"before\"</span><span class=\"token operator\">:</span> <span class=\"token string\">\"1234567\"</span><span class=\"token punctuation\">,</span>\n  <span class=\"token string-property property\">\"commits\"</span><span class=\"token operator\">:</span> <span class=\"token punctuation\">[</span><span class=\"token operator\">...</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">,</span>\n  <span class=\"token string-property property\">\"forced\"</span><span class=\"token operator\">:</span> <span class=\"token boolean\">false</span><span class=\"token punctuation\">,</span>\n  <span class=\"token string-property property\">\"repository\"</span><span class=\"token operator\">:</span> <span class=\"token punctuation\">{</span><span class=\"token operator\">...</span><span class=\"token punctuation\">}</span><span class=\"token punctuation\">,</span>\n  <span class=\"token string-property property\">\"sender\"</span><span class=\"token operator\">:</span> <span class=\"token punctuation\">{</span><span class=\"token operator\">...</span><span class=\"token punctuation\">}</span>\n<span class=\"token punctuation\">}</span></code></pre></div>\n<p>As you can see the payload is different from that of a pull request. On <code class=\"language-text\">push</code> we have less information, namely we lack <code class=\"language-text\">activity</code>, <code class=\"language-text\">number</code>, and <code class=\"language-text\">pull_request</code> from the payload. Note that even if you are pushing this particular commit to a pull request, if the workflow was triggered on <code class=\"language-text\">push</code>, it will not have any of the <code class=\"language-text\">pull_request</code> properties in the payload.</p>\n<p>Now that we have compared how a <code class=\"language-text\">push</code> payload differs from a <code class=\"language-text\">pull_request</code> payload, let's take a closer look at how the payload varies on different activity types of <code class=\"language-text\">pull_request</code>:</p>\n<ul>\n<li><code class=\"language-text\">opened</code>: Here is an example of a payload that does not have anything specific to its activity type, so the properties you see will be available on all pull request payloads:</li>\n</ul>\n<div class=\"gatsby-highlight\" data-language=\"js\"><pre class=\"language-js\"><code class=\"language-js\">  <span class=\"token punctuation\">{</span>\n\t<span class=\"token string-property property\">\"action\"</span><span class=\"token operator\">:</span> <span class=\"token string\">\"opened\"</span><span class=\"token punctuation\">,</span>\n\t<span class=\"token string-property property\">\"number\"</span><span class=\"token operator\">:</span> <span class=\"token number\">10</span><span class=\"token punctuation\">,</span>\n\t<span class=\"token string-property property\">\"pull_request\"</span><span class=\"token operator\">:</span> <span class=\"token punctuation\">{</span><span class=\"token operator\">...</span><span class=\"token punctuation\">}</span><span class=\"token punctuation\">,</span>\n\t<span class=\"token string-property property\">\"repository\"</span><span class=\"token operator\">:</span> <span class=\"token punctuation\">{</span><span class=\"token operator\">...</span><span class=\"token punctuation\">}</span><span class=\"token punctuation\">,</span>\n\t<span class=\"token string-property property\">\"sender\"</span><span class=\"token operator\">:</span> <span class=\"token punctuation\">{</span><span class=\"token operator\">...</span><span class=\"token punctuation\">}</span>\n  <span class=\"token punctuation\">}</span></code></pre></div>\n<ul>\n<li><code class=\"language-text\">edited</code>: This activity type offers information on the property of the pull request the user has edited.</li>\n<li><code class=\"language-text\">synchronize</code>: As seen above, this activity includes <code class=\"language-text\">before</code> and <code class=\"language-text\">after</code> commit SHAs. The <code class=\"language-text\">synchronize</code> activity type is triggered <em>per-push</em>, so if a single push has multiple commits, the workflow will only run once. The <code class=\"language-text\">before</code> pinpoints the most recent commit <em>prior</em> to the push, such that if you have commits <code class=\"language-text\">A-B-C</code> and you push <code class=\"language-text\">D-E-F</code>, the workflow will be comparing commit <code class=\"language-text\">F</code> to <code class=\"language-text\">C</code>.</li>\n<li><code class=\"language-text\">labeled</code> and <code class=\"language-text\">unlabeled</code>: These include the metadata of the label that triggered the workflow:</li>\n</ul>\n<div class=\"gatsby-highlight\" data-language=\"js\"><pre class=\"language-js\"><code class=\"language-js\">  <span class=\"token punctuation\">{</span>\n\t<span class=\"token string-property property\">\"action\"</span><span class=\"token operator\">:</span> <span class=\"token string\">\"unlabeled\"</span><span class=\"token punctuation\">,</span>\n\t<span class=\"token string-property property\">\"label\"</span><span class=\"token operator\">:</span> <span class=\"token punctuation\">{</span>\n  \t<span class=\"token string-property property\">\"color\"</span><span class=\"token operator\">:</span> <span class=\"token string\">\"red\"</span><span class=\"token punctuation\">,</span>\n  \t<span class=\"token string-property property\">\"default\"</span><span class=\"token operator\">:</span> <span class=\"token boolean\">true</span><span class=\"token punctuation\">,</span>\n  \t<span class=\"token string-property property\">\"description\"</span><span class=\"token operator\">:</span> <span class=\"token string\">\"Something isn't working\"</span><span class=\"token punctuation\">,</span>\n  \t<span class=\"token string-property property\">\"name\"</span><span class=\"token operator\">:</span> <span class=\"token string\">\"bug\"</span><span class=\"token punctuation\">,</span>\n\t<span class=\"token punctuation\">}</span>\n  <span class=\"token punctuation\">}</span></code></pre></div>\n<ul>\n<li><code class=\"language-text\">assigned</code> and <code class=\"language-text\">unassigned</code>: These are similar to <code class=\"language-text\">labeled</code>/<code class=\"language-text\">unlabeled</code> and the workflow will include the payload data of the added or removed assignee.</li>\n<li><code class=\"language-text\">review_requested</code> and <code class=\"language-text\">review_requested_removed</code>: as odd as it seems, neither of these provides the data of which reviewer changed, and so the payload structure for these actions is identical to <code class=\"language-text\">opened</code>. You are able to find the list of reviewers from within the <code class=\"language-text\">pull_request</code> portion of the payload, but it does not explicitly tell you which addition or removal of a reviewer triggered the workflow.</li>\n</ul>\n<h2 id=\"how-does-pull_request-affect-actionscheckout\" style=\"position:relative;\"><a href=\"#how-does-pull_request-affect-actionscheckout\" aria-label=\"how does pull_request affect actionscheckout permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>How does <code class=\"language-text\">pull_request</code> affect <code class=\"language-text\">@actions/checkout</code>?</h2>\n<p>When you use <code class=\"language-text\">pull_request</code>, <a href=\"https://github.com/actions/checkout\" target=\"_blank\" rel=\"nofollow noopener noreferrer\"><code class=\"language-text\">@actions/checkout</code></a> will perform a <code class=\"language-text\">git checkout</code> to the <code class=\"language-text\">github.ref</code> environment variable. Note that <code class=\"language-text\">git checkout</code> is not applied to the commit, as it would have been the case when using <code class=\"language-text\">push</code>.</p>\n<p>This difference means that a <code class=\"language-text\">pull_request</code> workflow <code class=\"language-text\">ref</code> would look like <code class=\"language-text\">refs/remotes/pull/##/merge</code> whereas a <code class=\"language-text\">push</code> workflow would be <code class=\"language-text\">refs/heads/branch_name</code>. This explains why the SHA of a <code class=\"language-text\">push</code> workflow matches the commit that triggered the workflow, whereas the SHA of a <code class=\"language-text\">pull_request</code> workflow does not; instead the SHA of the <code class=\"language-text\">pull_request</code> is the resulting commit that was created from merging the base to the head.</p>\n<p>You could configure the checkout action with the <code class=\"language-text\">ref</code> argument to be more explicit with what you want to check out. For instance, if you want to checkout the head commit instead of using the default merge ref, you could pass in <code class=\"language-text\">github.event.pull_request.head.sha</code> as the argument (or <code class=\"language-text\">github.event.pull_request.head.ref</code> if you are using <code class=\"language-text\">v1</code>):</p>\n<div class=\"gatsby-highlight\" data-language=\"yaml\"><pre class=\"language-yaml\"><code class=\"language-yaml\"><span class=\"token punctuation\">-</span> <span class=\"token key atrule\">uses</span><span class=\"token punctuation\">:</span> actions/checkout@v2\n  <span class=\"token key atrule\">with</span><span class=\"token punctuation\">:</span>\n    <span class=\"token key atrule\">ref</span><span class=\"token punctuation\">:</span> $<span class=\"token punctuation\">{</span><span class=\"token punctuation\">{</span> github.event.pull_request.head.sha <span class=\"token punctuation\">}</span><span class=\"token punctuation\">}</span></code></pre></div>\n<p class=\"blog-post--caption\">Checking out head commit using <code class=\"language-text\">checkout@v2</code>.</p>\n<p>Opting out from the default checkout to specify the head ref might be useful for any number of reasons. For example, if you have an action that relies on the output of <code class=\"language-text\">git log</code>, the merge commit would offset your results. Or merging with the base ref might introduce features that conflict with the head and possibly even go unnoticed. A third reason could be as follows: suppose your tests are comprehensive and catches those conflicts. A user might be confused as to why the tests are failing in CI but passing locally, especially if they are not familiar with how the checkout action works. Specifying the head ref allows you to have more granular control. In any case, a better understanding of how the checkout action works will allow you to troubleshoot effectively.</p>\n<hr>\n<p>Did we miss anything? Reach out via <a href=\"https://twitter.com/thefrontside\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">Twitter</a> and we'll gladly add it to the discussion! And let us know what cool things you're doing with Github Actions through Frontside’s <a href=\"https://discord.gg/r6AvtnU\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">Discord</a> community (where we hang out and talk about these topics).</p>\n<aside class=\"posts-list-list\">\n  <h2>Related article:</h2>\n  <div class=\"posts-list-entry\">\n    <h3 class=\"posts-list-title\">\n      <a href=\"/blog/2020-7-reasons-for-good-pull-request-descriptions/\">\n        7 reasons to write good Pull Request descriptions\n      </a>\n    </h3>\n    <p>\n      A good Pull Request description can lead to better reviews, improved solutions, better documentation, and more. In this article, Taras surveys seven big wins of PR descriptions.\n    </p>\n    <a href=\"/blog/2020-7-reasons-for-good-pull-request-descriptions/\" class=\"post-link\">\n      Continue reading\n      <span class=\"post-link--arrow\">→</span>\n    </a>\n  </div>\n</aside>","frontmatter":{"date":"May 26, 2020","description":"We have put together specific behaviors and information that you’ll need to use pull_request as a trigger for your Github Actions workflow.","tags":["github-actions","continuous-delivery"],"img":{"childImageSharp":{"fixed":{"src":"/static/2d452ef827f60fa2a3489aaf129ac06b/31987/2020-05-26-github-actions-pull_request-social-media.png"}}}}}}},"pageContext":{"id":"8f717b20-dc31-5829-a3bb-827e599c6d69"}},
    "staticQueryHashes": ["1241260443"]}