| title | redirect_from |
|---|---|
Building Your First GitHub App- JavaScript |
/guides/building-your-first-app-js/ |
{:toc}
This guide is designed to help you build a GitHub App and run it on a server. The app will be simple: it will add a label to any new issue that's opened in a repository the app is installed on.
This project will walk you through the following:
- Registering a GitHub App
- Exposing your local environment to the internet via smee
- Programming your app to listen for events
- Authenticate via Probot
- Using the Octokit.js library to do REST API operations through Probot
Once you've worked through the steps, you'll be ready to develop other kinds of integrations using the full suite of GitHub APIs. {% if page.version == 'dotcom' %}You can check out successful examples of apps on GitHub Marketplace and Works with GitHub.{% endif %}
You may find it helpful to have a basic understanding of the following:
- GitHub Apps
- Webhooks
- The JavaScript programming language (there's no official link)
- REST APIs
But you can follow along at any experience level. We'll link out to information you need along the way!
You'll need to complete the following tasks as part of the one-time setup for this project:
- Initial Setup using Probot
- Register a new app with GitHub
- Setup smee
- Fill in your environment variables
- Run the boilerplate
- Install the app on your account
Once you've completed these steps, you can start building your app!
For now, let's assume we are going to develop our app on your local machine, at least to start. We'll be able to move everything onto proper servers later, but it'll be easier to start with the machine in front of us.
In order to develop a GitHub App in JavaScript, we're going to use a framework called [Probot][probot] to help simplify this process.
The first thing we'll need to do is ensure that you have node and npm installed on your computer.
Run node -v in your terminal to check if you are on at least version 8.3.0. If not, install the latest version.
The best way to get started using [probot][probot] is to use create-probot-app to generate some boilerplate files in order to more easily get started on your app. We'll use npm to run:
$ npx create-probot-app my-first-app
This will ask you a series of optional questions about your new app which will look like:
This will create a new folder my-first-app, which we will navigate into on our terminal.
The most important files note here are index.js, which is where the code for your app will go, and package.json,
which makes this a standard npm module.
To help GitHub connect to your local computer, to talk to our app, we're going to use a tool called [smee][smee]. (Of course, if you're already familiar with smee or other similar tools like localtunnel or ngrok, feel free to use what you are comfortable with.)
Now we are going to run smee. Go to smee.io and click Start a new channel. smee will assign us a
unique domain that we can use. We will
need to know this domain for the next step. In this example above, we'll use https://smee.io/hello-world as the domain.
Now, we need to tell GitHub about our app. For now, we'll use the domain smee provided, but in the future we can update GitHub to point to our hosting provider. (If at this point you do not yet have a GitHub account, now would be a great time to join.)
Begin by visiting the [app settings page][app settings] in your GitHub profile, navigate to GitHub Apps, and click the "New GitHub App" button to begin registering our app with GitHub.
From here we will be presented with a form to fill out, giving GitHub the details on our new app. [Follow this guide][creating a github app] for the details on what each field is and requires, but for this guide we have some specific requirements for how it should be filled out.
-
Use the domain issued to us by smee.
-
Create a secret to secure our webhook endpoints. This should be something that only you (and GitHub, via this form) know. For local development, we recommend using 'development'.
- We must specify a set of permissions for our app—that is, how much data it should have access to. Let's begin with the bare minimum, and select nothing at all. We'll add permissions as we need them in later guides.
Once you've submitted the form, we'll be taken to the app management page. We have two more things we need to look at.
-
First, be sure to generate a private key for our app. This is necessary for us to authenticate our app later. Hit the green button in the screenshot, and save the file in your my-first-probot-app folder.

-
Second, take note of the App ID that GitHub assigns us. It might not look important, but in fact we'll need it so we can tell GitHub who we are from our app.

OK, that's everything we need from the GitHub site! Let's start playing with code!
Let's open up all our files in a text editor. You can use any editor you like. All the things necessary to run your GitHub App will live in a .env file, which is how nodejs handles environment variables. In your my-first-probot-app folder, you should see a file called .env.example. Let's go ahead and rename this file to .env. From there we need to add two important variables.
-
Fill in the
APP_ID=and set it to the App ID GitHub gave you. -
Fill in the
WEBHOOK_PROXY_URL=with the domain generated on smee.
In my case, my .env will look like:
# The ID of your GitHub App
APP_ID=1234
WEBHOOK_SECRET=development
# Use `trace` to get verbose logging or `info` to show less
LOG_LEVEL=debug
# Go to https://smee.io/new set this to the URL that you are redirected to.
WEBHOOK_PROXY_URL='https://smee.io/hello-world'{{#note}}
Note: Probot automatically sets WEBHOOK_SECRET to 'development' in its boilerplate, if you set it to something different, be sure to update your .env to reflect that.
{{/note}}
Great! Now we've got our environment prepped. Let's run the app!
Now, for one last test. We're going to start our server by running:
npm install
npm startand watching at the output in your terminal. You should see something like this:
That's good news! It means our app was able to successfully authenticate and recieve an access token from GitHub. If you saw something like this, we're good to go! 🙌
The remainder of this guide walks you through customizing this code so that the app does what you want: when someone opens a new issue in a repo that the app is installed on, the app automatically adds the label needs-response to it.
The following sections will walk you through these procedures:
When you first registered your app, you accepted the default permissions, which amount to "no access" for most operations.
But your app is going to need permission to read issues and write labels. To update its permissions, return to the app settings page, choose your app, and click Permissions & Webhooks in the sidebar.
- In the permissions section, find Issues, and select Read & Write in the Access dropdown next to it. The description says this option grants access to both issues and labels, which is just what you need.
- In the events section, subscribe to Issues events.
Save your changes!
{{#note}}
Note: Any time you change your app's permissions or webhooks, users who have installed the app (including yourself!) will need to accept the new permissions before the changes take effect. Users who have installed the app will receive an email prompting them to accept the new permissions. Make sure to check your own email and follow the link to accept the new permissions.
{{/note}}
Great! Your app has permission to do the tasks you want it to do. Now you can add the code to make it work.
Make sure you install the app on the repository you want to use it on!
OK, your app can tell when issues are opened. Now you want the app to add the label needs-response to any newly opened issue.
First, create the label. For the purposes of this guide, create the label manually via the GitHub website. In your repository, click Issues, then Labels, then click the New label button. Name the new label needs-response.
{{#note}}
Note: Wouldn't it be great if your app could create the label programmatically? It can! Try adding the code to do that on your own after you finish the steps in this guide.
{{/note}}
Now that the label exists, you can program your app to use the REST API to add the label to any newly opened issue.
We already know that Probot handles the authentication side of things, but what Probot also does is pass in an authenticated Octokit instance in the form of context.github that allows you to utilize GitHub's REST API.
Now we can copy this code into our index.js:
module.exports = app => {
// a typical probot app only exports `app`
app.on('issues.opened', check)
// when issues are opened call the `check` fucntion
async function check (context) {
// `check` fucntion that takes a context that has a `context.payload` the webhook payload and `context.github` authenticated github client using octokit/rest.js
await context.github.issues.addLabels(context.issue({ labels: ['needs-response'] }))
// await because it's async,
// issues.addLabels() is from octokit/rest.js docs
// context.issue() is an internal probot api that returns => {owner: 'username', repo: 'reponame', 'number': 123}
// context.issue() is specific to the issue webhook event that was triggered and contains the info to reference that specific issue
}
}Now we can install the app on any repository, and any time a new issue is opened, it will add the label 'needs-response' to all newly opened issues, like so:
Here are a few FAQs. If you run into any other trouble, you can ask for help or advice in the GitHub Community Forum: LINK-TO-COME
-
Q: When I run the server, I get the following error:
throw new Error(`Missing private key for GitHub App, ${hint}`) ^ Error: Missing private key for GitHub App, please use: * `--private-key=/path/to/private-key` flag, or * `PRIVATE_KEY` environment variable, or * `PRIVATE_KEY_PATH` environment variableA: You probably haven't saved up your private key to the right folder. It probably originally got saved in your
Downloadsfolder, so move it to your project's directory, and then try running the app again. -
Q: When I run the server, and submit a new issue, nothing happens. The app doesn't comment and I don't see anything new in my terminal.
A: There are two possibilities here. Either you haven't told the app to listen on the correct webhooks. In which case be sure to check under Subscribe to events, the Issues event. Or you may not have installed the app on your repository. Be sure the app installed on the repository you're trying to open the issue on.
-
Q: When I run the server, I see this error:
Missing GitHub App ID. Use --app flag or set APP_ID environment variable.or this one:
ERROR probot: {"message":"Integration not found","documentation_url":"https://developer.github.com/v3"}A: Be sure to set the APP_ID variable in your
.envto match the one GitHub gave you when registering the app.
After walking through this guide, you've learned the basic building blocks for developing GitHub Apps! To review, you:
- Registered a new GitHub App
- Exposed your local environment to the internet via smee
- Programmed your app to listen for events
- Used the Octokit.js library to do REST API operations
- Authenticated via Probot
Here are some ideas for what you can do next with your app:
{% if page.version == 'dotcom' or page.version ver_gt '2.13' %}
- Rewrite your app using GraphQL!{% endif %}
- Rewrite your app in Ruby using TODO: LINK TO RUBY GUIDE
- Have the app check whether the
needs-responselabel already exists on the issue, and if not, add it. - When the bot successfully adds the label, show a message in the Terminal. (Hint: compare the
needs-responselabel ID with the ID of the label in the payload as a condition for your message, so that the message only displays when the relevant label is added and not some other label.) - Move your code to a hosted server (e.g., Heroku). Don't forget to update your app settings with the new domain.
- Share your project or get advice in the Community Forum: LINK TO COME{% if page.version == 'dotcom' %}
- Have you developed a shiny new app you think others might find useful? Add it to GitHub Marketplace!{% endif %}
[app guides] /apps/guides/ [probot]: https://probot.github.io/ [smee]: https://smee.io/ [app settings]: https://github.com/settings/apps [creating a github app]: https://developer.github.com/apps/building-github-apps/creating-a-github-app/



