-
Notifications
You must be signed in to change notification settings - Fork 11
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Change-Id: I4d922e966bd53ff9f92f8d4ed3a196ce9cf90e34 Reviewed-on: https://review.couchbase.org/c/build-tools/+/183134 Tested-by: Blair Watt <[email protected]> Reviewed-by: Ming Ho <[email protected]>
- Loading branch information
Showing
3 changed files
with
191 additions
and
0 deletions.
There are no files selected for viewing
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
# Github group replacer | ||
|
||
The purpose of this helper script is to replace an existing 'from' team with | ||
a given 'to' team for all repositories in a specified GitHub organisation. | ||
|
||
It requires an access token with repo read/write access, present in the | ||
environment as GITHUB_TOKEN, once present, run with | ||
|
||
./app.py --org [org] --from-team-slug=[from] --to-team-slug=[to] [--dry-run] |
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,100 @@ | ||
#!/usr/bin/env python3 | ||
|
||
"""This script is used to switch out one team for another across all the | ||
repositories in a given Github organisation. | ||
Note: Only the source team's permissions are migrated (members are not added | ||
or removed) and the destination team must already exist | ||
""" | ||
|
||
import argparse | ||
import sys | ||
from github import Github | ||
from os import environ | ||
|
||
|
||
class GitHubTeamMover(): | ||
def __init__(self, org, dry_run): | ||
self.connect() | ||
self.get_org(org) | ||
self.dry_run = dry_run | ||
|
||
def connect(self): | ||
try: | ||
self.g = Github(environ["GITHUB_TOKEN"]) | ||
except KeyError: | ||
print("ERROR: Ensure GITHUB_TOKEN is present in environment") | ||
exit(1) | ||
|
||
def get_org(self, org): | ||
self.org = self.g.get_organization(org) | ||
|
||
def get_repos_team_present_in(self, team_slug): | ||
repos = [] | ||
for repo in self.org.get_repos(): | ||
if(team_slug in [t.slug for t in repo.get_teams()]): | ||
repos.append(repo) | ||
return repos | ||
|
||
def remove_from_repo(self, team_slug, repo): | ||
team = self.org.get_team_by_slug(team_slug) | ||
print("Removing", team.slug, "from", repo.name, "...", end=" ") | ||
if not self.dry_run: | ||
team.remove_from_repos(repo) | ||
print("ok!") | ||
else: | ||
print("no action (dry run)") | ||
|
||
def add_to_repo(self, team_slug, repo, role): | ||
team = self.org.get_team_by_slug(team_slug) | ||
print("Adding", team.slug, "to", repo.name, | ||
f"({role} access) ...", end=" ") | ||
if not self.dry_run: | ||
team.add_to_repos(repo) | ||
self.set_repo_role(team, repo, role) | ||
print("ok!") | ||
else: | ||
print("no action (dry run)") | ||
|
||
def get_repo_role(self, team_slug, repo): | ||
team = self.org.get_team_by_slug(team_slug) | ||
permission = team.get_repo_permission(repo) | ||
if permission.admin: | ||
role = "admin" | ||
elif permission.maintain: | ||
role = "maintain" | ||
elif permission.push: | ||
role = "push" # this is called 'write' in UI | ||
elif permission.triage: | ||
role = "triage" | ||
elif permission.pull: | ||
role = "read" | ||
else: | ||
print( | ||
f"Couldn't determine permission for {team_slug} on ", | ||
repo.full_name) | ||
sys.exit(1) | ||
return role | ||
|
||
def set_repo_role(self, team, repo, role): | ||
return team.update_team_repository(repo, role) | ||
|
||
def switch_teams(self, from_team, to_team): | ||
repos_present_in = self.get_repos_team_present_in(from_team) | ||
for repo in repos_present_in: | ||
role = self.get_repo_role(from_team, repo.full_name) | ||
self.add_to_repo(to_team, repo, role) | ||
self.remove_from_repo(from_team, repo) | ||
|
||
|
||
parser = argparse.ArgumentParser(description=__doc__, | ||
formatter_class=argparse.RawTextHelpFormatter) | ||
parser.add_argument('--org', action='store', required=True) | ||
parser.add_argument('--from-team-slug', action='store', required=True) | ||
parser.add_argument('--to-team-slug', action='store', required=True) | ||
parser.add_argument('--dry-run', action='store_true') | ||
args = parser.parse_args() | ||
|
||
|
||
team = GitHubTeamMover(args.org, args.dry_run) | ||
team.switch_teams(args.from_team_slug, args.to_team_slug) |
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,82 @@ | ||
amqp==5.0.6 | ||
appdirs==1.4.4 | ||
astroid==2.11.6 | ||
attrs==21.4.0 | ||
autopep8==1.5.6 | ||
billiard==3.6.4.0 | ||
boltons==21.0.0 | ||
bracex==2.3.post1 | ||
celery==5.1.2 | ||
certifi==2021.10.8 | ||
cffi==1.15.0 | ||
charset-normalizer==2.0.12 | ||
click==8.1.3 | ||
click-didyoumean==0.0.3 | ||
click-option-group==0.5.3 | ||
click-plugins==1.1.1 | ||
click-repl==0.2.0 | ||
colorama==0.4.5 | ||
coverage==5.5 | ||
dd-import==1.0.6 | ||
defusedxml==0.7.1 | ||
Deprecated==1.2.13 | ||
dill==0.3.5.1 | ||
distlib==0.3.1 | ||
face==20.1.1 | ||
filelock==3.0.12 | ||
Flask==2.0.1 | ||
Flask-Cors==3.0.10 | ||
glom==22.1.0 | ||
idna==3.3 | ||
importlib-metadata==4.11.3 | ||
iniconfig==1.1.1 | ||
isort==5.10.1 | ||
itsdangerous==2.0.1 | ||
Jinja2==3.0.1 | ||
jsonschema==4.7.2 | ||
kombu==5.1.0 | ||
lazy-object-proxy==1.7.1 | ||
Mako==1.2.0 | ||
Markdown==3.3.7 | ||
MarkupSafe==2.0.1 | ||
mccabe==0.7.0 | ||
packaging==21.0 | ||
pdoc3==0.10.0 | ||
peewee==3.15.1 | ||
platformdirs==2.5.2 | ||
pluggy==1.0.0 | ||
prompt-toolkit==3.0.19 | ||
py==1.10.0 | ||
pycodestyle==2.7.0 | ||
pycparser==2.21 | ||
PyGithub==1.55 | ||
PyJWT==2.3.0 | ||
pylint==2.14.4 | ||
PyNaCl==1.5.0 | ||
pyparsing==2.4.7 | ||
pyrsistent==0.18.1 | ||
pytest==6.2.5 | ||
pytest-cov==2.12.1 | ||
python-lsp-jsonrpc==1.0.0 | ||
pytz==2021.1 | ||
PyYAML==5.4.1 | ||
redis==3.5.3 | ||
requests==2.27.1 | ||
ruamel.yaml==0.17.21 | ||
ruamel.yaml.clib==0.2.6 | ||
semgrep==0.104.0 | ||
six==1.15.0 | ||
toml==0.10.2 | ||
tomli==2.0.1 | ||
tomlkit==0.11.1 | ||
tqdm==4.64.0 | ||
typing_extensions==4.3.0 | ||
ujson==5.4.0 | ||
urllib3==1.26.8 | ||
vine==5.0.0 | ||
virtualenv==20.4.4 | ||
wcmatch==8.4 | ||
wcwidth==0.2.5 | ||
Werkzeug==2.0.1 | ||
wrapt==1.13.3 | ||
zipp==3.8.0 |