Compare commits

...

6 commits

4 changed files with 96 additions and 56 deletions

View file

@ -6,7 +6,7 @@ import tomllib
from typing import Optional from typing import Optional
from datetime import datetime, timedelta, timezone from datetime import datetime, timedelta, timezone
from time import sleep from time import sleep
from pprint import pformat from pprint import pprint
import click import click
import requests import requests
@ -149,8 +149,6 @@ def parse_seconds(text: str) -> timedelta:
"--config", "--config",
"config_path", "config_path",
type=Path, type=Path,
default=lambda: Path(os.getenv("BUILD_WORKSPACE_DIRECTORY", ""))
/ "projects/gh-unnotifier/config.toml",
) )
@click.option("--schedule", "schedule", default="30 seconds", type=parse_seconds) @click.option("--schedule", "schedule", default="30 seconds", type=parse_seconds)
def maintain(config_path: Path, schedule: timedelta): def maintain(config_path: Path, schedule: timedelta):
@ -160,72 +158,107 @@ def maintain(config_path: Path, schedule: timedelta):
client = Client(config["gh-unnotifier"]["api_key"]) client = Client(config["gh-unnotifier"]["api_key"])
org_shitlist = config["gh-unnotifier"].get("org_shitlist", []) org_shitlist = config["gh-unnotifier"].get("org_shitlist", [])
team_shitlist = config["gh-unnotifier"].get("team_shitlist", []) team_shitlist = config["gh-unnotifier"].get("team_shitlist", [])
author_shitlist = config["gh-unnotifier"].get("author_shitlist", [])
user = client.get_user() user = client.get_user()
user_teams = {it["slug"] for it in client.get_user_teams()} user_teams = {it["slug"] for it in client.get_user_teams()}
mark = None mark = savepoint = prev = None
def _resolve(notif, reason): def _resolve(notif, reason):
client.read(notif) client.read(notif)
client.unsubscribe(notif) client.unsubscribe(notif)
click.echo(f"Resolved {notif['id']} {reason} ({notif['subject']})") click.echo(f"Resolved {notif['id']} {reason} ({notif['subject']})")
def _pr(subject, notif):
pr = client.get_pr(url=subject["url"])
if pr.get("merged", False):
_resolve(notif, "Merged")
return
if pr.get("state") == "closed":
_resolve(notif, "Closed")
return
if pr["user"]["login"] in author_shitlist:
_resolve(notif, "Ignoring PR by author")
return
if notif["reason"] == "review_requested":
reviewers = client.get_pr_reviewers(pr)
if (
any(org in subject["url"] for org in org_shitlist)
and not any(
it["login"] == user["login"]
for it in reviewers.get("users", [])
)
and not any(
it["slug"] in user_teams
and it["slug"] not in team_shitlist
for it in reviewers.get("teams", [])
)
):
_resolve(notif, "Reviewed")
return
print("Oustanding PR notification")
pprint({"subject": subject, "notif": notif, "pr": pr})
def _mention(subject, notif):
pr = client.get_pr(url=subject["url"])
reviewers = client.get_pr_reviewers(pr)
if (
any(org in subject["url"] for org in org_shitlist)
and not any(
it["login"] == user["login"]
for it in reviewers.get("users", [])
)
and not any(
it["slug"] in user_teams
and it["slug"] not in team_shitlist
for it in reviewers.get("teams", [])
)
):
_resolve(notif, "Ignoring team mention")
return
def _issue(subject, notif):
issue = client.get_issue(url=subject["url"])
if issue["state"] == "closed":
comments = client.get_comments(url=issue["comments_url"])
if not any(
it["user"]["login"] == user["login"] for it in comments
):
_resolve(notif, "Unengaged issue closed")
if issue["user"]["login"] in author_shitlist:
_resolve(notif, "Ignoring issue by author")
while True: while True:
try: try:
savepoint = prev
prev = mark prev = mark
mark = datetime.now(timezone.utc) mark = datetime.now(timezone.utc)
tick = mark + schedule tick = mark + schedule
assert tick - schedule == mark assert tick - schedule == mark
for notif in client.get_all_notifications(since=prev): for notif in client.get_all_notifications(since=prev):
notif_timestamp = datetime.fromisoformat(notif["updated_at"])
if (mark - notif_timestamp).days > 3:
_resolve(notif, "More than 3 days old")
continue
subject = notif["subject"] subject = notif["subject"]
pr = None match subject["type"].lower():
if subject["type"] == "PullRequest": case "pullrequest":
if notif["reason"] == "review_requested": _pr(subject, notif)
pr = client.get_pr(url=subject["url"])
reviewers = client.get_pr_reviewers(pr) case "mention":
if ( _mention(subject, notif)
any(org in subject["url"] for org in org_shitlist)
and not any(
it["login"] == user["login"]
for it in reviewers.get("users", [])
)
and not any(
it["slug"] in user_teams
and it["slug"] not in team_shitlist
for it in reviewers.get("teams", [])
)
):
_resolve(notif, "Reviewed")
continue
elif notif["reason"] == "team_mention": case "issue":
pr = client.get_pr(url=subject["url"]) _issue(subject, notif)
reviewers = client.get_pr_reviewers(pr)
if (
any(org in subject["url"] for org in org_shitlist)
and not any(
it["login"] == user["login"]
for it in reviewers.get("users", [])
)
and not any(
it["slug"] in user_teams
and it["slug"] not in team_shitlist
for it in reviewers.get("teams", [])
)
):
_resolve(notif, "Ignoring team mention")
continue
elif subject["type"] == "Issue":
issue = client.get_issue(url=subject["url"])
if issue["state"] == "closed":
comments = client.get_comments(url=issue["comments_url"])
if not any(
it["user"]["login"] == user["login"] for it in comments
):
_resolve(notif, "Unengaged issue closed")
duration = (tick - datetime.now(timezone.utc)).total_seconds() duration = (tick - datetime.now(timezone.utc)).total_seconds()
if duration > 0: if duration > 0:
@ -234,6 +267,11 @@ def maintain(config_path: Path, schedule: timedelta):
except KeyboardInterrupt: except KeyboardInterrupt:
break break
except requests.exceptions.HTTPError as e:
print("Encoutered exception", e, "backing off")
prev = savepoint
sleep(schedule.total_seconds())
if __name__ == "__main__": if __name__ == "__main__":
cli() cli()

View file

@ -70,7 +70,7 @@ def poll_printers(app: App, db: Db) -> None:
def _set_status(status: str): def _set_status(status: str):
if printer.status != status: if printer.status != status:
log.info(f"Printer {printer.id} {printer.status} -> {status}") log.info(f"Printer {printer.id} {printer.status} -> {status}")
db.update_printer_status(pid=printer.id, status=status) db.update_printer_status(pid=printer.id, status=status)
def _bed_clear(): def _bed_clear():
if not ( if not (
@ -117,7 +117,7 @@ def poll_printers(app: App, db: Db) -> None:
if mapped_job: if mapped_job:
db.start_job(jid=mapped_job.id) db.start_job(jid=mapped_job.id)
elif printer_job.get("state").lower() == "connecting": elif printer_job.get("state", "").lower() == "connecting":
_set_status("connecting") _set_status("connecting")
elif printer_state.get("ready"): elif printer_state.get("ready"):
@ -171,8 +171,8 @@ def assign_jobs(app: App, db: Db) -> None:
db.assign_job(jid=job.id, pid=printer.id) db.assign_job(jid=job.id, pid=printer.id)
log.info(f"Mapped job {job.id} to printer {printer.id}") log.info(f"Mapped job {job.id} to printer {printer.id}")
break break
else: else:
print("Could not map\n", job, "\n", printer) log.info(f"Could not map job {job!r}")
def push_jobs(app: App, db: Db) -> None: def push_jobs(app: App, db: Db) -> None:
@ -307,7 +307,8 @@ def analyze_files(app: App, db: Db):
for file in db.list_unanalyzed_files(): for file in db.list_unanalyzed_files():
p = Path(file.path) p = Path(file.path)
if not p.is_file(): if not p.is_file():
log.error(f"Invalid file {file.id}!") log.error(f"Deleting missing file {file.id}!")
db.delete_file(uid=file.user_id, fid=file.id)
continue continue
record = analyze_gcode_file(p) record = analyze_gcode_file(p)

View file

@ -54,3 +54,4 @@ unify
yamllint yamllint
yaspin yaspin
pytimeparse pytimeparse
git+https://github.com/arrdem/jaraco.text.git@0dd8d0b25a93c3fad896f3a92d11caff61ff273d#egg=jaraco.text

View file

@ -42,7 +42,7 @@ itsdangerous==2.1.2
jaraco.collections==4.3.0 jaraco.collections==4.3.0
jaraco.context==4.3.0 jaraco.context==4.3.0
jaraco.functools==3.8.0 jaraco.functools==3.8.0
jaraco.text==3.11.1 jaraco.text @ git+https://github.com/arrdem/jaraco.text.git@0dd8d0b25a93c3fad896f3a92d11caff61ff273d
jedi==0.18.2 jedi==0.18.2
Jinja2==3.1.2 Jinja2==3.1.2
jsonschema==4.18.4 jsonschema==4.18.4