fix(auto-approve-bot-prs): merge directly and surface skips that need action - #208
Open
sydorovdmytro wants to merge 1 commit into
Open
fix(auto-approve-bot-prs): merge directly and surface skips that need action#208sydorovdmytro wants to merge 1 commit into
sydorovdmytro wants to merge 1 commit into
Conversation
… action Three changes, all aimed at the same failure class: the action was silent about outcomes that require someone to act, so a PR that never merged looked identical to a PR that merged fine. Merge directly, keep --auto as the fallback. By the time the merge step runs, wait-for-ci.sh has confirmed every other check is green and the PR is approved, so there is normally nothing left for GitHub's auto-merge queue to wait on. `--auto` additionally requires the repository's allow_auto_merge setting, which is invisible from here and silently turns the merge into a no-op when it is off - and a merge that never happens strands whatever is waiting on it (the vcluster-release orchestrator blocks on exactly this merge during a legacy release cut). A refused direct merge still degrades to queueing, which is the right answer when a required check registered after the CI wait declared green. Re-runs are handled explicitly: an already-merged PR is benign and a PR closed unmerged is a human decision, so neither escalates. Report actionable skips at warning/error level. Nothing here exits non-zero - the composite must not red-X a caller's CI over an unrelated bot PR - but notices are invisible on a green run, and the cause of a non-merge is only knowable here (a caller waiting on the merge can see that it did not happen, never why). An approved-but-unmerged PR now carries both underlying gh errors in an ::error:: annotation. Conflicts, exhausted mergeability budgets, dead tokens and same-identity tokens are split apart instead of sharing one notice, since they need different responses. Fix a real defect found while splitting those: `--jq '.mergeable // "null"'` collapsed a genuine `mergeable: false` into "null", because jq's `//` treats false as empty. A conflicted PR was therefore indistinguishable from un-computed metadata AND burned the full ~30s retry budget re-polling a value that was already definitive. Both halves are pinned by regression tests that fail against the old filter. Adds enable-auto-merge.bats (the script had no coverage) and extends the gh mock to control the direct and --auto merges separately and to answer `gh pr view --json state`. 61 tests pass; shellcheck and actionlint clean.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Follow-up to #201 (the in-pipeline pro dependency bump). Three changes, all aimed at the same failure class: the action was silent about outcomes that require someone to act, so a PR that never merged looked identical to a PR that merged fine.
References DEVOPS-1209
Merge directly, keep
--autoas the fallbackBy the time the merge step runs,
wait-for-ci.shhas confirmed every other check is green and the PR is approved, so there is normally nothing left for GitHub's auto-merge queue to wait on.--autoadditionally requires the repository'sallow_auto_mergesetting, which is invisible from inside the action and silently turns the merge into a no-op when it is off — and a merge that never happens strands whatever is waiting on it. Thevcluster-releaseorchestrator blocks on exactly this merge during a legacy release cut, so that no-op stalls a release.A refused direct merge still degrades to queueing, which is the right answer when a required check registered after the CI wait declared green. Re-runs are handled explicitly: an already-merged PR is benign, and a PR closed unmerged is a human decision, so neither escalates.
Report actionable skips at warning/error level
Nothing here exits non-zero — the composite must not red-X a caller's CI over an unrelated bot PR — but notices are invisible on a green run, and the cause of a non-merge is only knowable inside the action. A caller waiting on the merge can see that it did not happen, never why.
An approved-but-unmerged PR now carries both underlying
gherrors in an::error::annotation. Four causes that previously shared one notice are split, because they need different responses:::notice::PR mergeability is '…'::warning::— needs a rebase::warning::— transient, re-run::notice::Skipping approval (…)::error::— expired/insufficient scope::error::— self-approval is impossible::notice::gh pr merge failed::error::with bothgherrorsA real defect found while splitting those
--jq '.mergeable // "null"'collapsed a genuinemergeable: falseinto"null", because jq's//treatsfalseas an empty value:So a conflicted PR was indistinguishable from un-computed metadata, and burned the full ~30s retry budget re-polling a value that was already definitive. The filter now tests for null explicitly. Both halves are pinned by regression tests that fail against the old filter and pass with the fix:
Tests
enable-auto-merge.shhad no coverage; this addsenable-auto-merge.bats(10 cases: direct-merge success without touching--auto, fallback-to-queue, both-refused escalation, already-merged, closed-unmerged, unreadable state, invalid merge method, per-method passthrough, env guards). Theghmock gains separate control of the direct and--automerges plusgh pr view --json state.make test-auto-approve-bot-prs— 61 pass, 0 fail.shellcheck,actionlintandmake check-docsclean.Compatibility
No new inputs;
auto-merge: truebehaves the same from a caller's point of view, minus the dependency on the repo setting. Existing callers onauto-merge: falseare unaffected by the merge change and only see the improved annotations. Docs regenerated viamake generate-docs.