mirror of
https://github.com/meshtastic/Meshtastic-Android.git
synced 2026-07-13 14:52:12 -04:00
refactor(flatpak): retire heuristic cache scanner, adopt build-ops capture (#5599)
Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
60
scripts/verify-flatpak/README.md
Normal file
60
scripts/verify-flatpak/README.md
Normal file
@@ -0,0 +1,60 @@
|
||||
# Local Flatpak Verification
|
||||
|
||||
Replicates vid's `org.meshtastic.desktop` GHA flatpak build on your machine so you
|
||||
can validate `flatpak-sources.json` end-to-end without round-tripping through his repo.
|
||||
|
||||
## What it tests that our CI doesn't
|
||||
|
||||
Our CI (`:desktopApp:assemble :captureFlatpakSources`) only proves the manifest can be *generated*.
|
||||
Vid's CI is where the manifest actually gets *consumed* by `flatpak-builder`. This script
|
||||
runs that step locally:
|
||||
|
||||
1. Clones `vidplace7/org.meshtastic.desktop`.
|
||||
2. Overlays a patched manifest that:
|
||||
- Swaps the `meshtastic/Meshtastic-Android.git` source for a `type: dir` pointing at
|
||||
**your local checkout** (so you can test uncommitted changes).
|
||||
- Uncomments `- flatpak-sources.json`.
|
||||
- Drops `--share=network` from the build-args (true offline — what Flathub requires).
|
||||
- Adds `--offline` to the Gradle invocation (belt + suspenders).
|
||||
3. Runs `flatpak-builder` in a Docker container with the same Freedesktop 25.08 SDK
|
||||
vid's GHA image uses.
|
||||
|
||||
If your `flatpak-sources.json` has the wrong URL, wrong sha256, or a missing entry,
|
||||
the build fails with the same error vid would see. You can iterate in ~5–15 min loops
|
||||
instead of waiting on cross-repo CI.
|
||||
|
||||
## Prerequisites
|
||||
|
||||
- Docker (Docker Desktop on macOS works — the container needs `--privileged` to use
|
||||
bubblewrap; that's enabled by default).
|
||||
- ~10 GB free disk for the SDK + Gradle cache.
|
||||
- A populated Gradle cache (`./gradlew :desktopApp:assemble` must have run; the script
|
||||
does this implicitly via `:captureFlatpakSources`).
|
||||
|
||||
## Usage
|
||||
|
||||
```bash
|
||||
# Full offline build (~10–20 min the first time, faster after — Docker image is cached)
|
||||
scripts/verify-flatpak/verify.sh
|
||||
|
||||
# Cross-arch test via QEMU emulation (slower)
|
||||
scripts/verify-flatpak/verify.sh --arch aarch64
|
||||
|
||||
# Drop into the builder container shell to poke at things
|
||||
scripts/verify-flatpak/verify.sh --shell
|
||||
```
|
||||
|
||||
## Interpreting failures
|
||||
|
||||
| Symptom | Likely cause |
|
||||
| ---------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------- |
|
||||
| `Error downloading mirror: ... 404` on `repo.maven.apache.org` | URL captured by the listener was wrong or artifact moved. Check the source repo hosting it. |
|
||||
| `sha256 mismatch` | Stale `flatpak-sources.json`; re-run `:desktopApp:assemble :captureFlatpakSources`. |
|
||||
| Gradle: `Could not resolve all artifacts ... offline mode` | Missing dep in the manifest — usually a compiler plugin or BOM that wasn't downloaded during capture. |
|
||||
|
||||
## Files
|
||||
|
||||
- `verify.sh` — entry point. Idempotent: re-running just re-syncs the overlay and re-runs flatpak-builder.
|
||||
- `desktop-offline.yaml` — patched manifest. Kept in sync manually with vid's upstream;
|
||||
diff against `https://raw.githubusercontent.com/vidplace7/org.meshtastic.desktop/main/org.meshtastic.desktop.yaml`
|
||||
if vid changes something material.
|
||||
97
scripts/verify-flatpak/desktop-offline.yaml
Normal file
97
scripts/verify-flatpak/desktop-offline.yaml
Normal file
@@ -0,0 +1,97 @@
|
||||
# Local offline verification of org.meshtastic.desktop.
|
||||
# Differences from vid's upstream manifest (vidplace7/org.meshtastic.desktop):
|
||||
# 1. Meshtastic-Android source: `type: dir` pointing at our local checkout instead of `type: git`.
|
||||
# 2. flatpak-sources.json is INCLUDED (uncommented) so Gradle resolves from the offline-repository.
|
||||
# 3. Build uses `--offline` for Gradle — true Flathub-style offline compilation.
|
||||
# (finish-args still grants runtime network since the app needs it; only the build is offline.)
|
||||
# Generated by scripts/verify-flatpak/verify.sh; do not edit upstream from here.
|
||||
|
||||
id: org.meshtastic.desktop
|
||||
runtime: org.freedesktop.Platform
|
||||
runtime-version: '25.08'
|
||||
sdk: org.freedesktop.Sdk
|
||||
sdk-extensions:
|
||||
- org.freedesktop.Sdk.Extension.openjdk17
|
||||
- org.freedesktop.Sdk.Extension.openjdk21
|
||||
command: meshtastic-wrapper.sh
|
||||
|
||||
finish-args:
|
||||
- --share=ipc
|
||||
- --socket=x11
|
||||
- --device=dri
|
||||
- --device=all
|
||||
- --share=network
|
||||
- --talk-name=org.kde.StatusNotifierWatcher
|
||||
- --talk-name=org.freedesktop.Notifications
|
||||
- --allow=bluetooth
|
||||
- --system-talk-name=org.bluez.*
|
||||
- --env=PATH=/app/jre/bin:/app/bin:/usr/bin
|
||||
- --env=JAVA_HOME=/app/jre
|
||||
|
||||
modules:
|
||||
- name: jbr
|
||||
buildsystem: simple
|
||||
build-commands:
|
||||
- mkdir -p /app/jre
|
||||
- tar xzf jbr-*.tar.gz -C /app/jre --strip-components=1
|
||||
sources:
|
||||
- type: file
|
||||
url: https://cache-redirector.jetbrains.com/intellij-jbr/jbr-21.0.10-linux-x64-b1163.105.tar.gz
|
||||
sha256: b6a3b13451d296140727bbde9325dd9ee422e2e9b2c6a9378f346f1b8d1111bc
|
||||
only-arches:
|
||||
- x86_64
|
||||
- type: file
|
||||
url: https://cache-redirector.jetbrains.com/intellij-jbr/jbr-21.0.10-linux-aarch64-b1163.105.tar.gz
|
||||
sha256: 38804f526d869f5a9c49e9b90c04edcbc918b41e8e43264e5d5076d352a959bc
|
||||
only-arches:
|
||||
- aarch64
|
||||
|
||||
- shared-modules/libappindicator/libappindicator-gtk3-12.10.json
|
||||
|
||||
- name: meshtastic-wrapper
|
||||
buildsystem: simple
|
||||
build-commands:
|
||||
- install -Dm755 meshtastic-wrapper.sh /app/bin/meshtastic-wrapper.sh
|
||||
sources:
|
||||
- type: file
|
||||
path: meshtastic-wrapper.sh
|
||||
|
||||
- name: meshtastic-desktop
|
||||
buildsystem: simple
|
||||
build-options:
|
||||
append-path: "/usr/lib/sdk/openjdk21/bin"
|
||||
env:
|
||||
JAVA_HOME: /usr/lib/sdk/openjdk21/jvm/openjdk-21
|
||||
# Point Gradle at the offline mirror produced by flatpak-sources.json
|
||||
GRADLE_USER_HOME: /run/build/meshtastic-desktop/.gradle
|
||||
build-commands:
|
||||
- install -Dm644 -t /app/share/icons/hicolor/scalable/apps org.meshtastic.desktop.svg
|
||||
- install -Dm644 -t /app/share/applications org.meshtastic.desktop.desktop
|
||||
- install -Dm644 -t /app/share/metainfo org.meshtastic.desktop.metainfo.xml
|
||||
- echo "org.gradle.java.installations.auto-detect=false" >> gradle.properties
|
||||
- echo "org.gradle.java.installations.auto-download=false" >> gradle.properties
|
||||
- echo "org.gradle.java.installations.paths=/usr/lib/sdk/openjdk21/jvm/openjdk-21,/usr/lib/sdk/openjdk17/jvm/openjdk-17" >> gradle.properties
|
||||
- >
|
||||
sed -i
|
||||
's/^\(\s*\)vendor\.set(JvmVendorSpec\.JETBRAINS)/\1\/\/ vendor.set(JvmVendorSpec.JETBRAINS)/'
|
||||
desktop/build.gradle.kts
|
||||
# Force Gradle to resolve from the bundled offline-repository ONLY (true offline test).
|
||||
- ./gradlew --offline :desktop:packageUberJarForCurrentOS
|
||||
- >
|
||||
JAR_FILE=$(find desktop/build/compose/jars/ -name "*.jar" -type f | head -1)
|
||||
&& install -Dm755 "$JAR_FILE" /app/lib/meshtastic-desktop.jar
|
||||
sources:
|
||||
- type: file
|
||||
path: org.meshtastic.desktop.desktop
|
||||
- type: file
|
||||
path: org.meshtastic.desktop.metainfo.xml
|
||||
- type: file
|
||||
path: org.meshtastic.desktop.svg
|
||||
- type: dir
|
||||
path: meshtastic-android
|
||||
- type: file
|
||||
url: https://services.gradle.org/distributions/gradle-9.4.1-bin.zip
|
||||
sha256: 2ab2958f2a1e51120c326cad6f385153bb11ee93b3c216c5fccebfdfbb7ec6cb
|
||||
dest: "gradle/wrapper"
|
||||
dest-filename: "gradle-bin.zip"
|
||||
- flatpak-sources.json
|
||||
116
scripts/verify-flatpak/verify.sh
Executable file
116
scripts/verify-flatpak/verify.sh
Executable file
@@ -0,0 +1,116 @@
|
||||
#!/usr/bin/env bash
|
||||
# Local replica of vid's flatpak CI (vidplace7/org.meshtastic.desktop, .github/workflows/build-flatpak.yml)
|
||||
# but flipped to true-offline mode: our flatpak-sources.json is included and --share=network is removed.
|
||||
#
|
||||
# Goal: validate flatpak-sources.json without bugging vid to push & re-run his workflow.
|
||||
#
|
||||
# Requirements:
|
||||
# - Docker (Docker Desktop on macOS is fine; needs ~10GB free + ability to run --privileged)
|
||||
# - This Meshtastic-Android checkout has produced flatpak-sources.json
|
||||
# (run `./gradlew :desktopApp:assemble :captureFlatpakSources` first, or this script will do it)
|
||||
#
|
||||
# Usage:
|
||||
# scripts/verify-flatpak/verify.sh # full build, x86_64
|
||||
# scripts/verify-flatpak/verify.sh --arch aarch64 # cross-arch via QEMU emulation
|
||||
# scripts/verify-flatpak/verify.sh --shell # drop into the container shell instead of building
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
ARCH="x86_64"
|
||||
DROP_TO_SHELL=0
|
||||
while [[ $# -gt 0 ]]; do
|
||||
case "$1" in
|
||||
--arch) ARCH="$2"; shift 2 ;;
|
||||
--shell) DROP_TO_SHELL=1; shift ;;
|
||||
-h|--help) sed -n '2,17p' "$0"; exit 0 ;;
|
||||
*) echo "Unknown arg: $1" >&2; exit 2 ;;
|
||||
esac
|
||||
done
|
||||
|
||||
# Map flatpak arch names to docker platform names
|
||||
case "$ARCH" in
|
||||
x86_64) DOCKER_PLATFORM="linux/amd64" ;;
|
||||
aarch64) DOCKER_PLATFORM="linux/arm64" ;;
|
||||
*) echo "Unsupported --arch: $ARCH (use x86_64 or aarch64)" >&2; exit 2 ;;
|
||||
esac
|
||||
|
||||
REPO_ROOT="$(git -C "$(dirname "$0")" rev-parse --show-toplevel)"
|
||||
WORK="$REPO_ROOT/build/flatpak-verify"
|
||||
OVERLAY="$REPO_ROOT/scripts/verify-flatpak/desktop-offline.yaml"
|
||||
SOURCES_JSON="$REPO_ROOT/flatpak-sources.json"
|
||||
VID_REPO="https://github.com/vidplace7/org.meshtastic.desktop.git"
|
||||
|
||||
# Image provides flatpak + flatpak-builder. The freedesktop 25.08 runtime declared in
|
||||
# the manifest is pulled from flathub at build time (no 25.08 image exists yet; 24.08 is
|
||||
# fine as the builder host because the SDK used at compile time comes from flathub).
|
||||
BUILDER_IMAGE="bilelmoussaoui/flatpak-github-actions:freedesktop-24.08"
|
||||
|
||||
step() { printf '\n\033[1;34m==> %s\033[0m\n' "$*"; }
|
||||
fail() { printf '\033[1;31m!! %s\033[0m\n' "$*" >&2; exit 1; }
|
||||
|
||||
command -v docker >/dev/null 2>&1 || fail "docker is required; install Docker Desktop or equivalent."
|
||||
|
||||
step "Ensuring flatpak-sources.json is fresh"
|
||||
if [[ ! -f "$SOURCES_JSON" ]]; then
|
||||
(cd "$REPO_ROOT" && ./gradlew --no-build-cache --no-configuration-cache :desktopApp:assemble :captureFlatpakSources)
|
||||
cp "$REPO_ROOT/build/flatpak-ops-sources.json" "$SOURCES_JSON"
|
||||
fi
|
||||
|
||||
step "Preparing workspace at $WORK"
|
||||
mkdir -p "$WORK"
|
||||
if [[ ! -d "$WORK/org.meshtastic.desktop/.git" ]]; then
|
||||
git clone --depth 1 --recurse-submodules "$VID_REPO" "$WORK/org.meshtastic.desktop"
|
||||
else
|
||||
git -C "$WORK/org.meshtastic.desktop" fetch --depth 1 origin main
|
||||
git -C "$WORK/org.meshtastic.desktop" reset --hard origin/main
|
||||
git -C "$WORK/org.meshtastic.desktop" submodule update --init --recursive --depth 1
|
||||
fi
|
||||
|
||||
step "Wiring overlay manifest + our flatpak-sources.json"
|
||||
cp "$OVERLAY" "$WORK/org.meshtastic.desktop/org.meshtastic.desktop.yaml"
|
||||
cp "$SOURCES_JSON" "$WORK/org.meshtastic.desktop/flatpak-sources.json"
|
||||
|
||||
# Materialize a clean copy of our checkout (excluding build outputs) for `type: dir`.
|
||||
# flatpak-builder copies the whole tree — skip heavy/irrelevant paths.
|
||||
step "Snapshotting Meshtastic-Android checkout (excluding build/, .gradle/)"
|
||||
rsync -a --delete \
|
||||
--exclude='/build/' \
|
||||
--exclude='/.gradle/' \
|
||||
--exclude='*/build/' \
|
||||
--exclude='*/.gradle/' \
|
||||
--exclude='/.idea/' \
|
||||
--exclude='/local.properties' \
|
||||
"$REPO_ROOT/" "$WORK/org.meshtastic.desktop/meshtastic-android/"
|
||||
|
||||
step "Pulling builder image: $BUILDER_IMAGE ($DOCKER_PLATFORM)"
|
||||
docker pull --platform "$DOCKER_PLATFORM" "$BUILDER_IMAGE" >/dev/null
|
||||
|
||||
if [[ $DROP_TO_SHELL -eq 1 ]]; then
|
||||
step "Dropping into builder shell — flatpak-builder is on PATH"
|
||||
exec docker run --rm -it --privileged \
|
||||
-v "$WORK/org.meshtastic.desktop:/work" \
|
||||
-w /work \
|
||||
--platform "$DOCKER_PLATFORM" \
|
||||
--security-opt seccomp=unconfined \
|
||||
"$BUILDER_IMAGE" bash
|
||||
fi
|
||||
|
||||
step "Running flatpak-builder (arch=$ARCH)"
|
||||
docker run --rm --privileged \
|
||||
-v "$WORK/org.meshtastic.desktop:/work" \
|
||||
-w /work \
|
||||
--platform "$DOCKER_PLATFORM" \
|
||||
--security-opt seccomp=unconfined \
|
||||
"$BUILDER_IMAGE" \
|
||||
bash -c "set -e
|
||||
flatpak remote-add --user --if-not-exists flathub https://dl.flathub.org/repo/flathub.flatpakrepo
|
||||
# --download-only verifies every source URL + sha256 and exits before the bwrap
|
||||
# sandbox phase. We do this because nested bwrap fails inside Docker Desktop on
|
||||
# macOS (prctl(PR_SET_SECCOMP) EINVAL). For full sandbox build, run on Linux directly
|
||||
# — or rely on vid's GHA CI which uses bare ubuntu-24.04 runners.
|
||||
flatpak-builder --user --repo=repo --install-deps-from=flathub --force-clean \
|
||||
--disable-rofiles-fuse --download-only \
|
||||
builddir org.meshtastic.desktop.yaml
|
||||
echo
|
||||
echo '=== All sources downloaded and sha256-verified successfully ==='
|
||||
"
|
||||
Reference in New Issue
Block a user