Compare commits
3 Commits
v1.1.0
...
fix/ci-yam
| Author | SHA1 | Date | |
|---|---|---|---|
| 2d1facfb41 | |||
| 7196cce237 | |||
| 47106ff281 |
48
.github/workflows/pr-iphone-deploy.yml
vendored
48
.github/workflows/pr-iphone-deploy.yml
vendored
@@ -215,6 +215,15 @@ jobs:
|
||||
timeout-minutes: 120
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
# Shallow clone — wait-approval only needs scripts/pr_lgtm_scanner.py,
|
||||
# nothing else from the repo. Same raw-git pattern as build-deploy's
|
||||
# Checkout step (avoids actions/checkout setup).
|
||||
run: |
|
||||
git clone --depth 1 -b ${{ github.head_ref }} https://x-access-token:${PR_TOKEN}@gitea.1000co.fr/${{ github.repository }}.git .
|
||||
env:
|
||||
PR_TOKEN: ${{ secrets.PR_API_TOKEN }}
|
||||
|
||||
- name: Poll for LGTM
|
||||
env:
|
||||
GT_TOKEN: ${{ secrets.PR_API_TOKEN }}
|
||||
@@ -233,8 +242,8 @@ jobs:
|
||||
# edits — e.g. a reviewer changing "KO" → "LGTM". Negligible cost for
|
||||
# PRs with <50 comments.
|
||||
#
|
||||
# Parsing is done with python3 (preinstalled on the macOS runner and
|
||||
# already used by scripts/ci-status.py) rather than grep over raw JSON:
|
||||
# The LGTM/KO decision is computed by scripts/pr_lgtm_scanner.py
|
||||
# (a standalone Python file) rather than grep over raw JSON:
|
||||
# - the bot's "Ready to test" comment body literally contains the
|
||||
# words LGTM/KO as instructions to the reviewer, so any naive
|
||||
# body grep would self-match and auto-merge ~30s after deploy.
|
||||
@@ -253,34 +262,13 @@ jobs:
|
||||
COMMENTS=$(curl -s -H "Authorization: token ${GT_TOKEN}" \
|
||||
"${API}/issues/${PR}/comments?limit=50&page=1")
|
||||
|
||||
DECISION=$(python3 - "$COMMENTS" <<'PY'
|
||||
import json, re, sys
|
||||
MARKER = "<!-- tabatago:ready-to-test -->"
|
||||
try:
|
||||
comments = json.loads(sys.argv[1] or "[]")
|
||||
except Exception:
|
||||
comments = []
|
||||
lgtm = re.compile(r"\bLGTM\b", re.IGNORECASE)
|
||||
ko = re.compile(r"\bKO\b", re.IGNORECASE)
|
||||
hit_lgtm = hit_ko = False
|
||||
for c in comments:
|
||||
body = c.get("body") or ""
|
||||
if MARKER in body:
|
||||
# Skip the bot's own "Ready to test" comment — its body mentions
|
||||
# LGTM/KO as instructions and would otherwise self-trigger.
|
||||
continue
|
||||
if ko.search(body):
|
||||
hit_ko = True
|
||||
if lgtm.search(body):
|
||||
hit_lgtm = True
|
||||
if hit_ko:
|
||||
print("KO")
|
||||
elif hit_lgtm:
|
||||
print("LGTM")
|
||||
else:
|
||||
print("PENDING")
|
||||
PY
|
||||
)
|
||||
# The LGTM/KO scanner lives in scripts/pr_lgtm_scanner.py rather
|
||||
# than inline here. Embedding multi-line Python in a YAML `run: |`
|
||||
# block scalar is fragile — YAML dedents block-scalar content to
|
||||
# the first line, which produced both YAML parse failures and
|
||||
# Python IndentationErrors in earlier iterations of this workflow.
|
||||
# A standalone script sidesteps all of that and is testable locally.
|
||||
DECISION=$(python3 scripts/pr_lgtm_scanner.py "$COMMENTS")
|
||||
|
||||
case "$DECISION" in
|
||||
LGTM)
|
||||
|
||||
70
scripts/pr_lgtm_scanner.py
Normal file
70
scripts/pr_lgtm_scanner.py
Normal file
@@ -0,0 +1,70 @@
|
||||
#!/usr/bin/env python3
|
||||
"""LGTM/KO scanner for the pr-iphone-deploy workflow's wait-approval job.
|
||||
|
||||
Reads a Gitea PR comments JSON array (as returned by
|
||||
``/api/v1/repos/{owner}/{repo}/issues/{pr}/comments``) on argv[1] and prints
|
||||
exactly one of: ``LGTM``, ``KO``, ``PENDING``.
|
||||
|
||||
Rules
|
||||
-----
|
||||
* The bot's own "Ready to test" comment body literally contains the words
|
||||
``LGTM`` and ``KO`` as instructions to the reviewer — without filtering it
|
||||
out, the workflow would self-merge ~30s after deploy. Bot comments are
|
||||
tagged with the sentinel ``<!-- tabatago:ready-to-test -->`` and skipped.
|
||||
* ``KO`` is checked BEFORE ``LGTM`` — a PR with both signals blocks (matches
|
||||
the existing "KO blocks" intent).
|
||||
* Word-boundary regex (``\\bLGTM\\b`` / ``\\bKO\\b``, case-insensitive) so
|
||||
"Tested, LGTM!" counts and "KOM" / "LGTMX" do not.
|
||||
|
||||
This script lives in ``scripts/`` (not inline in the workflow) because
|
||||
embedding multi-line Python inside a YAML ``run: |`` block scalar is fragile:
|
||||
YAML dedents block-scalar content to the first line, which produces either a
|
||||
YAML parse failure or a Python ``IndentationError`` depending on how the
|
||||
body is indented. A standalone file sidesteps all of that.
|
||||
"""
|
||||
import json
|
||||
import re
|
||||
import sys
|
||||
|
||||
MARKER = "<!-- tabatago:ready-to-test -->"
|
||||
LGTM_RE = re.compile(r"\bLGTM\b", re.IGNORECASE)
|
||||
KO_RE = re.compile(r"\bKO\b", re.IGNORECASE)
|
||||
|
||||
|
||||
def decide(comments_json: str) -> str:
|
||||
"""Return 'KO', 'LGTM', or 'PENDING' for the given comments JSON payload."""
|
||||
try:
|
||||
comments = json.loads(comments_json or "[]")
|
||||
except Exception:
|
||||
comments = []
|
||||
|
||||
hit_lgtm = False
|
||||
hit_ko = False
|
||||
for comment in comments:
|
||||
body = comment.get("body") or ""
|
||||
if MARKER in body:
|
||||
# Skip the bot's own "Ready to test" comment — its body mentions
|
||||
# LGTM/KO as instructions and would otherwise self-trigger.
|
||||
continue
|
||||
if KO_RE.search(body):
|
||||
hit_ko = True
|
||||
if LGTM_RE.search(body):
|
||||
hit_lgtm = True
|
||||
|
||||
if hit_ko:
|
||||
return "KO"
|
||||
if hit_lgtm:
|
||||
return "LGTM"
|
||||
return "PENDING"
|
||||
|
||||
|
||||
def main() -> int:
|
||||
if len(sys.argv) != 2:
|
||||
print("usage: pr_lgtm_scanner.py <comments_json>", file=sys.stderr)
|
||||
return 2
|
||||
print(decide(sys.argv[1]))
|
||||
return 0
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
sys.exit(main())
|
||||
Reference in New Issue
Block a user