"""Decides whether to create, update, or skip the PR bot comment. Reads: pr-meta/comment.md — new comment from format-comment.py pr-meta/findings-count.txt — number of findings (from format-comment.py) pr-meta/existing-comment.md — current bot comment on the PR (from workflow) Writes: pr-meta/action.txt — "create", "update", or "skip" pr-meta/final-comment.md — the body to post or update with """ import os import re WORK_DIR = "pr-meta" def read_file(path): """Read a file and return its stripped content, or None if missing/empty.""" try: with open(path) as f: content = f.read().strip() return content if content else None except Exception: return None def read_findings_count(new_body): """Return the findings count from findings-count.txt, or by counting bullets.""" raw = read_file(os.path.join(WORK_DIR, "findings-count.txt")) if raw is not None: try: return int(raw) except ValueError: pass # Fallback: count bullet lines before
(diff summary has its own bullets) body_before_details = new_body.split("
")[0] return len(re.findall(r"^- .+$", body_before_details, re.MULTILINE)) def _was_already_passing(existing_body): """Check if the most recent state in the comment is already all-clear.""" # If there's a previous "all passing" edit, the last state was passing if re.search(r"^(?:\*\*)?Edit(?: \d+)?(?:\*\*)?: (?:- )?All checks are (now passing|passing now)", existing_body, re.MULTILINE): return True # If there are no edits at all, check the original comment body if not re.search(r"^(?:\*\*)?Edit(?: \d+)?(?:\*\*)?:", existing_body, re.MULTILINE): return "All our automated checks have passed" in existing_body return False def _previous_failing_count(existing_body): """Extract the findings count from the most recent state in the comment.""" # Check edit lines first (most recent state) matches = re.findall(r"^(?:\*\*)?Edit(?: \d+)?(?:\*\*)?: (?:- )?(\d+) checks? (?:is|are) still failing", existing_body, re.MULTILINE) if matches: return int(matches[-1]) # No edits — count bullets in the original comment (before
) if not re.search(r"^(?:\*\*)?Edit(?: \d+)?(?:\*\*)?:", existing_body, re.MULTILINE): body_before_details = existing_body.split("
")[0] bullets = re.findall(r"^- .+$", body_before_details, re.MULTILINE) return len(bullets) if bullets else None return None def _extract_pr_author(existing_body): """Extract the PR author username from the 'Hello @user' greeting.""" match = re.search(r"Hello @([\w-]+)", existing_body) return match.group(1) if match else None def build_edit_line(existing_body, findings_count, check_run_id, repo): """Build the edit line to append, or None if nothing to do.""" run_tag = f"" # Idempotency: this run was already processed if run_tag in existing_body: return None # Skip if the state hasn't changed if findings_count == 0 and _was_already_passing(existing_body): return None if findings_count > 0 and _previous_failing_count(existing_body) == findings_count: return None # Count previous edits to determine the next number edits = re.findall(r"^(?:\*\*)?Edit(?: \d+)?(?:\*\*)?:", existing_body, re.MULTILINE) edit_count = len(edits) next_edit = edit_count + 1 run_url = f"https://github.com/{repo}/actions/runs/{check_run_id}" # Build resolved-issue prefix prev_count = _previous_failing_count(existing_body) resolved_prefix = "" if prev_count is not None and prev_count > findings_count: resolved = prev_count - findings_count noun = "issue was" if resolved == 1 else "issues were" resolved_prefix = f"{resolved} {noun} resolved, but " if findings_count == 0: edit_label = "**Edit:**" if edit_count == 0 else f"**Edit {next_edit}:**" line = f"{edit_label} - All checks are now passing \U0001f389, see [here]({run_url}) for details {run_tag}" # Add thank-you when transitioning from failures to passing if prev_count is not None and prev_count > 0: author = _extract_pr_author(existing_body) if author: line += ( f"\n\nThank you @{author} for fixing those issues! \U0001f607\n" f"This PR is now ready for human review, looping in @Lissy93 \U0001fae1" ) return line verb = "check is" if findings_count == 1 else "checks are" edit_label = f"**Edit {next_edit}:**" return ( f"{edit_label} - {resolved_prefix}{findings_count} {verb} still failing, " f"see [here]({run_url}) for details {run_tag}" ) def write_output(action, body=""): """Write action.txt and (optionally) final-comment.md.""" os.makedirs(WORK_DIR, exist_ok=True) with open(os.path.join(WORK_DIR, "action.txt"), "w") as f: f.write(action) if body: with open(os.path.join(WORK_DIR, "final-comment.md"), "w") as f: f.write(body) def main(): check_run_id = os.environ.get("CHECK_RUN_ID", "") repo = os.environ.get("GITHUB_REPOSITORY", "") new_body = read_file(os.path.join(WORK_DIR, "comment.md")) if not new_body: write_output("skip") return existing_body = read_file(os.path.join(WORK_DIR, "existing-comment.md")) # No existing comment — create a new one if not existing_body: write_output("create", new_body) return # Existing comment — build an edit line to append if not check_run_id: write_output("skip") return findings_count = read_findings_count(new_body) edit_line = build_edit_line(existing_body, findings_count, check_run_id, repo) if not edit_line: write_output("skip") return if "### Updates" in existing_body: updated = existing_body.rstrip() + "\n" + edit_line else: updated = existing_body.rstrip() + "\n\n---\n\n### Updates\n\n" + edit_line write_output("update", updated) if __name__ == "__main__": main()