ci: open a pull request for a clean backport instead of pushing it - #8626
Conversation
Direct Backport Push cherry-picks a cleanly-applying fix onto the release branch and pushes it. Every one of those pushes has been rejected since 2026-07-24 -- release/* is covered by the Merge Queue ruleset, which requires a pull request for everyone -- and ASF policy asks for prior Infrastructure authorization before an automated service writes a branch subject to official release. apache#8379 tried to exempt the Actions app from the ruleset; GitHub refuses to create that bypass, so the fast path has never once worked since it broke. Both outcomes now open a pull request. The conflicted one is unchanged: a draft, assigned to its author. A clean one opens ready for review, assigned to nobody, because there is no code for anyone to write on it. What a clean backport still needs is its checks started. GitHub creates no workflow run for anything GITHUB_TOKEN does, so a bot-opened pull request has none, and nothing will arrive on its own: with no run there is no re-run, and none of the three required workflows listens for ready_for_review. Reopening the pull request, or pushing to its branch, is what emits an event they subscribe to -- so the PR says exactly that, in the comment the conflict path already uses for its instructions. That leaves the release manager with three ordinary buttons: reopen, approve, and auto-merge if they would rather not come back for the checks. Nothing here depends on a token's pull-request scope, on an Actions bypass, or on a close/reopen the workflow performs itself -- the paths that can only be proven in production, and that fail quietly when they are wrong. push_entries is now always empty, leaving push-backports unreachable. Removing it is left to a separate change, so that this one is a behaviour change and that one is a pure deletion.
Automated Reviewer SuggestionsBased on the
|
There was a problem hiding this comment.
Copilot review overview
🟡 Changes recommended
Reruns can preserve an incorrect PR state, release-manager notifications have an uncovered edge case, and related documentation is stale.
Get a fresh assessment by requesting another Copilot review.
Review effort: Balanced
Findings: 2
Open (3)
What changed in this PR
Routes clean backports through reviewable pull requests instead of blocked direct pushes to protected release branches.
Changes:
- Routes all backport outcomes to PR creation.
- Opens clean backports ready for review; keeps conflicted ones as drafts.
- Adds serialized processing and instructions for manually triggering CI.
| File | Description |
|---|---|
.github/workflows/direct-backport-push.yml |
Implements PR-based clean backports and updated status messaging. |
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## main #8626 +/- ##
============================================
- Coverage 92.80% 92.79% -0.02%
+ Complexity 4898 4895 -3
============================================
Files 1239 1239
Lines 52252 52252
Branches 6425 6425
============================================
- Hits 48492 48486 -6
- Misses 2183 2186 +3
- Partials 1577 1580 +3
☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
|
| config | throughput | MB/s | latency | max Δ latest / 7d | |
|---|---|---|---|---|---|
| 🔴 | bs=10 sw=10 sl=64 | 542 | 0.331 | 17,787/25,043/25,043 us | 🔴 -5.9% / 🔴 +60.8% |
| 🟢 | bs=100 sw=10 sl=64 | 1,204 | 0.735 | 83,107/95,547/95,547 us | 🟢 -24.3% / 🟢 +21.3% |
| ⚪ | bs=1000 sw=10 sl=64 | 1,395 | 0.851 | 714,665/785,285/785,285 us | ⚪ within ±5% / 🟢 +36.4% |
Baseline details
Latest main 279e12b from same runner
| config | metric | PR | latest main | 7d avg | Δ latest | Δ 7d |
|---|---|---|---|---|---|---|
| bs=10 sw=10 sl=64 | throughput | 542 tuples/sec | 576 tuples/sec | 775.4 tuples/sec | -5.9% | -30.1% |
| bs=10 sw=10 sl=64 | MB/s | 0.331 MB/s | 0.351 MB/s | 0.473 MB/s | -5.7% | -30.1% |
| bs=10 sw=10 sl=64 | p50 | 17,787 us | 16,952 us | 12,716 us | +4.9% | +39.9% |
| bs=10 sw=10 sl=64 | p95 | 25,043 us | 24,663 us | 15,572 us | +1.5% | +60.8% |
| bs=10 sw=10 sl=64 | p99 | 25,043 us | 24,663 us | 19,527 us | +1.5% | +28.2% |
| bs=100 sw=10 sl=64 | throughput | 1,204 tuples/sec | 1,161 tuples/sec | 992.44 tuples/sec | +3.7% | +21.3% |
| bs=100 sw=10 sl=64 | MB/s | 0.735 MB/s | 0.708 MB/s | 0.606 MB/s | +3.8% | +21.3% |
| bs=100 sw=10 sl=64 | p50 | 83,107 us | 81,473 us | 102,140 us | +2.0% | -18.6% |
| bs=100 sw=10 sl=64 | p95 | 95,547 us | 126,289 us | 108,282 us | -24.3% | -11.8% |
| bs=100 sw=10 sl=64 | p99 | 95,547 us | 126,289 us | 118,936 us | -24.3% | -19.7% |
| bs=1000 sw=10 sl=64 | throughput | 1,395 tuples/sec | 1,432 tuples/sec | 1,023 tuples/sec | -2.6% | +36.4% |
| bs=1000 sw=10 sl=64 | MB/s | 0.851 MB/s | 0.874 MB/s | 0.624 MB/s | -2.6% | +36.3% |
| bs=1000 sw=10 sl=64 | p50 | 714,665 us | 696,656 us | 998,263 us | +2.6% | -28.4% |
| bs=1000 sw=10 sl=64 | p95 | 785,285 us | 759,955 us | 1,036,365 us | +3.3% | -24.2% |
| bs=1000 sw=10 sl=64 | p99 | 785,285 us | 759,955 us | 1,064,941 us | +3.3% | -26.3% |
Raw CSV
config_idx,batch_size,schema_width,string_len,num_batches,total_ms,total_tuples,total_bytes,tuples_per_sec,mb_per_sec,lat_p50_us,lat_p95_us,lat_p99_us
0,10,10,64,20,368.90,200,128000,542,0.331,17787.33,25042.73,25042.73
1,100,10,64,20,1661.75,2000,1280000,1204,0.735,83106.95,95546.56,95546.56
2,1000,10,64,20,14336.45,20000,12800000,1395,0.851,714664.77,785285.38,785285.38Three findings from the review, all of them real. A re-run force-pushes a fresh cherry-pick onto the release branch as it stands then, which may have moved; the open pull request was left alone, so a tree that now conflicts could keep sitting there ready for review under a comment saying nothing in it was edited by hand. Rewriting the PR from the workflow would overwrite whatever a human has done to it since, so it now says so on the PR, reds the backport status and fails the job. A clean backport has no assignee, and the review request was still guarded by MANAGER !== author -- a guard that made sense when the author owned the PR. This one is owned by github-actions[bot], so a fix written by the branch's own release manager notified nobody at all. The manager is now requested on every clean backport. The three places that still described the fast path -- the entries comment here, release-branches.yml and create-backport-branch.sh's header -- say what happens now.
There was a problem hiding this comment.
Copilot review overview
🟡 Changes recommended
Successful backports retain a stale failure status, and remaining workflow messaging still describes direct pushes.
Get a fresh assessment by requesting another Copilot review.
Review effort: Balanced
Findings: 1
Open (2)
backport-publish.yml's clean summary is what a contributor reads on their own PR, and it promised a cherry-pick straight to the release branch. backport-checks.yml's header described the same split. The comment on the backport commit status claimed the merge into the release branch is what turns it green. Nothing does: the status is never updated after it is written, which is why apache#8562's v1.2 status still names the draft apache#8585 that merged on 2026-09-19. The comment now says that, and where the fix belongs.


What changes were proposed in this PR?
Direct Backport Pushcherry-picks a cleanly-applying fix onto the release branch and pushes it. Every one of those pushes has been rejected since 2026-07-24:release/*is covered by the Merge Queue ruleset, which requires a pull request of everyone. #8379 tried to exempt the Actions app from it; GitHub refuses to create that bypass, and #8624 reverts it. ASF policy points the same way — an automated service must not push to a branch subject to official release without prior authorization from Infrastructure.Both outcomes now open a pull request. The conflicted one is unchanged: a draft, assigned to its author. A clean one opens ready for review and assigned to nobody, because there is no code for anyone to write on it.
What a clean backport still needs is its checks started, and that is the part worth stating plainly. GitHub creates no workflow run for anything
GITHUB_TOKENdoes, so a bot-opened pull request has none — and nothing will arrive on its own:synchronize)reopened)ready_for_reviewRequired ChecksA conflicted backport never had this problem: its author pushes a resolution, and that push brings CI with it. A clean one has nobody to push anything. So the comment the conflict path already posts for its instructions now says, for a clean backport, the one action that works — and says that marking it ready for review is not it.
That leaves the release manager three ordinary buttons: reopen, approve, and auto-merge if they would rather not come back when the checks finish. The approval is not automated and should not be: the
release/*label on the original PR records the decision, and this is the look at the tree that actually lands.Nothing here depends on a token's pull-request scope, on an Actions bypass, or on a close/reopen the workflow performs itself. Those are the paths that can only be proven in production, and that fail quietly when they are wrong — which is how #8432, #8494 and #8562 were lost.
push_entriesis now always empty, leavingpush-backportsunreachable. Removing it is left to a separate change, so that this one is a behaviour change and that one is a pure deletion.Any related issues, documentation, discussions?
Closes #8377. #8378 proposed the same routing with the workflow performing the close/reopen itself and arming auto-merge; this drops both in favour of the release manager's own click, and is closed in favour of this.
How was this PR tested?
The routing was driven locally against a stubbed
github-scriptenvironment. With the pre-merge preflight green, both targets come out as pull-request entries carryingclean: "true"andpush_entriesempty; with it neutral,clean: "false"; with no completed signal, neither target is acted on, as before. Restoring the oldpushEntries.pushturns that check red, so it is not vacuous. The workflow parses, and all four inlinegithub-scriptbodies passnode --check.That a bot-opened pull request starts with no checks is what this repository already shows: #8584 — bot-opened, one commit, nobody pushed to it — carries no check runs at all, while #8553, opened the same way, has the full set after a commit was pushed. That
ready_for_reviewdoes not start them is in the triggers:required-checks.ymllistsopened/reopened/synchronize/labeled/unlabeled,check-header.ymltakes the barepull_request:defaults, andlint-pr.ymllistsopened/edited/reopened/synchronize.Not provable before merge: that a human reopen produces the three contexts on a backport PR. #8619 to #8623 — five backports into
release/v1.3opened by hand this week — show that the contexts do appear and pass on a pull request into a release branch; the reopen path shares everything with them but the event that starts the run.Was this PR authored or co-authored using generative AI tooling?
Yes. Generated-by: Claude Code (claude-opus-5)