Half of features implemented #2
			
				
			
		
		
		
	
							
								
								
									
										6
									
								
								pom.xml
								
								
								
								
							
							
						
						
									
										6
									
								
								pom.xml
								
								
								
								
							| 
						 | 
					@ -67,6 +67,12 @@
 | 
				
			||||||
            <artifactId>jackson-annotations</artifactId>
 | 
					            <artifactId>jackson-annotations</artifactId>
 | 
				
			||||||
            <version>${jackson.version}</version>
 | 
					            <version>${jackson.version}</version>
 | 
				
			||||||
        </dependency>
 | 
					        </dependency>
 | 
				
			||||||
 | 
					        <!-- Github API Object Library -->
 | 
				
			||||||
 | 
					        <dependency>
 | 
				
			||||||
 | 
					            <groupId>org.kohsuke</groupId>
 | 
				
			||||||
 | 
					            <artifactId>github-api</artifactId>
 | 
				
			||||||
 | 
					            <version>1.93</version>
 | 
				
			||||||
 | 
					        </dependency>
 | 
				
			||||||
    </dependencies>
 | 
					    </dependencies>
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
</project>
 | 
					</project>
 | 
				
			||||||
| 
						 | 
					@ -1,6 +1,6 @@
 | 
				
			||||||
package nl.andrewlalis;
 | 
					package nl.andrewlalis;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import nl.andrewlalis.git_api.Initializer;
 | 
					import nl.andrewlalis.git_api.GithubManager;
 | 
				
			||||||
import nl.andrewlalis.model.StudentTeam;
 | 
					import nl.andrewlalis.model.StudentTeam;
 | 
				
			||||||
import nl.andrewlalis.util.Logging;
 | 
					import nl.andrewlalis.util.Logging;
 | 
				
			||||||
import nl.andrewlalis.util.TeamGenerator;
 | 
					import nl.andrewlalis.util.TeamGenerator;
 | 
				
			||||||
| 
						 | 
					@ -9,6 +9,7 @@ import java.io.IOException;
 | 
				
			||||||
import java.util.List;
 | 
					import java.util.List;
 | 
				
			||||||
import java.util.Map;
 | 
					import java.util.Map;
 | 
				
			||||||
import java.util.logging.ConsoleHandler;
 | 
					import java.util.logging.ConsoleHandler;
 | 
				
			||||||
 | 
					import java.util.logging.Handler;
 | 
				
			||||||
import java.util.logging.Level;
 | 
					import java.util.logging.Level;
 | 
				
			||||||
import java.util.logging.Logger;
 | 
					import java.util.logging.Logger;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -28,20 +29,25 @@ public class Main {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // Initialize logger.
 | 
					        // Initialize logger.
 | 
				
			||||||
        ConsoleHandler handler = new ConsoleHandler();
 | 
					        ConsoleHandler handler = new ConsoleHandler();
 | 
				
			||||||
        handler.setLevel(Level.FINEST);
 | 
					        handler.setLevel(Level.INFO);
 | 
				
			||||||
        logger.addHandler(handler);
 | 
					 | 
				
			||||||
        try {
 | 
					        try {
 | 
				
			||||||
            Logging.setup(true); // TODO: Replace true with command line arg.
 | 
					            Logging.setup(true); // TODO: Replace true with command line arg.
 | 
				
			||||||
 | 
					            Handler[] handlers = logger.getHandlers();
 | 
				
			||||||
 | 
					            for (Handler h : handlers) {
 | 
				
			||||||
 | 
					                logger.removeHandler(h);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            logger.setUseParentHandlers(false);
 | 
				
			||||||
 | 
					            logger.addHandler(handler);
 | 
				
			||||||
        } catch (IOException e) {
 | 
					        } catch (IOException e) {
 | 
				
			||||||
            logger.severe("Unable to save log to file.");
 | 
					            logger.severe("Unable to save log to file.");
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        logger.info("Initializer for Github Repositories in Educational Organizations.");
 | 
					        logger.info("GithubManager for Github Repositories in Educational Organizations.");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // Get studentTeams from CSV file.
 | 
					        // Get studentTeams from CSV file.
 | 
				
			||||||
        List<StudentTeam> studentTeams = getStudentTeamsFromCSV(userOptions.get("input"), Integer.parseInt(userOptions.get("teamsize")));
 | 
					        List<StudentTeam> studentTeams = getStudentTeamsFromCSV(userOptions.get("input"), Integer.parseInt(userOptions.get("teamsize")));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        Initializer initializer = new Initializer(
 | 
					        GithubManager githubManager = new GithubManager(
 | 
				
			||||||
                userOptions.get("organization"),
 | 
					                userOptions.get("organization"),
 | 
				
			||||||
                userOptions.get("token"),
 | 
					                userOptions.get("token"),
 | 
				
			||||||
                "assignments_2018",
 | 
					                "assignments_2018",
 | 
				
			||||||
| 
						 | 
					@ -50,7 +56,8 @@ public class Main {
 | 
				
			||||||
        );
 | 
					        );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        try {
 | 
					        try {
 | 
				
			||||||
            initializer.initializeGithubRepos(studentTeams);
 | 
					            githubManager.initializeGithubRepos(studentTeams);
 | 
				
			||||||
 | 
					            //githubManager.deleteAllRepositories();
 | 
				
			||||||
        } catch (Exception e) {
 | 
					        } catch (Exception e) {
 | 
				
			||||||
            e.printStackTrace();
 | 
					            e.printStackTrace();
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -0,0 +1,202 @@
 | 
				
			||||||
 | 
					package nl.andrewlalis.git_api;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import nl.andrewlalis.model.Student;
 | 
				
			||||||
 | 
					import nl.andrewlalis.model.StudentTeam;
 | 
				
			||||||
 | 
					import org.kohsuke.github.*;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import java.io.IOException;
 | 
				
			||||||
 | 
					import java.util.ArrayList;
 | 
				
			||||||
 | 
					import java.util.List;
 | 
				
			||||||
 | 
					import java.util.Map;
 | 
				
			||||||
 | 
					import java.util.logging.Logger;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * This class is responsible for initializing the Github repositories and setting permissions, adding teams, etc.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					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.
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    private GHRepository assignmentsRepo;
 | 
				
			||||||
 | 
					    private String assignmentsRepoName;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * The name of the team which contains all teaching assistants.
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    private String teachingAssistantsTeamName;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * The prefix used to prepend the names of student repositories.
 | 
				
			||||||
 | 
					     * Should ideally contain the current school year.
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    private String studentRepoPrefix;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * Github object for API interactions.
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    private GitHub github;
 | 
				
			||||||
 | 
					    private GHOrganization organization;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * The logger for outputting debug info.
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    private static final Logger logger = Logger.getLogger(GithubManager.class.getName());
 | 
				
			||||||
 | 
					    static {
 | 
				
			||||||
 | 
					        logger.setParent(Logger.getGlobal());
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public GithubManager(String organizationName, String accessToken, String assignmentsRepo, String teachingAssistantsTeamName, String studentRepoPrefix) {
 | 
				
			||||||
 | 
					        this.organizationName = organizationName;
 | 
				
			||||||
 | 
					        this.assignmentsRepoName = assignmentsRepo;
 | 
				
			||||||
 | 
					        this.teachingAssistantsTeamName = teachingAssistantsTeamName;
 | 
				
			||||||
 | 
					        this.studentRepoPrefix = studentRepoPrefix;
 | 
				
			||||||
 | 
					        this.urlBuilder = new URLBuilder(organizationName, accessToken);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        try {
 | 
				
			||||||
 | 
					            this.github = GitHub.connectUsingOAuth(accessToken);
 | 
				
			||||||
 | 
					            this.organization = this.github.getOrganization(this.organizationName);
 | 
				
			||||||
 | 
					        } catch (IOException e) {
 | 
				
			||||||
 | 
					            e.printStackTrace();
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * Initializes the github repository for all studentTeams given.
 | 
				
			||||||
 | 
					     *
 | 
				
			||||||
 | 
					     * Creates for the entire organization:
 | 
				
			||||||
 | 
					     * - an assignments repository with protected master branch and TA permissions.
 | 
				
			||||||
 | 
					     * Creates for each team:
 | 
				
			||||||
 | 
					     * - a repository
 | 
				
			||||||
 | 
					     * - protected master branch
 | 
				
			||||||
 | 
					     * - development branch
 | 
				
			||||||
 | 
					     * - adds students to repository
 | 
				
			||||||
 | 
					     * - adds all students to assignments repository.
 | 
				
			||||||
 | 
					     * @param studentTeams The list of student studentTeams.
 | 
				
			||||||
 | 
					     * @throws Exception If an error occurs while initializing the github repositories.
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    public void initializeGithubRepos(List<StudentTeam> studentTeams) throws Exception {
 | 
				
			||||||
 | 
					        GHTeam teamAll = this.organization.getTeamByName(this.teachingAssistantsTeamName);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        this.setupAssignmentsRepo(teamAll);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        StudentTeam t = new StudentTeam();
 | 
				
			||||||
 | 
					        Student s = new Student(3050831, "Andrew Lalis", "andrewlalisofficial@gmail.com", "andrewlalis", null);
 | 
				
			||||||
 | 
					        t.addStudent(s);
 | 
				
			||||||
 | 
					        t.setId(42);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        this.setupStudentTeam(t, teamAll);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * Sets up the organization's assignments repository, and grants permissions to all teaching assistants.
 | 
				
			||||||
 | 
					     * @param allTeachingAssistants A team consisting of all teaching assistants.
 | 
				
			||||||
 | 
					     * @throws IOException If an HTTP request failed.
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    private void setupAssignmentsRepo(GHTeam allTeachingAssistants) throws IOException {
 | 
				
			||||||
 | 
					        // Create the repository.
 | 
				
			||||||
 | 
					        GHCreateRepositoryBuilder builder = this.organization.createRepository(this.assignmentsRepoName);
 | 
				
			||||||
 | 
					        builder.description("Assignments repository for Advanced Object Oriented Programming");
 | 
				
			||||||
 | 
					        builder.wiki(false);
 | 
				
			||||||
 | 
					        builder.issues(true);
 | 
				
			||||||
 | 
					        builder.private_(false); // TODO: Make this true for production.
 | 
				
			||||||
 | 
					        builder.team(allTeachingAssistants);
 | 
				
			||||||
 | 
					        builder.gitignoreTemplate("Java");
 | 
				
			||||||
 | 
					        this.assignmentsRepo = builder.create();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // Protect the master branch.
 | 
				
			||||||
 | 
					        GHBranchProtectionBuilder protectionBuilder = this.assignmentsRepo.getBranch("master").enableProtection();
 | 
				
			||||||
 | 
					        protectionBuilder.includeAdmins(false);
 | 
				
			||||||
 | 
					        protectionBuilder.restrictPushAccess();
 | 
				
			||||||
 | 
					        protectionBuilder.teamPushAccess(allTeachingAssistants);
 | 
				
			||||||
 | 
					        protectionBuilder.addRequiredChecks("ci/circleci");
 | 
				
			||||||
 | 
					        protectionBuilder.enable();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // Grant all teaching assistants write access.
 | 
				
			||||||
 | 
					        allTeachingAssistants.add(this.assignmentsRepo, GHOrganization.Permission.ADMIN);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * Creates and sets up a student team's repository, and invites those students to the organization's assignments
 | 
				
			||||||
 | 
					     * repository as well.
 | 
				
			||||||
 | 
					     * @param team The student team to set up.
 | 
				
			||||||
 | 
					     * @param taTeam The team of teaching assistants that is responsible for these students.
 | 
				
			||||||
 | 
					     * @throws IOException If an HTTP request fails.
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    private void setupStudentTeam(StudentTeam team, GHTeam taTeam) throws IOException {
 | 
				
			||||||
 | 
					        String teamRepoName = team.generateUniqueName(this.studentRepoPrefix);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        List<Student> students = team.getStudents();
 | 
				
			||||||
 | 
					        StringBuilder description = new StringBuilder("Group ");
 | 
				
			||||||
 | 
					        description.append(team.getId()).append(": ");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        for (Student s : students) {
 | 
				
			||||||
 | 
					            description.append(s.getName()).append(' ');
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        GHCreateRepositoryBuilder builder = this.organization.createRepository(teamRepoName);
 | 
				
			||||||
 | 
					        builder.team(taTeam);
 | 
				
			||||||
 | 
					        builder.wiki(false);
 | 
				
			||||||
 | 
					        builder.issues(true);
 | 
				
			||||||
 | 
					        builder.description(description.toString());
 | 
				
			||||||
 | 
					        builder.gitignoreTemplate("Java");
 | 
				
			||||||
 | 
					        builder.private_(false); // TODO: Change this to true for production
 | 
				
			||||||
 | 
					        GHRepository repo = builder.create();
 | 
				
			||||||
 | 
					        logger.info("Created repository: " + repo.getName());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // Protect the master branch.
 | 
				
			||||||
 | 
					        GHBranchProtectionBuilder protectionBuilder = repo.getBranch("master").enableProtection();
 | 
				
			||||||
 | 
					        protectionBuilder.includeAdmins(false);
 | 
				
			||||||
 | 
					        protectionBuilder.teamPushAccess(taTeam);
 | 
				
			||||||
 | 
					        protectionBuilder.addRequiredChecks("ci/circleci");
 | 
				
			||||||
 | 
					        protectionBuilder.enable();
 | 
				
			||||||
 | 
					        logger.fine("Protected master branch of repository: " + repo.getName());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // Create development branch.
 | 
				
			||||||
 | 
					        String sha1 = repo.getBranch(repo.getDefaultBranch()).getSHA1();
 | 
				
			||||||
 | 
					        repo.createRef("refs/heads/development", sha1);
 | 
				
			||||||
 | 
					        logger.fine("Created development branch of repository: " + repo.getName());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        taTeam.add(repo, GHOrganization.Permission.ADMIN);
 | 
				
			||||||
 | 
					        logger.fine("Added team " + taTeam.getName() + " as admin to repository: " + repo.getName());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        List<GHUser> users = new ArrayList<>();
 | 
				
			||||||
 | 
					        for (Student student : team.getStudents()) {
 | 
				
			||||||
 | 
					            GHUser user = this.github.getUser(student.getGithubUsername());
 | 
				
			||||||
 | 
					            users.add(user);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        repo.addCollaborators(users);
 | 
				
			||||||
 | 
					        this.assignmentsRepo.addCollaborators(users);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * Deletes all repositories in the organization.
 | 
				
			||||||
 | 
					     * @throws IOException if an error occurs with sending requests.
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    public void deleteAllRepositories() throws IOException {
 | 
				
			||||||
 | 
					        Map<String, GHRepository> repoMap = this.organization.getRepositories();
 | 
				
			||||||
 | 
					        for (Map.Entry<String, GHRepository> repoEntry : repoMap.entrySet()) {
 | 
				
			||||||
 | 
					            repoEntry.getValue().delete();
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * Archives all repositories whose name contains the given substring.
 | 
				
			||||||
 | 
					     * @param sub Any repository containing this substring will be archived.
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    public void archiveAllRepositories(String sub) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -1,451 +0,0 @@
 | 
				
			||||||
package nl.andrewlalis.git_api;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
import com.fasterxml.jackson.core.JsonProcessingException;
 | 
					 | 
				
			||||||
import com.fasterxml.jackson.core.type.TypeReference;
 | 
					 | 
				
			||||||
import com.fasterxml.jackson.databind.ObjectMapper;
 | 
					 | 
				
			||||||
import com.fasterxml.jackson.databind.node.ArrayNode;
 | 
					 | 
				
			||||||
import com.fasterxml.jackson.databind.node.ObjectNode;
 | 
					 | 
				
			||||||
import nl.andrewlalis.model.Student;
 | 
					 | 
				
			||||||
import nl.andrewlalis.model.StudentTeam;
 | 
					 | 
				
			||||||
import nl.andrewlalis.model.TATeam;
 | 
					 | 
				
			||||||
import org.apache.http.HttpResponse;
 | 
					 | 
				
			||||||
import org.apache.http.StatusLine;
 | 
					 | 
				
			||||||
import org.apache.http.client.HttpClient;
 | 
					 | 
				
			||||||
import org.apache.http.client.methods.CloseableHttpResponse;
 | 
					 | 
				
			||||||
import org.apache.http.client.methods.HttpGet;
 | 
					 | 
				
			||||||
import org.apache.http.client.methods.HttpPost;
 | 
					 | 
				
			||||||
import org.apache.http.client.methods.HttpPut;
 | 
					 | 
				
			||||||
import org.apache.http.entity.StringEntity;
 | 
					 | 
				
			||||||
import org.apache.http.impl.client.CloseableHttpClient;
 | 
					 | 
				
			||||||
import org.apache.http.impl.client.HttpClientBuilder;
 | 
					 | 
				
			||||||
import org.apache.http.impl.client.HttpClients;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
import java.io.BufferedReader;
 | 
					 | 
				
			||||||
import java.io.IOException;
 | 
					 | 
				
			||||||
import java.io.InputStreamReader;
 | 
					 | 
				
			||||||
import java.io.UnsupportedEncodingException;
 | 
					 | 
				
			||||||
import java.util.HashMap;
 | 
					 | 
				
			||||||
import java.util.List;
 | 
					 | 
				
			||||||
import java.util.Map;
 | 
					 | 
				
			||||||
import java.util.logging.Logger;
 | 
					 | 
				
			||||||
import java.util.stream.Collectors;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/**
 | 
					 | 
				
			||||||
 * This class is responsible for initializing the Github repositories and setting permissions, adding teams, etc.
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
public class Initializer {
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    /**
 | 
					 | 
				
			||||||
     * The name of the organization to operate on.
 | 
					 | 
				
			||||||
     */
 | 
					 | 
				
			||||||
    private String organizationName;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    /**
 | 
					 | 
				
			||||||
     * The oauth access token needed for the request.
 | 
					 | 
				
			||||||
     */
 | 
					 | 
				
			||||||
    private String accessToken;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    /**
 | 
					 | 
				
			||||||
     * The object which simplifies creating REST URL's for most of the requests.
 | 
					 | 
				
			||||||
     */
 | 
					 | 
				
			||||||
    private URLBuilder urlBuilder;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    /**
 | 
					 | 
				
			||||||
     * The name of the assignments repository where students will get assignments from.
 | 
					 | 
				
			||||||
     */
 | 
					 | 
				
			||||||
    private String assignmentsRepo;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    /**
 | 
					 | 
				
			||||||
     * The name of the team which contains all teaching assistants.
 | 
					 | 
				
			||||||
     */
 | 
					 | 
				
			||||||
    private String teachingAssistantsTeamName;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    /**
 | 
					 | 
				
			||||||
     * The prefix used to prepend the names of student repositories.
 | 
					 | 
				
			||||||
     * Should ideally contain the current school year.
 | 
					 | 
				
			||||||
     */
 | 
					 | 
				
			||||||
    private String studentRepoPrefix;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    /**
 | 
					 | 
				
			||||||
     * The HttpClient object to use with all requests.
 | 
					 | 
				
			||||||
     */
 | 
					 | 
				
			||||||
    private HttpClient client;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    /**
 | 
					 | 
				
			||||||
     * ObjectMapper to use when constructing JSON objects.
 | 
					 | 
				
			||||||
     */
 | 
					 | 
				
			||||||
    private ObjectMapper mapper;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    /**
 | 
					 | 
				
			||||||
     * The logger for outputting debug info.
 | 
					 | 
				
			||||||
     */
 | 
					 | 
				
			||||||
    private static final Logger logger = Logger.getLogger(Initializer.class.getName());
 | 
					 | 
				
			||||||
    static {
 | 
					 | 
				
			||||||
        logger.setParent(Logger.getGlobal());
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    public Initializer(String organizationName, String accessToken, String assignmentsRepo, String teachingAssistantsTeamName, String studentRepoPrefix) {
 | 
					 | 
				
			||||||
        this.organizationName = organizationName;
 | 
					 | 
				
			||||||
        this.accessToken = accessToken;
 | 
					 | 
				
			||||||
        this.assignmentsRepo = assignmentsRepo;
 | 
					 | 
				
			||||||
        this.teachingAssistantsTeamName = teachingAssistantsTeamName;
 | 
					 | 
				
			||||||
        this.studentRepoPrefix = studentRepoPrefix;
 | 
					 | 
				
			||||||
        this.urlBuilder = new URLBuilder(organizationName, accessToken);
 | 
					 | 
				
			||||||
        this.client = HttpClientBuilder.create().build();
 | 
					 | 
				
			||||||
        this.mapper = new ObjectMapper();
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    /**
 | 
					 | 
				
			||||||
     * Initializes the github repository for all studentTeams given.
 | 
					 | 
				
			||||||
     *
 | 
					 | 
				
			||||||
     * Creates for the entire organization:
 | 
					 | 
				
			||||||
     * - an assignments repository with protected master branch and TA permissions.
 | 
					 | 
				
			||||||
     * Creates for each team:
 | 
					 | 
				
			||||||
     * - a repository
 | 
					 | 
				
			||||||
     * - protected master branch
 | 
					 | 
				
			||||||
     * - development branch
 | 
					 | 
				
			||||||
     * - adds students to repository
 | 
					 | 
				
			||||||
     * - adds all students to assignments repository.
 | 
					 | 
				
			||||||
     * @param studentTeams The list of student studentTeams.
 | 
					 | 
				
			||||||
     * @throws Exception If an error occurs while initializing the github repositories.
 | 
					 | 
				
			||||||
     */
 | 
					 | 
				
			||||||
    public void initializeGithubRepos(List<StudentTeam> studentTeams) throws Exception {
 | 
					 | 
				
			||||||
        List<TATeam> taTeams = listMemberTeams();
 | 
					 | 
				
			||||||
        TATeam teamAll = this.getTeamAll(taTeams, this.teachingAssistantsTeamName);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        this.setupAssignmentsRepo(teamAll);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    /**
 | 
					 | 
				
			||||||
     * Sets up the organization's assignments repository, and grants permissions to all teaching assistants.
 | 
					 | 
				
			||||||
     * @param allTeachingAssistants A team consisting of all teaching assistants.
 | 
					 | 
				
			||||||
     * @return True if everything went successfully, or false if an error occurred.
 | 
					 | 
				
			||||||
     * @throws IOException If an HTTP request failed.
 | 
					 | 
				
			||||||
     */
 | 
					 | 
				
			||||||
    private boolean setupAssignmentsRepo(TATeam allTeachingAssistants) throws IOException {
 | 
					 | 
				
			||||||
        // First, create the assignments repository.
 | 
					 | 
				
			||||||
        boolean successCreate = this.createRepository(this.assignmentsRepo, allTeachingAssistants);
 | 
					 | 
				
			||||||
        if (successCreate) {
 | 
					 | 
				
			||||||
            logger.info("Created repository: " + this.assignmentsRepo);
 | 
					 | 
				
			||||||
        } else {
 | 
					 | 
				
			||||||
            logger.severe("Could not create repository: " + this.assignmentsRepo);
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        // Then, protect the master branch.
 | 
					 | 
				
			||||||
        boolean successProtect = this.protectMasterBranch(this.assignmentsRepo, allTeachingAssistants);
 | 
					 | 
				
			||||||
        if (successProtect) {
 | 
					 | 
				
			||||||
            logger.info("Protected master branch of: " + this.assignmentsRepo);
 | 
					 | 
				
			||||||
        } else {
 | 
					 | 
				
			||||||
            logger.severe("Could not protect master branch of: " + this.assignmentsRepo);
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        // And finally give all teaching assistants admin permissions to the repository.
 | 
					 | 
				
			||||||
        boolean successGrant = this.grantTeamPermissions(this.assignmentsRepo, allTeachingAssistants);
 | 
					 | 
				
			||||||
        if (successGrant) {
 | 
					 | 
				
			||||||
            logger.info("Granted permissions to teaching assistants for: " + this.assignmentsRepo);
 | 
					 | 
				
			||||||
        } else {
 | 
					 | 
				
			||||||
            logger.severe("Could not grant permissions to teaching assistants for: " + this.assignmentsRepo);
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        return successCreate && successProtect && successGrant;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    /**
 | 
					 | 
				
			||||||
     * Creates and sets up a student team's repository, and invites those students to the organization's assignments
 | 
					 | 
				
			||||||
     * repository as well.
 | 
					 | 
				
			||||||
     * @param team The student team to set up.
 | 
					 | 
				
			||||||
     * @param taTeam The team of teaching assistants that is responsible for these students.
 | 
					 | 
				
			||||||
     * @return True if everything went according to plan, false if at least one error occurred.
 | 
					 | 
				
			||||||
     * @throws IOException If an HTTP request fails.
 | 
					 | 
				
			||||||
     */
 | 
					 | 
				
			||||||
    private boolean setupStudentTeam(StudentTeam team, TATeam taTeam) throws IOException {
 | 
					 | 
				
			||||||
        String teamRepoName = team.generateUniqueName(this.studentRepoPrefix);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        // First create the repository.
 | 
					 | 
				
			||||||
        boolean successCreate = this.createRepository(teamRepoName, taTeam);
 | 
					 | 
				
			||||||
        if (successCreate) {
 | 
					 | 
				
			||||||
            logger.info("Created repository: " + teamRepoName);
 | 
					 | 
				
			||||||
        } else {
 | 
					 | 
				
			||||||
            logger.severe("Could not create repository: " + teamRepoName);
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        // Then protect the master branch.
 | 
					 | 
				
			||||||
        boolean successProtect = this.protectMasterBranch(teamRepoName, taTeam);
 | 
					 | 
				
			||||||
        if (successProtect) {
 | 
					 | 
				
			||||||
            logger.info("Protected master branch of: " + teamRepoName);
 | 
					 | 
				
			||||||
        } else {
 | 
					 | 
				
			||||||
            logger.severe("Could not protect master branch of: " + teamRepoName);
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        // And finally create the development branch.
 | 
					 | 
				
			||||||
        boolean successDev = this.createDevelopmentBranch(teamRepoName);
 | 
					 | 
				
			||||||
        if (successDev) {
 | 
					 | 
				
			||||||
            logger.info("Created development branch for: " + teamRepoName);
 | 
					 | 
				
			||||||
        } else {
 | 
					 | 
				
			||||||
            logger.severe("Could not create development branch for: " + teamRepoName);
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        boolean successGrant = this.grantTeamPermissions(teamRepoName, taTeam);
 | 
					 | 
				
			||||||
        if (successGrant) {
 | 
					 | 
				
			||||||
            logger.info("Granted permissions for: " + teamRepoName + " to " + taTeam.getName());
 | 
					 | 
				
			||||||
        } else {
 | 
					 | 
				
			||||||
            logger.severe("Could not grant permissions for: " + teamRepoName + " to " + taTeam.getName());
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        Map<Student, Boolean[]> studentSuccesses = new HashMap<>();
 | 
					 | 
				
			||||||
        // For every student in the team, add them to the organization's assignments repo, and their own.
 | 
					 | 
				
			||||||
        for (Student student : team.getStudents()) {
 | 
					 | 
				
			||||||
            // First invite to their own repository.
 | 
					 | 
				
			||||||
            boolean successInviteOwn = this.addStudentToRepository(teamRepoName, student, true);
 | 
					 | 
				
			||||||
            if (successInviteOwn) {
 | 
					 | 
				
			||||||
                logger.info("Invited " + student + " to " + teamRepoName);
 | 
					 | 
				
			||||||
            } else {
 | 
					 | 
				
			||||||
                logger.severe("Could not invite " + student + " to " + teamRepoName);
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            // Then invite the student to the assignments repo.
 | 
					 | 
				
			||||||
            boolean successInviteAssign = this.addStudentToRepository(this.assignmentsRepo, student, false);
 | 
					 | 
				
			||||||
            if (successInviteAssign) {
 | 
					 | 
				
			||||||
                logger.info("Invited " + student + " to " + this.assignmentsRepo);
 | 
					 | 
				
			||||||
            } else {
 | 
					 | 
				
			||||||
                logger.severe("Could not invite " + student + " to " + this.assignmentsRepo);
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            studentSuccesses.put(student, new Boolean[]{successInviteOwn, successInviteAssign});
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        // Calculate total success.
 | 
					 | 
				
			||||||
        boolean allStudentSuccess = true;
 | 
					 | 
				
			||||||
        for (Map.Entry<Student, Boolean[]> entry : studentSuccesses.entrySet()) {
 | 
					 | 
				
			||||||
            for (boolean b : entry.getValue()) {
 | 
					 | 
				
			||||||
                allStudentSuccess &= b;
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        return successCreate && successProtect && successDev && successGrant && allStudentSuccess;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    /**
 | 
					 | 
				
			||||||
     * Invites a student as a collaborator to a repository.
 | 
					 | 
				
			||||||
     * @param repositoryName The name of the repository to invite the student to.
 | 
					 | 
				
			||||||
     * @param student The student to send the invitation to.
 | 
					 | 
				
			||||||
     * @param writeAllowed Whether or not the student is allowed to push to the repository.
 | 
					 | 
				
			||||||
     * @return True if successful and the invitation is created, false otherwise.
 | 
					 | 
				
			||||||
     * @throws IOException If an error occurs while performing a request or with json compiling.
 | 
					 | 
				
			||||||
     */
 | 
					 | 
				
			||||||
    private boolean addStudentToRepository(String repositoryName, Student student, boolean writeAllowed) throws IOException {
 | 
					 | 
				
			||||||
        // First create a simple JSON object that either gives push or pull permission.
 | 
					 | 
				
			||||||
        ObjectNode root = this.mapper.createObjectNode();
 | 
					 | 
				
			||||||
        root.put("permissions", (writeAllowed ? "push" : "pull"));
 | 
					 | 
				
			||||||
        String json = this.mapper.writeValueAsString(root);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        // Then make the request.
 | 
					 | 
				
			||||||
        HttpPut put = new HttpPut(this.urlBuilder.buildCollaboratorURL(repositoryName, student.getGithubUsername()));
 | 
					 | 
				
			||||||
        put.setEntity(new StringEntity(json));
 | 
					 | 
				
			||||||
        logger.fine("Sending PUT request to add student: " + student + " to repository: " + repositoryName);
 | 
					 | 
				
			||||||
        HttpResponse response = this.client.execute(put);
 | 
					 | 
				
			||||||
        logger.finest("Response from PUT to add student to repository: " + response.getStatusLine().getStatusCode());
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        // Only if 201 is returned do we know that a collaborator is invited.
 | 
					 | 
				
			||||||
        return response.getStatusLine().getStatusCode() == 201;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    /**
 | 
					 | 
				
			||||||
     * Creates the development branch needed by all student repositories.
 | 
					 | 
				
			||||||
     * @param repositoryName The name of the repository.
 | 
					 | 
				
			||||||
     * @return True if the branch could successfully be created, false otherwise.
 | 
					 | 
				
			||||||
     * @throws IOException If an error occurs while performing a request or with json compiling.
 | 
					 | 
				
			||||||
     */
 | 
					 | 
				
			||||||
    private boolean createDevelopmentBranch(String repositoryName) throws IOException {
 | 
					 | 
				
			||||||
        // First obtain a reference for the repository.
 | 
					 | 
				
			||||||
        HttpGet get = new HttpGet(this.urlBuilder.buildReferenceGetURL(repositoryName));
 | 
					 | 
				
			||||||
        HttpResponse getResponse = this.client.execute(get);
 | 
					 | 
				
			||||||
        if (getResponse.getStatusLine().getStatusCode() != 200) {
 | 
					 | 
				
			||||||
            return false;
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
        ObjectNode responseRoot = this.mapper.valueToTree(getResponseBody(getResponse));
 | 
					 | 
				
			||||||
        String sha = responseRoot.get("object").get("sha").textValue();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        // Construct the request data.
 | 
					 | 
				
			||||||
        ObjectNode root = this.mapper.createObjectNode();
 | 
					 | 
				
			||||||
        root.put("ref", "refs/heads/development");
 | 
					 | 
				
			||||||
        root.put("sha", sha);
 | 
					 | 
				
			||||||
        String json = this.mapper.writeValueAsString(root);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        // Send the request.
 | 
					 | 
				
			||||||
        HttpPost post = new HttpPost(this.urlBuilder.buildReferencePostURL(repositoryName));
 | 
					 | 
				
			||||||
        post.setEntity(new StringEntity(json));
 | 
					 | 
				
			||||||
        logger.fine("Sending POST request to create development branch for repository: " + repositoryName);
 | 
					 | 
				
			||||||
        HttpResponse postResponse = this.client.execute(post);
 | 
					 | 
				
			||||||
        logger.finest("Response from POST to create development branch: " + postResponse.getStatusLine().getStatusCode());
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        // Only if 201 is returned, is this successful.
 | 
					 | 
				
			||||||
        return postResponse.getStatusLine().getStatusCode() == 201;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    /**
 | 
					 | 
				
			||||||
     * Grants the given team admin permissions to the repository with the given name.
 | 
					 | 
				
			||||||
     * @param repositoryName The name of the repository.
 | 
					 | 
				
			||||||
     * @param team The team to give admin permissions to.
 | 
					 | 
				
			||||||
     * @return True if rights were successfully granted, false otherwise.
 | 
					 | 
				
			||||||
     * @throws IOException If an error occurs while attempting to give a team admin rights over the repository.
 | 
					 | 
				
			||||||
     */
 | 
					 | 
				
			||||||
    private boolean grantTeamPermissions(String repositoryName, TATeam team) throws IOException {
 | 
					 | 
				
			||||||
        // First, create the JSON object, which is simply one value pair.
 | 
					 | 
				
			||||||
        ObjectNode root = this.mapper.createObjectNode();
 | 
					 | 
				
			||||||
        root.put("permission", "admin");
 | 
					 | 
				
			||||||
        String json = this.mapper.writeValueAsString(root);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        // Create and send request.
 | 
					 | 
				
			||||||
        HttpPut put = new HttpPut(this.urlBuilder.buildTeamPermissionsURL(repositoryName, String.valueOf(team.getId())));
 | 
					 | 
				
			||||||
        put.setEntity(new StringEntity(json));
 | 
					 | 
				
			||||||
        logger.fine("Sending PUT request to add team " + team.getName() + " as admins for repo: " + repositoryName);
 | 
					 | 
				
			||||||
        HttpResponse response = this.client.execute(put);
 | 
					 | 
				
			||||||
        logger.finest("Response from adding team as admins: " + response.getStatusLine().getStatusCode());
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        // Return true only if request returns 204.
 | 
					 | 
				
			||||||
        return response.getStatusLine().getStatusCode() == 204;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    /**
 | 
					 | 
				
			||||||
     * Protects the master branch of the given repository.
 | 
					 | 
				
			||||||
     * @see <a href="https://developer.github.com/v3/repos/branches/#update-branch-protection">Github Branch Protection</a>
 | 
					 | 
				
			||||||
     * @param repositoryName The repository to protect the master branch of.
 | 
					 | 
				
			||||||
     * @param taTeam The team to give rights to.
 | 
					 | 
				
			||||||
     * @return True if the master branch has been protected, false otherwise.
 | 
					 | 
				
			||||||
     * @throws IOException If an error occurs with requests or compiling json.
 | 
					 | 
				
			||||||
     */
 | 
					 | 
				
			||||||
    private boolean protectMasterBranch(String repositoryName, TATeam taTeam) throws IOException {
 | 
					 | 
				
			||||||
        // First, create quite a complex JSON object.
 | 
					 | 
				
			||||||
        // settings
 | 
					 | 
				
			||||||
        ObjectNode root = this.mapper.createObjectNode();
 | 
					 | 
				
			||||||
        // required_status_checks
 | 
					 | 
				
			||||||
        {
 | 
					 | 
				
			||||||
            ObjectNode requiredStatusChecksNode = this.mapper.createObjectNode();
 | 
					 | 
				
			||||||
            requiredStatusChecksNode.put("strict", false);
 | 
					 | 
				
			||||||
            // contexts
 | 
					 | 
				
			||||||
            {
 | 
					 | 
				
			||||||
                ArrayNode contextsNode = this.mapper.createArrayNode();
 | 
					 | 
				
			||||||
                contextsNode.add("ci/circleci");
 | 
					 | 
				
			||||||
                requiredStatusChecksNode.set("contexts", contextsNode);
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
            root.set("required_status_checks", requiredStatusChecksNode);
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
        root.put("enforce_admins", false);
 | 
					 | 
				
			||||||
        root.set("required_pull_request_reviews", this.mapper.createObjectNode());
 | 
					 | 
				
			||||||
        // restrictions
 | 
					 | 
				
			||||||
        {
 | 
					 | 
				
			||||||
            ObjectNode restrictionsNode = this.mapper.createObjectNode();
 | 
					 | 
				
			||||||
            restrictionsNode.set("users", this.mapper.createArrayNode());
 | 
					 | 
				
			||||||
            // teams
 | 
					 | 
				
			||||||
            {
 | 
					 | 
				
			||||||
                ArrayNode teamsNode = this.mapper.createArrayNode();
 | 
					 | 
				
			||||||
                teamsNode.add(taTeam.getName());
 | 
					 | 
				
			||||||
                restrictionsNode.set("teams", teamsNode);
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
            root.set("restrictions", restrictionsNode);
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
        String json = this.mapper.writer().writeValueAsString(root);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        // Create request and put the json to the server.
 | 
					 | 
				
			||||||
        HttpPut put = new HttpPut(this.urlBuilder.buildBranchProtectionURL(repositoryName, "master"));
 | 
					 | 
				
			||||||
        put.setEntity(new StringEntity(json));
 | 
					 | 
				
			||||||
        put.setHeader("Accept", "application/vnd.github.luke-cage-preview+json");
 | 
					 | 
				
			||||||
        logger.fine("Sending PUT request to protect master branch of repository: " + repositoryName);
 | 
					 | 
				
			||||||
        HttpResponse response = this.client.execute(put);
 | 
					 | 
				
			||||||
        logger.finest("Response from protecting master branch: " + response.getStatusLine().getStatusCode());
 | 
					 | 
				
			||||||
        logger.finest(getResponseBody(response));
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        // Return true only if the status code is 200.
 | 
					 | 
				
			||||||
        return response.getStatusLine().getStatusCode() == 200;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    /**
 | 
					 | 
				
			||||||
     * Creates a repository of the given name and assigns the given team to it.
 | 
					 | 
				
			||||||
     * @param repositoryName The name of the repository to make.
 | 
					 | 
				
			||||||
     * @param taTeam The team to assign to this repository.
 | 
					 | 
				
			||||||
     * @return True if the repository was created successfully, or false if an error occurred.
 | 
					 | 
				
			||||||
     * @throws IOException If an error occurs during http requesting or JSON processing.
 | 
					 | 
				
			||||||
     */
 | 
					 | 
				
			||||||
    private boolean createRepository(String repositoryName, TATeam taTeam) throws IOException {
 | 
					 | 
				
			||||||
        logger.info("Creating repository: " + repositoryName);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        ObjectNode root = this.mapper.createObjectNode();
 | 
					 | 
				
			||||||
        root.put("name", repositoryName);
 | 
					 | 
				
			||||||
        root.put("private", false);
 | 
					 | 
				
			||||||
        root.put("has_issues", true);
 | 
					 | 
				
			||||||
        root.put("has_wiki", true);
 | 
					 | 
				
			||||||
        root.put("team_id", taTeam.getId());
 | 
					 | 
				
			||||||
        root.put("auto_init", false);
 | 
					 | 
				
			||||||
        root.put("gitignore_template", "Java");
 | 
					 | 
				
			||||||
        String json = this.mapper.writer().writeValueAsString(root);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        // Create the request and post it.
 | 
					 | 
				
			||||||
        HttpPost post = new HttpPost(this.urlBuilder.buildRepoURL());
 | 
					 | 
				
			||||||
        post.setEntity(new StringEntity(json));
 | 
					 | 
				
			||||||
        post.setHeader("Content-type", "application/json");
 | 
					 | 
				
			||||||
        logger.fine("Sending POST request to create repository: " + repositoryName);
 | 
					 | 
				
			||||||
        HttpResponse response = this.client.execute(post);
 | 
					 | 
				
			||||||
        logger.finest("Response from creating repository POST: " + response.getStatusLine().getStatusCode());
 | 
					 | 
				
			||||||
        logger.finest(getResponseBody(response));
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        // Return true if 201 is the response code, and false otherwise.
 | 
					 | 
				
			||||||
        return response.getStatusLine().getStatusCode() == 201;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    /**
 | 
					 | 
				
			||||||
     * Extracts the team containing all TA's from a list of all teams.
 | 
					 | 
				
			||||||
     * @param taTeams The list of all teams in the organization.
 | 
					 | 
				
			||||||
     * @param teamAllName The name of the team representing all TA's.
 | 
					 | 
				
			||||||
     * @return The team which holds all TA's.
 | 
					 | 
				
			||||||
     * @throws Exception If no team with the given name exists.
 | 
					 | 
				
			||||||
     */
 | 
					 | 
				
			||||||
    private TATeam getTeamAll(List<TATeam> taTeams, String teamAllName) throws Exception {
 | 
					 | 
				
			||||||
        for (TATeam team : taTeams) {
 | 
					 | 
				
			||||||
            if (team.getName().equals(teamAllName)) {
 | 
					 | 
				
			||||||
                return team;
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
        throw new Exception("No team with name " + teamAllName + " could be found.");
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    /**
 | 
					 | 
				
			||||||
     * Obtains a list of all teams in the organization, meaning all teaching assistant teams.
 | 
					 | 
				
			||||||
     * @return A list of all teams in the organization.
 | 
					 | 
				
			||||||
     */
 | 
					 | 
				
			||||||
    private List<TATeam> listMemberTeams() {
 | 
					 | 
				
			||||||
        CloseableHttpClient client = HttpClients.createDefault();
 | 
					 | 
				
			||||||
        HttpGet get = new HttpGet(this.urlBuilder.buildTeamURL());
 | 
					 | 
				
			||||||
        try (CloseableHttpResponse response = client.execute(get)) {
 | 
					 | 
				
			||||||
            StatusLine line = response.getStatusLine();
 | 
					 | 
				
			||||||
            logger.finer("Response code from listing member teams: " + line.getStatusCode());
 | 
					 | 
				
			||||||
            String result = getResponseBody(response);
 | 
					 | 
				
			||||||
            logger.finer("Response entity: " + result);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            ObjectMapper mapper = new ObjectMapper();
 | 
					 | 
				
			||||||
            List<TATeam> memberTeams = mapper.readValue(result, new TypeReference<List<TATeam>>(){});
 | 
					 | 
				
			||||||
            for (TATeam r : memberTeams) {
 | 
					 | 
				
			||||||
                logger.finest(r.toString());
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
            return memberTeams;
 | 
					 | 
				
			||||||
        } catch (IOException e) {
 | 
					 | 
				
			||||||
            e.printStackTrace();
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
        return null;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    /**
 | 
					 | 
				
			||||||
     * Extracts a string which represents the response body of an HttpResponse.
 | 
					 | 
				
			||||||
     * @param response The response to a previous request.
 | 
					 | 
				
			||||||
     * @return A string containing the whole response body.
 | 
					 | 
				
			||||||
     */
 | 
					 | 
				
			||||||
    private static String getResponseBody(HttpResponse response) {
 | 
					 | 
				
			||||||
        try {
 | 
					 | 
				
			||||||
            return new BufferedReader(new InputStreamReader(response.getEntity().getContent())).lines().collect(Collectors.joining("\n"));
 | 
					 | 
				
			||||||
        } catch (IOException e) {
 | 
					 | 
				
			||||||
            e.printStackTrace();
 | 
					 | 
				
			||||||
            return "";
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
| 
						 | 
					@ -11,7 +11,6 @@ import java.util.List;
 | 
				
			||||||
 * Represents a teaching assistant team, which is itself a 'team' in the organization. This class is used for parsing
 | 
					 * Represents a teaching assistant team, which is itself a 'team' in the organization. This class is used for parsing
 | 
				
			||||||
 * json from requests to github to get a list of all teams in the organization.
 | 
					 * json from requests to github to get a list of all teams in the organization.
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
@JsonIgnoreProperties(ignoreUnknown = true)
 | 
					 | 
				
			||||||
public class TATeam {
 | 
					public class TATeam {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    private List<TeachingAssistant> teachingAssistants;
 | 
					    private List<TeachingAssistant> teachingAssistants;
 | 
				
			||||||
| 
						 | 
					@ -19,13 +18,11 @@ public class TATeam {
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
     * The team's display name.
 | 
					     * The team's display name.
 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
    @JsonProperty("name")
 | 
					 | 
				
			||||||
    private String name;
 | 
					    private String name;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
     * The team's unique identifier.
 | 
					     * The team's unique identifier.
 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
    @JsonProperty("id")
 | 
					 | 
				
			||||||
    private int id;
 | 
					    private int id;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
| 
						 | 
					@ -33,8 +30,7 @@ public class TATeam {
 | 
				
			||||||
     * @param name The name of the team.
 | 
					     * @param name The name of the team.
 | 
				
			||||||
     * @param id The unique identifier for this team.
 | 
					     * @param id The unique identifier for this team.
 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
    @JsonCreator
 | 
					    public TATeam(String name, int id) {
 | 
				
			||||||
    public TATeam(@JsonProperty("name") String name, @JsonProperty("id") int id) {
 | 
					 | 
				
			||||||
        this.name = name;
 | 
					        this.name = name;
 | 
				
			||||||
        this.id = id;
 | 
					        this.id = id;
 | 
				
			||||||
        this.teachingAssistants = new ArrayList<TeachingAssistant>();
 | 
					        this.teachingAssistants = new ArrayList<TeachingAssistant>();
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,5 +1,7 @@
 | 
				
			||||||
package nl.andrewlalis.model;
 | 
					package nl.andrewlalis.model;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import org.kohsuke.github.GHTeam;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
public class TeachingAssistant extends Person {
 | 
					public class TeachingAssistant extends Person {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -67,7 +67,7 @@ public class CommandLine {
 | 
				
			||||||
        options.addOption(organizationInput);
 | 
					        options.addOption(organizationInput);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // The maximum team size.
 | 
					        // The maximum team size.
 | 
				
			||||||
        Option teamSizeInput = new Option("s", "teamsize", true, "The maximum size of teams to generate.");
 | 
					        Option teamSizeInput = new Option("ts", "teamsize", true, "The maximum size of teams to generate.");
 | 
				
			||||||
        teamSizeInput.setRequired(false);
 | 
					        teamSizeInput.setRequired(false);
 | 
				
			||||||
        options.addOption(teamSizeInput);
 | 
					        options.addOption(teamSizeInput);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in New Issue