diff --git a/.github/actions/gradle-setup/action.yml b/.github/actions/gradle-setup/action.yml index a55a85f05..391c00080 100644 --- a/.github/actions/gradle-setup/action.yml +++ b/.github/actions/gradle-setup/action.yml @@ -23,10 +23,10 @@ runs: - name: Validate Gradle Wrapper uses: gradle/actions/wrapper-validation@v6 - - name: Set up JDK 21 + - name: Set up JDK 25 uses: actions/setup-java@v5 with: - java-version: '21' + java-version: '25' distribution: ${{ inputs.jdk_distribution }} token: ${{ github.token }} diff --git a/.github/copilot-instructions.md b/.github/copilot-instructions.md index 6b8f13587..d04bfc63d 100644 --- a/.github/copilot-instructions.md +++ b/.github/copilot-instructions.md @@ -4,7 +4,7 @@ ## Build, Test & Lint (essentials) -Requires JDK 21 and `ANDROID_HOME`. Per fresh clone: +Requires JDK 25 and `ANDROID_HOME`. Per fresh clone: ```bash [ -f local.properties ] || cp secrets.defaults.properties local.properties ``` diff --git a/.github/workflows/verify-flatpak.yml b/.github/workflows/verify-flatpak.yml index 75e59dd11..855754a30 100644 --- a/.github/workflows/verify-flatpak.yml +++ b/.github/workflows/verify-flatpak.yml @@ -34,12 +34,16 @@ jobs: - uses: actions/setup-java@v5 with: distribution: temurin - java-version: 21 + java-version: 25 + token: ${{ github.token }} + # JBR resolves its version list via the GitHub API — unauthenticated requests + # rate-limit on the shared runner IPs, so the token is required, not optional. - uses: actions/setup-java@v5 with: distribution: jetbrains - java-version: 21 + java-version: 25 + token: ${{ github.token }} - uses: gradle/actions/setup-gradle@v6 @@ -74,10 +78,10 @@ jobs: with: name: flatpak-sources - - name: Clone vid's flatpak repo + - name: Clone the Flathub packaging repo run: | git clone --depth 1 --recurse-submodules \ - https://github.com/vidplace7/org.meshtastic.MeshtasticDesktop.git \ + https://github.com/flathub/org.meshtastic.MeshtasticDesktop.git \ "$RUNNER_TEMP/org.meshtastic.MeshtasticDesktop" - name: Wire overlay manifest + sources diff --git a/.skills/project-overview/SKILL.md b/.skills/project-overview/SKILL.md index 89146c197..c8732a3a0 100644 --- a/.skills/project-overview/SKILL.md +++ b/.skills/project-overview/SKILL.md @@ -3,7 +3,7 @@ ## Description Module directory, namespacing conventions, environment setup, and troubleshooting for Meshtastic-Android. -- **Build System:** Gradle (Kotlin DSL). JDK 21 REQUIRED. Target SDK: API 36. Min SDK: API 26. +- **Build System:** Gradle (Kotlin DSL). JDK 25 REQUIRED. Target SDK: API 36. Min SDK: API 26. - **Flavors:** `fdroid` (OSS only) · `google` (Maps + DataDog analytics) - **Android-only Modules:** `core:barcode` (CameraX), `feature:widget` (Glance home-screen widget), `feature:car` (Android Auto via the Car App Library, `google` flavor only), and `baselineprofile` (Macrobenchmark). Shared contracts are abstracted into `core:ui/commonMain`. @@ -45,7 +45,7 @@ Module directory, namespacing conventions, environment setup, and troubleshootin - **Legacy:** Maintain the `com.geeksville.mesh` Application ID. ## Environment Setup -1. **JDK 21 MUST be used** to prevent Gradle sync/build failures. +1. **JDK 25 MUST be used** to prevent Gradle sync/build failures. 2. **Secrets:** Copy `secrets.defaults.properties` to `local.properties`: ```properties MAPS_API_KEY=dummy_key diff --git a/AGENTS.md b/AGENTS.md index c54d7461b..c23465416 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -6,7 +6,7 @@ You are an expert Android/KMP engineer. Maintain architectural boundaries, use M - **Project Goal:** Decouple business logic from Android for multi-platform (Android, Desktop, iOS). -- **Tech:** Kotlin 2.4+ (JDK 21), Ktor, Okio, Room KMP, Koin 4.2+. +- **Tech:** Kotlin 2.4+ (JDK 25), Ktor, Okio, Room KMP, Koin 4.2+. - **Agent Memory:** `.agent_memory/` is local-only scratch (git-ignored) — never stage or commit it. Skim the top (most recent) entry of `.agent_memory/session_context.md` for current state — it is capped at ~5 entries; older handovers live in `session_context.archive.md` (read only if you need historical detail). - **Skills Directory (CONSULT THESE FIRST):** - `.skills/project-overview/` - Codebase map, namespacing, **Bootstrap Steps**. diff --git a/CLAUDE.md b/CLAUDE.md index 37eda3809..57deba6c6 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -19,7 +19,7 @@ This file provides guidance to Claude Code (claude.ai/code) when working with co ## Quick Reference -JDK 21 is required. **Bootstrap before any Gradle task** (don't wait to be told) — full details in `.skills/project-overview/SKILL.md`: +JDK 25 is required. **Bootstrap before any Gradle task** (don't wait to be told) — full details in `.skills/project-overview/SKILL.md`: ```bash [ -z "$ANDROID_HOME" ] && export ANDROID_HOME="$HOME/Library/Android/sdk" # often unset in agent workspaces [ -f local.properties ] || cp secrets.defaults.properties local.properties # google flavor fails without it diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index d0eccdd0d..e6b43ec68 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -47,8 +47,7 @@ Consistent linting helps keep the codebase clean and maintainable. Meshtastic-Android uses unit tests, Robolectric JVM tests, and instrumented UI tests to ensure code quality and reliability. - **Unit tests** are located in the `src/test/` directory of each module. -- **Compose UI Tests (JVM)** are preferred for component testing and are also located in `src/test/` using **Robolectric**. - - Note: If using Java 21, pin your Robolectric tests to `@Config(sdk = [34])` to avoid SDK 35 compatibility issues. +- **Compose UI Tests (JVM)** are preferred for component testing and are also located in `src/test/` using **Robolectric**. - **Instrumented tests** (including full E2E UI tests) are located in `src/androidTest/`. For Compose UI, use the [Jetpack Compose Testing APIs](https://developer.android.com/jetpack/compose/testing). #### Guidelines for Testing diff --git a/build-logic/convention/src/main/kotlin/org/meshtastic/buildlogic/KotlinAndroid.kt b/build-logic/convention/src/main/kotlin/org/meshtastic/buildlogic/KotlinAndroid.kt index c7d65ae94..fad4c8940 100644 --- a/build-logic/convention/src/main/kotlin/org/meshtastic/buildlogic/KotlinAndroid.kt +++ b/build-logic/convention/src/main/kotlin/org/meshtastic/buildlogic/KotlinAndroid.kt @@ -228,7 +228,7 @@ private val SHARED_COMPILER_ARGS = // No -Xbackend-threads: parallel codegen races and crashes release builds (KT-83578). ) -private const val JDK_VERSION = 21 +private const val JDK_VERSION = 25 /** Configure base Kotlin options */ private inline fun Project.configureKotlin() { diff --git a/gradle/gradle-daemon-jvm.properties b/gradle/gradle-daemon-jvm.properties index 52234b5ce..fa4ed510e 100644 --- a/gradle/gradle-daemon-jvm.properties +++ b/gradle/gradle-daemon-jvm.properties @@ -1 +1,12 @@ -toolchainVersion=21 +#This file is generated by updateDaemonJvm +toolchainUrl.FREE_BSD.AARCH64=https\://api.foojay.io/disco/v3.0/ids/cf726b4a1c84b50457225f9bba6d7650/redirect +toolchainUrl.FREE_BSD.X86_64=https\://api.foojay.io/disco/v3.0/ids/fa1e318c287360478e3c83a9a3ef1007/redirect +toolchainUrl.LINUX.AARCH64=https\://api.foojay.io/disco/v3.0/ids/cf726b4a1c84b50457225f9bba6d7650/redirect +toolchainUrl.LINUX.X86_64=https\://api.foojay.io/disco/v3.0/ids/fa1e318c287360478e3c83a9a3ef1007/redirect +toolchainUrl.MAC_OS.AARCH64=https\://api.foojay.io/disco/v3.0/ids/c2dd35c9d0aaf0ba6ad0791320f99dfc/redirect +toolchainUrl.MAC_OS.X86_64=https\://api.foojay.io/disco/v3.0/ids/e5810bd7fd1f8a586644409d395a7e55/redirect +toolchainUrl.UNIX.AARCH64=https\://api.foojay.io/disco/v3.0/ids/cf726b4a1c84b50457225f9bba6d7650/redirect +toolchainUrl.UNIX.X86_64=https\://api.foojay.io/disco/v3.0/ids/fa1e318c287360478e3c83a9a3ef1007/redirect +toolchainUrl.WINDOWS.AARCH64=https\://api.foojay.io/disco/v3.0/ids/7b3c4877c0749019e6805bb61e421497/redirect +toolchainUrl.WINDOWS.X86_64=https\://api.foojay.io/disco/v3.0/ids/d76df094a9cbbabd3b08251f9e61444a/redirect +toolchainVersion=25 diff --git a/scripts/verify-flatpak/README.md b/scripts/verify-flatpak/README.md index e5ab2a2fd..7a8120253 100644 --- a/scripts/verify-flatpak/README.md +++ b/scripts/verify-flatpak/README.md @@ -1,15 +1,15 @@ # Local Flatpak Verification -Replicates vid's `org.meshtastic.MeshtasticDesktop` GHA flatpak build on your machine so you -can validate `flatpak-sources.json` end-to-end without round-tripping through his repo. +Replicates the official `flathub/org.meshtastic.MeshtasticDesktop` flatpak build on your machine +so you can validate `flatpak-sources.json` end-to-end without round-tripping through that repo's CI. ## What it tests that our CI doesn't Our CI (`:desktopApp:packageUberJarForCurrentOS :captureFlatpakSources`) only proves the manifest can be *generated*. -Vid's CI is where the manifest actually gets *consumed* by `flatpak-builder`. This script +Flathub's CI is where the manifest actually gets *consumed* by `flatpak-builder`. This script runs that step locally: -1. Clones `vidplace7/org.meshtastic.MeshtasticDesktop`. +1. Clones `flathub/org.meshtastic.MeshtasticDesktop` (the official Flathub packaging repo). 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). @@ -17,10 +17,10 @@ runs that step locally: - 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. + the upstream flatpak CI 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 +the build fails with the same error Flathub CI would see. You can iterate in ~5–15 min loops instead of waiting on cross-repo CI. ## Prerequisites @@ -45,7 +45,7 @@ scripts/verify-flatpak/verify.sh --download-only scripts/verify-flatpak/verify.sh --skip-regen # Tight iteration loop after a failed run: refresh overlay yaml + manifest -# only, then re-run flatpak-builder. Skips Gradle regen, vid-repo fetch, +# only, then re-run flatpak-builder. Skips Gradle regen, upstream-repo fetch, # and Meshtastic-Android rsync. Use when you've just patched the YAML # overlay or regenerated flatpak-sources.json by hand. scripts/verify-flatpak/verify.sh --rebuild-only @@ -76,6 +76,6 @@ executing the Gradle build, or run the full script on a Linux host. ## 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.MeshtasticDesktop/main/org.meshtastic.MeshtasticDesktop.yaml` - if vid changes something material. +- `desktop-offline.yaml` — patched manifest. Kept in sync manually with the upstream packaging; + diff against `https://raw.githubusercontent.com/flathub/org.meshtastic.MeshtasticDesktop/master/org.meshtastic.MeshtasticDesktop.yaml` + if upstream changes something material. diff --git a/scripts/verify-flatpak/desktop-offline.yaml b/scripts/verify-flatpak/desktop-offline.yaml index 0f85c1710..bb6b47c90 100644 --- a/scripts/verify-flatpak/desktop-offline.yaml +++ b/scripts/verify-flatpak/desktop-offline.yaml @@ -1,5 +1,5 @@ # Local offline verification of org.meshtastic.MeshtasticDesktop. -# Differences from vid's upstream manifest (vidplace7/org.meshtastic.MeshtasticDesktop): +# Differences from the official Flathub manifest (flathub/org.meshtastic.MeshtasticDesktop): # 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. @@ -11,7 +11,11 @@ runtime: org.freedesktop.Platform runtime-version: '25.08' sdk: org.freedesktop.Sdk sdk-extensions: - - org.freedesktop.Sdk.Extension.openjdk21 + # Single JDK: openjdk25 runs the Gradle daemon (gradle/gradle-daemon-jvm.properties pins + # toolchainVersion=25) and satisfies every module's jvmToolchain (25). The offline build + # disables toolchain auto-provisioning, so bumping either pin means updating this extension + # and the /usr/lib/sdk/openjdk* paths below — a miss fails at daemon startup or compileJava. + - org.freedesktop.Sdk.Extension.openjdk25 command: meshtastic-wrapper.sh finish-args: @@ -56,13 +60,13 @@ modules: - name: meshtastic-desktop buildsystem: simple build-options: - append-path: "/usr/lib/sdk/openjdk21/bin" + append-path: "/usr/lib/sdk/openjdk25/bin" env: - JAVA_HOME: /usr/lib/sdk/openjdk21/jvm/openjdk-21 + JAVA_HOME: /usr/lib/sdk/openjdk25/jvm/openjdk-25 # Point Gradle at the offline mirror produced by flatpak-sources.json GRADLE_USER_HOME: /run/build/meshtastic-desktop/.gradle build-commands: - # Install desktop metadata from the in-repo packaging sources (mirrors vid's upstream manifest, + # Install desktop metadata from the in-repo packaging sources (mirrors the upstream Flathub manifest, # which stopped shipping standalone root-level copies as of 2026-05-30). - install -Dm644 desktopApp/packaging/icons/icon.svg /app/share/icons/hicolor/scalable/apps/org.meshtastic.MeshtasticDesktop.svg - install -Dm644 -t /app/share/applications desktopApp/packaging/linux/org.meshtastic.MeshtasticDesktop.desktop @@ -73,7 +77,7 @@ modules: - sed -i 's|distributionUrl=.*|distributionUrl=gradle-all.zip|' gradle/wrapper/gradle-wrapper.properties - 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" >> gradle.properties + - echo "org.gradle.java.installations.paths=/usr/lib/sdk/openjdk25/jvm/openjdk-25" >> gradle.properties - > sed -i 's/^\(\s*\)vendor\.set(JvmVendorSpec\.JETBRAINS)/\1\/\/ vendor.set(JvmVendorSpec.JETBRAINS)/' @@ -92,8 +96,8 @@ modules: - type: file # Must match the version in gradle/wrapper/gradle-wrapper.properties. # Bumping the wrapper? Update both the URL and sha256 here. - url: https://services.gradle.org/distributions/gradle-9.6.0-all.zip - sha256: 87a2216cc1f9122192d4e0fe905ffdf1b4c72cff797e9f733b174e157cadd396 + url: https://services.gradle.org/distributions/gradle-9.6.1-all.zip + sha256: 61ba77b3ff7167e60962763eb4bae79db7120c189b9544358d0ade3c1e712a83 dest: "gradle/wrapper" dest-filename: "gradle-all.zip" - flatpak-sources.json diff --git a/scripts/verify-flatpak/verify.sh b/scripts/verify-flatpak/verify.sh index 332c78e86..697c7c0e0 100755 --- a/scripts/verify-flatpak/verify.sh +++ b/scripts/verify-flatpak/verify.sh @@ -1,11 +1,10 @@ #!/usr/bin/env bash -# Local replica of vid's flatpak CI (vidplace7/org.meshtastic.MeshtasticDesktop, -# .github/workflows/build-flatpak.yml) but flipped to true-offline mode: our -# flatpak-sources.json is included and --share=network is removed from the -# build phase. +# Local replica of the official Flathub packaging build (flathub/org.meshtastic.MeshtasticDesktop) +# but flipped to true-offline mode: our flatpak-sources.json is included and +# --share=network is removed from the build phase. # # Goal: validate flatpak-sources.json end-to-end (download + verify sha256s + -# offline Gradle build) without bugging vid to push & re-run his workflow. +# offline Gradle build) without round-tripping through the Flathub repo's CI. # # Requirements: # - Docker (Docker Desktop on macOS works for --download-only mode; full builds @@ -18,12 +17,12 @@ # scripts/verify-flatpak/verify.sh --download-only # URLs+sha256 only (works on macOS) # scripts/verify-flatpak/verify.sh --arch aarch64 # cross-arch via QEMU emulation # scripts/verify-flatpak/verify.sh --shell # drop into builder container shell -# scripts/verify-flatpak/verify.sh --skip-regen # reuse flatpak-sources.json; still re-clone vid + re-rsync source +# scripts/verify-flatpak/verify.sh --skip-regen # reuse flatpak-sources.json; still re-clone upstream + re-rsync source # scripts/verify-flatpak/verify.sh --rebuild-only # tight loop: refresh overlay+manifest only, then re-run flatpak-builder # # Iteration tip: after a build fails partway, fix the overlay YAML (or the # Meshtastic-Android source) and re-run with --rebuild-only — Gradle regen, -# vid-repo fetch, and full source rsync are all skipped, so you get straight +# upstream-repo fetch, and full source rsync are all skipped, so you get straight # back to flatpak-builder in seconds. set -euo pipefail @@ -56,9 +55,9 @@ WORK="$REPO_ROOT/build/flatpak-verify" OVERLAY="$REPO_ROOT/scripts/verify-flatpak/desktop-offline.yaml" SOURCES_JSON="$REPO_ROOT/flatpak-sources.json" GRADLE_HOME_ISOLATED="$REPO_ROOT/build/flatpak-gradle-home" -VID_REPO="https://github.com/vidplace7/org.meshtastic.MeshtasticDesktop.git" +FLATHUB_REPO="https://github.com/flathub/org.meshtastic.MeshtasticDesktop.git" -# bilelmoussaoui's image is what vid's CI uses; freedesktop-24.08 is the latest +# bilelmoussaoui's image is what the upstream flatpak CI uses; freedesktop-24.08 is the latest # tag available. The 25.08 runtime declared in the manifest is pulled from # flathub at build time inside the container. BUILDER_IMAGE="bilelmoussaoui/flatpak-github-actions:freedesktop-24.08" @@ -95,10 +94,10 @@ else step "Preparing workspace at $WORK" mkdir -p "$WORK" if [[ ! -d "$WORK/org.meshtastic.MeshtasticDesktop/.git" ]]; then - git clone --depth 1 --recurse-submodules "$VID_REPO" "$WORK/org.meshtastic.MeshtasticDesktop" + git clone --depth 1 --recurse-submodules "$FLATHUB_REPO" "$WORK/org.meshtastic.MeshtasticDesktop" else - git -C "$WORK/org.meshtastic.MeshtasticDesktop" fetch --depth 1 origin main - git -C "$WORK/org.meshtastic.MeshtasticDesktop" reset --hard origin/main + git -C "$WORK/org.meshtastic.MeshtasticDesktop" fetch --depth 1 origin master + git -C "$WORK/org.meshtastic.MeshtasticDesktop" reset --hard origin/master git -C "$WORK/org.meshtastic.MeshtasticDesktop" submodule update --init --recursive --depth 1 fi fi