Skip to content

Instantly share code, notes, and snippets.

@gene1wood
Created February 6, 2018 22:53
Show Gist options
  • Star 3 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save gene1wood/c3214412cc9873a1a555bebb9b1c61c2 to your computer and use it in GitHub Desktop.
Save gene1wood/c3214412cc9873a1a555bebb9b1c61c2 to your computer and use it in GitHub Desktop.
For a given user, identify all repos in a given org for which that user has admin rights, then report the shortest list of team names of teams which are also administrative for those repos.
#!/usr/bin/env python
# This uses pagination functionality not yet present in master of agithub
import agithub.GitHub
import json
from pprint import pprint
def persist_to_file(file_name):
def decorator(original_func):
try:
cache = json.load(open(file_name, 'r'))
except (IOError, ValueError):
cache = {}
def new_func(param):
if param not in cache:
cache[param] = original_func(param)
json.dump(cache, open(file_name, 'w'))
return cache[param]
return new_func
return decorator
ag = agithub.GitHub.GitHub(
token='TOKEN GOES HERE',
paginate=True)
user = 'octocat'
org = 'mozilla'
@persist_to_file('repos.json')
def get_org_repos(org):
status, repos = ag.orgs[org].repos.get(per_page=100)
return repos
@persist_to_file('collaborators.json')
def get_collaborators(org):
# ~ 2000 calls
repos = get_org_repos(org)
collaborator_map = {}
for repo_name in [x['name'] for x in repos]:
print('Fetching collaborators for %s' % repo_name)
status, collaborators = ag.repos[org][repo_name].collaborators.get(
per_page=100)
collaborator_map[repo_name] = collaborators
return collaborator_map
@persist_to_file('org_owners.json')
def get_org_owners(org):
# ~ 20 calls
status, org_owners = ag.orgs[org].members.get(
role='admin',
per_page=100)
return org_owners
@persist_to_file('repo_teams.json')
def get_repo_teams(repo):
# ~ 5 calls
# no nested teams
status, teams = ag.repos[org][repo].teams.get(per_page=100)
return teams
def main():
"""For a given user, identify all repos in a given org for which that user
has admin rights, then report the shortest list of team names of teams
which are also administrative for those repos.
With this list of organization teams, one can contact the teams with
GitHub team discussions to ask them to confirm that the user in question
should indeed have admin rights on the list of repos that that team
administers
:return:
"""
status, ratelimit = ag.rate_limit.get()
print("Ratelimit is : %s" % ratelimit['rate'])
# List org repos
# https://developer.github.com/v3/repos/#list-organization-repositories
repos = get_org_repos(org)
print("%s repos found" % len(repos))
# For each repo list collaborators
# https://developer.github.com/v3/repos/collaborators/#list-collaborators
collaborators = get_collaborators(org)
print("collaborators on %s repos found" % len(collaborators))
# Determine org owners
org_owners = get_org_owners(org)
print("%s org owners found" % len(org_owners))
teams_to_contact = {}
for repo in collaborators:
repo_admins = [x['login'] for x in collaborators[repo]
if x['login'] not in [y['login'] for y in org_owners]
and x['permissions']['admin']]
if user in repo_admins:
teams = get_repo_teams(repo)
admin_teams = [x['slug'] for x in teams
if x['permission'] == 'admin']
if len(admin_teams) > 0:
for team in admin_teams:
if team not in teams_to_contact:
teams_to_contact[team] = []
teams_to_contact[team].append(repo)
else:
raise Exception('Repo %s has no teams which have admin rights '
'on it' % repo)
teams_to_contact_order = sorted(
teams_to_contact.keys(),
key=lambda x: len(teams_to_contact[x]),
reverse=True)
for team in teams_to_contact_order:
for repo in teams_to_contact[team]:
for other_team in [x for x in teams_to_contact if x != team]:
if repo in teams_to_contact[other_team]:
teams_to_contact[other_team].remove(repo)
if len(teams_to_contact[team]) == 0:
del teams_to_contact[team]
else:
pprint({team: teams_to_contact[team]})
if __name__ == "__main__":
main()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment