Page Menu
Home
Phabricator
Search
Configure Global Search
Log In
Files
F36395085
Code used to generate list for T200324
No One
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Award Token
Flag For Later
Authored By
Pppery
Jan 22 2023, 12:51 AM
2023-01-22 00:51:42 (UTC+0)
Size
3 KB
Referenced Files
None
Subscribers
None
Code used to generate list for T200324
View Options
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()
File Metadata
Details
Attached
Mime Type
text/plain; charset=utf-8
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
10377860
Default Alt Text
Code used to generate list for T200324 (3 KB)
Attached To
Mode
P43204 Code used to generate list for T200324
Attached
Detach File
Event Timeline
Log In to Comment