Skip to content

Instantly share code, notes, and snippets.

@rbren
Created January 25, 2016 23:36
Show Gist options
  • Star 3 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save rbren/fcb1843ab1341254c9b1 to your computer and use it in GitHub Desktop.
Save rbren/fcb1843ab1341254c9b1 to your computer and use it in GitHub Desktop.
Sync GitHub Issues to Trello

DataFire Daemon: Sync GitHub Issues to Trello

Create a Trello list for every Milestone, and a card for every Issue

View on DataFire

About

This Daemon syncs all the issues in a GitHub repo to a particular Trello board. Each Milestone in GH will become a new List on the Trello board, and every issue in that milestone will become a Card. Issues with no milestone will all get grouped in the same List.

The sync is one-way: if issues change in GitHub, the changes will be pulled into Trello, but not vice-versa.

Setup

  • Authorize both GitHub and Trello on the Settings page
    • Be sure to include the repo or private_repo scope for GH
    • Include all scopes (read, write, account) for Trello
  • Set the Trello board you want to edit on the Settings page
    • You can use either the board's ID, or it's name as it appears on Trello
  • Set the GitHub repository you want to watch, along with its owner

Contact

If you have any issues, contact support@datafire.io

// GET https://trello.com/1/members/{idMember}/boards
function request() {
return {idMember: 'me'}
}
// GET https://api.github.com/repos/{ownerId}/{repoId}/issues
function request(data) {
var pages = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
return pages.map(function(p) {
return {
ownerId: constants.owner,
repoId: constants.repo,
state: 'open',
page: p,
}
})
}
// GET https://trello.com/1/boards/{idBoard}/cards
function request(data) {
var board = data[0].filter(function(b) {
return b.name === constants.board || b.id === constants.board;
})[0];
if (!board) throw new Error("Could not find board " + constants.board)
return {
idBoard: board.id,
filter: 'open',
}
}
// GET https://trello.com/1/boards/{idBoard}/lists
function request(data) {
var board = data[0].filter(function(b) {
return b.name === constants.board || b.id === constants.board;
})[0];
return {
idBoard: board.id,
}
}
// GET https://api.github.com/repos/{ownerId}/{repoId}/milestones
function request(data) {
return {
ownerId: constants.owner,
repoId: constants.repo,
}
}
// POST https://trello.com/1/lists
function request(data) {
var board = data[0].filter(function(b) {
return b.name === constants.board || b.id === constants.board;
})[0];
var listsInTrello = data[3].map(function(list) {return list.name})
var milestones = data[4];
milestones.push({title: 'None'})
var newMilestones = milestones.filter(function(m) {
return listsInTrello.indexOf('Milestone: ' + m.title) === -1;
})
return newMilestones.map(function(m) {
return {
body: {
idBoard: board.id,
name: 'Milestone: ' + m.title,
}
}
});
}
// POST https://trello.com/1/cards
function request(data) {
var board = data[0].filter(function(b) {
return b.name === constants.board || b.id === constants.board;
})[0];
var descriptions = data[2].map(function(card) {return card.desc})
var issues = [];
data[1].forEach(function(page) {issues = issues.concat(page)});
var newIssues = issues.filter(function(i) {
return descriptions.indexOf('GitHub Issue ' + i.number) === -1;
})
var allLists = data[3].concat(data[5]);
return newIssues.map(function(i) {
var list = allLists.filter(function(list) {
return (list.name === 'Milestone: None' && !i.milestone) || (i.milestone && list.name === 'Milestone: ' + i.milestone.title)
})[0]
return {
body: {
idBoard: board.id,
idList: list.id,
desc: 'GitHub Issue ' + i.number,
name: i.title,
}
}
})
}
// PUT https://trello.com/1/cards/{idCard}/closed
function request(data) {
var issues = [];
data[1].forEach(function(page) {issues = issues.concat(page)});
var openIssues = issues.map(function(i) {
return 'GitHub Issue ' + i.number;
})
var closedCards = data[2].filter(function(card) {
return openIssues.indexOf(card.desc) === -1;
})
return closedCards.map(function(card) {
return {
idCard: card.id,
body: {value: true},
}
})
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment