# 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.
