Skip to content
This repository was archived by the owner on Jul 31, 2025. It is now read-only.

Commit 0b92fa5

Browse files
committed
Get all orgs/teams/permissions in a single GitHub API call
Exposes a new API call at GitHub root level to build the complete set of organisations and teams that current user belongs to. This change allows to massively reduce the number of calls to GitHub especially for people that belongs to multiple organisations with lots of teams and members. Signed-off-by: Luca Milanesio <[email protected]>
1 parent 590f7ba commit 0b92fa5

3 files changed

Lines changed: 67 additions & 11 deletions

File tree

src/main/java/org/kohsuke/github/GHTeam.java

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
public class GHTeam {
1616
private String name,permission;
1717
private int id;
18+
private GHOrganization organization; // populated by GET /user/teams where Teams+Orgs are returned together
1819

1920
protected /*final*/ GHOrganization org;
2021

@@ -23,6 +24,11 @@ public class GHTeam {
2324
return this;
2425
}
2526

27+
/*package*/ GHTeam wrapUp(GitHub root) { // auto-wrapUp when organization is known from GET /user/teams
28+
this.organization.wrapUp(root);
29+
return wrapUp(organization);
30+
}
31+
2632
/*package*/ static GHTeam[] wrapUp(GHTeam[] teams, GHOrganization owner) {
2733
for (GHTeam t : teams) {
2834
t.wrapUp(owner);
@@ -95,4 +101,8 @@ public void remove(GHRepository r) throws IOException {
95101
private String api(String tail) {
96102
return "/teams/"+id+tail;
97103
}
104+
105+
public GHOrganization getOrganization() {
106+
return org;
107+
}
98108
}

src/main/java/org/kohsuke/github/GitHub.java

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,8 @@
2323
*/
2424
package org.kohsuke.github;
2525

26-
import static com.fasterxml.jackson.annotation.JsonAutoDetect.Visibility.*;
26+
import static com.fasterxml.jackson.annotation.JsonAutoDetect.Visibility.ANY;
27+
import static com.fasterxml.jackson.annotation.JsonAutoDetect.Visibility.NONE;
2728

2829
import java.io.File;
2930
import java.io.FileInputStream;
@@ -38,9 +39,11 @@
3839
import java.util.Collection;
3940
import java.util.Date;
4041
import java.util.HashMap;
42+
import java.util.HashSet;
4143
import java.util.List;
4244
import java.util.Map;
4345
import java.util.Properties;
46+
import java.util.Set;
4447
import java.util.TimeZone;
4548

4649
import org.apache.commons.codec.binary.Base64;
@@ -328,6 +331,28 @@ public Map<String, GHOrganization> getMyOrganizations() throws IOException {
328331
return r;
329332
}
330333

334+
/**
335+
* Gets complete map of organizations/teams that current user belongs to.
336+
*
337+
* Leverages the new GitHub API /user/teams made available recently to
338+
* get in a single call the complete set of organizations, teams and permissions
339+
* in a single call.
340+
*/
341+
public Map<String, Set<GHTeam>> getMyTeams() throws IOException {
342+
Map<String, Set<GHTeam>> allMyTeams = new HashMap<String, Set<GHTeam>>();
343+
for (GHTeam team : retrieve().to("/user/teams", GHTeam[].class)) {
344+
team.wrapUp(this);
345+
String orgLogin = team.getOrganization().getLogin();
346+
Set<GHTeam> teamsPerOrg = allMyTeams.get(orgLogin);
347+
if (teamsPerOrg == null) {
348+
teamsPerOrg = new HashSet<GHTeam>();
349+
}
350+
teamsPerOrg.add(team);
351+
allMyTeams.put(orgLogin, teamsPerOrg);
352+
}
353+
return allMyTeams;
354+
}
355+
331356
/**
332357
* Public events visible to you. Equivalent of what's displayed on https://github.com/
333358
*/

src/test/java/org/kohsuke/github/AppTest.java

Lines changed: 31 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -3,19 +3,13 @@
33
import java.io.IOException;
44
import java.net.URL;
55
import java.util.ArrayList;
6-
import java.util.Collection;
6+
import java.util.Date;
77
import java.util.List;
88
import java.util.Map;
9+
import java.util.Map.Entry;
910
import java.util.Set;
1011
import java.util.UUID;
1112

12-
import static org.junit.Assert.assertEquals;
13-
import static org.junit.Assert.assertFalse;
14-
import static org.junit.Assert.assertNotNull;
15-
import static org.junit.Assert.assertSame;
16-
import static org.junit.Assert.assertTrue;
17-
import static org.junit.Assert.fail;
18-
1913
import org.junit.Assume;
2014
import org.junit.Test;
2115
import org.kohsuke.github.GHCommit.File;
@@ -24,8 +18,6 @@
2418
import com.google.common.base.Predicate;
2519
import com.google.common.collect.Iterables;
2620

27-
import java.util.Date;
28-
2921
/**
3022
* Unit test for simple App.
3123
*/
@@ -170,6 +162,35 @@ public void testMyOrganizations() throws IOException {
170162
System.out.println(org);
171163
}
172164

165+
@Test
166+
public void testMyTeamsContainsAllMyOrganizations() throws IOException {
167+
Map<String, Set<GHTeam>> teams = gitHub.getMyTeams();
168+
Map<String, GHOrganization> myOrganizations = gitHub.getMyOrganizations();
169+
assertEquals(teams.keySet(), myOrganizations.keySet());
170+
}
171+
172+
@Test
173+
public void testMyTeamsShouldIncludeMyself() throws IOException {
174+
Map<String, Set<GHTeam>> teams = gitHub.getMyTeams();
175+
for (Entry<String, Set<GHTeam>> teamsPerOrg : teams.entrySet()) {
176+
String organizationName = teamsPerOrg.getKey();
177+
for (GHTeam team : teamsPerOrg.getValue()) {
178+
String teamName = team.getName();
179+
assertTrue("Team " + teamName + " in organization " + organizationName
180+
+ " does not contain myself",
181+
shouldBelongToTeam(organizationName, teamName));
182+
}
183+
}
184+
}
185+
186+
private boolean shouldBelongToTeam(String organizationName, String teamName) throws IOException {
187+
GHOrganization org = gitHub.getOrganization(organizationName);
188+
assertNotNull(org);
189+
GHTeam team = org.getTeamByName(teamName);
190+
assertNotNull(team);
191+
return team.hasMember(gitHub.getMyself());
192+
}
193+
173194
@Test
174195
public void testFetchPullRequest() throws Exception {
175196
GHRepository r = gitHub.getOrganization("jenkinsci").getRepository("jenkins");

0 commit comments

Comments
 (0)