From 5f09f58a8272c64b11c6c4d3622c834a8e9d6d28 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=ABl?= Date: Sat, 6 Jun 2026 15:13:59 +0200 Subject: [PATCH] ci: add HealthChat desktop build pipeline --- .../workflows/build-healthchat-desktop.yaml | 140 ++++++++++++++++++ apps/desktop/element.io/healthchat/README | 62 ++++++++ apps/desktop/element.io/healthchat/build.json | 7 + .../desktop/element.io/healthchat/config.json | 104 +++++++++++++ .../scripts/build-healthchat-webapp.sh | 51 +++++++ 5 files changed, 364 insertions(+) create mode 100644 .github/workflows/build-healthchat-desktop.yaml create mode 100644 apps/desktop/element.io/healthchat/README create mode 100644 apps/desktop/element.io/healthchat/build.json create mode 100644 apps/desktop/element.io/healthchat/config.json create mode 100755 apps/desktop/scripts/build-healthchat-webapp.sh diff --git a/.github/workflows/build-healthchat-desktop.yaml b/.github/workflows/build-healthchat-desktop.yaml new file mode 100644 index 0000000000..b9a14cc1f9 --- /dev/null +++ b/.github/workflows/build-healthchat-desktop.yaml @@ -0,0 +1,140 @@ +name: Build HealthChat Desktop + +# Builds the HealthChat desktop (Electron) app: the fork's element-web webapp with +# the HealthChat plugin (healthchat-module.js + healthchat-elements.js) injected, +# packaged via the existing element-desktop build pipeline. +# +# This mirrors build-healthchat.yaml (web). It first builds the element-plugin from +# healthchat-workspace, builds the fork webapp with the plugin injected, then feeds it +# into build_desktop_prepare.yaml via its `webapp-artifact` input and packages it with +# build_desktop_linux.yaml. +# +# IMPORTANT CAVEATS (see apps/desktop/element.io/healthchat/README): +# - build_desktop_prepare.yaml / build_desktop_linux.yaml currently `actions/checkout` +# `element-hq/element-web` (upstream). The HealthChat webapp + branding come from the +# uploaded artifact + variant.json, but the Electron shell (electron-main, icons) is +# upstream Element's. To ship a fully fork-branded shell, point those reusable +# workflows at this fork (change their `repository:` / add a `ref` input). +# - Plugin loading depends on element-main.ts rewriting `/modules/*` -> `/webapp/modules/*`. +# Verify that rewrite exists in whichever desktop checkout is used. +# - macOS/Windows builds need Element's signing/notarization secrets and are intentionally +# omitted here; add build_desktop_macos.yaml / build_desktop_windows.yaml once those are +# available. +# - Confirm `ch.healthchat.api_base_url` in apps/desktop/element.io/healthchat/config.json +# points at the real production API origin (assumed https://healthchat.ch). + +on: + workflow_dispatch: + inputs: + version: + description: "Version (e.g. 1.4.0)." + required: true + type: string + workspace_ref: + description: "healthchat-workspace ref (defaults to .healthchat-workspace-version)." + required: false + type: string + +permissions: {} + +concurrency: + group: build-healthchat-desktop-${{ github.event.inputs.version }} + cancel-in-progress: false + +jobs: + webapp: + name: Build webapp + plugin + runs-on: ubuntu-latest + permissions: + contents: read + steps: + - uses: actions/checkout@v4 + with: + persist-credentials: false + + - name: Resolve workspace ref + id: workspace + env: + OVERRIDE: ${{ github.event.inputs.workspace_ref }} + run: | + set -euo pipefail + if [[ -n "$OVERRIDE" ]]; then + REF="$OVERRIDE" + elif [[ -f .healthchat-workspace-version ]]; then + REF=$(head -n1 .healthchat-workspace-version | tr -d '[:space:]') + [[ -n "$REF" ]] || { echo "::error::.healthchat-workspace-version is empty"; exit 1; } + else + echo "::error::.healthchat-workspace-version missing and no workspace_ref override provided" + exit 1 + fi + echo "ref=$REF" >> "$GITHUB_OUTPUT" + + - name: Checkout healthchat-workspace + uses: actions/checkout@v4 + with: + repository: Novaloop-AG/healthchat-workspace + path: healthchat-workspace + token: ${{ secrets.HEALTHCHAT_WORKSPACE_TOKEN }} + ref: ${{ steps.workspace.outputs.ref }} + persist-credentials: false + + - uses: pnpm/action-setup@v4 + - name: Setup Node.js + uses: actions/setup-node@v4 + with: + node-version: 22 + cache: "pnpm" + + - name: Install monorepo deps + run: pnpm install --frozen-lockfile + + - name: Build element-plugin + run: | + cd healthchat-workspace/element-plugin + npm ci + npm run build + cd module + npm ci + npm run build + + - name: Stage plugin artifacts + run: | + mkdir -p plugin-dist/elements + cp healthchat-workspace/element-plugin/module/dist/healthchat-module.js plugin-dist/healthchat-module.js + cp healthchat-workspace/element-plugin/dist/elements/browser/main.js plugin-dist/elements/healthchat-elements.js + + - name: Build webapp with plugin injected + env: + VERSION: ${{ github.event.inputs.version }} + run: ./apps/desktop/scripts/build-healthchat-webapp.sh + + - uses: actions/upload-artifact@v4 + with: + name: healthchat-webapp + retention-days: 1 + path: apps/desktop/webapp + + prepare: + name: Prepare desktop asar + needs: webapp + permissions: + contents: read + uses: ./.github/workflows/build_desktop_prepare.yaml + with: + config: element.io/healthchat + webapp-artifact: healthchat-webapp + nightly: false + deploy: false + + linux: + name: Linux ${{ matrix.arch }} + needs: prepare + strategy: + matrix: + arch: [amd64, arm64] + uses: ./.github/workflows/build_desktop_linux.yaml + with: + arch: ${{ matrix.arch }} + sqlcipher: static + version: ${{ github.event.inputs.version }} + test: false diff --git a/apps/desktop/element.io/healthchat/README b/apps/desktop/element.io/healthchat/README new file mode 100644 index 0000000000..189bb1d8f7 --- /dev/null +++ b/apps/desktop/element.io/healthchat/README @@ -0,0 +1,62 @@ +HealthChat desktop variant +=========================== + +This directory is the `--cfgdir` / build config for HealthChat desktop builds: + + config.json Element Web runtime config baked into webapp.asar. Mirrors + apps/web/config.json (HealthChat homeserver, theme, branding) and + loads the HealthChat plugin: + - "modules": ["/modules/healthchat-module.js"] + - "ch.healthchat.elements_base_url": "/webapp/modules/elements" + build.json electron-builder variant (appId, productName "HealthChat", protocols). + +Why the paths differ from web +----------------------------- +The desktop app serves the webapp from `vector://vector/webapp/`, so root-relative +paths need a `/webapp` prefix: + + - The `modules` array is rewritten automatically by apps/desktop/src/electron-main.ts + (`/modules/x` -> `/webapp/modules/x`), so it stays as `/modules/healthchat-module.js`. + - `ch.healthchat.elements_base_url` is NOT auto-rewritten (the elements bundle is loaded + by a