feat(desktop): build signed Windows + macOS apps in healthchat pipeline

Extend the HealthChat desktop pipeline beyond Linux to produce fully branded,
signed Windows (.exe/.msi) and macOS (.dmg/.zip) installers, published to the
GitHub Release on the healthchat-v* tag alongside the web build.

- Add HealthChat desktop icons (icon.png/ico + Apple Icon Composer bundle),
  derived from apps/web/res/vector-icons/1024.png
- Point the reusable build workflows at this fork (new repository/ref inputs)
  so the Electron shell, icons and healthchat:// handler are fork-branded
- Relax hardcoded Element*/element-desktop* filename asserts to be
  product-name-agnostic
- Wire signed macOS + Windows jobs into build-healthchat-desktop.yaml, trigger
  it on healthchat-v* tags, and add a release job that uploads installers
- Map the org-level eSigner secrets to the CKA names the reusable expects
- Document signing setup (Apple env, eSigner mapping, ESIGNER_MODE=prod) in the
  desktop README and releasing-healthchat skill
This commit is contained in:
2026-06-26 15:10:38 +02:00
parent eee3275f0c
commit f6925dbd77
12 changed files with 277 additions and 62 deletions
+56 -6
View File
@@ -6,13 +6,24 @@ description: Cut a versioned HealthChat release of element-web by tagging releas
# Releasing HealthChat (element-web)
Releases are driven by git tags of the form `healthchat-v<semver>` pushed to
`origin`. The tag triggers `.github/workflows/build-healthchat.yaml`, which
builds the HealthChat Docker image, publishes it to ghcr.io under
`healthchat-web:<version>`, `:stable`, and `:<sha>`, and creates a GitHub
Release whose body is the matching section of `HEALTHCHAT_CHANGES.md`.
`origin`. The tag triggers two workflows in parallel:
Publish target: **ghcr.io Docker image + GitHub Release only.** No npm,
no tarball distribution, no desktop/mobile fan-out.
- `.github/workflows/build-healthchat.yaml` (web) — builds the HealthChat Docker
image, publishes it to ghcr.io under `healthchat-web:<version>`, `:stable`, and
`:<sha>`, and creates a GitHub Release whose body is the matching section of
`HEALTHCHAT_CHANGES.md`.
- `.github/workflows/build-healthchat-desktop.yaml` (desktop) — builds the Electron
app for Linux (amd64/arm64), macOS (universal, signed+notarised) and Windows
(x64/arm64, signed), and attaches the installers (.dmg/.zip/.exe/.msi/.deb/.tar.gz)
to the **same** GitHub Release. The two workflows create-if-missing then upload, so
they race safely.
Publish target: **ghcr.io Docker image + GitHub Release (web bundle + desktop
installers).** No npm, no mobile fan-out.
The desktop app version is taken from `apps/desktop/package.json`, not the tag
(Windows squirrel rewrites any `version` override into a nightly string). Bump it
in the release commit if you want the About dialog / installer filenames to match.
## Preflight checklist
@@ -62,6 +73,11 @@ without moving tags.
path** — only the tag-push path creates Releases (keeps manual retries from
clobbering the release history).
The desktop workflow ("Build HealthChat Desktop") has its own workflow_dispatch
with the same inputs; like the web path, its `release` job only publishes on a
real tag push, so a manual dispatch builds and uploads run artifacts but does not
attach anything to a Release.
## Tag format
```
@@ -110,6 +126,11 @@ warning. Prefer fixing the changelog over relying on the fallback.
with the correct body.
- [ ] The `:stable` tag on ghcr.io now points at the new digest
(`docker buildx imagetools inspect ghcr.io/<owner>/healthchat-web:stable`).
- [ ] The desktop workflow run ("Build HealthChat Desktop") is green and the
GitHub Release has the desktop installers attached (.dmg, *-mac.zip, *.msi,
"* Setup*.exe", *.deb, *.tar.gz).
- [ ] Smoke-check signing: macOS `spctl -a -vvv -t install <app>` is accepted;
Windows installer shows a valid publisher (no SmartScreen block).
## Required secrets
@@ -120,6 +141,22 @@ Configured in repo Settings → Secrets and variables → Actions:
| `HEALTHCHAT_WORKSPACE_TOKEN` | PAT with read access to `Novaloop-AG/healthchat-workspace`. Needed by `actions/checkout` for the private plugin repo. |
| `GITHUB_TOKEN` | Auto-provided. Used for ghcr.io login and GitHub Release creation. No manual setup required. |
Desktop signing additionally requires two GitHub **environments** (Settings →
Environments). Without them the desktop builds still run but produce
unsigned/untrusted output:
| Environment | Secrets / variables |
|---|---|
| `Desktop Apple` | secrets `APPLE_ID`, `APPLE_ID_PASSWORD` (app-specific), `APPLE_CSC_LINK` (base64 `.p12`), `APPLE_CSC_KEY_PASSWORD`; variable `APPLE_TEAM_ID` |
Windows code-signing reuses the org-level SSL.com eSigner secrets shared with the
other Novaloop apps (`ESIGNER_USERNAME`, `ESIGNER_PASSWORD`, `ESIGNER_TOTP_SECRET`);
the windows job in `build-healthchat-desktop.yaml` maps them to the CKA names the
reusable expects (no `credential_id` needed). Set variable `ESIGNER_MODE=prod` for a
trusted signature. These org secrets are scoped to private/internal repos, so the
fork must stay **internal** (not public). Add branch/environment protection so only
`release/healthchat` + `healthchat-v*` runs can reach the signing credentials.
## Rollback
- **Bad image, notes fine** → fix the cause, commit, tag `healthchat-v<ver>-hotfix1`.
@@ -135,6 +172,19 @@ These files are HealthChat-only and will conflict cleanly when rebasing
during rebase):
- `.github/workflows/build-healthchat.yaml`
- `.github/workflows/build-healthchat-desktop.yaml`
- `HEALTHCHAT_CHANGES.md`
- `.healthchat-workspace-version`
- `.claude/skills/releasing-healthchat/SKILL.md`
- `apps/desktop/build/icon.png`, `apps/desktop/build/icon.ico`,
`apps/desktop/build/icon.icon/` (HealthChat icons)
The four shared desktop reusables carry small HealthChat additions (a `repository`
input + product-name-agnostic asserts). These should merge cleanly, but if they
conflict on rebase, re-apply the HealthChat changes rather than blindly taking
either side:
- `.github/workflows/build_desktop_prepare.yaml`
- `.github/workflows/build_desktop_linux.yaml`
- `.github/workflows/build_desktop_macos.yaml`
- `.github/workflows/build_desktop_windows.yaml`