]> git.ipfire.org Git - thirdparty/fastapi/fastapi.git/commitdiff
👷 Refactor label-approved, make it an internal script instead of an external GitHub...
authorSebastián Ramírez <tiangolo@gmail.com>
Sat, 12 Oct 2024 13:58:30 +0000 (15:58 +0200)
committerGitHub <noreply@github.com>
Sat, 12 Oct 2024 13:58:30 +0000 (13:58 +0000)
.github/workflows/label-approved.yml
scripts/label_approved.py [new file with mode: 0644]

index e44584cf151f41801c244a103e2420f895963e79..11176bed8230066d233a5b9412eb950e96f3c718 100644 (file)
@@ -20,7 +20,9 @@ jobs:
       env:
         GITHUB_CONTEXT: ${{ toJson(github) }}
       run: echo "$GITHUB_CONTEXT"
-    - uses: docker://tiangolo/label-approved:0.0.4
+    - uses: actions/checkout@v4
+    - name: Set up Python
+      uses: actions/setup-python@v5
       with:
         python-version: "3.11"
     - name: Setup uv
diff --git a/scripts/label_approved.py b/scripts/label_approved.py
new file mode 100644 (file)
index 0000000..2714445
--- /dev/null
@@ -0,0 +1,60 @@
+import logging
+from typing import Literal
+
+from github import Github
+from github.PullRequestReview import PullRequestReview
+from pydantic import BaseModel, SecretStr
+from pydantic_settings import BaseSettings
+
+
+class LabelSettings(BaseModel):
+    await_label: str | None = None
+    number: int
+
+
+default_config = {"approved-2": LabelSettings(await_label="awaiting-review", number=2)}
+
+
+class Settings(BaseSettings):
+    github_repository: str
+    token: SecretStr
+    debug: bool | None = False
+    config: dict[str, LabelSettings] | Literal[""] = default_config
+
+
+settings = Settings()
+if settings.debug:
+    logging.basicConfig(level=logging.DEBUG)
+else:
+    logging.basicConfig(level=logging.INFO)
+logging.debug(f"Using config: {settings.json()}")
+g = Github(settings.token.get_secret_value())
+repo = g.get_repo(settings.github_repository)
+for pr in repo.get_pulls(state="open"):
+    logging.info(f"Checking PR: #{pr.number}")
+    pr_labels = list(pr.get_labels())
+    pr_label_by_name = {label.name: label for label in pr_labels}
+    reviews = list(pr.get_reviews())
+    review_by_user: dict[str, PullRequestReview] = {}
+    for review in reviews:
+        if review.user.login in review_by_user:
+            stored_review = review_by_user[review.user.login]
+            if review.submitted_at >= stored_review.submitted_at:
+                review_by_user[review.user.login] = review
+        else:
+            review_by_user[review.user.login] = review
+    approved_reviews = [
+        review for review in review_by_user.values() if review.state == "APPROVED"
+    ]
+    config = settings.config or default_config
+    for approved_label, conf in config.items():
+        logging.debug(f"Processing config: {conf.json()}")
+        if conf.await_label is None or (conf.await_label in pr_label_by_name):
+            logging.debug(f"Processable PR: {pr.number}")
+            if len(approved_reviews) >= conf.number:
+                logging.info(f"Adding label to PR: {pr.number}")
+                pr.add_to_labels(approved_label)
+                if conf.await_label:
+                    logging.info(f"Removing label from PR: {pr.number}")
+                    pr.remove_from_labels(conf.await_label)
+logging.info("Finished")