Generally speaking, adding database storage or persistence to your Probot App will greatly complicate your life. It's perfectly doable, but for most use-cases you'll be able to manage relevant data within GitHub issues, pull requests and your app's configuration file.
Contents:
Probot includes a wrapper for the GitHub API which can enable you to store and manipulate data in the GitHub environment. Since your Probot App will usually be running to supplement work done on GitHub, it makes sense to try to keep everything in one place and avoid extra complications.
context.config()
allows storing configuration in the repository or the organization's .github
repository.If your Probot App needs to store more data than Issues and Pull Requests store normally, you can use the probot-metadata
extension to hide data in comments. It isn't meant to be super secure or scalable, but it's an easy way to manage some data without a full database.
There are even more APIs that you can use to increase the functionality of your Probot App. You can read about all of the ones available in Probot on the @octokit/rest
documentation.
For when you absolutely do need external data storage, here are some examples using a few popular database solutions. Note that these are just suggestions, and that your implementation will vary.
MongoDB is a popular NoSQL database, and Mongoose is a widely used Node.js wrapper for it.
// PeopleSchema.js
import * as mongoose from "mongoose";
const Schema = mongoose.Schema;
const PeopleSchema = new Schema({
name: {
type: String,
required: true,
},
});
export default mongoose.model("People", PeopleSchema);
// index.js
import * as mongoose from "mongoose";
// Connect to the Mongo database using credentials
// in your environment variables
const mongoUri = `mongodb://${process.env.DB_HOST}`;
mongoose.connect(mongoUri, {
user: process.env.DB_USER,
pass: process.env.DB_PASS,
useMongoClient: true,
});
// Register the mongoose model
import People from "./PeopleSchema.js";
export default (app) => {
app.on("issues.opened", async (context) => {
// Find all the people in the database
const people = await People.find().exec();
// Generate a string using all the peoples' names.
// It would look like: 'Jason, Jane, James, Jennifer'
const peoplesNames = people.map((person) => person.name).join(", ");
// `context` extracts information from the event, which can be passed to
// GitHub API calls. This will return:
// { owner: 'yourname', repo: 'yourrepo', number: 123, body: 'The following people are in the database: Jason, Jane, James, Jennifer' }
const params = context.issue({
body: `The following people are in the database: ${peoplesNames}`,
});
// Post a comment on the issue
return context.octokit.issues.createComment(params);
});
};
Using the @databases/mysql
module, we can connect to our MySQL database and perform queries.
// connection.js
import { connect } from "@databases/mysql";
// DATABASE_URL = mysql://my-user:my-password@localhost/my-db
const connection = connect(process.env.DATABASE_URL);
export default connection;
// index.js
import { sql } from "@databases/mysql";
import connection from "./connection.js";
export default (app) => {
app.on("issues.opened", async (context) => {
// Find all the people in the database
const people = await connection.query(sql`SELECT * FROM people`);
// Generate a string using all the peoples' names.
// It would look like: 'Jason, Jane, James, Jennifer'
const peoplesNames = people.map((key) => people[key].name).join(", ");
// `context` extracts information from the event, which can be passed to
// GitHub API calls. This will return:
// { owner: 'yourname', repo: 'yourrepo', number: 123, body: 'The following people are in the database: Jason, Jane, James, Jennifer' }
const params = context.issue({
body: `The following people are in the database: ${peoplesNames}`,
});
// Post a comment on the issue
return context.octokit.issues.createComment(params);
});
};
Using the @databases/pg
module, we can connect to our Postgres database and perform queries.
// connection.js
import { connect } from "@databases/pg";
// DATABASE_URL = postgresql://my-user:my-password@localhost/my-db
const connection = connect(process.env.DATABASE_URL);
export default connection;
// index.js
import { sql } from "@databases/pg";
import connection from "./connection.js";
export default (app) => {
app.on("issues.opened", async (context) => {
// Find all the people in the database
const people = await connection.query(sql`SELECT * FROM people`);
// Generate a string using all the peoples' names.
// It would look like: 'Jason, Jane, James, Jennifer'
const peoplesNames = people.map((key) => people[key].name).join(", ");
// `context` extracts information from the event, which can be passed to
// GitHub API calls. This will return:
// { owner: 'yourname', repo: 'yourrepo', number: 123, body: 'The following people are in the database: Jason, Jane, James, Jennifer' }
const params = context.issue({
body: `The following people are in the database: ${peoplesNames}`,
});
// Post a comment on the issue
return context.octokit.issues.createComment(params);
});
};
Firebase is Google's services-as-a-service that includes a simple JSON database. You can learn more about dealing with the JavaScript API here. Note that for security purposes, you may also want to look into the Admin API.
// index.js
import * as firebase from "firebase";
// Set the configuration for your app
// TODO: Replace with your project's config object
const config = {
apiKey: "apiKey",
authDomain: "projectId.firebaseapp.com",
databaseURL: "https://databaseName.firebaseio.com",
};
firebase.initializeApp(config);
const database = firebase.database();
export default (app) => {
app.on("issues.opened", async (context) => {
// Find all the people in the database
const people = await database
.ref("/people")
.once("value")
.then((snapshot) => {
return snapshot.val();
});
// Generate a string using all the peoples' names.
// It would look like: 'Jason, Jane, James, Jennifer'
const peoplesNames = Object.keys(people)
.map((key) => people[key].name)
.join(", ");
// `context` extracts information from the event, which can be passed to
// GitHub API calls. This will return:
// { owner: 'yourname', repo: 'yourrepo', number: 123, body: 'The following people are in the database: Jason, Jane, James, Jennifer' }
const params = context.issue({
body: `The following people are in the database: ${peoplesNames}`,
});
// Post a comment on the issue
return context.octokit.issues.createComment(params);
});
};
Found a mistake or want to help improve this documentation? Suggest changes on GitHub