Skip to content

GitHub Merge Queue #4406

GitHub Merge Queue

GitHub Merge Queue #4406

# Requires repo secret: PERSONAL_ACCESS_TOKEN with permissions:
# Pull Requests: read and write
# Workflow: read and write
# This effectively creates a merge queue out of all PRs marked as auto-merge, but merge queues are
# a GitHub feature is only available to organizations or those on Enterprise Cloud right now.
# https://docs.github.com/en/repositories/configuring-branches-and-merges-in-your-repository/configuring-pull-request-merges/managing-a-merge-queue
name: GitHub Merge Queue
on:
# A PR merge has occurred, or a PR is no longer eligible for the queue; move on to the next PR
pull_request_target:
types:
- closed
- converted_to_draft
- auto_merge_disabled
# Jiggle the handle every hour just in case
schedule:
- cron: '0 * * * *'
workflow_dispatch:
env:
renovate_rebase_label: 'renovate/rebase'
jobs:
# Update the oldest auto-merge PR that's out-of-date with the base branch
update-pr-branch:
runs-on: ubuntu-latest
steps:
# Required for `gh` CLI
- uses: actions/checkout@93cb6efe18208431cddfb8368fd83d5badbf9bfd # v5.0.1
- run: |
set -x
pr_search="sort:created-asc"
# Wait for the merge state status to be updated
while true; do
pr_list="$(gh pr list --search "${pr_search}" --json number,mergeable --jq '.[] | [.number, .mergeable] | @csv')"
# No PRs found, so none can be in an 'UNKNOWN' state
[[ "${pr_list}" == "" ]] && break
# At least one PR is not in an 'UNKNOWN' state
echo "${pr_list}" | grep -v "UNKNOWN" && break
echo "$(echo "${pr_list}" | wc -l | awk '{print $1}') PRs in an 'UNKNOWN' mergeable state, waiting ..."
sleep 5
done
echo "PRs found:"
gh pr list --search "${pr_search}" --json number,title,mergeable,mergeStateStatus,autoMergeRequest | jq
eligible_prs="$(gh pr list --search "${pr_search}" --json number,isDraft,mergeable,mergeStateStatus,autoMergeRequest --jq '.[] | select(.isDraft==false and .mergeable=="MERGEABLE" and .mergeStateStatus=="BEHIND" and .autoMergeRequest!=null) | .number')"
if [[ "${eligible_prs}" == "" ]]; then
echo "No eligible PRs found"
exit 0
fi
echo "$(echo "${eligible_prs}" | wc -l | awk '{print $1}') eligible PRs found: $(echo "${eligible_prs}" | awk '{print $1}' | awk 'ORS=", "' | sed 's/, *$//')"
while read -r number; do
echo "Updating PR #${number}"
gh pr update-branch "${number}" && break
done <<< "${eligible_prs}"
env:
# GitHub won't run workflows off of code commits+pushes from the `github-actions` user
GH_TOKEN: ${{ secrets.PERSONAL_ACCESS_TOKEN }}
# Add a label to the oldest Renovate auto-merge PR that has conflicts, such that Renovate rebases it
renovate-label-adder:
permissions:
# actions/checkout
contents: read
# `gh` CLI actions
pull-requests: write
issues: write
runs-on: ubuntu-latest
steps:
# Required for `gh` CLI
- uses: actions/checkout@93cb6efe18208431cddfb8368fd83d5badbf9bfd # v5.0.1
- run: |
set -x
author="app/renovate"
pr_search="author:${author} sort:created-asc -label:${{ env.renovate_rebase_label }}"
# Wait for the merge state status to be updated
while true; do
pr_list="$(gh pr list --search "${pr_search}" --json number,mergeable --jq '.[] | [.number, .mergeable] | @csv')"
# No PRs found, so none can be in an 'UNKNOWN' state
[[ "${pr_list}" == "" ]] && break
# At least one PR is not in an 'UNKNOWN' state
echo "${pr_list}" | grep -v "UNKNOWN" && break
echo "$(echo "${pr_list}" | wc -l | awk '{print $1}') PRs in an 'UNKNOWN' mergeable state, waiting ..."
sleep 5
done
echo "Renovate PRs found:"
gh pr list --search "${pr_search}" --json number,title,mergeable,mergeStateStatus,autoMergeRequest | jq
eligible_prs="$(gh pr list --search "${pr_search}" --json number,isDraft,mergeable,autoMergeRequest --jq '.[] | select(.isDraft==false and .mergeable=="CONFLICTING" and .autoMergeRequest!=null) | .number')"
if [[ "${eligible_prs}" == "" ]]; then
echo "No eligible PRs found"
exit 0
fi
echo "$(echo "${eligible_prs}" | wc -l | awk '{print $1}') eligible PRs found: $(echo "${eligible_prs}" | awk '{print $1}' | awk 'ORS=", "' | sed 's/, *$//')"
while read -r number; do
echo "Adding label '${{ env.renovate_rebase_label }}' to PR #${number}"
gh pr edit "${number}" --add-label "${{ env.renovate_rebase_label }}" && break
done <<< "${eligible_prs}"
env:
GH_TOKEN: ${{ github.token }}
renovate-label-remover:
if: ${{ github.event_name == 'pull_request' }}
permissions:
# actions/checkout
contents: read
# `gh` CLI actions
pull-requests: write
issues: write
runs-on: ubuntu-latest
steps:
# Required for `gh` CLI
- uses: actions/checkout@93cb6efe18208431cddfb8368fd83d5badbf9bfd # v5.0.1
- run: |
gh pr edit "${{ github.event.pull_request.number }}" --remove-label "${{ env.renovate_rebase_label }}"
env:
GH_TOKEN: ${{ github.token }}