Skip to content

Commit

Permalink
feature(team): add organizaiton team api
Browse files Browse the repository at this point in the history
  • Loading branch information
mtscout6 authored and clayreimann committed May 25, 2016
1 parent aa7ba49 commit 2aa5c11
Show file tree
Hide file tree
Showing 11 changed files with 380 additions and 8 deletions.
1 change: 1 addition & 0 deletions .editorconfig
Expand Up @@ -7,6 +7,7 @@ end_of_line = lf
charset = utf-8
trim_trailing_whitespace = true
insert_final_newline = true
max_line_length = 120

[{*.yml,package.json}]
indent_size = 2
Expand Down
1 change: 1 addition & 0 deletions .travis.yml
@@ -1,3 +1,4 @@
sudo: false
language: node_js
node_js:
- '5'
Expand Down
10 changes: 10 additions & 0 deletions lib/GitHub.js
Expand Up @@ -13,6 +13,7 @@ import Search from './Search';
import RateLimit from './RateLimit';
import Repository from './Repository';
import Organization from './Organization';
import Team from './Team';
import Markdown from './Markdown';

/**
Expand Down Expand Up @@ -59,6 +60,15 @@ class GitHub {
return new Organization(organization, this.__auth, this.__apiBase);
}

/**
* create a new Team wrapper
* @param {string} teamId - the name of the team
* @return {team}
*/
getTeam(teamId) {
return new Team(teamId, this.__auth, this.__apiBase);
}

/**
* Create a new Repository wrapper
* @param {string} user - the user who owns the respository
Expand Down
26 changes: 26 additions & 0 deletions lib/Organization.js
Expand Up @@ -67,6 +67,32 @@ class Organization extends Requestable {
listMembers(options, cb) {
return this._request('GET', `/orgs/${this.__name}/members`, options, cb);
}

/**
* List the Teams in the Organization
* @see https://developer.github.com/v3/orgs/teams/#list-teams
* @param {Requestable.callback} [cb] - will receive the list of teams
* @return {Promise} - the promise for the http request
*/
getTeams(cb) {
return this._requestAllPages(`/orgs/${this.__name}/teams`, undefined, cb);
}

/**
* Create a team
* @see https://developer.github.com/v3/orgs/teams/#create-team
* @param {object} options - Team creation parameters
* @param {string} options.name - The name of the team
* @param {string} [options.description] - Team description
* @param {string} [options.repo_names] - Repos to add the team to
* @param {string} [options.privacy=secret] - The level of privacy the team should have. Can be either one
* of: `secret`, or `closed`
* @param {Requestable.callback} [cb] - will receive the created team
* @return {Promise} - the promise for the http request
*/
createTeam(options, cb) {
return this._request('POST', `/orgs/${this.__name}/teams`, options, cb);
}
}

module.exports = Organization;
5 changes: 3 additions & 2 deletions lib/Requestable.js
Expand Up @@ -168,10 +168,11 @@ class Requestable {
* @param {string} path - the path to request
* @param {Object} data - any query parameters for the request
* @param {Requestable.callback} cb - the callback that will receive `true` or `false`
* @param {method} [method=GET] - HTTP Method to use
* @return {Promise} - the promise for the http request
*/
_request204or404(path, data, cb) {
return this._request('GET', path, data)
_request204or404(path, data, cb, method = 'GET') {
return this._request(method, path, data)
.then(function success(response) {
if (cb) {
cb(null, true, response);
Expand Down
160 changes: 160 additions & 0 deletions lib/Team.js
@@ -0,0 +1,160 @@
/**
* @file
* @copyright 2016 Matt Smith (Development Seed)
* @license Licensed under {@link https://spdx.org/licenses/BSD-3-Clause-Clear.html BSD-3-Clause-Clear}.
* Github.js is freely distributable.
*/

import Requestable from './Requestable';
import debug from 'debug';
const log = debug('github:team');

/**
* A Team allows scoping of API requests to a particular Github Organization Team.
*/
class Team extends Requestable {
/**
* Create a Team.
* @param {string} [teamId] - the id for the team
* @param {Requestable.auth} [auth] - information required to authenticate to Github
* @param {string} [apiBase=https://api.github.com] - the base Github API URL
*/
constructor(teamId, auth, apiBase) {
super(auth, apiBase);
this.__teamId = teamId;
}

/**
* Get Team information
* @see https://developer.github.com/v3/orgs/teams/#get-team
* @param {Requestable.callback} [cb] - will receive the team
* @return {Promise} - the promise for the http request
*/
getTeam(cb) {
log(`Fetching Team ${this.__teamId}`);
return this._request('Get', `/teams/${this.__teamId}`, undefined, cb);
}

/**
* List the Team's repositories
* @see https://developer.github.com/v3/orgs/teams/#list-team-repos
* @param {Requestable.callback} [cb] - will receive the list of repositories
* @return {Promise} - the promise for the http request
*/
getRepos(cb) {
log(`Fetching repositories for Team ${this.__teamId}`);
return this._requestAllPages(`/teams/${this.__teamId}/repos`, undefined, cb);
}

/**
* Edit Team information
* @see https://developer.github.com/v3/orgs/teams/#edit-team
* @param {object} options - Parameters for team edit
* @param {string} options.name - The name of the team
* @param {string} [options.description] - Team description
* @param {string} [options.repo_names] - Repos to add the team to
* @param {string} [options.privacy=secret] - The level of privacy the team should have. Can be either one
* of: `secret`, or `closed`
* @param {Requestable.callback} [cb] - will receive the updated team
* @return {Promise} - the promise for the http request
*/
editTeam(options, cb) {
log(`Editing Team ${this.__teamId}`);
return this._request('PATCH', `/teams/${this.__teamId}`, options, cb);
}

/**
* List the users who are members of the Team
* @see https://developer.github.com/v3/orgs/teams/#list-team-members
* @param {object} options - Parameters for listing team users
* @param {string} [options.role=all] - can be one of: `all`, `maintainer`, or `member`
* @param {Requestable.callback} [cb] - will receive the list of users
* @return {Promise} - the promise for the http request
*/
listMembers(options, cb) {
log(`Getting members of Team ${this.__teamId}`);
return this._requestAllPages(`/teams/${this.__teamId}/members`, options, cb);
}

/**
* Get Team membership status for a user
* @see https://developer.github.com/v3/orgs/teams/#get-team-membership
* @param {string} username - can be one of: `all`, `maintainer`, or `member`
* @param {Requestable.callback} [cb] - will receive the membership status of a user
* @return {Promise} - the promise for the http request
*/
getMembership(username, cb) {
log(`Getting membership of user ${username} in Team ${this.__teamId}`);
return this._request('GET', `/teams/${this.__teamId}/memberships/${username}`, undefined, cb);
}

/**
* Add a member to the Team
* @see https://developer.github.com/v3/orgs/teams/#add-team-membership
* @param {string} username - can be one of: `all`, `maintainer`, or `member`
* @param {object} options - Parameters for adding a team member
* @param {string} [options.role=member] - The role that this user should have in the team. Can be one
* of: `member`, or `maintainer`
* @param {Requestable.callback} [cb] - will receive the membership status of added user
* @return {Promise} - the promise for the http request
*/
addMembership(username, options, cb) {
log(`Adding user ${username} to Team ${this.__teamId}`);
return this._request('PUT', `/teams/${this.__teamId}/memberships/${username}`, options, cb);
}

/**
* Get repo management status for team
* @see https://developer.github.com/v3/orgs/teams/#remove-team-membership
* @param {string} owner - Organization name
* @param {string} repo - Repo name
* @param {Requestable.callback} [cb] - will receive the membership status of added user
* @return {Promise} - the promise for the http request
*/
isManagedRepo(owner, repo, cb) {
log(`Getting repo management by Team ${this.__teamId} for repo ${owner}/${repo}`);
return this._request204or404(`/teams/${this.__teamId}/repos/${owner}/${repo}`, undefined, cb);
}

/**
* Add or Update repo management status for team
* @see https://developer.github.com/v3/orgs/teams/#add-or-update-team-repository
* @param {string} owner - Organization name
* @param {string} repo - Repo name
* @param {object} options - Parameters for adding or updating repo management for the team
* @param {string} [options.permission] - The permission to grant the team on this repository. Can be one
* of: `pull`, `push`, or `admin`
* @param {Requestable.callback} [cb] - will receive the membership status of added user
* @return {Promise} - the promise for the http request
*/
manageRepo(owner, repo, options, cb) {
log(`Adding or Updating repo management by Team ${this.__teamId} for repo ${owner}/${repo}`);
return this._request204or404(`/teams/${this.__teamId}/repos/${owner}/${repo}`, options, cb, 'PUT');
}

/**
* Remove repo management status for team
* @see https://developer.github.com/v3/orgs/teams/#remove-team-repository
* @param {string} owner - Organization name
* @param {string} repo - Repo name
* @param {Requestable.callback} [cb] - will receive the membership status of added user
* @return {Promise} - the promise for the http request
*/
unmanageRepo(owner, repo, cb) {
log(`Remove repo management by Team ${this.__teamId} for repo ${owner}/${repo}`);
return this._request204or404(`/teams/${this.__teamId}/repos/${owner}/${repo}`, undefined, cb, 'DELETE');
}

/**
* Delete Team
* @see https://developer.github.com/v3/orgs/teams/#delete-team
* @param {Requestable.callback} [cb] - will receive the list of repositories
* @return {Promise} - the promise for the http request
*/
deleteTeam(cb) {
log(`Deleting Team ${this.__teamId}`);
return this._request204or404(`/teams/${this.__teamId}`, undefined, cb, 'DELETE');
}
}

module.exports = Team;
1 change: 1 addition & 0 deletions package.json
Expand Up @@ -61,6 +61,7 @@
"codecov": "^1.0.1",
"del": "^2.2.0",
"eslint-config-google": "^0.5.0",
"eslint-plugin-mocha": "^2.2.0",
"gulp": "^3.9.0",
"gulp-babel": "^6.1.2",
"gulp-eslint": "^2.0.0",
Expand Down
3 changes: 3 additions & 0 deletions test/.eslintrc.yaml
@@ -1,6 +1,9 @@
---
extends: ../.eslintrc.yaml
plugins:
- mocha
env:
mocha: true
rules:
handle-callback-err: off
mocha/no-exclusive-tests: 2
2 changes: 1 addition & 1 deletion test/auth.spec.js
Expand Up @@ -51,7 +51,7 @@ describe('Github', function() {
done();
} catch (e) {
try {
if (err && err.request.headers['x-ratelimit-remaining'] === '0') {
if (err && err.response.headers['x-ratelimit-remaining'] === '0') {
done();
return;
}
Expand Down
35 changes: 30 additions & 5 deletions test/organization.spec.js
Expand Up @@ -42,12 +42,11 @@ describe('Organization', function() {
}).catch(done);
});

it('should test for membership', function(done) {
organization.isMember(MEMBER_NAME)
it('should test for membership', function() {
return organization.isMember(MEMBER_NAME)
.then(function(isMember) {
expect(isMember).to.be.true();
done();
}).catch(done);
});
});
});

Expand All @@ -59,7 +58,7 @@ describe('Organization', function() {
organization = github.getOrganization(testUser.ORGANIZATION);
});

it('should create an organisation repo', function(done) {
it('should create an organization repo', function(done) {
const options = {
name: testRepoName,
description: 'test create organization repo',
Expand All @@ -76,5 +75,31 @@ describe('Organization', function() {
done();
}));
});

// TODO: The longer this is in place the slower it will get if we don't cleanup random test teams
it('should list the teams in the organization', function() {
return organization.getTeams()
.then(({data}) => {
const hasTeam = data.reduce(
(found, member) => member.slug === 'fixed-test-team-1' || found,
false);

expect(hasTeam).to.be.true();
});
});

it('should create an organization team', function(done) {
const options = {
name: testRepoName,
description: 'Created by unit tests',
privacy: 'secret'
};

organization.createTeam(options, assertSuccessful(done, function(err, team) {
expect(team.name).to.equal(testRepoName);
expect(team.organization.login).to.equal(testUser.ORGANIZATION); // jscs:ignore
done();
}));
});
});
});

0 comments on commit 2aa5c11

Please sign in to comment.