From 9d4ddefe17b07b25cff9b7671b3c2cb2bd6d1aa6 Mon Sep 17 00:00:00 2001 From: Guillaume Bernos Date: Thu, 6 Aug 2026 15:03:39 +0200 Subject: [PATCH] ci: remove unecessary cleaning step and make e2e-smoke and swift-integration only run when needed --- .github/workflows/all_plugins.yaml | 15 +++ .github/workflows/e2e_tests_fdc.yaml | 8 -- .github/workflows/e2e_tests_firestore.yaml | 1 - .github/workflows/e2e_tests_pipeline.yaml | 8 -- .github/workflows/e2e_tests_smoke.yaml | 49 ++++---- .github/workflows/reusable_e2e_android.yaml | 8 -- .github/workflows/reusable_e2e_ios.yaml | 21 ---- .github/workflows/reusable_repo_changes.yaml | 114 +++++++++++++++++++ 8 files changed, 154 insertions(+), 70 deletions(-) create mode 100644 .github/workflows/reusable_repo_changes.yaml diff --git a/.github/workflows/all_plugins.yaml b/.github/workflows/all_plugins.yaml index 7c7a93f39ae5..45162c2e9872 100644 --- a/.github/workflows/all_plugins.yaml +++ b/.github/workflows/all_plugins.yaml @@ -22,6 +22,15 @@ permissions: contents: read jobs: + # analyze, format and test below are deliberately ungated: they are pure Dart + # and every change in the repo is in scope for them. Only the three jobs that + # build for a specific platform - the two Swift ones and the web example + # build - are platform-scoped. + changes: + uses: ./.github/workflows/reusable_repo_changes.yaml + with: + app-path: 'packages/*/*/example' + # Home for every check that needs nothing but a bootstrapped workspace. The # pub dry run, the example `pub get` and the license-header check used to be # three separate jobs; each ran for a couple of minutes and paid a full @@ -153,6 +162,8 @@ jobs: find packages -type d -name build -prune -exec rm -rf {} + build_examples_dart: + needs: changes + if: needs.changes.outputs.web == 'true' timeout-minutes: 30 runs-on: ubuntu-latest steps: @@ -174,6 +185,8 @@ jobs: # `swift-integration.dart` still builds both when no `--platform` is passed, # which is how it is run locally. swift-integration-ios: + needs: changes + if: needs.changes.outputs.ios == 'true' runs-on: macos-15 timeout-minutes: 35 env: @@ -204,6 +217,8 @@ jobs: dart ./.github/workflows/scripts/swift-integration.dart --platform=ios $FLUTTER_DEPENDENCIES swift-integration-macos: + needs: changes + if: needs.changes.outputs.macos == 'true' runs-on: macos-15 timeout-minutes: 35 env: diff --git a/.github/workflows/e2e_tests_fdc.yaml b/.github/workflows/e2e_tests_fdc.yaml index 11cb8ce5f637..3bcde820e7cc 100644 --- a/.github/workflows/e2e_tests_fdc.yaml +++ b/.github/workflows/e2e_tests_fdc.yaml @@ -72,14 +72,6 @@ jobs: sudo udevadm trigger --name-match=kvm - name: Gradle cache uses: gradle/actions/setup-gradle@90ddb51e90a5fd9ba75f40cf85156b7b41bf76a3 - - name: Free Disk Space (Ubuntu) - uses: AdityaGarg8/remove-unwanted-software@90e01b21170618765a73370fcc3abbd1684a7793 - with: - remove-dotnet: true - remove-haskell: true - remove-codeql: true - remove-docker-images: true - remove-large-packages: true - name: Prepare AVD home on /mnt run: | sudo mkdir -p /mnt/avd diff --git a/.github/workflows/e2e_tests_firestore.yaml b/.github/workflows/e2e_tests_firestore.yaml index d5d06b3e250b..0b1ad1b386e2 100644 --- a/.github/workflows/e2e_tests_firestore.yaml +++ b/.github/workflows/e2e_tests_firestore.yaml @@ -69,7 +69,6 @@ jobs: package-path: 'packages/cloud_firestore/cloud_firestore' package-scope: 'cloud_firestore*' cache-key-suffix: 'firestore' - ios-free-up-space: true native-config-args: '--firestore-native' nightly_test_mode: ${{ inputs.nightly_test_mode == true }} diff --git a/.github/workflows/e2e_tests_pipeline.yaml b/.github/workflows/e2e_tests_pipeline.yaml index 1711cfd8dadc..b3a3aae592d3 100644 --- a/.github/workflows/e2e_tests_pipeline.yaml +++ b/.github/workflows/e2e_tests_pipeline.yaml @@ -73,14 +73,6 @@ jobs: sudo udevadm trigger --name-match=kvm - name: Gradle cache uses: gradle/actions/setup-gradle@90ddb51e90a5fd9ba75f40cf85156b7b41bf76a3 - - name: Free Disk Space (Ubuntu) - uses: AdityaGarg8/remove-unwanted-software@90e01b21170618765a73370fcc3abbd1684a7793 - with: - remove-dotnet: true - remove-haskell: true - remove-codeql: true - remove-docker-images: true - remove-large-packages: true - name: Prepare AVD home on /mnt run: | sudo mkdir -p /mnt/avd diff --git a/.github/workflows/e2e_tests_smoke.yaml b/.github/workflows/e2e_tests_smoke.yaml index 2d1ae9b4e593..3c91f5b3d812 100644 --- a/.github/workflows/e2e_tests_smoke.yaml +++ b/.github/workflows/e2e_tests_smoke.yaml @@ -2,8 +2,12 @@ name: e2e-smoke # The `tests` app depends on every plugin in the repository at once. Its job is # to prove they still build and boot together, so unlike the per-package e2e -# workflows this one is deliberately NOT path-scoped to a package: any change -# that is not documentation can break the combined app. +# workflows this one is deliberately NOT path-scoped to a package: a change to +# any plugin can break the combined app. +# +# It is still scoped by *platform*, via reusable_repo_changes.yaml: an +# Android-only change anywhere in the repo runs the android jobs and skips the +# four platforms it cannot affect. concurrency: group: ${{ github.workflow }}-${{ github.ref }}-smoke @@ -38,7 +42,14 @@ on: default: false jobs: + changes: + uses: ./.github/workflows/reusable_repo_changes.yaml + with: + app-path: 'tests' + android: + needs: changes + if: needs.changes.outputs.android == 'true' permissions: contents: read runs-on: ubuntu-latest @@ -79,14 +90,6 @@ jobs: sudo udevadm trigger --name-match=kvm - name: Gradle cache uses: gradle/actions/setup-gradle@90ddb51e90a5fd9ba75f40cf85156b7b41bf76a3 - - name: Free Disk Space (Ubuntu) - uses: AdityaGarg8/remove-unwanted-software@90e01b21170618765a73370fcc3abbd1684a7793 - with: - remove-dotnet: true - remove-haskell: true - remove-codeql: true - remove-docker-images: true - remove-large-packages: true - name: Prepare AVD home on /mnt # GitHub-hosted runners mount a ~74GB volume at /mnt. Create it before AVD cache # restore and android-emulator-runner (avdmanager needs the space at create time). @@ -177,6 +180,8 @@ jobs: ~/.android/adb* agp9-compatibility: + needs: changes + if: needs.changes.outputs.android == 'true' permissions: contents: read runs-on: ubuntu-latest @@ -194,6 +199,8 @@ jobs: run: bash ./.github/workflows/scripts/agp9-compatibility.sh ios: + needs: changes + if: needs.changes.outputs.ios == 'true' permissions: contents: read runs-on: macos-15 @@ -245,20 +252,6 @@ jobs: restore-keys: firebase-emulators-v5- - name: Generate dummy Firebase configs run: dart ./.github/workflows/scripts/generate-dummy-firebase-configs.dart - - name: 'Free up space' - run: | - sudo rm -rf \ - /usr/local/share/.cache \ - /opt/microsoft/msedge \ - /opt/microsoft/powershell \ - /opt/pipx \ - /usr/lib/mono \ - /usr/local/julia* \ - /usr/local/lib/android \ - /usr/local/share/chromium \ - /usr/local/share/powershell \ - /usr/share/dotnet - df -h / - name: 'Build Application' working-directory: tests timeout-minutes: 25 @@ -329,6 +322,8 @@ jobs: path: tests/ios/Pods macos: + needs: changes + if: needs.changes.outputs.macos == 'true' permissions: contents: read runs-on: macos-15 @@ -462,6 +457,8 @@ jobs: path: tests/macos/Pods web: + needs: changes + if: needs.changes.outputs.web == 'true' permissions: contents: read runs-on: ubuntu-latest @@ -536,6 +533,8 @@ jobs: path: ~/.cache/firebase/emulators web-wasm: + needs: changes + if: needs.changes.outputs.web == 'true' permissions: contents: read runs-on: ubuntu-latest @@ -615,6 +614,8 @@ jobs: path: ~/.cache/firebase/emulators windows: + needs: changes + if: needs.changes.outputs.windows == 'true' permissions: contents: read runs-on: windows-latest diff --git a/.github/workflows/reusable_e2e_android.yaml b/.github/workflows/reusable_e2e_android.yaml index c9c7bd5a0ddb..df2f599bc8f8 100644 --- a/.github/workflows/reusable_e2e_android.yaml +++ b/.github/workflows/reusable_e2e_android.yaml @@ -166,14 +166,6 @@ jobs: sudo udevadm trigger --name-match=kvm - name: Gradle cache uses: gradle/actions/setup-gradle@90ddb51e90a5fd9ba75f40cf85156b7b41bf76a3 - - name: Free Disk Space (Ubuntu) - uses: AdityaGarg8/remove-unwanted-software@90e01b21170618765a73370fcc3abbd1684a7793 - with: - remove-dotnet: true - remove-haskell: true - remove-codeql: true - remove-docker-images: true - remove-large-packages: true - name: Prepare AVD home on /mnt # GitHub-hosted runners mount a ~74GB volume at /mnt. Create it before AVD cache # restore and android-emulator-runner (avdmanager needs the space at create time). diff --git a/.github/workflows/reusable_e2e_ios.yaml b/.github/workflows/reusable_e2e_ios.yaml index 99804f055750..f1412fd2a92e 100644 --- a/.github/workflows/reusable_e2e_ios.yaml +++ b/.github/workflows/reusable_e2e_ios.yaml @@ -87,12 +87,6 @@ on: covered either way. type: boolean default: true - ios-free-up-space: - description: >- - Runs the aggressive `rm -rf` of preinstalled toolchains before the iOS - build. Only cloud_firestore needs it (its build fills the runner disk). - type: boolean - default: false nightly_test_mode: description: >- Passed down from nightly.yaml. Shortens the job timeout to 5 minutes. @@ -207,21 +201,6 @@ jobs: run: | # shellcheck disable=SC2086 # an argument list: word-splitting is the point dart ./.github/workflows/scripts/generate-dummy-firebase-configs.dart $NATIVE_CONFIG_ARGS - - name: 'Free up space' - if: inputs.ios-free-up-space - run: | - sudo rm -rf \ - /usr/local/share/.cache \ - /opt/microsoft/msedge \ - /opt/microsoft/powershell \ - /opt/pipx \ - /usr/lib/mono \ - /usr/local/julia* \ - /usr/local/lib/android \ - /usr/local/share/chromium \ - /usr/local/share/powershell \ - /usr/share/dotnet - df -h / - name: Prepare iOS project for Swift Package Manager # Done here rather than in the repository: the committed Podfile is what # CocoaPods users of the example rely on, and `flutter build` prefers diff --git a/.github/workflows/reusable_repo_changes.yaml b/.github/workflows/reusable_repo_changes.yaml new file mode 100644 index 000000000000..7243d8ca094c --- /dev/null +++ b/.github/workflows/reusable_repo_changes.yaml @@ -0,0 +1,114 @@ +name: reusable-repo-changes + +# Repo-wide sibling of reusable_e2e_changes.yaml. +# +# That one scopes every filter to a single package, because each +# `e2e_tests_.yaml` tests one plugin. The callers here - the smoke +# suite and all_plugins - build apps that depend on every plugin at once, so +# their filters have to span all packages instead: a Kotlin-only change in any +# plugin should still skip the iOS, macOS, web and Windows jobs. +# +# `app-path` is the app the caller builds and drives: `tests` for the smoke +# suite, `packages/*/*/example` for all_plugins. It is a glob, not a literal +# path, so one input covers both the single app and the per-package examples. +# +# Non-PR events (push to main, the nightly workflow_call) always run +# everything: the filter step is skipped and its empty outputs fall back to +# 'true' below. Same contract as reusable_e2e_changes.yaml. + +on: + workflow_call: + inputs: + app-path: + description: >- + Glob for the app(s) the caller builds, without a trailing slash, e.g. + 'tests' or 'packages/*/*/example'. Its per-platform subdirectory + (`/ios/**`) gates that platform; its Dart + (`/lib/**`) is shared across all of them. + type: string + required: true + outputs: + android: + description: 'true when the diff can affect the Android build or tests.' + value: ${{ jobs.changes.outputs.android }} + ios: + description: 'true when the diff can affect the iOS build or tests.' + value: ${{ jobs.changes.outputs.ios }} + macos: + description: 'true when the diff can affect the macOS build or tests.' + value: ${{ jobs.changes.outputs.macos }} + web: + description: 'true when the diff can affect the web (JS or wasm) build or tests.' + value: ${{ jobs.changes.outputs.web }} + windows: + description: 'true when the diff can affect the Windows build or tests.' + value: ${{ jobs.changes.outputs.windows }} + +permissions: + contents: read + +jobs: + changes: + permissions: + contents: read + runs-on: ubuntu-latest + timeout-minutes: 5 + outputs: + android: ${{ steps.filter.outputs.android || 'true' }} + ios: ${{ steps.filter.outputs.ios || 'true' }} + macos: ${{ steps.filter.outputs.macos || 'true' }} + web: ${{ steps.filter.outputs.web || 'true' }} + windows: ${{ steps.filter.outputs.windows || 'true' }} + steps: + - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 + if: github.event_name == 'pull_request' + - uses: dorny/paths-filter@d1c1ffe0248fe513906c8e24db8ea791d46f8590 + if: github.event_name == 'pull_request' + id: filter + with: + # `packages/*/*` is every plugin package - main, platform interface + # and web implementation alike. `packages/_flutterfire_internals` is + # the one package that sits a level higher, so it needs its own entry. + # + # Any change under `.github/workflows` runs everything. The filters + # here decide what CI skips, so a change to how CI works must not be + # able to skip its own validation. + # + # Dart is shared: a change to `_web/lib` runs the native jobs + # too, even though only web consumes it. Erring towards running an + # extra job beats needing a glob that can express "every package + # except the web ones". + filters: | + shared: &shared + - 'packages/*/*/lib/**' + - 'packages/*/*/pubspec.yaml' + - 'packages/_flutterfire_internals/**' + - '${{ inputs.app-path }}/lib/**' + - '${{ inputs.app-path }}/pubspec.yaml' + - '${{ inputs.app-path }}/integration_test/**' + - '${{ inputs.app-path }}/test_driver/**' + - '.github/workflows/**' + - '.github/actions/**' + - 'scripts/**' + - 'pubspec.yaml' + android: + - *shared + - 'packages/*/*/android/**' + - '${{ inputs.app-path }}/android/**' + ios: + - *shared + - 'packages/*/*/ios/**' + - 'packages/*/*/darwin/**' + - '${{ inputs.app-path }}/ios/**' + macos: + - *shared + - 'packages/*/*/macos/**' + - 'packages/*/*/darwin/**' + - '${{ inputs.app-path }}/macos/**' + web: + - *shared + - '${{ inputs.app-path }}/web/**' + windows: + - *shared + - 'packages/*/*/windows/**' + - '${{ inputs.app-path }}/windows/**'