--- name: release-app description: Use to cut a release of ApkAnalyzer — pick the MAJOR.MINOR.PATCH version, draft release notes, get them approved, and create the annotated tag that drives the release pipeline. Triggered by phrases like "release the app", "cut a release", "ship 3.6.0", "tag a release", "make a new version", "release notes for the next version", "publish to the Play Store", "promote the release to production". --- # Skill: Cut a Release The tag is the entire release input. It supplies the version name, the version code, and the release notes, so **the tag must be annotated and its annotation must never be empty** — [`release.yml`](../../../.github/workflows/release.yml) fails its first job on a lightweight tag, and a tag that already reached GitHub is painful to replace. Nothing in the repository records the version. `gradle.properties` stays at `version.name=dev`; there is no version-bump commit to make. ## Step 1 — Pick the version The tag is exactly `MAJOR.MINOR.PATCH` — three numbers, no `v` prefix, no suffix. Anything else does not match the workflow trigger and silently releases nothing. ```bash git fetch --tags git tag --sort=-v:refname | head -5 ``` Propose the next version from the change set and let the user correct it: patch for fixes only, minor for new user-visible behaviour, major for a break in how the app is used. `versionCode` is derived as `MAJOR * 10000 + MINOR * 100 + PATCH`, so the new tag must sort above the last one under that formula — Play rejects a lower code. ## Step 2 — Confirm what is being released ```bash git status --short git log --oneline -5 origin/develop ``` Release from `develop` at a commit that is pushed, clean, and green in CI. If CI for that commit failed or is still running, say so and stop — the release workflow re-runs the same gates and will fail the same way after the tag is public. ## Step 3 — Draft the release notes ```bash git log --oneline ..origin/develop ``` Turn the log into notes for users of the app, not for contributors: * Follow the User-Facing Copy rules in [`AGENTS.md`](../../../AGENTS.md) — active voice, present tense, sentence case, name the concrete thing. * Group into short bullets: new features first, then improvements, then fixes. * Drop anything a user cannot observe — refactors, dependency bumps, CI and agent-context changes. * Never surface class names, module names, PR numbers, or Android API names. * Keep it short. The same text becomes the GitHub release body and is read on a phone. ## Step 4 — Get approval, always **Never create the tag from a draft the user has not approved.** Print the proposed version and the full notes verbatim as plain text in the response itself — not only inside a question tool's option text, where the user may not see it — then ask for approval or edits. Repeat until the user approves. If the user supplies their own notes, use them as given rather than rewriting them. Approving the notes also approves creating and pushing the tag from them — steps 5 and 6 follow without a separate confirmation. ## Step 5 — Create the annotated tag Write the approved notes to a scratch file outside the repository and tag from it, so multi-line notes survive intact: ```bash git tag -a 3.6.0 -F /tmp/release-notes.txt ``` Use `-a` (or `-s`). Never `git tag 3.6.0` on its own, and never an empty or placeholder `-m`. Verify before pushing — both checks must pass: ```bash git cat-file -t 3.6.0 # must print: tag git for-each-ref --format='%(contents)' refs/tags/3.6.0 # must print the approved notes ``` If either check disagrees, delete the tag locally (`git tag -d 3.6.0`) and redo this step. ## Step 6 — Push the tag Pushing starts the release. The approval gate is Step 4 (notes) and Step 5 (tag verification) — once both are done, proceed to push: ```bash git push origin 3.6.0 ``` If a bad tag was already pushed, do not force-move it. Delete it on the remote, delete the GitHub release it created, then push a corrected tag — or release the fix as the next patch version. ## Step 7 — Watch the run and promote The release run publishes to the Play **beta** track, never production. Follow it with the `analyze-ci-failure` skill if a job goes red. Production is a separate, deliberate step: the `Promote release to production` workflow, run manually with the version and a rollout percentage. It promotes whatever currently sits on beta, so check the beta track first if the release run finished a while ago. Full pipeline reference, including secrets and the promotion rules: [`ci-and-release.md`](../../../docs/engineering/ci-and-release.md).