Source code for orcoursetrion.lib.github

# -*- coding: utf-8 -*-
"""
Github class for making needed API calls to github
"""
import requests


[docs]class GitHubException(Exception): """Base exception class others inherit.""" pass
[docs]class GitHubRepoExists(GitHubException): """Repo exists, and thus cannot be created.""" pass
[docs]class GitHubUnknownError(GitHubException): """Unexpected status code exception""" pass
[docs]class GitHubNoTeamFound(GitHubException): """Name team not found in list""" pass
[docs]class GitHub(object): """ API class for handling calls to github """ def __init__(self, api_url, oauth2_token): """Initialize a requests session for use with this class by specifying the base API endpoint and key. Args: api_url (str): Github API URL such as https://api.github.com/ oauth2_token (str): Github OAUTH2 token for v3 """ self.api_url = api_url if not api_url.endswith('/'): self.api_url += '/' self.session = requests.Session() # Add OAUTH2 token to session headers and set Agent self.session.headers = { 'Authorization': 'token {0}'.format(oauth2_token), 'User-Agent': 'Orcoursetrion', } def _get_all(self, url): """Return all results from URL given (i.e. page through them) Args: url(str): Full github URL with results. Returns: list: List of items returned. """ results = None response = self.session.get(url) if response.status_code == 200: results = response.json() while response.links.get('next', False): response = self.session.get(response.links['next']['url']) results += response.json() return results
[docs] def create_repo(self, org, repo, description): """Creates a new github repository or raises exceptions Args: org (str): Organization to create the repo in. repo (str): Name of the repo to create. description (str): Description of repo to use. Raises: GitHubRepoExists GitHubUnknownError requests.RequestException Returns: dict: Github dictionary of a repo (https://developer.github.com/v3/repos/#create) """ repo_url = '{url}repos/{org}/{repo}'.format( url=self.api_url, org=org, repo=repo ) # Try and get the URL, if it 404's we are good, otherwise raise repo_response = self.session.get(repo_url) if repo_response.status_code == 200: raise GitHubRepoExists('This repository already exists') if repo_response.status_code != 404: raise GitHubUnknownError(repo_response.text) # Everything looks clean, create the repo. create_url = '{url}orgs/{org}/repos'.format( url=self.api_url, org=org ) payload = { 'name': repo, 'description': description, 'private': True, } repo_create_response = self.session.post(create_url, json=payload) if repo_create_response.status_code != 201: raise GitHubUnknownError(repo_create_response.text) return repo_create_response.json()
[docs] def add_team_repo(self, org, repo, team): """Add a repo to an existing team (by name) in the specified org. We first look up the team to get its ID (https://developer.github.com/v3/orgs/teams/#list-teams), and then add the repo to that team (https://developer.github.com/v3/orgs/teams/#add-team-repo). Args: org (str): Organization to create the repo in. repo (str): Name of the repo to create. team (str): Name of team to add. Raises: GitHubNoTeamFound GitHubUnknownError requests.RequestException """ list_teams_url = '{url}orgs/{org}/teams'.format( url=self.api_url, org=org ) teams = self._get_all(list_teams_url) if not teams: raise GitHubUnknownError( 'No teams found in {0} organization'.format(org) ) found_team = [x for x in teams if x['name'].strip() == team.strip()] if len(found_team) != 1: raise GitHubNoTeamFound( '{0} not in list of teams for {1}'.format(team, org) ) found_team = found_team[0] team_repo_url = '{url}teams/{id}/repos/{org}/{repo}'.format( url=self.api_url, id=found_team['id'], org=org, repo=repo ) response = self.session.put(team_repo_url) if response.status_code != 204: raise GitHubUnknownError(response.text)
[docs] def add_web_hook(self, org, repo, url): """Adds an active hook to a github repository. This utilizes https://developer.github.com/v3/repos/hooks/#create-a-hook to create a form type Web hook that responds to push events (basically all the defaults). Args: org (str): Organization to create the repo in. repo (str): Name of the repo to create. url (str): URL of the hook to add Raises: GitHubUnknownError requests.RequestException Returns: dict: Github dictionary of a hook (https://developer.github.com/v3/repos/hooks/#response-2) """ hook_url = '{url}repos/{org}/{repo}/hooks'.format( url=self.api_url, org=org, repo=repo ) payload = { 'name': 'web', 'active': True, 'config': { 'url': url, } } response = self.session.post(hook_url, json=payload) if response.status_code != 201: raise GitHubUnknownError(response.text) return response.json()