Skip to content

Refresh PR Outdated Checks #10

Refresh PR Outdated Checks

Refresh PR Outdated Checks #10

name: Refresh PR Outdated Checks
# **What it does**: Posts Outdated PR Check commit statuses for every open PR once a day
# (~4am CT), including fork PRs. Catches PRs that go stale when production
# advances without any PR activity.
# **Why we have it**: The per-commit check (outdated-pr-check.yml) only runs when a PR is
# updated. This job handles the case where production moves forward and
# a PR becomes stale without the contributor pushing anything.
# Because this runs once daily, the effective enforcement window is
# 72–96 hours depending on when the PR was last rebased vs. the schedule.
# **Who does it impact**: All contributors with open PRs against production, including forks.
on:
schedule:
- cron: "0 10 * * *" # 4am CST (UTC-6); runs ~5am during CDT (UTC-5)
workflow_dispatch:
jobs:
refresh-outdated:
name: Refresh outdated check for all open PRs
runs-on: ubuntu-latest
permissions:
contents: read
pull-requests: read
# statuses: write is required to post commit statuses to PR head SHAs.
# Fork PR commits are reachable in the base repo via refs/pull/{n}/head,
# so this works for both internal and fork PRs.
statuses: write
steps:
- name: Post outdated status for all open PRs
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
set -euo pipefail
REPO="${{ github.repository }}"
# Get all open PRs targeting production (including forks)
PRS=$(gh pr list \
--repo "$REPO" \
--base production \
--state open \
--limit 500 \
--json number,headRefOid)
echo "$PRS" | jq -c '.[]' | while read -r PR; do
PR_NUMBER=$(echo "$PR" | jq -r '.number')
PR_SHA=$(echo "$PR" | jq -r '.headRefOid')
echo "Checking PR #${PR_NUMBER} (${PR_SHA:0:7})"
COMPARE=$(gh api "/repos/${REPO}/compare/production...${PR_SHA}" 2>/dev/null) || {
echo " Skipping PR #${PR_NUMBER}: compare API failed"
continue
}
BEHIND_BY=$(echo "$COMPARE" | jq -r '.behind_by')
if [ "$BEHIND_BY" = "0" ]; then
STATE="success"
DESCRIPTION="Branch is up to date with production"
else
MERGE_BASE_DATE=$(echo "$COMPARE" | jq -r '.merge_base_commit.commit.committer.date')
if [ -z "$MERGE_BASE_DATE" ] || [ "$MERGE_BASE_DATE" = "null" ]; then
echo " Skipping PR #${PR_NUMBER}: missing merge base date"
continue
fi
MERGE_BASE_TS=$(date -d "$MERGE_BASE_DATE" +%s)
NOW=$(date +%s)
AGE=$((NOW - MERGE_BASE_TS))
if [ "$AGE" -gt 259200 ]; then
DAYS=$((AGE / 86400))
STATE="failure"
DESCRIPTION="Branch is ${DAYS} days out of date with production. Please rebase or merge. Codeowners can comment /rebase on the PR to fix."
else
STATE="success"
DESCRIPTION="Branch is behind production but within the 72-hour grace period"
fi
fi
gh api \
--method POST \
-H "Accept: application/vnd.github+json" \
"/repos/${REPO}/statuses/${PR_SHA}" \
-f state="$STATE" \
-f context="Outdated PR Check" \
-f description="$DESCRIPTION" \
|| { echo " Failed to post status for PR #${PR_NUMBER} — continuing"; true; }
echo " Posted: $STATE — $DESCRIPTION"
done