Release cut mechanics — customization-branch squash-merge, changelog, tags, ruleset
The durable, reusable-across-partners git/GitHub mechanics for cutting a partner release on the vuer repos: how a devel-update PR actually lands on customization/<partner>, how the changelog is committed, how the source tag is created, and how the vuer-release build is triggered. Live-verified end-to-end by executing the NÚSZ 1.9.11.48 cut on 2026-08-25. This note is the customization/<partner> half; the vuer-release autobuild → Harbor half is vuer-release-cut-recipe.
For Agents
A partner release cut is FOUR distinct git operations across TWO repo families:
- Land the devel-update onto
customization/<partner>invuer_oss+vuer_css— via SQUASH merge (NOT a preserving merge, NOT a bypass override).- Commit the changelog (
customization/RELEASE.MD) directly tocustomization/<partner>— no PR needed, direct compliant commit.- Create the source tags
<partner>-<version>on both repos at the changelog commit — via API. Source tags do NOT trigger a build.- Cut vuer-release — add
release/<N>/release.json, tag<partner>@<N>→ fires Harbor autobuild. See vuer-release-cut-recipe.The ruleset facts below were read directly from the
vuer_ossGitHub rulesets on 2026-08-25 and correct the older “team override-merges partner PRs” belief.
The big correction — devel-update PRs land by SQUASH, not by bypass override
The prior belief (“the team override-merges partner PRs” / “merge commits never satisfy the ruleset, so they bypass it”) was imprecise. The real mechanism is a squash merge. Verified by reading the vuer_oss rulesets and recent customization/nusz history.
The four vuer_oss rulesets (all bypass_actors: NONE)
vuer_oss has 4 branch/tag rulesets. Every one has bypass_actors: NONE — literally nobody, org admins included, can bypass them. Anything with --admin bypasses failing status checks, never these rulesets.
| # | Ruleset | Enforces | Pattern | Applies to |
|---|---|---|---|---|
| 1 | Merge commit rules | commit message (per-commit) | ^(build|chore|ci|docs|feat|fix|perf|refactor|revert|style|test)(!)?(\([^)]+\))?: \[[a-z]+-\d+\] .{1,100}(\n[\s\S]*)?$ — bracketed lowercase ticket required | refs/heads/customization/** + refs/heads/devel |
| 2 | Feature commit rules | commit message (per-commit) | same conventional prefix but no bracket: …: [^\n]{1,100} | ~ALL |
| 3 | Custom branch rules | new branch name | ^(feature|feat|chore|fix|release)/(FKITDEV|FKQA)-\d+(-.+)?$ | ~ALL |
| 4 | Custom tag rules | tag name | ^.*-\d+\.\d+\.\d+\.\d+(-rc-\d+)?$ | ~ALL |
Why a preserving --merge can never pass on customization/**
A preserving merge of a devel-update PR drags every devel commit (which have bracket-less feat: … subjects) onto customization/**. Ruleset #1 (“Merge commit rules”) is enforced per-commit with no bypass, and those devel commits fail its bracketed-ticket pattern. So merge-commit style is structurally impossible for a devel-update PR into customization/<partner>.
The working path = SQUASH
gh pr merge <n> -R TechTeamer/vuer_oss --squash --admin- Squash collapses the whole PR to one commit whose message = the PR title (GitHub appends
(#N)). Only that single subject is checked against ruleset #1. - Therefore the PR title MUST be ruleset-compliant BEFORE merging:
chore: [fkitdev-9217] nusz devel update(conventional prefix + bracketed lowercase ticket). - Confirmed by history: recent
customization/nuszcommits are allparents:1squashes, e.g.fix: [fkitdev-9150]: … (#8095). - Fix the title first (always pass
-R):gh pr edit <n> -R TechTeamer/vuer_oss --title "chore: [fkitdev-9217] nusz devel update"
--adminskips RED CHECKS, not the ruleset
--adminbypasses only the failing status checks (Audit / Unused Dependencies / Unit Tests — the chronic inherited gates). It does NOT bypass the commit-message ruleset (bypass_actors: NONE). The override needs BOTH: a compliant title (satisfies ruleset #1) and--admin(skips the red checks).
Claude Code auto-mode classifier blocks
--adminmerges
gh pr merge … --adminis blocked by the auto-mode safety classifier (admin/bypass = high-stakes) — the USER must run it (via the!prefix) or approve it. Regulargh apiwrites are not blocked:gh api -X PUT …/contents/…(changelog commit) andgh api -X POST …/git/refs(tag creation) went through fine.
Changelog = direct compliant commit (no PR)
customization/<partner> has NO require-PR rule — only the commit-message pattern (ruleset #1). So the changelog lands as a direct commit on the branch, via API:
gh api -X PUT repos/TechTeamer/vuer_oss/contents/customization/RELEASE.MD \
-f message="chore: [assnusz-126] 1.9.11.48 changelog" \
-f branch="customization/nusz" \
-f sha="<current-blob-sha>" \
-f content="<base64>"- Message
chore: [assnusz-126] 1.9.11.48 changelog— bracketed lowercase ticket → satisfies ruleset #1. ossandcssRELEASE.MD are SEPARATE files with different per-repo entries. For .48: oss listed ASSNUSZ-76/117 + “általános rendszerfrissítés”; css listed only “általános rendszerfrissítés (devel szinkronizáció)“. Do not copy one into the other.- Determine the real per-repo delta before writing the entry:
gh api repos/TechTeamer/vuer_oss/compare/nusz-1.9.11.47...customization/nusz
Source tags via API
gh api -X POST repos/TechTeamer/vuer_oss/git/refs \
-f ref="refs/tags/nusz-1.9.11.48" \
-f sha="<changelog-commit-sha>"- Tag name
nusz-1.9.11.48satisfies ruleset #4 (^.*-\d+\.\d+\.\d+\.\d+…$). - Point the tag at the changelog commit on
customization/<partner>. - Source tags do NOT trigger a build. Only the
<partner>@<N>tag onvuer-releasefires Harbor autobuild.
vuer-release cut (build trigger) — quick facts
Full recipe: vuer-release-cut-recipe. Durable facts confirmed on the .48 cut:
- Default branch is
master(NOTmain— a 404 onmainwastes an API call). - Copy
projects/nusz/release/16/release.json→release/17/, then bump:RELEASE_VERSION16→17 (top-level AND insideDEFAULT_ARGS)- both
COMPONENT_LISTentries:VERSION→1.9.11.48,TAG→nusz-1.9.11.48 - unchanged:
BUILD_NUMBERstays"1",NODE_VERSION22,BUNDLE_IMAGEfalse, janusJANUS_VERSION_COMMITcc0fdca8…
- Commit it, then create tag
nusz@17. Confirm the next number from the remote:git ls-remote --tags … 'nusz@*'(@16 was highest; @8 was skipped historically — do not reuse skipped numbers). - The
nusz@<N>tag is the Harbor build trigger: workflow “VUER - Autobuild and Publish” fires on the pushed tag + changedrelease.json, builds and pushesharbor.techteamer.com/nusz/{vuer_oss,vuer_css}:1.9.11.48. nusz@Ntag names do NOT matchvuer_oss’s tag pattern (ruleset #4). Sovuer-releasehas its own / looser tag rules — the@Nconvention is only valid onvuer-release.
Known inherited red on the .48 PRs (NOT a regression)
- oss Unit Tests failed on the .48 PR:
test/tests/unit/translations.test.js→ “Directory not found: client/features” (hardcoded scan path vs the current devel structure). This is a known inherited failure — hence--admin. - css passed unit tests. The oss failure is the pre-existing one above, not something the devel-update introduced.
Worked example — NÚSZ 1.9.11.48 (executed 2026-08-25)
The .48 cut was run end-to-end today:
| Step | vuer_oss | vuer_css |
|---|---|---|
| devel-update PR squash-merged | e01bf599 | f8511f79 |
| changelog direct commit | c8c5f7e7 | 08fc5380 |
source tag nusz-1.9.11.48 at | (changelog commit) | (changelog commit) |
vuer-release release/17/release.json | commit 3bd20ec7 | — |
| build trigger tag | nusz@17 pushed | — |
Build running at time of writing. Release ticket ASSNUSZ-126, prep ticket FKITDEV-9217. Test runbook: nusz-1.9.11.48-test-runbook.
Related
vuer-release-cut-recipe · techteamer-commit-message-ruleset · nusz-1.9.11.48-test-runbook · nusz-1.9.11.47 · release-automation-design · release-pipeline-automation-spec