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/DEPS b/DEPS index aea8df8f..8d5494bb 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': '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': '7515be5ccd601ae0433d3682ba7737592b402014', - 'dart_core_rev': 'fe516ee1b38cc60e7a8c6e082c337037a043d782', - 'dart_devtools_rev': '21f1838f3a9b138ac377efb953ca5a53c8832e75', - 'dart_ecosystem_rev': 'edfdb3b4063b9034b708144633a700204f865f43', - 'dart_http_rev': '5d94ef52582867e077bf41c3fa20fb8b1d1d834e', - 'dart_i18n_rev': 'e1b5a798f8922bb27bbc6d858748ece6f9a19f02', + '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': '91efb90f437bb6a30e6726c3369a2fcb9bba06e7', - 'dart_pub_rev': 'ec276d10a7fa0f6c6ec005340fb9ad29f3b012d0', + 'dart_protobuf_rev': 'a73edc98c98fb25152aa3f12c1b9db91594c1369', + 'dart_pub_rev': 'eca8f8ada939be70f0be3189db31e421dd0be7fd', 'dart_sync_http_rev': '6666fff944221891182e1f80bf56569338164d72', - 'dart_tools_rev': 'b827a6e38b934232c7f7b8728a5aef6165e7df2d', + 'dart_tools_rev': '350bde54f8f1a8f49cf2ed520b8999afde02e25a', 'dart_vector_math_rev': 'cf3b5db7340d317dd3489e5a35434b408020a852', - 'dart_web_rev': '12a9ca2ebc08f5a6f2d69aebc7daa1f5a2e6a431', - 'dart_webdriver_rev': '3a711ebb36871eac997c5d5d2429f7414873dc63', + 'dart_web_rev': '63e6662dc7022a54439d4da6016685c49a0d6018', + 'dart_webdriver_rev': '8e5c611ea242efdc9f597a8a37c38a9c586120ee', 'dart_webkit_inspection_protocol_rev': '762115a971d1968bc940454ad1e88d506d8c5640', 'ocmock_rev': 'c4ec0e3a7a9f56cfdbd0aa01f4f97bb4b75c5ef8', # v3.7.1 @@ -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': 'vcANVO8VIDQHasH1X_XRoSYLvx7fNwvTbDM1NT9TwA4C', + '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': 'a87CbQSWEjkPUK1ZY_zsy8aZ9W-3Z2v73ohzhrWbDQ4C', + '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' + '@' + 'd578f2e8b7bd5938e21cfb6bf15c079e0aa5b738', + 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:21f1838f3a9b138ac377efb953ca5a53c8832e75'}]}, + {'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@dfdf6420c7ea923d28edef3f11e89b4ff23d03bf', + Var('dart_git') + '/dart_style.git@76978d23bfb3d225c81ce3f119ab7055a2a57136', 'engine/src/flutter/third_party/dart/third_party/pkg/dartdoc': - Var('dart_git') + '/dartdoc.git@ac96918074974dcd4ea20f764f17090f58c1e428', + 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@046f63d1d89cd9954623bfa2df9c69d1a395375e', + 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@6918a7690946044b4098e9f6735439044c676e13', + 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@bd92e633e7f05edc3301865bdc00d1ae181cb1f1', + 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'), @@ -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' } ], @@ -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', @@ -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': 'QdgqP02_cYpRQQQNNuRjshiknJeDe5ZKXyqGq2YkqKkC' } ], 'condition': 'download_fuchsia_deps and not download_fuchsia_sdk', 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/BUILD.gn b/engine/src/flutter/BUILD.gn index 325fa4c4..8cf0d534 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", ] @@ -196,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 @@ -263,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/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/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 a625cc38..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. @@ -18,6 +21,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/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/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/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/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/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/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. 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 96cfc2d0..173ddd39 100644 --- a/engine/src/flutter/shell/platform/darwin/macos/BUILD.gn +++ b/engine/src/flutter/shell/platform/darwin/macos/BUILD.gn @@ -111,18 +111,26 @@ 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 +139,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/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/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/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 602c59c9..d9e7b4b3 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,15 +440,12 @@ 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'), ] @@ -459,62 +453,24 @@ def make_test(name, flags=None, extra_env=None): # 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'), ] - 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,63 +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): @@ -598,13 +503,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 +652,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) @@ -982,7 +890,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/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/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..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" @@ -54,16 +55,9 @@ 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", - ] + 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/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/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..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 @@ -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); @@ -229,25 +305,47 @@ 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'); - } + // 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', '|'); + // 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 +426,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 +445,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 +457,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 +486,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 { @@ -473,6 +569,300 @@ class BuildConfigWriter { final ArtifactPublisher _artifactPublisher; } +/// A single test run inside an artifact test job. +class _ArtifactTest { + const _ArtifactTest({ + required this.name, + required this.variant, + required this.types, + this.dartSdk, + this.androidVariant, + this.iosVariant, + }); + + final String name; + 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; +} + +/// 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 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, + ); + } + + 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`. +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(); + 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)); + } + 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', "''"); + } + { + 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 g lient 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) { + 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'); + 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 +928,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 +952,7 @@ void main(List arguments) { } final yamlWriter = YamlWriter(); + final artifactTestSpecs = (args['artifact-tests'] as List?) ?? const []; final root = yamlWriter.root; root.writeln('# This file is generated through `scripts/update_github_workflow.sh.`'); root.writeln('# Do not edit directly.'); @@ -562,12 +960,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'); @@ -588,7 +986,14 @@ void main(List arguments) { writer.write(); } + _writeArtifactTestJobs(jobs, artifactPublisher, artifactTestSpecs); + 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/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'), 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. 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 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"