Gradle: Add flatpakGradleGenerator task (#5369)

This commit is contained in:
Austin
2026-05-11 10:44:29 -04:00
committed by GitHub
parent 2d5bcc1e50
commit 484518195e
17 changed files with 348 additions and 3 deletions

View File

@@ -131,6 +131,7 @@ jobs:
channel: ${{ inputs.channel }}
base_version: ${{ inputs.base_version }}
build_desktop: ${{ inputs.build_desktop }}
build_flatpak_src: ${{ inputs.build_desktop }}
secrets: inherit
call-promote-workflow:

View File

@@ -24,6 +24,11 @@ on:
required: false
type: boolean
default: false
build_flatpak_src:
description: 'Whether to build the Flatpak sources'
required: false
type: boolean
default: false
secrets:
GSERVICES:
required: true
@@ -339,10 +344,105 @@ jobs:
desktop/build/compose/binaries/main-release/*/*.AppImage
desktop/build/compose/jars/*-release.jar
create-flatpak-src:
if: ${{ inputs.build_flatpak_src }}
runs-on: ${{ matrix.os }}
needs: [prepare-build-info]
strategy:
fail-fast: false
matrix:
os: [ubuntu-22.04, ubuntu-22.04-arm]
env:
GRADLE_CACHE_URL: ${{ secrets.GRADLE_CACHE_URL }}
GRADLE_CACHE_USERNAME: ${{ secrets.GRADLE_CACHE_USERNAME }}
GRADLE_CACHE_PASSWORD: ${{ secrets.GRADLE_CACHE_PASSWORD }}
steps:
- name: Checkout code
uses: actions/checkout@v6
with:
ref: ${{ inputs.tag_name }}
fetch-depth: 0
submodules: 'recursive'
- name: Gradle Setup
uses: ./.github/actions/gradle-setup
with:
gradle_encryption_key: ${{ secrets.GRADLE_ENCRYPTION_KEY }}
cache_read_only: 'true'
- name: Python Setup
uses: actions/setup-python@v6
with:
python-version: '3.x'
- name: Install ast-grep
run: pip install ast-grep-cli
# Remove Android/iOS targets and other non-desktop bits
# that would break the flatpakGradleGenerator
- name: Prepare Offline Desktop Build
run: ./scripts/desktop-only-prep.sh
- name: Generate Flatpak Sources
env:
DESKTOP_ONLY: true
run: >
./gradlew :build-logic:convention:flatpakGradleGenerator flatpakGradleGenerator
--no-configuration-cache --refresh-dependencies --no-parallel
- name: List Flatpak source files
run: ls -R flatpak-sources*.json
- name: Upload Flatpak source artifacts
if: always()
uses: actions/upload-artifact@v7
with:
name: flatpak-multisrc-${{ runner.arch }}
path: flatpak-sources*.json
retention-days: 1
release-flatpak-src:
if: ${{ inputs.build_flatpak_src }}
runs-on: ubuntu-24.04
needs: [create-flatpak-src]
steps:
- name: Download Flatpak source artifacts
uses: actions/download-artifact@v8
with:
pattern: flatpak-multisrc-*
merge-multiple: true
- name: List Flatpak source files
run: ls -R flatpak-sources*.json
- name: Combine Flatpak source files
run: >
jq -s 'add | unique_by(.dest + "/" + .["dest-filename"])' flatpak-sources*.json
> flatpak-sources.json
- name: Upload combined Flatpak source artifact
if: always()
uses: actions/upload-artifact@v7
with:
name: flatpak-sources
path: flatpak-sources.json
retention-days: 1
- name: Attest combined Flatpak source artifact provenance
if: success()
uses: actions/attest@v4
with:
subject-path: flatpak-sources.json
github-release:
if: ${{ !cancelled() && !failure() }}
runs-on: ubuntu-24.04-arm
needs: [prepare-build-info, release-google, release-fdroid, release-desktop]
needs:
- prepare-build-info
- release-google
- release-fdroid
- release-desktop
- release-flatpak-src
env:
INTERNAL_BUILDS_HOST: ${{ secrets.INTERNAL_BUILDS_HOST }}
permissions:
@@ -360,6 +460,9 @@ jobs:
with:
path: ./artifacts
- name: Exclude flatpak-multisrc artifacts from release
run: rm -rf ./artifacts/flatpak-multisrc-*
- name: Create or Update GitHub Release
uses: softprops/action-gh-release@v3
with:

View File

@@ -15,6 +15,9 @@ on:
run_desktop_builds:
type: boolean
default: true
run_desktop_flatpak_src:
type: boolean
default: true
upload_artifacts:
type: boolean
default: true
@@ -490,3 +493,62 @@ jobs:
name: desktop-app-${{ runner.os }}-${{ runner.arch }}
path: desktop/build/compose/binaries/main/app/
retention-days: 7
# ── Flatpak Sources ───────────────────────────────────────────────────
build-flatpak-src:
name: Generate Flatpak Sources (${{ matrix.os }})
if: inputs.run_desktop_flatpak_src == true
runs-on: ${{ matrix.os }}
permissions:
contents: read
timeout-minutes: 60
needs: lint-check
strategy:
fail-fast: false
matrix:
os: [ubuntu-24.04, ubuntu-24.04-arm]
env:
VERSION_CODE: ${{ needs.lint-check.outputs.version_code }}
steps:
- name: Checkout code
uses: actions/checkout@v6
with:
fetch-depth: 1
submodules: true
- name: Gradle Setup
uses: ./.github/actions/gradle-setup
with:
gradle_encryption_key: ${{ secrets.GRADLE_ENCRYPTION_KEY }}
cache_read_only: true
- name: Python Setup
uses: actions/setup-python@v6
with:
python-version: '3.x'
- name: Install ast-grep
run: pip install ast-grep-cli
# Remove Android/iOS targets and other non-desktop bits
# that would break the flatpakGradleGenerator
- name: Prepare Offline Desktop Build
run: ./scripts/desktop-only-prep.sh
- name: Generate Flatpak Sources
env:
DESKTOP_ONLY: true
run: >
./gradlew :build-logic:convention:flatpakGradleGenerator flatpakGradleGenerator
--no-configuration-cache --refresh-dependencies --no-parallel
- run: ls -lah flatpak-sources*.json
- name: Upload Flatpak Sources
if: ${{ inputs.upload_artifacts }}
uses: actions/upload-artifact@v7
with:
name: flatpak-sources-${{ runner.arch }}
path: flatpak-sources*.json
retention-days: 7

3
.gitignore vendored
View File

@@ -60,3 +60,6 @@ firebase-debug.log
/coil/
/kable/
.opencode/
# flatpakGradleGenerator output
flatpak-sources*.json

View File

@@ -21,6 +21,7 @@ plugins {
`kotlin-dsl`
alias(libs.plugins.spotless)
alias(libs.plugins.detekt)
alias(libs.plugins.flatpak.gradle.generator)
}
group = "org.meshtastic.buildlogic"
@@ -96,6 +97,12 @@ detekt {
source.setFrom(files("src/main/java", "src/main/kotlin"))
}
tasks.flatpakGradleGenerator {
outputFile = file("../../flatpak-sources-convention.json")
downloadDirectory.set("./offline-repository")
excludeConfigurations.set(listOf("testCompileClasspath", "testRuntimeClasspath"))
}
gradlePlugin {
plugins {
register("androidApplication") {

View File

@@ -26,6 +26,7 @@ pluginManagement {
includeGroupByRegex("com\\.github\\..*")
}
}
maven { url = uri("../offline-repository") }
}
}
@@ -51,6 +52,7 @@ dependencyResolutionManagement {
includeGroupByRegex("com\\.github\\..*")
}
}
maven { url = uri("../offline-repository") }
}
versionCatalogs {
create("libs") {

View File

@@ -38,9 +38,23 @@ plugins {
alias(libs.plugins.spotless) apply false
alias(libs.plugins.dokka)
alias(libs.plugins.test.retry) apply false
alias(libs.plugins.flatpak.gradle.generator)
alias(libs.plugins.meshtastic.root)
}
dependencies {
dokkaPlugin(libs.dokka.android.documentation.plugin)
}
tasks.flatpakGradleGenerator {
outputFile = file("flatpak-sources-root.json")
downloadDirectory = "./offline-repository"
excludeConfigurations.set(
listOf(
"dokkaHtmlModuleOutputDirectoriesResolver~internal",
"koverExternalArtifacts",
"testCompileClasspath",
"testRuntimeClasspath",
)
)
}

View File

@@ -18,6 +18,7 @@
plugins {
alias(libs.plugins.meshtastic.kmp.library)
id("meshtastic.koin")
alias(libs.plugins.flatpak.gradle.generator)
}
kotlin {
@@ -51,3 +52,20 @@ kotlin {
}
}
}
tasks.flatpakGradleGenerator {
outputFile = file("../../flatpak-sources-core-ble.json")
downloadDirectory.set("./offline-repository")
excludeConfigurations.set(
listOf(
"androidRuntimeClasspath",
"androidCompileClasspath",
"androidMainLintChecksClasspath",
"androidHostTestCompileClasspath",
"androidHostTestLintChecksClasspath",
"androidHostTestRuntimeClasspath",
"testCompileClasspath",
"testRuntimeClasspath",
),
)
}

View File

@@ -20,6 +20,7 @@ plugins {
alias(libs.plugins.kotlin.parcelize)
id("meshtastic.kmp.jvm.android")
id("meshtastic.koin")
alias(libs.plugins.flatpak.gradle.generator)
}
kotlin {
@@ -44,3 +45,17 @@ kotlin {
commonTest.dependencies { implementation(libs.kotlinx.coroutines.test) }
}
}
tasks.flatpakGradleGenerator {
outputFile = file("../../flatpak-sources-core-common.json")
downloadDirectory.set("./offline-repository")
excludeConfigurations.set(
listOf(
"androidHostTestCompileClasspath",
"androidHostTestLintChecksClasspath",
"androidHostTestRuntimeClasspath",
"testCompileClasspath",
"testRuntimeClasspath",
),
)
}

View File

@@ -21,6 +21,7 @@ plugins {
alias(libs.plugins.meshtastic.kotlinx.serialization)
alias(libs.plugins.kotlin.parcelize)
id("meshtastic.koin")
alias(libs.plugins.flatpak.gradle.generator)
}
kotlin {
@@ -74,6 +75,29 @@ kotlin {
dependencies {
"kspJvm"(libs.androidx.room.compiler)
"kspJvmTest"(libs.androidx.room.compiler)
// KSP resolves this via a detached configuration at task execution time,
// so we declare it explicitly to ensure offline/Flatpak builds can resolve it.
"kspJvm"("com.google.devtools.ksp:symbol-processing-aa-embeddable:${libs.versions.devtools.ksp.get()}")
"kspAndroidHostTest"(libs.androidx.room.compiler)
"kspAndroidDeviceTest"(libs.androidx.room.compiler)
}
tasks.flatpakGradleGenerator {
outputFile = file("../../flatpak-sources-core-database.json")
downloadDirectory.set("./offline-repository")
excludeConfigurations.set(
listOf(
"androidRuntimeClasspath",
"androidMainLintChecksClasspath",
"androidHostTestRuntimeClasspath",
"androidHostTestLintChecksClasspath",
"androidHostTestCompileClasspath",
"androidDeviceTestRuntimeClasspath",
"androidDeviceTestLintChecksClasspath",
"androidDeviceTestCompileClasspath",
"androidCompileClasspath",
"testCompileClasspath",
"testRuntimeClasspath",
),
)
}

View File

@@ -21,6 +21,7 @@ plugins {
alias(libs.plugins.kotlin.parcelize)
id("meshtastic.kmp.jvm.android")
id("meshtastic.publishing")
alias(libs.plugins.flatpak.gradle.generator)
}
kotlin {
@@ -72,3 +73,23 @@ publishing {
}
}
}
tasks.flatpakGradleGenerator {
outputFile = file("../../flatpak-sources-core-model.json")
downloadDirectory.set("./offline-repository")
excludeConfigurations.set(
listOf(
"androidRuntimeClasspath",
"androidMainLintChecksClasspath",
"androidHostTestRuntimeClasspath",
"androidHostTestLintChecksClasspath",
"androidHostTestCompileClasspath",
"androidDeviceTestRuntimeClasspath",
"androidDeviceTestLintChecksClasspath",
"androidDeviceTestCompileClasspath",
"androidCompileClasspath",
"testCompileClasspath",
"testRuntimeClasspath",
),
)
}

View File

@@ -19,6 +19,7 @@ plugins {
alias(libs.plugins.meshtastic.kmp.library)
alias(libs.plugins.meshtastic.kmp.library.compose)
alias(libs.plugins.meshtastic.kotlinx.serialization)
alias(libs.plugins.flatpak.gradle.generator)
}
kotlin {
@@ -36,3 +37,23 @@ kotlin {
commonTest.dependencies { implementation(projects.core.testing) }
}
}
tasks.flatpakGradleGenerator {
outputFile = file("../../flatpak-sources-core-navigation.json")
downloadDirectory.set("./offline-repository")
excludeConfigurations.set(
listOf(
"androidRuntimeClasspath",
"androidMainLintChecksClasspath",
"androidHostTestRuntimeClasspath",
"androidHostTestLintChecksClasspath",
"androidHostTestCompileClasspath",
"androidDeviceTestRuntimeClasspath",
"androidDeviceTestLintChecksClasspath",
"androidDeviceTestCompileClasspath",
"androidCompileClasspath",
"testCompileClasspath",
"testRuntimeClasspath",
),
)
}

View File

@@ -19,6 +19,7 @@ plugins {
alias(libs.plugins.meshtastic.kmp.library)
alias(libs.plugins.wire)
id("meshtastic.publishing")
alias(libs.plugins.flatpak.gradle.generator)
}
kotlin {
@@ -61,3 +62,9 @@ publishing {
}
}
}
tasks.flatpakGradleGenerator {
outputFile = file("../../flatpak-sources-core-proto.json")
downloadDirectory.set("./offline-repository")
excludeConfigurations.set(listOf("testCompileClasspath", "testRuntimeClasspath"))
}

View File

@@ -30,6 +30,7 @@ plugins {
alias(libs.plugins.meshtastic.koin)
id("meshtastic.kover")
id("meshtastic.aboutlibraries")
alias(libs.plugins.flatpak.gradle.generator)
}
configureGraphTasks()
@@ -322,3 +323,12 @@ dependencies {
testImplementation(libs.kotlinx.coroutines.test)
testImplementation(kotlin("test"))
}
// Must be run on each architecture to generate separate flatpak-sources.
tasks.flatpakGradleGenerator {
val arch = System.getProperty("os.arch").let { if (it == "amd64") "x86_64" else it }
outputFile = file("../flatpak-sources-desktop-$arch.json")
downloadDirectory.set("./offline-repository")
onlyArches = arch
excludeConfigurations.set(listOf("testCompileClasspath", "testRuntimeClasspath"))
}

View File

@@ -15,7 +15,10 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
plugins { alias(libs.plugins.meshtastic.kmp.feature) }
plugins {
alias(libs.plugins.meshtastic.kmp.feature)
alias(libs.plugins.flatpak.gradle.generator)
}
kotlin {
android {
@@ -56,3 +59,34 @@ kotlin {
jvmTest.dependencies { implementation(compose.desktop.currentOs) }
}
}
// Gradle's KMP variant resolution follows `available-at` redirects in module
// metadata and needs android variant `.module` files for disambiguation, even
// when building desktop-only offline. The androidCompileClasspath configuration
// can't be resolved by the flatpak generator due to AGP variant ambiguity on
// project dependencies, so we capture android KMP metadata via a dedicated
// configuration that only holds external dependencies.
val flatpakKmpAndroidMeta by
configurations.creating {
isCanBeResolved = true
isCanBeConsumed = false
}
dependencies { flatpakKmpAndroidMeta("androidx.paging:paging-compose-android:${libs.versions.paging.get()}") }
tasks.flatpakGradleGenerator {
outputFile = file("../../flatpak-sources-feature-messaging.json")
downloadDirectory.set("./offline-repository")
excludeConfigurations.set(
listOf(
"androidRuntimeClasspath",
"androidMainLintChecksClasspath",
"androidCompileClasspath",
"androidHostTestCompileClasspath",
"androidHostTestLintChecksClasspath",
"androidHostTestRuntimeClasspath",
"testCompileClasspath",
"testRuntimeClasspath",
),
)
}

View File

@@ -300,6 +300,7 @@ wire = { id = "com.squareup.wire", version.ref = "wire" }
room = { id = "androidx.room3", version.ref = "room" }
spotless = { id = "com.diffplug.spotless", version.ref = "spotless" }
test-retry = { id = "org.gradle.test-retry", version.ref = "testRetry" }
flatpak-gradle-generator = { id = "io.github.jwharm.flatpak-gradle-generator", version = "1.7.0" }
# Meshtastic
meshtastic-android-application = { id = "meshtastic.android.application" }

View File

@@ -18,10 +18,11 @@
pluginManagement {
includeBuild("build-logic")
repositories {
gradlePluginPortal()
google()
mavenCentral()
gradlePluginPortal()
maven { url = uri("https://jitpack.io") }
maven { url = uri("./offline-repository") }
}
}
@@ -55,6 +56,7 @@ dependencyResolutionManagement {
includeGroupByRegex("com\\.github\\..*")
}
}
maven { url = uri("./offline-repository") }
}
}