From 1fdca019fb22f7e1598577f59c2ff75f5969a042 Mon Sep 17 00:00:00 2001 From: Billie Ponder Date: Sat, 17 Oct 2026 15:47:56 -0400 Subject: [PATCH] Speed up Android CI with parallel checks (#83) Co-authored-by: Developer --- .github/actions/flutter-ci-setup/action.yml | 36 ++++++++ .github/workflows/android-build.yml | 91 ++++++++++++++++----- 2 files changed, 108 insertions(+), 19 deletions(-) create mode 100644 .github/actions/flutter-ci-setup/action.yml diff --git a/.github/actions/flutter-ci-setup/action.yml b/.github/actions/flutter-ci-setup/action.yml new file mode 100644 index 0000000..47f40af --- /dev/null +++ b/.github/actions/flutter-ci-setup/action.yml @@ -0,0 +1,36 @@ +name: Flutter CI setup +description: Set up Flutter dependencies and restore build_runner state for CI jobs. + +inputs: + setup-java: + description: Whether this job needs the pinned Java toolchain. + required: false + default: 'false' + build-runner-cache-key: + description: Cache key for build_runner state. + required: true + +runs: + using: composite + steps: + - name: Set up Java + if: inputs.setup-java == 'true' + uses: actions/setup-java@v5 + with: + distribution: temurin + java-version: ${{ env.JAVA_VERSION }} + cache: gradle + - name: Set up Flutter + uses: subosito/flutter-action@v2 + with: + flutter-version: ${{ env.FLUTTER_VERSION }} + channel: stable + cache: true + - name: Get dependencies + shell: bash + run: flutter pub get + - name: Restore build_runner state + uses: actions/cache@v4 + with: + path: .dart_tool/build + key: ${{ inputs.build-runner-cache-key }} diff --git a/.github/workflows/android-build.yml b/.github/workflows/android-build.yml index cd33ed0..0498d7e 100644 --- a/.github/workflows/android-build.yml +++ b/.github/workflows/android-build.yml @@ -49,8 +49,54 @@ jobs: HEAD_SHA: ${{ github.event.pull_request.head.sha || github.sha }} run: node .github/scripts/detect-android-changes.cjs - analyze-and-build: - name: Analyze, test and debug build + analyze: + name: Analyze + runs-on: ubuntu-latest + needs: detect + if: github.event_name == 'workflow_dispatch' || needs.detect.outputs.android_changed == 'true' + permissions: + contents: read + steps: + - name: Checkout + uses: actions/checkout@v6 + with: + fetch-depth: 1 + - name: Set up Flutter CI + uses: ./.github/actions/flutter-ci-setup + with: + build-runner-cache-key: ${{ runner.os }}-build-runner-${{ hashFiles('pubspec.lock', 'lib/database/**') }} + - name: Generate Drift sources + run: dart run build_runner build --delete-conflicting-outputs + - name: Analyze + run: flutter analyze --no-fatal-infos + + test: + name: Tests (shard ${{ matrix.shard }}/4) + runs-on: ubuntu-latest + needs: detect + if: github.event_name == 'workflow_dispatch' || needs.detect.outputs.android_changed == 'true' + permissions: + contents: read + strategy: + fail-fast: false + matrix: + shard: [0, 1, 2, 3] + steps: + - name: Checkout + uses: actions/checkout@v6 + with: + fetch-depth: 1 + - name: Set up Flutter CI + uses: ./.github/actions/flutter-ci-setup + with: + build-runner-cache-key: ${{ runner.os }}-build-runner-${{ hashFiles('pubspec.lock', 'lib/database/**') }} + - name: Generate Drift sources + run: dart run build_runner build --delete-conflicting-outputs + - name: Run test shard + run: flutter test --total-shards 4 --shard-index ${{ matrix.shard }} + + debug-apk: + name: Debug APK build runs-on: ubuntu-latest needs: detect if: github.event_name == 'workflow_dispatch' || needs.detect.outputs.android_changed == 'true' @@ -61,18 +107,11 @@ jobs: uses: actions/checkout@v6 with: fetch-depth: 1 - - name: Set up Java - uses: actions/setup-java@v5 + - name: Set up Flutter CI + uses: ./.github/actions/flutter-ci-setup with: - distribution: temurin - java-version: ${{ env.JAVA_VERSION }} - cache: gradle - - name: Set up Flutter - uses: subosito/flutter-action@v2 - with: - flutter-version: ${{ env.FLUTTER_VERSION }} - channel: stable - cache: true + setup-java: 'true' + build-runner-cache-key: ${{ runner.os }}-build-runner-${{ hashFiles('pubspec.lock', 'lib/database/**') }} - name: Free runner disk space shell: bash run: | @@ -130,8 +169,6 @@ jobs: flutter --version flutter doctor -v java -version - - name: Get dependencies - run: flutter pub get - name: Generate Drift sources run: dart run build_runner build --delete-conflicting-outputs - name: Commit regenerated Drift sources @@ -148,10 +185,6 @@ jobs: git add lib/database/database.g.dart git commit -m 'Regenerate Drift database source' git push origin HEAD:${GITHUB_REF_NAME} - - name: Analyze - run: flutter analyze --no-fatal-infos - - name: Run tests - run: flutter test - name: Build debug APK shell: bash run: flutter build apk --debug @@ -184,6 +217,26 @@ jobs: if-no-files-found: error retention-days: 3 + analyze-and-build: + name: Analyze, test and debug build + runs-on: ubuntu-latest + needs: [detect, analyze, test, debug-apk] + if: always() && (github.event_name == 'workflow_dispatch' || needs.detect.outputs.android_changed == 'true') + permissions: + contents: read + steps: + - name: Require all Android CI jobs to pass + env: + ANALYZE_RESULT: ${{ needs.analyze.result }} + TEST_RESULT: ${{ needs.test.result }} + DEBUG_APK_RESULT: ${{ needs.debug-apk.result }} + shell: bash + run: | + set -euo pipefail + test "$ANALYZE_RESULT" = success + test "$TEST_RESULT" = success + test "$DEBUG_APK_RESULT" = success + release: name: Build signed release APK and AAB runs-on: ubuntu-latest