Skip to content

fix: ensure Android keystore is decoded for manual workflow triggers #19

fix: ensure Android keystore is decoded for manual workflow triggers

fix: ensure Android keystore is decoded for manual workflow triggers #19

Workflow file for this run

name: CI - Build & Test
on:
push:
branches: [ main, development ]
paths-ignore:
- '**.md'
- 'docs/**'
- 'LICENSE'
- '.gitignore'
pull_request:
branches: [ main, development ]
paths-ignore:
- '**.md'
- 'docs/**'
- 'LICENSE'
- '.gitignore'
workflow_dispatch:
# Cancel in-progress runs for same PR/branch
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
env:
JAVA_VERSION: '21'
JAVA_DISTRIBUTION: 'temurin'
GRADLE_OPTS: -Dorg.gradle.daemon=false -Dorg.gradle.parallel=true -Dorg.gradle.caching=true
jobs:
# ================== Unit Tests ==================
test-unit:
name: Unit Tests
runs-on: ubuntu-latest
timeout-minutes: 20
steps:
- name: Checkout code
uses: actions/checkout@v4
with:
fetch-depth: 1 # Shallow clone for speed
- name: Setup JDK ${{ env.JAVA_VERSION }}
uses: actions/setup-java@v4
with:
java-version: ${{ env.JAVA_VERSION }}
distribution: ${{ env.JAVA_DISTRIBUTION }}
cache: gradle
- name: Setup Gradle
uses: gradle/actions/setup-gradle@v3
with:
cache-read-only: ${{ github.ref != 'refs/heads/main' }}
- name: Run unit tests
run: |
./gradlew \
:pocketbase-kt-sdk:jvmTest \
:composeApp:jvmTest \
--parallel \
--build-cache \
--configuration-cache \
--no-daemon \
--stacktrace
continue-on-error: false
- name: Run shared unit tests (exclude integration)
run: |
./gradlew :shared:jvmTest \
--tests 'love.bside.app.unit.*' \
--tests 'love.bside.app.data.serialization.*' \
--tests 'love.bside.app.domain.models.*' \
--tests 'love.bside.app.domain.validation.*' \
--parallel \
--build-cache \
--no-daemon \
--stacktrace
continue-on-error: false
- name: Upload test reports
if: failure() # Only upload on failure to save storage
uses: actions/upload-artifact@v4
with:
name: test-reports-unit
path: |
**/build/reports/tests/
**/build/test-results/
retention-days: 3 # Reduced from 7 days
# ================== Android Build ==================
build-android:
name: Build Android
runs-on: ubuntu-latest
timeout-minutes: 30
needs: test-unit
if: github.event_name == 'push' || github.event.pull_request.draft == false
steps:
- name: Checkout code
uses: actions/checkout@v4
with:
fetch-depth: 1
- name: Setup JDK ${{ env.JAVA_VERSION }}
uses: actions/setup-java@v4
with:
java-version: ${{ env.JAVA_VERSION }}
distribution: ${{ env.JAVA_DISTRIBUTION }}
cache: gradle
- name: Setup Gradle
uses: gradle/actions/setup-gradle@v3
with:
cache-read-only: ${{ github.ref != 'refs/heads/main' }}
- name: Build Android APK (Debug)
run: |
./gradlew \
:composeApp:assembleDebug \
--parallel \
--build-cache \
--configuration-cache \
--no-daemon \
--stacktrace
- name: Upload Android APK
uses: actions/upload-artifact@v4
with:
name: android-apk-debug
path: composeApp/build/outputs/apk/debug/*.apk
retention-days: 14 # Reduced from 30 days
compression-level: 0 # APKs are already compressed
- name: Generate APK checksums
run: |
cd composeApp/build/outputs/apk/debug
sha256sum *.apk > checksums.txt
cat checksums.txt
- name: Upload checksums
uses: actions/upload-artifact@v4
with:
name: android-checksums
path: composeApp/build/outputs/apk/debug/checksums.txt
retention-days: 14
# ================== iOS Build (macOS only) ==================
build-ios:
name: Build iOS
runs-on: macos-14 # M1 runner (faster & cheaper than macos-latest)
timeout-minutes: 30
needs: test-unit
if: github.event_name == 'push' || github.event.pull_request.draft == false
steps:
- name: Checkout code
uses: actions/checkout@v4
with:
fetch-depth: 1
- name: Setup JDK ${{ env.JAVA_VERSION }}
uses: actions/setup-java@v4
with:
java-version: ${{ env.JAVA_VERSION }}
distribution: ${{ env.JAVA_DISTRIBUTION }}
cache: gradle
- name: Setup Gradle
uses: gradle/actions/setup-gradle@v3
with:
cache-read-only: ${{ github.ref != 'refs/heads/main' }}
- name: Build iOS Framework
run: |
./gradlew \
:composeApp:linkDebugFrameworkIosSimulatorArm64 \
--parallel \
--build-cache \
--configuration-cache \
--no-daemon \
--stacktrace
- name: Upload iOS Framework
uses: actions/upload-artifact@v4
with:
name: ios-framework-debug
path: composeApp/build/bin/iosSimulatorArm64/debugFramework/
retention-days: 14
# ================== Desktop Build ==================
build-desktop:
name: Build Desktop
strategy:
fail-fast: false # Continue other OS builds if one fails
matrix:
os: [ubuntu-latest, macos-14, windows-latest]
runs-on: ${{ matrix.os }}
timeout-minutes: 30
needs: test-unit
# Only build desktop on main branch or explicit request
if: github.ref == 'refs/heads/main' || github.event_name == 'workflow_dispatch'
steps:
- name: Checkout code
uses: actions/checkout@v4
with:
fetch-depth: 1
- name: Setup JDK ${{ env.JAVA_VERSION }}
uses: actions/setup-java@v4
with:
java-version: ${{ env.JAVA_VERSION }}
distribution: ${{ env.JAVA_DISTRIBUTION }}
cache: gradle
- name: Setup Gradle
uses: gradle/actions/setup-gradle@v3
with:
cache-read-only: ${{ github.ref != 'refs/heads/main' }}
- name: Build Desktop JAR
run: |
./gradlew \
:composeApp:jvmJar \
--parallel \
--build-cache \
--configuration-cache \
--no-daemon \
--stacktrace
- name: Upload Desktop Distribution
uses: actions/upload-artifact@v4
with:
name: desktop-${{ runner.os }}
path: composeApp/build/compose/binaries/main/app/
retention-days: 14
compression-level: 6 # Good balance for binaries
# ================== Web Build ==================
build-web:
name: Build Web
runs-on: ubuntu-latest
timeout-minutes: 30
needs: test-unit
if: github.event_name == 'push' || github.event.pull_request.draft == false
steps:
- name: Checkout code
uses: actions/checkout@v4
with:
fetch-depth: 1
- name: Setup JDK ${{ env.JAVA_VERSION }}
uses: actions/setup-java@v4
with:
java-version: ${{ env.JAVA_VERSION }}
distribution: ${{ env.JAVA_DISTRIBUTION }}
cache: gradle
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '20'
cache: 'npm'
- name: Setup Gradle
uses: gradle/actions/setup-gradle@v3
with:
cache-read-only: ${{ github.ref != 'refs/heads/main' }}
- name: Build Web
run: |
./gradlew \
:composeApp:jsBrowserProductionWebpack \
--parallel \
--build-cache \
--configuration-cache \
--no-daemon \
--stacktrace
- name: Upload Web Build
uses: actions/upload-artifact@v4
with:
name: web-production
path: composeApp/build/dist/js/productionExecutable/
retention-days: 14
compression-level: 9 # Max compression for web assets
# ================== Code Quality ==================
code-quality:
name: Code Quality
runs-on: ubuntu-latest
timeout-minutes: 15
# Run in parallel with builds, don't wait for tests
steps:
- name: Checkout code
uses: actions/checkout@v4
with:
fetch-depth: 1
- name: Setup JDK ${{ env.JAVA_VERSION }}
uses: actions/setup-java@v4
with:
java-version: ${{ env.JAVA_VERSION }}
distribution: ${{ env.JAVA_DISTRIBUTION }}
cache: gradle
- name: Setup Gradle
uses: gradle/actions/setup-gradle@v3
with:
cache-read-only: true # Read-only for lint
- name: Run Lint
run: |
./gradlew \
:pocketbase-kt-sdk:lintDebug \
:shared:lintDebug \
--parallel \
--build-cache \
--configuration-cache \
--no-daemon \
--continue
- name: Upload Lint Reports
if: failure() # Only upload on failure
uses: actions/upload-artifact@v4
with:
name: lint-reports
path: |
**/build/reports/lint-results*.html
retention-days: 3
# ================== Summary ==================
ci-summary:
name: CI Summary
runs-on: ubuntu-latest
needs: [test-unit, build-android, build-ios, build-desktop, build-web, code-quality]
if: always()
steps:
- name: Check all jobs
run: |
echo "Unit Tests: ${{ needs.test-unit.result }}"
echo "Android Build: ${{ needs.build-android.result }}"
echo "iOS Build: ${{ needs.build-ios.result }}"
echo "Desktop Build: ${{ needs.build-desktop.result }}"
echo "Web Build: ${{ needs.build-web.result }}"
echo "Code Quality: ${{ needs.code-quality.result }}"
if [[ "${{ needs.test-unit.result }}" == "failure" ]] || \
[[ "${{ needs.build-android.result }}" == "failure" ]] || \
[[ "${{ needs.build-ios.result }}" == "failure" ]] || \
[[ "${{ needs.build-desktop.result }}" == "failure" ]] || \
[[ "${{ needs.build-web.result }}" == "failure" ]]; then
echo "❌ CI pipeline failed"
exit 1
else
echo "✅ CI pipeline passed"
fi