mirror of
https://github.com/Novaloop-AG/healthchat-web.git
synced 2026-10-31 08:15:07 +00:00
ci: stage desktop feed on packages.healthchat.ch archive
This commit is contained in:
@@ -24,24 +24,26 @@ Releases are driven by git tags of the form `healthchat-v<semver>` pushed to
|
||||
so they race safely). (Linux is intentionally not built — the upstream Linux reusable
|
||||
pulls a build-env Docker image keyed by commit SHA that only exists in the upstream
|
||||
element-hq registry, so it cannot succeed in this fork.) The `release` job **stages**
|
||||
the Squirrel update feed and public installers and attaches them to the Release as
|
||||
split `healthchat-desktop-feed-<version>.tar.gz.part*` assets (the compressed feed
|
||||
exceeds GitHub's 2 GiB per-asset cap) — but it **does not publish them**. Installer
|
||||
binaries are not attached individually; the Release notes get a "## Downloads"
|
||||
section linking their public URLs on packages.healthchat.ch, which resolve once the
|
||||
version is deployed. See "Deploying the desktop release" below.
|
||||
the Squirrel update feed and public installers and uploads them to the versioned
|
||||
archive at `https://packages.healthchat.ch/desktop-releases/<version>/` — but it
|
||||
**does not publish them** to the live feed. Nothing binary is attached to the GitHub
|
||||
Release (the compressed feed outgrew GitHub's 2 GiB per-asset cap at 1.6.0); the
|
||||
Release notes get a "## Downloads" section linking the installers' public URLs on
|
||||
packages.healthchat.ch, which resolve once the version is deployed. See "Deploying
|
||||
the desktop release" below.
|
||||
- `.github/workflows/deploy-healthchat-desktop.yaml` (desktop deploy) — **manual
|
||||
dispatch only.** Downloads and reassembles those feed parts and mirrors the feed to
|
||||
`https://packages.healthchat.ch/desktop/` over FTPS (the private GitHub Release can
|
||||
serve neither end users nor the auto-updater), plus the legacy
|
||||
dispatch only.** Fetches the staged archive for the requested version and mirrors it
|
||||
to the live feed at `https://packages.healthchat.ch/desktop/` over FTPS (the private
|
||||
GitHub Release can serve neither end users nor the auto-updater), plus the legacy
|
||||
`https://healthchat.ch/packages/desktop/` path while clients built <= 1.5.0 are still
|
||||
in the field. This is what makes installed apps
|
||||
self-update; see `apps/desktop/element.io/healthchat/README` for the feed layout and
|
||||
the two caveats (first install is manual; Windows auto-update needs the Setup.exe path,
|
||||
not the .msi).
|
||||
|
||||
Publish target: **ghcr.io Docker image + GitHub Release (web bundle + desktop feed
|
||||
parts, with installer download links).** No npm, no mobile fan-out.
|
||||
Publish target: **ghcr.io Docker image + versioned feed archive on
|
||||
packages.healthchat.ch + GitHub Release (web bundle + installer download links).**
|
||||
No npm, no mobile fan-out.
|
||||
|
||||
## Release ≠ deploy
|
||||
|
||||
@@ -189,9 +191,9 @@ run or `:latest` had not moved yet.
|
||||
|
||||
## Deploying the desktop release
|
||||
|
||||
The desktop build attaches the split `healthchat-desktop-feed-<version>.tar.gz.part*`
|
||||
assets to the Release but
|
||||
leaves `https://packages.healthchat.ch/desktop/` untouched. Until you run this, installed
|
||||
The desktop build stages the feed at
|
||||
`https://packages.healthchat.ch/desktop-releases/<version>/` but
|
||||
leaves the live feed at `https://packages.healthchat.ch/desktop/` untouched. Until you run this, installed
|
||||
apps keep whatever version they have and the public download links still serve the old
|
||||
installers.
|
||||
|
||||
@@ -223,10 +225,10 @@ means the feed is genuinely live. Installed apps pick it up on their next update
|
||||
|
||||
### Deploying an RC or rolling back
|
||||
|
||||
`version` accepts any released version, including `1.5.0-rc1`. Because the feed lives on
|
||||
the Release (assets never expire, unlike workflow artifacts), **re-running this workflow
|
||||
with an older version republishes that feed** — no rebuild, no re-signing. That is the
|
||||
desktop rollback path:
|
||||
`version` accepts any released version, including `1.5.0-rc1`. Because staged feeds
|
||||
persist in the versioned archive (`desktop-releases/<version>/`), **re-running this
|
||||
workflow with an older version republishes that feed** — no rebuild, no re-signing.
|
||||
That is the desktop rollback path:
|
||||
|
||||
```bash
|
||||
gh workflow run deploy-healthchat-desktop.yaml --ref release/healthchat -f version=1.4.1
|
||||
@@ -237,9 +239,9 @@ newer `*.nupkg` files in place. That is intentional — Squirrel.Windows needs t
|
||||
history — and harmless, since clients follow `RELEASES`/`releases.json`, not directory
|
||||
listings.
|
||||
|
||||
Releases cut **before** this release/deploy split carry no feed tarball. The workflow says
|
||||
so explicitly and lists the assets it did find; re-run "Build HealthChat Desktop" for that
|
||||
version to produce one.
|
||||
Versions with no staged archive (cut before the archive design) fail the deploy with a
|
||||
pointer; dispatch "Build HealthChat Desktop" with `version=<version>` to rebuild and
|
||||
stage that version, then re-run the deploy.
|
||||
|
||||
## Manual / retry path (workflow_dispatch)
|
||||
|
||||
@@ -260,9 +262,10 @@ without moving tags.
|
||||
override in "Deploying the release" if that is what you want.
|
||||
|
||||
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.
|
||||
with the same inputs. Its `release` job **also runs on dispatch** to (re)stage the
|
||||
feed archive at `desktop-releases/<version>/` — that is the recovery path when a
|
||||
version's archive is missing — but the GitHub Release steps (create + Downloads
|
||||
links) stay tag-only, so a dispatch can never touch release history.
|
||||
|
||||
## Tag format
|
||||
|
||||
@@ -322,11 +325,10 @@ warning. Prefer fixing the changelog over relying on the fallback.
|
||||
|
||||
For an `-rc`/`-hotfix`/`-dryrun` tag the opposite is expected: `:latest` must
|
||||
be **unchanged**.
|
||||
- [ ] The desktop workflow run ("Build HealthChat Desktop") is green and the
|
||||
GitHub Release carries the split feed assets
|
||||
`healthchat-desktop-feed-<version>.tar.gz.part*` plus a "## Downloads" section
|
||||
in its notes linking the public installers. Without those parts the desktop
|
||||
deploy has nothing to publish.
|
||||
- [ ] The desktop workflow run ("Build HealthChat Desktop") is green, the GitHub
|
||||
Release notes carry the "## Downloads" section, and the staged archive exists:
|
||||
`curl -fsS https://packages.healthchat.ch/desktop-releases/<version>/update/macos/releases.json`.
|
||||
Without that archive the desktop deploy has nothing to publish.
|
||||
- [ ] Confirm the live feed is still on the **previous** version — releasing must not have
|
||||
moved it. `curl -fsS https://packages.healthchat.ch/desktop/update/macos/releases.json`
|
||||
- [ ] Smoke-check signing before shipping to users: macOS `spctl -a -vvv -t install <app>`
|
||||
@@ -354,7 +356,7 @@ 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. |
|
||||
| `FTP_SERVER` / `FTP_USERNAME` / `FTP_PASSWORD` | Credentials for the healthchat.ch FTP(S) account. Used **only** by `deploy-healthchat-desktop.yaml` to publish the update feed + public installers under `/public_html/packages/desktop/` (docroot of packages.healthchat.ch) plus, during the URL migration, the legacy `/public_html/healthchat.ch/packages/desktop/`. `FTP_SERVER` is the hostname only (explicit FTPS / AUTH TLS). The release workflows never touch FTP, so a missing/expired credential breaks the deploy but never the release. |
|
||||
| `FTP_SERVER` / `FTP_USERNAME` / `FTP_PASSWORD` | Credentials for the healthchat.ch FTP(S) account (docroot of packages.healthchat.ch is `/public_html/packages`). Used by the `release` job of `build-healthchat-desktop.yaml` to stage the feed archive under `/public_html/packages/desktop-releases/<version>/`, and by `deploy-healthchat-desktop.yaml` to publish the live feed under `/public_html/packages/desktop/` plus, during the URL migration, the legacy `/public_html/healthchat.ch/packages/desktop/`. `FTP_SERVER` is the hostname only (explicit FTPS / AUTH TLS). |
|
||||
|
||||
Desktop signing additionally requires two GitHub **environments** (Settings →
|
||||
Environments). Without them the desktop builds still run but produce
|
||||
|
||||
@@ -10,11 +10,12 @@ name: Build HealthChat Desktop
|
||||
# (via `webapp-artifact`) and the per-platform build_desktop_{macos,windows}.yaml reusables.
|
||||
#
|
||||
# Notes:
|
||||
# - This workflow RELEASES but does not DEPLOY. It attaches a staged update-feed tarball (split
|
||||
# into <2 GiB parts) to the GitHub Release and links the public installer URLs in the Release
|
||||
# notes; the live auto-update feed at packages.healthchat.ch/desktop/ is only touched by the
|
||||
# manually dispatched deploy-healthchat-desktop.yaml. So cutting a tag never pushes an update
|
||||
# to already-installed apps until a human decides to ship it.
|
||||
# - This workflow RELEASES but does not DEPLOY. It stages the update feed + public installers
|
||||
# to the versioned archive at packages.healthchat.ch/desktop-releases/<version>/ and links
|
||||
# the public installer URLs in the Release notes (nothing binary is attached to the GitHub
|
||||
# Release); the live auto-update feed at packages.healthchat.ch/desktop/ is only touched by
|
||||
# the manually dispatched deploy-healthchat-desktop.yaml. So cutting a tag never pushes an
|
||||
# update to already-installed apps until a human decides to ship it.
|
||||
# - The reusable build workflows are pointed at THIS fork (repository/ref inputs) so the Electron
|
||||
# shell, icons (apps/desktop/build/icon.*) and the healthchat:// deep-link handler
|
||||
# (apps/desktop/src/protocol.ts) are all fork-branded. Branding values come from
|
||||
@@ -228,10 +229,13 @@ jobs:
|
||||
targets: "squirrel msi"
|
||||
|
||||
release:
|
||||
name: Publish to GitHub Release
|
||||
name: Stage feed archive + Release notes
|
||||
needs: [macos, windows]
|
||||
# Only publish on a real tag push; manual workflow_dispatch runs build but do not publish.
|
||||
if: startsWith(github.ref, 'refs/tags/')
|
||||
# Runs on tag pushes AND manual dispatches: the archive upload is idempotent per version
|
||||
# (mirror --delete into desktop-releases/<version>/), and re-running it via dispatch is
|
||||
# the recovery path for a version whose archive is missing. The GitHub Release steps
|
||||
# below stay tag-only, so a dispatch can never touch release history.
|
||||
if: startsWith(github.ref, 'refs/tags/') || github.event_name == 'workflow_dispatch'
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
contents: write
|
||||
@@ -242,17 +246,31 @@ jobs:
|
||||
with:
|
||||
persist-credentials: false
|
||||
|
||||
- name: Resolve version
|
||||
id: relversion
|
||||
env:
|
||||
INPUT_VERSION: ${{ github.event.inputs.version }}
|
||||
run: |
|
||||
set -euo pipefail
|
||||
if [[ "${GITHUB_REF_TYPE}" == "tag" ]]; then
|
||||
VERSION="${GITHUB_REF_NAME#healthchat-v}"
|
||||
else
|
||||
VERSION="${INPUT_VERSION:?No version input on workflow_dispatch}"
|
||||
fi
|
||||
echo "version=$VERSION" >> "$GITHUB_OUTPUT"
|
||||
|
||||
- name: Download all build artifacts
|
||||
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8
|
||||
with:
|
||||
path: dist-artifacts
|
||||
|
||||
# Installers are NOT attached to the Release: they ship inside the feed tarball and are
|
||||
# Installers are NOT attached to the Release: they ship inside the staged feed and are
|
||||
# served from packages.healthchat.ch after the deploy — the Release body links to them
|
||||
# there (see "Link public downloads in the Release notes" below). Attaching them here
|
||||
# would duplicate ~1 GiB per release and the x64/arm64 Setup.exe share a filename, so
|
||||
# they'd clobber each other as flat Release assets anyway.
|
||||
- name: Ensure GitHub Release exists
|
||||
if: startsWith(github.ref, 'refs/tags/')
|
||||
env:
|
||||
GH_TOKEN: ${{ github.token }}
|
||||
GH_REPO: ${{ github.repository }}
|
||||
@@ -265,13 +283,16 @@ jobs:
|
||||
gh release view "$TAG" >/dev/null 2>&1 || \
|
||||
gh release create "$TAG" --title "$TAG" --notes "HealthChat $TAG"
|
||||
|
||||
# The GitHub Release above is private (internal fork), so it can't serve end users or the
|
||||
# The GitHub Release is private (internal fork), so it can't serve end users or the
|
||||
# Squirrel auto-updater. Those are served from packages.healthchat.ch/desktop/, which is
|
||||
# published by the SEPARATE, MANUALLY DISPATCHED "Deploy HealthChat Desktop" workflow
|
||||
# (deploy-healthchat-desktop.yaml) — releasing never touches the live update feed.
|
||||
# This job only *stages* that feed and attaches it to the Release as a tarball, so the
|
||||
# deploy workflow can publish any past version without rebuilding or re-signing.
|
||||
# This job only *stages* that feed and uploads it to the versioned archive at
|
||||
# packages.healthchat.ch/desktop-releases/<version>/ (the archive persists, so the
|
||||
# deploy workflow can publish any staged version without rebuilding or re-signing).
|
||||
- name: Stage update feed + public installers
|
||||
env:
|
||||
VERSION: ${{ steps.relversion.outputs.version }}
|
||||
run: |
|
||||
set -euo pipefail
|
||||
# --- Release notes: extract this version's section from HEALTHCHAT_CHANGES.md ---
|
||||
@@ -279,7 +300,6 @@ jobs:
|
||||
# auto-update "See changes" dialog: macOS reads it from releases.json's `notes`
|
||||
# field natively, Windows fetches notes.txt (Squirrel.Windows can't carry notes
|
||||
# through the update-downloaded event — only releaseName is available).
|
||||
VERSION="${GITHUB_REF_NAME#healthchat-v}"
|
||||
NOTES=$(awk -v ver="$VERSION" '
|
||||
/^## Changes in / {
|
||||
if (found) { exit }
|
||||
@@ -327,34 +347,46 @@ jobs:
|
||||
echo "--- staged feed tree ---"
|
||||
find feed -type f | sort
|
||||
|
||||
# Attach the staged feed to the Release instead of publishing it. "Deploy HealthChat
|
||||
# Desktop" (deploy-healthchat-desktop.yaml) downloads this tarball and mirrors it to
|
||||
# healthchat.ch when a human decides to ship. Release assets do not expire, so any past
|
||||
# version stays redeployable long after the workflow artifacts are gone.
|
||||
- name: Attach update feed to the GitHub Release
|
||||
# Upload the staged feed to the versioned archive instead of publishing it. "Deploy
|
||||
# HealthChat Desktop" (deploy-healthchat-desktop.yaml) mirrors this archive to the
|
||||
# live feed when a human decides to ship. The archive directories persist on the
|
||||
# server, so any staged version stays redeployable without rebuilding or re-signing.
|
||||
# (The feed used to be attached to the GitHub Release as a tarball, but the
|
||||
# compressed feed outgrew GitHub's 2 GiB per-asset cap at 1.6.0.)
|
||||
- name: Publish staged feed to the versioned archive
|
||||
env:
|
||||
GH_TOKEN: ${{ github.token }}
|
||||
GH_REPO: ${{ github.repository }}
|
||||
TAG: ${{ github.ref_name }}
|
||||
FTP_SERVER: ${{ secrets.FTP_SERVER }}
|
||||
FTP_USERNAME: ${{ secrets.FTP_USERNAME }}
|
||||
# Passed to lftp via LFTP_PASSWORD (--env-password) so it never appears on the
|
||||
# command line / process list.
|
||||
LFTP_PASSWORD: ${{ secrets.FTP_PASSWORD }}
|
||||
VERSION: ${{ steps.relversion.outputs.version }}
|
||||
run: |
|
||||
set -euo pipefail
|
||||
VERSION="${GITHUB_REF_NAME#healthchat-v}"
|
||||
TARBALL="healthchat-desktop-feed-${VERSION}.tar.gz"
|
||||
# Store paths relative to feed/ so the deploy side extracts a bare feed/ tree.
|
||||
# GitHub caps Release assets at 2 GiB and the compressed feed exceeds that
|
||||
# (first hit by 1.6.0), so stream the tarball through split and attach the
|
||||
# parts; the deploy workflow concatenates ${TARBALL}.part* in glob order
|
||||
# before extracting.
|
||||
tar -czf - feed | split -b 1536m -d - "${TARBALL}.part"
|
||||
ls -lh "${TARBALL}".part*
|
||||
gh release upload "$TAG" "${TARBALL}".part* --clobber
|
||||
echo "::notice::Update feed attached as ${TARBALL}.part*. The live feed at packages.healthchat.ch is UNCHANGED — run the 'Deploy HealthChat Desktop' workflow to publish it."
|
||||
: "${FTP_SERVER:?FTP_SERVER secret not set}"
|
||||
: "${FTP_USERNAME:?FTP_USERNAME secret not set}"
|
||||
: "${LFTP_PASSWORD:?FTP_PASSWORD secret not set}"
|
||||
sudo apt-get update && sudo apt-get install -y lftp
|
||||
# The archive dir is owned by this version's build: --delete makes re-runs
|
||||
# idempotent (a rebuild fully replaces the staged tree). The live feed under
|
||||
# /public_html/packages/desktop is never touched here.
|
||||
lftp -u "$FTP_USERNAME" --env-password "$FTP_SERVER" <<LFTP
|
||||
set cmd:fail-exit true
|
||||
set ftp:ssl-force true
|
||||
set ftp:ssl-protect-data true
|
||||
set ssl:verify-certificate true
|
||||
mkdir -pf /public_html/packages/desktop-releases/$VERSION
|
||||
mirror -R --delete --parallel=4 --verbose feed/ /public_html/packages/desktop-releases/$VERSION/
|
||||
bye
|
||||
LFTP
|
||||
echo "::notice::Feed staged at https://packages.healthchat.ch/desktop-releases/$VERSION/ — the live feed is UNCHANGED. Run 'Deploy HealthChat Desktop' to publish it."
|
||||
|
||||
# The Release carries no installer binaries (see "Ensure GitHub Release exists"), so
|
||||
# point readers at the public download URLs instead. The links are derived from the
|
||||
# staged feed/install tree, so they stay correct if electron-builder ever renames the
|
||||
# artifacts. They resolve once "Deploy HealthChat Desktop" has published this version.
|
||||
- name: Link public downloads in the Release notes
|
||||
if: startsWith(github.ref, 'refs/tags/')
|
||||
env:
|
||||
GH_TOKEN: ${{ github.token }}
|
||||
GH_REPO: ${{ github.repository }}
|
||||
|
||||
@@ -3,23 +3,24 @@ name: Deploy HealthChat Desktop
|
||||
# Publishes an already-released desktop build to packages.healthchat.ch/desktop/ over FTPS.
|
||||
#
|
||||
# This is the DEPLOY half of the desktop pipeline, deliberately split from the release half
|
||||
# (build-healthchat-desktop.yaml). Cutting a `healthchat-v*` tag builds, signs and attaches the
|
||||
# installers plus a staged update-feed tarball to the GitHub Release, but never touches the live
|
||||
# feed. Nothing reaches installed apps until this workflow is dispatched by hand.
|
||||
# (build-healthchat-desktop.yaml). Cutting a `healthchat-v*` tag builds, signs and stages the
|
||||
# update feed + public installers at packages.healthchat.ch/desktop-releases/<version>/, but
|
||||
# never touches the live feed. Nothing reaches installed apps until this workflow is dispatched
|
||||
# by hand.
|
||||
#
|
||||
# Why that split matters: the feed under .../desktop/update/ is what the Squirrel
|
||||
# auto-updater polls. Writing to it pushes an update to every installed client, so it is a
|
||||
# deployment, not a publication step — the same reason the ansible playbook's deploy is a manual
|
||||
# dispatch rather than a release trigger.
|
||||
#
|
||||
# The tarball is a GitHub Release asset (they do not expire, unlike workflow artifacts), so any
|
||||
# past version can be re-published without rebuilding or re-signing — that is the rollback path.
|
||||
# The versioned archive directories persist on the server, so any staged version can be
|
||||
# re-published without rebuilding or re-signing — that is the rollback path.
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
version:
|
||||
description: "Version to publish (e.g. 1.5.0). Must have a healthchat-v<version> Release carrying a healthchat-desktop-feed-<version>.tar.gz asset."
|
||||
description: "Version to publish (e.g. 1.5.0). Must have a staged feed at packages.healthchat.ch/desktop-releases/<version>/ (produced by Build HealthChat Desktop)."
|
||||
required: true
|
||||
type: string
|
||||
dry_run:
|
||||
@@ -28,8 +29,7 @@ on:
|
||||
type: boolean
|
||||
default: false
|
||||
|
||||
permissions:
|
||||
contents: read # download the Release asset
|
||||
permissions: {} # the feed comes from the packages.healthchat.ch archive, not from GitHub
|
||||
|
||||
concurrency:
|
||||
# Never let two runs mirror onto the same FTP tree at once.
|
||||
@@ -40,7 +40,8 @@ jobs:
|
||||
deploy:
|
||||
name: Publish update feed to packages.healthchat.ch
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 30
|
||||
# Fetches ~2 GiB from the archive and uploads it twice (canonical + legacy path).
|
||||
timeout-minutes: 60
|
||||
steps:
|
||||
- name: Resolve version
|
||||
id: version
|
||||
@@ -59,33 +60,37 @@ jobs:
|
||||
echo "tag=healthchat-v$VERSION" >> "$GITHUB_OUTPUT"
|
||||
echo "Publishing HealthChat Desktop $VERSION (tag healthchat-v$VERSION)"
|
||||
|
||||
- name: Download update feed from the Release
|
||||
- name: Install lftp
|
||||
run: sudo apt-get update && sudo apt-get install -y lftp
|
||||
|
||||
- name: Fetch staged feed from the archive
|
||||
env:
|
||||
GH_TOKEN: ${{ github.token }}
|
||||
GH_REPO: ${{ github.repository }}
|
||||
TAG: ${{ steps.version.outputs.tag }}
|
||||
FTP_SERVER: ${{ secrets.FTP_SERVER }}
|
||||
FTP_USERNAME: ${{ secrets.FTP_USERNAME }}
|
||||
# Passed to lftp via LFTP_PASSWORD (--env-password) so it never appears on the
|
||||
# command line / process list.
|
||||
LFTP_PASSWORD: ${{ secrets.FTP_PASSWORD }}
|
||||
VERSION: ${{ steps.version.outputs.version }}
|
||||
run: |
|
||||
set -euo pipefail
|
||||
TARBALL="healthchat-desktop-feed-${VERSION}.tar.gz"
|
||||
if ! gh release view "$TAG" >/dev/null 2>&1; then
|
||||
echo "::error::No GitHub Release found for tag $TAG"
|
||||
: "${FTP_SERVER:?FTP_SERVER secret not set}"
|
||||
: "${FTP_USERNAME:?FTP_USERNAME secret not set}"
|
||||
: "${LFTP_PASSWORD:?FTP_PASSWORD secret not set}"
|
||||
# The archive is public — probe it over HTTPS first for a clear error before
|
||||
# opening the FTP session.
|
||||
if ! curl -fsSI "https://packages.healthchat.ch/desktop-releases/$VERSION/update/macos/releases.json" >/dev/null 2>&1; then
|
||||
echo "::error::No staged feed at https://packages.healthchat.ch/desktop-releases/$VERSION/ — run 'Build HealthChat Desktop' (workflow_dispatch, version=$VERSION) to build and stage this version, then re-run the deploy."
|
||||
exit 1
|
||||
fi
|
||||
# The feed is attached as split ${TARBALL}.part* files (the compressed feed
|
||||
# outgrew GitHub's 2 GiB per-asset cap at 1.6.0); older releases may carry a
|
||||
# single-file tarball instead. Handle both.
|
||||
if ! gh release download "$TAG" --pattern "${TARBALL}*" --clobber; then
|
||||
echo "::error::Release $TAG has no asset matching '${TARBALL}*'. Releases cut before the deploy split do not carry one — re-run 'Build HealthChat Desktop' for this version to produce it."
|
||||
gh release view "$TAG" --json assets --jq '.assets[].name' || true
|
||||
exit 1
|
||||
fi
|
||||
if compgen -G "${TARBALL}.part*" > /dev/null; then
|
||||
cat "${TARBALL}".part* | tar -xzf -
|
||||
else
|
||||
tar -xzf "$TARBALL"
|
||||
fi
|
||||
test -d feed || { echo "::error::Tarball did not contain a feed/ directory"; exit 1; }
|
||||
lftp -u "$FTP_USERNAME" --env-password "$FTP_SERVER" <<LFTP
|
||||
set cmd:fail-exit true
|
||||
set ftp:ssl-force true
|
||||
set ftp:ssl-protect-data true
|
||||
set ssl:verify-certificate true
|
||||
mirror --parallel=4 --verbose /public_html/packages/desktop-releases/$VERSION/ feed/
|
||||
bye
|
||||
LFTP
|
||||
test -d feed || { echo "::error::Archive fetch produced no feed/ directory"; exit 1; }
|
||||
echo "--- feed to publish ---"
|
||||
find feed -type f | sort
|
||||
|
||||
@@ -108,10 +113,7 @@ jobs:
|
||||
fi
|
||||
exit $fail
|
||||
|
||||
- name: Install lftp
|
||||
run: sudo apt-get update && sudo apt-get install -y lftp
|
||||
|
||||
- name: Publish to healthchat.ch over FTPS
|
||||
- name: Publish to packages.healthchat.ch over FTPS
|
||||
env:
|
||||
FTP_SERVER: ${{ secrets.FTP_SERVER }}
|
||||
FTP_USERNAME: ${{ secrets.FTP_USERNAME }}
|
||||
|
||||
@@ -48,10 +48,12 @@ feeds it into build_desktop_prepare.yaml (`config: element.io/healthchat`,
|
||||
`webapp-artifact: healthchat-webapp`) and the per-platform build_desktop_{macos,windows}.yaml
|
||||
reusables. It runs on every `healthchat-v*` tag (alongside the web build) and via
|
||||
workflow_dispatch. The reusables are pointed at THIS fork (`repository`/`ref` inputs) so the
|
||||
Electron shell, icons and the healthchat:// deep-link handler are fork-branded. On a tag push the
|
||||
`release` job attaches the staged update feed as split healthchat-desktop-feed-<ver>.tar.gz.part*
|
||||
assets (the compressed feed exceeds GitHub's 2 GiB per-asset cap) and links the public installer
|
||||
URLs on packages.healthchat.ch in the Release notes — installer binaries are not attached.
|
||||
Electron shell, icons and the healthchat:// deep-link handler are fork-branded. The `release`
|
||||
job uploads the staged update feed + installers to the versioned archive at
|
||||
packages.healthchat.ch/desktop-releases/<ver>/ (also on workflow_dispatch — the recovery path
|
||||
for a missing archive) and, on tag pushes only, links the public installer URLs in the Release
|
||||
notes. Nothing binary is attached to the GitHub Release (the compressed feed outgrew GitHub's
|
||||
2 GiB per-asset cap at 1.6.0).
|
||||
(Linux is not built: the upstream build_desktop_linux.yaml needs a build-env Docker image
|
||||
keyed by commit SHA that only exists in the upstream element-hq registry, so it can't run here.)
|
||||
|
||||
@@ -115,9 +117,11 @@ subdomain's docroot on the healthchat.ch FTP account is /public_html/packages):
|
||||
install/macos/HealthChat-<ver>.dmg + HealthChat.dmg (stable "latest")
|
||||
install/win32/<arch>/HealthChat-Setup-<ver>.exe + HealthChat-Setup.exe (stable) + *.msi
|
||||
|
||||
The `release` job in build-healthchat-desktop.yaml stages these trees; the manually dispatched
|
||||
deploy-healthchat-desktop.yaml uploads them via lftp/FTPS (mirror -R, no-delete so prior nupkgs
|
||||
survive for delta history). Add these repo secrets:
|
||||
The `release` job in build-healthchat-desktop.yaml stages these trees and uploads them to the
|
||||
versioned archive desktop-releases/<ver>/ (sibling of desktop/ under /public_html/packages);
|
||||
the manually dispatched deploy-healthchat-desktop.yaml mirrors that archive onto the live
|
||||
desktop/ tree via lftp/FTPS (mirror -R, no-delete so prior nupkgs survive for delta history).
|
||||
Add these repo secrets:
|
||||
FTP_SERVER hostname only (explicit FTPS / AUTH TLS on port 21; if the host cert is untrusted,
|
||||
flip ssl:verify-certificate to no in the workflow)
|
||||
FTP_USERNAME
|
||||
|
||||
Reference in New Issue
Block a user