Files
zed/script/update_top_ranking_issues/main.py
Mohamad Khani b72a46db68
Some checks failed
Update All Top Ranking Issues / update_top_ranking_issues (push) Has been cancelled
Triage Project Sync (#84) / Sync triage project (push) Has been cancelled
release_nightly / notify_on_failure (push) Has been cancelled
release_nightly / check_style (push) Has been cancelled
release_nightly / run_tests_windows (push) Has been cancelled
release_nightly / clippy_windows (push) Has been cancelled
release_nightly / bundle_linux_aarch64 (push) Has been cancelled
release_nightly / bundle_linux_x86_64 (push) Has been cancelled
release_nightly / bundle_mac_aarch64 (push) Has been cancelled
release_nightly / bundle_mac_x86_64 (push) Has been cancelled
release_nightly / bundle_windows_aarch64 (push) Has been cancelled
release_nightly / bundle_windows_x86_64 (push) Has been cancelled
release_nightly / build_nix_linux_x86_64 (push) Has been cancelled
release_nightly / build_nix_mac_aarch64 (push) Has been cancelled
release_nightly / update_nightly_tag (push) Has been cancelled
Hotfix Review Monitor / check-hotfix-reviews (push) Has been cancelled
Stale PR Review Reminder / check-stale-prs (push) Has been cancelled
Update Weekly Top Ranking Issues / update_top_ranking_issues (push) Has been cancelled
Bump collab-staging Tag / update-collab-staging-tag (push) Has been cancelled
compliance_check / scheduled_compliance_check (push) Has been cancelled
logiguard fork: GPUI xdg-activation keyboard-focus serial fix
Single-commit orphan branch: full zed-industries/zed @ 8c74db0 source tree
with a 3-file patch applied (no upstream history).

Patch (crates/gpui_linux/src/linux/wayland/):
  - serial.rs: add SerialKind::KeyboardEnter
  - client.rs: store wl_keyboard.enter serial; add latest_serial_of()
  - window.rs: activate() uses keyboard-enter serial (Mutter focus gate)

Mutter honors window activation only when the token carries the keyboard-
focus serial from wl_keyboard.enter; GPUI used a stale mouse-press serial.
See docs/tray-window-focus-wayland.md in logiguard.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-14 02:22:17 +03:30

171 lines
5.3 KiB
Python

import os
import subprocess
from datetime import date, datetime, timedelta
from typing import Any, Optional
import requests
import typer
from pytz import timezone
from typer import Typer
app: Typer = typer.Typer()
AMERICA_NEW_YORK_TIMEZONE = "America/New_York"
DATETIME_FORMAT: str = "%B %d, %Y %I:%M %p"
ISSUES_PER_SECTION: int = 50
ISSUES_TO_FETCH: int = 100
REPO_OWNER = "zed-industries"
REPO_NAME = "zed"
GITHUB_API_BASE_URL = "https://api.github.com"
EXCLUDE_LABEL = "ignore top-ranking issues"
@app.command()
def main(
github_token: Optional[str] = None,
issue_reference_number: Optional[int] = None,
query_day_interval: Optional[int] = None,
) -> None:
script_start_time: datetime = datetime.now()
start_date: date | None = None
if query_day_interval:
tz = timezone(AMERICA_NEW_YORK_TIMEZONE)
today = datetime.now(tz).date()
start_date = today - timedelta(days=query_day_interval)
# GitHub Workflow will pass in the token as an argument,
# but we can place it in our env when running the script locally, for convenience
token = github_token or os.getenv("GITHUB_ACCESS_TOKEN")
if not token:
try:
result = subprocess.run(
["gh", "auth", "token"], capture_output=True, text=True, check=True
)
token = result.stdout.strip()
except (subprocess.CalledProcessError, FileNotFoundError):
raise typer.BadParameter(
"GitHub token is required. Pass --github-token, set GITHUB_ACCESS_TOKEN env var, or log in with `gh auth login`."
)
headers = {
"Authorization": f"token {token}",
"Accept": "application/vnd.github+json",
}
section_to_issues = get_section_to_issues(headers, start_date)
issue_text: str = create_issue_text(section_to_issues)
if issue_reference_number:
update_reference_issue(headers, issue_reference_number, issue_text)
else:
print(issue_text)
run_duration: timedelta = datetime.now() - script_start_time
print(f"Ran for {run_duration}")
def get_section_to_issues(
headers: dict[str, str], start_date: date | None = None
) -> dict[str, list[dict[str, Any]]]:
"""Fetch top-ranked issues for each section from GitHub."""
section_filters = {
"Bugs": "type:Bug",
"Crashes": "type:Crash",
"Features": "type:Feature",
"Tracking issues": "type:Tracking",
"Meta issues": "type:Meta",
"Windows": 'label:"platform:windows"',
}
section_to_issues: dict[str, list[dict[str, Any]]] = {}
for section, search_qualifier in section_filters.items():
query_parts = [
f"repo:{REPO_OWNER}/{REPO_NAME}",
"is:issue",
"is:open",
f'-label:"{EXCLUDE_LABEL}"',
search_qualifier,
]
if start_date:
query_parts.append(f"created:>={start_date.strftime('%Y-%m-%d')}")
query = " ".join(query_parts)
url = f"{GITHUB_API_BASE_URL}/search/issues"
params = {
"q": query,
"sort": "reactions-+1",
"order": "desc",
"per_page": ISSUES_TO_FETCH, # this will work as long as it's ≤ 100
}
# we are only fetching one page on purpose
response = requests.get(url, headers=headers, params=params)
response.raise_for_status()
items = response.json()["items"]
issues: list[dict[str, Any]] = []
for item in items:
reactions = item["reactions"]
score = reactions["+1"] - reactions["-1"]
if score > 0:
issues.append(
{
"url": item["html_url"],
"score": score,
"created_at": item["created_at"],
}
)
if not issues:
continue
issues.sort(key=lambda x: (-x["score"], x["created_at"]))
section_to_issues[section] = issues[:ISSUES_PER_SECTION]
# Sort sections by total score (highest total first)
section_to_issues = dict(
sorted(
section_to_issues.items(),
key=lambda item: sum(issue["score"] for issue in item[1]),
reverse=True,
)
)
return section_to_issues
def update_reference_issue(
headers: dict[str, str], issue_number: int, body: str
) -> None:
url = f"{GITHUB_API_BASE_URL}/repos/{REPO_OWNER}/{REPO_NAME}/issues/{issue_number}"
response = requests.patch(url, headers=headers, json={"body": body})
response.raise_for_status()
def create_issue_text(section_to_issues: dict[str, list[dict[str, Any]]]) -> str:
tz = timezone(AMERICA_NEW_YORK_TIMEZONE)
current_datetime: str = datetime.now(tz).strftime(f"{DATETIME_FORMAT} (%Z)")
lines: list[str] = [f"*Updated on {current_datetime}*"]
for section, issues in section_to_issues.items():
lines.append(f"\n## {section}\n")
for i, issue in enumerate(issues):
lines.append(f"{i + 1}. {issue['url']} ({issue['score']} :thumbsup:)")
lines.append("\n---\n")
lines.append(
"*For details on how this issue is generated, "
"[see the script](https://github.com/zed-industries/zed/blob/main/script/update_top_ranking_issues/main.py)*"
)
return "\n".join(lines)
if __name__ == "__main__":
app()