Sustainability of open source is a huge problem, especially in a world where all software depends, one way or the other, on open-source software to run. There are many ways to help and thank open-source maintainers but, IMHO, the only scalable option to make OSS sustainable is the use of bots.

There is already a fair number of bots to help in software development taking care of repetitive tasks, mainly at the code level. And that’s good, but not enough. I think bots can do much more in order to enable maintainers to focus on important tasks. But for that, bots must be able to talk and interact with the community. As an example, we introduce today our first chatbot for GitHub.

Build with Xatkit (our open-source low-code chatbot development platform), the bot allows you to “talk” with your repositories from Slack. We focus on two relevant scenarios:

For maintainers: the chatbot notifies you when a new issue is opened in Slack. You can assign the issue and add labels to it from Slack itself For users: You can file a bug report via the chatbot. Slack (or any other input platform) is probably more user-friendly than GitHub itself. And even more importantly, the chatbot will make sure you don’t forget any relevant information when filing the report. Otherwise, you and the maintainer will waste plenty of back and forth time collecting all the data needed to reproduce the bug.

Even if we focus on these use cases as “inspiration”, you can easily build your own chatbots for GitHub. With the predefined Xatkit GitHub platform, the sky is the limit. Combine it with the Slack one or the default web interface and start developing GitHub chatbots in no time and with almost no code.

From GitHub to Slack: receiving and reacting to GitHub notifications

Let’s first see how we can get notified in Slack of things happening in GitHub. In this example, we’ll just look at “New issue” notifications. The bot should be able to:

Receive New Issue notifications from GitHub Save time to the maintainer by enabling her to assign a label to the issue and a potential developer that could follow-up on it

In Xatkit, you define the bot behaviour via two different files: the intent library (that specifies the potential intentions of the user when talking to the chatbot) and the execution model (that defines how to react to the user intentions or other events directly received by the bot). All the code for this example is fully available, we’ll just show some code excerpts to give you an idea of how the bot works (take a look to the Stargazer Bot, that alerts you when somebody starts your project).

To process the OpenIssue notification and forward it to Slack, we just need to write this piece of code

1 2 3 4 on event Issue_Opened do action SlackPlatform.PostMessage(message : "An issue has been opened with the title " + context(issue).get("issue->title"), channel: config(slack.channel)) def issue = action GithubPlatform.GetIssue(user : config(github.repository.username), repository : config(github.repository.name), issueNumber : context(issue).get("issue->number")) session.store("issue", issue) on event Issue_Opened do action SlackPlatform.PostMessage(message : "An issue has been opened with the title " + context(issue).get("issue->title"), channel: config(slack.channel)) def issue = action GithubPlatform.GetIssue(user : config(github.repository.username), repository : config(github.repository.name), issueNumber : context(issue).get("issue->number")) session.store("issue", issue)

where we get the issue information from the event and post it to Slack (SlackPlatform is part of the predefined Slack platform in Xatkit). The issue itself is also stored in the session for further use.

Once the maintainer gets the notification, the chatbot starts listening to see if the maintainer expresses any intention to add a label or assign a user to it. These intents definitions will try to match whatever the maintaner writes in Slack to these two potential actions.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 intent SetLabel { requires context issue inputs { "Set label Label" "Give label Label" } creates context issue { sets parameter issueLabel from fragment Label (entity any) } } intent AssignUser { requires context issue inputs { "Assign user Username" "Username will take care of it" } creates context issue { sets parameter assignedUsername from fragment Username (entity any) } } intent SetLabel { requires context issue inputs { "Set label Label" "Give label Label" } creates context issue { sets parameter issueLabel from fragment Label (entity any) } } intent AssignUser { requires context issue inputs { "Assign user Username" "Username will take care of it" } creates context issue { sets parameter assignedUsername from fragment Username (entity any) } }

Note that intents are defined via a set of training sentences. Training sentences try to represent the different ways a maintainer can express that intention (e.g. set label or give label). Thanks to our DialogFlow integration, additional variations will also be recognized: see the following dialog, where I write “Add label” instead of Set or Give.

After this chat, the new issue gets properly tagged and assigned in the GitHub repo. No need for the maintainer to move out of Slack to do so. The execution actions associated with the intents take care of this.

1 2 3 on intent SetLabel do action GithubPlatform.SetLabel(issue : session.get("issue"), label : context(issue).get("issueLabel")) action SlackPlatform.Reply(message : "Done!") on intent SetLabel do action GithubPlatform.SetLabel(issue : session.get("issue"), label : context(issue).get("issueLabel")) action SlackPlatform.Reply(message : "Done!")

Filing a bug report from Slack

If you look at any OSS project, the first iterations in any new bug report are basically the maintainer trying to get from the user who submitted the report all the information needed to reproduce it.

This is a huge waste of time for both sides. And one that delays significantly the bug fixing since the communication is not synchronous so depending on the respective availability and time zones, it can go on for a few days.

I’ll show you how a chatbot can make sure a bug report has all the basic information a maintainer needs. In the example, we assume the project is a WordPress plugin. Typically, to debug a potential error there we always need to know the WP version and the PHP version the website is running. So to illustrate the capabilities of our chatbot approach for GitHub we’ll make sure the chatbot collects this information.

We start by defining the intents. Note that some of the intents are only possible after a previous intent has been matched. Some of the intents store conversation data that we’ll be used to open the bug at the end.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 intent OpenBug { inputs { "The plugin is not working" "I have a problem with the plugin" "I'd like to report an error" "I want to open a bug" "I want to report a bug" "There is an error in the plugin" } } intent DescribeBug follows OpenBug { inputs { "My error is Error" "The problem is Error" "I get this error: Error" "My error is that Error" "The problem is that Error" "I get the error Error" } creates context bug { sets parameter title from fragment Error (entity any) } } intent TellWPVersion follows DescribeBug { requires context bug inputs { "My version number is WPVersion" "I use number WPVersion" "It's version WPVersion" } creates context bug { sets parameter wpversion from fragment WPVersion (entity number) } } intent TellPHPVersion follows TellWPVersion { requires context bug inputs { "My version is PHPVersion" "I use PHPVersion" "It's version PHPVersion" "The server is on php version PHPVersion" } creates context bug { sets parameter phpversion from fragment PHPVersion (entity number) } } intent OpenBug { inputs { "The plugin is not working" "I have a problem with the plugin" "I'd like to report an error" "I want to open a bug" "I want to report a bug" "There is an error in the plugin" } } intent DescribeBug follows OpenBug { inputs { "My error is Error" "The problem is Error" "I get this error: Error" "My error is that Error" "The problem is that Error" "I get the error Error" } creates context bug { sets parameter title from fragment Error (entity any) } } intent TellWPVersion follows DescribeBug { requires context bug inputs { "My version number is WPVersion" "I use number WPVersion" "It's version WPVersion" } creates context bug { sets parameter wpversion from fragment WPVersion (entity number) } } intent TellPHPVersion follows TellWPVersion { requires context bug inputs { "My version is PHPVersion" "I use PHPVersion" "It's version PHPVersion" "The server is on php version PHPVersion" } creates context bug { sets parameter phpversion from fragment PHPVersion (entity number) } }

This is an example dialog with this chatbot.

And once all the error info has been gathered, we just need to put it all together and open an issue with it. As you can see in the following code excerpt, once the last intent has been matched we ask GitHub to create a new issue with the title and body parameters we collected along the way. We end up labeling the new issue as a bug.

1 2 3 4 5 6 on intent TellPHPVersion do action SlackPlatform.Reply(message : "Thanks for your detailed info") def newissue = action GithubPlatform.OpenIssue(user : "jcabot", repository : "xatkit-tests", issueTitle : context(bug).get("title") , issueContent : "WP version is " + context(bug).get("wpversion") + " PHP version is " + context(bug).get("phpversion") ) action GithubPlatform.SetLabel(issue : newissue, label : "bug") on intent TellPHPVersion do action SlackPlatform.Reply(message : "Thanks for your detailed info") def newissue = action GithubPlatform.OpenIssue(user : "jcabot", repository : "xatkit-tests", issueTitle : context(bug).get("title") , issueContent : "WP version is " + context(bug).get("wpversion") + " PHP version is " + context(bug).get("phpversion") ) action GithubPlatform.SetLabel(issue : newissue, label : "bug")

This generates as end result the following issue created from the above dialog.



To sum up, in a few lines of code we’ve been able to create a bidirectional Slack-GitHub chatbot to help open source maintainers. This was just an example but I hope it’s a good enough example to showcase the potential of (chat)bots to significantly improve the sustainability of open-source.