Files
TREK/.github/workflows/native.yml
T
Maurice 3c4c880c31 feat(native): push notifications on Android through the relay
The Android app now subscribes like the iOS one: TrekShell.registerPush asks
for the notification permission (Android 13+), creates the device's P-256
Web Push keys and returns the relay endpoint for its FCM token
(push.liketrek.com/v1/fcm/<token>). TrekPushService receives the relay's
data message, decrypts the record (RFC 8291, TrekWebPush) and shows the
notification. A tap opens the linked page, also when it starts the app.

The keys are sealed with an AES key kept in the Android Keystore. Firebase
is configured from res/values/firebase.xml, so no google-services plugin is
needed. The decryption is tested against the RFC 8291 example, and the
native workflow now runs the Android unit tests. On the web side push is no
longer limited to iOS: it follows the nativePush capability on both platforms.
2026-11-06 15:02:55 +01:00

133 lines
4.2 KiB
YAML

name: Native apps
permissions:
contents: read
# Builds the iOS and Android shells whenever they, their address screen or the
# Capacitor plugins change. Nobody on the team has to own a Mac for the Swift
# side to be compiled on every change, and every run leaves a debug APK to
# install on a phone.
#
# Unsigned on purpose: signing and store uploads need secrets that fork PRs do
# not get, and belong in a release workflow of their own.
on:
pull_request:
paths:
- 'client/android/**'
- 'client/ios/**'
- 'client/native-shell/**'
- 'client/src/native/trekShell.ts'
- 'client/src/native/serverAddress.ts'
- 'client/capacitor.config.ts'
- 'client/vite.native.config.js'
- 'client/scripts/check-store-metadata.mjs'
- 'client/fastlane/**'
- 'client/package.json'
- 'package-lock.json'
- 'shared/src/i18n/*/native.ts'
- '.github/workflows/native.yml'
workflow_dispatch:
concurrency:
group: native-${{ github.ref }}
cancel-in-progress: true
jobs:
# The store texts fit their limits and every listing image has its size and
# no alpha channel (client/fastlane/README.md). Plain Node, no install.
metadata:
runs-on: ubuntu-24.04
timeout-minutes: 5
steps:
- uses: actions/checkout@v6
- uses: actions/setup-node@v6
with:
node-version-file: .nvmrc
- name: Check the store listings
run: node client/scripts/check-store-metadata.mjs
android:
runs-on: ubuntu-24.04
timeout-minutes: 30
steps:
- uses: actions/checkout@v6
- uses: actions/setup-node@v6
with:
node-version-file: .nvmrc
cache: npm
- uses: actions/setup-java@v5
with:
distribution: temurin
java-version: 21
cache: gradle
- name: Install
run: npm ci --workspace=shared --workspace=client
- name: Build shared
run: npm run build --workspace=shared
- name: Build the address screen and sync it into the shells
working-directory: client
run: npm run cap:sync -- android
# The release build runs R8 with the keep rules in proguard-rules.pro, so a
# rule that goes missing fails here rather than in the store build. It is
# unsigned: the upload key only exists in native-release.yml.
- name: Assemble debug and release APKs
working-directory: client/android
run: ./gradlew assembleDebug assembleRelease lintDebug testDebugUnitTest --no-daemon
- uses: actions/upload-artifact@v6
with:
name: trek-android-debug
path: client/android/app/build/outputs/apk/debug/app-debug.apk
retention-days: 14
ios:
runs-on: macos-15
timeout-minutes: 40
steps:
- uses: actions/checkout@v6
# App Store uploads must be built with Xcode 26; the image's default is older.
- name: Select Xcode 26
run: |
XCODE=$(ls -d /Applications/Xcode_26*.app | sort -V | tail -1)
test -n "$XCODE"
sudo xcode-select -s "$XCODE"
xcodebuild -version
- name: Check the property lists
run: plutil -lint client/ios/App/App/Info.plist client/ios/ExportOptions.plist client/ios/App/NotificationService/Info.plist client/ios/App/NotificationService/NotificationService.entitlements client/ios/App/App/App.entitlements client/ios/App/TREKWidgets/Info.plist client/ios/App/TREKWidgets/TREKWidgets.entitlements
- uses: actions/setup-node@v6
with:
node-version-file: .nvmrc
cache: npm
- name: Install
run: npm ci --workspace=shared --workspace=client
- name: Build shared
run: npm run build --workspace=shared
- name: Build the address screen and sync it into the shells
working-directory: client
run: npm run cap:sync -- ios
- name: Build for the simulator
working-directory: client/ios/App
run: |
xcodebuild build \
-project App.xcodeproj \
-scheme App \
-configuration Debug \
-sdk iphonesimulator \
-destination 'generic/platform=iOS Simulator' \
CODE_SIGNING_ALLOWED=NO