diff --git a/lib/models/apis/github.js b/lib/models/apis/github.js index ea0ca4f45..32a3cd9c1 100644 --- a/lib/models/apis/github.js +++ b/lib/models/apis/github.js @@ -227,6 +227,41 @@ Github.prototype.getUserById = function (githubId, cb) { }, cb) } +/** + * Fetches all orgs recursively starting at page 1. + * + * @param {object} opts List of options passed in to fetch page + * @param {function} cb callback + * @private + */ +Github.prototype._getAllOrgs = function (opts, cb) { + opts = Object.assign({ per_page: 100 }, opts || {}) + // TODO: Remove after testing complete + opts.per_page = 3 + + const fetchPage = (page, allOrgs) => { + return Promise.fromCallback((cb) => { + return this.user.getOrgs(Object.assign({}, opts, {page}), cb) + }) + .then((orgs) => { + if (!orgs) { + return orgs + } + if (!allOrgs) { + allOrgs = orgs + } else { + orgs.forEach(org => allOrgs.push) + } + if (orgs.length === opts.per_page) { + return fetchPage(page + 1, allOrgs) + } + return allOrgs + }) + } + + return fetchPage(1).asCallback(cb) +} + Github.prototype.getUserAuthorizedOrgs = function (cb) { logger.log.info('Github.prototype.getUserAuthorizedOrgs') if (!this.token) { @@ -235,9 +270,9 @@ Github.prototype.getUserAuthorizedOrgs = function (cb) { } var userKey = keyPrefix + (this.token ? this.tokenHash : 'runnable') var userOrgsKey = new redisTypes.String(userKey + ':user:' + this.token + ':orgs') - this._runQueryAgainstCache({ - query: this.user.getOrgs, - debug: 'this.user.getOrgs', + return this._runQueryAgainstCache({ + query: this._getAllOrgs.bind(this), + debug: 'this._getAllOrgs', stringKey: userOrgsKey }, cb) } diff --git a/unit/models/apis/github.js b/unit/models/apis/github.js index 44d2c205b..49587f5dc 100644 --- a/unit/models/apis/github.js +++ b/unit/models/apis/github.js @@ -392,4 +392,84 @@ describe('github: ' + moduleName, function () { }) }) }) // end createHooksAndKeys + + describe('_getAllOrgs', () => { + let github + + beforeEach((done) => { + github = new Github({token: 'some-token'}) + sinon.stub(github.user,'getOrgs').yields(null, []) + done() + }) + + it('should return no results', (done) => { + let opts = {} + github.user.getOrgs.yields(null, []); + github._getAllOrgs(opts, function (err, allOrgs) { + sinon.assert.calledOnce(github.user.getOrgs) + sinon.assert.calledWith(github.user.getOrgs, {per_page: 100, page: 1}, sinon.match.func) + expect(allOrgs.length).to.equal(0) + done() + }) + + }) + + it('should return 99 results', (done) => { + let opts = {} + + github.user.getOrgs.yields(null, new Array(99)) + github._getAllOrgs(opts, (err, allOrgs) => { + sinon.assert.calledOnce(github.user.getOrgs) + sinon.assert.calledWith(github.user.getOrgs, {per_page: 100, page: 1}, sinon.match.func) + expect(allOrgs.length).to.equal(99) + done() + }) + }) + + it('should return 100 results', (done) => { + let opts = {} + + github.user.getOrgs.onFirstCall().yields(null, new Array(100)) + github.user.getOrgs.onSecondCall().yields(null, []) + github._getAllOrgs(opts, (err, allOrgs) => { + sinon.assert.calledTwice(github.user.getOrgs) + sinon.assert.calledWith(github.user.getOrgs, {per_page: 100, page: 1}, sinon.match.func) + sinon.assert.calledWith(github.user.getOrgs, {per_page: 100, page: 2}, sinon.match.func) + expect(allOrgs.length).to.equal(100) + done() + }) + }) + + it('should return 201 results', (done) => { + let opts = {} + + github.user.getOrgs.onFirstCall().yields(null, new Array(100)) + github.user.getOrgs.onSecondCall().yields(null, new Array(100)) + github.user.getOrgs.onThirdCall().yields(null, new Array(1)) + github._getAllOrgs(opts, (err, allOrgs) => { + sinon.assert.calledThrice(github.user.getOrgs) + sinon.assert.calledWith(github.user.getOrgs, {per_page: 100, page: 1}, sinon.match.func) + sinon.assert.calledWith(github.user.getOrgs, {per_page: 100, page: 2}, sinon.match.func) + sinon.assert.calledWith(github.user.getOrgs, {per_page: 100, page: 3}, sinon.match.func) + expect(allOrgs.length).to.equal(201) + done() + }) + }) + + it('should return 40 results, over 2 pages, with three calls', (done) => { + let opts = {per_page: 20} + + github.user.getOrgs.onFirstCall().yields(null, new Array(20)) + github.user.getOrgs.onSecondCall().yields(null, new Array(20)) + github.user.getOrgs.onThirdCall().yields(null, []) + github._getAllOrgs(opts, (err, allOrgs) => { + sinon.assert.calledThrice(github.user.getOrgs) + sinon.assert.calledWith(github.user.getOrgs, {per_page: 20, page: 1}, sinon.match.func) + sinon.assert.calledWith(github.user.getOrgs, {per_page: 20, page: 2}, sinon.match.func) + sinon.assert.calledWith(github.user.getOrgs, {per_page: 20, page: 3}, sinon.match.func) + expect(allOrgs.length).to.equal(40) + done() + }) + }) + }) })