def delete_team_repository(self, course, team, fail_if_not_exists=True): ghrepo_name = self.__get_team_ghrepo_name(course, team) github_repo = self.__get_repository(ghrepo_name) if github_repo is None: if fail_if_not_exists: raise ChisubmitException( "Trying to delete a repository that doesn't exist (%s)" % (ghrepo_name)) else: return try: github_repo.delete() except GithubException as ge: raise ChisubmitException( "Unexpected exception deleting repository %s (%i: %s)" % (ghrepo_name, ge.status, ge.data["message"]), ge) github_team_name = self.__get_team_ghteam_name(course, team) github_team = self.__get_ghteam_by_name(github_team_name) try: github_team.delete() except GithubException as ge: raise ChisubmitException( "Unexpected exception deleting team %s (%i: %s)" % (github_team_name, ge.status, ge.data["message"]), ge)
def __init__(self, connection_string, staging): if connection_string.server_type != self.get_server_type_name(): raise ChisubmitException( "Expected server_type in connection string to be '%s', got '%s'" % (self.get_server_type_name(), connection_string.server_type)) param_names = connection_string.params.keys() for p in self.get_connstr_mandatory_params(): if p not in param_names: raise ChisubmitException( "Connection string does not have required parameter '%s'" % p) param_names.remove(p) setattr(self, p, connection_string.params[p]) for p in param_names: if p not in self.get_connstr_optional_params(): raise ChisubmitException( "Connection string has invalid parameter '%s'" % p) setattr(self, p, connection_string.params[p]) for p in self.get_connstr_optional_params(): if p not in param_names: setattr(self, p, None) self.staging = staging self.is_connected = False
def create_grading_repo(cls, config, course, team, registration, staging_only): base_dir = config.work_dir if not staging_only: conn_server = create_connection(course, config) if conn_server is None: raise ChisubmitException("Could not connect to git server") conn_staging = create_connection(course, config, staging=True) if conn_staging is None: raise ChisubmitException("Could not connect to git staging server") repo_path = cls.get_grading_repo_path(base_dir, course, team, registration) staging_url = conn_staging.get_repository_git_url(course, team) if staging_only: repo = LocalGitRepo.create_repo(repo_path, clone_from_url=staging_url) else: server_url = conn_server.get_repository_git_url(course, team) repo = LocalGitRepo.create_repo(repo_path, clone_from_url=server_url, remotes=[("staging", staging_url)]) if registration.final_submission is None: commit_sha = None else: commit_sha = registration.final_submission.commit_sha return cls(team, registration, repo, repo_path, commit_sha, staging_only)
def __load_config_and_client(require_local): ctx = get_current_context() try: ctx.obj["config"] = Config.get_config(ctx.obj["config_dir"], ctx.obj["work_dir"], ctx.obj["config_overrides"]) except ConfigDirectoryNotFoundException: if not require_local: ctx.obj["config"] = Config.get_global_config( ctx.obj["config_overrides"]) else: raise ChisubmitException( "This command must be run in a directory configured to use chisubmit." ) api_url = ctx.obj["config"].get_api_url() api_key = ctx.obj["config"].get_api_key() ssl_verify = ctx.obj["config"].get_ssl_verify() if api_url is None: raise ChisubmitException("Configuration value 'api-url' not found") if api_key is None: raise ChisubmitException("No chisubmit credentials were found!") ctx.obj["client"] = Chisubmit(api_key, base_url=api_url, ssl_verify=ssl_verify)
def checkout_branch(self, branch): branch_refpath = "refs/heads/%s" % branch branch_head = self.__get_head(branch_refpath) if branch_head is None: raise ChisubmitException("No such branch: %s" % branch) try: branch_head.checkout() except GitCommandError: raise ChisubmitException("Error checking out")
def checkout_commit(self, commit_sha): commit = self.get_commit(commit_sha) if commit is None: raise ChisubmitException( "Tried to checkout a commit that does not exist: %s" % commit_sha) try: self.repo.git.checkout(commit_sha) except GitCommandError: raise ChisubmitException("Could not checkout commit %s" % commit_sha)
def __add_user_to_ghteam(self, github_id, ghteam): github_user = self.__get_user(github_id) if github_user is None: raise ChisubmitException("GitHub user '%s' does not exist " % github_id) try: self.__pygithub_add_membership(ghteam, github_user) except GithubException as ge: raise ChisubmitException( "Unexpected exception adding user %s to team (%i: %s)" % (github_id, ge.status, ge.data["message"]), ge)
def create_grading_branch(self): branch_name = self.registration.get_grading_branch_name() if self.repo.has_branch(branch_name): raise ChisubmitException("%s repository already has a %s branch" % (self.team.team_id, branch_name)) if self.commit_sha is not None: commit = self.repo.get_commit(self.commit_sha) if commit is None: self.sync() commit = self.repo.get_commit(self.commit_sha) if commit is None: raise ChisubmitException("%s repository does not have a commit %s" % (self.team.team_id, self.commit_sha)) self.repo.create_branch(branch_name, self.commit_sha) self.repo.checkout_branch(branch_name)
def get_credentials(self, username, password, delete_repo=False): gh = Github(username, password) token = None try: u = gh.get_user() scopes = ['user', 'public_repo', 'repo', 'gist'] note = "Created by chisubmit." if delete_repo: scopes.append("delete_repo") note += " Has delete permissions." auth = None for a in u.get_authorizations(): if a.note == note: auth = a break if auth is None: existing = False auth = u.create_authorization(scopes=scopes, note=note) else: existing = True token = auth.token except GithubException as ge: if ge.status == 401: return None, False else: raise ChisubmitException( "Unexpected error creating authorization token (%i: %s)" % (ge.status, ge.data["message"]), ge) return token, existing
def create_team_repository(self, course, team, fail_if_exists=True, private=True): repo_path = self.__get_team_path(course, team) if os.path.exists(repo_path) and fail_if_exists: raise ChisubmitException("Repository %s already exists" % repo_path) repo = LocalGitRepo.create_repo(repo_path, bare=True)
def __add_user_to_ghteam_by_name(self, github_id, ghteam_name): ghteam = self.__get_ghteam_by_name(ghteam_name) if ghteam is None: raise ChisubmitException("GitHub team '%s' does not exist " % ghteam_name) self.__add_user_to_ghteam(github_id, ghteam)
def checkout_grading_branch(self): branch_name = self.registration.get_grading_branch_name() if not self.repo.has_branch(branch_name): raise ChisubmitException( "%s repository does not have a %s branch" % (self.team.team_id, branch_name)) self.repo.checkout_branch(branch_name)
def save_config_file_values(config_file, config_values): try: f = open(config_file, 'w') yaml.safe_dump(config_values, f, default_flow_style=False) f.close() except IOError as ioe: raise ChisubmitException( "Error when saving configuration to file %s: %s" % (config_file, ioe), ioe)
def __init__(self, s): params = s.split(";") params = [x.split("=", 1) for x in params] try: params = dict([(k.strip(), v.strip()) for k, v in params]) except ValueError as ve: raise ChisubmitException( "Improperly formatted connection string: %s" % s, original_exception=ve) if "server_type" not in params: raise ChisubmitException( "Connection string does not have 'server_type' parameter: %s" % s) self.server_type = params.pop("server_type") self.params = params
def shared_team_show(ctx, course, team_id): team = course.get_team(team_id) if team is None: print "Team %s does not exist" % team_id ctx.exit(CHISUBMIT_FAIL) print "Team name: %s" % team.id print print "Extensions available: %i" % team.extensions_available print if len(team.extras) > 0: print "Attributes:" for k, v in team.extras.items(): print " - %s: %s" % (k, v) print if len(team.students) == 0: print "No students in this team" else: print "STUDENTS" print "--------" for student in team.students: if student.status == 0: status = "UNCONFIRMED" elif student.status == 1: status = "CONFIRMED" else: raise ChisubmitException( "Student '%s' in team '%s' has unknown status %i" % (student.user.id, team.id, student.status)) print "%s: %s, %s (%s)" % (student.user.id, student.user.last_name, student.user.first_name, status) print if len(team.assignments) == 0: print "This team is not registered for any assignments." else: print "ASSIGNMENTS" print "-----------" for ta in team.assignments: assignment = course.get_assignment(ta.assignment_id) print "ID: %s" % assignment.id print "Name: %s" % assignment.name print "Deadline: %s" % convert_datetime_to_local( assignment.deadline).isoformat(" ") if ta.submitted_at is not None: print "Last submitted at: %s" % convert_datetime_to_local( ta.submitted_at).isoformat(" ") print "Commit SHA: %s" % ta.commit_sha print "Extensions used: %i" % ta.extensions_used else: print "NOT SUBMITTED" print
def __push_grading_branch(self, remote_name, push_master = False): branch_name = self.registration.get_grading_branch_name() if not self.repo.has_branch(branch_name): raise ChisubmitException("%s repository does not have a %s branch" % (self.team.id, branch_name)) if push_master: self.repo.push(remote_name, "master") self.repo.push(remote_name, branch_name)
def __init__(self, s): params = s.split(";") params = [x.split("=", 1) for x in params] try: params = dict([(k.strip(), v.strip()) for k, v in params]) except ValueError, ve: raise ChisubmitException( "Improperly formatted connection string: %s" % s, original_exception=ve)
def reset_branch(self, remote_name, branch): branch_refpath = "refs/heads/%s" % branch remote_branch_refpath = "refs/remotes/%s/%s" % (remote_name, branch) branch_head = self.__get_head(branch_refpath) remote_branch = self.__get_ref(remote_branch_refpath) if branch_head is None: raise ChisubmitException("No such branch: %s" % branch) if remote_branch is None: raise ChisubmitException("No such remote branch: %s" % branch) if self.repo.head.is_detached or self.repo.head.ref != branch_head: try: branch_head.checkout() except GitCommandError, gce: print gce raise ChisubmitException("Error checking out")
def create_connection(connection_string, staging): cs = ConnectionString(connection_string) if not RemoteRepositoryConnectionFactory.server_types.has_key(cs.server_type): raise ChisubmitException("Unsupported server type in connection string: %s (expected one of: %s)" % (cs.server_type, ", ".join(RemoteRepositoryConnectionFactory.server_types.keys()))) conn_cls = RemoteRepositoryConnectionFactory.server_types[cs.server_type] return conn_cls(cs, staging)
def set_auth(server, config_profile): if config_profile.has_key("auth"): if config_profile["auth"]["type"] == "testing": server.set_auth_testing(config_profile["auth"]["password"]) elif config_profile["auth"]["type"] == "ldap": server.set_auth_ldap(config_profile["auth"]["server-uri"], config_profile["auth"]["base-dn"]) else: raise ChisubmitException("Unrecognized authentication type: %s" % config_profile["auth"]["type"])
def save(self): user_options = dict((k, v) for k, v in self.options.items() if k not in self.IMPLICIT_FIELDS) try: f = open(self.config_file, 'w') yaml.safe_dump(user_options, f, default_flow_style=False) f.close() except IOError, ioe: raise ChisubmitException( "Error when saving configuration to file %s: %s" % (self.config_file, ioe.meesage), ioe)
def __get_user(self, username): try: user = self.gh.get_user(username) return user except GithubException as ge: if ge.status == 404: return None else: raise ChisubmitException( "Unexpected error with user %s (%i: %s)" % (username, ge.status, ge.data["message"]), ge)
def connect(self, credentials): # Credentials are a GitHub access token self.gh = Github(credentials) try: self.organization = self.gh.get_organization( self.github_organization) except GithubException as ge: if ge.status == 401: raise ChisubmitException("Invalid Github Credentials", ge) elif ge.status == 404: raise ChisubmitException( "Organization %s does not exist" % self.github_organization, ge) else: raise ChisubmitException( "Unexpected error accessing organization %s (%i: %s)" % (self.github_organization, ge.status, ge.data["message"]), ge)
def __get_ghteam_by_name(self, team_name): try: teams = self.organization.get_teams() for t in teams: if t.name == team_name: return t return None except GithubException as ge: raise ChisubmitException( "Unexpected error with team %s (%i: %s)" % (team_name, ge.status, ge.data["message"]), ge)
def __add_users_to_course_group(self, course, usernames, access_level): group_name = self.__get_group_name(course) group = self.__get_group(course) if group is None: raise ChisubmitException( "Couldn't add users '%s' to group '%s'. Course group does not exist" % (usernames, group_name)) users = [] for username in usernames: user = self.__get_user_by_username(username) if user is None: raise ChisubmitException( "Couldn't add user '%s' to group '%s'. User does not exist" % (username, group_name)) users.append(user) for user in users: self.gitlab.addgroupmember(group["id"], user["id"], access_level)
def __get_repository(self, repository_name): try: repository = self.organization.get_repo(repository_name) return repository except GithubException as ge: if ge.status == 404: return None else: raise ChisubmitException( "Unexpected error with repository %s (%i: %s)" % (repository_name, ge.status, ge.data["message"]), ge)
def get_config_file_values(config_file): if not os.path.exists(config_file): return {} with open(config_file, 'r') as f: config_file_values = yaml.safe_load(f) if type(config_file_values) != dict: raise ChisubmitException("{} is not valid YAML".format(f)) return config_file_values
def __create_ghteam(self, team_name, repos, permissions, fail_if_exists=True): github_team = self.__get_ghteam_by_name(team_name) if github_team is not None: if fail_if_exists: raise ChisubmitException("Team %s already exists." % team_name) else: return github_team else: try: github_team = self.organization.create_team( team_name, repos, permissions) return github_team except GithubException as ge: raise ChisubmitException( "Unexpected exception creating team %s (%i: %s)" % (team_name, ge.status, ge.data["message"]), ge)
def __get_tag(self, project_name, tag_name): tags = self.gitlab.getrepositorytags(project_name) if tags == False: raise ChisubmitException("Couldn't get tags for project %s" % project_name) for t in tags: if t["id"] == tag_name: return t return None
def update_team_repository(self, course, team): repo_name = self.__get_team_namespaced_project_name(course, team) team_members = team.get_team_members() gitlab_project = self.__get_team_project(course, team) for tm in team_members: gitlab_student = self.__get_user_by_username( self._get_user_git_username(course, tm.student)) if gitlab_student is None: raise ChisubmitException( "GitLab user '%s' does not exist " % (self._get_user_git_username(course, tm.student))) rc = self.gitlab.addprojectmember(gitlab_project["id"], gitlab_student["id"], "developer") if rc == False: raise ChisubmitException( "Unable to add user %s to %s" % (gitlab_student["username"], repo_name))