107 lines
2.9 KiB
Bash
107 lines
2.9 KiB
Bash
|
|
#!/usr/bin/env bash
|
||
|
|
# review-poll.sh — Poll open PRs and review those with green CI
|
||
|
|
#
|
||
|
|
# Usage: ./scripts/review-poll.sh
|
||
|
|
#
|
||
|
|
# Runs from system cron. Checks all open PRs targeting master.
|
||
|
|
# Reviews unreviewed ones sequentially via review-pr.sh.
|
||
|
|
#
|
||
|
|
# Peek while running: cat /tmp/harb-review-status
|
||
|
|
# Full log: tail -f /home/debian/harb/logs/review.log
|
||
|
|
|
||
|
|
set -euo pipefail
|
||
|
|
|
||
|
|
# --- Environment (cron-safe) ---
|
||
|
|
export PATH="/home/debian/.nvm/versions/node/v22.20.0/bin:/usr/local/bin:/usr/bin:/bin:$PATH"
|
||
|
|
export HOME="${HOME:-/home/debian}"
|
||
|
|
|
||
|
|
# --- Config ---
|
||
|
|
REPO="johba/harb"
|
||
|
|
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
|
||
|
|
CODEBERG_TOKEN="$(awk '/codeberg.org/{getline;getline;print $2}' ~/.netrc)"
|
||
|
|
API_BASE="https://codeberg.org/api/v1/repos/${REPO}"
|
||
|
|
LOGDIR="/home/debian/harb/logs"
|
||
|
|
LOGFILE="$LOGDIR/review.log"
|
||
|
|
STATUSFILE="/tmp/harb-review-status"
|
||
|
|
MAX_REVIEWS=3
|
||
|
|
|
||
|
|
mkdir -p "$LOGDIR"
|
||
|
|
|
||
|
|
log() {
|
||
|
|
local ts
|
||
|
|
ts="$(date -u '+%Y-%m-%d %H:%M:%S UTC')"
|
||
|
|
echo "[$ts] $*" >> "$LOGFILE"
|
||
|
|
echo "[$ts] $*"
|
||
|
|
}
|
||
|
|
|
||
|
|
# --- Log rotation (keep last 50KB, archive once) ---
|
||
|
|
if [ -f "$LOGFILE" ] && [ "$(stat -c%s "$LOGFILE" 2>/dev/null || echo 0)" -gt 51200 ]; then
|
||
|
|
mv "$LOGFILE" "$LOGFILE.1"
|
||
|
|
# Only keep one rotated file
|
||
|
|
rm -f "$LOGFILE.2"
|
||
|
|
log "Log rotated"
|
||
|
|
fi
|
||
|
|
|
||
|
|
log "--- Poll start ---"
|
||
|
|
|
||
|
|
# --- Fetch open PRs targeting master ---
|
||
|
|
PRS=$(curl -sf -H "Authorization: token ${CODEBERG_TOKEN}" \
|
||
|
|
"${API_BASE}/pulls?state=open&limit=20" | \
|
||
|
|
jq -r '.[] | select(.base.ref == "master") | "\(.number) \(.head.sha)"')
|
||
|
|
|
||
|
|
if [ -z "$PRS" ]; then
|
||
|
|
log "No open PRs targeting master"
|
||
|
|
exit 0
|
||
|
|
fi
|
||
|
|
|
||
|
|
TOTAL=$(echo "$PRS" | wc -l)
|
||
|
|
log "Found ${TOTAL} open PRs"
|
||
|
|
|
||
|
|
REVIEWED=0
|
||
|
|
SKIPPED=0
|
||
|
|
|
||
|
|
while IFS= read -r line; do
|
||
|
|
PR_NUM=$(echo "$line" | awk '{print $1}')
|
||
|
|
PR_SHA=$(echo "$line" | awk '{print $2}')
|
||
|
|
|
||
|
|
# Quick pre-check: CI status (avoid calling review-pr.sh just to skip)
|
||
|
|
CI_STATE=$(curl -sf -H "Authorization: token ${CODEBERG_TOKEN}" \
|
||
|
|
"${API_BASE}/commits/${PR_SHA}/status" | jq -r '.state // "unknown"')
|
||
|
|
|
||
|
|
if [ "$CI_STATE" != "success" ]; then
|
||
|
|
log " #${PR_NUM} CI=${CI_STATE}, skip"
|
||
|
|
SKIPPED=$((SKIPPED + 1))
|
||
|
|
continue
|
||
|
|
fi
|
||
|
|
|
||
|
|
# Check for existing review at this SHA
|
||
|
|
HAS_REVIEW=$(curl -sf -H "Authorization: token ${CODEBERG_TOKEN}" \
|
||
|
|
"${API_BASE}/issues/${PR_NUM}/comments?limit=50" | \
|
||
|
|
jq -r --arg sha "$PR_SHA" \
|
||
|
|
'[.[] | select(.body | contains("<!-- reviewed:")) | select(.body | contains($sha))] | length')
|
||
|
|
|
||
|
|
if [ "$HAS_REVIEW" -gt "0" ]; then
|
||
|
|
log " #${PR_NUM} already reviewed at ${PR_SHA:0:7}, skip"
|
||
|
|
SKIPPED=$((SKIPPED + 1))
|
||
|
|
continue
|
||
|
|
fi
|
||
|
|
|
||
|
|
log " #${PR_NUM} needs review (CI=success, SHA=${PR_SHA:0:7})"
|
||
|
|
|
||
|
|
if "${SCRIPT_DIR}/review-pr.sh" "$PR_NUM" 2>&1; then
|
||
|
|
REVIEWED=$((REVIEWED + 1))
|
||
|
|
else
|
||
|
|
log " #${PR_NUM} review failed"
|
||
|
|
fi
|
||
|
|
|
||
|
|
if [ "$REVIEWED" -ge "$MAX_REVIEWS" ]; then
|
||
|
|
log "Hit max reviews (${MAX_REVIEWS}), stopping"
|
||
|
|
break
|
||
|
|
fi
|
||
|
|
|
||
|
|
sleep 2
|
||
|
|
|
||
|
|
done <<< "$PRS"
|
||
|
|
|
||
|
|
log "--- Poll done: ${REVIEWED} reviewed, ${SKIPPED} skipped ---"
|