Use submodule to get docs from probot/probot

This commit is contained in:
Brandon Keepers
2017-08-18 09:54:24 -05:00
parent da1ef40143
commit cec5d22525
15 changed files with 7 additions and 425 deletions

3
.gitmodules vendored Normal file
View File

@@ -0,0 +1,3 @@
[submodule "_submodules/probot"]
path = _submodules/probot
url = https://github.com/probot/probot.git

View File

@@ -9,6 +9,8 @@ exclude:
- package-lock.json
- README.md
- node_modules
- _submodules
- script
sass:
style: :compressed

1
_submodules/probot Submodule

Submodule _submodules/probot added at 22499a7c09

1
docs Symbolic link
View File

@@ -0,0 +1 @@
_submodules/probot/docs

View File

@@ -1,19 +0,0 @@
---
next: docs/hello-world.md
permalink: /docs/
---
# Introduction
If you've ever thought, "wouldn't it be cool if GitHub could…"; imma stop you right there. Most features can actually be added via [GitHub Apps](https://developer.github.com/apps/), which extend GitHub and can be installed directly on organizations and user accounts and granted access to specific repositories. They come with granular permissions and built-in webhooks. Apps are first class actors within GitHub.
**Probot is a framework for building [GitHub Apps](http://developer.github.com/apps) in [Node.js](https://nodejs.org/)**. It aims to eliminate all the drudgerylike receiving and validating webhooks, and doing authentication handstandsso you can focus on the features you want to build.
Probot apps are easy to write, deploy, and share. Many of the most popular Probot apps are hosted, so there's nothing for you to deploy and manage. Here are just a few examples of things that have been built with Probot:
- [stale](/apps/stale/) - closes abandoned issues after a period of inactivity.
- [settings](/apps/settings/) - syncs repository settings defined in `.github/config.yml` to GitHub, enabling Pull Requests for repository settings.
- [request-info](/apps/request-info/) - requests more info from newly opened Pull Requests and Issues that contain either default titles or whose description is left blank.
- [Browse more examples](https://github.com/search?q=topic%3Aprobot-plugin&type=Repositories)
Ready to get started?

View File

@@ -1,60 +0,0 @@
# Best Practices
First and foremost, your plugin must obey the [The Three Laws of Robotics](https://en.wikipedia.org/wiki/Three_Laws_of_Robotics):
> 1. A robot may not injure a human being or, through inaction, allow a human being to come to harm.
> 2. A robot must obey the orders given it by human beings except where such orders would conflict with the First Law.
> 3. A robot must protect its own existence as long as such protection does not conflict with the First or Second Laws.
Now that we agree that nobody will get hurt, here are some tips to make your plugin more effective.
**Contents:**
- [Empathy](#empathy)
- [Autonomy](#autonomy)
- [Configuration](#configuration)
## Empathy
Understanding and being aware of the what another person is thinking or feeling is critical to healthy relationships. This is true for interactions with humans as well as bots, and it works both ways. Empathy enhances our [ability to receive and process information](http://5a5f89b8e10a225a44ac-ccbed124c38c4f7a3066210c073e7d55.r9.cf1.rackcdn.com/files/pdfs/news/Empathy_on_the_Edge.pdf), and it helps us communicate more effectively.
Think about how how people will experience the interactions with your plugin.
### Avoid the uncanny valley
The [uncanny valley](https://en.wikipedia.org/wiki/Uncanny_valley) is the hypothesis that our emotional response to a robot becomes increasingly positive as it appears to be more human, until it becomes eerie and empathy quickly turns to revulsion. This area between a "barely human" and "fully human" is the uncanny valley.
![uncanny valley](https://upload.wikimedia.org/wikipedia/commons/f/f0/Mori_Uncanny_Valley.svg)
Your bot should be empathetic, but it shouldn't pretend to be human. It is a bot and everyone that interacts with it knows that.
> - :smile: "Latest build failures: _{listing of build failures}_…"
> - :cry: "Hey there! You asked for the build failures, so I went and dug them up for you: _{listing of build failures}_ … Have a fantastic day!"
## Autonomy
### Never take bulk actions without explicit permission
Being installed on an account is sufficient permission for actions in response to a user action, like replying on a single issue. But a plugin _must_ have explicit permission before performing bulk actions, like labeling all open issues.
For example, the [stale](https://github.com/probot/stale) plugin will only scan a repository for stale issues and pull requests if `.github/stale.yml` exists in the repository.
### Include "dry run" functionality
A dry run is when a plugin, instead of actually taking an action, only logs what actions it would have taken if it wasn't a dry run. A plugin _must_ offer a dry run feature if it does anything destructive and _should_ offer a dry run feature in all cases.
For example, the [stale](https://github.com/probot/stale) plugin will perform a dry run if there is no `.github/stale.yml` file in the repository.
## Configuration
### Require minimal configuration
Plugins _should_ provide sensible defaults for all settings.
### Provide full configuration
Plugins _should_ allow all settings to customized for each installation.
### Store configuration in the repository
Any configuration _should_ be stored in the repository. Unless the plugin is using files from an established convention, the configuration _should_ be stored in the `.github` directory. See the [API docs for `context.config`](https://probot.github.io/probot/latest/Context.html#config).

View File

@@ -1,125 +0,0 @@
---
next: docs/best-practices.md
---
# Deployment
Every plugin can either be deployed as a stand-alone bot, or combined with other plugins in one deployment.
> **Heads up!** Note that most [plugins in the @probot organization](https://github.com/search?q=topic%3Aprobot-plugin+org%3Aprobot&type=Repositories) have an official hosted app that you can use for your open source project. Use the hosted instance if you don't want to deploy your own.
**Contents:**
1. [Create the GitHub App](#create-the-github-app)
1. [Deploy the plugin](#deploy-the-plugin)
1. [Heroku](#heroku)
1. [Now](#now)
1. [Combining plugins](#combining-plugins)
## Create the GitHub App
Every deployment will need an [App](https://developer.github.com/apps/).
1. [Create a new GitHub App](https://github.com/settings/apps/new) with:
- **Homepage URL**: the URL to the GitHub repository for your plugin
- **Webhook URL**: Use `https://example.com/` for now, we'll come back in a minute to update this with the URL of your deployed plugin.
- **Webhook Secret**: Generate a unique secret with `openssl rand -base64 32` and save it because you'll need it in a minute to configure your deployed plugin.
- **Permissions & events**: See `docs/deploy.md` in the plugin for a list of the permissions and events that it needs access to.
1. Download the private key from the app.
1. Make sure that you click the green **Install** button on the top left of the app page. This gives you an option of installing the app on all or a subset of your repositories.
## Deploy the plugin
To deploy a plugin to any cloud provider, you will need 3 environment variables:
- `APP_ID`: the ID of the app, which you can get from the [app settings page](https://github.com/settings/apps).
- `WEBHOOK_SECRET`: the **Webhook Secret** that you generated when you created the app.
And one of:
- `PRIVATE_KEY`: the contents of the private key you downloaded after creating the app, OR...
- `PRIVATE_KEY_PATH`: the path to a private key file.
`PRIVATE_KEY` takes precedence over `PRIVATE_KEY_PATH`.
### Heroku
Probot runs like [any other Node app](https://devcenter.heroku.com/articles/deploying-nodejs) on Heroku. After [creating the GitHub App](#create-the-github-app):
1. Make sure you have the [Heroku CLI](https://devcenter.heroku.com/articles/heroku-cli) client installed.
1. Clone the plugin that you want to deploy. e.g. `git clone https://github.com/probot/stale`
1. Create the Heroku app with the `heroku create` command:
$ heroku create
Creating arcane-lowlands-8408... done, stack is cedar
http://arcane-lowlands-8408.herokuapp.com/ | git@heroku.com:arcane-lowlands-8408.git
Git remote heroku added
1. Go back to your [app settings page](https://github.com/settings/apps) and update the **Webhook URL** to the URL of your deployment, e.g. `http://arcane-lowlands-8408.herokuapp.com/`.
1. Configure the Heroku app, replacing the `APP_ID` and `WEBHOOK_SECRET` with the values for those variables, and setting the path for the `PRIVATE_KEY`:
$ heroku config:set APP_ID=aaa \
WEBHOOK_SECRET=bbb \
PRIVATE_KEY="$(cat ~/Downloads/*.private-key.pem)"
1. Deploy the plugin to heroku with `git push`:
$ git push heroku master
...
-----> Node.js app detected
...
-----> Launching... done
http://arcane-lowlands-8408.herokuapp.com deployed to Heroku
1. Your plugin should be up and running! To verify that your plugin
is receiving webhook data, you can tail your app's logs:
$ heroku config:set LOG_LEVEL=trace
$ heroku logs --tail
### Now
Zeit [Now](http://zeit.co/now) is a great service for running Probot plugins. After [creating the GitHub App](#create-the-github-app):
1. Install the now CLI with `npm i -g now`
1. Clone the plugin that you want to deploy. e.g. `git clone https://github.com/probot/stale`
1. Run `now` to deploy, replacing the `APP_ID` and `WEBHOOK_SECRET` with the values for those variables, and setting the path for the `PRIVATE_KEY`:
$ now -e APP_ID=aaa \
-e WEBHOOK_SECRET=bbb \
-e PRIVATE_KEY="$(cat ~/Downloads/*.private-key.pem)"
1. Once the deploy is started, go back to your [app settings page](https://github.com/settings/apps) and update the **Webhook URL** to the URL of your deployment (which `now` has kindly copied to your clipboard).
Your plugin should be up and running!
## Combining plugins
To deploy a bot that includes multiple plugins, create a new app that has the plugins listed as dependencies in `package.json`:
```json
{
"name": "my-probot",
"private": true,
"dependencies": {
"probot-autoresponder": "probot/autoresponder",
"probot-configurer": "probot/configurer"
},
"scripts": {
"start": "probot run"
},
"probot": {
"plugins": [
"probot-autoresponder",
"probot-configurer"
]
}
}
```

View File

@@ -1,84 +0,0 @@
---
next: docs/webhooks.md
---
# Developing a Plugin
To develop a Probot plugin, you will first need a recent version of [Node.js](https://nodejs.org/) installed. Probot uses the `async/await` keywords, so Node.js 7.6 is the minimum required version.
## Generating a new plugin
[create-probot-plugin](https://github.com/probot/create-probot-plugin) is the best way to start building a new plugin. It will generate a new plugin with everything you need to get started and run your plugin in production.
To get started, install the module from npm:
```
$ npm install -g create-probot-plugin
```
Next, run the app:
```
$ create-probot-plugin my-first-plugin
```
This will ask you a series of questions about your plugin, which should look something like this:
```
Let's create a Probot plugin!
? Plugin's package name: my-first-plugin
? Description of plugin: A "Hello World" GitHub App built with Probot
? Plugin author's full name: Brandon Keepers
? Plugin author's email address: bkeepers@github.com
? Plugin author's homepage:
? Plugin's GitHub user or org name: bkeepers
? Plugin's repo name: my-first-plugin
created file: my-first-plugin/.env.example
created file: my-first-plugin/.gitignore
created file: my-first-plugin/.travis.yml
created file: my-first-plugin/LICENSE
created file: my-first-plugin/README.md
created file: my-first-plugin/app.json
created file: my-first-plugin/index.js
created file: my-first-plugin/package-lock.json
created file: my-first-plugin/package.json
created file: my-first-plugin/docs/deploy.md
Done!
```
The most important files note here are `index.js`, which is where the code for your plugin will go, and `package.json`, which makes this a standard [npm module](https://docs.npmjs.com/files/package.json).
## Configure a GitHub App
To run your plugin in development, you will need to configure a GitHub App to deliver webhooks to your local machine.
1. [Create a new GitHub App](https://github.com/settings/apps/new) with:
- **Webhook URL**: Set to `https://example.com/` and we'll update it in a minute.
- **Webhook Secret:** `development`
- **Permissions & events** needed will depend on how you use the bot, but for development it may be easiest to enable everything.
1. Download the private key and move it to the project directory
1. Edit `.env` and set `APP_ID` to the ID of the app you just created.
1. Run `$ npm start` to start the server, which will output `Listening on https://yourname.localtunnel.me`;
1. Update the **Webhook URL** in the [app settings](https://github.com/settings/apps) to use the `localtunnel.me` URL.
You'll need to create a test repository and install your app by clicking the "Install" button on the settings page of your app.
## Running the plugin
Once you've set the `APP_ID` of your GitHub app in `.env` and downloaded the private key, you're ready to run your bot.
```
$ npm start
> probot run ./index.js
Yay, the plugin was loaded!
18:11:55.838Z DEBUG PRobot: Loaded plugin: ./index.js
Listening on https://bkeepers.localtunnel.me
```
Optionally, you can also run your plugin through [nodemon](https://github.com/remy/nodemon#nodemon) which will listen on any files changes in your local development environment and automatically restart the server. After installing nodemon, you can run `nodemon --exec "npm start"` and from there the server will automatically restart upon file changes.
## Debugging
1. Always run `$ npm install` and restart the server if `package.json` has changed.
1. To turn on verbose logging, start server by running: `$ LOG_LEVEL=trace npm start`

View File

@@ -1,27 +0,0 @@
---
next: docs/http.md
---
# Interacting with GitHub
Probot uses [GitHub Apps](https://developer.github.com/apps/). An app is a first-class actor on GitHub, like a user (e.g. [@defunkt](https://github/defunkt)) or an organization (e.g. [@github](https://github.com/github)). The app is given access to a repository or repositories by being "installed" on a user or organization account and can perform actions through the API like [commenting on an issue](https://developer.github.com/v3/issues/comments/#create-a-comment) or [creating a status](https://developer.github.com/v3/repos/statuses/#create-a-status).
`context.github` is an authenticated GitHub client that can be used to make API calls. It is an instance of the [github Node.js module](https://github.com/mikedeboer/node-github), which wraps the [GitHub API](https://developer.github.com/v3/) and allows you to do almost anything programmatically that you can do through a web browser.
Here is an example of an autoresponder plugin that comments on opened issues:
```js
module.exports = robot => {
robot.on('issues.opened', async context => {
// `context` extracts information from the event, which can be passed to
// GitHub API calls. This will return:
// {owner: 'yourname', repo: 'yourrepo', number: 123, body: 'Hello World!}
const params = context.issue({body: 'Hello World!'})
// Post a comment on the issue
return context.github.issues.createComment(params);
});
}
```
See the [full API docs](https://mikedeboer.github.io/node-github/) to see all the ways you can interact with GitHub. Some API endpoints are not available on GitHub Apps yet, so check [which ones are available](https://developer.github.com/v3/apps/available-endpoints/) first.

View File

@@ -1,15 +0,0 @@
---
next: docs/development.md
---
# Hello World
A Probot plugin is just a [Node.js module](https://nodejs.org/api/modules.html) that exports a function:
```js
module.exports = robot => {
// your code here
};
```
The `robot` parameter is an instance of [`Robot`](https://probot.github.io/probot/latest/Robot.html) and gives you access to all of the bot goodness.

View File

@@ -1,28 +0,0 @@
---
next: docs/simulating-webhooks.md
---
# HTTP Routes
Calling `robot.route('/my-plugin')` will return an [express](http://expressjs.com/) router that you can use to expose HTTP endpoints from your plugin.
```js
module.exports = robot => {
// Get an express router to expose new HTTP endpoints
const app = robot.route('/my-plugin');
// Use any middleware
app.use(require('express').static(__dirname + '/public'));
// Add a new route
app.get('/hello-world', (req, res) => {
res.end('Hello World');
});
};
```
Visit https://localhost:3000/my-plugin/hello-world to access the endpoint.
It is strongly encouraged to use the name of your package as the prefix so none of your routes or middleware conflict with other plugins. For example, if [`probot/owners`](https://github.com/probot/owners) exposed an endpoint, the plugin would call `robot.route('/owners')` to prefix all endpoints with `/owners`.
See the [express documentation](http://expressjs.com/en/guide/routing.html) for more information.

View File

@@ -1,15 +0,0 @@
---
next: docs/deployment.md
---
# Pagination
Many GitHub API endpoints are paginated. The `github.paginate` method can be used to get each page of the results.
```js
context.github.paginate(context.github.issues.getAll(context.repo()), res => {
res.data.issues.forEach(issue => {
robot.console.log('Issue: %s', issue.title);
});
});
```

View File

@@ -1,17 +0,0 @@
---
next: docs/pagination.md
---
# Simulating Webhooks
As you are developing your plugin, you will likely want to test it by repeatedly trigging the same webhook. You can simulate a webhook being delivered by saving the payload to a file, and then calling `probot simulate` from the command line.
To save a copy of the payload, go to the [settings](https://github.com/settings/apps) page for your App, and go to the **Advanced** tab. Click on one of the **Recent Deliveries** to expand it and see the details of the webhook event. Copy the JSON from the the **Payload** and save it to a new file. (`test/fixtures/issues.labeled.json` in this example).
![](https://user-images.githubusercontent.com/173/28491924-e03e91f2-6ebe-11e7-9570-6d48da68c6ca.png)
Next, simulate this event being delivered by running:
```
$ node_modules/.bin/probot simulate issues test/fixtures/issues.labeled.json ./index.js
```

View File

@@ -1,5 +0,0 @@
---
next: docs/pagination.md
---
# Testing

View File

@@ -1,30 +0,0 @@
---
next: docs/github-api.md
---
# Receiving Webhooks
[GitHub webhooks](https://developer.github.com/webhooks/) are fired for almost every significant action that users take on GitHub, whether it's pushes to code, opening or closing issues, opening or merging pull requests, or commenting on a discussion.
Many robots will spend their entire day responding to these actions. `robot.on` will listen for any GitHub webhook events:
```js
module.exports = robot => {
robot.on('push', async context => {
// Code was pushed to the repo, what should we do with it?
robot.log(context);
});
};
```
The robot can listen to any of the [GitHub webhook events](https://developer.github.com/webhooks/#events). The `context` object includes all of the information about the event that was triggered, and `context.payload` has the payload delivered by GitHub.
Most events also include an "action". For example, the [`issues`](https://developer.github.com/v3/activity/events/types/#issuesevent) event has actions of `assigned`, `unassigned`, `labeled`, `unlabeled`, `opened`, `edited`, `milestoned`, `demilestoned`, `closed`, and `reopened`. Often, your bot will only care about one type of action, so you can append it to the event name with a `.`:
```js
module.exports = robot => {
robot.on('issues.opened', async context => {
// An issue was just opened.
});
};
```