Automating your GitHub routine

Like many developers in the realm of Software Engineering, we are using git as our version control system. The most typical git workflow looks like the following:

Once a pull request is approved the changes can be merged to the master branch. One of the hosting solution for the source code is GitHub. It gives us a nice interface for reviewing pull requests, tracking issues, integrating with CI systems and many other cool features.

As engineers, we not only like to build software, but also automate repetitive tasks. Often we may find ourselves thinking the following: How could we bring automation to some of the actions on GitHub that we perform daily? Is it possible to speed up the process related to the pull requests?

GitHub apps

On GitHub it is possible to perform many actions using GitHub API. Creating a branch, pushing changes, creating a pull request, approving pull request and a lot of other actions are accessible via the API.

In addition to that, it is also possible to create web hooks - callbacks on specific actions on GitHub. This allows us to create flows of actions. For example, adding a label to a pull request once it’s approved. In this scenario, the user action is approving the pull request, which triggers a callback. We can use this callback to add a specific label to the pull request via the REST API.

One of the possible ways to achieve this kind of automation is using GitHub apps. Apps on GitHub let you automate actions related to git workflow using GitHub API. As a developer, you have to create and register an app on GitHub via its user interface. Besides providing basic information there such as app name, icon and description, you have to specify the permissions the app has (like write access to the source code etc.). Without required permissions, the app will not be able to execute an action.

Application permissions

Another important moment is to subscribe the app for specific callbacks (web hooks) which the app is supposed to receive. Without registering the app for callbacks, it will be never executed.

Callbacks to subscribe

After the app is registered, it will become accessible for others via the Marketplace. Any user or organization can integrate it for their repositories. The app will be acting as a user but will have a suffix [bot] after the name, so that it is easily recognizable by others that it is an application.

App overview

When the app is ready for usage, it needs to be deployed, for example, to any cloud platform. The app will be running at some cloud platform (Heroku in our case) and processes the callbacks and performs different actions.

Developing an app

The app can be developed using different technologies and programming languages. I would like to introduce the platform Probot. It is a framework for building GitHub apps which eliminates boilerplate codes and focuses on building the logic of the app. Every Probot app is a single Node.js module which exports one function. It is possible to use either Javascript or Typescript for development.

Let’s have a closer look at it and develop a simple app. Lets make an application that should approve all pull requests which have a label shipit on them.

Now let’s quickly go over what each line does in this app.

app.on(['pull_request.opened', 'pull_request.labeled'], async (context)

First, we need to specify events on which our function will execute. We are only interested in 2 events: when pull requests are opened and when labels are applied.

Then, we need to access current pull request and check which labels it has.

    const pullRequest = context.payload.pull_request
    const hasShiptItLabel: string[] = pullRequest.labels
                                                 .map((label: any) => label.name)
                                                 .includes('shipit')

Pull request as a data structure is available from the context.payload. Each label is an object, so we need to make a mapping and convert a list of objects to the list of label names (list of strings). After that we check if an array contains the item shipit - the label required to approve pull request.

const params = context.issue({ event: 'APPROVE' })

If pull request contains needed label, we have to approve it. For approving it we need to create an object using context.issue. This will build an object for making API call initialized already with owner, repo and number parameters. Parameter event is used to specify the type of the event will be submitted.

await context.github.pullRequests.createReview(params as PullRequestsCreateReviewParams)

And at last what we need to do is to submit the review. This is done with octokit - GitHub REST API client for Javascript. It is accessible through context.github. The function createReview as the name says submits a review to the pull request.

This is it. What is left is the app deployment and it is ready to meet the world. And this is how it will look like in action.

App example

Examples of usage

After we learned how to automate actions on GitHub, we can think about where all they can be applied. Here I would like to share with you a few examples which you might find useful.

Assigning pull request

If you constantly have issues finding a reviewer for your pull request, an app which assigns pull request randomly can be a solution. Checkout the app auto-assign which does this job. However, keep in mind, if it is a problem to find a reviewer for your pull request, an app might be a fix for the problem, but not for the roots of the problem.

Approve pull requests

In some cases you might have a situation when particular pull requests should be approved automatically. One of the possible scenarios is to get approved automatically pull requests for updating dependencies. We could ensure that this particular pull request contains necessary labels and is from specific user (if your dependencies got updated via another app). Besides that you can check existing autoapproval app.

Merge pull requests

Sometimes you would like to make sure that an approved pull request gets merged after it is approved and all checks are “green”. Even in the team of more than 10 engineers this can become challenging and can turn into a race among developers all trying to merge their own PRs, thus wasting time. The solution is to have an app which merges pull requests automatically based on some conditions. For example, if all tests are green and a pull request has been approved at least by 2 contributors, then it can be merged automatically. You may consider using probot-auto-merge app or implement your own.

There are many available apps on the GitHub Marketplace and on Probot featured apps. There is definitely something suitable for your team.