Sync Github Issues with Asana Board Tasks
Tags: opensource, reshuffle, github, asana
Published: 2021-01-25 17:28:04

Github issues are a great way to keep track of enhancements, bugs and tasks for your project. It provides a forum like space for outside developers to give feedback. It’s a great tool for smaller teams to keep track of tasks but as your product grows, and more repositories are made, going back and forth between repositories for task management is just not ideal.

Most teams are using project management tools like Asana. But what about the bug tracking from the repositories? It would be quite bothersome to scroll through and find all ‘bug’ labeled issues and then add them onto an Asana board. Is there a way to synchronize Github issues to be automatically added as a task on Asana? Certainly, there are a number of solutions that can be found on the web.

Having one platform to track all project tasks and bug reports would create a much more efficient workflow for the entire team. In this article, we’ll see a bi-directional sync between Asana and Github. To keep things simple, any new issues created on Github with the label of ‘bug’ will automatically be added as a task on Asana, if the task is marked as complete on Asana, the issue will be closed on Github’s end. This will be a great starting point to show how easily customizable it is for you and your team's needs.

In this example, you will not only learn how to integrate these, but also see how you can customize the integration to fit your team’s workflow using [Reshuffle](https://dev.reshuffle.com/).

Reshuffle is an open source, lightweight, and event-driven framework that helps you integrate services — these integrations and workflows are created inside a Reshuffle App. The objects that let you interact with these services are called connectors.

##Prerequisites

Before we jump in with the code, we’ll need to get credentials set up with Github and Asana.

__Github:__
- Log in and generate a token [here](https://github.com/settings/tokens)
- Save the token somewhere, as you'll need it soon

__Asana:__
- Log in and go [here](https://app.asana.com/0/developer-console)
- Under `Personal Access Token`' > `+ New Access Token`
- Name the token and save the token somewhere, you’ll use it soon
- You’ll need the workspace ID. To find this, go to the Asana Admin Console page and it will be in the URL:

![Admin-Console](https://i.imgur.com/fXXWZ1J.png)

##How to Build It

To get started, first we need to bring in the required packages to build this example. Then initiate a Reshuffle app and configure the Github and Asana connectors with the credentials we saved earlier.

___Note: To test this example locally, a tool like [ngrok](https://ngrok.com/) can be used to generate a url that exposes your localhost over SSL for Asana and Github Connectors as the baseUrl___

```javascript
const { Reshuffle, HttpConnector } = require("reshuffle");
const { AsanaConnector } = require("reshuffle-asana-connector");
const { GitHubConnector } = require("reshuffle-github-connectors");
 
 const app = new Reshuffle();
 
 //Github Config
 const githubConnector = new GitHubConnector(app, {
   token: process.env.GITHUB_TOKEN,
   runtimeBaseUrl: process.env.RUNTIME_BASE_URL,
 });
 // Asana config
 const asanaConnector = new AsanaConnector(app, {
   accessToken: process.env.ASANA_ACCESS_TOKEN,
   baseURL: process.env.RUNTIME_BASE_URL,
   workspaceId: process.env.ASANA_WORKSPACE_ID,
 });
 
 // Code listed further down
 // will be inserted here
app.start()

```
Reshuffle Connectors provide events and actions that allow developers to easily build custom workflows and integrations. With the connectors configured, we can now make use of what they can offer.

First up, we’ll build a one way sync from Github to Asana. As Reshuffle is an event-driven framework, we’ll need to define the event we want to listen to. In this case, from Github’s end, we will listen to the ‘issues’ event on a given repository.

```javascript
// will see this action in play further down
const project = await asanaConnector
.sdk()
.projects.findById(process.env.ASANA_PROJECT_ID);
 
githubConnector.on(
 {
   owner: process.env.GITHUB_OWNER,
   repo: process.env.GITHUB_REPO,
   githubEvent: "issues",
 },
 async (event, app) => {
   // handler code will come here  
 }
);

```
Next, we will need to handle the event that has been triggered. When an issue is either ‘opened’ or ‘reopened’, we will first fetch all the tasks in Asana with the tag of ‘bug’, using the `findByTag` action provided by the Asana Connector - to prevent any duplicate tasks from being created, we’ll compare the names between the Github event title and the Asana task name.

___Note: For simplicity, we are only going to compare the names to prevent duplicates, you and your team can handle this your own way to keep things more unique.___

If there are no duplicate names, it will continue to create the new task on the Asana board using the `createInWorkspace` action. This action will need the workspace ID (found on the project object retrieved earlier from the Asana connector) and followed by the task data to be saved on the board.

___Note: `findByTag` takes in an ID relating to certain tags in Asana, in this case, the tag passed in is the ‘bug’ tag.___

```javascript
const { data } = await asanaConnector
   .sdk()
   .tasks.findByTag("1199621513855890");
 
const foundTask = data.find((task) => {
 return event.issue.title === task.name;
});
if (["opened", "reopened"].includes(event.action) && event.issue.labels[0].name === "bug") {
 if (foundTask) {
   return;
 } else {
   const task = await asanaConnector
     .sdk()
     .tasks.createInWorkspace(project.workspace.gid, {
       name: event.issue.title,
       projects: process.env.ASANA_PROJECT_ID,
       tags: "1199621513855890",
     });
 }
}

```
___Note: the key ‘projects’ in the task data determines which project you want this task to be placed in.___

Similar to the event where an issue is opened, we can also decide what happens when the issue is closed. We can either mark it as complete or just delete it completely from the board. Here I am choosing to delete it. With the same strategy as before, find the matching task name, if it is found, we can simply delete the task using the ‘delete’ action.

```javascript
if (event.action === "closed") {
 if (foundTask) {
   await asanaConnector.sdk().tasks.delete(foundTask.gid);
 }
}
```
With that, we can create and delete Asana tasks when opening / closing an issue on Github’s end. This is awesome, but the example wouldn’t bi-directional if I didn’t include how events are handled from Asana’s side.

Very similar to how we handle things with Github events, we’ll need to define an Asana event to listen to. In this case, to keep this example from going on too long, we’ll only handle the event when a task on Asana is marked ‘complete’.

```javascript
asanaConnector.on(
 { gid: process.env.ASANA_PROJECT_ID, asanaEvent: "changed" },
 async (event, app) => {
   if (event.change.field === "completed_at") {
     //get the details for the completed task
     const taskDetails = await asanaConnector
       .sdk()
       .tasks.findById(event.resource.gid);
   //more handler code to come
   }
 }
);
```
When this event is triggered, we will need to grab the full details of the task that triggered the event using the `findById` action. Then we will check to see if this event has the same tag ID used in the Github event. If there’s a match it's safe to assume this task was created from Github, but to be sure, we will get the list of open issues and compare the names as we did before. If there’s a match on the name, we can update the issue to close it.

```javascript
if (taskDetails.tags[0].gid === "1199621513855890") {
 const { data } = await githubConnector.sdk().issues.listForRepo({
   repo: process.env.GITHUB_REPO,
   owner: process.env.GITHUB_OWNER,
   state: "open",
 });
 const foundIssue = data.find((issue) => {
   return issue.title === taskDetails.name;
 });
 if (foundIssue) {
   await githubConnector.sdk().issues.update({
     repo: process.env.GITHUB_REPO,
     owner: process.env.GITHUB_OWNER,
     issue_number: foundIssue.number,
     state: "closed",
   });
 }
}
```
With that, we have completed a simple bi-directional sync between Asana and Github. If you are interested in developing this further to suit you or your team's needs, please check out the documentation for the connectors.

__Full Documentation:__
- [Reshuffle](https://www.reshuffle.com/docs/intro-to-reshuffle)
- [Github Connector](https://www.reshuffle.com/docs/GithubConnector)
- [Asana Connector](https://www.reshuffle.com/docs/AsanaConnector)

{% youtube xJms8Mx1lSY %}

##Now, Make it Happen

As your developers and project management teams experience the ease of working with integrated applications, we encourage you to consider where else integrating workflows would benefit your teams. With so many different tools, the more you can consolidate them into one common interface, the easier people can get work done. 

Reshuffle is continually listening to what our customers need and desire. Don’t see a Connector to a service you’d like to integrate? Send a tweet to [@ReshuffleHQ](https://twitter.com/reshufflehq) to let us know which Connector you’d like us to develop next.