From c7509830035c304e7f2096f4a710b01c14c24fea Mon Sep 17 00:00:00 2001 From: Steven Silvester Date: Tue, 20 Oct 2026 21:50:40 -0500 Subject: [PATCH] fix: actually enable auto-merge on update PRs --- actions/common/auto_merge.sh | 8 +++++-- actions/common/test_auto_merge.sh | 36 +++++++++++++++++++++---------- 2 files changed, 31 insertions(+), 13 deletions(-) diff --git a/actions/common/auto_merge.sh b/actions/common/auto_merge.sh index e118a0a..a160108 100755 --- a/actions/common/auto_merge.sh +++ b/actions/common/auto_merge.sh @@ -31,7 +31,11 @@ fi # The branch (and its PR) may be reused across runs, so only enable auto-merge # when it is not already enabled, since re-enabling it errors. A failed lookup # must fail the step rather than silently skipping the merge. -AUTO_MERGE_REQUEST=$(gh pr view "$BRANCH" --json autoMergeRequest --jq '.autoMergeRequest') || exit $? -if [ "$AUTO_MERGE_REQUEST" = "null" ]; then +# +# Compare against a boolean rather than `null`: gh's built-in --jq prints an +# empty string for a JSON null (unlike jq, which prints "null"), so testing for +# "null" never matches and auto-merge would be silently skipped. +AUTO_MERGE_ENABLED=$(gh pr view "$BRANCH" --json autoMergeRequest --jq '.autoMergeRequest != null') || exit $? +if [ "$AUTO_MERGE_ENABLED" != "true" ]; then gh pr merge "$BRANCH" --auto --squash --delete-branch fi diff --git a/actions/common/test_auto_merge.sh b/actions/common/test_auto_merge.sh index f7b0947..488eb32 100755 --- a/actions/common/test_auto_merge.sh +++ b/actions/common/test_auto_merge.sh @@ -35,9 +35,12 @@ check_not_contains() { } # Fake `gh` that logs the effective GH_TOKEN and arguments for every call. For -# `pr view` it prints a canned autoMergeRequest value, or fails when the -# pr_view_fail sentinel exists. This is not a general gh emulator — it only -# handles the exact call shapes auto_merge.sh makes. +# `pr view` it evaluates the caller's real --jq expression against a canned PR +# JSON document, or fails when the pr_view_fail sentinel exists. Like gh's +# built-in jq (and unlike jq -r), a null result prints as an empty line, so a +# script that tests for the string "null" fails here as it does in production. +# This is not a general gh emulator — it only handles the exact call shapes +# auto_merge.sh makes. FAKE_GH="$TMPDIR/gh" cat > "$FAKE_GH" < +# run run() { echo "$4" > "$TMPDIR/pr_view_response" : > "$TMPDIR/gh_calls.log" @@ -61,8 +72,11 @@ run() { bash "$SCRIPT" "poetry-lock-update" > "$TMPDIR/output.log" 2>&1 } +NOT_ENABLED='{"autoMergeRequest":null}' +ENABLED='{"autoMergeRequest":{"enabledBy":{"login":"x"}}}' + # Case 1: disabled -> no gh calls at all -run "false" "false" "app-token" "null" +run "false" "false" "app-token" "$NOT_ENABLED" CALLS=$(cat "$TMPDIR/gh_calls.log") if [ -z "$CALLS" ]; then echo "OK: disabled: no gh calls" @@ -72,7 +86,7 @@ else fi # Case 2: dry-run -> no gh calls at all -run "true" "true" "app-token" "null" +run "true" "true" "app-token" "$NOT_ENABLED" CALLS=$(cat "$TMPDIR/gh_calls.log") if [ -z "$CALLS" ]; then echo "OK: dry-run: no gh calls" @@ -82,25 +96,25 @@ else fi # Case 3: opt-in, not yet enabled -> approve with the workflow token, then merge -run "true" "false" "app-token" "null" +run "true" "false" "app-token" "$NOT_ENABLED" CALLS=$(cat "$TMPDIR/gh_calls.log") check_contains "opt-in: approves with the workflow token" "GH_TOKEN=workflow-token :: pr review poetry-lock-update --approve" "$CALLS" check_contains "opt-in: enables squash auto-merge" "pr merge poetry-lock-update --auto --squash --delete-branch" "$CALLS" # Case 4: already enabled -> approve, but do not re-enable -run "true" "false" "app-token" '{"enabledBy":{"login":"x"}}' +run "true" "false" "app-token" "$ENABLED" CALLS=$(cat "$TMPDIR/gh_calls.log") check_contains "already enabled: still approves" "pr review poetry-lock-update --approve" "$CALLS" check_not_contains "already enabled: does NOT re-enable auto-merge" "pr merge" "$CALLS" # Case 5: no app token -> skip approval, still enable auto-merge -run "true" "false" "" "null" +run "true" "false" "" "$NOT_ENABLED" CALLS=$(cat "$TMPDIR/gh_calls.log") check_not_contains "no app token: does NOT approve" "pr review" "$CALLS" check_contains "no app token: still enables auto-merge" "pr merge poetry-lock-update --auto --squash --delete-branch" "$CALLS" # Case 6: gh pr view fails -> step fails, no merge attempted -echo "null" > "$TMPDIR/pr_view_response" +echo "$NOT_ENABLED" > "$TMPDIR/pr_view_response" : > "$TMPDIR/gh_calls.log" touch "$TMPDIR/pr_view_fail" set +e