# Release Procedure Describes how to publish a new TrainUs release. A local script prepares everything on your machine; all server-side steps (Forgejo, deployment, website) are done manually afterwards. ## Pre-release checklist Before running the script, verify: - [ ] All tests pass on both browsers: `npm run test:parallel` - [ ] `docs/plan.md` is up to date - [ ] Documentation updated (`website/content/developers/technical.en.md`, `website/content/docs/user-guide/index.en.md`, `docs/decisions-log.md`) - [ ] Working tree is clean on `main` ## Step 1 — Run the local script ```bash ./scripts/release.sh ``` The script asks for the new version (semver, e.g. `1.1.0`), then displays the full plan and asks for confirmation before doing anything. It then executes the following steps in order, printing what it does before each one: Before displaying the plan, the script lists all commits since the last tag (or all commits if no tag exists yet). This helps you choose the right version bump (patch/minor/major) and serves as the raw material for the release notes. | # | What | Command / output | | --- | ------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------- | | 1 | Bump version | `npm version X.Y.Z --no-git-tag-version` → updates `package.json` and `package-lock.json` | | 2 | Build the app | `npm run build` → outputs to `dist/` | | 3 | Release commit | `git commit -m "chore: release vX.Y.Z"` on the current branch | | 4 | Annotated tag | `git tag -a vX.Y.Z -m "Release vX.Y.Z"` — local only, not pushed | | 5 | Source archive | `git archive --format=zip HEAD --output=trainus-vX.Y.Z-src.zip` — tracked files only; excludes `node_modules/`, `dist/`, `.git/`, and untracked files | | 6 | Draft release notes | Writes `trainus-vX.Y.Z-notes.md` — a Markdown template pre-filled with the commit list, ready to edit | Nothing is pushed or sent anywhere during this step. ### Artifacts produced | File | Purpose | | ------------------------- | ------------------------------------------------------------------ | | `dist/` | Built PWA — deploy to your static host | | `trainus-vX.Y.Z-src.zip` | Source archive — attach to the Forgejo release | | `trainus-vX.Y.Z-notes.md` | Draft release notes — edit, then paste as the Forgejo release body | ## Step 2 — Edit the release notes Open `trainus-vX.Y.Z-notes.md` in your editor. The file contains: - A template with "What's new", "Bug fixes", and "Breaking changes" sections - The raw commit list since the last release, for reference Rewrite the sections into polished prose, remove the raw commit list, then save the file. ## Step 3 — Push to Forgejo ```bash git push origin main git push origin vX.Y.Z ``` ## Step 4 — Create the release on Forgejo In your Forgejo repository → **Releases → New release**: - **Tag**: `vX.Y.Z` - **Title**: `TrainUs vX.Y.Z` - **Body**: release notes (what's new, bug fixes, breaking changes) - **Attachments**: `trainus-vX.Y.Z-src.zip` (created by the script) Publish the release. You can then delete the local archive. ## Step 5 — Deploy the app Upload the contents of `dist/` to your static host (the live PWA). ## Step 6 — Deploy the website ```bash npm run site:build # outputs to website/public/ ``` Upload the contents of `website/public/` to your website host. ## Step 7 — Publish the release blog post 1. Duplicate `website/content/blog/release-template.en.md` 2. Rename it `YYYY-MM-DD-release-vX.Y.Z.en.md` (use today's date) 3. Fill in every `{PLACEHOLDER}` field 4. Set `draft: false` when the post is ready to publish 5. Write the French version yourself: `YYYY-MM-DD-release-vX.Y.Z.fr.md` 6. Rebuild and redeploy the website (step 5) ## Versioning TrainUs uses **semantic versioning**: `MAJOR.MINOR.PATCH` | Increment | When | | --------- | ---------------------------------- | | `PATCH` | Bug fixes only, no new features | | `MINOR` | New features, backwards-compatible | | `MAJOR` | Breaking change or major redesign | Git tags use the `v` prefix convention: `v1.0.0`, `v1.1.0`, `v2.0.0`, etc.