ci(desktop): enforce app version matches release tag

This commit is contained in:
2026-06-26 16:41:28 +02:00
parent d53b20e2a8
commit b8cf40ff5a
2 changed files with 67 additions and 11 deletions
+41 -7
View File
@@ -21,9 +21,15 @@ Releases are driven by git tags of the form `healthchat-v<semver>` pushed to
Publish target: **ghcr.io Docker image + GitHub Release (web bundle + desktop Publish target: **ghcr.io Docker image + GitHub Release (web bundle + desktop
installers).** No npm, no mobile fan-out. installers).** No npm, no mobile fan-out.
The desktop app version is taken from `apps/desktop/package.json`, not the tag The desktop app version is taken from `apps/desktop/package.json` (the per-job
(Windows squirrel rewrites any `version` override into a nightly string). Bump it `version` input cannot set it — Windows squirrel mangles it into a nightly string,
in the release commit if you want the About dialog / installer filenames to match. and on macOS/Linux it only feeds the update manifest). So `apps/desktop/package.json`
**must be bumped to the release version in the release commit** to keep the About
dialog and installer filenames matching the tag. This is no longer optional: the
desktop workflow's "Assert desktop app version matches release" step fails the build
if `apps/desktop/package.json` drifts from the tag's `MAJOR.MINOR.PATCH` (any
`-rc1`/`-hotfix1` suffix on the tag is ignored — squirrel needs a clean numeric
version, so set `1.4.0` even when tagging `healthchat-v1.4.0-rc1`).
## Preflight checklist ## Preflight checklist
@@ -33,14 +39,42 @@ Verify each item before tagging. If any fail, fix and commit first.
- [ ] `HEALTHCHAT_CHANGES.md` has a section `## Changes in <new-version> (<date>)` - [ ] `HEALTHCHAT_CHANGES.md` has a section `## Changes in <new-version> (<date>)`
at the top of the file. The pipeline's awk extractor matches this exact at the top of the file. The pipeline's awk extractor matches this exact
heading format. heading format.
- [ ] `apps/desktop/package.json` `version` is set to the release's
`MAJOR.MINOR.PATCH` (no suffix). **Required** — the desktop build asserts
this and fails otherwise. This is what the desktop apps report as their
version.
- [ ] `.healthchat-workspace-version` points at the healthchat-workspace tag - [ ] `.healthchat-workspace-version` points at the healthchat-workspace tag
or ref that should ship with this release. Bump it in the same commit or ref that should ship with this release. **Ask the user** whether to bump
as the changelog entry if needed. it to the latest plugin release or keep the currently pinned ref (see
- [ ] `package.json` version can optionally be bumped to match (cosmetic — "Choosing the plugin version" below). Commit any bump in the same commit as
the git tag is the source of truth for the build). the changelog entry.
- [ ] Root `package.json` version can optionally be bumped to match (cosmetic —
the web bundle version is injected from the tag at build time, and the git
tag is the source of truth for the build).
- [ ] No uncommitted changes to `.github/workflows/build-healthchat.yaml`, - [ ] No uncommitted changes to `.github/workflows/build-healthchat.yaml`,
`Dockerfile`, or `docker/` that haven't been manually sanity-checked. `Dockerfile`, or `docker/` that haven't been manually sanity-checked.
## Choosing the plugin version
The HealthChat plugin (healthchat-workspace) ref that ships with the release is
pinned in `.healthchat-workspace-version` (a single line, e.g. `v0.5.0-rc.4`).
Before tagging, **always ask the user** which they want:
1. **Update to the latest plugin release** — check the available releases:
```bash
gh release list --repo Novaloop-AG/healthchat-workspace --limit 10
```
If they choose a newer ref, write it to `.healthchat-workspace-version` and
commit it alongside the changelog entry.
2. **Keep the currently pinned ref** — leave `.healthchat-workspace-version`
untouched (show them the current value so the choice is informed).
Do not silently change the plugin ref; the user decides per release. The
`workspace_ref` workflow_dispatch input can override it for a one-off build
without committing, but the committed file is the source of truth for tag builds.
## Cutting the release (normal path) ## Cutting the release (normal path)
```bash ```bash
@@ -17,9 +17,13 @@ name: Build HealthChat Desktop
# - macOS notarisation and Windows code-signing require the `Desktop Apple` / `Desktop eSigner` # - macOS notarisation and Windows code-signing require the `Desktop Apple` / `Desktop eSigner`
# GitHub environments (secrets/vars) to be configured. Without them the builds still run but # GitHub environments (secrets/vars) to be configured. Without them the builds still run but
# produce unsigned/untrusted output. See apps/desktop/element.io/healthchat/README. # produce unsigned/untrusted output. See apps/desktop/element.io/healthchat/README.
# - The desktop app version comes from apps/desktop/package.json (electron-builder), NOT the tag # - The desktop app version comes from apps/desktop/package.json (electron-builder); the per-job
# (Windows squirrel rewrites any `version` override into a nightly string). Bump # `version` input only feeds the macOS/Linux update manifest and is mangled into a nightly
# apps/desktop/package.json in the release commit if you want it to match the tag. # string by Windows squirrel, so it cannot set the app version. To keep the installers / About
# dialog in sync with the tag, apps/desktop/package.json must be bumped to the release version
# in the release commit. The "Assert desktop app version matches release" step below enforces
# this: the build fails fast if package.json drifts from the tag's MAJOR.MINOR.PATCH (any
# -rc1/-hotfix1 suffix is ignored, since squirrel requires a clean numeric version).
on: on:
push: push:
@@ -28,7 +32,7 @@ on:
workflow_dispatch: workflow_dispatch:
inputs: inputs:
version: version:
description: "Version (e.g. 1.4.0). Used for the web bundle version; the desktop app version comes from apps/desktop/package.json." description: "Version (e.g. 1.4.0). Drives the web bundle version and must match apps/desktop/package.json (MAJOR.MINOR.PATCH), which sets the desktop app version."
required: true required: true
type: string type: string
workspace_ref: workspace_ref:
@@ -73,6 +77,24 @@ jobs:
fi fi
echo "version=$VERSION" >> "$GITHUB_OUTPUT" echo "version=$VERSION" >> "$GITHUB_OUTPUT"
# electron-builder bakes apps/desktop/package.json's version into the installers and the
# About dialog (the per-platform `version` input cannot override it). Fail fast if that
# file wasn't bumped to this release, so the desktop apps always match the tag. The
# comparison is on MAJOR.MINOR.PATCH only: tags may carry -rc1/-hotfix1 suffixes, but
# Windows squirrel needs package.json to stay a clean numeric version.
- name: Assert desktop app version matches release
env:
VERSION: ${{ steps.version.outputs.version }}
run: |
set -euo pipefail
BASE=$(printf '%s' "$VERSION" | grep -oE '^[0-9]+\.[0-9]+\.[0-9]+')
PKG=$(jq -r .version apps/desktop/package.json)
if [[ "$PKG" != "$BASE" ]]; then
echo "::error::apps/desktop/package.json version ($PKG) does not match release $BASE (tag: $VERSION). Bump apps/desktop/package.json to $BASE in the release commit so the desktop installers and About dialog match the tag."
exit 1
fi
echo "Desktop app version $PKG matches release $BASE"
- name: Resolve workspace ref - name: Resolve workspace ref
id: workspace id: workspace
env: env: