diff --git a/lib/GitHub.js b/lib/GitHub.js index 944fc868..bc83acb4 100644 --- a/lib/GitHub.js +++ b/lib/GitHub.js @@ -75,7 +75,7 @@ class GitHub { * @return {Repository} */ getRepo(user, repo) { - return new Repository(this._getFullName(user, repo), this.__auth, this.__apiBase); + return new Repository(user, repo, this.__auth, this.__apiBase); } /** diff --git a/lib/Repository.js b/lib/Repository.js index 301e1230..02c854c7 100644 --- a/lib/Repository.js +++ b/lib/Repository.js @@ -19,13 +19,16 @@ const log = debug('github:repository'); class Repository extends Requestable { /** * Create a Repository. - * @param {string} fullname - the full name of the repository + * @param {string} user - the name of the user + * @param {string} repo - the name of the repository * @param {Requestable.auth} [auth] - information required to authenticate to Github * @param {string} [apiBase=https://api.github.com] - the base Github API URL */ - constructor(fullname, auth, apiBase) { + constructor(user, repo, auth, apiBase) { super(auth, apiBase); - this.__fullname = fullname; + this.__user = user; + this.__repo = repo; + this.__fullname = repo ? `${user}/${repo}` : `${user}`; this.__currentTree = { branch: null, sha: null @@ -367,6 +370,41 @@ class Repository extends Requestable { }, cb); } + /** + * Update commit status + * @see https://developer.github.com/v3/repos/statuses/ + * @param {string} commitSHA - the SHA of the commit that should be updated + * @param {object} options - Commit status parameters + * @param {string} options.state - The state of the status. Can be one of: pending, success, error, or failure. + * @param {string} [options.target_url] - The target URL to associate with this status. + * @param {string} [options.description] - A short description of the status. + * @param {string} [options.context] - A string label to differentiate this status among CI systems. + * @param {Requestable.callback} cb - will receive the updated commit back + * @return {Promise} - the promise for the http request + */ + updateStatus(commitSHA, options, cb) { + return this._request('POST', `/repos/${this.__fullname}/statuses/${commitSHA}`, options, cb); + } + + /** + * Update repository information + * @see https://developer.github.com/v3/repos/#edit + * @param {object} options - New parameters that will be set to the repository + * @param {string} options.name - Name of the repository + * @param {string} [options.description] - A short description of the repository + * @param {string} [options.homepage] - A URL with more information about the repository + * @param {boolean} [options.private] - Either true to make the repository private, or false to make it public. + * @param {boolean} [options.has_issues] - Either true to enable issues for this repository, false to disable them. + * @param {boolean} [options.has_wiki] - Either true to enable the wiki for this repository, false to disable it. + * @param {boolean} [options.has_downloads] - Either true to enable downloads, false to disable them. + * @param {string} [options.default_branch] - Updates the default branch for this repository. + * @param {Requestable.callback} cb - will receive the updated repository back + * @return {Promise} - the promise for the http request + */ + updateRepository(options, cb) { + return this._request('PATCH', `/repos/${this.__fullname}`, options, cb); + } + /** * Get information about the repository * @see https://developer.github.com/v3/repos/#get @@ -409,6 +447,33 @@ class Repository extends Requestable { return this._request('GET', `/repos/${this.__fullname}/collaborators/${username}`, null, cb); } + /** + * Add collaborator to this repo. + * @see https://developer.github.com/v3/repos/collaborators/#add-user-as-a-collaborator + * @param {Object} options - options with username as collaborator - permission (optional) + * @param {Requestable.callback} [cb] - will receive the repo, invitee, and inviter. + * @return {Promise} - the promise for the http request + */ + addCollaborator(options, cb) { + options = options || {}; + const payload = options.permission ? {permission: options.permission} : null; + + return this._request('PUT', `/repos/${this.__fullname}/collaborators/${options.username}`, payload, cb); + } + + /** + * Remove collaborator to this repo. + * @see https://developer.github.com/v3/repos/collaborators/#remove-user-as-a-collaborator + * @param {Object} options - options with username as collaborator + * @param {Requestable.callback} [cb] - will not receive anything + * @return {Promise} - the promise for the http request + */ + removeCollaborator(options, cb) { + options = options || {}; + + return this._request('DELETE', `/repos/${this.__fullname}/collaborators/${options.username}`, null, cb); + } + /** * Get the contents of a repository * @see https://developer.github.com/v3/repos/contents/#get-contents @@ -504,7 +569,7 @@ class Repository extends Requestable { * @return {Promise} - the promise for the http request */ updatePullRequst(number, options, cb) { - log('Deprecated: This method contains a typo and it has been deprecated. It will be removed in next major version. Use updatePullRequest() instead.'); + log('Deprecated: This method will be removed in next major version. Use updatePullRequest() instead.'); return this.updatePullRequest(number, options, cb); } diff --git a/test/repository.spec.js b/test/repository.spec.js index f747878d..8e63fc47 100644 --- a/test/repository.spec.js +++ b/test/repository.spec.js @@ -288,6 +288,32 @@ describe('Repository', function() { })); }); + it('should be able to edit repository information', function(done) { + const options = { + name: testRepoName, + description: 'New short description', + homepage: 'http://example.com' + }; + + remoteRepo.updateRepository(options, assertSuccessful(done, + function(err, repository) { + expect(repository).to.have.own('homepage', options.homepage); + expect(repository).to.have.own('description', options.description); + expect(repository).to.have.own('name', testRepoName); + done(); + })); + }); + + it('add collaborator to repository', function(done) { + const options = {username: 'marwan-at-work', permission: 'admin'}; + remoteRepo.addCollaborator(options, assertSuccessful(done)); + }); + + it('should remove collaborator from repository', function(done) { + const options = {username: 'marwan-at-work'}; + remoteRepo.removeCollaborator(options, assertSuccessful(done)); + }); + it('should show repo collaborators', function(done) { remoteRepo.getCollaborators(assertSuccessful(done, function(err, collaborators) { if (!(collaborators instanceof Array)) { @@ -398,6 +424,24 @@ describe('Repository', function() { })); }); + it('should update commit status', function(done) { + const status = { + state: 'success', + target_url: 'http://example.com', // eslint-disable-line camelcase + description: 'Build was successful!' + }; + remoteRepo.getRef('heads/master', assertSuccessful(done, function(err, refSpec) { + remoteRepo.updateStatus(refSpec.object.sha, status, assertSuccessful(done, + function(err, updated) { + expect(updated).to.have.own('state', status.state); + expect(updated).to.have.own('target_url', status.target_url); + expect(updated).to.have.own('description', status.description); + expect(updated).to.have.own('context', 'default'); + done(); + })); + })); + }); + it('should delete ref on repo', function(done) { remoteRepo.deleteRef('heads/new-test-branch', assertSuccessful(done)); });