Added some package-info files, added a method to archive repositories which contain a substring, and did some more testing. Will add a user interface soon.

This commit is contained in:
Andrew Lalis 2018-08-17 07:51:34 +02:00
parent 46757539a1
commit e901b0affd
7 changed files with 64 additions and 162 deletions

View File

@ -73,6 +73,12 @@
<artifactId>github-api</artifactId> <artifactId>github-api</artifactId>
<version>1.93</version> <version>1.93</version>
</dependency> </dependency>
<!-- SQLite JDBC Driver -->
<dependency>
<groupId>org.xerial</groupId>
<artifactId>sqlite-jdbc</artifactId>
<version>3.23.1</version>
</dependency>
</dependencies> </dependencies>
</project> </project>

View File

@ -56,8 +56,8 @@ public class Main {
); );
try { try {
githubManager.initializeGithubRepos(studentTeams); //githubManager.initializeGithubRepos(studentTeams);
//githubManager.deleteAllRepositories(); //githubManager.archiveAllRepositories("team");
} catch (Exception e) { } catch (Exception e) {
e.printStackTrace(); e.printStackTrace();
} }

View File

@ -1,7 +1,14 @@
package nl.andrewlalis.git_api; package nl.andrewlalis.git_api;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ObjectNode;
import nl.andrewlalis.model.Student; import nl.andrewlalis.model.Student;
import nl.andrewlalis.model.StudentTeam; import nl.andrewlalis.model.StudentTeam;
import org.apache.http.HttpResponse;
import org.apache.http.client.methods.HttpPatch;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClientBuilder;
import org.kohsuke.github.*; import org.kohsuke.github.*;
import java.io.IOException; import java.io.IOException;
@ -15,16 +22,6 @@ import java.util.logging.Logger;
*/ */
public class GithubManager { public class GithubManager {
/**
* The name of the organization to operate on.
*/
private String organizationName;
/**
* The object which simplifies creating REST URL's for most of the requests.
*/
private URLBuilder urlBuilder;
/** /**
* The assignments repository where students will get assignments from. * The assignments repository where students will get assignments from.
*/ */
@ -47,6 +44,7 @@ public class GithubManager {
*/ */
private GitHub github; private GitHub github;
private GHOrganization organization; private GHOrganization organization;
private String accessToken;
/** /**
* The logger for outputting debug info. * The logger for outputting debug info.
@ -57,15 +55,14 @@ public class GithubManager {
} }
public GithubManager(String organizationName, String accessToken, String assignmentsRepo, String teachingAssistantsTeamName, String studentRepoPrefix) { public GithubManager(String organizationName, String accessToken, String assignmentsRepo, String teachingAssistantsTeamName, String studentRepoPrefix) {
this.organizationName = organizationName;
this.assignmentsRepoName = assignmentsRepo; this.assignmentsRepoName = assignmentsRepo;
this.teachingAssistantsTeamName = teachingAssistantsTeamName; this.teachingAssistantsTeamName = teachingAssistantsTeamName;
this.studentRepoPrefix = studentRepoPrefix; this.studentRepoPrefix = studentRepoPrefix;
this.urlBuilder = new URLBuilder(organizationName, accessToken); this.accessToken = accessToken;
try { try {
this.github = GitHub.connectUsingOAuth(accessToken); this.github = GitHub.connectUsingOAuth(accessToken);
this.organization = this.github.getOrganization(this.organizationName); this.organization = this.github.getOrganization(organizationName);
} catch (IOException e) { } catch (IOException e) {
e.printStackTrace(); e.printStackTrace();
} }
@ -104,6 +101,13 @@ public class GithubManager {
* @throws IOException If an HTTP request failed. * @throws IOException If an HTTP request failed.
*/ */
private void setupAssignmentsRepo(GHTeam allTeachingAssistants) throws IOException { private void setupAssignmentsRepo(GHTeam allTeachingAssistants) throws IOException {
// Check if the repository already exists.
GHRepository existingRepo = this.organization.getRepository(this.assignmentsRepoName);
if (existingRepo != null) {
existingRepo.delete();
logger.fine("Deleted pre-existing assignments repository.");
}
// Create the repository. // Create the repository.
GHCreateRepositoryBuilder builder = this.organization.createRepository(this.assignmentsRepoName); GHCreateRepositoryBuilder builder = this.organization.createRepository(this.assignmentsRepoName);
builder.description("Assignments repository for Advanced Object Oriented Programming"); builder.description("Assignments repository for Advanced Object Oriented Programming");
@ -113,6 +117,7 @@ public class GithubManager {
builder.team(allTeachingAssistants); builder.team(allTeachingAssistants);
builder.gitignoreTemplate("Java"); builder.gitignoreTemplate("Java");
this.assignmentsRepo = builder.create(); this.assignmentsRepo = builder.create();
logger.info("Created assignments repository.");
// Protect the master branch. // Protect the master branch.
GHBranchProtectionBuilder protectionBuilder = this.assignmentsRepo.getBranch("master").enableProtection(); GHBranchProtectionBuilder protectionBuilder = this.assignmentsRepo.getBranch("master").enableProtection();
@ -121,9 +126,11 @@ public class GithubManager {
protectionBuilder.teamPushAccess(allTeachingAssistants); protectionBuilder.teamPushAccess(allTeachingAssistants);
protectionBuilder.addRequiredChecks("ci/circleci"); protectionBuilder.addRequiredChecks("ci/circleci");
protectionBuilder.enable(); protectionBuilder.enable();
logger.fine("Protected master branch of assignments repository.");
// Grant all teaching assistants write access. // Grant all teaching assistants write access.
allTeachingAssistants.add(this.assignmentsRepo, GHOrganization.Permission.ADMIN); allTeachingAssistants.add(this.assignmentsRepo, GHOrganization.Permission.ADMIN);
logger.fine("Gave admin rights to all teaching assistants in team: " + allTeachingAssistants.getName());
} }
/** /**
@ -185,9 +192,9 @@ public class GithubManager {
* @throws IOException if an error occurs with sending requests. * @throws IOException if an error occurs with sending requests.
*/ */
public void deleteAllRepositories() throws IOException { public void deleteAllRepositories() throws IOException {
Map<String, GHRepository> repoMap = this.organization.getRepositories(); List<GHRepository> repositories = this.organization.listRepositories().asList();
for (Map.Entry<String, GHRepository> repoEntry : repoMap.entrySet()) { for (GHRepository repo : repositories) {
repoEntry.getValue().delete(); repo.delete();
} }
} }
@ -195,8 +202,25 @@ public class GithubManager {
* Archives all repositories whose name contains the given substring. * Archives all repositories whose name contains the given substring.
* @param sub Any repository containing this substring will be archived. * @param sub Any repository containing this substring will be archived.
*/ */
public void archiveAllRepositories(String sub) { public void archiveAllRepositories(String sub) throws IOException {
List<GHRepository> repositories = this.organization.listRepositories().asList();
for (GHRepository repo : repositories) {
if (repo.getName().contains(sub)) {
HttpPatch patch = new HttpPatch("https://api.github.com/repos/" + repo.getFullName() + "?access_token=" + this.accessToken);
CloseableHttpClient client = HttpClientBuilder.create().build();
ObjectMapper mapper = new ObjectMapper();
ObjectNode root = mapper.createObjectNode();
root.put("archived", true);
String json = mapper.writeValueAsString(root);
patch.setEntity(new StringEntity(json));
HttpResponse response = client.execute(patch);
if (response.getStatusLine().getStatusCode() != 200) {
throw new IOException("Could not archive repository: " + repo.getName() + ". Code: " + response.getStatusLine().getStatusCode());
}
logger.info("Archived repository: " + repo.getFullName());
// TODO: archive repository using Github Java API, instead of Apache HttpUtils.
}
}
} }
} }

View File

@ -1,140 +0,0 @@
package nl.andrewlalis.git_api;
public class URLBuilder {
/**
* The main URL from which all requests must be formed.
*/
private static final String baseURL = "https://api.github.com";
/**
* The name of the github organization in which to create repositories.
*/
private String organizationName;
/**
* The token needed to use the API.
*/
private String accessToken;
public URLBuilder(String organizationName, String accessToken) {
this.organizationName = organizationName;
this.accessToken = accessToken;
}
/**
* @return The URL for adding a repository.
*/
public String buildRepoURL() {
return baseURL
+ "/orgs/"
+ this.organizationName
+ "/repos?access_token="
+ this.accessToken;
}
/**
* @param repoName The name of the repository.
* @param branch The name of the branch in the repository above.
* @return The URL for setting branch protection.
*/
public String buildBranchProtectionURL(String repoName, String branch) {
return baseURL
+ "/repos/"
+ this.organizationName
+ '/'
+ repoName
+ "/branches/"
+ branch
+ "/protection?access_token="
+ this.accessToken;
}
/**
* @param repoName The name of the repository the branch is in.
* @return The URL for getting a branch reference.
*/
public String buildReferenceGetURL(String repoName) {
return baseURL
+ "/repos/"
+ this.organizationName
+ '/'
+ repoName
+ "/git/refs/heads/master?access_token="
+ this.accessToken;
}
/**
* @param repoName The repository name.
* @return The URL for creating a new branch, once a reference has been obtained.
*/
public String buildReferencePostURL(String repoName) {
return baseURL
+ "/repos/"
+ this.organizationName
+ '/'
+ repoName
+ "/git/refs?access_token="
+ this.accessToken;
}
/**
* @param repoName The name of the repository.
* @param collaborator The collaborator's name.
* @return The URL for adding a collaborator to a repository.
*/
public String buildCollaboratorURL(String repoName, String collaborator) {
return baseURL
+ "/repos/"
+ this.organizationName
+ '/'
+ repoName
+ "/collaborators/"
+ collaborator
+ "?access_token="
+ this.accessToken;
}
/**
* @return The URL for obtaining the teams.
*/
public String buildTeamURL() {
return baseURL
+ "/orgs/"
+ this.organizationName
+ "/teams?access_token="
+ this.accessToken;
}
/**
* @param repoName The name of the repository.
* @param teamName The name of the team to set permissions for.
* @return The URL for setting team permissions of a repository.
*/
public String buildTeamPermissionsURL(String repoName, String teamName) {
return baseURL
+ "/teams/"
+ teamName
+ "/repos/"
+ this.organizationName
+ '/'
+ repoName
+ "?access_token="
+ this.accessToken;
}
/**
* @param repoName The name of the repository.
* @return The URL for archiving a repository.
*/
public String buildArchiveRepoURL(String repoName) {
return baseURL
+ "/repos/"
+ this.organizationName
+ '/'
+ repoName
+ "?access_token="
+ this.accessToken;
}
}

View File

@ -0,0 +1,7 @@
/**
* Contains all logic which directly interacts with the Github API. All methods which need to perform an action on a
* repository or team should find it within this package.
*
* @author Andrew Lalis
*/
package nl.andrewlalis.git_api;

View File

@ -1,7 +1,5 @@
package nl.andrewlalis.model; package nl.andrewlalis.model;
import org.kohsuke.github.GHTeam;
public class TeachingAssistant extends Person { public class TeachingAssistant extends Person {
/** /**

View File

@ -0,0 +1,7 @@
/**
* Contains all objects which form the conceptual basis for this application, such as Students, Teams, and any other
* abstract data containers.
*
* @author Andrew Lalis
*/
package nl.andrewlalis.model;