How to extend GitHub and improve your workflow with GitHub Apps

Learn how to automate your dev and software delivery workflow with GitHub Apps

Have you ever wondered if you could extend GitHub to perform specific actions, or use features that reflect your team's workflow? GitHub Apps can do that for you.

GitHub Apps are applications that give you access to GitHub APIs, so that you can build integrations with GitHub, with the benefits of productivity, flexibility and reduced friction in your workflow. They can be installed directly on organizations and user accounts, and granted access to specific repositories. They come with granular permissions and built-in webhooks.

To improve your workflow, you can create a GitHub App that contains multiple scripts or an entire application, and then connect that app to many other tools. For example, you can connect GitHub Apps to GitHub or Slack. For the Knative project, we have a GitHub App that manages pull requests. When a PR is created, it checks if the user has accepted the project's CLA and adds a label indicating the status of that check. It does a few more validations before a PR can be merged.

Building Your First GitHub App

You can create GitHub Apps in different programming languages and register them under your personal account or organization. I'm going to show you how to build a GitHub App in under 5 minutes, using the Probot app framework. Probot is a framework for building GitHub Apps in Node.js. It aims to eliminate all the drudgery–like receiving and validating webhooks, and doing authentication handstands–so you can focus on the features you want to build.

The create-probot-app is the best way to start building a new app. It will generate a new app with everything you need to get started and run your app in production. To get started, open your command line application and run the following command:

npx create-probot-app my-github-app

You will be asked a series of questions. Answer them as you so choose, but for the question Which template would you like to use?, choose basic-js (you're free to choose basic-ts if you want to). The necessary files and packages will be downloaded and installed. The list below describes some of the important files in the project:

  1. index.js: This is the entry point into the application.
  2. app.yml: This is the GitHub App Manifest used when initializing the app.
  3. Dockerfile: A Dockerfile that can be used to containerize and deploy the app.

The default event enabled for the app when it is bootstrapped is only the issues event. You will later write code to check for comments in issues. For that, you'll need to enable the issue_comment event. Open app.yaml, go to line 25 and uncomment it. The default_events section of the manifest should look like what you see below.

default_events:
  # - check_run
  # - check_suite
  # - commit_comment
  # - create
  # - delete
  # - deployment
  # - deployment_status
  # - fork
  # - gollum
  - issue_comment
  - issues

Let's inspect the index.js file. The code below is the content of the file.

/**
 * This is the main entrypoint to your Probot app
 * @param {import('probot').Probot} app
 */
module.exports = (app) => {
  app.log.info("Yay, the app was loaded!");

  app.on("issues.opened", async (context) => {
    const issueComment = context.issue({
      body: "Thanks for opening this issue!",
    });
    return context.octokit.issues.createComment(issueComment);
  });
};

The app parameter is an instance of Probot and gives you access to all of the GitHub goodness. app.on is used to subscribe to events triggered by GitHub. You have to specify the name of the event and a function to handle the event.

The context passed to the event handler includes everything about the event that was triggered, as well as some helpful properties for doing something useful in response to the event. context.octokit is an authenticated GitHub client that can be used to make REST API and GraphQL calls to GitHub, and it allows you to do almost anything programmatically that you can do through a web browser on GitHub.

In the sample code, context.octokit is used to create an issue comment. The app and context objects both have a log object that can be used to log information to the standard output stream.

Registering the GitHub App

With the application code ready, you can now register it on GitHub. Follow the instructions below to do so.

  1. Run the app by running npm start in your terminal.
  2. Go to http://localhost:3000 in your browser.
  3. You should see a web page with buttons to register the app or use an existing one. Go ahead and click the Register a GitHub App button.
  4. Next, you'll get to decide on an app name that isn't already taken. Note: If you see a message "Name is already in use" although no such app exists, it means that a GitHub organization with that name exists and cannot be used as an app name.
  5. After registering your GitHub App, you'll be redirected to install the app on any repositories of your choosing repositories. Select a repository to try it on. You can also check your local .env and notice it will be populated with values GitHub sent back in the course of that redirect.
  6. Restart the server in your terminal (press CTRL/CMD + C to stop the server).

Now that the app is registered and installed in a repository, go to the issues page of the repository and open a new issue. You should notice the GitHub App leave a comment when a new issue is created.

GitHub App new issue: pmbanugo commented “My first app,” and telerik-github-app bot replied, “Thanks for opening this issue!”

Extend the App With probot-commands

Probot doesn't have any official extensions API, but there are some reusable utilities that have been extracted from existing apps. One of these utilities is called probot-commands. It is an extension that adds slash commands to GitHub. Slash commands are lines that start with / in comments on Issues or Pull Requests that allow users to interact directly with your app. We will use it to add labels to issues so that we can filter issues by either bug or feature labels.

To use this utility, open the terminal and run npm install --save probot-commands. Afterward, open index.js and add the code statement below.

commands(app, "kind", (context, command) => {
  const labels = command.arguments.split(/, */);
  return context.octokit.issues.addLabels(context.issue({ labels }));
});

The code gets the value passed from GitHub and uses it to add labels by calling context.octokit.issues.addLabels(context.issue({ labels })).

Let's try out the new changes. Restart the server and add a comment that begins with /kind to the issue you opened in the previous section of this post. For example, enter /kind bug as a new comment to the issue.

To demonstrate a slash command, pmbanugo commented, “/kind feature,” and the telerik-github-app bot added the `feature` label.

Deploying the App

So far you've been running the app locally. You can deploy it to any cloud provider and run it as a Node.js application. The Docker file included can be used to package and deploy it as a containerized app. I'm going to use DigitalOcean App platform as the hosting provider. You can find more details about other hosting options in the documentation.

To get started, commit your changes to Git and create a GitHub (or GitLab) repository, then push your changes there.

If you have a DigitalOcean account, log in and go to the Apps page. If you don't have an account, you can create one using my referral link, which gives you $100 to try out different things on DigitalOcean (and I’ll get $25 credit if you become an active user and spend $25). After creating a new account, go to the Apps page and click Launch Your App button. You will be redirected to a page where you will specify the source for the application. Choose GitHub (or GitLab if that's what you use).

You will be redirected to GitHub to authorize and install the DigitalOcean GitHub App (yes, they use GitHub App as well!). Select the user or organization and repositories to give it access to. You can choose to authorize it only for the repository you want to deploy. After the installation and authorization, you will be redirected back to DigitalOcean. Select GitHub and choose the repository you want to deploy from the dropdown and select a branch. Then click the Next button to proceed.

You will be redirected to a page to configure the app. Click Edit beside the Environment Variables to add some environment variables. You need 3 environment variables:

  1. APP_ID: the ID of the app, which you can get from the app settings page.

  2. WEBHOOK_SECRET: the Webhook Secret that you generated when you created the app.

  3. And one of the following:

  4. PRIVATE_KEY: the contents of the private key you downloaded after creating the app, OR...

  5. PRIVATEKEYPATH: the path to a private key file. PRIVATEKEY_ takes precedence over PRIVATEKEYPATH.

Copy these values from the .env file in your project folder (Note: this was generated when you registered the App on GitHub) and click Next.

Choose a name and region for the application and click Next. You will be redirected to the final page where you need to choose a plan to run the application. For prototype purposes, use the Basic plan and a container size that cost $5/month. Scroll to the bottom of the page and click the Launch App button.

It'll take a while for the application to be built. When it's done, you will get a domain that you can then use for the GitHub App. Go to the GitHub Apps settings page and click the Edit button to update the App. Scroll down to the Webhook section and change the Webhook URL to the new domain from DigitalOcean. Click the Save changes button to save the changes.

With the app deployed on DigitalOcean and the Webhook URL updated, every new event will be sent to the new URL.

my-github-app has the URL my-github-app-ewqgo.ondigitalocean.app. We’re looking at its overview page on the DigitalOcean App platform

What's Next?

You learned how to automate your workflow and integrate with GitHub using GitHub Apps. It is the officially recommended way to integrate with GitHub because they offer much more granular permissions to access data. GitHub Apps can be installed directly on organizations and user accounts and granted access to specific repositories. You saw how to use Probot to build a Node.js GitHub App, and how to deploy the app to the cloud.

The app you registered by following the instructions in this post is public but it's not discoverable by other GitHub users. You can also share or sell apps in GitHub Marketplace. To learn how to list an app on GitHub Marketplace, see the GitHub documentation "Getting started with GitHub Marketplace."

If you need your App to do more things than the permissions enabled when the App was registered, you can add more permissions through the GitHub App settings page. For more details, see "Editing a GitHub App's permissions.".

You can get the source code for the sample application on GitHub.

If you want to see more ways to build GitHub Apps, check out my upcoming book about building a serverless app platform by integrating GitHub, Next.js, Kubernetes and other Cloud Native tools to build a serverless platform

Originally published on Telerik blog