{"id":2171,"date":"2015-08-01T03:00:00","date_gmt":"2015-08-01T03:00:00","guid":{"rendered":"https:\/\/www.microsoft.com\/reallifecode\/index.php\/2015\/08\/01\/a-peer-review-bot-for-github\/"},"modified":"2020-03-15T08:41:09","modified_gmt":"2020-03-15T15:41:09","slug":"a-peer-review-bot-for-github","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/ise\/a-peer-review-bot-for-github\/","title":{"rendered":"A Peer Review Bot for GitHub"},"content":{"rendered":"<p>We, in Microsoft\u2019s Open Source team, occasionally write case studies to explain our work with a bit more technical depth for both external engineers as well as our fellow internal Microsoft engineers. Naturally, we don\u2019t want to embarrass ourselves. So before any case study is released, we have to get some peer reviews.<\/p>\n<p>Our blog is basically just a GitHub page, which means that every additional post is added to the site in the form of a pull request. Keeping track of which pull request is ready to be merged is quite tedious work, which is why we wrote a <a href=\"http:\/\/github.com\/felixrieseberg\/peer-review-bot\">Node.js-driven bot that automates the whole flow<\/a>.<\/p>\n<h2 id=\"maintaining-a-workflow-is-hard\">Maintaining a Workflow is Hard<\/h2>\n<p>Managing the review workflow isn\u2019t fun. Depending on the size of your team, you probably have a bunch of pull requests in flight. If the engineering culture happens to be good, people are likely interested in collecting feedback early and often, meaning that your pull request list is a wild mix of various stages.<\/p>\n<p>One would assume that self-management is a good solution &#8211; and it often is. Many teams just mark unfinished pull requests with a \u2018WIP\u2019 in the title or a \u2018wip\u2019 label, which is being updated by whomever opened the pull request. Without dwelling on the reasons, let\u2019s just say that our team is highly creative and very productive, but not exactly great at being a synchronized body, so the poor souls in charge of our website and case studies had to manually check and track the status of case studies, where they are in terms of reviews, and whether or not they\u2019re ready for release.<\/p>\n<h2 id=\"automation-is-easy\">Automation is Easy<\/h2>\n<p>Instead of paying someone to constantly check all pull requests, we decided to use automation. GitHub comes with web hooks for all repositories &#8211; whenever a certain action is performed on a repository, GitHub can automatically post a JSON representation of the action to a given URL.<\/p>\n<p>We registered a small Node.js bot that would respond to those events with a simple checklist:<\/p>\n<ul>\n<li>Let\u2019s check if a new pull request was opened or a new comment was made on an existing pull request.<\/li>\n<li>If that\u2019s the case, the bot pulls the latest information about said pull request from GitHub.<\/li>\n<li>Once we got the info, we\u2019re checking if the pull request is already labeled. If it\u2019s labeled as \u2018no-review\u2019 or as \u2018peer-reviewed\u2019, we stop right away &#8211; there\u2019s nothing left to do.<\/li>\n<li>If we didn\u2019t already do so, we post a comment explaining the process.<\/li>\n<li>If other people have commented, we\u2019re checking if we received enough \u2018LGTM\u2019 or \u2018Looks good to me!\u2019 comments. If we have, we update the labels.<\/li>\n<li>If the bot is configured to automatically merge \u2018approved\u2019 pull requests, we go and ask GitHub to merge it. If the pull request isn\u2019t mergable, GitHub will naturally refuse.<\/li>\n<\/ul>\n<h4 id=\"lets-check-out-some-code\">Let\u2019s Check Out Some Code<\/h4>\n<p>Under the hood, the bot is just a small Express-driven app with one endpoint: http:\/\/botaddress.com\/pullrequests. A GET HTTP request will check the configured repo for open pull requests, while POST HTTP requests expects a GitHub-style JSON payload and handles only pull requests mentioned in it.<\/p>\n<p>Using Mike de Boer\u2019s excellent GitHub Node module, we just had to <a href=\"https:\/\/github.com\/felixrieseberg\/peer-review-bot\/blob\/master\/src\/bot.js\">describe all the individual interactions with GitHub<\/a> as well as a <a href=\"https:\/\/github.com\/felixrieseberg\/peer-review-bot\/blob\/master\/routes\/pullrequest.js\">small router module describing the review flow mentioned above<\/a>.<\/p>\n<h2 id=\"setup-your-own-bot\">Setup Your Own Bot!<\/h2>\n<p>If you too would like to require peer reviews of pull requests in your repo, you\u2019re in luck: Before we get started, let\u2019s do some required housekeeping:<\/p>\n<h4 id=\"1-creating-a-github-user-for-the-bot\">1) Creating a GitHub User for the Bot<\/h4>\n<p>The bot will need a GitHub user to interact with GitHub. You can just use your own account, but no good bot was ever written without a good robot pun. Head over to GitHub and create a new user, choosing from the many robots out there &#8211; Terminator, Tinman, Bender &#8211; choose wisely.<\/p>\n<p>While the bot works fine with a username\/password combination, we recommend setting up an OAuth2 token. GitHub has API rate limits which are a little bit higher for OAuth-authenticated calls.<\/p>\n<h4 id=\"2-deploying-the-bot\">2) Deploying the Bot<\/h4>\n<p>If you\u2019re using Azure, setting up a bot takes about a minute. Simply head over to the <a href=\"http:\/\/github.com\/felixrieseberg\/peer-review-bot\">Peer Review Bot\u2019s repository<\/a> and click the \u2018Deploy to Azure\u2019 button. The Azure deployment wizard will automatically create a website for you; but also setup environment variables configuring the bot itself.<\/p>\n<p>If you\u2019re anywhere else, make sure you\u2019re running Node (at least on 0.10.x). Then, setup configuration by either directly editing <code class=\"highlighter-rouge\">config.js<\/code> or by setting environment variables. Here are your options:<\/p>\n<ul>\n<li><code class=\"highlighter-rouge\">user<\/code> User\/organization owning the repository<\/li>\n<li><code class=\"highlighter-rouge\">repo<\/code> Repository to watch (case-studies)<\/li>\n<li><code class=\"highlighter-rouge\">botUser<\/code> Bot\u2019s GitHub username<\/li>\n<li><code class=\"highlighter-rouge\">botPassword<\/code> Bot\u2019s Github password<\/li>\n<li><code class=\"highlighter-rouge\">labelReviewed<\/code> Name of the label indicating enough peer reviews<\/li>\n<li><code class=\"highlighter-rouge\">labelNeedsreview<\/code> Name of the label indicating missing peer reviews<\/li>\n<li><code class=\"highlighter-rouge\">reviewsNeeded<\/code> Number of reviews needed<\/li>\n<li><code class=\"highlighter-rouge\">instructionsComment<\/code> Comment posted by the bot when a new PR is opened &#8211; if you use <code class=\"highlighter-rouge\"><span class=\"p\">{<\/span><span class=\"err\">reviewsNeeded<\/span><span class=\"p\">}<\/span><\/code> in your comment, it\u2019ll automatically be replaced with the number of reviews needed<\/li>\n<li><code class=\"highlighter-rouge\">mergeOnReview<\/code> (default: false) If set to true, the bot will automatically merge a PR as soon as it consideres it revieweed<\/li>\n<li>\n<table>\n<tbody>\n<tr>\n<td><code class=\"highlighter-rouge\">pullRequestsStatus<\/code> (default: open) Status of the pull requests to consider. Options are: all<\/td>\n<td>open<\/td>\n<td>closed<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<\/li>\n<li><code class=\"highlighter-rouge\">oauth2token<\/code> If set, we\u2019ll use an <a href=\"https:\/\/help.github.com\/articles\/creating-an-access-token-for-command-line-use\/\">OAuth token<\/a> instead of the username\/password combination to authenticate the bot.<\/li>\n<li><code class=\"highlighter-rouge\">excludeLabels<\/code> If set, the bot will automatically ignore PRs with those labels (format: <code class=\"highlighter-rouge\">no-review i-hate-reviews<\/code>)<\/li>\n<\/ul>\n<p>If you add configuration directly to the <code class=\"highlighter-rouge\">config.js<\/code>, please make sure to not check it into GitHub.<\/p>\n<p>Once configured, start the bot with <code class=\"highlighter-rouge\">npm start<\/code> or <code class=\"highlighter-rouge\">node .\/bin\/www<\/code>. Now that a robot is taking care of your peer review workflow, the humans can do something more fun!<\/p>\n","protected":false},"excerpt":{"rendered":"<p>We built a peer review bot for GitHub, automating review workflows for pull requests &#8211; so that humans can spend their time with more fun things.<\/p>\n","protected":false},"author":21345,"featured_media":11192,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[13],"tags":[110,187,275],"class_list":["post-2171","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-bots","tag-bots","tag-github","tag-node"],"acf":[],"blog_post_summary":"<p>We built a peer review bot for GitHub, automating review workflows for pull requests &#8211; so that humans can spend their time with more fun things.<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/ise\/wp-json\/wp\/v2\/posts\/2171","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/devblogs.microsoft.com\/ise\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/devblogs.microsoft.com\/ise\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/ise\/wp-json\/wp\/v2\/users\/21345"}],"replies":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/ise\/wp-json\/wp\/v2\/comments?post=2171"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/ise\/wp-json\/wp\/v2\/posts\/2171\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/ise\/wp-json\/wp\/v2\/media\/11192"}],"wp:attachment":[{"href":"https:\/\/devblogs.microsoft.com\/ise\/wp-json\/wp\/v2\/media?parent=2171"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/ise\/wp-json\/wp\/v2\/categories?post=2171"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/ise\/wp-json\/wp\/v2\/tags?post=2171"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}