From d6420c246229bcb9140fa53edb6afd444a04eac2 Mon Sep 17 00:00:00 2001 From: Matej Knopp Date: Fri, 2 Oct 2026 20:41:10 +0200 Subject: [PATCH 1/6] Add unittests and smoke tests to CI. (#10) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Tests now run in the engine artifacts workflow The workflow used to only build artifacts and only triggered on staging pushes. Now PRs also trigger it, so changes get tested before merge: - Test jobs reuse build-output tars uploaded by the build jobs. 5 jobs run engine C++ unit tests, 13 jobs run a smoke test (dev/smoke_test/run.py) — in debug it launches the app on each platform and asserts hot reload (after a real source modification) and hot restart; profile/release verify the released compile. - Publishing to R2 still happens only on pushes to staging, and only after all tests pass. --- .../build-and-upload-engine-artifacts.yml | 2133 +++++++++++++---- .github/workflows/call-smoke-test.yml | 68 + .github/workflows/smoke-test.yml | 173 ++ dev/smoke_test/main.dart | 33 + dev/smoke_test/run.py | 561 +++++ engine/src/build/vs_toolchain.py | 7 + .../builders/linux_android_debug_engine.json | 4 +- .../ci/builders/linux_arm_host_engine.json | 9 +- .../builders/linux_host_desktop_engine.json | 9 +- .../ci/builders/linux_host_engine.json | 7 +- .../ci/builders/linux_host_engine_test.json | 6 +- .../src/flutter/ci/builders/linux_unopt.json | 2 +- .../flutter/ci/builders/mac_host_engine.json | 18 +- .../builders/mac_ios_engine_no_ext_safe.json | 52 + .../builders/standalone/linux_benchmarks.json | 2 +- .../ci/builders/windows_host_engine.json | 11 +- .../lib/web_ui/lib/platform_dispatcher.dart | 9 + .../shell/platform/darwin/macos/BUILD.gn | 44 +- .../shell/platform/darwin/macos/README.md | 4 +- .../embedder/tests/embedder_unittests.cc | 4 +- engine/src/flutter/testing/run_tests.py | 145 +- .../artifact_tests.json | 57 + .../lib/github_workflow_generator.dart | 530 +++- .../lib/src/base/user_messages.dart | 4 +- .../lib/src/build_system/targets/web.dart | 61 +- .../lib/src/linux/linux_doctor.dart | 4 +- .../app/linux.tmpl/CMakeLists.txt.tmpl | 5 +- .../app/linux.tmpl/flutter/CMakeLists.txt | 2 - .../app/linux.tmpl/runner/CMakeLists.txt | 2 +- .../linux.tmpl/runner/my_application.cc.tmpl | 9 +- .../app/linux.tmpl/runner/my_application.h | 4 +- .../plugin/linux.tmpl/CMakeLists.txt.tmpl | 4 +- .../templates/template_manifest.json | 1 + .../linux/linux_doctor_test.dart | 13 +- ...project-only-depends-on-glib-not-Gtk.patch | 224 ++ ...Application-template-in-the-manifest.patch | 22 + ...er-bundle-the-Roboto-fallback-on-web.patch | 92 + scripts/update_github_workflow.sh | 1 + 38 files changed, 3619 insertions(+), 717 deletions(-) create mode 100644 .github/workflows/call-smoke-test.yml create mode 100644 .github/workflows/smoke-test.yml create mode 100644 dev/smoke_test/main.dart create mode 100644 dev/smoke_test/run.py create mode 100644 engine/src/flutter/tools/pkg/github_workflow_generator/artifact_tests.json create mode 100644 packages/flutter_tools_patches/0001-Linux-project-only-depends-on-glib-not-Gtk.patch create mode 100644 packages/flutter_tools_patches/0005-flutter_tools-List-Application-template-in-the-manifest.patch create mode 100644 packages/flutter_tools_patches/0006-flutter_tools-Never-bundle-the-Roboto-fallback-on-web.patch diff --git a/.github/workflows/build-and-upload-engine-artifacts.yml b/.github/workflows/build-and-upload-engine-artifacts.yml index 31bd5950..6517b00b 100644 --- a/.github/workflows/build-and-upload-engine-artifacts.yml +++ b/.github/workflows/build-and-upload-engine-artifacts.yml @@ -3,11 +3,11 @@ name: Engine Artifacts on: push: - branches: ["master", "staging"] + branches: ["staging"] + pull_request: env: DEPOT_TOOLS_WIN_TOOLCHAIN: 0 FLUTTER_PREBUILT_DART_SDK: 1 - R2_BUCKET: flutter-zero-engine ENGINE_CHECKOUT_PATH: ${{ github.workspace }}/engine jobs: guard: @@ -62,7 +62,14 @@ jobs: - name: Set up depot_tools if: runner.os != 'Windows' run: | - git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git $HOME/depot_tools + rm -rf "$HOME/depot_tools" + for attempt in 1 2 3; do + git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git "$HOME/depot_tools" && break + rm -rf "$HOME/depot_tools" + echo "depot_tools clone failed (attempt $attempt), retrying..." + sleep 5 + done + test -d "$HOME/depot_tools/.git" # Append depot_tools to the PATH for subsequent steps echo "$HOME/depot_tools" >> $GITHUB_PATH - name: Free disk space @@ -71,7 +78,14 @@ jobs: - name: Set up depot_tools if: runner.os == 'Windows' run: | - git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git $HOME/depot_tools + rm -rf "$HOME/depot_tools" + for attempt in 1 2 3; do + git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git "$HOME/depot_tools" && break + rm -rf "$HOME/depot_tools" + echo "depot_tools clone failed (attempt $attempt), retrying..." + sleep 5 + done + test -d "$HOME/depot_tools/.git" # Append depot_tools to the PATH for subsequent steps DEPOT_TOOLS_WIN=$(cygpath -w "$HOME/depot_tools") echo "$DEPOT_TOOLS_WIN" >> $GITHUB_PATH @@ -92,6 +106,7 @@ jobs: ./flutter/bin/et build --config ci/host_debug_framework - name: Tar build files run: | + find engine/src/out/ci/host_debug_framework -type l -lname "/*" -delete || true tar -cvf mac_host_debug_framework.tar engine/src/out/ci/host_debug_framework - name: Upload build files uses: actions/upload-artifact@v4 @@ -115,7 +130,14 @@ jobs: - name: Set up depot_tools if: runner.os != 'Windows' run: | - git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git $HOME/depot_tools + rm -rf "$HOME/depot_tools" + for attempt in 1 2 3; do + git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git "$HOME/depot_tools" && break + rm -rf "$HOME/depot_tools" + echo "depot_tools clone failed (attempt $attempt), retrying..." + sleep 5 + done + test -d "$HOME/depot_tools/.git" # Append depot_tools to the PATH for subsequent steps echo "$HOME/depot_tools" >> $GITHUB_PATH - name: Free disk space @@ -124,7 +146,14 @@ jobs: - name: Set up depot_tools if: runner.os == 'Windows' run: | - git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git $HOME/depot_tools + rm -rf "$HOME/depot_tools" + for attempt in 1 2 3; do + git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git "$HOME/depot_tools" && break + rm -rf "$HOME/depot_tools" + echo "depot_tools clone failed (attempt $attempt), retrying..." + sleep 5 + done + test -d "$HOME/depot_tools/.git" # Append depot_tools to the PATH for subsequent steps DEPOT_TOOLS_WIN=$(cygpath -w "$HOME/depot_tools") echo "$DEPOT_TOOLS_WIN" >> $GITHUB_PATH @@ -143,8 +172,16 @@ jobs: run: | cd engine/src ./flutter/bin/et build --config ci/host_debug + - name: Run engine unit tests + run: | + cd engine/src + python3 flutter/testing/run_tests.py \ + --variant ci/host_debug \ + --type engine \ + --engine-capture-core-dump - name: Tar build files run: | + find engine/src/out/ci/host_debug -type l -lname "/*" -delete || true tar -cvf mac_host_debug.tar engine/src/out/ci/host_debug - name: Upload build files uses: actions/upload-artifact@v4 @@ -188,7 +225,14 @@ jobs: - name: Set up depot_tools if: runner.os != 'Windows' run: | - git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git $HOME/depot_tools + rm -rf "$HOME/depot_tools" + for attempt in 1 2 3; do + git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git "$HOME/depot_tools" && break + rm -rf "$HOME/depot_tools" + echo "depot_tools clone failed (attempt $attempt), retrying..." + sleep 5 + done + test -d "$HOME/depot_tools/.git" # Append depot_tools to the PATH for subsequent steps echo "$HOME/depot_tools" >> $GITHUB_PATH - name: Free disk space @@ -197,7 +241,14 @@ jobs: - name: Set up depot_tools if: runner.os == 'Windows' run: | - git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git $HOME/depot_tools + rm -rf "$HOME/depot_tools" + for attempt in 1 2 3; do + git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git "$HOME/depot_tools" && break + rm -rf "$HOME/depot_tools" + echo "depot_tools clone failed (attempt $attempt), retrying..." + sleep 5 + done + test -d "$HOME/depot_tools/.git" # Append depot_tools to the PATH for subsequent steps DEPOT_TOOLS_WIN=$(cygpath -w "$HOME/depot_tools") echo "$DEPOT_TOOLS_WIN" >> $GITHUB_PATH @@ -218,6 +269,7 @@ jobs: ./flutter/bin/et build --config ci/host_debug_gen_snapshot - name: Tar build files run: | + find engine/src/out/ci/host_debug_gen_snapshot -type l -lname "/*" -delete || true tar -cvf mac_host_debug_gen_snapshot.tar engine/src/out/ci/host_debug_gen_snapshot - name: Upload build files uses: actions/upload-artifact@v4 @@ -241,7 +293,14 @@ jobs: - name: Set up depot_tools if: runner.os != 'Windows' run: | - git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git $HOME/depot_tools + rm -rf "$HOME/depot_tools" + for attempt in 1 2 3; do + git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git "$HOME/depot_tools" && break + rm -rf "$HOME/depot_tools" + echo "depot_tools clone failed (attempt $attempt), retrying..." + sleep 5 + done + test -d "$HOME/depot_tools/.git" # Append depot_tools to the PATH for subsequent steps echo "$HOME/depot_tools" >> $GITHUB_PATH - name: Free disk space @@ -250,7 +309,14 @@ jobs: - name: Set up depot_tools if: runner.os == 'Windows' run: | - git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git $HOME/depot_tools + rm -rf "$HOME/depot_tools" + for attempt in 1 2 3; do + git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git "$HOME/depot_tools" && break + rm -rf "$HOME/depot_tools" + echo "depot_tools clone failed (attempt $attempt), retrying..." + sleep 5 + done + test -d "$HOME/depot_tools/.git" # Append depot_tools to the PATH for subsequent steps DEPOT_TOOLS_WIN=$(cygpath -w "$HOME/depot_tools") echo "$DEPOT_TOOLS_WIN" >> $GITHUB_PATH @@ -269,8 +335,16 @@ jobs: run: | cd engine/src ./flutter/bin/et build --config ci/host_profile + - name: Run engine unit tests + run: | + cd engine/src + python3 flutter/testing/run_tests.py \ + --variant ci/host_profile \ + --type engine \ + --engine-capture-core-dump - name: Tar build files run: | + find engine/src/out/ci/host_profile -type l -lname "/*" -delete || true tar -cvf mac_host_profile.tar engine/src/out/ci/host_profile - name: Upload build files uses: actions/upload-artifact@v4 @@ -304,7 +378,14 @@ jobs: - name: Set up depot_tools if: runner.os != 'Windows' run: | - git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git $HOME/depot_tools + rm -rf "$HOME/depot_tools" + for attempt in 1 2 3; do + git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git "$HOME/depot_tools" && break + rm -rf "$HOME/depot_tools" + echo "depot_tools clone failed (attempt $attempt), retrying..." + sleep 5 + done + test -d "$HOME/depot_tools/.git" # Append depot_tools to the PATH for subsequent steps echo "$HOME/depot_tools" >> $GITHUB_PATH - name: Free disk space @@ -313,7 +394,14 @@ jobs: - name: Set up depot_tools if: runner.os == 'Windows' run: | - git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git $HOME/depot_tools + rm -rf "$HOME/depot_tools" + for attempt in 1 2 3; do + git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git "$HOME/depot_tools" && break + rm -rf "$HOME/depot_tools" + echo "depot_tools clone failed (attempt $attempt), retrying..." + sleep 5 + done + test -d "$HOME/depot_tools/.git" # Append depot_tools to the PATH for subsequent steps DEPOT_TOOLS_WIN=$(cygpath -w "$HOME/depot_tools") echo "$DEPOT_TOOLS_WIN" >> $GITHUB_PATH @@ -334,6 +422,7 @@ jobs: ./flutter/bin/et build --config ci/host_profile_framework - name: Tar build files run: | + find engine/src/out/ci/host_profile_framework -type l -lname "/*" -delete || true tar -cvf mac_host_profile_framework.tar engine/src/out/ci/host_profile_framework - name: Upload build files uses: actions/upload-artifact@v4 @@ -357,7 +446,14 @@ jobs: - name: Set up depot_tools if: runner.os != 'Windows' run: | - git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git $HOME/depot_tools + rm -rf "$HOME/depot_tools" + for attempt in 1 2 3; do + git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git "$HOME/depot_tools" && break + rm -rf "$HOME/depot_tools" + echo "depot_tools clone failed (attempt $attempt), retrying..." + sleep 5 + done + test -d "$HOME/depot_tools/.git" # Append depot_tools to the PATH for subsequent steps echo "$HOME/depot_tools" >> $GITHUB_PATH - name: Free disk space @@ -366,7 +462,14 @@ jobs: - name: Set up depot_tools if: runner.os == 'Windows' run: | - git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git $HOME/depot_tools + rm -rf "$HOME/depot_tools" + for attempt in 1 2 3; do + git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git "$HOME/depot_tools" && break + rm -rf "$HOME/depot_tools" + echo "depot_tools clone failed (attempt $attempt), retrying..." + sleep 5 + done + test -d "$HOME/depot_tools/.git" # Append depot_tools to the PATH for subsequent steps DEPOT_TOOLS_WIN=$(cygpath -w "$HOME/depot_tools") echo "$DEPOT_TOOLS_WIN" >> $GITHUB_PATH @@ -387,6 +490,7 @@ jobs: ./flutter/bin/et build --config ci/host_profile_gen_snapshot - name: Tar build files run: | + find engine/src/out/ci/host_profile_gen_snapshot -type l -lname "/*" -delete || true tar -cvf mac_host_profile_gen_snapshot.tar engine/src/out/ci/host_profile_gen_snapshot - name: Upload build files uses: actions/upload-artifact@v4 @@ -410,7 +514,14 @@ jobs: - name: Set up depot_tools if: runner.os != 'Windows' run: | - git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git $HOME/depot_tools + rm -rf "$HOME/depot_tools" + for attempt in 1 2 3; do + git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git "$HOME/depot_tools" && break + rm -rf "$HOME/depot_tools" + echo "depot_tools clone failed (attempt $attempt), retrying..." + sleep 5 + done + test -d "$HOME/depot_tools/.git" # Append depot_tools to the PATH for subsequent steps echo "$HOME/depot_tools" >> $GITHUB_PATH - name: Free disk space @@ -419,7 +530,14 @@ jobs: - name: Set up depot_tools if: runner.os == 'Windows' run: | - git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git $HOME/depot_tools + rm -rf "$HOME/depot_tools" + for attempt in 1 2 3; do + git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git "$HOME/depot_tools" && break + rm -rf "$HOME/depot_tools" + echo "depot_tools clone failed (attempt $attempt), retrying..." + sleep 5 + done + test -d "$HOME/depot_tools/.git" # Append depot_tools to the PATH for subsequent steps DEPOT_TOOLS_WIN=$(cygpath -w "$HOME/depot_tools") echo "$DEPOT_TOOLS_WIN" >> $GITHUB_PATH @@ -438,8 +556,16 @@ jobs: run: | cd engine/src ./flutter/bin/et build --config ci/host_release + - name: Run engine unit tests + run: | + cd engine/src + python3 flutter/testing/run_tests.py \ + --variant ci/host_release \ + --type engine \ + --engine-capture-core-dump - name: Tar build files run: | + find engine/src/out/ci/host_release -type l -lname "/*" -delete || true tar -cvf mac_host_release.tar engine/src/out/ci/host_release - name: Upload build files uses: actions/upload-artifact@v4 @@ -483,7 +609,14 @@ jobs: - name: Set up depot_tools if: runner.os != 'Windows' run: | - git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git $HOME/depot_tools + rm -rf "$HOME/depot_tools" + for attempt in 1 2 3; do + git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git "$HOME/depot_tools" && break + rm -rf "$HOME/depot_tools" + echo "depot_tools clone failed (attempt $attempt), retrying..." + sleep 5 + done + test -d "$HOME/depot_tools/.git" # Append depot_tools to the PATH for subsequent steps echo "$HOME/depot_tools" >> $GITHUB_PATH - name: Free disk space @@ -492,7 +625,14 @@ jobs: - name: Set up depot_tools if: runner.os == 'Windows' run: | - git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git $HOME/depot_tools + rm -rf "$HOME/depot_tools" + for attempt in 1 2 3; do + git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git "$HOME/depot_tools" && break + rm -rf "$HOME/depot_tools" + echo "depot_tools clone failed (attempt $attempt), retrying..." + sleep 5 + done + test -d "$HOME/depot_tools/.git" # Append depot_tools to the PATH for subsequent steps DEPOT_TOOLS_WIN=$(cygpath -w "$HOME/depot_tools") echo "$DEPOT_TOOLS_WIN" >> $GITHUB_PATH @@ -513,6 +653,7 @@ jobs: ./flutter/bin/et build --config ci/host_release_framework - name: Tar build files run: | + find engine/src/out/ci/host_release_framework -type l -lname "/*" -delete || true tar -cvf mac_host_release_framework.tar engine/src/out/ci/host_release_framework - name: Upload build files uses: actions/upload-artifact@v4 @@ -536,7 +677,14 @@ jobs: - name: Set up depot_tools if: runner.os != 'Windows' run: | - git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git $HOME/depot_tools + rm -rf "$HOME/depot_tools" + for attempt in 1 2 3; do + git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git "$HOME/depot_tools" && break + rm -rf "$HOME/depot_tools" + echo "depot_tools clone failed (attempt $attempt), retrying..." + sleep 5 + done + test -d "$HOME/depot_tools/.git" # Append depot_tools to the PATH for subsequent steps echo "$HOME/depot_tools" >> $GITHUB_PATH - name: Free disk space @@ -545,7 +693,14 @@ jobs: - name: Set up depot_tools if: runner.os == 'Windows' run: | - git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git $HOME/depot_tools + rm -rf "$HOME/depot_tools" + for attempt in 1 2 3; do + git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git "$HOME/depot_tools" && break + rm -rf "$HOME/depot_tools" + echo "depot_tools clone failed (attempt $attempt), retrying..." + sleep 5 + done + test -d "$HOME/depot_tools/.git" # Append depot_tools to the PATH for subsequent steps DEPOT_TOOLS_WIN=$(cygpath -w "$HOME/depot_tools") echo "$DEPOT_TOOLS_WIN" >> $GITHUB_PATH @@ -566,6 +721,7 @@ jobs: ./flutter/bin/et build --config ci/host_release_gen_snapshot - name: Tar build files run: | + find engine/src/out/ci/host_release_gen_snapshot -type l -lname "/*" -delete || true tar -cvf mac_host_release_gen_snapshot.tar engine/src/out/ci/host_release_gen_snapshot - name: Upload build files uses: actions/upload-artifact@v4 @@ -589,7 +745,14 @@ jobs: - name: Set up depot_tools if: runner.os != 'Windows' run: | - git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git $HOME/depot_tools + rm -rf "$HOME/depot_tools" + for attempt in 1 2 3; do + git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git "$HOME/depot_tools" && break + rm -rf "$HOME/depot_tools" + echo "depot_tools clone failed (attempt $attempt), retrying..." + sleep 5 + done + test -d "$HOME/depot_tools/.git" # Append depot_tools to the PATH for subsequent steps echo "$HOME/depot_tools" >> $GITHUB_PATH - name: Free disk space @@ -598,7 +761,14 @@ jobs: - name: Set up depot_tools if: runner.os == 'Windows' run: | - git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git $HOME/depot_tools + rm -rf "$HOME/depot_tools" + for attempt in 1 2 3; do + git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git "$HOME/depot_tools" && break + rm -rf "$HOME/depot_tools" + echo "depot_tools clone failed (attempt $attempt), retrying..." + sleep 5 + done + test -d "$HOME/depot_tools/.git" # Append depot_tools to the PATH for subsequent steps DEPOT_TOOLS_WIN=$(cygpath -w "$HOME/depot_tools") echo "$DEPOT_TOOLS_WIN" >> $GITHUB_PATH @@ -617,8 +787,16 @@ jobs: run: | cd engine/src ./flutter/bin/et build --config ci/mac_debug_arm64 + - name: Run engine unit tests + run: | + cd engine/src + python3 flutter/testing/run_tests.py \ + --variant ci/mac_debug_arm64 \ + --type engine \ + --engine-capture-core-dump - name: Tar build files run: | + find engine/src/out/ci/mac_debug_arm64 -type l -lname "/*" -delete || true tar -cvf mac_debug_arm64.tar engine/src/out/ci/mac_debug_arm64 - name: Upload build files uses: actions/upload-artifact@v4 @@ -662,7 +840,14 @@ jobs: - name: Set up depot_tools if: runner.os != 'Windows' run: | - git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git $HOME/depot_tools + rm -rf "$HOME/depot_tools" + for attempt in 1 2 3; do + git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git "$HOME/depot_tools" && break + rm -rf "$HOME/depot_tools" + echo "depot_tools clone failed (attempt $attempt), retrying..." + sleep 5 + done + test -d "$HOME/depot_tools/.git" # Append depot_tools to the PATH for subsequent steps echo "$HOME/depot_tools" >> $GITHUB_PATH - name: Free disk space @@ -671,7 +856,14 @@ jobs: - name: Set up depot_tools if: runner.os == 'Windows' run: | - git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git $HOME/depot_tools + rm -rf "$HOME/depot_tools" + for attempt in 1 2 3; do + git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git "$HOME/depot_tools" && break + rm -rf "$HOME/depot_tools" + echo "depot_tools clone failed (attempt $attempt), retrying..." + sleep 5 + done + test -d "$HOME/depot_tools/.git" # Append depot_tools to the PATH for subsequent steps DEPOT_TOOLS_WIN=$(cygpath -w "$HOME/depot_tools") echo "$DEPOT_TOOLS_WIN" >> $GITHUB_PATH @@ -692,6 +884,7 @@ jobs: ./flutter/bin/et build --config ci/mac_debug_framework_arm64 - name: Tar build files run: | + find engine/src/out/ci/mac_debug_framework_arm64 -type l -lname "/*" -delete || true tar -cvf mac_debug_framework_arm64.tar engine/src/out/ci/mac_debug_framework_arm64 - name: Upload build files uses: actions/upload-artifact@v4 @@ -715,7 +908,14 @@ jobs: - name: Set up depot_tools if: runner.os != 'Windows' run: | - git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git $HOME/depot_tools + rm -rf "$HOME/depot_tools" + for attempt in 1 2 3; do + git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git "$HOME/depot_tools" && break + rm -rf "$HOME/depot_tools" + echo "depot_tools clone failed (attempt $attempt), retrying..." + sleep 5 + done + test -d "$HOME/depot_tools/.git" # Append depot_tools to the PATH for subsequent steps echo "$HOME/depot_tools" >> $GITHUB_PATH - name: Free disk space @@ -724,7 +924,14 @@ jobs: - name: Set up depot_tools if: runner.os == 'Windows' run: | - git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git $HOME/depot_tools + rm -rf "$HOME/depot_tools" + for attempt in 1 2 3; do + git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git "$HOME/depot_tools" && break + rm -rf "$HOME/depot_tools" + echo "depot_tools clone failed (attempt $attempt), retrying..." + sleep 5 + done + test -d "$HOME/depot_tools/.git" # Append depot_tools to the PATH for subsequent steps DEPOT_TOOLS_WIN=$(cygpath -w "$HOME/depot_tools") echo "$DEPOT_TOOLS_WIN" >> $GITHUB_PATH @@ -745,6 +952,7 @@ jobs: ./flutter/bin/et build --config ci/mac_debug_gen_snapshot_arm64 - name: Tar build files run: | + find engine/src/out/ci/mac_debug_gen_snapshot_arm64 -type l -lname "/*" -delete || true tar -cvf mac_debug_gen_snapshot_arm64.tar engine/src/out/ci/mac_debug_gen_snapshot_arm64 - name: Upload build files uses: actions/upload-artifact@v4 @@ -768,7 +976,14 @@ jobs: - name: Set up depot_tools if: runner.os != 'Windows' run: | - git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git $HOME/depot_tools + rm -rf "$HOME/depot_tools" + for attempt in 1 2 3; do + git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git "$HOME/depot_tools" && break + rm -rf "$HOME/depot_tools" + echo "depot_tools clone failed (attempt $attempt), retrying..." + sleep 5 + done + test -d "$HOME/depot_tools/.git" # Append depot_tools to the PATH for subsequent steps echo "$HOME/depot_tools" >> $GITHUB_PATH - name: Free disk space @@ -777,7 +992,14 @@ jobs: - name: Set up depot_tools if: runner.os == 'Windows' run: | - git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git $HOME/depot_tools + rm -rf "$HOME/depot_tools" + for attempt in 1 2 3; do + git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git "$HOME/depot_tools" && break + rm -rf "$HOME/depot_tools" + echo "depot_tools clone failed (attempt $attempt), retrying..." + sleep 5 + done + test -d "$HOME/depot_tools/.git" # Append depot_tools to the PATH for subsequent steps DEPOT_TOOLS_WIN=$(cygpath -w "$HOME/depot_tools") echo "$DEPOT_TOOLS_WIN" >> $GITHUB_PATH @@ -796,8 +1018,16 @@ jobs: run: | cd engine/src ./flutter/bin/et build --config ci/mac_profile_arm64 + - name: Run engine unit tests + run: | + cd engine/src + python3 flutter/testing/run_tests.py \ + --variant ci/mac_profile_arm64 \ + --type engine \ + --engine-capture-core-dump - name: Tar build files run: | + find engine/src/out/ci/mac_profile_arm64 -type l -lname "/*" -delete || true tar -cvf mac_profile_arm64.tar engine/src/out/ci/mac_profile_arm64 - name: Upload build files uses: actions/upload-artifact@v4 @@ -831,7 +1061,14 @@ jobs: - name: Set up depot_tools if: runner.os != 'Windows' run: | - git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git $HOME/depot_tools + rm -rf "$HOME/depot_tools" + for attempt in 1 2 3; do + git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git "$HOME/depot_tools" && break + rm -rf "$HOME/depot_tools" + echo "depot_tools clone failed (attempt $attempt), retrying..." + sleep 5 + done + test -d "$HOME/depot_tools/.git" # Append depot_tools to the PATH for subsequent steps echo "$HOME/depot_tools" >> $GITHUB_PATH - name: Free disk space @@ -840,7 +1077,14 @@ jobs: - name: Set up depot_tools if: runner.os == 'Windows' run: | - git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git $HOME/depot_tools + rm -rf "$HOME/depot_tools" + for attempt in 1 2 3; do + git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git "$HOME/depot_tools" && break + rm -rf "$HOME/depot_tools" + echo "depot_tools clone failed (attempt $attempt), retrying..." + sleep 5 + done + test -d "$HOME/depot_tools/.git" # Append depot_tools to the PATH for subsequent steps DEPOT_TOOLS_WIN=$(cygpath -w "$HOME/depot_tools") echo "$DEPOT_TOOLS_WIN" >> $GITHUB_PATH @@ -861,6 +1105,7 @@ jobs: ./flutter/bin/et build --config ci/mac_profile_framework_arm64 - name: Tar build files run: | + find engine/src/out/ci/mac_profile_framework_arm64 -type l -lname "/*" -delete || true tar -cvf mac_profile_framework_arm64.tar engine/src/out/ci/mac_profile_framework_arm64 - name: Upload build files uses: actions/upload-artifact@v4 @@ -884,7 +1129,14 @@ jobs: - name: Set up depot_tools if: runner.os != 'Windows' run: | - git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git $HOME/depot_tools + rm -rf "$HOME/depot_tools" + for attempt in 1 2 3; do + git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git "$HOME/depot_tools" && break + rm -rf "$HOME/depot_tools" + echo "depot_tools clone failed (attempt $attempt), retrying..." + sleep 5 + done + test -d "$HOME/depot_tools/.git" # Append depot_tools to the PATH for subsequent steps echo "$HOME/depot_tools" >> $GITHUB_PATH - name: Free disk space @@ -893,7 +1145,14 @@ jobs: - name: Set up depot_tools if: runner.os == 'Windows' run: | - git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git $HOME/depot_tools + rm -rf "$HOME/depot_tools" + for attempt in 1 2 3; do + git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git "$HOME/depot_tools" && break + rm -rf "$HOME/depot_tools" + echo "depot_tools clone failed (attempt $attempt), retrying..." + sleep 5 + done + test -d "$HOME/depot_tools/.git" # Append depot_tools to the PATH for subsequent steps DEPOT_TOOLS_WIN=$(cygpath -w "$HOME/depot_tools") echo "$DEPOT_TOOLS_WIN" >> $GITHUB_PATH @@ -914,6 +1173,7 @@ jobs: ./flutter/bin/et build --config ci/mac_profile_gen_snapshot_arm64 - name: Tar build files run: | + find engine/src/out/ci/mac_profile_gen_snapshot_arm64 -type l -lname "/*" -delete || true tar -cvf mac_profile_gen_snapshot_arm64.tar engine/src/out/ci/mac_profile_gen_snapshot_arm64 - name: Upload build files uses: actions/upload-artifact@v4 @@ -937,7 +1197,14 @@ jobs: - name: Set up depot_tools if: runner.os != 'Windows' run: | - git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git $HOME/depot_tools + rm -rf "$HOME/depot_tools" + for attempt in 1 2 3; do + git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git "$HOME/depot_tools" && break + rm -rf "$HOME/depot_tools" + echo "depot_tools clone failed (attempt $attempt), retrying..." + sleep 5 + done + test -d "$HOME/depot_tools/.git" # Append depot_tools to the PATH for subsequent steps echo "$HOME/depot_tools" >> $GITHUB_PATH - name: Free disk space @@ -946,7 +1213,14 @@ jobs: - name: Set up depot_tools if: runner.os == 'Windows' run: | - git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git $HOME/depot_tools + rm -rf "$HOME/depot_tools" + for attempt in 1 2 3; do + git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git "$HOME/depot_tools" && break + rm -rf "$HOME/depot_tools" + echo "depot_tools clone failed (attempt $attempt), retrying..." + sleep 5 + done + test -d "$HOME/depot_tools/.git" # Append depot_tools to the PATH for subsequent steps DEPOT_TOOLS_WIN=$(cygpath -w "$HOME/depot_tools") echo "$DEPOT_TOOLS_WIN" >> $GITHUB_PATH @@ -965,8 +1239,16 @@ jobs: run: | cd engine/src ./flutter/bin/et build --config ci/mac_release_arm64 + - name: Run engine unit tests + run: | + cd engine/src + python3 flutter/testing/run_tests.py \ + --variant ci/mac_release_arm64 \ + --type engine \ + --engine-capture-core-dump - name: Tar build files run: | + find engine/src/out/ci/mac_release_arm64 -type l -lname "/*" -delete || true tar -cvf mac_release_arm64.tar engine/src/out/ci/mac_release_arm64 - name: Upload build files uses: actions/upload-artifact@v4 @@ -1010,7 +1292,14 @@ jobs: - name: Set up depot_tools if: runner.os != 'Windows' run: | - git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git $HOME/depot_tools + rm -rf "$HOME/depot_tools" + for attempt in 1 2 3; do + git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git "$HOME/depot_tools" && break + rm -rf "$HOME/depot_tools" + echo "depot_tools clone failed (attempt $attempt), retrying..." + sleep 5 + done + test -d "$HOME/depot_tools/.git" # Append depot_tools to the PATH for subsequent steps echo "$HOME/depot_tools" >> $GITHUB_PATH - name: Free disk space @@ -1019,7 +1308,14 @@ jobs: - name: Set up depot_tools if: runner.os == 'Windows' run: | - git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git $HOME/depot_tools + rm -rf "$HOME/depot_tools" + for attempt in 1 2 3; do + git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git "$HOME/depot_tools" && break + rm -rf "$HOME/depot_tools" + echo "depot_tools clone failed (attempt $attempt), retrying..." + sleep 5 + done + test -d "$HOME/depot_tools/.git" # Append depot_tools to the PATH for subsequent steps DEPOT_TOOLS_WIN=$(cygpath -w "$HOME/depot_tools") echo "$DEPOT_TOOLS_WIN" >> $GITHUB_PATH @@ -1040,6 +1336,7 @@ jobs: ./flutter/bin/et build --config ci/mac_release_framework_arm64 - name: Tar build files run: | + find engine/src/out/ci/mac_release_framework_arm64 -type l -lname "/*" -delete || true tar -cvf mac_release_framework_arm64.tar engine/src/out/ci/mac_release_framework_arm64 - name: Upload build files uses: actions/upload-artifact@v4 @@ -1063,7 +1360,14 @@ jobs: - name: Set up depot_tools if: runner.os != 'Windows' run: | - git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git $HOME/depot_tools + rm -rf "$HOME/depot_tools" + for attempt in 1 2 3; do + git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git "$HOME/depot_tools" && break + rm -rf "$HOME/depot_tools" + echo "depot_tools clone failed (attempt $attempt), retrying..." + sleep 5 + done + test -d "$HOME/depot_tools/.git" # Append depot_tools to the PATH for subsequent steps echo "$HOME/depot_tools" >> $GITHUB_PATH - name: Free disk space @@ -1072,7 +1376,14 @@ jobs: - name: Set up depot_tools if: runner.os == 'Windows' run: | - git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git $HOME/depot_tools + rm -rf "$HOME/depot_tools" + for attempt in 1 2 3; do + git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git "$HOME/depot_tools" && break + rm -rf "$HOME/depot_tools" + echo "depot_tools clone failed (attempt $attempt), retrying..." + sleep 5 + done + test -d "$HOME/depot_tools/.git" # Append depot_tools to the PATH for subsequent steps DEPOT_TOOLS_WIN=$(cygpath -w "$HOME/depot_tools") echo "$DEPOT_TOOLS_WIN" >> $GITHUB_PATH @@ -1093,6 +1404,7 @@ jobs: ./flutter/bin/et build --config ci/mac_release_gen_snapshot_arm64 - name: Tar build files run: | + find engine/src/out/ci/mac_release_gen_snapshot_arm64 -type l -lname "/*" -delete || true tar -cvf mac_release_gen_snapshot_arm64.tar engine/src/out/ci/mac_release_gen_snapshot_arm64 - name: Upload build files uses: actions/upload-artifact@v4 @@ -1134,7 +1446,14 @@ jobs: - name: Set up depot_tools if: runner.os != 'Windows' run: | - git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git $HOME/depot_tools + rm -rf "$HOME/depot_tools" + for attempt in 1 2 3; do + git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git "$HOME/depot_tools" && break + rm -rf "$HOME/depot_tools" + echo "depot_tools clone failed (attempt $attempt), retrying..." + sleep 5 + done + test -d "$HOME/depot_tools/.git" # Append depot_tools to the PATH for subsequent steps echo "$HOME/depot_tools" >> $GITHUB_PATH - name: Free disk space @@ -1143,7 +1462,14 @@ jobs: - name: Set up depot_tools if: runner.os == 'Windows' run: | - git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git $HOME/depot_tools + rm -rf "$HOME/depot_tools" + for attempt in 1 2 3; do + git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git "$HOME/depot_tools" && break + rm -rf "$HOME/depot_tools" + echo "depot_tools clone failed (attempt $attempt), retrying..." + sleep 5 + done + test -d "$HOME/depot_tools/.git" # Append depot_tools to the PATH for subsequent steps DEPOT_TOOLS_WIN=$(cygpath -w "$HOME/depot_tools") echo "$DEPOT_TOOLS_WIN" >> $GITHUB_PATH @@ -1503,7 +1829,14 @@ jobs: - name: Set up depot_tools if: runner.os != 'Windows' run: | - git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git $HOME/depot_tools + rm -rf "$HOME/depot_tools" + for attempt in 1 2 3; do + git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git "$HOME/depot_tools" && break + rm -rf "$HOME/depot_tools" + echo "depot_tools clone failed (attempt $attempt), retrying..." + sleep 5 + done + test -d "$HOME/depot_tools/.git" # Append depot_tools to the PATH for subsequent steps echo "$HOME/depot_tools" >> $GITHUB_PATH - name: Free disk space @@ -1512,7 +1845,14 @@ jobs: - name: Set up depot_tools if: runner.os == 'Windows' run: | - git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git $HOME/depot_tools + rm -rf "$HOME/depot_tools" + for attempt in 1 2 3; do + git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git "$HOME/depot_tools" && break + rm -rf "$HOME/depot_tools" + echo "depot_tools clone failed (attempt $attempt), retrying..." + sleep 5 + done + test -d "$HOME/depot_tools/.git" # Append depot_tools to the PATH for subsequent steps DEPOT_TOOLS_WIN=$(cygpath -w "$HOME/depot_tools") echo "$DEPOT_TOOLS_WIN" >> $GITHUB_PATH @@ -1533,6 +1873,7 @@ jobs: ./flutter/bin/et build --config ci/ios_debug_sim - name: Tar build files run: | + find engine/src/out/ci/ios_debug_sim -type l -lname "/*" -delete || true tar -cvf mac_ios_debug_sim.tar engine/src/out/ci/ios_debug_sim - name: Upload build files uses: actions/upload-artifact@v4 @@ -1556,7 +1897,14 @@ jobs: - name: Set up depot_tools if: runner.os != 'Windows' run: | - git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git $HOME/depot_tools + rm -rf "$HOME/depot_tools" + for attempt in 1 2 3; do + git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git "$HOME/depot_tools" && break + rm -rf "$HOME/depot_tools" + echo "depot_tools clone failed (attempt $attempt), retrying..." + sleep 5 + done + test -d "$HOME/depot_tools/.git" # Append depot_tools to the PATH for subsequent steps echo "$HOME/depot_tools" >> $GITHUB_PATH - name: Free disk space @@ -1565,7 +1913,14 @@ jobs: - name: Set up depot_tools if: runner.os == 'Windows' run: | - git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git $HOME/depot_tools + rm -rf "$HOME/depot_tools" + for attempt in 1 2 3; do + git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git "$HOME/depot_tools" && break + rm -rf "$HOME/depot_tools" + echo "depot_tools clone failed (attempt $attempt), retrying..." + sleep 5 + done + test -d "$HOME/depot_tools/.git" # Append depot_tools to the PATH for subsequent steps DEPOT_TOOLS_WIN=$(cygpath -w "$HOME/depot_tools") echo "$DEPOT_TOOLS_WIN" >> $GITHUB_PATH @@ -1586,6 +1941,7 @@ jobs: ./flutter/bin/et build --config ci/ios_debug_sim_arm64 - name: Tar build files run: | + find engine/src/out/ci/ios_debug_sim_arm64 -type l -lname "/*" -delete || true tar -cvf mac_ios_debug_sim_arm64.tar engine/src/out/ci/ios_debug_sim_arm64 - name: Upload build files uses: actions/upload-artifact@v4 @@ -1593,6 +1949,74 @@ jobs: name: artifacts-mac_ios_debug_sim_arm64-${{ steps.engine_content_hash.outputs.value }} path: mac_ios_debug_sim_arm64.tar retention-days: 1 + mac_ios_test_binaries_arm64: + runs-on: macos-latest + defaults: + run: + shell: bash + needs: + - guard + if: ${{ needs.guard.outputs.should_run == 'true' }} + steps: + - name: Checkout the repository + uses: actions/checkout@v4 + with: + path: '' + - name: Set up depot_tools + if: runner.os != 'Windows' + run: | + rm -rf "$HOME/depot_tools" + for attempt in 1 2 3; do + git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git "$HOME/depot_tools" && break + rm -rf "$HOME/depot_tools" + echo "depot_tools clone failed (attempt $attempt), retrying..." + sleep 5 + done + test -d "$HOME/depot_tools/.git" + # Append depot_tools to the PATH for subsequent steps + echo "$HOME/depot_tools" >> $GITHUB_PATH + - name: Free disk space + if: runner.os == 'Linux' && runner.arch == 'X64' + run: curl -fsSL https://raw.githubusercontent.com/apache/arrow/e49d8ae15583ceff03237571569099a6ad62be32/ci/scripts/util_free_space.sh | bash + - name: Set up depot_tools + if: runner.os == 'Windows' + run: | + rm -rf "$HOME/depot_tools" + for attempt in 1 2 3; do + git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git "$HOME/depot_tools" && break + rm -rf "$HOME/depot_tools" + echo "depot_tools clone failed (attempt $attempt), retrying..." + sleep 5 + done + test -d "$HOME/depot_tools/.git" + # Append depot_tools to the PATH for subsequent steps + DEPOT_TOOLS_WIN=$(cygpath -w "$HOME/depot_tools") + echo "$DEPOT_TOOLS_WIN" >> $GITHUB_PATH + - name: Generate engine content hash + id: engine_content_hash + run: | + engine_content_hash=${{ needs.guard.outputs.engine_content_hash }} + echo "value=${engine_content_hash}" >> $GITHUB_OUTPUT + - name: Copy gclient file + run: | + cp engine/scripts/slim.gclient .gclient + - name: GClient sync + run: | + gclient sync -D --no-history --shallow --with_branch_heads + - name: Build engine + run: | + cd engine/src + ./flutter/bin/et build --config ci/ios_test_binaries_arm64 + - name: Tar build files + run: | + find engine/src/out/ci/ios_test_binaries_arm64 -type l -lname "/*" -delete || true + tar -cvf mac_ios_test_binaries_arm64.tar engine/src/out/ci/ios_test_binaries_arm64 + - name: Upload build files + uses: actions/upload-artifact@v4 + with: + name: artifacts-mac_ios_test_binaries_arm64-${{ steps.engine_content_hash.outputs.value }} + path: mac_ios_test_binaries_arm64.tar + retention-days: 1 mac_ios_debug: runs-on: macos-latest defaults: @@ -1609,7 +2033,14 @@ jobs: - name: Set up depot_tools if: runner.os != 'Windows' run: | - git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git $HOME/depot_tools + rm -rf "$HOME/depot_tools" + for attempt in 1 2 3; do + git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git "$HOME/depot_tools" && break + rm -rf "$HOME/depot_tools" + echo "depot_tools clone failed (attempt $attempt), retrying..." + sleep 5 + done + test -d "$HOME/depot_tools/.git" # Append depot_tools to the PATH for subsequent steps echo "$HOME/depot_tools" >> $GITHUB_PATH - name: Free disk space @@ -1618,7 +2049,14 @@ jobs: - name: Set up depot_tools if: runner.os == 'Windows' run: | - git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git $HOME/depot_tools + rm -rf "$HOME/depot_tools" + for attempt in 1 2 3; do + git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git "$HOME/depot_tools" && break + rm -rf "$HOME/depot_tools" + echo "depot_tools clone failed (attempt $attempt), retrying..." + sleep 5 + done + test -d "$HOME/depot_tools/.git" # Append depot_tools to the PATH for subsequent steps DEPOT_TOOLS_WIN=$(cygpath -w "$HOME/depot_tools") echo "$DEPOT_TOOLS_WIN" >> $GITHUB_PATH @@ -1639,6 +2077,7 @@ jobs: ./flutter/bin/et build --config ci/ios_debug - name: Tar build files run: | + find engine/src/out/ci/ios_debug -type l -lname "/*" -delete || true tar -cvf mac_ios_debug.tar engine/src/out/ci/ios_debug - name: Upload build files uses: actions/upload-artifact@v4 @@ -1662,7 +2101,14 @@ jobs: - name: Set up depot_tools if: runner.os != 'Windows' run: | - git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git $HOME/depot_tools + rm -rf "$HOME/depot_tools" + for attempt in 1 2 3; do + git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git "$HOME/depot_tools" && break + rm -rf "$HOME/depot_tools" + echo "depot_tools clone failed (attempt $attempt), retrying..." + sleep 5 + done + test -d "$HOME/depot_tools/.git" # Append depot_tools to the PATH for subsequent steps echo "$HOME/depot_tools" >> $GITHUB_PATH - name: Free disk space @@ -1671,7 +2117,14 @@ jobs: - name: Set up depot_tools if: runner.os == 'Windows' run: | - git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git $HOME/depot_tools + rm -rf "$HOME/depot_tools" + for attempt in 1 2 3; do + git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git "$HOME/depot_tools" && break + rm -rf "$HOME/depot_tools" + echo "depot_tools clone failed (attempt $attempt), retrying..." + sleep 5 + done + test -d "$HOME/depot_tools/.git" # Append depot_tools to the PATH for subsequent steps DEPOT_TOOLS_WIN=$(cygpath -w "$HOME/depot_tools") echo "$DEPOT_TOOLS_WIN" >> $GITHUB_PATH @@ -1692,6 +2145,7 @@ jobs: ./flutter/bin/et build --config ci/ios_profile - name: Tar build files run: | + find engine/src/out/ci/ios_profile -type l -lname "/*" -delete || true tar -cvf mac_ios_profile.tar engine/src/out/ci/ios_profile - name: Upload build files uses: actions/upload-artifact@v4 @@ -1715,7 +2169,14 @@ jobs: - name: Set up depot_tools if: runner.os != 'Windows' run: | - git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git $HOME/depot_tools + rm -rf "$HOME/depot_tools" + for attempt in 1 2 3; do + git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git "$HOME/depot_tools" && break + rm -rf "$HOME/depot_tools" + echo "depot_tools clone failed (attempt $attempt), retrying..." + sleep 5 + done + test -d "$HOME/depot_tools/.git" # Append depot_tools to the PATH for subsequent steps echo "$HOME/depot_tools" >> $GITHUB_PATH - name: Free disk space @@ -1724,7 +2185,14 @@ jobs: - name: Set up depot_tools if: runner.os == 'Windows' run: | - git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git $HOME/depot_tools + rm -rf "$HOME/depot_tools" + for attempt in 1 2 3; do + git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git "$HOME/depot_tools" && break + rm -rf "$HOME/depot_tools" + echo "depot_tools clone failed (attempt $attempt), retrying..." + sleep 5 + done + test -d "$HOME/depot_tools/.git" # Append depot_tools to the PATH for subsequent steps DEPOT_TOOLS_WIN=$(cygpath -w "$HOME/depot_tools") echo "$DEPOT_TOOLS_WIN" >> $GITHUB_PATH @@ -1745,6 +2213,7 @@ jobs: ./flutter/bin/et build --config ci/ios_release - name: Tar build files run: | + find engine/src/out/ci/ios_release -type l -lname "/*" -delete || true tar -cvf mac_ios_release.tar engine/src/out/ci/ios_release - name: Upload build files uses: actions/upload-artifact@v4 @@ -1757,6 +2226,7 @@ jobs: needs: - mac_ios_debug_sim - mac_ios_debug_sim_arm64 + - mac_ios_test_binaries_arm64 - mac_ios_debug - mac_ios_profile - mac_ios_release @@ -1773,7 +2243,14 @@ jobs: - name: Set up depot_tools if: runner.os != 'Windows' run: | - git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git $HOME/depot_tools + rm -rf "$HOME/depot_tools" + for attempt in 1 2 3; do + git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git "$HOME/depot_tools" && break + rm -rf "$HOME/depot_tools" + echo "depot_tools clone failed (attempt $attempt), retrying..." + sleep 5 + done + test -d "$HOME/depot_tools/.git" # Append depot_tools to the PATH for subsequent steps echo "$HOME/depot_tools" >> $GITHUB_PATH - name: Free disk space @@ -1782,7 +2259,14 @@ jobs: - name: Set up depot_tools if: runner.os == 'Windows' run: | - git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git $HOME/depot_tools + rm -rf "$HOME/depot_tools" + for attempt in 1 2 3; do + git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git "$HOME/depot_tools" && break + rm -rf "$HOME/depot_tools" + echo "depot_tools clone failed (attempt $attempt), retrying..." + sleep 5 + done + test -d "$HOME/depot_tools/.git" # Append depot_tools to the PATH for subsequent steps DEPOT_TOOLS_WIN=$(cygpath -w "$HOME/depot_tools") echo "$DEPOT_TOOLS_WIN" >> $GITHUB_PATH @@ -1813,6 +2297,14 @@ jobs: run: | tar -xvf mac_ios_debug_sim_arm64.tar rm mac_ios_debug_sim_arm64.tar + - name: Download Artifacts from mac_ios_test_binaries_arm64 + uses: actions/download-artifact@v4 + with: + name: artifacts-mac_ios_test_binaries_arm64-${{ steps.engine_content_hash.outputs.value }} + - name: Extract Artifacts from mac_ios_test_binaries_arm64 + run: | + tar -xvf mac_ios_test_binaries_arm64.tar + rm mac_ios_test_binaries_arm64.tar - name: Download Artifacts from mac_ios_debug uses: actions/download-artifact@v4 with: @@ -1930,7 +2422,14 @@ jobs: - name: Set up depot_tools if: runner.os != 'Windows' run: | - git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git $HOME/depot_tools + rm -rf "$HOME/depot_tools" + for attempt in 1 2 3; do + git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git "$HOME/depot_tools" && break + rm -rf "$HOME/depot_tools" + echo "depot_tools clone failed (attempt $attempt), retrying..." + sleep 5 + done + test -d "$HOME/depot_tools/.git" # Append depot_tools to the PATH for subsequent steps echo "$HOME/depot_tools" >> $GITHUB_PATH - name: Free disk space @@ -1939,7 +2438,14 @@ jobs: - name: Set up depot_tools if: runner.os == 'Windows' run: | - git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git $HOME/depot_tools + rm -rf "$HOME/depot_tools" + for attempt in 1 2 3; do + git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git "$HOME/depot_tools" && break + rm -rf "$HOME/depot_tools" + echo "depot_tools clone failed (attempt $attempt), retrying..." + sleep 5 + done + test -d "$HOME/depot_tools/.git" # Append depot_tools to the PATH for subsequent steps DEPOT_TOOLS_WIN=$(cygpath -w "$HOME/depot_tools") echo "$DEPOT_TOOLS_WIN" >> $GITHUB_PATH @@ -1959,6 +2465,12 @@ jobs: run: | cd engine\src flutter\bin\et.bat build --config ci\host_debug + - name: Run engine unit tests + run: | + cd engine/src + python flutter/testing/run_tests.py \ + --variant ci/host_debug \ + --type engine \ - name: Tar engine/src/out/ci/host_debug/zip_archives/windows-x64/artifacts.zip run: | cd engine/src/out/ci/host_debug/zip_archives/windows-x64 @@ -2035,7 +2547,14 @@ jobs: - name: Set up depot_tools if: runner.os != 'Windows' run: | - git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git $HOME/depot_tools + rm -rf "$HOME/depot_tools" + for attempt in 1 2 3; do + git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git "$HOME/depot_tools" && break + rm -rf "$HOME/depot_tools" + echo "depot_tools clone failed (attempt $attempt), retrying..." + sleep 5 + done + test -d "$HOME/depot_tools/.git" # Append depot_tools to the PATH for subsequent steps echo "$HOME/depot_tools" >> $GITHUB_PATH - name: Free disk space @@ -2044,7 +2563,14 @@ jobs: - name: Set up depot_tools if: runner.os == 'Windows' run: | - git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git $HOME/depot_tools + rm -rf "$HOME/depot_tools" + for attempt in 1 2 3; do + git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git "$HOME/depot_tools" && break + rm -rf "$HOME/depot_tools" + echo "depot_tools clone failed (attempt $attempt), retrying..." + sleep 5 + done + test -d "$HOME/depot_tools/.git" # Append depot_tools to the PATH for subsequent steps DEPOT_TOOLS_WIN=$(cygpath -w "$HOME/depot_tools") echo "$DEPOT_TOOLS_WIN" >> $GITHUB_PATH @@ -2090,7 +2616,14 @@ jobs: - name: Set up depot_tools if: runner.os != 'Windows' run: | - git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git $HOME/depot_tools + rm -rf "$HOME/depot_tools" + for attempt in 1 2 3; do + git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git "$HOME/depot_tools" && break + rm -rf "$HOME/depot_tools" + echo "depot_tools clone failed (attempt $attempt), retrying..." + sleep 5 + done + test -d "$HOME/depot_tools/.git" # Append depot_tools to the PATH for subsequent steps echo "$HOME/depot_tools" >> $GITHUB_PATH - name: Free disk space @@ -2099,7 +2632,14 @@ jobs: - name: Set up depot_tools if: runner.os == 'Windows' run: | - git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git $HOME/depot_tools + rm -rf "$HOME/depot_tools" + for attempt in 1 2 3; do + git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git "$HOME/depot_tools" && break + rm -rf "$HOME/depot_tools" + echo "depot_tools clone failed (attempt $attempt), retrying..." + sleep 5 + done + test -d "$HOME/depot_tools/.git" # Append depot_tools to the PATH for subsequent steps DEPOT_TOOLS_WIN=$(cygpath -w "$HOME/depot_tools") echo "$DEPOT_TOOLS_WIN" >> $GITHUB_PATH @@ -2145,7 +2685,14 @@ jobs: - name: Set up depot_tools if: runner.os != 'Windows' run: | - git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git $HOME/depot_tools + rm -rf "$HOME/depot_tools" + for attempt in 1 2 3; do + git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git "$HOME/depot_tools" && break + rm -rf "$HOME/depot_tools" + echo "depot_tools clone failed (attempt $attempt), retrying..." + sleep 5 + done + test -d "$HOME/depot_tools/.git" # Append depot_tools to the PATH for subsequent steps echo "$HOME/depot_tools" >> $GITHUB_PATH - name: Free disk space @@ -2154,7 +2701,14 @@ jobs: - name: Set up depot_tools if: runner.os == 'Windows' run: | - git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git $HOME/depot_tools + rm -rf "$HOME/depot_tools" + for attempt in 1 2 3; do + git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git "$HOME/depot_tools" && break + rm -rf "$HOME/depot_tools" + echo "depot_tools clone failed (attempt $attempt), retrying..." + sleep 5 + done + test -d "$HOME/depot_tools/.git" # Append depot_tools to the PATH for subsequent steps DEPOT_TOOLS_WIN=$(cygpath -w "$HOME/depot_tools") echo "$DEPOT_TOOLS_WIN" >> $GITHUB_PATH @@ -2250,7 +2804,14 @@ jobs: - name: Set up depot_tools if: runner.os != 'Windows' run: | - git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git $HOME/depot_tools + rm -rf "$HOME/depot_tools" + for attempt in 1 2 3; do + git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git "$HOME/depot_tools" && break + rm -rf "$HOME/depot_tools" + echo "depot_tools clone failed (attempt $attempt), retrying..." + sleep 5 + done + test -d "$HOME/depot_tools/.git" # Append depot_tools to the PATH for subsequent steps echo "$HOME/depot_tools" >> $GITHUB_PATH - name: Free disk space @@ -2259,7 +2820,14 @@ jobs: - name: Set up depot_tools if: runner.os == 'Windows' run: | - git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git $HOME/depot_tools + rm -rf "$HOME/depot_tools" + for attempt in 1 2 3; do + git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git "$HOME/depot_tools" && break + rm -rf "$HOME/depot_tools" + echo "depot_tools clone failed (attempt $attempt), retrying..." + sleep 5 + done + test -d "$HOME/depot_tools/.git" # Append depot_tools to the PATH for subsequent steps DEPOT_TOOLS_WIN=$(cygpath -w "$HOME/depot_tools") echo "$DEPOT_TOOLS_WIN" >> $GITHUB_PATH @@ -2305,7 +2873,14 @@ jobs: - name: Set up depot_tools if: runner.os != 'Windows' run: | - git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git $HOME/depot_tools + rm -rf "$HOME/depot_tools" + for attempt in 1 2 3; do + git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git "$HOME/depot_tools" && break + rm -rf "$HOME/depot_tools" + echo "depot_tools clone failed (attempt $attempt), retrying..." + sleep 5 + done + test -d "$HOME/depot_tools/.git" # Append depot_tools to the PATH for subsequent steps echo "$HOME/depot_tools" >> $GITHUB_PATH - name: Free disk space @@ -2314,7 +2889,14 @@ jobs: - name: Set up depot_tools if: runner.os == 'Windows' run: | - git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git $HOME/depot_tools + rm -rf "$HOME/depot_tools" + for attempt in 1 2 3; do + git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git "$HOME/depot_tools" && break + rm -rf "$HOME/depot_tools" + echo "depot_tools clone failed (attempt $attempt), retrying..." + sleep 5 + done + test -d "$HOME/depot_tools/.git" # Append depot_tools to the PATH for subsequent steps DEPOT_TOOLS_WIN=$(cygpath -w "$HOME/depot_tools") echo "$DEPOT_TOOLS_WIN" >> $GITHUB_PATH @@ -2360,7 +2942,14 @@ jobs: - name: Set up depot_tools if: runner.os != 'Windows' run: | - git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git $HOME/depot_tools + rm -rf "$HOME/depot_tools" + for attempt in 1 2 3; do + git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git "$HOME/depot_tools" && break + rm -rf "$HOME/depot_tools" + echo "depot_tools clone failed (attempt $attempt), retrying..." + sleep 5 + done + test -d "$HOME/depot_tools/.git" # Append depot_tools to the PATH for subsequent steps echo "$HOME/depot_tools" >> $GITHUB_PATH - name: Install doxygen @@ -2374,7 +2963,14 @@ jobs: - name: Set up depot_tools if: runner.os == 'Windows' run: | - git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git $HOME/depot_tools + rm -rf "$HOME/depot_tools" + for attempt in 1 2 3; do + git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git "$HOME/depot_tools" && break + rm -rf "$HOME/depot_tools" + echo "depot_tools clone failed (attempt $attempt), retrying..." + sleep 5 + done + test -d "$HOME/depot_tools/.git" # Append depot_tools to the PATH for subsequent steps DEPOT_TOOLS_WIN=$(cygpath -w "$HOME/depot_tools") echo "$DEPOT_TOOLS_WIN" >> $GITHUB_PATH @@ -2393,8 +2989,16 @@ jobs: run: | cd engine/src ./flutter/bin/et build --config ci/host_debug + - name: Run engine unit tests + run: | + cd engine/src + python3 flutter/testing/run_tests.py \ + --variant ci/host_debug \ + --type engine \ + --engine-capture-core-dump - name: Tar build files run: | + find engine/src/out/ci/host_debug -type l -lname "/*" -delete || true tar -cvf linux_host_debug.tar engine/src/out/ci/host_debug - name: Upload build files uses: actions/upload-artifact@v4 @@ -2468,7 +3072,14 @@ jobs: - name: Set up depot_tools if: runner.os != 'Windows' run: | - git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git $HOME/depot_tools + rm -rf "$HOME/depot_tools" + for attempt in 1 2 3; do + git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git "$HOME/depot_tools" && break + rm -rf "$HOME/depot_tools" + echo "depot_tools clone failed (attempt $attempt), retrying..." + sleep 5 + done + test -d "$HOME/depot_tools/.git" # Append depot_tools to the PATH for subsequent steps echo "$HOME/depot_tools" >> $GITHUB_PATH - name: Install doxygen @@ -2482,7 +3093,14 @@ jobs: - name: Set up depot_tools if: runner.os == 'Windows' run: | - git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git $HOME/depot_tools + rm -rf "$HOME/depot_tools" + for attempt in 1 2 3; do + git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git "$HOME/depot_tools" && break + rm -rf "$HOME/depot_tools" + echo "depot_tools clone failed (attempt $attempt), retrying..." + sleep 5 + done + test -d "$HOME/depot_tools/.git" # Append depot_tools to the PATH for subsequent steps DEPOT_TOOLS_WIN=$(cygpath -w "$HOME/depot_tools") echo "$DEPOT_TOOLS_WIN" >> $GITHUB_PATH @@ -2501,8 +3119,16 @@ jobs: run: | cd engine/src ./flutter/bin/et build --config ci/host_release + - name: Run engine unit tests + run: | + cd engine/src + python3 flutter/testing/run_tests.py \ + --variant ci/host_release \ + --type engine \ + --engine-capture-core-dump - name: Tar build files run: | + find engine/src/out/ci/host_release -type l -lname "/*" -delete || true tar -cvf linux_host_release.tar engine/src/out/ci/host_release - name: Upload build files uses: actions/upload-artifact@v4 @@ -2538,7 +3164,14 @@ jobs: - name: Set up depot_tools if: runner.os != 'Windows' run: | - git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git $HOME/depot_tools + rm -rf "$HOME/depot_tools" + for attempt in 1 2 3; do + git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git "$HOME/depot_tools" && break + rm -rf "$HOME/depot_tools" + echo "depot_tools clone failed (attempt $attempt), retrying..." + sleep 5 + done + test -d "$HOME/depot_tools/.git" # Append depot_tools to the PATH for subsequent steps echo "$HOME/depot_tools" >> $GITHUB_PATH - name: Install doxygen @@ -2552,7 +3185,14 @@ jobs: - name: Set up depot_tools if: runner.os == 'Windows' run: | - git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git $HOME/depot_tools + rm -rf "$HOME/depot_tools" + for attempt in 1 2 3; do + git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git "$HOME/depot_tools" && break + rm -rf "$HOME/depot_tools" + echo "depot_tools clone failed (attempt $attempt), retrying..." + sleep 5 + done + test -d "$HOME/depot_tools/.git" # Append depot_tools to the PATH for subsequent steps DEPOT_TOOLS_WIN=$(cygpath -w "$HOME/depot_tools") echo "$DEPOT_TOOLS_WIN" >> $GITHUB_PATH @@ -2675,7 +3315,14 @@ jobs: - name: Set up depot_tools if: runner.os != 'Windows' run: | - git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git $HOME/depot_tools + rm -rf "$HOME/depot_tools" + for attempt in 1 2 3; do + git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git "$HOME/depot_tools" && break + rm -rf "$HOME/depot_tools" + echo "depot_tools clone failed (attempt $attempt), retrying..." + sleep 5 + done + test -d "$HOME/depot_tools/.git" # Append depot_tools to the PATH for subsequent steps echo "$HOME/depot_tools" >> $GITHUB_PATH - name: Free disk space @@ -2684,7 +3331,14 @@ jobs: - name: Set up depot_tools if: runner.os == 'Windows' run: | - git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git $HOME/depot_tools + rm -rf "$HOME/depot_tools" + for attempt in 1 2 3; do + git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git "$HOME/depot_tools" && break + rm -rf "$HOME/depot_tools" + echo "depot_tools clone failed (attempt $attempt), retrying..." + sleep 5 + done + test -d "$HOME/depot_tools/.git" # Append depot_tools to the PATH for subsequent steps DEPOT_TOOLS_WIN=$(cygpath -w "$HOME/depot_tools") echo "$DEPOT_TOOLS_WIN" >> $GITHUB_PATH @@ -2703,6 +3357,13 @@ jobs: run: | cd engine/src ./flutter/bin/et build --config ci/host_debug_desktop + - name: Run engine unit tests + run: | + cd engine/src + python3 flutter/testing/run_tests.py \ + --variant ci/host_debug_desktop \ + --type engine \ + --engine-capture-core-dump - name: Tar engine/src/out/ci/host_debug_desktop/zip_archives/linux-x64-debug/linux-x64-flutter-gtk.zip run: | cd engine/src/out/ci/host_debug_desktop/zip_archives/linux-x64-debug @@ -2729,7 +3390,14 @@ jobs: - name: Set up depot_tools if: runner.os != 'Windows' run: | - git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git $HOME/depot_tools + rm -rf "$HOME/depot_tools" + for attempt in 1 2 3; do + git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git "$HOME/depot_tools" && break + rm -rf "$HOME/depot_tools" + echo "depot_tools clone failed (attempt $attempt), retrying..." + sleep 5 + done + test -d "$HOME/depot_tools/.git" # Append depot_tools to the PATH for subsequent steps echo "$HOME/depot_tools" >> $GITHUB_PATH - name: Free disk space @@ -2738,7 +3406,14 @@ jobs: - name: Set up depot_tools if: runner.os == 'Windows' run: | - git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git $HOME/depot_tools + rm -rf "$HOME/depot_tools" + for attempt in 1 2 3; do + git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git "$HOME/depot_tools" && break + rm -rf "$HOME/depot_tools" + echo "depot_tools clone failed (attempt $attempt), retrying..." + sleep 5 + done + test -d "$HOME/depot_tools/.git" # Append depot_tools to the PATH for subsequent steps DEPOT_TOOLS_WIN=$(cygpath -w "$HOME/depot_tools") echo "$DEPOT_TOOLS_WIN" >> $GITHUB_PATH @@ -2757,6 +3432,13 @@ jobs: run: | cd engine/src ./flutter/bin/et build --config ci/host_profile_desktop + - name: Run engine unit tests + run: | + cd engine/src + python3 flutter/testing/run_tests.py \ + --variant ci/host_profile_desktop \ + --type engine \ + --engine-capture-core-dump - name: Tar engine/src/out/ci/host_profile_desktop/zip_archives/linux-x64-profile/linux-x64-flutter-gtk.zip run: | cd engine/src/out/ci/host_profile_desktop/zip_archives/linux-x64-profile @@ -2783,7 +3465,14 @@ jobs: - name: Set up depot_tools if: runner.os != 'Windows' run: | - git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git $HOME/depot_tools + rm -rf "$HOME/depot_tools" + for attempt in 1 2 3; do + git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git "$HOME/depot_tools" && break + rm -rf "$HOME/depot_tools" + echo "depot_tools clone failed (attempt $attempt), retrying..." + sleep 5 + done + test -d "$HOME/depot_tools/.git" # Append depot_tools to the PATH for subsequent steps echo "$HOME/depot_tools" >> $GITHUB_PATH - name: Free disk space @@ -2792,7 +3481,14 @@ jobs: - name: Set up depot_tools if: runner.os == 'Windows' run: | - git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git $HOME/depot_tools + rm -rf "$HOME/depot_tools" + for attempt in 1 2 3; do + git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git "$HOME/depot_tools" && break + rm -rf "$HOME/depot_tools" + echo "depot_tools clone failed (attempt $attempt), retrying..." + sleep 5 + done + test -d "$HOME/depot_tools/.git" # Append depot_tools to the PATH for subsequent steps DEPOT_TOOLS_WIN=$(cygpath -w "$HOME/depot_tools") echo "$DEPOT_TOOLS_WIN" >> $GITHUB_PATH @@ -2811,6 +3507,13 @@ jobs: run: | cd engine/src ./flutter/bin/et build --config ci/host_release_desktop + - name: Run engine unit tests + run: | + cd engine/src + python3 flutter/testing/run_tests.py \ + --variant ci/host_release_desktop \ + --type engine \ + --engine-capture-core-dump - name: Tar engine/src/out/ci/host_release_desktop/zip_archives/linux-x64-release/linux-x64-flutter-gtk.zip run: | cd engine/src/out/ci/host_release_desktop/zip_archives/linux-x64-release @@ -2837,7 +3540,14 @@ jobs: - name: Set up depot_tools if: runner.os != 'Windows' run: | - git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git $HOME/depot_tools + rm -rf "$HOME/depot_tools" + for attempt in 1 2 3; do + git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git "$HOME/depot_tools" && break + rm -rf "$HOME/depot_tools" + echo "depot_tools clone failed (attempt $attempt), retrying..." + sleep 5 + done + test -d "$HOME/depot_tools/.git" # Append depot_tools to the PATH for subsequent steps echo "$HOME/depot_tools" >> $GITHUB_PATH - name: Free disk space @@ -2846,7 +3556,14 @@ jobs: - name: Set up depot_tools if: runner.os == 'Windows' run: | - git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git $HOME/depot_tools + rm -rf "$HOME/depot_tools" + for attempt in 1 2 3; do + git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git "$HOME/depot_tools" && break + rm -rf "$HOME/depot_tools" + echo "depot_tools clone failed (attempt $attempt), retrying..." + sleep 5 + done + test -d "$HOME/depot_tools/.git" # Append depot_tools to the PATH for subsequent steps DEPOT_TOOLS_WIN=$(cygpath -w "$HOME/depot_tools") echo "$DEPOT_TOOLS_WIN" >> $GITHUB_PATH @@ -2865,6 +3582,13 @@ jobs: run: | cd engine/src ./flutter/bin/et build --config ci/linux_profile_arm64 + - name: Run engine unit tests + run: | + cd engine/src + python3 flutter/testing/run_tests.py \ + --variant ci/linux_profile_arm64 \ + --type engine \ + --engine-capture-core-dump - name: Tar engine/src/out/ci/linux_profile_arm64/zip_archives/linux-arm64-profile/linux-arm64-flutter-gtk.zip run: | cd engine/src/out/ci/linux_profile_arm64/zip_archives/linux-arm64-profile @@ -2891,7 +3615,14 @@ jobs: - name: Set up depot_tools if: runner.os != 'Windows' run: | - git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git $HOME/depot_tools + rm -rf "$HOME/depot_tools" + for attempt in 1 2 3; do + git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git "$HOME/depot_tools" && break + rm -rf "$HOME/depot_tools" + echo "depot_tools clone failed (attempt $attempt), retrying..." + sleep 5 + done + test -d "$HOME/depot_tools/.git" # Append depot_tools to the PATH for subsequent steps echo "$HOME/depot_tools" >> $GITHUB_PATH - name: Free disk space @@ -2900,7 +3631,14 @@ jobs: - name: Set up depot_tools if: runner.os == 'Windows' run: | - git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git $HOME/depot_tools + rm -rf "$HOME/depot_tools" + for attempt in 1 2 3; do + git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git "$HOME/depot_tools" && break + rm -rf "$HOME/depot_tools" + echo "depot_tools clone failed (attempt $attempt), retrying..." + sleep 5 + done + test -d "$HOME/depot_tools/.git" # Append depot_tools to the PATH for subsequent steps DEPOT_TOOLS_WIN=$(cygpath -w "$HOME/depot_tools") echo "$DEPOT_TOOLS_WIN" >> $GITHUB_PATH @@ -2919,6 +3657,13 @@ jobs: run: | cd engine/src ./flutter/bin/et build --config ci/linux_debug_arm64 + - name: Run engine unit tests + run: | + cd engine/src + python3 flutter/testing/run_tests.py \ + --variant ci/linux_debug_arm64 \ + --type engine \ + --engine-capture-core-dump - name: Tar engine/src/out/ci/linux_debug_arm64/zip_archives/linux-arm64/artifacts.zip run: | cd engine/src/out/ci/linux_debug_arm64/zip_archives/linux-arm64 @@ -2985,7 +3730,14 @@ jobs: - name: Set up depot_tools if: runner.os != 'Windows' run: | - git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git $HOME/depot_tools + rm -rf "$HOME/depot_tools" + for attempt in 1 2 3; do + git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git "$HOME/depot_tools" && break + rm -rf "$HOME/depot_tools" + echo "depot_tools clone failed (attempt $attempt), retrying..." + sleep 5 + done + test -d "$HOME/depot_tools/.git" # Append depot_tools to the PATH for subsequent steps echo "$HOME/depot_tools" >> $GITHUB_PATH - name: Free disk space @@ -2994,7 +3746,14 @@ jobs: - name: Set up depot_tools if: runner.os == 'Windows' run: | - git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git $HOME/depot_tools + rm -rf "$HOME/depot_tools" + for attempt in 1 2 3; do + git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git "$HOME/depot_tools" && break + rm -rf "$HOME/depot_tools" + echo "depot_tools clone failed (attempt $attempt), retrying..." + sleep 5 + done + test -d "$HOME/depot_tools/.git" # Append depot_tools to the PATH for subsequent steps DEPOT_TOOLS_WIN=$(cygpath -w "$HOME/depot_tools") echo "$DEPOT_TOOLS_WIN" >> $GITHUB_PATH @@ -3013,6 +3772,13 @@ jobs: run: | cd engine/src ./flutter/bin/et build --config ci/linux_release_arm64 + - name: Run engine unit tests + run: | + cd engine/src + python3 flutter/testing/run_tests.py \ + --variant ci/linux_release_arm64 \ + --type engine \ + --engine-capture-core-dump - name: Tar engine/src/out/ci/linux_release_arm64/zip_archives/linux-arm64-release/linux-arm64-flutter-gtk.zip run: | cd engine/src/out/ci/linux_release_arm64/zip_archives/linux-arm64-release @@ -3039,7 +3805,14 @@ jobs: - name: Set up depot_tools if: runner.os != 'Windows' run: | - git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git $HOME/depot_tools + rm -rf "$HOME/depot_tools" + for attempt in 1 2 3; do + git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git "$HOME/depot_tools" && break + rm -rf "$HOME/depot_tools" + echo "depot_tools clone failed (attempt $attempt), retrying..." + sleep 5 + done + test -d "$HOME/depot_tools/.git" # Append depot_tools to the PATH for subsequent steps echo "$HOME/depot_tools" >> $GITHUB_PATH - name: Free disk space @@ -3048,7 +3821,14 @@ jobs: - name: Set up depot_tools if: runner.os == 'Windows' run: | - git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git $HOME/depot_tools + rm -rf "$HOME/depot_tools" + for attempt in 1 2 3; do + git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git "$HOME/depot_tools" && break + rm -rf "$HOME/depot_tools" + echo "depot_tools clone failed (attempt $attempt), retrying..." + sleep 5 + done + test -d "$HOME/depot_tools/.git" # Append depot_tools to the PATH for subsequent steps DEPOT_TOOLS_WIN=$(cygpath -w "$HOME/depot_tools") echo "$DEPOT_TOOLS_WIN" >> $GITHUB_PATH @@ -3094,7 +3874,14 @@ jobs: - name: Set up depot_tools if: runner.os != 'Windows' run: | - git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git $HOME/depot_tools + rm -rf "$HOME/depot_tools" + for attempt in 1 2 3; do + git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git "$HOME/depot_tools" && break + rm -rf "$HOME/depot_tools" + echo "depot_tools clone failed (attempt $attempt), retrying..." + sleep 5 + done + test -d "$HOME/depot_tools/.git" # Append depot_tools to the PATH for subsequent steps echo "$HOME/depot_tools" >> $GITHUB_PATH - name: Free disk space @@ -3103,7 +3890,14 @@ jobs: - name: Set up depot_tools if: runner.os == 'Windows' run: | - git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git $HOME/depot_tools + rm -rf "$HOME/depot_tools" + for attempt in 1 2 3; do + git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git "$HOME/depot_tools" && break + rm -rf "$HOME/depot_tools" + echo "depot_tools clone failed (attempt $attempt), retrying..." + sleep 5 + done + test -d "$HOME/depot_tools/.git" # Append depot_tools to the PATH for subsequent steps DEPOT_TOOLS_WIN=$(cygpath -w "$HOME/depot_tools") echo "$DEPOT_TOOLS_WIN" >> $GITHUB_PATH @@ -3149,7 +3943,14 @@ jobs: - name: Set up depot_tools if: runner.os != 'Windows' run: | - git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git $HOME/depot_tools + rm -rf "$HOME/depot_tools" + for attempt in 1 2 3; do + git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git "$HOME/depot_tools" && break + rm -rf "$HOME/depot_tools" + echo "depot_tools clone failed (attempt $attempt), retrying..." + sleep 5 + done + test -d "$HOME/depot_tools/.git" # Append depot_tools to the PATH for subsequent steps echo "$HOME/depot_tools" >> $GITHUB_PATH - name: Free disk space @@ -3158,7 +3959,14 @@ jobs: - name: Set up depot_tools if: runner.os == 'Windows' run: | - git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git $HOME/depot_tools + rm -rf "$HOME/depot_tools" + for attempt in 1 2 3; do + git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git "$HOME/depot_tools" && break + rm -rf "$HOME/depot_tools" + echo "depot_tools clone failed (attempt $attempt), retrying..." + sleep 5 + done + test -d "$HOME/depot_tools/.git" # Append depot_tools to the PATH for subsequent steps DEPOT_TOOLS_WIN=$(cygpath -w "$HOME/depot_tools") echo "$DEPOT_TOOLS_WIN" >> $GITHUB_PATH @@ -3204,7 +4012,14 @@ jobs: - name: Set up depot_tools if: runner.os != 'Windows' run: | - git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git $HOME/depot_tools + rm -rf "$HOME/depot_tools" + for attempt in 1 2 3; do + git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git "$HOME/depot_tools" && break + rm -rf "$HOME/depot_tools" + echo "depot_tools clone failed (attempt $attempt), retrying..." + sleep 5 + done + test -d "$HOME/depot_tools/.git" # Append depot_tools to the PATH for subsequent steps echo "$HOME/depot_tools" >> $GITHUB_PATH - name: Free disk space @@ -3213,7 +4028,14 @@ jobs: - name: Set up depot_tools if: runner.os == 'Windows' run: | - git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git $HOME/depot_tools + rm -rf "$HOME/depot_tools" + for attempt in 1 2 3; do + git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git "$HOME/depot_tools" && break + rm -rf "$HOME/depot_tools" + echo "depot_tools clone failed (attempt $attempt), retrying..." + sleep 5 + done + test -d "$HOME/depot_tools/.git" # Append depot_tools to the PATH for subsequent steps DEPOT_TOOLS_WIN=$(cygpath -w "$HOME/depot_tools") echo "$DEPOT_TOOLS_WIN" >> $GITHUB_PATH @@ -3259,7 +4081,14 @@ jobs: - name: Set up depot_tools if: runner.os != 'Windows' run: | - git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git $HOME/depot_tools + rm -rf "$HOME/depot_tools" + for attempt in 1 2 3; do + git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git "$HOME/depot_tools" && break + rm -rf "$HOME/depot_tools" + echo "depot_tools clone failed (attempt $attempt), retrying..." + sleep 5 + done + test -d "$HOME/depot_tools/.git" # Append depot_tools to the PATH for subsequent steps echo "$HOME/depot_tools" >> $GITHUB_PATH - name: Free disk space @@ -3268,7 +4097,14 @@ jobs: - name: Set up depot_tools if: runner.os == 'Windows' run: | - git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git $HOME/depot_tools + rm -rf "$HOME/depot_tools" + for attempt in 1 2 3; do + git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git "$HOME/depot_tools" && break + rm -rf "$HOME/depot_tools" + echo "depot_tools clone failed (attempt $attempt), retrying..." + sleep 5 + done + test -d "$HOME/depot_tools/.git" # Append depot_tools to the PATH for subsequent steps DEPOT_TOOLS_WIN=$(cygpath -w "$HOME/depot_tools") echo "$DEPOT_TOOLS_WIN" >> $GITHUB_PATH @@ -3314,7 +4150,14 @@ jobs: - name: Set up depot_tools if: runner.os != 'Windows' run: | - git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git $HOME/depot_tools + rm -rf "$HOME/depot_tools" + for attempt in 1 2 3; do + git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git "$HOME/depot_tools" && break + rm -rf "$HOME/depot_tools" + echo "depot_tools clone failed (attempt $attempt), retrying..." + sleep 5 + done + test -d "$HOME/depot_tools/.git" # Append depot_tools to the PATH for subsequent steps echo "$HOME/depot_tools" >> $GITHUB_PATH - name: Free disk space @@ -3323,7 +4166,14 @@ jobs: - name: Set up depot_tools if: runner.os == 'Windows' run: | - git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git $HOME/depot_tools + rm -rf "$HOME/depot_tools" + for attempt in 1 2 3; do + git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git "$HOME/depot_tools" && break + rm -rf "$HOME/depot_tools" + echo "depot_tools clone failed (attempt $attempt), retrying..." + sleep 5 + done + test -d "$HOME/depot_tools/.git" # Append depot_tools to the PATH for subsequent steps DEPOT_TOOLS_WIN=$(cygpath -w "$HOME/depot_tools") echo "$DEPOT_TOOLS_WIN" >> $GITHUB_PATH @@ -3369,7 +4219,14 @@ jobs: - name: Set up depot_tools if: runner.os != 'Windows' run: | - git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git $HOME/depot_tools + rm -rf "$HOME/depot_tools" + for attempt in 1 2 3; do + git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git "$HOME/depot_tools" && break + rm -rf "$HOME/depot_tools" + echo "depot_tools clone failed (attempt $attempt), retrying..." + sleep 5 + done + test -d "$HOME/depot_tools/.git" # Append depot_tools to the PATH for subsequent steps echo "$HOME/depot_tools" >> $GITHUB_PATH - name: Free disk space @@ -3378,7 +4235,14 @@ jobs: - name: Set up depot_tools if: runner.os == 'Windows' run: | - git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git $HOME/depot_tools + rm -rf "$HOME/depot_tools" + for attempt in 1 2 3; do + git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git "$HOME/depot_tools" && break + rm -rf "$HOME/depot_tools" + echo "depot_tools clone failed (attempt $attempt), retrying..." + sleep 5 + done + test -d "$HOME/depot_tools/.git" # Append depot_tools to the PATH for subsequent steps DEPOT_TOOLS_WIN=$(cygpath -w "$HOME/depot_tools") echo "$DEPOT_TOOLS_WIN" >> $GITHUB_PATH @@ -3423,7 +4287,14 @@ jobs: - name: Set up depot_tools if: runner.os != 'Windows' run: | - git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git $HOME/depot_tools + rm -rf "$HOME/depot_tools" + for attempt in 1 2 3; do + git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git "$HOME/depot_tools" && break + rm -rf "$HOME/depot_tools" + echo "depot_tools clone failed (attempt $attempt), retrying..." + sleep 5 + done + test -d "$HOME/depot_tools/.git" # Append depot_tools to the PATH for subsequent steps echo "$HOME/depot_tools" >> $GITHUB_PATH - name: Free disk space @@ -3432,7 +4303,14 @@ jobs: - name: Set up depot_tools if: runner.os == 'Windows' run: | - git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git $HOME/depot_tools + rm -rf "$HOME/depot_tools" + for attempt in 1 2 3; do + git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git "$HOME/depot_tools" && break + rm -rf "$HOME/depot_tools" + echo "depot_tools clone failed (attempt $attempt), retrying..." + sleep 5 + done + test -d "$HOME/depot_tools/.git" # Append depot_tools to the PATH for subsequent steps DEPOT_TOOLS_WIN=$(cygpath -w "$HOME/depot_tools") echo "$DEPOT_TOOLS_WIN" >> $GITHUB_PATH @@ -3477,7 +4355,14 @@ jobs: - name: Set up depot_tools if: runner.os != 'Windows' run: | - git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git $HOME/depot_tools + rm -rf "$HOME/depot_tools" + for attempt in 1 2 3; do + git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git "$HOME/depot_tools" && break + rm -rf "$HOME/depot_tools" + echo "depot_tools clone failed (attempt $attempt), retrying..." + sleep 5 + done + test -d "$HOME/depot_tools/.git" # Append depot_tools to the PATH for subsequent steps echo "$HOME/depot_tools" >> $GITHUB_PATH - name: Free disk space @@ -3486,7 +4371,14 @@ jobs: - name: Set up depot_tools if: runner.os == 'Windows' run: | - git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git $HOME/depot_tools + rm -rf "$HOME/depot_tools" + for attempt in 1 2 3; do + git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git "$HOME/depot_tools" && break + rm -rf "$HOME/depot_tools" + echo "depot_tools clone failed (attempt $attempt), retrying..." + sleep 5 + done + test -d "$HOME/depot_tools/.git" # Append depot_tools to the PATH for subsequent steps DEPOT_TOOLS_WIN=$(cygpath -w "$HOME/depot_tools") echo "$DEPOT_TOOLS_WIN" >> $GITHUB_PATH @@ -3531,7 +4423,14 @@ jobs: - name: Set up depot_tools if: runner.os != 'Windows' run: | - git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git $HOME/depot_tools + rm -rf "$HOME/depot_tools" + for attempt in 1 2 3; do + git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git "$HOME/depot_tools" && break + rm -rf "$HOME/depot_tools" + echo "depot_tools clone failed (attempt $attempt), retrying..." + sleep 5 + done + test -d "$HOME/depot_tools/.git" # Append depot_tools to the PATH for subsequent steps echo "$HOME/depot_tools" >> $GITHUB_PATH - name: Free disk space @@ -3540,7 +4439,14 @@ jobs: - name: Set up depot_tools if: runner.os == 'Windows' run: | - git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git $HOME/depot_tools + rm -rf "$HOME/depot_tools" + for attempt in 1 2 3; do + git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git "$HOME/depot_tools" && break + rm -rf "$HOME/depot_tools" + echo "depot_tools clone failed (attempt $attempt), retrying..." + sleep 5 + done + test -d "$HOME/depot_tools/.git" # Append depot_tools to the PATH for subsequent steps DEPOT_TOOLS_WIN=$(cygpath -w "$HOME/depot_tools") echo "$DEPOT_TOOLS_WIN" >> $GITHUB_PATH @@ -3585,7 +4491,14 @@ jobs: - name: Set up depot_tools if: runner.os != 'Windows' run: | - git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git $HOME/depot_tools + rm -rf "$HOME/depot_tools" + for attempt in 1 2 3; do + git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git "$HOME/depot_tools" && break + rm -rf "$HOME/depot_tools" + echo "depot_tools clone failed (attempt $attempt), retrying..." + sleep 5 + done + test -d "$HOME/depot_tools/.git" # Append depot_tools to the PATH for subsequent steps echo "$HOME/depot_tools" >> $GITHUB_PATH - name: Free disk space @@ -3594,7 +4507,14 @@ jobs: - name: Set up depot_tools if: runner.os == 'Windows' run: | - git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git $HOME/depot_tools + rm -rf "$HOME/depot_tools" + for attempt in 1 2 3; do + git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git "$HOME/depot_tools" && break + rm -rf "$HOME/depot_tools" + echo "depot_tools clone failed (attempt $attempt), retrying..." + sleep 5 + done + test -d "$HOME/depot_tools/.git" # Append depot_tools to the PATH for subsequent steps DEPOT_TOOLS_WIN=$(cygpath -w "$HOME/depot_tools") echo "$DEPOT_TOOLS_WIN" >> $GITHUB_PATH @@ -3639,7 +4559,14 @@ jobs: - name: Set up depot_tools if: runner.os != 'Windows' run: | - git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git $HOME/depot_tools + rm -rf "$HOME/depot_tools" + for attempt in 1 2 3; do + git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git "$HOME/depot_tools" && break + rm -rf "$HOME/depot_tools" + echo "depot_tools clone failed (attempt $attempt), retrying..." + sleep 5 + done + test -d "$HOME/depot_tools/.git" # Append depot_tools to the PATH for subsequent steps echo "$HOME/depot_tools" >> $GITHUB_PATH - name: Free disk space @@ -3648,7 +4575,14 @@ jobs: - name: Set up depot_tools if: runner.os == 'Windows' run: | - git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git $HOME/depot_tools + rm -rf "$HOME/depot_tools" + for attempt in 1 2 3; do + git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git "$HOME/depot_tools" && break + rm -rf "$HOME/depot_tools" + echo "depot_tools clone failed (attempt $attempt), retrying..." + sleep 5 + done + test -d "$HOME/depot_tools/.git" # Append depot_tools to the PATH for subsequent steps DEPOT_TOOLS_WIN=$(cygpath -w "$HOME/depot_tools") echo "$DEPOT_TOOLS_WIN" >> $GITHUB_PATH @@ -3693,7 +4627,14 @@ jobs: - name: Set up depot_tools if: runner.os != 'Windows' run: | - git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git $HOME/depot_tools + rm -rf "$HOME/depot_tools" + for attempt in 1 2 3; do + git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git "$HOME/depot_tools" && break + rm -rf "$HOME/depot_tools" + echo "depot_tools clone failed (attempt $attempt), retrying..." + sleep 5 + done + test -d "$HOME/depot_tools/.git" # Append depot_tools to the PATH for subsequent steps echo "$HOME/depot_tools" >> $GITHUB_PATH - name: Free disk space @@ -3702,7 +4643,14 @@ jobs: - name: Set up depot_tools if: runner.os == 'Windows' run: | - git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git $HOME/depot_tools + rm -rf "$HOME/depot_tools" + for attempt in 1 2 3; do + git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git "$HOME/depot_tools" && break + rm -rf "$HOME/depot_tools" + echo "depot_tools clone failed (attempt $attempt), retrying..." + sleep 5 + done + test -d "$HOME/depot_tools/.git" # Append depot_tools to the PATH for subsequent steps DEPOT_TOOLS_WIN=$(cygpath -w "$HOME/depot_tools") echo "$DEPOT_TOOLS_WIN" >> $GITHUB_PATH @@ -3723,6 +4671,7 @@ jobs: ./flutter/bin/et build --config ci/android_profile - name: Tar build files run: | + find engine/src/out/ci/android_profile -type l -lname "/*" -delete || true tar -cvf linux_android_profile.tar engine/src/out/ci/android_profile - name: Upload build files uses: actions/upload-artifact@v4 @@ -3786,7 +4735,14 @@ jobs: - name: Set up depot_tools if: runner.os != 'Windows' run: | - git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git $HOME/depot_tools + rm -rf "$HOME/depot_tools" + for attempt in 1 2 3; do + git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git "$HOME/depot_tools" && break + rm -rf "$HOME/depot_tools" + echo "depot_tools clone failed (attempt $attempt), retrying..." + sleep 5 + done + test -d "$HOME/depot_tools/.git" # Append depot_tools to the PATH for subsequent steps echo "$HOME/depot_tools" >> $GITHUB_PATH - name: Free disk space @@ -3795,7 +4751,14 @@ jobs: - name: Set up depot_tools if: runner.os == 'Windows' run: | - git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git $HOME/depot_tools + rm -rf "$HOME/depot_tools" + for attempt in 1 2 3; do + git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git "$HOME/depot_tools" && break + rm -rf "$HOME/depot_tools" + echo "depot_tools clone failed (attempt $attempt), retrying..." + sleep 5 + done + test -d "$HOME/depot_tools/.git" # Append depot_tools to the PATH for subsequent steps DEPOT_TOOLS_WIN=$(cygpath -w "$HOME/depot_tools") echo "$DEPOT_TOOLS_WIN" >> $GITHUB_PATH @@ -3816,6 +4779,7 @@ jobs: ./flutter/bin/et build --config ci/android_release - name: Tar build files run: | + find engine/src/out/ci/android_release -type l -lname "/*" -delete || true tar -cvf linux_android_release.tar engine/src/out/ci/android_release - name: Upload build files uses: actions/upload-artifact@v4 @@ -3879,7 +4843,14 @@ jobs: - name: Set up depot_tools if: runner.os != 'Windows' run: | - git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git $HOME/depot_tools + rm -rf "$HOME/depot_tools" + for attempt in 1 2 3; do + git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git "$HOME/depot_tools" && break + rm -rf "$HOME/depot_tools" + echo "depot_tools clone failed (attempt $attempt), retrying..." + sleep 5 + done + test -d "$HOME/depot_tools/.git" # Append depot_tools to the PATH for subsequent steps echo "$HOME/depot_tools" >> $GITHUB_PATH - name: Free disk space @@ -3888,7 +4859,14 @@ jobs: - name: Set up depot_tools if: runner.os == 'Windows' run: | - git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git $HOME/depot_tools + rm -rf "$HOME/depot_tools" + for attempt in 1 2 3; do + git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git "$HOME/depot_tools" && break + rm -rf "$HOME/depot_tools" + echo "depot_tools clone failed (attempt $attempt), retrying..." + sleep 5 + done + test -d "$HOME/depot_tools/.git" # Append depot_tools to the PATH for subsequent steps DEPOT_TOOLS_WIN=$(cygpath -w "$HOME/depot_tools") echo "$DEPOT_TOOLS_WIN" >> $GITHUB_PATH @@ -3909,6 +4887,7 @@ jobs: ./flutter/bin/et build --config ci/android_release_arm64 - name: Tar build files run: | + find engine/src/out/ci/android_release_arm64 -type l -lname "/*" -delete || true tar -cvf linux_android_release_arm64.tar engine/src/out/ci/android_release_arm64 - name: Upload build files uses: actions/upload-artifact@v4 @@ -3982,7 +4961,14 @@ jobs: - name: Set up depot_tools if: runner.os != 'Windows' run: | - git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git $HOME/depot_tools + rm -rf "$HOME/depot_tools" + for attempt in 1 2 3; do + git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git "$HOME/depot_tools" && break + rm -rf "$HOME/depot_tools" + echo "depot_tools clone failed (attempt $attempt), retrying..." + sleep 5 + done + test -d "$HOME/depot_tools/.git" # Append depot_tools to the PATH for subsequent steps echo "$HOME/depot_tools" >> $GITHUB_PATH - name: Free disk space @@ -3991,7 +4977,14 @@ jobs: - name: Set up depot_tools if: runner.os == 'Windows' run: | - git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git $HOME/depot_tools + rm -rf "$HOME/depot_tools" + for attempt in 1 2 3; do + git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git "$HOME/depot_tools" && break + rm -rf "$HOME/depot_tools" + echo "depot_tools clone failed (attempt $attempt), retrying..." + sleep 5 + done + test -d "$HOME/depot_tools/.git" # Append depot_tools to the PATH for subsequent steps DEPOT_TOOLS_WIN=$(cygpath -w "$HOME/depot_tools") echo "$DEPOT_TOOLS_WIN" >> $GITHUB_PATH @@ -4012,6 +5005,7 @@ jobs: ./flutter/bin/et build --config ci/android_profile_arm64 - name: Tar build files run: | + find engine/src/out/ci/android_profile_arm64 -type l -lname "/*" -delete || true tar -cvf linux_android_profile_arm64.tar engine/src/out/ci/android_profile_arm64 - name: Upload build files uses: actions/upload-artifact@v4 @@ -4085,7 +5079,14 @@ jobs: - name: Set up depot_tools if: runner.os != 'Windows' run: | - git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git $HOME/depot_tools + rm -rf "$HOME/depot_tools" + for attempt in 1 2 3; do + git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git "$HOME/depot_tools" && break + rm -rf "$HOME/depot_tools" + echo "depot_tools clone failed (attempt $attempt), retrying..." + sleep 5 + done + test -d "$HOME/depot_tools/.git" # Append depot_tools to the PATH for subsequent steps echo "$HOME/depot_tools" >> $GITHUB_PATH - name: Free disk space @@ -4094,7 +5095,14 @@ jobs: - name: Set up depot_tools if: runner.os == 'Windows' run: | - git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git $HOME/depot_tools + rm -rf "$HOME/depot_tools" + for attempt in 1 2 3; do + git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git "$HOME/depot_tools" && break + rm -rf "$HOME/depot_tools" + echo "depot_tools clone failed (attempt $attempt), retrying..." + sleep 5 + done + test -d "$HOME/depot_tools/.git" # Append depot_tools to the PATH for subsequent steps DEPOT_TOOLS_WIN=$(cygpath -w "$HOME/depot_tools") echo "$DEPOT_TOOLS_WIN" >> $GITHUB_PATH @@ -4115,6 +5123,7 @@ jobs: ./flutter/bin/et build --config ci/android_profile_x64 - name: Tar build files run: | + find engine/src/out/ci/android_profile_x64 -type l -lname "/*" -delete || true tar -cvf linux_android_profile_x64.tar engine/src/out/ci/android_profile_x64 - name: Upload build files uses: actions/upload-artifact@v4 @@ -4188,7 +5197,14 @@ jobs: - name: Set up depot_tools if: runner.os != 'Windows' run: | - git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git $HOME/depot_tools + rm -rf "$HOME/depot_tools" + for attempt in 1 2 3; do + git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git "$HOME/depot_tools" && break + rm -rf "$HOME/depot_tools" + echo "depot_tools clone failed (attempt $attempt), retrying..." + sleep 5 + done + test -d "$HOME/depot_tools/.git" # Append depot_tools to the PATH for subsequent steps echo "$HOME/depot_tools" >> $GITHUB_PATH - name: Free disk space @@ -4197,7 +5213,14 @@ jobs: - name: Set up depot_tools if: runner.os == 'Windows' run: | - git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git $HOME/depot_tools + rm -rf "$HOME/depot_tools" + for attempt in 1 2 3; do + git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git "$HOME/depot_tools" && break + rm -rf "$HOME/depot_tools" + echo "depot_tools clone failed (attempt $attempt), retrying..." + sleep 5 + done + test -d "$HOME/depot_tools/.git" # Append depot_tools to the PATH for subsequent steps DEPOT_TOOLS_WIN=$(cygpath -w "$HOME/depot_tools") echo "$DEPOT_TOOLS_WIN" >> $GITHUB_PATH @@ -4218,6 +5241,7 @@ jobs: ./flutter/bin/et build --config ci/android_release_x64 - name: Tar build files run: | + find engine/src/out/ci/android_release_x64 -type l -lname "/*" -delete || true tar -cvf linux_android_release_x64.tar engine/src/out/ci/android_release_x64 - name: Upload build files uses: actions/upload-artifact@v4 @@ -4291,7 +5315,14 @@ jobs: - name: Set up depot_tools if: runner.os != 'Windows' run: | - git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git $HOME/depot_tools + rm -rf "$HOME/depot_tools" + for attempt in 1 2 3; do + git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git "$HOME/depot_tools" && break + rm -rf "$HOME/depot_tools" + echo "depot_tools clone failed (attempt $attempt), retrying..." + sleep 5 + done + test -d "$HOME/depot_tools/.git" # Append depot_tools to the PATH for subsequent steps echo "$HOME/depot_tools" >> $GITHUB_PATH - name: Free disk space @@ -4300,7 +5331,14 @@ jobs: - name: Set up depot_tools if: runner.os == 'Windows' run: | - git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git $HOME/depot_tools + rm -rf "$HOME/depot_tools" + for attempt in 1 2 3; do + git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git "$HOME/depot_tools" && break + rm -rf "$HOME/depot_tools" + echo "depot_tools clone failed (attempt $attempt), retrying..." + sleep 5 + done + test -d "$HOME/depot_tools/.git" # Append depot_tools to the PATH for subsequent steps DEPOT_TOOLS_WIN=$(cygpath -w "$HOME/depot_tools") echo "$DEPOT_TOOLS_WIN" >> $GITHUB_PATH @@ -4321,6 +5359,7 @@ jobs: ./flutter/bin/et build --config ci/android_profile_riscv64 - name: Tar build files run: | + find engine/src/out/ci/android_profile_riscv64 -type l -lname "/*" -delete || true tar -cvf linux_android_profile_riscv64.tar engine/src/out/ci/android_profile_riscv64 - name: Upload build files uses: actions/upload-artifact@v4 @@ -4394,7 +5433,14 @@ jobs: - name: Set up depot_tools if: runner.os != 'Windows' run: | - git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git $HOME/depot_tools + rm -rf "$HOME/depot_tools" + for attempt in 1 2 3; do + git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git "$HOME/depot_tools" && break + rm -rf "$HOME/depot_tools" + echo "depot_tools clone failed (attempt $attempt), retrying..." + sleep 5 + done + test -d "$HOME/depot_tools/.git" # Append depot_tools to the PATH for subsequent steps echo "$HOME/depot_tools" >> $GITHUB_PATH - name: Free disk space @@ -4403,7 +5449,14 @@ jobs: - name: Set up depot_tools if: runner.os == 'Windows' run: | - git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git $HOME/depot_tools + rm -rf "$HOME/depot_tools" + for attempt in 1 2 3; do + git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git "$HOME/depot_tools" && break + rm -rf "$HOME/depot_tools" + echo "depot_tools clone failed (attempt $attempt), retrying..." + sleep 5 + done + test -d "$HOME/depot_tools/.git" # Append depot_tools to the PATH for subsequent steps DEPOT_TOOLS_WIN=$(cygpath -w "$HOME/depot_tools") echo "$DEPOT_TOOLS_WIN" >> $GITHUB_PATH @@ -4424,6 +5477,7 @@ jobs: ./flutter/bin/et build --config ci/android_release_riscv64 - name: Tar build files run: | + find engine/src/out/ci/android_release_riscv64 -type l -lname "/*" -delete || true tar -cvf linux_android_release_riscv64.tar engine/src/out/ci/android_release_riscv64 - name: Upload build files uses: actions/upload-artifact@v4 @@ -4505,7 +5559,14 @@ jobs: - name: Set up depot_tools if: runner.os != 'Windows' run: | - git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git $HOME/depot_tools + rm -rf "$HOME/depot_tools" + for attempt in 1 2 3; do + git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git "$HOME/depot_tools" && break + rm -rf "$HOME/depot_tools" + echo "depot_tools clone failed (attempt $attempt), retrying..." + sleep 5 + done + test -d "$HOME/depot_tools/.git" # Append depot_tools to the PATH for subsequent steps echo "$HOME/depot_tools" >> $GITHUB_PATH - name: Free disk space @@ -4514,7 +5575,14 @@ jobs: - name: Set up depot_tools if: runner.os == 'Windows' run: | - git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git $HOME/depot_tools + rm -rf "$HOME/depot_tools" + for attempt in 1 2 3; do + git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git "$HOME/depot_tools" && break + rm -rf "$HOME/depot_tools" + echo "depot_tools clone failed (attempt $attempt), retrying..." + sleep 5 + done + test -d "$HOME/depot_tools/.git" # Append depot_tools to the PATH for subsequent steps DEPOT_TOOLS_WIN=$(cygpath -w "$HOME/depot_tools") echo "$DEPOT_TOOLS_WIN" >> $GITHUB_PATH @@ -4615,7 +5683,14 @@ jobs: - name: Set up depot_tools if: runner.os != 'Windows' run: | - git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git $HOME/depot_tools + rm -rf "$HOME/depot_tools" + for attempt in 1 2 3; do + git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git "$HOME/depot_tools" && break + rm -rf "$HOME/depot_tools" + echo "depot_tools clone failed (attempt $attempt), retrying..." + sleep 5 + done + test -d "$HOME/depot_tools/.git" # Append depot_tools to the PATH for subsequent steps echo "$HOME/depot_tools" >> $GITHUB_PATH - name: Free disk space @@ -4624,7 +5699,14 @@ jobs: - name: Set up depot_tools if: runner.os == 'Windows' run: | - git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git $HOME/depot_tools + rm -rf "$HOME/depot_tools" + for attempt in 1 2 3; do + git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git "$HOME/depot_tools" && break + rm -rf "$HOME/depot_tools" + echo "depot_tools clone failed (attempt $attempt), retrying..." + sleep 5 + done + test -d "$HOME/depot_tools/.git" # Append depot_tools to the PATH for subsequent steps DEPOT_TOOLS_WIN=$(cygpath -w "$HOME/depot_tools") echo "$DEPOT_TOOLS_WIN" >> $GITHUB_PATH @@ -4645,6 +5727,7 @@ jobs: ./flutter/bin/et build --config ci/android_debug - name: Tar build files run: | + find engine/src/out/ci/android_debug -type l -lname "/*" -delete || true tar -cvf linux_android_debug.tar engine/src/out/ci/android_debug - name: Upload build files uses: actions/upload-artifact@v4 @@ -4728,7 +5811,14 @@ jobs: - name: Set up depot_tools if: runner.os != 'Windows' run: | - git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git $HOME/depot_tools + rm -rf "$HOME/depot_tools" + for attempt in 1 2 3; do + git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git "$HOME/depot_tools" && break + rm -rf "$HOME/depot_tools" + echo "depot_tools clone failed (attempt $attempt), retrying..." + sleep 5 + done + test -d "$HOME/depot_tools/.git" # Append depot_tools to the PATH for subsequent steps echo "$HOME/depot_tools" >> $GITHUB_PATH - name: Free disk space @@ -4737,7 +5827,14 @@ jobs: - name: Set up depot_tools if: runner.os == 'Windows' run: | - git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git $HOME/depot_tools + rm -rf "$HOME/depot_tools" + for attempt in 1 2 3; do + git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git "$HOME/depot_tools" && break + rm -rf "$HOME/depot_tools" + echo "depot_tools clone failed (attempt $attempt), retrying..." + sleep 5 + done + test -d "$HOME/depot_tools/.git" # Append depot_tools to the PATH for subsequent steps DEPOT_TOOLS_WIN=$(cygpath -w "$HOME/depot_tools") echo "$DEPOT_TOOLS_WIN" >> $GITHUB_PATH @@ -4758,6 +5855,7 @@ jobs: ./flutter/bin/et build --config ci/android_debug_arm64 - name: Tar build files run: | + find engine/src/out/ci/android_debug_arm64 -type l -lname "/*" -delete || true tar -cvf linux_android_debug_arm64.tar engine/src/out/ci/android_debug_arm64 - name: Upload build files uses: actions/upload-artifact@v4 @@ -4821,7 +5919,14 @@ jobs: - name: Set up depot_tools if: runner.os != 'Windows' run: | - git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git $HOME/depot_tools + rm -rf "$HOME/depot_tools" + for attempt in 1 2 3; do + git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git "$HOME/depot_tools" && break + rm -rf "$HOME/depot_tools" + echo "depot_tools clone failed (attempt $attempt), retrying..." + sleep 5 + done + test -d "$HOME/depot_tools/.git" # Append depot_tools to the PATH for subsequent steps echo "$HOME/depot_tools" >> $GITHUB_PATH - name: Free disk space @@ -4830,7 +5935,14 @@ jobs: - name: Set up depot_tools if: runner.os == 'Windows' run: | - git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git $HOME/depot_tools + rm -rf "$HOME/depot_tools" + for attempt in 1 2 3; do + git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git "$HOME/depot_tools" && break + rm -rf "$HOME/depot_tools" + echo "depot_tools clone failed (attempt $attempt), retrying..." + sleep 5 + done + test -d "$HOME/depot_tools/.git" # Append depot_tools to the PATH for subsequent steps DEPOT_TOOLS_WIN=$(cygpath -w "$HOME/depot_tools") echo "$DEPOT_TOOLS_WIN" >> $GITHUB_PATH @@ -4851,6 +5963,7 @@ jobs: ./flutter/bin/et build --config ci/android_debug_x86 - name: Tar build files run: | + find engine/src/out/ci/android_debug_x86 -type l -lname "/*" -delete || true tar -cvf linux_android_debug_x86.tar engine/src/out/ci/android_debug_x86 - name: Upload build files uses: actions/upload-artifact@v4 @@ -4914,7 +6027,14 @@ jobs: - name: Set up depot_tools if: runner.os != 'Windows' run: | - git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git $HOME/depot_tools + rm -rf "$HOME/depot_tools" + for attempt in 1 2 3; do + git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git "$HOME/depot_tools" && break + rm -rf "$HOME/depot_tools" + echo "depot_tools clone failed (attempt $attempt), retrying..." + sleep 5 + done + test -d "$HOME/depot_tools/.git" # Append depot_tools to the PATH for subsequent steps echo "$HOME/depot_tools" >> $GITHUB_PATH - name: Free disk space @@ -4923,7 +6043,14 @@ jobs: - name: Set up depot_tools if: runner.os == 'Windows' run: | - git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git $HOME/depot_tools + rm -rf "$HOME/depot_tools" + for attempt in 1 2 3; do + git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git "$HOME/depot_tools" && break + rm -rf "$HOME/depot_tools" + echo "depot_tools clone failed (attempt $attempt), retrying..." + sleep 5 + done + test -d "$HOME/depot_tools/.git" # Append depot_tools to the PATH for subsequent steps DEPOT_TOOLS_WIN=$(cygpath -w "$HOME/depot_tools") echo "$DEPOT_TOOLS_WIN" >> $GITHUB_PATH @@ -4944,6 +6071,7 @@ jobs: ./flutter/bin/et build --config ci/android_debug_x64 - name: Tar build files run: | + find engine/src/out/ci/android_debug_x64 -type l -lname "/*" -delete || true tar -cvf linux_android_debug_x64.tar engine/src/out/ci/android_debug_x64 - name: Upload build files uses: actions/upload-artifact@v4 @@ -5007,7 +6135,14 @@ jobs: - name: Set up depot_tools if: runner.os != 'Windows' run: | - git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git $HOME/depot_tools + rm -rf "$HOME/depot_tools" + for attempt in 1 2 3; do + git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git "$HOME/depot_tools" && break + rm -rf "$HOME/depot_tools" + echo "depot_tools clone failed (attempt $attempt), retrying..." + sleep 5 + done + test -d "$HOME/depot_tools/.git" # Append depot_tools to the PATH for subsequent steps echo "$HOME/depot_tools" >> $GITHUB_PATH - name: Free disk space @@ -5016,7 +6151,14 @@ jobs: - name: Set up depot_tools if: runner.os == 'Windows' run: | - git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git $HOME/depot_tools + rm -rf "$HOME/depot_tools" + for attempt in 1 2 3; do + git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git "$HOME/depot_tools" && break + rm -rf "$HOME/depot_tools" + echo "depot_tools clone failed (attempt $attempt), retrying..." + sleep 5 + done + test -d "$HOME/depot_tools/.git" # Append depot_tools to the PATH for subsequent steps DEPOT_TOOLS_WIN=$(cygpath -w "$HOME/depot_tools") echo "$DEPOT_TOOLS_WIN" >> $GITHUB_PATH @@ -5037,6 +6179,7 @@ jobs: ./flutter/bin/et build --config ci/android_debug_riscv64 - name: Tar build files run: | + find engine/src/out/ci/android_debug_riscv64 -type l -lname "/*" -delete || true tar -cvf linux_android_debug_riscv64.tar engine/src/out/ci/android_debug_riscv64 - name: Upload build files uses: actions/upload-artifact@v4 @@ -5105,7 +6248,14 @@ jobs: - name: Set up depot_tools if: runner.os != 'Windows' run: | - git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git $HOME/depot_tools + rm -rf "$HOME/depot_tools" + for attempt in 1 2 3; do + git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git "$HOME/depot_tools" && break + rm -rf "$HOME/depot_tools" + echo "depot_tools clone failed (attempt $attempt), retrying..." + sleep 5 + done + test -d "$HOME/depot_tools/.git" # Append depot_tools to the PATH for subsequent steps echo "$HOME/depot_tools" >> $GITHUB_PATH - name: Free disk space @@ -5114,7 +6264,14 @@ jobs: - name: Set up depot_tools if: runner.os == 'Windows' run: | - git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git $HOME/depot_tools + rm -rf "$HOME/depot_tools" + for attempt in 1 2 3; do + git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git "$HOME/depot_tools" && break + rm -rf "$HOME/depot_tools" + echo "depot_tools clone failed (attempt $attempt), retrying..." + sleep 5 + done + test -d "$HOME/depot_tools/.git" # Append depot_tools to the PATH for subsequent steps DEPOT_TOOLS_WIN=$(cygpath -w "$HOME/depot_tools") echo "$DEPOT_TOOLS_WIN" >> $GITHUB_PATH @@ -5191,7 +6348,14 @@ jobs: - name: Set up depot_tools if: runner.os != 'Windows' run: | - git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git $HOME/depot_tools + rm -rf "$HOME/depot_tools" + for attempt in 1 2 3; do + git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git "$HOME/depot_tools" && break + rm -rf "$HOME/depot_tools" + echo "depot_tools clone failed (attempt $attempt), retrying..." + sleep 5 + done + test -d "$HOME/depot_tools/.git" # Append depot_tools to the PATH for subsequent steps echo "$HOME/depot_tools" >> $GITHUB_PATH - name: Free disk space @@ -5200,7 +6364,14 @@ jobs: - name: Set up depot_tools if: runner.os == 'Windows' run: | - git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git $HOME/depot_tools + rm -rf "$HOME/depot_tools" + for attempt in 1 2 3; do + git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git "$HOME/depot_tools" && break + rm -rf "$HOME/depot_tools" + echo "depot_tools clone failed (attempt $attempt), retrying..." + sleep 5 + done + test -d "$HOME/depot_tools/.git" # Append depot_tools to the PATH for subsequent steps DEPOT_TOOLS_WIN=$(cygpath -w "$HOME/depot_tools") echo "$DEPOT_TOOLS_WIN" >> $GITHUB_PATH @@ -5229,6 +6400,112 @@ jobs: name: artifact_${{ steps.engine_content_hash.outputs.value }}_133 path: engine/src/out/wasm_release/zip_archives/artifact_133.tar retention-days: 1 + ios_unit_engine_test: + runs-on: macos-latest + defaults: + run: + shell: bash + needs: + - mac_ios_test_binaries_arm64 + - guard + if: ${{ needs.guard.outputs.should_run == 'true' }} + steps: + - name: Checkout the repository + uses: actions/checkout@v4 + with: + path: '' + - name: Set up depot_tools + run: | + rm -rf "$HOME/depot_tools" + for attempt in 1 2 3; do + git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git "$HOME/depot_tools" && break + rm -rf "$HOME/depot_tools" + echo "depot_tools clone failed (attempt $attempt), retrying..." + sleep 5 + done + test -d "$HOME/depot_tools/.git" + # Append depot_tools to the PATH for subsequent steps + echo "$HOME/depot_tools" >> $GITHUB_PATH + - name: Expose engine content hash + id: engine_content_hash + run: | + engine_content_hash=${{ needs.guard.outputs.engine_content_hash }} + echo "value=${engine_content_hash}" >> $GITHUB_OUTPUT + - name: Copy gclient file + run: | + cp engine/scripts/slim.gclient .gclient + - name: GClient sync + run: | + gclient sync -D --no-history --shallow --with_branch_heads + - name: Download Artifacts from mac_ios_test_binaries_arm64 + uses: actions/download-artifact@v4 + with: + name: artifacts-mac_ios_test_binaries_arm64-${{ steps.engine_content_hash.outputs.value }} + - name: Extract Artifacts from mac_ios_test_binaries_arm64 + run: | + tar -xvf mac_ios_test_binaries_arm64.tar + rm mac_ios_test_binaries_arm64.tar + - name: Run test iOS unit tests for ci/ios_test_binaries_arm64 + run: | + cd engine/src + python3 flutter/testing/run_tests.py \ + --variant ci/ios_test_binaries_arm64 \ + --type objc \ + --ios-variant ci/ios_test_binaries_arm64 \ + --engine-capture-core-dump + android_java_engine_test: + runs-on: ubuntu-latest + defaults: + run: + shell: bash + needs: + - linux_android_debug_arm64 + - guard + if: ${{ needs.guard.outputs.should_run == 'true' }} + steps: + - name: Checkout the repository + uses: actions/checkout@v4 + with: + path: '' + - name: Set up depot_tools + run: | + rm -rf "$HOME/depot_tools" + for attempt in 1 2 3; do + git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git "$HOME/depot_tools" && break + rm -rf "$HOME/depot_tools" + echo "depot_tools clone failed (attempt $attempt), retrying..." + sleep 5 + done + test -d "$HOME/depot_tools/.git" + # Append depot_tools to the PATH for subsequent steps + echo "$HOME/depot_tools" >> $GITHUB_PATH + - name: Expose engine content hash + id: engine_content_hash + run: | + engine_content_hash=${{ needs.guard.outputs.engine_content_hash }} + echo "value=${engine_content_hash}" >> $GITHUB_OUTPUT + - name: Copy gclient file + run: | + cp engine/scripts/standard.gclient .gclient + - name: GClient sync + run: | + gclient sync -D --no-history --shallow --with_branch_heads + - name: Download Artifacts from linux_android_debug_arm64 + uses: actions/download-artifact@v4 + with: + name: artifacts-linux_android_debug_arm64-${{ steps.engine_content_hash.outputs.value }} + - name: Extract Artifacts from linux_android_debug_arm64 + run: | + tar -xvf linux_android_debug_arm64.tar + rm linux_android_debug_arm64.tar + - name: Run test Android Java unit tests for ci/android_debug_arm64 + run: | + cd engine/src + python3 flutter/testing/run_tests.py \ + --variant ci/android_debug_arm64 \ + --type java \ + --android-variant ci/android_debug_arm64 \ + --engine-capture-core-dump publish_artifacts: defaults: run: @@ -5283,6 +6560,8 @@ jobs: - linux_android_debug_x64 - linux_android_debug_riscv64 - linux_wasm_release + - ios_unit_engine_test + - android_java_engine_test - guard runs-on: ubuntu-latest if: ${{ needs.guard.outputs.should_run == 'true' }} @@ -6498,1222 +7777,1262 @@ jobs: run: | tar -xvf artifact-133/artifact_133.tar -C artifact-133/ rm artifact-133/artifact_133.tar + - name: Select the R2 target + id: r2_target + env: + R2_ENGINE_BUCKET: flutter-zero-engine + R2_CI_BUCKET: flutter-zero-ci + run: | + if [ "${GITHUB_EVENT_NAME}" = "pull_request" ]; then + echo "bucket=$R2_CI_BUCKET" >> $GITHUB_OUTPUT + echo "prefix=pr-${GITHUB_RUN_ID}/" >> $GITHUB_OUTPUT + else + echo "bucket=$R2_ENGINE_BUCKET" >> $GITHUB_OUTPUT + echo "prefix=" >> $GITHUB_OUTPUT + fi - name: Publish darwin-x64/artifacts.zip uses: ryand56/r2-upload-action@b801a390acbdeb034c5e684ff5e1361c06639e7c with: r2-account-id: ${{ secrets.R2_ACCOUNT_ID }} r2-access-key-id: ${{ secrets.R2_ACCESS_KEY_ID }} r2-secret-access-key: ${{ secrets.R2_SECRET_ACCESS_KEY }} - r2-bucket: ${{ env.R2_BUCKET }} + r2-bucket: ${{ steps.r2_target.outputs.bucket }} source-dir: artifact-0/ - destination-dir: flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/darwin-x64 + destination-dir: ${{ steps.r2_target.outputs.prefix }}flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/darwin-x64 - name: Publish /dart-sdk-darwin-x64.zip uses: ryand56/r2-upload-action@b801a390acbdeb034c5e684ff5e1361c06639e7c with: r2-account-id: ${{ secrets.R2_ACCOUNT_ID }} r2-access-key-id: ${{ secrets.R2_ACCESS_KEY_ID }} r2-secret-access-key: ${{ secrets.R2_SECRET_ACCESS_KEY }} - r2-bucket: ${{ env.R2_BUCKET }} + r2-bucket: ${{ steps.r2_target.outputs.bucket }} source-dir: artifact-1/ - destination-dir: flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/ + destination-dir: ${{ steps.r2_target.outputs.prefix }}flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/ - name: Publish darwin-x64-profile/artifacts.zip uses: ryand56/r2-upload-action@b801a390acbdeb034c5e684ff5e1361c06639e7c with: r2-account-id: ${{ secrets.R2_ACCOUNT_ID }} r2-access-key-id: ${{ secrets.R2_ACCESS_KEY_ID }} r2-secret-access-key: ${{ secrets.R2_SECRET_ACCESS_KEY }} - r2-bucket: ${{ env.R2_BUCKET }} + r2-bucket: ${{ steps.r2_target.outputs.bucket }} source-dir: artifact-2/ - destination-dir: flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/darwin-x64-profile + destination-dir: ${{ steps.r2_target.outputs.prefix }}flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/darwin-x64-profile - name: Publish darwin-x64-release/artifacts.zip uses: ryand56/r2-upload-action@b801a390acbdeb034c5e684ff5e1361c06639e7c with: r2-account-id: ${{ secrets.R2_ACCOUNT_ID }} r2-access-key-id: ${{ secrets.R2_ACCESS_KEY_ID }} r2-secret-access-key: ${{ secrets.R2_SECRET_ACCESS_KEY }} - r2-bucket: ${{ env.R2_BUCKET }} + r2-bucket: ${{ steps.r2_target.outputs.bucket }} source-dir: artifact-3/ - destination-dir: flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/darwin-x64-release + destination-dir: ${{ steps.r2_target.outputs.prefix }}flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/darwin-x64-release - name: Publish darwin-x64/font-subset.zip uses: ryand56/r2-upload-action@b801a390acbdeb034c5e684ff5e1361c06639e7c with: r2-account-id: ${{ secrets.R2_ACCOUNT_ID }} r2-access-key-id: ${{ secrets.R2_ACCESS_KEY_ID }} r2-secret-access-key: ${{ secrets.R2_SECRET_ACCESS_KEY }} - r2-bucket: ${{ env.R2_BUCKET }} + r2-bucket: ${{ steps.r2_target.outputs.bucket }} source-dir: artifact-4/ - destination-dir: flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/darwin-x64 + destination-dir: ${{ steps.r2_target.outputs.prefix }}flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/darwin-x64 - name: Publish darwin-arm64/artifacts.zip uses: ryand56/r2-upload-action@b801a390acbdeb034c5e684ff5e1361c06639e7c with: r2-account-id: ${{ secrets.R2_ACCOUNT_ID }} r2-access-key-id: ${{ secrets.R2_ACCESS_KEY_ID }} r2-secret-access-key: ${{ secrets.R2_SECRET_ACCESS_KEY }} - r2-bucket: ${{ env.R2_BUCKET }} + r2-bucket: ${{ steps.r2_target.outputs.bucket }} source-dir: artifact-5/ - destination-dir: flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/darwin-arm64 + destination-dir: ${{ steps.r2_target.outputs.prefix }}flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/darwin-arm64 - name: Publish /dart-sdk-darwin-arm64.zip uses: ryand56/r2-upload-action@b801a390acbdeb034c5e684ff5e1361c06639e7c with: r2-account-id: ${{ secrets.R2_ACCOUNT_ID }} r2-access-key-id: ${{ secrets.R2_ACCESS_KEY_ID }} r2-secret-access-key: ${{ secrets.R2_SECRET_ACCESS_KEY }} - r2-bucket: ${{ env.R2_BUCKET }} + r2-bucket: ${{ steps.r2_target.outputs.bucket }} source-dir: artifact-6/ - destination-dir: flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/ + destination-dir: ${{ steps.r2_target.outputs.prefix }}flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/ - name: Publish darwin-arm64-profile/artifacts.zip uses: ryand56/r2-upload-action@b801a390acbdeb034c5e684ff5e1361c06639e7c with: r2-account-id: ${{ secrets.R2_ACCOUNT_ID }} r2-access-key-id: ${{ secrets.R2_ACCESS_KEY_ID }} r2-secret-access-key: ${{ secrets.R2_SECRET_ACCESS_KEY }} - r2-bucket: ${{ env.R2_BUCKET }} + r2-bucket: ${{ steps.r2_target.outputs.bucket }} source-dir: artifact-7/ - destination-dir: flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/darwin-arm64-profile + destination-dir: ${{ steps.r2_target.outputs.prefix }}flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/darwin-arm64-profile - name: Publish darwin-arm64/font-subset.zip uses: ryand56/r2-upload-action@b801a390acbdeb034c5e684ff5e1361c06639e7c with: r2-account-id: ${{ secrets.R2_ACCOUNT_ID }} r2-access-key-id: ${{ secrets.R2_ACCESS_KEY_ID }} r2-secret-access-key: ${{ secrets.R2_SECRET_ACCESS_KEY }} - r2-bucket: ${{ env.R2_BUCKET }} + r2-bucket: ${{ steps.r2_target.outputs.bucket }} source-dir: artifact-8/ - destination-dir: flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/darwin-arm64 + destination-dir: ${{ steps.r2_target.outputs.prefix }}flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/darwin-arm64 - name: Publish darwin-arm64-release/artifacts.zip uses: ryand56/r2-upload-action@b801a390acbdeb034c5e684ff5e1361c06639e7c with: r2-account-id: ${{ secrets.R2_ACCOUNT_ID }} r2-access-key-id: ${{ secrets.R2_ACCESS_KEY_ID }} r2-secret-access-key: ${{ secrets.R2_SECRET_ACCESS_KEY }} - r2-bucket: ${{ env.R2_BUCKET }} + r2-bucket: ${{ steps.r2_target.outputs.bucket }} source-dir: artifact-9/ - destination-dir: flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/darwin-arm64-release + destination-dir: ${{ steps.r2_target.outputs.prefix }}flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/darwin-arm64-release - name: Publish darwin-x64/FlutterEmbedder.framework.zip uses: ryand56/r2-upload-action@b801a390acbdeb034c5e684ff5e1361c06639e7c with: r2-account-id: ${{ secrets.R2_ACCOUNT_ID }} r2-access-key-id: ${{ secrets.R2_ACCESS_KEY_ID }} r2-secret-access-key: ${{ secrets.R2_SECRET_ACCESS_KEY }} - r2-bucket: ${{ env.R2_BUCKET }} + r2-bucket: ${{ steps.r2_target.outputs.bucket }} source-dir: artifact-10/ - destination-dir: flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/darwin-x64 + destination-dir: ${{ steps.r2_target.outputs.prefix }}flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/darwin-x64 - name: Publish darwin-x64/FlutterMacOS.framework.zip uses: ryand56/r2-upload-action@b801a390acbdeb034c5e684ff5e1361c06639e7c with: r2-account-id: ${{ secrets.R2_ACCOUNT_ID }} r2-access-key-id: ${{ secrets.R2_ACCESS_KEY_ID }} r2-secret-access-key: ${{ secrets.R2_SECRET_ACCESS_KEY }} - r2-bucket: ${{ env.R2_BUCKET }} + r2-bucket: ${{ steps.r2_target.outputs.bucket }} source-dir: artifact-11/ - destination-dir: flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/darwin-x64 + destination-dir: ${{ steps.r2_target.outputs.prefix }}flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/darwin-x64 - name: Publish darwin-x64-profile/FlutterMacOS.framework.zip uses: ryand56/r2-upload-action@b801a390acbdeb034c5e684ff5e1361c06639e7c with: r2-account-id: ${{ secrets.R2_ACCOUNT_ID }} r2-access-key-id: ${{ secrets.R2_ACCESS_KEY_ID }} r2-secret-access-key: ${{ secrets.R2_SECRET_ACCESS_KEY }} - r2-bucket: ${{ env.R2_BUCKET }} + r2-bucket: ${{ steps.r2_target.outputs.bucket }} source-dir: artifact-12/ - destination-dir: flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/darwin-x64-profile + destination-dir: ${{ steps.r2_target.outputs.prefix }}flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/darwin-x64-profile - name: Publish darwin-x64-release/FlutterMacOS.framework.zip uses: ryand56/r2-upload-action@b801a390acbdeb034c5e684ff5e1361c06639e7c with: r2-account-id: ${{ secrets.R2_ACCOUNT_ID }} r2-access-key-id: ${{ secrets.R2_ACCESS_KEY_ID }} r2-secret-access-key: ${{ secrets.R2_SECRET_ACCESS_KEY }} - r2-bucket: ${{ env.R2_BUCKET }} + r2-bucket: ${{ steps.r2_target.outputs.bucket }} source-dir: artifact-13/ - destination-dir: flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/darwin-x64-release + destination-dir: ${{ steps.r2_target.outputs.prefix }}flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/darwin-x64-release - name: Publish darwin-x64/gen_snapshot.zip uses: ryand56/r2-upload-action@b801a390acbdeb034c5e684ff5e1361c06639e7c with: r2-account-id: ${{ secrets.R2_ACCOUNT_ID }} r2-access-key-id: ${{ secrets.R2_ACCESS_KEY_ID }} r2-secret-access-key: ${{ secrets.R2_SECRET_ACCESS_KEY }} - r2-bucket: ${{ env.R2_BUCKET }} + r2-bucket: ${{ steps.r2_target.outputs.bucket }} source-dir: artifact-14/ - destination-dir: flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/darwin-x64 + destination-dir: ${{ steps.r2_target.outputs.prefix }}flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/darwin-x64 - name: Publish darwin-x64-profile/gen_snapshot.zip uses: ryand56/r2-upload-action@b801a390acbdeb034c5e684ff5e1361c06639e7c with: r2-account-id: ${{ secrets.R2_ACCOUNT_ID }} r2-access-key-id: ${{ secrets.R2_ACCESS_KEY_ID }} r2-secret-access-key: ${{ secrets.R2_SECRET_ACCESS_KEY }} - r2-bucket: ${{ env.R2_BUCKET }} + r2-bucket: ${{ steps.r2_target.outputs.bucket }} source-dir: artifact-15/ - destination-dir: flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/darwin-x64-profile + destination-dir: ${{ steps.r2_target.outputs.prefix }}flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/darwin-x64-profile - name: Publish darwin-x64-release/gen_snapshot.zip uses: ryand56/r2-upload-action@b801a390acbdeb034c5e684ff5e1361c06639e7c with: r2-account-id: ${{ secrets.R2_ACCOUNT_ID }} r2-access-key-id: ${{ secrets.R2_ACCESS_KEY_ID }} r2-secret-access-key: ${{ secrets.R2_SECRET_ACCESS_KEY }} - r2-bucket: ${{ env.R2_BUCKET }} + r2-bucket: ${{ steps.r2_target.outputs.bucket }} source-dir: artifact-16/ - destination-dir: flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/darwin-x64-release + destination-dir: ${{ steps.r2_target.outputs.prefix }}flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/darwin-x64-release - name: Publish darwin-x64/framework.zip uses: ryand56/r2-upload-action@b801a390acbdeb034c5e684ff5e1361c06639e7c with: r2-account-id: ${{ secrets.R2_ACCOUNT_ID }} r2-access-key-id: ${{ secrets.R2_ACCESS_KEY_ID }} r2-secret-access-key: ${{ secrets.R2_SECRET_ACCESS_KEY }} - r2-bucket: ${{ env.R2_BUCKET }} + r2-bucket: ${{ steps.r2_target.outputs.bucket }} source-dir: artifact-17/ - destination-dir: flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/darwin-x64 + destination-dir: ${{ steps.r2_target.outputs.prefix }}flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/darwin-x64 - name: Publish darwin-x64-profile/framework.zip uses: ryand56/r2-upload-action@b801a390acbdeb034c5e684ff5e1361c06639e7c with: r2-account-id: ${{ secrets.R2_ACCOUNT_ID }} r2-access-key-id: ${{ secrets.R2_ACCESS_KEY_ID }} r2-secret-access-key: ${{ secrets.R2_SECRET_ACCESS_KEY }} - r2-bucket: ${{ env.R2_BUCKET }} + r2-bucket: ${{ steps.r2_target.outputs.bucket }} source-dir: artifact-18/ - destination-dir: flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/darwin-x64-profile + destination-dir: ${{ steps.r2_target.outputs.prefix }}flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/darwin-x64-profile - name: Publish darwin-x64-release/framework.zip uses: ryand56/r2-upload-action@b801a390acbdeb034c5e684ff5e1361c06639e7c with: r2-account-id: ${{ secrets.R2_ACCOUNT_ID }} r2-access-key-id: ${{ secrets.R2_ACCESS_KEY_ID }} r2-secret-access-key: ${{ secrets.R2_SECRET_ACCESS_KEY }} - r2-bucket: ${{ env.R2_BUCKET }} + r2-bucket: ${{ steps.r2_target.outputs.bucket }} source-dir: artifact-19/ - destination-dir: flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/darwin-x64-release + destination-dir: ${{ steps.r2_target.outputs.prefix }}flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/darwin-x64-release - name: Publish ios/artifacts.zip uses: ryand56/r2-upload-action@b801a390acbdeb034c5e684ff5e1361c06639e7c with: r2-account-id: ${{ secrets.R2_ACCOUNT_ID }} r2-access-key-id: ${{ secrets.R2_ACCESS_KEY_ID }} r2-secret-access-key: ${{ secrets.R2_SECRET_ACCESS_KEY }} - r2-bucket: ${{ env.R2_BUCKET }} + r2-bucket: ${{ steps.r2_target.outputs.bucket }} source-dir: artifact-20/ - destination-dir: flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/ios + destination-dir: ${{ steps.r2_target.outputs.prefix }}flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/ios - name: Publish ios-profile/artifacts.zip uses: ryand56/r2-upload-action@b801a390acbdeb034c5e684ff5e1361c06639e7c with: r2-account-id: ${{ secrets.R2_ACCOUNT_ID }} r2-access-key-id: ${{ secrets.R2_ACCESS_KEY_ID }} r2-secret-access-key: ${{ secrets.R2_SECRET_ACCESS_KEY }} - r2-bucket: ${{ env.R2_BUCKET }} + r2-bucket: ${{ steps.r2_target.outputs.bucket }} source-dir: artifact-21/ - destination-dir: flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/ios-profile + destination-dir: ${{ steps.r2_target.outputs.prefix }}flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/ios-profile - name: Publish ios-release/artifacts.zip uses: ryand56/r2-upload-action@b801a390acbdeb034c5e684ff5e1361c06639e7c with: r2-account-id: ${{ secrets.R2_ACCOUNT_ID }} r2-access-key-id: ${{ secrets.R2_ACCESS_KEY_ID }} r2-secret-access-key: ${{ secrets.R2_SECRET_ACCESS_KEY }} - r2-bucket: ${{ env.R2_BUCKET }} + r2-bucket: ${{ steps.r2_target.outputs.bucket }} source-dir: artifact-22/ - destination-dir: flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/ios-release + destination-dir: ${{ steps.r2_target.outputs.prefix }}flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/ios-release - name: Publish windows-x64/artifacts.zip uses: ryand56/r2-upload-action@b801a390acbdeb034c5e684ff5e1361c06639e7c with: r2-account-id: ${{ secrets.R2_ACCOUNT_ID }} r2-access-key-id: ${{ secrets.R2_ACCESS_KEY_ID }} r2-secret-access-key: ${{ secrets.R2_SECRET_ACCESS_KEY }} - r2-bucket: ${{ env.R2_BUCKET }} + r2-bucket: ${{ steps.r2_target.outputs.bucket }} source-dir: artifact-23/ - destination-dir: flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/windows-x64 + destination-dir: ${{ steps.r2_target.outputs.prefix }}flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/windows-x64 - name: Publish windows-x64/windows-x64-embedder.zip uses: ryand56/r2-upload-action@b801a390acbdeb034c5e684ff5e1361c06639e7c with: r2-account-id: ${{ secrets.R2_ACCOUNT_ID }} r2-access-key-id: ${{ secrets.R2_ACCESS_KEY_ID }} r2-secret-access-key: ${{ secrets.R2_SECRET_ACCESS_KEY }} - r2-bucket: ${{ env.R2_BUCKET }} + r2-bucket: ${{ steps.r2_target.outputs.bucket }} source-dir: artifact-24/ - destination-dir: flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/windows-x64 + destination-dir: ${{ steps.r2_target.outputs.prefix }}flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/windows-x64 - name: Publish windows-x64/font-subset.zip uses: ryand56/r2-upload-action@b801a390acbdeb034c5e684ff5e1361c06639e7c with: r2-account-id: ${{ secrets.R2_ACCOUNT_ID }} r2-access-key-id: ${{ secrets.R2_ACCESS_KEY_ID }} r2-secret-access-key: ${{ secrets.R2_SECRET_ACCESS_KEY }} - r2-bucket: ${{ env.R2_BUCKET }} + r2-bucket: ${{ steps.r2_target.outputs.bucket }} source-dir: artifact-25/ - destination-dir: flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/windows-x64 + destination-dir: ${{ steps.r2_target.outputs.prefix }}flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/windows-x64 - name: Publish /dart-sdk-windows-x64.zip uses: ryand56/r2-upload-action@b801a390acbdeb034c5e684ff5e1361c06639e7c with: r2-account-id: ${{ secrets.R2_ACCOUNT_ID }} r2-access-key-id: ${{ secrets.R2_ACCESS_KEY_ID }} r2-secret-access-key: ${{ secrets.R2_SECRET_ACCESS_KEY }} - r2-bucket: ${{ env.R2_BUCKET }} + r2-bucket: ${{ steps.r2_target.outputs.bucket }} source-dir: artifact-26/ - destination-dir: flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/ + destination-dir: ${{ steps.r2_target.outputs.prefix }}flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/ - name: Publish windows-x64-debug/windows-x64-flutter.zip uses: ryand56/r2-upload-action@b801a390acbdeb034c5e684ff5e1361c06639e7c with: r2-account-id: ${{ secrets.R2_ACCOUNT_ID }} r2-access-key-id: ${{ secrets.R2_ACCESS_KEY_ID }} r2-secret-access-key: ${{ secrets.R2_SECRET_ACCESS_KEY }} - r2-bucket: ${{ env.R2_BUCKET }} + r2-bucket: ${{ steps.r2_target.outputs.bucket }} source-dir: artifact-27/ - destination-dir: flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/windows-x64-debug + destination-dir: ${{ steps.r2_target.outputs.prefix }}flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/windows-x64-debug - name: Publish windows-x64/flutter-cpp-client-wrapper.zip uses: ryand56/r2-upload-action@b801a390acbdeb034c5e684ff5e1361c06639e7c with: r2-account-id: ${{ secrets.R2_ACCOUNT_ID }} r2-access-key-id: ${{ secrets.R2_ACCESS_KEY_ID }} r2-secret-access-key: ${{ secrets.R2_SECRET_ACCESS_KEY }} - r2-bucket: ${{ env.R2_BUCKET }} + r2-bucket: ${{ steps.r2_target.outputs.bucket }} source-dir: artifact-28/ - destination-dir: flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/windows-x64 + destination-dir: ${{ steps.r2_target.outputs.prefix }}flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/windows-x64 - name: Publish windows-x64-profile/windows-x64-flutter.zip uses: ryand56/r2-upload-action@b801a390acbdeb034c5e684ff5e1361c06639e7c with: r2-account-id: ${{ secrets.R2_ACCOUNT_ID }} r2-access-key-id: ${{ secrets.R2_ACCESS_KEY_ID }} r2-secret-access-key: ${{ secrets.R2_SECRET_ACCESS_KEY }} - r2-bucket: ${{ env.R2_BUCKET }} + r2-bucket: ${{ steps.r2_target.outputs.bucket }} source-dir: artifact-29/ - destination-dir: flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/windows-x64-profile + destination-dir: ${{ steps.r2_target.outputs.prefix }}flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/windows-x64-profile - name: Publish windows-x64-release/windows-x64-flutter.zip uses: ryand56/r2-upload-action@b801a390acbdeb034c5e684ff5e1361c06639e7c with: r2-account-id: ${{ secrets.R2_ACCOUNT_ID }} r2-access-key-id: ${{ secrets.R2_ACCESS_KEY_ID }} r2-secret-access-key: ${{ secrets.R2_SECRET_ACCESS_KEY }} - r2-bucket: ${{ env.R2_BUCKET }} + r2-bucket: ${{ steps.r2_target.outputs.bucket }} source-dir: artifact-30/ - destination-dir: flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/windows-x64-release + destination-dir: ${{ steps.r2_target.outputs.prefix }}flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/windows-x64-release - name: Publish windows-arm64/artifacts.zip uses: ryand56/r2-upload-action@b801a390acbdeb034c5e684ff5e1361c06639e7c with: r2-account-id: ${{ secrets.R2_ACCOUNT_ID }} r2-access-key-id: ${{ secrets.R2_ACCESS_KEY_ID }} r2-secret-access-key: ${{ secrets.R2_SECRET_ACCESS_KEY }} - r2-bucket: ${{ env.R2_BUCKET }} + r2-bucket: ${{ steps.r2_target.outputs.bucket }} source-dir: artifact-31/ - destination-dir: flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/windows-arm64 + destination-dir: ${{ steps.r2_target.outputs.prefix }}flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/windows-arm64 - name: Publish windows-arm64/windows-arm64-embedder.zip uses: ryand56/r2-upload-action@b801a390acbdeb034c5e684ff5e1361c06639e7c with: r2-account-id: ${{ secrets.R2_ACCOUNT_ID }} r2-access-key-id: ${{ secrets.R2_ACCESS_KEY_ID }} r2-secret-access-key: ${{ secrets.R2_SECRET_ACCESS_KEY }} - r2-bucket: ${{ env.R2_BUCKET }} + r2-bucket: ${{ steps.r2_target.outputs.bucket }} source-dir: artifact-32/ - destination-dir: flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/windows-arm64 + destination-dir: ${{ steps.r2_target.outputs.prefix }}flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/windows-arm64 - name: Publish windows-arm64/font-subset.zip uses: ryand56/r2-upload-action@b801a390acbdeb034c5e684ff5e1361c06639e7c with: r2-account-id: ${{ secrets.R2_ACCOUNT_ID }} r2-access-key-id: ${{ secrets.R2_ACCESS_KEY_ID }} r2-secret-access-key: ${{ secrets.R2_SECRET_ACCESS_KEY }} - r2-bucket: ${{ env.R2_BUCKET }} + r2-bucket: ${{ steps.r2_target.outputs.bucket }} source-dir: artifact-33/ - destination-dir: flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/windows-arm64 + destination-dir: ${{ steps.r2_target.outputs.prefix }}flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/windows-arm64 - name: Publish /dart-sdk-windows-arm64.zip uses: ryand56/r2-upload-action@b801a390acbdeb034c5e684ff5e1361c06639e7c with: r2-account-id: ${{ secrets.R2_ACCOUNT_ID }} r2-access-key-id: ${{ secrets.R2_ACCESS_KEY_ID }} r2-secret-access-key: ${{ secrets.R2_SECRET_ACCESS_KEY }} - r2-bucket: ${{ env.R2_BUCKET }} + r2-bucket: ${{ steps.r2_target.outputs.bucket }} source-dir: artifact-34/ - destination-dir: flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/ + destination-dir: ${{ steps.r2_target.outputs.prefix }}flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/ - name: Publish windows-arm64-debug/windows-arm64-flutter.zip uses: ryand56/r2-upload-action@b801a390acbdeb034c5e684ff5e1361c06639e7c with: r2-account-id: ${{ secrets.R2_ACCOUNT_ID }} r2-access-key-id: ${{ secrets.R2_ACCESS_KEY_ID }} r2-secret-access-key: ${{ secrets.R2_SECRET_ACCESS_KEY }} - r2-bucket: ${{ env.R2_BUCKET }} + r2-bucket: ${{ steps.r2_target.outputs.bucket }} source-dir: artifact-35/ - destination-dir: flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/windows-arm64-debug + destination-dir: ${{ steps.r2_target.outputs.prefix }}flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/windows-arm64-debug - name: Publish windows-arm64/flutter-cpp-client-wrapper.zip uses: ryand56/r2-upload-action@b801a390acbdeb034c5e684ff5e1361c06639e7c with: r2-account-id: ${{ secrets.R2_ACCOUNT_ID }} r2-access-key-id: ${{ secrets.R2_ACCESS_KEY_ID }} r2-secret-access-key: ${{ secrets.R2_SECRET_ACCESS_KEY }} - r2-bucket: ${{ env.R2_BUCKET }} + r2-bucket: ${{ steps.r2_target.outputs.bucket }} source-dir: artifact-36/ - destination-dir: flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/windows-arm64 + destination-dir: ${{ steps.r2_target.outputs.prefix }}flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/windows-arm64 - name: Publish windows-arm64-profile/windows-arm64-flutter.zip uses: ryand56/r2-upload-action@b801a390acbdeb034c5e684ff5e1361c06639e7c with: r2-account-id: ${{ secrets.R2_ACCOUNT_ID }} r2-access-key-id: ${{ secrets.R2_ACCESS_KEY_ID }} r2-secret-access-key: ${{ secrets.R2_SECRET_ACCESS_KEY }} - r2-bucket: ${{ env.R2_BUCKET }} + r2-bucket: ${{ steps.r2_target.outputs.bucket }} source-dir: artifact-37/ - destination-dir: flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/windows-arm64-profile + destination-dir: ${{ steps.r2_target.outputs.prefix }}flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/windows-arm64-profile - name: Publish windows-arm64-release/windows-arm64-flutter.zip uses: ryand56/r2-upload-action@b801a390acbdeb034c5e684ff5e1361c06639e7c with: r2-account-id: ${{ secrets.R2_ACCOUNT_ID }} r2-access-key-id: ${{ secrets.R2_ACCESS_KEY_ID }} r2-secret-access-key: ${{ secrets.R2_SECRET_ACCESS_KEY }} - r2-bucket: ${{ env.R2_BUCKET }} + r2-bucket: ${{ steps.r2_target.outputs.bucket }} source-dir: artifact-38/ - destination-dir: flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/windows-arm64-release + destination-dir: ${{ steps.r2_target.outputs.prefix }}flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/windows-arm64-release - name: Publish /dart-sdk-linux-x64.zip uses: ryand56/r2-upload-action@b801a390acbdeb034c5e684ff5e1361c06639e7c with: r2-account-id: ${{ secrets.R2_ACCOUNT_ID }} r2-access-key-id: ${{ secrets.R2_ACCESS_KEY_ID }} r2-secret-access-key: ${{ secrets.R2_SECRET_ACCESS_KEY }} - r2-bucket: ${{ env.R2_BUCKET }} + r2-bucket: ${{ steps.r2_target.outputs.bucket }} source-dir: artifact-39/ - destination-dir: flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/ + destination-dir: ${{ steps.r2_target.outputs.prefix }}flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/ - name: Publish /flutter_patched_sdk.zip uses: ryand56/r2-upload-action@b801a390acbdeb034c5e684ff5e1361c06639e7c with: r2-account-id: ${{ secrets.R2_ACCOUNT_ID }} r2-access-key-id: ${{ secrets.R2_ACCESS_KEY_ID }} r2-secret-access-key: ${{ secrets.R2_SECRET_ACCESS_KEY }} - r2-bucket: ${{ env.R2_BUCKET }} + r2-bucket: ${{ steps.r2_target.outputs.bucket }} source-dir: artifact-40/ - destination-dir: flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/ + destination-dir: ${{ steps.r2_target.outputs.prefix }}flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/ - name: Publish linux-x64/artifacts.zip uses: ryand56/r2-upload-action@b801a390acbdeb034c5e684ff5e1361c06639e7c with: r2-account-id: ${{ secrets.R2_ACCOUNT_ID }} r2-access-key-id: ${{ secrets.R2_ACCESS_KEY_ID }} r2-secret-access-key: ${{ secrets.R2_SECRET_ACCESS_KEY }} - r2-bucket: ${{ env.R2_BUCKET }} + r2-bucket: ${{ steps.r2_target.outputs.bucket }} source-dir: artifact-41/ - destination-dir: flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/linux-x64 + destination-dir: ${{ steps.r2_target.outputs.prefix }}flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/linux-x64 - name: Publish linux-x64/font-subset.zip uses: ryand56/r2-upload-action@b801a390acbdeb034c5e684ff5e1361c06639e7c with: r2-account-id: ${{ secrets.R2_ACCOUNT_ID }} r2-access-key-id: ${{ secrets.R2_ACCESS_KEY_ID }} r2-secret-access-key: ${{ secrets.R2_SECRET_ACCESS_KEY }} - r2-bucket: ${{ env.R2_BUCKET }} + r2-bucket: ${{ steps.r2_target.outputs.bucket }} source-dir: artifact-42/ - destination-dir: flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/linux-x64 + destination-dir: ${{ steps.r2_target.outputs.prefix }}flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/linux-x64 - name: Publish linux-x64/linux-x64-embedder.zip uses: ryand56/r2-upload-action@b801a390acbdeb034c5e684ff5e1361c06639e7c with: r2-account-id: ${{ secrets.R2_ACCOUNT_ID }} r2-access-key-id: ${{ secrets.R2_ACCESS_KEY_ID }} r2-secret-access-key: ${{ secrets.R2_SECRET_ACCESS_KEY }} - r2-bucket: ${{ env.R2_BUCKET }} + r2-bucket: ${{ steps.r2_target.outputs.bucket }} source-dir: artifact-43/ - destination-dir: flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/linux-x64 + destination-dir: ${{ steps.r2_target.outputs.prefix }}flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/linux-x64 - name: Publish /flutter_patched_sdk_product.zip uses: ryand56/r2-upload-action@b801a390acbdeb034c5e684ff5e1361c06639e7c with: r2-account-id: ${{ secrets.R2_ACCOUNT_ID }} r2-access-key-id: ${{ secrets.R2_ACCESS_KEY_ID }} r2-secret-access-key: ${{ secrets.R2_SECRET_ACCESS_KEY }} - r2-bucket: ${{ env.R2_BUCKET }} + r2-bucket: ${{ steps.r2_target.outputs.bucket }} source-dir: artifact-44/ - destination-dir: flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/ + destination-dir: ${{ steps.r2_target.outputs.prefix }}flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/ - name: Publish /ios-docs.zip uses: ryand56/r2-upload-action@b801a390acbdeb034c5e684ff5e1361c06639e7c with: r2-account-id: ${{ secrets.R2_ACCOUNT_ID }} r2-access-key-id: ${{ secrets.R2_ACCESS_KEY_ID }} r2-secret-access-key: ${{ secrets.R2_SECRET_ACCESS_KEY }} - r2-bucket: ${{ env.R2_BUCKET }} + r2-bucket: ${{ steps.r2_target.outputs.bucket }} source-dir: artifact-45/ - destination-dir: flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/ + destination-dir: ${{ steps.r2_target.outputs.prefix }}flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/ - name: Publish /macos-docs.zip uses: ryand56/r2-upload-action@b801a390acbdeb034c5e684ff5e1361c06639e7c with: r2-account-id: ${{ secrets.R2_ACCOUNT_ID }} r2-access-key-id: ${{ secrets.R2_ACCESS_KEY_ID }} r2-secret-access-key: ${{ secrets.R2_SECRET_ACCESS_KEY }} - r2-bucket: ${{ env.R2_BUCKET }} + r2-bucket: ${{ steps.r2_target.outputs.bucket }} source-dir: artifact-46/ - destination-dir: flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/ + destination-dir: ${{ steps.r2_target.outputs.prefix }}flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/ - name: Publish /linux-docs.zip uses: ryand56/r2-upload-action@b801a390acbdeb034c5e684ff5e1361c06639e7c with: r2-account-id: ${{ secrets.R2_ACCOUNT_ID }} r2-access-key-id: ${{ secrets.R2_ACCESS_KEY_ID }} r2-secret-access-key: ${{ secrets.R2_SECRET_ACCESS_KEY }} - r2-bucket: ${{ env.R2_BUCKET }} + r2-bucket: ${{ steps.r2_target.outputs.bucket }} source-dir: artifact-47/ - destination-dir: flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/ + destination-dir: ${{ steps.r2_target.outputs.prefix }}flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/ - name: Publish /windows-docs.zip uses: ryand56/r2-upload-action@b801a390acbdeb034c5e684ff5e1361c06639e7c with: r2-account-id: ${{ secrets.R2_ACCOUNT_ID }} r2-access-key-id: ${{ secrets.R2_ACCESS_KEY_ID }} r2-secret-access-key: ${{ secrets.R2_SECRET_ACCESS_KEY }} - r2-bucket: ${{ env.R2_BUCKET }} + r2-bucket: ${{ steps.r2_target.outputs.bucket }} source-dir: artifact-48/ - destination-dir: flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/ + destination-dir: ${{ steps.r2_target.outputs.prefix }}flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/ - name: Publish /impeller-docs.zip uses: ryand56/r2-upload-action@b801a390acbdeb034c5e684ff5e1361c06639e7c with: r2-account-id: ${{ secrets.R2_ACCOUNT_ID }} r2-access-key-id: ${{ secrets.R2_ACCESS_KEY_ID }} r2-secret-access-key: ${{ secrets.R2_SECRET_ACCESS_KEY }} - r2-bucket: ${{ env.R2_BUCKET }} + r2-bucket: ${{ steps.r2_target.outputs.bucket }} source-dir: artifact-49/ - destination-dir: flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/ + destination-dir: ${{ steps.r2_target.outputs.prefix }}flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/ - name: Publish /engine_stamp.json uses: ryand56/r2-upload-action@b801a390acbdeb034c5e684ff5e1361c06639e7c with: r2-account-id: ${{ secrets.R2_ACCOUNT_ID }} r2-access-key-id: ${{ secrets.R2_ACCESS_KEY_ID }} r2-secret-access-key: ${{ secrets.R2_SECRET_ACCESS_KEY }} - r2-bucket: ${{ env.R2_BUCKET }} + r2-bucket: ${{ steps.r2_target.outputs.bucket }} source-dir: artifact-50/ - destination-dir: flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/ + destination-dir: ${{ steps.r2_target.outputs.prefix }}flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/ - name: Publish linux-x64-debug/linux-x64-flutter-gtk.zip uses: ryand56/r2-upload-action@b801a390acbdeb034c5e684ff5e1361c06639e7c with: r2-account-id: ${{ secrets.R2_ACCOUNT_ID }} r2-access-key-id: ${{ secrets.R2_ACCESS_KEY_ID }} r2-secret-access-key: ${{ secrets.R2_SECRET_ACCESS_KEY }} - r2-bucket: ${{ env.R2_BUCKET }} + r2-bucket: ${{ steps.r2_target.outputs.bucket }} source-dir: artifact-51/ - destination-dir: flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/linux-x64-debug + destination-dir: ${{ steps.r2_target.outputs.prefix }}flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/linux-x64-debug - name: Publish linux-x64-profile/linux-x64-flutter-gtk.zip uses: ryand56/r2-upload-action@b801a390acbdeb034c5e684ff5e1361c06639e7c with: r2-account-id: ${{ secrets.R2_ACCOUNT_ID }} r2-access-key-id: ${{ secrets.R2_ACCESS_KEY_ID }} r2-secret-access-key: ${{ secrets.R2_SECRET_ACCESS_KEY }} - r2-bucket: ${{ env.R2_BUCKET }} + r2-bucket: ${{ steps.r2_target.outputs.bucket }} source-dir: artifact-52/ - destination-dir: flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/linux-x64-profile + destination-dir: ${{ steps.r2_target.outputs.prefix }}flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/linux-x64-profile - name: Publish linux-x64-release/linux-x64-flutter-gtk.zip uses: ryand56/r2-upload-action@b801a390acbdeb034c5e684ff5e1361c06639e7c with: r2-account-id: ${{ secrets.R2_ACCOUNT_ID }} r2-access-key-id: ${{ secrets.R2_ACCESS_KEY_ID }} r2-secret-access-key: ${{ secrets.R2_SECRET_ACCESS_KEY }} - r2-bucket: ${{ env.R2_BUCKET }} + r2-bucket: ${{ steps.r2_target.outputs.bucket }} source-dir: artifact-53/ - destination-dir: flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/linux-x64-release + destination-dir: ${{ steps.r2_target.outputs.prefix }}flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/linux-x64-release - name: Publish linux-arm64-profile/linux-arm64-flutter-gtk.zip uses: ryand56/r2-upload-action@b801a390acbdeb034c5e684ff5e1361c06639e7c with: r2-account-id: ${{ secrets.R2_ACCOUNT_ID }} r2-access-key-id: ${{ secrets.R2_ACCESS_KEY_ID }} r2-secret-access-key: ${{ secrets.R2_SECRET_ACCESS_KEY }} - r2-bucket: ${{ env.R2_BUCKET }} + r2-bucket: ${{ steps.r2_target.outputs.bucket }} source-dir: artifact-54/ - destination-dir: flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/linux-arm64-profile + destination-dir: ${{ steps.r2_target.outputs.prefix }}flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/linux-arm64-profile - name: Publish linux-arm64/artifacts.zip uses: ryand56/r2-upload-action@b801a390acbdeb034c5e684ff5e1361c06639e7c with: r2-account-id: ${{ secrets.R2_ACCOUNT_ID }} r2-access-key-id: ${{ secrets.R2_ACCESS_KEY_ID }} r2-secret-access-key: ${{ secrets.R2_SECRET_ACCESS_KEY }} - r2-bucket: ${{ env.R2_BUCKET }} + r2-bucket: ${{ steps.r2_target.outputs.bucket }} source-dir: artifact-55/ - destination-dir: flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/linux-arm64 + destination-dir: ${{ steps.r2_target.outputs.prefix }}flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/linux-arm64 - name: Publish linux-arm64/linux-arm64-embedder.zip uses: ryand56/r2-upload-action@b801a390acbdeb034c5e684ff5e1361c06639e7c with: r2-account-id: ${{ secrets.R2_ACCOUNT_ID }} r2-access-key-id: ${{ secrets.R2_ACCESS_KEY_ID }} r2-secret-access-key: ${{ secrets.R2_SECRET_ACCESS_KEY }} - r2-bucket: ${{ env.R2_BUCKET }} + r2-bucket: ${{ steps.r2_target.outputs.bucket }} source-dir: artifact-56/ - destination-dir: flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/linux-arm64 + destination-dir: ${{ steps.r2_target.outputs.prefix }}flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/linux-arm64 - name: Publish linux-arm64/font-subset.zip uses: ryand56/r2-upload-action@b801a390acbdeb034c5e684ff5e1361c06639e7c with: r2-account-id: ${{ secrets.R2_ACCOUNT_ID }} r2-access-key-id: ${{ secrets.R2_ACCESS_KEY_ID }} r2-secret-access-key: ${{ secrets.R2_SECRET_ACCESS_KEY }} - r2-bucket: ${{ env.R2_BUCKET }} + r2-bucket: ${{ steps.r2_target.outputs.bucket }} source-dir: artifact-57/ - destination-dir: flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/linux-arm64 + destination-dir: ${{ steps.r2_target.outputs.prefix }}flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/linux-arm64 - name: Publish linux-arm64-debug/linux-arm64-flutter-gtk.zip uses: ryand56/r2-upload-action@b801a390acbdeb034c5e684ff5e1361c06639e7c with: r2-account-id: ${{ secrets.R2_ACCOUNT_ID }} r2-access-key-id: ${{ secrets.R2_ACCESS_KEY_ID }} r2-secret-access-key: ${{ secrets.R2_SECRET_ACCESS_KEY }} - r2-bucket: ${{ env.R2_BUCKET }} + r2-bucket: ${{ steps.r2_target.outputs.bucket }} source-dir: artifact-58/ - destination-dir: flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/linux-arm64-debug + destination-dir: ${{ steps.r2_target.outputs.prefix }}flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/linux-arm64-debug - name: Publish /dart-sdk-linux-arm64.zip uses: ryand56/r2-upload-action@b801a390acbdeb034c5e684ff5e1361c06639e7c with: r2-account-id: ${{ secrets.R2_ACCOUNT_ID }} r2-access-key-id: ${{ secrets.R2_ACCESS_KEY_ID }} r2-secret-access-key: ${{ secrets.R2_SECRET_ACCESS_KEY }} - r2-bucket: ${{ env.R2_BUCKET }} + r2-bucket: ${{ steps.r2_target.outputs.bucket }} source-dir: artifact-59/ - destination-dir: flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/ + destination-dir: ${{ steps.r2_target.outputs.prefix }}flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/ - name: Publish linux-arm64-release/linux-arm64-flutter-gtk.zip uses: ryand56/r2-upload-action@b801a390acbdeb034c5e684ff5e1361c06639e7c with: r2-account-id: ${{ secrets.R2_ACCOUNT_ID }} r2-access-key-id: ${{ secrets.R2_ACCESS_KEY_ID }} r2-secret-access-key: ${{ secrets.R2_SECRET_ACCESS_KEY }} - r2-bucket: ${{ env.R2_BUCKET }} + r2-bucket: ${{ steps.r2_target.outputs.bucket }} source-dir: artifact-60/ - destination-dir: flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/linux-arm64-release + destination-dir: ${{ steps.r2_target.outputs.prefix }}flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/linux-arm64-release - name: Publish android-arm-profile/windows-x64.zip uses: ryand56/r2-upload-action@b801a390acbdeb034c5e684ff5e1361c06639e7c with: r2-account-id: ${{ secrets.R2_ACCOUNT_ID }} r2-access-key-id: ${{ secrets.R2_ACCESS_KEY_ID }} r2-secret-access-key: ${{ secrets.R2_SECRET_ACCESS_KEY }} - r2-bucket: ${{ env.R2_BUCKET }} + r2-bucket: ${{ steps.r2_target.outputs.bucket }} source-dir: artifact-61/ - destination-dir: flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/android-arm-profile + destination-dir: ${{ steps.r2_target.outputs.prefix }}flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/android-arm-profile - name: Publish android-arm64-profile/windows-x64.zip uses: ryand56/r2-upload-action@b801a390acbdeb034c5e684ff5e1361c06639e7c with: r2-account-id: ${{ secrets.R2_ACCOUNT_ID }} r2-access-key-id: ${{ secrets.R2_ACCESS_KEY_ID }} r2-secret-access-key: ${{ secrets.R2_SECRET_ACCESS_KEY }} - r2-bucket: ${{ env.R2_BUCKET }} + r2-bucket: ${{ steps.r2_target.outputs.bucket }} source-dir: artifact-62/ - destination-dir: flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/android-arm64-profile + destination-dir: ${{ steps.r2_target.outputs.prefix }}flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/android-arm64-profile - name: Publish android-x64-profile/windows-x64.zip uses: ryand56/r2-upload-action@b801a390acbdeb034c5e684ff5e1361c06639e7c with: r2-account-id: ${{ secrets.R2_ACCOUNT_ID }} r2-access-key-id: ${{ secrets.R2_ACCESS_KEY_ID }} r2-secret-access-key: ${{ secrets.R2_SECRET_ACCESS_KEY }} - r2-bucket: ${{ env.R2_BUCKET }} + r2-bucket: ${{ steps.r2_target.outputs.bucket }} source-dir: artifact-63/ - destination-dir: flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/android-x64-profile + destination-dir: ${{ steps.r2_target.outputs.prefix }}flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/android-x64-profile - name: Publish android-arm-release/windows-x64.zip uses: ryand56/r2-upload-action@b801a390acbdeb034c5e684ff5e1361c06639e7c with: r2-account-id: ${{ secrets.R2_ACCOUNT_ID }} r2-access-key-id: ${{ secrets.R2_ACCESS_KEY_ID }} r2-secret-access-key: ${{ secrets.R2_SECRET_ACCESS_KEY }} - r2-bucket: ${{ env.R2_BUCKET }} + r2-bucket: ${{ steps.r2_target.outputs.bucket }} source-dir: artifact-64/ - destination-dir: flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/android-arm-release + destination-dir: ${{ steps.r2_target.outputs.prefix }}flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/android-arm-release - name: Publish android-arm64-release/windows-x64.zip uses: ryand56/r2-upload-action@b801a390acbdeb034c5e684ff5e1361c06639e7c with: r2-account-id: ${{ secrets.R2_ACCOUNT_ID }} r2-access-key-id: ${{ secrets.R2_ACCESS_KEY_ID }} r2-secret-access-key: ${{ secrets.R2_SECRET_ACCESS_KEY }} - r2-bucket: ${{ env.R2_BUCKET }} + r2-bucket: ${{ steps.r2_target.outputs.bucket }} source-dir: artifact-65/ - destination-dir: flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/android-arm64-release + destination-dir: ${{ steps.r2_target.outputs.prefix }}flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/android-arm64-release - name: Publish android-x64-release/windows-x64.zip uses: ryand56/r2-upload-action@b801a390acbdeb034c5e684ff5e1361c06639e7c with: r2-account-id: ${{ secrets.R2_ACCOUNT_ID }} r2-access-key-id: ${{ secrets.R2_ACCESS_KEY_ID }} r2-secret-access-key: ${{ secrets.R2_SECRET_ACCESS_KEY }} - r2-bucket: ${{ env.R2_BUCKET }} + r2-bucket: ${{ steps.r2_target.outputs.bucket }} source-dir: artifact-66/ - destination-dir: flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/android-x64-release + destination-dir: ${{ steps.r2_target.outputs.prefix }}flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/android-x64-release - name: Publish android-arm-profile/darwin-x64.zip uses: ryand56/r2-upload-action@b801a390acbdeb034c5e684ff5e1361c06639e7c with: r2-account-id: ${{ secrets.R2_ACCOUNT_ID }} r2-access-key-id: ${{ secrets.R2_ACCESS_KEY_ID }} r2-secret-access-key: ${{ secrets.R2_SECRET_ACCESS_KEY }} - r2-bucket: ${{ env.R2_BUCKET }} + r2-bucket: ${{ steps.r2_target.outputs.bucket }} source-dir: artifact-67/ - destination-dir: flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/android-arm-profile + destination-dir: ${{ steps.r2_target.outputs.prefix }}flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/android-arm-profile - name: Publish android-arm64-profile/darwin-x64.zip uses: ryand56/r2-upload-action@b801a390acbdeb034c5e684ff5e1361c06639e7c with: r2-account-id: ${{ secrets.R2_ACCOUNT_ID }} r2-access-key-id: ${{ secrets.R2_ACCESS_KEY_ID }} r2-secret-access-key: ${{ secrets.R2_SECRET_ACCESS_KEY }} - r2-bucket: ${{ env.R2_BUCKET }} + r2-bucket: ${{ steps.r2_target.outputs.bucket }} source-dir: artifact-68/ - destination-dir: flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/android-arm64-profile + destination-dir: ${{ steps.r2_target.outputs.prefix }}flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/android-arm64-profile - name: Publish android-x64-profile/darwin-x64.zip uses: ryand56/r2-upload-action@b801a390acbdeb034c5e684ff5e1361c06639e7c with: r2-account-id: ${{ secrets.R2_ACCOUNT_ID }} r2-access-key-id: ${{ secrets.R2_ACCESS_KEY_ID }} r2-secret-access-key: ${{ secrets.R2_SECRET_ACCESS_KEY }} - r2-bucket: ${{ env.R2_BUCKET }} + r2-bucket: ${{ steps.r2_target.outputs.bucket }} source-dir: artifact-69/ - destination-dir: flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/android-x64-profile + destination-dir: ${{ steps.r2_target.outputs.prefix }}flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/android-x64-profile - name: Publish android-arm-release/darwin-x64.zip uses: ryand56/r2-upload-action@b801a390acbdeb034c5e684ff5e1361c06639e7c with: r2-account-id: ${{ secrets.R2_ACCOUNT_ID }} r2-access-key-id: ${{ secrets.R2_ACCESS_KEY_ID }} r2-secret-access-key: ${{ secrets.R2_SECRET_ACCESS_KEY }} - r2-bucket: ${{ env.R2_BUCKET }} + r2-bucket: ${{ steps.r2_target.outputs.bucket }} source-dir: artifact-70/ - destination-dir: flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/android-arm-release + destination-dir: ${{ steps.r2_target.outputs.prefix }}flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/android-arm-release - name: Publish android-arm64-release/darwin-x64.zip uses: ryand56/r2-upload-action@b801a390acbdeb034c5e684ff5e1361c06639e7c with: r2-account-id: ${{ secrets.R2_ACCOUNT_ID }} r2-access-key-id: ${{ secrets.R2_ACCESS_KEY_ID }} r2-secret-access-key: ${{ secrets.R2_SECRET_ACCESS_KEY }} - r2-bucket: ${{ env.R2_BUCKET }} + r2-bucket: ${{ steps.r2_target.outputs.bucket }} source-dir: artifact-71/ - destination-dir: flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/android-arm64-release + destination-dir: ${{ steps.r2_target.outputs.prefix }}flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/android-arm64-release - name: Publish android-x64-release/darwin-x64.zip uses: ryand56/r2-upload-action@b801a390acbdeb034c5e684ff5e1361c06639e7c with: r2-account-id: ${{ secrets.R2_ACCOUNT_ID }} r2-access-key-id: ${{ secrets.R2_ACCESS_KEY_ID }} r2-secret-access-key: ${{ secrets.R2_SECRET_ACCESS_KEY }} - r2-bucket: ${{ env.R2_BUCKET }} + r2-bucket: ${{ steps.r2_target.outputs.bucket }} source-dir: artifact-72/ - destination-dir: flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/android-x64-release + destination-dir: ${{ steps.r2_target.outputs.prefix }}flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/android-x64-release - name: Publish android-arm-profile/artifacts.zip uses: ryand56/r2-upload-action@b801a390acbdeb034c5e684ff5e1361c06639e7c with: r2-account-id: ${{ secrets.R2_ACCOUNT_ID }} r2-access-key-id: ${{ secrets.R2_ACCESS_KEY_ID }} r2-secret-access-key: ${{ secrets.R2_SECRET_ACCESS_KEY }} - r2-bucket: ${{ env.R2_BUCKET }} + r2-bucket: ${{ steps.r2_target.outputs.bucket }} source-dir: artifact-73/ - destination-dir: flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/android-arm-profile + destination-dir: ${{ steps.r2_target.outputs.prefix }}flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/android-arm-profile - name: Publish android-arm-profile/linux-x64.zip uses: ryand56/r2-upload-action@b801a390acbdeb034c5e684ff5e1361c06639e7c with: r2-account-id: ${{ secrets.R2_ACCOUNT_ID }} r2-access-key-id: ${{ secrets.R2_ACCESS_KEY_ID }} r2-secret-access-key: ${{ secrets.R2_SECRET_ACCESS_KEY }} - r2-bucket: ${{ env.R2_BUCKET }} + r2-bucket: ${{ steps.r2_target.outputs.bucket }} source-dir: artifact-74/ - destination-dir: flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/android-arm-profile + destination-dir: ${{ steps.r2_target.outputs.prefix }}flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/android-arm-profile - name: Publish android-arm-profile/symbols.zip uses: ryand56/r2-upload-action@b801a390acbdeb034c5e684ff5e1361c06639e7c with: r2-account-id: ${{ secrets.R2_ACCOUNT_ID }} r2-access-key-id: ${{ secrets.R2_ACCESS_KEY_ID }} r2-secret-access-key: ${{ secrets.R2_SECRET_ACCESS_KEY }} - r2-bucket: ${{ env.R2_BUCKET }} + r2-bucket: ${{ steps.r2_target.outputs.bucket }} source-dir: artifact-75/ - destination-dir: flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/android-arm-profile + destination-dir: ${{ steps.r2_target.outputs.prefix }}flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/android-arm-profile - name: Publish /download.flutter.io uses: ryand56/r2-upload-action@b801a390acbdeb034c5e684ff5e1361c06639e7c with: r2-account-id: ${{ secrets.R2_ACCOUNT_ID }} r2-access-key-id: ${{ secrets.R2_ACCESS_KEY_ID }} r2-secret-access-key: ${{ secrets.R2_SECRET_ACCESS_KEY }} - r2-bucket: ${{ env.R2_BUCKET }} + r2-bucket: ${{ steps.r2_target.outputs.bucket }} source-dir: artifact-76/ - destination-dir: ./ + destination-dir: ${{ steps.r2_target.outputs.prefix }} - name: Publish android-arm-release/artifacts.zip uses: ryand56/r2-upload-action@b801a390acbdeb034c5e684ff5e1361c06639e7c with: r2-account-id: ${{ secrets.R2_ACCOUNT_ID }} r2-access-key-id: ${{ secrets.R2_ACCESS_KEY_ID }} r2-secret-access-key: ${{ secrets.R2_SECRET_ACCESS_KEY }} - r2-bucket: ${{ env.R2_BUCKET }} + r2-bucket: ${{ steps.r2_target.outputs.bucket }} source-dir: artifact-77/ - destination-dir: flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/android-arm-release + destination-dir: ${{ steps.r2_target.outputs.prefix }}flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/android-arm-release - name: Publish android-arm-release/linux-x64.zip uses: ryand56/r2-upload-action@b801a390acbdeb034c5e684ff5e1361c06639e7c with: r2-account-id: ${{ secrets.R2_ACCOUNT_ID }} r2-access-key-id: ${{ secrets.R2_ACCESS_KEY_ID }} r2-secret-access-key: ${{ secrets.R2_SECRET_ACCESS_KEY }} - r2-bucket: ${{ env.R2_BUCKET }} + r2-bucket: ${{ steps.r2_target.outputs.bucket }} source-dir: artifact-78/ - destination-dir: flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/android-arm-release + destination-dir: ${{ steps.r2_target.outputs.prefix }}flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/android-arm-release - name: Publish android-arm-release/symbols.zip uses: ryand56/r2-upload-action@b801a390acbdeb034c5e684ff5e1361c06639e7c with: r2-account-id: ${{ secrets.R2_ACCOUNT_ID }} r2-access-key-id: ${{ secrets.R2_ACCESS_KEY_ID }} r2-secret-access-key: ${{ secrets.R2_SECRET_ACCESS_KEY }} - r2-bucket: ${{ env.R2_BUCKET }} + r2-bucket: ${{ steps.r2_target.outputs.bucket }} source-dir: artifact-79/ - destination-dir: flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/android-arm-release + destination-dir: ${{ steps.r2_target.outputs.prefix }}flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/android-arm-release - name: Publish /download.flutter.io uses: ryand56/r2-upload-action@b801a390acbdeb034c5e684ff5e1361c06639e7c with: r2-account-id: ${{ secrets.R2_ACCOUNT_ID }} r2-access-key-id: ${{ secrets.R2_ACCESS_KEY_ID }} r2-secret-access-key: ${{ secrets.R2_SECRET_ACCESS_KEY }} - r2-bucket: ${{ env.R2_BUCKET }} + r2-bucket: ${{ steps.r2_target.outputs.bucket }} source-dir: artifact-80/ - destination-dir: ./ + destination-dir: ${{ steps.r2_target.outputs.prefix }} - name: Publish android-arm64-release/artifacts.zip uses: ryand56/r2-upload-action@b801a390acbdeb034c5e684ff5e1361c06639e7c with: r2-account-id: ${{ secrets.R2_ACCOUNT_ID }} r2-access-key-id: ${{ secrets.R2_ACCESS_KEY_ID }} r2-secret-access-key: ${{ secrets.R2_SECRET_ACCESS_KEY }} - r2-bucket: ${{ env.R2_BUCKET }} + r2-bucket: ${{ steps.r2_target.outputs.bucket }} source-dir: artifact-81/ - destination-dir: flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/android-arm64-release + destination-dir: ${{ steps.r2_target.outputs.prefix }}flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/android-arm64-release - name: Publish android-arm64-release/linux-x64.zip uses: ryand56/r2-upload-action@b801a390acbdeb034c5e684ff5e1361c06639e7c with: r2-account-id: ${{ secrets.R2_ACCOUNT_ID }} r2-access-key-id: ${{ secrets.R2_ACCESS_KEY_ID }} r2-secret-access-key: ${{ secrets.R2_SECRET_ACCESS_KEY }} - r2-bucket: ${{ env.R2_BUCKET }} + r2-bucket: ${{ steps.r2_target.outputs.bucket }} source-dir: artifact-82/ - destination-dir: flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/android-arm64-release + destination-dir: ${{ steps.r2_target.outputs.prefix }}flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/android-arm64-release - name: Publish android-arm64-release/symbols.zip uses: ryand56/r2-upload-action@b801a390acbdeb034c5e684ff5e1361c06639e7c with: r2-account-id: ${{ secrets.R2_ACCOUNT_ID }} r2-access-key-id: ${{ secrets.R2_ACCESS_KEY_ID }} r2-secret-access-key: ${{ secrets.R2_SECRET_ACCESS_KEY }} - r2-bucket: ${{ env.R2_BUCKET }} + r2-bucket: ${{ steps.r2_target.outputs.bucket }} source-dir: artifact-83/ - destination-dir: flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/android-arm64-release + destination-dir: ${{ steps.r2_target.outputs.prefix }}flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/android-arm64-release - name: Publish android-arm64-release/analyze-snapshot-linux-x64.zip uses: ryand56/r2-upload-action@b801a390acbdeb034c5e684ff5e1361c06639e7c with: r2-account-id: ${{ secrets.R2_ACCOUNT_ID }} r2-access-key-id: ${{ secrets.R2_ACCESS_KEY_ID }} r2-secret-access-key: ${{ secrets.R2_SECRET_ACCESS_KEY }} - r2-bucket: ${{ env.R2_BUCKET }} + r2-bucket: ${{ steps.r2_target.outputs.bucket }} source-dir: artifact-84/ - destination-dir: flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/android-arm64-release + destination-dir: ${{ steps.r2_target.outputs.prefix }}flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/android-arm64-release - name: Publish /download.flutter.io uses: ryand56/r2-upload-action@b801a390acbdeb034c5e684ff5e1361c06639e7c with: r2-account-id: ${{ secrets.R2_ACCOUNT_ID }} r2-access-key-id: ${{ secrets.R2_ACCESS_KEY_ID }} r2-secret-access-key: ${{ secrets.R2_SECRET_ACCESS_KEY }} - r2-bucket: ${{ env.R2_BUCKET }} + r2-bucket: ${{ steps.r2_target.outputs.bucket }} source-dir: artifact-85/ - destination-dir: ./ + destination-dir: ${{ steps.r2_target.outputs.prefix }} - name: Publish android-arm64-profile/artifacts.zip uses: ryand56/r2-upload-action@b801a390acbdeb034c5e684ff5e1361c06639e7c with: r2-account-id: ${{ secrets.R2_ACCOUNT_ID }} r2-access-key-id: ${{ secrets.R2_ACCESS_KEY_ID }} r2-secret-access-key: ${{ secrets.R2_SECRET_ACCESS_KEY }} - r2-bucket: ${{ env.R2_BUCKET }} + r2-bucket: ${{ steps.r2_target.outputs.bucket }} source-dir: artifact-86/ - destination-dir: flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/android-arm64-profile + destination-dir: ${{ steps.r2_target.outputs.prefix }}flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/android-arm64-profile - name: Publish android-arm64-profile/linux-x64.zip uses: ryand56/r2-upload-action@b801a390acbdeb034c5e684ff5e1361c06639e7c with: r2-account-id: ${{ secrets.R2_ACCOUNT_ID }} r2-access-key-id: ${{ secrets.R2_ACCESS_KEY_ID }} r2-secret-access-key: ${{ secrets.R2_SECRET_ACCESS_KEY }} - r2-bucket: ${{ env.R2_BUCKET }} + r2-bucket: ${{ steps.r2_target.outputs.bucket }} source-dir: artifact-87/ - destination-dir: flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/android-arm64-profile + destination-dir: ${{ steps.r2_target.outputs.prefix }}flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/android-arm64-profile - name: Publish android-arm64-profile/symbols.zip uses: ryand56/r2-upload-action@b801a390acbdeb034c5e684ff5e1361c06639e7c with: r2-account-id: ${{ secrets.R2_ACCOUNT_ID }} r2-access-key-id: ${{ secrets.R2_ACCESS_KEY_ID }} r2-secret-access-key: ${{ secrets.R2_SECRET_ACCESS_KEY }} - r2-bucket: ${{ env.R2_BUCKET }} + r2-bucket: ${{ steps.r2_target.outputs.bucket }} source-dir: artifact-88/ - destination-dir: flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/android-arm64-profile + destination-dir: ${{ steps.r2_target.outputs.prefix }}flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/android-arm64-profile - name: Publish android-arm64-profile/analyze-snapshot-linux-x64.zip uses: ryand56/r2-upload-action@b801a390acbdeb034c5e684ff5e1361c06639e7c with: r2-account-id: ${{ secrets.R2_ACCOUNT_ID }} r2-access-key-id: ${{ secrets.R2_ACCESS_KEY_ID }} r2-secret-access-key: ${{ secrets.R2_SECRET_ACCESS_KEY }} - r2-bucket: ${{ env.R2_BUCKET }} + r2-bucket: ${{ steps.r2_target.outputs.bucket }} source-dir: artifact-89/ - destination-dir: flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/android-arm64-profile + destination-dir: ${{ steps.r2_target.outputs.prefix }}flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/android-arm64-profile - name: Publish /download.flutter.io uses: ryand56/r2-upload-action@b801a390acbdeb034c5e684ff5e1361c06639e7c with: r2-account-id: ${{ secrets.R2_ACCOUNT_ID }} r2-access-key-id: ${{ secrets.R2_ACCESS_KEY_ID }} r2-secret-access-key: ${{ secrets.R2_SECRET_ACCESS_KEY }} - r2-bucket: ${{ env.R2_BUCKET }} + r2-bucket: ${{ steps.r2_target.outputs.bucket }} source-dir: artifact-90/ - destination-dir: ./ + destination-dir: ${{ steps.r2_target.outputs.prefix }} - name: Publish android-x64-profile/artifacts.zip uses: ryand56/r2-upload-action@b801a390acbdeb034c5e684ff5e1361c06639e7c with: r2-account-id: ${{ secrets.R2_ACCOUNT_ID }} r2-access-key-id: ${{ secrets.R2_ACCESS_KEY_ID }} r2-secret-access-key: ${{ secrets.R2_SECRET_ACCESS_KEY }} - r2-bucket: ${{ env.R2_BUCKET }} + r2-bucket: ${{ steps.r2_target.outputs.bucket }} source-dir: artifact-91/ - destination-dir: flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/android-x64-profile + destination-dir: ${{ steps.r2_target.outputs.prefix }}flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/android-x64-profile - name: Publish android-x64-profile/linux-x64.zip uses: ryand56/r2-upload-action@b801a390acbdeb034c5e684ff5e1361c06639e7c with: r2-account-id: ${{ secrets.R2_ACCOUNT_ID }} r2-access-key-id: ${{ secrets.R2_ACCESS_KEY_ID }} r2-secret-access-key: ${{ secrets.R2_SECRET_ACCESS_KEY }} - r2-bucket: ${{ env.R2_BUCKET }} + r2-bucket: ${{ steps.r2_target.outputs.bucket }} source-dir: artifact-92/ - destination-dir: flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/android-x64-profile + destination-dir: ${{ steps.r2_target.outputs.prefix }}flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/android-x64-profile - name: Publish android-x64-profile/symbols.zip uses: ryand56/r2-upload-action@b801a390acbdeb034c5e684ff5e1361c06639e7c with: r2-account-id: ${{ secrets.R2_ACCOUNT_ID }} r2-access-key-id: ${{ secrets.R2_ACCESS_KEY_ID }} r2-secret-access-key: ${{ secrets.R2_SECRET_ACCESS_KEY }} - r2-bucket: ${{ env.R2_BUCKET }} + r2-bucket: ${{ steps.r2_target.outputs.bucket }} source-dir: artifact-93/ - destination-dir: flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/android-x64-profile + destination-dir: ${{ steps.r2_target.outputs.prefix }}flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/android-x64-profile - name: Publish android-x64-profile/analyze-snapshot-linux-x64.zip uses: ryand56/r2-upload-action@b801a390acbdeb034c5e684ff5e1361c06639e7c with: r2-account-id: ${{ secrets.R2_ACCOUNT_ID }} r2-access-key-id: ${{ secrets.R2_ACCESS_KEY_ID }} r2-secret-access-key: ${{ secrets.R2_SECRET_ACCESS_KEY }} - r2-bucket: ${{ env.R2_BUCKET }} + r2-bucket: ${{ steps.r2_target.outputs.bucket }} source-dir: artifact-94/ - destination-dir: flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/android-x64-profile + destination-dir: ${{ steps.r2_target.outputs.prefix }}flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/android-x64-profile - name: Publish /download.flutter.io uses: ryand56/r2-upload-action@b801a390acbdeb034c5e684ff5e1361c06639e7c with: r2-account-id: ${{ secrets.R2_ACCOUNT_ID }} r2-access-key-id: ${{ secrets.R2_ACCESS_KEY_ID }} r2-secret-access-key: ${{ secrets.R2_SECRET_ACCESS_KEY }} - r2-bucket: ${{ env.R2_BUCKET }} + r2-bucket: ${{ steps.r2_target.outputs.bucket }} source-dir: artifact-95/ - destination-dir: ./ + destination-dir: ${{ steps.r2_target.outputs.prefix }} - name: Publish android-x64-release/artifacts.zip uses: ryand56/r2-upload-action@b801a390acbdeb034c5e684ff5e1361c06639e7c with: r2-account-id: ${{ secrets.R2_ACCOUNT_ID }} r2-access-key-id: ${{ secrets.R2_ACCESS_KEY_ID }} r2-secret-access-key: ${{ secrets.R2_SECRET_ACCESS_KEY }} - r2-bucket: ${{ env.R2_BUCKET }} + r2-bucket: ${{ steps.r2_target.outputs.bucket }} source-dir: artifact-96/ - destination-dir: flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/android-x64-release + destination-dir: ${{ steps.r2_target.outputs.prefix }}flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/android-x64-release - name: Publish android-x64-release/linux-x64.zip uses: ryand56/r2-upload-action@b801a390acbdeb034c5e684ff5e1361c06639e7c with: r2-account-id: ${{ secrets.R2_ACCOUNT_ID }} r2-access-key-id: ${{ secrets.R2_ACCESS_KEY_ID }} r2-secret-access-key: ${{ secrets.R2_SECRET_ACCESS_KEY }} - r2-bucket: ${{ env.R2_BUCKET }} + r2-bucket: ${{ steps.r2_target.outputs.bucket }} source-dir: artifact-97/ - destination-dir: flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/android-x64-release + destination-dir: ${{ steps.r2_target.outputs.prefix }}flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/android-x64-release - name: Publish android-x64-release/symbols.zip uses: ryand56/r2-upload-action@b801a390acbdeb034c5e684ff5e1361c06639e7c with: r2-account-id: ${{ secrets.R2_ACCOUNT_ID }} r2-access-key-id: ${{ secrets.R2_ACCESS_KEY_ID }} r2-secret-access-key: ${{ secrets.R2_SECRET_ACCESS_KEY }} - r2-bucket: ${{ env.R2_BUCKET }} + r2-bucket: ${{ steps.r2_target.outputs.bucket }} source-dir: artifact-98/ - destination-dir: flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/android-x64-release + destination-dir: ${{ steps.r2_target.outputs.prefix }}flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/android-x64-release - name: Publish android-x64-release/analyze-snapshot-linux-x64.zip uses: ryand56/r2-upload-action@b801a390acbdeb034c5e684ff5e1361c06639e7c with: r2-account-id: ${{ secrets.R2_ACCOUNT_ID }} r2-access-key-id: ${{ secrets.R2_ACCESS_KEY_ID }} r2-secret-access-key: ${{ secrets.R2_SECRET_ACCESS_KEY }} - r2-bucket: ${{ env.R2_BUCKET }} + r2-bucket: ${{ steps.r2_target.outputs.bucket }} source-dir: artifact-99/ - destination-dir: flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/android-x64-release + destination-dir: ${{ steps.r2_target.outputs.prefix }}flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/android-x64-release - name: Publish /download.flutter.io uses: ryand56/r2-upload-action@b801a390acbdeb034c5e684ff5e1361c06639e7c with: r2-account-id: ${{ secrets.R2_ACCOUNT_ID }} r2-access-key-id: ${{ secrets.R2_ACCESS_KEY_ID }} r2-secret-access-key: ${{ secrets.R2_SECRET_ACCESS_KEY }} - r2-bucket: ${{ env.R2_BUCKET }} + r2-bucket: ${{ steps.r2_target.outputs.bucket }} source-dir: artifact-100/ - destination-dir: ./ + destination-dir: ${{ steps.r2_target.outputs.prefix }} - name: Publish android-riscv64-profile/artifacts.zip uses: ryand56/r2-upload-action@b801a390acbdeb034c5e684ff5e1361c06639e7c with: r2-account-id: ${{ secrets.R2_ACCOUNT_ID }} r2-access-key-id: ${{ secrets.R2_ACCESS_KEY_ID }} r2-secret-access-key: ${{ secrets.R2_SECRET_ACCESS_KEY }} - r2-bucket: ${{ env.R2_BUCKET }} + r2-bucket: ${{ steps.r2_target.outputs.bucket }} source-dir: artifact-101/ - destination-dir: flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/android-riscv64-profile + destination-dir: ${{ steps.r2_target.outputs.prefix }}flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/android-riscv64-profile - name: Publish android-riscv64-profile/linux-x64.zip uses: ryand56/r2-upload-action@b801a390acbdeb034c5e684ff5e1361c06639e7c with: r2-account-id: ${{ secrets.R2_ACCOUNT_ID }} r2-access-key-id: ${{ secrets.R2_ACCESS_KEY_ID }} r2-secret-access-key: ${{ secrets.R2_SECRET_ACCESS_KEY }} - r2-bucket: ${{ env.R2_BUCKET }} + r2-bucket: ${{ steps.r2_target.outputs.bucket }} source-dir: artifact-102/ - destination-dir: flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/android-riscv64-profile + destination-dir: ${{ steps.r2_target.outputs.prefix }}flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/android-riscv64-profile - name: Publish android-riscv64-profile/symbols.zip uses: ryand56/r2-upload-action@b801a390acbdeb034c5e684ff5e1361c06639e7c with: r2-account-id: ${{ secrets.R2_ACCOUNT_ID }} r2-access-key-id: ${{ secrets.R2_ACCESS_KEY_ID }} r2-secret-access-key: ${{ secrets.R2_SECRET_ACCESS_KEY }} - r2-bucket: ${{ env.R2_BUCKET }} + r2-bucket: ${{ steps.r2_target.outputs.bucket }} source-dir: artifact-103/ - destination-dir: flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/android-riscv64-profile + destination-dir: ${{ steps.r2_target.outputs.prefix }}flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/android-riscv64-profile - name: Publish android-riscv64-profile/analyze-snapshot-linux-x64.zip uses: ryand56/r2-upload-action@b801a390acbdeb034c5e684ff5e1361c06639e7c with: r2-account-id: ${{ secrets.R2_ACCOUNT_ID }} r2-access-key-id: ${{ secrets.R2_ACCESS_KEY_ID }} r2-secret-access-key: ${{ secrets.R2_SECRET_ACCESS_KEY }} - r2-bucket: ${{ env.R2_BUCKET }} + r2-bucket: ${{ steps.r2_target.outputs.bucket }} source-dir: artifact-104/ - destination-dir: flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/android-riscv64-profile + destination-dir: ${{ steps.r2_target.outputs.prefix }}flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/android-riscv64-profile - name: Publish /download.flutter.io uses: ryand56/r2-upload-action@b801a390acbdeb034c5e684ff5e1361c06639e7c with: r2-account-id: ${{ secrets.R2_ACCOUNT_ID }} r2-access-key-id: ${{ secrets.R2_ACCESS_KEY_ID }} r2-secret-access-key: ${{ secrets.R2_SECRET_ACCESS_KEY }} - r2-bucket: ${{ env.R2_BUCKET }} + r2-bucket: ${{ steps.r2_target.outputs.bucket }} source-dir: artifact-105/ - destination-dir: ./ + destination-dir: ${{ steps.r2_target.outputs.prefix }} - name: Publish android-riscv64-release/artifacts.zip uses: ryand56/r2-upload-action@b801a390acbdeb034c5e684ff5e1361c06639e7c with: r2-account-id: ${{ secrets.R2_ACCOUNT_ID }} r2-access-key-id: ${{ secrets.R2_ACCESS_KEY_ID }} r2-secret-access-key: ${{ secrets.R2_SECRET_ACCESS_KEY }} - r2-bucket: ${{ env.R2_BUCKET }} + r2-bucket: ${{ steps.r2_target.outputs.bucket }} source-dir: artifact-106/ - destination-dir: flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/android-riscv64-release + destination-dir: ${{ steps.r2_target.outputs.prefix }}flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/android-riscv64-release - name: Publish android-riscv64-release/linux-x64.zip uses: ryand56/r2-upload-action@b801a390acbdeb034c5e684ff5e1361c06639e7c with: r2-account-id: ${{ secrets.R2_ACCOUNT_ID }} r2-access-key-id: ${{ secrets.R2_ACCESS_KEY_ID }} r2-secret-access-key: ${{ secrets.R2_SECRET_ACCESS_KEY }} - r2-bucket: ${{ env.R2_BUCKET }} + r2-bucket: ${{ steps.r2_target.outputs.bucket }} source-dir: artifact-107/ - destination-dir: flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/android-riscv64-release + destination-dir: ${{ steps.r2_target.outputs.prefix }}flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/android-riscv64-release - name: Publish android-riscv64-release/symbols.zip uses: ryand56/r2-upload-action@b801a390acbdeb034c5e684ff5e1361c06639e7c with: r2-account-id: ${{ secrets.R2_ACCOUNT_ID }} r2-access-key-id: ${{ secrets.R2_ACCESS_KEY_ID }} r2-secret-access-key: ${{ secrets.R2_SECRET_ACCESS_KEY }} - r2-bucket: ${{ env.R2_BUCKET }} + r2-bucket: ${{ steps.r2_target.outputs.bucket }} source-dir: artifact-108/ - destination-dir: flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/android-riscv64-release + destination-dir: ${{ steps.r2_target.outputs.prefix }}flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/android-riscv64-release - name: Publish android-riscv64-release/analyze-snapshot-linux-x64.zip uses: ryand56/r2-upload-action@b801a390acbdeb034c5e684ff5e1361c06639e7c with: r2-account-id: ${{ secrets.R2_ACCOUNT_ID }} r2-access-key-id: ${{ secrets.R2_ACCESS_KEY_ID }} r2-secret-access-key: ${{ secrets.R2_SECRET_ACCESS_KEY }} - r2-bucket: ${{ env.R2_BUCKET }} + r2-bucket: ${{ steps.r2_target.outputs.bucket }} source-dir: artifact-109/ - destination-dir: flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/android-riscv64-release + destination-dir: ${{ steps.r2_target.outputs.prefix }}flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/android-riscv64-release - name: Publish /download.flutter.io uses: ryand56/r2-upload-action@b801a390acbdeb034c5e684ff5e1361c06639e7c with: r2-account-id: ${{ secrets.R2_ACCOUNT_ID }} r2-access-key-id: ${{ secrets.R2_ACCESS_KEY_ID }} r2-secret-access-key: ${{ secrets.R2_SECRET_ACCESS_KEY }} - r2-bucket: ${{ env.R2_BUCKET }} + r2-bucket: ${{ steps.r2_target.outputs.bucket }} source-dir: artifact-110/ - destination-dir: ./ + destination-dir: ${{ steps.r2_target.outputs.prefix }} - name: Publish android-arm/artifacts.zip uses: ryand56/r2-upload-action@b801a390acbdeb034c5e684ff5e1361c06639e7c with: r2-account-id: ${{ secrets.R2_ACCOUNT_ID }} r2-access-key-id: ${{ secrets.R2_ACCESS_KEY_ID }} r2-secret-access-key: ${{ secrets.R2_SECRET_ACCESS_KEY }} - r2-bucket: ${{ env.R2_BUCKET }} + r2-bucket: ${{ steps.r2_target.outputs.bucket }} source-dir: artifact-111/ - destination-dir: flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/android-arm + destination-dir: ${{ steps.r2_target.outputs.prefix }}flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/android-arm - name: Publish android-arm/android-arm-embedder.zip uses: ryand56/r2-upload-action@b801a390acbdeb034c5e684ff5e1361c06639e7c with: r2-account-id: ${{ secrets.R2_ACCOUNT_ID }} r2-access-key-id: ${{ secrets.R2_ACCESS_KEY_ID }} r2-secret-access-key: ${{ secrets.R2_SECRET_ACCESS_KEY }} - r2-bucket: ${{ env.R2_BUCKET }} + r2-bucket: ${{ steps.r2_target.outputs.bucket }} source-dir: artifact-112/ - destination-dir: flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/android-arm + destination-dir: ${{ steps.r2_target.outputs.prefix }}flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/android-arm - name: Publish android-arm/symbols.zip uses: ryand56/r2-upload-action@b801a390acbdeb034c5e684ff5e1361c06639e7c with: r2-account-id: ${{ secrets.R2_ACCOUNT_ID }} r2-access-key-id: ${{ secrets.R2_ACCESS_KEY_ID }} r2-secret-access-key: ${{ secrets.R2_SECRET_ACCESS_KEY }} - r2-bucket: ${{ env.R2_BUCKET }} + r2-bucket: ${{ steps.r2_target.outputs.bucket }} source-dir: artifact-113/ - destination-dir: flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/android-arm + destination-dir: ${{ steps.r2_target.outputs.prefix }}flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/android-arm - name: Publish /download.flutter.io uses: ryand56/r2-upload-action@b801a390acbdeb034c5e684ff5e1361c06639e7c with: r2-account-id: ${{ secrets.R2_ACCOUNT_ID }} r2-access-key-id: ${{ secrets.R2_ACCESS_KEY_ID }} r2-secret-access-key: ${{ secrets.R2_SECRET_ACCESS_KEY }} - r2-bucket: ${{ env.R2_BUCKET }} + r2-bucket: ${{ steps.r2_target.outputs.bucket }} source-dir: artifact-114/ - destination-dir: ./ + destination-dir: ${{ steps.r2_target.outputs.prefix }} - name: Publish /sky_engine.zip uses: ryand56/r2-upload-action@b801a390acbdeb034c5e684ff5e1361c06639e7c with: r2-account-id: ${{ secrets.R2_ACCOUNT_ID }} r2-access-key-id: ${{ secrets.R2_ACCESS_KEY_ID }} r2-secret-access-key: ${{ secrets.R2_SECRET_ACCESS_KEY }} - r2-bucket: ${{ env.R2_BUCKET }} + r2-bucket: ${{ steps.r2_target.outputs.bucket }} source-dir: artifact-115/ - destination-dir: flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/ + destination-dir: ${{ steps.r2_target.outputs.prefix }}flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/ - name: Publish /android-javadoc.zip uses: ryand56/r2-upload-action@b801a390acbdeb034c5e684ff5e1361c06639e7c with: r2-account-id: ${{ secrets.R2_ACCOUNT_ID }} r2-access-key-id: ${{ secrets.R2_ACCESS_KEY_ID }} r2-secret-access-key: ${{ secrets.R2_SECRET_ACCESS_KEY }} - r2-bucket: ${{ env.R2_BUCKET }} + r2-bucket: ${{ steps.r2_target.outputs.bucket }} source-dir: artifact-116/ - destination-dir: flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/ + destination-dir: ${{ steps.r2_target.outputs.prefix }}flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/ - name: Publish android-arm64/artifacts.zip uses: ryand56/r2-upload-action@b801a390acbdeb034c5e684ff5e1361c06639e7c with: r2-account-id: ${{ secrets.R2_ACCOUNT_ID }} r2-access-key-id: ${{ secrets.R2_ACCESS_KEY_ID }} r2-secret-access-key: ${{ secrets.R2_SECRET_ACCESS_KEY }} - r2-bucket: ${{ env.R2_BUCKET }} + r2-bucket: ${{ steps.r2_target.outputs.bucket }} source-dir: artifact-117/ - destination-dir: flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/android-arm64 + destination-dir: ${{ steps.r2_target.outputs.prefix }}flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/android-arm64 - name: Publish android-arm64/android-arm64-embedder.zip uses: ryand56/r2-upload-action@b801a390acbdeb034c5e684ff5e1361c06639e7c with: r2-account-id: ${{ secrets.R2_ACCOUNT_ID }} r2-access-key-id: ${{ secrets.R2_ACCESS_KEY_ID }} r2-secret-access-key: ${{ secrets.R2_SECRET_ACCESS_KEY }} - r2-bucket: ${{ env.R2_BUCKET }} + r2-bucket: ${{ steps.r2_target.outputs.bucket }} source-dir: artifact-118/ - destination-dir: flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/android-arm64 + destination-dir: ${{ steps.r2_target.outputs.prefix }}flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/android-arm64 - name: Publish android-arm64/symbols.zip uses: ryand56/r2-upload-action@b801a390acbdeb034c5e684ff5e1361c06639e7c with: r2-account-id: ${{ secrets.R2_ACCOUNT_ID }} r2-access-key-id: ${{ secrets.R2_ACCESS_KEY_ID }} r2-secret-access-key: ${{ secrets.R2_SECRET_ACCESS_KEY }} - r2-bucket: ${{ env.R2_BUCKET }} + r2-bucket: ${{ steps.r2_target.outputs.bucket }} source-dir: artifact-119/ - destination-dir: flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/android-arm64 + destination-dir: ${{ steps.r2_target.outputs.prefix }}flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/android-arm64 - name: Publish /download.flutter.io uses: ryand56/r2-upload-action@b801a390acbdeb034c5e684ff5e1361c06639e7c with: r2-account-id: ${{ secrets.R2_ACCOUNT_ID }} r2-access-key-id: ${{ secrets.R2_ACCESS_KEY_ID }} r2-secret-access-key: ${{ secrets.R2_SECRET_ACCESS_KEY }} - r2-bucket: ${{ env.R2_BUCKET }} + r2-bucket: ${{ steps.r2_target.outputs.bucket }} source-dir: artifact-120/ - destination-dir: ./ + destination-dir: ${{ steps.r2_target.outputs.prefix }} - name: Publish android-x86/artifacts.zip uses: ryand56/r2-upload-action@b801a390acbdeb034c5e684ff5e1361c06639e7c with: r2-account-id: ${{ secrets.R2_ACCOUNT_ID }} r2-access-key-id: ${{ secrets.R2_ACCESS_KEY_ID }} r2-secret-access-key: ${{ secrets.R2_SECRET_ACCESS_KEY }} - r2-bucket: ${{ env.R2_BUCKET }} + r2-bucket: ${{ steps.r2_target.outputs.bucket }} source-dir: artifact-121/ - destination-dir: flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/android-x86 + destination-dir: ${{ steps.r2_target.outputs.prefix }}flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/android-x86 - name: Publish android-x86/android-x86-embedder.zip uses: ryand56/r2-upload-action@b801a390acbdeb034c5e684ff5e1361c06639e7c with: r2-account-id: ${{ secrets.R2_ACCOUNT_ID }} r2-access-key-id: ${{ secrets.R2_ACCESS_KEY_ID }} r2-secret-access-key: ${{ secrets.R2_SECRET_ACCESS_KEY }} - r2-bucket: ${{ env.R2_BUCKET }} + r2-bucket: ${{ steps.r2_target.outputs.bucket }} source-dir: artifact-122/ - destination-dir: flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/android-x86 + destination-dir: ${{ steps.r2_target.outputs.prefix }}flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/android-x86 - name: Publish android-x86/symbols.zip uses: ryand56/r2-upload-action@b801a390acbdeb034c5e684ff5e1361c06639e7c with: r2-account-id: ${{ secrets.R2_ACCOUNT_ID }} r2-access-key-id: ${{ secrets.R2_ACCESS_KEY_ID }} r2-secret-access-key: ${{ secrets.R2_SECRET_ACCESS_KEY }} - r2-bucket: ${{ env.R2_BUCKET }} + r2-bucket: ${{ steps.r2_target.outputs.bucket }} source-dir: artifact-123/ - destination-dir: flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/android-x86 + destination-dir: ${{ steps.r2_target.outputs.prefix }}flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/android-x86 - name: Publish /download.flutter.io uses: ryand56/r2-upload-action@b801a390acbdeb034c5e684ff5e1361c06639e7c with: r2-account-id: ${{ secrets.R2_ACCOUNT_ID }} r2-access-key-id: ${{ secrets.R2_ACCESS_KEY_ID }} r2-secret-access-key: ${{ secrets.R2_SECRET_ACCESS_KEY }} - r2-bucket: ${{ env.R2_BUCKET }} + r2-bucket: ${{ steps.r2_target.outputs.bucket }} source-dir: artifact-124/ - destination-dir: ./ + destination-dir: ${{ steps.r2_target.outputs.prefix }} - name: Publish android-x64/artifacts.zip uses: ryand56/r2-upload-action@b801a390acbdeb034c5e684ff5e1361c06639e7c with: r2-account-id: ${{ secrets.R2_ACCOUNT_ID }} r2-access-key-id: ${{ secrets.R2_ACCESS_KEY_ID }} r2-secret-access-key: ${{ secrets.R2_SECRET_ACCESS_KEY }} - r2-bucket: ${{ env.R2_BUCKET }} + r2-bucket: ${{ steps.r2_target.outputs.bucket }} source-dir: artifact-125/ - destination-dir: flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/android-x64 + destination-dir: ${{ steps.r2_target.outputs.prefix }}flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/android-x64 - name: Publish android-x64/android-x64-embedder.zip uses: ryand56/r2-upload-action@b801a390acbdeb034c5e684ff5e1361c06639e7c with: r2-account-id: ${{ secrets.R2_ACCOUNT_ID }} r2-access-key-id: ${{ secrets.R2_ACCESS_KEY_ID }} r2-secret-access-key: ${{ secrets.R2_SECRET_ACCESS_KEY }} - r2-bucket: ${{ env.R2_BUCKET }} + r2-bucket: ${{ steps.r2_target.outputs.bucket }} source-dir: artifact-126/ - destination-dir: flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/android-x64 + destination-dir: ${{ steps.r2_target.outputs.prefix }}flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/android-x64 - name: Publish android-x64/symbols.zip uses: ryand56/r2-upload-action@b801a390acbdeb034c5e684ff5e1361c06639e7c with: r2-account-id: ${{ secrets.R2_ACCOUNT_ID }} r2-access-key-id: ${{ secrets.R2_ACCESS_KEY_ID }} r2-secret-access-key: ${{ secrets.R2_SECRET_ACCESS_KEY }} - r2-bucket: ${{ env.R2_BUCKET }} + r2-bucket: ${{ steps.r2_target.outputs.bucket }} source-dir: artifact-127/ - destination-dir: flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/android-x64 + destination-dir: ${{ steps.r2_target.outputs.prefix }}flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/android-x64 - name: Publish /download.flutter.io uses: ryand56/r2-upload-action@b801a390acbdeb034c5e684ff5e1361c06639e7c with: r2-account-id: ${{ secrets.R2_ACCOUNT_ID }} r2-access-key-id: ${{ secrets.R2_ACCESS_KEY_ID }} r2-secret-access-key: ${{ secrets.R2_SECRET_ACCESS_KEY }} - r2-bucket: ${{ env.R2_BUCKET }} + r2-bucket: ${{ steps.r2_target.outputs.bucket }} source-dir: artifact-128/ - destination-dir: ./ + destination-dir: ${{ steps.r2_target.outputs.prefix }} - name: Publish android-riscv64/artifacts.zip uses: ryand56/r2-upload-action@b801a390acbdeb034c5e684ff5e1361c06639e7c with: r2-account-id: ${{ secrets.R2_ACCOUNT_ID }} r2-access-key-id: ${{ secrets.R2_ACCESS_KEY_ID }} r2-secret-access-key: ${{ secrets.R2_SECRET_ACCESS_KEY }} - r2-bucket: ${{ env.R2_BUCKET }} + r2-bucket: ${{ steps.r2_target.outputs.bucket }} source-dir: artifact-129/ - destination-dir: flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/android-riscv64 + destination-dir: ${{ steps.r2_target.outputs.prefix }}flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/android-riscv64 - name: Publish android-riscv64/android-riscv64-embedder.zip uses: ryand56/r2-upload-action@b801a390acbdeb034c5e684ff5e1361c06639e7c with: r2-account-id: ${{ secrets.R2_ACCOUNT_ID }} r2-access-key-id: ${{ secrets.R2_ACCESS_KEY_ID }} r2-secret-access-key: ${{ secrets.R2_SECRET_ACCESS_KEY }} - r2-bucket: ${{ env.R2_BUCKET }} + r2-bucket: ${{ steps.r2_target.outputs.bucket }} source-dir: artifact-130/ - destination-dir: flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/android-riscv64 + destination-dir: ${{ steps.r2_target.outputs.prefix }}flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/android-riscv64 - name: Publish android-riscv64/symbols.zip uses: ryand56/r2-upload-action@b801a390acbdeb034c5e684ff5e1361c06639e7c with: r2-account-id: ${{ secrets.R2_ACCOUNT_ID }} r2-access-key-id: ${{ secrets.R2_ACCESS_KEY_ID }} r2-secret-access-key: ${{ secrets.R2_SECRET_ACCESS_KEY }} - r2-bucket: ${{ env.R2_BUCKET }} + r2-bucket: ${{ steps.r2_target.outputs.bucket }} source-dir: artifact-131/ - destination-dir: flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/android-riscv64 + destination-dir: ${{ steps.r2_target.outputs.prefix }}flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/android-riscv64 - name: Publish /download.flutter.io uses: ryand56/r2-upload-action@b801a390acbdeb034c5e684ff5e1361c06639e7c with: r2-account-id: ${{ secrets.R2_ACCOUNT_ID }} r2-access-key-id: ${{ secrets.R2_ACCESS_KEY_ID }} r2-secret-access-key: ${{ secrets.R2_SECRET_ACCESS_KEY }} - r2-bucket: ${{ env.R2_BUCKET }} + r2-bucket: ${{ steps.r2_target.outputs.bucket }} source-dir: artifact-132/ - destination-dir: ./ + destination-dir: ${{ steps.r2_target.outputs.prefix }} - name: Publish /flutter-web-sdk.zip uses: ryand56/r2-upload-action@b801a390acbdeb034c5e684ff5e1361c06639e7c with: r2-account-id: ${{ secrets.R2_ACCOUNT_ID }} r2-access-key-id: ${{ secrets.R2_ACCESS_KEY_ID }} r2-secret-access-key: ${{ secrets.R2_SECRET_ACCESS_KEY }} - r2-bucket: ${{ env.R2_BUCKET }} + r2-bucket: ${{ steps.r2_target.outputs.bucket }} source-dir: artifact-133/ - destination-dir: flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/ + destination-dir: ${{ steps.r2_target.outputs.prefix }}flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/ - name: Create latest_content_hash.txt + if: ${{ github.event_name != 'pull_request' }} run: | mkdir -p latest_content_hash echo "${{ needs.guard.outputs.engine_content_hash }}" > latest_content_hash/latest_content_hash.txt - name: Publish latest_content_hash.txt + if: ${{ github.event_name != 'pull_request' }} + id: publish_latest_content_hash uses: ryand56/r2-upload-action@b801a390acbdeb034c5e684ff5e1361c06639e7c with: r2-account-id: ${{ secrets.R2_ACCOUNT_ID }} r2-access-key-id: ${{ secrets.R2_ACCESS_KEY_ID }} r2-secret-access-key: ${{ secrets.R2_SECRET_ACCESS_KEY }} - r2-bucket: ${{ env.R2_BUCKET }} + r2-bucket: ${{ steps.r2_target.outputs.bucket }} source-dir: latest_content_hash/ destination-dir: flutter_infra_release/flutter/ + smoke_test: + name: Run the smoke test + uses: ./.github/workflows/smoke-test.yml + needs: + - publish_artifacts + if: ${{ github.event_name == 'pull_request' }} + with: + run_id: ${{ github.run_id }} + remove_ci_artifacts: + runs-on: ubuntu-latest + needs: + - publish_artifacts + - smoke_test + if: always() + steps: + - name: Remove the run prefix from the CI bucket + if: ${{ github.event_name == 'pull_request' }} + env: + AWS_ACCESS_KEY_ID: ${{ secrets.R2_ACCESS_KEY_ID }} + AWS_SECRET_ACCESS_KEY: ${{ secrets.R2_SECRET_ACCESS_KEY }} + AWS_ENDPOINT_URL_S3: https://b468378afe5657ffecccb682fe82ccac.r2.cloudflarestorage.com + AWS_DEFAULT_REGION: auto + run: | + aws s3 rm s3://flutter-zero-ci/pr-${{ github.run_id }}/ --recursive diff --git a/.github/workflows/call-smoke-test.yml b/.github/workflows/call-smoke-test.yml new file mode 100644 index 00000000..a4176be3 --- /dev/null +++ b/.github/workflows/call-smoke-test.yml @@ -0,0 +1,68 @@ +# Runs the smoke test against the already-published engine artifacts. +# +# Companion of the build-and-upload workflow. Both trigger on pull requests +# and share the same guard: the build-and-upload workflow checks whether the +# engine bucket already carries the pull request's engine content hash, and +# builds + smoke tests fresh artifacts under a CI-bucket prefix when it does +# not. This workflow covers the other case - the engine content is already +# deployed (no build needed), and the smoke test runs against the engine +# bucket. The two never run for the same pull request. +# +# NOTE: this file is intentionally not generated; edit directly. + +name: Call Smoke Test + +# Quoted so that YAML 1.1 parsers do not coerce the key to a boolean. +'on': + pull_request: + # Manual fallback (smoke tests the currently deployed engine artifacts). + workflow_dispatch: + +permissions: + contents: read + +jobs: + guard: + name: Resolve the engine artifacts state + runs-on: ubuntu-latest + outputs: + engine_content_hash: ${{ steps.engine_content_hash.outputs.value }} + already_deployed: ${{ steps.check.outputs.already_deployed }} + steps: + - name: Checkout the repository + uses: actions/checkout@v4 + + - name: Generate engine content hash + id: engine_content_hash + run: | + engine_content_hash=$(bin/internal/content_aware_hash.sh) + echo "::notice:: Engine content hash: ${engine_content_hash}" + echo "value=${engine_content_hash}" >> $GITHUB_OUTPUT + + - name: Check if the engine artifacts are already deployed + # Mirrors the guard of the build-and-upload workflow (same hash, same + # probe), but with the inverted conclusion: the smoke test here runs + # against the production engine bucket, which only carries this hash + # when build-and-upload decided (for the same commit) not to build. + id: check + env: + HASH: ${{ steps.engine_content_hash.outputs.value }} + run: | + URL="https://engine.flutter0.dev/flutter_infra_release/flutter/$HASH/engine_stamp.json" + if curl --head --silent --fail "$URL" > /dev/null; then + echo "Engine artifacts already deployed at $URL" + echo "already_deployed=true" >> $GITHUB_OUTPUT + else + echo "Engine artifacts are not deployed at $URL" + echo "already_deployed=false" >> $GITHUB_OUTPUT + fi + + smoke: + name: Run the smoke test + needs: [guard] + if: ${{ needs.guard.outputs.already_deployed == 'true' }} + uses: ./.github/workflows/smoke-test.yml + with: + # Empty selects the production engine bucket inside the smoke test + # workflow. + run_id: '' diff --git a/.github/workflows/smoke-test.yml b/.github/workflows/smoke-test.yml new file mode 100644 index 00000000..85d35a45 --- /dev/null +++ b/.github/workflows/smoke-test.yml @@ -0,0 +1,173 @@ +# Smoke test for the deployed engine artifacts. +# +# Runs the sample project in this checkout with the flutter tool consuming the +# published engine artifacts as storage (as a user would), through +# FLUTTER_STORAGE_BASE_URL. It consumes the same relative layout +# (flutter_infra_release/flutter//...) from either the CI-only +# artifacts bucket (deployed by the build-and-upload workflow for pull +# requests under a per-run prefix) or the production bucket. +# +# This workflow is on-call only: it is invoked +# * by the build-and-upload workflow, which passes the run id of its +# publishing run, or +# * by the call-smoke-test workflow, which selects already-published +# production artifacts. +# NOTE: this file is intentionally not generated; edit directly. + +name: Smoke Test + +# Quoted so that YAML 1.1 parsers do not coerce the key to a boolean. +'on': + workflow_call: + inputs: + run_id: + description: 'The run id of the build-and-upload run that published the artifacts; consumed as pr- in the CI bucket. Empty selects the production bucket.' + type: string + default: '' + required: false + +permissions: + contents: read + +jobs: + resolve: + name: Resolve the artifacts location + runs-on: ubuntu-latest + defaults: + run: + shell: bash + outputs: + engine_content_hash: ${{ steps.engine_content_hash.outputs.value }} + storage_base_url: ${{ steps.storage.outputs.base_url }} + steps: + - name: Checkout the repository + uses: actions/checkout@v4 + + - name: Generate engine content hash + id: engine_content_hash + run: | + engine_content_hash=$(bin/internal/content_aware_hash.sh) + echo "::notice:: Engine content hash: ${engine_content_hash}" + echo "value=${engine_content_hash}" >> $GITHUB_OUTPUT + + - name: Select the artifacts storage + id: storage + env: + HASH: ${{ steps.engine_content_hash.outputs.value }} + RUN_ID: ${{ inputs.run_id }} + run: | + for BASE in $(if [ -n "$RUN_ID" ]; then + echo "https://ci.flutter0.dev/pr-${RUN_ID}" + fi) "https://engine.flutter0.dev"; do + URL="$BASE/flutter_infra_release/flutter/$HASH/engine_stamp.json" + if curl --head --silent --fail "$URL" > /dev/null; then + echo "::notice:: Consuming artifacts from $BASE" + echo "base_url=$BASE" >> $GITHUB_OUTPUT + exit 0 + fi + done + echo "::error::No deployed artifacts for engine hash $HASH (checked the CI prefix pr-${RUN_ID} and the engine bucket); cannot smoke test." + exit 1 + + smoke: + name: Smoke (${{ matrix.device }} ${{ matrix.mode }}) + needs: [resolve] + runs-on: ${{ matrix.runs_on }} + defaults: + run: + shell: bash + strategy: + fail-fast: false + matrix: + include: + - { device: macos, mode: debug, runs_on: macos-latest, python: python3 } + - { device: macos, mode: profile, runs_on: macos-latest, python: python3 } + - { device: macos, mode: release, runs_on: macos-latest, python: python3 } + - { device: windows, mode: debug, runs_on: windows-latest, python: python } + - { device: windows, mode: profile, runs_on: windows-latest, python: python } + - { device: windows, mode: release, runs_on: windows-latest, python: python } + - { device: linux, mode: debug, runs_on: ubuntu-latest, python: python3 } + - { device: linux, mode: profile, runs_on: ubuntu-latest, python: python3 } + - { device: linux, mode: release, runs_on: ubuntu-latest, python: python3 } + # The iOS simulator is created and booted from scratch by the + # harness; the Android emulator image is installed and booted by + # the harness. + - { device: ios, mode: debug, runs_on: macos-latest, python: python3 } + - { device: android, mode: debug, runs_on: ubuntu-latest, python: python3 } + - { device: android, mode: profile, runs_on: ubuntu-latest, python: python3 } + - { device: android, mode: release, runs_on: ubuntu-latest, python: python3 } + steps: + - name: Checkout the repository + uses: actions/checkout@v4 + # Full history + tags so that the tool can determine its version + # from git (see version.dart: GitTagVersion.determine). + with: + fetch-depth: 0 + fetch-tags: true + + - name: Pin the framework version + # The tool derives its framework version from git tags, but the CI + # checkouts of this fork contain none, so the tool would report the + # '0.0.0-unknown' placeholder (see kUnknownFrameworkVersion in + # version.dart); `pub get` then fails because the sample project + # requires Flutter >= 1.17.0. Hardcode a valid version for the smoke + # test before the tool snapshot is compiled (a fresh checkout builds + # it from the patched source). The intended constant is asserted to + # catch upstream drift. + run: | + FILE=packages/flutter_tools/lib/src/version.dart + sed "s|const kUnknownFrameworkVersion = '0.0.0-unknown';|const kUnknownFrameworkVersion = '3.48.0-0.0.pre';|" \ + "$FILE" > "$FILE.new" + mv "$FILE.new" "$FILE" + grep -q "const kUnknownFrameworkVersion = '3.48.0-0.0.pre';" "$FILE" + + - name: Install Linux desktop build prerequisites + # Building the sample app for the linux device runs the template's + # CMake, which pkg-config's glib-2.0; the hosted Ubuntu image does not + # include the glib development package. + if: matrix.device == 'linux' + run: | + sudo apt-get update + sudo apt-get install -y libglib2.0-dev liblzma-dev + + - name: Enable KVM group perms + # The hosted Ubuntu runners expose /dev/kvm, but with default + # permissions (root:kvm, mode 0660) the runner user cannot open it; + # without this rule the emulator crashes or silently falls back to + # software emulation and the boot never completes inside the timeout. + # https://github.blog/2024-04-02-github-actions-hardware-accelerated-android-virtualization-now-available/ + if: matrix.device == 'android' + run: | + test -e /dev/kvm + # chmod synchronously; udevadm applies rules to the live device only + # asynchronously, so relying on just the trigger is racy. + sudo chmod 666 /dev/kvm + echo 'KERNEL=="kvm", GROUP="kvm", MODE="0666", OPTIONS+="static_node=kvm"' | sudo tee /etc/udev/rules.d/99-kvm4all.rules + test -w /dev/kvm + + - name: Pin the Android AVD home + # On the ubuntu-24.04 runner image avdmanager writes AVDs into + # ~/.config/.android/avd (XDG_CONFIG_HOME is set), while the emulator + # looks in ~/.android/avd and dies immediately ("no avd found"). + # Pinning the documented variables makes both tools agree. + # https://github.com/actions/runner-images/issues/11482 + if: matrix.device == 'android' + run: | + echo "ANDROID_USER_HOME=$HOME/.android" >> "$GITHUB_ENV" + echo "ANDROID_EMULATOR_HOME=$HOME/.android" >> "$GITHUB_ENV" + echo "ANDROID_AVD_HOME=$HOME/.android/avd" >> "$GITHUB_ENV" + mkdir -p "$HOME/.android/avd" + + - name: Run smoke test (${{ matrix.device }} ${{ matrix.mode }}) + env: + FLUTTER_STORAGE_BASE_URL: ${{ needs.resolve.outputs.storage_base_url }} + # update_engine_version.sh otherwise recomputes the engine version + # from the master base tree (content_aware_hash.sh's merge-base + # logic), which does not match the deployed artifact directory of + # this pull request; the deployment is keyed by the hash captured at + # build time, so it is passed through here instead. + FLUTTER_PREBUILT_ENGINE_VERSION: ${{ needs.resolve.outputs.engine_content_hash }} + run: | + ${{ matrix.python }} dev/smoke_test/run.py \ + --device ${{ matrix.device }} \ + --mode ${{ matrix.mode }} diff --git a/dev/smoke_test/main.dart b/dev/smoke_test/main.dart new file mode 100644 index 00000000..ec983801 --- /dev/null +++ b/dev/smoke_test/main.dart @@ -0,0 +1,33 @@ +// Smoke test application for the headless flutter_zero engine. +// +// Printed lines are read from the flutter tool console by +// dev/smoke_test/run.py and asserted on. Do not change this file without +// updating dev/smoke_test/run.py. +// +// Semantics: +// - Top-level statics are preserved across a hot reload, but are re-initialized +// when the isolate is replaced by a hot restart. `tickCount` therefore +// distinguishes reload (continues incrementing) from restart (resets to 0). +// - `kVersion` lets the harness prove that *modified source* was actually +// loaded, since a constant change only shows up in newly loaded code. +// - registerHotRestartListener is a flutter_zero dart:ui hook that fires just +// before the isolate is destroyed (hot restart only, no reload). +import 'dart:async'; +import 'dart:ui'; + +const String kVersion = 'A'; + +int tickCount = 0; + +void main() { + print('SMOKE:boot:$kVersion:$tickCount'); + Timer.periodic(const Duration(seconds: 1), (timer) { + tickCount = tickCount + 1; + print('SMOKE:tick:${versionName()}:$tickCount'); + }); + PlatformDispatcher.instance.registerHotRestartListener(() { + print('SMOKE:pre-restart:$tickCount'); + }); +} + +String versionName() => kVersion; diff --git a/dev/smoke_test/run.py b/dev/smoke_test/run.py new file mode 100644 index 00000000..8443b384 --- /dev/null +++ b/dev/smoke_test/run.py @@ -0,0 +1,561 @@ +#!/usr/bin/env python3 +"""Smoke test for the headless flutter_zero engine. + +Runs a sample project (created with the in-tree flutter tool) against the +local engine and asserts on the output it prints: launch, hot reload (after +modifying the source), hot restart, quit. + + python3 dev/smoke_test/run.py --device [macos|windows|linux|ios|android] \ + --engine ci/host_debug [--host-engine ci/host_engine] + +iOS simulators and Android emulators are booted when needed and closed after +the run. +""" +import argparse +import collections +import json +import os +import platform +import subprocess +import sys +import tempfile +import threading +import time + +REPO_ROOT = os.path.abspath( + os.path.join(os.path.dirname(os.path.abspath(__file__)), '..', '..')) +ENGINE_SRC_ROOT = os.path.join(REPO_ROOT, 'engine', 'src') +APP_SOURCE = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'main.dart') +PROJECT_NAME = 'smoke_sample_project' +DEVICE_BOOT_TIMEOUT_S = 600.0 +ANDROID_BOOT_TIMEOUT_S = 900.0 +RELOAD_TIMEOUT_S = 120.0 +QUIT_GRACE_S = 30.0 +# The tool is the in-tree one of this checkout; all invocations (including +# the nested ones during the app build) use it. +FLUTTER_TOOL = os.path.join( + REPO_ROOT, 'bin', 'flutter.bat' if platform.system() == 'Windows' else 'flutter') + + +def log(msg): + print('SMOKE-HARNESS:%s' % msg, flush=True) + + +def die(tool_tail, msg): + log('FAIL:%s' % msg) + for line in tool_tail: + if line is not None: + log('tool:%s' % line.rstrip() if line.rstrip() else '') + sys.exit(1) + + +def send_daemon_command(process, index, method, app_id, full_restart=False): + """Sends one daemon command. + + `app.restart` covers both hot reload (fullRestart false) and hot restart + (fullRestart true). Daemon lines are single-command json arrays with the + appId in params.""" + payload = [{'method': method, 'id': index, + 'params': {'appId': app_id, 'fullRestart': full_restart}}] + process.stdin.write(json.dumps(payload) + '\n') + process.stdin.flush() + + +def write_app_file(project_dir, version): + """Writes the versioned fixture as the sample project entrypoint. + + The version constant lets the harness prove that modified source (not just + re-executed code) was loaded by a hot reload. + """ + output = [] + with open(APP_SOURCE) as fixture: + for line in fixture: + output.append(line.replace("const String kVersion = 'A';", + "const String kVersion = '%s';" % version)) + main_path = os.path.join(project_dir, 'lib', 'main.dart') + with open(main_path, 'w') as main_file: + main_file.write(''.join(output)) + return main_path + + +def create_project(workspace, platforms, engine, host_engine): + log('creating sample project with the in-tree flutter tool') + os.makedirs(workspace, exist_ok=True) + # Create with the local engine configured as well, so that the tool caches + # do not rely on downloadable sdk artifacts; CI may need to operate without + # any published storage. + local_engines = [] if engine is None else [ + '--local-engine=%s' % engine, + '--local-engine-host=%s' % host_engine, + '--local-engine-src-path=%s' % ENGINE_SRC_ROOT, + ] + code, output = run_tool_sync( + ['create', '--platforms=%s' % platforms, PROJECT_NAME, + '--suppress-analytics', *local_engines], + cwd=workspace) + if code != 0: + die(output.splitlines()[-5:], + '`flutter create` of the sample project failed') + return os.path.join(workspace, PROJECT_NAME) + + +SIM_NAME = 'flutter_zero_smoke_test_sim' + + +def boot_ios_simulator(): + """Creates and boots a fresh iOS simulator; returns (udid, device flag).""" + # Device lines look like: "iPhone 16 Pro (292C3A03-2D02-4548-9154-34A231D581C3)" + # so the UDID is captured, not the trailing boot state. + def _udid_of(state): + return os.popen( + 'xcrun simctl list devices %s | grep -m1 iPhone | ' + 'grep -Eo "[0-9A-F]{8}-[0-9A-F-]{27}"' % state).read().strip() + udid = _udid_of('booted') + if udid: + log('found a booted iOS simulator: %s' % udid) + return udid, None + log('creating and booting the iOS simulator') + udid = _udid_of('available') + if not udid: + die([], 'no available iOS simulator device found') + subprocess.run(['xcrun', 'simctl', 'create', SIM_NAME, udid], + check=False, stdout=subprocess.PIPE) + boot = subprocess.run( + ['xcrun', 'simctl', 'boot', udid], + check=False, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, + text=True) + if boot.returncode != 0 and 'already booted' not in boot.stderr.lower(): + die([], 'booting the iOS simulator failed') + try: + subprocess.run(['xcrun', 'simctl', 'bootstatus', udid, '-b'], + check=False, stdout=subprocess.DEVNULL, + timeout=DEVICE_BOOT_TIMEOUT_S) + except subprocess.TimeoutExpired: + die([], 'iOS simulator did not boot in %ss' % DEVICE_BOOT_TIMEOUT_S) + return udid, SIM_NAME + + +def android_tools(): + """Returns the (emulator, adb, avdmanager) command paths of the Android SDK. + + Precedence: ANDROID_SDK_ROOT / ANDROID_HOME, then the platform defaults.""" + sdk = _android_sdk_root() + if sdk is None: + die([], 'Android SDK not found; set ANDROID_SDK_ROOT to its location') + emulator, adb, avdmanager = ( + os.path.join(sdk, 'emulator', 'emulator'), + os.path.join(sdk, 'platform-tools', 'adb'), + os.path.join(sdk, 'cmdline-tools', 'latest', 'bin', 'avdmanager'), + ) + missing = [tool for tool in (emulator, adb, avdmanager) + if not os.path.exists(tool)] + if missing: + die([], 'Android SDK is missing tools: %s' % ', '.join(missing)) + return emulator, adb, avdmanager + + +def android_abi(): + """Returns the Android system image ABI for the host architecture.""" + return {'arm64': 'arm64-v8a'}.get(platform.machine(), 'x86_64') + + +# SDK packages that smoke test needs to boot an emulator on CI, where the +# runner image does not preinstall them with the Android SDK. +ANDROID_SDK_IMAGE = 'system-images;android-31;google_apis;%s' % android_abi() + + +def _android_sdk_root(): + """Returns the Android SDK root directory, or None.""" + candidates = [ + os.environ.get('ANDROID_SDK_ROOT'), + os.environ.get('ANDROID_HOME'), + os.path.join(os.path.expanduser('~'), 'Library', 'Android', 'sdk'), + os.path.join(os.path.expanduser('~'), 'Android', 'Sdk'), + os.path.join(os.path.expanduser('~'), 'AppData', 'Local', 'Android', + 'Sdk'), + '/usr/local/lib/android/sdk', + ] + return next((path for path in candidates if path and os.path.isdir(path)), + None) + + +def _install_android_emulator_packages(): + """Installs the Android emulator and AVD system image when missing. + + CI runner images ship the Android SDK without the emulator package and + system images required to boot an AVD.""" + sdk = _android_sdk_root() + if sdk is None: + die([], 'Android SDK not found; set ANDROID_SDK_ROOT to its location') + system_image_path = os.path.join(sdk, *filter(None, ANDROID_SDK_IMAGE.split(';'))) + missing = [] + if not os.path.isdir(os.path.join(sdk, 'emulator')): + missing.append('emulator') + if not os.path.isdir(system_image_path): + missing.append(ANDROID_SDK_IMAGE) + if not missing: + return + sdkmanager = os.path.join( + sdk, 'cmdline-tools', 'latest', 'bin', + 'sdkmanager.bat' if platform.system() == 'Windows' else 'sdkmanager') + if not os.path.isfile(sdkmanager): + die([], 'the Android SDK is missing sdkmanager at %s' % sdkmanager) + log('installing Android SDK packages: %s' % ', '.join(missing)) + result = subprocess.run( + [sdkmanager if platform.system() != 'Windows' + else 'cmd', '--install'] + missing, + input='y\n' * 64, # accept the licenses + stdout=subprocess.PIPE, stderr=subprocess.STDOUT, text=True, + check=False, env={**os.environ, 'ANDROID_SDK_ROOT': sdk}) + if result.returncode != 0: + die(result.stdout.splitlines()[-8:], + 'installing Android SDK packages failed') + + +def boot_android_emulator(): + _install_android_emulator_packages() + emulator, adb, avdmanager = android_tools() + device = subprocess.run( + [adb, 'devices'], stdout=subprocess.PIPE, stderr=subprocess.STDOUT, + text=True, check=False).stdout.strip().splitlines() + emulators = [line.split()[0] for line in device + if 'emulator' in line and 'daemon' not in line] + if emulators: + log('found a running Android emulator: %s' % emulators[0]) + return emulators[0], None + log('creating the Android AVD') + avd = 'flutter_zero_smoke_test_avd' + result = subprocess.run( + [avdmanager, 'create', 'avd', '-n', avd, + '-k', ANDROID_SDK_IMAGE], + input='no\n', + stdout=subprocess.PIPE, stderr=subprocess.STDOUT, text=True, + check=False) + tool_output = (result.stdout or '') + (result.stderr or '') + avd_ready = result.returncode == 0 or 'already exists' in tool_output + if not avd_ready: + die([], 'avdmanager failed; is the Android SDK installed?') + log('checking the Android emulator acceleration') + accel = subprocess.run( + [emulator, '-accel-check'], stdout=subprocess.PIPE, + stderr=subprocess.STDOUT, text=True) + if accel.returncode != 0: + # Software-only emulation boots far too slowly for CI; fail fast with the + # probe's output, which points at the missing permissions (hosted runners + # expose /dev/kvm but the runner user needs the udev rule from the + # workflow's 'Enable KVM group perms' step). + die([accel.stdout, accel.stderr], + 'the Android emulator cannot use hardware acceleration (KVM/HVF)') + emulator_tail = collections.deque(maxlen=10) + + def _log_emulator(): + """Drains the emulator's output continuously and logs it. + + Without a reader, an emulator crash (e.g. a missing hypervisor) would go + unnoticed while `adb wait-for-device` spins until the boot timeout; the + CI log must show the reason and the final output lines on failure. + """ + for line in emulator_process.stdout: + text = line.rstrip() + if text: + log('emulator:%s' % text) + emulator_tail.append(text) + + log('booting the Android emulator (headless, software rendering)') + emulator_process = subprocess.Popen( + [emulator, '-avd', avd, + '-no-window', '-gpu', 'swiftshader_indirect', + '-no-snapshot', '-no-audio'], + stdout=subprocess.PIPE, stderr=subprocess.STDOUT) + threading.Thread(target=_log_emulator, daemon=True).start() + try: + subprocess.run( + [adb, 'wait-for-device', 'shell', 'getprop', 'sys.boot_completed'], + check=False, timeout=ANDROID_BOOT_TIMEOUT_S) + except subprocess.TimeoutExpired: + die(list(emulator_tail), 'Android emulator did not boot in %ss' % ANDROID_BOOT_TIMEOUT_S) + device = subprocess.run( + [adb, 'devices'], stdout=subprocess.PIPE, stderr=subprocess.STDOUT, + text=True, check=False).stdout.strip().splitlines() + emulators = [line.split()[0] for line in device + if 'emulator' in line and 'daemon' not in line] + if not emulators: + die([], 'no running Android emulator found after boot attempt') + return emulators[0], emulator_process + + +def launch_flutter_run(project_dir, device, engine, host_engine, mode='debug'): + build_mode_flags = {'profile': ['--profile'], 'release': ['--release']}.get( + mode, []) + # engine=None means: run against the prebuilt engine in bin/cache, without + # any --local-engine flags. + local_engine_flags = [] if engine is None else [ + '--local-engine=%s' % engine, + '--local-engine-host=%s' % host_engine, + '--local-engine-src-path=%s' % ENGINE_SRC_ROOT, + ] + local_web_sdk_flags = [] if engine is None else [ + '--local-web-sdk=%s' % engine, + '--local-engine-src-path=%s' % ENGINE_SRC_ROOT, + ] + device_flag = {'web': 'chrome'}.get(device, device) + args = [ + FLUTTER_TOOL, 'run', '--machine', '--verbose', + '--suppress-analytics', '--no-version-check', + *(local_web_sdk_flags if device == 'web' else local_engine_flags), + '-d', device_flag, + ] + build_mode_flags + log('flutter run args: %s' % args) + return subprocess.Popen( + args, cwd=project_dir, + stdin=subprocess.PIPE, stdout=subprocess.PIPE, + stderr=subprocess.STDOUT, text=True, bufsize=1) + + +def stop_tool(process): + # Best effort: this runs from a `finally` block, so a hard failure here + # would mask the run's own exit status. + if process.poll() is None: + try: + send_daemon_command(process, 0, 'app.stop', None) + process.wait(timeout=QUIT_GRACE_S) + return + except Exception as e: + log('stopping the tool failed; terminating (%s)' % e) + try: + process.terminate() + except Exception as e: + log('terminating the tool failed (%s)' % e) + + +class ToolConsole: + """Watches the flutter tool's console while it runs the sample app. + + One reader thread digests the tool's merged stdout continuously, so the + tool can never block on a full pipe: lines are reconstructed from raw + chunks, echoed to the harness log, and daemon-protocol frames are parsed: + + app.start -> records the running app's id (app_id), which + app.restart/app.stop commands address + app.started -> the device/service protocol is initialized; the tool + rejects app.restart requests before this point with + "Device initialization has not completed." (observed on + the iOS simulator, whose service connection completes a + few seconds after the app's first print) + + wait_for() and wait_started() block until their moment and fail the run + with the recent console output when they time out (or when the tool + exits first). + """ + + def __init__(self, process): + self.process = process + self.app_id = None + self._started = False + self._lines = [] + self._tail = collections.deque(maxlen=12) + self._lock = threading.Condition() + self._eof = False + self._reader = threading.Thread(target=self._read_process, daemon=True) + self._reader.start() + + def _read_process(self): + for raw in self.process.stdout: + line = raw.rstrip('\r\n') + log('run:%s' % line) + self._note_daemon(line) + with self._lock: + self._lines.append(line) + self._tail.append(line) + self._lock.notify_all() + with self._lock: + self._eof = True + self._lock.notify_all() + + def _note_daemon(self, line): + """Interprets one daemon-protocol line; every other line is noise.""" + try: + payload = json.loads(line) # daemon frames are single-element arrays + frame = payload[0] if isinstance(payload, list) else payload + except ValueError: + return + if not isinstance(frame, dict) or 'event' not in frame: + return + if frame['event'] == 'app.start': + app_id = (frame.get('params') or {}).get('appId') + if app_id: + self.app_id = app_id + elif frame['event'] == 'app.started': + self._started = True + + def _wait(self, predicate, timeout, failure): + """Returns the first console line matching predicate, or fails the run.""" + deadline = time.monotonic() + timeout + while True: + with self._lock: + match = next((line for line in self._lines if predicate(line)), None) + if match is not None: + return match + remaining = deadline - time.monotonic() + if remaining <= 0 or self._eof: + break + self._lock.wait(min(0.5, remaining)) + die(list(self._tail), failure) + + def wait_for(self, sentinel, timeout): + """Waits for the app to print a console line containing sentinel.""" + _FAILED = 'the app did not print %s within %.0fs' % (sentinel, timeout) + return self._wait(lambda line: sentinel in line, timeout, _FAILED) + + def wait_started(self, timeout): + """Waits for the daemon's app.started event (the restart gate).""" + self._wait(lambda _: self._started, timeout, + 'the daemon did not report app.started within %.0fs' % timeout) + + +def run_debug_flow(project_dir, device, engine, host_engine): + """Launch, hot reload (with modified source), hot restart, quit.""" + console = ToolConsole(launch_flutter_run(project_dir, device, engine, + host_engine)) + command_index = 1 + try: + console.wait_for('SMOKE:boot:A:', DEVICE_BOOT_TIMEOUT_S) + log('launch ok') + log('waiting for app.started') + console.wait_started(DEVICE_BOOT_TIMEOUT_S) + log('app started; modifying lib/main.dart (A -> B)') + write_app_file(project_dir, 'B') + log('requesting hot reload') + send_daemon_command(console.process, command_index, 'app.restart', + console.app_id, full_restart=False) + command_index += 1 + line = console.wait_for('SMOKE:tick:B:', RELOAD_TIMEOUT_S) + log('hot reload ok (%s)' % line.strip()) + log('requesting hot restart') + send_daemon_command(console.process, command_index, 'app.restart', + console.app_id, full_restart=True) + command_index += 1 + if device != 'web': + # The web engine's hot restart hooks are dummies (no invocation), so the + # pre-restart listener sentinel is only asserted on native devices. + console.wait_for('SMOKE:pre-restart:', RELOAD_TIMEOUT_S) + console.wait_for('SMOKE:boot:B:0', RELOAD_TIMEOUT_S) + log('hot restart ok') + send_daemon_command(console.process, command_index, 'app.stop', + console.app_id) + console.process.wait(timeout=QUIT_GRACE_S) + finally: + stop_tool(console.process) + + +def run_tool_sync(args, cwd=None): + """Runs the in-tree tool synchronously, streaming all of its output. + + Every line is echoed to the CI log as it is produced (the full output + remains available to the caller for failure reporting). + """ + process = subprocess.Popen( + [FLUTTER_TOOL] + args, + cwd=cwd if cwd is not None else REPO_ROOT, + stdout=subprocess.PIPE, stderr=subprocess.STDOUT, + text=True, bufsize=1) + lines = [] + for line in process.stdout: + lines.append(line) + log('tool:%s' % line.rstrip()) + process.wait() + return process.returncode, ''.join(lines) + + +def run_boot_only_flow(project_dir, device, engine, host_engine, mode): + """profile/release posture: verify the released compile, no console checks. + + For web the app is built with `flutter build web` and its artifacts are + asserted (the released runtime has no console plumbing to forward); native + devices run `flutter run --profile/--release` and assert the boot sentinel. + """ + if device == 'web': + code, output = run_tool_sync( + ['build', 'web', '--verbose', + '--suppress-analytics', '--no-version-check', + '--local-web-sdk=%s' % engine, + '--local-engine-src-path=%s' % ENGINE_SRC_ROOT, + *( ['--profile'] if mode == 'profile' else ['--release'])], + cwd=project_dir) + if code != 0: + die(output.splitlines()[-20:], 'web %s build failed' % mode) + build_dir = os.path.join(project_dir, 'build', 'web') + missing = [artifact for artifact in ('flutter.js', 'flutter_service_worker.js') + if not os.path.exists(os.path.join(build_dir, artifact))] + if missing: + die([], 'web %s build is missing artifacts: %s' % (mode, ', '.join(missing))) + log('build ok (%s)' % mode) + return + console = ToolConsole(launch_flutter_run(project_dir, device, engine, + host_engine, mode)) + try: + console.wait_for('SMOKE:boot:A:', DEVICE_BOOT_TIMEOUT_S) + log('launch ok (%s)' % mode) + time.sleep(3.0) + send_daemon_command(console.process, 0, 'app.stop', console.app_id) + console.process.wait(timeout=QUIT_GRACE_S) + finally: + stop_tool(console.process) + + +def main(): + parser = argparse.ArgumentParser(description=__doc__) + parser.add_argument( + '--device', required=True, + choices=['macos', 'windows', 'linux', 'ios', 'android', 'web']) + parser.add_argument( + '--mode', default='debug', choices=['debug', 'profile', 'release']) + parser.add_argument( + '--engine', default=None, + help='name of the local engine build the app runs against ' + '(default: run against the prebuilt engine in bin/cache ' + 'without --local-engine flags).') + parser.add_argument( + '--host-engine', default=None, + help='name of the local host engine the tool runs against ' + '(default: same as --engine).') + parser.add_argument( + '--workspace', default=None, + help='where the sample project is created and left behind.') + args = parser.parse_args() + if args.engine is not None and args.host_engine is None: + # The tool validates the host engine relative to the target out dir, so + # the host variant is named without the "ci/" prefix. + args.host_engine = args.engine[len('ci/'):] if args.engine.startswith('ci/') else args.engine + device = args.device + simulator = None + emulator = None + if args.device == 'ios': + device, simulator = boot_ios_simulator() + elif args.device == 'android': + device, emulator = boot_android_emulator() + platforms = args.device + workspace = (args.workspace if args.workspace is not None + else tempfile.mkdtemp(prefix='flutter_zero_smoke_test_')) + try: + project_dir = create_project(workspace, platforms, args.engine, + args.host_engine) + write_app_file(project_dir, 'A') + if args.mode == 'debug': + run_debug_flow(project_dir, device, args.engine, args.host_engine) + else: + run_boot_only_flow(project_dir, device, args.engine, args.host_engine, + args.mode) + log('sample project left at %s' % workspace) + finally: + if args.device == 'ios' and simulator is not None: + subprocess.run(['xcrun', 'simctl', 'shutdown', SIM_NAME], + check=False, stdout=subprocess.DEVNULL) + subprocess.run(['xcrun', 'simctl', 'delete', SIM_NAME], + check=False, stdout=subprocess.DEVNULL) + if emulator is not None and emulator.poll() is None: + emulator.terminate() + + +if __name__ == '__main__': + main() diff --git a/engine/src/build/vs_toolchain.py b/engine/src/build/vs_toolchain.py index b6d84818..e4e4b438 100644 --- a/engine/src/build/vs_toolchain.py +++ b/engine/src/build/vs_toolchain.py @@ -268,6 +268,13 @@ def _CopyUCRTRuntime(target_dir, source_dir, target_cpu, dll_pattern, suffix): exist, but the target directory does exist.""" if target_cpu == 'arm64': env_version = GetVisualStudioVersion() + # GetVisualStudioVersion() may return the numeric install-folder form + # (e.g. '18' for VS 2026). Map it back to the year key used by + # VC_VERSIONS. + for year_key, install_folder in MSVS_VERSIONS.items(): + if env_version == install_folder: + env_version = year_key + break vc_version = VC_VERSIONS[env_version] prefix = 'Microsoft.' + vc_version diff --git a/engine/src/flutter/ci/builders/linux_android_debug_engine.json b/engine/src/flutter/ci/builders/linux_android_debug_engine.json index 80ff10ff..f5f43d90 100644 --- a/engine/src/flutter/ci/builders/linux_android_debug_engine.json +++ b/engine/src/flutter/ci/builders/linux_android_debug_engine.json @@ -95,7 +95,9 @@ "targets": [ "flutter", "flutter/shell/platform/android:abi_jars", - "flutter/shell/platform/embedder:embedder-archive" + "flutter/shell/platform/embedder:embedder-archive", + "flutter/shell/platform/android:android_jar", + "flutter/shell/platform/android:robolectric_tests" ] } }, diff --git a/engine/src/flutter/ci/builders/linux_arm_host_engine.json b/engine/src/flutter/ci/builders/linux_arm_host_engine.json index fc42117b..4af33cc4 100644 --- a/engine/src/flutter/ci/builders/linux_arm_host_engine.json +++ b/engine/src/flutter/ci/builders/linux_arm_host_engine.json @@ -49,7 +49,8 @@ "ninja": { "config": "ci/linux_profile_arm64", "targets": [ - "flutter/shell/platform/linux:flutter_gtk" + "flutter/shell/platform/linux:flutter_gtk", + "flutter:unittests" ] } }, @@ -98,8 +99,9 @@ "flutter/build/archives:artifacts", "flutter/build/archives:dart_sdk_archive", "flutter/tools/font_subset", + "flutter/build/archives:embedder", "flutter/shell/platform/linux:flutter_gtk", - "flutter/build/archives:embedder" + "flutter:unittests" ] } }, @@ -141,7 +143,8 @@ "ninja": { "config": "ci/linux_release_arm64", "targets": [ - "flutter/shell/platform/linux:flutter_gtk" + "flutter/shell/platform/linux:flutter_gtk", + "flutter:unittests" ] } } diff --git a/engine/src/flutter/ci/builders/linux_host_desktop_engine.json b/engine/src/flutter/ci/builders/linux_host_desktop_engine.json index adf1f260..e2887a4a 100644 --- a/engine/src/flutter/ci/builders/linux_host_desktop_engine.json +++ b/engine/src/flutter/ci/builders/linux_host_desktop_engine.json @@ -48,7 +48,8 @@ "ninja": { "config": "ci/host_debug_desktop", "targets": [ - "flutter/shell/platform/linux:flutter_gtk" + "flutter/shell/platform/linux:flutter_gtk", + "flutter:unittests" ] } }, @@ -89,7 +90,8 @@ "ninja": { "config": "ci/host_profile_desktop", "targets": [ - "flutter/shell/platform/linux:flutter_gtk" + "flutter/shell/platform/linux:flutter_gtk", + "flutter:unittests" ] } }, @@ -130,7 +132,8 @@ "ninja": { "config": "ci/host_release_desktop", "targets": [ - "flutter/shell/platform/linux:flutter_gtk" + "flutter/shell/platform/linux:flutter_gtk", + "flutter:unittests" ] } } diff --git a/engine/src/flutter/ci/builders/linux_host_engine.json b/engine/src/flutter/ci/builders/linux_host_engine.json index 30ae59e6..c4e449a4 100644 --- a/engine/src/flutter/ci/builders/linux_host_engine.json +++ b/engine/src/flutter/ci/builders/linux_host_engine.json @@ -55,7 +55,8 @@ "flutter/build/archives:flutter_patched_sdk", "flutter/build/archives:artifacts", "flutter/tools/font_subset", - "flutter/build/archives:embedder" + "flutter/build/archives:embedder", + "flutter:unittests" ] } }, @@ -101,7 +102,9 @@ "ninja": { "config": "ci/host_release", "targets": [ - "flutter/build/archives:flutter_patched_sdk" + "flutter/build/archives:flutter_patched_sdk", + "flutter/shell/testing", + "flutter:unittests" ] } } diff --git a/engine/src/flutter/ci/builders/linux_host_engine_test.json b/engine/src/flutter/ci/builders/linux_host_engine_test.json index f1a9d331..dd15bfb2 100644 --- a/engine/src/flutter/ci/builders/linux_host_engine_test.json +++ b/engine/src/flutter/ci/builders/linux_host_engine_test.json @@ -31,7 +31,7 @@ "config": "ci/host_debug_test", "targets": [ "flutter:unittests", - "flutter/build/dart:copy_dart_sdk", + "flutter/build/dart:dart_sdk", "flutter/shell/testing" ] }, @@ -77,7 +77,7 @@ "config": "ci/host_profile_test", "targets": [ "flutter:unittests", - "flutter/build/dart:copy_dart_sdk", + "flutter/build/dart:dart_sdk", "flutter/shell/testing" ] }, @@ -129,7 +129,7 @@ "config": "ci/host_release_test", "targets": [ "flutter:unittests", - "flutter/build/dart:copy_dart_sdk", + "flutter/build/dart:dart_sdk", "flutter/display_list:display_list_benchmarks", "flutter/display_list:display_list_builder_benchmarks", "flutter/display_list:display_list_region_benchmarks", diff --git a/engine/src/flutter/ci/builders/linux_unopt.json b/engine/src/flutter/ci/builders/linux_unopt.json index 21c47780..24b23a08 100644 --- a/engine/src/flutter/ci/builders/linux_unopt.json +++ b/engine/src/flutter/ci/builders/linux_unopt.json @@ -27,7 +27,7 @@ "targets": [ "flutter/tools/font_subset", "flutter:unittests", - "flutter/build/dart:copy_dart_sdk", + "flutter/build/dart:dart_sdk", "flutter/shell/platform/common/client_wrapper:client_wrapper_unittests", "flutter/shell/platform/common:common_cpp_core_unittests", "flutter/shell/platform/common:common_cpp_unittests", diff --git a/engine/src/flutter/ci/builders/mac_host_engine.json b/engine/src/flutter/ci/builders/mac_host_engine.json index 5b1a0c96..b642b78e 100644 --- a/engine/src/flutter/ci/builders/mac_host_engine.json +++ b/engine/src/flutter/ci/builders/mac_host_engine.json @@ -111,7 +111,8 @@ "config": "ci/host_debug", "targets": [ "flutter/build/archives:artifacts", - "flutter/build/archives:dart_sdk_archive" + "flutter/build/archives:dart_sdk_archive", + "flutter:unittests" ] }, "postsubmit_overrides": { @@ -228,7 +229,8 @@ "ninja": { "config": "ci/host_profile", "targets": [ - "flutter/build/archives:artifacts" + "flutter/build/archives:artifacts", + "flutter:unittests" ] }, "postsubmit_overrides": { @@ -395,7 +397,8 @@ "config": "ci/host_release", "targets": [ "flutter/build/archives:artifacts", - "flutter/tools/font_subset" + "flutter/tools/font_subset", + "flutter:unittests" ] }, "postsubmit_overrides": { @@ -568,7 +571,8 @@ "config": "ci/mac_debug_arm64", "targets": [ "flutter/build/archives:artifacts", - "flutter/build/archives:dart_sdk_archive" + "flutter/build/archives:dart_sdk_archive", + "flutter:unittests" ] }, "postsubmit_overrides": { @@ -745,7 +749,8 @@ "ninja": { "config": "ci/mac_profile_arm64", "targets": [ - "flutter/build/archives:artifacts" + "flutter/build/archives:artifacts", + "flutter:unittests" ] }, "postsubmit_overrides": { @@ -924,7 +929,8 @@ "config": "ci/mac_release_arm64", "targets": [ "flutter/build/archives:artifacts", - "flutter/tools/font_subset" + "flutter/tools/font_subset", + "flutter:unittests" ] }, "postsubmit_overrides": { diff --git a/engine/src/flutter/ci/builders/mac_ios_engine_no_ext_safe.json b/engine/src/flutter/ci/builders/mac_ios_engine_no_ext_safe.json index 9788c3bc..7c92a15b 100644 --- a/engine/src/flutter/ci/builders/mac_ios_engine_no_ext_safe.json +++ b/engine/src/flutter/ci/builders/mac_ios_engine_no_ext_safe.json @@ -107,6 +107,58 @@ } } }, + { + "drone_dimensions": [ + "device_type=none", + "os=Mac-15.5|Mac-15.7", + "cpu=arm64" + ], + "gclient_variables": { + "download_android_deps": false, + "download_jdk": false, + "use_rbe": true + }, + "gn": [ + "--target-dir", + "ci/ios_test_binaries_arm64", + "--ios", + "--runtime-mode", + "debug", + "--simulator", + "--simulator-cpu=arm64", + "--no-lto", + "--rbe", + "--no-goma", + "--xcode-symlinks" + ], + "name": "ci/ios_test_binaries_arm64", + "description": "Builds the iOS simulator unit tests (host-side test binaries for arm64 iOS).", + "ninja": { + "config": "ci/ios_test_binaries_arm64", + "targets": [ + "flutter/shell/platform/darwin/ios:ios_test_flutter" + ] + }, + "properties": { + "$flutter/osx_sdk": { + "sdk_version": "16c5032a" + } + }, + "postsubmit_overrides": { + "gn": [ + "--target-dir", + "ci/ios_test_binaries_arm64", + "--ios", + "--runtime-mode", + "debug", + "--simulator", + "--simulator-cpu=arm64", + "--no-lto", + "--no-rbe", + "--no-goma" + ] + } + }, { "drone_dimensions": [ "device_type=none", diff --git a/engine/src/flutter/ci/builders/standalone/linux_benchmarks.json b/engine/src/flutter/ci/builders/standalone/linux_benchmarks.json index cfae8fa1..398246cd 100644 --- a/engine/src/flutter/ci/builders/standalone/linux_benchmarks.json +++ b/engine/src/flutter/ci/builders/standalone/linux_benchmarks.json @@ -23,7 +23,7 @@ "ninja": { "config": "ci/host_release_benchmarks", "targets": [ - "flutter/build/dart:copy_dart_sdk", + "flutter/build/dart:dart_sdk", "flutter/display_list:display_list_benchmarks", "flutter/display_list:display_list_builder_benchmarks", "flutter/display_list:display_list_region_benchmarks", diff --git a/engine/src/flutter/ci/builders/windows_host_engine.json b/engine/src/flutter/ci/builders/windows_host_engine.json index 07f17e0c..1e40ab29 100644 --- a/engine/src/flutter/ci/builders/windows_host_engine.json +++ b/engine/src/flutter/ci/builders/windows_host_engine.json @@ -8,7 +8,7 @@ "definition files." ], "luci_flags": { - "upload_content_hash": true + "upload_content_hash": true }, "builds": [ { @@ -56,7 +56,8 @@ "flutter/tools/font_subset", "flutter/build/archives:dart_sdk_archive", "flutter/shell/platform/windows/client_wrapper:client_wrapper_archive", - "flutter/build/archives:windows_flutter" + "flutter/build/archives:windows_flutter", + "flutter:unittests" ] } }, @@ -97,7 +98,8 @@ "targets": [ "windows", "gen_snapshot", - "flutter/build/archives:windows_flutter" + "flutter/build/archives:windows_flutter", + "flutter/shell/testing" ] } }, @@ -139,7 +141,8 @@ "targets": [ "windows", "gen_snapshot", - "flutter/build/archives:windows_flutter" + "flutter/build/archives:windows_flutter", + "flutter/shell/testing" ] } } diff --git a/engine/src/flutter/lib/web_ui/lib/platform_dispatcher.dart b/engine/src/flutter/lib/web_ui/lib/platform_dispatcher.dart index a625cc38..c86c4ef8 100644 --- a/engine/src/flutter/lib/web_ui/lib/platform_dispatcher.dart +++ b/engine/src/flutter/lib/web_ui/lib/platform_dispatcher.dart @@ -18,6 +18,15 @@ class RootIsolateToken { } abstract class PlatformDispatcher { + /// Registers a callback to be called when the application receives a hot + /// restart signal. + /// + /// The web engine does not implement hot restart signals; this is a dummy + /// implementation matching the native dart:ui API. + void registerHotRestartListener(VoidCallback callback) {} + + /// Unregisters a callback registered by [registerHotRestartListener]. + void unregisterHotRestartListener(VoidCallback callback) {} static PlatformDispatcher get instance => engine.EnginePlatformDispatcher.instance; int? get engineId; diff --git a/engine/src/flutter/shell/platform/darwin/macos/BUILD.gn b/engine/src/flutter/shell/platform/darwin/macos/BUILD.gn index 96cfc2d0..27449b24 100644 --- a/engine/src/flutter/shell/platform/darwin/macos/BUILD.gn +++ b/engine/src/flutter/shell/platform/darwin/macos/BUILD.gn @@ -111,18 +111,27 @@ test_fixtures("flutter_desktop_darwin_fixtures") { fixtures = [ "//flutter/third_party/icu/common/icudtl.dat" ] } -executable("flutter_desktop_darwin_swift_unittests") { - testonly = true - public_configs = [ - "//flutter/shell/platform/darwin/common:config", - "//flutter/shell/platform/darwin/common:test_config", - "//flutter/shell/platform/darwin/common:swift_testing_config", - ] - sources = [ "framework/Source/ResizeSynchronizerTest.swift" ] - deps = [ - ":flutter_framework_source", - "//flutter/shell/platform/darwin/common:swift_testing_main", - "//flutter/shell/platform/darwin/common:test_utils_swift", + +# Keeps the Dart VM snapshot blobs of the engine inside the test executable. +# +# The blobs are resolved at runtime with dlsym from the current process, and +# nothing references them statically. In builds where the mac linker is asked +# to dead strip, they would otherwise be removed, and the Dart VM creation of +# the engine would fail. +config("flutter_desktop_darwin_unittests_engine_snapshot") { + ldflags = [ + "-Xlinker", + "-u", + "-Xlinker", + "_kDartSnapshotData", + "-Xlinker", + "-u", + "-Xlinker", + "_kDartSnapshotText", + "-Xlinker", + "-u", + "-Xlinker", + "_kPlatformStrongDill", ] } @@ -131,6 +140,17 @@ executable("flutter_desktop_darwin_unittests") { cflags_objc = flutter_cflags_objc cflags_objcc = flutter_cflags_objcc ldflags = [ "-ObjC" ] + if (flutter_runtime_mode == "debug") { + # In debug builds the Dart VM snapshot blobs are resolved at runtime with + # dlsym from the current process; without being exported the dynamic + # symbol lookup can not find them, and without these anchors the mac + # linker may dead strip them, which makes the Dart VM creation of the + # test engine fail. + public_configs = [ + "//flutter:export_dynamic_symbols", + ":flutter_desktop_darwin_unittests_engine_snapshot", + ] + } sources = [ "framework/Source/FlutterAppDelegateTest.mm", diff --git a/engine/src/flutter/shell/platform/darwin/macos/README.md b/engine/src/flutter/shell/platform/darwin/macos/README.md index 7404a506..cbd2ffb2 100644 --- a/engine/src/flutter/shell/platform/darwin/macos/README.md +++ b/engine/src/flutter/shell/platform/darwin/macos/README.md @@ -44,8 +44,8 @@ Builds are architecture-specific, and can be controlled by specifying ## Testing The macOS-specific embedder tests are built as the -`flutter_desktop_darwin_unittests` and `flutter_desktop_darwin_swift_unittests` -binaries. Like all gtest-based test binaries, a subset of tests can be run by +`flutter_desktop_darwin_unittests` binaries. Like all gtest-based test binaries, +a subset of tests can be run by applying a filter such as `--gtest_filter='FlutterViewControllerTest.*Key*'`. More general details on testing can be found on the [Wiki][wiki_engine_testing]. diff --git a/engine/src/flutter/shell/platform/embedder/tests/embedder_unittests.cc b/engine/src/flutter/shell/platform/embedder/tests/embedder_unittests.cc index 5e39a5b5..11e172bf 100644 --- a/engine/src/flutter/shell/platform/embedder/tests/embedder_unittests.cc +++ b/engine/src/flutter/shell/platform/embedder/tests/embedder_unittests.cc @@ -1034,8 +1034,8 @@ TEST_F(EmbedderTest, CanPostTaskToAllNativeThreads) { ASSERT_EQ(captures.platform_threads_count, 1u); ASSERT_EQ(captures.ui_threads_count, 1u); ASSERT_EQ(captures.worker_threads_count, worker_count); - EXPECT_GE(captures.worker_threads_count - 1, 2u); - EXPECT_LE(captures.worker_threads_count - 1, 4u); + EXPECT_GE(captures.worker_threads_count, 2u); + EXPECT_LE(captures.worker_threads_count, 4u); platform_task_runner->PostTask([&]() { engine.reset(); diff --git a/engine/src/flutter/testing/run_tests.py b/engine/src/flutter/testing/run_tests.py index 602c59c9..a67a1b2c 100755 --- a/engine/src/flutter/testing/run_tests.py +++ b/engine/src/flutter/testing/run_tests.py @@ -424,9 +424,6 @@ def make_test(name, flags=None, extra_env=None): make_test('common_cpp_core_unittests'), make_test('common_cpp_unittests'), make_test('dart_plugin_registrant_unittests'), - make_test('display_list_rendertests'), - make_test('display_list_unittests'), - make_test('embedder_a11y_unittests'), make_test('embedder_proctable_unittests'), make_test('embedder_unittests'), make_test('fml_unittests'), @@ -443,78 +440,37 @@ def make_test(name, flags=None, extra_env=None): unittests += [ # https://github.com/google/googletest/issues/2490 make_test('jni_unittests'), - make_test('platform_view_android_delegate_unittests'), # https://github.com/flutter/flutter/issues/36295 make_test('shell_unittests'), ] if is_windows(): unittests += [ - # The accessibility library only supports Mac and Windows. - make_test('accessibility_unittests'), - make_test('client_wrapper_windows_unittests'), - make_test('flutter_windows_unittests'), + make_test('client_wrapper_windows_unittests'), + make_test('flutter_windows_unittests'), ] # These unit-tests are Objective-C and can only run on Darwin. if is_mac(): unittests += [ - # The accessibility library only supports Mac and Windows. - make_test('accessibility_unittests'), - make_test('availability_version_check_unittests'), - make_test('framework_common_swift_unittests'), - make_test('framework_common_unittests'), - make_test('spring_animation_unittests'), - make_test('gpu_surface_metal_unittests'), + make_test('availability_version_check_unittests'), + make_test('framework_common_swift_unittests'), + make_test('framework_common_unittests'), + make_test('spring_animation_unittests'), ] - if is_linux(): - flow_flags = [ - '--golden-dir=%s' % GOLDEN_DIR, - '--font-file=%s' % ROBOTO_FONT_PATH, - ] - icu_flags = ['--icu-data-file-path=%s' % os.path.join(build_dir, 'icudtl.dat')] - unittests += [ - make_test('flow_unittests', flags=repeat_flags + ['--'] + flow_flags), - make_test('flutter_glfw_unittests'), - make_test('flutter_linux_unittests', extra_env={'G_DEBUG': 'fatal-criticals'}), - # https://github.com/flutter/flutter/issues/36296 - make_test('txt_unittests', flags=repeat_flags + ['--'] + icu_flags), - ] - else: - flow_flags = ['--gtest_filter=-PerformanceOverlayLayer.Gold'] - unittests += [ - make_test('flow_unittests', flags=repeat_flags + flow_flags), - ] - - build_name = os.path.basename(build_dir) - try: - if is_linux(): - xvfb.start_virtual_x(build_name, build_dir) - for test, flags, extra_env in unittests: - run_engine_executable( - build_dir, - test, - executable_filter, - flags, - coverage=coverage, - extra_env=extra_env, - gtest=True - ) - finally: - if is_linux(): - xvfb.stop_virtual_x(build_name) - - if is_mac(): - # macOS Desktop unit tests written in Swift. + for test, flags, extra_env in unittests: run_engine_executable( build_dir, - 'flutter_desktop_darwin_swift_unittests', + test, executable_filter, - shuffle_flags, - coverage=coverage + flags, + coverage=coverage, + extra_env=extra_env, + gtest=True ) + if is_mac(): # flutter_desktop_darwin_unittests uses global state that isn't handled # correctly by gtest-parallel. # https://github.com/flutter/flutter/issues/104789 @@ -528,64 +484,12 @@ def make_test(name, flags=None, extra_env=None): shuffle_flags, coverage=coverage ) + extra_env = metal_validation_env() extra_env.update(vulkan_validation_env(build_dir)) - mac_impeller_unittests_flags = repeat_flags + [ - '--gtest_filter=-*OpenGLES', # These are covered in the golden tests. - '--', - '--enable_vulkan_validation', - ] - # Impeller tests are only supported on macOS for now. - run_engine_executable( - build_dir, - 'impeller_unittests', - executable_filter, - mac_impeller_unittests_flags, - coverage=coverage, - extra_env=extra_env, - gtest=True, - # TODO(https://github.com/flutter/flutter/issues/123733): Remove this allowlist. - # See also https://github.com/flutter/flutter/issues/114872. - allowed_failure_output=[ - '[MTLCompiler createVertexStageAndLinkPipelineWithFragment:', - '[MTLCompiler pipelineStateWithVariant:', - ] - ) - - # Run one interactive Vulkan test with validation enabled. - # - # TODO(matanlurey): https://github.com/flutter/flutter/issues/134852; enable - # more of the suite, and ideally we'd like to use Skia gold and take screen - # shots as well. - run_engine_executable( - build_dir, - 'impeller_unittests', - executable_filter, - shuffle_flags + [ - '--enable_vulkan_validation', - '--enable_playground', - '--playground_timeout_ms=4000', - '--gtest_filter="*ColorWheel*"', - ], - coverage=coverage, - extra_env=extra_env, - ) - - # Run the Flutter GPU test suite. - run_engine_executable( - build_dir, - 'impeller_dart_unittests', - executable_filter, - shuffle_flags + [ - '--enable_vulkan_validation', - # TODO(https://github.com/flutter/flutter/issues/145036) - # TODO(https://github.com/flutter/flutter/issues/142642) - '--gtest_filter=*Metal', - ], - coverage=coverage, - extra_env=extra_env, - ) - + del extra_env + # Impeller, and with it the interactive Metal/Vulkan tests, were removed + # from flutter_zero. def run_engine_benchmarks(build_dir, executable_filter): logger.info('Running Engine Benchmarks.') @@ -598,13 +502,8 @@ def run_engine_benchmarks(build_dir, executable_filter): run_engine_executable(build_dir, 'ui_benchmarks', executable_filter, icu_flags) - run_engine_executable(build_dir, 'display_list_builder_benchmarks', executable_filter, icu_flags) - run_engine_executable(build_dir, 'geometry_benchmarks', executable_filter, icu_flags) - if is_linux(): - run_engine_executable(build_dir, 'txt_benchmarks', executable_filter, icu_flags) - class FlutterTesterOptions(): @@ -752,7 +651,15 @@ def run_java_tests(executable_filter, android_variant='android_debug_unopt'): '--gradle-user-home=%s' % gradle_cache_dir, ] - env = dict(os.environ, ANDROID_HOME=android_home, JAVA_HOME=java_home()) + # Gradle fails if ANDROID_HOME and ANDROID_SDK_ROOT resolve to different + # SDK locations (CI images export ANDROID_SDK_ROOT to their own SDK), so + # both are pinned to the engine-provided SDK. + env = dict( + os.environ, + ANDROID_HOME=android_home, + ANDROID_SDK_ROOT=android_home, + JAVA_HOME=java_home(), + ) run_cmd(command, cwd=test_runner_dir, env=env) diff --git a/engine/src/flutter/tools/pkg/github_workflow_generator/artifact_tests.json b/engine/src/flutter/tools/pkg/github_workflow_generator/artifact_tests.json new file mode 100644 index 00000000..4de82def --- /dev/null +++ b/engine/src/flutter/tools/pkg/github_workflow_generator/artifact_tests.json @@ -0,0 +1,57 @@ +{ + "_comment": [ + "Defines special test jobs that download the full build output of", + "artifact-producing build jobs (no rebuilding) and run the engine", + "C++ unit tests against them.", + "", + "Each job downloads the out/ directory tar uploaded by the", + "build job named in `downloads` (every build job uploads its build", + "output). The tested build's ninja targets must include", + "`flutter:unittests` so that the *_unittests binaries are present in", + "the build dir; run_tests.py then discovers and runs them (--type", + "engine).", + "", + "For each entry in `tests`, run_tests.py runs with --variant, --type", + "and, when present, --android-variant / --ios-variant.", + "", + "The jobs below run the engine unittests for ci/host_debug on", + "linux/windows and for the debug/profile/release arm64 host builds", + "on macOS." + ], + "test_jobs": [ + { + "name": "ios_unit_engine_test", + "runs_on": "macos-latest", + "python": "python3", + "gclient": "slim", + "downloads": [ + "mac_ios_test_binaries_arm64" + ], + "tests": [ + { + "name": "iOS unit tests for ci/ios_test_binaries_arm64", + "variant": "ci/ios_test_binaries_arm64", + "ios_variant": "ci/ios_test_binaries_arm64", + "types": "objc" + } + ] + }, + { + "name": "android_java_engine_test", + "runs_on": "ubuntu-latest", + "python": "python3", + "gclient": "standard", + "downloads": [ + "linux_android_debug_arm64" + ], + "tests": [ + { + "name": "Android Java unit tests for ci/android_debug_arm64", + "variant": "ci/android_debug_arm64", + "android_variant": "ci/android_debug_arm64", + "types": "java" + } + ] + } + ] +} diff --git a/engine/src/flutter/tools/pkg/github_workflow_generator/lib/github_workflow_generator.dart b/engine/src/flutter/tools/pkg/github_workflow_generator/lib/github_workflow_generator.dart index 832930a5..08d9f6f1 100644 --- a/engine/src/flutter/tools/pkg/github_workflow_generator/lib/github_workflow_generator.dart +++ b/engine/src/flutter/tools/pkg/github_workflow_generator/lib/github_workflow_generator.dart @@ -70,6 +70,15 @@ class ArtifactPublisher { ); } + void registerTestJob(String jobName) { + _dependentTestJobs.add(jobName); + } + + /// Publishes everything this run produced. On staging pushes the artifacts + /// go to the production bucket, and the `latest_content_hash` pointer is + /// advanced. On pull requests everything goes under a unique per-run prefix + /// of the CI-only bucket instead - a disposable deployment that the + /// `remove_ci_artifacts` teardown job of the same run deletes afterwards. void writePublishJob(YamlWriterSection jobsSection) { if (_artifacts.isEmpty) { return; @@ -80,9 +89,13 @@ class ArtifactPublisher { run.writeln('shell: bash'); final needs = job.beginArray('needs'); _dependentJobs.forEach(needs.writeln); + _dependentTestJobs.forEach(needs.writeln); needs.writeln('guard'); job.write('runs-on', 'ubuntu-latest'); - job.write('if', r"${{ needs.guard.outputs.should_run == 'true' }}"); + job.write( + 'if', + r"${{ needs.guard.outputs.should_run == 'true' }}", + ); final steps = job.beginArray('steps'); { final step = steps.beginMap('name', 'Expose engine content hash'); @@ -108,31 +121,47 @@ class ArtifactPublisher { run.writeln('rm artifact-${artifact.id}/artifact_${artifact.id}.tar'); } } + { + // Selects the R2 destination for this run once for all publish + // steps: pull requests deploy under a unique per-run prefix of the + // CI-only bucket (disposable, the run's teardown job removes it); + // staging pushes deploy to the production bucket with no prefix and + // advance latest_content_hash. The same credential secrets have write + // access to both buckets. + final step = steps.beginMap('name', 'Select the R2 target'); + step.write('id', 'r2_target'); + final runEnv = step.beginMap('env'); + runEnv.writeln('R2_ENGINE_BUCKET: flutter-zero-engine'); + runEnv.writeln('R2_CI_BUCKET: $ciBucketName'); + final run = step.beginMap('run', '|'); + run.writeln(r'if [ "${GITHUB_EVENT_NAME}" = "pull_request" ]; then'); + run.writeln(r' echo "bucket=$R2_CI_BUCKET" >> $GITHUB_OUTPUT'); + run.writeln(r' echo "prefix=pr-${GITHUB_RUN_ID}/" >> $GITHUB_OUTPUT'); + run.writeln(r'else'); + run.writeln(r' echo "bucket=$R2_ENGINE_BUCKET" >> $GITHUB_OUTPUT'); + run.writeln(r' echo "prefix=" >> $GITHUB_OUTPUT'); + run.writeln(r'fi'); + } for (final artifact in _artifacts) { final name = path.basename(artifact.sourcePath); - final step = steps.beginMap('name', 'Publish ${artifact.outputPath}/$name'); - step.write('uses', 'ryand56/r2-upload-action@b801a390acbdeb034c5e684ff5e1361c06639e7c'); - final w = step.beginMap('with'); - w.write('r2-account-id', r'${{ secrets.R2_ACCOUNT_ID }}'); - w.write('r2-access-key-id', r'${{ secrets.R2_ACCESS_KEY_ID }}'); - w.write('r2-secret-access-key', r'${{ secrets.R2_SECRET_ACCESS_KEY }}'); - w.write('r2-bucket', r'${{ env.R2_BUCKET }}'); - w.write('source-dir', 'artifact-${artifact.id}/'); - if (name.contains('flutter.io')) { - // android - w.write( - 'destination-dir', - './', - ); - } else { - w.write( - 'destination-dir', - 'flutter_infra_release/flutter/\${{ steps.engine_content_hash.outputs.value }}/${artifact.outputPath}', - ); - } + // Pull requests deploy under the selected per-run prefix; staging + // pushes deploy (as before) keyed directly by the engine content hash + // with no prefix. + final baseDestination = name.contains('flutter.io') + // android + ? '' + : 'flutter_infra_release/flutter/\${{ steps.engine_content_hash.outputs.value }}/${artifact.outputPath}'; + _writeR2UploadStep( + steps, + name: 'Publish ${artifact.outputPath}/$name', + bucket: '\${{ steps.r2_target.outputs.bucket }}', + destinationDir: '\${{ steps.r2_target.outputs.prefix }}$baseDestination', + sourceDir: 'artifact-${artifact.id}/', + ); } { final step = steps.beginMap('name', 'Create latest_content_hash.txt'); + step.write('if', r"${{ github.event_name != 'pull_request' }}"); final run = step.beginMap('run', '|'); run.writeln(r'mkdir -p latest_content_hash'); run.writeln( @@ -140,21 +169,47 @@ class ArtifactPublisher { ); } { - final step = steps.beginMap('name', 'Publish latest_content_hash.txt'); - step.write('uses', 'ryand56/r2-upload-action@b801a390acbdeb034c5e684ff5e1361c06639e7c'); - final w = step.beginMap('with'); - w.write('r2-account-id', r'${{ secrets.R2_ACCOUNT_ID }}'); - w.write('r2-access-key-id', r'${{ secrets.R2_ACCESS_KEY_ID }}'); - w.write('r2-secret-access-key', r'${{ secrets.R2_SECRET_ACCESS_KEY }}'); - w.write('r2-bucket', r'${{ env.R2_BUCKET }}'); - w.write('source-dir', 'latest_content_hash/'); - w.write( - 'destination-dir', - 'flutter_infra_release/flutter/', + _writeR2UploadStep( + steps, + name: 'Publish latest_content_hash.txt', + ifCondition: r"${{ github.event_name != 'pull_request' }}", + bucket: '\${{ steps.r2_target.outputs.bucket }}', + destinationDir: 'flutter_infra_release/flutter/', + sourceDir: 'latest_content_hash/', + id: 'publish_latest_content_hash', ); } } + void _writeR2UploadStep( + YamlWriterSection steps, { + required String name, + required String bucket, + required String destinationDir, + required String sourceDir, + String? ifCondition, + String? id, + }) { + final step = steps.beginMap('name', name); + if (ifCondition != null) { + step.write('if', ifCondition); + } + if (id != null) { + step.write('id', id); + } + step.write('uses', r2UploadAction); + final w = step.beginMap('with'); + w.write('r2-account-id', '\${{ secrets.R2_ACCOUNT_ID }}'); + w.write('r2-access-key-id', '\${{ secrets.R2_ACCESS_KEY_ID }}'); + w.write('r2-secret-access-key', '\${{ secrets.R2_SECRET_ACCESS_KEY }}'); + w.write('r2-bucket', bucket); + w.write('source-dir', sourceDir); + w.write('destination-dir', destinationDir.isEmpty ? './' : destinationDir); + } + + static const r2UploadAction = 'ryand56/r2-upload-action@b801a390acbdeb034c5e684ff5e1361c06639e7c'; + + final _dependentTestJobs = {}; final _dependentJobs = {}; final _artifacts = <_Artifact>[]; int _count = 0; @@ -171,10 +226,31 @@ class YamlWriterSection { } void write(String label, String value) { - final line = value.isEmpty ? '$label:' : '$label: $value'; + final line = value.isEmpty ? '$label:' : '$label: ${_escapeScalar(value)}'; writeln(line); } + static String _escapeScalar(String value) { + // '|' is written bare for run-step block scalars (beginMap('run', '|')). + if (value == '|') { + return value; + } + // A plain (unquoted) scalar must not look like a comment, a nested map, or + // contain characters that terminate the scalar early (':' followed by + // whitespace, or a ' #' comment start). + final problematic = + value.startsWith(' ') || + value.endsWith(' ') || + value.contains(': ') || + value.endsWith(':') || + value.contains(' #'); + if (!problematic) { + return value; + } + final escaped = value.replaceAll("'", "''"); + return "'$escaped'"; + } + YamlWriterSection beginMap(String label, [String value = '']) { write(label, value); final section = YamlWriterSection._(writer, isArray: false); @@ -198,9 +274,11 @@ class BuildConfigWriter { required BuilderConfig config, required YamlWriterSection jobsSections, required ArtifactPublisher artifactPublisher, + required Set testBuildOutputs, }) : _config = config, _jobsSections = jobsSections, - _artifactPublisher = artifactPublisher; + _artifactPublisher = artifactPublisher, + _testBuildOutputs = testBuildOutputs; void write() { for (final build in _config.builds) { @@ -229,25 +307,49 @@ class BuildConfigWriter { run.writeln('./flutter/bin/et build --config ${build.name}'); } } + // Host builds that compile the unit test binaries run them in-place - + // no artifact download needed. + if (build.ninja.targets.contains('flutter:unittests')) { + final bool isWindows = _getRunnerForBuilder(build).startsWith('windows'); + final step = steps.beginMap('name', 'Run engine unit tests'); + final run = step.beginMap('run', '|'); + run.writeln('cd engine/src'); + // Windows runners only provide an unprefixed `python` executable. + run.writeln('${isWindows ? 'python' : 'python3'} flutter/testing/run_tests.py \\'); + // Forward slashes: the step runs under bash even on Windows + // runners, where a backslash would escape the next character. + run.writeln(' --variant ${build.name.replaceAll(r'\', '/')} \\'); + run.writeln(' --type engine \\'); + if (!isWindows) { + run.writeln(' --engine-capture-core-dump'); + } + } for (final generator in build.generators) { _writeBuildTask(steps, generator); } - // For global generators we need to upload artifacts so that we can use them - // in dependent jobs. - if (_config.generators.isNotEmpty) { - { - final step = steps.beginMap('name', 'Tar build files'); - final run = step.beginMap('run', '|'); - run.writeln('tar -cvf ${_nameForBuild(build)}.tar engine/src/out/${build.name}'); - } - { - final step = steps.beginMap('name', 'Upload build files'); - step.write('uses', 'actions/upload-artifact@v4'); - final w = step.beginMap('with'); - w.write('name', 'artifacts-${_nameForBuild(build)}-\${{ steps.engine_content_hash.outputs.value }}'); - w.write('path', '${_nameForBuild(build)}.tar'); - w.write('retention-days', '1'); - } + // Full build outputs are needed only by global packaging or test jobs. + if (_config.generators.isNotEmpty || _config.archives.isNotEmpty || + _testBuildOutputs.contains(_nameForBuild(build))) { + { + final step = steps.beginMap('name', 'Tar build files'); + final run = step.beginMap('run', '|'); + // The out dir is derived from the ninja config (which may lack the + // "ci/" prefix, e.g. the web wasm_release build), not from the build + // name. + final outDir = build.ninja.config.isEmpty + ? build.name.replaceAll(r'\', '/') + : build.ninja.config.replaceAll(r'\', '/'); + run.writeln('find engine/src/out/$outDir -type l -lname "/*" -delete || true'); + run.writeln('tar -cvf ${_nameForBuild(build)}.tar engine/src/out/$outDir'); + } + { + final step = steps.beginMap('name', 'Upload build files'); + step.write('uses', 'actions/upload-artifact@v4'); + final w = step.beginMap('with'); + w.write('name', 'artifacts-${_nameForBuild(build)}-\${{ steps.engine_content_hash.outputs.value }}'); + w.write('path', '${_nameForBuild(build)}.tar'); + w.write('retention-days', '1'); + } } for (final archive in build.archives) { for (final assetPath in archive.includePaths) { @@ -328,12 +430,7 @@ class BuildConfigWriter { w.write('path', "''"); } { - final step = steps.beginMap('name', 'Set up depot_tools'); - step.write('if', "runner.os != 'Windows'"); - final run = step.beginMap('run', '|'); - run.writeln(r'git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git $HOME/depot_tools'); - run.writeln('# Append depot_tools to the PATH for subsequent steps'); - run.writeln(r'echo "$HOME/depot_tools" >> $GITHUB_PATH'); + _writeDepotToolsStep(steps, ifCondition: "runner.os != 'Windows'", isWindows: false); } if (_config.generators.any((b) => b.name == 'api-documentation')) { final step = steps.beginMap('name', 'Install doxygen'); @@ -352,13 +449,7 @@ class BuildConfigWriter { ); } { - final step = steps.beginMap('name', 'Set up depot_tools'); - step.write('if', "runner.os == 'Windows'"); - final run = step.beginMap('run', '|'); - run.writeln(r'git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git $HOME/depot_tools'); - run.writeln('# Append depot_tools to the PATH for subsequent steps'); - run.writeln(r'DEPOT_TOOLS_WIN=$(cygpath -w "$HOME/depot_tools")'); - run.writeln(r'echo "$DEPOT_TOOLS_WIN" >> $GITHUB_PATH'); + _writeDepotToolsStep(steps, ifCondition: "runner.os == 'Windows'", isWindows: true); } { final step = steps.beginMap('name', 'Generate engine content hash'); @@ -370,7 +461,14 @@ class BuildConfigWriter { { final step = steps.beginMap('name', 'Copy gclient file'); final run = step.beginMap('run', '|'); - if (path.basename(_config.path).contains('android')) { + // Android toolchains are only fetched when the standard gclient file + // is used. This must cover configs that build android targets even + // when the config file itself is not named after android (e.g. + // linux_unopt.json). + final needsAndroidDeps = + path.basename(_config.path).contains('android') || + _config.builds.any((build) => build.gn.contains('--android')); + if (needsAndroidDeps) { run.writeln('cp engine/scripts/standard.gclient .gclient'); } else if (path.basename(_config.path).contains('web')) { run.writeln('cp engine/scripts/web.gclient .gclient'); @@ -392,6 +490,8 @@ class BuildConfigWriter { return 'FLUTTER_PREBUILT_ENGINE_VERSION=\${{ needs.guard.outputs.latest_content_hash }} ../../bin/dart $script'; } else if (language == 'python3') { return 'python3 $script'; + } else if (language == 'python') { + return 'python $script'; } else if (language == 'bash' || language == '') { return script; } else { @@ -471,8 +571,288 @@ class BuildConfigWriter { final BuilderConfig _config; final YamlWriterSection _jobsSections; final ArtifactPublisher _artifactPublisher; + final Set _testBuildOutputs; +} + +/// A single test run inside an artifact test job. +class _ArtifactTest { + const _ArtifactTest({ + required this.name, + required this.variant, + required this.types, + this.androidVariant, + this.iosVariant, + }); + + final String name; + final String variant; + final String types; + + final String? androidVariant; + final String? iosVariant; +} + +/// A generated test job that runs against build outputs uploaded by regular +/// build jobs, without rebuilding anything. +class _ArtifactTestJob { + const _ArtifactTestJob({ + required this.name, + required this.runsOn, + required this.python, + required this.gclient, + required this.downloads, + required this.tests, + }); + + final String name; + final String runsOn; + + /// Python executable used to invoke run_tests.py (GitHub Windows runners + /// only provide an unprefixed `python`). + final String python; + + /// Which gclient file to sync with (slim, standard or web). + final String gclient; + + /// Names of build jobs whose full build-output tar is downloaded and + /// extracted before the tests run. + final List downloads; + final List<_ArtifactTest> tests; + + static _ArtifactTest _testFromJson(Map map) { + final variant = map['variant']! as String; + final types = map['types']! as String; + final androidVariant = map['android_variant'] as String?; + final iosVariant = map['ios_variant'] as String?; + return _ArtifactTest( + name: (map['name'] as String?) ?? 'for $variant', + variant: variant, + types: types, + androidVariant: androidVariant, + iosVariant: iosVariant, + ); + } + + static _ArtifactTestJob fromJson(Map map) { + final name = map['name']! as String; + final runsOn = map['runs_on']! as String; + final python = map['python'] as String? ?? 'python3'; + final gclient = map['gclient'] as String? ?? 'slim'; + final downloads = (map['downloads'] as List? ?? []).cast(); + final tests = (map['tests'] as List? ?? []).cast>().map(_testFromJson).toList(); + if (downloads.isEmpty) { + throw Exception('Artifact test job $name has no downloads'); + } + if (tests.isEmpty) { + throw Exception('Artifact test job $name has no tests'); + } + return _ArtifactTestJob( + name: name, + runsOn: runsOn, + python: python, + gclient: gclient, + downloads: downloads, + tests: tests, + ); + } +} + +/// Emits a depot_tools setup step: cleans up any checkout left corrupt by a +/// failed previous attempt (the same HOME is reused across job retries), then +/// clones with retries - clones from chromium.googlesource.com occasionally +/// fail mid-transfer and the bare command is the most common source of CI +/// flake. +void _writeDepotToolsStep( + YamlWriterSection steps, { + String? ifCondition, + required bool isWindows, +}) { + final step = steps.beginMap('name', 'Set up depot_tools'); + if (ifCondition != null) { + step.write('if', ifCondition); + } + final run = step.beginMap('run', '|'); + run.writeln(r'rm -rf "$HOME/depot_tools"'); + run.writeln('for attempt in 1 2 3; do'); + run.writeln( + r' git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git "$HOME/depot_tools" && break', + ); + run.writeln(r' rm -rf "$HOME/depot_tools"'); + run.writeln(r' echo "depot_tools clone failed (attempt $attempt), retrying..."'); + run.writeln(' sleep 5'); + run.writeln('done'); + run.writeln(r'test -d "$HOME/depot_tools/.git"'); + run.writeln('# Append depot_tools to the PATH for subsequent steps'); + if (isWindows) { + run.writeln(r'DEPOT_TOOLS_WIN=$(cygpath -w "$HOME/depot_tools")'); + run.writeln(r'echo "$DEPOT_TOOLS_WIN" >> $GITHUB_PATH'); + } else { + run.writeln(r'echo "$HOME/depot_tools" >> $GITHUB_PATH'); + } +} + +/// Emits jobs that run tests against build outputs uploaded by the +/// artifact-producing build jobs (no rebuilding). The job specs come from the +/// JSON files passed via `--artifact-tests`. +List<_ArtifactTestJob> _readArtifactTestJobs(List specFiles) { + final jobs = <_ArtifactTestJob>[]; + for (final specFile in specFiles) { + final content = File(specFile).readAsStringSync(); + final map = jsonDecode(content) as Map; + final jobMaps = (map['test_jobs'] as List? ?? []).cast>(); + if (jobMaps.isEmpty) { + throw Exception('Artifact test spec $specFile has no test_jobs'); + } + jobs.addAll(jobMaps.map(_ArtifactTestJob.fromJson)); + } + return jobs; +} + +void _writeArtifactTestJobs( + YamlWriterSection jobsSection, + ArtifactPublisher artifactPublisher, + List<_ArtifactTestJob> jobs, +) { + const gclientFileFor = { + 'slim': 'slim.gclient', + 'standard': 'standard.gclient', + 'web': 'web.gclient', + }; + for (final job in jobs) { + final generated = jobsSection.beginMap(job.name); + generated.write('runs-on', job.runsOn); + final defaults = generated.beginMap('defaults'); + final runDefaults = defaults.beginMap('run'); + runDefaults.writeln('shell: bash'); + final needs = generated.beginArray('needs'); + job.downloads.forEach(needs.writeln); + needs.writeln('guard'); + generated.write('if', r"${{ needs.guard.outputs.should_run == 'true' }}"); + final steps = generated.beginArray('steps'); + { + final step = steps.beginMap('name', 'Checkout the repository'); + step.write('uses', 'actions/checkout@v4'); + final w = step.beginMap('with'); + w.write('path', "''"); + } + { + _writeDepotToolsStep(steps, isWindows: job.runsOn.startsWith('windows')); + } + { + final step = steps.beginMap('name', 'Expose engine content hash'); + step.write('id', 'engine_content_hash'); + final run = step.beginMap('run', '|'); + run.writeln(r'engine_content_hash=${{ needs.guard.outputs.engine_content_hash }}'); + run.writeln(r'echo "value=${engine_content_hash}" >> $GITHUB_OUTPUT'); + } + { + final step = steps.beginMap('name', 'Copy gclient file'); + final run = step.beginMap('run', '|'); + final gclientFile = gclientFileFor[job.gclient]; + if (gclientFile == null) { + throw Exception('Unknown gclient flavor ${job.gclient} in artifact test job ${job.name}'); + } + run.writeln('cp engine/scripts/$gclientFile .gclient'); + } + { + final step = steps.beginMap('name', 'GClient sync'); + final run = step.beginMap('run', '|'); + run.writeln('gclient sync -D --no-history --shallow --with_branch_heads'); + } + for (final download in job.downloads) { + { + final step = steps.beginMap('name', 'Download Artifacts from $download'); + step.write('uses', 'actions/download-artifact@v4'); + final w = step.beginMap('with'); + w.write('name', 'artifacts-$download-\${{ steps.engine_content_hash.outputs.value }}'); + } + { + final step = steps.beginMap('name', 'Extract Artifacts from $download'); + final run = step.beginMap('run', '|'); + run.writeln('tar -xvf $download.tar'); + run.writeln('rm $download.tar'); + } + } + for (final test in job.tests) { + final step = steps.beginMap('name', 'Run test ${test.name}'); + final run = step.beginMap('run', '|'); + run.writeln('cd engine/src'); + run.writeln('${job.python} flutter/testing/run_tests.py \\'); + run.writeln(' --variant ${test.variant} \\'); + run.writeln(' --type ${test.types} \\'); + if (test.androidVariant != null) { + run.writeln(' --android-variant ${test.androidVariant} \\'); + } + if (test.iosVariant != null) { + run.writeln(' --ios-variant ${test.iosVariant} \\'); + } + // --engine-capture-core-dump is not supported on Windows runners. + if (!job.runsOn.startsWith('windows')) { + run.writeln(' --engine-capture-core-dump'); + } + } + artifactPublisher.registerTestJob(job.name); + } +} + +/// Emits the job that invokes the smoke test workflow with the per-run prefix +/// of this deployment (the same run). Only for pull requests; on staging +/// pushes the smoke test flow is exercised by the call-smoke-test companion +/// workflow instead. The smoke test workflow itself is call-only. +void _writeSmokeTestInvocationJob(YamlWriterSection jobsSection) { + final job = jobsSection.beginMap('smoke_test'); + job.write('name', 'Run the smoke test'); + job.write('uses', './.github/workflows/smoke-test.yml'); + final needs = job.beginArray('needs'); + needs.writeln('publish_artifacts'); + job.write( + 'if', + r"${{ github.event_name == 'pull_request' }}", + ); + final withNode = job.beginMap('with'); + withNode.write('run_id', r'${{ github.run_id }}'); } +/// Emits the teardown job of the CI-only artifacts bucket: the per-run prefix +/// this run published is removed again, unconditionally (always(), pass, +/// fail, cancel - the run's deployment is disposable). +void _writeCiBucketTeardownJob( + YamlWriterSection jobsSection, + Set targets, +) { + final job = jobsSection.beginMap('remove_ci_artifacts'); + job.write('runs-on', 'ubuntu-latest'); + final needs = job.beginArray('needs'); + targets.forEach(needs.writeln); + job.write('if', 'always()'); + final steps = job.beginArray('steps'); + { + final step = steps.beginMap('name', 'Remove the run prefix from the CI bucket'); + step.write('if', r"${{ github.event_name == 'pull_request' }}"); + final runEnv = step.beginMap('env'); + runEnv.writeln( + 'AWS_ACCESS_KEY_ID: \${{ secrets.R2_ACCESS_KEY_ID }}', + ); + runEnv.writeln( + 'AWS_SECRET_ACCESS_KEY: \${{ secrets.R2_SECRET_ACCESS_KEY }}', + ); + runEnv.writeln( + 'AWS_ENDPOINT_URL_S3: $r2S3Endpoint', + ); + runEnv.writeln('AWS_DEFAULT_REGION: auto'); + final run = step.beginMap('run', '|'); + run.writeln( + 'aws s3 rm s3://$ciBucketName/pr-\${{ github.run_id }}/ --recursive', + ); + } +} + +/// The CI-only artifacts bucket: pull request deployments are published under +/// a unique per-run prefix here, giving short-lived, disposable copies that +/// never touch the production buckets. +const ciBucketName = 'flutter-zero-ci'; +const r2S3Endpoint = 'https://b468378afe5657ffecccb682fe82ccac.r2.cloudflarestorage.com'; + void _writeGuardJob(YamlWriterSection jobsSection) { final job = jobsSection.beginMap('guard'); job.write('runs-on', 'ubuntu-latest'); @@ -538,6 +918,13 @@ void main(List arguments) { valueHelp: 'path', defaultsTo: '', ); + parser.addMultiOption( + 'artifact-tests', + abbr: 't', + help: 'Path to a JSON file with artifact test job specs (test_jobs).', + valueHelp: 'path', + defaultsTo: [], + ); final ArgResults args; try { @@ -555,6 +942,9 @@ void main(List arguments) { } final yamlWriter = YamlWriter(); + final artifactTestSpecs = (args['artifact-tests'] as List?) ?? const []; + final artifactTestJobs = _readArtifactTestJobs(artifactTestSpecs); + final testBuildOutputs = artifactTestJobs.expand((job) => job.downloads).toSet(); final root = yamlWriter.root; root.writeln('# This file is generated through `scripts/update_github_workflow.sh.`'); root.writeln('# Do not edit directly.'); @@ -562,12 +952,12 @@ void main(List arguments) { final on = root.beginMap('on'); final push = on.beginMap('push'); - push.write('branches', '["master", "staging"]'); + push.write('branches', '["staging"]'); + on.beginMap('pull_request'); final env = root.beginMap('env'); env.write('DEPOT_TOOLS_WIN_TOOLCHAIN', '0'); env.write('FLUTTER_PREBUILT_DART_SDK', '1'); - env.write('R2_BUCKET', 'flutter-zero-engine'); env.write('ENGINE_CHECKOUT_PATH', r'${{ github.workspace }}/engine'); final jobs = root.beginMap('jobs'); @@ -584,11 +974,19 @@ void main(List arguments) { config: buildConfig, jobsSections: jobs, artifactPublisher: artifactPublisher, + testBuildOutputs: testBuildOutputs, ); writer.write(); } + _writeArtifactTestJobs(jobs, artifactPublisher, artifactTestJobs); + artifactPublisher.writePublishJob(jobs); + _writeSmokeTestInvocationJob(jobs); + // The per-run prefix this run published to the CI bucket is removed + // afterwards, unconditionally (always(), pass, fail, cancel - the run's + // deployment is disposable). + _writeCiBucketTeardownJob(jobs, const {'publish_artifacts', 'smoke_test'}); if (args['output'] != '') { final outputFile = File(args['output'] as String); diff --git a/packages/flutter_tools/lib/src/base/user_messages.dart b/packages/flutter_tools/lib/src/base/user_messages.dart index 608e75b5..40d56b8f 100644 --- a/packages/flutter_tools/lib/src/base/user_messages.dart +++ b/packages/flutter_tools/lib/src/base/user_messages.dart @@ -161,8 +161,8 @@ class UserMessages { String pkgConfigTooOld(String minimumVersion) => 'pkg-config $minimumVersion or later is required.'; String get gtkLibrariesMissing => - 'GTK 3.0 development libraries are required for Linux development.\n' - 'They are likely available from your distribution (e.g.: apt install libgtk-3-dev)'; + 'GLib development libraries are required for Linux development.\n' + 'They are likely available from your distribution (e.g.: apt install libglib2.0-dev)'; String get eglinfoMissing => "Unable to access driver information using 'eglinfo'.\n" 'It is likely available from your distribution (e.g.: apt install mesa-utils)'; diff --git a/packages/flutter_tools/lib/src/build_system/targets/web.dart b/packages/flutter_tools/lib/src/build_system/targets/web.dart index 9f5a78f4..12ee35e1 100644 --- a/packages/flutter_tools/lib/src/build_system/targets/web.dart +++ b/packages/flutter_tools/lib/src/build_system/targets/web.dart @@ -684,9 +684,8 @@ class WebReleaseBundle extends Target { targetPlatform: TargetPlatform.web_javascript, buildMode: buildMode, ); - final Depfile bundledDepfile = _bundleLocalRobotoFallback(environment, depfile); final DepfileService depfileService = environment.depFileService; - depfileService.writeToFile(bundledDepfile, environment.buildDir.childFile('flutter_assets.d')); + depfileService.writeToFile(depfile, environment.buildDir.childFile('flutter_assets.d')); final Directory webResources = environment.projectDir.childDirectory('web'); final List inputResourceFiles = webResources @@ -731,61 +730,9 @@ class WebReleaseBundle extends Target { environment.outputDir.childFile('version.json').writeAsStringSync(jsonEncode(versionInfo)); } - Depfile _bundleLocalRobotoFallback(Environment environment, Depfile depfile) { - if (environment.defines[kUseLocalCanvasKitFlag] != 'true') { - return depfile; - } - - final File fontManifestFile = environment.outputDir - .childDirectory('assets') - .childFile(_kFontManifestJsonFile); - final manifestJson = fontManifestFile.existsSync() - ? (jsonDecode(fontManifestFile.readAsStringSync()) as List) - : []; - - final bool hasRobotoFamily = manifestJson.any((Object? entry) { - return entry is Map && entry['family'] == _kBundledFallbackRobotoFamily; - }); - if (hasRobotoFamily) { - return depfile; - } - - final File sourceRobotoFont = environment.fileSystem.file( - environment.fileSystem.path.join( - Cache.flutterRoot!, - 'engine', - 'src', - 'flutter', - 'txt', - 'third_party', - 'fonts', - 'Roboto-Regular.ttf', - ), - ); - if (!sourceRobotoFont.existsSync()) { - throwToolExit('Failed to find the bundled Roboto font at ${sourceRobotoFont.path}.'); - } - - manifestJson.add({ - 'family': _kBundledFallbackRobotoFamily, - 'fonts': >[ - {'asset': _kBundledFallbackRobotoAsset}, - ], - }); - fontManifestFile.parent.createSync(recursive: true); - fontManifestFile.writeAsStringSync(jsonEncode(manifestJson)); - - final File bundledRobotoFont = environment.outputDir - .childDirectory('assets') - .childFile(_kBundledFallbackRobotoAsset); - bundledRobotoFont.parent.createSync(recursive: true); - sourceRobotoFont.copySync(bundledRobotoFont.path); - - return Depfile( - [...depfile.inputs, sourceRobotoFont], - [...depfile.outputs, fontManifestFile, bundledRobotoFont], - ); - } + // flutter_zero never bundles the Roboto fallback font (headless engine, no + // txt/third_party/fonts tree), so the upstream `_bundleLocalRobotoFallback` + // hook is removed entirely. } class WebTemplatedFiles extends Target { diff --git a/packages/flutter_tools/lib/src/linux/linux_doctor.dart b/packages/flutter_tools/lib/src/linux/linux_doctor.dart index 2900f7da..2024b92c 100644 --- a/packages/flutter_tools/lib/src/linux/linux_doctor.dart +++ b/packages/flutter_tools/lib/src/linux/linux_doctor.dart @@ -137,7 +137,7 @@ class LinuxDoctorValidator extends DoctorValidator { kPkgConfigBinary: Version(0, 29, 0), }; - final _requiredGtkLibraries = ['gtk+-3.0', 'glib-2.0', 'gio-2.0']; + final _requiredGLibLibraries = ['glib-2.0', 'gio-2.0']; @override Future validateImpl() async { @@ -234,7 +234,7 @@ class LinuxDoctorValidator extends DoctorValidator { // Messages for libraries. { var libraryMissing = false; - for (final String library in _requiredGtkLibraries) { + for (final String library in _requiredGLibLibraries) { if (!await _libraryIsPresent(library)) { libraryMissing = true; break; diff --git a/packages/flutter_tools/templates/app/linux.tmpl/CMakeLists.txt.tmpl b/packages/flutter_tools/templates/app/linux.tmpl/CMakeLists.txt.tmpl index f710aa3d..ddcafc32 100644 --- a/packages/flutter_tools/templates/app/linux.tmpl/CMakeLists.txt.tmpl +++ b/packages/flutter_tools/templates/app/linux.tmpl/CMakeLists.txt.tmpl @@ -5,7 +5,7 @@ project(runner LANGUAGES CXX) # The name of the executable created for the application. Change this to change # the on-disk name of your application. set(BINARY_NAME "{{projectName}}") -# The unique GTK application identifier for this application. See: +# The unique application identifier for this application. See: # https://wiki.gnome.org/HowDoI/ChooseApplicationID set(APPLICATION_ID "{{linuxIdentifier}}") @@ -52,7 +52,8 @@ add_subdirectory(${FLUTTER_MANAGED_DIR}) # System-level dependencies. find_package(PkgConfig REQUIRED) -pkg_check_modules(GTK REQUIRED IMPORTED_TARGET gtk+-3.0) +pkg_check_modules(GLIB REQUIRED IMPORTED_TARGET glib-2.0) +pkg_check_modules(GIO REQUIRED IMPORTED_TARGET gio-2.0) # Application build; see runner/CMakeLists.txt. add_subdirectory("runner") diff --git a/packages/flutter_tools/templates/app/linux.tmpl/flutter/CMakeLists.txt b/packages/flutter_tools/templates/app/linux.tmpl/flutter/CMakeLists.txt index d5bd0164..5fc74f9c 100644 --- a/packages/flutter_tools/templates/app/linux.tmpl/flutter/CMakeLists.txt +++ b/packages/flutter_tools/templates/app/linux.tmpl/flutter/CMakeLists.txt @@ -22,7 +22,6 @@ endfunction() # === Flutter Library === # System-level dependencies. find_package(PkgConfig REQUIRED) -pkg_check_modules(GTK REQUIRED IMPORTED_TARGET gtk+-3.0) pkg_check_modules(GLIB REQUIRED IMPORTED_TARGET glib-2.0) pkg_check_modules(GIO REQUIRED IMPORTED_TARGET gio-2.0) @@ -63,7 +62,6 @@ target_include_directories(flutter INTERFACE ) target_link_libraries(flutter INTERFACE "${FLUTTER_LIBRARY}") target_link_libraries(flutter INTERFACE - PkgConfig::GTK PkgConfig::GLIB PkgConfig::GIO ) diff --git a/packages/flutter_tools/templates/app/linux.tmpl/runner/CMakeLists.txt b/packages/flutter_tools/templates/app/linux.tmpl/runner/CMakeLists.txt index e97dabc7..bf63b0bd 100644 --- a/packages/flutter_tools/templates/app/linux.tmpl/runner/CMakeLists.txt +++ b/packages/flutter_tools/templates/app/linux.tmpl/runner/CMakeLists.txt @@ -21,6 +21,6 @@ add_definitions(-DAPPLICATION_ID="${APPLICATION_ID}") # Add dependency libraries. Add any application-specific dependencies here. target_link_libraries(${BINARY_NAME} PRIVATE flutter) -target_link_libraries(${BINARY_NAME} PRIVATE PkgConfig::GTK) +target_link_libraries(${BINARY_NAME} PRIVATE PkgConfig::GLIB PkgConfig::GIO) target_include_directories(${BINARY_NAME} PRIVATE "${CMAKE_SOURCE_DIR}") diff --git a/packages/flutter_tools/templates/app/linux.tmpl/runner/my_application.cc.tmpl b/packages/flutter_tools/templates/app/linux.tmpl/runner/my_application.cc.tmpl index 6ff97760..8a5eddb8 100644 --- a/packages/flutter_tools/templates/app/linux.tmpl/runner/my_application.cc.tmpl +++ b/packages/flutter_tools/templates/app/linux.tmpl/runner/my_application.cc.tmpl @@ -1,19 +1,16 @@ #include "my_application.h" #include -#ifdef GDK_WINDOWING_X11 -#include -#endif #include "flutter/generated_plugin_registrant.h" struct _MyApplication { - GtkApplication parent_instance; + GApplication parent_instance; char** dart_entrypoint_arguments; FlEngine *engine; }; -G_DEFINE_TYPE(MyApplication, my_application, GTK_TYPE_APPLICATION) +G_DEFINE_TYPE(MyApplication, my_application, G_TYPE_APPLICATION) // Implements GApplication::activate. static void my_application_activate(GApplication *application) { @@ -95,7 +92,7 @@ static void my_application_init(MyApplication* self) {} MyApplication* my_application_new() { // Set the program name to the application ID, which helps various systems - // like GTK and desktop environments map this running application to its + // like desktop environments map this running application to its // corresponding .desktop file. This ensures better integration by allowing // the application to be recognized beyond its binary name. g_set_prgname(APPLICATION_ID); diff --git a/packages/flutter_tools/templates/app/linux.tmpl/runner/my_application.h b/packages/flutter_tools/templates/app/linux.tmpl/runner/my_application.h index db16367a..43759e8c 100644 --- a/packages/flutter_tools/templates/app/linux.tmpl/runner/my_application.h +++ b/packages/flutter_tools/templates/app/linux.tmpl/runner/my_application.h @@ -1,13 +1,13 @@ #ifndef FLUTTER_MY_APPLICATION_H_ #define FLUTTER_MY_APPLICATION_H_ -#include +#include G_DECLARE_FINAL_TYPE(MyApplication, my_application, MY, APPLICATION, - GtkApplication) + GApplication) /** * my_application_new: diff --git a/packages/flutter_tools/templates/plugin/linux.tmpl/CMakeLists.txt.tmpl b/packages/flutter_tools/templates/plugin/linux.tmpl/CMakeLists.txt.tmpl index 2d8110fe..eb1a2ddf 100644 --- a/packages/flutter_tools/templates/plugin/linux.tmpl/CMakeLists.txt.tmpl +++ b/packages/flutter_tools/templates/plugin/linux.tmpl/CMakeLists.txt.tmpl @@ -39,7 +39,7 @@ target_compile_definitions(${PLUGIN_NAME} PRIVATE FLUTTER_PLUGIN_IMPL) target_include_directories(${PLUGIN_NAME} INTERFACE "${CMAKE_CURRENT_SOURCE_DIR}/include") target_link_libraries(${PLUGIN_NAME} PRIVATE flutter) -target_link_libraries(${PLUGIN_NAME} PRIVATE PkgConfig::GTK) +target_link_libraries(${PLUGIN_NAME} PRIVATE PkgConfig::GLIB PkgConfig::GIO) # List of absolute paths to libraries that should be bundled with the plugin. # This list could contain prebuilt libraries, or libraries created by an @@ -83,7 +83,7 @@ add_executable(${TEST_RUNNER} apply_standard_settings(${TEST_RUNNER}) target_include_directories(${TEST_RUNNER} PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}") target_link_libraries(${TEST_RUNNER} PRIVATE flutter) -target_link_libraries(${TEST_RUNNER} PRIVATE PkgConfig::GTK) +target_link_libraries(${TEST_RUNNER} PRIVATE PkgConfig::GLIB PkgConfig::GIO) target_link_libraries(${TEST_RUNNER} PRIVATE gtest_main gmock) # Enable automatic test discovery. diff --git a/packages/flutter_tools/templates/template_manifest.json b/packages/flutter_tools/templates/template_manifest.json index 0765605b..e6e08d90 100644 --- a/packages/flutter_tools/templates/template_manifest.json +++ b/packages/flutter_tools/templates/template_manifest.json @@ -27,6 +27,7 @@ "templates/app/android-java.tmpl/build.gradle.kts.tmpl", "templates/app/android-java.tmpl/projectName_android.iml.tmpl", "templates/app/android-kotlin.tmpl/app/build.gradle.kts.tmpl", + "templates/app/android-kotlin.tmpl/app/src/main/kotlin/androidIdentifier/Application.kt.tmpl", "templates/app/android-kotlin.tmpl/app/src/main/kotlin/androidIdentifier/MainActivity.kt.tmpl", "templates/app/android-kotlin.tmpl/build.gradle.kts.tmpl", "templates/app/android-kotlin.tmpl/projectName_android.iml.tmpl", diff --git a/packages/flutter_tools/test/general.shard/linux/linux_doctor_test.dart b/packages/flutter_tools/test/general.shard/linux/linux_doctor_test.dart index e0790da9..370bc324 100644 --- a/packages/flutter_tools/test/general.shard/linux/linux_doctor_test.dart +++ b/packages/flutter_tools/test/general.shard/linux/linux_doctor_test.dart @@ -60,13 +60,9 @@ FakeCommand _libraryCheckCommand(String library, {bool exists = true}) { ); } -// Commands that give positive replies for all the GTK library pkg-config queries. +// Commands that give positive replies for all the GLib library pkg-config queries. List _gtkLibrariesPresentCommands() { - return [ - _libraryCheckCommand('gtk+-3.0'), - _libraryCheckCommand('glib-2.0'), - _libraryCheckCommand('gio-2.0'), - ]; + return [_libraryCheckCommand('glib-2.0'), _libraryCheckCommand('gio-2.0')]; } // A command that will return typical-looking 'eglinfo' output @@ -169,12 +165,11 @@ FakeCommand _eglinfoMissingCommand() { ); } -// Commands that give some failures for the GTK library pkg-config queries. +// Commands that give some failures for the GLib library pkg-config queries. List _gtkLibrariesMissingCommands() { return [ - _libraryCheckCommand('gtk+-3.0'), _libraryCheckCommand('glib-2.0', exists: false), - // No more entries, since the first missing GTK library stops the + // No more entries, since the first missing library stops the // checks. ]; } diff --git a/packages/flutter_tools_patches/0001-Linux-project-only-depends-on-glib-not-Gtk.patch b/packages/flutter_tools_patches/0001-Linux-project-only-depends-on-glib-not-Gtk.patch new file mode 100644 index 00000000..e3cf5739 --- /dev/null +++ b/packages/flutter_tools_patches/0001-Linux-project-only-depends-on-glib-not-Gtk.patch @@ -0,0 +1,224 @@ +From d9c8450347bb880b6b59c450775dc8061c0fefb6 Mon Sep 17 00:00:00 2001 +From: Matej Knopp +Date: Tue, 29 Sep 2026 22:06:20 +0200 +Subject: [PATCH] Linux project only depends on glib, not Gtk + +--- + .../flutter_tools/lib/src/base/user_messages.dart | 4 ++-- + .../flutter_tools/lib/src/linux/linux_doctor.dart | 4 ++-- + .../templates/app/linux.tmpl/CMakeLists.txt.tmpl | 5 +++-- + .../templates/app/linux.tmpl/flutter/CMakeLists.txt | 2 -- + .../templates/app/linux.tmpl/runner/CMakeLists.txt | 2 +- + .../app/linux.tmpl/runner/my_application.cc.tmpl | 9 +++------ + .../app/linux.tmpl/runner/my_application.h | 4 ++-- + .../templates/plugin/linux.tmpl/CMakeLists.txt.tmpl | 4 ++-- + .../test/general.shard/linux/linux_doctor_test.dart | 13 ++++--------- + 9 files changed, 19 insertions(+), 28 deletions(-) + +diff --git a/packages/flutter_tools/lib/src/base/user_messages.dart b/packages/flutter_tools/lib/src/base/user_messages.dart +index 608e75b5e0a..40d56b8fd20 100644 +--- a/packages/flutter_tools/lib/src/base/user_messages.dart ++++ b/packages/flutter_tools/lib/src/base/user_messages.dart +@@ -161,8 +161,8 @@ class UserMessages { + String pkgConfigTooOld(String minimumVersion) => + 'pkg-config $minimumVersion or later is required.'; + String get gtkLibrariesMissing => +- 'GTK 3.0 development libraries are required for Linux development.\n' +- 'They are likely available from your distribution (e.g.: apt install libgtk-3-dev)'; ++ 'GLib development libraries are required for Linux development.\n' ++ 'They are likely available from your distribution (e.g.: apt install libglib2.0-dev)'; + String get eglinfoMissing => + "Unable to access driver information using 'eglinfo'.\n" + 'It is likely available from your distribution (e.g.: apt install mesa-utils)'; +diff --git a/packages/flutter_tools/lib/src/linux/linux_doctor.dart b/packages/flutter_tools/lib/src/linux/linux_doctor.dart +index 2900f7dac6d..2024b92c274 100644 +--- a/packages/flutter_tools/lib/src/linux/linux_doctor.dart ++++ b/packages/flutter_tools/lib/src/linux/linux_doctor.dart +@@ -137,7 +137,7 @@ class LinuxDoctorValidator extends DoctorValidator { + kPkgConfigBinary: Version(0, 29, 0), + }; + +- final _requiredGtkLibraries = ['gtk+-3.0', 'glib-2.0', 'gio-2.0']; ++ final _requiredGLibLibraries = ['glib-2.0', 'gio-2.0']; + + @override + Future validateImpl() async { +@@ -234,7 +234,7 @@ class LinuxDoctorValidator extends DoctorValidator { + // Messages for libraries. + { + var libraryMissing = false; +- for (final String library in _requiredGtkLibraries) { ++ for (final String library in _requiredGLibLibraries) { + if (!await _libraryIsPresent(library)) { + libraryMissing = true; + break; +diff --git a/packages/flutter_tools/templates/app/linux.tmpl/CMakeLists.txt.tmpl b/packages/flutter_tools/templates/app/linux.tmpl/CMakeLists.txt.tmpl +index f710aa3d4ef..ddcafc32e2c 100644 +--- a/packages/flutter_tools/templates/app/linux.tmpl/CMakeLists.txt.tmpl ++++ b/packages/flutter_tools/templates/app/linux.tmpl/CMakeLists.txt.tmpl +@@ -5,7 +5,7 @@ project(runner LANGUAGES CXX) + # The name of the executable created for the application. Change this to change + # the on-disk name of your application. + set(BINARY_NAME "{{projectName}}") +-# The unique GTK application identifier for this application. See: ++# The unique application identifier for this application. See: + # https://wiki.gnome.org/HowDoI/ChooseApplicationID + set(APPLICATION_ID "{{linuxIdentifier}}") + +@@ -52,7 +52,8 @@ add_subdirectory(${FLUTTER_MANAGED_DIR}) + + # System-level dependencies. + find_package(PkgConfig REQUIRED) +-pkg_check_modules(GTK REQUIRED IMPORTED_TARGET gtk+-3.0) ++pkg_check_modules(GLIB REQUIRED IMPORTED_TARGET glib-2.0) ++pkg_check_modules(GIO REQUIRED IMPORTED_TARGET gio-2.0) + + # Application build; see runner/CMakeLists.txt. + add_subdirectory("runner") +diff --git a/packages/flutter_tools/templates/app/linux.tmpl/flutter/CMakeLists.txt b/packages/flutter_tools/templates/app/linux.tmpl/flutter/CMakeLists.txt +index d5bd01648a9..5fc74f9cb49 100644 +--- a/packages/flutter_tools/templates/app/linux.tmpl/flutter/CMakeLists.txt ++++ b/packages/flutter_tools/templates/app/linux.tmpl/flutter/CMakeLists.txt +@@ -22,7 +22,6 @@ endfunction() + # === Flutter Library === + # System-level dependencies. + find_package(PkgConfig REQUIRED) +-pkg_check_modules(GTK REQUIRED IMPORTED_TARGET gtk+-3.0) + pkg_check_modules(GLIB REQUIRED IMPORTED_TARGET glib-2.0) + pkg_check_modules(GIO REQUIRED IMPORTED_TARGET gio-2.0) + +@@ -63,7 +62,6 @@ target_include_directories(flutter INTERFACE + ) + target_link_libraries(flutter INTERFACE "${FLUTTER_LIBRARY}") + target_link_libraries(flutter INTERFACE +- PkgConfig::GTK + PkgConfig::GLIB + PkgConfig::GIO + ) +diff --git a/packages/flutter_tools/templates/app/linux.tmpl/runner/CMakeLists.txt b/packages/flutter_tools/templates/app/linux.tmpl/runner/CMakeLists.txt +index e97dabc7028..bf63b0bd7bc 100644 +--- a/packages/flutter_tools/templates/app/linux.tmpl/runner/CMakeLists.txt ++++ b/packages/flutter_tools/templates/app/linux.tmpl/runner/CMakeLists.txt +@@ -21,6 +21,6 @@ add_definitions(-DAPPLICATION_ID="${APPLICATION_ID}") + + # Add dependency libraries. Add any application-specific dependencies here. + target_link_libraries(${BINARY_NAME} PRIVATE flutter) +-target_link_libraries(${BINARY_NAME} PRIVATE PkgConfig::GTK) ++target_link_libraries(${BINARY_NAME} PRIVATE PkgConfig::GLIB PkgConfig::GIO) + + target_include_directories(${BINARY_NAME} PRIVATE "${CMAKE_SOURCE_DIR}") +diff --git a/packages/flutter_tools/templates/app/linux.tmpl/runner/my_application.cc.tmpl b/packages/flutter_tools/templates/app/linux.tmpl/runner/my_application.cc.tmpl +index 6ff97760cce..8a5eddb8624 100644 +--- a/packages/flutter_tools/templates/app/linux.tmpl/runner/my_application.cc.tmpl ++++ b/packages/flutter_tools/templates/app/linux.tmpl/runner/my_application.cc.tmpl +@@ -1,19 +1,16 @@ + #include "my_application.h" + + #include +-#ifdef GDK_WINDOWING_X11 +-#include +-#endif + + #include "flutter/generated_plugin_registrant.h" + + struct _MyApplication { +- GtkApplication parent_instance; ++ GApplication parent_instance; + char** dart_entrypoint_arguments; + FlEngine *engine; + }; + +-G_DEFINE_TYPE(MyApplication, my_application, GTK_TYPE_APPLICATION) ++G_DEFINE_TYPE(MyApplication, my_application, G_TYPE_APPLICATION) + + // Implements GApplication::activate. + static void my_application_activate(GApplication *application) { +@@ -95,7 +92,7 @@ static void my_application_init(MyApplication* self) {} + + MyApplication* my_application_new() { + // Set the program name to the application ID, which helps various systems +- // like GTK and desktop environments map this running application to its ++ // like desktop environments map this running application to its + // corresponding .desktop file. This ensures better integration by allowing + // the application to be recognized beyond its binary name. + g_set_prgname(APPLICATION_ID); +diff --git a/packages/flutter_tools/templates/app/linux.tmpl/runner/my_application.h b/packages/flutter_tools/templates/app/linux.tmpl/runner/my_application.h +index db16367a77d..43759e8c46f 100644 +--- a/packages/flutter_tools/templates/app/linux.tmpl/runner/my_application.h ++++ b/packages/flutter_tools/templates/app/linux.tmpl/runner/my_application.h +@@ -1,13 +1,13 @@ + #ifndef FLUTTER_MY_APPLICATION_H_ + #define FLUTTER_MY_APPLICATION_H_ + +-#include ++#include + + G_DECLARE_FINAL_TYPE(MyApplication, + my_application, + MY, + APPLICATION, +- GtkApplication) ++ GApplication) + + /** + * my_application_new: +diff --git a/packages/flutter_tools/templates/plugin/linux.tmpl/CMakeLists.txt.tmpl b/packages/flutter_tools/templates/plugin/linux.tmpl/CMakeLists.txt.tmpl +index 2d8110fe75c..eb1a2ddf55f 100644 +--- a/packages/flutter_tools/templates/plugin/linux.tmpl/CMakeLists.txt.tmpl ++++ b/packages/flutter_tools/templates/plugin/linux.tmpl/CMakeLists.txt.tmpl +@@ -39,7 +39,7 @@ target_compile_definitions(${PLUGIN_NAME} PRIVATE FLUTTER_PLUGIN_IMPL) + target_include_directories(${PLUGIN_NAME} INTERFACE + "${CMAKE_CURRENT_SOURCE_DIR}/include") + target_link_libraries(${PLUGIN_NAME} PRIVATE flutter) +-target_link_libraries(${PLUGIN_NAME} PRIVATE PkgConfig::GTK) ++target_link_libraries(${PLUGIN_NAME} PRIVATE PkgConfig::GLIB PkgConfig::GIO) + + # List of absolute paths to libraries that should be bundled with the plugin. + # This list could contain prebuilt libraries, or libraries created by an +@@ -83,7 +83,7 @@ add_executable(${TEST_RUNNER} + apply_standard_settings(${TEST_RUNNER}) + target_include_directories(${TEST_RUNNER} PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}") + target_link_libraries(${TEST_RUNNER} PRIVATE flutter) +-target_link_libraries(${TEST_RUNNER} PRIVATE PkgConfig::GTK) ++target_link_libraries(${TEST_RUNNER} PRIVATE PkgConfig::GLIB PkgConfig::GIO) + target_link_libraries(${TEST_RUNNER} PRIVATE gtest_main gmock) + + # Enable automatic test discovery. +diff --git a/packages/flutter_tools/test/general.shard/linux/linux_doctor_test.dart b/packages/flutter_tools/test/general.shard/linux/linux_doctor_test.dart +index e0790da9475..370bc3248cb 100644 +--- a/packages/flutter_tools/test/general.shard/linux/linux_doctor_test.dart ++++ b/packages/flutter_tools/test/general.shard/linux/linux_doctor_test.dart +@@ -60,13 +60,9 @@ FakeCommand _libraryCheckCommand(String library, {bool exists = true}) { + ); + } + +-// Commands that give positive replies for all the GTK library pkg-config queries. ++// Commands that give positive replies for all the GLib library pkg-config queries. + List _gtkLibrariesPresentCommands() { +- return [ +- _libraryCheckCommand('gtk+-3.0'), +- _libraryCheckCommand('glib-2.0'), +- _libraryCheckCommand('gio-2.0'), +- ]; ++ return [_libraryCheckCommand('glib-2.0'), _libraryCheckCommand('gio-2.0')]; + } + + // A command that will return typical-looking 'eglinfo' output +@@ -169,12 +165,11 @@ FakeCommand _eglinfoMissingCommand() { + ); + } + +-// Commands that give some failures for the GTK library pkg-config queries. ++// Commands that give some failures for the GLib library pkg-config queries. + List _gtkLibrariesMissingCommands() { + return [ +- _libraryCheckCommand('gtk+-3.0'), + _libraryCheckCommand('glib-2.0', exists: false), +- // No more entries, since the first missing GTK library stops the ++ // No more entries, since the first missing library stops the + // checks. + ]; + } +-- +2.51.2 + diff --git a/packages/flutter_tools_patches/0005-flutter_tools-List-Application-template-in-the-manifest.patch b/packages/flutter_tools_patches/0005-flutter_tools-List-Application-template-in-the-manifest.patch new file mode 100644 index 00000000..ac36e37f --- /dev/null +++ b/packages/flutter_tools_patches/0005-flutter_tools-List-Application-template-in-the-manifest.patch @@ -0,0 +1,22 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Matej Knopp +Date: Mon, 28 Sep 2026 23:15:00 +0200 +Subject: [PATCH] flutter_tools: List Application template in the manifest. + +The Application.kt template was not listed in template_manifest.json, +so `flutter create` never rendered it while AndroidManifest.xml +referenced it, producing a project that crashes on launch. + +--- +diff --git a/packages/flutter_tools/templates/template_manifest.json b/packages/flutter_tools/templates/template_manifest.json +index 0765605bb2d..e6e08d90881 100644 +--- a/packages/flutter_tools/templates/template_manifest.json ++++ b/packages/flutter_tools/templates/template_manifest.json +@@ -27,6 +27,7 @@ + "templates/app/android-java.tmpl/build.gradle.kts.tmpl", + "templates/app/android-java.tmpl/projectName_android.iml.tmpl", + "templates/app/android-kotlin.tmpl/app/build.gradle.kts.tmpl", ++ "templates/app/android-kotlin.tmpl/app/src/main/kotlin/androidIdentifier/Application.kt.tmpl", + "templates/app/android-kotlin.tmpl/app/src/main/kotlin/androidIdentifier/MainActivity.kt.tmpl", + "templates/app/android-kotlin.tmpl/build.gradle.kts.tmpl", + "templates/app/android-kotlin.tmpl/projectName_android.iml.tmpl", diff --git a/packages/flutter_tools_patches/0006-flutter_tools-Never-bundle-the-Roboto-fallback-on-web.patch b/packages/flutter_tools_patches/0006-flutter_tools-Never-bundle-the-Roboto-fallback-on-web.patch new file mode 100644 index 00000000..3ac8b60b --- /dev/null +++ b/packages/flutter_tools_patches/0006-flutter_tools-Never-bundle-the-Roboto-fallback-on-web.patch @@ -0,0 +1,92 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Matej Knopp +Date: Mon, 28 Sep 2026 23:25:00 +0200 +Subject: [PATCH] flutter_tools: Never bundle the Roboto fallback on web. + +flutter_zero has no txt/third_party/fonts tree (headless engine), and +web builds must not bundle the Roboto fallback font at all. The +upstream `_bundleLocalRobotoFallback` hook (which copied the engine +tree font into the bundle and crashed when it was missing) is removed +entirely. + +--- +diff --git a/packages/flutter_tools/lib/src/build_system/targets/web.dart b/packages/flutter_tools/lib/src/build_system/targets/web.dart +index 9f5a78f4de3..12ee35e110b 100644 +--- a/packages/flutter_tools/lib/src/build_system/targets/web.dart ++++ b/packages/flutter_tools/lib/src/build_system/targets/web.dart +@@ -684,9 +684,8 @@ class WebReleaseBundle extends Target { + targetPlatform: TargetPlatform.web_javascript, + buildMode: buildMode, + ); +- final Depfile bundledDepfile = _bundleLocalRobotoFallback(environment, depfile); + final DepfileService depfileService = environment.depFileService; +- depfileService.writeToFile(bundledDepfile, environment.buildDir.childFile('flutter_assets.d')); ++ depfileService.writeToFile(depfile, environment.buildDir.childFile('flutter_assets.d')); + + final Directory webResources = environment.projectDir.childDirectory('web'); + final List inputResourceFiles = webResources +@@ -731,61 +730,9 @@ class WebReleaseBundle extends Target { + environment.outputDir.childFile('version.json').writeAsStringSync(jsonEncode(versionInfo)); + } + +- Depfile _bundleLocalRobotoFallback(Environment environment, Depfile depfile) { +- if (environment.defines[kUseLocalCanvasKitFlag] != 'true') { +- return depfile; +- } +- +- final File fontManifestFile = environment.outputDir +- .childDirectory('assets') +- .childFile(_kFontManifestJsonFile); +- final manifestJson = fontManifestFile.existsSync() +- ? (jsonDecode(fontManifestFile.readAsStringSync()) as List) +- : []; +- +- final bool hasRobotoFamily = manifestJson.any((Object? entry) { +- return entry is Map && entry['family'] == _kBundledFallbackRobotoFamily; +- }); +- if (hasRobotoFamily) { +- return depfile; +- } +- +- final File sourceRobotoFont = environment.fileSystem.file( +- environment.fileSystem.path.join( +- Cache.flutterRoot!, +- 'engine', +- 'src', +- 'flutter', +- 'txt', +- 'third_party', +- 'fonts', +- 'Roboto-Regular.ttf', +- ), +- ); +- if (!sourceRobotoFont.existsSync()) { +- throwToolExit('Failed to find the bundled Roboto font at ${sourceRobotoFont.path}.'); +- } +- +- manifestJson.add({ +- 'family': _kBundledFallbackRobotoFamily, +- 'fonts': >[ +- {'asset': _kBundledFallbackRobotoAsset}, +- ], +- }); +- fontManifestFile.parent.createSync(recursive: true); +- fontManifestFile.writeAsStringSync(jsonEncode(manifestJson)); +- +- final File bundledRobotoFont = environment.outputDir +- .childDirectory('assets') +- .childFile(_kBundledFallbackRobotoAsset); +- bundledRobotoFont.parent.createSync(recursive: true); +- sourceRobotoFont.copySync(bundledRobotoFont.path); +- +- return Depfile( +- [...depfile.inputs, sourceRobotoFont], +- [...depfile.outputs, fontManifestFile, bundledRobotoFont], +- ); +- } ++ // flutter_zero never bundles the Roboto fallback font (headless engine, no ++ // txt/third_party/fonts tree), so the upstream `_bundleLocalRobotoFallback` ++ // hook is removed entirely. + } + + class WebTemplatedFiles extends Target { diff --git a/scripts/update_github_workflow.sh b/scripts/update_github_workflow.sh index 81e2ce9a..d4a404f6 100755 --- a/scripts/update_github_workflow.sh +++ b/scripts/update_github_workflow.sh @@ -19,4 +19,5 @@ ${REPO_PATH}/bin/dart flutter/tools/pkg/github_workflow_generator/bin/run.dart \ -i flutter/ci/builders/linux_android_aot_engine.json \ -i flutter/ci/builders/linux_android_debug_engine.json \ -i flutter/ci/builders/linux_web_engine_build.json \ + -t flutter/tools/pkg/github_workflow_generator/artifact_tests.json \ -o "${REPO_PATH}/.github/workflows/build-and-upload-engine-artifacts.yml" From 895e046c7a8d57a853950e31889cbd51fe02af79 Mon Sep 17 00:00:00 2001 From: Matej Knopp Date: Mon, 28 Sep 2026 15:58:03 +0200 Subject: [PATCH 2/6] Update dependencies. --- DEPS | 56 +-- engine/src/flutter/BUILD.gn | 1 - engine/src/flutter/pubspec.yaml | 5 +- engine/src/flutter/testing/run_tests.py | 1 - .../src/flutter/tools/const_finder/.gitignore | 5 - .../src/flutter/tools/const_finder/BUILD.gn | 16 - .../src/flutter/tools/const_finder/README.md | 11 - .../flutter/tools/const_finder/bin/main.dart | 114 ------ .../flutter/tools/const_finder/pubspec.yaml | 23 -- .../const_finder/test/const_finder_test.dart | 332 ------------------ .../fixtures/.dart_tool/package_config.json | 15 - .../const_finder/test/fixtures/.packages | 3 - .../const_finder/test/fixtures/lib/box.dart | 231 ------------ .../test/fixtures/lib/consts.dart | 76 ---- .../test/fixtures/lib/consts_and_non.dart | 44 --- .../fixtures/lib/static_icon_provider.dart | 31 -- .../test/fixtures/lib/target.dart | 50 --- .../test/fixtures/pkg/package.dart | 16 - engine/src/flutter/tools/font_subset/BUILD.gn | 5 - engine/src/flutter/tools/gn | 5 - examples/hello_world/analysis_options.yaml | 9 + 21 files changed, 40 insertions(+), 1009 deletions(-) delete mode 100644 engine/src/flutter/tools/const_finder/.gitignore delete mode 100644 engine/src/flutter/tools/const_finder/BUILD.gn delete mode 100644 engine/src/flutter/tools/const_finder/README.md delete mode 100644 engine/src/flutter/tools/const_finder/bin/main.dart delete mode 100644 engine/src/flutter/tools/const_finder/pubspec.yaml delete mode 100644 engine/src/flutter/tools/const_finder/test/const_finder_test.dart delete mode 100644 engine/src/flutter/tools/const_finder/test/fixtures/.dart_tool/package_config.json delete mode 100644 engine/src/flutter/tools/const_finder/test/fixtures/.packages delete mode 100644 engine/src/flutter/tools/const_finder/test/fixtures/lib/box.dart delete mode 100644 engine/src/flutter/tools/const_finder/test/fixtures/lib/consts.dart delete mode 100644 engine/src/flutter/tools/const_finder/test/fixtures/lib/consts_and_non.dart delete mode 100644 engine/src/flutter/tools/const_finder/test/fixtures/lib/static_icon_provider.dart delete mode 100644 engine/src/flutter/tools/const_finder/test/fixtures/lib/target.dart delete mode 100644 engine/src/flutter/tools/const_finder/test/fixtures/pkg/package.dart diff --git a/DEPS b/DEPS index aea8df8f..bd6e3899 100644 --- a/DEPS +++ b/DEPS @@ -31,7 +31,7 @@ vars = { # updates to Clang Tidy will not turn the tree red. # # See https://github.com/flutter/flutter/wiki/Engine-pre‐submits-and-post‐submits#post-submit - 'clang_version': 'git_revision:80743bd43fd5b38fedc503308e7a652e23d3ec93', + 'clang_version': 'git_revision:07d67299a15ce03b053736e2d31a668ee0576987', 'reclient_version': 're_client_version:0.185.0.db415f21-gomaip', @@ -47,25 +47,25 @@ vars = { # updated revision list of existing dependencies. You will need to # gclient sync before and after update deps to ensure all deps are updated. # updated revision list of existing dependencies. - 'dart_revision': 'bb17f25f176f5209179b23d51aab9725ffb5146d', + 'dart_revision': '0e7642b85457515cfac6ffda9e0e10906a5e5356', # WARNING: DO NOT EDIT MANUALLY # The lines between blank lines above and below are generated by a script. See create_updated_flutter_deps.py 'dart_binaryen_rev': '9926156a583cec3d22d521232b31c70fa9a87dc1', - 'dart_boringssl_rev': '7515be5ccd601ae0433d3682ba7737592b402014', - 'dart_core_rev': 'fe516ee1b38cc60e7a8c6e082c337037a043d782', - 'dart_devtools_rev': '21f1838f3a9b138ac377efb953ca5a53c8832e75', - 'dart_ecosystem_rev': 'edfdb3b4063b9034b708144633a700204f865f43', - 'dart_http_rev': '5d94ef52582867e077bf41c3fa20fb8b1d1d834e', - 'dart_i18n_rev': 'e1b5a798f8922bb27bbc6d858748ece6f9a19f02', + 'dart_boringssl_rev': '1097261733d85c85147a5c96ff6ee835c90f5951', + 'dart_core_rev': '08e4022160c465780690c43ffdbce60812975d2c', + 'dart_devtools_rev': 'fd39ed6deeed50104b5262d8228f5ae3ceab7bfd', + 'dart_ecosystem_rev': '16dca7ae5d3ff896a4db47e1ed6cd50f7ebbf115', + 'dart_http_rev': 'd8e8e9cd1ae6ed0f0339cfa0f47f92e837a786f5', + 'dart_i18n_rev': '1f5ea2fb2381bdf7bab054a43c0d69771f104561', 'dart_perfetto_rev': '13ce0c9e13b0940d2476cd0cff2301708a9a2e2b', - 'dart_protobuf_rev': '91efb90f437bb6a30e6726c3369a2fcb9bba06e7', - 'dart_pub_rev': 'ec276d10a7fa0f6c6ec005340fb9ad29f3b012d0', + 'dart_protobuf_rev': 'a73edc98c98fb25152aa3f12c1b9db91594c1369', + 'dart_pub_rev': '0382a52acba89ff0080d559bb22f4017962bbd1d', 'dart_sync_http_rev': '6666fff944221891182e1f80bf56569338164d72', - 'dart_tools_rev': 'b827a6e38b934232c7f7b8728a5aef6165e7df2d', + 'dart_tools_rev': '3614ce064ae452a15e83de3531236f5f89dfa526', 'dart_vector_math_rev': 'cf3b5db7340d317dd3489e5a35434b408020a852', - 'dart_web_rev': '12a9ca2ebc08f5a6f2d69aebc7daa1f5a2e6a431', - 'dart_webdriver_rev': '3a711ebb36871eac997c5d5d2429f7414873dc63', + 'dart_web_rev': 'e5c6c028da66688a2295557757850a1599ec392e', + 'dart_webdriver_rev': '8e5c611ea242efdc9f597a8a37c38a9c586120ee', 'dart_webkit_inspection_protocol_rev': '762115a971d1968bc940454ad1e88d506d8c5640', 'ocmock_rev': 'c4ec0e3a7a9f56cfdbd0aa01f4f97bb4b75c5ef8', # v3.7.1 @@ -181,11 +181,11 @@ vars = { # The version / instance id of the cipd:chromium/fuchsia/test-scripts which # will be used altogether with fuchsia-sdk to setup the build / test # environment. - 'fuchsia_test_scripts_version': 'vcANVO8VIDQHasH1X_XRoSYLvx7fNwvTbDM1NT9TwA4C', + 'fuchsia_test_scripts_version': 'whZAV1mfT-Rdc0rQ81s_IEef2L7kbGPFtiQPitjf_akC', # The version / instance id of the cipd:chromium/fuchsia/gn-sdk which will be # used altogether with fuchsia-sdk to generate gn based build rules. - 'fuchsia_gn_sdk_version': 'a87CbQSWEjkPUK1ZY_zsy8aZ9W-3Z2v73ohzhrWbDQ4C', + 'fuchsia_gn_sdk_version': 'PDJz3b3CL31uoLOkDb0mm8FidqJ1eCJryoRFd9iVmbIC', } gclient_gn_args_file = 'engine/src/flutter/third_party/dart/build/config/gclient_args.gni' @@ -225,7 +225,7 @@ deps = { Var('llvm_git') + '/llvm-project/libc' + '@' + '5af39a19a1ad51ce93972cdab206dcd3ff9b6afa', 'engine/src/flutter/third_party/icu': - Var('chromium_git') + '/chromium/deps/icu.git' + '@' + 'd578f2e8b7bd5938e21cfb6bf15c079e0aa5b738', + Var('chromium_git') + '/chromium/deps/icu.git' + '@' + '6ebb40c594776cc2c21ea14df85a2a89a328b364', 'engine/src/flutter/third_party/gtest-parallel': Var('chromium_git') + '/external/github.com/google/gtest-parallel' + '@' + '38191e2733d7cbaeaef6a3f1a942ddeb38a2ad14', @@ -257,7 +257,7 @@ deps = { Var('chromium_git') + '/external/github.com/WebAssembly/binaryen.git' + '@' + Var('dart_binaryen_rev'), 'engine/src/flutter/third_party/dart/third_party/devtools': - {'dep_type': 'cipd', 'packages': [{'package': 'dart/third_party/flutter/devtools', 'version': 'git_revision:21f1838f3a9b138ac377efb953ca5a53c8832e75'}]}, + {'dep_type': 'cipd', 'packages': [{'package': 'dart/third_party/flutter/devtools', 'version': 'git_revision:fd39ed6deeed50104b5262d8228f5ae3ceab7bfd'}]}, 'engine/src/flutter/third_party/dart/third_party/perfetto/src': Var('chromium_git') + '/external/github.com/google/perfetto' + '@' + Var('dart_perfetto_rev'), @@ -266,10 +266,10 @@ deps = { Var('dart_git') + '/core.git' + '@' + Var('dart_core_rev'), 'engine/src/flutter/third_party/dart/third_party/pkg/dart_style': - Var('dart_git') + '/dart_style.git@dfdf6420c7ea923d28edef3f11e89b4ff23d03bf', + Var('dart_git') + '/dart_style.git@5a9534fad9ff2faba89596a70323d2b1f1bcf163', 'engine/src/flutter/third_party/dart/third_party/pkg/dartdoc': - Var('dart_git') + '/dartdoc.git@ac96918074974dcd4ea20f764f17090f58c1e428', + Var('dart_git') + '/dartdoc.git@c68debcb5636ba8d66210110092d39d5b06f8225', 'engine/src/flutter/third_party/dart/third_party/pkg/ecosystem': Var('dart_git') + '/ecosystem.git' + '@' + Var('dart_ecosystem_rev'), @@ -284,7 +284,7 @@ deps = { Var('dart_git') + '/leak_tracker.git@f5620600a5ce1c44f65ddaa02001e200b096e14c', 'engine/src/flutter/third_party/dart/third_party/pkg/native': - Var('dart_git') + '/native.git@046f63d1d89cd9954623bfa2df9c69d1a395375e', + Var('dart_git') + '/native.git@f628b26f039c3824d83c352c489fd1a4496780d0', 'engine/src/flutter/third_party/dart/third_party/pkg/protobuf': Var('dart_git') + '/protobuf.git' + '@' + Var('dart_protobuf_rev'), @@ -293,7 +293,7 @@ deps = { Var('dart_git') + '/pub.git' + '@' + Var('dart_pub_rev'), 'engine/src/flutter/third_party/dart/third_party/pkg/shelf': - Var('dart_git') + '/shelf.git@6918a7690946044b4098e9f6735439044c676e13', + Var('dart_git') + '/shelf.git@e5c8dc663bf1325ad8f997c4a2387923d37a90d9', 'engine/src/flutter/third_party/dart/third_party/pkg/sync_http': Var('dart_git') + '/sync_http.git' + '@' + Var('dart_sync_http_rev'), @@ -302,7 +302,7 @@ deps = { Var('dart_git') + '/external/github.com/simolus3/tar.git@13479f7c2a18f499e840ad470cfcca8c579f6909', 'engine/src/flutter/third_party/dart/third_party/pkg/test': - Var('dart_git') + '/test.git@bd92e633e7f05edc3301865bdc00d1ae181cb1f1', + Var('dart_git') + '/test.git@9946c9551ddaffd6092c22372b7e146600aa3264', 'engine/src/flutter/third_party/dart/third_party/pkg/tools': Var('dart_git') + '/tools.git' + '@' + Var('dart_tools_rev'), @@ -320,7 +320,7 @@ deps = { Var('dart_git') + '/external/github.com/google/webkit_inspection_protocol.dart.git' + '@' + Var('dart_webkit_inspection_protocol_rev'), 'engine/src/flutter/third_party/dart/tools/sdks/dart-sdk': - {'dep_type': 'cipd', 'packages': [{'package': 'dart/dart-sdk/${{platform}}', 'version': 'version:3.14.0-75.0.dev'}]}, + {'dep_type': 'cipd', 'packages': [{'package': 'dart/dart-sdk/${{platform}}', 'version': 'version:3.14.0-226.0.dev'}]}, # WARNING: end of dart dependencies list that is cleaned up automatically - see create_updated_flutter_deps.py. @@ -432,13 +432,13 @@ deps = { Var('chromium_git') + '/external/github.com/libexpat/libexpat.git' + '@' + '8e49998f003d693213b538ef765814c7d21abada', 'engine/src/flutter/third_party/freetype2': - Var('flutter_git') + '/third_party/freetype2' + '@' + 'be4bcb57914154fc1b9e2900bf8e4b516057e2b8', + Var('flutter_git') + '/third_party/freetype2' + '@' + 'db7276fd53cda30c7f0fcd6b11e2e8f43b4b5e82', 'engine/src/flutter/third_party/ocmock': Var('flutter_git') + '/third_party/ocmock' + '@' + Var('ocmock_rev'), 'engine/src/flutter/third_party/libpng': - Var('flutter_git') + '/third_party/libpng' + '@' + 'b6004397d2ab98f0250376d9b357337b7f422d13', + Var('flutter_git') + '/third_party/libpng' + '@' + 'ced6b6c0c1e24716423a417b399d3c7d4623890d', 'engine/src/flutter/third_party/zlib': Var('chromium_git') + '/chromium/src/third_party/zlib.git' + '@' + '7eda07b1e067ef3fd7eea0419c88b5af45c9a776', @@ -497,7 +497,7 @@ deps = { { # See tools/gradle/README.md for update instructions. # Version here means the CIPD tag. - 'version': 'version:9.3.1', + 'version': 'version:9.5.0', 'package': 'flutter/gradle' } ], @@ -693,7 +693,7 @@ deps = { 'packages': [ { 'package': 'flutter_internal/rbe/reclient_cfgs', - 'version': '0vARzGeIZgIhW7zVfWuqIPQ_HXMLDccjAstykWZKjaEC', + 'version': 'Vk7WiSKwQdBHbCrZ9PtRl3po2WpRFQZSag9M6-sxF_0C', } ], 'condition': 'use_rbe', @@ -729,7 +729,7 @@ deps = { 'packages': [ { 'package': 'fuchsia/sdk/core/linux-amd64', - 'version': '_J8wM3kyQpLN9wvRD5upBr9L1g5TCYF3Oc8P0m3QeZMC' + 'version': 'ukukV5lEkKabtOATkSbVa6yIaU7g4nfmCcVvWNxfMQMC' } ], 'condition': 'download_fuchsia_deps and not download_fuchsia_sdk', diff --git a/engine/src/flutter/BUILD.gn b/engine/src/flutter/BUILD.gn index 325fa4c4..77b676ac 100644 --- a/engine/src/flutter/BUILD.gn +++ b/engine/src/flutter/BUILD.gn @@ -124,7 +124,6 @@ group("flutter") { "//flutter/build/dart/test:gen_dartcli_call", "//flutter/build/dart/test:gen_executable_call", "//flutter/shell/testing", - "//flutter/tools/const_finder", "//flutter/tools/engine_tool:tests", "//flutter/tools/font_subset", ] diff --git a/engine/src/flutter/pubspec.yaml b/engine/src/flutter/pubspec.yaml index 33035ca0..99888fbe 100644 --- a/engine/src/flutter/pubspec.yaml +++ b/engine/src/flutter/pubspec.yaml @@ -76,7 +76,7 @@ name: _engine_workspace # Required for workspace support. environment: - sdk: ^3.9.0-0 + sdk: ^3.13.0-0 # Declare all packages that are part of the workspace. workspace: @@ -93,7 +93,6 @@ workspace: - tools/build_bucket_golden_scraper - tools/clang_tidy - tools/clangd_check - - tools/const_finder - tools/engine_tool - tools/header_guard_check - tools/gen_web_locale_keymap @@ -174,6 +173,8 @@ dependency_overrides: path: ./third_party/dart/third_party/pkg/tools/pkgs/boolean_selector cli_config: path: ./third_party/dart/third_party/pkg/tools/pkgs/cli_config + cli_util: + path: ./third_party/dart/third_party/pkg/tools/pkgs/cli_util collection: path: ./third_party/dart/third_party/pkg/core/pkgs/collection convert: diff --git a/engine/src/flutter/testing/run_tests.py b/engine/src/flutter/testing/run_tests.py index a67a1b2c..78a1fd7d 100755 --- a/engine/src/flutter/testing/run_tests.py +++ b/engine/src/flutter/testing/run_tests.py @@ -889,7 +889,6 @@ def build_dart_host_test_list(): os.path.join('flutter', 'tools', 'api_check'), os.path.join('flutter', 'tools', 'build_bucket_golden_scraper'), os.path.join('flutter', 'tools', 'clang_tidy'), - os.path.join('flutter', 'tools', 'const_finder'), os.path.join('flutter', 'tools', 'engine_tool'), os.path.join('flutter', 'tools', 'githooks'), os.path.join('flutter', 'tools', 'header_guard_check'), diff --git a/engine/src/flutter/tools/const_finder/.gitignore b/engine/src/flutter/tools/const_finder/.gitignore deleted file mode 100644 index fb0d5a5d..00000000 --- a/engine/src/flutter/tools/const_finder/.gitignore +++ /dev/null @@ -1,5 +0,0 @@ -*.dill - -!test/fixtures/.dart_tool -!test/fixtures/.dart_tool/package_config.json -!test/fixtures/.packages diff --git a/engine/src/flutter/tools/const_finder/BUILD.gn b/engine/src/flutter/tools/const_finder/BUILD.gn deleted file mode 100644 index 09be6591..00000000 --- a/engine/src/flutter/tools/const_finder/BUILD.gn +++ /dev/null @@ -1,16 +0,0 @@ -# Copyright 2013 The Flutter Authors. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. - -import("//flutter/build/dart/rules.gni") - -application_snapshot("const_finder") { - main_dart = "bin/main.dart" - snapshot_kind = "kernel" - - training_args = [ "--help" ] - - inputs = [ "bin/main.dart" ] - - deps = [ "//flutter/flutter_frontend_server:frontend_server" ] -} diff --git a/engine/src/flutter/tools/const_finder/README.md b/engine/src/flutter/tools/const_finder/README.md deleted file mode 100644 index dce32b80..00000000 --- a/engine/src/flutter/tools/const_finder/README.md +++ /dev/null @@ -1,11 +0,0 @@ -# Const Finder - -This program uses package:kernel from the Dart SDK in //third_party. - -A snapshot is created via the build rules in BUILD.gn. This is then vended -to the Flutter tool, which uses it to find `const` creations of `IconData` -classes. The information from this can then be passed to the `font-subset` tool -to create a smaller icon font file specific to the application. - -Once [flutter/flutter#47162](https://github.com/flutter/flutter/issues/47162) is -resolved, this package should be moved to the flutter tool. diff --git a/engine/src/flutter/tools/const_finder/bin/main.dart b/engine/src/flutter/tools/const_finder/bin/main.dart deleted file mode 100644 index 25c14249..00000000 --- a/engine/src/flutter/tools/const_finder/bin/main.dart +++ /dev/null @@ -1,114 +0,0 @@ -// Copyright 2013 The Flutter Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -import 'dart:convert'; -import 'dart:io'; - -import 'package:args/args.dart'; -import 'package:kernel/const_finder.dart'; - -void main(List args) { - final parser = ArgParser(); - parser - ..addSeparator( - 'Finds constant instances of a specified class from the\n' - 'specified package, and outputs JSON like the following:', - ) - ..addSeparator(''' - { - "constantInstances": [ - { - "codePoint": 59470, - "fontFamily": "MaterialIcons", - "fontPackage": null, - "matchTextDirection": false - } - ], - "nonConstantInstances": [ - { - "file": "file:///Path/to/hello_world/lib/file.dart", - "line": 19, - "column": 11 - } - ] - }''') - ..addSeparator( - 'Where the "constantInstances" is a list of objects containing\n' - 'the properties passed to the const constructor of the class, and\n' - '"nonConstantInstances" is a list of source locations of non-constant\n' - 'creation of the specified class. Non-constant creation cannot be\n' - 'statically evaluated by this tool, and callers may wish to treat them\n' - 'as errors. The non-constant creation may include entries that are not\n' - 'reachable at runtime.', - ) - ..addSeparator('Required arguments:') - ..addOption( - 'kernel-file', - valueHelp: 'path/to/main.dill', - help: - 'The path to a kernel file to parse, which was created from the ' - 'main-package-uri library.', - mandatory: true, - ) - ..addOption( - 'class-library-uri', - mandatory: true, - help: 'The package: URI of the class to find.', - valueHelp: 'package:flutter/src/widgets/icon_data.dart', - ) - ..addOption( - 'class-name', - help: 'The class name for the class to find.', - valueHelp: 'IconData', - mandatory: true, - ) - ..addSeparator('Optional arguments:') - ..addFlag('pretty', negatable: false, help: 'Pretty print JSON output (defaults to false).') - ..addFlag('help', abbr: 'h', negatable: false, help: 'Print usage and exit') - ..addOption( - 'annotation-class-name', - help: - 'The class name of the annotation for classes that should be ' - 'ignored.', - valueHelp: 'StaticIconProvider', - ) - ..addOption( - 'annotation-class-library-uri', - help: - 'The package: URI of the class of the annotation for classes ' - 'that should be ignored.', - valueHelp: 'package:flutter/src/material/icons.dart', - ); - - final ArgResults argResults = parser.parse(args); - T getArg(String name) => argResults[name] as T; - - final String? annotationClassName = getArg('annotation-class-name'); - final String? annotationClassLibraryUri = getArg('annotation-class-library-uri'); - - final annotationClassNameProvided = annotationClassName != null; - final annotationClassLibraryUriProvided = annotationClassLibraryUri != null; - if (annotationClassNameProvided != annotationClassLibraryUriProvided) { - throw StateError( - 'If either "--annotation-class-name" or "--annotation-class-library-uri" are provided they both must be', - ); - } - - if (getArg('help')) { - stdout.writeln(parser.usage); - exit(0); - } - - final finder = ConstFinder( - kernelFilePath: getArg('kernel-file'), - classLibraryUri: getArg('class-library-uri'), - className: getArg('class-name'), - annotationClassName: annotationClassName, - annotationClassLibraryUri: annotationClassLibraryUri, - ); - - final encoder = getArg('pretty') ? const JsonEncoder.withIndent(' ') : const JsonEncoder(); - - stdout.writeln(encoder.convert(finder.findInstances())); -} diff --git a/engine/src/flutter/tools/const_finder/pubspec.yaml b/engine/src/flutter/tools/const_finder/pubspec.yaml deleted file mode 100644 index d19a5b16..00000000 --- a/engine/src/flutter/tools/const_finder/pubspec.yaml +++ /dev/null @@ -1,23 +0,0 @@ -# Copyright 2013 The Flutter Authors. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. - -name: const_finder -publish_to: none - -# Required for workspace support. -environment: - sdk: ^3.9.0-0 - -# This package is managed as part of the engine workspace. -resolution: workspace - -dependencies: - args: any - kernel: any - -dev_dependencies: - collection: any - engine_repo_tools: any - path: any - test: any diff --git a/engine/src/flutter/tools/const_finder/test/const_finder_test.dart b/engine/src/flutter/tools/const_finder/test/const_finder_test.dart deleted file mode 100644 index aeb28388..00000000 --- a/engine/src/flutter/tools/const_finder/test/const_finder_test.dart +++ /dev/null @@ -1,332 +0,0 @@ -// Copyright 2013 The Flutter Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -import 'dart:convert'; -import 'dart:io' as io; - -import 'package:engine_repo_tools/engine_repo_tools.dart'; -import 'package:kernel/const_finder.dart'; -import 'package:path/path.dart' as path; -import 'package:test/test.dart'; - -void main() { - final engine = Engine.findWithin(); - String? buildDir = io.Platform.environment['FLUTTER_BUILD_DIRECTORY']; - buildDir ??= engine.latestOutput()?.path.path; - if (buildDir == null) { - fail('No build directory found. Set FLUTTER_BUILD_DIRECTORY'); - } - - final String fixturesPath = path.join( - engine.flutterDir.path, - 'tools', - 'const_finder', - 'test', - 'fixtures', - ); - final String fixturesUrl = io.Platform.isWindows - ? '/$fixturesPath'.replaceAll(io.Platform.pathSeparator, '/') - : fixturesPath; - - final String frontendServerSnapshot = path.join( - buildDir, - 'gen', - 'frontend_server_aot.dart.snapshot', - ); - final String flutterPatchedSdk = path.join(buildDir, 'flutter_patched_sdk'); - final String librariesDotJson = path.join(flutterPatchedSdk, 'lib', 'libraries.json'); - final String packageConfig = path.join(fixturesPath, '.dart_tool', 'package_config.json'); - - final String dart = io.Platform.resolvedExecutable; - final String dartaotruntime = path.join( - path.dirname(io.Platform.resolvedExecutable), - 'dartaotruntime', - ); - - void compileAOTDill({required String sourcePath, required String dillPath}) { - final io.ProcessResult result = io.Process.runSync(dartaotruntime, [ - frontendServerSnapshot, - '--sdk-root=$flutterPatchedSdk', - '--target=flutter', - '--aot', - '--tfa', - '--packages=$packageConfig', - '--output-dill=$dillPath', - sourcePath, - ]); - printOnFailure(result.stdout.toString()); - printOnFailure(result.stderr.toString()); - if (result.exitCode != 0) { - fail('Failed to compile AOT dill'); - } - addTearDown(() => io.File(dillPath).deleteSync()); - } - - void compileDart2JSDill({required String sourcePath, required String dillPath}) { - final io.ProcessResult result = io.Process.runSync(dart, [ - 'compile', - 'js', - '--libraries-spec=$librariesDotJson', - '-Ddart.vm.product=true', - '-o', - dillPath, - '--packages=$packageConfig', - '--cfe-only', - sourcePath, - ]); - printOnFailure(result.stdout.toString()); - printOnFailure(result.stderr.toString()); - if (result.exitCode != 0) { - fail('Failed to compile Dart2JS dill'); - } - addTearDown(() => io.File(dillPath).deleteSync()); - } - - test('box_frontend (aot)', () { - final String sourcePath = path.join(fixturesPath, 'lib', 'box.dart'); - final String dillPath = path.join(fixturesPath, 'box_frontend.dill'); - compileAOTDill(sourcePath: sourcePath, dillPath: dillPath); - final finder = ConstFinder( - kernelFilePath: dillPath, - classLibraryUri: 'package:const_finder_fixtures/box.dart', - className: 'Box', - ); - - // Will timeout if we did things wrong. - jsonEncode(finder.findInstances()); - }); - - test('box_web (dart2js)', () { - final String sourcePath = path.join(fixturesPath, 'lib', 'box.dart'); - final String dillPath = path.join(fixturesPath, 'box_web.dill'); - compileDart2JSDill(sourcePath: sourcePath, dillPath: dillPath); - final finder = ConstFinder( - kernelFilePath: dillPath, - classLibraryUri: 'package:const_finder_fixtures/box.dart', - className: 'Box', - ); - - // Will timeout if we did things wrong. - jsonEncode(finder.findInstances()); - }); - - test('consts_frontend (aot)', () { - final String sourcePath = path.join(fixturesPath, 'lib', 'consts.dart'); - final String dillPath = path.join(fixturesPath, 'consts_frontend.dill'); - compileAOTDill(sourcePath: sourcePath, dillPath: dillPath); - - final { - 'constantInstances': List constantInstances, - 'nonConstantLocations': List nonConstantLocations, - } = ConstFinder( - kernelFilePath: dillPath, - classLibraryUri: 'package:const_finder_fixtures/target.dart', - className: 'Target', - ).findInstances(); - - expect( - constantInstances, - unorderedEquals([ - {'stringValue': '100', 'intValue': 100, 'targetValue': null}, - {'stringValue': '102', 'intValue': 102, 'targetValue': null}, - {'stringValue': '101', 'intValue': 101}, - {'stringValue': '103', 'intValue': 103, 'targetValue': null}, - {'stringValue': '105', 'intValue': 105, 'targetValue': null}, - {'stringValue': '104', 'intValue': 104}, - {'stringValue': '106', 'intValue': 106, 'targetValue': null}, - {'stringValue': '108', 'intValue': 108, 'targetValue': null}, - {'stringValue': '107', 'intValue': 107}, - {'stringValue': '1', 'intValue': 1, 'targetValue': null}, - {'stringValue': '4', 'intValue': 4, 'targetValue': null}, - {'stringValue': '2', 'intValue': 2}, - {'stringValue': '6', 'intValue': 6, 'targetValue': null}, - {'stringValue': '8', 'intValue': 8, 'targetValue': null}, - {'stringValue': '10', 'intValue': 10, 'targetValue': null}, - {'stringValue': '9', 'intValue': 9}, - {'stringValue': '7', 'intValue': 7, 'targetValue': null}, - {'stringValue': '11', 'intValue': 11, 'targetValue': null}, - {'stringValue': '12', 'intValue': 12, 'targetValue': null}, - {'stringValue': 'package', 'intValue': -1, 'targetValue': null}, - ]), - ); - expect(nonConstantLocations, isEmpty); - }); - - test('consts_web (dart2js)', () { - final String sourcePath = path.join(fixturesPath, 'lib', 'consts.dart'); - final String dillPath = path.join(fixturesPath, 'consts_web.dill'); - compileDart2JSDill(sourcePath: sourcePath, dillPath: dillPath); - - final { - 'constantInstances': List constantInstances, - 'nonConstantLocations': List nonConstantLocations, - } = ConstFinder( - kernelFilePath: dillPath, - classLibraryUri: 'package:const_finder_fixtures/target.dart', - className: 'Target', - ).findInstances(); - - expect( - constantInstances, - unorderedEquals([ - {'stringValue': '100', 'intValue': 100, 'targetValue': null}, - {'stringValue': '102', 'intValue': 102, 'targetValue': null}, - {'stringValue': '101', 'intValue': 101}, - {'stringValue': '103', 'intValue': 103, 'targetValue': null}, - {'stringValue': '105', 'intValue': 105, 'targetValue': null}, - {'stringValue': '104', 'intValue': 104}, - {'stringValue': '106', 'intValue': 106, 'targetValue': null}, - {'stringValue': '108', 'intValue': 108, 'targetValue': null}, - {'stringValue': '107', 'intValue': 107}, - {'stringValue': '1', 'intValue': 1, 'targetValue': null}, - {'stringValue': '4', 'intValue': 4, 'targetValue': null}, - {'stringValue': '2', 'intValue': 2}, - {'stringValue': '6', 'intValue': 6, 'targetValue': null}, - {'stringValue': '8', 'intValue': 8, 'targetValue': null}, - {'stringValue': '10', 'intValue': 10, 'targetValue': null}, - {'stringValue': '9', 'intValue': 9}, - {'stringValue': '7', 'intValue': 7, 'targetValue': null}, - {'stringValue': '11', 'intValue': 11, 'targetValue': null}, - {'stringValue': '12', 'intValue': 12, 'targetValue': null}, - {'stringValue': 'package', 'intValue': -1, 'targetValue': null}, - ]), - ); - - expect(nonConstantLocations, [ - {'file': 'file://$fixturesUrl/pkg/package.dart', 'line': 14, 'column': 18}, - ]); - }); - - test('consts_and_non_frontend (aot)', () { - final String sourcePath = path.join(fixturesPath, 'lib', 'consts_and_non.dart'); - final String dillPath = path.join(fixturesPath, 'consts_and_non_frontend.dill'); - compileAOTDill(sourcePath: sourcePath, dillPath: dillPath); - - final { - 'constantInstances': List constantInstances, - 'nonConstantLocations': List nonConstantLocations, - } = ConstFinder( - kernelFilePath: dillPath, - classLibraryUri: 'package:const_finder_fixtures/target.dart', - className: 'Target', - ).findInstances(); - - expect( - constantInstances, - unorderedEquals([ - {'stringValue': '1', 'intValue': 1, 'targetValue': null}, - {'stringValue': '4', 'intValue': 4, 'targetValue': null}, - {'stringValue': '6', 'intValue': 6, 'targetValue': null}, - {'stringValue': '8', 'intValue': 8, 'targetValue': null}, - {'stringValue': '10', 'intValue': 10, 'targetValue': null}, - {'stringValue': '9', 'intValue': 9}, - {'stringValue': '7', 'intValue': 7, 'targetValue': null}, - ]), - ); - expect(nonConstantLocations, [ - {'file': 'file://$fixturesUrl/lib/consts_and_non.dart', 'line': 14, 'column': 19}, - {'file': 'file://$fixturesUrl/lib/consts_and_non.dart', 'line': 16, 'column': 19}, - {'file': 'file://$fixturesUrl/lib/consts_and_non.dart', 'line': 16, 'column': 34}, - {'file': 'file://$fixturesUrl/lib/consts_and_non.dart', 'line': 17, 'column': 19}, - {'file': 'file://$fixturesUrl/pkg/package.dart', 'line': 14, 'column': 18}, - ]); - }); - - test('consts_and_non_web (dart2js)', () { - final String sourcePath = path.join(fixturesPath, 'lib', 'consts_and_non.dart'); - final String dillPath = path.join(fixturesPath, 'consts_and_non_web.dill'); - compileDart2JSDill(sourcePath: sourcePath, dillPath: dillPath); - - final { - 'constantInstances': List constantInstances, - 'nonConstantLocations': List nonConstantLocations, - } = ConstFinder( - kernelFilePath: dillPath, - classLibraryUri: 'package:const_finder_fixtures/target.dart', - className: 'Target', - ).findInstances(); - - expect( - constantInstances, - unorderedEquals([ - {'stringValue': '1', 'intValue': 1, 'targetValue': null}, - {'stringValue': '4', 'intValue': 4, 'targetValue': null}, - {'stringValue': '6', 'intValue': 6, 'targetValue': null}, - {'stringValue': '8', 'intValue': 8, 'targetValue': null}, - {'stringValue': '10', 'intValue': 10, 'targetValue': null}, - {'stringValue': '9', 'intValue': 9}, - {'stringValue': '7', 'intValue': 7, 'targetValue': null}, - {'stringValue': 'package', 'intValue': -1, 'targetValue': null}, - ]), - ); - - expect(nonConstantLocations, [ - {'file': 'file://$fixturesUrl/lib/consts_and_non.dart', 'line': 14, 'column': 19}, - {'file': 'file://$fixturesUrl/lib/consts_and_non.dart', 'line': 16, 'column': 19}, - {'file': 'file://$fixturesUrl/lib/consts_and_non.dart', 'line': 16, 'column': 34}, - {'file': 'file://$fixturesUrl/lib/consts_and_non.dart', 'line': 17, 'column': 19}, - {'file': 'file://$fixturesUrl/pkg/package.dart', 'line': 14, 'column': 18}, - ]); - }); - - test('static_icon_provider_frontend (aot)', () { - final String sourcePath = path.join(fixturesPath, 'lib', 'static_icon_provider.dart'); - final String dillPath = path.join(fixturesPath, 'static_icon_provider_frontend.dill'); - compileAOTDill(sourcePath: sourcePath, dillPath: dillPath); - final finder = ConstFinder( - kernelFilePath: dillPath, - classLibraryUri: 'package:const_finder_fixtures/target.dart', - className: 'Target', - annotationClassName: 'StaticIconProvider', - annotationClassLibraryUri: 'package:const_finder_fixtures/static_icon_provider.dart', - ); - - final { - 'constantInstances': List constantInstances, - 'nonConstantLocations': List nonConstantLocations, - } = finder - .findInstances(); - expect( - constantInstances, - unorderedEquals([ - {'stringValue': 'used1', 'intValue': 1, 'targetValue': null}, - {'stringValue': 'used2', 'intValue': 2, 'targetValue': null}, - ]), - ); - - // TODO(fujino): This should have non-constant locations from the use of - // a tear-off, see https://github.com/flutter/flutter/issues/116797 - expect(nonConstantLocations, isEmpty); - }); - - test('static_icon_provider_web (dart2js)', () { - final String sourcePath = path.join(fixturesPath, 'lib', 'static_icon_provider.dart'); - final String dillPath = path.join(fixturesPath, 'static_icon_provider_web.dill'); - compileDart2JSDill(sourcePath: sourcePath, dillPath: dillPath); - final finder = ConstFinder( - kernelFilePath: dillPath, - classLibraryUri: 'package:const_finder_fixtures/target.dart', - className: 'Target', - annotationClassName: 'StaticIconProvider', - annotationClassLibraryUri: 'package:const_finder_fixtures/static_icon_provider.dart', - ); - - final { - 'constantInstances': List constantInstances, - 'nonConstantLocations': List nonConstantLocations, - } = finder - .findInstances(); - expect( - constantInstances, - unorderedEquals([ - {'stringValue': 'used1', 'intValue': 1, 'targetValue': null}, - {'stringValue': 'used2', 'intValue': 2, 'targetValue': null}, - ]), - ); - - // TODO(fujino): This should have non-constant locations from the use of - // a tear-off, see https://github.com/flutter/flutter/issues/116797 - expect(nonConstantLocations, isEmpty); - }); -} diff --git a/engine/src/flutter/tools/const_finder/test/fixtures/.dart_tool/package_config.json b/engine/src/flutter/tools/const_finder/test/fixtures/.dart_tool/package_config.json deleted file mode 100644 index b6392ddc..00000000 --- a/engine/src/flutter/tools/const_finder/test/fixtures/.dart_tool/package_config.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "configVersion": 2, - "packages": [ - { - "name": "const_finder_fixtures", - "rootUri": "../lib/", - "languageVersion": "2.17" - }, - { - "name": "const_finder_fixtures_package", - "rootUri": "../pkg/", - "languageVersion": "2.17" - } - ] -} diff --git a/engine/src/flutter/tools/const_finder/test/fixtures/.packages b/engine/src/flutter/tools/const_finder/test/fixtures/.packages deleted file mode 100644 index 0ef0f0b0..00000000 --- a/engine/src/flutter/tools/const_finder/test/fixtures/.packages +++ /dev/null @@ -1,3 +0,0 @@ -# Generated by pub on 2020-01-15 10:08:29.776333. -const_finder_fixtures:lib/ -const_finder_fixtures_package:pkg/ \ No newline at end of file diff --git a/engine/src/flutter/tools/const_finder/test/fixtures/lib/box.dart b/engine/src/flutter/tools/const_finder/test/fixtures/lib/box.dart deleted file mode 100644 index 51b2a5ed..00000000 --- a/engine/src/flutter/tools/const_finder/test/fixtures/lib/box.dart +++ /dev/null @@ -1,231 +0,0 @@ -// Copyright 2013 The Flutter Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// If canonicalization uses deep structural hashing without memoizing, this -// will exhibit superlinear time. - -// Compare with Dart version of this test at: -// https://github.com/dart-lang/sdk/blob/ca3ad264a64937d5d336cd04dbf2746d1b7d8fc4/tests/language_2/canonicalize/hashing_memoize_instance_test.dart - -class Box { - const Box(this.content1, this.content2); - final Object? content1; // ignore: unreachable_from_main - final Object? content2; // ignore: unreachable_from_main -} - -const Box box1_0 = Box(null, null); -const Box box1_1 = Box(box1_0, box1_0); -const Box box1_2 = Box(box1_1, box1_1); -const Box box1_3 = Box(box1_2, box1_2); -const Box box1_4 = Box(box1_3, box1_3); -const Box box1_5 = Box(box1_4, box1_4); -const Box box1_6 = Box(box1_5, box1_5); -const Box box1_7 = Box(box1_6, box1_6); -const Box box1_8 = Box(box1_7, box1_7); -const Box box1_9 = Box(box1_8, box1_8); -const Box box1_10 = Box(box1_9, box1_9); -const Box box1_11 = Box(box1_10, box1_10); -const Box box1_12 = Box(box1_11, box1_11); -const Box box1_13 = Box(box1_12, box1_12); -const Box box1_14 = Box(box1_13, box1_13); -const Box box1_15 = Box(box1_14, box1_14); -const Box box1_16 = Box(box1_15, box1_15); -const Box box1_17 = Box(box1_16, box1_16); -const Box box1_18 = Box(box1_17, box1_17); -const Box box1_19 = Box(box1_18, box1_18); -const Box box1_20 = Box(box1_19, box1_19); -const Box box1_21 = Box(box1_20, box1_20); -const Box box1_22 = Box(box1_21, box1_21); -const Box box1_23 = Box(box1_22, box1_22); -const Box box1_24 = Box(box1_23, box1_23); -const Box box1_25 = Box(box1_24, box1_24); -const Box box1_26 = Box(box1_25, box1_25); -const Box box1_27 = Box(box1_26, box1_26); -const Box box1_28 = Box(box1_27, box1_27); -const Box box1_29 = Box(box1_28, box1_28); -const Box box1_30 = Box(box1_29, box1_29); -const Box box1_31 = Box(box1_30, box1_30); -const Box box1_32 = Box(box1_31, box1_31); -const Box box1_33 = Box(box1_32, box1_32); -const Box box1_34 = Box(box1_33, box1_33); -const Box box1_35 = Box(box1_34, box1_34); -const Box box1_36 = Box(box1_35, box1_35); -const Box box1_37 = Box(box1_36, box1_36); -const Box box1_38 = Box(box1_37, box1_37); -const Box box1_39 = Box(box1_38, box1_38); -const Box box1_40 = Box(box1_39, box1_39); -const Box box1_41 = Box(box1_40, box1_40); -const Box box1_42 = Box(box1_41, box1_41); -const Box box1_43 = Box(box1_42, box1_42); -const Box box1_44 = Box(box1_43, box1_43); -const Box box1_45 = Box(box1_44, box1_44); -const Box box1_46 = Box(box1_45, box1_45); -const Box box1_47 = Box(box1_46, box1_46); -const Box box1_48 = Box(box1_47, box1_47); -const Box box1_49 = Box(box1_48, box1_48); -const Box box1_50 = Box(box1_49, box1_49); -const Box box1_51 = Box(box1_50, box1_50); -const Box box1_52 = Box(box1_51, box1_51); -const Box box1_53 = Box(box1_52, box1_52); -const Box box1_54 = Box(box1_53, box1_53); -const Box box1_55 = Box(box1_54, box1_54); -const Box box1_56 = Box(box1_55, box1_55); -const Box box1_57 = Box(box1_56, box1_56); -const Box box1_58 = Box(box1_57, box1_57); -const Box box1_59 = Box(box1_58, box1_58); -const Box box1_60 = Box(box1_59, box1_59); -const Box box1_61 = Box(box1_60, box1_60); -const Box box1_62 = Box(box1_61, box1_61); -const Box box1_63 = Box(box1_62, box1_62); -const Box box1_64 = Box(box1_63, box1_63); -const Box box1_65 = Box(box1_64, box1_64); -const Box box1_66 = Box(box1_65, box1_65); -const Box box1_67 = Box(box1_66, box1_66); -const Box box1_68 = Box(box1_67, box1_67); -const Box box1_69 = Box(box1_68, box1_68); -const Box box1_70 = Box(box1_69, box1_69); -const Box box1_71 = Box(box1_70, box1_70); -const Box box1_72 = Box(box1_71, box1_71); -const Box box1_73 = Box(box1_72, box1_72); -const Box box1_74 = Box(box1_73, box1_73); -const Box box1_75 = Box(box1_74, box1_74); -const Box box1_76 = Box(box1_75, box1_75); -const Box box1_77 = Box(box1_76, box1_76); -const Box box1_78 = Box(box1_77, box1_77); -const Box box1_79 = Box(box1_78, box1_78); -const Box box1_80 = Box(box1_79, box1_79); -const Box box1_81 = Box(box1_80, box1_80); -const Box box1_82 = Box(box1_81, box1_81); -const Box box1_83 = Box(box1_82, box1_82); -const Box box1_84 = Box(box1_83, box1_83); -const Box box1_85 = Box(box1_84, box1_84); -const Box box1_86 = Box(box1_85, box1_85); -const Box box1_87 = Box(box1_86, box1_86); -const Box box1_88 = Box(box1_87, box1_87); -const Box box1_89 = Box(box1_88, box1_88); -const Box box1_90 = Box(box1_89, box1_89); -const Box box1_91 = Box(box1_90, box1_90); -const Box box1_92 = Box(box1_91, box1_91); -const Box box1_93 = Box(box1_92, box1_92); -const Box box1_94 = Box(box1_93, box1_93); -const Box box1_95 = Box(box1_94, box1_94); -const Box box1_96 = Box(box1_95, box1_95); -const Box box1_97 = Box(box1_96, box1_96); -const Box box1_98 = Box(box1_97, box1_97); -const Box box1_99 = Box(box1_98, box1_98); - -const Box box2_0 = Box(null, null); -const Box box2_1 = Box(box2_0, box2_0); -const Box box2_2 = Box(box2_1, box2_1); -const Box box2_3 = Box(box2_2, box2_2); -const Box box2_4 = Box(box2_3, box2_3); -const Box box2_5 = Box(box2_4, box2_4); -const Box box2_6 = Box(box2_5, box2_5); -const Box box2_7 = Box(box2_6, box2_6); -const Box box2_8 = Box(box2_7, box2_7); -const Box box2_9 = Box(box2_8, box2_8); -const Box box2_10 = Box(box2_9, box2_9); -const Box box2_11 = Box(box2_10, box2_10); -const Box box2_12 = Box(box2_11, box2_11); -const Box box2_13 = Box(box2_12, box2_12); -const Box box2_14 = Box(box2_13, box2_13); -const Box box2_15 = Box(box2_14, box2_14); -const Box box2_16 = Box(box2_15, box2_15); -const Box box2_17 = Box(box2_16, box2_16); -const Box box2_18 = Box(box2_17, box2_17); -const Box box2_19 = Box(box2_18, box2_18); -const Box box2_20 = Box(box2_19, box2_19); -const Box box2_21 = Box(box2_20, box2_20); -const Box box2_22 = Box(box2_21, box2_21); -const Box box2_23 = Box(box2_22, box2_22); -const Box box2_24 = Box(box2_23, box2_23); -const Box box2_25 = Box(box2_24, box2_24); -const Box box2_26 = Box(box2_25, box2_25); -const Box box2_27 = Box(box2_26, box2_26); -const Box box2_28 = Box(box2_27, box2_27); -const Box box2_29 = Box(box2_28, box2_28); -const Box box2_30 = Box(box2_29, box2_29); -const Box box2_31 = Box(box2_30, box2_30); -const Box box2_32 = Box(box2_31, box2_31); -const Box box2_33 = Box(box2_32, box2_32); -const Box box2_34 = Box(box2_33, box2_33); -const Box box2_35 = Box(box2_34, box2_34); -const Box box2_36 = Box(box2_35, box2_35); -const Box box2_37 = Box(box2_36, box2_36); -const Box box2_38 = Box(box2_37, box2_37); -const Box box2_39 = Box(box2_38, box2_38); -const Box box2_40 = Box(box2_39, box2_39); -const Box box2_41 = Box(box2_40, box2_40); -const Box box2_42 = Box(box2_41, box2_41); -const Box box2_43 = Box(box2_42, box2_42); -const Box box2_44 = Box(box2_43, box2_43); -const Box box2_45 = Box(box2_44, box2_44); -const Box box2_46 = Box(box2_45, box2_45); -const Box box2_47 = Box(box2_46, box2_46); -const Box box2_48 = Box(box2_47, box2_47); -const Box box2_49 = Box(box2_48, box2_48); -const Box box2_50 = Box(box2_49, box2_49); -const Box box2_51 = Box(box2_50, box2_50); -const Box box2_52 = Box(box2_51, box2_51); -const Box box2_53 = Box(box2_52, box2_52); -const Box box2_54 = Box(box2_53, box2_53); -const Box box2_55 = Box(box2_54, box2_54); -const Box box2_56 = Box(box2_55, box2_55); -const Box box2_57 = Box(box2_56, box2_56); -const Box box2_58 = Box(box2_57, box2_57); -const Box box2_59 = Box(box2_58, box2_58); -const Box box2_60 = Box(box2_59, box2_59); -const Box box2_61 = Box(box2_60, box2_60); -const Box box2_62 = Box(box2_61, box2_61); -const Box box2_63 = Box(box2_62, box2_62); -const Box box2_64 = Box(box2_63, box2_63); -const Box box2_65 = Box(box2_64, box2_64); -const Box box2_66 = Box(box2_65, box2_65); -const Box box2_67 = Box(box2_66, box2_66); -const Box box2_68 = Box(box2_67, box2_67); -const Box box2_69 = Box(box2_68, box2_68); -const Box box2_70 = Box(box2_69, box2_69); -const Box box2_71 = Box(box2_70, box2_70); -const Box box2_72 = Box(box2_71, box2_71); -const Box box2_73 = Box(box2_72, box2_72); -const Box box2_74 = Box(box2_73, box2_73); -const Box box2_75 = Box(box2_74, box2_74); -const Box box2_76 = Box(box2_75, box2_75); -const Box box2_77 = Box(box2_76, box2_76); -const Box box2_78 = Box(box2_77, box2_77); -const Box box2_79 = Box(box2_78, box2_78); -const Box box2_80 = Box(box2_79, box2_79); -const Box box2_81 = Box(box2_80, box2_80); -const Box box2_82 = Box(box2_81, box2_81); -const Box box2_83 = Box(box2_82, box2_82); -const Box box2_84 = Box(box2_83, box2_83); -const Box box2_85 = Box(box2_84, box2_84); -const Box box2_86 = Box(box2_85, box2_85); -const Box box2_87 = Box(box2_86, box2_86); -const Box box2_88 = Box(box2_87, box2_87); -const Box box2_89 = Box(box2_88, box2_88); -const Box box2_90 = Box(box2_89, box2_89); -const Box box2_91 = Box(box2_90, box2_90); -const Box box2_92 = Box(box2_91, box2_91); -const Box box2_93 = Box(box2_92, box2_92); -const Box box2_94 = Box(box2_93, box2_93); -const Box box2_95 = Box(box2_94, box2_94); -const Box box2_96 = Box(box2_95, box2_95); -const Box box2_97 = Box(box2_96, box2_96); -const Box box2_98 = Box(box2_97, box2_97); -const Box box2_99 = Box(box2_98, box2_98); - -Object confuse(Box x) { - try { - throw x; // ignore: only_throw_errors - } catch (e) { - return e; - } -} - -void main() { - if (!identical(confuse(box1_99), confuse(box2_99))) { - throw Exception('box1_99 !== box2_99'); - } -} diff --git a/engine/src/flutter/tools/const_finder/test/fixtures/lib/consts.dart b/engine/src/flutter/tools/const_finder/test/fixtures/lib/consts.dart deleted file mode 100644 index 2afa8ca5..00000000 --- a/engine/src/flutter/tools/const_finder/test/fixtures/lib/consts.dart +++ /dev/null @@ -1,76 +0,0 @@ -// Copyright 2013 The Flutter Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// ignore_for_file: prefer_const_constructors, unused_local_variable -import 'dart:core'; - -import 'package:const_finder_fixtures_package/package.dart'; - -import 'target.dart'; - -void main() { - const target1 = Target('1', 1, null); - const target2 = Target('2', 2, Target('4', 4, null)); - const target3 = Target('3', 3, Target('5', 5, null)); // should be tree shaken out. - target1.hit(); - target2.hit(); - - blah(const Target('6', 6, null)); - - const ignoreMe = IgnoreMe(Target('7', 7, null)); // IgnoreMe is ignored but 7 is not. - final ignoreMe2 = IgnoreMe(const Target('8', 8, null)); - final ignoreMe3 = IgnoreMe(const Target('9', 9, Target('10', 10, null))); - print(ignoreMe); - print(ignoreMe2); - print(ignoreMe3); - - createTargetInPackage(); - - final staticConstMap = StaticConstInitializer(); - staticConstMap.useOne(1); - - const extendsTarget = ExtendsTarget('11', 11, null); - extendsTarget.hit(); - const implementsTarget = ImplementsTarget('12', 12, null); - implementsTarget.hit(); - - const mixedInTraget = MixedInTarget('13'); - mixedInTraget.hit(); -} - -class IgnoreMe { - const IgnoreMe(this.target); - - final Target target; - - @override - String toString() => target.toString(); -} - -class StaticConstInitializer { - static const List targets = [ - Target('100', 100, null), - Target('101', 101, Target('102', 102, null)), - ]; - - static const Set targetSet = { - Target('103', 103, null), - Target('104', 104, Target('105', 105, null)), - }; - - static const Map targetMap = { - 0: Target('106', 106, null), - 1: Target('107', 107, Target('108', 108, null)), - }; - - void useOne(int index) { - targets[index].hit(); - targetSet.skip(index).first.hit(); - targetMap[index]!.hit(); - } -} - -void blah(Target target) { - print(target); -} diff --git a/engine/src/flutter/tools/const_finder/test/fixtures/lib/consts_and_non.dart b/engine/src/flutter/tools/const_finder/test/fixtures/lib/consts_and_non.dart deleted file mode 100644 index f06cae49..00000000 --- a/engine/src/flutter/tools/const_finder/test/fixtures/lib/consts_and_non.dart +++ /dev/null @@ -1,44 +0,0 @@ -// Copyright 2013 The Flutter Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// ignore_for_file: prefer_const_constructors, unused_local_variable -import 'dart:core'; - -import 'package:const_finder_fixtures_package/package.dart'; - -import 'target.dart'; - -void main() { - const target1 = Target('1', 1, null); - final target2 = Target('2', 2, const Target('4', 4, null)); - - final target3 = Target('3', 3, Target('5', 5, null)); // should be tree shaken out. - final target6 = Target('6', 6, null); // should be tree shaken out. - target1.hit(); - target2.hit(); - - blah(const Target('6', 6, null)); - - const ignoreMe = IgnoreMe(Target('7', 7, null)); // IgnoreMe is ignored but 7 is not. - final ignoreMe2 = IgnoreMe(const Target('8', 8, null)); - final ignoreMe3 = IgnoreMe(const Target('9', 9, Target('10', 10, null))); - print(ignoreMe); - print(ignoreMe2); - print(ignoreMe3); - - createNonConstTargetInPackage(); -} - -class IgnoreMe { - const IgnoreMe(this.target); - - final Target target; - - @override - String toString() => target.toString(); -} - -void blah(Target target) { - print(target); -} diff --git a/engine/src/flutter/tools/const_finder/test/fixtures/lib/static_icon_provider.dart b/engine/src/flutter/tools/const_finder/test/fixtures/lib/static_icon_provider.dart deleted file mode 100644 index 11840397..00000000 --- a/engine/src/flutter/tools/const_finder/test/fixtures/lib/static_icon_provider.dart +++ /dev/null @@ -1,31 +0,0 @@ -// Copyright 2013 The Flutter Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -import 'target.dart'; - -void main() { - Targets.used1.hit(); - Targets.used2.hit(); - final Target nonConstUsed3 = helper(Target.new); - nonConstUsed3.hit(); -} - -Target helper(Target Function(String, int, Target?) tearOff) { - return tearOff('from tear-off', 3, null); -} - -@staticIconProvider -class Targets { - static const Target used1 = Target('used1', 1, null); - static const Target used2 = Target('used2', 2, null); - static const Target unused1 = Target('unused1', 1, null); // ignore: unreachable_from_main -} - -// const_finder explicitly does not retain constants appearing within a class -// with this annotation. -class StaticIconProvider { - const StaticIconProvider(); -} - -const StaticIconProvider staticIconProvider = StaticIconProvider(); diff --git a/engine/src/flutter/tools/const_finder/test/fixtures/lib/target.dart b/engine/src/flutter/tools/const_finder/test/fixtures/lib/target.dart deleted file mode 100644 index 821dade2..00000000 --- a/engine/src/flutter/tools/const_finder/test/fixtures/lib/target.dart +++ /dev/null @@ -1,50 +0,0 @@ -// Copyright 2013 The Flutter Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -class Target { - const Target(this.stringValue, this.intValue, this.targetValue); - - final String stringValue; - final int intValue; - final Target? targetValue; - - void hit() { - print('$stringValue $intValue'); - } -} - -class ExtendsTarget extends Target { - const ExtendsTarget(super.stringValue, super.intValue, super.targetValue); -} - -class ImplementsTarget implements Target { - const ImplementsTarget(this.stringValue, this.intValue, this.targetValue); - - @override - final String stringValue; - @override - final int intValue; - @override - final Target? targetValue; - - @override - void hit() { - print('ImplementsTarget - $stringValue $intValue'); - } -} - -mixin MixableTarget { - String get val; - - void hit() { - print(val); - } -} - -class MixedInTarget with MixableTarget { - const MixedInTarget(this.val); - - @override - final String val; -} diff --git a/engine/src/flutter/tools/const_finder/test/fixtures/pkg/package.dart b/engine/src/flutter/tools/const_finder/test/fixtures/pkg/package.dart deleted file mode 100644 index 6a9011f8..00000000 --- a/engine/src/flutter/tools/const_finder/test/fixtures/pkg/package.dart +++ /dev/null @@ -1,16 +0,0 @@ -// Copyright 2013 The Flutter Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// ignore_for_file: prefer_const_constructors -import 'package:const_finder_fixtures/target.dart'; - -void createTargetInPackage() { - const target = Target('package', -1, null); - target.hit(); -} - -void createNonConstTargetInPackage() { - final target = Target('package_non', -2, null); - target.hit(); -} diff --git a/engine/src/flutter/tools/font_subset/BUILD.gn b/engine/src/flutter/tools/font_subset/BUILD.gn index 14d23cf6..37c3719d 100644 --- a/engine/src/flutter/tools/font_subset/BUILD.gn +++ b/engine/src/flutter/tools/font_subset/BUILD.gn @@ -54,15 +54,10 @@ zip_bundle("font_subset") { source = "$root_build_dir/$font_subset_bin" destination = font_subset_bin }, - { - source = "$root_gen_dir/const_finder.dart.snapshot" - destination = "const_finder.dart.snapshot" - }, ] deps = [ ":_font-subset", - "//flutter/tools/const_finder", ] if (is_mac) { deps += [ ":font_entitlement_config" ] diff --git a/engine/src/flutter/tools/gn b/engine/src/flutter/tools/gn index bb2bfb14..f26cbb74 100755 --- a/engine/src/flutter/tools/gn +++ b/engine/src/flutter/tools/gn @@ -562,11 +562,6 @@ def to_gn_args(args): gn_args['concurrent_toolchain_jobs'] = get_concurrent_jobs('1GB', '100MB') - # Hardcoding this avoids invoking a relatively expensive python script from - # GN, but removes the ability to use git-worktrees in the Dart checkout from - # within the Engine repo, but it's unlikely anyone is using that. - gn_args['default_git_folder'] = os.path.join(get_dart_path(), '.git') - # By default, the Dart GN build will invoke a relatively expensive python # script to calculate an SDK "hash" that ensures compatibility between the # Dart VM and the Dart front-end. This default hash calculation allows some diff --git a/examples/hello_world/analysis_options.yaml b/examples/hello_world/analysis_options.yaml index f9b30346..743e05ad 100644 --- a/examples/hello_world/analysis_options.yaml +++ b/examples/hello_world/analysis_options.yaml @@ -1 +1,10 @@ +analyzer: + exclude: + - build/** + - android/** + - ios/** + - web/** + - windows/** + - macos/** + - linux/** include: package:flutter_lints/flutter.yaml From 512315a944f91dd19eef5976b904ff9dd27827c1 Mon Sep 17 00:00:00 2001 From: Matej Knopp Date: Fri, 2 Oct 2026 21:16:02 +0200 Subject: [PATCH 3/6] Remove const_finder from pub_get_offline --- engine/src/flutter/tools/pub_get_offline.py | 1 - 1 file changed, 1 deletion(-) diff --git a/engine/src/flutter/tools/pub_get_offline.py b/engine/src/flutter/tools/pub_get_offline.py index 2bc0f920..59e6e9e2 100644 --- a/engine/src/flutter/tools/pub_get_offline.py +++ b/engine/src/flutter/tools/pub_get_offline.py @@ -36,7 +36,6 @@ os.path.join(ENGINE_DIR, 'tools', 'build_bucket_golden_scraper'), os.path.join(ENGINE_DIR, 'tools', 'clang_tidy'), os.path.join(ENGINE_DIR, 'tools', 'clangd_check'), - os.path.join(ENGINE_DIR, 'tools', 'const_finder'), os.path.join(ENGINE_DIR, 'tools', 'engine_tool'), os.path.join(ENGINE_DIR, 'tools', 'gen_web_locale_keymap'), os.path.join(ENGINE_DIR, 'tools', 'githooks'), From e70efa7aced2aee2ee8becc6cdd1415202c8a49c Mon Sep 17 00:00:00 2001 From: Matej Knopp Date: Fri, 16 Oct 2026 16:41:15 +0200 Subject: [PATCH 4/6] Update dependencies. --- DEPS | 46 +++++++++++++++++++++++----------------------- 1 file changed, 23 insertions(+), 23 deletions(-) diff --git a/DEPS b/DEPS index bd6e3899..8d5494bb 100644 --- a/DEPS +++ b/DEPS @@ -47,24 +47,24 @@ vars = { # updated revision list of existing dependencies. You will need to # gclient sync before and after update deps to ensure all deps are updated. # updated revision list of existing dependencies. - 'dart_revision': '0e7642b85457515cfac6ffda9e0e10906a5e5356', + 'dart_revision': '55a734a01fb13e51162d4fff5439c193d681e5d2', # WARNING: DO NOT EDIT MANUALLY # The lines between blank lines above and below are generated by a script. See create_updated_flutter_deps.py - 'dart_binaryen_rev': '9926156a583cec3d22d521232b31c70fa9a87dc1', - 'dart_boringssl_rev': '1097261733d85c85147a5c96ff6ee835c90f5951', - 'dart_core_rev': '08e4022160c465780690c43ffdbce60812975d2c', - 'dart_devtools_rev': 'fd39ed6deeed50104b5262d8228f5ae3ceab7bfd', - 'dart_ecosystem_rev': '16dca7ae5d3ff896a4db47e1ed6cd50f7ebbf115', - 'dart_http_rev': 'd8e8e9cd1ae6ed0f0339cfa0f47f92e837a786f5', + 'dart_binaryen_rev': '1c0c9f3836e858e01c4f94ac2e5a936d16a6ba1d', + 'dart_boringssl_rev': '44979b8a96e43671e1283fdfc6757724248978bc', + 'dart_core_rev': '4d80610a878cdb3f9f10e6a16a2af6631251a3c6', + 'dart_devtools_rev': '85f945ac99379d64d4df6f67d9b011e4cc418e7e', + 'dart_ecosystem_rev': '622ef61a7edd5de7df38661e163e55c57606c96a', + 'dart_http_rev': '7d7aae2fb8777f2bb31599fdde18b11e3dd6f986', 'dart_i18n_rev': '1f5ea2fb2381bdf7bab054a43c0d69771f104561', 'dart_perfetto_rev': '13ce0c9e13b0940d2476cd0cff2301708a9a2e2b', 'dart_protobuf_rev': 'a73edc98c98fb25152aa3f12c1b9db91594c1369', - 'dart_pub_rev': '0382a52acba89ff0080d559bb22f4017962bbd1d', + 'dart_pub_rev': 'eca8f8ada939be70f0be3189db31e421dd0be7fd', 'dart_sync_http_rev': '6666fff944221891182e1f80bf56569338164d72', - 'dart_tools_rev': '3614ce064ae452a15e83de3531236f5f89dfa526', + 'dart_tools_rev': '350bde54f8f1a8f49cf2ed520b8999afde02e25a', 'dart_vector_math_rev': 'cf3b5db7340d317dd3489e5a35434b408020a852', - 'dart_web_rev': 'e5c6c028da66688a2295557757850a1599ec392e', + 'dart_web_rev': '63e6662dc7022a54439d4da6016685c49a0d6018', 'dart_webdriver_rev': '8e5c611ea242efdc9f597a8a37c38a9c586120ee', 'dart_webkit_inspection_protocol_rev': '762115a971d1968bc940454ad1e88d506d8c5640', @@ -93,7 +93,7 @@ vars = { # logic or condition may not work if this flag is False. # TODO(zijiehe): Make this condition more strict to only download fuchsia # dependencies when necessary: b/40935282 - 'download_fuchsia_deps': False, #'host_os == "linux"', + 'download_fuchsia_deps': False, #'host_os == "linux" and host_cpu == "x64"', # Downloads the fuchsia SDK as listed in fuchsia_sdk_path var. This variable # is currently only used for the Fuchsia LSC process and is not intended for # local development. @@ -181,11 +181,11 @@ vars = { # The version / instance id of the cipd:chromium/fuchsia/test-scripts which # will be used altogether with fuchsia-sdk to setup the build / test # environment. - 'fuchsia_test_scripts_version': 'whZAV1mfT-Rdc0rQ81s_IEef2L7kbGPFtiQPitjf_akC', + 'fuchsia_test_scripts_version': '2T18KC7-LDQtmQiLP1Rg2lDrCCXFDhyJT9-NxMKlV00C', # The version / instance id of the cipd:chromium/fuchsia/gn-sdk which will be # used altogether with fuchsia-sdk to generate gn based build rules. - 'fuchsia_gn_sdk_version': 'PDJz3b3CL31uoLOkDb0mm8FidqJ1eCJryoRFd9iVmbIC', + 'fuchsia_gn_sdk_version': 'kFdyRnojbVy0cxvRZueVcnyi4XuxGnAiSK0YOvpzOG8C', } gclient_gn_args_file = 'engine/src/flutter/third_party/dart/build/config/gclient_args.gni' @@ -225,7 +225,7 @@ deps = { Var('llvm_git') + '/llvm-project/libc' + '@' + '5af39a19a1ad51ce93972cdab206dcd3ff9b6afa', 'engine/src/flutter/third_party/icu': - Var('chromium_git') + '/chromium/deps/icu.git' + '@' + '6ebb40c594776cc2c21ea14df85a2a89a328b364', + Var('chromium_git') + '/chromium/deps/icu.git' + '@' + '5aa526207171ecadf31597f0980a7b7ad8872f33', 'engine/src/flutter/third_party/gtest-parallel': Var('chromium_git') + '/external/github.com/google/gtest-parallel' + '@' + '38191e2733d7cbaeaef6a3f1a942ddeb38a2ad14', @@ -257,7 +257,7 @@ deps = { Var('chromium_git') + '/external/github.com/WebAssembly/binaryen.git' + '@' + Var('dart_binaryen_rev'), 'engine/src/flutter/third_party/dart/third_party/devtools': - {'dep_type': 'cipd', 'packages': [{'package': 'dart/third_party/flutter/devtools', 'version': 'git_revision:fd39ed6deeed50104b5262d8228f5ae3ceab7bfd'}]}, + {'dep_type': 'cipd', 'packages': [{'package': 'dart/third_party/flutter/devtools', 'version': 'git_revision:85f945ac99379d64d4df6f67d9b011e4cc418e7e'}]}, 'engine/src/flutter/third_party/dart/third_party/perfetto/src': Var('chromium_git') + '/external/github.com/google/perfetto' + '@' + Var('dart_perfetto_rev'), @@ -266,10 +266,10 @@ deps = { Var('dart_git') + '/core.git' + '@' + Var('dart_core_rev'), 'engine/src/flutter/third_party/dart/third_party/pkg/dart_style': - Var('dart_git') + '/dart_style.git@5a9534fad9ff2faba89596a70323d2b1f1bcf163', + Var('dart_git') + '/dart_style.git@76978d23bfb3d225c81ce3f119ab7055a2a57136', 'engine/src/flutter/third_party/dart/third_party/pkg/dartdoc': - Var('dart_git') + '/dartdoc.git@c68debcb5636ba8d66210110092d39d5b06f8225', + Var('dart_git') + '/dartdoc.git@e1859cfc70702d65476b087b0d577db18c67abfa', 'engine/src/flutter/third_party/dart/third_party/pkg/ecosystem': Var('dart_git') + '/ecosystem.git' + '@' + Var('dart_ecosystem_rev'), @@ -284,7 +284,7 @@ deps = { Var('dart_git') + '/leak_tracker.git@f5620600a5ce1c44f65ddaa02001e200b096e14c', 'engine/src/flutter/third_party/dart/third_party/pkg/native': - Var('dart_git') + '/native.git@f628b26f039c3824d83c352c489fd1a4496780d0', + Var('dart_git') + '/native.git@cc7e4b076efadf9705de472bcbed05bf32a87d6a', 'engine/src/flutter/third_party/dart/third_party/pkg/protobuf': Var('dart_git') + '/protobuf.git' + '@' + Var('dart_protobuf_rev'), @@ -293,7 +293,7 @@ deps = { Var('dart_git') + '/pub.git' + '@' + Var('dart_pub_rev'), 'engine/src/flutter/third_party/dart/third_party/pkg/shelf': - Var('dart_git') + '/shelf.git@e5c8dc663bf1325ad8f997c4a2387923d37a90d9', + Var('dart_git') + '/shelf.git@b2cb503d3ba2f0ce6320b820f2b3b0c2b1777485', 'engine/src/flutter/third_party/dart/third_party/pkg/sync_http': Var('dart_git') + '/sync_http.git' + '@' + Var('dart_sync_http_rev'), @@ -302,7 +302,7 @@ deps = { Var('dart_git') + '/external/github.com/simolus3/tar.git@13479f7c2a18f499e840ad470cfcca8c579f6909', 'engine/src/flutter/third_party/dart/third_party/pkg/test': - Var('dart_git') + '/test.git@9946c9551ddaffd6092c22372b7e146600aa3264', + Var('dart_git') + '/test.git@9bf69a88002d96855abf0a27ff09ca28ce087332', 'engine/src/flutter/third_party/dart/third_party/pkg/tools': Var('dart_git') + '/tools.git' + '@' + Var('dart_tools_rev'), @@ -559,7 +559,7 @@ deps = { 'packages': [ { 'package': 'flutter/java/openjdk/${{platform}}', - 'version': 'version:21' + 'version': 'version:25.0.2' } ], # Always download the JDK since java is required for running the formatter. @@ -572,7 +572,7 @@ deps = { 'packages': [ { 'package': 'gn/gn/${{platform}}', - 'version': 'git_revision:81b24e01531ecf0eff12ec9359a555ec3944ec4e' + 'version': 'git_revision:f9eca75ae5549af4a6d4a2e2a912c652590de9da' }, ], 'dep_type': 'cipd', @@ -729,7 +729,7 @@ deps = { 'packages': [ { 'package': 'fuchsia/sdk/core/linux-amd64', - 'version': 'ukukV5lEkKabtOATkSbVa6yIaU7g4nfmCcVvWNxfMQMC' + 'version': 'QdgqP02_cYpRQQQNNuRjshiknJeDe5ZKXyqGq2YkqKkC' } ], 'condition': 'download_fuchsia_deps and not download_fuchsia_sdk', From e6a65f0b45d1008f1787ca8766b4167c4dcd879d Mon Sep 17 00:00:00 2001 From: Matej Knopp Date: Fri, 16 Oct 2026 16:46:55 +0200 Subject: [PATCH 5/6] Reformat everything. --- engine/src/flutter/BUILD.gn | 5 +- engine/src/flutter/build/archives/BUILD.gn | 14 +- .../dart/internal/flutter_frontend_server.gni | 1 + .../build/dart/internal/flutter_snapshot.gni | 7 +- engine/src/flutter/build/dart/test/BUILD.gn | 3 +- engine/src/flutter/build/esbuild/esbuild.gni | 1 + .../testing/libfuzzer/fuzzer_test.gni | 1 + engine/src/flutter/common/settings.h | 1 - engine/src/flutter/lib/snapshot/BUILD.gn | 8 +- .../src/flutter/lib/ui/channel_buffers.dart | 6 +- .../flutter/lib/ui/platform_dispatcher.dart | 7 +- engine/src/flutter/lib/ui/ui_benchmarks.cc | 2 +- .../flutter/lib/web_ui/dev/felt_config.dart | 1 + .../lib/web_ui/lib/channel_buffers.dart | 6 +- .../lib/web_ui/lib/platform_dispatcher.dart | 7 +- .../web_ui/lib/src/engine/configuration.dart | 13 +- .../lib/web_ui/lib/src/engine/dom.dart | 13 +- .../lib/src/engine/js_interop/js_loader.dart | 7 +- .../test/engine/initialization_test.dart | 138 ++++--- engine/src/flutter/runtime/BUILD.gn | 3 +- .../flutter/runtime/dart_isolate_unittests.cc | 3 +- engine/src/flutter/shell/common/BUILD.gn | 5 +- .../flutter/shell/platform/android/BUILD.gn | 6 +- .../android/FlutterEngineProvider.java | 4 +- .../embedding/engine/FlutterEngine.java | 300 +++++---------- .../FlutterEngineConnectionRegistry.java | 1 - .../embedding/engine/FlutterEngineGroup.java | 16 +- .../engine/FlutterEngineGroupCache.java | 5 +- .../flutter/embedding/engine/FlutterJNI.java | 357 ++++++------------ .../engine/plugins/FlutterPlugin.java | 9 +- .../FlutterEngineGroupComponentTest.java | 11 +- .../embedding/engine/FlutterEngineTest.java | 2 - .../engine/FlutterShellArgsTest.java | 1 - .../embedding/engine/PluginComponentTest.java | 2 - .../flutter/shell/platform/common/BUILD.gn | 4 +- .../platform/common/client_wrapper/BUILD.gn | 4 +- .../framework/Source/FlutterChannels.mm | 8 +- .../shell/platform/darwin/macos/BUILD.gn | 1 - .../framework/Source/FlutterEngineTest.mm | 2 +- .../flutter/shell/platform/embedder/BUILD.gn | 12 +- .../shell/platform/embedder/embedder.cc | 2 +- .../platform/embedder/fixtures/main.dart | 17 +- .../dart-pkg/zircon_ffi/lib/zircon_ffi.dart | 169 +++++---- .../platform/fuchsia/dart_runner/BUILD.gn | 2 + .../fuchsia/dart_runner/embedder/BUILD.gn | 4 +- .../dart_echo_server/BUILD.gn | 6 +- .../src/flutter/shell/platform/linux/BUILD.gn | 3 +- .../shell/platform/linux/fl_engine_test.cc | 17 +- .../linux/fl_plugin_registrar_private.h | 3 +- .../flutter/shell/platform/windows/BUILD.gn | 9 +- .../platform/windows/client_wrapper/BUILD.gn | 12 +- .../windows/flutter_windows_engine.cc | 3 +- .../flutter_windows_engine_unittests.cc | 2 +- .../testing/windows_test_config_builder.h | 1 - .../testing/android/native_activity/BUILD.gn | 4 +- .../native_activity/native_activity.gni | 3 + engine/src/flutter/testing/dart/BUILD.gn | 1 + engine/src/flutter/testing/run_tests.py | 21 +- engine/src/flutter/testing/testing.gni | 4 + engine/src/flutter/tools/font_subset/BUILD.gn | 7 +- .../tools/fuchsia/dart/dart_library.gni | 10 +- .../flutter/tools/fuchsia/dart/dart_tool.gni | 1 + .../tools/fuchsia/dart/kernel/dart_kernel.gni | 4 +- .../fuchsia/flutter/flutter_build_config.gni | 4 +- .../internal/flutter_dart_component.gni | 9 +- .../flutter/tools/fuchsia/fuchsia_archive.gni | 4 + .../flutter/tools/fuchsia/fuchsia_libs.gni | 7 +- .../fuchsia/toolchain/basic_toolchain.gni | 1 + .../lib/github_workflow_generator.dart | 61 +-- engine/src/flutter/web_sdk/BUILD.gn | 8 +- engine/src/flutter/web_sdk/sdk_rewriter.dart | 5 +- .../web_sdk/test/sdk_rewriter_test.dart | 4 +- .../web_test_utils/lib/environment.dart | 1 + 73 files changed, 610 insertions(+), 796 deletions(-) diff --git a/engine/src/flutter/BUILD.gn b/engine/src/flutter/BUILD.gn index 77b676ac..8cf0d534 100644 --- a/engine/src/flutter/BUILD.gn +++ b/engine/src/flutter/BUILD.gn @@ -195,9 +195,7 @@ group("unittests") { } if (!is_win && !is_fuchsia) { - public_deps += [ - "//flutter/shell/platform/android/jni:jni_unittests", - ] + public_deps += [ "//flutter/shell/platform/android/jni:jni_unittests" ] } # Unit tests for desktop embeddings should only be built if the desktop @@ -262,6 +260,7 @@ if (is_fuchsia && enable_unittests) { # we can specify the toolchain to use, too. if (host_os == "win") { _gen_snapshot_target = "$dart_src/runtime/bin:gen_snapshot($host_toolchain)" + copy("gen_snapshot") { deps = [ _gen_snapshot_target ] diff --git a/engine/src/flutter/build/archives/BUILD.gn b/engine/src/flutter/build/archives/BUILD.gn index 708742f3..b535e4da 100644 --- a/engine/src/flutter/build/archives/BUILD.gn +++ b/engine/src/flutter/build/archives/BUILD.gn @@ -12,9 +12,7 @@ generated_file("artifacts_entitlement_config") { deps = [ "//flutter/lib/snapshot:generate_snapshot_bin" ] if (flutter_runtime_mode == "debug") { - deps += [ - "//flutter/shell/testing", - ] + deps += [ "//flutter/shell/testing" ] } } @@ -48,9 +46,10 @@ if (build_engine_artifacts) { "//flutter/shell/testing", ] if (is_mac) { - # TODO(godofredoc): Remove after paths are standardized flutter/flutter#105351. - # Mac artifacts sometimes use mac and sometimes darwin. Standardizing the - # names will require changes in the list of artifacts the tool is downloading. + # TODO(godofredoc): Remove after paths are standardized + # flutter/flutter#105351. Mac artifacts sometimes use mac and sometimes + # darwin. Standardizing the names will require changes in the list of + # artifacts the tool is downloading. if (flutter_runtime_mode == "debug") { prefix = "darwin-$target_cpu" } else { @@ -188,7 +187,8 @@ if (build_engine_artifacts && flutter_prebuilt_dart_sdk) { ] if (is_mac) { # Mac artifacts sometimes use mac and sometimes darwin. Standardizing the - # names will require changes in the list of artifacts the tool is downloading. + # names will require changes in the list of artifacts the tool is + # downloading. output = "dart-sdk-darwin-$target_cpu.zip" files += [ { diff --git a/engine/src/flutter/build/dart/internal/flutter_frontend_server.gni b/engine/src/flutter/build/dart/internal/flutter_frontend_server.gni index 372527a8..a56ef4cb 100644 --- a/engine/src/flutter/build/dart/internal/flutter_frontend_server.gni +++ b/engine/src/flutter/build/dart/internal/flutter_frontend_server.gni @@ -76,6 +76,7 @@ template("flutter_frontend_server") { if (flutter_prebuilt_dart_sdk) { common_deps += [ "//flutter/flutter_frontend_server:frontend_server" ] + action(target_name) { forward_variables_from(invoker, [ diff --git a/engine/src/flutter/build/dart/internal/flutter_snapshot.gni b/engine/src/flutter/build/dart/internal/flutter_snapshot.gni index 2af42d11..c1ac80ed 100644 --- a/engine/src/flutter/build/dart/internal/flutter_snapshot.gni +++ b/engine/src/flutter/build/dart/internal/flutter_snapshot.gni @@ -71,9 +71,10 @@ template("flutter_snapshot") { compiled_action(snapshot_target) { if (target_cpu == "x86" && host_os == "linux") { - # By default Dart will create a 32-bit gen_snapshot host binary if the target - # platform is 32-bit. Override this to create a 64-bit gen_snapshot for x86 - # targets because some host platforms may not support 32-bit binaries. + # By default Dart will create a 32-bit gen_snapshot host binary if the + # target platform is 32-bit. Override this to create a 64-bit gen_snapshot + # for x86 targets because some host platforms may not support 32-bit + # binaries. tool = "$dart_src/runtime/bin:gen_snapshot_host_targeting_host" toolchain = "//build/toolchain/$host_os:clang_x64" } else { diff --git a/engine/src/flutter/build/dart/test/BUILD.gn b/engine/src/flutter/build/dart/test/BUILD.gn index c33392a8..5f0758ad 100644 --- a/engine/src/flutter/build/dart/test/BUILD.gn +++ b/engine/src/flutter/build/dart/test/BUILD.gn @@ -16,7 +16,8 @@ gen_executable_call("gen_executable_call") { args = [ "Hello, World!" ] } -# ninja -C ../out/host_debug flutter/build/dart/test:gen_executable_call_with_cwd +# ninja -C ../out/host_debug +# flutter/build/dart/test:gen_executable_call_with_cwd # ../out/host_debug/gen/flutter/build/dart/test/gen_executable_call_with_cwd # # Expected output: {varies}/flutter/build/dart/test diff --git a/engine/src/flutter/build/esbuild/esbuild.gni b/engine/src/flutter/build/esbuild/esbuild.gni index f20cdb3c..119109cf 100644 --- a/engine/src/flutter/build/esbuild/esbuild.gni +++ b/engine/src/flutter/build/esbuild/esbuild.gni @@ -7,6 +7,7 @@ import("//flutter/common/config.gni") template("esbuild") { assert(defined(invoker.entry_point)) assert(defined(invoker.output_bundle)) + action(target_name) { forward_variables_from(invoker, [ "public_deps" ]) if (host_os == "win") { diff --git a/engine/src/flutter/build/secondary/testing/libfuzzer/fuzzer_test.gni b/engine/src/flutter/build/secondary/testing/libfuzzer/fuzzer_test.gni index 8f8f3e75..02052a05 100644 --- a/engine/src/flutter/build/secondary/testing/libfuzzer/fuzzer_test.gni +++ b/engine/src/flutter/build/secondary/testing/libfuzzer/fuzzer_test.gni @@ -6,6 +6,7 @@ # implementation from the real (Chromium) fuzzer_test.gni. template("fuzzer_test") { not_needed(invoker, "*") + group(target_name) { } } diff --git a/engine/src/flutter/common/settings.h b/engine/src/flutter/common/settings.h index 11df6914..92eda59a 100644 --- a/engine/src/flutter/common/settings.h +++ b/engine/src/flutter/common/settings.h @@ -289,7 +289,6 @@ struct Settings { // Max bytes threshold of resource cache, or 0 for unlimited. size_t resource_cache_max_bytes_threshold = 0; - enum class MergedPlatformUIThread { // Use separate threads for the UI and platform task runners. kDisabled, diff --git a/engine/src/flutter/lib/snapshot/BUILD.gn b/engine/src/flutter/lib/snapshot/BUILD.gn index bc1359d7..d9b96ca4 100644 --- a/engine/src/flutter/lib/snapshot/BUILD.gn +++ b/engine/src/flutter/lib/snapshot/BUILD.gn @@ -56,6 +56,7 @@ generated_file("vm_isolate_snapshot_data") { contents = "" outputs = [ "$target_gen_dir/vm_isolate_snapshot.bin" ] } + generated_file("vm_isolate_snapshot_instructions") { contents = "" outputs = [ "$target_gen_dir/vm_snapshot_instructions.bin" ] @@ -79,9 +80,10 @@ generated_file("vm_isolate_snapshot_instructions") { # See: https://github.com/flutter/flutter/wiki/Flutter-engine-operation-in-AOT-Mode compiled_action("generate_snapshot_bin") { if (target_cpu == "x86" && host_os == "linux") { - # By default Dart will create a 32-bit gen_snapshot host binary if the target - # platform is 32-bit. Override this to create a 64-bit gen_snapshot for x86 - # targets because some host platforms may not support 32-bit binaries. + # By default Dart will create a 32-bit gen_snapshot host binary if the + # target platform is 32-bit. Override this to create a 64-bit gen_snapshot + # for x86 targets because some host platforms may not support 32-bit + # binaries. tool = "$dart_src/runtime/bin:gen_snapshot_host_targeting_host" toolchain = "//build/toolchain/$host_os:clang_x64" } else { diff --git a/engine/src/flutter/lib/ui/channel_buffers.dart b/engine/src/flutter/lib/ui/channel_buffers.dart index 6f490fdc..1f4c48b4 100644 --- a/engine/src/flutter/lib/ui/channel_buffers.dart +++ b/engine/src/flutter/lib/ui/channel_buffers.dart @@ -17,8 +17,10 @@ part of dart.ui; 'Migrate to ChannelCallback instead. ' 'This feature was deprecated after v3.11.0-20.0.pre.', ) -typedef DrainChannelCallback = - Future Function(ByteData? data, PlatformMessageResponseCallback callback); +typedef DrainChannelCallback = Future Function( + ByteData? data, + PlatformMessageResponseCallback callback, +); /// Signature for [ChannelBuffers.setListener]'s `callback` argument. /// diff --git a/engine/src/flutter/lib/ui/platform_dispatcher.dart b/engine/src/flutter/lib/ui/platform_dispatcher.dart index 2f8a38cb..30b23e60 100644 --- a/engine/src/flutter/lib/ui/platform_dispatcher.dart +++ b/engine/src/flutter/lib/ui/platform_dispatcher.dart @@ -19,8 +19,11 @@ typedef PlatformMessageResponseCallback = void Function(ByteData? data); 'Migrate to ChannelBuffers.setListener instead. ' 'This feature was deprecated after v3.11.0-20.0.pre.', ) -typedef PlatformMessageCallback = - void Function(String name, ByteData? data, PlatformMessageResponseCallback? callback); +typedef PlatformMessageCallback = void Function( + String name, + ByteData? data, + PlatformMessageResponseCallback? callback, +); /// Signature for [PlatformDispatcher.onError]. /// diff --git a/engine/src/flutter/lib/ui/ui_benchmarks.cc b/engine/src/flutter/lib/ui/ui_benchmarks.cc index f41ad809..dbd3dbe3 100644 --- a/engine/src/flutter/lib/ui/ui_benchmarks.cc +++ b/engine/src/flutter/lib/ui/ui_benchmarks.cc @@ -15,7 +15,7 @@ namespace flutter { class Fixture : public testing::FixtureTest { - void TestBody() override{}; + void TestBody() override {}; }; static void BM_PlatformMessageResponseDartComplete(benchmark::State& state) { diff --git a/engine/src/flutter/lib/web_ui/dev/felt_config.dart b/engine/src/flutter/lib/web_ui/dev/felt_config.dart index 7c7aa2bb..bff96619 100644 --- a/engine/src/flutter/lib/web_ui/dev/felt_config.dart +++ b/engine/src/flutter/lib/web_ui/dev/felt_config.dart @@ -3,6 +3,7 @@ // found in the LICENSE file. import 'dart:io' as io; + import 'package:yaml/yaml.dart'; enum Compiler { dart2js, dart2wasm } diff --git a/engine/src/flutter/lib/web_ui/lib/channel_buffers.dart b/engine/src/flutter/lib/web_ui/lib/channel_buffers.dart index d8ba4f33..fa13ad6e 100644 --- a/engine/src/flutter/lib/web_ui/lib/channel_buffers.dart +++ b/engine/src/flutter/lib/web_ui/lib/channel_buffers.dart @@ -11,8 +11,10 @@ part of ui; -typedef DrainChannelCallback = - Future Function(ByteData? data, PlatformMessageResponseCallback callback); +typedef DrainChannelCallback = Future Function( + ByteData? data, + PlatformMessageResponseCallback callback, +); typedef ChannelCallback = void Function(ByteData? data, PlatformMessageResponseCallback callback); diff --git a/engine/src/flutter/lib/web_ui/lib/platform_dispatcher.dart b/engine/src/flutter/lib/web_ui/lib/platform_dispatcher.dart index c86c4ef8..71f4eecf 100644 --- a/engine/src/flutter/lib/web_ui/lib/platform_dispatcher.dart +++ b/engine/src/flutter/lib/web_ui/lib/platform_dispatcher.dart @@ -6,8 +6,11 @@ part of ui; typedef VoidCallback = void Function(); typedef PlatformMessageResponseCallback = void Function(ByteData? data); -typedef PlatformMessageCallback = - void Function(String name, ByteData? data, PlatformMessageResponseCallback? callback); +typedef PlatformMessageCallback = void Function( + String name, + ByteData? data, + PlatformMessageResponseCallback? callback, +); typedef ErrorCallback = bool Function(Object exception, StackTrace stackTrace); /// A token that represents a root isolate. diff --git a/engine/src/flutter/lib/web_ui/lib/src/engine/configuration.dart b/engine/src/flutter/lib/web_ui/lib/src/engine/configuration.dart index 53d6f221..8e8f4711 100644 --- a/engine/src/flutter/lib/web_ui/lib/src/engine/configuration.dart +++ b/engine/src/flutter/lib/web_ui/lib/src/engine/configuration.dart @@ -47,6 +47,7 @@ library configuration; import 'dart:js_interop'; import 'package:meta/meta.dart'; + import 'dom.dart'; enum CanvasKitVariant { @@ -139,13 +140,11 @@ class FlutterConfiguration { } FlutterConfiguration withOverrides(JsFlutterConfiguration? overrides) { - final newJsConfig = - objectConstructor.assign( - {}.jsify(), - _configuration.jsify(), - overrides.jsify(), - ) - as JsFlutterConfiguration; + final newJsConfig = objectConstructor.assign( + {}.jsify(), + _configuration.jsify(), + overrides.jsify(), + ) as JsFlutterConfiguration; final newConfig = FlutterConfiguration(); newConfig._configuration = newJsConfig; return newConfig; diff --git a/engine/src/flutter/lib/web_ui/lib/src/engine/dom.dart b/engine/src/flutter/lib/web_ui/lib/src/engine/dom.dart index 72224d4d..9b481a0a 100644 --- a/engine/src/flutter/lib/web_ui/lib/src/engine/dom.dart +++ b/engine/src/flutter/lib/web_ui/lib/src/engine/dom.dart @@ -1578,8 +1578,11 @@ extension type DomFontFaceSet._(JSObject _) implements DomEventTarget { void forEach(DomFontFaceSetForEachCallback callback) => _forEach(callback.toJS); } -typedef DomFontFaceSetForEachCallback = - void Function(DomFontFace fontFace, DomFontFace fontFaceAgain, DomFontFaceSet set); +typedef DomFontFaceSetForEachCallback = void Function( + DomFontFace fontFace, + DomFontFace fontFaceAgain, + DomFontFaceSet set, +); @JS('VisualViewport') extension type DomVisualViewport._(JSObject _) implements DomEventTarget { @@ -2255,8 +2258,10 @@ extension type DomResizeObserverObserveOptions._(JSObject _) implements JSObject } /// Type of the function used to create a Resize Observer. -typedef DomResizeObserverCallbackFn = - void Function(List entries, DomResizeObserver observer); +typedef DomResizeObserverCallbackFn = void Function( + List entries, + DomResizeObserver observer, +); /// The object passed to the [DomResizeObserverCallbackFn], which allows access to the new dimensions of the observed element. /// diff --git a/engine/src/flutter/lib/web_ui/lib/src/engine/js_interop/js_loader.dart b/engine/src/flutter/lib/web_ui/lib/src/engine/js_interop/js_loader.dart index 12662e9d..9e322a90 100644 --- a/engine/src/flutter/lib/web_ui/lib/src/engine/js_interop/js_loader.dart +++ b/engine/src/flutter/lib/web_ui/lib/src/engine/js_interop/js_loader.dart @@ -46,10 +46,9 @@ extension type FlutterEngineInitializer._primary(JSObject _) implements JSObject required InitializeEngineFn initializeEngine, required ImmediateRunAppFn autoStart, }) => FlutterEngineInitializer._( - initializeEngine: - (([JsFlutterConfiguration? config]) => - (initializeEngine(config) as Future).toPromise) - .toJS, + initializeEngine: (([ + JsFlutterConfiguration? config, + ]) => (initializeEngine(config) as Future).toPromise).toJS, autoStart: (() => (autoStart() as Future).toPromise).toJS, ); external factory FlutterEngineInitializer._({ diff --git a/engine/src/flutter/lib/web_ui/test/engine/initialization_test.dart b/engine/src/flutter/lib/web_ui/test/engine/initialization_test.dart index 6f217aec..a1ae2789 100644 --- a/engine/src/flutter/lib/web_ui/test/engine/initialization_test.dart +++ b/engine/src/flutter/lib/web_ui/test/engine/initialization_test.dart @@ -31,79 +31,71 @@ void main() { } void testMain() { - test( - 'bootstrapEngine calls _flutter.loader.didCreateEngineInitializer callback', - () async { - JSAny? engineInitializer; - - void didCreateEngineInitializerMock(JSAny? obj) { - engineInitializer = obj; - } - - // Prepare the DOM for: _flutter.loader.didCreateEngineInitializer - didCreateEngineInitializer = didCreateEngineInitializerMock.toJS; - - // Reset the engine - engine.debugResetEngineInitializationState(); - - await ui_web.bootstrapEngine(registerPlugins: () {}, runApp: () {}); - - // Check that the object we captured is actually a loader - expect(engineInitializer, isNotNull); - expect( - (engineInitializer! as JSObject).has('initializeEngine'), - isTrue, - reason: 'Missing FlutterEngineInitializer method: initializeEngine.', - ); - expect( - (engineInitializer! as JSObject).has('autoStart'), - isTrue, - reason: 'Missing FlutterEngineInitializer method: autoStart.', - ); - // https://github.com/flutter/flutter/issues/160096 - }, - skip: ui_web.browser.isFirefox, - ); - - test( - 'bootstrapEngine does auto-start when _flutter.loader.didCreateEngineInitializer does not exist', - () async { - loader = null; - - var pluginsRegistered = false; - var appRan = false; - void registerPluginsMock() { - pluginsRegistered = true; - } - - void runAppMock() { - appRan = true; - } - - // Reset the engine - engine.debugResetEngineInitializationState(); - - await ui_web.bootstrapEngine(registerPlugins: registerPluginsMock, runApp: runAppMock); - - // Check that the object we captured is actually a loader - expect( - pluginsRegistered, - isTrue, - reason: 'Plugins should be immediately registered in autoStart mode.', - ); - expect(appRan, isTrue, reason: 'App should run immediately in autoStart mode'); - - // After starting the engine, the meta-generator tag should be on the page - final DomElement? meta = domDocument.querySelector('meta[name=generator][content=Flutter]'); - expect( - meta, - isNotNull, - reason: 'The generator meta-tag should be added when Flutter initializes its UI.', - ); - // https://github.com/flutter/flutter/issues/160096 - }, - skip: ui_web.browser.isFirefox, - ); + test('bootstrapEngine calls _flutter.loader.didCreateEngineInitializer callback', () async { + JSAny? engineInitializer; + + void didCreateEngineInitializerMock(JSAny? obj) { + engineInitializer = obj; + } + + // Prepare the DOM for: _flutter.loader.didCreateEngineInitializer + didCreateEngineInitializer = didCreateEngineInitializerMock.toJS; + + // Reset the engine + engine.debugResetEngineInitializationState(); + + await ui_web.bootstrapEngine(registerPlugins: () {}, runApp: () {}); + + // Check that the object we captured is actually a loader + expect(engineInitializer, isNotNull); + expect( + (engineInitializer! as JSObject).has('initializeEngine'), + isTrue, + reason: 'Missing FlutterEngineInitializer method: initializeEngine.', + ); + expect( + (engineInitializer! as JSObject).has('autoStart'), + isTrue, + reason: 'Missing FlutterEngineInitializer method: autoStart.', + ); + // https://github.com/flutter/flutter/issues/160096 + }, skip: ui_web.browser.isFirefox); + + test('bootstrapEngine does auto-start when _flutter.loader.didCreateEngineInitializer does not exist', () async { + loader = null; + + var pluginsRegistered = false; + var appRan = false; + void registerPluginsMock() { + pluginsRegistered = true; + } + + void runAppMock() { + appRan = true; + } + + // Reset the engine + engine.debugResetEngineInitializationState(); + + await ui_web.bootstrapEngine(registerPlugins: registerPluginsMock, runApp: runAppMock); + + // Check that the object we captured is actually a loader + expect( + pluginsRegistered, + isTrue, + reason: 'Plugins should be immediately registered in autoStart mode.', + ); + expect(appRan, isTrue, reason: 'App should run immediately in autoStart mode'); + + // After starting the engine, the meta-generator tag should be on the page + final DomElement? meta = domDocument.querySelector('meta[name=generator][content=Flutter]'); + expect( + meta, + isNotNull, + reason: 'The generator meta-tag should be added when Flutter initializes its UI.', + ); + // https://github.com/flutter/flutter/issues/160096 + }, skip: ui_web.browser.isFirefox); // We cannot test anymore, because by now the engine has registered some stuff that can't be rewound back. // Like the `ext.flutter.disassemble` developer extension. diff --git a/engine/src/flutter/runtime/BUILD.gn b/engine/src/flutter/runtime/BUILD.gn index a56a65ca..57b19d02 100644 --- a/engine/src/flutter/runtime/BUILD.gn +++ b/engine/src/flutter/runtime/BUILD.gn @@ -69,7 +69,8 @@ source_set("runtime") { ] if (is_ios && flutter_runtime_mode == "debug") { - # These contain references to private APIs and this TU must only be compiled in debug runtime modes. + # These contain references to private APIs and this TU must only be compiled + # in debug runtime modes. sources += [ "ptrace_check.cc" ] } diff --git a/engine/src/flutter/runtime/dart_isolate_unittests.cc b/engine/src/flutter/runtime/dart_isolate_unittests.cc index 1a66a7ce..77315a12 100644 --- a/engine/src/flutter/runtime/dart_isolate_unittests.cc +++ b/engine/src/flutter/runtime/dart_isolate_unittests.cc @@ -359,7 +359,8 @@ TEST_F(DartIsolateTest, CanCreateServiceIsolate) { ASSERT_TRUE(root_isolate); ASSERT_EQ(root_isolate->GetPhase(), DartIsolate::Phase::Running); service_isolate_latch.Wait(); - // This is a bit racy, the latch completes before the isolate is fully running. + // This is a bit racy, the latch completes before the isolate is fully + // running. std::this_thread::sleep_for(std::chrono::milliseconds(100)); ASSERT_TRUE(root_isolate->Shutdown()); } diff --git a/engine/src/flutter/shell/common/BUILD.gn b/engine/src/flutter/shell/common/BUILD.gn index cd7d5f8e..60e5f373 100644 --- a/engine/src/flutter/shell/common/BUILD.gn +++ b/engine/src/flutter/shell/common/BUILD.gn @@ -103,7 +103,8 @@ source_set("common") { ] } -# These are in their own source_set to avoid a dependency cycle with //common/graphics +# These are in their own source_set to avoid a dependency cycle with +# //common/graphics source_set("base64") { sources = [ "base64.cc", @@ -165,9 +166,9 @@ if (enable_unittests) { testonly = true sources = [ - "shell_test_platform_view.cc", "shell_test.cc", "shell_test.h", + "shell_test_platform_view.cc", ] public_deps = [ diff --git a/engine/src/flutter/shell/platform/android/BUILD.gn b/engine/src/flutter/shell/platform/android/BUILD.gn index ce9e9190..4ed97ac6 100644 --- a/engine/src/flutter/shell/platform/android/BUILD.gn +++ b/engine/src/flutter/shell/platform/android/BUILD.gn @@ -220,7 +220,8 @@ action("check_imports") { stamp_file = "$root_out_dir/check_android_imports" - # File does not actually get created, but GN expects us to have an output here. + # File does not actually get created, but GN expects us to have an output + # here. outputs = [ stamp_file ] args = [ @@ -454,7 +455,8 @@ action("pom_content_hash_embedding") { ] } -# TODO(jsimmons): remove this placeholder when it is no longer used by the LUCI recipes +# TODO(jsimmons): remove this placeholder when it is no longer used by the LUCI +# recipes group("robolectric_tests") { deps = [ ":android_jar" ] } diff --git a/engine/src/flutter/shell/platform/android/io/flutter/embedding/android/FlutterEngineProvider.java b/engine/src/flutter/shell/platform/android/io/flutter/embedding/android/FlutterEngineProvider.java index ac52a060..8fc2225c 100644 --- a/engine/src/flutter/shell/platform/android/io/flutter/embedding/android/FlutterEngineProvider.java +++ b/engine/src/flutter/shell/platform/android/io/flutter/embedding/android/FlutterEngineProvider.java @@ -15,8 +15,8 @@ * *

{@link io.flutter.embedding.engine.FlutterEngine} instances require significant time to warm * up. Therefore, a developer might choose to hold onto an existing {@link - * io.flutter.embedding.engine.FlutterEngine}. This interface facilitates providing a cached, pre-warmed {@link - * io.flutter.embedding.engine.FlutterEngine}. + * io.flutter.embedding.engine.FlutterEngine}. This interface facilitates providing a cached, + * pre-warmed {@link io.flutter.embedding.engine.FlutterEngine}. */ public interface FlutterEngineProvider { /** diff --git a/engine/src/flutter/shell/platform/android/io/flutter/embedding/engine/FlutterEngine.java b/engine/src/flutter/shell/platform/android/io/flutter/embedding/engine/FlutterEngine.java index d670e781..b7e40c8a 100644 --- a/engine/src/flutter/shell/platform/android/io/flutter/embedding/engine/FlutterEngine.java +++ b/engine/src/flutter/shell/platform/android/io/flutter/embedding/engine/FlutterEngine.java @@ -34,79 +34,51 @@ /** * A single Flutter execution environment. * - *

- * The {@code FlutterEngine} is the container through which Dart code can be run - * in an Android + *

The {@code FlutterEngine} is the container through which Dart code can be run in an Android * application. * - *

- * Dart code in a {@code FlutterEngine} can execute in the background and Dart - * code using the Flutter - * framework on the Dart side. Rendering can be started and stopped, thus - * allowing a {@code - * FlutterEngine} to move from UI interaction to data-only processing and then - * back to UI + *

Dart code in a {@code FlutterEngine} can execute in the background and Dart code using the + * Flutter framework on the Dart side. Rendering can be started and stopped, thus allowing a {@code + * FlutterEngine} to move from UI interaction to data-only processing and then back to UI * interaction. * - *

- * Multiple {@code FlutterEngine}s may exist, execute Dart code, and render UIs - * within a single - * Android app. For better memory performance characteristics, construct - * multiple {@code - * FlutterEngine}s via {@link io.flutter.embedding.engine.FlutterEngineGroup} - * rather than via {@code + *

Multiple {@code FlutterEngine}s may exist, execute Dart code, and render UIs within a single + * Android app. For better memory performance characteristics, construct multiple {@code + * FlutterEngine}s via {@link io.flutter.embedding.engine.FlutterEngineGroup} rather than via {@code * FlutterEngine}'s constructor directly. * - *

- * To start running Dart and/or Flutter within this {@code FlutterEngine}, get a - * reference to + *

To start running Dart and/or Flutter within this {@code FlutterEngine}, get a reference to * this engine's {@link DartExecutor} and then use {@link * DartExecutor#executeDartEntrypoint(DartExecutor.DartEntrypoint)}. The {@link - * DartExecutor#executeDartEntrypoint(DartExecutor.DartEntrypoint)} method must - * not be invoked twice + * DartExecutor#executeDartEntrypoint(DartExecutor.DartEntrypoint)} method must not be invoked twice * on the same {@code FlutterEngine}. * - *

- * Instatiating the first {@code FlutterEngine} per process will also load the - * Flutter engine's - * native library and start the Dart VM. Subsequent {@code FlutterEngine}s will - * run on the same VM - * instance but will have their own Dart Isolate - * when the - * {@link DartExecutor} is run. Each Isolate is a self-contained Dart - * environment and cannot - * communicate with each other except via Isolate ports. + *

Instatiating the first {@code FlutterEngine} per process will also load the Flutter engine's + * native library and start the Dart VM. Subsequent {@code FlutterEngine}s will run on the same VM + * instance but will have their own Dart Isolate when the {@link + * DartExecutor} is run. Each Isolate is a self-contained Dart environment and cannot communicate + * with each other except via Isolate ports. */ public class FlutterEngine { private static final String TAG = "FlutterEngine"; - @NonNull - private final FlutterJNI flutterJNI; - @NonNull - private final DartExecutor dartExecutor; - @NonNull - private final FlutterEngineConnectionRegistry pluginRegistry; - @NonNull - private final LocalizationPlugin localizationPlugin; + @NonNull private final FlutterJNI flutterJNI; + @NonNull private final DartExecutor dartExecutor; + @NonNull private final FlutterEngineConnectionRegistry pluginRegistry; + @NonNull private final LocalizationPlugin localizationPlugin; // System channels. - @NonNull - private final DeferredComponentChannel deferredComponentChannel; - @NonNull - private final LocalizationChannel localizationChannel; + @NonNull private final DeferredComponentChannel deferredComponentChannel; + @NonNull private final LocalizationChannel localizationChannel; - @NonNull - private final SystemChannel systemChannel; + @NonNull private final SystemChannel systemChannel; // Engine Lifecycle. - @NonNull - private final Set engineLifecycleListeners = new HashSet<>(); + @NonNull private final Set engineLifecycleListeners = new HashSet<>(); // Unique handle for this engine. - @NonNull - private final long engineId; + @NonNull private final long engineId; @VisibleForTesting(otherwise = VisibleForTesting.PACKAGE_PRIVATE) public static void resetNextEngineId() { @@ -120,55 +92,43 @@ public static void resetNextEngineId() { private static final Map idToEngine = new HashMap<>(); @NonNull - private final EngineLifecycleListener engineLifecycleListener = new EngineLifecycleListener() { - @SuppressWarnings("unused") - public void onPreEngineRestart() { - Log.v(TAG, "onPreEngineRestart()"); - for (EngineLifecycleListener lifecycleListener : engineLifecycleListeners) { - lifecycleListener.onPreEngineRestart(); - } - } - - @Override - public void onEngineWillDestroy() { - // This inner implementation doesn't do anything since FlutterEngine sent this - // notification in the first place. It's meant for external listeners. - } - }; + private final EngineLifecycleListener engineLifecycleListener = + new EngineLifecycleListener() { + @SuppressWarnings("unused") + public void onPreEngineRestart() { + Log.v(TAG, "onPreEngineRestart()"); + for (EngineLifecycleListener lifecycleListener : engineLifecycleListeners) { + lifecycleListener.onPreEngineRestart(); + } + } + + @Override + public void onEngineWillDestroy() { + // This inner implementation doesn't do anything since FlutterEngine sent this + // notification in the first place. It's meant for external listeners. + } + }; /** * Constructs a new {@code FlutterEngine}. * - *

- * A new {@code FlutterEngine} does not execute any Dart code automatically. See - * {@link - * #getDartExecutor()} and - * {@link DartExecutor#executeDartEntrypoint(DartExecutor.DartEntrypoint)} + *

A new {@code FlutterEngine} does not execute any Dart code automatically. See {@link + * #getDartExecutor()} and {@link DartExecutor#executeDartEntrypoint(DartExecutor.DartEntrypoint)} * to begin executing Dart code within this {@code FlutterEngine}. * - *

- * A new {@code FlutterEngine} will not display any UI. + *

A new {@code FlutterEngine} will not display any UI. * - *

- * A new {@code FlutterEngine} automatically attaches all plugins. See - * {@link #getPlugins()}. + *

A new {@code FlutterEngine} automatically attaches all plugins. See {@link #getPlugins()}. * - *

- * A new {@code FlutterEngine} does come with all default system channels - * attached. + *

A new {@code FlutterEngine} does come with all default system channels attached. * - *

- * The first {@code FlutterEngine} instance constructed per process will also - * load the Flutter + *

The first {@code FlutterEngine} instance constructed per process will also load the Flutter * native library and start a Dart VM. * - *

- * In order to pass Dart VM initialization arguments (see {@link - * io.flutter.embedding.engine.FlutterShellArgs}) when creating the VM, manually - * set the + *

In order to pass Dart VM initialization arguments (see {@link + * io.flutter.embedding.engine.FlutterShellArgs}) when creating the VM, manually set the * initialization arguments by calling {@link - * io.flutter.embedding.engine.loader.FlutterLoader#startInitialization(Context)} - * and {@link + * io.flutter.embedding.engine.loader.FlutterLoader#startInitialization(Context)} and {@link * io.flutter.embedding.engine.loader.FlutterLoader#ensureInitializationComplete(Context, * String[])} before constructing the engine. */ @@ -177,23 +137,19 @@ public FlutterEngine(@NonNull Context context) { } /** - * Same as {@link #FlutterEngine(Context)} with added support for passing Dart - * VM arguments. + * Same as {@link #FlutterEngine(Context)} with added support for passing Dart VM arguments. * - *

- * If the Dart VM has already started, the given arguments will have no effect. + *

If the Dart VM has already started, the given arguments will have no effect. */ public FlutterEngine(@NonNull Context context, @Nullable String[] dartVmArgs) { this(context, /* flutterLoader */ null, /* flutterJNI */ null, dartVmArgs, true); } /** - * Same as {@link #FlutterEngine(Context)} with added support for passing Dart - * VM arguments and + * Same as {@link #FlutterEngine(Context)} with added support for passing Dart VM arguments and * avoiding automatic plugin registration. * - *

- * If the Dart VM has already started, the given arguments will have no effect. + *

If the Dart VM has already started, the given arguments will have no effect. */ public FlutterEngine( @NonNull Context context, @@ -208,34 +164,22 @@ public FlutterEngine( } /** - * Same as {@link #FlutterEngine(Context, String[], boolean)} with added support - * for configuring + * Same as {@link #FlutterEngine(Context, String[], boolean)} with added support for configuring * whether the engine will receive restoration data. * - *

- * The {@code waitForRestorationData} flag controls whether the engine delays - * responding to - * requests from the framework for restoration data until that data has been - * provided to the - * engine via {@code RestorationChannel.setRestorationData(byte[] data)}. If the - * flag is false, - * the framework may temporarily initialize itself to default values before the - * restoration data - * has been made available to the engine. Setting {@code waitForRestorationData} - * to true avoids + *

The {@code waitForRestorationData} flag controls whether the engine delays responding to + * requests from the framework for restoration data until that data has been provided to the + * engine via {@code RestorationChannel.setRestorationData(byte[] data)}. If the flag is false, + * the framework may temporarily initialize itself to default values before the restoration data + * has been made available to the engine. Setting {@code waitForRestorationData} to true avoids * this extra work by delaying initialization until the data is available. * - *

- * When {@code waitForRestorationData} is set, {@code - * RestorationChannel.setRestorationData(byte[] data)} must be called at a later - * point in time. If - * it later turns out that no restoration data is available to restore the - * framework from, that + *

When {@code waitForRestorationData} is set, {@code + * RestorationChannel.setRestorationData(byte[] data)} must be called at a later point in time. If + * it later turns out that no restoration data is available to restore the framework from, that * method must still be called with null as an argument to indicate "no data". * - *

- * If the framework never requests the restoration data, this flag has no - * effect. + *

If the framework never requests the restoration data, this flag has no effect. */ public FlutterEngine( @NonNull Context context, @@ -252,14 +196,10 @@ public FlutterEngine( } /** - * Same as - * {@link #FlutterEngine(Context, FlutterLoader, FlutterJNI, String[], boolean)} - * but with + * Same as {@link #FlutterEngine(Context, FlutterLoader, FlutterJNI, String[], boolean)} but with * no Dart VM flags and automatically registers plugins. * - *

- * {@code flutterJNI} should be a new instance that has never been attached to - * an engine + *

{@code flutterJNI} should be a new instance that has never been attached to an engine * before. */ public FlutterEngine( @@ -270,9 +210,7 @@ public FlutterEngine( } /** - * Same as - * {@link #FlutterEngine(Context, FlutterLoader, FlutterJNI, String[], boolean)}, - * plus the + * Same as {@link #FlutterEngine(Context, FlutterLoader, FlutterJNI, String[], boolean)}, plus the * ability to provide a custom {@code PlatformViewsController}. */ public FlutterEngine( @@ -281,13 +219,7 @@ public FlutterEngine( @NonNull FlutterJNI flutterJNI, @Nullable String[] dartVmArgs, boolean automaticallyRegisterPlugins) { - this( - context, - flutterLoader, - flutterJNI, - dartVmArgs, - automaticallyRegisterPlugins, - false); + this(context, flutterLoader, flutterJNI, dartVmArgs, automaticallyRegisterPlugins, false); } /** Fully configurable {@code FlutterEngine} constructor. */ @@ -338,7 +270,8 @@ public FlutterEngine( this.dartExecutor = new DartExecutor(flutterJNI, assetManager, engineId); this.dartExecutor.onAttachedToJNI(); - DeferredComponentManager deferredComponentManager = FlutterInjector.instance().deferredComponentManager(); + DeferredComponentManager deferredComponentManager = + FlutterInjector.instance().deferredComponentManager(); deferredComponentChannel = new DeferredComponentChannel(dartExecutor); localizationChannel = new LocalizationChannel(dartExecutor); @@ -372,8 +305,9 @@ public FlutterEngine( attachToJni(); } - this.pluginRegistry = new FlutterEngineConnectionRegistry( - context.getApplicationContext(), this, flutterLoader, group); + this.pluginRegistry = + new FlutterEngineConnectionRegistry( + context.getApplicationContext(), this, flutterLoader, group); localizationPlugin.sendLocalesToFlutter(context.getResources().getConfiguration()); @@ -399,28 +333,19 @@ private boolean isAttachedToJni() { } /** - * Create a second {@link io.flutter.embedding.engine.FlutterEngine} based on - * this current one by - * sharing as much resources together as possible to minimize startup latency - * and memory cost. + * Create a second {@link io.flutter.embedding.engine.FlutterEngine} based on this current one by + * sharing as much resources together as possible to minimize startup latency and memory cost. * - * @param context is a Context used to create the {@link - * io.flutter.embedding.engine.FlutterEngine}. Could - * be the same Context as the current engine - * or a different one. Generally, only an application - * Context is needed for the {@link - * io.flutter.embedding.engine.FlutterEngine} and its - * dependencies. - * @param dartEntrypoint specifies the {@link DartEntrypoint} the new engine - * should run. It - * doesn't need to be the same entrypoint as the - * current engine but must be built in the same - * AOT or snapshot. - * @param initialRoute The name of the initial Flutter `Navigator` `Route` - * to load. If this is - * null, it will default to the "/" route. - * @param dartEntrypointArgs Arguments passed as a list of string to Dart's - * entrypoint function. + * @param context is a Context used to create the {@link + * io.flutter.embedding.engine.FlutterEngine}. Could be the same Context as the current engine + * or a different one. Generally, only an application Context is needed for the {@link + * io.flutter.embedding.engine.FlutterEngine} and its dependencies. + * @param dartEntrypoint specifies the {@link DartEntrypoint} the new engine should run. It + * doesn't need to be the same entrypoint as the current engine but must be built in the same + * AOT or snapshot. + * @param initialRoute The name of the initial Flutter `Navigator` `Route` to load. If this is + * null, it will default to the "/" route. + * @param dartEntrypointArgs Arguments passed as a list of string to Dart's entrypoint function. * @return a new {@link io.flutter.embedding.engine.FlutterEngine}. */ @NonNull @@ -435,32 +360,29 @@ private boolean isAttachedToJni() { "Spawn can only be called on a fully constructed FlutterEngine"); } - FlutterJNI newFlutterJNI = flutterJNI.spawn( - dartEntrypoint.dartEntrypointFunctionName, - dartEntrypoint.dartEntrypointLibrary, - dartEntrypointArgs, - nextEngineId); + FlutterJNI newFlutterJNI = + flutterJNI.spawn( + dartEntrypoint.dartEntrypointFunctionName, + dartEntrypoint.dartEntrypointLibrary, + dartEntrypointArgs, + nextEngineId); return new FlutterEngine( context, // Context. null, // FlutterLoader. A null value passed here causes the constructor to get it from - // the + // the // FlutterInjector. newFlutterJNI, // FlutterJNI. null, // String[]. The Dart VM has already started, this arguments will have no - // effect. + // effect. automaticallyRegisterPlugins, // boolean. waitForRestorationData); // boolean } /** - * Cleans up all components within this {@code FlutterEngine} and destroys the - * associated Dart - * Isolate. All state held by the Dart Isolate, such as the Flutter Elements - * tree, is lost. + * Cleans up all components within this {@code FlutterEngine} and destroys the associated Dart + * Isolate. All state held by the Dart Isolate, such as the Flutter Elements tree, is lost. * - *

- * This {@code FlutterEngine} instance should be discarded after invoking this - * method. + *

This {@code FlutterEngine} instance should be discarded after invoking this method. */ public void destroy() { Log.v(TAG, "Destroying."); @@ -481,8 +403,7 @@ public void destroy() { } /** - * Adds a {@code listener} to be notified of Flutter engine lifecycle events, - * e.g., {@code + * Adds a {@code listener} to be notified of Flutter engine lifecycle events, e.g., {@code * onPreEngineStart()}. */ public void addEngineLifecycleListener(@NonNull EngineLifecycleListener listener) { @@ -500,14 +421,10 @@ public void removeEngineLifecycleListener(@NonNull EngineLifecycleListener liste /** * The Dart execution context associated with this {@code FlutterEngine}. * - *

- * The {@link DartExecutor} can be used to start executing Dart code from a - * given entrypoint. + *

The {@link DartExecutor} can be used to start executing Dart code from a given entrypoint. * See {@link DartExecutor#executeDartEntrypoint(DartExecutor.DartEntrypoint)}. * - *

- * Use the {@link DartExecutor} to connect any desired message channels and - * method channels to + *

Use the {@link DartExecutor} to connect any desired message channels and method channels to * facilitate communication between Android and Dart/Flutter. */ @NonNull @@ -521,26 +438,20 @@ public LocalizationChannel getLocalizationChannel() { return localizationChannel; } - /** - * System channel that allows manual installation and state querying of deferred - * components. - */ + /** System channel that allows manual installation and state querying of deferred components. */ @NonNull public DeferredComponentChannel getDeferredComponentChannel() { return deferredComponentChannel; } - /** - * System channel that sends memory pressure warnings from Android to Flutter. - */ + /** System channel that sends memory pressure warnings from Android to Flutter. */ @NonNull public SystemChannel getSystemChannel() { return systemChannel; } /** - * Plugin registry, which registers plugins that want to be applied to this - * {@code FlutterEngine}. + * Plugin registry, which registers plugins that want to be applied to this {@code FlutterEngine}. */ @NonNull public PluginRegistry getPlugins() { @@ -574,16 +485,14 @@ public long getEngineId() { } /** - * Returns engine for the given identifier or null if identifier is not valid. - * The handle can be + * Returns engine for the given identifier or null if identifier is not valid. The handle can be * obtained through * *

    * PlatformDispatcher.instance.engineId
    * 
* - *

- * Must be called on the UI thread. + *

Must be called on the UI thread. */ @Nullable @VisibleForTesting(otherwise = VisibleForTesting.PACKAGE_PRIVATE) @@ -599,8 +508,7 @@ public interface EngineLifecycleListener { /** * Lifecycle callback invoked before the Flutter engine is destroyed. * - *

- * For the duration of the call, the Flutter engine is still valid. + *

For the duration of the call, the Flutter engine is still valid. */ void onEngineWillDestroy(); } diff --git a/engine/src/flutter/shell/platform/android/io/flutter/embedding/engine/FlutterEngineConnectionRegistry.java b/engine/src/flutter/shell/platform/android/io/flutter/embedding/engine/FlutterEngineConnectionRegistry.java index cdbb4b36..d564f66b 100644 --- a/engine/src/flutter/shell/platform/android/io/flutter/embedding/engine/FlutterEngineConnectionRegistry.java +++ b/engine/src/flutter/shell/platform/android/io/flutter/embedding/engine/FlutterEngineConnectionRegistry.java @@ -4,7 +4,6 @@ package io.flutter.embedding.engine; -import android.app.Activity; import android.app.Service; import android.content.BroadcastReceiver; import android.content.ContentProvider; diff --git a/engine/src/flutter/shell/platform/android/io/flutter/embedding/engine/FlutterEngineGroup.java b/engine/src/flutter/shell/platform/android/io/flutter/embedding/engine/FlutterEngineGroup.java index 1716755e..adbab076 100644 --- a/engine/src/flutter/shell/platform/android/io/flutter/embedding/engine/FlutterEngineGroup.java +++ b/engine/src/flutter/shell/platform/android/io/flutter/embedding/engine/FlutterEngineGroup.java @@ -95,10 +95,8 @@ public FlutterEngine createAndRunDefaultEngine(@NonNull Context context) { * engine created will recreate its dependencies. */ public FlutterEngine createAndRunEngine( - @NonNull Context context, - @Nullable DartEntrypoint dartEntrypoint) { - return createAndRunEngine( - new Options(context).setDartEntrypoint(dartEntrypoint)); + @NonNull Context context, @Nullable DartEntrypoint dartEntrypoint) { + return createAndRunEngine(new Options(context).setDartEntrypoint(dartEntrypoint)); } /** @@ -129,11 +127,7 @@ public FlutterEngine createAndRunEngine(@NonNull Options options) { } if (activeEngines.size() == 0) { - engine = - createEngine( - context, - automaticallyRegisterPlugins, - waitForRestorationData); + engine = createEngine(context, automaticallyRegisterPlugins, waitForRestorationData); engine.getDartExecutor().executeDartEntrypoint(dartEntrypoint, dartEntrypointArgs); } else { engine = @@ -168,9 +162,7 @@ public void onEngineWillDestroy() { @VisibleForTesting /* package */ FlutterEngine createEngine( - Context context, - boolean automaticallyRegisterPlugins, - boolean waitForRestorationData) { + Context context, boolean automaticallyRegisterPlugins, boolean waitForRestorationData) { return new FlutterEngine( context, // Context. null, // FlutterLoader. diff --git a/engine/src/flutter/shell/platform/android/io/flutter/embedding/engine/FlutterEngineGroupCache.java b/engine/src/flutter/shell/platform/android/io/flutter/embedding/engine/FlutterEngineGroupCache.java index 8635425a..313a7fa0 100644 --- a/engine/src/flutter/shell/platform/android/io/flutter/embedding/engine/FlutterEngineGroupCache.java +++ b/engine/src/flutter/shell/platform/android/io/flutter/embedding/engine/FlutterEngineGroupCache.java @@ -17,9 +17,8 @@ *

The ID of a given {@link io.flutter.embedding.engine.FlutterEngineGroup} can be whatever * {@code String} is desired. * - * Use the {@code FlutterEngineGroupCache} singleton - * internally when instructed to use a cached {@link io.flutter.embedding.engine.FlutterEngineGroup} - * based on a given ID. + *

Use the {@code FlutterEngineGroupCache} singleton internally when instructed to use a cached + * {@link io.flutter.embedding.engine.FlutterEngineGroup} based on a given ID. */ public class FlutterEngineGroupCache { private static volatile FlutterEngineGroupCache instance; diff --git a/engine/src/flutter/shell/platform/android/io/flutter/embedding/engine/FlutterJNI.java b/engine/src/flutter/shell/platform/android/io/flutter/embedding/engine/FlutterJNI.java index 8f34fb7d..06da7dca 100644 --- a/engine/src/flutter/shell/platform/android/io/flutter/embedding/engine/FlutterJNI.java +++ b/engine/src/flutter/shell/platform/android/io/flutter/embedding/engine/FlutterJNI.java @@ -29,52 +29,30 @@ import java.util.concurrent.locks.ReentrantReadWriteLock; /** - * Interface between Flutter embedding's Java code and Flutter engine's C/C++ - * code. + * Interface between Flutter embedding's Java code and Flutter engine's C/C++ code. * - *

- * Flutter's engine is built with C/C++. The Android Flutter embedding is - * responsible for - * coordinating Android OS events and app user interactions with the C/C++ - * engine. Such coordination - * requires messaging from an Android app in Java code to the C/C++ engine code. - * This communication + *

Flutter's engine is built with C/C++. The Android Flutter embedding is responsible for + * coordinating Android OS events and app user interactions with the C/C++ engine. Such coordination + * requires messaging from an Android app in Java code to the C/C++ engine code. This communication * requires a JNI (Java Native Interface) API to cross the Java/native boundary. * - *

- * The entirety of Flutter's JNI API is codified in {@code FlutterJNI}. There - * are multiple - * reasons that all such calls are centralized in one class. First, JNI calls - * are inherently static - * and contain no Java implementation, therefore there is little reason to - * associate calls with - * different classes. Second, every JNI call must be registered in C/C++ code - * and this registration - * becomes more complicated with every additional Java class that contains JNI - * calls. Third, most - * Android developers are not familiar with native development or JNI - * intricacies, therefore it is - * in the interest of future maintenance to reduce the API surface that includes - * JNI declarations. + *

The entirety of Flutter's JNI API is codified in {@code FlutterJNI}. There are multiple + * reasons that all such calls are centralized in one class. First, JNI calls are inherently static + * and contain no Java implementation, therefore there is little reason to associate calls with + * different classes. Second, every JNI call must be registered in C/C++ code and this registration + * becomes more complicated with every additional Java class that contains JNI calls. Third, most + * Android developers are not familiar with native development or JNI intricacies, therefore it is + * in the interest of future maintenance to reduce the API surface that includes JNI declarations. * Thus, all Flutter JNI calls are centralized in {@code FlutterJNI}. * - *

- * Despite the fact that individual JNI calls are inherently static, there is - * state that exists - * within {@code FlutterJNI}. Most calls within {@code FlutterJNI} correspond to - * a specific - * "platform view", of which there may be many. Therefore, each - * {@code FlutterJNI} instance holds - * onto a "native platform view ID" after {@link #attachToNative()}, which is - * shared with the native - * C/C++ engine code. That ID is passed to every platform-view-specific native - * method. ID management - * is handled within {@code FlutterJNI} so that developers don't have to hold - * onto that ID. + *

Despite the fact that individual JNI calls are inherently static, there is state that exists + * within {@code FlutterJNI}. Most calls within {@code FlutterJNI} correspond to a specific + * "platform view", of which there may be many. Therefore, each {@code FlutterJNI} instance holds + * onto a "native platform view ID" after {@link #attachToNative()}, which is shared with the native + * C/C++ engine code. That ID is passed to every platform-view-specific native method. ID management + * is handled within {@code FlutterJNI} so that developers don't have to hold onto that ID. * - *

- * To connect part of an Android app to Flutter's C/C++ engine, instantiate a - * {@code FlutterJNI} + *

To connect part of an Android app to Flutter's C/C++ engine, instantiate a {@code FlutterJNI} * and then attach it to the native side: * *

{@code
@@ -88,26 +66,19 @@
  * flutterJNI.detachFromNativeAndReleaseResources();
  * }
* - *

- * To receive callbacks for certain events that occur on the native side, - * register listeners: + *

To receive callbacks for certain events that occur on the native side, register listeners: * *

    - *
  1. {@link #addEngineLifecycleListener(FlutterEngine.EngineLifecycleListener)} + *
  2. {@link #addEngineLifecycleListener(FlutterEngine.EngineLifecycleListener)} *
* - * To facilitate platform messages between Java and Dart running in Flutter, - * register a handler: + * To facilitate platform messages between Java and Dart running in Flutter, register a handler: * - *

- * {@link #setPlatformMessageHandler(PlatformMessageHandler)} + *

{@link #setPlatformMessageHandler(PlatformMessageHandler)} * - *

- * To invoke a native method that is not associated with a platform view, invoke - * it statically: + *

To invoke a native method that is not associated with a platform view, invoke it statically: * - *

- * {@code bool enabled = FlutterJNI.getIsSoftwareRenderingEnabled(); } + *

{@code bool enabled = FlutterJNI.getIsSoftwareRenderingEnabled(); } */ @Keep public class FlutterJNI { @@ -128,8 +99,7 @@ public FlutterJNI() { } /** - * A factory for creating {@code FlutterJNI} instances. Useful for FlutterJNI - * injections during + * A factory for creating {@code FlutterJNI} instances. Useful for FlutterJNI injections during * tests. */ public static class Factory { @@ -143,13 +113,10 @@ public FlutterJNI provideFlutterJNI() { /** * Loads the libflutter.so C++ library. * - *

- * This must be called before any other native methods, and can be overridden by - * tests to avoid + *

This must be called before any other native methods, and can be overridden by tests to avoid * loading native libraries. * - *

- * This method should only be called once across all FlutterJNI instances. + *

This method should only be called once across all FlutterJNI instances. */ public void loadLibrary(Context context) { if (FlutterJNI.loadLibraryCalled) { @@ -173,18 +140,15 @@ private static native void nativeInit( /** * Perform one time initialization of the Dart VM and Flutter engine. * - *

- * This method must be called only once. Calling more than once will cause an - * exception. + *

This method must be called only once. Calling more than once will cause an exception. * - * @param context The application context. - * @param args Arguments to the Dart VM/Flutter engine. - * @param bundlePath For JIT runtimes, the path to the Dart kernel file - * for the application. - * @param appStoragePath The path to the application data directory. + * @param context The application context. + * @param args Arguments to the Dart VM/Flutter engine. + * @param bundlePath For JIT runtimes, the path to the Dart kernel file for the application. + * @param appStoragePath The path to the application data directory. * @param engineCachesPath The path to the application cache directory. - * @param initTimeMillis The time, in milliseconds, taken for initialization. - * @param apiLevel The current Android API level. + * @param initTimeMillis The time, in milliseconds, taken for initialization. + * @param apiLevel The current Android API level. */ public void init( @NonNull Context context, @@ -207,16 +171,14 @@ public void init( // END methods related to FlutterLoader // This is set from native code via JNI. - @Nullable - private static String vmServiceUri; + @Nullable private static String vmServiceUri; private native boolean nativeGetIsSoftwareRenderingEnabled(); /** * Checks launch settings for whether software rendering is requested. * - *

- * The value is the same per program. + *

The value is the same per program. */ @UiThread public boolean getIsSoftwareRenderingEnabled() { @@ -226,9 +188,7 @@ public boolean getIsSoftwareRenderingEnabled() { /** * VM Service URI for the VM instance. * - *

- * Its value is set by the native engine once - * {@link #init(Context, String[], String, String, + *

Its value is set by the native engine once {@link #init(Context, String[], String, String, * String, long, int)} is run. */ @Nullable @@ -246,26 +206,20 @@ public static String getVMServiceUri() { // static per program. // Conceptually, it represents a native shell instance. - @Nullable - private Long nativeShellHolderId; - @Nullable - private PlatformMessageHandler platformMessageHandler; - @Nullable - private LocalizationPlugin localizationPlugin; + @Nullable private Long nativeShellHolderId; + @Nullable private PlatformMessageHandler platformMessageHandler; + @Nullable private LocalizationPlugin localizationPlugin; - @Nullable - private DeferredComponentManager deferredComponentManager; + @Nullable private DeferredComponentManager deferredComponentManager; @NonNull private final Set engineLifecycleListeners = new CopyOnWriteArraySet<>(); - @NonNull - private final Looper mainLooper; // cached to avoid synchronization on repeat access. + @NonNull private final Looper mainLooper; // cached to avoid synchronization on repeat access. // ------ Start Native Attach/Detach Support ---- /** - * Returns true if this instance of {@code FlutterJNI} is connected to Flutter's - * native engine via + * Returns true if this instance of {@code FlutterJNI} is connected to Flutter's native engine via * a Java Native Interface (JNI). */ public boolean isAttached() { @@ -273,13 +227,10 @@ public boolean isAttached() { } /** - * Attaches this {@code FlutterJNI} instance to Flutter's native engine, which - * allows for + * Attaches this {@code FlutterJNI} instance to Flutter's native engine, which allows for * communication between Android code and Flutter's platform agnostic engine. * - *

- * This method must not be invoked if {@code FlutterJNI} is already attached to - * native. + *

This method must not be invoked if {@code FlutterJNI} is already attached to native. */ @UiThread public void attachToNative() { @@ -303,23 +254,15 @@ public long performNativeAttach(@NonNull FlutterJNI flutterJNI) { /** * Spawns a new FlutterJNI instance from the current instance. * - *

- * This creates another native shell from the current shell. This causes the 2 - * shells to re-use - * some of the shared resources, reducing the total memory consumption versus - * creating a new + *

This creates another native shell from the current shell. This causes the 2 shells to re-use + * some of the shared resources, reducing the total memory consumption versus creating a new * FlutterJNI by calling its standard constructor. * - *

- * This can only be called once the current FlutterJNI instance is attached by - * calling {@link + *

This can only be called once the current FlutterJNI instance is attached by calling {@link * #attachToNative()}. * - *

- * Static methods that should be only called once such as - * {@link #init(Context, String[], - * String, String, String, long, int)} shouldn't be called again on the spawned - * FlutterJNI + *

Static methods that should be only called once such as {@link #init(Context, String[], + * String, String, String, long, int)} shouldn't be called again on the spawned FlutterJNI * instance. */ @UiThread @@ -331,12 +274,13 @@ public FlutterJNI spawn( long engineId) { ensureRunningOnMainThread(); ensureAttachedToNative(); - FlutterJNI spawnedJNI = nativeSpawn( - nativeShellHolderId, - entrypointFunctionName, - pathToEntrypointFunction, - entrypointArgs, - engineId); + FlutterJNI spawnedJNI = + nativeSpawn( + nativeShellHolderId, + entrypointFunctionName, + pathToEntrypointFunction, + entrypointArgs, + engineId); Preconditions.checkState( spawnedJNI.nativeShellHolderId != null && spawnedJNI.nativeShellHolderId != 0, "Failed to spawn new JNI connected shell from existing shell."); @@ -352,25 +296,16 @@ private native FlutterJNI nativeSpawn( long engineId); /** - * Detaches this {@code FlutterJNI} instance from Flutter's native engine, which - * precludes any - * further communication between Android code and Flutter's platform agnostic - * engine. + * Detaches this {@code FlutterJNI} instance from Flutter's native engine, which precludes any + * further communication between Android code and Flutter's platform agnostic engine. * - *

- * This method must not be invoked if {@code FlutterJNI} is not already attached - * to native. + *

This method must not be invoked if {@code FlutterJNI} is not already attached to native. * - *

- * Invoking this method will result in the release of all native-side resources - * that were set - * up during {@link #attachToNative()} or - * {@link #spawn(String, String, List, long)}, or + *

Invoking this method will result in the release of all native-side resources that were set + * up during {@link #attachToNative()} or {@link #spawn(String, String, List, long)}, or * accumulated thereafter. * - *

- * It is permissible to re-attach this instance to native after detaching it - * from native. + *

It is permissible to re-attach this instance to native after detaching it from native. */ @UiThread public void detachFromNativeAndReleaseResources() { @@ -406,9 +341,7 @@ private void ensureAttachedToNative() { /** * Executes a Dart entrypoint. * - *

- * This can only be done once per JNI attachment because a Dart isolate can only - * be entered + *

This can only be done once per JNI attachment because a Dart isolate can only be entered * once. */ @UiThread @@ -443,41 +376,27 @@ private native void nativeRunBundleAndSnapshotFromLibrary( // --------- Start Platform Message Support ------ /** - * Sets the handler for all platform messages that come from the attached - * platform view to Java. + * Sets the handler for all platform messages that come from the attached platform view to Java. * - *

- * Communication between a specific Flutter context (Dart) and the host platform - * (Java) is - * accomplished by passing messages. Messages can be sent from Java to Dart with - * the corresponding + *

Communication between a specific Flutter context (Dart) and the host platform (Java) is + * accomplished by passing messages. Messages can be sent from Java to Dart with the corresponding * {@code FlutterJNI} methods: * *

    - *
  • {@link #dispatchPlatformMessage(String, ByteBuffer, int, int)} - *
  • {@link #dispatchEmptyPlatformMessage(String, int)} + *
  • {@link #dispatchPlatformMessage(String, ByteBuffer, int, int)} + *
  • {@link #dispatchEmptyPlatformMessage(String, int)} *
* - *

- * {@code FlutterJNI} is also the recipient of all platform messages sent from - * its attached - * Flutter context. {@code FlutterJNI} does not know what to do with these - * messages, so a handler - * is exposed to allow these messages to be processed in whatever manner is - * desired: + *

{@code FlutterJNI} is also the recipient of all platform messages sent from its attached + * Flutter context. {@code FlutterJNI} does not know what to do with these messages, so a handler + * is exposed to allow these messages to be processed in whatever manner is desired: * - *

- * {@code setPlatformMessageHandler(PlatformMessageHandler)} + *

{@code setPlatformMessageHandler(PlatformMessageHandler)} * - *

- * If a message is received but no {@link PlatformMessageHandler} is registered, - * that message - * will be dropped (ignored). Therefore, when using {@code FlutterJNI} to - * integrate a Flutter - * context in an app, a {@link PlatformMessageHandler} must be registered for - * 2-way Java/Dart - * communication to operate correctly. Moreover, the handler must be implemented - * such that + *

If a message is received but no {@link PlatformMessageHandler} is registered, that message + * will be dropped (ignored). Therefore, when using {@code FlutterJNI} to integrate a Flutter + * context in an app, a {@link PlatformMessageHandler} must be registered for 2-way Java/Dart + * communication to operate correctly. Moreover, the handler must be implemented such that * fundamental platform messages are handled as expected. */ @UiThread @@ -491,8 +410,7 @@ public void setPlatformMessageHandler(@Nullable PlatformMessageHandler platformM /** * Destroys the resources provided sent to `handlePlatformMessage`. * - *

- * This can be called on any thread. + *

This can be called on any thread. * * @param messageData the argument sent to handlePlatformMessage. */ @@ -525,8 +443,7 @@ private void handlePlatformMessageResponse(int replyId, ByteBuffer reply) { } /** - * Sends an empty reply (identified by {@code responseId}) from Android to - * Flutter over the given + * Sends an empty reply (identified by {@code responseId}) from Android to Flutter over the given * {@code channel}. */ @UiThread @@ -548,10 +465,7 @@ public void dispatchEmptyPlatformMessage(@NonNull String channel, int responseId private native void nativeDispatchEmptyPlatformMessage( long nativeShellHolderId, @NonNull String channel, int responseId); - /** - * Sends a reply {@code message} from Android to Flutter over the given - * {@code channel}. - */ + /** Sends a reply {@code message} from Android to Flutter over the given {@code channel}. */ @UiThread public void dispatchPlatformMessage( @NonNull String channel, @Nullable ByteBuffer message, int position, int responseId) { @@ -626,8 +540,7 @@ private native void nativeInvokePlatformMessageResponseCallback( // ----- Start Engine Lifecycle Support ---- /** - * Adds the given {@code engineLifecycleListener} to be notified of Flutter - * engine lifecycle + * Adds the given {@code engineLifecycleListener} to be notified of Flutter engine lifecycle * events, e.g., {@link EngineLifecycleListener#onPreEngineRestart()}. */ @UiThread @@ -637,8 +550,7 @@ public void addEngineLifecycleListener(@NonNull EngineLifecycleListener engineLi } /** - * Removes the given {@code engineLifecycleListener}, which was previously added - * using {@link + * Removes the given {@code engineLifecycleListener}, which was previously added using {@link * #addEngineLifecycleListener(EngineLifecycleListener)}. */ @UiThread @@ -660,19 +572,14 @@ private void onPreEngineRestart() { // ----- Start Localization Support ---- - /** - * Sets the localization plugin that is used in various localization methods. - */ + /** Sets the localization plugin that is used in various localization methods. */ @UiThread public void setLocalizationPlugin(@Nullable LocalizationPlugin localizationPlugin) { ensureRunningOnMainThread(); this.localizationPlugin = localizationPlugin; } - /** - * Invoked by native to obtain the results of Android's locale resolution - * algorithm. - */ + /** Invoked by native to obtain the results of Android's locale resolution algorithm. */ @SuppressWarnings("unused") @VisibleForTesting public String[] computePlatformResolvedLocale(@NonNull String[] strings) { @@ -714,10 +621,7 @@ public String[] computePlatformResolvedLocale(@NonNull String[] strings) { // ----- Start Deferred Components Support ---- - /** - * Sets the deferred component manager that is used to download and install - * split features. - */ + /** Sets the deferred component manager that is used to download and install split features. */ @UiThread public void setDeferredComponentManager( @Nullable DeferredComponentManager deferredComponentManager) { @@ -729,19 +633,14 @@ public void setDeferredComponentManager( } /** - * Called by dart to request that a Dart deferred library corresponding to - * loadingUnitId be + * Called by dart to request that a Dart deferred library corresponding to loadingUnitId be * downloaded (if necessary) and loaded into the dart vm. * - *

- * This method delegates the task to DeferredComponentManager, which handles the - * download and + *

This method delegates the task to DeferredComponentManager, which handles the download and * loading of the dart library and any assets. * - * @param loadingUnitId The loadingUnitId is assigned during compile time by - * gen_snapshot and is - * automatically retrieved when loadLibrary() is called on - * a dart deferred library. + * @param loadingUnitId The loadingUnitId is assigned during compile time by gen_snapshot and is + * automatically retrieved when loadLibrary() is called on a dart deferred library. */ @SuppressWarnings("unused") @UiThread @@ -757,30 +656,20 @@ public void requestDartDeferredLibrary(int loadingUnitId) { } /** - * Searches each of the provided paths for a valid Dart shared library .so file - * and resolves + * Searches each of the provided paths for a valid Dart shared library .so file and resolves * symbols to load into the dart VM. * - *

- * Successful loading of the dart library completes the future returned by - * loadLibrary() that + *

Successful loading of the dart library completes the future returned by loadLibrary() that * triggered the install/load process. * - * @param loadingUnitId The loadingUnitId is assigned during compile time by - * gen_snapshot and is - * automatically retrieved when loadLibrary() is called on - * a dart deferred library. This is - * used to identify which Dart deferred library the - * resolved correspond to. - * @param searchPaths An array of paths in which to look for valid dart shared - * libraries. This - * supports paths within zipped apks as long as the apks - * are not compressed using the - * `path/to/apk.apk!path/inside/apk/lib.so` format. Paths - * will be tried first to last and ends - * when a library is successfully found. When the found - * library is invalid, no additional - * paths will be attempted. + * @param loadingUnitId The loadingUnitId is assigned during compile time by gen_snapshot and is + * automatically retrieved when loadLibrary() is called on a dart deferred library. This is + * used to identify which Dart deferred library the resolved correspond to. + * @param searchPaths An array of paths in which to look for valid dart shared libraries. This + * supports paths within zipped apks as long as the apks are not compressed using the + * `path/to/apk.apk!path/inside/apk/lib.so` format. Paths will be tried first to last and ends + * when a library is successfully found. When the found library is invalid, no additional + * paths will be attempted. */ @UiThread public void loadDartDeferredLibrary(int loadingUnitId, @NonNull String[] searchPaths) { @@ -793,20 +682,14 @@ private native void nativeLoadDartDeferredLibrary( long nativeShellHolderId, int loadingUnitId, @NonNull String[] searchPaths); /** - * Adds the specified AssetManager as an APKAssetResolver in the Flutter - * Engine's AssetManager. + * Adds the specified AssetManager as an APKAssetResolver in the Flutter Engine's AssetManager. * - *

- * This may be used to update the engine AssetManager when a new deferred - * component is - * installed and a new Android AssetManager is created with access to new - * assets. + *

This may be used to update the engine AssetManager when a new deferred component is + * installed and a new Android AssetManager is created with access to new assets. * - * @param assetManager An android AssetManager that is able to access the - * newly downloaded assets. - * @param assetBundlePath The subdirectory that the flutter assets are stored - * in. The typical - * value is `flutter_assets`. + * @param assetManager An android AssetManager that is able to access the newly downloaded assets. + * @param assetBundlePath The subdirectory that the flutter assets are stored in. The typical + * value is `flutter_assets`. */ @UiThread public void updateJavaAssetManager( @@ -822,25 +705,18 @@ private native void nativeUpdateJavaAssetManager( @NonNull String assetBundlePath); /** - * Indicates that a failure was encountered during the Android portion of - * downloading a dynamic - * feature module and loading a dart deferred library, which is typically done - * by + * Indicates that a failure was encountered during the Android portion of downloading a dynamic + * feature module and loading a dart deferred library, which is typically done by * DeferredComponentManager. * - *

- * This will inform dart that the future returned by loadLibrary() should - * complete with an + *

This will inform dart that the future returned by loadLibrary() should complete with an * error. * - * @param loadingUnitId The loadingUnitId that corresponds to the dart deferred - * library that - * failed to install. - * @param error The error message to display. - * @param isTransient When isTransient is false, new attempts to install will - * automatically result - * in same error in Dart before the request is passed to - * Android. + * @param loadingUnitId The loadingUnitId that corresponds to the dart deferred library that + * failed to install. + * @param error The error message to display. + * @param isTransient When isTransient is false, new attempts to install will automatically result + * in same error in Dart before the request is passed to Android. */ @SuppressWarnings("unused") @UiThread @@ -856,13 +732,10 @@ private native void nativeDeferredComponentInstallFailure( // ----- End Deferred Components Support ---- /** - * Notifies the Dart VM of a low memory event, or that the application is in a - * state such that now + * Notifies the Dart VM of a low memory event, or that the application is in a state such that now * is an appropriate time to free resources, such as going to the background. * - *

- * This is distinct from sending a SystemChannel message about low memory, which - * only notifies + *

This is distinct from sending a SystemChannel message about low memory, which only notifies * the running Flutter application. */ @UiThread diff --git a/engine/src/flutter/shell/platform/android/io/flutter/embedding/engine/plugins/FlutterPlugin.java b/engine/src/flutter/shell/platform/android/io/flutter/embedding/engine/plugins/FlutterPlugin.java index 5dd3fc99..e997ee94 100644 --- a/engine/src/flutter/shell/platform/android/io/flutter/embedding/engine/plugins/FlutterPlugin.java +++ b/engine/src/flutter/shell/platform/android/io/flutter/embedding/engine/plugins/FlutterPlugin.java @@ -51,11 +51,10 @@ * be retrieved through a {@link Context}. Developers can access the application context via {@link * FlutterPluginBinding#getApplicationContext()}. * - * All plugins must respect the possibility that a - * Flutter experience may never be associated with an {@code Activity}, e.g., when Flutter is used - * for background behavior. Additionally, all plugins must respect that a {@code Activity}s may come - * and go over time, thus requiring plugins to cleanup resources and recreate those resources as the - * {@code Activity} comes and goes. + *

All plugins must respect the possibility that a Flutter experience may never be associated + * with an {@code Activity}, e.g., when Flutter is used for background behavior. Additionally, all + * plugins must respect that a {@code Activity}s may come and go over time, thus requiring plugins + * to cleanup resources and recreate those resources as the {@code Activity} comes and goes. */ public interface FlutterPlugin { diff --git a/engine/src/flutter/shell/platform/android/test/io/flutter/embedding/engine/FlutterEngineGroupComponentTest.java b/engine/src/flutter/shell/platform/android/test/io/flutter/embedding/engine/FlutterEngineGroupComponentTest.java index 8465877c..6260172d 100644 --- a/engine/src/flutter/shell/platform/android/test/io/flutter/embedding/engine/FlutterEngineGroupComponentTest.java +++ b/engine/src/flutter/shell/platform/android/test/io/flutter/embedding/engine/FlutterEngineGroupComponentTest.java @@ -211,11 +211,7 @@ public void canCreateAndRunWithCustomEntrypointArgs() { doAnswer(invocation -> jniAttached = true).when(secondMockFlutterJNI).attachToNative(); doReturn(secondMockFlutterJNI) .when(mockFlutterJNI) - .spawn( - nullable(String.class), - nullable(String.class), - nullable(List.class), - eq(2l)); + .spawn(nullable(String.class), nullable(String.class), nullable(List.class), eq(2l)); List secondDartEntrypointArgs = new ArrayList(); FlutterEngine secondEngine = engineGroupUnderTest.createAndRunEngine( @@ -226,9 +222,6 @@ public void canCreateAndRunWithCustomEntrypointArgs() { assertEquals(2, engineGroupUnderTest.activeEngines.size()); verify(mockFlutterJNI, times(1)) .spawn( - nullable(String.class), - nullable(String.class), - eq(secondDartEntrypointArgs), - eq(2l)); + nullable(String.class), nullable(String.class), eq(secondDartEntrypointArgs), eq(2l)); } } diff --git a/engine/src/flutter/shell/platform/android/test/io/flutter/embedding/engine/FlutterEngineTest.java b/engine/src/flutter/shell/platform/android/test/io/flutter/embedding/engine/FlutterEngineTest.java index cadc2fd6..60696cb6 100644 --- a/engine/src/flutter/shell/platform/android/test/io/flutter/embedding/engine/FlutterEngineTest.java +++ b/engine/src/flutter/shell/platform/android/test/io/flutter/embedding/engine/FlutterEngineTest.java @@ -38,8 +38,6 @@ import org.mockito.MockitoAnnotations; import org.mockito.invocation.InvocationOnMock; import org.mockito.stubbing.Answer; -import org.robolectric.Robolectric; -import org.robolectric.android.controller.ActivityController; import org.robolectric.shadows.ShadowLog; @RunWith(AndroidJUnit4.class) diff --git a/engine/src/flutter/shell/platform/android/test/io/flutter/embedding/engine/FlutterShellArgsTest.java b/engine/src/flutter/shell/platform/android/test/io/flutter/embedding/engine/FlutterShellArgsTest.java index 4b7936fc..c568ae23 100644 --- a/engine/src/flutter/shell/platform/android/test/io/flutter/embedding/engine/FlutterShellArgsTest.java +++ b/engine/src/flutter/shell/platform/android/test/io/flutter/embedding/engine/FlutterShellArgsTest.java @@ -9,7 +9,6 @@ import android.content.Intent; import androidx.test.ext.junit.runners.AndroidJUnit4; -import io.flutter.embedding.engine.FlutterShellArgs; import java.util.Arrays; import java.util.HashSet; import org.junit.Test; diff --git a/engine/src/flutter/shell/platform/android/test/io/flutter/embedding/engine/PluginComponentTest.java b/engine/src/flutter/shell/platform/android/test/io/flutter/embedding/engine/PluginComponentTest.java index ed146c61..1001947b 100644 --- a/engine/src/flutter/shell/platform/android/test/io/flutter/embedding/engine/PluginComponentTest.java +++ b/engine/src/flutter/shell/platform/android/test/io/flutter/embedding/engine/PluginComponentTest.java @@ -12,8 +12,6 @@ import androidx.annotation.NonNull; import androidx.test.core.app.ApplicationProvider; import androidx.test.ext.junit.runners.AndroidJUnit4; -import io.flutter.embedding.engine.FlutterEngine; -import io.flutter.embedding.engine.FlutterJNI; import io.flutter.embedding.engine.loader.FlutterLoader; import io.flutter.embedding.engine.plugins.FlutterPlugin; import org.junit.Test; diff --git a/engine/src/flutter/shell/platform/common/BUILD.gn b/engine/src/flutter/shell/platform/common/BUILD.gn index 62b576a0..7f5000f5 100644 --- a/engine/src/flutter/shell/platform/common/BUILD.gn +++ b/engine/src/flutter/shell/platform/common/BUILD.gn @@ -94,9 +94,7 @@ source_set("common_cpp") { # embedding is further along and it's clearer how much, if any, shared # API surface there will be. source_set("common_cpp_core") { - public = [ - "path_utils.h", - ] + public = [ "path_utils.h" ] sources = [ "path_utils.cc" ] diff --git a/engine/src/flutter/shell/platform/common/client_wrapper/BUILD.gn b/engine/src/flutter/shell/platform/common/client_wrapper/BUILD.gn index caa8df4e..cb02c0dd 100644 --- a/engine/src/flutter/shell/platform/common/client_wrapper/BUILD.gn +++ b/engine/src/flutter/shell/platform/common/client_wrapper/BUILD.gn @@ -58,8 +58,8 @@ executable("client_wrapper_unittests") { ":client_wrapper_library_stubs", "//flutter/testing", - # TODO(chunhtai): Consider refactoring flutter_root/testing so that there's a testing - # target that doesn't require a Dart runtime to be linked in. + # TODO(chunhtai): Consider refactoring flutter_root/testing so that there's + # a testing target that doesn't require a Dart runtime to be linked in. # https://github.com/flutter/flutter/issues/41414. "$dart_src/runtime:libdart_jit", ] diff --git a/engine/src/flutter/shell/platform/darwin/common/framework/Source/FlutterChannels.mm b/engine/src/flutter/shell/platform/darwin/common/framework/Source/FlutterChannels.mm index 78d5c084..fad428dd 100644 --- a/engine/src/flutter/shell/platform/darwin/common/framework/Source/FlutterChannels.mm +++ b/engine/src/flutter/shell/platform/darwin/common/framework/Source/FlutterChannels.mm @@ -53,9 +53,11 @@ static FlutterBinaryMessengerConnection SetMessageHandler( FlutterBinaryMessageHandler handler, NSObject* taskQueue) { if (taskQueue) { - NSCAssert([messenger respondsToSelector:@selector(setMessageHandlerOnChannel: - binaryMessageHandler:taskQueue:)], - @""); + NSCAssert( + [messenger + respondsToSelector:@selector( + setMessageHandlerOnChannel:binaryMessageHandler:taskQueue:)], + @""); return [messenger setMessageHandlerOnChannel:name binaryMessageHandler:handler taskQueue:taskQueue]; diff --git a/engine/src/flutter/shell/platform/darwin/macos/BUILD.gn b/engine/src/flutter/shell/platform/darwin/macos/BUILD.gn index 27449b24..173ddd39 100644 --- a/engine/src/flutter/shell/platform/darwin/macos/BUILD.gn +++ b/engine/src/flutter/shell/platform/darwin/macos/BUILD.gn @@ -111,7 +111,6 @@ test_fixtures("flutter_desktop_darwin_fixtures") { fixtures = [ "//flutter/third_party/icu/common/icudtl.dat" ] } - # Keeps the Dart VM snapshot blobs of the engine inside the test executable. # # The blobs are resolved at runtime with dlsym from the current process, and diff --git a/engine/src/flutter/shell/platform/darwin/macos/framework/Source/FlutterEngineTest.mm b/engine/src/flutter/shell/platform/darwin/macos/framework/Source/FlutterEngineTest.mm index 338d88d7..4a1a73cf 100644 --- a/engine/src/flutter/shell/platform/darwin/macos/framework/Source/FlutterEngineTest.mm +++ b/engine/src/flutter/shell/platform/darwin/macos/framework/Source/FlutterEngineTest.mm @@ -235,7 +235,7 @@ @implementation MockableFlutterEngine engine.embedderAPI.Initialize = MOCK_ENGINE_PROC( Initialize, ([&called, &original_init](size_t version, const FlutterProjectArgs* args, void* user_data, - FLUTTER_API_SYMBOL(FlutterEngine) * engine_out) { + FLUTTER_API_SYMBOL(FlutterEngine)* engine_out) { called = true; EXPECT_EQ(args->dart_entrypoint_argc, 2); NSString* arg1 = [[NSString alloc] initWithCString:args->dart_entrypoint_argv[0] diff --git a/engine/src/flutter/shell/platform/embedder/BUILD.gn b/engine/src/flutter/shell/platform/embedder/BUILD.gn index 50e5af14..9e77891d 100644 --- a/engine/src/flutter/shell/platform/embedder/BUILD.gn +++ b/engine/src/flutter/shell/platform/embedder/BUILD.gn @@ -73,7 +73,8 @@ template("embedder_source_set") { "//flutter/third_party/tonic", ] - # Depend on 'icudtl.dat.S' to avoid dynamic lookups of engine library symbols. + # Depend on 'icudtl.dat.S' to avoid dynamic lookups of engine library + # symbols. if (is_android) { deps += [ "//flutter/shell/platform/android:icudtl_asm" ] sources += [ "$root_build_dir/gen/flutter/shell/platform/android/flutter/third_party/icu/flutter/icudtl.dat.S" ] @@ -101,9 +102,7 @@ source_set("embedder_headers") { } source_set("embedder_test_utils") { - public = [ - "test_utils/proc_table_replacement.h", - ] + public = [ "test_utils/proc_table_replacement.h" ] deps = [ ":embedder_headers" ] @@ -153,7 +152,7 @@ if (enable_unittests) { "//flutter/lib/snapshot", "//flutter/lib/ui", "//flutter/runtime", - "//flutter/shell/common:common", + "//flutter/shell/common", "//flutter/testing", "//flutter/testing:dart", "//flutter/third_party/tonic", @@ -328,7 +327,8 @@ group("flutter_engine") { ":flutter_engine_library", ] - # For the Mac, the dylib is packaged in a framework with the appropriate headers. + # For the Mac, the dylib is packaged in a framework with the appropriate + # headers. if (is_mac && !embedder_for_target) { deps += [ ":flutter_embedder_framework" ] } diff --git a/engine/src/flutter/shell/platform/embedder/embedder.cc b/engine/src/flutter/shell/platform/embedder/embedder.cc index b17cb779..57a5300f 100644 --- a/engine/src/flutter/shell/platform/embedder/embedder.cc +++ b/engine/src/flutter/shell/platform/embedder/embedder.cc @@ -503,7 +503,7 @@ FlutterEngineResult FlutterEngineInitialize(size_t version, compute_platform_resolved_locale_callback, // on_pre_engine_restart_callback, // channel_update_callback, // - }; + }; auto on_create_platform_view = InferPlatformViewCreationCallback(user_data, platform_dispatch_table); diff --git a/engine/src/flutter/shell/platform/embedder/fixtures/main.dart b/engine/src/flutter/shell/platform/embedder/fixtures/main.dart index ef075352..37f8128f 100644 --- a/engine/src/flutter/shell/platform/embedder/fixtures/main.dart +++ b/engine/src/flutter/shell/platform/embedder/fixtures/main.dart @@ -108,15 +108,14 @@ void platform_messages_response() { @pragma('vm:entry-point') // ignore: non_constant_identifier_names void platform_messages_no_response() { - PlatformDispatcher - .instance - .onPlatformMessage = (String name, ByteData? data, PlatformMessageResponseCallback? callback) { - final Uint8List list = data!.buffer.asUint8List(data.offsetInBytes, data.lengthInBytes); - signalNativeMessage(utf8.decode(list)); - // This does nothing because no one is listening on the other side. But complete the loop anyway - // to make sure all null checking on response handles in the engine is in place. - callback!(data); - }; + PlatformDispatcher.instance.onPlatformMessage = + (String name, ByteData? data, PlatformMessageResponseCallback? callback) { + final Uint8List list = data!.buffer.asUint8List(data.offsetInBytes, data.lengthInBytes); + signalNativeMessage(utf8.decode(list)); + // This does nothing because no one is listening on the other side. But complete the loop anyway + // to make sure all null checking on response handles in the engine is in place. + callback!(data); + }; signalNativeTest(); } diff --git a/engine/src/flutter/shell/platform/fuchsia/dart-pkg/zircon_ffi/lib/zircon_ffi.dart b/engine/src/flutter/shell/platform/fuchsia/dart-pkg/zircon_ffi/lib/zircon_ffi.dart index bd23da2d..ca272783 100644 --- a/engine/src/flutter/shell/platform/fuchsia/dart-pkg/zircon_ffi/lib/zircon_ffi.dart +++ b/engine/src/flutter/shell/platform/fuchsia/dart-pkg/zircon_ffi/lib/zircon_ffi.dart @@ -215,48 +215,59 @@ final class zircon_dart_handle_list_t extends ffi.Struct { final class _Dart_Handle extends ffi.Opaque {} -typedef _c_zircon_dart_byte_array_create = - ffi.Pointer Function(ffi.Uint32 size); - -typedef _dart_zircon_dart_byte_array_create = - ffi.Pointer Function(int size); - -typedef _c_zircon_dart_byte_array_set_value = - ffi.Void Function(ffi.Pointer arr, ffi.Uint32 index, ffi.Uint8 value); - -typedef _dart_zircon_dart_byte_array_set_value = - void Function(ffi.Pointer arr, int index, int value); - -typedef _c_zircon_dart_byte_array_free = - ffi.Void Function(ffi.Pointer arr); - -typedef _dart_zircon_dart_byte_array_free = - void Function(ffi.Pointer arr); +typedef _c_zircon_dart_byte_array_create = ffi.Pointer Function( + ffi.Uint32 size, +); + +typedef _dart_zircon_dart_byte_array_create = ffi.Pointer Function( + int size, +); + +typedef _c_zircon_dart_byte_array_set_value = ffi.Void Function( + ffi.Pointer arr, + ffi.Uint32 index, + ffi.Uint8 value, +); + +typedef _dart_zircon_dart_byte_array_set_value = void Function( + ffi.Pointer arr, + int index, + int value, +); + +typedef _c_zircon_dart_byte_array_free = ffi.Void Function( + ffi.Pointer arr, +); + +typedef _dart_zircon_dart_byte_array_free = void Function( + ffi.Pointer arr, +); typedef _c_zircon_dart_handle_list_create = ffi.Pointer Function(); typedef _dart_zircon_dart_handle_list_create = ffi.Pointer Function(); -typedef _c_zircon_dart_handle_list_append = - ffi.Void Function( - ffi.Pointer list, - ffi.Pointer handle, - ); +typedef _c_zircon_dart_handle_list_append = ffi.Void Function( + ffi.Pointer list, + ffi.Pointer handle, +); -typedef _dart_zircon_dart_handle_list_append = - void Function( - ffi.Pointer list, - ffi.Pointer handle, - ); +typedef _dart_zircon_dart_handle_list_append = void Function( + ffi.Pointer list, + ffi.Pointer handle, +); -typedef _c_zircon_dart_handle_list_free = - ffi.Void Function(ffi.Pointer list); +typedef _c_zircon_dart_handle_list_free = ffi.Void Function( + ffi.Pointer list, +); -typedef _dart_zircon_dart_handle_list_free = - void Function(ffi.Pointer list); +typedef _dart_zircon_dart_handle_list_free = void Function( + ffi.Pointer list, +); -typedef _c_zircon_dart_handle_is_valid = - ffi.Int32 Function(ffi.Pointer handle); +typedef _c_zircon_dart_handle_is_valid = ffi.Int32 Function( + ffi.Pointer handle, +); typedef _dart_zircon_dart_handle_is_valid = int Function(ffi.Pointer handle); @@ -268,52 +279,58 @@ typedef _c_zircon_dart_handle_free = ffi.Void Function(ffi.Pointer handle); -typedef _c_zircon_dart_handle_pair_attach_finalizer = - ffi.Int32 Function( - ffi.Handle object, - ffi.Pointer pointer, - ffi.IntPtr external_allocation_size, - ); - -typedef _dart_zircon_dart_handle_pair_attach_finalizer = - int Function(Object object, ffi.Pointer pointer, int external_allocation_size); - -typedef _c_zircon_dart_handle_attach_finalizer = - ffi.Int32 Function( - ffi.Handle object, - ffi.Pointer pointer, - ffi.IntPtr external_allocation_size, - ); - -typedef _dart_zircon_dart_handle_attach_finalizer = - int Function(Object object, ffi.Pointer pointer, int external_allocation_size); - -typedef _c_zircon_dart_channel_create = - ffi.Pointer Function(ffi.Uint32 options); - -typedef _dart_zircon_dart_channel_create = - ffi.Pointer Function(int options); - -typedef _c_zircon_dart_channel_write = - ffi.Int32 Function( - ffi.Pointer handle, - ffi.Pointer bytes, - ffi.Pointer handles, - ); - -typedef _dart_zircon_dart_channel_write = - int Function( - ffi.Pointer handle, - ffi.Pointer bytes, - ffi.Pointer handles, - ); +typedef _c_zircon_dart_handle_pair_attach_finalizer = ffi.Int32 Function( + ffi.Handle object, + ffi.Pointer pointer, + ffi.IntPtr external_allocation_size, +); + +typedef _dart_zircon_dart_handle_pair_attach_finalizer = int Function( + Object object, + ffi.Pointer pointer, + int external_allocation_size, +); + +typedef _c_zircon_dart_handle_attach_finalizer = ffi.Int32 Function( + ffi.Handle object, + ffi.Pointer pointer, + ffi.IntPtr external_allocation_size, +); + +typedef _dart_zircon_dart_handle_attach_finalizer = int Function( + Object object, + ffi.Pointer pointer, + int external_allocation_size, +); + +typedef _c_zircon_dart_channel_create = ffi.Pointer Function( + ffi.Uint32 options, +); + +typedef _dart_zircon_dart_channel_create = ffi.Pointer Function( + int options, +); + +typedef _c_zircon_dart_channel_write = ffi.Int32 Function( + ffi.Pointer handle, + ffi.Pointer bytes, + ffi.Pointer handles, +); + +typedef _dart_zircon_dart_channel_write = int Function( + ffi.Pointer handle, + ffi.Pointer bytes, + ffi.Pointer handles, +); typedef _c_zircon_dart_clock_get_monotonic = ffi.Uint64 Function(); typedef _dart_zircon_dart_clock_get_monotonic = int Function(); -typedef _c_zircon_dart_dl_initialize = - ffi.Int32 Function(ffi.Pointer initialize_api_dl_data); +typedef _c_zircon_dart_dl_initialize = ffi.Int32 Function( + ffi.Pointer initialize_api_dl_data, +); -typedef _dart_zircon_dart_dl_initialize = - int Function(ffi.Pointer initialize_api_dl_data); +typedef _dart_zircon_dart_dl_initialize = int Function( + ffi.Pointer initialize_api_dl_data, +); diff --git a/engine/src/flutter/shell/platform/fuchsia/dart_runner/BUILD.gn b/engine/src/flutter/shell/platform/fuchsia/dart_runner/BUILD.gn index e1cf5f75..3ed069da 100644 --- a/engine/src/flutter/shell/platform/fuchsia/dart_runner/BUILD.gn +++ b/engine/src/flutter/shell/platform/fuchsia/dart_runner/BUILD.gn @@ -13,6 +13,7 @@ import("//flutter/tools/fuchsia/gn-sdk/src/gn_configs.gni") template("runner_sources") { assert(defined(invoker.product), "runner_sources must define product") + source_set(target_name) { forward_variables_from(invoker, [ "defines" ]) sources = [ @@ -163,6 +164,7 @@ template("aot_runner_package") { if (invoker.product) { product_suffix = "_product" } + fuchsia_archive(target_name) { deps = [ ":dart_aot${product_suffix}_runner_bin" ] if (!invoker.product) { diff --git a/engine/src/flutter/shell/platform/fuchsia/dart_runner/embedder/BUILD.gn b/engine/src/flutter/shell/platform/fuchsia/dart_runner/embedder/BUILD.gn index eb7e0562..09709384 100644 --- a/engine/src/flutter/shell/platform/fuchsia/dart_runner/embedder/BUILD.gn +++ b/engine/src/flutter/shell/platform/fuchsia/dart_runner/embedder/BUILD.gn @@ -27,10 +27,12 @@ template("create_aot_snapshot") { if (invoker.product) { product_suffix = "_product" } + compiled_action("${target_name}_assembly") { snapshot_assembly = "$target_gen_dir/aot${product_suffix}_vm_snapshot.S" - # gen_snapshot only needs this to go through the motions of setting up an isolate. + # gen_snapshot only needs this to go through the motions of setting up an + # isolate. shim_target = ":shim${product_suffix}_kernel($host_toolchain)" shim_kernel = get_label_info(shim_target, "target_gen_dir") + "/shim${product_suffix}_kernel.dill" diff --git a/engine/src/flutter/shell/platform/fuchsia/dart_runner/tests/startup_integration_test/dart_echo_server/BUILD.gn b/engine/src/flutter/shell/platform/fuchsia/dart_runner/tests/startup_integration_test/dart_echo_server/BUILD.gn index 245bdb7a..7ee8747b 100644 --- a/engine/src/flutter/shell/platform/fuchsia/dart_runner/tests/startup_integration_test/dart_echo_server/BUILD.gn +++ b/engine/src/flutter/shell/platform/fuchsia/dart_runner/tests/startup_integration_test/dart_echo_server/BUILD.gn @@ -16,7 +16,8 @@ dart_library("lib") { sources = [ "main.dart" ] } -# Dart component that serves the test Echo FIDL protocol, built using the Dart AOT runner +# Dart component that serves the test Echo FIDL protocol, built using the Dart +# AOT runner dart_component("aot_component") { testonly = true @@ -27,7 +28,8 @@ dart_component("aot_component") { deps = [ ":lib" ] } -# Dart component that serves the test Echo FIDL protocol, built using the Dart AOT runner +# Dart component that serves the test Echo FIDL protocol, built using the Dart +# AOT runner dart_component("jit_component") { testonly = true diff --git a/engine/src/flutter/shell/platform/linux/BUILD.gn b/engine/src/flutter/shell/platform/linux/BUILD.gn index 2342b93f..f1880956 100644 --- a/engine/src/flutter/shell/platform/linux/BUILD.gn +++ b/engine/src/flutter/shell/platform/linux/BUILD.gn @@ -96,7 +96,8 @@ source_set("flutter_linux_sources") { "fl_value.cc", ] - # Set flag to stop headers being directly included (library users should not do this) + # Set flag to stop headers being directly included (library users should not + # do this) defines = [ "FLUTTER_LINUX_COMPILATION", "FLUTTER_ENGINE_NO_PROTOTYPES", diff --git a/engine/src/flutter/shell/platform/linux/fl_engine_test.cc b/engine/src/flutter/shell/platform/linux/fl_engine_test.cc index 458c1b4f..12d3da50 100644 --- a/engine/src/flutter/shell/platform/linux/fl_engine_test.cc +++ b/engine/src/flutter/shell/platform/linux/fl_engine_test.cc @@ -108,7 +108,7 @@ TEST(FlEngineTest, OnPreEngineRestart) { Initialize, ([&callback, &callback_user_data, &called]( size_t version, const FlutterProjectArgs* args, void* user_data, - FLUTTER_API_SYMBOL(FlutterEngine) * engine_out) { + FLUTTER_API_SYMBOL(FlutterEngine)* engine_out) { called = true; callback = args->on_pre_engine_restart_callback; callback_user_data = user_data; @@ -158,7 +158,7 @@ TEST(FlEngineTest, DartEntrypointArgs) { Initialize, ([&called, &set_args = args]( size_t version, const FlutterProjectArgs* args, void* user_data, - FLUTTER_API_SYMBOL(FlutterEngine) * engine_out) { + FLUTTER_API_SYMBOL(FlutterEngine)* engine_out) { called = true; EXPECT_NE(set_args, args->dart_entrypoint_argv); EXPECT_EQ(args->dart_entrypoint_argc, 3); @@ -180,10 +180,9 @@ TEST(FlEngineTest, EngineId) { g_autoptr(FlEngine) engine = fl_engine_new(project); int64_t engine_id; fl_engine_get_embedder_api(engine)->Initialize = MOCK_ENGINE_PROC( - Initialize, - ([&engine_id](size_t version, const FlutterProjectArgs* args, - void* user_data, - FLUTTER_API_SYMBOL(FlutterEngine) * engine_out) { + Initialize, ([&engine_id](size_t version, const FlutterProjectArgs* args, + void* user_data, + FLUTTER_API_SYMBOL(FlutterEngine)* engine_out) { engine_id = args->engine_id; return kSuccess; })); @@ -209,7 +208,7 @@ TEST(FlEngineTest, UIIsolateDefaultThreadPolicy) { Initialize, ([&same_task_runner](size_t version, const FlutterProjectArgs* args, void* user_data, - FLUTTER_API_SYMBOL(FlutterEngine) * engine_out) { + FLUTTER_API_SYMBOL(FlutterEngine)* engine_out) { same_task_runner = args->custom_task_runners->platform_task_runner == args->custom_task_runners->ui_task_runner; return kSuccess; @@ -235,7 +234,7 @@ TEST(FlEngineTest, UIIsolateOnPlatformTaskRunner) { Initialize, ([&same_task_runner](size_t version, const FlutterProjectArgs* args, void* user_data, - FLUTTER_API_SYMBOL(FlutterEngine) * engine_out) { + FLUTTER_API_SYMBOL(FlutterEngine)* engine_out) { same_task_runner = args->custom_task_runners->platform_task_runner == args->custom_task_runners->ui_task_runner; return kSuccess; @@ -261,7 +260,7 @@ TEST(FlEngineTest, UIIsolateOnSeparateThread) { Initialize, ([&separate_thread](size_t version, const FlutterProjectArgs* args, void* user_data, - FLUTTER_API_SYMBOL(FlutterEngine) * engine_out) { + FLUTTER_API_SYMBOL(FlutterEngine)* engine_out) { separate_thread = args->custom_task_runners->ui_task_runner == nullptr; return kSuccess; })); diff --git a/engine/src/flutter/shell/platform/linux/fl_plugin_registrar_private.h b/engine/src/flutter/shell/platform/linux/fl_plugin_registrar_private.h index 2aa213a2..f640344f 100644 --- a/engine/src/flutter/shell/platform/linux/fl_plugin_registrar_private.h +++ b/engine/src/flutter/shell/platform/linux/fl_plugin_registrar_private.h @@ -20,8 +20,7 @@ G_BEGIN_DECLS * * Returns: a new #FlPluginRegistrar. */ -FlPluginRegistrar* fl_plugin_registrar_new( - FlBinaryMessenger* messenger); +FlPluginRegistrar* fl_plugin_registrar_new(FlBinaryMessenger* messenger); G_END_DECLS diff --git a/engine/src/flutter/shell/platform/windows/BUILD.gn b/engine/src/flutter/shell/platform/windows/BUILD.gn index e509d5c3..ef0b4f53 100644 --- a/engine/src/flutter/shell/platform/windows/BUILD.gn +++ b/engine/src/flutter/shell/platform/windows/BUILD.gn @@ -59,15 +59,12 @@ source_set("flutter_windows_source") { "imm32.lib", ] - configs += [ - "//flutter/shell/platform/common:desktop_library_implementation", - ] + configs += + [ "//flutter/shell/platform/common:desktop_library_implementation" ] defines = [ "FLUTTER_ENGINE_NO_PROTOTYPES" ] - public_deps = [ - "//flutter/fml:string_conversion", - ] + public_deps = [ "//flutter/fml:string_conversion" ] deps = [ ":flutter_windows_headers", diff --git a/engine/src/flutter/shell/platform/windows/client_wrapper/BUILD.gn b/engine/src/flutter/shell/platform/windows/client_wrapper/BUILD.gn index 97d04e1d..3cc1f9e9 100644 --- a/engine/src/flutter/shell/platform/windows/client_wrapper/BUILD.gn +++ b/engine/src/flutter/shell/platform/windows/client_wrapper/BUILD.gn @@ -12,9 +12,7 @@ _wrapper_includes = [ "include/flutter/plugin_registrar_windows.h", ] -_wrapper_sources = [ - "flutter_engine.cc", -] +_wrapper_sources = [ "flutter_engine.cc" ] # This code will be merged into .../common/client_wrapper for client use, # so uses header paths that assume the merged state. Include the header @@ -87,8 +85,8 @@ executable("client_wrapper_windows_unittests") { "//flutter/shell/platform/common/client_wrapper:client_wrapper_library_stubs", "//flutter/testing", - # TODO(chunhtai): Consider refactoring flutter_root/testing so that there's a testing - # target that doesn't require a Dart runtime to be linked in. + # TODO(chunhtai): Consider refactoring flutter_root/testing so that there's + # a testing target that doesn't require a Dart runtime to be linked in. # https://github.com/flutter/flutter/issues/41414. "$dart_src/runtime:libdart_jit", ] @@ -102,9 +100,7 @@ client_wrapper_file_archive_list = [ "standard_codec.cc", ] -win_client_wrapper_file_archive_list = [ - "flutter_engine.cc", -] +win_client_wrapper_file_archive_list = [ "flutter_engine.cc" ] zip_bundle("client_wrapper_archive") { output = "$full_target_platform_name/flutter-cpp-client-wrapper.zip" diff --git a/engine/src/flutter/shell/platform/windows/flutter_windows_engine.cc b/engine/src/flutter/shell/platform/windows/flutter_windows_engine.cc index 7c4159c5..ff958485 100644 --- a/engine/src/flutter/shell/platform/windows/flutter_windows_engine.cc +++ b/engine/src/flutter/shell/platform/windows/flutter_windows_engine.cc @@ -307,8 +307,7 @@ void FlutterWindowsEngine::HandlePlatformMessage( auto message = ConvertToDesktopMessage(*engine_message); - message_dispatcher_->HandleMessage( - message, [this] {}, [this] {}); + message_dispatcher_->HandleMessage(message, [this] {}, [this] {}); } void FlutterWindowsEngine::SendSystemLocales() { diff --git a/engine/src/flutter/shell/platform/windows/flutter_windows_engine_unittests.cc b/engine/src/flutter/shell/platform/windows/flutter_windows_engine_unittests.cc index bb6b35cc..dbd4a813 100644 --- a/engine/src/flutter/shell/platform/windows/flutter_windows_engine_unittests.cc +++ b/engine/src/flutter/shell/platform/windows/flutter_windows_engine_unittests.cc @@ -164,7 +164,7 @@ TEST_F(FlutterWindowsEngineTest, RunDoesExpectedInitialization) { modifier.embedder_api().Run = MOCK_ENGINE_PROC( Run, ([&run_called, engine_instance = engine.get()]( size_t version, const FlutterProjectArgs* args, void* user_data, - FLUTTER_API_SYMBOL(FlutterEngine) * engine_out) { + FLUTTER_API_SYMBOL(FlutterEngine)* engine_out) { run_called = true; *engine_out = reinterpret_cast(1); diff --git a/engine/src/flutter/shell/platform/windows/testing/windows_test_config_builder.h b/engine/src/flutter/shell/platform/windows/testing/windows_test_config_builder.h index ac5c5f97..0dc4f0bb 100644 --- a/engine/src/flutter/shell/platform/windows/testing/windows_test_config_builder.h +++ b/engine/src/flutter/shell/platform/windows/testing/windows_test_config_builder.h @@ -15,7 +15,6 @@ #include "flutter/shell/platform/windows/public/flutter_windows.h" #include "flutter/shell/platform/windows/testing/windows_test_context.h" - namespace flutter { namespace testing { diff --git a/engine/src/flutter/testing/android/native_activity/BUILD.gn b/engine/src/flutter/testing/android/native_activity/BUILD.gn index 3044d1aa..3373690c 100644 --- a/engine/src/flutter/testing/android/native_activity/BUILD.gn +++ b/engine/src/flutter/testing/android/native_activity/BUILD.gn @@ -13,9 +13,7 @@ source_set("native_activity") { "native_activity.h", ] - public_deps = [ - "//flutter/fml", - ] + public_deps = [ "//flutter/fml" ] libs = [ "android", diff --git a/engine/src/flutter/testing/android/native_activity/native_activity.gni b/engine/src/flutter/testing/android/native_activity/native_activity.gni index e84ed704..ce51768f 100644 --- a/engine/src/flutter/testing/android/native_activity/native_activity.gni +++ b/engine/src/flutter/testing/android/native_activity/native_activity.gni @@ -27,6 +27,7 @@ template("native_activity_apk") { android_manifest = "$target_gen_dir/AndroidManifest.xml" android_manifest_target_name = "android_manifest_$target_name" + templater(android_manifest_target_name) { input = android_manifest_template output = android_manifest @@ -34,12 +35,14 @@ template("native_activity_apk") { } shared_library_target_name = "shared_library_$target_name" + shared_library(shared_library_target_name) { forward_variables_from(invoker, "*", [ "output_name" ]) output_name = invoker_apk_name } apk_target_name = "apk_$target_name" + action(apk_target_name) { forward_variables_from(invoker, [ "testonly" ]) diff --git a/engine/src/flutter/testing/dart/BUILD.gn b/engine/src/flutter/testing/dart/BUILD.gn index 4ae37479..cd740a0b 100644 --- a/engine/src/flutter/testing/dart/BUILD.gn +++ b/engine/src/flutter/testing/dart/BUILD.gn @@ -27,6 +27,7 @@ tests = [ foreach(test, tests) { flutter_build_dir = rebase_path("$root_gen_dir") flutter_src_dir = rebase_path("//flutter") + flutter_frontend_server("compile_$test") { main_dart = test kernel_output = "$root_gen_dir/$test.dill" diff --git a/engine/src/flutter/testing/run_tests.py b/engine/src/flutter/testing/run_tests.py index 78a1fd7d..d9e7b4b3 100755 --- a/engine/src/flutter/testing/run_tests.py +++ b/engine/src/flutter/testing/run_tests.py @@ -446,17 +446,17 @@ def make_test(name, flags=None, extra_env=None): if is_windows(): unittests += [ - make_test('client_wrapper_windows_unittests'), - make_test('flutter_windows_unittests'), + make_test('client_wrapper_windows_unittests'), + make_test('flutter_windows_unittests'), ] # These unit-tests are Objective-C and can only run on Darwin. if is_mac(): unittests += [ - make_test('availability_version_check_unittests'), - make_test('framework_common_swift_unittests'), - make_test('framework_common_unittests'), - make_test('spring_animation_unittests'), + make_test('availability_version_check_unittests'), + make_test('framework_common_swift_unittests'), + make_test('framework_common_unittests'), + make_test('spring_animation_unittests'), ] for test, flags, extra_env in unittests: @@ -491,6 +491,7 @@ def make_test(name, flags=None, extra_env=None): # Impeller, and with it the interactive Metal/Vulkan tests, were removed # from flutter_zero. + def run_engine_benchmarks(build_dir, executable_filter): logger.info('Running Engine Benchmarks.') @@ -655,10 +656,10 @@ def run_java_tests(executable_filter, android_variant='android_debug_unopt'): # SDK locations (CI images export ANDROID_SDK_ROOT to their own SDK), so # both are pinned to the engine-provided SDK. env = dict( - os.environ, - ANDROID_HOME=android_home, - ANDROID_SDK_ROOT=android_home, - JAVA_HOME=java_home(), + os.environ, + ANDROID_HOME=android_home, + ANDROID_SDK_ROOT=android_home, + JAVA_HOME=java_home(), ) run_cmd(command, cwd=test_runner_dir, env=env) diff --git a/engine/src/flutter/testing/testing.gni b/engine/src/flutter/testing/testing.gni index 5ead3d22..c72ee381 100644 --- a/engine/src/flutter/testing/testing.gni +++ b/engine/src/flutter/testing/testing.gni @@ -173,6 +173,7 @@ template("dart_snapshot") { "The main Dart ELF filename must be specified.") dart_snapshot_aot_target_name = "_dsa_$target_name" + dart_snapshot_aot(dart_snapshot_aot_target_name) { dart_kernel = dart_snapshot_kernel_path dart_elf_filename = invoker.dart_elf_filename @@ -264,6 +265,7 @@ template("test_fixtures") { # Even if no fixtures are present, the location of the fixtures directory # must always be known to tests. fixtures_location_target_name = "_fl_$target_name" + fixtures_location(fixtures_location_target_name) { if (is_fuchsia) { assets_dir = "/pkg/data/assets" @@ -277,6 +279,7 @@ template("test_fixtures") { # If the fixtures are specified, copy them to the assets directory. if (defined(invoker.fixtures)) { copy_fixtures_target_name = "_cf_$target_name" + copy_fixtures(copy_fixtures_target_name) { fixtures = invoker.fixtures dest = dest @@ -295,6 +298,7 @@ template("test_fixtures") { artifact_prefix = "" } dart_snapshot_target_name = "_ds_$target_name" + dart_snapshot(dart_snapshot_target_name) { dart_main = invoker.dart_main dart_kernel_filename = "${artifact_prefix}kernel_blob.bin" diff --git a/engine/src/flutter/tools/font_subset/BUILD.gn b/engine/src/flutter/tools/font_subset/BUILD.gn index 37c3719d..2fbeadfb 100644 --- a/engine/src/flutter/tools/font_subset/BUILD.gn +++ b/engine/src/flutter/tools/font_subset/BUILD.gn @@ -38,7 +38,8 @@ generated_file("font_entitlement_config") { zip_bundle("font_subset") { if (is_mac) { # Mac artifacts sometimes use mac and sometimes darwin. Standardizing the - # names will require changes in the list of artifacts the tool is downloading. + # names will require changes in the list of artifacts the tool is + # downloading. output = "darwin-${target_cpu}/font-subset.zip" } else { output = "${full_target_platform_name}/font-subset.zip" @@ -56,9 +57,7 @@ zip_bundle("font_subset") { }, ] - deps = [ - ":_font-subset", - ] + deps = [ ":_font-subset" ] if (is_mac) { deps += [ ":font_entitlement_config" ] files += [ diff --git a/engine/src/flutter/tools/fuchsia/dart/dart_library.gni b/engine/src/flutter/tools/fuchsia/dart/dart_library.gni index ed3ded2c..5dddf969 100644 --- a/engine/src/flutter/tools/fuchsia/dart/dart_library.gni +++ b/engine/src/flutter/tools/fuchsia/dart/dart_library.gni @@ -212,16 +212,19 @@ if (current_toolchain == dart_toolchain) { # that data. We also expose this in the group target below so that users of # the dart_package_config target can just add the targets to the deps list. _publish_metadata_target_name = "${target_name}_package_metadata" + group(_publish_metadata_target_name) { metadata = _metadata } _dart_package_config_target_name = "${target_name}_dart_package" _packages_path = "$target_gen_dir/${target_name}_package_config.json" + dart_package_config(_dart_package_config_target_name) { # Do not publish the metadata to the dart_package_config json file if the - # disable_metadata_entry flag is enabled in the dart_tool. The reason this is here - # is to avoid entries that may have identical rootUris as fxb/58781 has highlighted. + # disable_metadata_entry flag is enabled in the dart_tool. The reason this + # is here is to avoid entries that may have identical rootUris as + # fxb/58781 has highlighted. deps = _dart_deps if (!defined(invoker.disable_metadata_entry) || !invoker.disable_metadata_entry) { @@ -244,6 +247,7 @@ if (current_toolchain == dart_toolchain) { # Also warn if nonexistent files are included in sources. if (!disable_source_verification) { source_verification_target_name = "${target_name}_source_verification" + action(source_verification_target_name) { script = "//flutter/tools/fuchsia/dart/verify_sources.py" output_file = "$target_gen_dir/$target_name.missing" @@ -271,6 +275,7 @@ if (current_toolchain == dart_toolchain) { _all_deps_sources_list_target = "${target_name}.all_deps_sources.list" _all_deps_sources_list_file = "${target_gen_dir}/${target_name}.all_deps_sources.list" + generated_file(_all_deps_sources_list_target) { forward_variables_from(invoker, [ "testonly" ]) outputs = [ _all_deps_sources_list_file ] @@ -289,6 +294,7 @@ if (current_toolchain == dart_toolchain) { # analyzer, which recursively reads all sources. _all_deps_sources_target = "${target_name}.all_deps_sources" _all_deps_sources_file = "${target_gen_dir}/${target_name}.all_deps_sources" + action(_all_deps_sources_target) { forward_variables_from(invoker, [ "testonly" ]) diff --git a/engine/src/flutter/tools/fuchsia/dart/dart_tool.gni b/engine/src/flutter/tools/fuchsia/dart/dart_tool.gni index 2aa900d9..88ea5d55 100644 --- a/engine/src/flutter/tools/fuchsia/dart/dart_tool.gni +++ b/engine/src/flutter/tools/fuchsia/dart/dart_tool.gni @@ -96,6 +96,7 @@ template("_dart_snapshot_invocation") { template("dart_prebuilt_tool") { assert(defined(invoker.snapshot), "Must specify the path to the dart snapshot") + _dart_snapshot_invocation(target_name) { dart = prebuilt_dart forward_variables_from(invoker, "*") diff --git a/engine/src/flutter/tools/fuchsia/dart/kernel/dart_kernel.gni b/engine/src/flutter/tools/fuchsia/dart/kernel/dart_kernel.gni index 6053eb5f..35abcc61 100644 --- a/engine/src/flutter/tools/fuchsia/dart/kernel/dart_kernel.gni +++ b/engine/src/flutter/tools/fuchsia/dart/kernel/dart_kernel.gni @@ -174,6 +174,7 @@ template("dart_kernel") { _kernel_manifest = "$target_gen_dir/${target_name}.dilpmanifest" _convert_target_name = "${target_name}_convert_kernel_manifest" + _convert_kernel_manifest(_convert_target_name) { forward_variables_from(invoker, [ @@ -233,7 +234,8 @@ template("dart_kernel") { # Explicit output when using --manifest. _kernel_manifest, - # Implicit output when using --manifest; see createManifest in compiler.dart. + # Implicit output when using --manifest; see createManifest in + # compiler.dart. _kernel_manifest + ".dilplist", _kernel_manifest + ".frameworkversion", ] diff --git a/engine/src/flutter/tools/fuchsia/flutter/flutter_build_config.gni b/engine/src/flutter/tools/fuchsia/flutter/flutter_build_config.gni index a322a7e2..9c76483b 100644 --- a/engine/src/flutter/tools/fuchsia/flutter/flutter_build_config.gni +++ b/engine/src/flutter/tools/fuchsia/flutter/flutter_build_config.gni @@ -4,8 +4,8 @@ import("//flutter/common/config.gni") -# Non-product JIT is "debug". It launches the vm service. -# Non-product AOT is "profile". It also launches the vm service, but lacks tools that rely on JIT. +# Non-product JIT is "debug". It launches the vm service. Non-product AOT is +# "profile". It also launches the vm service, but lacks tools that rely on JIT. # Product JIT is "release". It doesn't launch the vm service. # Product AOT is "release". It doesn't launch the vm service. diff --git a/engine/src/flutter/tools/fuchsia/flutter/internal/flutter_dart_component.gni b/engine/src/flutter/tools/fuchsia/flutter/internal/flutter_dart_component.gni index 72cd952b..c0b0fcec 100644 --- a/engine/src/flutter/tools/fuchsia/flutter/internal/flutter_dart_component.gni +++ b/engine/src/flutter/tools/fuchsia/flutter/internal/flutter_dart_component.gni @@ -112,6 +112,7 @@ template("flutter_dart_component") { } _dart_package_config_target_name = "${target_name}_dart_package" + dart_package_config(_dart_package_config_target_name) { forward_variables_from(invoker, [ @@ -205,8 +206,8 @@ template("flutter_dart_component") { # Get the path to the executable. Currently, this assumes that the tool # does not specify output_name so that the target name is the name to use. # If that's not the case, we'll need another argument to the script to - # specify this, since we can't know what the output name is (it might be in - # another file not processed yet). + # specify this, since we can't know what the output name is (it might be + # in another file not processed yet). host_executable = get_label_info(host_tool, "root_out_dir") + "/" + get_label_info(host_tool, "name") + host_executable_suffix @@ -259,8 +260,8 @@ template("flutter_dart_component") { _convert_kernel_target_name = "${_kernel_target_name}_convert_kernel_manifest" _convert_kernel_manifest_file = - # TODO(richkadel): This is prefixed by "dartlang/", which is not found. - # Is the current toolchain set incorrectly somewhere? + # TODO(richkadel): This is prefixed by "dartlang/", which is not + # found. Is the current toolchain set incorrectly somewhere? string_replace( "${target_gen_dir}/${_convert_kernel_target_name}_kernel_manifest.json", "dartlang/", diff --git a/engine/src/flutter/tools/fuchsia/fuchsia_archive.gni b/engine/src/flutter/tools/fuchsia/fuchsia_archive.gni index 911c30ac..c6eb067f 100644 --- a/engine/src/flutter/tools/fuchsia/fuchsia_archive.gni +++ b/engine/src/flutter/tools/fuchsia/fuchsia_archive.gni @@ -40,6 +40,7 @@ template("fuchsia_archive") { } _component_target = target_name + "__component" + fuchsia_component(_component_target) { forward_variables_from(invoker, [ @@ -85,6 +86,7 @@ template("fuchsia_archive") { _package_target = target_name + "__package" _package_name = target_name + fuchsia_package(_package_target) { forward_variables_from(invoker, [ "testonly" ]) package_name = _package_name @@ -94,6 +96,7 @@ template("fuchsia_archive") { # TODO(zijiehe): http://crbug.com/368608542, prefer using # gn-sdk/build_id_dir.gni _build_id_target = target_name + "__build_id" + fuchsia_debug_symbols(_build_id_target) { forward_variables_from(invoker, [ @@ -136,6 +139,7 @@ template("fuchsia_test_archive") { if (defined(invoker.gen_cml_file) && invoker.gen_cml_file) { _cml_file = "$root_out_dir/${target_name}.cml" _interpolate_cml_target = "${target_name}_interpolate_cml" + action(_interpolate_cml_target) { testonly = true script = "//flutter/tools/fuchsia/interpolate_test_suite.py" diff --git a/engine/src/flutter/tools/fuchsia/fuchsia_libs.gni b/engine/src/flutter/tools/fuchsia/fuchsia_libs.gni index e2c3aa85..a226f3b6 100644 --- a/engine/src/flutter/tools/fuchsia/fuchsia_libs.gni +++ b/engine/src/flutter/tools/fuchsia/fuchsia_libs.gni @@ -88,9 +88,10 @@ if (is_asan) { vulkan_dist = "$fuchsia_sdk_path/arch/$target_cpu/dist" -# Note that the other validation libraries in the Fuchsia SDK seem to have a bug right -# now causing crashes, so it is only recommended that we use -# VkLayer_khronos_validation.so until we have a confirmation that they are fixed. +# Note that the other validation libraries in the Fuchsia SDK seem to have a bug +# right now causing crashes, so it is only recommended that we use +# VkLayer_khronos_validation.so until we have a confirmation that they are +# fixed. vulkan_validation_libs = [ { name = "VkLayer_khronos_validation.so" diff --git a/engine/src/flutter/tools/fuchsia/toolchain/basic_toolchain.gni b/engine/src/flutter/tools/fuchsia/toolchain/basic_toolchain.gni index 5dd4636b..fe418754 100644 --- a/engine/src/flutter/tools/fuchsia/toolchain/basic_toolchain.gni +++ b/engine/src/flutter/tools/fuchsia/toolchain/basic_toolchain.gni @@ -37,6 +37,7 @@ template("basic_toolchain") { command = stamp_command description = stamp_description } + tool("copy") { command = copy_command description = copy_description diff --git a/engine/src/flutter/tools/pkg/github_workflow_generator/lib/github_workflow_generator.dart b/engine/src/flutter/tools/pkg/github_workflow_generator/lib/github_workflow_generator.dart index 08d9f6f1..463cb37c 100644 --- a/engine/src/flutter/tools/pkg/github_workflow_generator/lib/github_workflow_generator.dart +++ b/engine/src/flutter/tools/pkg/github_workflow_generator/lib/github_workflow_generator.dart @@ -274,11 +274,9 @@ class BuildConfigWriter { required BuilderConfig config, required YamlWriterSection jobsSections, required ArtifactPublisher artifactPublisher, - required Set testBuildOutputs, }) : _config = config, _jobsSections = jobsSections, - _artifactPublisher = artifactPublisher, - _testBuildOutputs = testBuildOutputs; + _artifactPublisher = artifactPublisher; void write() { for (final build in _config.builds) { @@ -327,9 +325,8 @@ class BuildConfigWriter { for (final generator in build.generators) { _writeBuildTask(steps, generator); } - // Full build outputs are needed only by global packaging or test jobs. - if (_config.generators.isNotEmpty || _config.archives.isNotEmpty || - _testBuildOutputs.contains(_nameForBuild(build))) { + // Always upload the full build output. The artifact test jobs extract + // these tars and run tests against them without rebuilding. { final step = steps.beginMap('name', 'Tar build files'); final run = step.beginMap('run', '|'); @@ -350,7 +347,6 @@ class BuildConfigWriter { w.write('path', '${_nameForBuild(build)}.tar'); w.write('retention-days', '1'); } - } for (final archive in build.archives) { for (final assetPath in archive.includePaths) { if (!assetPath.startsWith(archive.basePath)) { @@ -571,7 +567,6 @@ class BuildConfigWriter { final BuilderConfig _config; final YamlWriterSection _jobsSections; final ArtifactPublisher _artifactPublisher; - final Set _testBuildOutputs; } /// A single test run inside an artifact test job. @@ -580,6 +575,7 @@ class _ArtifactTest { required this.name, required this.variant, required this.types, + this.dartSdk, this.androidVariant, this.iosVariant, }); @@ -588,6 +584,10 @@ class _ArtifactTest { final String variant; final String types; + /// Name of a prebuilt dart SDK directory under `flutter/prebuilts/`, copied + /// to `out//dart-sdk` so that dart tests can run. + final String? dartSdk; + final String? androidVariant; final String? iosVariant; } @@ -622,12 +622,14 @@ class _ArtifactTestJob { static _ArtifactTest _testFromJson(Map map) { final variant = map['variant']! as String; final types = map['types']! as String; + final dartSdk = map['dart_sdk'] as String?; final androidVariant = map['android_variant'] as String?; final iosVariant = map['ios_variant'] as String?; return _ArtifactTest( name: (map['name'] as String?) ?? 'for $variant', variant: variant, types: types, + dartSdk: dartSdk, androidVariant: androidVariant, iosVariant: iosVariant, ); @@ -694,7 +696,16 @@ void _writeDepotToolsStep( /// Emits jobs that run tests against build outputs uploaded by the /// artifact-producing build jobs (no rebuilding). The job specs come from the /// JSON files passed via `--artifact-tests`. -List<_ArtifactTestJob> _readArtifactTestJobs(List specFiles) { +void _writeArtifactTestJobs( + YamlWriterSection jobsSection, + ArtifactPublisher artifactPublisher, + List specFiles, +) { + const gclientFileFor = { + 'slim': 'slim.gclient', + 'standard': 'standard.gclient', + 'web': 'web.gclient', + }; final jobs = <_ArtifactTestJob>[]; for (final specFile in specFiles) { final content = File(specFile).readAsStringSync(); @@ -705,19 +716,6 @@ List<_ArtifactTestJob> _readArtifactTestJobs(List specFiles) { } jobs.addAll(jobMaps.map(_ArtifactTestJob.fromJson)); } - return jobs; -} - -void _writeArtifactTestJobs( - YamlWriterSection jobsSection, - ArtifactPublisher artifactPublisher, - List<_ArtifactTestJob> jobs, -) { - const gclientFileFor = { - 'slim': 'slim.gclient', - 'standard': 'standard.gclient', - 'web': 'web.gclient', - }; for (final job in jobs) { final generated = jobsSection.beginMap(job.name); generated.write('runs-on', job.runsOn); @@ -735,6 +733,12 @@ void _writeArtifactTestJobs( final w = step.beginMap('with'); w.write('path', "''"); } + { + final step = steps.beginMap('name', 'Checkout the repository'); + step.write('uses', 'actions/checkout@v4'); + final w = step.beginMap('with'); + w.write('path', "''"); + } { _writeDepotToolsStep(steps, isWindows: job.runsOn.startsWith('windows')); } @@ -746,7 +750,7 @@ void _writeArtifactTestJobs( run.writeln(r'echo "value=${engine_content_hash}" >> $GITHUB_OUTPUT'); } { - final step = steps.beginMap('name', 'Copy gclient file'); + final step = steps.beginMap('name', 'Copy g lient file'); final run = step.beginMap('run', '|'); final gclientFile = gclientFileFor[job.gclient]; if (gclientFile == null) { @@ -774,6 +778,12 @@ void _writeArtifactTestJobs( } } for (final test in job.tests) { + if (test.dartSdk != null) { + final step = steps.beginMap('name', 'Copy prebuilt dart sdk'); + final run = step.beginMap('run', '|'); + run.writeln('cd engine/src'); + run.writeln('cp -r flutter/prebuilts/${test.dartSdk}/dart-sdk out/${test.variant}/dart-sdk'); + } final step = steps.beginMap('name', 'Run test ${test.name}'); final run = step.beginMap('run', '|'); run.writeln('cd engine/src'); @@ -943,8 +953,6 @@ void main(List arguments) { final yamlWriter = YamlWriter(); final artifactTestSpecs = (args['artifact-tests'] as List?) ?? const []; - final artifactTestJobs = _readArtifactTestJobs(artifactTestSpecs); - final testBuildOutputs = artifactTestJobs.expand((job) => job.downloads).toSet(); final root = yamlWriter.root; root.writeln('# This file is generated through `scripts/update_github_workflow.sh.`'); root.writeln('# Do not edit directly.'); @@ -974,12 +982,11 @@ void main(List arguments) { config: buildConfig, jobsSections: jobs, artifactPublisher: artifactPublisher, - testBuildOutputs: testBuildOutputs, ); writer.write(); } - _writeArtifactTestJobs(jobs, artifactPublisher, artifactTestJobs); + _writeArtifactTestJobs(jobs, artifactPublisher, artifactTestSpecs); artifactPublisher.writePublishJob(jobs); _writeSmokeTestInvocationJob(jobs); diff --git a/engine/src/flutter/web_sdk/BUILD.gn b/engine/src/flutter/web_sdk/BUILD.gn index d47a75d1..a137941a 100644 --- a/engine/src/flutter/web_sdk/BUILD.gn +++ b/engine/src/flutter/web_sdk/BUILD.gn @@ -34,7 +34,8 @@ sdk_rewriter("web_ui_library_sources") { input_dir = "//flutter/lib/web_ui/lib/" output_dir = "$root_out_dir/flutter_web_sdk/lib/ui/" - # exclude everything in the engine directory, it will be a separate internal library + # exclude everything in the engine directory, it will be a separate internal + # library exclude_pattern = rebase_path("//flutter/lib/web_ui/lib/src") } @@ -166,6 +167,7 @@ template("_compile_platform") { "summary_only must be defined for $target_name") assert(defined(invoker.output_dill), "output_dill must be defined for $target_name") + _kernel_worker(target_name) { inputs = [ "sdk_rewriter.dart" ] + web_ui_sources @@ -314,8 +316,8 @@ template("_compile_ddc_modules") { forward_variables_from(invoker, "*") # We compile multiple times instead of passing multiple modules to a single - # compile as the DDC library bundle flutter_platform_dillsformat cannot be used when passing - # multiple module formats as arguments. + # compile as the DDC library bundle flutter_platform_dillsformat cannot be + # used when passing multiple module formats as arguments. _compile_ddc_module("${target_name}_amd") { sdk_path_prefix = "amd" module_format = "amd" diff --git a/engine/src/flutter/web_sdk/sdk_rewriter.dart b/engine/src/flutter/web_sdk/sdk_rewriter.dart index ff13d700..824d253a 100644 --- a/engine/src/flutter/web_sdk/sdk_rewriter.dart +++ b/engine/src/flutter/web_sdk/sdk_rewriter.dart @@ -141,9 +141,8 @@ void main(List arguments) { } final inputFiles = []; - final List entries = Directory( - inputDirectoryPath, - ).listSync(recursive: true, followLinks: false); + final List entries = Directory(inputDirectoryPath) + .listSync(recursive: true, followLinks: false); for (final File inputFile in entries.whereType()) { if (excludePattern != null && inputFile.path.startsWith(excludePattern)) { continue; diff --git a/engine/src/flutter/web_sdk/test/sdk_rewriter_test.dart b/engine/src/flutter/web_sdk/test/sdk_rewriter_test.dart index 98854957..79cc298f 100644 --- a/engine/src/flutter/web_sdk/test/sdk_rewriter_test.dart +++ b/engine/src/flutter/web_sdk/test/sdk_rewriter_test.dart @@ -153,9 +153,7 @@ void printSomething() { test('gets correct extra imports', () { // Root libraries. - expect(getExtraImportsForLibrary('engine'), [ - "import 'dart:ui_web' as ui_web;", - ]); + expect(getExtraImportsForLibrary('engine'), ["import 'dart:ui_web' as ui_web;"]); expect(getExtraImportsForLibrary('skwasm_stub'), [ "import 'dart:ui_web' as ui_web;", "import 'dart:_engine';", diff --git a/engine/src/flutter/web_sdk/web_test_utils/lib/environment.dart b/engine/src/flutter/web_sdk/web_test_utils/lib/environment.dart index 7093c8e0..c56540c3 100644 --- a/engine/src/flutter/web_sdk/web_test_utils/lib/environment.dart +++ b/engine/src/flutter/web_sdk/web_test_utils/lib/environment.dart @@ -3,6 +3,7 @@ // found in the LICENSE file. import 'dart:io' as io; + import 'package:path/path.dart' as pathlib; /// Contains various environment variables, such as common file paths and command-line options. From 4407b3f033e919ff78e37b54f2d524f12a8b548b Mon Sep 17 00:00:00 2001 From: Matej Knopp Date: Fri, 16 Oct 2026 20:54:37 +0200 Subject: [PATCH 6/6] Fix android test_runner. --- .../shell/platform/android/build.gradle | 2 +- .../platform/android/test_runner/build.gradle | 38 +++++++++++++++++-- 2 files changed, 35 insertions(+), 5 deletions(-) diff --git a/engine/src/flutter/shell/platform/android/build.gradle b/engine/src/flutter/shell/platform/android/build.gradle index 9a2fe44c..3da700a0 100644 --- a/engine/src/flutter/shell/platform/android/build.gradle +++ b/engine/src/flutter/shell/platform/android/build.gradle @@ -55,7 +55,7 @@ android { implementation "androidx.test:core:1.4.0" implementation "com.google.android.play:core:1.8.0" implementation "com.ibm.icu:icu4j:69.1" - implementation "org.robolectric:robolectric:4.16" + implementation "org.robolectric:robolectric:4.17" implementation "junit:junit:4.13.2" implementation "androidx.test.ext:junit:1.1.4-alpha07" diff --git a/engine/src/flutter/shell/platform/android/test_runner/build.gradle b/engine/src/flutter/shell/platform/android/test_runner/build.gradle index 7d968fc5..1c503404 100644 --- a/engine/src/flutter/shell/platform/android/test_runner/build.gradle +++ b/engine/src/flutter/shell/platform/android/test_runner/build.gradle @@ -4,7 +4,7 @@ buildscript { mavenCentral() } dependencies { - classpath "com.android.tools.build:gradle:8.9.1" + classpath "com.android.tools.build:gradle:9.3.1" } } @@ -15,6 +15,10 @@ repositories { apply plugin: "com.android.library" +configurations { + mockitoAgent +} + rootProject.buildDir = project.property("build_dir") // Shows warnings for usage of deprecated API usages. @@ -33,7 +37,7 @@ println "==========================================" android { namespace 'io.flutter.app.test' - compileSdk = 36 + compileSdk = 37 defaultConfig { minSdk = 24 @@ -51,6 +55,27 @@ android { unitTests.all { jvmArgs "-Xmx8g" // Max JVM heap size is 8G/30G available in the CI bot. + // Recommended flag set starting Robolectric 4.17 for JDK 17+, see + // https://robolectric.org/getting-started/#running-with-java-17-and-higher + jvmArgs "--add-opens=java.base/java.lang=ALL-UNNAMED", + "--add-opens=java.base/java.util=ALL-UNNAMED", + "--add-opens=java.base/java.io=ALL-UNNAMED", + "--add-opens=java.base/java.net=ALL-UNNAMED", + "--add-opens=java.base/java.security=ALL-UNNAMED", + "--add-opens=java.base/java.text=ALL-UNNAMED", + "--add-opens=java.base/jdk.internal.access=ALL-UNNAMED", + "--add-opens=java.desktop/java.awt.font=ALL-UNNAMED", + "--add-opens=jdk.compiler/com.sun.tools.javac.api=ALL-UNNAMED" + jvmArgumentProviders.add(new CommandLineArgumentProvider() { + @InputFiles + @Classpath + def agentFiles = configurations.mockitoAgent + + @Override + Iterable asArguments() { + return ["-javaagent:${agentFiles.asPath}"] + } + }) maxHeapSize "8g" maxParallelForks availableProcessors // The CI bot has 8 CPUs. testLogging { @@ -72,11 +97,16 @@ android { //noinspection RiskyLibrary,PlaySdkIndexDeprecated testImplementation "com.google.android.play:core:1.8.0" testImplementation "com.ibm.icu:icu4j:75.1" - testImplementation "org.robolectric:robolectric:4.16" + testImplementation "org.robolectric:robolectric:4.17" testImplementation "junit:junit:4.13.2" testImplementation "androidx.test.ext:junit:1.2.1" - testImplementation "org.mockito:mockito-core:5.17.0" + // Mockito >= 5.20.0 (Byte Buddy >= 1.17.7) is required to run on JDK 25. + def mockitoVersion = "5.20.0" + testImplementation "org.mockito:mockito-core:$mockitoVersion" + mockitoAgent("org.mockito:mockito-core:$mockitoVersion") { + transitive = false + } } // Configure the embedding dependencies.