I still think PRobot is a good idea, but I'm going to be honest and say that it really sucks right now. You can't do much with the current feature set, and implementing new features is hard and confusing.
After talking with @groundwater, I would like to take PRobot in a very different direction for a while. Feedback on this would be appreciated.
Thus far the aim has been to expose useful GitHub APIs through a jQuery-style API that is safe-ish to run on a single hosted instance. Eventually, I think that is the right idea, but right now, it's a premature optimization. It makes it much less useful because people can only use PRobot for things have been implemented in this custom API.
So I'd like to remove the existing API right now, focus on building a good stand-alone bot framework that can make use of any existing node libraries, and then later figure out how to provide a simple API and run it on a hosted instance.
Here's basically the new proposed roadmap:
- v0.1 - GitHub bot framework
- v1.0 - Hosted GitHub Integration
- v2.0 - High-Level API
v0.1- GitHub bot framework
This will make it really easy to create new bots by abstracting the details of handling webhooks and building a GitHub Integration.
For example, here is an autoresponder module that comments on opened issues with the template in github/AUTOREPLY_TEMPLATE.md
:
// Export a function that takes `robot` as an argument
module.exports = function(robot) {
// `robot.on` will listen for any GitHub webhook events
robot.on('issues.opened', async function(event, context) {
// `context` extracts information from the event, which can be passed to
// GitHub API calls.
const options = context.repo({path: '.github/AUTOREPLY_TEMPLATE.md'});
// This returns:
// {owner: 'yourname', repo: 'yourrepo', path: '.github/AUTOREPLY_TEMPLATE.md'}
// `context.github` is an instance of the NodeJS wrapper for the GitHub API
// https://mikedeboer.github.io/node-github/
const data = await context.github.repos.getContent(options);
const template = new Buffer(data.content, 'base64').toString();
return context.github.issues.createComment(context.issue({body: template}));
});
}
This bot would be run locally with the probot
command, which will start up a server and listen for GitHub webhooks:
$ probot autoresponder.js
Listening on http://localhost:5000
Here's a more sophisticated bot based on github-configurer, which will update GitHub settings for a repository whenever .github/config.yml
is modified.
module.exports = robot => robot.on('push', push);
const configurer = require('github-configurer');
const FILE_NAME = '.github/config.yml';
async function push(event, context) {
const payload = event.payload;
const defaultBranch = payload.ref === 'refs/heads/' + payload.repository.default_branch;
const configModified = payload.commits.find(commit => {
return commit.added.includes(FILE_NAME) || commit.modified.includes(FILE_NAME);
});
if (defaultBranch && configModified) {
const options = {
owner: payload.repository.owner.name,
repo: payload.repository.name,
path: FILE_NAME
};
const data = await context.github.repos.getContent(options);
const content = new Buffer(data.content, 'base64').toString();
return configurer(context.github, options, content).update();
}
}
These examples can be published as behaviors in NPM modules (e.g. probot-autoresponder
and probot-configurer
) and deployed as stand-alone bots, or combined into one instance.
For example, if you wanted to deploy a bot for your project that included both of these behaviors, you could just create a new app that has them both listed as dependencies in package.json
:
{
"name": "my-probot",
"priate": true,
"dependencies": {
"probot-autoresponder": "~1.0",
"probot-configurer": "~1.0",
},
"scripts": {
"start": "probot"
}
}
Running the $ npm start
on this app would start up a bot that included both of these behaviors.
This approach creates a ton of flexibility. The core of probot
will handle the GitHub Integration and provide some basic services. Behaviors will be relatively easy to implement and reuse, and more importantly they'll be free to experiment and explore new patterns.
Hosted GitHub Integration
Later we can explore the idea of providing a single hosted integration and allowing people to run their probot behaviors directly from their repository via a .probot.js
file.
High-Level API (current version)
Finally, after there is some adoption and people are writing a lot of behaviors, I'd like to revisit the idea of exposing a friendlier and more expressive API that allows combining common actions in a chainable manner like we currently have:
on('issues.labeled')
.filter(event => event.payload.label.name == 'plugins')
.comment('Hey @jekyll/plugins, the `plugins` label was added');
Thoughts?
cc @lee-dohm @zeke @migarjo @jonico