Skcript's LogoSudo vs Root
Skcript's Logo

Announcing GitInfo - GitHub app for Google Assistant [Open Source]

Here’s how you can build your own Google Assistant App for GitHub! We’re open sourcing this and worry not, it’s legit cool stuff!

Announcing GitInfo - GitHub app for Google Assistant [Open Source]

Currently reading:

Announcing GitInfo - GitHub app for Google Assistant [Open Source]

Yes, you all read the title right. It’s possible to make a Google Assistant App for GitHub! As a developer, I’ve always wanted to know the number of bugs or issues in my repo very often - so I thought why not make an assistant app for the same?

For the implementation of this project, please go through the full code here - you can also clone it to get a better understanding.

First things first, prepare all the nuts and bolts as shown here for API.AI and Google Actions setup. We will be setting up our own node client using heroku in this project.

The working model:

GitInfo

Now from the list of repositories we can choose any to get some details and insights about it. So here we go,

GitInfo

It’ll always be great for the owner of the repo to see that “0 open issues” including mine. So we can try out description and some commit details as well.

GitInfo

GitInfo

It’s now very easy to get to know the number of stars available for the particular GitHub repository. Every developer would just love that Github star including me! ⭐️

I love Github so much! Who doesn’t?! I thought of different ways to make Github more easy to use. While initializing the thought process, I thought of utilizing the Github APIs to the fullest and build something new. Then I thought why not an assistant app? So think of this environment where you code something seriously but you want to know who made the latest commit you can just get it with your voice sounds! Cool and easy isn’t it? ☺️

Let’s now explore the approach.

First let’s initialize ApiAiApp object,

const ApiAiApp = require('actions-on-google').ApiAiApp;
const app = new ApiAiApp({request: req, response: res});
app.handleRequest(responseHandler);

Then based on the intent’s action name that we defined in our API.AI console we can build this responseHandler() function.

function responseHandler (app) {
  // intent contains the name of the intent you defined in the Actions area of API.AI
  let intent = app.getIntent();
  switch (intent) {
    
    case WELCOME_INTENT:
         app.ask('Welcome! Tell about which git organization you wanna hear ?');
         break;
 
    case ORGANIZATION_NAME:
         app.data.organization = app.getRawInput();
         git.getRepositories(app.data.organization,function (err, stream){      
         for(var i=0;i<JSON.parse(stream).length;i++)
         {
                 repoList.push(JSON.parse(stream)[i].name);
         }
         list(app,repoList,'Choose a git repo from this list of available repos : ');            
         });
        break;
 
    case REPO_NAME:
          app.data.repo=app.getRawInput()
          list(app,suggestionsList,'Choose one of the available git info we provide');
          break;
 
    case STARS_COUNT:
         git.getRepoDetails(app.data.organization,app.data.repo,function (err, stream){     
         app.ask("There are total of "+JSON.parse(stream).stargazers_count+" stars for this repo.");
         });
         break;
 
    case BUGS_COUNT:
         git.getRepoDetails(app.data.organization,app.data.repo,function (err, stream){     
         app.ask("There are total of "+JSON.parse(stream).open_issues_count+" open issues for this repo.");
         });
         break;
 
    case FORKS_COUNT:
         git.getRepoDetails(app.data.organization,app.data.repo,function (err, stream){     
         app.ask("There are total of "+JSON.parse(stream).forks_count+" forks for this repo.");
         });
         break;
 
    case DESCRIPTION:
         git.getRepoDetails(app.data.organization,app.data.repo,function (err, stream){     
         app.ask(JSON.parse(stream).description);
         });
         break;
 
    case COMMITS_INFO:
         git.getCommitInfo(app.data.organization,app.data.repo,function (err, stream){     
         app.ask(JSON.parse(stream)[0].commit.author.name+' made the latest commit at '+JSON.parse(stream)[0].commit.author.date+' and there are total of '+JSON.parse(stream).length+' commits made.');
         });
         break;                   
  }
}

Based on the intent all the events will be triggered.

For a good card based suggestions view, we can use this function where suggestions are passed as an array to the list function,

var suggestionsList=['DESCRIPTION','STARS', 'BUGS COUNT', 'FORKS', 'COMMITS'];

Here richResponse is a string that will be displayed as heading the above suggestions,

function list (app,lists,richResponse) {
  app.ask(app.buildRichResponse()
    .addSimpleResponse(richResponse)
    .addSuggestions(lists)
    );
}

Then of course we should make two Github API calls - one for getting all the repositories available and one for getting details about a particular repo,

exports.getRepositories = function(organizationName,cb) {
var options = {
    url: 'https://api.github.com/orgs/' + organizationName + '/repos',
    method: 'GET',
    headers: {
    'User-Agent': 'request'
  }
};
function callback(error, response, body) {
  if (!error && response.statusCode == 200) {
          console.log(body)
    cb(null,body)
  }
}
request(options, callback);
};
 
exports.getRepoDetails = function(organizationName,repoName,cb) {
var options = {
    url: 'https://api.github.com/repos/' + organizationName + '/'+repoName,
    method: 'GET',
    headers: {
    'User-Agent': 'request'
  }
};
function callback(error, response, body) {
  if (!error && response.statusCode == 200) {
    cb(null,body)
  }
}
 
request(options, callback);
 
};
 
exports.getCommitInfo = function(organizationName,repoName,cb) {
var options = {
    url: 'https://api.github.com/repos/' + organizationName + '/'+repoName+'/commits',
    method: 'GET',
    headers: {
    'User-Agent': 'request'
  }
};
function callback(error, response, body) {
  if (!error && response.statusCode == 200) {
    cb(null,body)
  }
}
 
request(options, callback);
 
};

The JSON response is sent as call back and then we parse only the detail the user asked for which we track using the Intent that gets triggered.

Please refer to my Github repository for the complete code: Ramkishorevit/GitInfo-Git-for-Google-Assistant

Now (assuming) that you’ve referred to my github code let us now host it in heroku. It’s very simple - install heroku first to your system. Then follow this, Heroku NodeJS Setup

Then after its hosted, bang! We are done! Just paste your webhook url in your API.AI console so every time a request comes from the user to API.AI, it’s going to get the response from our node client or webhook and this will return the response based on the intents and entities we classified.

So that’s it folks let’s all build amazing products for Google Assistant. If you want to contribute to this project and take Git to a whole new level, then feel free to open issues and send pull requests ‘cause I’m very open to open source!

Just code and just Git! 😉

Share article on

Join our community of over 4500+ readers.

Comments and Discussions

NEXT ARTICLE

Static Sites with Blogs using Middleman - Part 1