Skip to content

Rebase Dependabot

Rebase Dependabot #275

name: Rebase Dependabot
# After a merge, strict required checks leave other Dependabot PRs BEHIND.
# Dependabot rebase-strategy: auto is slow, so auto-merge sits armed forever.
# Replay each behind branch onto origin/main. Do not comment
# @dependabot rebase: github-actions[bot] and the auto-approve App are
# both rejected ("only users with push access", #1508 / #1509).
on:
push:
branches: [main]
schedule:
- cron: "17 * * * *"
workflow_dispatch:
concurrency:
group: ${{ github.workflow }}
cancel-in-progress: true
permissions:
contents: read
jobs:
rebase:
runs-on: ubuntu-latest
timeout-minutes: 10
permissions:
contents: write
pull-requests: read
steps:
- name: Harden runner
uses: step-security/harden-runner@05e31511f85b41b11d1cf0ef85d0992719546e2c # v2.21.0
with:
egress-policy: audit
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7
with:
fetch-depth: 0
persist-credentials: false
- name: Rebase Dependabot PRs that are behind main
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
REPO: ${{ github.repository }}
run: |
set -euo pipefail
git config user.name "github-actions[bot]"
git config user.email "41898282+github-actions[bot]@users.noreply.github.com"
nums=$(gh pr list --repo "${REPO}" --author "app/dependabot" --state open \
--json number,mergeStateStatus \
--jq '[.[] | select(.mergeStateStatus == "BEHIND") | .number] | .[]')
if [ -z "${nums}" ]; then
echo "No Dependabot PRs behind main."
exit 0
fi
git fetch origin main
remote_url="https://x-access-token:${GH_TOKEN}@github.com/${REPO}.git"
for n in ${nums}; do
branch=$(gh pr view "${n}" --repo "${REPO}" --json headRefName --jq .headRefName)
echo "Rebasing #${n} (${branch}) onto origin/main"
# Named-remote lease needs a tracking SHA. Pushing to a URL has none,
# so bare --force-with-lease reports stale info and aborts (#1513).
git fetch origin "refs/heads/${branch}:refs/remotes/origin/${branch}"
expected=$(git rev-parse "origin/${branch}")
git checkout -B "${branch}" "origin/${branch}"
if ! git rebase origin/main; then
echo "Conflict on #${n}; leaving it for a human."
git rebase --abort
continue
fi
if ! git push --force-with-lease="refs/heads/${branch}:${expected}" \
"${remote_url}" "HEAD:refs/heads/${branch}"; then
echo "Lease rejected on #${n}; refetch and retry once."
git fetch origin "refs/heads/${branch}:refs/remotes/origin/${branch}"
expected=$(git rev-parse "origin/${branch}")
git checkout -B "${branch}" "origin/${branch}"
if ! git rebase origin/main; then
echo "Conflict on #${n} after retry; leaving it for a human."
git rebase --abort
continue
fi
git push --force-with-lease="refs/heads/${branch}:${expected}" \
"${remote_url}" "HEAD:refs/heads/${branch}"
fi
done