confirm() prints 'declined: <reason>' and exits 3 whenever the answer is no or nobody can answer (not a terminal without --yes, serve without the owner's dialog), so no command reports success after declining. flow run stops at such a step with 'step N declined: <reason>' (status declined), never ok. flow run --apply --yes passes --yes to write steps only; --yes without --apply is refused. Pitfall 24.
67 lines
4.5 KiB
Markdown
67 lines
4.5 KiB
Markdown
---
|
|
name: release-flows
|
|
description: Repo-local workflows for a mobile app or game - named multi-step flows in store/workflows/*.yml (release, beta, or your own) that run storebound steps in order (next build number, build, upload, wait for processing, release notes, validate, scan, release plan) with progress, dry runs by default, resume after a failure and the owner's clicks (Submit for Review, release, rollout) listed but never executed. Use when the user wants to automate a release or beta routine, replace fastlane lanes, asks for a "one command" release, or wants to resume a failed release run.
|
|
---
|
|
|
|
# Release flows
|
|
|
|
CLI: `storebound flow list | validate | run <name> [NAME=value ...] [--dry | --apply] [--from <step> | --resume]`.
|
|
MCP: `flow_list`, `flow_run` (always the safe mode: writes as dry runs; `--apply` is a terminal command the owner runs).
|
|
|
|
## Where flows live
|
|
- `store/workflows/<name>.yml` (one flow per file, named after the file; `.yaml`, `.json` and `.ts` work too), or
|
|
- `storebound.workflows.yml|json|ts` with several flows (`flows: { release: {...}, beta: {...} }`).
|
|
- `storebound init --profile app|game` writes `release.yml` and `beta.yml` as starting points.
|
|
|
|
## A flow
|
|
```yaml
|
|
description: Build, upload and check one version on both stores
|
|
params:
|
|
VERSION: "1.0.0" # flow run release VERSION=1.2.0 overrides
|
|
steps:
|
|
- id: next-build
|
|
if: apple # apple | play | exists <path> | ${VAR} | !${VAR} | ${A} == x; && joins
|
|
run: apple next-build # a storebound command line, without "storebound"
|
|
capture: BUILD # the last stdout line becomes ${BUILD}
|
|
- id: build
|
|
run: apple build --version ${VERSION} --build-number ${BUILD}
|
|
- id: web
|
|
sh: npm run build:web # your own shell command: only runs with --apply
|
|
- id: submit
|
|
owner: "App Store Connect: Submit for Review" # never run: listed as your click
|
|
- id: beta
|
|
flow: beta # the steps of another flow (ids become beta.<id>); `private: true` hides a sub-flow
|
|
before: [] # hooks: before / after the steps, onError when a step failed
|
|
after: []
|
|
onError: []
|
|
```
|
|
`continueOnError: true` lets a step fail without stopping the flow.
|
|
A web build before the native builds (Capacitor: `npm run build && npx cap sync`) belongs in `build.prebuild` in the
|
|
config rather than an `sh:` step: `apple build` and `play build` run it themselves, and within one `flow run` it runs
|
|
once (the second build step prints "prebuild skipped (already ran in this flow run)").
|
|
|
|
## Modes
|
|
- `flow run release VERSION=1.2.0` (default): read steps (check, validate, scan, release plan, next-build, status ...)
|
|
run for real; **every write step runs with `--dry`**; wait steps check once; shell steps are skipped. Nothing
|
|
changes. Show this output to the owner.
|
|
- `--dry`: the plan only, nothing runs.
|
|
- `--apply`: writes and shell steps run for real, **only after the owner agreed in chat**; each write command still
|
|
asks its own confirmation in the terminal. Never add `--yes` to a step (flow validate refuses it).
|
|
- `--apply --yes`: the owner's approval of every write step of this run (they get `--yes`; reads, waits and owner
|
|
steps do not). Only when the owner said so in chat for this run, e.g. a background run with a log where no terminal
|
|
can answer. Without `--yes` and without a terminal, a confirming command declines: the flow stops there with
|
|
"step N declined: not a terminal and no --yes ...", never "ok" (status `declined` in `--json` and the state file).
|
|
- Owner steps never run in any mode: submit, release, phased release, rollout, sending review replies, price
|
|
imports, inviting testers, Beta App Review, starting experiments, offer codes (AGENTS.md rule 1). They print as
|
|
"YOUR CLICK" with the exact text, also when written as `run:`.
|
|
- A failed step stops the flow and names it; after the fix `storebound flow run release --resume [--apply]` starts at
|
|
that step with the captured variables of the last run (`.storebound/flows/<name>.json`). `--from <step>` starts
|
|
anywhere.
|
|
|
|
## Writing flows for the owner
|
|
1. Start from the init templates; keep one store concern per step so a resume is cheap.
|
|
2. Pick builds by the captured number (`${BUILD}`), never "the latest" (AGENTS.md rule 6).
|
|
3. Long uploads: run the flow in a terminal with a log (`storebound flow run release --apply > .storebound/flow.log 2>&1 &`)
|
|
and report the progress lines.
|
|
4. `storebound flow validate` before committing a flow: unknown commands, `${VAR}` that no param or earlier capture
|
|
sets, duplicate ids, sub-flow cycles.
|