request = require 'request' Restzilla = require 'restzilla' BUGZILLA_URL = 'https://www.w3.org/Bugs/Public/' BURL = 'http://localhost:8000/AudioWG/MIDI%20API/' GH_USER = 'jussi-kalliokoski' GH_REPO = 'webmidi-issues' GH_URL = 'https://api.github.com/repos/' + GH_USER + '/' + GH_REPO + '/issues' GH_AUTH = username: 'octocat' password: 'secret' # create a RESTful wrapper for Bugzilla server = Restzilla baseURL: BUGZILLA_URL server.listen 8000 gh = (method, url, body, callback) -> options = method: method headers: authorization: 'Basic ' + Buffer(GH_AUTH.username + ':' + GH_AUTH.password).toString('base64') body: JSON.stringify(body) url: GH_URL + url request options, (e, res, body) -> callback e, res, JSON.parse(body) createIssue = (issue, callback) -> gh 'POST', '', issue, (e, res, body) -> return callback(e, null) if e return callback(Error('Error creating issue (' + res.statusCode + ')\n' + JSON.stringify(body)), null) if res.statusCode isnt 201 callback null, body createComment = (issueNumber, comment, callback) -> gh 'POST', '/' + issueNumber + '/comments', comment, (e, res, body) -> return callback(e, null) if e return callback(Error('Error creating comment (' + res.statusCode + ')\n' + JSON.stringify(body)), null) if res.statusCode isnt 201 callback null, body closeIssue = (issueNumber, callback) -> body = state: 'closed' gh 'PATCH', '/' + issueNumber, body, (e, res, body) -> return callback(e, null) if e return callback(Error('Error closing issue ' + issueNumber + ' (' + res.statusCode + ')\n' + JSON.stringify(body)), null) if res.statusCode isnt 200 callback null, body start = -> request BURL, (e, res, body) -> throw e if e issues = JSON.parse(body) c = issues.length for issue in issues processIssue issue, -> if not --c process.nextTick finish convertBugToIssue = (bug) -> body = '> Originally reported on W3C Bugzilla [ISSUE-' + bug.number + '](' + BUGZILLA_URL + 'show_bug.cgi?id=' + bug.number + ')' body += ' ' + (new Date(bug.created_at)).toGMTString() + '\n' body += '> Reported by ' + bug.reporter + '\n' body += '> Assigned to ' + bug.assignee + '\n' body += '\n' + bug.body issue = user: GH_USER repo: GH_REPO title: bug.title body: body labels: bug.status.split(' ').filter (v) -> !~['NEW'].indexOf(v) processIssue = (id, done) -> request BURL + id, (e, res, body) -> throw e if e bug = JSON.parse body issue = convertBugToIssue bug createIssue issue, (e, ghissue) -> throw e if e console.error 'Created issue #' + ghissue.number, ghissue.title closeIfNeeded = -> closed = /^(RESOLVED|CLOSED)/.test(bug.status) return done() if not closed closeIssue ghissue.number, (e, body) -> throw e if e console.error 'Closed issue #' + ghissue.number, ghissue.title, '(Was ' + bug.status + ')' done() return closeIfNeeded() if not bug.comments request BURL + id + '/comments', (e, res, body) -> throw e if e comments = JSON.parse(body) ids = [] cont = (id) -> ids.push id if id comment = comments.shift() if not comment console.error 'Populated ' + ids.length + ' comments for issue #' + ghissue.number, ghissue.title return closeIfNeeded() comment.bugURL = BUGZILLA_URL + 'show_bug.cgi?id=' + bug.number + '#' + comment.number processComment(comment, ghissue, ids, cont) cont() convertCommentToGHComment = (comment, idlist) -> body = '> [Original comment](' + comment.bugURL + ') by ' + comment.user + ' on W3C Bugzilla.' body += ' ' + (new Date(comment.created_at)).toGMTString() + '\n' body += '\n' body += comment.body.replace /\(In reply to comment #(\d+)\)/g, (all, num) -> num -= 1 return all if not idlist[num] return '(In reply to [comment #' + (num + 1) + '](#issuecomment-' + idlist[num] + '))' comm = body: body processComment = (comment, ghissue, idlist, done) -> body = convertCommentToGHComment comment, idlist createComment ghissue.number, body, (e, ghcomment) -> throw e if e done(ghcomment.id) finish = -> console.log 'Done' process.exit() start()