prepare-release
GitHub用于准备软件发布,包括更新版本元数据、生成变更日志、整理新功能亮点及刷新贡献者列表。通过Git和GitHub CLI获取基线,评估PR内容以决定版本号(小版本或补丁),并同步更新构建号。
Trigger Scenarios
Install
npx skills add Apollo-Reborn/Apollo-Reborn --skill prepare-release -g -y
SKILL.md
Frontmatter
{
"name": "prepare-release",
"description": "Prepare a release by updating version metadata, drafting `CHANGELOG.md`, curating What's New highlights, and refreshing contributors. Use for release preparation, version bumps, changelogs, or release notes.",
"allowed-tools": "shell"
}
Prepare release
Step 1. Establish the baseline
grep ^Version control
git tag --list 'v1.15.11_*' --sort=-version:refname | head -5
gh release list --repo Apollo-Reborn/Apollo-Reborn --limit 10
sed -n '/^## \[Unreleased\]/,/^## \[/p' CHANGELOG.md
git log --oneline <last-release-tag>..HEAD
gh pr list --repo Apollo-Reborn/Apollo-Reborn --state open --base main --limit 100 \
--json number,title,author,url
Use the latest published, non-prerelease v1.15.11_<version> tag as the release boundary. Local plain vX.Y.Z tags may be incomplete or sort ahead of newer prefixed tags, so cross-check git tag against gh release list; fetch the published tag if it is missing locally.
Treat the existing ## [Unreleased] section as a working list, not a complete or status-accurate release manifest. Recent release PRs intentionally leave open work there while publishing merged work below it, and merged PRs are sometimes missing from it entirely.
- Release section: merged PRs and commits actually included since the previous release tag.
- Unreleased: user-facing open PRs or explicitly pending work that should remain visible for a later release.
- Omit: internal diagnostics, refactors, CI/release plumbing, documentation maintenance, and other non-user-facing work.
Inspect every PR in scope rather than relying on its title or commit subject:
gh pr view <number> --repo Apollo-Reborn/Apollo-Reborn \
--json title,body,labels,author,state,mergedAt,files
gh pr diff <number> --repo Apollo-Reborn/Apollo-Reborn
The description gives intent; the file list and diff show what shipped. Check reviews or comments only when they supply missing context. Read the latest 2–3 changelog entries before drafting so the result matches current tone and structure.
Treat user notes as authoritative scope guidance, while verifying inclusion and wording against the PR data. Confirm ambiguous pending items; never place an open PR in the release section unless its commits are already included by another route.
Step 2. Decide the version
Follow the repository's pragmatic versioning convention rather than classifying solely by whether any feature exists:
- Minor bump (
3.3.0 → 3.4.0) for a substantial feature release or a batch that materially expands the product. - Patch bump (
3.4.1 → 3.4.2) for a maintenance-sized release. Small additions such as an app icon, host support, or a narrowly scoped option can still ship in a patch release. - Read the recent release history and follow the user's intended scope. If either version is defensible, ask rather than choosing from the changelog section labels alone.
Edit control:
Version: <new>
Then bump the monotonic IPA build number in distribution/config.json:
"app": {
"buildVersion": "<previous + 1>",
...
}
This is the CFBundleVersion the release pipeline writes into the IPA and the AltStore source buildVersion. AltStore validates the source value against the downloaded IPA before installing, and it must increase monotonically across releases — never reuse or decrement. See DISTRIBUTION.md for the full versioning model.
Do not run scripts/update_source_json.py or edit apps*.json / release-manifest.json. Those files require published assets and are regenerated by the release workflows after publication.
Step 3. Draft the changelog entry
Create a new ## [vX.Y.Z] - YYYY-MM-DD section below ## [Unreleased]. Move or rewrite only the merged/included items into it:
- Leave open and pending items under
## [Unreleased]. - Remove an item from
## [Unreleased]when its PR is included in the release, so it does not appear twice. - Add missing user-facing open PRs to
## [Unreleased]when they are intentionally being tracked for a later release. - If no pending items remain, keep a fresh empty
## [Unreleased]section. - Use the intended release date. If the date is not confirmed yet, use an explicit
YYYY-MM-??placeholder rather than guessing.
Also add a new compare-link to the reference-link footer at the bottom of CHANGELOG.md, matching the existing pattern:
[vX.Y.Z]: https://github.com/Apollo-Reborn/Apollo-Reborn/compare/v1.15.11_<previous-version>...v1.15.11_X.Y.Z
Insert it as the new top entry of the footer block (entries are ordered newest-first).
Structure
## [Unreleased]
...open or pending items only...
## [vX.Y.Z] - YYYY-MM-DD
### Features
- ...
### Fixes
- ...
- Omit
### Featuresor### Fixesif empty in the released section. - Omit empty subheadings from
## [Unreleased]too; an entirely empty section can be just the heading. - For fix-only releases, a flat bullet list with no subheadings is fine (see v2.11.0, v2.7.2).
Ordering
Use judgment to order bullets for a natural top-to-bottom read, generally starting with the changes that best represent the release and keeping related items together.
Bullet style
- User-facing language. Describe what the user sees or can do, not the implementation. Drop internal mechanics (thread-safety details, debounce intervals, refactor notes, rebase context).
- Keep it to roughly one sentence. Each bullet should read at a glance, like the surrounding entries. Resist piling on rationale, background, or every edge case — even for nuanced fixes, state the before/after and the one caveat that matters, then stop. Deep explanation belongs in the README or
docs/, not the changelog. If a bullet grows into multiple sentences with parentheticals, it's too verbose; trim it or split out a sub-bullet. - Lead with a verb and bold the feature name or setting path the first time it appears:
Add **Inline Media Previews**,Fix **Settings > Custom API > Media**. - Indented sub-bullets for configuration details, sub-features, or caveats tied to the parent bullet.
- Keep one bullet per logical change. Merge tightly-related items into a parent + sub-bullet group instead of repeating.
- Filter out: build/CI/tooling changes, internal refactors, dependency bumps, doc-only edits, anything not user-observable.
Contributor attribution
Format: (#PR: @handle) or (#PR: @handle1, @handle2) at the end of the bullet.
- Multiple PRs that share a bullet:
(#262, #266: @icpryde, @jordanearle). - Group related sub-bullets under one parent and put the credit on the parent only — don't repeat the same
@handleon every child bullet. - For non-GitHub credit (e.g. Reddit icon designers), write it inline in prose:
(thanks @jordanearle and /u/harunatsu91202024!)— matches prior entries. - Never invent PR numbers or handles; verify them or omit the parenthetical.
Step 4. Curate the What's New splash
Decide whether this release has a small set of major, broadly useful highlights worth showing once after users update. The What's New sheet is a curated recap, not a copy of the changelog:
- Create a catalog entry for feature-heavy or otherwise notable releases.
- Skip it for routine patch releases or releases without enough meaningful highlights. A version with no matching catalog entry intentionally shows no sheet.
- Prefer roughly 3–8 highlights that represent the release as a whole. Do not include minor fixes, internal work, or every changelog bullet.
- Only highlight changes that are actually included in the release; never pull content from still-open
## [Unreleased]items.
Catalog sources live at whats-new/releases/<version>.json, where <version> is the marketing version from control without a dpkg revision suffix. If the branch already contains a draft catalog for the pending release, rename/update it if the chosen release version changed.
Use this schema:
{
"schemaVersion": 1,
"version": "X.Y.Z",
"headline": "What's New in Apollo Reborn",
"items": [
{
"icon": "star.fill",
"title": "Short Feature Name",
"subtitle": "One concise sentence describing the user-visible benefit."
}
]
}
- The filename stem and
versionvalue must exactly match. - Use valid SF Symbol names and concise, user-facing copy.
- Keep titles short and subtitles to one sentence.
- Order the strongest or broadest highlights first.
Regenerate the committed catalog after adding, renaming, editing, or removing a release JSON:
python3 whats-new/scripts/generate_catalog.py \
whats-new/releases \
whats-new/generated/ApolloWhatsNewCatalog.gen.h \
whats-new/generated/ApolloWhatsNewCatalog.gen.m
The generator validates every release file and must complete successfully.
Step 5. Update contributors
After the release metadata, changelog, and What's New content are prepared, invoke the update-contributors skill and complete its workflow. Run it even when no additions are expected so the release diff confirms that every included contributor is already credited.
Step 6. Verify
grep ^Version control
grep buildVersion distribution/config.json
sed -n '1,60p' CHANGELOG.md
tail -5 CHANGELOG.md
python3 whats-new/scripts/generate_catalog.py \
whats-new/releases \
whats-new/generated/ApolloWhatsNewCatalog.gen.h \
whats-new/generated/ApolloWhatsNewCatalog.gen.m
APOLLO_VERSION=1.15.11 TWEAK_VERSION=X.Y.Z \
python3 scripts/generate_release_notes.py
git --no-pager diff -- \
control distribution/config.json CHANGELOG.md whats-new \
contributors.json README.md .agents/skills/update-contributors
Confirm:
controlhas the newVersion:distribution/config.jsonbuildVersionis incremented (strictly greater than the previous release)- The new release contains only included work, while open/pending items remain under
## [Unreleased] - No PR appears in both the release section and
## [Unreleased] - The footer has a new
[vX.Y.Z]: ...compare/v1.15.11_<previous>...v1.15.11_X.Y.Zlink - Any What's New JSON uses the chosen marketing version and the generated catalog is current
generate_release_notes.pyprints exactly the new release section and does not include pending## [Unreleased]content- Every included contributor is present in
contributors.jsonand the README contributor block is regenerated
Show the diff to the user. Do not commit or tag — the user does that.
Version History
- 4f343cd Current 2026-07-30 20:17


