Sync GitHub Issues With Asana Board Tasks
A full stack developer gives a tutorial on how to connect GitHub and Asana so that issues boards are automatically updated with GitHub issues.
Join the DZone community and get the full member experience.
Join For FreeGitHub 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.
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.
- Save the token somewhere, as you'll need it soon.
Asana:
- Log in and go here.
- 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:
How to Build It
To get started, we first 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 can be used to generate a URL that exposes your localhost over SSL for Asana and GitHub Connectors as the baseUrl.
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 to which we want to listen. In this case, from GitHub’s end, we will listen to the ‘issues’ event on a given repository.
xxxxxxxxxx
// 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.
xxxxxxxxxx
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 in which project you want this task to be placed.
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.
xxxxxxxxxx
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.’
xxxxxxxxxx
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.
xxxxxxxxxx
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:
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 to let us know which Connector you’d like us to develop next.
Published at DZone with permission of Alan Lee. See the original article here.
Opinions expressed by DZone contributors are their own.
Comments