From 39ec6ec94847d921d5cbfad76255e3ef0798a871 Mon Sep 17 00:00:00 2001 From: David Cramer Date: Wed, 4 Feb 2026 12:04:45 -0800 Subject: [PATCH] fix(iterate-pr): Fix regex pattern error and clarify script paths - Fix re.PatternError when combining patterns with inline (?i) flags by using re.IGNORECASE flag in re.search() instead - Add note that scripts must run from repository root directory - Update all script references to use ${CLAUDE_SKILL_ROOT} for full paths Co-Authored-By: Claude Opus 4.5 --- .../sentry-skills/skills/iterate-pr/SKILL.md | 10 +++-- .../iterate-pr/scripts/fetch_pr_checks.py | 44 +++++++++---------- 2 files changed, 28 insertions(+), 26 deletions(-) diff --git a/plugins/sentry-skills/skills/iterate-pr/SKILL.md b/plugins/sentry-skills/skills/iterate-pr/SKILL.md index 4f30d36..76bfd54 100644 --- a/plugins/sentry-skills/skills/iterate-pr/SKILL.md +++ b/plugins/sentry-skills/skills/iterate-pr/SKILL.md @@ -9,6 +9,8 @@ Continuously iterate on the current branch until all CI checks pass and review f **Requires**: GitHub CLI (`gh`) authenticated. +**Important**: All scripts must be run from the repository root directory (where `.git` is located), not from the skill directory. Use the full path to the script via `${CLAUDE_SKILL_ROOT}`. + ## Bundled Scripts ### `scripts/fetch_pr_checks.py` @@ -16,7 +18,7 @@ Continuously iterate on the current branch until all CI checks pass and review f Fetches CI check status and extracts failure snippets from logs. ```bash -uv run scripts/fetch_pr_checks.py [--pr NUMBER] +uv run ${CLAUDE_SKILL_ROOT}/scripts/fetch_pr_checks.py [--pr NUMBER] ``` Returns JSON: @@ -36,7 +38,7 @@ Returns JSON: Fetches and categorizes PR review feedback using the [LOGAF scale](https://develop.sentry.dev/engineering-practices/code-review/#logaf-scale). ```bash -uv run scripts/fetch_pr_feedback.py [--pr NUMBER] +uv run ${CLAUDE_SKILL_ROOT}/scripts/fetch_pr_feedback.py [--pr NUMBER] ``` Returns JSON with feedback categorized as: @@ -58,7 +60,7 @@ Stop if no PR exists for the current branch. ### 2. Check CI Status -Run `scripts/fetch_pr_checks.py` to get structured failure data. +Run `${CLAUDE_SKILL_ROOT}/scripts/fetch_pr_checks.py` to get structured failure data. **Wait if pending:** If bot-related checks (sentry, codecov, cursor, bugbot, seer) are still running, wait before proceeding—they may post additional feedback. @@ -73,7 +75,7 @@ Do NOT assume what failed based on check name alone—always read the logs. ### 4. Gather Review Feedback -Run `scripts/fetch_pr_feedback.py` to get categorized feedback. +Run `${CLAUDE_SKILL_ROOT}/scripts/fetch_pr_feedback.py` to get categorized feedback. ### 5. Handle Feedback by LOGAF Priority diff --git a/plugins/sentry-skills/skills/iterate-pr/scripts/fetch_pr_checks.py b/plugins/sentry-skills/skills/iterate-pr/scripts/fetch_pr_checks.py index 77955d0..70ff26d 100755 --- a/plugins/sentry-skills/skills/iterate-pr/scripts/fetch_pr_checks.py +++ b/plugins/sentry-skills/skills/iterate-pr/scripts/fetch_pr_checks.py @@ -77,28 +77,28 @@ def extract_failure_snippet(log_text: str, max_lines: int = 50) -> str: """ lines = log_text.split("\n") - # Patterns that indicate failure points + # Patterns that indicate failure points (case-insensitive via re.IGNORECASE) failure_patterns = [ - r"(?i)error[:\s]", - r"(?i)failed[:\s]", - r"(?i)failure[:\s]", - r"(?i)traceback", - r"(?i)exception", - r"(?i)assert(ion)?.*failed", - r"(?i)FAILED", - r"(?i)panic:", - r"(?i)fatal:", - r"(?i)npm ERR!", - r"(?i)yarn error", - r"(?i)ModuleNotFoundError", - r"(?i)ImportError", - r"(?i)SyntaxError", - r"(?i)TypeError", - r"(?i)ValueError", - r"(?i)KeyError", - r"(?i)AttributeError", - r"(?i)NameError", - r"(?i)IndentationError", + r"error[:\s]", + r"failed[:\s]", + r"failure[:\s]", + r"traceback", + r"exception", + r"assert(ion)?.*failed", + r"FAILED", + r"panic:", + r"fatal:", + r"npm ERR!", + r"yarn error", + r"ModuleNotFoundError", + r"ImportError", + r"SyntaxError", + r"TypeError", + r"ValueError", + r"KeyError", + r"AttributeError", + r"NameError", + r"IndentationError", r"===.*FAILURES.*===", r"___.*___", # pytest failure separators ] @@ -108,7 +108,7 @@ def extract_failure_snippet(log_text: str, max_lines: int = 50) -> str: # Find lines matching failure patterns failure_indices = [] for i, line in enumerate(lines): - if re.search(combined_pattern, line): + if re.search(combined_pattern, line, re.IGNORECASE): failure_indices.append(i) if not failure_indices: