storebound/skills/release-management/SKILL.md

83 lines
6.8 KiB
Markdown

---
name: release-management
description: Ship updates safely after the first release - App Store phased release (on, pause, resume, complete) with manual release by default, Google Play staged rollout (fraction, halt, resume, complete), waiting for review, picking build numbers, pulling live store texts back into the listing files, and what to do when a release goes wrong (pausing is not a rollback). Use when the user releases an update, wants a gradual rollout, needs to stop a bad release, or asks how long review takes.
---
# Release management (updates on both stores)
CLI: `storebound` (on PATH as a plugin; or `bunx storebound` / `bun <toolchain>/cli/index.ts`). Rules: the owner
presses release; you prepare, dry-run and report. `storebound mcp` deliberately offers only "phased on" and "pause".
## Where each version stands (release trains)
- `storebound release status` (MCP `release_status`, read-only): per app, both stores on one train per version:
build > testing > review > live > rollout (with the rollout %), the version that reaches users and the next one;
`--versions` lists every version the stores know. The same stages as the desktop's Releases tab.
- `storebound release plan 1.3.0` (MCP `release_plan`, read-only): what is left for that version on each store, in
fix order: config problems (`check`), the version on the store, store blockers (`validate`), the next move, warnings.
Owner steps (submit, release, raise / complete a rollout) are named with where the owner does them; you never run
them. "could not be read" means unknown, not "not there": fix the credentials first.
- Many apps (a `storebound.workspace.json` above the app folders): the same commands cover every app, or `--app a,b`.
`storebound ws status` is the portfolio table across apps and stores.
## Defaults
- **App Store**: release type **manual** (storebound sets `MANUAL` on every version it touches) and **phased release
on**. Never choose "reset ratings" when releasing an update (storebound never sets it); only an owner who really
wants the rating summary wiped does that in the UI.
- **Play**: production updates as a **staged rollout** starting at 5-10 %.
## App Store
1. Build numbers: `storebound apple next-build` before archiving, then attach exactly that build:
`storebound apple listing --version 1.3.0 --build <that number>`. Never pick "the latest build": a CI or a
teammate may have uploaded another one meanwhile.
2. `storebound apple release --phased on --dry`, then without `--dry` (works while the version is being prepared).
With versions on more than one App Store platform add `--platform ios|macos|tvos|visionos` (pitfall 79).
3. Submit (owner, UI). Wait: `storebound apple status --wait-review` (polls with backoff, exit 0 approved, 1 rejected,
7 timeout; `--timeout 72h`). Rejected: `review-rejections` skill.
4. Approved = PENDING_DEVELOPER_RELEASE. Owner releases: `storebound apple release --manual-release` (asks to confirm)
or the "Release This Version" button. With phased release on, automatic updates reach 1 %, 2 %, 5 %, 10 %, 20 %,
50 %, 100 % over 7 days; anyone can still update manually from the store.
5. During the rollout watch crashes / reviews. Problem: `storebound apple release --phased pause` (up to 30 days in
total). Pausing stops automatic updates only; it is **not a rollback**: users who updated keep the build, and new
users still get the new version. The fix is a new build (expedited review is possible for critical bugs).
6. All good early: `storebound apple release --phased resume` / `--phased complete` (owner; asks to confirm).
## Google Play
1. `storebound play next-version-code` before building; the versionCode must be higher than every uploaded one.
2. Upload and start the rollout (owner confirms): `storebound play release app.aab --production inProgress --fraction 0.05`.
Draft apps cannot do this until the first release is reviewed (`play-first-release`).
Changes made in the Console (listing, App content) are sent from Publishing overview > "Submit N changes for
review". While a review is running that button opens "Do you want to restart your review?" with **Restart
review**: the running review starts over with the new changes. The owner's button, never the agent's; to keep the
running review, Cancel and send the changes after it is done.
3. Increase: `storebound play rollout --fraction 0.2` (then 0.5, ...). Play never lowers a fraction.
4. Problem: `storebound play rollout --halt` (no confirmation needed; stops new installs of the update). Like Apple's
pause it is **not a rollback**: updated users keep it. Ship a fixed build with a higher versionCode; resume with
`--resume [--fraction x]` only if the halted build is fine after all.
5. Done: `storebound play rollout --complete` (100 %). Before each increase, `storebound health --play` (store-health
skill): crash / ANR rates near Play's thresholds are a reason to halt, not to widen.
6. Every rollout command runs in an edit: a Console save at the same time makes it retry once.
## Review wait
- Apple: most reviews finish within a day or two; holidays and big OS launches are slower. Expedited review is for
critical fixes, not deadlines.
- Play: updates usually take hours to a few days; new apps and policy-sensitive changes longer.
- Do not resubmit or cancel to "jump the queue": it puts you at the back.
## Release notes
`whats-new` skill (`storebound whats-new`, `--languages` for one file per language), then `apple listing` /
`play release` push them.
## Someone edited the listing in the console
Before pushing local texts over a console edit, pull the live ones and read the diff:
- `storebound apple listing pull [--version x.y.z]` (name, subtitle, description, keywords, promotional text, what's
new per locale) and `storebound play listing pull` (title, short and full description; one throwaway edit, deleted).
Both print the diff against `store/appstore.md` / `store/listing.md` and write only with `--write` (MCP:
`apple_listing_pull` / `play_listing_pull` with dry_run false). New locales are appended as sections; a Play section
shared by several codes is only changed when the store has the same text for all of them.
- An app that was live before storebound: `storebound onboard` (then `--write`) imports the live products and
subscriptions with their USD / base prices, contact values, the App Review contact and demo account, sign-in for
review and the account deletion page; then `storebound catalog diff` is clean. Ask the owner only the questions it
lists at the end.
- `storebound catalog pull [--write]`: IAP and subscription titles / descriptions (Play: benefits) against the config.
`storebound.config.ts` is never rewritten: `--write` saves `.storebound/pull/catalog.json` as a proposal; merge the
listings into the config yourself (the agent), then `storebound check`.