Skip to content

Latest commit

 

History

History
119 lines (86 loc) · 4.7 KB

RELEASING.md

File metadata and controls

119 lines (86 loc) · 4.7 KB

Releasing & Changelog

Reference for cutting a release and for editing the changelog. Read this file when you need it — it is deliberately kept out of AGENTS.md so it doesn't occupy context in every session.

AGENTS.md keeps only the two guardrails that must always be in force:

  • Never edit constants/changelog.ts unless the user explicitly asks.
  • Pushing main with "easBuild": true ships to the App Store.

Everything below is the how.


1. Changelog

The in-app "What's New" panel reads CHANGELOG (newest first) from constants/changelog.ts.

You never edit this file unless the user explicitly asks you to. No speculative entries, no "while I'm here" additions, no entry per edit. When the user does ask, edit it as the last step before the commit — one pass covering everything in the session, not one entry per change.

Which entry to edit

All work now branches off main and returns by PR (develop and preview are retired — see AGENTS.md). Versions in the changelog are therefore always real; there is no .TESTFLIGHT placeholder flow any more.

Compare package.json's version to CHANGELOG[0].version:

  • They DIFFER (changelog ahead) → an unreleased entry is already open. Append to it. Don't create an entry, don't change its version.
  • They're EQUAL → the top entry is already released. Add ONE new entry at the top with a patch bump only and today's date. Don't touch package.json — the release process owns the app version, unless the user explicitly asks you to bump it.

Patch numbers are always two digits (3.8.05, never 3.8.5).

Ignore semver instinct. You never decide major vs. minor vs. patch. The only version edit you ever make is a single patch bump in the EQUAL case on main. A new feature does not mean a minor bump.

Entry format

Use sections, not the legacy flat changes[]. Up to three sections, in this order, omitting any that would be empty:

  • New Features — user-visible capabilities and UI additions
  • Bugs Fixed — corrections to broken or incorrect behavior
  • Maintenance — polish, copy clarifications, reliability work users can feel
{
  version: 'x.y.zz',
  date: 'YYYY-MM-DD',
  sections: [
    { title: 'New Features', items: ['…'] },
    { title: 'Bugs Fixed', items: ['…'] },
    { title: 'Maintenance', items: ['…'] },
  ],
}

Older releases still use flat changes?: string[] — leave them alone. The What's New screen renders sections when present and falls back to changes.

Keep every line short. One plain sentence written for a user — not a bug report. State what changed, and when it happens only if genuinely necessary. Skip the mechanism, the root cause, and the edge cases. If a line needs a semicolon or an em-dash aside to fit everything in, it's too long.

✅ "Fixed torrent speed limits sometimes applying the wrong units" ❌ A paragraph on the KiB/s-vs-bytes/s bug, which server versions it affected, and how the fix compares to other limit fields.

Deduplicate. If a line already covers your change, don't add a near-duplicate — fold the variant into the existing line.

No entry for internal-only work — docs, config, refactors, tests, tooling, AGENTS.md itself.


2. Release & CI

Two GitHub Actions workflows, both in .github/workflows/.

ios-deploy.yml — App Store release

Triggered by a push to main that touches package.json. The gate is the "easBuild": true flag in package.json, not the version number. When it's true the workflow: creates a GitHub Release (notes generated by parsing constants/changelog.ts for the current version) → eas build --profile production → eas submit to App Store Connect.

This means a push to main with that flag set ships to the App Store. Treat package.json on main as a release trigger, not just metadata.

Version plumbing:

  • app.config.js sets version: packageJson.version — package.json is the single source of truth for the marketing version.
  • Build numbers are not in git and not set by hand in Xcode. eas.json uses appVersionSource: "remote" with autoIncrement on the preview and production profiles, so EAS owns them.
  • OTA updates go out through EAS Update (expo-updates), with runtimeVersion.policy: "appVersion" — an OTA update only reaches builds sharing its marketing version. Channels: development, preview, production.

coverage.yml — coverage badge

Runs on push to main. Executes jest --coverage, then force-pushes a single badge.json to the orphan coverage branch, which the README badge reads through shields.io's endpoint type. That branch holds nothing else — don't treat it as a real branch.