forked from carbon-language/carbon-lang
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathupdate_label_access.py
145 lines (118 loc) · 4.05 KB
/
update_label_access.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
"""Updates the contributors-with-label-access team.
This team exists because we need a team to manage triage access to repos;
GitHub doesn't allow the org to be set to triage access, only read/write. It
will be updated to include all members of the carbon-language organization.
"""
__copyright__ = """
Part of the Carbon Language project, under the Apache License v2.0 with LLVM
Exceptions. See /LICENSE for license information.
SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
"""
import argparse
from typing import List, Optional, Set
# https://github.com/PyGithub/PyGithub
# GraphQL is preferred, but falling back to pygithub for unsupported mutations.
import github
from github_tools import github_helpers
# The organization to mirror members from.
_ORG = "carbon-language"
# The team to mirror to.
_TEAM = "contributors"
# Accounts in the org to skip mirroring.
_IGNORE_ACCOUNTS = ("CarbonLangInfra", "google-admin", "googlebot")
# Queries organization members.
_ORG_MEMBER_QUERY = """
query {
organization(login: "%s") {
membersWithRole(first: 100%%(cursor)s) {
nodes {
login
}
%%(pagination)s
}
}
}
"""
# The path for nodes in _ORG_MEMBER_QUERY.
_ORG_MEMBER_PATH = ("organization", "membersWithRole")
# Queries team members.
_TEAM_MEMBER_QUERY = """
query {
organization(login: "%s") {
team(slug: "%s") {
members(first: 100%%(cursor)s) {
nodes {
login
}
%%(pagination)s
}
}
}
}
"""
# The path for nodes in _TEAM_MEMBER_QUERY.
_TEAM_MEMBER_PATH = ("organization", "team", "members")
def _parse_args(args: Optional[List[str]] = None) -> argparse.Namespace:
"""Parses command-line arguments and flags."""
parser = argparse.ArgumentParser(description=__doc__)
github_helpers.add_access_token_arg(parser, "admin:org, repo")
return parser.parse_args(args=args)
def _load_org_members(client: github_helpers.Client) -> Set[str]:
"""Loads org members."""
print("Loading %s..." % _ORG)
org_members = set()
ignored = set()
for node in client.execute_and_paginate(
_ORG_MEMBER_QUERY % _ORG, _ORG_MEMBER_PATH
):
login = node["login"]
if login not in _IGNORE_ACCOUNTS:
org_members.add(login)
else:
ignored.add(login)
print(
"%s has %d non-ignored members, and %d ignored."
% (_ORG, len(org_members), len(ignored))
)
unignored = set(_IGNORE_ACCOUNTS) - ignored
assert not unignored, "Missing ignored accounts: %s" % unignored
return org_members
def _load_team_members(client: github_helpers.Client) -> Set[str]:
"""Load team members."""
print("Loading %s..." % _TEAM)
team_members = set()
for node in client.execute_and_paginate(
_TEAM_MEMBER_QUERY % (_ORG, _TEAM), _TEAM_MEMBER_PATH
):
team_members.add(node["login"])
print("%s has %d members." % (_ORG, len(team_members)))
return team_members
def _update_team(
gh: github.Github, org_members: Set[str], team_members: Set[str]
) -> None:
"""Updates the team if needed.
This switches to pygithub because GraphQL lacks equivalent mutation support.
"""
gh_team = gh.get_organization(_ORG).get_team_by_slug(_TEAM)
add_members = org_members - team_members
if add_members:
print("Adding members: %s" % ", ".join(add_members))
for member in add_members:
gh_team.add_membership(gh.get_user(member))
remove_members = team_members - org_members
if remove_members:
print("Removing members: %s" % ", ".join(remove_members))
for member in remove_members:
gh_team.remove_membership(gh.get_user(member))
def main() -> None:
parsed_args = _parse_args()
print("Connecting...")
client = github_helpers.Client(parsed_args)
org_members = _load_org_members(client)
team_members = _load_team_members(client)
if org_members != team_members:
gh = github.Github(parsed_args.access_token)
_update_team(gh, org_members, team_members)
print("Done!")
if __name__ == "__main__":
main()