name: PR Base Gate
on:
pull_request:
branches: [main]
types: [opened, reopened, synchronize, edited]
permissions:
checks: read
jobs:
verify-source:
name: PR source gate
runs-on: ubuntu-latest
timeout-minutes: 60
steps:
- name: main only accepts merges from dev
env:
HEAD_REF: ${{ github.event.pull_request.head.ref }}
HEAD_REPO: ${{ github.event.pull_request.head.repo.full_name }}
BASE_REPO: ${{ github.repository }}
run: |
if [ "${HEAD_REPO}" != "${BASE_REPO}" ]; then
echo "::error::Pull requests into 'main' must come from this repository, not a fork."
exit 1
fi
if [ "${HEAD_REF}" != "dev" ]; then
echo "::error::Pull requests into 'main' are only allowed from 'dev'. Retarget this pull request at 'dev' instead."
exit 1
fi
echo "'${HEAD_REF}' -> 'main': source branch allowed."
- name: wait for every other check on this PR to go green
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
HEAD_SHA: ${{ github.event.pull_request.head.sha }}
MERGE_SHA: ${{ github.event.pull_request.merge_commit_sha }}
run: |
set -euo pipefail
deadline=$(( $(date +%s) + 3300 ))
while :; do
{
gh api "repos/${GITHUB_REPOSITORY}/commits/${HEAD_SHA}/check-runs?per_page=100" \
--jq '.check_runs[] | [.name, (.conclusion // "pending")] | @tsv'
if [ -n "${MERGE_SHA:-}" ] && [ "${MERGE_SHA}" != "null" ]; then
gh api "repos/${GITHUB_REPOSITORY}/commits/${MERGE_SHA}/check-runs?per_page=100" \
--jq '.check_runs[] | [.name, (.conclusion // "pending")] | @tsv'
fi
} 2>/dev/null | grep -v '^PR source gate\b' > checks.tsv || true
if grep -E '\t(failure|cancelled|timed_out|action_required|startup_failure|stale)$' checks.tsv; then
echo "::error::a check on this pull request did not pass (see list above)"
exit 1
fi
pending=$(grep -c $'\tpending$' checks.tsv || true)
if [ "${pending}" -eq 0 ]; then
echo "all checks on this pull request have passed"
exit 0
fi
if [ "$(date +%s)" -gt "${deadline}" ]; then
echo "::error::timed out after 55 minutes waiting for ${pending} check(s) to conclude"
grep $'\tpending$' checks.tsv
exit 1
fi
echo "waiting on ${pending} check(s)..."
sleep 30
done