Last active
December 2, 2020 10:47
-
-
Save heuristicus/5a1eccc8aebee2d2ac2ceed7989783f1 to your computer and use it in GitHub Desktop.
Get details of ori-drs organisation repositories by using the github API
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #!/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) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #!/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