How to use the Github API?

As a developer you may use Github to maintain, share and create your project. The Github API allows you to ease your work. As an example, I will share my experience: checking all pull requests without leaving Slack.

Setup

To allow us to speak with Github and Slack, we are going to use a bot. Quite original isn’t it?

For more precision, we are using ES6 and Lodash which make JavaScript easier to read and use.

index.js

/**
 * Setting and launching the Slack process for the bot
 * @module GithupApi
 */
import Botkit from 'botkit';

import logger from './config/winston';
import { token, options, channel } from './config';
import githubService from './services/github.service';


/**
 * Starts the bot and register the services
 * @return { Promise } A promise to resolve.
 */
const start = () => new Promise((resolve, reject) => {
  const controller = Botkit.slackbot(options);

  return controller.spawn({ token }).startRTM((err, bot) => {
    if (err) {
      return reject(err);
    }
    // Register the dedicated services
    githubService(controller);

    // Join the channel
    bot.api.channels.join(channel);

    return resolve(bot);
  });
});

// if the service is not launched, we start it
if (!module.parent) {
  start()
  .then(bot => process.on('SIGINT', () => {
    bot.closeRTM();
    process.exit();
  }))
  .catch(err => logger.error(err));
} else {
  module.exports = { start };
}

Making the service

1/ The service use the hears() function provided by Botkit listen to the message.

github.service.js

  controller.hears('pr_list', 'direct_message,direct_mention,mention', (bot, message) =>

2/The request of Github Api: the URL start by https://api.github.com, next we want to get all the pull requests names within an organization. Github doc

Don’t forget to included the Header: You must add the authorization and provide a custom media type. The authorization needs your Github Token and your Github username.

config/index.js

// This is your environment variable
export const token = process.env.SLACK_TOKEN || '';
export const options = {
  debug: process.env.DEBUG || false,
};
export const channel = process.env.BOT_CHANNEL || '';

// This is the header for the request
export const optionsRequest = {
  auth: {
    user: '',
    pass: process.env.GIT_TOKEN,
    sendImmediatly: false,
  },
  headers: {
    Accept: 'application/vnd.github.inertia-preview+json',
    ContentType: 'application/json'
  },
  json: true,
};

3/ We gather all the promises to return a single promise in an array of values, running each names of the repos. With this values, we can do the next request to get the list of the pull requests

4/ At last with the list of pull requests, we trigger a reply to the message by our bot. To make your answer nice-looking, you can use the attachments from Slack API

github.service.js

import request from 'request';
import Promise from 'bluebird';
import { map, flatten, forEach } from 'lodash';

import { optionsRequest } from '../config';

// The Github organization name
export const userOrg = process.env.USER_ORG || '';

// Attachments is the message of the Pull Request Promise sent to slack.
const attachments = pr => [{
  title: `Repositories : ${pr.base.repo.name}`,
  text: `Title : ${pr.title}
   Url: ${pr.html_url}
   Description: ${pr.body}
   Code: ${pr.base.repo.name}${pr.number}`,
  color: '#F0A212',
}];

export default (controller) => {
  controller.hears('pr_list', 'direct_message,direct_mention', (bot, message) =>
  // Promise to collect the list of pr.
    request(`https://api.github.com/orgs/${userOrg}/repos`, optionsRequest, resolver(resolve, reject)))
     .then(data => Promise.all(map(data, repo => new Promise((resolve, reject) =>
       request(`https://api.github.com/repos/${repo.owner.login}/${repo.name}/pulls`,
        optionsRequest, resolver(resolve, reject))))));
  .then(data => forEach(flatten(data), pr =>
      bot.reply(message, { attachments: attachments(pr) }))));

conclusion

Result