mirror of
https://github.com/zhigang1992/probot.github.io.git
synced 2026-01-12 22:49:53 +08:00
Add docs with layout
This commit is contained in:
@@ -28,6 +28,10 @@ defaults:
|
||||
type: plugins
|
||||
values:
|
||||
layout: plugin
|
||||
- scope:
|
||||
path: "docs"
|
||||
values:
|
||||
layout: docs
|
||||
|
||||
gems:
|
||||
- jekyll-octicons
|
||||
|
||||
13
_includes/footer.html
Normal file
13
_includes/footer.html
Normal file
@@ -0,0 +1,13 @@
|
||||
<div class="bg-gray-dark text-gray">
|
||||
<div class="container-lg px-3 page-section">
|
||||
<p class="mb-3">
|
||||
<a class="text-white text-bold mr-3" href="https://github.com/probot">GitHub</a>
|
||||
<a class="text-white text-bold mr-3" href="/docs/">Docs</a>
|
||||
</p>
|
||||
<p>
|
||||
<span class="mr-2">{% octicon code %} with {% octicon heart %} by <a class="text-gray-light" href="https://twitter.com/bkeepers">@bkeepers</a></span>
|
||||
<span class="mx-2">Code licensed <a class="text-gray-light" href="https://github.com/probot/probot/blob/master/LICENSE.md">MIT</a></span>
|
||||
<span class="mx-2">Docs licensed <a class="text-gray-light" href="https://creativecommons.org/licenses/by/4.0/">CC-BY-4.0</a></span>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
17
_includes/nav.html
Normal file
17
_includes/nav.html
Normal file
@@ -0,0 +1,17 @@
|
||||
<div class="border-bottom">
|
||||
<div class="container-lg px-3">
|
||||
<div class="py-4 d-flex d-flex-row">
|
||||
<h1 class="alt-h4 col-4 lh-default v-align-middle">
|
||||
<a href="/" class="no-underline text-uppercase text-brand-blue-dark">
|
||||
<img class="v-align-middle" style="margin: -20px 8px -8px 0;" src="/assets/probot-head.png" height="36" alt="">
|
||||
Probot
|
||||
</a>
|
||||
</h1>
|
||||
<nav class="text-bold col-8 text-right">
|
||||
<a class="text-inherit px-2 d-inline-block" href="/#explore">Explore</a>
|
||||
<a class="text-inherit px-2 d-inline-block" href="/docs/">Build</a>
|
||||
<a class="text-inherit px-2 d-inline-block" href="https://github.com/probot/probot">Contribute</a>
|
||||
</nav>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -8,5 +8,7 @@
|
||||
</head>
|
||||
<body>
|
||||
{{ content }}
|
||||
|
||||
{% include footer.html %}
|
||||
</body>
|
||||
</html>
|
||||
|
||||
22
_layouts/docs.html
Normal file
22
_layouts/docs.html
Normal file
@@ -0,0 +1,22 @@
|
||||
---
|
||||
layout: default
|
||||
---
|
||||
|
||||
{% include nav.html %}
|
||||
|
||||
<div class="container-lg px-3">
|
||||
<div class="d-flex flex-row gutter-spacious">
|
||||
<div class="col-3 py-6">
|
||||
<ul class="menu">
|
||||
<li class="menu-item"><a class="d-block" href="/docs/plugins/">Getting Started</a></li>
|
||||
<li class="menu-item"><a class="d-block" href="/docs/development/">Development</a></li>
|
||||
<li class="menu-item"><a class="d-block" href="/docs/deployment/">Deployment</a></li>
|
||||
<li class="menu-item"><a class="d-block" href="/docs/best-practices/">Best Practices</a></li>
|
||||
<li class="menu-item"><a class="d-block" href="/docs/best-practices/">API Docs</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="col-9 markdown-body p-6">
|
||||
{{ content }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -2,23 +2,7 @@
|
||||
layout: default
|
||||
---
|
||||
|
||||
<div class="border-bottom bg-gray-dark text-white">
|
||||
<div class="container-lg px-3">
|
||||
<div class="py-4 d-flex d-flex-row">
|
||||
<h1 class="alt-h5 col-4 lh-default v-align-middle">
|
||||
<a href="/" class="no-underline text-uppercase text-inherit">
|
||||
<img style="margin: -12px 8px -10px 0;" src="/assets/probot-head.png" height="36" alt="">
|
||||
Probot
|
||||
</a>
|
||||
</h1>
|
||||
<nav class="text-bold col-8 text-right">
|
||||
<a class="text-inherit px-2 d-inline-block" href="/#explore">Explore</a>
|
||||
<a class="text-inherit px-2 d-inline-block" href="/#build">Build</a>
|
||||
<a class="text-inherit px-2 d-inline-block" href="https://github.com/probot/probot">Contribute</a>
|
||||
</nav>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% include nav.html %}
|
||||
|
||||
<div class="border-bottom">
|
||||
<div class="container-lg px-3 jumbotron jumbotron-minitron">
|
||||
|
||||
62
docs/best-practices.md
Normal file
62
docs/best-practices.md
Normal file
@@ -0,0 +1,62 @@
|
||||
# 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.
|
||||
|
||||

|
||||
|
||||
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.
|
||||
|
||||
For example, the [owners](https://github.com/probot/owners) plugin reads from the `OWNERS` file, which is a convention that existed before the plugin was created, while the [configurer](https://github.com/probot/configurer) plugin reads from `.github/config.yml`.
|
||||
117
docs/deployment.md
Normal file
117
docs/deployment.md
Normal file
@@ -0,0 +1,117 @@
|
||||
# Deploy
|
||||
|
||||
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
|
||||
|
||||
Your plugin should be up and running!
|
||||
|
||||
### 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"
|
||||
]
|
||||
}
|
||||
}
|
||||
```
|
||||
22
docs/development.md
Normal file
22
docs/development.md
Normal file
@@ -0,0 +1,22 @@
|
||||
# Development
|
||||
|
||||
To run a plugin locally, you'll need to create a GitHub App and configure it to deliver webhooks to your local machine.
|
||||
|
||||
1. Make sure you have a recent version of [Node.js](https://nodejs.org/) installed
|
||||
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.
|
||||
|
||||
Whenever you come back to work on the app after you've already had it running once, you should only need to run `$ npm start`.
|
||||
|
||||
## 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`
|
||||
2
docs/index.html
Normal file
2
docs/index.html
Normal file
@@ -0,0 +1,2 @@
|
||||
---
|
||||
---
|
||||
112
docs/plugins.md
Normal file
112
docs/plugins.md
Normal file
@@ -0,0 +1,112 @@
|
||||
---
|
||||
---
|
||||
|
||||
|
||||
# Plugins
|
||||
|
||||
A 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`](/lib/robot.js) and gives you access to all of the bot goodness.
|
||||
|
||||
## Receiving GitHub 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.
|
||||
});
|
||||
};
|
||||
```
|
||||
|
||||
## 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.
|
||||
|
||||
### 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);
|
||||
});
|
||||
});
|
||||
```
|
||||
|
||||
## Running plugins
|
||||
|
||||
Before you can run your plugin against GitHub, you'll need to set up your [development environment](development.md) and configure a GitHub App for testing. You will need the ID and private key of a GitHub App to run the bot.
|
||||
|
||||
Once you have an app created, install `probot`:
|
||||
|
||||
```
|
||||
$ npm install -g probot
|
||||
```
|
||||
|
||||
and run your bot from your plugin's directory, replacing `APP_ID` and `private-key.pem` below with your App's ID and the path to the private key of your app.
|
||||
|
||||
```
|
||||
$ probot run -a APP_ID -P private-key.pem ./index.js
|
||||
Listening on http://localhost:3000
|
||||
```
|
||||
|
||||
## Publishing your bot
|
||||
|
||||
Plugins can be published in NPM modules, which can either be deployed as stand-alone bots, or combined with other plugins.
|
||||
|
||||
Use the [plugin-template](https://github.com/probot/plugin-template) repository to get started building your plugin as a node module.
|
||||
|
||||
```
|
||||
$ curl -L https://github.com/probot/plugin-template/archive/master.tar.gz | tar xvz
|
||||
$ mv plugin-template-master probot-myplugin && cd probot-myplugin
|
||||
```
|
||||
|
||||
## Next
|
||||
|
||||
- [See the full Probot API](https://probot.github.io/probot/latest/)
|
||||
- [Tips for development](development.md)
|
||||
- [Deploy your plugin](deployment.md)
|
||||
@@ -6,7 +6,7 @@ layout: default
|
||||
<div class="py-4 clearfix">
|
||||
<nav class="text-bold d-block float-right">
|
||||
<a class="text-inherit px-2 d-inline-block" href="/#explore">Explore</a>
|
||||
<a class="text-inherit px-2 d-inline-block" href="/#build">Build</a>
|
||||
<a class="text-inherit px-2 d-inline-block" href="/docs/">Build</a>
|
||||
<a class="text-inherit px-2 d-inline-block" href="https://github.com/probot/probot">Contribute</a>
|
||||
</nav>
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user