Skip to content

Dependabot Auto-merge (2-day soak) #149

Dependabot Auto-merge (2-day soak)

Dependabot Auto-merge (2-day soak) #149

name: Dependabot Auto-merge (2-day soak)
# Runs daily. For any open Dependabot PR that is >= 2 days old, approved, and
# has passing CI — adds it directly to the merge queue.
on:
schedule:
- cron: '0 9 * * *' # 09:00 UTC daily
workflow_dispatch: # allow manual trigger for testing
permissions:
contents: write
pull-requests: write
jobs:
automerge:
name: Auto-merge
runs-on: ubuntu-latest
steps:
- name: Merge eligible Dependabot PRs
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
REPO: ${{ github.repository }}
run: |
SEVEN_DAYS_AGO=$(date -u -d '2 days ago' '+%Y-%m-%dT%H:%M:%SZ' 2>/dev/null || \
date -u -v-2d '+%Y-%m-%dT%H:%M:%SZ')
echo "Looking for Dependabot PRs opened before $SEVEN_DAYS_AGO ..."
gh pr list \
--repo "$REPO" \
--author "app/dependabot" \
--state open \
--json number,title,createdAt,reviewDecision,mergeStateStatus \
| jq -c '.[]' \
| while IFS= read -r pr; do
NUMBER=$(echo "$pr" | jq -r '.number')
TITLE=$(echo "$pr" | jq -r '.title')
CREATED=$(echo "$pr" | jq -r '.createdAt')
REVIEW=$(echo "$pr" | jq -r '.reviewDecision')
MERGE_STATE=$(echo "$pr" | jq -r '.mergeStateStatus')
# Skip only on states that definitively mean "can't merge
# right now": real conflicts (DIRTY) or failing
# required-checks/review (BLOCKED — reviewDecision is
# checked separately below anyway). UNKNOWN is NOT one of
# these — it just means GitHub hasn't finished computing
# mergeability yet (very common right after a PR updates),
# not "already queued." Treating it as "skip" meant every
# PR here was skipped forever, since gh pr list almost
# always returns UNKNOWN on a fresh poll. Let a merge
# attempt happen and fail on its own terms instead of
# pre-filtering on a stale/transient field.
if [ "$MERGE_STATE" = "DIRTY" ] || [ "$MERGE_STATE" = "BLOCKED" ]; then
echo "PR #$NUMBER — merge state is $MERGE_STATE, skipping"
continue
fi
# Skip if not yet approved
if [ "$REVIEW" != "APPROVED" ]; then
echo "PR #$NUMBER — not approved yet ($REVIEW), skipping"
continue
fi
# Skip if less than 2 days old
if [[ "$CREATED" > "$SEVEN_DAYS_AGO" ]]; then
echo "PR #$NUMBER — opened $CREATED, not yet 2 days old, skipping"
continue
fi
echo "PR #$NUMBER ($TITLE) — eligible, adding to merge queue"
# --auto is required here, not optional: this repo's main
# branch only accepts merges via the merge queue, and a
# bare `gh pr merge --squash` (no --auto) just prints
# "the merge strategy for main is set by the merge queue"
# and does nothing — it was never actually enqueuing
# anything even on the rare PR that got this far.
gh pr merge --squash --auto "$NUMBER" --repo "$REPO" || \
echo "PR #$NUMBER — merge queue failed (may already be queued)"
done