Skip to content

chore(release): add the release-branch script so ui stops doing this by hand - #359

Merged
0xmanhnv merged 1 commit into
developfrom
chore/release-branch-script
Aug 4, 2026
Merged

chore(release): add the release-branch script so ui stops doing this by hand#359
0xmanhnv merged 1 commit into
developfrom
chore/release-branch-script

Conversation

@0xmanhnv

@0xmanhnv 0xmanhnv commented Aug 4, 2026

Copy link
Copy Markdown
Contributor

api has had scripts/release-branch.sh since api#406. ui did not — so cutting v0.5.0 here meant reproducing the merge -s ours pattern by hand and hoping the preconditions had been checked.

They are not the kind of thing to check from memory. -s ours discards mains side entirely. If anyone has ever hotfixed main directly, that one check is all that stands between the fix and oblivion.

Why this pattern exists

Releases here are squash-merged, so mains HEAD ends up with a single parent and git cannot see that develop already contains it. The next release then reports dozens of conflicting files that are not disagreements at all — 27 of them the first time.

Merging main back into develop is the textbook answer and does not stick: the following release squashes again and the ancestry breaks again. It has broken four times across the two repos.

So the branch carries its own ancestry instead: develops tree byte-for-byte, plus one merge -s ours commit recording main as a parent. It merges cleanly whichever button anyone presses.

Guards — verified, not asserted

any file in main but not develop refuse, and list them
origin/release/<version> already exists refuse — never force-pushes
after the merge: tree identical to develop? main actually an ancestor? refuse if either is false

The last one matters most: it checks the outcome instead of trusting that the merge did what it was asked. Reporting success from an assumption is how ancestry problems stay invisible until the next release.

Verified in this repo before committing

  • Refusal path — against the existing origin/release/v0.5.0: prints REFUSING: origin/release/v0.5.0 already exists, exit code 1 (measured without a pipe masking it).
  • Happy path — a full build on a throwaway version: tree identical to develop: yes, main recorded as an ancestor: yes, files in main absent from develop: 0. Throwaway branch deleted, never pushed.

Copied verbatim rather than adapted — the script is pure git with nothing api-specific in it, so identical copies also mean the two repos cannot drift apart on the one procedure that has already failed four times.

…by hand

api has had scripts/release-branch.sh since api#406; ui did not, so cutting
v0.5.0 here meant reproducing the `merge -s ours` pattern by hand and hoping
the preconditions were checked. They are not the kind of thing to check by
memory: `-s ours` discards main's side entirely, and if anyone has ever
hotfixed main directly, that check is the only thing standing between the fix
and oblivion.

The script is repo-agnostic — pure git, nothing api-specific — so it is copied
verbatim rather than adapted, which also means the two repos cannot drift.

What it does, and why the pattern exists at all: releases here are
squash-merged, so main's HEAD ends up with a single parent and git cannot see
that develop already contains it. The next release then reports dozens of
conflicting files that are not disagreements — 27 the first time. Merging main
back into develop is the textbook answer and does not stick, because the
following release squashes again. It has broken four times across the two
repos. So the branch carries its own ancestry instead: develop's tree
byte-for-byte, plus one `merge -s ours` commit recording main as a parent.

Three guards, all verified rather than asserted:
  - refuses if any file exists in main but not in develop
  - refuses if origin/release/<version> already exists (never force-pushes)
  - after merging, checks the tree really is identical to develop and that main
    really is an ancestor, and refuses to report success otherwise

Both paths exercised in this repo before committing: the refusal on the
existing origin/release/v0.5.0 (exit 1, measured without a pipe masking it),
and a full build on a throwaway version, which reported tree-identical,
main-is-an-ancestor, 0 files only in main.
@0xmanhnv
0xmanhnv merged commit 55a987d into develop Aug 4, 2026
13 checks 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