Skip to content

Instantly share code, notes, and snippets.

@heuristicus
Last active December 2, 2020 10:47
Show Gist options
  • Save heuristicus/5a1eccc8aebee2d2ac2ceed7989783f1 to your computer and use it in GitHub Desktop.
Save heuristicus/5a1eccc8aebee2d2ac2ceed7989783f1 to your computer and use it in GitHub Desktop.
Get details of ori-drs organisation repositories by using the github API
#!/usr/bin/env python
# This script hooks into the github API to make it easy and quick to add repositories and people to teams in
# github organisations.
import sys
import getpass
import argparse
import github
def get_api_object():
github_token = getpass.getpass("Enter your GitHub Personal Access Token: ")
return github.Github(github_token)
def slugify(in_str):
"""
Github uses 'slug' names to refer to teams. Basically lowercase names with no special characters except - and
_, with spaces replaced by -. / is also replaced by -. This more or less conforms to what github does
:param in_str: String to slugify
:return: slugified string
"""
in_str = "".join(c for c in in_str if c.isalnum() or c in "-_ /")
return in_str.lower().replace(" ", "-").replace("/", "-")
def get_list_from_file(filename):
"""
Get a list from a file where each line is an item in the list
:param filename:
:return:
"""
vals = []
with open(filename, "r") as f:
for line in f:
vals.append(line.strip())
return vals
def add_user(args):
"""
Add a user or set of users to a team or set of teams.
:param args: Arguments from argparse
:return:
"""
g = get_api_object()
org = g.get_organization(args.org_name)
users = [args.user] or get_list_from_file(args.user_list)
teams = [args.team] or get_list_from_file(args.team_list)
for user in users:
try:
gh_user = g.get_user(user)
except github.UnknownObjectException:
print(f"Invalid user {user}, skipping.")
continue
for team in teams:
try:
gh_team = org.get_team_by_slug(slugify(team))
if not args.dry_run:
gh_team.add_membership(gh_user)
print(f"Added user '{user}' to team '{team}'")
except github.UnknownObjectException:
print(f"Invalid team '{team}', skipping.")
continue
def add_repo(args):
"""
Add a repository or set of repositories to a team or set of teams
:param args: Arguments from argparse
:return:
"""
g = get_api_object()
org = g.get_organization(args.org_name)
repos_to_add = []
if args.repo_list:
listed_repos = get_list_from_file(args.repo_list)
print("Checking repos from user-provided list...")
for repo in listed_repos:
try:
check = org.get_repo(repo)
repos_to_add.append(check)
print(f"Repo '{check.name}' is valid.")
except github.UnknownObjectException:
print(f"Invalid repo '{repo}', skipping.")
if args.all_private:
for repo in org.get_repos(type="private"):
repos_to_add.append(repo)
if args.all_public:
for repo in org.get_repos(type="public"):
repos_to_add.append(repo)
if args.team_list:
teams = get_list_from_file(args.team_list)
else:
teams = [args.team]
for team in teams:
try:
print(f"Adding repos to team '{team}'")
gh_team = org.get_team_by_slug(slugify(team))
except github.UnknownObjectException:
print(f"Invalid team '{team}', skipping.")
continue
for repo in repos_to_add:
if not args.dry_run:
gh_team.add_to_repos(repo)
print(f"Added repo '{repo.name}' to team '{team}'")
if __name__ == "__main__":
parser = argparse.ArgumentParser(__file__)
parser.add_argument(
"--org-name", help="The name of the organisation to modify", required=True
)
run_mutex = parser.add_mutually_exclusive_group(required=True)
run_mutex.add_argument(
"--dry-run",
action="store_true",
help="Don't actually make any of the API calls which do addition, just show what the result would be.",
)
run_mutex.add_argument(
"--apply",
action="store_true",
help="Actually make the API calls to make changes to the organisation",
)
team_mutex = parser.add_mutually_exclusive_group(required=True)
team_mutex.add_argument("--team", help="Apply the requested action to this team")
team_mutex.add_argument(
"--team-list",
help="Apply the requested action to teams in this file, where each line is a team name",
)
subparsers = parser.add_subparsers(
title="Subcommands",
description="Use these subcommands to perform a specific modification to the organisation",
)
user_sub = subparsers.add_parser("add_user", help="Add a user to a team")
user_sub.set_defaults(func=add_user)
user_mutex = user_sub.add_mutually_exclusive_group(required=True)
user_mutex.add_argument("--user", help="Apply the requested action to this user")
user_mutex.add_argument(
"--user-list",
help="Apply the requested action to users in this file, where each line is a username",
)
repo_sub = subparsers.add_parser("add_repo", help="Add repositories to a team")
repo_sub.set_defaults(func=add_repo)
repo_sub.add_argument(
"--all-private",
action="store_true",
help="Add all private repositories of the organisation to this team",
)
repo_sub.add_argument(
"--all-public",
action="store_true",
help="Add all public repositories of the organisation to this team",
)
repo_sub.add_argument(
"--repo-list",
help="Add all repositories in the given file to the team. Each line in the file should be a repo of the "
"organisation. If this arg is given along with --all-public or --all-private or both, the repositories in the "
"given list will be added in addition to those which would be added by the other commands",
metavar="LIST_FILE",
)
repo_sub.add_argument(
"--include-archived",
action="store_true",
help="Also add archived repositories. Default is to exclude them.",
)
args = parser.parse_args(sys.argv[1:])
args.func(args)
#!/usr/bin/env python
import os
import sys
import requests
import getpass
import json
github_token = getpass.getpass("Enter your GitHub token: ")
headers = {"Authorization" : "token {}".format(github_token)}
url = "https://api.github.com/orgs/ori-drs/repos?per_page=100"
resp = requests.get(url, headers=headers)
repos = resp.json()
while 'next' in resp.links.keys():
resp=requests.get(resp.links['next']['url'],headers=headers)
repos.extend(resp.json())
repo_dict = {"private": [], "archived": [], "public": []}
for repo in repos:
name = str(repo["name"])
if repo["archived"]:
repo_dict["archived"].append(name)
if repo["private"]:
repo_dict["private"].append(name)
else:
repo_dict["public"].append(name)
print("Public")
print(sorted(repo_dict["public"]))
print("Private")
print(sorted(repo_dict["private"]))
print("Archived")
print(sorted(repo_dict["archived"]))
print("Non-archived private")
print(set(repo_dict["private"]) - set(repo_dict["archived"]))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment