Skip to content

fix(ci): guard series-branch mirrors before merge-upstream, not after - #13

Merged
dnplkndll merged 1 commit into
mainfrom
fix/series-branch-mirror-guard
Jul 16, 2026
Merged

fix(ci): guard series-branch mirrors before merge-upstream, not after#13
dnplkndll merged 1 commit into
mainfrom
fix/series-branch-mirror-guard

Conversation

@dnplkndll

Copy link
Copy Markdown
Contributor

What changed

The nightly fork sync was quietly destroying the one property series branches are supposed to have: being exact copies of upstream. 14 OCA series branches had accumulated ~140 Merge branch 'OCA:18.0' into 18.0 commits, and every digest reported them as healthy.

Why it happened

Two mechanisms compounding:

  1. The seed. install_forward_port used to be true. The distributor pushed .github/workflows/forward-port.yml onto each fork's series branch as a real commit. The flag was later flipped to false everywhere — but the distributor only ever adds (opted_in = [f for f in forks if f.get("install_forward_port")]). The file was stranded.

  2. The ratchet. A branch with a commit upstream doesn't have can never be fast-forwarded, so GitHub's merge-upstream API mints a merge commit instead — and returns 200 either way. That merge commit leaves the branch ahead, so the next night's run mints another. sale-workflow@18.0 reached 26.

And it stayed invisible because MANAGED_COMMIT_PATTERNS whitelisted ^Merge branch '...' into , so each merge commit the tool itself produced was classified as an expected structural overlay. The mechanism laundered its own damage.

The fix

  • Check before merging, not after. The compare now runs first; a mirror branch that is ahead is reported and left alone. Merging it would only bury the drift under another merge commit. Post-hoc detection could only ever document the damage — this prevents it.
  • Drop the merge-commit whitelist. A merge commit on a series branch is always a bug, so it must always be reportable.
  • Non-OCA forks are unaffected. sentry@master legitimately carries customizations (upstream_org: null), and merging upstream into it is the correct primitive — those take no guard and no compare call.

Verified

  • 42/42 tests pass. The suite previously enshrined the bug (test_chore_plus_sync_merge_is_managed_not_diverged asserted merge commits were fine); that test is replaced by test_merge_commit_is_no_longer_whitelisted and test_ahead_branch_is_never_merged.
  • Exercised live against real repos: social@18.0 (still 11 ahead) is refused with merge_type=None and no POST — under the old code this call would have created merge commit ci(forks): opt OpenUpgrade into nightly feature-branch rebasing #11. web@18.0 (freshly reset) syncs normally and stays ahead=0 behind=0.

Branch cleanup done separately

13 of the 14 branches were reset to their upstream tips and are now byte-identical mirrors. Nothing was lost — all were behind_by=0, and the entire content delta vs upstream was the dead forward-port.yml. No open PR carried the file.

social@18.0 is still ahead by 11 — its force-push is blocked by branch protection (allow_force_pushes: false) and I did not touch that setting. It needs a decision.

https://claude.ai/code/session_014td9mfVrkca9eeCR7SMpAb

merge-upstream cannot fast-forward a branch that is ahead of upstream,
so it silently mints a merge commit and returns 200 anyway. That leaves
the branch ahead forever, so the next run mints another. One orphaned
forward-port.yml commit (install_forward_port was flipped to false, but
the distributor only ever adds, never removes) seeded ~140 merge commits
across 14 OCA series branches.

The post-hoc divergence check could not catch it: MANAGED_COMMIT_PATTERNS
whitelisted /^Merge branch '...' into /, so every merge commit the tool
produced was classified as an expected structural overlay. The mechanism
laundered its own damage and the digest reported the branches as healthy.

- Run the compare BEFORE merge-upstream and refuse to merge a mirror
  branch that is ahead. Reporting after the fact only documents the
  damage; checking first prevents it.
- Drop the merge-commit whitelist. A merge commit on a series branch is
  always a bug, so it must always be reportable.
- Non-OCA forks (upstream_org: null) are unaffected — sentry/master
  legitimately carries customizations, and merging upstream into it is
  the correct primitive.

The 14 affected branches were reset to their upstream tips separately;
nothing was lost (all were behind_by=0, and the only content delta was
the dead forward-port.yml).

Claude-Session: https://claude.ai/code/session_014td9mfVrkca9eeCR7SMpAb
@dnplkndll
dnplkndll merged commit dff2ef9 into main Jul 16, 2026
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant