From 66d4d825743cebcb37214fe46b73c69321da4025 Mon Sep 17 00:00:00 2001 From: Ngo Quoc Dat Date: Mon, 19 Oct 2026 04:02:39 +0700 Subject: [PATCH] docs(release): let changelog forward-ports through the train gate --- .claude/skills/release/SKILL.md | 6 +++--- RELEASING.md | 5 ++--- 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/.claude/skills/release/SKILL.md b/.claude/skills/release/SKILL.md index 145777e9dd..8987f63cce 100644 --- a/.claude/skills/release/SKILL.md +++ b/.claude/skills/release/SKILL.md @@ -26,7 +26,7 @@ Before any decision, gather: - the tags, newest first: `git -c versionsort.suffix=-beta tag -l 'v*' --sort=-v:refname | head`; - the live lines: `git ls-remote --heads origin 'release/*'`; - open regressions: `gh issue list --label regression --state open`; -- the newest beta's age, `gh release view v.0-beta. --json publishedAt -q .publishedAt`, and the code on the line after it, `git log --oneline v.0-beta...origin/release/ -- . ':!changelog.d'`; +- the newest beta's age, `gh release view v.0-beta. --json publishedAt -q .publishedAt`, and the code on the line after it, `git log --oneline v.0-beta...origin/release/ -- . ':!changelog.d' ':!CHANGELOG.md'`; - open Dependabot alerts: `gh api --paginate 'repos/TableProApp/TablePro/dependabot/alerts?state=open&per_page=100' -q '.[].security_advisory.summary'`; - main's push runs: `gh run list --branch main --event push --limit 10`, with macOS Tests, iOS and Package Tests and Release Build green on the commit you would cut; - whether `main` has the last stable's `## [X.Y.Z]` heading. If not, the forward-port is missing and the next tag will refuse to build: do that first (section 9). @@ -35,7 +35,7 @@ Before any decision, gather: The days, the gate and the patch bar live in `RELEASING.md`, Schedule. -- **Promote to X.Y.0**: Monday, when the gate passes: the line's age, the newest beta's age and nothing but fragments after it (section 2), no open `regression` issue, and the storage check (section 4). +- **Promote to X.Y.0**: Monday, when the gate passes: the line's age, the newest beta's age and nothing but changelog changes after it (section 2), no open `regression` issue, and the storage check (section 4). - **beta.1 of X.(Y+1)**: the same Monday, after X.Y.0's forward-port merges (section 9). The tag refuses to build until `main` has `## [X.Y.0]`. - **beta.N**: Tuesday to Thursday, when the line has picks since its last beta. - **Patch X.Y.Z**: Tuesday to Thursday, when the stable line has a fix past the patch bar. @@ -56,7 +56,7 @@ What counts as critical: `RELEASING.md`, Channels. Name the fix and the reason, ## 6. Backport candidates - Candidates: merged `main` PRs labeled `backport release/`, plus `fix` PRs for a bug the line has. -- Never a `feat` or a PluginKit bump (`RELEASING.md`, Plugins). On the stable line, only a fix past the patch bar (`RELEASING.md`, Schedule). A closed line takes no picks (`RELEASING.md`, Branches). +- Never a `feat` or a PluginKit bump (`.claude/rules/plugin-system.md`, ABI). On the stable line, only a fix past the patch bar (`RELEASING.md`, Schedule). A closed line takes no picks (`RELEASING.md`, Branches). - Already picked: `gh pr list --base release/ --state merged --limit 200`. A pick's title keeps the original subject and its ` (#N)`. - One fix per pick PR, from `backport/-`. A conflict that needs more than a mechanical resolution goes back to the maintainer. diff --git a/RELEASING.md b/RELEASING.md index 0c20d8c3c2..b1006555a1 100644 --- a/RELEASING.md +++ b/RELEASING.md @@ -32,7 +32,7 @@ This runbook covers the macOS app, its registry plugins and the static libraries Tags go out between 13:00 and 15:00 ICT (UTC+7). - Monday, the train: promote the open line's newest beta to `vX.Y.0` when the gate passes, forward-port it, then cut `release/X.(Y+1)` from the newest green `main` commit and tag its beta.1. The forward-port merges first: `version.py` refuses beta.1 of X.(Y+1) until `main` has `## [X.Y.0]`. -- The gate: the line is 7 days old; its newest beta is at least 72 h old and nothing but changelog fragments landed on the line after it; no open issue is labeled `regression`; the storage check passes (`.claude/skills/release/SKILL.md`, section 4). +- The gate: the line is 7 days old; its newest beta is at least 72 h old and nothing outside `CHANGELOG.md` and `changelog.d/` landed on the line after it; no open issue is labeled `regression`; the storage check passes (`.claude/skills/release/SKILL.md`, section 4). - When the gate fails, nothing is promoted or cut. Fix on `main`, pick it, and ship beta.N+1. Promote it on the first Tuesday to Thursday when it is 48 h old with no open `regression` issue, and cut the next beta.1 the same day. That line's train is the first Monday it is 7 days old. - Tuesday to Thursday: a beta.N when the line has picks, at most one a day. A patch `X.Y.Z` goes straight to stable, only for a regression from the previous stable, a crash, a plugin that fails to load, a security fix or data loss. - Friday to Sunday: no tags, except a critical release or the fix for a build that fails to launch, update or connect. @@ -143,8 +143,7 @@ gh workflow run withdraw.yml --ref v -f version=X.Y.Z - Retention per channel, kit and `minimumSystemVersion`: the two highest builds stay; a beta goes once a stable with the same key has a higher build; a kit below `retainFromPluginKit` goes. A release pruned on arrival is a logged no-op. - `retainFromPluginKit` is the kit of the oldest app version still on at least 1% of the machines seen in the last 30 days (license dashboard, App Versions). Check it before each stable and raise it with a normal PR. The manifest keeps the higher of its own value and the tag's, so an older line never lowers it. - Accepted risks: the manifest is trusted through HTTPS, the plugin's Team ID check and the sha256, so a rollback or freeze of the manifest goes undetected. -- A `TABLEPRO_PLUGINKIT_VERSION` bump enters a line only at beta.1, never through a pick or a patch. -- PluginKit ABI rules: `.claude/rules/plugin-system.md`, ABI. +- PluginKit ABI rules and when the kit version moves: `.claude/rules/plugin-system.md`, ABI. ## Static libraries