Page MenuHomePhabricator
Paste P43204

Code used to generate list for T200324
ActivePublic

Authored by Pppery on Jan 22 2023, 12:51 AM.
Tags
None
Referenced Files
F36395085: Code used to generate list for T200324
Jan 22 2023, 12:51 AM
Subscribers
None
import json
import urllib.error
import urllib.request
from base64 import b64encode
token = b"<GERRIT USERNAME>:<GERRIT HTTPS PASSWORD>"
def read_json_url(url,skip_lines=0):
with urllib.request.urlopen(url) as f:
for _ in range(skip_lines):
f.readline()
return json.load(f)
def authenticated_request(url):
req = urllib.request.Request("https://gerrit.wikimedia.org/r/a"+url)
req.add_header("Authorization",b"Basic "+b64encode(token))
return read_json_url(req,1)
def get_projects():
for name, data in authenticated_request("/projects/?r=mediawiki/extensions/.*").items():
state = data["state"]
if state == "ACTIVE":
yield name, data["id"]
def get_group_members(group):
data = authenticated_request(f"/groups/{group}/detail/")
members = set()
for member in data["members"]:
members.add(member["_account_id"])
for included in data["includes"]:
if included["id"] != group:
# Suppress infinite recursion if a group is a member of itself
# happens with WMF Campaigns team
members.update(get_group_members(included["id"]))
return members
def get_project_access(project):
access = authenticated_request(f"/projects/{project}/access/")
inherits_from = access["inherits_from"]["id"]
allowed = set()
if inherits_from != "mediawiki%2Fextensions":
allowed.update(get_project_access(inherits_from))
try:
groups = access["local"]["refs/*"]["permissions"]["owner"]["rules"]
except KeyError:
# Suppress KeyError if a project has no groups at all
# (This happens with DynamicSidebar)
#print(f"*** {project} has no owners")
return set()
for groupid, perms in groups.items():
if perms != {"action":"ALLOW","force":False}:
#print("f**** {project} has nonstandard permissions")
continue
try:
allowed.update(get_group_members(groupid))
except urllib.error.HTTPError as error:
# Suppress 404 error in case a group is misconfigured
# (This happens with AddPersonalURLs, DynamicPageListEngine, some others)
if error.code != 404:
raise
error.close()
#print(f"*** {project} has misconfigured groups")
return allowed
def check_dates(date="2022-01-21",start=""):
for repo, id_ in get_projects():
if repo < start:
continue
members = get_project_access(id_)
changes = authenticated_request(f"/changes/?q=status:merged+"
f"after:{date}+project:{repo}"
f"&o=DETAILED_ACCOUNTS")
for change in changes:
if change["owner"]["_account_id"] in (137, 5266):
# Ignore l10n-bot/Libraryupgrader
continue
elif change["submit_records"] == []:
# Open-pushed change indicates maintenance
#print(f"{repo}: Patch {change['_number']} pushed without approval")
break
else:
for label in change["submit_records"][0]["labels"]:
if label["label"] == "Code-Review":
if label["applied_by"]["_account_id"] in members:
#print(f"{repo}: Patch {change['_number']} was approved"
# "by a member of the repository")
break
else:
continue
break
else:
print(repo)
check_dates()