Skip to content

Commit 2aa5c11

Browse files
mtscout6clayreimann
authored andcommitted
feature(team): add organizaiton team api
1 parent aa7ba49 commit 2aa5c11

File tree

11 files changed

+380
-8
lines changed

11 files changed

+380
-8
lines changed

.editorconfig

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ end_of_line = lf
77
charset = utf-8
88
trim_trailing_whitespace = true
99
insert_final_newline = true
10+
max_line_length = 120
1011

1112
[{*.yml,package.json}]
1213
indent_size = 2

.travis.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
sudo: false
12
language: node_js
23
node_js:
34
- '5'

lib/GitHub.js

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import Search from './Search';
1313
import RateLimit from './RateLimit';
1414
import Repository from './Repository';
1515
import Organization from './Organization';
16+
import Team from './Team';
1617
import Markdown from './Markdown';
1718

1819
/**
@@ -59,6 +60,15 @@ class GitHub {
5960
return new Organization(organization, this.__auth, this.__apiBase);
6061
}
6162

63+
/**
64+
* create a new Team wrapper
65+
* @param {string} teamId - the name of the team
66+
* @return {team}
67+
*/
68+
getTeam(teamId) {
69+
return new Team(teamId, this.__auth, this.__apiBase);
70+
}
71+
6272
/**
6373
* Create a new Repository wrapper
6474
* @param {string} user - the user who owns the respository

lib/Organization.js

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,32 @@ class Organization extends Requestable {
6767
listMembers(options, cb) {
6868
return this._request('GET', `/orgs/${this.__name}/members`, options, cb);
6969
}
70+
71+
/**
72+
* List the Teams in the Organization
73+
* @see https://developer.github.com/v3/orgs/teams/#list-teams
74+
* @param {Requestable.callback} [cb] - will receive the list of teams
75+
* @return {Promise} - the promise for the http request
76+
*/
77+
getTeams(cb) {
78+
return this._requestAllPages(`/orgs/${this.__name}/teams`, undefined, cb);
79+
}
80+
81+
/**
82+
* Create a team
83+
* @see https://developer.github.com/v3/orgs/teams/#create-team
84+
* @param {object} options - Team creation parameters
85+
* @param {string} options.name - The name of the team
86+
* @param {string} [options.description] - Team description
87+
* @param {string} [options.repo_names] - Repos to add the team to
88+
* @param {string} [options.privacy=secret] - The level of privacy the team should have. Can be either one
89+
* of: `secret`, or `closed`
90+
* @param {Requestable.callback} [cb] - will receive the created team
91+
* @return {Promise} - the promise for the http request
92+
*/
93+
createTeam(options, cb) {
94+
return this._request('POST', `/orgs/${this.__name}/teams`, options, cb);
95+
}
7096
}
7197

7298
module.exports = Organization;

lib/Requestable.js

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -168,10 +168,11 @@ class Requestable {
168168
* @param {string} path - the path to request
169169
* @param {Object} data - any query parameters for the request
170170
* @param {Requestable.callback} cb - the callback that will receive `true` or `false`
171+
* @param {method} [method=GET] - HTTP Method to use
171172
* @return {Promise} - the promise for the http request
172173
*/
173-
_request204or404(path, data, cb) {
174-
return this._request('GET', path, data)
174+
_request204or404(path, data, cb, method = 'GET') {
175+
return this._request(method, path, data)
175176
.then(function success(response) {
176177
if (cb) {
177178
cb(null, true, response);

lib/Team.js

Lines changed: 160 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,160 @@
1+
/**
2+
* @file
3+
* @copyright 2016 Matt Smith (Development Seed)
4+
* @license Licensed under {@link https://spdx.org/licenses/BSD-3-Clause-Clear.html BSD-3-Clause-Clear}.
5+
* Github.js is freely distributable.
6+
*/
7+
8+
import Requestable from './Requestable';
9+
import debug from 'debug';
10+
const log = debug('github:team');
11+
12+
/**
13+
* A Team allows scoping of API requests to a particular Github Organization Team.
14+
*/
15+
class Team extends Requestable {
16+
/**
17+
* Create a Team.
18+
* @param {string} [teamId] - the id for the team
19+
* @param {Requestable.auth} [auth] - information required to authenticate to Github
20+
* @param {string} [apiBase=https://api.github.com] - the base Github API URL
21+
*/
22+
constructor(teamId, auth, apiBase) {
23+
super(auth, apiBase);
24+
this.__teamId = teamId;
25+
}
26+
27+
/**
28+
* Get Team information
29+
* @see https://developer.github.com/v3/orgs/teams/#get-team
30+
* @param {Requestable.callback} [cb] - will receive the team
31+
* @return {Promise} - the promise for the http request
32+
*/
33+
getTeam(cb) {
34+
log(`Fetching Team ${this.__teamId}`);
35+
return this._request('Get', `/teams/${this.__teamId}`, undefined, cb);
36+
}
37+
38+
/**
39+
* List the Team's repositories
40+
* @see https://developer.github.com/v3/orgs/teams/#list-team-repos
41+
* @param {Requestable.callback} [cb] - will receive the list of repositories
42+
* @return {Promise} - the promise for the http request
43+
*/
44+
getRepos(cb) {
45+
log(`Fetching repositories for Team ${this.__teamId}`);
46+
return this._requestAllPages(`/teams/${this.__teamId}/repos`, undefined, cb);
47+
}
48+
49+
/**
50+
* Edit Team information
51+
* @see https://developer.github.com/v3/orgs/teams/#edit-team
52+
* @param {object} options - Parameters for team edit
53+
* @param {string} options.name - The name of the team
54+
* @param {string} [options.description] - Team description
55+
* @param {string} [options.repo_names] - Repos to add the team to
56+
* @param {string} [options.privacy=secret] - The level of privacy the team should have. Can be either one
57+
* of: `secret`, or `closed`
58+
* @param {Requestable.callback} [cb] - will receive the updated team
59+
* @return {Promise} - the promise for the http request
60+
*/
61+
editTeam(options, cb) {
62+
log(`Editing Team ${this.__teamId}`);
63+
return this._request('PATCH', `/teams/${this.__teamId}`, options, cb);
64+
}
65+
66+
/**
67+
* List the users who are members of the Team
68+
* @see https://developer.github.com/v3/orgs/teams/#list-team-members
69+
* @param {object} options - Parameters for listing team users
70+
* @param {string} [options.role=all] - can be one of: `all`, `maintainer`, or `member`
71+
* @param {Requestable.callback} [cb] - will receive the list of users
72+
* @return {Promise} - the promise for the http request
73+
*/
74+
listMembers(options, cb) {
75+
log(`Getting members of Team ${this.__teamId}`);
76+
return this._requestAllPages(`/teams/${this.__teamId}/members`, options, cb);
77+
}
78+
79+
/**
80+
* Get Team membership status for a user
81+
* @see https://developer.github.com/v3/orgs/teams/#get-team-membership
82+
* @param {string} username - can be one of: `all`, `maintainer`, or `member`
83+
* @param {Requestable.callback} [cb] - will receive the membership status of a user
84+
* @return {Promise} - the promise for the http request
85+
*/
86+
getMembership(username, cb) {
87+
log(`Getting membership of user ${username} in Team ${this.__teamId}`);
88+
return this._request('GET', `/teams/${this.__teamId}/memberships/${username}`, undefined, cb);
89+
}
90+
91+
/**
92+
* Add a member to the Team
93+
* @see https://developer.github.com/v3/orgs/teams/#add-team-membership
94+
* @param {string} username - can be one of: `all`, `maintainer`, or `member`
95+
* @param {object} options - Parameters for adding a team member
96+
* @param {string} [options.role=member] - The role that this user should have in the team. Can be one
97+
* of: `member`, or `maintainer`
98+
* @param {Requestable.callback} [cb] - will receive the membership status of added user
99+
* @return {Promise} - the promise for the http request
100+
*/
101+
addMembership(username, options, cb) {
102+
log(`Adding user ${username} to Team ${this.__teamId}`);
103+
return this._request('PUT', `/teams/${this.__teamId}/memberships/${username}`, options, cb);
104+
}
105+
106+
/**
107+
* Get repo management status for team
108+
* @see https://developer.github.com/v3/orgs/teams/#remove-team-membership
109+
* @param {string} owner - Organization name
110+
* @param {string} repo - Repo name
111+
* @param {Requestable.callback} [cb] - will receive the membership status of added user
112+
* @return {Promise} - the promise for the http request
113+
*/
114+
isManagedRepo(owner, repo, cb) {
115+
log(`Getting repo management by Team ${this.__teamId} for repo ${owner}/${repo}`);
116+
return this._request204or404(`/teams/${this.__teamId}/repos/${owner}/${repo}`, undefined, cb);
117+
}
118+
119+
/**
120+
* Add or Update repo management status for team
121+
* @see https://developer.github.com/v3/orgs/teams/#add-or-update-team-repository
122+
* @param {string} owner - Organization name
123+
* @param {string} repo - Repo name
124+
* @param {object} options - Parameters for adding or updating repo management for the team
125+
* @param {string} [options.permission] - The permission to grant the team on this repository. Can be one
126+
* of: `pull`, `push`, or `admin`
127+
* @param {Requestable.callback} [cb] - will receive the membership status of added user
128+
* @return {Promise} - the promise for the http request
129+
*/
130+
manageRepo(owner, repo, options, cb) {
131+
log(`Adding or Updating repo management by Team ${this.__teamId} for repo ${owner}/${repo}`);
132+
return this._request204or404(`/teams/${this.__teamId}/repos/${owner}/${repo}`, options, cb, 'PUT');
133+
}
134+
135+
/**
136+
* Remove repo management status for team
137+
* @see https://developer.github.com/v3/orgs/teams/#remove-team-repository
138+
* @param {string} owner - Organization name
139+
* @param {string} repo - Repo name
140+
* @param {Requestable.callback} [cb] - will receive the membership status of added user
141+
* @return {Promise} - the promise for the http request
142+
*/
143+
unmanageRepo(owner, repo, cb) {
144+
log(`Remove repo management by Team ${this.__teamId} for repo ${owner}/${repo}`);
145+
return this._request204or404(`/teams/${this.__teamId}/repos/${owner}/${repo}`, undefined, cb, 'DELETE');
146+
}
147+
148+
/**
149+
* Delete Team
150+
* @see https://developer.github.com/v3/orgs/teams/#delete-team
151+
* @param {Requestable.callback} [cb] - will receive the list of repositories
152+
* @return {Promise} - the promise for the http request
153+
*/
154+
deleteTeam(cb) {
155+
log(`Deleting Team ${this.__teamId}`);
156+
return this._request204or404(`/teams/${this.__teamId}`, undefined, cb, 'DELETE');
157+
}
158+
}
159+
160+
module.exports = Team;

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,7 @@
6161
"codecov": "^1.0.1",
6262
"del": "^2.2.0",
6363
"eslint-config-google": "^0.5.0",
64+
"eslint-plugin-mocha": "^2.2.0",
6465
"gulp": "^3.9.0",
6566
"gulp-babel": "^6.1.2",
6667
"gulp-eslint": "^2.0.0",

test/.eslintrc.yaml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
---
22
extends: ../.eslintrc.yaml
3+
plugins:
4+
- mocha
35
env:
46
mocha: true
57
rules:
68
handle-callback-err: off
9+
mocha/no-exclusive-tests: 2

test/auth.spec.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ describe('Github', function() {
5151
done();
5252
} catch (e) {
5353
try {
54-
if (err && err.request.headers['x-ratelimit-remaining'] === '0') {
54+
if (err && err.response.headers['x-ratelimit-remaining'] === '0') {
5555
done();
5656
return;
5757
}

test/organization.spec.js

Lines changed: 30 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -42,12 +42,11 @@ describe('Organization', function() {
4242
}).catch(done);
4343
});
4444

45-
it('should test for membership', function(done) {
46-
organization.isMember(MEMBER_NAME)
45+
it('should test for membership', function() {
46+
return organization.isMember(MEMBER_NAME)
4747
.then(function(isMember) {
4848
expect(isMember).to.be.true();
49-
done();
50-
}).catch(done);
49+
});
5150
});
5251
});
5352

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

62-
it('should create an organisation repo', function(done) {
61+
it('should create an organization repo', function(done) {
6362
const options = {
6463
name: testRepoName,
6564
description: 'test create organization repo',
@@ -76,5 +75,31 @@ describe('Organization', function() {
7675
done();
7776
}));
7877
});
78+
79+
// TODO: The longer this is in place the slower it will get if we don't cleanup random test teams
80+
it('should list the teams in the organization', function() {
81+
return organization.getTeams()
82+
.then(({data}) => {
83+
const hasTeam = data.reduce(
84+
(found, member) => member.slug === 'fixed-test-team-1' || found,
85+
false);
86+
87+
expect(hasTeam).to.be.true();
88+
});
89+
});
90+
91+
it('should create an organization team', function(done) {
92+
const options = {
93+
name: testRepoName,
94+
description: 'Created by unit tests',
95+
privacy: 'secret'
96+
};
97+
98+
organization.createTeam(options, assertSuccessful(done, function(err, team) {
99+
expect(team.name).to.equal(testRepoName);
100+
expect(team.organization.login).to.equal(testUser.ORGANIZATION); // jscs:ignore
101+
done();
102+
}));
103+
});
79104
});
80105
});

0 commit comments

Comments
 (0)