From 7147fbd08560045951c4b38101115d188618ffcd Mon Sep 17 00:00:00 2001 From: Joey Stanford Date: Wed, 5 Aug 2026 07:59:52 -0600 Subject: [PATCH] feat(ci): extend schema upgrade warnings to Build Flatpak Run schema-release-compare on flatpak.yaml (including workflow_dispatch / no-release), embed SCHEMA-UPGRADE.txt when bumped, and upload READ-ME-FIRST-flatpak.md beside Flatpak artifacts. --- .github/workflows/flatpak.yaml | 57 +++++++++++++++++++++- .gitignore | 1 + docs/ci-cd.md | 21 ++++---- docs/release-process.md | 11 +++-- scripts/ci-schema-release-compare.mjs | 14 +++++- scripts/ci-schema-release-compare.test.mjs | 14 ++++++ 6 files changed, 101 insertions(+), 17 deletions(-) diff --git a/.github/workflows/flatpak.yaml b/.github/workflows/flatpak.yaml index 29192fbc9..16cd1f146 100644 --- a/.github/workflows/flatpak.yaml +++ b/.github/workflows/flatpak.yaml @@ -7,6 +7,38 @@ on: tags: ['v*'] jobs: + schema-release-compare: + name: Schema vs last official release + runs-on: ubuntu-latest + permissions: + contents: read + outputs: + schema_bumped: ${{ steps.compare.outputs.schema_bumped }} + curr_schema: ${{ steps.compare.outputs.curr_schema }} + prev_schema: ${{ steps.compare.outputs.prev_schema }} + prev_tag: ${{ steps.compare.outputs.prev_tag }} + steps: + - name: Checkout code + uses: actions/checkout@v6 + with: + fetch-depth: 0 + + - name: Compare schema to last published release + id: compare + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + run: > + node scripts/ci-schema-release-compare.mjs + --workflow-label "Build Flatpak" + --write-readme READ-ME-FIRST-flatpak.md + + - name: Upload READ-ME-FIRST warning + uses: actions/upload-artifact@v7 + with: + name: READ-ME-FIRST-flatpak + path: READ-ME-FIRST-flatpak.md + retention-days: 30 + # Sidecar is built on bare Ubuntu runners (apt). The flathub-infra Flatpak container is a # minimal freedesktopsdk/sdk rootfs with no apt/dnf — host cargo builds cannot install deps there. reticulum-sidecar: @@ -60,7 +92,7 @@ jobs: # "Flatpak system operation Deploy not allowed for user". flatpak: name: Flatpak (${{ matrix.arch }}) - needs: reticulum-sidecar + needs: [reticulum-sidecar, schema-release-compare] runs-on: ${{ matrix.runner }} permissions: contents: read @@ -84,6 +116,20 @@ jobs: name: mesh-client-reticulum-${{ matrix.arch }} path: resources/reticulum-sidecar + - name: Write schema upgrade installer notice + env: + MESH_CLIENT_SCHEMA_BUMPED: ${{ needs.schema-release-compare.outputs.schema_bumped }} + MESH_CLIENT_SCHEMA_CURR: ${{ needs.schema-release-compare.outputs.curr_schema }} + MESH_CLIENT_SCHEMA_PREV: ${{ needs.schema-release-compare.outputs.prev_schema }} + MESH_CLIENT_SCHEMA_PREV_TAG: ${{ needs.schema-release-compare.outputs.prev_tag }} + run: node scripts/write-schema-upgrade-notice.mjs + + - name: Download READ-ME-FIRST warning + uses: actions/download-artifact@v8 + with: + name: READ-ME-FIRST-flatpak + path: flatpak-warnings + - name: Generate offline pnpm sources run: | FBTOOLS=git+https://github.com/flatpak/flatpak-builder-tools @@ -149,6 +195,15 @@ jobs: exit 1 fi + # flatpak-builder already uploaded the .flatpak; attach the schema warning beside it + # for workflow_dispatch test builds (and tag runs) downloading Actions artifacts. + - name: Upload READ-ME-FIRST with Flatpak artifacts + uses: actions/upload-artifact@v7 + with: + name: flatpak-schema-warning-${{ matrix.arch }} + path: flatpak-warnings/READ-ME-FIRST-flatpak.md + retention-days: 30 + publish: name: Publish to GitHub Release needs: flatpak diff --git a/.gitignore b/.gitignore index 3831d1f6d..5e3446ce1 100644 --- a/.gitignore +++ b/.gitignore @@ -40,6 +40,7 @@ resources/SCHEMA-UPGRADE.txt resources/schema-upgrade-notice.nsh READ-ME-FIRST-test-build.md READ-ME-FIRST-schema.md +READ-ME-FIRST-flatpak.md # Local runtime state (identities, path tables, caches) from running the sidecar # directly (e.g. `pnpm run reticulum:sidecar:dev`) with no --reticulum-config-dir override diff --git a/docs/ci-cd.md b/docs/ci-cd.md index 8a797a7b0..60add661d 100644 --- a/docs/ci-cd.md +++ b/docs/ci-cd.md @@ -14,7 +14,7 @@ Mesh-Client uses GitHub Actions for continuous integration and deployment. | `build.yaml` | Manual `workflow_dispatch` | Native 3-OS packaging smoke build (+ schema compare vs last official) | | `reticulum-sidecar.yaml` | Path-filtered push/PR to `main` | Sidecar fmt + Clippy (ubuntu); multi-OS matrix build/test | | `release.yaml` | Version tags (`v*`) | Build & publish releases (AppImage/deb/rpm) | -| `flatpak.yaml` | Version tags (`v*`), manual | Build Flatpak; publish to release on tags | +| `flatpak.yaml` | Version tags (`v*`), manual | Build Flatpak (+ schema compare vs last official); publish to release on tags | | `docs.yml` | Push to `main` | Deploy MkDocs to GitHub Pages | --- @@ -117,13 +117,14 @@ See [Release Process](release-process.md) for the maintainer workflow. Builds Flatpak bundles using [`flatpak/flatpak-github-actions`](https://github.com/flatpak/flatpak-github-actions). -**Triggers:** version tags (`v*`) and manual `workflow_dispatch`. +**Triggers:** version tags (`v*`) and manual `workflow_dispatch` (**Build Flatpak (no release)**). A matrix builds **x86_64** and **aarch64** in parallel. Both use the same privileged `ghcr.io/flathub-infra/flatpak-github-actions:freedesktop-24.08` container (Flathub remote, `flatpak-builder`, and system-scope runtime installs). **x86_64** runs on `ubuntu-latest`; **aarch64** runs on `ubuntu-24.04-arm` (native ARM runners — not QEMU on bare Ubuntu). -1. Generates `flatpak/generated-sources.json` via `flatpak-node-generator` -2. Builds from `org.coloradomesh.MeshClient.yml` with offline pnpm sources -3. Uploads `org.coloradomesh.MeshClient-{x86_64,aarch64}.flatpak` artifacts +1. **`schema-release-compare`** — same compare as Build Binaries / Release; uploads `READ-ME-FIRST-flatpak.md` and feeds `write-schema-upgrade-notice.mjs` so bumped schemas embed `SCHEMA-UPGRADE.txt` under Flatpak `resources/` +2. Builds the Reticulum sidecar on bare Ubuntu runners, then generates `flatpak/generated-sources.json` via `flatpak-node-generator` +3. Builds from `org.coloradomesh.MeshClient.yml` with offline pnpm sources +4. Uploads `org.coloradomesh.MeshClient-{x86_64,aarch64}.flatpak` artifacts plus per-arch `flatpak-schema-warning-*` (the READ-ME-FIRST note for Actions downloads) On **version tag pushes**, a `publish` job attaches both bundles to the GitHub Release. aarch64 is the primary ARM Linux install path (release `build.yaml` only produces x86_64 AppImage/deb/rpm). @@ -307,18 +308,18 @@ CI focuses on lint, typecheck, build, Flatpak metadata validation, and coverage --- -## Packaging smoke builds (`build.yaml` / `release.yaml`) +## Packaging smoke builds (`build.yaml` / `flatpak.yaml` / `release.yaml`) ### Schema compare vs last official release -Both workflows start with a **`schema-release-compare`** job (`scripts/ci-schema-release-compare.mjs`) that: +**Build Binaries**, **Build Flatpak**, and **Release** start with a **`schema-release-compare`** job (`scripts/ci-schema-release-compare.mjs`) that: -1. Labels **Build Binaries** runs as a **test build** (not an official release) in `$GITHUB_STEP_SUMMARY` +1. Labels **Build Binaries** / **Build Flatpak (no release)** runs as a **test build** (not an official release) in `$GITHUB_STEP_SUMMARY` 2. Compares this tree’s `CURRENT_SCHEMA_VERSION` to the last published (non-draft) GitHub Release tag -3. Uploads `READ-ME-FIRST-test-build.md` (build) / `READ-ME-FIRST-schema.md` (release) and includes the warning in platform artifact uploads when sharing Actions downloads +3. Uploads `READ-ME-FIRST-test-build.md` (build) / `READ-ME-FIRST-flatpak.md` (flatpak) / `READ-ME-FIRST-schema.md` (release) and includes the warning in platform / Flatpak artifact uploads when sharing Actions downloads 4. Exposes `schema_bumped` / `curr_schema` / `prev_schema` / `prev_tag` for packaging -When schema is bumped, packaging runs `scripts/write-schema-upgrade-notice.mjs` so Windows NSIS can show a MessageBox and macOS/Linux bundles can include `SCHEMA-UPGRADE.txt` via `electron-builder-before-pack.mjs`. +When schema is bumped, packaging runs `scripts/write-schema-upgrade-notice.mjs` so Windows NSIS can show a MessageBox and macOS/Linux/Flatpak bundles can include `SCHEMA-UPGRADE.txt` in app resources (`electron-builder-before-pack.mjs` / Flatpak `resources/` copy). On first launch after a schema bump against an existing database, the app shows a blocking **Quit / Upgrade** dialog before mutating SQLite (see [Release Process — Database schema upgrades](release-process.md#database-schema-upgrades)). diff --git a/docs/release-process.md b/docs/release-process.md index 4ac1f056a..e9fc190d0 100644 --- a/docs/release-process.md +++ b/docs/release-process.md @@ -23,8 +23,8 @@ Documentation deploys separately: [`docs.yml`](../.github/workflows/docs.yml) ru `CURRENT_SCHEMA_VERSION` in [`src/main/db-schema-sync.ts`](../src/main/db-schema-sync.ts) is the on-disk SQLite `user_version` this build supports. Schema upgrades are **one-way**: -- **CI:** `schema-release-compare` (Build Binaries and Release) warns when this build’s schema is newer than the last published release. Test builds also upload `READ-ME-FIRST-test-build.md` with the artifact set. -- **Installers:** when bumped, Windows NSIS shows an advisory MessageBox; macOS/Linux packages may include `SCHEMA-UPGRADE.txt` in app resources. +- **CI:** `schema-release-compare` (Build Binaries, Build Flatpak, and Release) warns when this build’s schema is newer than the last published release. Test builds also upload a `READ-ME-FIRST-*.md` artifact with the download set. +- **Installers:** when bumped, Windows NSIS shows an advisory MessageBox; macOS/Linux/Flatpak packages may include `SCHEMA-UPGRADE.txt` in app resources. - **App launch:** if an existing database’s `user_version` is behind this build, Mesh-Client shows a blocking **Quit / Upgrade** dialog **before** running `runSchemaUpgrade`. Quit leaves the database unchanged. Set `MESH_CLIENT_ACCEPT_SCHEMA_UPGRADE=1` to auto-accept (E2E / automation only). - **Too new:** opening a database upgraded by a newer app with an older build still fails with the existing schema-too-new fatal dialog. @@ -167,9 +167,10 @@ Build jobs also run `verify-reticulum-sidecar-staged.mjs` after staging sidecars ### `flatpak.yaml` (Build Flatpak) -1. **`reticulum-sidecar`** — builds `mesh-client-reticulum` per arch (x86_64 on `ubuntu-latest`, aarch64 on `ubuntu-24.04-arm`) with full RNS stack features -2. **`flatpak`** — generates offline pnpm sources, builds `org.coloradomesh.MeshClient.flatpak` per arch inside the Flathub freedesktop 24.08 container, smoke-installs the bundle -3. **`publish`** — attaches both `.flatpak` files to the GitHub Release with **`draft: true`** (does not auto-publish an existing draft) +1. **`schema-release-compare`** — compares this SHA’s schema to the last published release; uploads `READ-ME-FIRST-flatpak.md` (included again beside Flatpak Actions artifacts) +2. **`reticulum-sidecar`** — builds `mesh-client-reticulum` per arch (x86_64 on `ubuntu-latest`, aarch64 on `ubuntu-24.04-arm`) with full RNS stack features +3. **`flatpak`** — writes schema upgrade notice into `resources/` when bumped, generates offline pnpm sources, builds `org.coloradomesh.MeshClient.flatpak` per arch inside the Flathub freedesktop 24.08 container, smoke-installs the bundle +4. **`publish`** — attaches both `.flatpak` files to the GitHub Release with **`draft: true`** (does not auto-publish an existing draft) Both tag-triggered workflows must complete before the release is fully populated. Flatpak bundles often arrive a few minutes after the Electron artifacts. diff --git a/scripts/ci-schema-release-compare.mjs b/scripts/ci-schema-release-compare.mjs index 33976ac95..1f5da96fc 100644 --- a/scripts/ci-schema-release-compare.mjs +++ b/scripts/ci-schema-release-compare.mjs @@ -47,15 +47,17 @@ export function readSchemaVersionFromFile(filePath) { * prevSchema: number | null * prevTag: string | null * schemaBumped: boolean + * workflowLabel?: string * }} opts */ export function formatSchemaCompareMarkdown(opts) { const lines = []; if (opts.mode === 'test-build') { + const workflowLabel = opts.workflowLabel?.trim() || 'Build Binaries'; lines.push('# Test build — not an official release'); lines.push(''); lines.push( - 'These artifacts are from **Build Binaries** (`workflow_dispatch`). They are not a published GitHub Release.', + `These artifacts are from **${workflowLabel}** (\`workflow_dispatch\`). They are not a published GitHub Release.`, ); lines.push(''); } else { @@ -207,6 +209,15 @@ export async function runSchemaReleaseCompare(argv, env = process.env) { ? path.resolve(argv[readmeIdx + 1]) : path.join(ROOT, 'READ-ME-FIRST-test-build.md'); + const labelIdx = argv.indexOf('--workflow-label'); + const workflowLabel = + labelIdx >= 0 && argv[labelIdx + 1] + ? argv[labelIdx + 1] + : typeof env.MESH_CLIENT_SCHEMA_WORKFLOW_LABEL === 'string' && + env.MESH_CLIENT_SCHEMA_WORKFLOW_LABEL + ? env.MESH_CLIENT_SCHEMA_WORKFLOW_LABEL + : undefined; + const currFile = path.join(ROOT, SCHEMA_REL); const currSchema = readSchemaVersionFromFile(currFile); @@ -232,6 +243,7 @@ export async function runSchemaReleaseCompare(argv, env = process.env) { prevSchema, prevTag, schemaBumped, + workflowLabel, }); writeStepSummary(markdown, env.GITHUB_STEP_SUMMARY); diff --git a/scripts/ci-schema-release-compare.test.mjs b/scripts/ci-schema-release-compare.test.mjs index 1cb04cd6d..98f04a7ef 100644 --- a/scripts/ci-schema-release-compare.test.mjs +++ b/scripts/ci-schema-release-compare.test.mjs @@ -38,12 +38,26 @@ describe('formatSchemaCompareMarkdown', () => { schemaBumped: true, }); expect(md).toContain('Test build — not an official release'); + expect(md).toContain('Build Binaries'); expect(md).toContain('49'); expect(md).toContain('v5.26.0'); expect(md).toContain('48 → 49'); expect(md).toContain('cannot downgrade'); }); + it('uses a custom workflow label for Flatpak test builds', () => { + const md = formatSchemaCompareMarkdown({ + mode: 'test-build', + currSchema: 49, + prevSchema: 48, + prevTag: 'v5.26.0', + schemaBumped: true, + workflowLabel: 'Build Flatpak', + }); + expect(md).toContain('Build Flatpak'); + expect(md).not.toContain('Build Binaries'); + }); + it('notes when there is no bump', () => { const md = formatSchemaCompareMarkdown({ mode: 'test-build',