Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 7 additions & 1 deletion .github/workflows/build.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,12 @@ jobs:
APPLE_TEAM_ID: ${{ matrix.os == 'macos-latest' && secrets.APPLE_TEAM_ID || '' }}
run: ${{ matrix.build_script }}

# Stamp downloadable installer basenames with -run{N} so same-semver test
# builds do not overwrite each other after unzip. Runs after dist:* verify
# (unstamped names) and before upload (packaging-smoke downloads stamped names).
- name: Rename test-build installers with run number
run: node scripts/rename-test-build-artifacts.mjs --root release

# Stage under release/ so upload-artifact@v7's least-common-ancestor stays
# release/ (paths outside release/ nest installers as release/release/*.exe and
# break packaging-smoke, which downloads to path: release).
Expand Down Expand Up @@ -198,7 +204,7 @@ jobs:
with:
name: mesh-client-windows-${{ github.sha }}
path: |
# Per-arch NSIS installers: Mesh-client Setup {version}.exe + {version}-arm64.exe
# Per-arch NSIS installers (test builds: …-run{N}.exe / …-run{N}-arm64.exe)
release/*.exe
release/READ-ME-FIRST-test-build.md
retention-days: 30
Expand Down
45 changes: 39 additions & 6 deletions .github/workflows/flatpak.yaml
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
name: Build Flatpak
run-name: Build Flatpak${{ github.event_name == 'workflow_dispatch' && ' (no release)' || '' }}
# Dual-purpose: manual dispatch = test (no release); tag push = publish to GitHub Release.
run-name: ${{ github.event_name == 'workflow_dispatch' && 'Build Flatpak (no release)' || 'Build Flatpak' }}

on:
workflow_dispatch:
Expand Down Expand Up @@ -27,9 +28,13 @@ jobs:
id: compare
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
WORKFLOW_LABEL: >-
${{ github.event_name == 'workflow_dispatch'
&& 'Build Flatpak (no release)'
|| 'Build Flatpak' }}
run: >
node scripts/ci-schema-release-compare.mjs
--workflow-label "Build Flatpak"
--workflow-label "${WORKFLOW_LABEL}"
--write-readme READ-ME-FIRST-flatpak.md

- name: Upload READ-ME-FIRST warning
Expand Down Expand Up @@ -157,16 +162,30 @@ jobs:
console.log('generated-sources storeDir YAML: ok');
EOF

# Embed buildChannel=test|release + Actions runUrl into the Flatpak main bundle.
- name: Stamp CI build info
env:
MESH_CLIENT_BUILD_CHANNEL: ${{ github.event_name == 'workflow_dispatch' && 'test' || 'release' }}
MESH_CLIENT_BUILD_WORKFLOW: >-
${{ github.event_name == 'workflow_dispatch'
&& 'Build Flatpak (no release)'
|| 'Build Flatpak' }}
run: |
set -euo pipefail
node scripts/ci-write-build-info-env.mjs
node scripts/write-flatpak-ci-build-info.mjs

# flatpak/flatpak-github-actions v6 appends -${arch} to the artifact name on upload;
# keep bundle arch-agnostic here to avoid org.coloradomesh.MeshClient-aarch64-aarch64.flatpak.
# upload-artifact: false — we upload once after smoke (+ optional -run{N} rename on dispatch).
- uses: flatpak/flatpak-github-actions/flatpak-builder@401fe28a8384095fc1531b9d320b292f0ee45adb
with:
bundle: org.coloradomesh.MeshClient.flatpak
manifest-path: org.coloradomesh.MeshClient.yml
arch: ${{ matrix.arch }}
branch: stable
cache-key: flatpak-builder-${{ matrix.arch }}-${{ github.sha }}
upload-artifact: true
upload-artifact: false

- name: Smoke test Flatpak install
run: |
Expand Down Expand Up @@ -195,8 +214,22 @@ 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.
# Test (dispatch) only: stamp downloadable basename with -run{N}. Tag releases stay clean.
- name: Rename test Flatpak bundle with run number
if: github.event_name == 'workflow_dispatch'
run: node scripts/rename-test-build-artifacts.mjs --flatpak .

# Artifact name ends with .flatpak so publish flatten → flatpak-dist/*.flatpak matches.
- name: Upload Flatpak bundle
uses: actions/upload-artifact@v7
with:
name: org.coloradomesh.MeshClient.flatpak-${{ matrix.arch }}.flatpak
path: |
org.coloradomesh.MeshClient*.flatpak
if-no-files-found: error
Comment thread
coderabbitai[bot] marked this conversation as resolved.
retention-days: 30

# Schema warning beside the bundle for Actions downloads.
- name: Upload READ-ME-FIRST with Flatpak artifacts
uses: actions/upload-artifact@v7
with:
Expand All @@ -219,7 +252,7 @@ jobs:

- uses: actions/download-artifact@v8
with:
pattern: 'org.coloradomesh.MeshClient-*'
pattern: 'org.coloradomesh.MeshClient.flatpak-*.flatpak'
path: flatpak-dist

- name: Flatten arch-suffixed bundles for release
Expand Down
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,8 @@ coverage/
.rtk
.githooks/bin/
flatpak/generated-sources.json
# Written by scripts/write-flatpak-ci-build-info.mjs in Flatpak CI
flatpak/ci-build-info.json

# Rust reticulum sidecar (cargo build output)
reticulum-sidecar/target/
Expand Down
34 changes: 25 additions & 9 deletions docs/ci-cd.md
Original file line number Diff line number Diff line change
Expand Up @@ -124,10 +124,11 @@ A matrix builds **x86_64** and **aarch64** in parallel. Both use the same privil

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)
3. Stamps CI build info (`test` on dispatch / `release` on tag), builds from `org.coloradomesh.MeshClient.yml` with offline pnpm sources
4. Smoke-installs the unstamped local bundle; on **dispatch only**, renames to `org.coloradomesh.MeshClient-run{N}.flatpak`
5. Uploads `org.coloradomesh.MeshClient.flatpak-{x86_64,aarch64}.flatpak` artifacts (file basename stamped on test builds) plus per-arch `flatpak-schema-warning-*`

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).
On **version tag pushes**, a `publish` job attaches both **clean-named** bundles to the GitHub Release. aarch64 is the primary ARM Linux install path (release `build.yaml` only produces x86_64 AppImage/deb/rpm).

`flatpak/generated-sources.json` is generated automatically in CI by `flatpak-node-generator` before each build — it does not need to be committed to the repo. For local builds, generate it manually; see [development-environment.md](development-environment.md) for steps. If submitting to Flathub's dedicated submission repo, the file must be committed there.

Expand Down Expand Up @@ -313,16 +314,31 @@ CI focuses on lint, typecheck, build, Flatpak metadata validation, and coverage

### Build channel stamp (test vs release)

**Build Binaries** (`build.yaml`) and **Release** (`release.yaml`) run `scripts/ci-write-build-info-env.mjs` before packaging. That writes a JSON `MESH_CLIENT_BUILD_INFO` blob into `$GITHUB_ENV`, which `scripts/esbuild-main-build.mjs` embeds via esbuild `--define` into the main process.
**Build Binaries** (`build.yaml`), **Release** (`release.yaml`), and **Build Flatpak** (`flatpak.yaml`) run `scripts/ci-write-build-info-env.mjs` before packaging. That writes a JSON `MESH_CLIENT_BUILD_INFO` blob into `$GITHUB_ENV`, which `scripts/esbuild-main-build.mjs` embeds via esbuild `--define` into the main process. Flatpak also writes `flatpak/ci-build-info.json` (gitignored) so the sandbox `pnpm run build` sees the same env.

| Channel | Workflow | Support-bundle `manifest.json` |
| --------- | ------------------------------ | --------------------------------------------------------- |
| `test` | Build Binaries (no release) | `buildChannel: "test"` + `buildInfo.runUrl` (Actions run) |
| `release` | Build/Release Electron App | `buildChannel: "release"` + `tag` + `buildInfo.runUrl` |
| `local` | unmarked `pnpm run dist` / dev | `buildChannel: "local"` only |
| Channel | Workflow | Support-bundle `manifest.json` |
| --------- | ------------------------------------------------------- | --------------------------------------------------------- |
| `test` | Build Binaries (no release); Build Flatpak (no release) | `buildChannel: "test"` + `buildInfo.runUrl` (Actions run) |
| `release` | Build/Release Electron App; Build Flatpak (tag) | `buildChannel: "release"` + `tag` + `buildInfo.runUrl` |
| `local` | unmarked `pnpm run dist` / dev / local Flatpak | `buildChannel: "local"` only |

`appVersion` remains `package.json` semver (unchanged). Use `buildChannel` + `buildInfo.runUrl` when triaging Export for GitHub / Developer zips so a test binary is not mistaken for an official release. Startup logs include a compact fragment (`buildChannel=… run=… runId=… sha=…`).

**Which binary am I running?** If a tester says they downloaded Actions run N but the app reports a different run, open **Export for GitHub** → `manifest.json` → `buildInfo.runUrl` (authoritative), or the `[Startup] runtime … run=…` line in the app log. Same-semver test installers used to share identical filenames across runs; test builds now stamp `-run{N}` into downloadable basenames (see below).

### Test-build installer filenames (`-run{N}`)

**Test / one-off only** — never official GitHub Release assets:

| Workflow | When | Filename stamp |
| -------------- | -------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `build.yaml` | Always (dispatch-only) | After `dist:*`, `scripts/rename-test-build-artifacts.mjs` renames AppImage/deb/rpm/DMG/ZIP/Setup under `release/` to include `-run{GITHUB_RUN_NUMBER}` (e.g. `Mesh-client-5.26.0-run214.AppImage`, `Mesh-client Setup 5.26.0-run214.exe`) |
| `flatpak.yaml` | `workflow_dispatch` only | After in-job smoke, rename to `org.coloradomesh.MeshClient-run{N}.flatpak`, then upload |
| `flatpak.yaml` | tag `v*` (release publish) | Clean `org.coloradomesh.MeshClient.flatpak` (no `-run{N}`) |
| `release.yaml` | tag publish | Clean electron-builder names (no rename step) |

`packaging-smoke` on Build Binaries downloads **stamped** names (Windows Setup matcher accepts default or `-run{N}`). Flatpak smoke always uses the unstamped local path **before** rename. Manual Flatpak runs use Actions run title **`Build Flatpak (no release)`**; tag runs use **`Build Flatpak`**.

### Schema compare vs last official release

**Build Binaries**, **Build Flatpak**, and **Release** start with a **`schema-release-compare`** job (`scripts/ci-schema-release-compare.mjs`) that:
Expand Down
2 changes: 1 addition & 1 deletion docs/credits.md
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ Exact semver ranges live in [`package.json`](https://github.com/Colorado-Mesh/me
| -------------------------------- | -------------------------------------------------- | --------------- | -------------------------------- |
| @axe-core/react | ^4.12.1 | MPL-2.0 | Accessibility testing |
| @eslint/js | ^10.0.1 | MIT | ESLint flat-config helpers |
| @liamcottle/meshcore.js | ^1.13.0 | MIT | MeshCore JS library |
| @liamcottle/meshcore.js | ^1.14.0 | MIT | MeshCore JS library |
| @meshtastic/core | npm:@jsr/meshtastic\_\_core@^2.6.6 | Apache-2.0 | Meshtastic core |
| @meshtastic/transport-http | npm:@jsr/meshtastic\_\_transport-http@^0.2.1 | Apache-2.0 | HTTP transport |
| @meshtastic/transport-web-serial | npm:@jsr/meshtastic\_\_transport-web-serial@^0.2.5 | Apache-2.0 | Web Serial transport |
Expand Down
4 changes: 2 additions & 2 deletions docs/release-process.md
Original file line number Diff line number Diff line change
Expand Up @@ -169,8 +169,8 @@ Build jobs also run `verify-reticulum-sidecar-staged.mjs` after staging sidecars

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)
3. **`flatpak`** — stamps CI build info, writes schema upgrade notice when bumped, generates offline pnpm sources, builds `org.coloradomesh.MeshClient.flatpak` per arch inside the Flathub freedesktop 24.08 container, smoke-installs the unstamped bundle (manual **Build Flatpak (no release)** dispatch also renames downloadable artifacts to `…-run{N}.flatpak`; tag runs keep clean names)
4. **`publish`** (tag only) — attaches both clean-named `.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.

Expand Down
Loading