Skip to main content

Release Process & Changelog

Version bumping is automated — do not hand-edit versions

The version number used to be bumped by hand in package.json, src/core/Cargo.toml, and src/core/tauri.conf.json, which caused real drift in production (see the 1.0.0-beta.13 "fix: sync tauri.conf.json version with Cargo.toml" entry in RELEASES.md). This is now fully automated with release-pleasethere is no other supported way to bump the version. Do not manually edit the version field in any of those three files, do not hand-edit the generated src/core/tauri.windows.msi.conf.json overlay (see MSI/WiX version overlay below), and do not manually add entries to RELEASES.md; all of these are now generated.

How it works end-to-end

  1. Write a Conventional Commit PR title. Every PR must have a title in Conventional Commits format (e.g. feat: ..., fix(core): ..., chore: ..., docs: ..., refactor: ..., ci: ..., test: ...). This is enforced by .github/workflows/pr-title-lint.yml. Because PRs in this repo are squash-merged, the PR title becomes the single commit message on main that release-please parses — a malformed title breaks both the version bump and the changelog grouping for that change.
  2. Merge to main. .github/workflows/release-please.yml runs on every push to main and maintains a standing "Release PR" (opened/updated automatically) that:
    • Computes the next X.Y.Z-rc.N version from all conventional commits merged since the last release.
    • Updates package.json, src/core/Cargo.toml, and src/core/tauri.conf.json to the exact same version string, in the same commit — see release-please-config.json's extra-files entries for how the Cargo.toml/tauri.conf.json updates are wired up.
    • Refreshes src/core/Cargo.lock's core-crate version entry and regenerates src/core/tauri.windows.msi.conf.json's WiX version via a follow-up job (cargo generate-lockfile + node scripts/sync-msi-version.mjs) that pushes a single commit onto the same PR branch.
    • Prepends a new dated section to RELEASES.md, grouped by commit type (Features, Bug Fixes, Chores, Documentation, Refactors, CI/CD, Tests), from the commits since the last release — replacing the previous manual per-release bullet list process.
  3. Merge the Release PR (a maintainer reviews and merges it like any other PR) to actually cut the release. Merging it tags the commit (X.Y.Z-rc.N, no v/component prefix, matching this repo's existing tag history) and publishes the GitHub Release.
  4. Publishing the GitHub Release triggers .github/workflows/release.yml exactly as before — that workflow is untouched by this automation and still builds/uploads the cross-platform installers.

Note: release-please authenticates with a fine-grained Personal Access Token (the RELEASE_PLEASE_TOKEN repository secret), not the default GITHUB_TOKEN. This is a hard GitHub Actions constraint — the default token can never re-trigger other workflows, which would otherwise silently prevent the GitHub Release from triggering release.yml.

CI safety net

.github/workflows/ci-linux.yml runs a version-consistency job (backed by scripts/check-version-consistency.mjs) on every PR that fails the build if package.json, src/core/Cargo.toml, and src/core/tauri.conf.json ever disagree on their version string, or if src/core/tauri.windows.msi.conf.json's WiX version doesn't match the value derived from the canonical version — this guards against the drift bug recurring even if someone manually edits one of these files. The same job also runs npm run test:scripts, which unit-tests the WiX version derivation logic in scripts/sync-msi-version.mjs.

MSI/WiX version overlay

Tauri's msi bundle target (built with WiX on Windows) requires an all-numeric 4-part version (each field ≤ 65535), so a semver pre-release like 1.0.1-rc.2 fails to bundle as-is with:

failed to bundle project: `optional pre-release identifier in app version must be numeric-only
and cannot be greater than 65535 for msi target`

nsis, dmg, deb, rpm, and appimage don't have this restriction, so only the Windows build needs special handling. src/core/tauri.windows.msi.conf.json is a generated overlay config (only bundle.windows.wix.version) that maps the canonical version to a WiX-safe one:

  • X.Y.Z-rc.NX.Y.Z.N (e.g. 1.0.1-rc.21.0.1.2)
  • X.Y.Z (no pre-release) → X.Y.Z.0

It's generated by node scripts/sync-msi-version.mjs (exposed as npm run sync:msi-version), applied for Windows release builds via --config in .github/workflows/release.yml (runner.os == 'Windows' only), and available locally via npm run tauri:build:windows. Never hand-edit it — scripts/check-version-consistency.mjs will fail CI if it drifts from the derived value.

RELEASES.md

Every release is recorded as a version heading with a changelog-type-grouped bullet list of changes, newest entries first:

### 1.0.0-beta.14 / 2026.08.23

#### Features

- feat: add export_test_to_zip Tauri command

#### Bug Fixes

- fix(core): correct pagination cursor advance

This file is now generated by release-please as part of the Release PR — do not hand-edit past entries. If you need to describe a change in more detail than a squash-merged PR title provides, add it to the PR body; release-please can be configured to include PR body notes over time if needed, but the primary source is the conventional commit type + PR title.

Versioning scheme

Versions follow MAJOR.MINOR.PATCH-rc.N (e.g. 1.0.0-rc.1), tracked in package.json's version field and mirrored automatically (never manually) into src/core/Cargo.toml and src/core/tauri.conf.json by release-please, and into src/core/tauri.windows.msi.conf.json (in WiX-safe form) by scripts/sync-msi-version.mjs. The -rc.N prerelease counter keeps incrementing indefinitely for now; there is no target date/criteria yet for promoting to a stable 1.0.0.

Binary releases

Downloadable binary releases are published at https://github.com/open-lingua/ielts-mastery-hub/releases, per the link at the top of RELEASES.md.

Expectations when shipping a feature

  • Write your PR title as a valid Conventional Commit (see above) — this is what ends up in the generated RELEASES.md entry, so keep it scoped and specific, mirroring the level of detail in existing entries (e.g. naming the exact command/module added, as in core: add export_test_to_zip Tauri command).
  • Do not manually edit RELEASES.md, the version fields in package.json, src/core/Cargo.toml, or src/core/tauri.conf.json, or the generated src/core/tauri.windows.msi.conf.json — release-please and scripts/sync-msi-version.mjs own all of these.
  • See Adding a New Feature End-to-End for how a full feature's changelog entries typically look across its implementation sequence.