Skip to content

Instantly share code, notes, and snippets.

@soofstad
Last active April 21, 2020 14:34
Show Gist options
  • Save soofstad/68e2e0694c25adf60b61fce2e8427207 to your computer and use it in GitHub Desktop.
Save soofstad/68e2e0694c25adf60b61fce2e8427207 to your computer and use it in GitHub Desktop.
Python script getting owners of repos with outside collaborators
import csv
import json
from urllib import request
usage = """
------------------------
Usage
------------------------
Add your Github Access Token with "read_user, user:email, public_repo, repo:invite" scopes like so;
token = "ksdjhkglkfjhløaksjbli378gblaup"
Usage;
$ python3 ./outside_collaborators.py
This will create a .csv file with every owner of a repository which has outside collaborators.
"""
github_admins = ("knut-erik", "ingvald", "pgdr", "solomson", "StigNil", "roar-statoil", "MerMyhr")
token = ""
if not token:
print(f"ERROR: Access token not given.")
print(usage)
print("Exiting...")
exit(1)
def collabs_query(end_cursor):
graphql_query = f"""
query{{organization(login: "equinor"){{
repositories(first: 100{end_cursor}){{
nodes{{
name,
description,
url,
collaborators(affiliation: OUTSIDE){{
nodes{{
login,
company,
name,
email
}}
}}
}},
pageInfo{{
endCursor,
hasNextPage
}}
}}
}}
}}
"""
post_data = json.dumps({"query": graphql_query}).encode()
return post_data
def owners_query(repo):
graphql_query = f"""
{{
organization(login: "equinor") {{
repository(name: "{repo}") {{
name
description
url
collaborators(affiliation: ALL) {{
edges {{
node {{
login
email
}}
permission
}}
totalCount
}}
}}
}}
}}
"""
post_data = json.dumps({"query": graphql_query}).encode()
return post_data
def get_outside_colabs():
print("Getting all outside collaborators in the Equinor organization")
url = 'https://api.github.com/graphql'
headers = {'Accept': 'application/vnd.github.v3+json',
'Authorization': 'Bearer ' + token}
end_cursor = ""
outsiders = {}
while True:
req = request.Request(url=url, headers=headers, data=collabs_query(end_cursor))
response = request.urlopen(req).read().decode()
users_page = json.loads(response)
cursor = users_page['data']['organization']['repositories']['pageInfo']['endCursor']
end_cursor = ", after: \"" + cursor + "\""
repositories = [r for r in users_page["data"]["organization"]["repositories"]["nodes"]]
for repo in repositories:
collaborators = repo.get('collaborators')
users = collaborators.get("nodes") if collaborators else None
if users:
for user in users:
outsiders[user["login"]] = {
"repo": repo["name"],
"email": user["email"],
"login": user["login"],
"name": user["name"],
"company": user["company"]
}
if not users_page['data']['organization']['repositories']['pageInfo']['hasNextPage']:
break
print(f"{len(outsiders)} total outside collaborators in the Equinor Org")
return outsiders
def get_repo_owners(repo_list):
print("Getting all owners of every repository with an outside collaborator")
url = 'https://api.github.com/graphql'
headers = {'Accept': 'application/vnd.github.v3+json',
'Authorization': 'Bearer ' + token}
repo_owners_w_outsiders = []
for repo in repo_list:
req = request.Request(url=url, headers=headers, data=owners_query(repo))
response = request.urlopen(req).read().decode()
users_page = json.loads(response)
collaborators = [c for c in users_page["data"]["organization"]["repository"]["collaborators"]["edges"]]
for user in collaborators:
login = user["node"]["login"]
role = user["permission"]
email = user["node"]["email"]
if login not in github_admins and role is "ADMIN":
repo_owners_w_outsiders.append({"repo": repo, "role": role, "login": login, "email": email})
return repo_owners_w_outsiders
if __name__ == "__main__":
with open("collab_repo_owners.csv", "w") as file:
fieldnames = ['repo', "role", 'email', 'login']
writer = csv.DictWriter(file, fieldnames=fieldnames)
writer.writeheader()
outsiders = get_outside_colabs()
repos_with_outsiders = []
[repos_with_outsiders.append(o["repo"]) for o in outsiders.values() if o["repo"] not in repos_with_outsiders]
repo_owners = get_repo_owners(repos_with_outsiders)
for user in repo_owners:
writer.writerow(user)
@soofstad
Copy link
Author

soofstad commented Apr 3, 2020

Notes

  • Written in Python version 3.8, so you should probably use that as well.
  • No dependencies! No need for pip install, venv etc.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment