From d9ac2a538f6edf20a3ca58ca4f15bc6c16a95384 Mon Sep 17 00:00:00 2001 From: Jacob Fielding Date: Wed, 27 May 2026 20:51:57 -0700 Subject: [PATCH 1/2] ci: add GitHub Actions for CI and Maven Central release Adapt the workflows from maplibre-compose-playground: - ci.yml: build / ktfmtCheck / test / connectedCheck on push + PR to main - release.yml: manual dispatch that bumps the version, cuts a GH release, and runs publishAndReleaseToMavenCentral with in-memory signing - dependabot.yml: monthly Gradle updates Adaptations for this repo: JDK 21 (not 17), drop the MapLibre api_keys step, and fix version_bump.sh to use $GITHUB_OUTPUT instead of the disabled ::set-output workflow command. Co-Authored-By: Claude Opus 4.7 --- .github/dependabot.yml | 6 ++ .github/workflows/ci.yml | 120 ++++++++++++++++++++++++++++++++++ .github/workflows/release.yml | 82 +++++++++++++++++++++++ scripts/version_bump.sh | 8 ++- 4 files changed, 214 insertions(+), 2 deletions(-) create mode 100644 .github/dependabot.yml create mode 100644 .github/workflows/ci.yml create mode 100644 .github/workflows/release.yml diff --git a/.github/dependabot.yml b/.github/dependabot.yml new file mode 100644 index 0000000..df213d9 --- /dev/null +++ b/.github/dependabot.yml @@ -0,0 +1,6 @@ +version: 2 +updates: + - package-ecosystem: gradle + directory: / + schedule: + interval: monthly diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000..8f7fc88 --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,120 @@ +name: CI + +on: + push: + branches: [ main ] + pull_request: + branches: [ main ] + +jobs: + build: + + runs-on: ubuntu-latest + concurrency: + group: ${{ github.workflow }}-${{ github.ref }}-build + cancel-in-progress: true + + steps: + - uses: actions/checkout@v4 + + - name: set up JDK 21 + uses: actions/setup-java@v4 + with: + java-version: '21' + distribution: 'temurin' + cache: gradle + + - name: Grant execute permission for gradlew + run: chmod +x gradlew + + - name: Build with Gradle + run: ./gradlew build + + check-ktfmt: + + runs-on: ubuntu-latest + concurrency: + group: ${{ github.workflow }}-${{ github.ref }}-ktfmt + cancel-in-progress: true + + steps: + - uses: actions/checkout@v4 + + - name: set up JDK 21 + uses: actions/setup-java@v4 + with: + java-version: '21' + distribution: 'temurin' + cache: gradle + + - name: Grant execute permission for gradlew + run: chmod +x gradlew + + - name: Verify Kotlin formatting + run: ./gradlew ktfmtCheck + + test: + + runs-on: ubuntu-latest + concurrency: + group: ${{ github.workflow }}-${{ github.ref }}-test + cancel-in-progress: true + + steps: + - uses: actions/checkout@v4 + + - name: set up JDK 21 + uses: actions/setup-java@v4 + with: + java-version: '21' + distribution: 'temurin' + cache: gradle + + - name: Grant execute permission for gradlew + run: chmod +x gradlew + + - name: Run unit tests + run: ./gradlew test + + connected-check: + + runs-on: ubuntu-latest + concurrency: + group: ${{ github.workflow }}-${{ github.ref }}-android-connected-check + cancel-in-progress: true + + steps: + - uses: actions/checkout@v4 + + - name: set up JDK 21 + uses: actions/setup-java@v4 + with: + java-version: "21" + distribution: "temurin" + cache: gradle + + - name: Grant execute permission for gradlew + run: chmod +x gradlew + + - name: Enable KVM group perms + run: | + echo 'KERNEL=="kvm", GROUP="kvm", MODE="0666", OPTIONS+="static_node=kvm"' | sudo tee /etc/udev/rules.d/99-kvm4all.rules + sudo udevadm control --reload-rules + sudo udevadm trigger --name-match=kvm + + - name: Run Connected Checks + uses: reactivecircus/android-emulator-runner@v2 + with: + api-level: 30 + avd-name: ubuntu-latest-x86_64-aosp-atd-30 + arch: x86_64 + target: aosp_atd + script: ./gradlew connectedCheck + + - name: Upload Artifacts + uses: actions/upload-artifact@v4 + if: always() + with: + name: connected-reports + path: | + **/build/reports diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 0000000..09e7b2e --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,82 @@ +# This workflow will build a package using Gradle and then publish it to Maven Central when a release is published. + +name: Publish + +on: + workflow_dispatch: + inputs: + bump_version_scheme: + type: choice + description: "Release" + required: true + default: "patch" + options: + - "patch" + - "minor" + - "major" + +jobs: + version_bump: + runs-on: ubuntu-latest + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + permissions: + # Give the default GITHUB_TOKEN write permission to commit and push the + # added or changed files to the repository. + contents: write + + steps: + - name: Check out repo + uses: actions/checkout@v4 + with: + token: ${{ secrets.PAT }} + + - name: Configure Git + run: | + git config user.name github-actions + git config user.email github-actions@github.com + + - name: Bump version + id: version + run: ./scripts/version_bump.sh ${{ github.event_name == 'push' && github.ref == 'refs/heads/main' && 'patch' || inputs.bump_version_scheme }} + + - name: Commit version update + run: | + git add build.gradle.kts + git commit -m "Update version to ${{ steps.version.outputs.version }}" + git push + + - uses: softprops/action-gh-release@v1 + id: release + with: + generate_release_notes: true + tag_name: ${{ steps.version.outputs.version }} + + publish: + runs-on: ubuntu-latest + needs: version_bump + + steps: + - name: Check out repo + uses: actions/checkout@v4 + with: + ref: main + fetch-depth: 0 + + - name: Set up JDK 21 + uses: actions/setup-java@v4 + with: + java-version: "21" + distribution: "temurin" + cache: gradle + + - name: Setup Gradle + uses: gradle/actions/setup-gradle@417ae3ccd767c252f5661f1ace9f835f9654f2b5 # v3.1.0 + + - name: Publish to Maven Central + run: ./gradlew publishAndReleaseToMavenCentral --no-configuration-cache + env: + ORG_GRADLE_PROJECT_mavenCentralUsername: ${{ secrets.MAVEN_CENTRAL_USERNAME }} + ORG_GRADLE_PROJECT_mavenCentralPassword: ${{ secrets.MAVEN_CENTRAL_PASSWORD }} + ORG_GRADLE_PROJECT_signingInMemoryKey: ${{ secrets.MAVEN_GPG_PRIVATE_KEY }} + ORG_GRADLE_PROJECT_signingInMemoryKeyPassword: ${{ secrets.MAVEN_GPG_PASSPHRASE }} diff --git a/scripts/version_bump.sh b/scripts/version_bump.sh index f3132ff..d62dbc4 100755 --- a/scripts/version_bump.sh +++ b/scripts/version_bump.sh @@ -23,5 +23,9 @@ echo "Bumping version from $last_version to $next_version" # Update the version in build.gradle.kts sed -i "s/version = \"$last_version\"/version = \"$next_version\"/" build.gradle.kts -# Output the tag to stdout -echo ::set-output name=version::$next_version +# Expose the new version to later workflow steps (falls back to stdout locally) +if [ -n "$GITHUB_OUTPUT" ]; then + echo "version=$next_version" >> "$GITHUB_OUTPUT" +else + echo "version=$next_version" +fi From 81c3924ee97097f1a6dd4eb839c92b646568d970 Mon Sep 17 00:00:00 2001 From: Jacob Fielding Date: Wed, 27 May 2026 20:55:12 -0700 Subject: [PATCH 2/2] applied ktfmt --- .../app/compose/demo/auto/CameraExampleScreen.kt | 14 ++++++++------ .../app/compose/demo/auto/SymbolExampleScreen.kt | 5 ++--- .../compose/demo/automotive/CameraExampleScreen.kt | 9 ++++----- .../compose/demo/automotive/SymbolExampleScreen.kt | 5 ++--- 4 files changed, 16 insertions(+), 17 deletions(-) diff --git a/app/src/main/java/com/rallista/car/app/compose/demo/auto/CameraExampleScreen.kt b/app/src/main/java/com/rallista/car/app/compose/demo/auto/CameraExampleScreen.kt index 33a7d59..f2823f5 100644 --- a/app/src/main/java/com/rallista/car/app/compose/demo/auto/CameraExampleScreen.kt +++ b/app/src/main/java/com/rallista/car/app/compose/demo/auto/CameraExampleScreen.kt @@ -34,8 +34,8 @@ import org.maplibre.compose.location.LocationProvider import org.maplibre.compose.location.LocationPuck import org.maplibre.compose.location.LocationTrackingEffect import org.maplibre.compose.location.rememberUserLocationState -import org.maplibre.compose.map.MaplibreMap import org.maplibre.compose.map.MapOptions +import org.maplibre.compose.map.MaplibreMap import org.maplibre.compose.map.RenderOptions import org.maplibre.compose.style.BaseStyle import org.maplibre.spatialk.geojson.Position @@ -75,7 +75,8 @@ class CameraExampleScreen(carContext: CarContext) : ComposableScreen(carContext, } } - if (mode is CameraMode.TrackingUserLocation || mode is CameraMode.TrackingUserLocationWithBearing) { + if (mode is CameraMode.TrackingUserLocation || + mode is CameraMode.TrackingUserLocationWithBearing) { LocationTrackingEffect(userLocation) { cam.updateFromLocation( updateBearing = @@ -90,8 +91,7 @@ class CameraExampleScreen(carContext: CarContext) : ComposableScreen(carContext, cameraState = cam, options = MapOptions( - renderOptions = - RenderOptions(renderMode = RenderOptions.RenderMode.TextureView)), + renderOptions = RenderOptions(renderMode = RenderOptions.RenderMode.TextureView)), ) { LocationPuck(idPrefix = "puck", locationState = userLocation, cameraState = cam) } @@ -100,7 +100,8 @@ class CameraExampleScreen(carContext: CarContext) : ComposableScreen(carContext, override fun onGetTemplate(): Template { return MapWithContentTemplate.Builder() .setContentTemplate( - MessageTemplate.Builder("Camera is currently ${cameraMode.value::class.simpleName}").build()) + MessageTemplate.Builder("Camera is currently ${cameraMode.value::class.simpleName}") + .build()) .setActionStrip( ActionStrip.Builder() .addAction( @@ -108,7 +109,8 @@ class CameraExampleScreen(carContext: CarContext) : ComposableScreen(carContext, .setTitle("Symbols") .setOnClickListener { Log.d(TAG, "Navigating to SymbolExampleScreen") - screenManager.push(SymbolExampleScreen(carContext) { screenManager.pop() }) + screenManager.push( + SymbolExampleScreen(carContext) { screenManager.pop() }) } .build()) .build()) diff --git a/app/src/main/java/com/rallista/car/app/compose/demo/auto/SymbolExampleScreen.kt b/app/src/main/java/com/rallista/car/app/compose/demo/auto/SymbolExampleScreen.kt index 522aae0..cfb9c5c 100644 --- a/app/src/main/java/com/rallista/car/app/compose/demo/auto/SymbolExampleScreen.kt +++ b/app/src/main/java/com/rallista/car/app/compose/demo/auto/SymbolExampleScreen.kt @@ -26,8 +26,8 @@ import org.maplibre.compose.expressions.value.SymbolAnchor import org.maplibre.compose.layers.CircleLayer import org.maplibre.compose.layers.LineLayer import org.maplibre.compose.layers.SymbolLayer -import org.maplibre.compose.map.MaplibreMap import org.maplibre.compose.map.MapOptions +import org.maplibre.compose.map.MaplibreMap import org.maplibre.compose.map.RenderOptions import org.maplibre.compose.sources.GeoJsonData import org.maplibre.compose.sources.rememberGeoJsonSource @@ -59,8 +59,7 @@ class SymbolExampleScreen(carContext: CarContext, private val onNavigateBack: () cameraState = cam, options = MapOptions( - renderOptions = - RenderOptions(renderMode = RenderOptions.RenderMode.TextureView)), + renderOptions = RenderOptions(renderMode = RenderOptions.RenderMode.TextureView)), onMapClick = { pos, _ -> Log.d(TAG, "Tapped at $pos") ClickResult.Pass diff --git a/auto/src/main/java/com/rallista/car/app/compose/demo/automotive/CameraExampleScreen.kt b/auto/src/main/java/com/rallista/car/app/compose/demo/automotive/CameraExampleScreen.kt index 9ee8234..046b1ff 100644 --- a/auto/src/main/java/com/rallista/car/app/compose/demo/automotive/CameraExampleScreen.kt +++ b/auto/src/main/java/com/rallista/car/app/compose/demo/automotive/CameraExampleScreen.kt @@ -23,7 +23,6 @@ import kotlin.time.TimeSource import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.flow.asStateFlow -import org.maplibre.compose.camera.CameraPosition import org.maplibre.compose.camera.rememberCameraState import org.maplibre.compose.location.BearingUpdate import org.maplibre.compose.location.Location @@ -31,8 +30,8 @@ import org.maplibre.compose.location.LocationProvider import org.maplibre.compose.location.LocationPuck import org.maplibre.compose.location.LocationTrackingEffect import org.maplibre.compose.location.rememberUserLocationState -import org.maplibre.compose.map.MaplibreMap import org.maplibre.compose.map.MapOptions +import org.maplibre.compose.map.MaplibreMap import org.maplibre.compose.map.RenderOptions import org.maplibre.compose.style.BaseStyle import org.maplibre.spatialk.geojson.Position @@ -73,7 +72,8 @@ class CameraExampleScreen(carContext: CarContext) : } } - if (mode is CameraMode.TrackingUserLocation || mode is CameraMode.TrackingUserLocationWithBearing) { + if (mode is CameraMode.TrackingUserLocation || + mode is CameraMode.TrackingUserLocationWithBearing) { LocationTrackingEffect(userLocation) { cam.updateFromLocation( updateBearing = @@ -88,8 +88,7 @@ class CameraExampleScreen(carContext: CarContext) : cameraState = cam, options = MapOptions( - renderOptions = - RenderOptions(renderMode = RenderOptions.RenderMode.TextureView)), + renderOptions = RenderOptions(renderMode = RenderOptions.RenderMode.TextureView)), ) { LocationPuck(idPrefix = "puck", locationState = userLocation, cameraState = cam) } diff --git a/auto/src/main/java/com/rallista/car/app/compose/demo/automotive/SymbolExampleScreen.kt b/auto/src/main/java/com/rallista/car/app/compose/demo/automotive/SymbolExampleScreen.kt index ff386f1..3d4fecd 100644 --- a/auto/src/main/java/com/rallista/car/app/compose/demo/automotive/SymbolExampleScreen.kt +++ b/auto/src/main/java/com/rallista/car/app/compose/demo/automotive/SymbolExampleScreen.kt @@ -25,8 +25,8 @@ import org.maplibre.compose.expressions.value.SymbolAnchor import org.maplibre.compose.layers.CircleLayer import org.maplibre.compose.layers.LineLayer import org.maplibre.compose.layers.SymbolLayer -import org.maplibre.compose.map.MaplibreMap import org.maplibre.compose.map.MapOptions +import org.maplibre.compose.map.MaplibreMap import org.maplibre.compose.map.RenderOptions import org.maplibre.compose.sources.GeoJsonData import org.maplibre.compose.sources.rememberGeoJsonSource @@ -58,8 +58,7 @@ class SymbolExampleScreen(carContext: CarContext, private val onNavigateBack: () cameraState = cam, options = MapOptions( - renderOptions = - RenderOptions(renderMode = RenderOptions.RenderMode.TextureView)), + renderOptions = RenderOptions(renderMode = RenderOptions.RenderMode.TextureView)), onMapClick = { pos, _ -> Log.d(TAG, "Tapped at $pos") ClickResult.Pass