Skip to content

Commit 45a2b0f

Browse files
committed
Merge branch 'feature'
2 parents 6a11556 + 2138e2d commit 45a2b0f

File tree

13 files changed

+520
-117
lines changed

13 files changed

+520
-117
lines changed

config.xml

+2
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
2+
<config hasRun="true"/>

pom.xml

+6
Original file line numberDiff line numberDiff line change
@@ -256,6 +256,12 @@
256256
<artifactId>gson</artifactId>
257257
<version>2.11.0</version>
258258
</dependency>
259+
<dependency>
260+
<groupId>org.mockito</groupId>
261+
<artifactId>mockito-junit-jupiter</artifactId>
262+
<version>5.7.0</version>
263+
<scope>test</scope>
264+
</dependency>
259265

260266
</dependencies>
261267

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
package io.jenkins.infra.repository_permissions_updater.github_team_sync;
2+
3+
public class AdditionalTeamDefinition {
4+
private String teamName;
5+
private Role role;
6+
7+
public AdditionalTeamDefinition(String teamName, String role) {
8+
this.teamName = teamName;
9+
this.role = validateRole(role);
10+
}
11+
12+
public String getName() {
13+
return teamName;
14+
}
15+
16+
public Role getRole() {
17+
return role;
18+
}
19+
20+
private Role validateRole(String role) {
21+
if (role == null) {
22+
return null;
23+
}
24+
try {
25+
return Role.valueOf(role.toUpperCase());
26+
} catch (IllegalArgumentException e) {
27+
throw new IllegalArgumentException("Invalid team role: " + role);
28+
}
29+
}
30+
}
31+

src/main/java/io/jenkins/infra/repository_permissions_updater/github_team_sync/GitHubService.java

+9
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
import java.util.Set;
55

66
import org.kohsuke.github.GHOrganization;
7+
import org.kohsuke.github.GHRepository;
78
import org.kohsuke.github.GHTeam;
89

910
public interface GitHubService {
@@ -17,4 +18,12 @@ public interface GitHubService {
1718
Set<String> getCurrentTeamMembers(GHTeam team) throws IOException;
1819

1920
GHTeam createTeam(String orgName, String teamName, GHTeam.Privacy privacy) throws IOException;
21+
22+
void updateTeamRole(GHRepository repo, GHTeam ghTeam, Role role) throws IOException;
23+
24+
GHTeam getTeamFromRepo(String orgName, String repoName, String teamName) throws IOException;
25+
26+
void removeTeamFromRepository(GHTeam team, GHRepository repo) throws IOException;
27+
28+
Set<String> getCurrentTeams(GHRepository repo, GHTeam repoTeam) throws IOException;
2029
}

src/main/java/io/jenkins/infra/repository_permissions_updater/github_team_sync/GitHubServiceImpl.java

+55-5
Original file line numberDiff line numberDiff line change
@@ -2,18 +2,24 @@
22

33
import java.io.IOException;
44
import java.util.HashSet;
5+
import java.util.Map;
56
import java.util.Set;
7+
import java.util.stream.Collectors;
68

7-
import org.kohsuke.github.GHOrganization;
8-
import org.kohsuke.github.GHTeam;
9-
import org.kohsuke.github.GHUser;
10-
import org.kohsuke.github.GitHub;
11-
import org.kohsuke.github.GitHubBuilder;
9+
import org.kohsuke.github.*;
1210

1311

1412
public class GitHubServiceImpl implements GitHubService {
1513
private GitHub github;
1614

15+
private static final Map<Role, GHOrganization.Permission> PERMISSIONS_MAP = Map.of(
16+
Role.READ, GHOrganization.Permission.PULL,
17+
Role.TRIAGE, GHOrganization.Permission.TRIAGE,
18+
Role.WRITE, GHOrganization.Permission.PUSH,
19+
Role.MAINTAIN, GHOrganization.Permission.MAINTAIN,
20+
Role.ADMIN, GHOrganization.Permission.ADMIN
21+
);
22+
1723
public GitHubServiceImpl(String oauthToken) {
1824
try {
1925
this.github = new GitHubBuilder().withOAuthToken(oauthToken).build();
@@ -22,11 +28,27 @@ public GitHubServiceImpl(String oauthToken) {
2228
}
2329
}
2430

31+
@Override
32+
public GHTeam getTeamFromRepo(
33+
String repoName, String orgName, String teamName) throws IOException {
34+
GHOrganization org = github.getOrganization(orgName);
35+
GHRepository repo = org.getRepository(repoName);
36+
Set<GHTeam> teams = ((GHRepository) repo).getTeams();
37+
38+
for (GHTeam team : teams) {
39+
if (team.getName().equals(teamName)) {
40+
return team;
41+
}
42+
}
43+
return null;
44+
}
45+
2546
@Override
2647
public GHOrganization getOrganization(String name) throws IOException {
2748
return github.getOrganization(name);
2849
}
2950

51+
3052
@Override
3153
public void addDeveloperToTeam(GHTeam team, String developer) throws IOException {
3254
GHUser user = github.getUser(developer);
@@ -53,4 +75,32 @@ public GHTeam createTeam(String orgName, String teamName, GHTeam.Privacy privacy
5375
GHOrganization org = github.getOrganization(orgName);
5476
return org.createTeam(teamName).privacy(privacy).create();
5577
}
78+
79+
@Override
80+
public void updateTeamRole(GHRepository repo, GHTeam ghTeam, Role role) throws IOException {
81+
GHOrganization.Permission permission = PERMISSIONS_MAP.get(role);
82+
GHOrganization.RepositoryRole repoRole = GHOrganization.RepositoryRole.from(permission);
83+
ghTeam.add(repo, repoRole);
84+
}
85+
86+
@Override
87+
public void removeTeamFromRepository(GHTeam team, GHRepository repo) throws IOException {
88+
team.remove(repo);
89+
}
90+
91+
/**
92+
* Retrieves the names of all additional teams associated with the given GitHub repository, excluding the repo team.
93+
* This method returns only team names because the current Java GitHub API does not support retrieving roles
94+
* that teams hold within specific repositories. Therefore, role-related information is not available.
95+
*/
96+
@Override
97+
public Set<String> getCurrentTeams(GHRepository repo, GHTeam repoTeam) throws IOException {
98+
Set<GHTeam> allTeams = repo.getTeams();
99+
100+
return allTeams.stream()
101+
.filter(team -> !team.equals(repoTeam))
102+
.map(GHTeam::getName)
103+
.collect(Collectors.toSet());
104+
}
105+
56106
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
package io.jenkins.infra.repository_permissions_updater.github_team_sync;
2+
3+
import java.util.Set;
4+
5+
public class RepoTeamDefinition {
6+
7+
private String repoName;
8+
private String orgName;
9+
private String teamName;
10+
11+
private static final String DEFAULT_ORG_NAME = "jenkinsci";
12+
private final Role role = Role.ADMIN;
13+
private Set<String> developers;
14+
private Set<AdditionalTeamDefinition> additionalTeams;
15+
16+
public RepoTeamDefinition(String repoName, String orgName, String teamName,
17+
Set<String> developers, Set<AdditionalTeamDefinition> additionalTeams) {
18+
this.repoName = repoName;
19+
this.orgName = orgName != null ? orgName : DEFAULT_ORG_NAME;
20+
this.teamName = teamName;
21+
this.developers = developers;
22+
this.additionalTeams = additionalTeams;
23+
}
24+
25+
public RepoTeamDefinition() {
26+
}
27+
28+
29+
public String getRepoName() {
30+
return repoName;
31+
}
32+
33+
public String getOrgName() {
34+
return orgName;
35+
}
36+
37+
public String getTeamName() {
38+
return teamName;
39+
}
40+
41+
public Role getRole() {
42+
return role;
43+
}
44+
45+
public Set<String> getDevelopers() {
46+
return developers;
47+
}
48+
49+
public Set<AdditionalTeamDefinition> getAdditionalTeams() {
50+
return additionalTeams;
51+
}
52+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
package io.jenkins.infra.repository_permissions_updater.github_team_sync;
2+
3+
public enum Role {
4+
READ,
5+
TRIAGE,
6+
WRITE,
7+
MAINTAIN,
8+
ADMIN
9+
}
+10-11
Original file line numberDiff line numberDiff line change
@@ -2,32 +2,31 @@
22

33
import java.util.Set;
44

5-
public class GithubTeamDefinition {
6-
7-
private String repoName;
5+
public class SpecialTeamDefinition{
6+
private String orgName;
87
private String teamName;
98
private Set<String> developers;
109

11-
public GithubTeamDefinition(String repoName, String teamName, Set<String> developers) {
12-
this.repoName = repoName;
10+
private static final String DEFAULT_ORG_NAME = "jenkinsci";
11+
12+
public SpecialTeamDefinition(String orgName, String teamName, Set<String> developers) {
13+
this.orgName = orgName != null ? orgName : DEFAULT_ORG_NAME;
1314
this.teamName = teamName;
1415
this.developers = developers;
1516
}
1617

17-
public GithubTeamDefinition() {
18+
public SpecialTeamDefinition() {
1819
}
1920

20-
public String getName() {
21-
return repoName;
21+
public String getOrgName() {
22+
return orgName;
2223
}
2324

24-
public String getTeamName(){
25+
public String getTeamName() {
2526
return teamName;
2627
}
2728

2829
public Set<String> getDevelopers() {
2930
return developers;
3031
}
3132
}
32-
33-

src/main/java/io/jenkins/infra/repository_permissions_updater/github_team_sync/TeamSyncExecutor.java

+9-2
Original file line numberDiff line numberDiff line change
@@ -28,8 +28,15 @@ public void run(String[] args) {
2828
for (String yamlFilePath : args) {
2929
try {
3030
logger.info("Processing team configuration for file: " + yamlFilePath);
31-
GithubTeamDefinition team = YamlTeamLoader.loadTeam(yamlFilePath);
32-
teamUpdater.updateTeam(team);
31+
Object team = YamlTeamManager.loadTeam(yamlFilePath);
32+
33+
if (team instanceof RepoTeamDefinition) {
34+
teamUpdater.updateTeam((RepoTeamDefinition) team);
35+
} else if (team instanceof SpecialTeamDefinition) {
36+
teamUpdater.updateSpecialTeam((SpecialTeamDefinition) team);
37+
} else {
38+
throw new IllegalArgumentException("Unsupported team definition type.");
39+
}
3340
} catch (Exception e) {
3441
logger.error("Failed to update team for file " + yamlFilePath + ": " + e.getMessage(), e);
3542
}

0 commit comments

Comments
 (0)