From e8e310b2888202b5aacdace2bebc98ad6d86647a Mon Sep 17 00:00:00 2001 From: Tom Martensen Date: Fri, 10 Apr 2026 14:23:21 +0200 Subject: [PATCH 1/9] Enhance auto-merge configurability --- automerge/README.md | 16 ++-- automerge/action.yml | 101 +++++++----------------- automerge/automerge.sh | 171 +++++++++++++++++++++++++++++++++++++++++ 3 files changed, 210 insertions(+), 78 deletions(-) create mode 100755 automerge/automerge.sh diff --git a/automerge/README.md b/automerge/README.md index db8b333..60c4327 100644 --- a/automerge/README.md +++ b/automerge/README.md @@ -1,23 +1,27 @@ # Auto-merge Action -This composite action enables auto-merge for eligible pull requests based on specified labels. +This composite action enables auto-merge for eligible pull requests based on specified labels. Defaults to approving Dependabot PRs with green CI against all branches. ## Features -- Finds PRs with specified label (default: `auto-merge`) +- Finds PRs with specified label (default: `auto-merge`) for the allowed base branches - Verifies PRs are in mergeable state (non-draft) -- Checks that all status checks have passed +- Checks that required status checks have passed - Enables auto-merge with squash strategy -- Auto-approves Dependabot PRs +- Auto-approves PRs for allowed author ## Inputs | Input | Description | Required | Default | |-------|-------------|----------|---------| +| `allowed-authors` | Authors to filter PRs for auto-merge (regex)| No | `app/dependabot` | +| `allowed-base-branches` | Allowed base branches for auto-merge (regex) | No | `.*` | +| `dry-run` | Whether to dry-run the auto-merge | No | `false` | | `github-token` | GitHub token with permissions to merge PRs and approve reviews (`contents: write` and `pull-requests: write` permissions) | Yes | - | +| `labels` | Labels to filter PRs for auto-merge (comma-separated `and` logic) | No | `auto-merge` | +| `limit` | Maximum number of PRs to process per run | No | `50` | | `repository` | Repository in owner/repo format | No | `${{ github.repository }}` | -| `label` | Label to filter PRs for auto-merge | No | `auto-merge` | -| `limit` | Maximum number of PRs to process | No | `50` | +| `required-checks` | Required checks to pass for auto-merge (regex) | No | `.*` | ## Usage diff --git a/automerge/action.yml b/automerge/action.yml index d106e18..118070c 100644 --- a/automerge/action.yml +++ b/automerge/action.yml @@ -2,13 +2,21 @@ name: Auto-merge PRs description: Enable auto-merge for eligible PRs with specified labels inputs: + allowed-author: + description: 'Author to filter PRs for auto-merge' + required: false + default: 'app/dependabot' + allowed-base-branches: + description: 'Allowed base branches for auto-merge' + required: false + default: '.*' + dry-run: + description: 'Whether to dry-run the auto-merge' + required: false + default: 'false' github-token: description: 'GitHub token with permissions to merge PRs and approve reviews' required: true - repository: - description: 'Repository in owner/repo format' - required: false - default: ${{ github.repository }} label: description: 'Label to filter PRs for auto-merge' required: false @@ -17,6 +25,14 @@ inputs: description: 'Maximum number of PRs to process per run.' required: false default: '50' + repository: + description: 'Repository in owner/repo format' + required: false + default: ${{ github.repository }} + required-checks: + description: 'Required checks to pass for auto-merge' + required: false + default: '.*' runs: using: composite @@ -25,74 +41,15 @@ runs: shell: bash env: GH_TOKEN: ${{ inputs.github-token }} + DRY_RUN: ${{ inputs.dry-run }} run: | set -euo pipefail - # Extract repo owner and name - IFS='/' read -r OWNER REPO <<< "${{ inputs.repository }}" - - echo "::notice::Querying PRs with '${{ inputs.label }}' label in ${{ inputs.repository }}" - - # Get all PRs with auto-merge labels (non-draft, mergeable only) - PR_DATA=$(gh pr list \ - --repo "${{ inputs.repository }}" \ - --label "${{ inputs.label }}" \ - --draft=false \ - --state open \ - --limit "${{ inputs.limit }}" \ - --json number,mergeable,author \ - --jq ".[] | select(.mergeable == \"MERGEABLE\") | {number, author: .author.login}") - - if [[ -z "$PR_DATA" ]]; then - echo "::notice::No eligible PRs found with '${{ inputs.label }}' label" - exit 0 - fi - - # Process each PR - echo "$PR_DATA" | jq -c '.' | while read -r PR_JSON; do - PR_NUMBER=$(echo "$PR_JSON" | jq -r '.number') - AUTHOR=$(echo "$PR_JSON" | jq -r '.author') - - echo "::notice::Processing PR #$PR_NUMBER (author=$AUTHOR)" - - # Check if all checks have passed using GraphQL statusCheckRollup - STATUS=$(gh api graphql -F owner="$OWNER" -F repo="$REPO" -F number="$PR_NUMBER" -f query=" - query(\$owner: String!, \$repo: String!, \$number: Int!) { - repository(owner: \$owner, name: \$repo) { - pullRequest(number: \$number) { - commits(last: 1) { - nodes { - commit { - statusCheckRollup { - state - } - } - } - } - } - } - } - " --jq ".data.repository.pullRequest.commits.nodes[0].commit.statusCheckRollup.state" || echo "null") - - echo "::notice::PR #$PR_NUMBER status check rollup: $STATUS" - - # Only proceed if all checks passed - if [[ "$STATUS" != "SUCCESS" ]]; then - echo "::warning::Skipping PR #$PR_NUMBER - checks not passed (status: $STATUS)" - continue - fi - - # Enable auto-merge for all PRs with the label - echo "::notice::Enabling auto-merge for PR #$PR_NUMBER" - gh pr merge --repo "${{ inputs.repository }}" \ - --auto --squash "$PR_NUMBER" - - # Auto-approve only Dependabot PRs - if [[ "$AUTHOR" == "app/dependabot" ]]; then - echo "::notice::Approving Dependabot PR #$PR_NUMBER" - gh pr review --repo "${{ inputs.repository }}" \ - --approve "$PR_NUMBER" || true - fi - - echo "::notice::✓ Auto-merge enabled for PR #$PR_NUMBER" - done + "${GITHUB_ACTION_PATH}/../../common/common.sh" \ + "${GITHUB_ACTION_PATH}/automerge.sh" \ + "${{ inputs.repository }}" \ + "${{ inputs.limit }}" \ + "${{ inputs.label }}" \ + "${{ inputs.allowed-author }}" \ + "${{ inputs.required-checks }}" \ + "${{ inputs.allowed-base-branches }}" diff --git a/automerge/automerge.sh b/automerge/automerge.sh new file mode 100755 index 0000000..e83f150 --- /dev/null +++ b/automerge/automerge.sh @@ -0,0 +1,171 @@ +#!/bin/bash + +# + +# +# Enables auto-merge for eligible PRs with specified labels. +# PRs can be filtered by labels, base branches, and allowed author. +# Required status checks must pass for auto-merge to be enabled. +# +# Local run: +# +# test/local-env.sh automerge/automerge.sh +# + +set -euo pipefail + +function main() { + REPOSITORY="${1:-}" + LIMIT="${2:-}" + LABELS="${3:-}" + ALLOWED_AUTHORS="${4:-}" + REQUIRED_CHECKS="${5:-}" + ALLOWED_BASE_BRANCHES="${6:-}" + + check_not_empty \ + DRY_RUN GH_TOKEN \ + REPOSITORY LIMIT LABELS ALLOWED_AUTHORS REQUIRED_CHECKS + + gh_log notice "Querying PRs with '${LABELS}' label(s) in ${REPOSITORY}, allowed authors: ${ALLOWED_AUTHORS}, required checks: ${REQUIRED_CHECKS}, allowed base branches: ${ALLOWED_BASE_BRANCHES}" + gh_log notice "DRY_RUN: ${DRY_RUN}" + + # Extract repo owner and name + IFS='/' read -r OWNER REPO <<< "${REPOSITORY}" + + # Get all PRs with auto-merge labels (non-draft, mergeable only) + PR_DATA=$(gh pr list \ + --repo "${REPOSITORY}" \ + --label "${LABELS}" \ + --draft=false \ + --state open \ + --limit "${LIMIT}" \ + --json number,mergeable,author,baseRefName \ + --jq ".[] | select(.mergeable == \"MERGEABLE\") | {number, author: .author.login, baseRefName: .baseRefName}") + + if [[ -z "${PR_DATA}" ]]; then + gh_log notice "No eligible PRs found with '${LABELS}' labels" + exit 0 + fi + + # Process each PR + echo "${PR_DATA}" | jq -c '.' | while read -r PR_JSON; do + PR_NUMBER=$(echo "$PR_JSON" | jq -r '.number') + AUTHOR=$(echo "$PR_JSON" | jq -r '.author') + BASE_BRANCH=$(echo "$PR_JSON" | jq -r '.baseRefName') + + gh_log notice "PR #${PR_NUMBER} - author='${AUTHOR}', base branch='${BASE_BRANCH}'" + if [[ ! "${BASE_BRANCH}" =~ ^(${ALLOWED_BASE_BRANCHES})$ ]]; then + gh_log warning "PR #${PR_NUMBER} skipped - base branch '${BASE_BRANCH}' not allowed" + continue + fi + + STATUS="$(get_combined_success_status "${PR_NUMBER}")" + + # Only proceed if the required checks have passed + if [[ "${STATUS}" == "true" ]]; then + gh_log notice "✓ PR #${PR_NUMBER} - all required checks passed or skipped" + else + gh_log warning "x PR #${PR_NUMBER} skipped - not all required checks passed or skipped" + continue + fi + + # Enable auto-merge for all PRs with the label(s) + if [[ "${DRY_RUN}" == "true" ]]; then + gh_log notice "✓ PR #${PR_NUMBER} - would have enabled auto-merge [DRY RUN]" + else + gh pr merge --repo "${REPOSITORY}" \ + --auto --squash "${PR_NUMBER}" + gh_log notice "✓ PR #${PR_NUMBER} - auto-merge enabled" + fi + + # Approve only PRs by allowed authors + if [[ "${AUTHOR}" =~ ^(${ALLOWED_AUTHORS})$ ]]; then + if [[ "${DRY_RUN}" == "true" ]]; then + gh_log notice "✓ PR #${PR_NUMBER} - would have approved [DRY RUN]" + else + gh pr review --repo "${REPOSITORY}" \ + --approve "${PR_NUMBER}" + gh_log notice "✓ PR #${PR_NUMBER} - approved" + fi + else + gh_log warning "x PR #${PR_NUMBER} not approved - author '${AUTHOR}' not in allowed authors" + fi + done +} + +function get_combined_success_status() { + PAGE_SIZE=100 + CURSOR="" + NODES_JSON='[]' + + QUERY=' + query($owner: String!, $repo: String!, $number: Int!, $first: Int!, $after: String) { + repository(owner: $owner, name: $repo) { + pullRequest(number: $number) { + commits(last: 1) { + nodes { + commit { + statusCheckRollup { + contexts(first: $first, after: $after) { + pageInfo { + hasNextPage + endCursor + } + nodes { + ... on CheckRun { + name + status + conclusion + } + } + } + } + } + } + } + } + } + } + ' + + while true; do + ARGS=( + graphql + -F owner="$OWNER" + -F repo="$REPO" + -F number="$PR_NUMBER" + -F first="$PAGE_SIZE" + -f query="$QUERY" + ) + if [[ -n "$CURSOR" ]]; then + ARGS+=(-F after="$CURSOR") + fi + + RESP=$(gh api "${ARGS[@]}") + + PAGE_NODES=$(echo "$RESP" | jq '.data.repository.pullRequest.commits.nodes[0].commit.statusCheckRollup.contexts.nodes // []') + NODES_JSON=$(jq -n --argjson acc "$NODES_JSON" --argjson page "$PAGE_NODES" '$acc + $page') + + HAS_NEXT=$(echo "$RESP" | jq -r '.data.repository.pullRequest.commits.nodes[0].commit.statusCheckRollup.contexts.pageInfo.hasNextPage // false') + if [[ "$HAS_NEXT" != "true" ]]; then + break + fi + CURSOR=$(echo "$RESP" | jq -r '.data.repository.pullRequest.commits.nodes[0].commit.statusCheckRollup.contexts.pageInfo.endCursor // empty') + if [[ -z "$CURSOR" ]]; then + echo "::error::pagination indicated hasNextPage but endCursor is empty" >&2 + exit 1 + fi + done + + echo "$NODES_JSON" | jq ' + map(select( + .name != null + and (.name | test("'"${REQUIRED_CHECKS}"'")) + )) + | { + ALL_SUCCESS: (length > 0 and all(.conclusion == "SUCCESS" or .conclusion == "SKIPPED")) + } | .ALL_SUCCESS + ' +} + +main "$@" From 8036b7da6a040b0978e3f7d714fe57acdab768ef Mon Sep 17 00:00:00 2001 From: Tom Martensen Date: Fri, 10 Apr 2026 14:27:41 +0200 Subject: [PATCH 2/9] ignore shellcheck warning for GH API GraphQL query --- automerge/automerge.sh | 1 + 1 file changed, 1 insertion(+) diff --git a/automerge/automerge.sh b/automerge/automerge.sh index e83f150..ce7b63f 100755 --- a/automerge/automerge.sh +++ b/automerge/automerge.sh @@ -98,6 +98,7 @@ function get_combined_success_status() { CURSOR="" NODES_JSON='[]' + # shellcheck disable=SC2016 QUERY=' query($owner: String!, $repo: String!, $number: Int!, $first: Int!, $after: String) { repository(owner: $owner, name: $repo) { From db189d3c1ce0590d29317885be9ecfc34e6e5010 Mon Sep 17 00:00:00 2001 From: Tom Martensen Date: Fri, 10 Apr 2026 14:32:20 +0200 Subject: [PATCH 3/9] test dry-run input --- automerge/automerge.sh | 2 ++ 1 file changed, 2 insertions(+) diff --git a/automerge/automerge.sh b/automerge/automerge.sh index ce7b63f..0878e56 100755 --- a/automerge/automerge.sh +++ b/automerge/automerge.sh @@ -29,6 +29,8 @@ function main() { gh_log notice "Querying PRs with '${LABELS}' label(s) in ${REPOSITORY}, allowed authors: ${ALLOWED_AUTHORS}, required checks: ${REQUIRED_CHECKS}, allowed base branches: ${ALLOWED_BASE_BRANCHES}" gh_log notice "DRY_RUN: ${DRY_RUN}" + exit 1 + # Extract repo owner and name IFS='/' read -r OWNER REPO <<< "${REPOSITORY}" From 92ef0f27b1eb089de04e3501c404e3ad879467e7 Mon Sep 17 00:00:00 2001 From: Tom Martensen Date: Fri, 10 Apr 2026 14:37:09 +0200 Subject: [PATCH 4/9] fix path to common.sh --- automerge/action.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/automerge/action.yml b/automerge/action.yml index 118070c..db6d094 100644 --- a/automerge/action.yml +++ b/automerge/action.yml @@ -45,7 +45,7 @@ runs: run: | set -euo pipefail - "${GITHUB_ACTION_PATH}/../../common/common.sh" \ + "${GITHUB_ACTION_PATH}/../common/common.sh" \ "${GITHUB_ACTION_PATH}/automerge.sh" \ "${{ inputs.repository }}" \ "${{ inputs.limit }}" \ From d19bfcac8d5bb9501ae507c277bea00fd294dc76 Mon Sep 17 00:00:00 2001 From: Tom Martensen Date: Fri, 10 Apr 2026 14:41:37 +0200 Subject: [PATCH 5/9] less verbose output --- automerge/automerge.sh | 21 +++++++++------------ 1 file changed, 9 insertions(+), 12 deletions(-) diff --git a/automerge/automerge.sh b/automerge/automerge.sh index 0878e56..7a64811 100755 --- a/automerge/automerge.sh +++ b/automerge/automerge.sh @@ -1,7 +1,4 @@ #!/bin/bash - -# - # # Enables auto-merge for eligible PRs with specified labels. # PRs can be filtered by labels, base branches, and allowed author. @@ -55,9 +52,9 @@ function main() { AUTHOR=$(echo "$PR_JSON" | jq -r '.author') BASE_BRANCH=$(echo "$PR_JSON" | jq -r '.baseRefName') - gh_log notice "PR #${PR_NUMBER} - author='${AUTHOR}', base branch='${BASE_BRANCH}'" + gh_summary "PR #${PR_NUMBER} - author='${AUTHOR}', base branch='${BASE_BRANCH}'" if [[ ! "${BASE_BRANCH}" =~ ^(${ALLOWED_BASE_BRANCHES})$ ]]; then - gh_log warning "PR #${PR_NUMBER} skipped - base branch '${BASE_BRANCH}' not allowed" + gh_summary "PR #${PR_NUMBER} skipped - base branch '${BASE_BRANCH}' not allowed" continue fi @@ -65,32 +62,32 @@ function main() { # Only proceed if the required checks have passed if [[ "${STATUS}" == "true" ]]; then - gh_log notice "✓ PR #${PR_NUMBER} - all required checks passed or skipped" + gh_summary "✓ PR #${PR_NUMBER} - all required checks passed or skipped" else - gh_log warning "x PR #${PR_NUMBER} skipped - not all required checks passed or skipped" + gh_summary "x PR #${PR_NUMBER} skipped - not all required checks passed or skipped" continue fi # Enable auto-merge for all PRs with the label(s) if [[ "${DRY_RUN}" == "true" ]]; then - gh_log notice "✓ PR #${PR_NUMBER} - would have enabled auto-merge [DRY RUN]" + gh_summary "✓ PR #${PR_NUMBER} - would have enabled auto-merge [DRY RUN]" else gh pr merge --repo "${REPOSITORY}" \ --auto --squash "${PR_NUMBER}" - gh_log notice "✓ PR #${PR_NUMBER} - auto-merge enabled" + gh_summary "✓ PR #${PR_NUMBER} - auto-merge enabled" fi # Approve only PRs by allowed authors if [[ "${AUTHOR}" =~ ^(${ALLOWED_AUTHORS})$ ]]; then if [[ "${DRY_RUN}" == "true" ]]; then - gh_log notice "✓ PR #${PR_NUMBER} - would have approved [DRY RUN]" + gh_summary "✓ PR #${PR_NUMBER} - would have approved [DRY RUN]" else gh pr review --repo "${REPOSITORY}" \ --approve "${PR_NUMBER}" - gh_log notice "✓ PR #${PR_NUMBER} - approved" + gh_summary "✓ PR #${PR_NUMBER} - approved" fi else - gh_log warning "x PR #${PR_NUMBER} not approved - author '${AUTHOR}' not in allowed authors" + gh_summary "x PR #${PR_NUMBER} not approved - author '${AUTHOR}' not in allowed authors" fi done } From 3b1b6811e91add7107204163d35fb5e513b58877 Mon Sep 17 00:00:00 2001 From: Tom Martensen Date: Fri, 10 Apr 2026 14:53:39 +0200 Subject: [PATCH 6/9] undo dry-run guard, fix input parameters --- automerge/action.yml | 16 ++++++++-------- automerge/automerge.sh | 2 -- 2 files changed, 8 insertions(+), 10 deletions(-) diff --git a/automerge/action.yml b/automerge/action.yml index db6d094..9026485 100644 --- a/automerge/action.yml +++ b/automerge/action.yml @@ -2,12 +2,12 @@ name: Auto-merge PRs description: Enable auto-merge for eligible PRs with specified labels inputs: - allowed-author: - description: 'Author to filter PRs for auto-merge' + allowed-authors: + description: 'Authors to filter PRs for auto-merge (regex)' required: false default: 'app/dependabot' allowed-base-branches: - description: 'Allowed base branches for auto-merge' + description: 'Allowed base branches for auto-merge (regex)' required: false default: '.*' dry-run: @@ -17,8 +17,8 @@ inputs: github-token: description: 'GitHub token with permissions to merge PRs and approve reviews' required: true - label: - description: 'Label to filter PRs for auto-merge' + labels: + description: 'Labels to filter PRs for auto-merge (comma-separated `and` logic)' required: false default: 'auto-merge' limit: @@ -30,7 +30,7 @@ inputs: required: false default: ${{ github.repository }} required-checks: - description: 'Required checks to pass for auto-merge' + description: 'Required checks to pass for auto-merge (regex)' required: false default: '.*' @@ -49,7 +49,7 @@ runs: "${GITHUB_ACTION_PATH}/automerge.sh" \ "${{ inputs.repository }}" \ "${{ inputs.limit }}" \ - "${{ inputs.label }}" \ - "${{ inputs.allowed-author }}" \ + "${{ inputs.labels }}" \ + "${{ inputs.allowed-authors }}" \ "${{ inputs.required-checks }}" \ "${{ inputs.allowed-base-branches }}" diff --git a/automerge/automerge.sh b/automerge/automerge.sh index 7a64811..92313b6 100755 --- a/automerge/automerge.sh +++ b/automerge/automerge.sh @@ -26,8 +26,6 @@ function main() { gh_log notice "Querying PRs with '${LABELS}' label(s) in ${REPOSITORY}, allowed authors: ${ALLOWED_AUTHORS}, required checks: ${REQUIRED_CHECKS}, allowed base branches: ${ALLOWED_BASE_BRANCHES}" gh_log notice "DRY_RUN: ${DRY_RUN}" - exit 1 - # Extract repo owner and name IFS='/' read -r OWNER REPO <<< "${REPOSITORY}" From 63ad0edf3e13a56d7d89145439c91f4532d3199a Mon Sep 17 00:00:00 2001 From: Tom Martensen Date: Fri, 10 Apr 2026 15:00:28 +0200 Subject: [PATCH 7/9] fix: use gh_log debug instead of gh_summary --- automerge/automerge.sh | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/automerge/automerge.sh b/automerge/automerge.sh index 92313b6..b800978 100755 --- a/automerge/automerge.sh +++ b/automerge/automerge.sh @@ -50,9 +50,9 @@ function main() { AUTHOR=$(echo "$PR_JSON" | jq -r '.author') BASE_BRANCH=$(echo "$PR_JSON" | jq -r '.baseRefName') - gh_summary "PR #${PR_NUMBER} - author='${AUTHOR}', base branch='${BASE_BRANCH}'" + gh_log debug "PR #${PR_NUMBER} - author='${AUTHOR}', base branch='${BASE_BRANCH}'" if [[ ! "${BASE_BRANCH}" =~ ^(${ALLOWED_BASE_BRANCHES})$ ]]; then - gh_summary "PR #${PR_NUMBER} skipped - base branch '${BASE_BRANCH}' not allowed" + gh_log debug "PR #${PR_NUMBER} skipped - base branch '${BASE_BRANCH}' not allowed" continue fi @@ -60,32 +60,32 @@ function main() { # Only proceed if the required checks have passed if [[ "${STATUS}" == "true" ]]; then - gh_summary "✓ PR #${PR_NUMBER} - all required checks passed or skipped" + gh_log debug "✓ PR #${PR_NUMBER} - all required checks passed or skipped" else - gh_summary "x PR #${PR_NUMBER} skipped - not all required checks passed or skipped" + gh_log debug "x PR #${PR_NUMBER} skipped - not all required checks passed or skipped" continue fi # Enable auto-merge for all PRs with the label(s) if [[ "${DRY_RUN}" == "true" ]]; then - gh_summary "✓ PR #${PR_NUMBER} - would have enabled auto-merge [DRY RUN]" + gh_log debug "✓ PR #${PR_NUMBER} - would have enabled auto-merge [DRY RUN]" else gh pr merge --repo "${REPOSITORY}" \ --auto --squash "${PR_NUMBER}" - gh_summary "✓ PR #${PR_NUMBER} - auto-merge enabled" + gh_log debug "✓ PR #${PR_NUMBER} - auto-merge enabled" fi # Approve only PRs by allowed authors if [[ "${AUTHOR}" =~ ^(${ALLOWED_AUTHORS})$ ]]; then if [[ "${DRY_RUN}" == "true" ]]; then - gh_summary "✓ PR #${PR_NUMBER} - would have approved [DRY RUN]" + gh_log debug "✓ PR #${PR_NUMBER} - would have approved [DRY RUN]" else gh pr review --repo "${REPOSITORY}" \ --approve "${PR_NUMBER}" - gh_summary "✓ PR #${PR_NUMBER} - approved" + gh_log debug "✓ PR #${PR_NUMBER} - approved" fi else - gh_summary "x PR #${PR_NUMBER} not approved - author '${AUTHOR}' not in allowed authors" + gh_log debug "x PR #${PR_NUMBER} not approved - author '${AUTHOR}' not in allowed authors" fi done } From 9c7098462e315c0d2b31b0ff1b9eb5c6b9ebada2 Mon Sep 17 00:00:00 2001 From: Tom Martensen Date: Fri, 10 Apr 2026 15:02:56 +0200 Subject: [PATCH 8/9] improvement to output --- automerge/automerge.sh | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/automerge/automerge.sh b/automerge/automerge.sh index b800978..52a83db 100755 --- a/automerge/automerge.sh +++ b/automerge/automerge.sh @@ -50,9 +50,9 @@ function main() { AUTHOR=$(echo "$PR_JSON" | jq -r '.author') BASE_BRANCH=$(echo "$PR_JSON" | jq -r '.baseRefName') - gh_log debug "PR #${PR_NUMBER} - author='${AUTHOR}', base branch='${BASE_BRANCH}'" + echo "[DEBUG] PR #${PR_NUMBER} - author='${AUTHOR}', base branch='${BASE_BRANCH}'" if [[ ! "${BASE_BRANCH}" =~ ^(${ALLOWED_BASE_BRANCHES})$ ]]; then - gh_log debug "PR #${PR_NUMBER} skipped - base branch '${BASE_BRANCH}' not allowed" + echo "[DEBUG] PR #${PR_NUMBER} skipped - base branch '${BASE_BRANCH}' not allowed" continue fi @@ -60,32 +60,32 @@ function main() { # Only proceed if the required checks have passed if [[ "${STATUS}" == "true" ]]; then - gh_log debug "✓ PR #${PR_NUMBER} - all required checks passed or skipped" + echo "[DEBUG] ✓ PR #${PR_NUMBER} - all required checks passed or skipped" else - gh_log debug "x PR #${PR_NUMBER} skipped - not all required checks passed or skipped" + echo "[DEBUG] x PR #${PR_NUMBER} skipped - not all required checks passed or skipped" continue fi # Enable auto-merge for all PRs with the label(s) if [[ "${DRY_RUN}" == "true" ]]; then - gh_log debug "✓ PR #${PR_NUMBER} - would have enabled auto-merge [DRY RUN]" + echo "[DEBUG] ✓ PR #${PR_NUMBER} - would have enabled auto-merge [DRY RUN]" else gh pr merge --repo "${REPOSITORY}" \ --auto --squash "${PR_NUMBER}" - gh_log debug "✓ PR #${PR_NUMBER} - auto-merge enabled" + echo "[DEBUG] ✓ PR #${PR_NUMBER} - auto-merge enabled" fi # Approve only PRs by allowed authors if [[ "${AUTHOR}" =~ ^(${ALLOWED_AUTHORS})$ ]]; then if [[ "${DRY_RUN}" == "true" ]]; then - gh_log debug "✓ PR #${PR_NUMBER} - would have approved [DRY RUN]" + echo "[DEBUG] ✓ PR #${PR_NUMBER} - would have approved [DRY RUN]" else gh pr review --repo "${REPOSITORY}" \ --approve "${PR_NUMBER}" - gh_log debug "✓ PR #${PR_NUMBER} - approved" + echo "[DEBUG] ✓ PR #${PR_NUMBER} - approved" fi else - gh_log debug "x PR #${PR_NUMBER} not approved - author '${AUTHOR}' not in allowed authors" + echo "[DEBUG] x PR #${PR_NUMBER} not approved - author '${AUTHOR}' not in allowed authors" fi done } From 59de5bbc992b2c9e576a929fad272340af330762 Mon Sep 17 00:00:00 2001 From: Tom Martensen Date: Fri, 10 Apr 2026 15:19:26 +0200 Subject: [PATCH 9/9] self-review --- automerge/automerge.sh | 46 +++++++++++++++++++++--------------------- 1 file changed, 23 insertions(+), 23 deletions(-) diff --git a/automerge/automerge.sh b/automerge/automerge.sh index 52a83db..41ffda7 100755 --- a/automerge/automerge.sh +++ b/automerge/automerge.sh @@ -127,32 +127,32 @@ function get_combined_success_status() { ' while true; do - ARGS=( - graphql - -F owner="$OWNER" - -F repo="$REPO" - -F number="$PR_NUMBER" - -F first="$PAGE_SIZE" - -f query="$QUERY" - ) - if [[ -n "$CURSOR" ]]; then - ARGS+=(-F after="$CURSOR") - fi + ARGS=( + graphql + -F owner="$OWNER" + -F repo="$REPO" + -F number="$PR_NUMBER" + -F first="$PAGE_SIZE" + -f query="$QUERY" + ) + if [[ -n "${CURSOR}" ]]; then + ARGS+=(-F after="${CURSOR}") + fi - RESP=$(gh api "${ARGS[@]}") + RESP=$(gh api "${ARGS[@]}") - PAGE_NODES=$(echo "$RESP" | jq '.data.repository.pullRequest.commits.nodes[0].commit.statusCheckRollup.contexts.nodes // []') - NODES_JSON=$(jq -n --argjson acc "$NODES_JSON" --argjson page "$PAGE_NODES" '$acc + $page') + PAGE_NODES=$(echo "${RESP}" | jq '.data.repository.pullRequest.commits.nodes[0].commit.statusCheckRollup.contexts.nodes // []') + NODES_JSON=$(jq -n --argjson acc "${NODES_JSON}" --argjson page "${PAGE_NODES}" '$acc + $page') - HAS_NEXT=$(echo "$RESP" | jq -r '.data.repository.pullRequest.commits.nodes[0].commit.statusCheckRollup.contexts.pageInfo.hasNextPage // false') - if [[ "$HAS_NEXT" != "true" ]]; then - break - fi - CURSOR=$(echo "$RESP" | jq -r '.data.repository.pullRequest.commits.nodes[0].commit.statusCheckRollup.contexts.pageInfo.endCursor // empty') - if [[ -z "$CURSOR" ]]; then - echo "::error::pagination indicated hasNextPage but endCursor is empty" >&2 - exit 1 - fi + HAS_NEXT=$(echo "${RESP}" | jq -r '.data.repository.pullRequest.commits.nodes[0].commit.statusCheckRollup.contexts.pageInfo.hasNextPage // false') + if [[ "${HAS_NEXT}" != "true" ]]; then + break + fi + CURSOR=$(echo "${RESP}" | jq -r '.data.repository.pullRequest.commits.nodes[0].commit.statusCheckRollup.contexts.pageInfo.endCursor // empty') + if [[ -z "${CURSOR}" ]]; then + gh_log error "Pagination indicated hasNextPage but endCursor is empty" + exit 1 + fi done echo "$NODES_JSON" | jq '