diff --git a/.github/workflows/build-and-upload-engine-artifacts.yml b/.github/workflows/build-and-upload-engine-artifacts.yml index 31bd5950..6517b00b 100644 --- a/.github/workflows/build-and-upload-engine-artifacts.yml +++ b/.github/workflows/build-and-upload-engine-artifacts.yml @@ -3,11 +3,11 @@ name: Engine Artifacts on: push: - branches: ["master", "staging"] + branches: ["staging"] + pull_request: env: DEPOT_TOOLS_WIN_TOOLCHAIN: 0 FLUTTER_PREBUILT_DART_SDK: 1 - R2_BUCKET: flutter-zero-engine ENGINE_CHECKOUT_PATH: ${{ github.workspace }}/engine jobs: guard: @@ -62,7 +62,14 @@ jobs: - name: Set up depot_tools if: runner.os != 'Windows' run: | - git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git $HOME/depot_tools + rm -rf "$HOME/depot_tools" + for attempt in 1 2 3; do + git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git "$HOME/depot_tools" && break + rm -rf "$HOME/depot_tools" + echo "depot_tools clone failed (attempt $attempt), retrying..." + sleep 5 + done + test -d "$HOME/depot_tools/.git" # Append depot_tools to the PATH for subsequent steps echo "$HOME/depot_tools" >> $GITHUB_PATH - name: Free disk space @@ -71,7 +78,14 @@ jobs: - name: Set up depot_tools if: runner.os == 'Windows' run: | - git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git $HOME/depot_tools + rm -rf "$HOME/depot_tools" + for attempt in 1 2 3; do + git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git "$HOME/depot_tools" && break + rm -rf "$HOME/depot_tools" + echo "depot_tools clone failed (attempt $attempt), retrying..." + sleep 5 + done + test -d "$HOME/depot_tools/.git" # Append depot_tools to the PATH for subsequent steps DEPOT_TOOLS_WIN=$(cygpath -w "$HOME/depot_tools") echo "$DEPOT_TOOLS_WIN" >> $GITHUB_PATH @@ -92,6 +106,7 @@ jobs: ./flutter/bin/et build --config ci/host_debug_framework - name: Tar build files run: | + find engine/src/out/ci/host_debug_framework -type l -lname "/*" -delete || true tar -cvf mac_host_debug_framework.tar engine/src/out/ci/host_debug_framework - name: Upload build files uses: actions/upload-artifact@v4 @@ -115,7 +130,14 @@ jobs: - name: Set up depot_tools if: runner.os != 'Windows' run: | - git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git $HOME/depot_tools + rm -rf "$HOME/depot_tools" + for attempt in 1 2 3; do + git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git "$HOME/depot_tools" && break + rm -rf "$HOME/depot_tools" + echo "depot_tools clone failed (attempt $attempt), retrying..." + sleep 5 + done + test -d "$HOME/depot_tools/.git" # Append depot_tools to the PATH for subsequent steps echo "$HOME/depot_tools" >> $GITHUB_PATH - name: Free disk space @@ -124,7 +146,14 @@ jobs: - name: Set up depot_tools if: runner.os == 'Windows' run: | - git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git $HOME/depot_tools + rm -rf "$HOME/depot_tools" + for attempt in 1 2 3; do + git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git "$HOME/depot_tools" && break + rm -rf "$HOME/depot_tools" + echo "depot_tools clone failed (attempt $attempt), retrying..." + sleep 5 + done + test -d "$HOME/depot_tools/.git" # Append depot_tools to the PATH for subsequent steps DEPOT_TOOLS_WIN=$(cygpath -w "$HOME/depot_tools") echo "$DEPOT_TOOLS_WIN" >> $GITHUB_PATH @@ -143,8 +172,16 @@ jobs: run: | cd engine/src ./flutter/bin/et build --config ci/host_debug + - name: Run engine unit tests + run: | + cd engine/src + python3 flutter/testing/run_tests.py \ + --variant ci/host_debug \ + --type engine \ + --engine-capture-core-dump - name: Tar build files run: | + find engine/src/out/ci/host_debug -type l -lname "/*" -delete || true tar -cvf mac_host_debug.tar engine/src/out/ci/host_debug - name: Upload build files uses: actions/upload-artifact@v4 @@ -188,7 +225,14 @@ jobs: - name: Set up depot_tools if: runner.os != 'Windows' run: | - git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git $HOME/depot_tools + rm -rf "$HOME/depot_tools" + for attempt in 1 2 3; do + git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git "$HOME/depot_tools" && break + rm -rf "$HOME/depot_tools" + echo "depot_tools clone failed (attempt $attempt), retrying..." + sleep 5 + done + test -d "$HOME/depot_tools/.git" # Append depot_tools to the PATH for subsequent steps echo "$HOME/depot_tools" >> $GITHUB_PATH - name: Free disk space @@ -197,7 +241,14 @@ jobs: - name: Set up depot_tools if: runner.os == 'Windows' run: | - git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git $HOME/depot_tools + rm -rf "$HOME/depot_tools" + for attempt in 1 2 3; do + git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git "$HOME/depot_tools" && break + rm -rf "$HOME/depot_tools" + echo "depot_tools clone failed (attempt $attempt), retrying..." + sleep 5 + done + test -d "$HOME/depot_tools/.git" # Append depot_tools to the PATH for subsequent steps DEPOT_TOOLS_WIN=$(cygpath -w "$HOME/depot_tools") echo "$DEPOT_TOOLS_WIN" >> $GITHUB_PATH @@ -218,6 +269,7 @@ jobs: ./flutter/bin/et build --config ci/host_debug_gen_snapshot - name: Tar build files run: | + find engine/src/out/ci/host_debug_gen_snapshot -type l -lname "/*" -delete || true tar -cvf mac_host_debug_gen_snapshot.tar engine/src/out/ci/host_debug_gen_snapshot - name: Upload build files uses: actions/upload-artifact@v4 @@ -241,7 +293,14 @@ jobs: - name: Set up depot_tools if: runner.os != 'Windows' run: | - git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git $HOME/depot_tools + rm -rf "$HOME/depot_tools" + for attempt in 1 2 3; do + git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git "$HOME/depot_tools" && break + rm -rf "$HOME/depot_tools" + echo "depot_tools clone failed (attempt $attempt), retrying..." + sleep 5 + done + test -d "$HOME/depot_tools/.git" # Append depot_tools to the PATH for subsequent steps echo "$HOME/depot_tools" >> $GITHUB_PATH - name: Free disk space @@ -250,7 +309,14 @@ jobs: - name: Set up depot_tools if: runner.os == 'Windows' run: | - git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git $HOME/depot_tools + rm -rf "$HOME/depot_tools" + for attempt in 1 2 3; do + git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git "$HOME/depot_tools" && break + rm -rf "$HOME/depot_tools" + echo "depot_tools clone failed (attempt $attempt), retrying..." + sleep 5 + done + test -d "$HOME/depot_tools/.git" # Append depot_tools to the PATH for subsequent steps DEPOT_TOOLS_WIN=$(cygpath -w "$HOME/depot_tools") echo "$DEPOT_TOOLS_WIN" >> $GITHUB_PATH @@ -269,8 +335,16 @@ jobs: run: | cd engine/src ./flutter/bin/et build --config ci/host_profile + - name: Run engine unit tests + run: | + cd engine/src + python3 flutter/testing/run_tests.py \ + --variant ci/host_profile \ + --type engine \ + --engine-capture-core-dump - name: Tar build files run: | + find engine/src/out/ci/host_profile -type l -lname "/*" -delete || true tar -cvf mac_host_profile.tar engine/src/out/ci/host_profile - name: Upload build files uses: actions/upload-artifact@v4 @@ -304,7 +378,14 @@ jobs: - name: Set up depot_tools if: runner.os != 'Windows' run: | - git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git $HOME/depot_tools + rm -rf "$HOME/depot_tools" + for attempt in 1 2 3; do + git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git "$HOME/depot_tools" && break + rm -rf "$HOME/depot_tools" + echo "depot_tools clone failed (attempt $attempt), retrying..." + sleep 5 + done + test -d "$HOME/depot_tools/.git" # Append depot_tools to the PATH for subsequent steps echo "$HOME/depot_tools" >> $GITHUB_PATH - name: Free disk space @@ -313,7 +394,14 @@ jobs: - name: Set up depot_tools if: runner.os == 'Windows' run: | - git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git $HOME/depot_tools + rm -rf "$HOME/depot_tools" + for attempt in 1 2 3; do + git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git "$HOME/depot_tools" && break + rm -rf "$HOME/depot_tools" + echo "depot_tools clone failed (attempt $attempt), retrying..." + sleep 5 + done + test -d "$HOME/depot_tools/.git" # Append depot_tools to the PATH for subsequent steps DEPOT_TOOLS_WIN=$(cygpath -w "$HOME/depot_tools") echo "$DEPOT_TOOLS_WIN" >> $GITHUB_PATH @@ -334,6 +422,7 @@ jobs: ./flutter/bin/et build --config ci/host_profile_framework - name: Tar build files run: | + find engine/src/out/ci/host_profile_framework -type l -lname "/*" -delete || true tar -cvf mac_host_profile_framework.tar engine/src/out/ci/host_profile_framework - name: Upload build files uses: actions/upload-artifact@v4 @@ -357,7 +446,14 @@ jobs: - name: Set up depot_tools if: runner.os != 'Windows' run: | - git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git $HOME/depot_tools + rm -rf "$HOME/depot_tools" + for attempt in 1 2 3; do + git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git "$HOME/depot_tools" && break + rm -rf "$HOME/depot_tools" + echo "depot_tools clone failed (attempt $attempt), retrying..." + sleep 5 + done + test -d "$HOME/depot_tools/.git" # Append depot_tools to the PATH for subsequent steps echo "$HOME/depot_tools" >> $GITHUB_PATH - name: Free disk space @@ -366,7 +462,14 @@ jobs: - name: Set up depot_tools if: runner.os == 'Windows' run: | - git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git $HOME/depot_tools + rm -rf "$HOME/depot_tools" + for attempt in 1 2 3; do + git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git "$HOME/depot_tools" && break + rm -rf "$HOME/depot_tools" + echo "depot_tools clone failed (attempt $attempt), retrying..." + sleep 5 + done + test -d "$HOME/depot_tools/.git" # Append depot_tools to the PATH for subsequent steps DEPOT_TOOLS_WIN=$(cygpath -w "$HOME/depot_tools") echo "$DEPOT_TOOLS_WIN" >> $GITHUB_PATH @@ -387,6 +490,7 @@ jobs: ./flutter/bin/et build --config ci/host_profile_gen_snapshot - name: Tar build files run: | + find engine/src/out/ci/host_profile_gen_snapshot -type l -lname "/*" -delete || true tar -cvf mac_host_profile_gen_snapshot.tar engine/src/out/ci/host_profile_gen_snapshot - name: Upload build files uses: actions/upload-artifact@v4 @@ -410,7 +514,14 @@ jobs: - name: Set up depot_tools if: runner.os != 'Windows' run: | - git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git $HOME/depot_tools + rm -rf "$HOME/depot_tools" + for attempt in 1 2 3; do + git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git "$HOME/depot_tools" && break + rm -rf "$HOME/depot_tools" + echo "depot_tools clone failed (attempt $attempt), retrying..." + sleep 5 + done + test -d "$HOME/depot_tools/.git" # Append depot_tools to the PATH for subsequent steps echo "$HOME/depot_tools" >> $GITHUB_PATH - name: Free disk space @@ -419,7 +530,14 @@ jobs: - name: Set up depot_tools if: runner.os == 'Windows' run: | - git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git $HOME/depot_tools + rm -rf "$HOME/depot_tools" + for attempt in 1 2 3; do + git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git "$HOME/depot_tools" && break + rm -rf "$HOME/depot_tools" + echo "depot_tools clone failed (attempt $attempt), retrying..." + sleep 5 + done + test -d "$HOME/depot_tools/.git" # Append depot_tools to the PATH for subsequent steps DEPOT_TOOLS_WIN=$(cygpath -w "$HOME/depot_tools") echo "$DEPOT_TOOLS_WIN" >> $GITHUB_PATH @@ -438,8 +556,16 @@ jobs: run: | cd engine/src ./flutter/bin/et build --config ci/host_release + - name: Run engine unit tests + run: | + cd engine/src + python3 flutter/testing/run_tests.py \ + --variant ci/host_release \ + --type engine \ + --engine-capture-core-dump - name: Tar build files run: | + find engine/src/out/ci/host_release -type l -lname "/*" -delete || true tar -cvf mac_host_release.tar engine/src/out/ci/host_release - name: Upload build files uses: actions/upload-artifact@v4 @@ -483,7 +609,14 @@ jobs: - name: Set up depot_tools if: runner.os != 'Windows' run: | - git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git $HOME/depot_tools + rm -rf "$HOME/depot_tools" + for attempt in 1 2 3; do + git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git "$HOME/depot_tools" && break + rm -rf "$HOME/depot_tools" + echo "depot_tools clone failed (attempt $attempt), retrying..." + sleep 5 + done + test -d "$HOME/depot_tools/.git" # Append depot_tools to the PATH for subsequent steps echo "$HOME/depot_tools" >> $GITHUB_PATH - name: Free disk space @@ -492,7 +625,14 @@ jobs: - name: Set up depot_tools if: runner.os == 'Windows' run: | - git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git $HOME/depot_tools + rm -rf "$HOME/depot_tools" + for attempt in 1 2 3; do + git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git "$HOME/depot_tools" && break + rm -rf "$HOME/depot_tools" + echo "depot_tools clone failed (attempt $attempt), retrying..." + sleep 5 + done + test -d "$HOME/depot_tools/.git" # Append depot_tools to the PATH for subsequent steps DEPOT_TOOLS_WIN=$(cygpath -w "$HOME/depot_tools") echo "$DEPOT_TOOLS_WIN" >> $GITHUB_PATH @@ -513,6 +653,7 @@ jobs: ./flutter/bin/et build --config ci/host_release_framework - name: Tar build files run: | + find engine/src/out/ci/host_release_framework -type l -lname "/*" -delete || true tar -cvf mac_host_release_framework.tar engine/src/out/ci/host_release_framework - name: Upload build files uses: actions/upload-artifact@v4 @@ -536,7 +677,14 @@ jobs: - name: Set up depot_tools if: runner.os != 'Windows' run: | - git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git $HOME/depot_tools + rm -rf "$HOME/depot_tools" + for attempt in 1 2 3; do + git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git "$HOME/depot_tools" && break + rm -rf "$HOME/depot_tools" + echo "depot_tools clone failed (attempt $attempt), retrying..." + sleep 5 + done + test -d "$HOME/depot_tools/.git" # Append depot_tools to the PATH for subsequent steps echo "$HOME/depot_tools" >> $GITHUB_PATH - name: Free disk space @@ -545,7 +693,14 @@ jobs: - name: Set up depot_tools if: runner.os == 'Windows' run: | - git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git $HOME/depot_tools + rm -rf "$HOME/depot_tools" + for attempt in 1 2 3; do + git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git "$HOME/depot_tools" && break + rm -rf "$HOME/depot_tools" + echo "depot_tools clone failed (attempt $attempt), retrying..." + sleep 5 + done + test -d "$HOME/depot_tools/.git" # Append depot_tools to the PATH for subsequent steps DEPOT_TOOLS_WIN=$(cygpath -w "$HOME/depot_tools") echo "$DEPOT_TOOLS_WIN" >> $GITHUB_PATH @@ -566,6 +721,7 @@ jobs: ./flutter/bin/et build --config ci/host_release_gen_snapshot - name: Tar build files run: | + find engine/src/out/ci/host_release_gen_snapshot -type l -lname "/*" -delete || true tar -cvf mac_host_release_gen_snapshot.tar engine/src/out/ci/host_release_gen_snapshot - name: Upload build files uses: actions/upload-artifact@v4 @@ -589,7 +745,14 @@ jobs: - name: Set up depot_tools if: runner.os != 'Windows' run: | - git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git $HOME/depot_tools + rm -rf "$HOME/depot_tools" + for attempt in 1 2 3; do + git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git "$HOME/depot_tools" && break + rm -rf "$HOME/depot_tools" + echo "depot_tools clone failed (attempt $attempt), retrying..." + sleep 5 + done + test -d "$HOME/depot_tools/.git" # Append depot_tools to the PATH for subsequent steps echo "$HOME/depot_tools" >> $GITHUB_PATH - name: Free disk space @@ -598,7 +761,14 @@ jobs: - name: Set up depot_tools if: runner.os == 'Windows' run: | - git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git $HOME/depot_tools + rm -rf "$HOME/depot_tools" + for attempt in 1 2 3; do + git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git "$HOME/depot_tools" && break + rm -rf "$HOME/depot_tools" + echo "depot_tools clone failed (attempt $attempt), retrying..." + sleep 5 + done + test -d "$HOME/depot_tools/.git" # Append depot_tools to the PATH for subsequent steps DEPOT_TOOLS_WIN=$(cygpath -w "$HOME/depot_tools") echo "$DEPOT_TOOLS_WIN" >> $GITHUB_PATH @@ -617,8 +787,16 @@ jobs: run: | cd engine/src ./flutter/bin/et build --config ci/mac_debug_arm64 + - name: Run engine unit tests + run: | + cd engine/src + python3 flutter/testing/run_tests.py \ + --variant ci/mac_debug_arm64 \ + --type engine \ + --engine-capture-core-dump - name: Tar build files run: | + find engine/src/out/ci/mac_debug_arm64 -type l -lname "/*" -delete || true tar -cvf mac_debug_arm64.tar engine/src/out/ci/mac_debug_arm64 - name: Upload build files uses: actions/upload-artifact@v4 @@ -662,7 +840,14 @@ jobs: - name: Set up depot_tools if: runner.os != 'Windows' run: | - git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git $HOME/depot_tools + rm -rf "$HOME/depot_tools" + for attempt in 1 2 3; do + git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git "$HOME/depot_tools" && break + rm -rf "$HOME/depot_tools" + echo "depot_tools clone failed (attempt $attempt), retrying..." + sleep 5 + done + test -d "$HOME/depot_tools/.git" # Append depot_tools to the PATH for subsequent steps echo "$HOME/depot_tools" >> $GITHUB_PATH - name: Free disk space @@ -671,7 +856,14 @@ jobs: - name: Set up depot_tools if: runner.os == 'Windows' run: | - git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git $HOME/depot_tools + rm -rf "$HOME/depot_tools" + for attempt in 1 2 3; do + git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git "$HOME/depot_tools" && break + rm -rf "$HOME/depot_tools" + echo "depot_tools clone failed (attempt $attempt), retrying..." + sleep 5 + done + test -d "$HOME/depot_tools/.git" # Append depot_tools to the PATH for subsequent steps DEPOT_TOOLS_WIN=$(cygpath -w "$HOME/depot_tools") echo "$DEPOT_TOOLS_WIN" >> $GITHUB_PATH @@ -692,6 +884,7 @@ jobs: ./flutter/bin/et build --config ci/mac_debug_framework_arm64 - name: Tar build files run: | + find engine/src/out/ci/mac_debug_framework_arm64 -type l -lname "/*" -delete || true tar -cvf mac_debug_framework_arm64.tar engine/src/out/ci/mac_debug_framework_arm64 - name: Upload build files uses: actions/upload-artifact@v4 @@ -715,7 +908,14 @@ jobs: - name: Set up depot_tools if: runner.os != 'Windows' run: | - git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git $HOME/depot_tools + rm -rf "$HOME/depot_tools" + for attempt in 1 2 3; do + git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git "$HOME/depot_tools" && break + rm -rf "$HOME/depot_tools" + echo "depot_tools clone failed (attempt $attempt), retrying..." + sleep 5 + done + test -d "$HOME/depot_tools/.git" # Append depot_tools to the PATH for subsequent steps echo "$HOME/depot_tools" >> $GITHUB_PATH - name: Free disk space @@ -724,7 +924,14 @@ jobs: - name: Set up depot_tools if: runner.os == 'Windows' run: | - git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git $HOME/depot_tools + rm -rf "$HOME/depot_tools" + for attempt in 1 2 3; do + git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git "$HOME/depot_tools" && break + rm -rf "$HOME/depot_tools" + echo "depot_tools clone failed (attempt $attempt), retrying..." + sleep 5 + done + test -d "$HOME/depot_tools/.git" # Append depot_tools to the PATH for subsequent steps DEPOT_TOOLS_WIN=$(cygpath -w "$HOME/depot_tools") echo "$DEPOT_TOOLS_WIN" >> $GITHUB_PATH @@ -745,6 +952,7 @@ jobs: ./flutter/bin/et build --config ci/mac_debug_gen_snapshot_arm64 - name: Tar build files run: | + find engine/src/out/ci/mac_debug_gen_snapshot_arm64 -type l -lname "/*" -delete || true tar -cvf mac_debug_gen_snapshot_arm64.tar engine/src/out/ci/mac_debug_gen_snapshot_arm64 - name: Upload build files uses: actions/upload-artifact@v4 @@ -768,7 +976,14 @@ jobs: - name: Set up depot_tools if: runner.os != 'Windows' run: | - git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git $HOME/depot_tools + rm -rf "$HOME/depot_tools" + for attempt in 1 2 3; do + git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git "$HOME/depot_tools" && break + rm -rf "$HOME/depot_tools" + echo "depot_tools clone failed (attempt $attempt), retrying..." + sleep 5 + done + test -d "$HOME/depot_tools/.git" # Append depot_tools to the PATH for subsequent steps echo "$HOME/depot_tools" >> $GITHUB_PATH - name: Free disk space @@ -777,7 +992,14 @@ jobs: - name: Set up depot_tools if: runner.os == 'Windows' run: | - git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git $HOME/depot_tools + rm -rf "$HOME/depot_tools" + for attempt in 1 2 3; do + git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git "$HOME/depot_tools" && break + rm -rf "$HOME/depot_tools" + echo "depot_tools clone failed (attempt $attempt), retrying..." + sleep 5 + done + test -d "$HOME/depot_tools/.git" # Append depot_tools to the PATH for subsequent steps DEPOT_TOOLS_WIN=$(cygpath -w "$HOME/depot_tools") echo "$DEPOT_TOOLS_WIN" >> $GITHUB_PATH @@ -796,8 +1018,16 @@ jobs: run: | cd engine/src ./flutter/bin/et build --config ci/mac_profile_arm64 + - name: Run engine unit tests + run: | + cd engine/src + python3 flutter/testing/run_tests.py \ + --variant ci/mac_profile_arm64 \ + --type engine \ + --engine-capture-core-dump - name: Tar build files run: | + find engine/src/out/ci/mac_profile_arm64 -type l -lname "/*" -delete || true tar -cvf mac_profile_arm64.tar engine/src/out/ci/mac_profile_arm64 - name: Upload build files uses: actions/upload-artifact@v4 @@ -831,7 +1061,14 @@ jobs: - name: Set up depot_tools if: runner.os != 'Windows' run: | - git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git $HOME/depot_tools + rm -rf "$HOME/depot_tools" + for attempt in 1 2 3; do + git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git "$HOME/depot_tools" && break + rm -rf "$HOME/depot_tools" + echo "depot_tools clone failed (attempt $attempt), retrying..." + sleep 5 + done + test -d "$HOME/depot_tools/.git" # Append depot_tools to the PATH for subsequent steps echo "$HOME/depot_tools" >> $GITHUB_PATH - name: Free disk space @@ -840,7 +1077,14 @@ jobs: - name: Set up depot_tools if: runner.os == 'Windows' run: | - git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git $HOME/depot_tools + rm -rf "$HOME/depot_tools" + for attempt in 1 2 3; do + git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git "$HOME/depot_tools" && break + rm -rf "$HOME/depot_tools" + echo "depot_tools clone failed (attempt $attempt), retrying..." + sleep 5 + done + test -d "$HOME/depot_tools/.git" # Append depot_tools to the PATH for subsequent steps DEPOT_TOOLS_WIN=$(cygpath -w "$HOME/depot_tools") echo "$DEPOT_TOOLS_WIN" >> $GITHUB_PATH @@ -861,6 +1105,7 @@ jobs: ./flutter/bin/et build --config ci/mac_profile_framework_arm64 - name: Tar build files run: | + find engine/src/out/ci/mac_profile_framework_arm64 -type l -lname "/*" -delete || true tar -cvf mac_profile_framework_arm64.tar engine/src/out/ci/mac_profile_framework_arm64 - name: Upload build files uses: actions/upload-artifact@v4 @@ -884,7 +1129,14 @@ jobs: - name: Set up depot_tools if: runner.os != 'Windows' run: | - git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git $HOME/depot_tools + rm -rf "$HOME/depot_tools" + for attempt in 1 2 3; do + git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git "$HOME/depot_tools" && break + rm -rf "$HOME/depot_tools" + echo "depot_tools clone failed (attempt $attempt), retrying..." + sleep 5 + done + test -d "$HOME/depot_tools/.git" # Append depot_tools to the PATH for subsequent steps echo "$HOME/depot_tools" >> $GITHUB_PATH - name: Free disk space @@ -893,7 +1145,14 @@ jobs: - name: Set up depot_tools if: runner.os == 'Windows' run: | - git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git $HOME/depot_tools + rm -rf "$HOME/depot_tools" + for attempt in 1 2 3; do + git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git "$HOME/depot_tools" && break + rm -rf "$HOME/depot_tools" + echo "depot_tools clone failed (attempt $attempt), retrying..." + sleep 5 + done + test -d "$HOME/depot_tools/.git" # Append depot_tools to the PATH for subsequent steps DEPOT_TOOLS_WIN=$(cygpath -w "$HOME/depot_tools") echo "$DEPOT_TOOLS_WIN" >> $GITHUB_PATH @@ -914,6 +1173,7 @@ jobs: ./flutter/bin/et build --config ci/mac_profile_gen_snapshot_arm64 - name: Tar build files run: | + find engine/src/out/ci/mac_profile_gen_snapshot_arm64 -type l -lname "/*" -delete || true tar -cvf mac_profile_gen_snapshot_arm64.tar engine/src/out/ci/mac_profile_gen_snapshot_arm64 - name: Upload build files uses: actions/upload-artifact@v4 @@ -937,7 +1197,14 @@ jobs: - name: Set up depot_tools if: runner.os != 'Windows' run: | - git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git $HOME/depot_tools + rm -rf "$HOME/depot_tools" + for attempt in 1 2 3; do + git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git "$HOME/depot_tools" && break + rm -rf "$HOME/depot_tools" + echo "depot_tools clone failed (attempt $attempt), retrying..." + sleep 5 + done + test -d "$HOME/depot_tools/.git" # Append depot_tools to the PATH for subsequent steps echo "$HOME/depot_tools" >> $GITHUB_PATH - name: Free disk space @@ -946,7 +1213,14 @@ jobs: - name: Set up depot_tools if: runner.os == 'Windows' run: | - git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git $HOME/depot_tools + rm -rf "$HOME/depot_tools" + for attempt in 1 2 3; do + git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git "$HOME/depot_tools" && break + rm -rf "$HOME/depot_tools" + echo "depot_tools clone failed (attempt $attempt), retrying..." + sleep 5 + done + test -d "$HOME/depot_tools/.git" # Append depot_tools to the PATH for subsequent steps DEPOT_TOOLS_WIN=$(cygpath -w "$HOME/depot_tools") echo "$DEPOT_TOOLS_WIN" >> $GITHUB_PATH @@ -965,8 +1239,16 @@ jobs: run: | cd engine/src ./flutter/bin/et build --config ci/mac_release_arm64 + - name: Run engine unit tests + run: | + cd engine/src + python3 flutter/testing/run_tests.py \ + --variant ci/mac_release_arm64 \ + --type engine \ + --engine-capture-core-dump - name: Tar build files run: | + find engine/src/out/ci/mac_release_arm64 -type l -lname "/*" -delete || true tar -cvf mac_release_arm64.tar engine/src/out/ci/mac_release_arm64 - name: Upload build files uses: actions/upload-artifact@v4 @@ -1010,7 +1292,14 @@ jobs: - name: Set up depot_tools if: runner.os != 'Windows' run: | - git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git $HOME/depot_tools + rm -rf "$HOME/depot_tools" + for attempt in 1 2 3; do + git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git "$HOME/depot_tools" && break + rm -rf "$HOME/depot_tools" + echo "depot_tools clone failed (attempt $attempt), retrying..." + sleep 5 + done + test -d "$HOME/depot_tools/.git" # Append depot_tools to the PATH for subsequent steps echo "$HOME/depot_tools" >> $GITHUB_PATH - name: Free disk space @@ -1019,7 +1308,14 @@ jobs: - name: Set up depot_tools if: runner.os == 'Windows' run: | - git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git $HOME/depot_tools + rm -rf "$HOME/depot_tools" + for attempt in 1 2 3; do + git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git "$HOME/depot_tools" && break + rm -rf "$HOME/depot_tools" + echo "depot_tools clone failed (attempt $attempt), retrying..." + sleep 5 + done + test -d "$HOME/depot_tools/.git" # Append depot_tools to the PATH for subsequent steps DEPOT_TOOLS_WIN=$(cygpath -w "$HOME/depot_tools") echo "$DEPOT_TOOLS_WIN" >> $GITHUB_PATH @@ -1040,6 +1336,7 @@ jobs: ./flutter/bin/et build --config ci/mac_release_framework_arm64 - name: Tar build files run: | + find engine/src/out/ci/mac_release_framework_arm64 -type l -lname "/*" -delete || true tar -cvf mac_release_framework_arm64.tar engine/src/out/ci/mac_release_framework_arm64 - name: Upload build files uses: actions/upload-artifact@v4 @@ -1063,7 +1360,14 @@ jobs: - name: Set up depot_tools if: runner.os != 'Windows' run: | - git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git $HOME/depot_tools + rm -rf "$HOME/depot_tools" + for attempt in 1 2 3; do + git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git "$HOME/depot_tools" && break + rm -rf "$HOME/depot_tools" + echo "depot_tools clone failed (attempt $attempt), retrying..." + sleep 5 + done + test -d "$HOME/depot_tools/.git" # Append depot_tools to the PATH for subsequent steps echo "$HOME/depot_tools" >> $GITHUB_PATH - name: Free disk space @@ -1072,7 +1376,14 @@ jobs: - name: Set up depot_tools if: runner.os == 'Windows' run: | - git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git $HOME/depot_tools + rm -rf "$HOME/depot_tools" + for attempt in 1 2 3; do + git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git "$HOME/depot_tools" && break + rm -rf "$HOME/depot_tools" + echo "depot_tools clone failed (attempt $attempt), retrying..." + sleep 5 + done + test -d "$HOME/depot_tools/.git" # Append depot_tools to the PATH for subsequent steps DEPOT_TOOLS_WIN=$(cygpath -w "$HOME/depot_tools") echo "$DEPOT_TOOLS_WIN" >> $GITHUB_PATH @@ -1093,6 +1404,7 @@ jobs: ./flutter/bin/et build --config ci/mac_release_gen_snapshot_arm64 - name: Tar build files run: | + find engine/src/out/ci/mac_release_gen_snapshot_arm64 -type l -lname "/*" -delete || true tar -cvf mac_release_gen_snapshot_arm64.tar engine/src/out/ci/mac_release_gen_snapshot_arm64 - name: Upload build files uses: actions/upload-artifact@v4 @@ -1134,7 +1446,14 @@ jobs: - name: Set up depot_tools if: runner.os != 'Windows' run: | - git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git $HOME/depot_tools + rm -rf "$HOME/depot_tools" + for attempt in 1 2 3; do + git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git "$HOME/depot_tools" && break + rm -rf "$HOME/depot_tools" + echo "depot_tools clone failed (attempt $attempt), retrying..." + sleep 5 + done + test -d "$HOME/depot_tools/.git" # Append depot_tools to the PATH for subsequent steps echo "$HOME/depot_tools" >> $GITHUB_PATH - name: Free disk space @@ -1143,7 +1462,14 @@ jobs: - name: Set up depot_tools if: runner.os == 'Windows' run: | - git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git $HOME/depot_tools + rm -rf "$HOME/depot_tools" + for attempt in 1 2 3; do + git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git "$HOME/depot_tools" && break + rm -rf "$HOME/depot_tools" + echo "depot_tools clone failed (attempt $attempt), retrying..." + sleep 5 + done + test -d "$HOME/depot_tools/.git" # Append depot_tools to the PATH for subsequent steps DEPOT_TOOLS_WIN=$(cygpath -w "$HOME/depot_tools") echo "$DEPOT_TOOLS_WIN" >> $GITHUB_PATH @@ -1503,7 +1829,14 @@ jobs: - name: Set up depot_tools if: runner.os != 'Windows' run: | - git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git $HOME/depot_tools + rm -rf "$HOME/depot_tools" + for attempt in 1 2 3; do + git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git "$HOME/depot_tools" && break + rm -rf "$HOME/depot_tools" + echo "depot_tools clone failed (attempt $attempt), retrying..." + sleep 5 + done + test -d "$HOME/depot_tools/.git" # Append depot_tools to the PATH for subsequent steps echo "$HOME/depot_tools" >> $GITHUB_PATH - name: Free disk space @@ -1512,7 +1845,14 @@ jobs: - name: Set up depot_tools if: runner.os == 'Windows' run: | - git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git $HOME/depot_tools + rm -rf "$HOME/depot_tools" + for attempt in 1 2 3; do + git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git "$HOME/depot_tools" && break + rm -rf "$HOME/depot_tools" + echo "depot_tools clone failed (attempt $attempt), retrying..." + sleep 5 + done + test -d "$HOME/depot_tools/.git" # Append depot_tools to the PATH for subsequent steps DEPOT_TOOLS_WIN=$(cygpath -w "$HOME/depot_tools") echo "$DEPOT_TOOLS_WIN" >> $GITHUB_PATH @@ -1533,6 +1873,7 @@ jobs: ./flutter/bin/et build --config ci/ios_debug_sim - name: Tar build files run: | + find engine/src/out/ci/ios_debug_sim -type l -lname "/*" -delete || true tar -cvf mac_ios_debug_sim.tar engine/src/out/ci/ios_debug_sim - name: Upload build files uses: actions/upload-artifact@v4 @@ -1556,7 +1897,14 @@ jobs: - name: Set up depot_tools if: runner.os != 'Windows' run: | - git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git $HOME/depot_tools + rm -rf "$HOME/depot_tools" + for attempt in 1 2 3; do + git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git "$HOME/depot_tools" && break + rm -rf "$HOME/depot_tools" + echo "depot_tools clone failed (attempt $attempt), retrying..." + sleep 5 + done + test -d "$HOME/depot_tools/.git" # Append depot_tools to the PATH for subsequent steps echo "$HOME/depot_tools" >> $GITHUB_PATH - name: Free disk space @@ -1565,7 +1913,14 @@ jobs: - name: Set up depot_tools if: runner.os == 'Windows' run: | - git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git $HOME/depot_tools + rm -rf "$HOME/depot_tools" + for attempt in 1 2 3; do + git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git "$HOME/depot_tools" && break + rm -rf "$HOME/depot_tools" + echo "depot_tools clone failed (attempt $attempt), retrying..." + sleep 5 + done + test -d "$HOME/depot_tools/.git" # Append depot_tools to the PATH for subsequent steps DEPOT_TOOLS_WIN=$(cygpath -w "$HOME/depot_tools") echo "$DEPOT_TOOLS_WIN" >> $GITHUB_PATH @@ -1586,6 +1941,7 @@ jobs: ./flutter/bin/et build --config ci/ios_debug_sim_arm64 - name: Tar build files run: | + find engine/src/out/ci/ios_debug_sim_arm64 -type l -lname "/*" -delete || true tar -cvf mac_ios_debug_sim_arm64.tar engine/src/out/ci/ios_debug_sim_arm64 - name: Upload build files uses: actions/upload-artifact@v4 @@ -1593,6 +1949,74 @@ jobs: name: artifacts-mac_ios_debug_sim_arm64-${{ steps.engine_content_hash.outputs.value }} path: mac_ios_debug_sim_arm64.tar retention-days: 1 + mac_ios_test_binaries_arm64: + runs-on: macos-latest + defaults: + run: + shell: bash + needs: + - guard + if: ${{ needs.guard.outputs.should_run == 'true' }} + steps: + - name: Checkout the repository + uses: actions/checkout@v4 + with: + path: '' + - name: Set up depot_tools + if: runner.os != 'Windows' + run: | + rm -rf "$HOME/depot_tools" + for attempt in 1 2 3; do + git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git "$HOME/depot_tools" && break + rm -rf "$HOME/depot_tools" + echo "depot_tools clone failed (attempt $attempt), retrying..." + sleep 5 + done + test -d "$HOME/depot_tools/.git" + # Append depot_tools to the PATH for subsequent steps + echo "$HOME/depot_tools" >> $GITHUB_PATH + - name: Free disk space + if: runner.os == 'Linux' && runner.arch == 'X64' + run: curl -fsSL https://raw.githubusercontent.com/apache/arrow/e49d8ae15583ceff03237571569099a6ad62be32/ci/scripts/util_free_space.sh | bash + - name: Set up depot_tools + if: runner.os == 'Windows' + run: | + rm -rf "$HOME/depot_tools" + for attempt in 1 2 3; do + git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git "$HOME/depot_tools" && break + rm -rf "$HOME/depot_tools" + echo "depot_tools clone failed (attempt $attempt), retrying..." + sleep 5 + done + test -d "$HOME/depot_tools/.git" + # Append depot_tools to the PATH for subsequent steps + DEPOT_TOOLS_WIN=$(cygpath -w "$HOME/depot_tools") + echo "$DEPOT_TOOLS_WIN" >> $GITHUB_PATH + - name: Generate engine content hash + id: engine_content_hash + run: | + engine_content_hash=${{ needs.guard.outputs.engine_content_hash }} + echo "value=${engine_content_hash}" >> $GITHUB_OUTPUT + - name: Copy gclient file + run: | + cp engine/scripts/slim.gclient .gclient + - name: GClient sync + run: | + gclient sync -D --no-history --shallow --with_branch_heads + - name: Build engine + run: | + cd engine/src + ./flutter/bin/et build --config ci/ios_test_binaries_arm64 + - name: Tar build files + run: | + find engine/src/out/ci/ios_test_binaries_arm64 -type l -lname "/*" -delete || true + tar -cvf mac_ios_test_binaries_arm64.tar engine/src/out/ci/ios_test_binaries_arm64 + - name: Upload build files + uses: actions/upload-artifact@v4 + with: + name: artifacts-mac_ios_test_binaries_arm64-${{ steps.engine_content_hash.outputs.value }} + path: mac_ios_test_binaries_arm64.tar + retention-days: 1 mac_ios_debug: runs-on: macos-latest defaults: @@ -1609,7 +2033,14 @@ jobs: - name: Set up depot_tools if: runner.os != 'Windows' run: | - git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git $HOME/depot_tools + rm -rf "$HOME/depot_tools" + for attempt in 1 2 3; do + git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git "$HOME/depot_tools" && break + rm -rf "$HOME/depot_tools" + echo "depot_tools clone failed (attempt $attempt), retrying..." + sleep 5 + done + test -d "$HOME/depot_tools/.git" # Append depot_tools to the PATH for subsequent steps echo "$HOME/depot_tools" >> $GITHUB_PATH - name: Free disk space @@ -1618,7 +2049,14 @@ jobs: - name: Set up depot_tools if: runner.os == 'Windows' run: | - git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git $HOME/depot_tools + rm -rf "$HOME/depot_tools" + for attempt in 1 2 3; do + git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git "$HOME/depot_tools" && break + rm -rf "$HOME/depot_tools" + echo "depot_tools clone failed (attempt $attempt), retrying..." + sleep 5 + done + test -d "$HOME/depot_tools/.git" # Append depot_tools to the PATH for subsequent steps DEPOT_TOOLS_WIN=$(cygpath -w "$HOME/depot_tools") echo "$DEPOT_TOOLS_WIN" >> $GITHUB_PATH @@ -1639,6 +2077,7 @@ jobs: ./flutter/bin/et build --config ci/ios_debug - name: Tar build files run: | + find engine/src/out/ci/ios_debug -type l -lname "/*" -delete || true tar -cvf mac_ios_debug.tar engine/src/out/ci/ios_debug - name: Upload build files uses: actions/upload-artifact@v4 @@ -1662,7 +2101,14 @@ jobs: - name: Set up depot_tools if: runner.os != 'Windows' run: | - git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git $HOME/depot_tools + rm -rf "$HOME/depot_tools" + for attempt in 1 2 3; do + git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git "$HOME/depot_tools" && break + rm -rf "$HOME/depot_tools" + echo "depot_tools clone failed (attempt $attempt), retrying..." + sleep 5 + done + test -d "$HOME/depot_tools/.git" # Append depot_tools to the PATH for subsequent steps echo "$HOME/depot_tools" >> $GITHUB_PATH - name: Free disk space @@ -1671,7 +2117,14 @@ jobs: - name: Set up depot_tools if: runner.os == 'Windows' run: | - git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git $HOME/depot_tools + rm -rf "$HOME/depot_tools" + for attempt in 1 2 3; do + git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git "$HOME/depot_tools" && break + rm -rf "$HOME/depot_tools" + echo "depot_tools clone failed (attempt $attempt), retrying..." + sleep 5 + done + test -d "$HOME/depot_tools/.git" # Append depot_tools to the PATH for subsequent steps DEPOT_TOOLS_WIN=$(cygpath -w "$HOME/depot_tools") echo "$DEPOT_TOOLS_WIN" >> $GITHUB_PATH @@ -1692,6 +2145,7 @@ jobs: ./flutter/bin/et build --config ci/ios_profile - name: Tar build files run: | + find engine/src/out/ci/ios_profile -type l -lname "/*" -delete || true tar -cvf mac_ios_profile.tar engine/src/out/ci/ios_profile - name: Upload build files uses: actions/upload-artifact@v4 @@ -1715,7 +2169,14 @@ jobs: - name: Set up depot_tools if: runner.os != 'Windows' run: | - git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git $HOME/depot_tools + rm -rf "$HOME/depot_tools" + for attempt in 1 2 3; do + git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git "$HOME/depot_tools" && break + rm -rf "$HOME/depot_tools" + echo "depot_tools clone failed (attempt $attempt), retrying..." + sleep 5 + done + test -d "$HOME/depot_tools/.git" # Append depot_tools to the PATH for subsequent steps echo "$HOME/depot_tools" >> $GITHUB_PATH - name: Free disk space @@ -1724,7 +2185,14 @@ jobs: - name: Set up depot_tools if: runner.os == 'Windows' run: | - git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git $HOME/depot_tools + rm -rf "$HOME/depot_tools" + for attempt in 1 2 3; do + git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git "$HOME/depot_tools" && break + rm -rf "$HOME/depot_tools" + echo "depot_tools clone failed (attempt $attempt), retrying..." + sleep 5 + done + test -d "$HOME/depot_tools/.git" # Append depot_tools to the PATH for subsequent steps DEPOT_TOOLS_WIN=$(cygpath -w "$HOME/depot_tools") echo "$DEPOT_TOOLS_WIN" >> $GITHUB_PATH @@ -1745,6 +2213,7 @@ jobs: ./flutter/bin/et build --config ci/ios_release - name: Tar build files run: | + find engine/src/out/ci/ios_release -type l -lname "/*" -delete || true tar -cvf mac_ios_release.tar engine/src/out/ci/ios_release - name: Upload build files uses: actions/upload-artifact@v4 @@ -1757,6 +2226,7 @@ jobs: needs: - mac_ios_debug_sim - mac_ios_debug_sim_arm64 + - mac_ios_test_binaries_arm64 - mac_ios_debug - mac_ios_profile - mac_ios_release @@ -1773,7 +2243,14 @@ jobs: - name: Set up depot_tools if: runner.os != 'Windows' run: | - git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git $HOME/depot_tools + rm -rf "$HOME/depot_tools" + for attempt in 1 2 3; do + git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git "$HOME/depot_tools" && break + rm -rf "$HOME/depot_tools" + echo "depot_tools clone failed (attempt $attempt), retrying..." + sleep 5 + done + test -d "$HOME/depot_tools/.git" # Append depot_tools to the PATH for subsequent steps echo "$HOME/depot_tools" >> $GITHUB_PATH - name: Free disk space @@ -1782,7 +2259,14 @@ jobs: - name: Set up depot_tools if: runner.os == 'Windows' run: | - git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git $HOME/depot_tools + rm -rf "$HOME/depot_tools" + for attempt in 1 2 3; do + git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git "$HOME/depot_tools" && break + rm -rf "$HOME/depot_tools" + echo "depot_tools clone failed (attempt $attempt), retrying..." + sleep 5 + done + test -d "$HOME/depot_tools/.git" # Append depot_tools to the PATH for subsequent steps DEPOT_TOOLS_WIN=$(cygpath -w "$HOME/depot_tools") echo "$DEPOT_TOOLS_WIN" >> $GITHUB_PATH @@ -1813,6 +2297,14 @@ jobs: run: | tar -xvf mac_ios_debug_sim_arm64.tar rm mac_ios_debug_sim_arm64.tar + - name: Download Artifacts from mac_ios_test_binaries_arm64 + uses: actions/download-artifact@v4 + with: + name: artifacts-mac_ios_test_binaries_arm64-${{ steps.engine_content_hash.outputs.value }} + - name: Extract Artifacts from mac_ios_test_binaries_arm64 + run: | + tar -xvf mac_ios_test_binaries_arm64.tar + rm mac_ios_test_binaries_arm64.tar - name: Download Artifacts from mac_ios_debug uses: actions/download-artifact@v4 with: @@ -1930,7 +2422,14 @@ jobs: - name: Set up depot_tools if: runner.os != 'Windows' run: | - git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git $HOME/depot_tools + rm -rf "$HOME/depot_tools" + for attempt in 1 2 3; do + git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git "$HOME/depot_tools" && break + rm -rf "$HOME/depot_tools" + echo "depot_tools clone failed (attempt $attempt), retrying..." + sleep 5 + done + test -d "$HOME/depot_tools/.git" # Append depot_tools to the PATH for subsequent steps echo "$HOME/depot_tools" >> $GITHUB_PATH - name: Free disk space @@ -1939,7 +2438,14 @@ jobs: - name: Set up depot_tools if: runner.os == 'Windows' run: | - git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git $HOME/depot_tools + rm -rf "$HOME/depot_tools" + for attempt in 1 2 3; do + git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git "$HOME/depot_tools" && break + rm -rf "$HOME/depot_tools" + echo "depot_tools clone failed (attempt $attempt), retrying..." + sleep 5 + done + test -d "$HOME/depot_tools/.git" # Append depot_tools to the PATH for subsequent steps DEPOT_TOOLS_WIN=$(cygpath -w "$HOME/depot_tools") echo "$DEPOT_TOOLS_WIN" >> $GITHUB_PATH @@ -1959,6 +2465,12 @@ jobs: run: | cd engine\src flutter\bin\et.bat build --config ci\host_debug + - name: Run engine unit tests + run: | + cd engine/src + python flutter/testing/run_tests.py \ + --variant ci/host_debug \ + --type engine \ - name: Tar engine/src/out/ci/host_debug/zip_archives/windows-x64/artifacts.zip run: | cd engine/src/out/ci/host_debug/zip_archives/windows-x64 @@ -2035,7 +2547,14 @@ jobs: - name: Set up depot_tools if: runner.os != 'Windows' run: | - git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git $HOME/depot_tools + rm -rf "$HOME/depot_tools" + for attempt in 1 2 3; do + git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git "$HOME/depot_tools" && break + rm -rf "$HOME/depot_tools" + echo "depot_tools clone failed (attempt $attempt), retrying..." + sleep 5 + done + test -d "$HOME/depot_tools/.git" # Append depot_tools to the PATH for subsequent steps echo "$HOME/depot_tools" >> $GITHUB_PATH - name: Free disk space @@ -2044,7 +2563,14 @@ jobs: - name: Set up depot_tools if: runner.os == 'Windows' run: | - git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git $HOME/depot_tools + rm -rf "$HOME/depot_tools" + for attempt in 1 2 3; do + git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git "$HOME/depot_tools" && break + rm -rf "$HOME/depot_tools" + echo "depot_tools clone failed (attempt $attempt), retrying..." + sleep 5 + done + test -d "$HOME/depot_tools/.git" # Append depot_tools to the PATH for subsequent steps DEPOT_TOOLS_WIN=$(cygpath -w "$HOME/depot_tools") echo "$DEPOT_TOOLS_WIN" >> $GITHUB_PATH @@ -2090,7 +2616,14 @@ jobs: - name: Set up depot_tools if: runner.os != 'Windows' run: | - git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git $HOME/depot_tools + rm -rf "$HOME/depot_tools" + for attempt in 1 2 3; do + git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git "$HOME/depot_tools" && break + rm -rf "$HOME/depot_tools" + echo "depot_tools clone failed (attempt $attempt), retrying..." + sleep 5 + done + test -d "$HOME/depot_tools/.git" # Append depot_tools to the PATH for subsequent steps echo "$HOME/depot_tools" >> $GITHUB_PATH - name: Free disk space @@ -2099,7 +2632,14 @@ jobs: - name: Set up depot_tools if: runner.os == 'Windows' run: | - git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git $HOME/depot_tools + rm -rf "$HOME/depot_tools" + for attempt in 1 2 3; do + git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git "$HOME/depot_tools" && break + rm -rf "$HOME/depot_tools" + echo "depot_tools clone failed (attempt $attempt), retrying..." + sleep 5 + done + test -d "$HOME/depot_tools/.git" # Append depot_tools to the PATH for subsequent steps DEPOT_TOOLS_WIN=$(cygpath -w "$HOME/depot_tools") echo "$DEPOT_TOOLS_WIN" >> $GITHUB_PATH @@ -2145,7 +2685,14 @@ jobs: - name: Set up depot_tools if: runner.os != 'Windows' run: | - git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git $HOME/depot_tools + rm -rf "$HOME/depot_tools" + for attempt in 1 2 3; do + git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git "$HOME/depot_tools" && break + rm -rf "$HOME/depot_tools" + echo "depot_tools clone failed (attempt $attempt), retrying..." + sleep 5 + done + test -d "$HOME/depot_tools/.git" # Append depot_tools to the PATH for subsequent steps echo "$HOME/depot_tools" >> $GITHUB_PATH - name: Free disk space @@ -2154,7 +2701,14 @@ jobs: - name: Set up depot_tools if: runner.os == 'Windows' run: | - git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git $HOME/depot_tools + rm -rf "$HOME/depot_tools" + for attempt in 1 2 3; do + git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git "$HOME/depot_tools" && break + rm -rf "$HOME/depot_tools" + echo "depot_tools clone failed (attempt $attempt), retrying..." + sleep 5 + done + test -d "$HOME/depot_tools/.git" # Append depot_tools to the PATH for subsequent steps DEPOT_TOOLS_WIN=$(cygpath -w "$HOME/depot_tools") echo "$DEPOT_TOOLS_WIN" >> $GITHUB_PATH @@ -2250,7 +2804,14 @@ jobs: - name: Set up depot_tools if: runner.os != 'Windows' run: | - git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git $HOME/depot_tools + rm -rf "$HOME/depot_tools" + for attempt in 1 2 3; do + git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git "$HOME/depot_tools" && break + rm -rf "$HOME/depot_tools" + echo "depot_tools clone failed (attempt $attempt), retrying..." + sleep 5 + done + test -d "$HOME/depot_tools/.git" # Append depot_tools to the PATH for subsequent steps echo "$HOME/depot_tools" >> $GITHUB_PATH - name: Free disk space @@ -2259,7 +2820,14 @@ jobs: - name: Set up depot_tools if: runner.os == 'Windows' run: | - git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git $HOME/depot_tools + rm -rf "$HOME/depot_tools" + for attempt in 1 2 3; do + git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git "$HOME/depot_tools" && break + rm -rf "$HOME/depot_tools" + echo "depot_tools clone failed (attempt $attempt), retrying..." + sleep 5 + done + test -d "$HOME/depot_tools/.git" # Append depot_tools to the PATH for subsequent steps DEPOT_TOOLS_WIN=$(cygpath -w "$HOME/depot_tools") echo "$DEPOT_TOOLS_WIN" >> $GITHUB_PATH @@ -2305,7 +2873,14 @@ jobs: - name: Set up depot_tools if: runner.os != 'Windows' run: | - git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git $HOME/depot_tools + rm -rf "$HOME/depot_tools" + for attempt in 1 2 3; do + git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git "$HOME/depot_tools" && break + rm -rf "$HOME/depot_tools" + echo "depot_tools clone failed (attempt $attempt), retrying..." + sleep 5 + done + test -d "$HOME/depot_tools/.git" # Append depot_tools to the PATH for subsequent steps echo "$HOME/depot_tools" >> $GITHUB_PATH - name: Free disk space @@ -2314,7 +2889,14 @@ jobs: - name: Set up depot_tools if: runner.os == 'Windows' run: | - git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git $HOME/depot_tools + rm -rf "$HOME/depot_tools" + for attempt in 1 2 3; do + git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git "$HOME/depot_tools" && break + rm -rf "$HOME/depot_tools" + echo "depot_tools clone failed (attempt $attempt), retrying..." + sleep 5 + done + test -d "$HOME/depot_tools/.git" # Append depot_tools to the PATH for subsequent steps DEPOT_TOOLS_WIN=$(cygpath -w "$HOME/depot_tools") echo "$DEPOT_TOOLS_WIN" >> $GITHUB_PATH @@ -2360,7 +2942,14 @@ jobs: - name: Set up depot_tools if: runner.os != 'Windows' run: | - git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git $HOME/depot_tools + rm -rf "$HOME/depot_tools" + for attempt in 1 2 3; do + git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git "$HOME/depot_tools" && break + rm -rf "$HOME/depot_tools" + echo "depot_tools clone failed (attempt $attempt), retrying..." + sleep 5 + done + test -d "$HOME/depot_tools/.git" # Append depot_tools to the PATH for subsequent steps echo "$HOME/depot_tools" >> $GITHUB_PATH - name: Install doxygen @@ -2374,7 +2963,14 @@ jobs: - name: Set up depot_tools if: runner.os == 'Windows' run: | - git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git $HOME/depot_tools + rm -rf "$HOME/depot_tools" + for attempt in 1 2 3; do + git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git "$HOME/depot_tools" && break + rm -rf "$HOME/depot_tools" + echo "depot_tools clone failed (attempt $attempt), retrying..." + sleep 5 + done + test -d "$HOME/depot_tools/.git" # Append depot_tools to the PATH for subsequent steps DEPOT_TOOLS_WIN=$(cygpath -w "$HOME/depot_tools") echo "$DEPOT_TOOLS_WIN" >> $GITHUB_PATH @@ -2393,8 +2989,16 @@ jobs: run: | cd engine/src ./flutter/bin/et build --config ci/host_debug + - name: Run engine unit tests + run: | + cd engine/src + python3 flutter/testing/run_tests.py \ + --variant ci/host_debug \ + --type engine \ + --engine-capture-core-dump - name: Tar build files run: | + find engine/src/out/ci/host_debug -type l -lname "/*" -delete || true tar -cvf linux_host_debug.tar engine/src/out/ci/host_debug - name: Upload build files uses: actions/upload-artifact@v4 @@ -2468,7 +3072,14 @@ jobs: - name: Set up depot_tools if: runner.os != 'Windows' run: | - git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git $HOME/depot_tools + rm -rf "$HOME/depot_tools" + for attempt in 1 2 3; do + git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git "$HOME/depot_tools" && break + rm -rf "$HOME/depot_tools" + echo "depot_tools clone failed (attempt $attempt), retrying..." + sleep 5 + done + test -d "$HOME/depot_tools/.git" # Append depot_tools to the PATH for subsequent steps echo "$HOME/depot_tools" >> $GITHUB_PATH - name: Install doxygen @@ -2482,7 +3093,14 @@ jobs: - name: Set up depot_tools if: runner.os == 'Windows' run: | - git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git $HOME/depot_tools + rm -rf "$HOME/depot_tools" + for attempt in 1 2 3; do + git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git "$HOME/depot_tools" && break + rm -rf "$HOME/depot_tools" + echo "depot_tools clone failed (attempt $attempt), retrying..." + sleep 5 + done + test -d "$HOME/depot_tools/.git" # Append depot_tools to the PATH for subsequent steps DEPOT_TOOLS_WIN=$(cygpath -w "$HOME/depot_tools") echo "$DEPOT_TOOLS_WIN" >> $GITHUB_PATH @@ -2501,8 +3119,16 @@ jobs: run: | cd engine/src ./flutter/bin/et build --config ci/host_release + - name: Run engine unit tests + run: | + cd engine/src + python3 flutter/testing/run_tests.py \ + --variant ci/host_release \ + --type engine \ + --engine-capture-core-dump - name: Tar build files run: | + find engine/src/out/ci/host_release -type l -lname "/*" -delete || true tar -cvf linux_host_release.tar engine/src/out/ci/host_release - name: Upload build files uses: actions/upload-artifact@v4 @@ -2538,7 +3164,14 @@ jobs: - name: Set up depot_tools if: runner.os != 'Windows' run: | - git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git $HOME/depot_tools + rm -rf "$HOME/depot_tools" + for attempt in 1 2 3; do + git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git "$HOME/depot_tools" && break + rm -rf "$HOME/depot_tools" + echo "depot_tools clone failed (attempt $attempt), retrying..." + sleep 5 + done + test -d "$HOME/depot_tools/.git" # Append depot_tools to the PATH for subsequent steps echo "$HOME/depot_tools" >> $GITHUB_PATH - name: Install doxygen @@ -2552,7 +3185,14 @@ jobs: - name: Set up depot_tools if: runner.os == 'Windows' run: | - git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git $HOME/depot_tools + rm -rf "$HOME/depot_tools" + for attempt in 1 2 3; do + git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git "$HOME/depot_tools" && break + rm -rf "$HOME/depot_tools" + echo "depot_tools clone failed (attempt $attempt), retrying..." + sleep 5 + done + test -d "$HOME/depot_tools/.git" # Append depot_tools to the PATH for subsequent steps DEPOT_TOOLS_WIN=$(cygpath -w "$HOME/depot_tools") echo "$DEPOT_TOOLS_WIN" >> $GITHUB_PATH @@ -2675,7 +3315,14 @@ jobs: - name: Set up depot_tools if: runner.os != 'Windows' run: | - git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git $HOME/depot_tools + rm -rf "$HOME/depot_tools" + for attempt in 1 2 3; do + git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git "$HOME/depot_tools" && break + rm -rf "$HOME/depot_tools" + echo "depot_tools clone failed (attempt $attempt), retrying..." + sleep 5 + done + test -d "$HOME/depot_tools/.git" # Append depot_tools to the PATH for subsequent steps echo "$HOME/depot_tools" >> $GITHUB_PATH - name: Free disk space @@ -2684,7 +3331,14 @@ jobs: - name: Set up depot_tools if: runner.os == 'Windows' run: | - git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git $HOME/depot_tools + rm -rf "$HOME/depot_tools" + for attempt in 1 2 3; do + git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git "$HOME/depot_tools" && break + rm -rf "$HOME/depot_tools" + echo "depot_tools clone failed (attempt $attempt), retrying..." + sleep 5 + done + test -d "$HOME/depot_tools/.git" # Append depot_tools to the PATH for subsequent steps DEPOT_TOOLS_WIN=$(cygpath -w "$HOME/depot_tools") echo "$DEPOT_TOOLS_WIN" >> $GITHUB_PATH @@ -2703,6 +3357,13 @@ jobs: run: | cd engine/src ./flutter/bin/et build --config ci/host_debug_desktop + - name: Run engine unit tests + run: | + cd engine/src + python3 flutter/testing/run_tests.py \ + --variant ci/host_debug_desktop \ + --type engine \ + --engine-capture-core-dump - name: Tar engine/src/out/ci/host_debug_desktop/zip_archives/linux-x64-debug/linux-x64-flutter-gtk.zip run: | cd engine/src/out/ci/host_debug_desktop/zip_archives/linux-x64-debug @@ -2729,7 +3390,14 @@ jobs: - name: Set up depot_tools if: runner.os != 'Windows' run: | - git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git $HOME/depot_tools + rm -rf "$HOME/depot_tools" + for attempt in 1 2 3; do + git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git "$HOME/depot_tools" && break + rm -rf "$HOME/depot_tools" + echo "depot_tools clone failed (attempt $attempt), retrying..." + sleep 5 + done + test -d "$HOME/depot_tools/.git" # Append depot_tools to the PATH for subsequent steps echo "$HOME/depot_tools" >> $GITHUB_PATH - name: Free disk space @@ -2738,7 +3406,14 @@ jobs: - name: Set up depot_tools if: runner.os == 'Windows' run: | - git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git $HOME/depot_tools + rm -rf "$HOME/depot_tools" + for attempt in 1 2 3; do + git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git "$HOME/depot_tools" && break + rm -rf "$HOME/depot_tools" + echo "depot_tools clone failed (attempt $attempt), retrying..." + sleep 5 + done + test -d "$HOME/depot_tools/.git" # Append depot_tools to the PATH for subsequent steps DEPOT_TOOLS_WIN=$(cygpath -w "$HOME/depot_tools") echo "$DEPOT_TOOLS_WIN" >> $GITHUB_PATH @@ -2757,6 +3432,13 @@ jobs: run: | cd engine/src ./flutter/bin/et build --config ci/host_profile_desktop + - name: Run engine unit tests + run: | + cd engine/src + python3 flutter/testing/run_tests.py \ + --variant ci/host_profile_desktop \ + --type engine \ + --engine-capture-core-dump - name: Tar engine/src/out/ci/host_profile_desktop/zip_archives/linux-x64-profile/linux-x64-flutter-gtk.zip run: | cd engine/src/out/ci/host_profile_desktop/zip_archives/linux-x64-profile @@ -2783,7 +3465,14 @@ jobs: - name: Set up depot_tools if: runner.os != 'Windows' run: | - git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git $HOME/depot_tools + rm -rf "$HOME/depot_tools" + for attempt in 1 2 3; do + git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git "$HOME/depot_tools" && break + rm -rf "$HOME/depot_tools" + echo "depot_tools clone failed (attempt $attempt), retrying..." + sleep 5 + done + test -d "$HOME/depot_tools/.git" # Append depot_tools to the PATH for subsequent steps echo "$HOME/depot_tools" >> $GITHUB_PATH - name: Free disk space @@ -2792,7 +3481,14 @@ jobs: - name: Set up depot_tools if: runner.os == 'Windows' run: | - git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git $HOME/depot_tools + rm -rf "$HOME/depot_tools" + for attempt in 1 2 3; do + git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git "$HOME/depot_tools" && break + rm -rf "$HOME/depot_tools" + echo "depot_tools clone failed (attempt $attempt), retrying..." + sleep 5 + done + test -d "$HOME/depot_tools/.git" # Append depot_tools to the PATH for subsequent steps DEPOT_TOOLS_WIN=$(cygpath -w "$HOME/depot_tools") echo "$DEPOT_TOOLS_WIN" >> $GITHUB_PATH @@ -2811,6 +3507,13 @@ jobs: run: | cd engine/src ./flutter/bin/et build --config ci/host_release_desktop + - name: Run engine unit tests + run: | + cd engine/src + python3 flutter/testing/run_tests.py \ + --variant ci/host_release_desktop \ + --type engine \ + --engine-capture-core-dump - name: Tar engine/src/out/ci/host_release_desktop/zip_archives/linux-x64-release/linux-x64-flutter-gtk.zip run: | cd engine/src/out/ci/host_release_desktop/zip_archives/linux-x64-release @@ -2837,7 +3540,14 @@ jobs: - name: Set up depot_tools if: runner.os != 'Windows' run: | - git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git $HOME/depot_tools + rm -rf "$HOME/depot_tools" + for attempt in 1 2 3; do + git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git "$HOME/depot_tools" && break + rm -rf "$HOME/depot_tools" + echo "depot_tools clone failed (attempt $attempt), retrying..." + sleep 5 + done + test -d "$HOME/depot_tools/.git" # Append depot_tools to the PATH for subsequent steps echo "$HOME/depot_tools" >> $GITHUB_PATH - name: Free disk space @@ -2846,7 +3556,14 @@ jobs: - name: Set up depot_tools if: runner.os == 'Windows' run: | - git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git $HOME/depot_tools + rm -rf "$HOME/depot_tools" + for attempt in 1 2 3; do + git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git "$HOME/depot_tools" && break + rm -rf "$HOME/depot_tools" + echo "depot_tools clone failed (attempt $attempt), retrying..." + sleep 5 + done + test -d "$HOME/depot_tools/.git" # Append depot_tools to the PATH for subsequent steps DEPOT_TOOLS_WIN=$(cygpath -w "$HOME/depot_tools") echo "$DEPOT_TOOLS_WIN" >> $GITHUB_PATH @@ -2865,6 +3582,13 @@ jobs: run: | cd engine/src ./flutter/bin/et build --config ci/linux_profile_arm64 + - name: Run engine unit tests + run: | + cd engine/src + python3 flutter/testing/run_tests.py \ + --variant ci/linux_profile_arm64 \ + --type engine \ + --engine-capture-core-dump - name: Tar engine/src/out/ci/linux_profile_arm64/zip_archives/linux-arm64-profile/linux-arm64-flutter-gtk.zip run: | cd engine/src/out/ci/linux_profile_arm64/zip_archives/linux-arm64-profile @@ -2891,7 +3615,14 @@ jobs: - name: Set up depot_tools if: runner.os != 'Windows' run: | - git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git $HOME/depot_tools + rm -rf "$HOME/depot_tools" + for attempt in 1 2 3; do + git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git "$HOME/depot_tools" && break + rm -rf "$HOME/depot_tools" + echo "depot_tools clone failed (attempt $attempt), retrying..." + sleep 5 + done + test -d "$HOME/depot_tools/.git" # Append depot_tools to the PATH for subsequent steps echo "$HOME/depot_tools" >> $GITHUB_PATH - name: Free disk space @@ -2900,7 +3631,14 @@ jobs: - name: Set up depot_tools if: runner.os == 'Windows' run: | - git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git $HOME/depot_tools + rm -rf "$HOME/depot_tools" + for attempt in 1 2 3; do + git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git "$HOME/depot_tools" && break + rm -rf "$HOME/depot_tools" + echo "depot_tools clone failed (attempt $attempt), retrying..." + sleep 5 + done + test -d "$HOME/depot_tools/.git" # Append depot_tools to the PATH for subsequent steps DEPOT_TOOLS_WIN=$(cygpath -w "$HOME/depot_tools") echo "$DEPOT_TOOLS_WIN" >> $GITHUB_PATH @@ -2919,6 +3657,13 @@ jobs: run: | cd engine/src ./flutter/bin/et build --config ci/linux_debug_arm64 + - name: Run engine unit tests + run: | + cd engine/src + python3 flutter/testing/run_tests.py \ + --variant ci/linux_debug_arm64 \ + --type engine \ + --engine-capture-core-dump - name: Tar engine/src/out/ci/linux_debug_arm64/zip_archives/linux-arm64/artifacts.zip run: | cd engine/src/out/ci/linux_debug_arm64/zip_archives/linux-arm64 @@ -2985,7 +3730,14 @@ jobs: - name: Set up depot_tools if: runner.os != 'Windows' run: | - git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git $HOME/depot_tools + rm -rf "$HOME/depot_tools" + for attempt in 1 2 3; do + git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git "$HOME/depot_tools" && break + rm -rf "$HOME/depot_tools" + echo "depot_tools clone failed (attempt $attempt), retrying..." + sleep 5 + done + test -d "$HOME/depot_tools/.git" # Append depot_tools to the PATH for subsequent steps echo "$HOME/depot_tools" >> $GITHUB_PATH - name: Free disk space @@ -2994,7 +3746,14 @@ jobs: - name: Set up depot_tools if: runner.os == 'Windows' run: | - git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git $HOME/depot_tools + rm -rf "$HOME/depot_tools" + for attempt in 1 2 3; do + git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git "$HOME/depot_tools" && break + rm -rf "$HOME/depot_tools" + echo "depot_tools clone failed (attempt $attempt), retrying..." + sleep 5 + done + test -d "$HOME/depot_tools/.git" # Append depot_tools to the PATH for subsequent steps DEPOT_TOOLS_WIN=$(cygpath -w "$HOME/depot_tools") echo "$DEPOT_TOOLS_WIN" >> $GITHUB_PATH @@ -3013,6 +3772,13 @@ jobs: run: | cd engine/src ./flutter/bin/et build --config ci/linux_release_arm64 + - name: Run engine unit tests + run: | + cd engine/src + python3 flutter/testing/run_tests.py \ + --variant ci/linux_release_arm64 \ + --type engine \ + --engine-capture-core-dump - name: Tar engine/src/out/ci/linux_release_arm64/zip_archives/linux-arm64-release/linux-arm64-flutter-gtk.zip run: | cd engine/src/out/ci/linux_release_arm64/zip_archives/linux-arm64-release @@ -3039,7 +3805,14 @@ jobs: - name: Set up depot_tools if: runner.os != 'Windows' run: | - git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git $HOME/depot_tools + rm -rf "$HOME/depot_tools" + for attempt in 1 2 3; do + git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git "$HOME/depot_tools" && break + rm -rf "$HOME/depot_tools" + echo "depot_tools clone failed (attempt $attempt), retrying..." + sleep 5 + done + test -d "$HOME/depot_tools/.git" # Append depot_tools to the PATH for subsequent steps echo "$HOME/depot_tools" >> $GITHUB_PATH - name: Free disk space @@ -3048,7 +3821,14 @@ jobs: - name: Set up depot_tools if: runner.os == 'Windows' run: | - git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git $HOME/depot_tools + rm -rf "$HOME/depot_tools" + for attempt in 1 2 3; do + git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git "$HOME/depot_tools" && break + rm -rf "$HOME/depot_tools" + echo "depot_tools clone failed (attempt $attempt), retrying..." + sleep 5 + done + test -d "$HOME/depot_tools/.git" # Append depot_tools to the PATH for subsequent steps DEPOT_TOOLS_WIN=$(cygpath -w "$HOME/depot_tools") echo "$DEPOT_TOOLS_WIN" >> $GITHUB_PATH @@ -3094,7 +3874,14 @@ jobs: - name: Set up depot_tools if: runner.os != 'Windows' run: | - git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git $HOME/depot_tools + rm -rf "$HOME/depot_tools" + for attempt in 1 2 3; do + git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git "$HOME/depot_tools" && break + rm -rf "$HOME/depot_tools" + echo "depot_tools clone failed (attempt $attempt), retrying..." + sleep 5 + done + test -d "$HOME/depot_tools/.git" # Append depot_tools to the PATH for subsequent steps echo "$HOME/depot_tools" >> $GITHUB_PATH - name: Free disk space @@ -3103,7 +3890,14 @@ jobs: - name: Set up depot_tools if: runner.os == 'Windows' run: | - git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git $HOME/depot_tools + rm -rf "$HOME/depot_tools" + for attempt in 1 2 3; do + git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git "$HOME/depot_tools" && break + rm -rf "$HOME/depot_tools" + echo "depot_tools clone failed (attempt $attempt), retrying..." + sleep 5 + done + test -d "$HOME/depot_tools/.git" # Append depot_tools to the PATH for subsequent steps DEPOT_TOOLS_WIN=$(cygpath -w "$HOME/depot_tools") echo "$DEPOT_TOOLS_WIN" >> $GITHUB_PATH @@ -3149,7 +3943,14 @@ jobs: - name: Set up depot_tools if: runner.os != 'Windows' run: | - git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git $HOME/depot_tools + rm -rf "$HOME/depot_tools" + for attempt in 1 2 3; do + git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git "$HOME/depot_tools" && break + rm -rf "$HOME/depot_tools" + echo "depot_tools clone failed (attempt $attempt), retrying..." + sleep 5 + done + test -d "$HOME/depot_tools/.git" # Append depot_tools to the PATH for subsequent steps echo "$HOME/depot_tools" >> $GITHUB_PATH - name: Free disk space @@ -3158,7 +3959,14 @@ jobs: - name: Set up depot_tools if: runner.os == 'Windows' run: | - git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git $HOME/depot_tools + rm -rf "$HOME/depot_tools" + for attempt in 1 2 3; do + git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git "$HOME/depot_tools" && break + rm -rf "$HOME/depot_tools" + echo "depot_tools clone failed (attempt $attempt), retrying..." + sleep 5 + done + test -d "$HOME/depot_tools/.git" # Append depot_tools to the PATH for subsequent steps DEPOT_TOOLS_WIN=$(cygpath -w "$HOME/depot_tools") echo "$DEPOT_TOOLS_WIN" >> $GITHUB_PATH @@ -3204,7 +4012,14 @@ jobs: - name: Set up depot_tools if: runner.os != 'Windows' run: | - git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git $HOME/depot_tools + rm -rf "$HOME/depot_tools" + for attempt in 1 2 3; do + git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git "$HOME/depot_tools" && break + rm -rf "$HOME/depot_tools" + echo "depot_tools clone failed (attempt $attempt), retrying..." + sleep 5 + done + test -d "$HOME/depot_tools/.git" # Append depot_tools to the PATH for subsequent steps echo "$HOME/depot_tools" >> $GITHUB_PATH - name: Free disk space @@ -3213,7 +4028,14 @@ jobs: - name: Set up depot_tools if: runner.os == 'Windows' run: | - git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git $HOME/depot_tools + rm -rf "$HOME/depot_tools" + for attempt in 1 2 3; do + git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git "$HOME/depot_tools" && break + rm -rf "$HOME/depot_tools" + echo "depot_tools clone failed (attempt $attempt), retrying..." + sleep 5 + done + test -d "$HOME/depot_tools/.git" # Append depot_tools to the PATH for subsequent steps DEPOT_TOOLS_WIN=$(cygpath -w "$HOME/depot_tools") echo "$DEPOT_TOOLS_WIN" >> $GITHUB_PATH @@ -3259,7 +4081,14 @@ jobs: - name: Set up depot_tools if: runner.os != 'Windows' run: | - git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git $HOME/depot_tools + rm -rf "$HOME/depot_tools" + for attempt in 1 2 3; do + git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git "$HOME/depot_tools" && break + rm -rf "$HOME/depot_tools" + echo "depot_tools clone failed (attempt $attempt), retrying..." + sleep 5 + done + test -d "$HOME/depot_tools/.git" # Append depot_tools to the PATH for subsequent steps echo "$HOME/depot_tools" >> $GITHUB_PATH - name: Free disk space @@ -3268,7 +4097,14 @@ jobs: - name: Set up depot_tools if: runner.os == 'Windows' run: | - git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git $HOME/depot_tools + rm -rf "$HOME/depot_tools" + for attempt in 1 2 3; do + git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git "$HOME/depot_tools" && break + rm -rf "$HOME/depot_tools" + echo "depot_tools clone failed (attempt $attempt), retrying..." + sleep 5 + done + test -d "$HOME/depot_tools/.git" # Append depot_tools to the PATH for subsequent steps DEPOT_TOOLS_WIN=$(cygpath -w "$HOME/depot_tools") echo "$DEPOT_TOOLS_WIN" >> $GITHUB_PATH @@ -3314,7 +4150,14 @@ jobs: - name: Set up depot_tools if: runner.os != 'Windows' run: | - git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git $HOME/depot_tools + rm -rf "$HOME/depot_tools" + for attempt in 1 2 3; do + git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git "$HOME/depot_tools" && break + rm -rf "$HOME/depot_tools" + echo "depot_tools clone failed (attempt $attempt), retrying..." + sleep 5 + done + test -d "$HOME/depot_tools/.git" # Append depot_tools to the PATH for subsequent steps echo "$HOME/depot_tools" >> $GITHUB_PATH - name: Free disk space @@ -3323,7 +4166,14 @@ jobs: - name: Set up depot_tools if: runner.os == 'Windows' run: | - git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git $HOME/depot_tools + rm -rf "$HOME/depot_tools" + for attempt in 1 2 3; do + git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git "$HOME/depot_tools" && break + rm -rf "$HOME/depot_tools" + echo "depot_tools clone failed (attempt $attempt), retrying..." + sleep 5 + done + test -d "$HOME/depot_tools/.git" # Append depot_tools to the PATH for subsequent steps DEPOT_TOOLS_WIN=$(cygpath -w "$HOME/depot_tools") echo "$DEPOT_TOOLS_WIN" >> $GITHUB_PATH @@ -3369,7 +4219,14 @@ jobs: - name: Set up depot_tools if: runner.os != 'Windows' run: | - git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git $HOME/depot_tools + rm -rf "$HOME/depot_tools" + for attempt in 1 2 3; do + git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git "$HOME/depot_tools" && break + rm -rf "$HOME/depot_tools" + echo "depot_tools clone failed (attempt $attempt), retrying..." + sleep 5 + done + test -d "$HOME/depot_tools/.git" # Append depot_tools to the PATH for subsequent steps echo "$HOME/depot_tools" >> $GITHUB_PATH - name: Free disk space @@ -3378,7 +4235,14 @@ jobs: - name: Set up depot_tools if: runner.os == 'Windows' run: | - git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git $HOME/depot_tools + rm -rf "$HOME/depot_tools" + for attempt in 1 2 3; do + git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git "$HOME/depot_tools" && break + rm -rf "$HOME/depot_tools" + echo "depot_tools clone failed (attempt $attempt), retrying..." + sleep 5 + done + test -d "$HOME/depot_tools/.git" # Append depot_tools to the PATH for subsequent steps DEPOT_TOOLS_WIN=$(cygpath -w "$HOME/depot_tools") echo "$DEPOT_TOOLS_WIN" >> $GITHUB_PATH @@ -3423,7 +4287,14 @@ jobs: - name: Set up depot_tools if: runner.os != 'Windows' run: | - git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git $HOME/depot_tools + rm -rf "$HOME/depot_tools" + for attempt in 1 2 3; do + git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git "$HOME/depot_tools" && break + rm -rf "$HOME/depot_tools" + echo "depot_tools clone failed (attempt $attempt), retrying..." + sleep 5 + done + test -d "$HOME/depot_tools/.git" # Append depot_tools to the PATH for subsequent steps echo "$HOME/depot_tools" >> $GITHUB_PATH - name: Free disk space @@ -3432,7 +4303,14 @@ jobs: - name: Set up depot_tools if: runner.os == 'Windows' run: | - git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git $HOME/depot_tools + rm -rf "$HOME/depot_tools" + for attempt in 1 2 3; do + git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git "$HOME/depot_tools" && break + rm -rf "$HOME/depot_tools" + echo "depot_tools clone failed (attempt $attempt), retrying..." + sleep 5 + done + test -d "$HOME/depot_tools/.git" # Append depot_tools to the PATH for subsequent steps DEPOT_TOOLS_WIN=$(cygpath -w "$HOME/depot_tools") echo "$DEPOT_TOOLS_WIN" >> $GITHUB_PATH @@ -3477,7 +4355,14 @@ jobs: - name: Set up depot_tools if: runner.os != 'Windows' run: | - git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git $HOME/depot_tools + rm -rf "$HOME/depot_tools" + for attempt in 1 2 3; do + git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git "$HOME/depot_tools" && break + rm -rf "$HOME/depot_tools" + echo "depot_tools clone failed (attempt $attempt), retrying..." + sleep 5 + done + test -d "$HOME/depot_tools/.git" # Append depot_tools to the PATH for subsequent steps echo "$HOME/depot_tools" >> $GITHUB_PATH - name: Free disk space @@ -3486,7 +4371,14 @@ jobs: - name: Set up depot_tools if: runner.os == 'Windows' run: | - git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git $HOME/depot_tools + rm -rf "$HOME/depot_tools" + for attempt in 1 2 3; do + git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git "$HOME/depot_tools" && break + rm -rf "$HOME/depot_tools" + echo "depot_tools clone failed (attempt $attempt), retrying..." + sleep 5 + done + test -d "$HOME/depot_tools/.git" # Append depot_tools to the PATH for subsequent steps DEPOT_TOOLS_WIN=$(cygpath -w "$HOME/depot_tools") echo "$DEPOT_TOOLS_WIN" >> $GITHUB_PATH @@ -3531,7 +4423,14 @@ jobs: - name: Set up depot_tools if: runner.os != 'Windows' run: | - git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git $HOME/depot_tools + rm -rf "$HOME/depot_tools" + for attempt in 1 2 3; do + git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git "$HOME/depot_tools" && break + rm -rf "$HOME/depot_tools" + echo "depot_tools clone failed (attempt $attempt), retrying..." + sleep 5 + done + test -d "$HOME/depot_tools/.git" # Append depot_tools to the PATH for subsequent steps echo "$HOME/depot_tools" >> $GITHUB_PATH - name: Free disk space @@ -3540,7 +4439,14 @@ jobs: - name: Set up depot_tools if: runner.os == 'Windows' run: | - git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git $HOME/depot_tools + rm -rf "$HOME/depot_tools" + for attempt in 1 2 3; do + git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git "$HOME/depot_tools" && break + rm -rf "$HOME/depot_tools" + echo "depot_tools clone failed (attempt $attempt), retrying..." + sleep 5 + done + test -d "$HOME/depot_tools/.git" # Append depot_tools to the PATH for subsequent steps DEPOT_TOOLS_WIN=$(cygpath -w "$HOME/depot_tools") echo "$DEPOT_TOOLS_WIN" >> $GITHUB_PATH @@ -3585,7 +4491,14 @@ jobs: - name: Set up depot_tools if: runner.os != 'Windows' run: | - git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git $HOME/depot_tools + rm -rf "$HOME/depot_tools" + for attempt in 1 2 3; do + git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git "$HOME/depot_tools" && break + rm -rf "$HOME/depot_tools" + echo "depot_tools clone failed (attempt $attempt), retrying..." + sleep 5 + done + test -d "$HOME/depot_tools/.git" # Append depot_tools to the PATH for subsequent steps echo "$HOME/depot_tools" >> $GITHUB_PATH - name: Free disk space @@ -3594,7 +4507,14 @@ jobs: - name: Set up depot_tools if: runner.os == 'Windows' run: | - git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git $HOME/depot_tools + rm -rf "$HOME/depot_tools" + for attempt in 1 2 3; do + git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git "$HOME/depot_tools" && break + rm -rf "$HOME/depot_tools" + echo "depot_tools clone failed (attempt $attempt), retrying..." + sleep 5 + done + test -d "$HOME/depot_tools/.git" # Append depot_tools to the PATH for subsequent steps DEPOT_TOOLS_WIN=$(cygpath -w "$HOME/depot_tools") echo "$DEPOT_TOOLS_WIN" >> $GITHUB_PATH @@ -3639,7 +4559,14 @@ jobs: - name: Set up depot_tools if: runner.os != 'Windows' run: | - git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git $HOME/depot_tools + rm -rf "$HOME/depot_tools" + for attempt in 1 2 3; do + git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git "$HOME/depot_tools" && break + rm -rf "$HOME/depot_tools" + echo "depot_tools clone failed (attempt $attempt), retrying..." + sleep 5 + done + test -d "$HOME/depot_tools/.git" # Append depot_tools to the PATH for subsequent steps echo "$HOME/depot_tools" >> $GITHUB_PATH - name: Free disk space @@ -3648,7 +4575,14 @@ jobs: - name: Set up depot_tools if: runner.os == 'Windows' run: | - git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git $HOME/depot_tools + rm -rf "$HOME/depot_tools" + for attempt in 1 2 3; do + git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git "$HOME/depot_tools" && break + rm -rf "$HOME/depot_tools" + echo "depot_tools clone failed (attempt $attempt), retrying..." + sleep 5 + done + test -d "$HOME/depot_tools/.git" # Append depot_tools to the PATH for subsequent steps DEPOT_TOOLS_WIN=$(cygpath -w "$HOME/depot_tools") echo "$DEPOT_TOOLS_WIN" >> $GITHUB_PATH @@ -3693,7 +4627,14 @@ jobs: - name: Set up depot_tools if: runner.os != 'Windows' run: | - git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git $HOME/depot_tools + rm -rf "$HOME/depot_tools" + for attempt in 1 2 3; do + git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git "$HOME/depot_tools" && break + rm -rf "$HOME/depot_tools" + echo "depot_tools clone failed (attempt $attempt), retrying..." + sleep 5 + done + test -d "$HOME/depot_tools/.git" # Append depot_tools to the PATH for subsequent steps echo "$HOME/depot_tools" >> $GITHUB_PATH - name: Free disk space @@ -3702,7 +4643,14 @@ jobs: - name: Set up depot_tools if: runner.os == 'Windows' run: | - git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git $HOME/depot_tools + rm -rf "$HOME/depot_tools" + for attempt in 1 2 3; do + git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git "$HOME/depot_tools" && break + rm -rf "$HOME/depot_tools" + echo "depot_tools clone failed (attempt $attempt), retrying..." + sleep 5 + done + test -d "$HOME/depot_tools/.git" # Append depot_tools to the PATH for subsequent steps DEPOT_TOOLS_WIN=$(cygpath -w "$HOME/depot_tools") echo "$DEPOT_TOOLS_WIN" >> $GITHUB_PATH @@ -3723,6 +4671,7 @@ jobs: ./flutter/bin/et build --config ci/android_profile - name: Tar build files run: | + find engine/src/out/ci/android_profile -type l -lname "/*" -delete || true tar -cvf linux_android_profile.tar engine/src/out/ci/android_profile - name: Upload build files uses: actions/upload-artifact@v4 @@ -3786,7 +4735,14 @@ jobs: - name: Set up depot_tools if: runner.os != 'Windows' run: | - git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git $HOME/depot_tools + rm -rf "$HOME/depot_tools" + for attempt in 1 2 3; do + git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git "$HOME/depot_tools" && break + rm -rf "$HOME/depot_tools" + echo "depot_tools clone failed (attempt $attempt), retrying..." + sleep 5 + done + test -d "$HOME/depot_tools/.git" # Append depot_tools to the PATH for subsequent steps echo "$HOME/depot_tools" >> $GITHUB_PATH - name: Free disk space @@ -3795,7 +4751,14 @@ jobs: - name: Set up depot_tools if: runner.os == 'Windows' run: | - git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git $HOME/depot_tools + rm -rf "$HOME/depot_tools" + for attempt in 1 2 3; do + git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git "$HOME/depot_tools" && break + rm -rf "$HOME/depot_tools" + echo "depot_tools clone failed (attempt $attempt), retrying..." + sleep 5 + done + test -d "$HOME/depot_tools/.git" # Append depot_tools to the PATH for subsequent steps DEPOT_TOOLS_WIN=$(cygpath -w "$HOME/depot_tools") echo "$DEPOT_TOOLS_WIN" >> $GITHUB_PATH @@ -3816,6 +4779,7 @@ jobs: ./flutter/bin/et build --config ci/android_release - name: Tar build files run: | + find engine/src/out/ci/android_release -type l -lname "/*" -delete || true tar -cvf linux_android_release.tar engine/src/out/ci/android_release - name: Upload build files uses: actions/upload-artifact@v4 @@ -3879,7 +4843,14 @@ jobs: - name: Set up depot_tools if: runner.os != 'Windows' run: | - git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git $HOME/depot_tools + rm -rf "$HOME/depot_tools" + for attempt in 1 2 3; do + git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git "$HOME/depot_tools" && break + rm -rf "$HOME/depot_tools" + echo "depot_tools clone failed (attempt $attempt), retrying..." + sleep 5 + done + test -d "$HOME/depot_tools/.git" # Append depot_tools to the PATH for subsequent steps echo "$HOME/depot_tools" >> $GITHUB_PATH - name: Free disk space @@ -3888,7 +4859,14 @@ jobs: - name: Set up depot_tools if: runner.os == 'Windows' run: | - git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git $HOME/depot_tools + rm -rf "$HOME/depot_tools" + for attempt in 1 2 3; do + git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git "$HOME/depot_tools" && break + rm -rf "$HOME/depot_tools" + echo "depot_tools clone failed (attempt $attempt), retrying..." + sleep 5 + done + test -d "$HOME/depot_tools/.git" # Append depot_tools to the PATH for subsequent steps DEPOT_TOOLS_WIN=$(cygpath -w "$HOME/depot_tools") echo "$DEPOT_TOOLS_WIN" >> $GITHUB_PATH @@ -3909,6 +4887,7 @@ jobs: ./flutter/bin/et build --config ci/android_release_arm64 - name: Tar build files run: | + find engine/src/out/ci/android_release_arm64 -type l -lname "/*" -delete || true tar -cvf linux_android_release_arm64.tar engine/src/out/ci/android_release_arm64 - name: Upload build files uses: actions/upload-artifact@v4 @@ -3982,7 +4961,14 @@ jobs: - name: Set up depot_tools if: runner.os != 'Windows' run: | - git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git $HOME/depot_tools + rm -rf "$HOME/depot_tools" + for attempt in 1 2 3; do + git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git "$HOME/depot_tools" && break + rm -rf "$HOME/depot_tools" + echo "depot_tools clone failed (attempt $attempt), retrying..." + sleep 5 + done + test -d "$HOME/depot_tools/.git" # Append depot_tools to the PATH for subsequent steps echo "$HOME/depot_tools" >> $GITHUB_PATH - name: Free disk space @@ -3991,7 +4977,14 @@ jobs: - name: Set up depot_tools if: runner.os == 'Windows' run: | - git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git $HOME/depot_tools + rm -rf "$HOME/depot_tools" + for attempt in 1 2 3; do + git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git "$HOME/depot_tools" && break + rm -rf "$HOME/depot_tools" + echo "depot_tools clone failed (attempt $attempt), retrying..." + sleep 5 + done + test -d "$HOME/depot_tools/.git" # Append depot_tools to the PATH for subsequent steps DEPOT_TOOLS_WIN=$(cygpath -w "$HOME/depot_tools") echo "$DEPOT_TOOLS_WIN" >> $GITHUB_PATH @@ -4012,6 +5005,7 @@ jobs: ./flutter/bin/et build --config ci/android_profile_arm64 - name: Tar build files run: | + find engine/src/out/ci/android_profile_arm64 -type l -lname "/*" -delete || true tar -cvf linux_android_profile_arm64.tar engine/src/out/ci/android_profile_arm64 - name: Upload build files uses: actions/upload-artifact@v4 @@ -4085,7 +5079,14 @@ jobs: - name: Set up depot_tools if: runner.os != 'Windows' run: | - git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git $HOME/depot_tools + rm -rf "$HOME/depot_tools" + for attempt in 1 2 3; do + git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git "$HOME/depot_tools" && break + rm -rf "$HOME/depot_tools" + echo "depot_tools clone failed (attempt $attempt), retrying..." + sleep 5 + done + test -d "$HOME/depot_tools/.git" # Append depot_tools to the PATH for subsequent steps echo "$HOME/depot_tools" >> $GITHUB_PATH - name: Free disk space @@ -4094,7 +5095,14 @@ jobs: - name: Set up depot_tools if: runner.os == 'Windows' run: | - git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git $HOME/depot_tools + rm -rf "$HOME/depot_tools" + for attempt in 1 2 3; do + git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git "$HOME/depot_tools" && break + rm -rf "$HOME/depot_tools" + echo "depot_tools clone failed (attempt $attempt), retrying..." + sleep 5 + done + test -d "$HOME/depot_tools/.git" # Append depot_tools to the PATH for subsequent steps DEPOT_TOOLS_WIN=$(cygpath -w "$HOME/depot_tools") echo "$DEPOT_TOOLS_WIN" >> $GITHUB_PATH @@ -4115,6 +5123,7 @@ jobs: ./flutter/bin/et build --config ci/android_profile_x64 - name: Tar build files run: | + find engine/src/out/ci/android_profile_x64 -type l -lname "/*" -delete || true tar -cvf linux_android_profile_x64.tar engine/src/out/ci/android_profile_x64 - name: Upload build files uses: actions/upload-artifact@v4 @@ -4188,7 +5197,14 @@ jobs: - name: Set up depot_tools if: runner.os != 'Windows' run: | - git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git $HOME/depot_tools + rm -rf "$HOME/depot_tools" + for attempt in 1 2 3; do + git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git "$HOME/depot_tools" && break + rm -rf "$HOME/depot_tools" + echo "depot_tools clone failed (attempt $attempt), retrying..." + sleep 5 + done + test -d "$HOME/depot_tools/.git" # Append depot_tools to the PATH for subsequent steps echo "$HOME/depot_tools" >> $GITHUB_PATH - name: Free disk space @@ -4197,7 +5213,14 @@ jobs: - name: Set up depot_tools if: runner.os == 'Windows' run: | - git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git $HOME/depot_tools + rm -rf "$HOME/depot_tools" + for attempt in 1 2 3; do + git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git "$HOME/depot_tools" && break + rm -rf "$HOME/depot_tools" + echo "depot_tools clone failed (attempt $attempt), retrying..." + sleep 5 + done + test -d "$HOME/depot_tools/.git" # Append depot_tools to the PATH for subsequent steps DEPOT_TOOLS_WIN=$(cygpath -w "$HOME/depot_tools") echo "$DEPOT_TOOLS_WIN" >> $GITHUB_PATH @@ -4218,6 +5241,7 @@ jobs: ./flutter/bin/et build --config ci/android_release_x64 - name: Tar build files run: | + find engine/src/out/ci/android_release_x64 -type l -lname "/*" -delete || true tar -cvf linux_android_release_x64.tar engine/src/out/ci/android_release_x64 - name: Upload build files uses: actions/upload-artifact@v4 @@ -4291,7 +5315,14 @@ jobs: - name: Set up depot_tools if: runner.os != 'Windows' run: | - git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git $HOME/depot_tools + rm -rf "$HOME/depot_tools" + for attempt in 1 2 3; do + git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git "$HOME/depot_tools" && break + rm -rf "$HOME/depot_tools" + echo "depot_tools clone failed (attempt $attempt), retrying..." + sleep 5 + done + test -d "$HOME/depot_tools/.git" # Append depot_tools to the PATH for subsequent steps echo "$HOME/depot_tools" >> $GITHUB_PATH - name: Free disk space @@ -4300,7 +5331,14 @@ jobs: - name: Set up depot_tools if: runner.os == 'Windows' run: | - git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git $HOME/depot_tools + rm -rf "$HOME/depot_tools" + for attempt in 1 2 3; do + git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git "$HOME/depot_tools" && break + rm -rf "$HOME/depot_tools" + echo "depot_tools clone failed (attempt $attempt), retrying..." + sleep 5 + done + test -d "$HOME/depot_tools/.git" # Append depot_tools to the PATH for subsequent steps DEPOT_TOOLS_WIN=$(cygpath -w "$HOME/depot_tools") echo "$DEPOT_TOOLS_WIN" >> $GITHUB_PATH @@ -4321,6 +5359,7 @@ jobs: ./flutter/bin/et build --config ci/android_profile_riscv64 - name: Tar build files run: | + find engine/src/out/ci/android_profile_riscv64 -type l -lname "/*" -delete || true tar -cvf linux_android_profile_riscv64.tar engine/src/out/ci/android_profile_riscv64 - name: Upload build files uses: actions/upload-artifact@v4 @@ -4394,7 +5433,14 @@ jobs: - name: Set up depot_tools if: runner.os != 'Windows' run: | - git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git $HOME/depot_tools + rm -rf "$HOME/depot_tools" + for attempt in 1 2 3; do + git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git "$HOME/depot_tools" && break + rm -rf "$HOME/depot_tools" + echo "depot_tools clone failed (attempt $attempt), retrying..." + sleep 5 + done + test -d "$HOME/depot_tools/.git" # Append depot_tools to the PATH for subsequent steps echo "$HOME/depot_tools" >> $GITHUB_PATH - name: Free disk space @@ -4403,7 +5449,14 @@ jobs: - name: Set up depot_tools if: runner.os == 'Windows' run: | - git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git $HOME/depot_tools + rm -rf "$HOME/depot_tools" + for attempt in 1 2 3; do + git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git "$HOME/depot_tools" && break + rm -rf "$HOME/depot_tools" + echo "depot_tools clone failed (attempt $attempt), retrying..." + sleep 5 + done + test -d "$HOME/depot_tools/.git" # Append depot_tools to the PATH for subsequent steps DEPOT_TOOLS_WIN=$(cygpath -w "$HOME/depot_tools") echo "$DEPOT_TOOLS_WIN" >> $GITHUB_PATH @@ -4424,6 +5477,7 @@ jobs: ./flutter/bin/et build --config ci/android_release_riscv64 - name: Tar build files run: | + find engine/src/out/ci/android_release_riscv64 -type l -lname "/*" -delete || true tar -cvf linux_android_release_riscv64.tar engine/src/out/ci/android_release_riscv64 - name: Upload build files uses: actions/upload-artifact@v4 @@ -4505,7 +5559,14 @@ jobs: - name: Set up depot_tools if: runner.os != 'Windows' run: | - git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git $HOME/depot_tools + rm -rf "$HOME/depot_tools" + for attempt in 1 2 3; do + git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git "$HOME/depot_tools" && break + rm -rf "$HOME/depot_tools" + echo "depot_tools clone failed (attempt $attempt), retrying..." + sleep 5 + done + test -d "$HOME/depot_tools/.git" # Append depot_tools to the PATH for subsequent steps echo "$HOME/depot_tools" >> $GITHUB_PATH - name: Free disk space @@ -4514,7 +5575,14 @@ jobs: - name: Set up depot_tools if: runner.os == 'Windows' run: | - git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git $HOME/depot_tools + rm -rf "$HOME/depot_tools" + for attempt in 1 2 3; do + git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git "$HOME/depot_tools" && break + rm -rf "$HOME/depot_tools" + echo "depot_tools clone failed (attempt $attempt), retrying..." + sleep 5 + done + test -d "$HOME/depot_tools/.git" # Append depot_tools to the PATH for subsequent steps DEPOT_TOOLS_WIN=$(cygpath -w "$HOME/depot_tools") echo "$DEPOT_TOOLS_WIN" >> $GITHUB_PATH @@ -4615,7 +5683,14 @@ jobs: - name: Set up depot_tools if: runner.os != 'Windows' run: | - git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git $HOME/depot_tools + rm -rf "$HOME/depot_tools" + for attempt in 1 2 3; do + git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git "$HOME/depot_tools" && break + rm -rf "$HOME/depot_tools" + echo "depot_tools clone failed (attempt $attempt), retrying..." + sleep 5 + done + test -d "$HOME/depot_tools/.git" # Append depot_tools to the PATH for subsequent steps echo "$HOME/depot_tools" >> $GITHUB_PATH - name: Free disk space @@ -4624,7 +5699,14 @@ jobs: - name: Set up depot_tools if: runner.os == 'Windows' run: | - git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git $HOME/depot_tools + rm -rf "$HOME/depot_tools" + for attempt in 1 2 3; do + git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git "$HOME/depot_tools" && break + rm -rf "$HOME/depot_tools" + echo "depot_tools clone failed (attempt $attempt), retrying..." + sleep 5 + done + test -d "$HOME/depot_tools/.git" # Append depot_tools to the PATH for subsequent steps DEPOT_TOOLS_WIN=$(cygpath -w "$HOME/depot_tools") echo "$DEPOT_TOOLS_WIN" >> $GITHUB_PATH @@ -4645,6 +5727,7 @@ jobs: ./flutter/bin/et build --config ci/android_debug - name: Tar build files run: | + find engine/src/out/ci/android_debug -type l -lname "/*" -delete || true tar -cvf linux_android_debug.tar engine/src/out/ci/android_debug - name: Upload build files uses: actions/upload-artifact@v4 @@ -4728,7 +5811,14 @@ jobs: - name: Set up depot_tools if: runner.os != 'Windows' run: | - git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git $HOME/depot_tools + rm -rf "$HOME/depot_tools" + for attempt in 1 2 3; do + git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git "$HOME/depot_tools" && break + rm -rf "$HOME/depot_tools" + echo "depot_tools clone failed (attempt $attempt), retrying..." + sleep 5 + done + test -d "$HOME/depot_tools/.git" # Append depot_tools to the PATH for subsequent steps echo "$HOME/depot_tools" >> $GITHUB_PATH - name: Free disk space @@ -4737,7 +5827,14 @@ jobs: - name: Set up depot_tools if: runner.os == 'Windows' run: | - git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git $HOME/depot_tools + rm -rf "$HOME/depot_tools" + for attempt in 1 2 3; do + git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git "$HOME/depot_tools" && break + rm -rf "$HOME/depot_tools" + echo "depot_tools clone failed (attempt $attempt), retrying..." + sleep 5 + done + test -d "$HOME/depot_tools/.git" # Append depot_tools to the PATH for subsequent steps DEPOT_TOOLS_WIN=$(cygpath -w "$HOME/depot_tools") echo "$DEPOT_TOOLS_WIN" >> $GITHUB_PATH @@ -4758,6 +5855,7 @@ jobs: ./flutter/bin/et build --config ci/android_debug_arm64 - name: Tar build files run: | + find engine/src/out/ci/android_debug_arm64 -type l -lname "/*" -delete || true tar -cvf linux_android_debug_arm64.tar engine/src/out/ci/android_debug_arm64 - name: Upload build files uses: actions/upload-artifact@v4 @@ -4821,7 +5919,14 @@ jobs: - name: Set up depot_tools if: runner.os != 'Windows' run: | - git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git $HOME/depot_tools + rm -rf "$HOME/depot_tools" + for attempt in 1 2 3; do + git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git "$HOME/depot_tools" && break + rm -rf "$HOME/depot_tools" + echo "depot_tools clone failed (attempt $attempt), retrying..." + sleep 5 + done + test -d "$HOME/depot_tools/.git" # Append depot_tools to the PATH for subsequent steps echo "$HOME/depot_tools" >> $GITHUB_PATH - name: Free disk space @@ -4830,7 +5935,14 @@ jobs: - name: Set up depot_tools if: runner.os == 'Windows' run: | - git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git $HOME/depot_tools + rm -rf "$HOME/depot_tools" + for attempt in 1 2 3; do + git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git "$HOME/depot_tools" && break + rm -rf "$HOME/depot_tools" + echo "depot_tools clone failed (attempt $attempt), retrying..." + sleep 5 + done + test -d "$HOME/depot_tools/.git" # Append depot_tools to the PATH for subsequent steps DEPOT_TOOLS_WIN=$(cygpath -w "$HOME/depot_tools") echo "$DEPOT_TOOLS_WIN" >> $GITHUB_PATH @@ -4851,6 +5963,7 @@ jobs: ./flutter/bin/et build --config ci/android_debug_x86 - name: Tar build files run: | + find engine/src/out/ci/android_debug_x86 -type l -lname "/*" -delete || true tar -cvf linux_android_debug_x86.tar engine/src/out/ci/android_debug_x86 - name: Upload build files uses: actions/upload-artifact@v4 @@ -4914,7 +6027,14 @@ jobs: - name: Set up depot_tools if: runner.os != 'Windows' run: | - git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git $HOME/depot_tools + rm -rf "$HOME/depot_tools" + for attempt in 1 2 3; do + git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git "$HOME/depot_tools" && break + rm -rf "$HOME/depot_tools" + echo "depot_tools clone failed (attempt $attempt), retrying..." + sleep 5 + done + test -d "$HOME/depot_tools/.git" # Append depot_tools to the PATH for subsequent steps echo "$HOME/depot_tools" >> $GITHUB_PATH - name: Free disk space @@ -4923,7 +6043,14 @@ jobs: - name: Set up depot_tools if: runner.os == 'Windows' run: | - git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git $HOME/depot_tools + rm -rf "$HOME/depot_tools" + for attempt in 1 2 3; do + git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git "$HOME/depot_tools" && break + rm -rf "$HOME/depot_tools" + echo "depot_tools clone failed (attempt $attempt), retrying..." + sleep 5 + done + test -d "$HOME/depot_tools/.git" # Append depot_tools to the PATH for subsequent steps DEPOT_TOOLS_WIN=$(cygpath -w "$HOME/depot_tools") echo "$DEPOT_TOOLS_WIN" >> $GITHUB_PATH @@ -4944,6 +6071,7 @@ jobs: ./flutter/bin/et build --config ci/android_debug_x64 - name: Tar build files run: | + find engine/src/out/ci/android_debug_x64 -type l -lname "/*" -delete || true tar -cvf linux_android_debug_x64.tar engine/src/out/ci/android_debug_x64 - name: Upload build files uses: actions/upload-artifact@v4 @@ -5007,7 +6135,14 @@ jobs: - name: Set up depot_tools if: runner.os != 'Windows' run: | - git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git $HOME/depot_tools + rm -rf "$HOME/depot_tools" + for attempt in 1 2 3; do + git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git "$HOME/depot_tools" && break + rm -rf "$HOME/depot_tools" + echo "depot_tools clone failed (attempt $attempt), retrying..." + sleep 5 + done + test -d "$HOME/depot_tools/.git" # Append depot_tools to the PATH for subsequent steps echo "$HOME/depot_tools" >> $GITHUB_PATH - name: Free disk space @@ -5016,7 +6151,14 @@ jobs: - name: Set up depot_tools if: runner.os == 'Windows' run: | - git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git $HOME/depot_tools + rm -rf "$HOME/depot_tools" + for attempt in 1 2 3; do + git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git "$HOME/depot_tools" && break + rm -rf "$HOME/depot_tools" + echo "depot_tools clone failed (attempt $attempt), retrying..." + sleep 5 + done + test -d "$HOME/depot_tools/.git" # Append depot_tools to the PATH for subsequent steps DEPOT_TOOLS_WIN=$(cygpath -w "$HOME/depot_tools") echo "$DEPOT_TOOLS_WIN" >> $GITHUB_PATH @@ -5037,6 +6179,7 @@ jobs: ./flutter/bin/et build --config ci/android_debug_riscv64 - name: Tar build files run: | + find engine/src/out/ci/android_debug_riscv64 -type l -lname "/*" -delete || true tar -cvf linux_android_debug_riscv64.tar engine/src/out/ci/android_debug_riscv64 - name: Upload build files uses: actions/upload-artifact@v4 @@ -5105,7 +6248,14 @@ jobs: - name: Set up depot_tools if: runner.os != 'Windows' run: | - git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git $HOME/depot_tools + rm -rf "$HOME/depot_tools" + for attempt in 1 2 3; do + git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git "$HOME/depot_tools" && break + rm -rf "$HOME/depot_tools" + echo "depot_tools clone failed (attempt $attempt), retrying..." + sleep 5 + done + test -d "$HOME/depot_tools/.git" # Append depot_tools to the PATH for subsequent steps echo "$HOME/depot_tools" >> $GITHUB_PATH - name: Free disk space @@ -5114,7 +6264,14 @@ jobs: - name: Set up depot_tools if: runner.os == 'Windows' run: | - git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git $HOME/depot_tools + rm -rf "$HOME/depot_tools" + for attempt in 1 2 3; do + git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git "$HOME/depot_tools" && break + rm -rf "$HOME/depot_tools" + echo "depot_tools clone failed (attempt $attempt), retrying..." + sleep 5 + done + test -d "$HOME/depot_tools/.git" # Append depot_tools to the PATH for subsequent steps DEPOT_TOOLS_WIN=$(cygpath -w "$HOME/depot_tools") echo "$DEPOT_TOOLS_WIN" >> $GITHUB_PATH @@ -5191,7 +6348,14 @@ jobs: - name: Set up depot_tools if: runner.os != 'Windows' run: | - git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git $HOME/depot_tools + rm -rf "$HOME/depot_tools" + for attempt in 1 2 3; do + git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git "$HOME/depot_tools" && break + rm -rf "$HOME/depot_tools" + echo "depot_tools clone failed (attempt $attempt), retrying..." + sleep 5 + done + test -d "$HOME/depot_tools/.git" # Append depot_tools to the PATH for subsequent steps echo "$HOME/depot_tools" >> $GITHUB_PATH - name: Free disk space @@ -5200,7 +6364,14 @@ jobs: - name: Set up depot_tools if: runner.os == 'Windows' run: | - git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git $HOME/depot_tools + rm -rf "$HOME/depot_tools" + for attempt in 1 2 3; do + git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git "$HOME/depot_tools" && break + rm -rf "$HOME/depot_tools" + echo "depot_tools clone failed (attempt $attempt), retrying..." + sleep 5 + done + test -d "$HOME/depot_tools/.git" # Append depot_tools to the PATH for subsequent steps DEPOT_TOOLS_WIN=$(cygpath -w "$HOME/depot_tools") echo "$DEPOT_TOOLS_WIN" >> $GITHUB_PATH @@ -5229,6 +6400,112 @@ jobs: name: artifact_${{ steps.engine_content_hash.outputs.value }}_133 path: engine/src/out/wasm_release/zip_archives/artifact_133.tar retention-days: 1 + ios_unit_engine_test: + runs-on: macos-latest + defaults: + run: + shell: bash + needs: + - mac_ios_test_binaries_arm64 + - guard + if: ${{ needs.guard.outputs.should_run == 'true' }} + steps: + - name: Checkout the repository + uses: actions/checkout@v4 + with: + path: '' + - name: Set up depot_tools + run: | + rm -rf "$HOME/depot_tools" + for attempt in 1 2 3; do + git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git "$HOME/depot_tools" && break + rm -rf "$HOME/depot_tools" + echo "depot_tools clone failed (attempt $attempt), retrying..." + sleep 5 + done + test -d "$HOME/depot_tools/.git" + # Append depot_tools to the PATH for subsequent steps + echo "$HOME/depot_tools" >> $GITHUB_PATH + - name: Expose engine content hash + id: engine_content_hash + run: | + engine_content_hash=${{ needs.guard.outputs.engine_content_hash }} + echo "value=${engine_content_hash}" >> $GITHUB_OUTPUT + - name: Copy gclient file + run: | + cp engine/scripts/slim.gclient .gclient + - name: GClient sync + run: | + gclient sync -D --no-history --shallow --with_branch_heads + - name: Download Artifacts from mac_ios_test_binaries_arm64 + uses: actions/download-artifact@v4 + with: + name: artifacts-mac_ios_test_binaries_arm64-${{ steps.engine_content_hash.outputs.value }} + - name: Extract Artifacts from mac_ios_test_binaries_arm64 + run: | + tar -xvf mac_ios_test_binaries_arm64.tar + rm mac_ios_test_binaries_arm64.tar + - name: Run test iOS unit tests for ci/ios_test_binaries_arm64 + run: | + cd engine/src + python3 flutter/testing/run_tests.py \ + --variant ci/ios_test_binaries_arm64 \ + --type objc \ + --ios-variant ci/ios_test_binaries_arm64 \ + --engine-capture-core-dump + android_java_engine_test: + runs-on: ubuntu-latest + defaults: + run: + shell: bash + needs: + - linux_android_debug_arm64 + - guard + if: ${{ needs.guard.outputs.should_run == 'true' }} + steps: + - name: Checkout the repository + uses: actions/checkout@v4 + with: + path: '' + - name: Set up depot_tools + run: | + rm -rf "$HOME/depot_tools" + for attempt in 1 2 3; do + git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git "$HOME/depot_tools" && break + rm -rf "$HOME/depot_tools" + echo "depot_tools clone failed (attempt $attempt), retrying..." + sleep 5 + done + test -d "$HOME/depot_tools/.git" + # Append depot_tools to the PATH for subsequent steps + echo "$HOME/depot_tools" >> $GITHUB_PATH + - name: Expose engine content hash + id: engine_content_hash + run: | + engine_content_hash=${{ needs.guard.outputs.engine_content_hash }} + echo "value=${engine_content_hash}" >> $GITHUB_OUTPUT + - name: Copy gclient file + run: | + cp engine/scripts/standard.gclient .gclient + - name: GClient sync + run: | + gclient sync -D --no-history --shallow --with_branch_heads + - name: Download Artifacts from linux_android_debug_arm64 + uses: actions/download-artifact@v4 + with: + name: artifacts-linux_android_debug_arm64-${{ steps.engine_content_hash.outputs.value }} + - name: Extract Artifacts from linux_android_debug_arm64 + run: | + tar -xvf linux_android_debug_arm64.tar + rm linux_android_debug_arm64.tar + - name: Run test Android Java unit tests for ci/android_debug_arm64 + run: | + cd engine/src + python3 flutter/testing/run_tests.py \ + --variant ci/android_debug_arm64 \ + --type java \ + --android-variant ci/android_debug_arm64 \ + --engine-capture-core-dump publish_artifacts: defaults: run: @@ -5283,6 +6560,8 @@ jobs: - linux_android_debug_x64 - linux_android_debug_riscv64 - linux_wasm_release + - ios_unit_engine_test + - android_java_engine_test - guard runs-on: ubuntu-latest if: ${{ needs.guard.outputs.should_run == 'true' }} @@ -6498,1222 +7777,1262 @@ jobs: run: | tar -xvf artifact-133/artifact_133.tar -C artifact-133/ rm artifact-133/artifact_133.tar + - name: Select the R2 target + id: r2_target + env: + R2_ENGINE_BUCKET: flutter-zero-engine + R2_CI_BUCKET: flutter-zero-ci + run: | + if [ "${GITHUB_EVENT_NAME}" = "pull_request" ]; then + echo "bucket=$R2_CI_BUCKET" >> $GITHUB_OUTPUT + echo "prefix=pr-${GITHUB_RUN_ID}/" >> $GITHUB_OUTPUT + else + echo "bucket=$R2_ENGINE_BUCKET" >> $GITHUB_OUTPUT + echo "prefix=" >> $GITHUB_OUTPUT + fi - name: Publish darwin-x64/artifacts.zip uses: ryand56/r2-upload-action@b801a390acbdeb034c5e684ff5e1361c06639e7c with: r2-account-id: ${{ secrets.R2_ACCOUNT_ID }} r2-access-key-id: ${{ secrets.R2_ACCESS_KEY_ID }} r2-secret-access-key: ${{ secrets.R2_SECRET_ACCESS_KEY }} - r2-bucket: ${{ env.R2_BUCKET }} + r2-bucket: ${{ steps.r2_target.outputs.bucket }} source-dir: artifact-0/ - destination-dir: flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/darwin-x64 + destination-dir: ${{ steps.r2_target.outputs.prefix }}flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/darwin-x64 - name: Publish /dart-sdk-darwin-x64.zip uses: ryand56/r2-upload-action@b801a390acbdeb034c5e684ff5e1361c06639e7c with: r2-account-id: ${{ secrets.R2_ACCOUNT_ID }} r2-access-key-id: ${{ secrets.R2_ACCESS_KEY_ID }} r2-secret-access-key: ${{ secrets.R2_SECRET_ACCESS_KEY }} - r2-bucket: ${{ env.R2_BUCKET }} + r2-bucket: ${{ steps.r2_target.outputs.bucket }} source-dir: artifact-1/ - destination-dir: flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/ + destination-dir: ${{ steps.r2_target.outputs.prefix }}flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/ - name: Publish darwin-x64-profile/artifacts.zip uses: ryand56/r2-upload-action@b801a390acbdeb034c5e684ff5e1361c06639e7c with: r2-account-id: ${{ secrets.R2_ACCOUNT_ID }} r2-access-key-id: ${{ secrets.R2_ACCESS_KEY_ID }} r2-secret-access-key: ${{ secrets.R2_SECRET_ACCESS_KEY }} - r2-bucket: ${{ env.R2_BUCKET }} + r2-bucket: ${{ steps.r2_target.outputs.bucket }} source-dir: artifact-2/ - destination-dir: flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/darwin-x64-profile + destination-dir: ${{ steps.r2_target.outputs.prefix }}flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/darwin-x64-profile - name: Publish darwin-x64-release/artifacts.zip uses: ryand56/r2-upload-action@b801a390acbdeb034c5e684ff5e1361c06639e7c with: r2-account-id: ${{ secrets.R2_ACCOUNT_ID }} r2-access-key-id: ${{ secrets.R2_ACCESS_KEY_ID }} r2-secret-access-key: ${{ secrets.R2_SECRET_ACCESS_KEY }} - r2-bucket: ${{ env.R2_BUCKET }} + r2-bucket: ${{ steps.r2_target.outputs.bucket }} source-dir: artifact-3/ - destination-dir: flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/darwin-x64-release + destination-dir: ${{ steps.r2_target.outputs.prefix }}flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/darwin-x64-release - name: Publish darwin-x64/font-subset.zip uses: ryand56/r2-upload-action@b801a390acbdeb034c5e684ff5e1361c06639e7c with: r2-account-id: ${{ secrets.R2_ACCOUNT_ID }} r2-access-key-id: ${{ secrets.R2_ACCESS_KEY_ID }} r2-secret-access-key: ${{ secrets.R2_SECRET_ACCESS_KEY }} - r2-bucket: ${{ env.R2_BUCKET }} + r2-bucket: ${{ steps.r2_target.outputs.bucket }} source-dir: artifact-4/ - destination-dir: flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/darwin-x64 + destination-dir: ${{ steps.r2_target.outputs.prefix }}flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/darwin-x64 - name: Publish darwin-arm64/artifacts.zip uses: ryand56/r2-upload-action@b801a390acbdeb034c5e684ff5e1361c06639e7c with: r2-account-id: ${{ secrets.R2_ACCOUNT_ID }} r2-access-key-id: ${{ secrets.R2_ACCESS_KEY_ID }} r2-secret-access-key: ${{ secrets.R2_SECRET_ACCESS_KEY }} - r2-bucket: ${{ env.R2_BUCKET }} + r2-bucket: ${{ steps.r2_target.outputs.bucket }} source-dir: artifact-5/ - destination-dir: flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/darwin-arm64 + destination-dir: ${{ steps.r2_target.outputs.prefix }}flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/darwin-arm64 - name: Publish /dart-sdk-darwin-arm64.zip uses: ryand56/r2-upload-action@b801a390acbdeb034c5e684ff5e1361c06639e7c with: r2-account-id: ${{ secrets.R2_ACCOUNT_ID }} r2-access-key-id: ${{ secrets.R2_ACCESS_KEY_ID }} r2-secret-access-key: ${{ secrets.R2_SECRET_ACCESS_KEY }} - r2-bucket: ${{ env.R2_BUCKET }} + r2-bucket: ${{ steps.r2_target.outputs.bucket }} source-dir: artifact-6/ - destination-dir: flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/ + destination-dir: ${{ steps.r2_target.outputs.prefix }}flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/ - name: Publish darwin-arm64-profile/artifacts.zip uses: ryand56/r2-upload-action@b801a390acbdeb034c5e684ff5e1361c06639e7c with: r2-account-id: ${{ secrets.R2_ACCOUNT_ID }} r2-access-key-id: ${{ secrets.R2_ACCESS_KEY_ID }} r2-secret-access-key: ${{ secrets.R2_SECRET_ACCESS_KEY }} - r2-bucket: ${{ env.R2_BUCKET }} + r2-bucket: ${{ steps.r2_target.outputs.bucket }} source-dir: artifact-7/ - destination-dir: flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/darwin-arm64-profile + destination-dir: ${{ steps.r2_target.outputs.prefix }}flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/darwin-arm64-profile - name: Publish darwin-arm64/font-subset.zip uses: ryand56/r2-upload-action@b801a390acbdeb034c5e684ff5e1361c06639e7c with: r2-account-id: ${{ secrets.R2_ACCOUNT_ID }} r2-access-key-id: ${{ secrets.R2_ACCESS_KEY_ID }} r2-secret-access-key: ${{ secrets.R2_SECRET_ACCESS_KEY }} - r2-bucket: ${{ env.R2_BUCKET }} + r2-bucket: ${{ steps.r2_target.outputs.bucket }} source-dir: artifact-8/ - destination-dir: flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/darwin-arm64 + destination-dir: ${{ steps.r2_target.outputs.prefix }}flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/darwin-arm64 - name: Publish darwin-arm64-release/artifacts.zip uses: ryand56/r2-upload-action@b801a390acbdeb034c5e684ff5e1361c06639e7c with: r2-account-id: ${{ secrets.R2_ACCOUNT_ID }} r2-access-key-id: ${{ secrets.R2_ACCESS_KEY_ID }} r2-secret-access-key: ${{ secrets.R2_SECRET_ACCESS_KEY }} - r2-bucket: ${{ env.R2_BUCKET }} + r2-bucket: ${{ steps.r2_target.outputs.bucket }} source-dir: artifact-9/ - destination-dir: flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/darwin-arm64-release + destination-dir: ${{ steps.r2_target.outputs.prefix }}flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/darwin-arm64-release - name: Publish darwin-x64/FlutterEmbedder.framework.zip uses: ryand56/r2-upload-action@b801a390acbdeb034c5e684ff5e1361c06639e7c with: r2-account-id: ${{ secrets.R2_ACCOUNT_ID }} r2-access-key-id: ${{ secrets.R2_ACCESS_KEY_ID }} r2-secret-access-key: ${{ secrets.R2_SECRET_ACCESS_KEY }} - r2-bucket: ${{ env.R2_BUCKET }} + r2-bucket: ${{ steps.r2_target.outputs.bucket }} source-dir: artifact-10/ - destination-dir: flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/darwin-x64 + destination-dir: ${{ steps.r2_target.outputs.prefix }}flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/darwin-x64 - name: Publish darwin-x64/FlutterMacOS.framework.zip uses: ryand56/r2-upload-action@b801a390acbdeb034c5e684ff5e1361c06639e7c with: r2-account-id: ${{ secrets.R2_ACCOUNT_ID }} r2-access-key-id: ${{ secrets.R2_ACCESS_KEY_ID }} r2-secret-access-key: ${{ secrets.R2_SECRET_ACCESS_KEY }} - r2-bucket: ${{ env.R2_BUCKET }} + r2-bucket: ${{ steps.r2_target.outputs.bucket }} source-dir: artifact-11/ - destination-dir: flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/darwin-x64 + destination-dir: ${{ steps.r2_target.outputs.prefix }}flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/darwin-x64 - name: Publish darwin-x64-profile/FlutterMacOS.framework.zip uses: ryand56/r2-upload-action@b801a390acbdeb034c5e684ff5e1361c06639e7c with: r2-account-id: ${{ secrets.R2_ACCOUNT_ID }} r2-access-key-id: ${{ secrets.R2_ACCESS_KEY_ID }} r2-secret-access-key: ${{ secrets.R2_SECRET_ACCESS_KEY }} - r2-bucket: ${{ env.R2_BUCKET }} + r2-bucket: ${{ steps.r2_target.outputs.bucket }} source-dir: artifact-12/ - destination-dir: flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/darwin-x64-profile + destination-dir: ${{ steps.r2_target.outputs.prefix }}flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/darwin-x64-profile - name: Publish darwin-x64-release/FlutterMacOS.framework.zip uses: ryand56/r2-upload-action@b801a390acbdeb034c5e684ff5e1361c06639e7c with: r2-account-id: ${{ secrets.R2_ACCOUNT_ID }} r2-access-key-id: ${{ secrets.R2_ACCESS_KEY_ID }} r2-secret-access-key: ${{ secrets.R2_SECRET_ACCESS_KEY }} - r2-bucket: ${{ env.R2_BUCKET }} + r2-bucket: ${{ steps.r2_target.outputs.bucket }} source-dir: artifact-13/ - destination-dir: flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/darwin-x64-release + destination-dir: ${{ steps.r2_target.outputs.prefix }}flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/darwin-x64-release - name: Publish darwin-x64/gen_snapshot.zip uses: ryand56/r2-upload-action@b801a390acbdeb034c5e684ff5e1361c06639e7c with: r2-account-id: ${{ secrets.R2_ACCOUNT_ID }} r2-access-key-id: ${{ secrets.R2_ACCESS_KEY_ID }} r2-secret-access-key: ${{ secrets.R2_SECRET_ACCESS_KEY }} - r2-bucket: ${{ env.R2_BUCKET }} + r2-bucket: ${{ steps.r2_target.outputs.bucket }} source-dir: artifact-14/ - destination-dir: flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/darwin-x64 + destination-dir: ${{ steps.r2_target.outputs.prefix }}flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/darwin-x64 - name: Publish darwin-x64-profile/gen_snapshot.zip uses: ryand56/r2-upload-action@b801a390acbdeb034c5e684ff5e1361c06639e7c with: r2-account-id: ${{ secrets.R2_ACCOUNT_ID }} r2-access-key-id: ${{ secrets.R2_ACCESS_KEY_ID }} r2-secret-access-key: ${{ secrets.R2_SECRET_ACCESS_KEY }} - r2-bucket: ${{ env.R2_BUCKET }} + r2-bucket: ${{ steps.r2_target.outputs.bucket }} source-dir: artifact-15/ - destination-dir: flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/darwin-x64-profile + destination-dir: ${{ steps.r2_target.outputs.prefix }}flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/darwin-x64-profile - name: Publish darwin-x64-release/gen_snapshot.zip uses: ryand56/r2-upload-action@b801a390acbdeb034c5e684ff5e1361c06639e7c with: r2-account-id: ${{ secrets.R2_ACCOUNT_ID }} r2-access-key-id: ${{ secrets.R2_ACCESS_KEY_ID }} r2-secret-access-key: ${{ secrets.R2_SECRET_ACCESS_KEY }} - r2-bucket: ${{ env.R2_BUCKET }} + r2-bucket: ${{ steps.r2_target.outputs.bucket }} source-dir: artifact-16/ - destination-dir: flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/darwin-x64-release + destination-dir: ${{ steps.r2_target.outputs.prefix }}flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/darwin-x64-release - name: Publish darwin-x64/framework.zip uses: ryand56/r2-upload-action@b801a390acbdeb034c5e684ff5e1361c06639e7c with: r2-account-id: ${{ secrets.R2_ACCOUNT_ID }} r2-access-key-id: ${{ secrets.R2_ACCESS_KEY_ID }} r2-secret-access-key: ${{ secrets.R2_SECRET_ACCESS_KEY }} - r2-bucket: ${{ env.R2_BUCKET }} + r2-bucket: ${{ steps.r2_target.outputs.bucket }} source-dir: artifact-17/ - destination-dir: flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/darwin-x64 + destination-dir: ${{ steps.r2_target.outputs.prefix }}flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/darwin-x64 - name: Publish darwin-x64-profile/framework.zip uses: ryand56/r2-upload-action@b801a390acbdeb034c5e684ff5e1361c06639e7c with: r2-account-id: ${{ secrets.R2_ACCOUNT_ID }} r2-access-key-id: ${{ secrets.R2_ACCESS_KEY_ID }} r2-secret-access-key: ${{ secrets.R2_SECRET_ACCESS_KEY }} - r2-bucket: ${{ env.R2_BUCKET }} + r2-bucket: ${{ steps.r2_target.outputs.bucket }} source-dir: artifact-18/ - destination-dir: flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/darwin-x64-profile + destination-dir: ${{ steps.r2_target.outputs.prefix }}flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/darwin-x64-profile - name: Publish darwin-x64-release/framework.zip uses: ryand56/r2-upload-action@b801a390acbdeb034c5e684ff5e1361c06639e7c with: r2-account-id: ${{ secrets.R2_ACCOUNT_ID }} r2-access-key-id: ${{ secrets.R2_ACCESS_KEY_ID }} r2-secret-access-key: ${{ secrets.R2_SECRET_ACCESS_KEY }} - r2-bucket: ${{ env.R2_BUCKET }} + r2-bucket: ${{ steps.r2_target.outputs.bucket }} source-dir: artifact-19/ - destination-dir: flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/darwin-x64-release + destination-dir: ${{ steps.r2_target.outputs.prefix }}flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/darwin-x64-release - name: Publish ios/artifacts.zip uses: ryand56/r2-upload-action@b801a390acbdeb034c5e684ff5e1361c06639e7c with: r2-account-id: ${{ secrets.R2_ACCOUNT_ID }} r2-access-key-id: ${{ secrets.R2_ACCESS_KEY_ID }} r2-secret-access-key: ${{ secrets.R2_SECRET_ACCESS_KEY }} - r2-bucket: ${{ env.R2_BUCKET }} + r2-bucket: ${{ steps.r2_target.outputs.bucket }} source-dir: artifact-20/ - destination-dir: flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/ios + destination-dir: ${{ steps.r2_target.outputs.prefix }}flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/ios - name: Publish ios-profile/artifacts.zip uses: ryand56/r2-upload-action@b801a390acbdeb034c5e684ff5e1361c06639e7c with: r2-account-id: ${{ secrets.R2_ACCOUNT_ID }} r2-access-key-id: ${{ secrets.R2_ACCESS_KEY_ID }} r2-secret-access-key: ${{ secrets.R2_SECRET_ACCESS_KEY }} - r2-bucket: ${{ env.R2_BUCKET }} + r2-bucket: ${{ steps.r2_target.outputs.bucket }} source-dir: artifact-21/ - destination-dir: flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/ios-profile + destination-dir: ${{ steps.r2_target.outputs.prefix }}flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/ios-profile - name: Publish ios-release/artifacts.zip uses: ryand56/r2-upload-action@b801a390acbdeb034c5e684ff5e1361c06639e7c with: r2-account-id: ${{ secrets.R2_ACCOUNT_ID }} r2-access-key-id: ${{ secrets.R2_ACCESS_KEY_ID }} r2-secret-access-key: ${{ secrets.R2_SECRET_ACCESS_KEY }} - r2-bucket: ${{ env.R2_BUCKET }} + r2-bucket: ${{ steps.r2_target.outputs.bucket }} source-dir: artifact-22/ - destination-dir: flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/ios-release + destination-dir: ${{ steps.r2_target.outputs.prefix }}flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/ios-release - name: Publish windows-x64/artifacts.zip uses: ryand56/r2-upload-action@b801a390acbdeb034c5e684ff5e1361c06639e7c with: r2-account-id: ${{ secrets.R2_ACCOUNT_ID }} r2-access-key-id: ${{ secrets.R2_ACCESS_KEY_ID }} r2-secret-access-key: ${{ secrets.R2_SECRET_ACCESS_KEY }} - r2-bucket: ${{ env.R2_BUCKET }} + r2-bucket: ${{ steps.r2_target.outputs.bucket }} source-dir: artifact-23/ - destination-dir: flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/windows-x64 + destination-dir: ${{ steps.r2_target.outputs.prefix }}flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/windows-x64 - name: Publish windows-x64/windows-x64-embedder.zip uses: ryand56/r2-upload-action@b801a390acbdeb034c5e684ff5e1361c06639e7c with: r2-account-id: ${{ secrets.R2_ACCOUNT_ID }} r2-access-key-id: ${{ secrets.R2_ACCESS_KEY_ID }} r2-secret-access-key: ${{ secrets.R2_SECRET_ACCESS_KEY }} - r2-bucket: ${{ env.R2_BUCKET }} + r2-bucket: ${{ steps.r2_target.outputs.bucket }} source-dir: artifact-24/ - destination-dir: flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/windows-x64 + destination-dir: ${{ steps.r2_target.outputs.prefix }}flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/windows-x64 - name: Publish windows-x64/font-subset.zip uses: ryand56/r2-upload-action@b801a390acbdeb034c5e684ff5e1361c06639e7c with: r2-account-id: ${{ secrets.R2_ACCOUNT_ID }} r2-access-key-id: ${{ secrets.R2_ACCESS_KEY_ID }} r2-secret-access-key: ${{ secrets.R2_SECRET_ACCESS_KEY }} - r2-bucket: ${{ env.R2_BUCKET }} + r2-bucket: ${{ steps.r2_target.outputs.bucket }} source-dir: artifact-25/ - destination-dir: flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/windows-x64 + destination-dir: ${{ steps.r2_target.outputs.prefix }}flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/windows-x64 - name: Publish /dart-sdk-windows-x64.zip uses: ryand56/r2-upload-action@b801a390acbdeb034c5e684ff5e1361c06639e7c with: r2-account-id: ${{ secrets.R2_ACCOUNT_ID }} r2-access-key-id: ${{ secrets.R2_ACCESS_KEY_ID }} r2-secret-access-key: ${{ secrets.R2_SECRET_ACCESS_KEY }} - r2-bucket: ${{ env.R2_BUCKET }} + r2-bucket: ${{ steps.r2_target.outputs.bucket }} source-dir: artifact-26/ - destination-dir: flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/ + destination-dir: ${{ steps.r2_target.outputs.prefix }}flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/ - name: Publish windows-x64-debug/windows-x64-flutter.zip uses: ryand56/r2-upload-action@b801a390acbdeb034c5e684ff5e1361c06639e7c with: r2-account-id: ${{ secrets.R2_ACCOUNT_ID }} r2-access-key-id: ${{ secrets.R2_ACCESS_KEY_ID }} r2-secret-access-key: ${{ secrets.R2_SECRET_ACCESS_KEY }} - r2-bucket: ${{ env.R2_BUCKET }} + r2-bucket: ${{ steps.r2_target.outputs.bucket }} source-dir: artifact-27/ - destination-dir: flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/windows-x64-debug + destination-dir: ${{ steps.r2_target.outputs.prefix }}flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/windows-x64-debug - name: Publish windows-x64/flutter-cpp-client-wrapper.zip uses: ryand56/r2-upload-action@b801a390acbdeb034c5e684ff5e1361c06639e7c with: r2-account-id: ${{ secrets.R2_ACCOUNT_ID }} r2-access-key-id: ${{ secrets.R2_ACCESS_KEY_ID }} r2-secret-access-key: ${{ secrets.R2_SECRET_ACCESS_KEY }} - r2-bucket: ${{ env.R2_BUCKET }} + r2-bucket: ${{ steps.r2_target.outputs.bucket }} source-dir: artifact-28/ - destination-dir: flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/windows-x64 + destination-dir: ${{ steps.r2_target.outputs.prefix }}flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/windows-x64 - name: Publish windows-x64-profile/windows-x64-flutter.zip uses: ryand56/r2-upload-action@b801a390acbdeb034c5e684ff5e1361c06639e7c with: r2-account-id: ${{ secrets.R2_ACCOUNT_ID }} r2-access-key-id: ${{ secrets.R2_ACCESS_KEY_ID }} r2-secret-access-key: ${{ secrets.R2_SECRET_ACCESS_KEY }} - r2-bucket: ${{ env.R2_BUCKET }} + r2-bucket: ${{ steps.r2_target.outputs.bucket }} source-dir: artifact-29/ - destination-dir: flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/windows-x64-profile + destination-dir: ${{ steps.r2_target.outputs.prefix }}flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/windows-x64-profile - name: Publish windows-x64-release/windows-x64-flutter.zip uses: ryand56/r2-upload-action@b801a390acbdeb034c5e684ff5e1361c06639e7c with: r2-account-id: ${{ secrets.R2_ACCOUNT_ID }} r2-access-key-id: ${{ secrets.R2_ACCESS_KEY_ID }} r2-secret-access-key: ${{ secrets.R2_SECRET_ACCESS_KEY }} - r2-bucket: ${{ env.R2_BUCKET }} + r2-bucket: ${{ steps.r2_target.outputs.bucket }} source-dir: artifact-30/ - destination-dir: flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/windows-x64-release + destination-dir: ${{ steps.r2_target.outputs.prefix }}flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/windows-x64-release - name: Publish windows-arm64/artifacts.zip uses: ryand56/r2-upload-action@b801a390acbdeb034c5e684ff5e1361c06639e7c with: r2-account-id: ${{ secrets.R2_ACCOUNT_ID }} r2-access-key-id: ${{ secrets.R2_ACCESS_KEY_ID }} r2-secret-access-key: ${{ secrets.R2_SECRET_ACCESS_KEY }} - r2-bucket: ${{ env.R2_BUCKET }} + r2-bucket: ${{ steps.r2_target.outputs.bucket }} source-dir: artifact-31/ - destination-dir: flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/windows-arm64 + destination-dir: ${{ steps.r2_target.outputs.prefix }}flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/windows-arm64 - name: Publish windows-arm64/windows-arm64-embedder.zip uses: ryand56/r2-upload-action@b801a390acbdeb034c5e684ff5e1361c06639e7c with: r2-account-id: ${{ secrets.R2_ACCOUNT_ID }} r2-access-key-id: ${{ secrets.R2_ACCESS_KEY_ID }} r2-secret-access-key: ${{ secrets.R2_SECRET_ACCESS_KEY }} - r2-bucket: ${{ env.R2_BUCKET }} + r2-bucket: ${{ steps.r2_target.outputs.bucket }} source-dir: artifact-32/ - destination-dir: flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/windows-arm64 + destination-dir: ${{ steps.r2_target.outputs.prefix }}flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/windows-arm64 - name: Publish windows-arm64/font-subset.zip uses: ryand56/r2-upload-action@b801a390acbdeb034c5e684ff5e1361c06639e7c with: r2-account-id: ${{ secrets.R2_ACCOUNT_ID }} r2-access-key-id: ${{ secrets.R2_ACCESS_KEY_ID }} r2-secret-access-key: ${{ secrets.R2_SECRET_ACCESS_KEY }} - r2-bucket: ${{ env.R2_BUCKET }} + r2-bucket: ${{ steps.r2_target.outputs.bucket }} source-dir: artifact-33/ - destination-dir: flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/windows-arm64 + destination-dir: ${{ steps.r2_target.outputs.prefix }}flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/windows-arm64 - name: Publish /dart-sdk-windows-arm64.zip uses: ryand56/r2-upload-action@b801a390acbdeb034c5e684ff5e1361c06639e7c with: r2-account-id: ${{ secrets.R2_ACCOUNT_ID }} r2-access-key-id: ${{ secrets.R2_ACCESS_KEY_ID }} r2-secret-access-key: ${{ secrets.R2_SECRET_ACCESS_KEY }} - r2-bucket: ${{ env.R2_BUCKET }} + r2-bucket: ${{ steps.r2_target.outputs.bucket }} source-dir: artifact-34/ - destination-dir: flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/ + destination-dir: ${{ steps.r2_target.outputs.prefix }}flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/ - name: Publish windows-arm64-debug/windows-arm64-flutter.zip uses: ryand56/r2-upload-action@b801a390acbdeb034c5e684ff5e1361c06639e7c with: r2-account-id: ${{ secrets.R2_ACCOUNT_ID }} r2-access-key-id: ${{ secrets.R2_ACCESS_KEY_ID }} r2-secret-access-key: ${{ secrets.R2_SECRET_ACCESS_KEY }} - r2-bucket: ${{ env.R2_BUCKET }} + r2-bucket: ${{ steps.r2_target.outputs.bucket }} source-dir: artifact-35/ - destination-dir: flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/windows-arm64-debug + destination-dir: ${{ steps.r2_target.outputs.prefix }}flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/windows-arm64-debug - name: Publish windows-arm64/flutter-cpp-client-wrapper.zip uses: ryand56/r2-upload-action@b801a390acbdeb034c5e684ff5e1361c06639e7c with: r2-account-id: ${{ secrets.R2_ACCOUNT_ID }} r2-access-key-id: ${{ secrets.R2_ACCESS_KEY_ID }} r2-secret-access-key: ${{ secrets.R2_SECRET_ACCESS_KEY }} - r2-bucket: ${{ env.R2_BUCKET }} + r2-bucket: ${{ steps.r2_target.outputs.bucket }} source-dir: artifact-36/ - destination-dir: flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/windows-arm64 + destination-dir: ${{ steps.r2_target.outputs.prefix }}flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/windows-arm64 - name: Publish windows-arm64-profile/windows-arm64-flutter.zip uses: ryand56/r2-upload-action@b801a390acbdeb034c5e684ff5e1361c06639e7c with: r2-account-id: ${{ secrets.R2_ACCOUNT_ID }} r2-access-key-id: ${{ secrets.R2_ACCESS_KEY_ID }} r2-secret-access-key: ${{ secrets.R2_SECRET_ACCESS_KEY }} - r2-bucket: ${{ env.R2_BUCKET }} + r2-bucket: ${{ steps.r2_target.outputs.bucket }} source-dir: artifact-37/ - destination-dir: flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/windows-arm64-profile + destination-dir: ${{ steps.r2_target.outputs.prefix }}flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/windows-arm64-profile - name: Publish windows-arm64-release/windows-arm64-flutter.zip uses: ryand56/r2-upload-action@b801a390acbdeb034c5e684ff5e1361c06639e7c with: r2-account-id: ${{ secrets.R2_ACCOUNT_ID }} r2-access-key-id: ${{ secrets.R2_ACCESS_KEY_ID }} r2-secret-access-key: ${{ secrets.R2_SECRET_ACCESS_KEY }} - r2-bucket: ${{ env.R2_BUCKET }} + r2-bucket: ${{ steps.r2_target.outputs.bucket }} source-dir: artifact-38/ - destination-dir: flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/windows-arm64-release + destination-dir: ${{ steps.r2_target.outputs.prefix }}flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/windows-arm64-release - name: Publish /dart-sdk-linux-x64.zip uses: ryand56/r2-upload-action@b801a390acbdeb034c5e684ff5e1361c06639e7c with: r2-account-id: ${{ secrets.R2_ACCOUNT_ID }} r2-access-key-id: ${{ secrets.R2_ACCESS_KEY_ID }} r2-secret-access-key: ${{ secrets.R2_SECRET_ACCESS_KEY }} - r2-bucket: ${{ env.R2_BUCKET }} + r2-bucket: ${{ steps.r2_target.outputs.bucket }} source-dir: artifact-39/ - destination-dir: flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/ + destination-dir: ${{ steps.r2_target.outputs.prefix }}flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/ - name: Publish /flutter_patched_sdk.zip uses: ryand56/r2-upload-action@b801a390acbdeb034c5e684ff5e1361c06639e7c with: r2-account-id: ${{ secrets.R2_ACCOUNT_ID }} r2-access-key-id: ${{ secrets.R2_ACCESS_KEY_ID }} r2-secret-access-key: ${{ secrets.R2_SECRET_ACCESS_KEY }} - r2-bucket: ${{ env.R2_BUCKET }} + r2-bucket: ${{ steps.r2_target.outputs.bucket }} source-dir: artifact-40/ - destination-dir: flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/ + destination-dir: ${{ steps.r2_target.outputs.prefix }}flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/ - name: Publish linux-x64/artifacts.zip uses: ryand56/r2-upload-action@b801a390acbdeb034c5e684ff5e1361c06639e7c with: r2-account-id: ${{ secrets.R2_ACCOUNT_ID }} r2-access-key-id: ${{ secrets.R2_ACCESS_KEY_ID }} r2-secret-access-key: ${{ secrets.R2_SECRET_ACCESS_KEY }} - r2-bucket: ${{ env.R2_BUCKET }} + r2-bucket: ${{ steps.r2_target.outputs.bucket }} source-dir: artifact-41/ - destination-dir: flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/linux-x64 + destination-dir: ${{ steps.r2_target.outputs.prefix }}flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/linux-x64 - name: Publish linux-x64/font-subset.zip uses: ryand56/r2-upload-action@b801a390acbdeb034c5e684ff5e1361c06639e7c with: r2-account-id: ${{ secrets.R2_ACCOUNT_ID }} r2-access-key-id: ${{ secrets.R2_ACCESS_KEY_ID }} r2-secret-access-key: ${{ secrets.R2_SECRET_ACCESS_KEY }} - r2-bucket: ${{ env.R2_BUCKET }} + r2-bucket: ${{ steps.r2_target.outputs.bucket }} source-dir: artifact-42/ - destination-dir: flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/linux-x64 + destination-dir: ${{ steps.r2_target.outputs.prefix }}flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/linux-x64 - name: Publish linux-x64/linux-x64-embedder.zip uses: ryand56/r2-upload-action@b801a390acbdeb034c5e684ff5e1361c06639e7c with: r2-account-id: ${{ secrets.R2_ACCOUNT_ID }} r2-access-key-id: ${{ secrets.R2_ACCESS_KEY_ID }} r2-secret-access-key: ${{ secrets.R2_SECRET_ACCESS_KEY }} - r2-bucket: ${{ env.R2_BUCKET }} + r2-bucket: ${{ steps.r2_target.outputs.bucket }} source-dir: artifact-43/ - destination-dir: flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/linux-x64 + destination-dir: ${{ steps.r2_target.outputs.prefix }}flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/linux-x64 - name: Publish /flutter_patched_sdk_product.zip uses: ryand56/r2-upload-action@b801a390acbdeb034c5e684ff5e1361c06639e7c with: r2-account-id: ${{ secrets.R2_ACCOUNT_ID }} r2-access-key-id: ${{ secrets.R2_ACCESS_KEY_ID }} r2-secret-access-key: ${{ secrets.R2_SECRET_ACCESS_KEY }} - r2-bucket: ${{ env.R2_BUCKET }} + r2-bucket: ${{ steps.r2_target.outputs.bucket }} source-dir: artifact-44/ - destination-dir: flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/ + destination-dir: ${{ steps.r2_target.outputs.prefix }}flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/ - name: Publish /ios-docs.zip uses: ryand56/r2-upload-action@b801a390acbdeb034c5e684ff5e1361c06639e7c with: r2-account-id: ${{ secrets.R2_ACCOUNT_ID }} r2-access-key-id: ${{ secrets.R2_ACCESS_KEY_ID }} r2-secret-access-key: ${{ secrets.R2_SECRET_ACCESS_KEY }} - r2-bucket: ${{ env.R2_BUCKET }} + r2-bucket: ${{ steps.r2_target.outputs.bucket }} source-dir: artifact-45/ - destination-dir: flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/ + destination-dir: ${{ steps.r2_target.outputs.prefix }}flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/ - name: Publish /macos-docs.zip uses: ryand56/r2-upload-action@b801a390acbdeb034c5e684ff5e1361c06639e7c with: r2-account-id: ${{ secrets.R2_ACCOUNT_ID }} r2-access-key-id: ${{ secrets.R2_ACCESS_KEY_ID }} r2-secret-access-key: ${{ secrets.R2_SECRET_ACCESS_KEY }} - r2-bucket: ${{ env.R2_BUCKET }} + r2-bucket: ${{ steps.r2_target.outputs.bucket }} source-dir: artifact-46/ - destination-dir: flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/ + destination-dir: ${{ steps.r2_target.outputs.prefix }}flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/ - name: Publish /linux-docs.zip uses: ryand56/r2-upload-action@b801a390acbdeb034c5e684ff5e1361c06639e7c with: r2-account-id: ${{ secrets.R2_ACCOUNT_ID }} r2-access-key-id: ${{ secrets.R2_ACCESS_KEY_ID }} r2-secret-access-key: ${{ secrets.R2_SECRET_ACCESS_KEY }} - r2-bucket: ${{ env.R2_BUCKET }} + r2-bucket: ${{ steps.r2_target.outputs.bucket }} source-dir: artifact-47/ - destination-dir: flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/ + destination-dir: ${{ steps.r2_target.outputs.prefix }}flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/ - name: Publish /windows-docs.zip uses: ryand56/r2-upload-action@b801a390acbdeb034c5e684ff5e1361c06639e7c with: r2-account-id: ${{ secrets.R2_ACCOUNT_ID }} r2-access-key-id: ${{ secrets.R2_ACCESS_KEY_ID }} r2-secret-access-key: ${{ secrets.R2_SECRET_ACCESS_KEY }} - r2-bucket: ${{ env.R2_BUCKET }} + r2-bucket: ${{ steps.r2_target.outputs.bucket }} source-dir: artifact-48/ - destination-dir: flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/ + destination-dir: ${{ steps.r2_target.outputs.prefix }}flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/ - name: Publish /impeller-docs.zip uses: ryand56/r2-upload-action@b801a390acbdeb034c5e684ff5e1361c06639e7c with: r2-account-id: ${{ secrets.R2_ACCOUNT_ID }} r2-access-key-id: ${{ secrets.R2_ACCESS_KEY_ID }} r2-secret-access-key: ${{ secrets.R2_SECRET_ACCESS_KEY }} - r2-bucket: ${{ env.R2_BUCKET }} + r2-bucket: ${{ steps.r2_target.outputs.bucket }} source-dir: artifact-49/ - destination-dir: flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/ + destination-dir: ${{ steps.r2_target.outputs.prefix }}flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/ - name: Publish /engine_stamp.json uses: ryand56/r2-upload-action@b801a390acbdeb034c5e684ff5e1361c06639e7c with: r2-account-id: ${{ secrets.R2_ACCOUNT_ID }} r2-access-key-id: ${{ secrets.R2_ACCESS_KEY_ID }} r2-secret-access-key: ${{ secrets.R2_SECRET_ACCESS_KEY }} - r2-bucket: ${{ env.R2_BUCKET }} + r2-bucket: ${{ steps.r2_target.outputs.bucket }} source-dir: artifact-50/ - destination-dir: flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/ + destination-dir: ${{ steps.r2_target.outputs.prefix }}flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/ - name: Publish linux-x64-debug/linux-x64-flutter-gtk.zip uses: ryand56/r2-upload-action@b801a390acbdeb034c5e684ff5e1361c06639e7c with: r2-account-id: ${{ secrets.R2_ACCOUNT_ID }} r2-access-key-id: ${{ secrets.R2_ACCESS_KEY_ID }} r2-secret-access-key: ${{ secrets.R2_SECRET_ACCESS_KEY }} - r2-bucket: ${{ env.R2_BUCKET }} + r2-bucket: ${{ steps.r2_target.outputs.bucket }} source-dir: artifact-51/ - destination-dir: flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/linux-x64-debug + destination-dir: ${{ steps.r2_target.outputs.prefix }}flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/linux-x64-debug - name: Publish linux-x64-profile/linux-x64-flutter-gtk.zip uses: ryand56/r2-upload-action@b801a390acbdeb034c5e684ff5e1361c06639e7c with: r2-account-id: ${{ secrets.R2_ACCOUNT_ID }} r2-access-key-id: ${{ secrets.R2_ACCESS_KEY_ID }} r2-secret-access-key: ${{ secrets.R2_SECRET_ACCESS_KEY }} - r2-bucket: ${{ env.R2_BUCKET }} + r2-bucket: ${{ steps.r2_target.outputs.bucket }} source-dir: artifact-52/ - destination-dir: flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/linux-x64-profile + destination-dir: ${{ steps.r2_target.outputs.prefix }}flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/linux-x64-profile - name: Publish linux-x64-release/linux-x64-flutter-gtk.zip uses: ryand56/r2-upload-action@b801a390acbdeb034c5e684ff5e1361c06639e7c with: r2-account-id: ${{ secrets.R2_ACCOUNT_ID }} r2-access-key-id: ${{ secrets.R2_ACCESS_KEY_ID }} r2-secret-access-key: ${{ secrets.R2_SECRET_ACCESS_KEY }} - r2-bucket: ${{ env.R2_BUCKET }} + r2-bucket: ${{ steps.r2_target.outputs.bucket }} source-dir: artifact-53/ - destination-dir: flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/linux-x64-release + destination-dir: ${{ steps.r2_target.outputs.prefix }}flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/linux-x64-release - name: Publish linux-arm64-profile/linux-arm64-flutter-gtk.zip uses: ryand56/r2-upload-action@b801a390acbdeb034c5e684ff5e1361c06639e7c with: r2-account-id: ${{ secrets.R2_ACCOUNT_ID }} r2-access-key-id: ${{ secrets.R2_ACCESS_KEY_ID }} r2-secret-access-key: ${{ secrets.R2_SECRET_ACCESS_KEY }} - r2-bucket: ${{ env.R2_BUCKET }} + r2-bucket: ${{ steps.r2_target.outputs.bucket }} source-dir: artifact-54/ - destination-dir: flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/linux-arm64-profile + destination-dir: ${{ steps.r2_target.outputs.prefix }}flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/linux-arm64-profile - name: Publish linux-arm64/artifacts.zip uses: ryand56/r2-upload-action@b801a390acbdeb034c5e684ff5e1361c06639e7c with: r2-account-id: ${{ secrets.R2_ACCOUNT_ID }} r2-access-key-id: ${{ secrets.R2_ACCESS_KEY_ID }} r2-secret-access-key: ${{ secrets.R2_SECRET_ACCESS_KEY }} - r2-bucket: ${{ env.R2_BUCKET }} + r2-bucket: ${{ steps.r2_target.outputs.bucket }} source-dir: artifact-55/ - destination-dir: flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/linux-arm64 + destination-dir: ${{ steps.r2_target.outputs.prefix }}flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/linux-arm64 - name: Publish linux-arm64/linux-arm64-embedder.zip uses: ryand56/r2-upload-action@b801a390acbdeb034c5e684ff5e1361c06639e7c with: r2-account-id: ${{ secrets.R2_ACCOUNT_ID }} r2-access-key-id: ${{ secrets.R2_ACCESS_KEY_ID }} r2-secret-access-key: ${{ secrets.R2_SECRET_ACCESS_KEY }} - r2-bucket: ${{ env.R2_BUCKET }} + r2-bucket: ${{ steps.r2_target.outputs.bucket }} source-dir: artifact-56/ - destination-dir: flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/linux-arm64 + destination-dir: ${{ steps.r2_target.outputs.prefix }}flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/linux-arm64 - name: Publish linux-arm64/font-subset.zip uses: ryand56/r2-upload-action@b801a390acbdeb034c5e684ff5e1361c06639e7c with: r2-account-id: ${{ secrets.R2_ACCOUNT_ID }} r2-access-key-id: ${{ secrets.R2_ACCESS_KEY_ID }} r2-secret-access-key: ${{ secrets.R2_SECRET_ACCESS_KEY }} - r2-bucket: ${{ env.R2_BUCKET }} + r2-bucket: ${{ steps.r2_target.outputs.bucket }} source-dir: artifact-57/ - destination-dir: flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/linux-arm64 + destination-dir: ${{ steps.r2_target.outputs.prefix }}flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/linux-arm64 - name: Publish linux-arm64-debug/linux-arm64-flutter-gtk.zip uses: ryand56/r2-upload-action@b801a390acbdeb034c5e684ff5e1361c06639e7c with: r2-account-id: ${{ secrets.R2_ACCOUNT_ID }} r2-access-key-id: ${{ secrets.R2_ACCESS_KEY_ID }} r2-secret-access-key: ${{ secrets.R2_SECRET_ACCESS_KEY }} - r2-bucket: ${{ env.R2_BUCKET }} + r2-bucket: ${{ steps.r2_target.outputs.bucket }} source-dir: artifact-58/ - destination-dir: flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/linux-arm64-debug + destination-dir: ${{ steps.r2_target.outputs.prefix }}flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/linux-arm64-debug - name: Publish /dart-sdk-linux-arm64.zip uses: ryand56/r2-upload-action@b801a390acbdeb034c5e684ff5e1361c06639e7c with: r2-account-id: ${{ secrets.R2_ACCOUNT_ID }} r2-access-key-id: ${{ secrets.R2_ACCESS_KEY_ID }} r2-secret-access-key: ${{ secrets.R2_SECRET_ACCESS_KEY }} - r2-bucket: ${{ env.R2_BUCKET }} + r2-bucket: ${{ steps.r2_target.outputs.bucket }} source-dir: artifact-59/ - destination-dir: flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/ + destination-dir: ${{ steps.r2_target.outputs.prefix }}flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/ - name: Publish linux-arm64-release/linux-arm64-flutter-gtk.zip uses: ryand56/r2-upload-action@b801a390acbdeb034c5e684ff5e1361c06639e7c with: r2-account-id: ${{ secrets.R2_ACCOUNT_ID }} r2-access-key-id: ${{ secrets.R2_ACCESS_KEY_ID }} r2-secret-access-key: ${{ secrets.R2_SECRET_ACCESS_KEY }} - r2-bucket: ${{ env.R2_BUCKET }} + r2-bucket: ${{ steps.r2_target.outputs.bucket }} source-dir: artifact-60/ - destination-dir: flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/linux-arm64-release + destination-dir: ${{ steps.r2_target.outputs.prefix }}flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/linux-arm64-release - name: Publish android-arm-profile/windows-x64.zip uses: ryand56/r2-upload-action@b801a390acbdeb034c5e684ff5e1361c06639e7c with: r2-account-id: ${{ secrets.R2_ACCOUNT_ID }} r2-access-key-id: ${{ secrets.R2_ACCESS_KEY_ID }} r2-secret-access-key: ${{ secrets.R2_SECRET_ACCESS_KEY }} - r2-bucket: ${{ env.R2_BUCKET }} + r2-bucket: ${{ steps.r2_target.outputs.bucket }} source-dir: artifact-61/ - destination-dir: flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/android-arm-profile + destination-dir: ${{ steps.r2_target.outputs.prefix }}flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/android-arm-profile - name: Publish android-arm64-profile/windows-x64.zip uses: ryand56/r2-upload-action@b801a390acbdeb034c5e684ff5e1361c06639e7c with: r2-account-id: ${{ secrets.R2_ACCOUNT_ID }} r2-access-key-id: ${{ secrets.R2_ACCESS_KEY_ID }} r2-secret-access-key: ${{ secrets.R2_SECRET_ACCESS_KEY }} - r2-bucket: ${{ env.R2_BUCKET }} + r2-bucket: ${{ steps.r2_target.outputs.bucket }} source-dir: artifact-62/ - destination-dir: flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/android-arm64-profile + destination-dir: ${{ steps.r2_target.outputs.prefix }}flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/android-arm64-profile - name: Publish android-x64-profile/windows-x64.zip uses: ryand56/r2-upload-action@b801a390acbdeb034c5e684ff5e1361c06639e7c with: r2-account-id: ${{ secrets.R2_ACCOUNT_ID }} r2-access-key-id: ${{ secrets.R2_ACCESS_KEY_ID }} r2-secret-access-key: ${{ secrets.R2_SECRET_ACCESS_KEY }} - r2-bucket: ${{ env.R2_BUCKET }} + r2-bucket: ${{ steps.r2_target.outputs.bucket }} source-dir: artifact-63/ - destination-dir: flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/android-x64-profile + destination-dir: ${{ steps.r2_target.outputs.prefix }}flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/android-x64-profile - name: Publish android-arm-release/windows-x64.zip uses: ryand56/r2-upload-action@b801a390acbdeb034c5e684ff5e1361c06639e7c with: r2-account-id: ${{ secrets.R2_ACCOUNT_ID }} r2-access-key-id: ${{ secrets.R2_ACCESS_KEY_ID }} r2-secret-access-key: ${{ secrets.R2_SECRET_ACCESS_KEY }} - r2-bucket: ${{ env.R2_BUCKET }} + r2-bucket: ${{ steps.r2_target.outputs.bucket }} source-dir: artifact-64/ - destination-dir: flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/android-arm-release + destination-dir: ${{ steps.r2_target.outputs.prefix }}flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/android-arm-release - name: Publish android-arm64-release/windows-x64.zip uses: ryand56/r2-upload-action@b801a390acbdeb034c5e684ff5e1361c06639e7c with: r2-account-id: ${{ secrets.R2_ACCOUNT_ID }} r2-access-key-id: ${{ secrets.R2_ACCESS_KEY_ID }} r2-secret-access-key: ${{ secrets.R2_SECRET_ACCESS_KEY }} - r2-bucket: ${{ env.R2_BUCKET }} + r2-bucket: ${{ steps.r2_target.outputs.bucket }} source-dir: artifact-65/ - destination-dir: flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/android-arm64-release + destination-dir: ${{ steps.r2_target.outputs.prefix }}flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/android-arm64-release - name: Publish android-x64-release/windows-x64.zip uses: ryand56/r2-upload-action@b801a390acbdeb034c5e684ff5e1361c06639e7c with: r2-account-id: ${{ secrets.R2_ACCOUNT_ID }} r2-access-key-id: ${{ secrets.R2_ACCESS_KEY_ID }} r2-secret-access-key: ${{ secrets.R2_SECRET_ACCESS_KEY }} - r2-bucket: ${{ env.R2_BUCKET }} + r2-bucket: ${{ steps.r2_target.outputs.bucket }} source-dir: artifact-66/ - destination-dir: flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/android-x64-release + destination-dir: ${{ steps.r2_target.outputs.prefix }}flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/android-x64-release - name: Publish android-arm-profile/darwin-x64.zip uses: ryand56/r2-upload-action@b801a390acbdeb034c5e684ff5e1361c06639e7c with: r2-account-id: ${{ secrets.R2_ACCOUNT_ID }} r2-access-key-id: ${{ secrets.R2_ACCESS_KEY_ID }} r2-secret-access-key: ${{ secrets.R2_SECRET_ACCESS_KEY }} - r2-bucket: ${{ env.R2_BUCKET }} + r2-bucket: ${{ steps.r2_target.outputs.bucket }} source-dir: artifact-67/ - destination-dir: flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/android-arm-profile + destination-dir: ${{ steps.r2_target.outputs.prefix }}flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/android-arm-profile - name: Publish android-arm64-profile/darwin-x64.zip uses: ryand56/r2-upload-action@b801a390acbdeb034c5e684ff5e1361c06639e7c with: r2-account-id: ${{ secrets.R2_ACCOUNT_ID }} r2-access-key-id: ${{ secrets.R2_ACCESS_KEY_ID }} r2-secret-access-key: ${{ secrets.R2_SECRET_ACCESS_KEY }} - r2-bucket: ${{ env.R2_BUCKET }} + r2-bucket: ${{ steps.r2_target.outputs.bucket }} source-dir: artifact-68/ - destination-dir: flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/android-arm64-profile + destination-dir: ${{ steps.r2_target.outputs.prefix }}flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/android-arm64-profile - name: Publish android-x64-profile/darwin-x64.zip uses: ryand56/r2-upload-action@b801a390acbdeb034c5e684ff5e1361c06639e7c with: r2-account-id: ${{ secrets.R2_ACCOUNT_ID }} r2-access-key-id: ${{ secrets.R2_ACCESS_KEY_ID }} r2-secret-access-key: ${{ secrets.R2_SECRET_ACCESS_KEY }} - r2-bucket: ${{ env.R2_BUCKET }} + r2-bucket: ${{ steps.r2_target.outputs.bucket }} source-dir: artifact-69/ - destination-dir: flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/android-x64-profile + destination-dir: ${{ steps.r2_target.outputs.prefix }}flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/android-x64-profile - name: Publish android-arm-release/darwin-x64.zip uses: ryand56/r2-upload-action@b801a390acbdeb034c5e684ff5e1361c06639e7c with: r2-account-id: ${{ secrets.R2_ACCOUNT_ID }} r2-access-key-id: ${{ secrets.R2_ACCESS_KEY_ID }} r2-secret-access-key: ${{ secrets.R2_SECRET_ACCESS_KEY }} - r2-bucket: ${{ env.R2_BUCKET }} + r2-bucket: ${{ steps.r2_target.outputs.bucket }} source-dir: artifact-70/ - destination-dir: flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/android-arm-release + destination-dir: ${{ steps.r2_target.outputs.prefix }}flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/android-arm-release - name: Publish android-arm64-release/darwin-x64.zip uses: ryand56/r2-upload-action@b801a390acbdeb034c5e684ff5e1361c06639e7c with: r2-account-id: ${{ secrets.R2_ACCOUNT_ID }} r2-access-key-id: ${{ secrets.R2_ACCESS_KEY_ID }} r2-secret-access-key: ${{ secrets.R2_SECRET_ACCESS_KEY }} - r2-bucket: ${{ env.R2_BUCKET }} + r2-bucket: ${{ steps.r2_target.outputs.bucket }} source-dir: artifact-71/ - destination-dir: flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/android-arm64-release + destination-dir: ${{ steps.r2_target.outputs.prefix }}flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/android-arm64-release - name: Publish android-x64-release/darwin-x64.zip uses: ryand56/r2-upload-action@b801a390acbdeb034c5e684ff5e1361c06639e7c with: r2-account-id: ${{ secrets.R2_ACCOUNT_ID }} r2-access-key-id: ${{ secrets.R2_ACCESS_KEY_ID }} r2-secret-access-key: ${{ secrets.R2_SECRET_ACCESS_KEY }} - r2-bucket: ${{ env.R2_BUCKET }} + r2-bucket: ${{ steps.r2_target.outputs.bucket }} source-dir: artifact-72/ - destination-dir: flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/android-x64-release + destination-dir: ${{ steps.r2_target.outputs.prefix }}flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/android-x64-release - name: Publish android-arm-profile/artifacts.zip uses: ryand56/r2-upload-action@b801a390acbdeb034c5e684ff5e1361c06639e7c with: r2-account-id: ${{ secrets.R2_ACCOUNT_ID }} r2-access-key-id: ${{ secrets.R2_ACCESS_KEY_ID }} r2-secret-access-key: ${{ secrets.R2_SECRET_ACCESS_KEY }} - r2-bucket: ${{ env.R2_BUCKET }} + r2-bucket: ${{ steps.r2_target.outputs.bucket }} source-dir: artifact-73/ - destination-dir: flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/android-arm-profile + destination-dir: ${{ steps.r2_target.outputs.prefix }}flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/android-arm-profile - name: Publish android-arm-profile/linux-x64.zip uses: ryand56/r2-upload-action@b801a390acbdeb034c5e684ff5e1361c06639e7c with: r2-account-id: ${{ secrets.R2_ACCOUNT_ID }} r2-access-key-id: ${{ secrets.R2_ACCESS_KEY_ID }} r2-secret-access-key: ${{ secrets.R2_SECRET_ACCESS_KEY }} - r2-bucket: ${{ env.R2_BUCKET }} + r2-bucket: ${{ steps.r2_target.outputs.bucket }} source-dir: artifact-74/ - destination-dir: flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/android-arm-profile + destination-dir: ${{ steps.r2_target.outputs.prefix }}flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/android-arm-profile - name: Publish android-arm-profile/symbols.zip uses: ryand56/r2-upload-action@b801a390acbdeb034c5e684ff5e1361c06639e7c with: r2-account-id: ${{ secrets.R2_ACCOUNT_ID }} r2-access-key-id: ${{ secrets.R2_ACCESS_KEY_ID }} r2-secret-access-key: ${{ secrets.R2_SECRET_ACCESS_KEY }} - r2-bucket: ${{ env.R2_BUCKET }} + r2-bucket: ${{ steps.r2_target.outputs.bucket }} source-dir: artifact-75/ - destination-dir: flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/android-arm-profile + destination-dir: ${{ steps.r2_target.outputs.prefix }}flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/android-arm-profile - name: Publish /download.flutter.io uses: ryand56/r2-upload-action@b801a390acbdeb034c5e684ff5e1361c06639e7c with: r2-account-id: ${{ secrets.R2_ACCOUNT_ID }} r2-access-key-id: ${{ secrets.R2_ACCESS_KEY_ID }} r2-secret-access-key: ${{ secrets.R2_SECRET_ACCESS_KEY }} - r2-bucket: ${{ env.R2_BUCKET }} + r2-bucket: ${{ steps.r2_target.outputs.bucket }} source-dir: artifact-76/ - destination-dir: ./ + destination-dir: ${{ steps.r2_target.outputs.prefix }} - name: Publish android-arm-release/artifacts.zip uses: ryand56/r2-upload-action@b801a390acbdeb034c5e684ff5e1361c06639e7c with: r2-account-id: ${{ secrets.R2_ACCOUNT_ID }} r2-access-key-id: ${{ secrets.R2_ACCESS_KEY_ID }} r2-secret-access-key: ${{ secrets.R2_SECRET_ACCESS_KEY }} - r2-bucket: ${{ env.R2_BUCKET }} + r2-bucket: ${{ steps.r2_target.outputs.bucket }} source-dir: artifact-77/ - destination-dir: flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/android-arm-release + destination-dir: ${{ steps.r2_target.outputs.prefix }}flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/android-arm-release - name: Publish android-arm-release/linux-x64.zip uses: ryand56/r2-upload-action@b801a390acbdeb034c5e684ff5e1361c06639e7c with: r2-account-id: ${{ secrets.R2_ACCOUNT_ID }} r2-access-key-id: ${{ secrets.R2_ACCESS_KEY_ID }} r2-secret-access-key: ${{ secrets.R2_SECRET_ACCESS_KEY }} - r2-bucket: ${{ env.R2_BUCKET }} + r2-bucket: ${{ steps.r2_target.outputs.bucket }} source-dir: artifact-78/ - destination-dir: flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/android-arm-release + destination-dir: ${{ steps.r2_target.outputs.prefix }}flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/android-arm-release - name: Publish android-arm-release/symbols.zip uses: ryand56/r2-upload-action@b801a390acbdeb034c5e684ff5e1361c06639e7c with: r2-account-id: ${{ secrets.R2_ACCOUNT_ID }} r2-access-key-id: ${{ secrets.R2_ACCESS_KEY_ID }} r2-secret-access-key: ${{ secrets.R2_SECRET_ACCESS_KEY }} - r2-bucket: ${{ env.R2_BUCKET }} + r2-bucket: ${{ steps.r2_target.outputs.bucket }} source-dir: artifact-79/ - destination-dir: flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/android-arm-release + destination-dir: ${{ steps.r2_target.outputs.prefix }}flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/android-arm-release - name: Publish /download.flutter.io uses: ryand56/r2-upload-action@b801a390acbdeb034c5e684ff5e1361c06639e7c with: r2-account-id: ${{ secrets.R2_ACCOUNT_ID }} r2-access-key-id: ${{ secrets.R2_ACCESS_KEY_ID }} r2-secret-access-key: ${{ secrets.R2_SECRET_ACCESS_KEY }} - r2-bucket: ${{ env.R2_BUCKET }} + r2-bucket: ${{ steps.r2_target.outputs.bucket }} source-dir: artifact-80/ - destination-dir: ./ + destination-dir: ${{ steps.r2_target.outputs.prefix }} - name: Publish android-arm64-release/artifacts.zip uses: ryand56/r2-upload-action@b801a390acbdeb034c5e684ff5e1361c06639e7c with: r2-account-id: ${{ secrets.R2_ACCOUNT_ID }} r2-access-key-id: ${{ secrets.R2_ACCESS_KEY_ID }} r2-secret-access-key: ${{ secrets.R2_SECRET_ACCESS_KEY }} - r2-bucket: ${{ env.R2_BUCKET }} + r2-bucket: ${{ steps.r2_target.outputs.bucket }} source-dir: artifact-81/ - destination-dir: flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/android-arm64-release + destination-dir: ${{ steps.r2_target.outputs.prefix }}flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/android-arm64-release - name: Publish android-arm64-release/linux-x64.zip uses: ryand56/r2-upload-action@b801a390acbdeb034c5e684ff5e1361c06639e7c with: r2-account-id: ${{ secrets.R2_ACCOUNT_ID }} r2-access-key-id: ${{ secrets.R2_ACCESS_KEY_ID }} r2-secret-access-key: ${{ secrets.R2_SECRET_ACCESS_KEY }} - r2-bucket: ${{ env.R2_BUCKET }} + r2-bucket: ${{ steps.r2_target.outputs.bucket }} source-dir: artifact-82/ - destination-dir: flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/android-arm64-release + destination-dir: ${{ steps.r2_target.outputs.prefix }}flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/android-arm64-release - name: Publish android-arm64-release/symbols.zip uses: ryand56/r2-upload-action@b801a390acbdeb034c5e684ff5e1361c06639e7c with: r2-account-id: ${{ secrets.R2_ACCOUNT_ID }} r2-access-key-id: ${{ secrets.R2_ACCESS_KEY_ID }} r2-secret-access-key: ${{ secrets.R2_SECRET_ACCESS_KEY }} - r2-bucket: ${{ env.R2_BUCKET }} + r2-bucket: ${{ steps.r2_target.outputs.bucket }} source-dir: artifact-83/ - destination-dir: flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/android-arm64-release + destination-dir: ${{ steps.r2_target.outputs.prefix }}flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/android-arm64-release - name: Publish android-arm64-release/analyze-snapshot-linux-x64.zip uses: ryand56/r2-upload-action@b801a390acbdeb034c5e684ff5e1361c06639e7c with: r2-account-id: ${{ secrets.R2_ACCOUNT_ID }} r2-access-key-id: ${{ secrets.R2_ACCESS_KEY_ID }} r2-secret-access-key: ${{ secrets.R2_SECRET_ACCESS_KEY }} - r2-bucket: ${{ env.R2_BUCKET }} + r2-bucket: ${{ steps.r2_target.outputs.bucket }} source-dir: artifact-84/ - destination-dir: flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/android-arm64-release + destination-dir: ${{ steps.r2_target.outputs.prefix }}flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/android-arm64-release - name: Publish /download.flutter.io uses: ryand56/r2-upload-action@b801a390acbdeb034c5e684ff5e1361c06639e7c with: r2-account-id: ${{ secrets.R2_ACCOUNT_ID }} r2-access-key-id: ${{ secrets.R2_ACCESS_KEY_ID }} r2-secret-access-key: ${{ secrets.R2_SECRET_ACCESS_KEY }} - r2-bucket: ${{ env.R2_BUCKET }} + r2-bucket: ${{ steps.r2_target.outputs.bucket }} source-dir: artifact-85/ - destination-dir: ./ + destination-dir: ${{ steps.r2_target.outputs.prefix }} - name: Publish android-arm64-profile/artifacts.zip uses: ryand56/r2-upload-action@b801a390acbdeb034c5e684ff5e1361c06639e7c with: r2-account-id: ${{ secrets.R2_ACCOUNT_ID }} r2-access-key-id: ${{ secrets.R2_ACCESS_KEY_ID }} r2-secret-access-key: ${{ secrets.R2_SECRET_ACCESS_KEY }} - r2-bucket: ${{ env.R2_BUCKET }} + r2-bucket: ${{ steps.r2_target.outputs.bucket }} source-dir: artifact-86/ - destination-dir: flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/android-arm64-profile + destination-dir: ${{ steps.r2_target.outputs.prefix }}flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/android-arm64-profile - name: Publish android-arm64-profile/linux-x64.zip uses: ryand56/r2-upload-action@b801a390acbdeb034c5e684ff5e1361c06639e7c with: r2-account-id: ${{ secrets.R2_ACCOUNT_ID }} r2-access-key-id: ${{ secrets.R2_ACCESS_KEY_ID }} r2-secret-access-key: ${{ secrets.R2_SECRET_ACCESS_KEY }} - r2-bucket: ${{ env.R2_BUCKET }} + r2-bucket: ${{ steps.r2_target.outputs.bucket }} source-dir: artifact-87/ - destination-dir: flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/android-arm64-profile + destination-dir: ${{ steps.r2_target.outputs.prefix }}flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/android-arm64-profile - name: Publish android-arm64-profile/symbols.zip uses: ryand56/r2-upload-action@b801a390acbdeb034c5e684ff5e1361c06639e7c with: r2-account-id: ${{ secrets.R2_ACCOUNT_ID }} r2-access-key-id: ${{ secrets.R2_ACCESS_KEY_ID }} r2-secret-access-key: ${{ secrets.R2_SECRET_ACCESS_KEY }} - r2-bucket: ${{ env.R2_BUCKET }} + r2-bucket: ${{ steps.r2_target.outputs.bucket }} source-dir: artifact-88/ - destination-dir: flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/android-arm64-profile + destination-dir: ${{ steps.r2_target.outputs.prefix }}flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/android-arm64-profile - name: Publish android-arm64-profile/analyze-snapshot-linux-x64.zip uses: ryand56/r2-upload-action@b801a390acbdeb034c5e684ff5e1361c06639e7c with: r2-account-id: ${{ secrets.R2_ACCOUNT_ID }} r2-access-key-id: ${{ secrets.R2_ACCESS_KEY_ID }} r2-secret-access-key: ${{ secrets.R2_SECRET_ACCESS_KEY }} - r2-bucket: ${{ env.R2_BUCKET }} + r2-bucket: ${{ steps.r2_target.outputs.bucket }} source-dir: artifact-89/ - destination-dir: flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/android-arm64-profile + destination-dir: ${{ steps.r2_target.outputs.prefix }}flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/android-arm64-profile - name: Publish /download.flutter.io uses: ryand56/r2-upload-action@b801a390acbdeb034c5e684ff5e1361c06639e7c with: r2-account-id: ${{ secrets.R2_ACCOUNT_ID }} r2-access-key-id: ${{ secrets.R2_ACCESS_KEY_ID }} r2-secret-access-key: ${{ secrets.R2_SECRET_ACCESS_KEY }} - r2-bucket: ${{ env.R2_BUCKET }} + r2-bucket: ${{ steps.r2_target.outputs.bucket }} source-dir: artifact-90/ - destination-dir: ./ + destination-dir: ${{ steps.r2_target.outputs.prefix }} - name: Publish android-x64-profile/artifacts.zip uses: ryand56/r2-upload-action@b801a390acbdeb034c5e684ff5e1361c06639e7c with: r2-account-id: ${{ secrets.R2_ACCOUNT_ID }} r2-access-key-id: ${{ secrets.R2_ACCESS_KEY_ID }} r2-secret-access-key: ${{ secrets.R2_SECRET_ACCESS_KEY }} - r2-bucket: ${{ env.R2_BUCKET }} + r2-bucket: ${{ steps.r2_target.outputs.bucket }} source-dir: artifact-91/ - destination-dir: flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/android-x64-profile + destination-dir: ${{ steps.r2_target.outputs.prefix }}flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/android-x64-profile - name: Publish android-x64-profile/linux-x64.zip uses: ryand56/r2-upload-action@b801a390acbdeb034c5e684ff5e1361c06639e7c with: r2-account-id: ${{ secrets.R2_ACCOUNT_ID }} r2-access-key-id: ${{ secrets.R2_ACCESS_KEY_ID }} r2-secret-access-key: ${{ secrets.R2_SECRET_ACCESS_KEY }} - r2-bucket: ${{ env.R2_BUCKET }} + r2-bucket: ${{ steps.r2_target.outputs.bucket }} source-dir: artifact-92/ - destination-dir: flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/android-x64-profile + destination-dir: ${{ steps.r2_target.outputs.prefix }}flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/android-x64-profile - name: Publish android-x64-profile/symbols.zip uses: ryand56/r2-upload-action@b801a390acbdeb034c5e684ff5e1361c06639e7c with: r2-account-id: ${{ secrets.R2_ACCOUNT_ID }} r2-access-key-id: ${{ secrets.R2_ACCESS_KEY_ID }} r2-secret-access-key: ${{ secrets.R2_SECRET_ACCESS_KEY }} - r2-bucket: ${{ env.R2_BUCKET }} + r2-bucket: ${{ steps.r2_target.outputs.bucket }} source-dir: artifact-93/ - destination-dir: flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/android-x64-profile + destination-dir: ${{ steps.r2_target.outputs.prefix }}flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/android-x64-profile - name: Publish android-x64-profile/analyze-snapshot-linux-x64.zip uses: ryand56/r2-upload-action@b801a390acbdeb034c5e684ff5e1361c06639e7c with: r2-account-id: ${{ secrets.R2_ACCOUNT_ID }} r2-access-key-id: ${{ secrets.R2_ACCESS_KEY_ID }} r2-secret-access-key: ${{ secrets.R2_SECRET_ACCESS_KEY }} - r2-bucket: ${{ env.R2_BUCKET }} + r2-bucket: ${{ steps.r2_target.outputs.bucket }} source-dir: artifact-94/ - destination-dir: flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/android-x64-profile + destination-dir: ${{ steps.r2_target.outputs.prefix }}flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/android-x64-profile - name: Publish /download.flutter.io uses: ryand56/r2-upload-action@b801a390acbdeb034c5e684ff5e1361c06639e7c with: r2-account-id: ${{ secrets.R2_ACCOUNT_ID }} r2-access-key-id: ${{ secrets.R2_ACCESS_KEY_ID }} r2-secret-access-key: ${{ secrets.R2_SECRET_ACCESS_KEY }} - r2-bucket: ${{ env.R2_BUCKET }} + r2-bucket: ${{ steps.r2_target.outputs.bucket }} source-dir: artifact-95/ - destination-dir: ./ + destination-dir: ${{ steps.r2_target.outputs.prefix }} - name: Publish android-x64-release/artifacts.zip uses: ryand56/r2-upload-action@b801a390acbdeb034c5e684ff5e1361c06639e7c with: r2-account-id: ${{ secrets.R2_ACCOUNT_ID }} r2-access-key-id: ${{ secrets.R2_ACCESS_KEY_ID }} r2-secret-access-key: ${{ secrets.R2_SECRET_ACCESS_KEY }} - r2-bucket: ${{ env.R2_BUCKET }} + r2-bucket: ${{ steps.r2_target.outputs.bucket }} source-dir: artifact-96/ - destination-dir: flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/android-x64-release + destination-dir: ${{ steps.r2_target.outputs.prefix }}flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/android-x64-release - name: Publish android-x64-release/linux-x64.zip uses: ryand56/r2-upload-action@b801a390acbdeb034c5e684ff5e1361c06639e7c with: r2-account-id: ${{ secrets.R2_ACCOUNT_ID }} r2-access-key-id: ${{ secrets.R2_ACCESS_KEY_ID }} r2-secret-access-key: ${{ secrets.R2_SECRET_ACCESS_KEY }} - r2-bucket: ${{ env.R2_BUCKET }} + r2-bucket: ${{ steps.r2_target.outputs.bucket }} source-dir: artifact-97/ - destination-dir: flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/android-x64-release + destination-dir: ${{ steps.r2_target.outputs.prefix }}flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/android-x64-release - name: Publish android-x64-release/symbols.zip uses: ryand56/r2-upload-action@b801a390acbdeb034c5e684ff5e1361c06639e7c with: r2-account-id: ${{ secrets.R2_ACCOUNT_ID }} r2-access-key-id: ${{ secrets.R2_ACCESS_KEY_ID }} r2-secret-access-key: ${{ secrets.R2_SECRET_ACCESS_KEY }} - r2-bucket: ${{ env.R2_BUCKET }} + r2-bucket: ${{ steps.r2_target.outputs.bucket }} source-dir: artifact-98/ - destination-dir: flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/android-x64-release + destination-dir: ${{ steps.r2_target.outputs.prefix }}flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/android-x64-release - name: Publish android-x64-release/analyze-snapshot-linux-x64.zip uses: ryand56/r2-upload-action@b801a390acbdeb034c5e684ff5e1361c06639e7c with: r2-account-id: ${{ secrets.R2_ACCOUNT_ID }} r2-access-key-id: ${{ secrets.R2_ACCESS_KEY_ID }} r2-secret-access-key: ${{ secrets.R2_SECRET_ACCESS_KEY }} - r2-bucket: ${{ env.R2_BUCKET }} + r2-bucket: ${{ steps.r2_target.outputs.bucket }} source-dir: artifact-99/ - destination-dir: flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/android-x64-release + destination-dir: ${{ steps.r2_target.outputs.prefix }}flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/android-x64-release - name: Publish /download.flutter.io uses: ryand56/r2-upload-action@b801a390acbdeb034c5e684ff5e1361c06639e7c with: r2-account-id: ${{ secrets.R2_ACCOUNT_ID }} r2-access-key-id: ${{ secrets.R2_ACCESS_KEY_ID }} r2-secret-access-key: ${{ secrets.R2_SECRET_ACCESS_KEY }} - r2-bucket: ${{ env.R2_BUCKET }} + r2-bucket: ${{ steps.r2_target.outputs.bucket }} source-dir: artifact-100/ - destination-dir: ./ + destination-dir: ${{ steps.r2_target.outputs.prefix }} - name: Publish android-riscv64-profile/artifacts.zip uses: ryand56/r2-upload-action@b801a390acbdeb034c5e684ff5e1361c06639e7c with: r2-account-id: ${{ secrets.R2_ACCOUNT_ID }} r2-access-key-id: ${{ secrets.R2_ACCESS_KEY_ID }} r2-secret-access-key: ${{ secrets.R2_SECRET_ACCESS_KEY }} - r2-bucket: ${{ env.R2_BUCKET }} + r2-bucket: ${{ steps.r2_target.outputs.bucket }} source-dir: artifact-101/ - destination-dir: flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/android-riscv64-profile + destination-dir: ${{ steps.r2_target.outputs.prefix }}flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/android-riscv64-profile - name: Publish android-riscv64-profile/linux-x64.zip uses: ryand56/r2-upload-action@b801a390acbdeb034c5e684ff5e1361c06639e7c with: r2-account-id: ${{ secrets.R2_ACCOUNT_ID }} r2-access-key-id: ${{ secrets.R2_ACCESS_KEY_ID }} r2-secret-access-key: ${{ secrets.R2_SECRET_ACCESS_KEY }} - r2-bucket: ${{ env.R2_BUCKET }} + r2-bucket: ${{ steps.r2_target.outputs.bucket }} source-dir: artifact-102/ - destination-dir: flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/android-riscv64-profile + destination-dir: ${{ steps.r2_target.outputs.prefix }}flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/android-riscv64-profile - name: Publish android-riscv64-profile/symbols.zip uses: ryand56/r2-upload-action@b801a390acbdeb034c5e684ff5e1361c06639e7c with: r2-account-id: ${{ secrets.R2_ACCOUNT_ID }} r2-access-key-id: ${{ secrets.R2_ACCESS_KEY_ID }} r2-secret-access-key: ${{ secrets.R2_SECRET_ACCESS_KEY }} - r2-bucket: ${{ env.R2_BUCKET }} + r2-bucket: ${{ steps.r2_target.outputs.bucket }} source-dir: artifact-103/ - destination-dir: flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/android-riscv64-profile + destination-dir: ${{ steps.r2_target.outputs.prefix }}flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/android-riscv64-profile - name: Publish android-riscv64-profile/analyze-snapshot-linux-x64.zip uses: ryand56/r2-upload-action@b801a390acbdeb034c5e684ff5e1361c06639e7c with: r2-account-id: ${{ secrets.R2_ACCOUNT_ID }} r2-access-key-id: ${{ secrets.R2_ACCESS_KEY_ID }} r2-secret-access-key: ${{ secrets.R2_SECRET_ACCESS_KEY }} - r2-bucket: ${{ env.R2_BUCKET }} + r2-bucket: ${{ steps.r2_target.outputs.bucket }} source-dir: artifact-104/ - destination-dir: flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/android-riscv64-profile + destination-dir: ${{ steps.r2_target.outputs.prefix }}flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/android-riscv64-profile - name: Publish /download.flutter.io uses: ryand56/r2-upload-action@b801a390acbdeb034c5e684ff5e1361c06639e7c with: r2-account-id: ${{ secrets.R2_ACCOUNT_ID }} r2-access-key-id: ${{ secrets.R2_ACCESS_KEY_ID }} r2-secret-access-key: ${{ secrets.R2_SECRET_ACCESS_KEY }} - r2-bucket: ${{ env.R2_BUCKET }} + r2-bucket: ${{ steps.r2_target.outputs.bucket }} source-dir: artifact-105/ - destination-dir: ./ + destination-dir: ${{ steps.r2_target.outputs.prefix }} - name: Publish android-riscv64-release/artifacts.zip uses: ryand56/r2-upload-action@b801a390acbdeb034c5e684ff5e1361c06639e7c with: r2-account-id: ${{ secrets.R2_ACCOUNT_ID }} r2-access-key-id: ${{ secrets.R2_ACCESS_KEY_ID }} r2-secret-access-key: ${{ secrets.R2_SECRET_ACCESS_KEY }} - r2-bucket: ${{ env.R2_BUCKET }} + r2-bucket: ${{ steps.r2_target.outputs.bucket }} source-dir: artifact-106/ - destination-dir: flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/android-riscv64-release + destination-dir: ${{ steps.r2_target.outputs.prefix }}flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/android-riscv64-release - name: Publish android-riscv64-release/linux-x64.zip uses: ryand56/r2-upload-action@b801a390acbdeb034c5e684ff5e1361c06639e7c with: r2-account-id: ${{ secrets.R2_ACCOUNT_ID }} r2-access-key-id: ${{ secrets.R2_ACCESS_KEY_ID }} r2-secret-access-key: ${{ secrets.R2_SECRET_ACCESS_KEY }} - r2-bucket: ${{ env.R2_BUCKET }} + r2-bucket: ${{ steps.r2_target.outputs.bucket }} source-dir: artifact-107/ - destination-dir: flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/android-riscv64-release + destination-dir: ${{ steps.r2_target.outputs.prefix }}flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/android-riscv64-release - name: Publish android-riscv64-release/symbols.zip uses: ryand56/r2-upload-action@b801a390acbdeb034c5e684ff5e1361c06639e7c with: r2-account-id: ${{ secrets.R2_ACCOUNT_ID }} r2-access-key-id: ${{ secrets.R2_ACCESS_KEY_ID }} r2-secret-access-key: ${{ secrets.R2_SECRET_ACCESS_KEY }} - r2-bucket: ${{ env.R2_BUCKET }} + r2-bucket: ${{ steps.r2_target.outputs.bucket }} source-dir: artifact-108/ - destination-dir: flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/android-riscv64-release + destination-dir: ${{ steps.r2_target.outputs.prefix }}flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/android-riscv64-release - name: Publish android-riscv64-release/analyze-snapshot-linux-x64.zip uses: ryand56/r2-upload-action@b801a390acbdeb034c5e684ff5e1361c06639e7c with: r2-account-id: ${{ secrets.R2_ACCOUNT_ID }} r2-access-key-id: ${{ secrets.R2_ACCESS_KEY_ID }} r2-secret-access-key: ${{ secrets.R2_SECRET_ACCESS_KEY }} - r2-bucket: ${{ env.R2_BUCKET }} + r2-bucket: ${{ steps.r2_target.outputs.bucket }} source-dir: artifact-109/ - destination-dir: flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/android-riscv64-release + destination-dir: ${{ steps.r2_target.outputs.prefix }}flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/android-riscv64-release - name: Publish /download.flutter.io uses: ryand56/r2-upload-action@b801a390acbdeb034c5e684ff5e1361c06639e7c with: r2-account-id: ${{ secrets.R2_ACCOUNT_ID }} r2-access-key-id: ${{ secrets.R2_ACCESS_KEY_ID }} r2-secret-access-key: ${{ secrets.R2_SECRET_ACCESS_KEY }} - r2-bucket: ${{ env.R2_BUCKET }} + r2-bucket: ${{ steps.r2_target.outputs.bucket }} source-dir: artifact-110/ - destination-dir: ./ + destination-dir: ${{ steps.r2_target.outputs.prefix }} - name: Publish android-arm/artifacts.zip uses: ryand56/r2-upload-action@b801a390acbdeb034c5e684ff5e1361c06639e7c with: r2-account-id: ${{ secrets.R2_ACCOUNT_ID }} r2-access-key-id: ${{ secrets.R2_ACCESS_KEY_ID }} r2-secret-access-key: ${{ secrets.R2_SECRET_ACCESS_KEY }} - r2-bucket: ${{ env.R2_BUCKET }} + r2-bucket: ${{ steps.r2_target.outputs.bucket }} source-dir: artifact-111/ - destination-dir: flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/android-arm + destination-dir: ${{ steps.r2_target.outputs.prefix }}flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/android-arm - name: Publish android-arm/android-arm-embedder.zip uses: ryand56/r2-upload-action@b801a390acbdeb034c5e684ff5e1361c06639e7c with: r2-account-id: ${{ secrets.R2_ACCOUNT_ID }} r2-access-key-id: ${{ secrets.R2_ACCESS_KEY_ID }} r2-secret-access-key: ${{ secrets.R2_SECRET_ACCESS_KEY }} - r2-bucket: ${{ env.R2_BUCKET }} + r2-bucket: ${{ steps.r2_target.outputs.bucket }} source-dir: artifact-112/ - destination-dir: flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/android-arm + destination-dir: ${{ steps.r2_target.outputs.prefix }}flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/android-arm - name: Publish android-arm/symbols.zip uses: ryand56/r2-upload-action@b801a390acbdeb034c5e684ff5e1361c06639e7c with: r2-account-id: ${{ secrets.R2_ACCOUNT_ID }} r2-access-key-id: ${{ secrets.R2_ACCESS_KEY_ID }} r2-secret-access-key: ${{ secrets.R2_SECRET_ACCESS_KEY }} - r2-bucket: ${{ env.R2_BUCKET }} + r2-bucket: ${{ steps.r2_target.outputs.bucket }} source-dir: artifact-113/ - destination-dir: flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/android-arm + destination-dir: ${{ steps.r2_target.outputs.prefix }}flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/android-arm - name: Publish /download.flutter.io uses: ryand56/r2-upload-action@b801a390acbdeb034c5e684ff5e1361c06639e7c with: r2-account-id: ${{ secrets.R2_ACCOUNT_ID }} r2-access-key-id: ${{ secrets.R2_ACCESS_KEY_ID }} r2-secret-access-key: ${{ secrets.R2_SECRET_ACCESS_KEY }} - r2-bucket: ${{ env.R2_BUCKET }} + r2-bucket: ${{ steps.r2_target.outputs.bucket }} source-dir: artifact-114/ - destination-dir: ./ + destination-dir: ${{ steps.r2_target.outputs.prefix }} - name: Publish /sky_engine.zip uses: ryand56/r2-upload-action@b801a390acbdeb034c5e684ff5e1361c06639e7c with: r2-account-id: ${{ secrets.R2_ACCOUNT_ID }} r2-access-key-id: ${{ secrets.R2_ACCESS_KEY_ID }} r2-secret-access-key: ${{ secrets.R2_SECRET_ACCESS_KEY }} - r2-bucket: ${{ env.R2_BUCKET }} + r2-bucket: ${{ steps.r2_target.outputs.bucket }} source-dir: artifact-115/ - destination-dir: flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/ + destination-dir: ${{ steps.r2_target.outputs.prefix }}flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/ - name: Publish /android-javadoc.zip uses: ryand56/r2-upload-action@b801a390acbdeb034c5e684ff5e1361c06639e7c with: r2-account-id: ${{ secrets.R2_ACCOUNT_ID }} r2-access-key-id: ${{ secrets.R2_ACCESS_KEY_ID }} r2-secret-access-key: ${{ secrets.R2_SECRET_ACCESS_KEY }} - r2-bucket: ${{ env.R2_BUCKET }} + r2-bucket: ${{ steps.r2_target.outputs.bucket }} source-dir: artifact-116/ - destination-dir: flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/ + destination-dir: ${{ steps.r2_target.outputs.prefix }}flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/ - name: Publish android-arm64/artifacts.zip uses: ryand56/r2-upload-action@b801a390acbdeb034c5e684ff5e1361c06639e7c with: r2-account-id: ${{ secrets.R2_ACCOUNT_ID }} r2-access-key-id: ${{ secrets.R2_ACCESS_KEY_ID }} r2-secret-access-key: ${{ secrets.R2_SECRET_ACCESS_KEY }} - r2-bucket: ${{ env.R2_BUCKET }} + r2-bucket: ${{ steps.r2_target.outputs.bucket }} source-dir: artifact-117/ - destination-dir: flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/android-arm64 + destination-dir: ${{ steps.r2_target.outputs.prefix }}flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/android-arm64 - name: Publish android-arm64/android-arm64-embedder.zip uses: ryand56/r2-upload-action@b801a390acbdeb034c5e684ff5e1361c06639e7c with: r2-account-id: ${{ secrets.R2_ACCOUNT_ID }} r2-access-key-id: ${{ secrets.R2_ACCESS_KEY_ID }} r2-secret-access-key: ${{ secrets.R2_SECRET_ACCESS_KEY }} - r2-bucket: ${{ env.R2_BUCKET }} + r2-bucket: ${{ steps.r2_target.outputs.bucket }} source-dir: artifact-118/ - destination-dir: flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/android-arm64 + destination-dir: ${{ steps.r2_target.outputs.prefix }}flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/android-arm64 - name: Publish android-arm64/symbols.zip uses: ryand56/r2-upload-action@b801a390acbdeb034c5e684ff5e1361c06639e7c with: r2-account-id: ${{ secrets.R2_ACCOUNT_ID }} r2-access-key-id: ${{ secrets.R2_ACCESS_KEY_ID }} r2-secret-access-key: ${{ secrets.R2_SECRET_ACCESS_KEY }} - r2-bucket: ${{ env.R2_BUCKET }} + r2-bucket: ${{ steps.r2_target.outputs.bucket }} source-dir: artifact-119/ - destination-dir: flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/android-arm64 + destination-dir: ${{ steps.r2_target.outputs.prefix }}flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/android-arm64 - name: Publish /download.flutter.io uses: ryand56/r2-upload-action@b801a390acbdeb034c5e684ff5e1361c06639e7c with: r2-account-id: ${{ secrets.R2_ACCOUNT_ID }} r2-access-key-id: ${{ secrets.R2_ACCESS_KEY_ID }} r2-secret-access-key: ${{ secrets.R2_SECRET_ACCESS_KEY }} - r2-bucket: ${{ env.R2_BUCKET }} + r2-bucket: ${{ steps.r2_target.outputs.bucket }} source-dir: artifact-120/ - destination-dir: ./ + destination-dir: ${{ steps.r2_target.outputs.prefix }} - name: Publish android-x86/artifacts.zip uses: ryand56/r2-upload-action@b801a390acbdeb034c5e684ff5e1361c06639e7c with: r2-account-id: ${{ secrets.R2_ACCOUNT_ID }} r2-access-key-id: ${{ secrets.R2_ACCESS_KEY_ID }} r2-secret-access-key: ${{ secrets.R2_SECRET_ACCESS_KEY }} - r2-bucket: ${{ env.R2_BUCKET }} + r2-bucket: ${{ steps.r2_target.outputs.bucket }} source-dir: artifact-121/ - destination-dir: flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/android-x86 + destination-dir: ${{ steps.r2_target.outputs.prefix }}flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/android-x86 - name: Publish android-x86/android-x86-embedder.zip uses: ryand56/r2-upload-action@b801a390acbdeb034c5e684ff5e1361c06639e7c with: r2-account-id: ${{ secrets.R2_ACCOUNT_ID }} r2-access-key-id: ${{ secrets.R2_ACCESS_KEY_ID }} r2-secret-access-key: ${{ secrets.R2_SECRET_ACCESS_KEY }} - r2-bucket: ${{ env.R2_BUCKET }} + r2-bucket: ${{ steps.r2_target.outputs.bucket }} source-dir: artifact-122/ - destination-dir: flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/android-x86 + destination-dir: ${{ steps.r2_target.outputs.prefix }}flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/android-x86 - name: Publish android-x86/symbols.zip uses: ryand56/r2-upload-action@b801a390acbdeb034c5e684ff5e1361c06639e7c with: r2-account-id: ${{ secrets.R2_ACCOUNT_ID }} r2-access-key-id: ${{ secrets.R2_ACCESS_KEY_ID }} r2-secret-access-key: ${{ secrets.R2_SECRET_ACCESS_KEY }} - r2-bucket: ${{ env.R2_BUCKET }} + r2-bucket: ${{ steps.r2_target.outputs.bucket }} source-dir: artifact-123/ - destination-dir: flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/android-x86 + destination-dir: ${{ steps.r2_target.outputs.prefix }}flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/android-x86 - name: Publish /download.flutter.io uses: ryand56/r2-upload-action@b801a390acbdeb034c5e684ff5e1361c06639e7c with: r2-account-id: ${{ secrets.R2_ACCOUNT_ID }} r2-access-key-id: ${{ secrets.R2_ACCESS_KEY_ID }} r2-secret-access-key: ${{ secrets.R2_SECRET_ACCESS_KEY }} - r2-bucket: ${{ env.R2_BUCKET }} + r2-bucket: ${{ steps.r2_target.outputs.bucket }} source-dir: artifact-124/ - destination-dir: ./ + destination-dir: ${{ steps.r2_target.outputs.prefix }} - name: Publish android-x64/artifacts.zip uses: ryand56/r2-upload-action@b801a390acbdeb034c5e684ff5e1361c06639e7c with: r2-account-id: ${{ secrets.R2_ACCOUNT_ID }} r2-access-key-id: ${{ secrets.R2_ACCESS_KEY_ID }} r2-secret-access-key: ${{ secrets.R2_SECRET_ACCESS_KEY }} - r2-bucket: ${{ env.R2_BUCKET }} + r2-bucket: ${{ steps.r2_target.outputs.bucket }} source-dir: artifact-125/ - destination-dir: flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/android-x64 + destination-dir: ${{ steps.r2_target.outputs.prefix }}flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/android-x64 - name: Publish android-x64/android-x64-embedder.zip uses: ryand56/r2-upload-action@b801a390acbdeb034c5e684ff5e1361c06639e7c with: r2-account-id: ${{ secrets.R2_ACCOUNT_ID }} r2-access-key-id: ${{ secrets.R2_ACCESS_KEY_ID }} r2-secret-access-key: ${{ secrets.R2_SECRET_ACCESS_KEY }} - r2-bucket: ${{ env.R2_BUCKET }} + r2-bucket: ${{ steps.r2_target.outputs.bucket }} source-dir: artifact-126/ - destination-dir: flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/android-x64 + destination-dir: ${{ steps.r2_target.outputs.prefix }}flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/android-x64 - name: Publish android-x64/symbols.zip uses: ryand56/r2-upload-action@b801a390acbdeb034c5e684ff5e1361c06639e7c with: r2-account-id: ${{ secrets.R2_ACCOUNT_ID }} r2-access-key-id: ${{ secrets.R2_ACCESS_KEY_ID }} r2-secret-access-key: ${{ secrets.R2_SECRET_ACCESS_KEY }} - r2-bucket: ${{ env.R2_BUCKET }} + r2-bucket: ${{ steps.r2_target.outputs.bucket }} source-dir: artifact-127/ - destination-dir: flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/android-x64 + destination-dir: ${{ steps.r2_target.outputs.prefix }}flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/android-x64 - name: Publish /download.flutter.io uses: ryand56/r2-upload-action@b801a390acbdeb034c5e684ff5e1361c06639e7c with: r2-account-id: ${{ secrets.R2_ACCOUNT_ID }} r2-access-key-id: ${{ secrets.R2_ACCESS_KEY_ID }} r2-secret-access-key: ${{ secrets.R2_SECRET_ACCESS_KEY }} - r2-bucket: ${{ env.R2_BUCKET }} + r2-bucket: ${{ steps.r2_target.outputs.bucket }} source-dir: artifact-128/ - destination-dir: ./ + destination-dir: ${{ steps.r2_target.outputs.prefix }} - name: Publish android-riscv64/artifacts.zip uses: ryand56/r2-upload-action@b801a390acbdeb034c5e684ff5e1361c06639e7c with: r2-account-id: ${{ secrets.R2_ACCOUNT_ID }} r2-access-key-id: ${{ secrets.R2_ACCESS_KEY_ID }} r2-secret-access-key: ${{ secrets.R2_SECRET_ACCESS_KEY }} - r2-bucket: ${{ env.R2_BUCKET }} + r2-bucket: ${{ steps.r2_target.outputs.bucket }} source-dir: artifact-129/ - destination-dir: flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/android-riscv64 + destination-dir: ${{ steps.r2_target.outputs.prefix }}flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/android-riscv64 - name: Publish android-riscv64/android-riscv64-embedder.zip uses: ryand56/r2-upload-action@b801a390acbdeb034c5e684ff5e1361c06639e7c with: r2-account-id: ${{ secrets.R2_ACCOUNT_ID }} r2-access-key-id: ${{ secrets.R2_ACCESS_KEY_ID }} r2-secret-access-key: ${{ secrets.R2_SECRET_ACCESS_KEY }} - r2-bucket: ${{ env.R2_BUCKET }} + r2-bucket: ${{ steps.r2_target.outputs.bucket }} source-dir: artifact-130/ - destination-dir: flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/android-riscv64 + destination-dir: ${{ steps.r2_target.outputs.prefix }}flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/android-riscv64 - name: Publish android-riscv64/symbols.zip uses: ryand56/r2-upload-action@b801a390acbdeb034c5e684ff5e1361c06639e7c with: r2-account-id: ${{ secrets.R2_ACCOUNT_ID }} r2-access-key-id: ${{ secrets.R2_ACCESS_KEY_ID }} r2-secret-access-key: ${{ secrets.R2_SECRET_ACCESS_KEY }} - r2-bucket: ${{ env.R2_BUCKET }} + r2-bucket: ${{ steps.r2_target.outputs.bucket }} source-dir: artifact-131/ - destination-dir: flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/android-riscv64 + destination-dir: ${{ steps.r2_target.outputs.prefix }}flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/android-riscv64 - name: Publish /download.flutter.io uses: ryand56/r2-upload-action@b801a390acbdeb034c5e684ff5e1361c06639e7c with: r2-account-id: ${{ secrets.R2_ACCOUNT_ID }} r2-access-key-id: ${{ secrets.R2_ACCESS_KEY_ID }} r2-secret-access-key: ${{ secrets.R2_SECRET_ACCESS_KEY }} - r2-bucket: ${{ env.R2_BUCKET }} + r2-bucket: ${{ steps.r2_target.outputs.bucket }} source-dir: artifact-132/ - destination-dir: ./ + destination-dir: ${{ steps.r2_target.outputs.prefix }} - name: Publish /flutter-web-sdk.zip uses: ryand56/r2-upload-action@b801a390acbdeb034c5e684ff5e1361c06639e7c with: r2-account-id: ${{ secrets.R2_ACCOUNT_ID }} r2-access-key-id: ${{ secrets.R2_ACCESS_KEY_ID }} r2-secret-access-key: ${{ secrets.R2_SECRET_ACCESS_KEY }} - r2-bucket: ${{ env.R2_BUCKET }} + r2-bucket: ${{ steps.r2_target.outputs.bucket }} source-dir: artifact-133/ - destination-dir: flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/ + destination-dir: ${{ steps.r2_target.outputs.prefix }}flutter_infra_release/flutter/${{ steps.engine_content_hash.outputs.value }}/ - name: Create latest_content_hash.txt + if: ${{ github.event_name != 'pull_request' }} run: | mkdir -p latest_content_hash echo "${{ needs.guard.outputs.engine_content_hash }}" > latest_content_hash/latest_content_hash.txt - name: Publish latest_content_hash.txt + if: ${{ github.event_name != 'pull_request' }} + id: publish_latest_content_hash uses: ryand56/r2-upload-action@b801a390acbdeb034c5e684ff5e1361c06639e7c with: r2-account-id: ${{ secrets.R2_ACCOUNT_ID }} r2-access-key-id: ${{ secrets.R2_ACCESS_KEY_ID }} r2-secret-access-key: ${{ secrets.R2_SECRET_ACCESS_KEY }} - r2-bucket: ${{ env.R2_BUCKET }} + r2-bucket: ${{ steps.r2_target.outputs.bucket }} source-dir: latest_content_hash/ destination-dir: flutter_infra_release/flutter/ + smoke_test: + name: Run the smoke test + uses: ./.github/workflows/smoke-test.yml + needs: + - publish_artifacts + if: ${{ github.event_name == 'pull_request' }} + with: + run_id: ${{ github.run_id }} + remove_ci_artifacts: + runs-on: ubuntu-latest + needs: + - publish_artifacts + - smoke_test + if: always() + steps: + - name: Remove the run prefix from the CI bucket + if: ${{ github.event_name == 'pull_request' }} + env: + AWS_ACCESS_KEY_ID: ${{ secrets.R2_ACCESS_KEY_ID }} + AWS_SECRET_ACCESS_KEY: ${{ secrets.R2_SECRET_ACCESS_KEY }} + AWS_ENDPOINT_URL_S3: https://b468378afe5657ffecccb682fe82ccac.r2.cloudflarestorage.com + AWS_DEFAULT_REGION: auto + run: | + aws s3 rm s3://flutter-zero-ci/pr-${{ github.run_id }}/ --recursive diff --git a/.github/workflows/call-smoke-test.yml b/.github/workflows/call-smoke-test.yml new file mode 100644 index 00000000..a4176be3 --- /dev/null +++ b/.github/workflows/call-smoke-test.yml @@ -0,0 +1,68 @@ +# Runs the smoke test against the already-published engine artifacts. +# +# Companion of the build-and-upload workflow. Both trigger on pull requests +# and share the same guard: the build-and-upload workflow checks whether the +# engine bucket already carries the pull request's engine content hash, and +# builds + smoke tests fresh artifacts under a CI-bucket prefix when it does +# not. This workflow covers the other case - the engine content is already +# deployed (no build needed), and the smoke test runs against the engine +# bucket. The two never run for the same pull request. +# +# NOTE: this file is intentionally not generated; edit directly. + +name: Call Smoke Test + +# Quoted so that YAML 1.1 parsers do not coerce the key to a boolean. +'on': + pull_request: + # Manual fallback (smoke tests the currently deployed engine artifacts). + workflow_dispatch: + +permissions: + contents: read + +jobs: + guard: + name: Resolve the engine artifacts state + runs-on: ubuntu-latest + outputs: + engine_content_hash: ${{ steps.engine_content_hash.outputs.value }} + already_deployed: ${{ steps.check.outputs.already_deployed }} + steps: + - name: Checkout the repository + uses: actions/checkout@v4 + + - name: Generate engine content hash + id: engine_content_hash + run: | + engine_content_hash=$(bin/internal/content_aware_hash.sh) + echo "::notice:: Engine content hash: ${engine_content_hash}" + echo "value=${engine_content_hash}" >> $GITHUB_OUTPUT + + - name: Check if the engine artifacts are already deployed + # Mirrors the guard of the build-and-upload workflow (same hash, same + # probe), but with the inverted conclusion: the smoke test here runs + # against the production engine bucket, which only carries this hash + # when build-and-upload decided (for the same commit) not to build. + id: check + env: + HASH: ${{ steps.engine_content_hash.outputs.value }} + run: | + URL="https://engine.flutter0.dev/flutter_infra_release/flutter/$HASH/engine_stamp.json" + if curl --head --silent --fail "$URL" > /dev/null; then + echo "Engine artifacts already deployed at $URL" + echo "already_deployed=true" >> $GITHUB_OUTPUT + else + echo "Engine artifacts are not deployed at $URL" + echo "already_deployed=false" >> $GITHUB_OUTPUT + fi + + smoke: + name: Run the smoke test + needs: [guard] + if: ${{ needs.guard.outputs.already_deployed == 'true' }} + uses: ./.github/workflows/smoke-test.yml + with: + # Empty selects the production engine bucket inside the smoke test + # workflow. + run_id: '' diff --git a/.github/workflows/smoke-test.yml b/.github/workflows/smoke-test.yml new file mode 100644 index 00000000..85d35a45 --- /dev/null +++ b/.github/workflows/smoke-test.yml @@ -0,0 +1,173 @@ +# Smoke test for the deployed engine artifacts. +# +# Runs the sample project in this checkout with the flutter tool consuming the +# published engine artifacts as storage (as a user would), through +# FLUTTER_STORAGE_BASE_URL. It consumes the same relative layout +# (flutter_infra_release/flutter//...) from either the CI-only +# artifacts bucket (deployed by the build-and-upload workflow for pull +# requests under a per-run prefix) or the production bucket. +# +# This workflow is on-call only: it is invoked +# * by the build-and-upload workflow, which passes the run id of its +# publishing run, or +# * by the call-smoke-test workflow, which selects already-published +# production artifacts. +# NOTE: this file is intentionally not generated; edit directly. + +name: Smoke Test + +# Quoted so that YAML 1.1 parsers do not coerce the key to a boolean. +'on': + workflow_call: + inputs: + run_id: + description: 'The run id of the build-and-upload run that published the artifacts; consumed as pr- in the CI bucket. Empty selects the production bucket.' + type: string + default: '' + required: false + +permissions: + contents: read + +jobs: + resolve: + name: Resolve the artifacts location + runs-on: ubuntu-latest + defaults: + run: + shell: bash + outputs: + engine_content_hash: ${{ steps.engine_content_hash.outputs.value }} + storage_base_url: ${{ steps.storage.outputs.base_url }} + steps: + - name: Checkout the repository + uses: actions/checkout@v4 + + - name: Generate engine content hash + id: engine_content_hash + run: | + engine_content_hash=$(bin/internal/content_aware_hash.sh) + echo "::notice:: Engine content hash: ${engine_content_hash}" + echo "value=${engine_content_hash}" >> $GITHUB_OUTPUT + + - name: Select the artifacts storage + id: storage + env: + HASH: ${{ steps.engine_content_hash.outputs.value }} + RUN_ID: ${{ inputs.run_id }} + run: | + for BASE in $(if [ -n "$RUN_ID" ]; then + echo "https://ci.flutter0.dev/pr-${RUN_ID}" + fi) "https://engine.flutter0.dev"; do + URL="$BASE/flutter_infra_release/flutter/$HASH/engine_stamp.json" + if curl --head --silent --fail "$URL" > /dev/null; then + echo "::notice:: Consuming artifacts from $BASE" + echo "base_url=$BASE" >> $GITHUB_OUTPUT + exit 0 + fi + done + echo "::error::No deployed artifacts for engine hash $HASH (checked the CI prefix pr-${RUN_ID} and the engine bucket); cannot smoke test." + exit 1 + + smoke: + name: Smoke (${{ matrix.device }} ${{ matrix.mode }}) + needs: [resolve] + runs-on: ${{ matrix.runs_on }} + defaults: + run: + shell: bash + strategy: + fail-fast: false + matrix: + include: + - { device: macos, mode: debug, runs_on: macos-latest, python: python3 } + - { device: macos, mode: profile, runs_on: macos-latest, python: python3 } + - { device: macos, mode: release, runs_on: macos-latest, python: python3 } + - { device: windows, mode: debug, runs_on: windows-latest, python: python } + - { device: windows, mode: profile, runs_on: windows-latest, python: python } + - { device: windows, mode: release, runs_on: windows-latest, python: python } + - { device: linux, mode: debug, runs_on: ubuntu-latest, python: python3 } + - { device: linux, mode: profile, runs_on: ubuntu-latest, python: python3 } + - { device: linux, mode: release, runs_on: ubuntu-latest, python: python3 } + # The iOS simulator is created and booted from scratch by the + # harness; the Android emulator image is installed and booted by + # the harness. + - { device: ios, mode: debug, runs_on: macos-latest, python: python3 } + - { device: android, mode: debug, runs_on: ubuntu-latest, python: python3 } + - { device: android, mode: profile, runs_on: ubuntu-latest, python: python3 } + - { device: android, mode: release, runs_on: ubuntu-latest, python: python3 } + steps: + - name: Checkout the repository + uses: actions/checkout@v4 + # Full history + tags so that the tool can determine its version + # from git (see version.dart: GitTagVersion.determine). + with: + fetch-depth: 0 + fetch-tags: true + + - name: Pin the framework version + # The tool derives its framework version from git tags, but the CI + # checkouts of this fork contain none, so the tool would report the + # '0.0.0-unknown' placeholder (see kUnknownFrameworkVersion in + # version.dart); `pub get` then fails because the sample project + # requires Flutter >= 1.17.0. Hardcode a valid version for the smoke + # test before the tool snapshot is compiled (a fresh checkout builds + # it from the patched source). The intended constant is asserted to + # catch upstream drift. + run: | + FILE=packages/flutter_tools/lib/src/version.dart + sed "s|const kUnknownFrameworkVersion = '0.0.0-unknown';|const kUnknownFrameworkVersion = '3.48.0-0.0.pre';|" \ + "$FILE" > "$FILE.new" + mv "$FILE.new" "$FILE" + grep -q "const kUnknownFrameworkVersion = '3.48.0-0.0.pre';" "$FILE" + + - name: Install Linux desktop build prerequisites + # Building the sample app for the linux device runs the template's + # CMake, which pkg-config's glib-2.0; the hosted Ubuntu image does not + # include the glib development package. + if: matrix.device == 'linux' + run: | + sudo apt-get update + sudo apt-get install -y libglib2.0-dev liblzma-dev + + - name: Enable KVM group perms + # The hosted Ubuntu runners expose /dev/kvm, but with default + # permissions (root:kvm, mode 0660) the runner user cannot open it; + # without this rule the emulator crashes or silently falls back to + # software emulation and the boot never completes inside the timeout. + # https://github.blog/2024-04-02-github-actions-hardware-accelerated-android-virtualization-now-available/ + if: matrix.device == 'android' + run: | + test -e /dev/kvm + # chmod synchronously; udevadm applies rules to the live device only + # asynchronously, so relying on just the trigger is racy. + sudo chmod 666 /dev/kvm + echo 'KERNEL=="kvm", GROUP="kvm", MODE="0666", OPTIONS+="static_node=kvm"' | sudo tee /etc/udev/rules.d/99-kvm4all.rules + test -w /dev/kvm + + - name: Pin the Android AVD home + # On the ubuntu-24.04 runner image avdmanager writes AVDs into + # ~/.config/.android/avd (XDG_CONFIG_HOME is set), while the emulator + # looks in ~/.android/avd and dies immediately ("no avd found"). + # Pinning the documented variables makes both tools agree. + # https://github.com/actions/runner-images/issues/11482 + if: matrix.device == 'android' + run: | + echo "ANDROID_USER_HOME=$HOME/.android" >> "$GITHUB_ENV" + echo "ANDROID_EMULATOR_HOME=$HOME/.android" >> "$GITHUB_ENV" + echo "ANDROID_AVD_HOME=$HOME/.android/avd" >> "$GITHUB_ENV" + mkdir -p "$HOME/.android/avd" + + - name: Run smoke test (${{ matrix.device }} ${{ matrix.mode }}) + env: + FLUTTER_STORAGE_BASE_URL: ${{ needs.resolve.outputs.storage_base_url }} + # update_engine_version.sh otherwise recomputes the engine version + # from the master base tree (content_aware_hash.sh's merge-base + # logic), which does not match the deployed artifact directory of + # this pull request; the deployment is keyed by the hash captured at + # build time, so it is passed through here instead. + FLUTTER_PREBUILT_ENGINE_VERSION: ${{ needs.resolve.outputs.engine_content_hash }} + run: | + ${{ matrix.python }} dev/smoke_test/run.py \ + --device ${{ matrix.device }} \ + --mode ${{ matrix.mode }} diff --git a/dev/smoke_test/main.dart b/dev/smoke_test/main.dart new file mode 100644 index 00000000..ec983801 --- /dev/null +++ b/dev/smoke_test/main.dart @@ -0,0 +1,33 @@ +// Smoke test application for the headless flutter_zero engine. +// +// Printed lines are read from the flutter tool console by +// dev/smoke_test/run.py and asserted on. Do not change this file without +// updating dev/smoke_test/run.py. +// +// Semantics: +// - Top-level statics are preserved across a hot reload, but are re-initialized +// when the isolate is replaced by a hot restart. `tickCount` therefore +// distinguishes reload (continues incrementing) from restart (resets to 0). +// - `kVersion` lets the harness prove that *modified source* was actually +// loaded, since a constant change only shows up in newly loaded code. +// - registerHotRestartListener is a flutter_zero dart:ui hook that fires just +// before the isolate is destroyed (hot restart only, no reload). +import 'dart:async'; +import 'dart:ui'; + +const String kVersion = 'A'; + +int tickCount = 0; + +void main() { + print('SMOKE:boot:$kVersion:$tickCount'); + Timer.periodic(const Duration(seconds: 1), (timer) { + tickCount = tickCount + 1; + print('SMOKE:tick:${versionName()}:$tickCount'); + }); + PlatformDispatcher.instance.registerHotRestartListener(() { + print('SMOKE:pre-restart:$tickCount'); + }); +} + +String versionName() => kVersion; diff --git a/dev/smoke_test/run.py b/dev/smoke_test/run.py new file mode 100644 index 00000000..8443b384 --- /dev/null +++ b/dev/smoke_test/run.py @@ -0,0 +1,561 @@ +#!/usr/bin/env python3 +"""Smoke test for the headless flutter_zero engine. + +Runs a sample project (created with the in-tree flutter tool) against the +local engine and asserts on the output it prints: launch, hot reload (after +modifying the source), hot restart, quit. + + python3 dev/smoke_test/run.py --device [macos|windows|linux|ios|android] \ + --engine ci/host_debug [--host-engine ci/host_engine] + +iOS simulators and Android emulators are booted when needed and closed after +the run. +""" +import argparse +import collections +import json +import os +import platform +import subprocess +import sys +import tempfile +import threading +import time + +REPO_ROOT = os.path.abspath( + os.path.join(os.path.dirname(os.path.abspath(__file__)), '..', '..')) +ENGINE_SRC_ROOT = os.path.join(REPO_ROOT, 'engine', 'src') +APP_SOURCE = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'main.dart') +PROJECT_NAME = 'smoke_sample_project' +DEVICE_BOOT_TIMEOUT_S = 600.0 +ANDROID_BOOT_TIMEOUT_S = 900.0 +RELOAD_TIMEOUT_S = 120.0 +QUIT_GRACE_S = 30.0 +# The tool is the in-tree one of this checkout; all invocations (including +# the nested ones during the app build) use it. +FLUTTER_TOOL = os.path.join( + REPO_ROOT, 'bin', 'flutter.bat' if platform.system() == 'Windows' else 'flutter') + + +def log(msg): + print('SMOKE-HARNESS:%s' % msg, flush=True) + + +def die(tool_tail, msg): + log('FAIL:%s' % msg) + for line in tool_tail: + if line is not None: + log('tool:%s' % line.rstrip() if line.rstrip() else '') + sys.exit(1) + + +def send_daemon_command(process, index, method, app_id, full_restart=False): + """Sends one daemon command. + + `app.restart` covers both hot reload (fullRestart false) and hot restart + (fullRestart true). Daemon lines are single-command json arrays with the + appId in params.""" + payload = [{'method': method, 'id': index, + 'params': {'appId': app_id, 'fullRestart': full_restart}}] + process.stdin.write(json.dumps(payload) + '\n') + process.stdin.flush() + + +def write_app_file(project_dir, version): + """Writes the versioned fixture as the sample project entrypoint. + + The version constant lets the harness prove that modified source (not just + re-executed code) was loaded by a hot reload. + """ + output = [] + with open(APP_SOURCE) as fixture: + for line in fixture: + output.append(line.replace("const String kVersion = 'A';", + "const String kVersion = '%s';" % version)) + main_path = os.path.join(project_dir, 'lib', 'main.dart') + with open(main_path, 'w') as main_file: + main_file.write(''.join(output)) + return main_path + + +def create_project(workspace, platforms, engine, host_engine): + log('creating sample project with the in-tree flutter tool') + os.makedirs(workspace, exist_ok=True) + # Create with the local engine configured as well, so that the tool caches + # do not rely on downloadable sdk artifacts; CI may need to operate without + # any published storage. + local_engines = [] if engine is None else [ + '--local-engine=%s' % engine, + '--local-engine-host=%s' % host_engine, + '--local-engine-src-path=%s' % ENGINE_SRC_ROOT, + ] + code, output = run_tool_sync( + ['create', '--platforms=%s' % platforms, PROJECT_NAME, + '--suppress-analytics', *local_engines], + cwd=workspace) + if code != 0: + die(output.splitlines()[-5:], + '`flutter create` of the sample project failed') + return os.path.join(workspace, PROJECT_NAME) + + +SIM_NAME = 'flutter_zero_smoke_test_sim' + + +def boot_ios_simulator(): + """Creates and boots a fresh iOS simulator; returns (udid, device flag).""" + # Device lines look like: "iPhone 16 Pro (292C3A03-2D02-4548-9154-34A231D581C3)" + # so the UDID is captured, not the trailing boot state. + def _udid_of(state): + return os.popen( + 'xcrun simctl list devices %s | grep -m1 iPhone | ' + 'grep -Eo "[0-9A-F]{8}-[0-9A-F-]{27}"' % state).read().strip() + udid = _udid_of('booted') + if udid: + log('found a booted iOS simulator: %s' % udid) + return udid, None + log('creating and booting the iOS simulator') + udid = _udid_of('available') + if not udid: + die([], 'no available iOS simulator device found') + subprocess.run(['xcrun', 'simctl', 'create', SIM_NAME, udid], + check=False, stdout=subprocess.PIPE) + boot = subprocess.run( + ['xcrun', 'simctl', 'boot', udid], + check=False, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, + text=True) + if boot.returncode != 0 and 'already booted' not in boot.stderr.lower(): + die([], 'booting the iOS simulator failed') + try: + subprocess.run(['xcrun', 'simctl', 'bootstatus', udid, '-b'], + check=False, stdout=subprocess.DEVNULL, + timeout=DEVICE_BOOT_TIMEOUT_S) + except subprocess.TimeoutExpired: + die([], 'iOS simulator did not boot in %ss' % DEVICE_BOOT_TIMEOUT_S) + return udid, SIM_NAME + + +def android_tools(): + """Returns the (emulator, adb, avdmanager) command paths of the Android SDK. + + Precedence: ANDROID_SDK_ROOT / ANDROID_HOME, then the platform defaults.""" + sdk = _android_sdk_root() + if sdk is None: + die([], 'Android SDK not found; set ANDROID_SDK_ROOT to its location') + emulator, adb, avdmanager = ( + os.path.join(sdk, 'emulator', 'emulator'), + os.path.join(sdk, 'platform-tools', 'adb'), + os.path.join(sdk, 'cmdline-tools', 'latest', 'bin', 'avdmanager'), + ) + missing = [tool for tool in (emulator, adb, avdmanager) + if not os.path.exists(tool)] + if missing: + die([], 'Android SDK is missing tools: %s' % ', '.join(missing)) + return emulator, adb, avdmanager + + +def android_abi(): + """Returns the Android system image ABI for the host architecture.""" + return {'arm64': 'arm64-v8a'}.get(platform.machine(), 'x86_64') + + +# SDK packages that smoke test needs to boot an emulator on CI, where the +# runner image does not preinstall them with the Android SDK. +ANDROID_SDK_IMAGE = 'system-images;android-31;google_apis;%s' % android_abi() + + +def _android_sdk_root(): + """Returns the Android SDK root directory, or None.""" + candidates = [ + os.environ.get('ANDROID_SDK_ROOT'), + os.environ.get('ANDROID_HOME'), + os.path.join(os.path.expanduser('~'), 'Library', 'Android', 'sdk'), + os.path.join(os.path.expanduser('~'), 'Android', 'Sdk'), + os.path.join(os.path.expanduser('~'), 'AppData', 'Local', 'Android', + 'Sdk'), + '/usr/local/lib/android/sdk', + ] + return next((path for path in candidates if path and os.path.isdir(path)), + None) + + +def _install_android_emulator_packages(): + """Installs the Android emulator and AVD system image when missing. + + CI runner images ship the Android SDK without the emulator package and + system images required to boot an AVD.""" + sdk = _android_sdk_root() + if sdk is None: + die([], 'Android SDK not found; set ANDROID_SDK_ROOT to its location') + system_image_path = os.path.join(sdk, *filter(None, ANDROID_SDK_IMAGE.split(';'))) + missing = [] + if not os.path.isdir(os.path.join(sdk, 'emulator')): + missing.append('emulator') + if not os.path.isdir(system_image_path): + missing.append(ANDROID_SDK_IMAGE) + if not missing: + return + sdkmanager = os.path.join( + sdk, 'cmdline-tools', 'latest', 'bin', + 'sdkmanager.bat' if platform.system() == 'Windows' else 'sdkmanager') + if not os.path.isfile(sdkmanager): + die([], 'the Android SDK is missing sdkmanager at %s' % sdkmanager) + log('installing Android SDK packages: %s' % ', '.join(missing)) + result = subprocess.run( + [sdkmanager if platform.system() != 'Windows' + else 'cmd', '--install'] + missing, + input='y\n' * 64, # accept the licenses + stdout=subprocess.PIPE, stderr=subprocess.STDOUT, text=True, + check=False, env={**os.environ, 'ANDROID_SDK_ROOT': sdk}) + if result.returncode != 0: + die(result.stdout.splitlines()[-8:], + 'installing Android SDK packages failed') + + +def boot_android_emulator(): + _install_android_emulator_packages() + emulator, adb, avdmanager = android_tools() + device = subprocess.run( + [adb, 'devices'], stdout=subprocess.PIPE, stderr=subprocess.STDOUT, + text=True, check=False).stdout.strip().splitlines() + emulators = [line.split()[0] for line in device + if 'emulator' in line and 'daemon' not in line] + if emulators: + log('found a running Android emulator: %s' % emulators[0]) + return emulators[0], None + log('creating the Android AVD') + avd = 'flutter_zero_smoke_test_avd' + result = subprocess.run( + [avdmanager, 'create', 'avd', '-n', avd, + '-k', ANDROID_SDK_IMAGE], + input='no\n', + stdout=subprocess.PIPE, stderr=subprocess.STDOUT, text=True, + check=False) + tool_output = (result.stdout or '') + (result.stderr or '') + avd_ready = result.returncode == 0 or 'already exists' in tool_output + if not avd_ready: + die([], 'avdmanager failed; is the Android SDK installed?') + log('checking the Android emulator acceleration') + accel = subprocess.run( + [emulator, '-accel-check'], stdout=subprocess.PIPE, + stderr=subprocess.STDOUT, text=True) + if accel.returncode != 0: + # Software-only emulation boots far too slowly for CI; fail fast with the + # probe's output, which points at the missing permissions (hosted runners + # expose /dev/kvm but the runner user needs the udev rule from the + # workflow's 'Enable KVM group perms' step). + die([accel.stdout, accel.stderr], + 'the Android emulator cannot use hardware acceleration (KVM/HVF)') + emulator_tail = collections.deque(maxlen=10) + + def _log_emulator(): + """Drains the emulator's output continuously and logs it. + + Without a reader, an emulator crash (e.g. a missing hypervisor) would go + unnoticed while `adb wait-for-device` spins until the boot timeout; the + CI log must show the reason and the final output lines on failure. + """ + for line in emulator_process.stdout: + text = line.rstrip() + if text: + log('emulator:%s' % text) + emulator_tail.append(text) + + log('booting the Android emulator (headless, software rendering)') + emulator_process = subprocess.Popen( + [emulator, '-avd', avd, + '-no-window', '-gpu', 'swiftshader_indirect', + '-no-snapshot', '-no-audio'], + stdout=subprocess.PIPE, stderr=subprocess.STDOUT) + threading.Thread(target=_log_emulator, daemon=True).start() + try: + subprocess.run( + [adb, 'wait-for-device', 'shell', 'getprop', 'sys.boot_completed'], + check=False, timeout=ANDROID_BOOT_TIMEOUT_S) + except subprocess.TimeoutExpired: + die(list(emulator_tail), 'Android emulator did not boot in %ss' % ANDROID_BOOT_TIMEOUT_S) + device = subprocess.run( + [adb, 'devices'], stdout=subprocess.PIPE, stderr=subprocess.STDOUT, + text=True, check=False).stdout.strip().splitlines() + emulators = [line.split()[0] for line in device + if 'emulator' in line and 'daemon' not in line] + if not emulators: + die([], 'no running Android emulator found after boot attempt') + return emulators[0], emulator_process + + +def launch_flutter_run(project_dir, device, engine, host_engine, mode='debug'): + build_mode_flags = {'profile': ['--profile'], 'release': ['--release']}.get( + mode, []) + # engine=None means: run against the prebuilt engine in bin/cache, without + # any --local-engine flags. + local_engine_flags = [] if engine is None else [ + '--local-engine=%s' % engine, + '--local-engine-host=%s' % host_engine, + '--local-engine-src-path=%s' % ENGINE_SRC_ROOT, + ] + local_web_sdk_flags = [] if engine is None else [ + '--local-web-sdk=%s' % engine, + '--local-engine-src-path=%s' % ENGINE_SRC_ROOT, + ] + device_flag = {'web': 'chrome'}.get(device, device) + args = [ + FLUTTER_TOOL, 'run', '--machine', '--verbose', + '--suppress-analytics', '--no-version-check', + *(local_web_sdk_flags if device == 'web' else local_engine_flags), + '-d', device_flag, + ] + build_mode_flags + log('flutter run args: %s' % args) + return subprocess.Popen( + args, cwd=project_dir, + stdin=subprocess.PIPE, stdout=subprocess.PIPE, + stderr=subprocess.STDOUT, text=True, bufsize=1) + + +def stop_tool(process): + # Best effort: this runs from a `finally` block, so a hard failure here + # would mask the run's own exit status. + if process.poll() is None: + try: + send_daemon_command(process, 0, 'app.stop', None) + process.wait(timeout=QUIT_GRACE_S) + return + except Exception as e: + log('stopping the tool failed; terminating (%s)' % e) + try: + process.terminate() + except Exception as e: + log('terminating the tool failed (%s)' % e) + + +class ToolConsole: + """Watches the flutter tool's console while it runs the sample app. + + One reader thread digests the tool's merged stdout continuously, so the + tool can never block on a full pipe: lines are reconstructed from raw + chunks, echoed to the harness log, and daemon-protocol frames are parsed: + + app.start -> records the running app's id (app_id), which + app.restart/app.stop commands address + app.started -> the device/service protocol is initialized; the tool + rejects app.restart requests before this point with + "Device initialization has not completed." (observed on + the iOS simulator, whose service connection completes a + few seconds after the app's first print) + + wait_for() and wait_started() block until their moment and fail the run + with the recent console output when they time out (or when the tool + exits first). + """ + + def __init__(self, process): + self.process = process + self.app_id = None + self._started = False + self._lines = [] + self._tail = collections.deque(maxlen=12) + self._lock = threading.Condition() + self._eof = False + self._reader = threading.Thread(target=self._read_process, daemon=True) + self._reader.start() + + def _read_process(self): + for raw in self.process.stdout: + line = raw.rstrip('\r\n') + log('run:%s' % line) + self._note_daemon(line) + with self._lock: + self._lines.append(line) + self._tail.append(line) + self._lock.notify_all() + with self._lock: + self._eof = True + self._lock.notify_all() + + def _note_daemon(self, line): + """Interprets one daemon-protocol line; every other line is noise.""" + try: + payload = json.loads(line) # daemon frames are single-element arrays + frame = payload[0] if isinstance(payload, list) else payload + except ValueError: + return + if not isinstance(frame, dict) or 'event' not in frame: + return + if frame['event'] == 'app.start': + app_id = (frame.get('params') or {}).get('appId') + if app_id: + self.app_id = app_id + elif frame['event'] == 'app.started': + self._started = True + + def _wait(self, predicate, timeout, failure): + """Returns the first console line matching predicate, or fails the run.""" + deadline = time.monotonic() + timeout + while True: + with self._lock: + match = next((line for line in self._lines if predicate(line)), None) + if match is not None: + return match + remaining = deadline - time.monotonic() + if remaining <= 0 or self._eof: + break + self._lock.wait(min(0.5, remaining)) + die(list(self._tail), failure) + + def wait_for(self, sentinel, timeout): + """Waits for the app to print a console line containing sentinel.""" + _FAILED = 'the app did not print %s within %.0fs' % (sentinel, timeout) + return self._wait(lambda line: sentinel in line, timeout, _FAILED) + + def wait_started(self, timeout): + """Waits for the daemon's app.started event (the restart gate).""" + self._wait(lambda _: self._started, timeout, + 'the daemon did not report app.started within %.0fs' % timeout) + + +def run_debug_flow(project_dir, device, engine, host_engine): + """Launch, hot reload (with modified source), hot restart, quit.""" + console = ToolConsole(launch_flutter_run(project_dir, device, engine, + host_engine)) + command_index = 1 + try: + console.wait_for('SMOKE:boot:A:', DEVICE_BOOT_TIMEOUT_S) + log('launch ok') + log('waiting for app.started') + console.wait_started(DEVICE_BOOT_TIMEOUT_S) + log('app started; modifying lib/main.dart (A -> B)') + write_app_file(project_dir, 'B') + log('requesting hot reload') + send_daemon_command(console.process, command_index, 'app.restart', + console.app_id, full_restart=False) + command_index += 1 + line = console.wait_for('SMOKE:tick:B:', RELOAD_TIMEOUT_S) + log('hot reload ok (%s)' % line.strip()) + log('requesting hot restart') + send_daemon_command(console.process, command_index, 'app.restart', + console.app_id, full_restart=True) + command_index += 1 + if device != 'web': + # The web engine's hot restart hooks are dummies (no invocation), so the + # pre-restart listener sentinel is only asserted on native devices. + console.wait_for('SMOKE:pre-restart:', RELOAD_TIMEOUT_S) + console.wait_for('SMOKE:boot:B:0', RELOAD_TIMEOUT_S) + log('hot restart ok') + send_daemon_command(console.process, command_index, 'app.stop', + console.app_id) + console.process.wait(timeout=QUIT_GRACE_S) + finally: + stop_tool(console.process) + + +def run_tool_sync(args, cwd=None): + """Runs the in-tree tool synchronously, streaming all of its output. + + Every line is echoed to the CI log as it is produced (the full output + remains available to the caller for failure reporting). + """ + process = subprocess.Popen( + [FLUTTER_TOOL] + args, + cwd=cwd if cwd is not None else REPO_ROOT, + stdout=subprocess.PIPE, stderr=subprocess.STDOUT, + text=True, bufsize=1) + lines = [] + for line in process.stdout: + lines.append(line) + log('tool:%s' % line.rstrip()) + process.wait() + return process.returncode, ''.join(lines) + + +def run_boot_only_flow(project_dir, device, engine, host_engine, mode): + """profile/release posture: verify the released compile, no console checks. + + For web the app is built with `flutter build web` and its artifacts are + asserted (the released runtime has no console plumbing to forward); native + devices run `flutter run --profile/--release` and assert the boot sentinel. + """ + if device == 'web': + code, output = run_tool_sync( + ['build', 'web', '--verbose', + '--suppress-analytics', '--no-version-check', + '--local-web-sdk=%s' % engine, + '--local-engine-src-path=%s' % ENGINE_SRC_ROOT, + *( ['--profile'] if mode == 'profile' else ['--release'])], + cwd=project_dir) + if code != 0: + die(output.splitlines()[-20:], 'web %s build failed' % mode) + build_dir = os.path.join(project_dir, 'build', 'web') + missing = [artifact for artifact in ('flutter.js', 'flutter_service_worker.js') + if not os.path.exists(os.path.join(build_dir, artifact))] + if missing: + die([], 'web %s build is missing artifacts: %s' % (mode, ', '.join(missing))) + log('build ok (%s)' % mode) + return + console = ToolConsole(launch_flutter_run(project_dir, device, engine, + host_engine, mode)) + try: + console.wait_for('SMOKE:boot:A:', DEVICE_BOOT_TIMEOUT_S) + log('launch ok (%s)' % mode) + time.sleep(3.0) + send_daemon_command(console.process, 0, 'app.stop', console.app_id) + console.process.wait(timeout=QUIT_GRACE_S) + finally: + stop_tool(console.process) + + +def main(): + parser = argparse.ArgumentParser(description=__doc__) + parser.add_argument( + '--device', required=True, + choices=['macos', 'windows', 'linux', 'ios', 'android', 'web']) + parser.add_argument( + '--mode', default='debug', choices=['debug', 'profile', 'release']) + parser.add_argument( + '--engine', default=None, + help='name of the local engine build the app runs against ' + '(default: run against the prebuilt engine in bin/cache ' + 'without --local-engine flags).') + parser.add_argument( + '--host-engine', default=None, + help='name of the local host engine the tool runs against ' + '(default: same as --engine).') + parser.add_argument( + '--workspace', default=None, + help='where the sample project is created and left behind.') + args = parser.parse_args() + if args.engine is not None and args.host_engine is None: + # The tool validates the host engine relative to the target out dir, so + # the host variant is named without the "ci/" prefix. + args.host_engine = args.engine[len('ci/'):] if args.engine.startswith('ci/') else args.engine + device = args.device + simulator = None + emulator = None + if args.device == 'ios': + device, simulator = boot_ios_simulator() + elif args.device == 'android': + device, emulator = boot_android_emulator() + platforms = args.device + workspace = (args.workspace if args.workspace is not None + else tempfile.mkdtemp(prefix='flutter_zero_smoke_test_')) + try: + project_dir = create_project(workspace, platforms, args.engine, + args.host_engine) + write_app_file(project_dir, 'A') + if args.mode == 'debug': + run_debug_flow(project_dir, device, args.engine, args.host_engine) + else: + run_boot_only_flow(project_dir, device, args.engine, args.host_engine, + args.mode) + log('sample project left at %s' % workspace) + finally: + if args.device == 'ios' and simulator is not None: + subprocess.run(['xcrun', 'simctl', 'shutdown', SIM_NAME], + check=False, stdout=subprocess.DEVNULL) + subprocess.run(['xcrun', 'simctl', 'delete', SIM_NAME], + check=False, stdout=subprocess.DEVNULL) + if emulator is not None and emulator.poll() is None: + emulator.terminate() + + +if __name__ == '__main__': + main() diff --git a/engine/src/build/vs_toolchain.py b/engine/src/build/vs_toolchain.py index b6d84818..e4e4b438 100644 --- a/engine/src/build/vs_toolchain.py +++ b/engine/src/build/vs_toolchain.py @@ -268,6 +268,13 @@ def _CopyUCRTRuntime(target_dir, source_dir, target_cpu, dll_pattern, suffix): exist, but the target directory does exist.""" if target_cpu == 'arm64': env_version = GetVisualStudioVersion() + # GetVisualStudioVersion() may return the numeric install-folder form + # (e.g. '18' for VS 2026). Map it back to the year key used by + # VC_VERSIONS. + for year_key, install_folder in MSVS_VERSIONS.items(): + if env_version == install_folder: + env_version = year_key + break vc_version = VC_VERSIONS[env_version] prefix = 'Microsoft.' + vc_version diff --git a/engine/src/flutter/ci/builders/linux_android_debug_engine.json b/engine/src/flutter/ci/builders/linux_android_debug_engine.json index 80ff10ff..f5f43d90 100644 --- a/engine/src/flutter/ci/builders/linux_android_debug_engine.json +++ b/engine/src/flutter/ci/builders/linux_android_debug_engine.json @@ -95,7 +95,9 @@ "targets": [ "flutter", "flutter/shell/platform/android:abi_jars", - "flutter/shell/platform/embedder:embedder-archive" + "flutter/shell/platform/embedder:embedder-archive", + "flutter/shell/platform/android:android_jar", + "flutter/shell/platform/android:robolectric_tests" ] } }, diff --git a/engine/src/flutter/ci/builders/linux_arm_host_engine.json b/engine/src/flutter/ci/builders/linux_arm_host_engine.json index fc42117b..4af33cc4 100644 --- a/engine/src/flutter/ci/builders/linux_arm_host_engine.json +++ b/engine/src/flutter/ci/builders/linux_arm_host_engine.json @@ -49,7 +49,8 @@ "ninja": { "config": "ci/linux_profile_arm64", "targets": [ - "flutter/shell/platform/linux:flutter_gtk" + "flutter/shell/platform/linux:flutter_gtk", + "flutter:unittests" ] } }, @@ -98,8 +99,9 @@ "flutter/build/archives:artifacts", "flutter/build/archives:dart_sdk_archive", "flutter/tools/font_subset", + "flutter/build/archives:embedder", "flutter/shell/platform/linux:flutter_gtk", - "flutter/build/archives:embedder" + "flutter:unittests" ] } }, @@ -141,7 +143,8 @@ "ninja": { "config": "ci/linux_release_arm64", "targets": [ - "flutter/shell/platform/linux:flutter_gtk" + "flutter/shell/platform/linux:flutter_gtk", + "flutter:unittests" ] } } diff --git a/engine/src/flutter/ci/builders/linux_host_desktop_engine.json b/engine/src/flutter/ci/builders/linux_host_desktop_engine.json index adf1f260..e2887a4a 100644 --- a/engine/src/flutter/ci/builders/linux_host_desktop_engine.json +++ b/engine/src/flutter/ci/builders/linux_host_desktop_engine.json @@ -48,7 +48,8 @@ "ninja": { "config": "ci/host_debug_desktop", "targets": [ - "flutter/shell/platform/linux:flutter_gtk" + "flutter/shell/platform/linux:flutter_gtk", + "flutter:unittests" ] } }, @@ -89,7 +90,8 @@ "ninja": { "config": "ci/host_profile_desktop", "targets": [ - "flutter/shell/platform/linux:flutter_gtk" + "flutter/shell/platform/linux:flutter_gtk", + "flutter:unittests" ] } }, @@ -130,7 +132,8 @@ "ninja": { "config": "ci/host_release_desktop", "targets": [ - "flutter/shell/platform/linux:flutter_gtk" + "flutter/shell/platform/linux:flutter_gtk", + "flutter:unittests" ] } } diff --git a/engine/src/flutter/ci/builders/linux_host_engine.json b/engine/src/flutter/ci/builders/linux_host_engine.json index 30ae59e6..c4e449a4 100644 --- a/engine/src/flutter/ci/builders/linux_host_engine.json +++ b/engine/src/flutter/ci/builders/linux_host_engine.json @@ -55,7 +55,8 @@ "flutter/build/archives:flutter_patched_sdk", "flutter/build/archives:artifacts", "flutter/tools/font_subset", - "flutter/build/archives:embedder" + "flutter/build/archives:embedder", + "flutter:unittests" ] } }, @@ -101,7 +102,9 @@ "ninja": { "config": "ci/host_release", "targets": [ - "flutter/build/archives:flutter_patched_sdk" + "flutter/build/archives:flutter_patched_sdk", + "flutter/shell/testing", + "flutter:unittests" ] } } diff --git a/engine/src/flutter/ci/builders/linux_host_engine_test.json b/engine/src/flutter/ci/builders/linux_host_engine_test.json index f1a9d331..dd15bfb2 100644 --- a/engine/src/flutter/ci/builders/linux_host_engine_test.json +++ b/engine/src/flutter/ci/builders/linux_host_engine_test.json @@ -31,7 +31,7 @@ "config": "ci/host_debug_test", "targets": [ "flutter:unittests", - "flutter/build/dart:copy_dart_sdk", + "flutter/build/dart:dart_sdk", "flutter/shell/testing" ] }, @@ -77,7 +77,7 @@ "config": "ci/host_profile_test", "targets": [ "flutter:unittests", - "flutter/build/dart:copy_dart_sdk", + "flutter/build/dart:dart_sdk", "flutter/shell/testing" ] }, @@ -129,7 +129,7 @@ "config": "ci/host_release_test", "targets": [ "flutter:unittests", - "flutter/build/dart:copy_dart_sdk", + "flutter/build/dart:dart_sdk", "flutter/display_list:display_list_benchmarks", "flutter/display_list:display_list_builder_benchmarks", "flutter/display_list:display_list_region_benchmarks", diff --git a/engine/src/flutter/ci/builders/linux_unopt.json b/engine/src/flutter/ci/builders/linux_unopt.json index 21c47780..24b23a08 100644 --- a/engine/src/flutter/ci/builders/linux_unopt.json +++ b/engine/src/flutter/ci/builders/linux_unopt.json @@ -27,7 +27,7 @@ "targets": [ "flutter/tools/font_subset", "flutter:unittests", - "flutter/build/dart:copy_dart_sdk", + "flutter/build/dart:dart_sdk", "flutter/shell/platform/common/client_wrapper:client_wrapper_unittests", "flutter/shell/platform/common:common_cpp_core_unittests", "flutter/shell/platform/common:common_cpp_unittests", diff --git a/engine/src/flutter/ci/builders/mac_host_engine.json b/engine/src/flutter/ci/builders/mac_host_engine.json index 5b1a0c96..b642b78e 100644 --- a/engine/src/flutter/ci/builders/mac_host_engine.json +++ b/engine/src/flutter/ci/builders/mac_host_engine.json @@ -111,7 +111,8 @@ "config": "ci/host_debug", "targets": [ "flutter/build/archives:artifacts", - "flutter/build/archives:dart_sdk_archive" + "flutter/build/archives:dart_sdk_archive", + "flutter:unittests" ] }, "postsubmit_overrides": { @@ -228,7 +229,8 @@ "ninja": { "config": "ci/host_profile", "targets": [ - "flutter/build/archives:artifacts" + "flutter/build/archives:artifacts", + "flutter:unittests" ] }, "postsubmit_overrides": { @@ -395,7 +397,8 @@ "config": "ci/host_release", "targets": [ "flutter/build/archives:artifacts", - "flutter/tools/font_subset" + "flutter/tools/font_subset", + "flutter:unittests" ] }, "postsubmit_overrides": { @@ -568,7 +571,8 @@ "config": "ci/mac_debug_arm64", "targets": [ "flutter/build/archives:artifacts", - "flutter/build/archives:dart_sdk_archive" + "flutter/build/archives:dart_sdk_archive", + "flutter:unittests" ] }, "postsubmit_overrides": { @@ -745,7 +749,8 @@ "ninja": { "config": "ci/mac_profile_arm64", "targets": [ - "flutter/build/archives:artifacts" + "flutter/build/archives:artifacts", + "flutter:unittests" ] }, "postsubmit_overrides": { @@ -924,7 +929,8 @@ "config": "ci/mac_release_arm64", "targets": [ "flutter/build/archives:artifacts", - "flutter/tools/font_subset" + "flutter/tools/font_subset", + "flutter:unittests" ] }, "postsubmit_overrides": { diff --git a/engine/src/flutter/ci/builders/mac_ios_engine_no_ext_safe.json b/engine/src/flutter/ci/builders/mac_ios_engine_no_ext_safe.json index 9788c3bc..7c92a15b 100644 --- a/engine/src/flutter/ci/builders/mac_ios_engine_no_ext_safe.json +++ b/engine/src/flutter/ci/builders/mac_ios_engine_no_ext_safe.json @@ -107,6 +107,58 @@ } } }, + { + "drone_dimensions": [ + "device_type=none", + "os=Mac-15.5|Mac-15.7", + "cpu=arm64" + ], + "gclient_variables": { + "download_android_deps": false, + "download_jdk": false, + "use_rbe": true + }, + "gn": [ + "--target-dir", + "ci/ios_test_binaries_arm64", + "--ios", + "--runtime-mode", + "debug", + "--simulator", + "--simulator-cpu=arm64", + "--no-lto", + "--rbe", + "--no-goma", + "--xcode-symlinks" + ], + "name": "ci/ios_test_binaries_arm64", + "description": "Builds the iOS simulator unit tests (host-side test binaries for arm64 iOS).", + "ninja": { + "config": "ci/ios_test_binaries_arm64", + "targets": [ + "flutter/shell/platform/darwin/ios:ios_test_flutter" + ] + }, + "properties": { + "$flutter/osx_sdk": { + "sdk_version": "16c5032a" + } + }, + "postsubmit_overrides": { + "gn": [ + "--target-dir", + "ci/ios_test_binaries_arm64", + "--ios", + "--runtime-mode", + "debug", + "--simulator", + "--simulator-cpu=arm64", + "--no-lto", + "--no-rbe", + "--no-goma" + ] + } + }, { "drone_dimensions": [ "device_type=none", diff --git a/engine/src/flutter/ci/builders/standalone/linux_benchmarks.json b/engine/src/flutter/ci/builders/standalone/linux_benchmarks.json index cfae8fa1..398246cd 100644 --- a/engine/src/flutter/ci/builders/standalone/linux_benchmarks.json +++ b/engine/src/flutter/ci/builders/standalone/linux_benchmarks.json @@ -23,7 +23,7 @@ "ninja": { "config": "ci/host_release_benchmarks", "targets": [ - "flutter/build/dart:copy_dart_sdk", + "flutter/build/dart:dart_sdk", "flutter/display_list:display_list_benchmarks", "flutter/display_list:display_list_builder_benchmarks", "flutter/display_list:display_list_region_benchmarks", diff --git a/engine/src/flutter/ci/builders/windows_host_engine.json b/engine/src/flutter/ci/builders/windows_host_engine.json index 07f17e0c..1e40ab29 100644 --- a/engine/src/flutter/ci/builders/windows_host_engine.json +++ b/engine/src/flutter/ci/builders/windows_host_engine.json @@ -8,7 +8,7 @@ "definition files." ], "luci_flags": { - "upload_content_hash": true + "upload_content_hash": true }, "builds": [ { @@ -56,7 +56,8 @@ "flutter/tools/font_subset", "flutter/build/archives:dart_sdk_archive", "flutter/shell/platform/windows/client_wrapper:client_wrapper_archive", - "flutter/build/archives:windows_flutter" + "flutter/build/archives:windows_flutter", + "flutter:unittests" ] } }, @@ -97,7 +98,8 @@ "targets": [ "windows", "gen_snapshot", - "flutter/build/archives:windows_flutter" + "flutter/build/archives:windows_flutter", + "flutter/shell/testing" ] } }, @@ -139,7 +141,8 @@ "targets": [ "windows", "gen_snapshot", - "flutter/build/archives:windows_flutter" + "flutter/build/archives:windows_flutter", + "flutter/shell/testing" ] } } diff --git a/engine/src/flutter/lib/web_ui/lib/platform_dispatcher.dart b/engine/src/flutter/lib/web_ui/lib/platform_dispatcher.dart index a625cc38..c86c4ef8 100644 --- a/engine/src/flutter/lib/web_ui/lib/platform_dispatcher.dart +++ b/engine/src/flutter/lib/web_ui/lib/platform_dispatcher.dart @@ -18,6 +18,15 @@ class RootIsolateToken { } abstract class PlatformDispatcher { + /// Registers a callback to be called when the application receives a hot + /// restart signal. + /// + /// The web engine does not implement hot restart signals; this is a dummy + /// implementation matching the native dart:ui API. + void registerHotRestartListener(VoidCallback callback) {} + + /// Unregisters a callback registered by [registerHotRestartListener]. + void unregisterHotRestartListener(VoidCallback callback) {} static PlatformDispatcher get instance => engine.EnginePlatformDispatcher.instance; int? get engineId; diff --git a/engine/src/flutter/shell/platform/darwin/macos/BUILD.gn b/engine/src/flutter/shell/platform/darwin/macos/BUILD.gn index 96cfc2d0..27449b24 100644 --- a/engine/src/flutter/shell/platform/darwin/macos/BUILD.gn +++ b/engine/src/flutter/shell/platform/darwin/macos/BUILD.gn @@ -111,18 +111,27 @@ test_fixtures("flutter_desktop_darwin_fixtures") { fixtures = [ "//flutter/third_party/icu/common/icudtl.dat" ] } -executable("flutter_desktop_darwin_swift_unittests") { - testonly = true - public_configs = [ - "//flutter/shell/platform/darwin/common:config", - "//flutter/shell/platform/darwin/common:test_config", - "//flutter/shell/platform/darwin/common:swift_testing_config", - ] - sources = [ "framework/Source/ResizeSynchronizerTest.swift" ] - deps = [ - ":flutter_framework_source", - "//flutter/shell/platform/darwin/common:swift_testing_main", - "//flutter/shell/platform/darwin/common:test_utils_swift", + +# Keeps the Dart VM snapshot blobs of the engine inside the test executable. +# +# The blobs are resolved at runtime with dlsym from the current process, and +# nothing references them statically. In builds where the mac linker is asked +# to dead strip, they would otherwise be removed, and the Dart VM creation of +# the engine would fail. +config("flutter_desktop_darwin_unittests_engine_snapshot") { + ldflags = [ + "-Xlinker", + "-u", + "-Xlinker", + "_kDartSnapshotData", + "-Xlinker", + "-u", + "-Xlinker", + "_kDartSnapshotText", + "-Xlinker", + "-u", + "-Xlinker", + "_kPlatformStrongDill", ] } @@ -131,6 +140,17 @@ executable("flutter_desktop_darwin_unittests") { cflags_objc = flutter_cflags_objc cflags_objcc = flutter_cflags_objcc ldflags = [ "-ObjC" ] + if (flutter_runtime_mode == "debug") { + # In debug builds the Dart VM snapshot blobs are resolved at runtime with + # dlsym from the current process; without being exported the dynamic + # symbol lookup can not find them, and without these anchors the mac + # linker may dead strip them, which makes the Dart VM creation of the + # test engine fail. + public_configs = [ + "//flutter:export_dynamic_symbols", + ":flutter_desktop_darwin_unittests_engine_snapshot", + ] + } sources = [ "framework/Source/FlutterAppDelegateTest.mm", diff --git a/engine/src/flutter/shell/platform/darwin/macos/README.md b/engine/src/flutter/shell/platform/darwin/macos/README.md index 7404a506..cbd2ffb2 100644 --- a/engine/src/flutter/shell/platform/darwin/macos/README.md +++ b/engine/src/flutter/shell/platform/darwin/macos/README.md @@ -44,8 +44,8 @@ Builds are architecture-specific, and can be controlled by specifying ## Testing The macOS-specific embedder tests are built as the -`flutter_desktop_darwin_unittests` and `flutter_desktop_darwin_swift_unittests` -binaries. Like all gtest-based test binaries, a subset of tests can be run by +`flutter_desktop_darwin_unittests` binaries. Like all gtest-based test binaries, +a subset of tests can be run by applying a filter such as `--gtest_filter='FlutterViewControllerTest.*Key*'`. More general details on testing can be found on the [Wiki][wiki_engine_testing]. diff --git a/engine/src/flutter/shell/platform/embedder/tests/embedder_unittests.cc b/engine/src/flutter/shell/platform/embedder/tests/embedder_unittests.cc index 5e39a5b5..11e172bf 100644 --- a/engine/src/flutter/shell/platform/embedder/tests/embedder_unittests.cc +++ b/engine/src/flutter/shell/platform/embedder/tests/embedder_unittests.cc @@ -1034,8 +1034,8 @@ TEST_F(EmbedderTest, CanPostTaskToAllNativeThreads) { ASSERT_EQ(captures.platform_threads_count, 1u); ASSERT_EQ(captures.ui_threads_count, 1u); ASSERT_EQ(captures.worker_threads_count, worker_count); - EXPECT_GE(captures.worker_threads_count - 1, 2u); - EXPECT_LE(captures.worker_threads_count - 1, 4u); + EXPECT_GE(captures.worker_threads_count, 2u); + EXPECT_LE(captures.worker_threads_count, 4u); platform_task_runner->PostTask([&]() { engine.reset(); diff --git a/engine/src/flutter/testing/run_tests.py b/engine/src/flutter/testing/run_tests.py index 602c59c9..a67a1b2c 100755 --- a/engine/src/flutter/testing/run_tests.py +++ b/engine/src/flutter/testing/run_tests.py @@ -424,9 +424,6 @@ def make_test(name, flags=None, extra_env=None): make_test('common_cpp_core_unittests'), make_test('common_cpp_unittests'), make_test('dart_plugin_registrant_unittests'), - make_test('display_list_rendertests'), - make_test('display_list_unittests'), - make_test('embedder_a11y_unittests'), make_test('embedder_proctable_unittests'), make_test('embedder_unittests'), make_test('fml_unittests'), @@ -443,78 +440,37 @@ def make_test(name, flags=None, extra_env=None): unittests += [ # https://github.com/google/googletest/issues/2490 make_test('jni_unittests'), - make_test('platform_view_android_delegate_unittests'), # https://github.com/flutter/flutter/issues/36295 make_test('shell_unittests'), ] if is_windows(): unittests += [ - # The accessibility library only supports Mac and Windows. - make_test('accessibility_unittests'), - make_test('client_wrapper_windows_unittests'), - make_test('flutter_windows_unittests'), + make_test('client_wrapper_windows_unittests'), + make_test('flutter_windows_unittests'), ] # These unit-tests are Objective-C and can only run on Darwin. if is_mac(): unittests += [ - # The accessibility library only supports Mac and Windows. - make_test('accessibility_unittests'), - make_test('availability_version_check_unittests'), - make_test('framework_common_swift_unittests'), - make_test('framework_common_unittests'), - make_test('spring_animation_unittests'), - make_test('gpu_surface_metal_unittests'), + make_test('availability_version_check_unittests'), + make_test('framework_common_swift_unittests'), + make_test('framework_common_unittests'), + make_test('spring_animation_unittests'), ] - if is_linux(): - flow_flags = [ - '--golden-dir=%s' % GOLDEN_DIR, - '--font-file=%s' % ROBOTO_FONT_PATH, - ] - icu_flags = ['--icu-data-file-path=%s' % os.path.join(build_dir, 'icudtl.dat')] - unittests += [ - make_test('flow_unittests', flags=repeat_flags + ['--'] + flow_flags), - make_test('flutter_glfw_unittests'), - make_test('flutter_linux_unittests', extra_env={'G_DEBUG': 'fatal-criticals'}), - # https://github.com/flutter/flutter/issues/36296 - make_test('txt_unittests', flags=repeat_flags + ['--'] + icu_flags), - ] - else: - flow_flags = ['--gtest_filter=-PerformanceOverlayLayer.Gold'] - unittests += [ - make_test('flow_unittests', flags=repeat_flags + flow_flags), - ] - - build_name = os.path.basename(build_dir) - try: - if is_linux(): - xvfb.start_virtual_x(build_name, build_dir) - for test, flags, extra_env in unittests: - run_engine_executable( - build_dir, - test, - executable_filter, - flags, - coverage=coverage, - extra_env=extra_env, - gtest=True - ) - finally: - if is_linux(): - xvfb.stop_virtual_x(build_name) - - if is_mac(): - # macOS Desktop unit tests written in Swift. + for test, flags, extra_env in unittests: run_engine_executable( build_dir, - 'flutter_desktop_darwin_swift_unittests', + test, executable_filter, - shuffle_flags, - coverage=coverage + flags, + coverage=coverage, + extra_env=extra_env, + gtest=True ) + if is_mac(): # flutter_desktop_darwin_unittests uses global state that isn't handled # correctly by gtest-parallel. # https://github.com/flutter/flutter/issues/104789 @@ -528,64 +484,12 @@ def make_test(name, flags=None, extra_env=None): shuffle_flags, coverage=coverage ) + extra_env = metal_validation_env() extra_env.update(vulkan_validation_env(build_dir)) - mac_impeller_unittests_flags = repeat_flags + [ - '--gtest_filter=-*OpenGLES', # These are covered in the golden tests. - '--', - '--enable_vulkan_validation', - ] - # Impeller tests are only supported on macOS for now. - run_engine_executable( - build_dir, - 'impeller_unittests', - executable_filter, - mac_impeller_unittests_flags, - coverage=coverage, - extra_env=extra_env, - gtest=True, - # TODO(https://github.com/flutter/flutter/issues/123733): Remove this allowlist. - # See also https://github.com/flutter/flutter/issues/114872. - allowed_failure_output=[ - '[MTLCompiler createVertexStageAndLinkPipelineWithFragment:', - '[MTLCompiler pipelineStateWithVariant:', - ] - ) - - # Run one interactive Vulkan test with validation enabled. - # - # TODO(matanlurey): https://github.com/flutter/flutter/issues/134852; enable - # more of the suite, and ideally we'd like to use Skia gold and take screen - # shots as well. - run_engine_executable( - build_dir, - 'impeller_unittests', - executable_filter, - shuffle_flags + [ - '--enable_vulkan_validation', - '--enable_playground', - '--playground_timeout_ms=4000', - '--gtest_filter="*ColorWheel*"', - ], - coverage=coverage, - extra_env=extra_env, - ) - - # Run the Flutter GPU test suite. - run_engine_executable( - build_dir, - 'impeller_dart_unittests', - executable_filter, - shuffle_flags + [ - '--enable_vulkan_validation', - # TODO(https://github.com/flutter/flutter/issues/145036) - # TODO(https://github.com/flutter/flutter/issues/142642) - '--gtest_filter=*Metal', - ], - coverage=coverage, - extra_env=extra_env, - ) - + del extra_env + # Impeller, and with it the interactive Metal/Vulkan tests, were removed + # from flutter_zero. def run_engine_benchmarks(build_dir, executable_filter): logger.info('Running Engine Benchmarks.') @@ -598,13 +502,8 @@ def run_engine_benchmarks(build_dir, executable_filter): run_engine_executable(build_dir, 'ui_benchmarks', executable_filter, icu_flags) - run_engine_executable(build_dir, 'display_list_builder_benchmarks', executable_filter, icu_flags) - run_engine_executable(build_dir, 'geometry_benchmarks', executable_filter, icu_flags) - if is_linux(): - run_engine_executable(build_dir, 'txt_benchmarks', executable_filter, icu_flags) - class FlutterTesterOptions(): @@ -752,7 +651,15 @@ def run_java_tests(executable_filter, android_variant='android_debug_unopt'): '--gradle-user-home=%s' % gradle_cache_dir, ] - env = dict(os.environ, ANDROID_HOME=android_home, JAVA_HOME=java_home()) + # Gradle fails if ANDROID_HOME and ANDROID_SDK_ROOT resolve to different + # SDK locations (CI images export ANDROID_SDK_ROOT to their own SDK), so + # both are pinned to the engine-provided SDK. + env = dict( + os.environ, + ANDROID_HOME=android_home, + ANDROID_SDK_ROOT=android_home, + JAVA_HOME=java_home(), + ) run_cmd(command, cwd=test_runner_dir, env=env) diff --git a/engine/src/flutter/tools/pkg/github_workflow_generator/artifact_tests.json b/engine/src/flutter/tools/pkg/github_workflow_generator/artifact_tests.json new file mode 100644 index 00000000..4de82def --- /dev/null +++ b/engine/src/flutter/tools/pkg/github_workflow_generator/artifact_tests.json @@ -0,0 +1,57 @@ +{ + "_comment": [ + "Defines special test jobs that download the full build output of", + "artifact-producing build jobs (no rebuilding) and run the engine", + "C++ unit tests against them.", + "", + "Each job downloads the out/ directory tar uploaded by the", + "build job named in `downloads` (every build job uploads its build", + "output). The tested build's ninja targets must include", + "`flutter:unittests` so that the *_unittests binaries are present in", + "the build dir; run_tests.py then discovers and runs them (--type", + "engine).", + "", + "For each entry in `tests`, run_tests.py runs with --variant, --type", + "and, when present, --android-variant / --ios-variant.", + "", + "The jobs below run the engine unittests for ci/host_debug on", + "linux/windows and for the debug/profile/release arm64 host builds", + "on macOS." + ], + "test_jobs": [ + { + "name": "ios_unit_engine_test", + "runs_on": "macos-latest", + "python": "python3", + "gclient": "slim", + "downloads": [ + "mac_ios_test_binaries_arm64" + ], + "tests": [ + { + "name": "iOS unit tests for ci/ios_test_binaries_arm64", + "variant": "ci/ios_test_binaries_arm64", + "ios_variant": "ci/ios_test_binaries_arm64", + "types": "objc" + } + ] + }, + { + "name": "android_java_engine_test", + "runs_on": "ubuntu-latest", + "python": "python3", + "gclient": "standard", + "downloads": [ + "linux_android_debug_arm64" + ], + "tests": [ + { + "name": "Android Java unit tests for ci/android_debug_arm64", + "variant": "ci/android_debug_arm64", + "android_variant": "ci/android_debug_arm64", + "types": "java" + } + ] + } + ] +} diff --git a/engine/src/flutter/tools/pkg/github_workflow_generator/lib/github_workflow_generator.dart b/engine/src/flutter/tools/pkg/github_workflow_generator/lib/github_workflow_generator.dart index 832930a5..08d9f6f1 100644 --- a/engine/src/flutter/tools/pkg/github_workflow_generator/lib/github_workflow_generator.dart +++ b/engine/src/flutter/tools/pkg/github_workflow_generator/lib/github_workflow_generator.dart @@ -70,6 +70,15 @@ class ArtifactPublisher { ); } + void registerTestJob(String jobName) { + _dependentTestJobs.add(jobName); + } + + /// Publishes everything this run produced. On staging pushes the artifacts + /// go to the production bucket, and the `latest_content_hash` pointer is + /// advanced. On pull requests everything goes under a unique per-run prefix + /// of the CI-only bucket instead - a disposable deployment that the + /// `remove_ci_artifacts` teardown job of the same run deletes afterwards. void writePublishJob(YamlWriterSection jobsSection) { if (_artifacts.isEmpty) { return; @@ -80,9 +89,13 @@ class ArtifactPublisher { run.writeln('shell: bash'); final needs = job.beginArray('needs'); _dependentJobs.forEach(needs.writeln); + _dependentTestJobs.forEach(needs.writeln); needs.writeln('guard'); job.write('runs-on', 'ubuntu-latest'); - job.write('if', r"${{ needs.guard.outputs.should_run == 'true' }}"); + job.write( + 'if', + r"${{ needs.guard.outputs.should_run == 'true' }}", + ); final steps = job.beginArray('steps'); { final step = steps.beginMap('name', 'Expose engine content hash'); @@ -108,31 +121,47 @@ class ArtifactPublisher { run.writeln('rm artifact-${artifact.id}/artifact_${artifact.id}.tar'); } } + { + // Selects the R2 destination for this run once for all publish + // steps: pull requests deploy under a unique per-run prefix of the + // CI-only bucket (disposable, the run's teardown job removes it); + // staging pushes deploy to the production bucket with no prefix and + // advance latest_content_hash. The same credential secrets have write + // access to both buckets. + final step = steps.beginMap('name', 'Select the R2 target'); + step.write('id', 'r2_target'); + final runEnv = step.beginMap('env'); + runEnv.writeln('R2_ENGINE_BUCKET: flutter-zero-engine'); + runEnv.writeln('R2_CI_BUCKET: $ciBucketName'); + final run = step.beginMap('run', '|'); + run.writeln(r'if [ "${GITHUB_EVENT_NAME}" = "pull_request" ]; then'); + run.writeln(r' echo "bucket=$R2_CI_BUCKET" >> $GITHUB_OUTPUT'); + run.writeln(r' echo "prefix=pr-${GITHUB_RUN_ID}/" >> $GITHUB_OUTPUT'); + run.writeln(r'else'); + run.writeln(r' echo "bucket=$R2_ENGINE_BUCKET" >> $GITHUB_OUTPUT'); + run.writeln(r' echo "prefix=" >> $GITHUB_OUTPUT'); + run.writeln(r'fi'); + } for (final artifact in _artifacts) { final name = path.basename(artifact.sourcePath); - final step = steps.beginMap('name', 'Publish ${artifact.outputPath}/$name'); - step.write('uses', 'ryand56/r2-upload-action@b801a390acbdeb034c5e684ff5e1361c06639e7c'); - final w = step.beginMap('with'); - w.write('r2-account-id', r'${{ secrets.R2_ACCOUNT_ID }}'); - w.write('r2-access-key-id', r'${{ secrets.R2_ACCESS_KEY_ID }}'); - w.write('r2-secret-access-key', r'${{ secrets.R2_SECRET_ACCESS_KEY }}'); - w.write('r2-bucket', r'${{ env.R2_BUCKET }}'); - w.write('source-dir', 'artifact-${artifact.id}/'); - if (name.contains('flutter.io')) { - // android - w.write( - 'destination-dir', - './', - ); - } else { - w.write( - 'destination-dir', - 'flutter_infra_release/flutter/\${{ steps.engine_content_hash.outputs.value }}/${artifact.outputPath}', - ); - } + // Pull requests deploy under the selected per-run prefix; staging + // pushes deploy (as before) keyed directly by the engine content hash + // with no prefix. + final baseDestination = name.contains('flutter.io') + // android + ? '' + : 'flutter_infra_release/flutter/\${{ steps.engine_content_hash.outputs.value }}/${artifact.outputPath}'; + _writeR2UploadStep( + steps, + name: 'Publish ${artifact.outputPath}/$name', + bucket: '\${{ steps.r2_target.outputs.bucket }}', + destinationDir: '\${{ steps.r2_target.outputs.prefix }}$baseDestination', + sourceDir: 'artifact-${artifact.id}/', + ); } { final step = steps.beginMap('name', 'Create latest_content_hash.txt'); + step.write('if', r"${{ github.event_name != 'pull_request' }}"); final run = step.beginMap('run', '|'); run.writeln(r'mkdir -p latest_content_hash'); run.writeln( @@ -140,21 +169,47 @@ class ArtifactPublisher { ); } { - final step = steps.beginMap('name', 'Publish latest_content_hash.txt'); - step.write('uses', 'ryand56/r2-upload-action@b801a390acbdeb034c5e684ff5e1361c06639e7c'); - final w = step.beginMap('with'); - w.write('r2-account-id', r'${{ secrets.R2_ACCOUNT_ID }}'); - w.write('r2-access-key-id', r'${{ secrets.R2_ACCESS_KEY_ID }}'); - w.write('r2-secret-access-key', r'${{ secrets.R2_SECRET_ACCESS_KEY }}'); - w.write('r2-bucket', r'${{ env.R2_BUCKET }}'); - w.write('source-dir', 'latest_content_hash/'); - w.write( - 'destination-dir', - 'flutter_infra_release/flutter/', + _writeR2UploadStep( + steps, + name: 'Publish latest_content_hash.txt', + ifCondition: r"${{ github.event_name != 'pull_request' }}", + bucket: '\${{ steps.r2_target.outputs.bucket }}', + destinationDir: 'flutter_infra_release/flutter/', + sourceDir: 'latest_content_hash/', + id: 'publish_latest_content_hash', ); } } + void _writeR2UploadStep( + YamlWriterSection steps, { + required String name, + required String bucket, + required String destinationDir, + required String sourceDir, + String? ifCondition, + String? id, + }) { + final step = steps.beginMap('name', name); + if (ifCondition != null) { + step.write('if', ifCondition); + } + if (id != null) { + step.write('id', id); + } + step.write('uses', r2UploadAction); + final w = step.beginMap('with'); + w.write('r2-account-id', '\${{ secrets.R2_ACCOUNT_ID }}'); + w.write('r2-access-key-id', '\${{ secrets.R2_ACCESS_KEY_ID }}'); + w.write('r2-secret-access-key', '\${{ secrets.R2_SECRET_ACCESS_KEY }}'); + w.write('r2-bucket', bucket); + w.write('source-dir', sourceDir); + w.write('destination-dir', destinationDir.isEmpty ? './' : destinationDir); + } + + static const r2UploadAction = 'ryand56/r2-upload-action@b801a390acbdeb034c5e684ff5e1361c06639e7c'; + + final _dependentTestJobs = {}; final _dependentJobs = {}; final _artifacts = <_Artifact>[]; int _count = 0; @@ -171,10 +226,31 @@ class YamlWriterSection { } void write(String label, String value) { - final line = value.isEmpty ? '$label:' : '$label: $value'; + final line = value.isEmpty ? '$label:' : '$label: ${_escapeScalar(value)}'; writeln(line); } + static String _escapeScalar(String value) { + // '|' is written bare for run-step block scalars (beginMap('run', '|')). + if (value == '|') { + return value; + } + // A plain (unquoted) scalar must not look like a comment, a nested map, or + // contain characters that terminate the scalar early (':' followed by + // whitespace, or a ' #' comment start). + final problematic = + value.startsWith(' ') || + value.endsWith(' ') || + value.contains(': ') || + value.endsWith(':') || + value.contains(' #'); + if (!problematic) { + return value; + } + final escaped = value.replaceAll("'", "''"); + return "'$escaped'"; + } + YamlWriterSection beginMap(String label, [String value = '']) { write(label, value); final section = YamlWriterSection._(writer, isArray: false); @@ -198,9 +274,11 @@ class BuildConfigWriter { required BuilderConfig config, required YamlWriterSection jobsSections, required ArtifactPublisher artifactPublisher, + required Set testBuildOutputs, }) : _config = config, _jobsSections = jobsSections, - _artifactPublisher = artifactPublisher; + _artifactPublisher = artifactPublisher, + _testBuildOutputs = testBuildOutputs; void write() { for (final build in _config.builds) { @@ -229,25 +307,49 @@ class BuildConfigWriter { run.writeln('./flutter/bin/et build --config ${build.name}'); } } + // Host builds that compile the unit test binaries run them in-place - + // no artifact download needed. + if (build.ninja.targets.contains('flutter:unittests')) { + final bool isWindows = _getRunnerForBuilder(build).startsWith('windows'); + final step = steps.beginMap('name', 'Run engine unit tests'); + final run = step.beginMap('run', '|'); + run.writeln('cd engine/src'); + // Windows runners only provide an unprefixed `python` executable. + run.writeln('${isWindows ? 'python' : 'python3'} flutter/testing/run_tests.py \\'); + // Forward slashes: the step runs under bash even on Windows + // runners, where a backslash would escape the next character. + run.writeln(' --variant ${build.name.replaceAll(r'\', '/')} \\'); + run.writeln(' --type engine \\'); + if (!isWindows) { + run.writeln(' --engine-capture-core-dump'); + } + } for (final generator in build.generators) { _writeBuildTask(steps, generator); } - // For global generators we need to upload artifacts so that we can use them - // in dependent jobs. - if (_config.generators.isNotEmpty) { - { - final step = steps.beginMap('name', 'Tar build files'); - final run = step.beginMap('run', '|'); - run.writeln('tar -cvf ${_nameForBuild(build)}.tar engine/src/out/${build.name}'); - } - { - final step = steps.beginMap('name', 'Upload build files'); - step.write('uses', 'actions/upload-artifact@v4'); - final w = step.beginMap('with'); - w.write('name', 'artifacts-${_nameForBuild(build)}-\${{ steps.engine_content_hash.outputs.value }}'); - w.write('path', '${_nameForBuild(build)}.tar'); - w.write('retention-days', '1'); - } + // Full build outputs are needed only by global packaging or test jobs. + if (_config.generators.isNotEmpty || _config.archives.isNotEmpty || + _testBuildOutputs.contains(_nameForBuild(build))) { + { + final step = steps.beginMap('name', 'Tar build files'); + final run = step.beginMap('run', '|'); + // The out dir is derived from the ninja config (which may lack the + // "ci/" prefix, e.g. the web wasm_release build), not from the build + // name. + final outDir = build.ninja.config.isEmpty + ? build.name.replaceAll(r'\', '/') + : build.ninja.config.replaceAll(r'\', '/'); + run.writeln('find engine/src/out/$outDir -type l -lname "/*" -delete || true'); + run.writeln('tar -cvf ${_nameForBuild(build)}.tar engine/src/out/$outDir'); + } + { + final step = steps.beginMap('name', 'Upload build files'); + step.write('uses', 'actions/upload-artifact@v4'); + final w = step.beginMap('with'); + w.write('name', 'artifacts-${_nameForBuild(build)}-\${{ steps.engine_content_hash.outputs.value }}'); + w.write('path', '${_nameForBuild(build)}.tar'); + w.write('retention-days', '1'); + } } for (final archive in build.archives) { for (final assetPath in archive.includePaths) { @@ -328,12 +430,7 @@ class BuildConfigWriter { w.write('path', "''"); } { - final step = steps.beginMap('name', 'Set up depot_tools'); - step.write('if', "runner.os != 'Windows'"); - final run = step.beginMap('run', '|'); - run.writeln(r'git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git $HOME/depot_tools'); - run.writeln('# Append depot_tools to the PATH for subsequent steps'); - run.writeln(r'echo "$HOME/depot_tools" >> $GITHUB_PATH'); + _writeDepotToolsStep(steps, ifCondition: "runner.os != 'Windows'", isWindows: false); } if (_config.generators.any((b) => b.name == 'api-documentation')) { final step = steps.beginMap('name', 'Install doxygen'); @@ -352,13 +449,7 @@ class BuildConfigWriter { ); } { - final step = steps.beginMap('name', 'Set up depot_tools'); - step.write('if', "runner.os == 'Windows'"); - final run = step.beginMap('run', '|'); - run.writeln(r'git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git $HOME/depot_tools'); - run.writeln('# Append depot_tools to the PATH for subsequent steps'); - run.writeln(r'DEPOT_TOOLS_WIN=$(cygpath -w "$HOME/depot_tools")'); - run.writeln(r'echo "$DEPOT_TOOLS_WIN" >> $GITHUB_PATH'); + _writeDepotToolsStep(steps, ifCondition: "runner.os == 'Windows'", isWindows: true); } { final step = steps.beginMap('name', 'Generate engine content hash'); @@ -370,7 +461,14 @@ class BuildConfigWriter { { final step = steps.beginMap('name', 'Copy gclient file'); final run = step.beginMap('run', '|'); - if (path.basename(_config.path).contains('android')) { + // Android toolchains are only fetched when the standard gclient file + // is used. This must cover configs that build android targets even + // when the config file itself is not named after android (e.g. + // linux_unopt.json). + final needsAndroidDeps = + path.basename(_config.path).contains('android') || + _config.builds.any((build) => build.gn.contains('--android')); + if (needsAndroidDeps) { run.writeln('cp engine/scripts/standard.gclient .gclient'); } else if (path.basename(_config.path).contains('web')) { run.writeln('cp engine/scripts/web.gclient .gclient'); @@ -392,6 +490,8 @@ class BuildConfigWriter { return 'FLUTTER_PREBUILT_ENGINE_VERSION=\${{ needs.guard.outputs.latest_content_hash }} ../../bin/dart $script'; } else if (language == 'python3') { return 'python3 $script'; + } else if (language == 'python') { + return 'python $script'; } else if (language == 'bash' || language == '') { return script; } else { @@ -471,8 +571,288 @@ class BuildConfigWriter { final BuilderConfig _config; final YamlWriterSection _jobsSections; final ArtifactPublisher _artifactPublisher; + final Set _testBuildOutputs; +} + +/// A single test run inside an artifact test job. +class _ArtifactTest { + const _ArtifactTest({ + required this.name, + required this.variant, + required this.types, + this.androidVariant, + this.iosVariant, + }); + + final String name; + final String variant; + final String types; + + final String? androidVariant; + final String? iosVariant; +} + +/// A generated test job that runs against build outputs uploaded by regular +/// build jobs, without rebuilding anything. +class _ArtifactTestJob { + const _ArtifactTestJob({ + required this.name, + required this.runsOn, + required this.python, + required this.gclient, + required this.downloads, + required this.tests, + }); + + final String name; + final String runsOn; + + /// Python executable used to invoke run_tests.py (GitHub Windows runners + /// only provide an unprefixed `python`). + final String python; + + /// Which gclient file to sync with (slim, standard or web). + final String gclient; + + /// Names of build jobs whose full build-output tar is downloaded and + /// extracted before the tests run. + final List downloads; + final List<_ArtifactTest> tests; + + static _ArtifactTest _testFromJson(Map map) { + final variant = map['variant']! as String; + final types = map['types']! as String; + final androidVariant = map['android_variant'] as String?; + final iosVariant = map['ios_variant'] as String?; + return _ArtifactTest( + name: (map['name'] as String?) ?? 'for $variant', + variant: variant, + types: types, + androidVariant: androidVariant, + iosVariant: iosVariant, + ); + } + + static _ArtifactTestJob fromJson(Map map) { + final name = map['name']! as String; + final runsOn = map['runs_on']! as String; + final python = map['python'] as String? ?? 'python3'; + final gclient = map['gclient'] as String? ?? 'slim'; + final downloads = (map['downloads'] as List? ?? []).cast(); + final tests = (map['tests'] as List? ?? []).cast>().map(_testFromJson).toList(); + if (downloads.isEmpty) { + throw Exception('Artifact test job $name has no downloads'); + } + if (tests.isEmpty) { + throw Exception('Artifact test job $name has no tests'); + } + return _ArtifactTestJob( + name: name, + runsOn: runsOn, + python: python, + gclient: gclient, + downloads: downloads, + tests: tests, + ); + } +} + +/// Emits a depot_tools setup step: cleans up any checkout left corrupt by a +/// failed previous attempt (the same HOME is reused across job retries), then +/// clones with retries - clones from chromium.googlesource.com occasionally +/// fail mid-transfer and the bare command is the most common source of CI +/// flake. +void _writeDepotToolsStep( + YamlWriterSection steps, { + String? ifCondition, + required bool isWindows, +}) { + final step = steps.beginMap('name', 'Set up depot_tools'); + if (ifCondition != null) { + step.write('if', ifCondition); + } + final run = step.beginMap('run', '|'); + run.writeln(r'rm -rf "$HOME/depot_tools"'); + run.writeln('for attempt in 1 2 3; do'); + run.writeln( + r' git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git "$HOME/depot_tools" && break', + ); + run.writeln(r' rm -rf "$HOME/depot_tools"'); + run.writeln(r' echo "depot_tools clone failed (attempt $attempt), retrying..."'); + run.writeln(' sleep 5'); + run.writeln('done'); + run.writeln(r'test -d "$HOME/depot_tools/.git"'); + run.writeln('# Append depot_tools to the PATH for subsequent steps'); + if (isWindows) { + run.writeln(r'DEPOT_TOOLS_WIN=$(cygpath -w "$HOME/depot_tools")'); + run.writeln(r'echo "$DEPOT_TOOLS_WIN" >> $GITHUB_PATH'); + } else { + run.writeln(r'echo "$HOME/depot_tools" >> $GITHUB_PATH'); + } +} + +/// Emits jobs that run tests against build outputs uploaded by the +/// artifact-producing build jobs (no rebuilding). The job specs come from the +/// JSON files passed via `--artifact-tests`. +List<_ArtifactTestJob> _readArtifactTestJobs(List specFiles) { + final jobs = <_ArtifactTestJob>[]; + for (final specFile in specFiles) { + final content = File(specFile).readAsStringSync(); + final map = jsonDecode(content) as Map; + final jobMaps = (map['test_jobs'] as List? ?? []).cast>(); + if (jobMaps.isEmpty) { + throw Exception('Artifact test spec $specFile has no test_jobs'); + } + jobs.addAll(jobMaps.map(_ArtifactTestJob.fromJson)); + } + return jobs; +} + +void _writeArtifactTestJobs( + YamlWriterSection jobsSection, + ArtifactPublisher artifactPublisher, + List<_ArtifactTestJob> jobs, +) { + const gclientFileFor = { + 'slim': 'slim.gclient', + 'standard': 'standard.gclient', + 'web': 'web.gclient', + }; + for (final job in jobs) { + final generated = jobsSection.beginMap(job.name); + generated.write('runs-on', job.runsOn); + final defaults = generated.beginMap('defaults'); + final runDefaults = defaults.beginMap('run'); + runDefaults.writeln('shell: bash'); + final needs = generated.beginArray('needs'); + job.downloads.forEach(needs.writeln); + needs.writeln('guard'); + generated.write('if', r"${{ needs.guard.outputs.should_run == 'true' }}"); + final steps = generated.beginArray('steps'); + { + final step = steps.beginMap('name', 'Checkout the repository'); + step.write('uses', 'actions/checkout@v4'); + final w = step.beginMap('with'); + w.write('path', "''"); + } + { + _writeDepotToolsStep(steps, isWindows: job.runsOn.startsWith('windows')); + } + { + final step = steps.beginMap('name', 'Expose engine content hash'); + step.write('id', 'engine_content_hash'); + final run = step.beginMap('run', '|'); + run.writeln(r'engine_content_hash=${{ needs.guard.outputs.engine_content_hash }}'); + run.writeln(r'echo "value=${engine_content_hash}" >> $GITHUB_OUTPUT'); + } + { + final step = steps.beginMap('name', 'Copy gclient file'); + final run = step.beginMap('run', '|'); + final gclientFile = gclientFileFor[job.gclient]; + if (gclientFile == null) { + throw Exception('Unknown gclient flavor ${job.gclient} in artifact test job ${job.name}'); + } + run.writeln('cp engine/scripts/$gclientFile .gclient'); + } + { + final step = steps.beginMap('name', 'GClient sync'); + final run = step.beginMap('run', '|'); + run.writeln('gclient sync -D --no-history --shallow --with_branch_heads'); + } + for (final download in job.downloads) { + { + final step = steps.beginMap('name', 'Download Artifacts from $download'); + step.write('uses', 'actions/download-artifact@v4'); + final w = step.beginMap('with'); + w.write('name', 'artifacts-$download-\${{ steps.engine_content_hash.outputs.value }}'); + } + { + final step = steps.beginMap('name', 'Extract Artifacts from $download'); + final run = step.beginMap('run', '|'); + run.writeln('tar -xvf $download.tar'); + run.writeln('rm $download.tar'); + } + } + for (final test in job.tests) { + final step = steps.beginMap('name', 'Run test ${test.name}'); + final run = step.beginMap('run', '|'); + run.writeln('cd engine/src'); + run.writeln('${job.python} flutter/testing/run_tests.py \\'); + run.writeln(' --variant ${test.variant} \\'); + run.writeln(' --type ${test.types} \\'); + if (test.androidVariant != null) { + run.writeln(' --android-variant ${test.androidVariant} \\'); + } + if (test.iosVariant != null) { + run.writeln(' --ios-variant ${test.iosVariant} \\'); + } + // --engine-capture-core-dump is not supported on Windows runners. + if (!job.runsOn.startsWith('windows')) { + run.writeln(' --engine-capture-core-dump'); + } + } + artifactPublisher.registerTestJob(job.name); + } +} + +/// Emits the job that invokes the smoke test workflow with the per-run prefix +/// of this deployment (the same run). Only for pull requests; on staging +/// pushes the smoke test flow is exercised by the call-smoke-test companion +/// workflow instead. The smoke test workflow itself is call-only. +void _writeSmokeTestInvocationJob(YamlWriterSection jobsSection) { + final job = jobsSection.beginMap('smoke_test'); + job.write('name', 'Run the smoke test'); + job.write('uses', './.github/workflows/smoke-test.yml'); + final needs = job.beginArray('needs'); + needs.writeln('publish_artifacts'); + job.write( + 'if', + r"${{ github.event_name == 'pull_request' }}", + ); + final withNode = job.beginMap('with'); + withNode.write('run_id', r'${{ github.run_id }}'); } +/// Emits the teardown job of the CI-only artifacts bucket: the per-run prefix +/// this run published is removed again, unconditionally (always(), pass, +/// fail, cancel - the run's deployment is disposable). +void _writeCiBucketTeardownJob( + YamlWriterSection jobsSection, + Set targets, +) { + final job = jobsSection.beginMap('remove_ci_artifacts'); + job.write('runs-on', 'ubuntu-latest'); + final needs = job.beginArray('needs'); + targets.forEach(needs.writeln); + job.write('if', 'always()'); + final steps = job.beginArray('steps'); + { + final step = steps.beginMap('name', 'Remove the run prefix from the CI bucket'); + step.write('if', r"${{ github.event_name == 'pull_request' }}"); + final runEnv = step.beginMap('env'); + runEnv.writeln( + 'AWS_ACCESS_KEY_ID: \${{ secrets.R2_ACCESS_KEY_ID }}', + ); + runEnv.writeln( + 'AWS_SECRET_ACCESS_KEY: \${{ secrets.R2_SECRET_ACCESS_KEY }}', + ); + runEnv.writeln( + 'AWS_ENDPOINT_URL_S3: $r2S3Endpoint', + ); + runEnv.writeln('AWS_DEFAULT_REGION: auto'); + final run = step.beginMap('run', '|'); + run.writeln( + 'aws s3 rm s3://$ciBucketName/pr-\${{ github.run_id }}/ --recursive', + ); + } +} + +/// The CI-only artifacts bucket: pull request deployments are published under +/// a unique per-run prefix here, giving short-lived, disposable copies that +/// never touch the production buckets. +const ciBucketName = 'flutter-zero-ci'; +const r2S3Endpoint = 'https://b468378afe5657ffecccb682fe82ccac.r2.cloudflarestorage.com'; + void _writeGuardJob(YamlWriterSection jobsSection) { final job = jobsSection.beginMap('guard'); job.write('runs-on', 'ubuntu-latest'); @@ -538,6 +918,13 @@ void main(List arguments) { valueHelp: 'path', defaultsTo: '', ); + parser.addMultiOption( + 'artifact-tests', + abbr: 't', + help: 'Path to a JSON file with artifact test job specs (test_jobs).', + valueHelp: 'path', + defaultsTo: [], + ); final ArgResults args; try { @@ -555,6 +942,9 @@ void main(List arguments) { } final yamlWriter = YamlWriter(); + final artifactTestSpecs = (args['artifact-tests'] as List?) ?? const []; + final artifactTestJobs = _readArtifactTestJobs(artifactTestSpecs); + final testBuildOutputs = artifactTestJobs.expand((job) => job.downloads).toSet(); final root = yamlWriter.root; root.writeln('# This file is generated through `scripts/update_github_workflow.sh.`'); root.writeln('# Do not edit directly.'); @@ -562,12 +952,12 @@ void main(List arguments) { final on = root.beginMap('on'); final push = on.beginMap('push'); - push.write('branches', '["master", "staging"]'); + push.write('branches', '["staging"]'); + on.beginMap('pull_request'); final env = root.beginMap('env'); env.write('DEPOT_TOOLS_WIN_TOOLCHAIN', '0'); env.write('FLUTTER_PREBUILT_DART_SDK', '1'); - env.write('R2_BUCKET', 'flutter-zero-engine'); env.write('ENGINE_CHECKOUT_PATH', r'${{ github.workspace }}/engine'); final jobs = root.beginMap('jobs'); @@ -584,11 +974,19 @@ void main(List arguments) { config: buildConfig, jobsSections: jobs, artifactPublisher: artifactPublisher, + testBuildOutputs: testBuildOutputs, ); writer.write(); } + _writeArtifactTestJobs(jobs, artifactPublisher, artifactTestJobs); + artifactPublisher.writePublishJob(jobs); + _writeSmokeTestInvocationJob(jobs); + // The per-run prefix this run published to the CI bucket is removed + // afterwards, unconditionally (always(), pass, fail, cancel - the run's + // deployment is disposable). + _writeCiBucketTeardownJob(jobs, const {'publish_artifacts', 'smoke_test'}); if (args['output'] != '') { final outputFile = File(args['output'] as String); diff --git a/packages/flutter_tools/lib/src/base/user_messages.dart b/packages/flutter_tools/lib/src/base/user_messages.dart index 608e75b5..40d56b8f 100644 --- a/packages/flutter_tools/lib/src/base/user_messages.dart +++ b/packages/flutter_tools/lib/src/base/user_messages.dart @@ -161,8 +161,8 @@ class UserMessages { String pkgConfigTooOld(String minimumVersion) => 'pkg-config $minimumVersion or later is required.'; String get gtkLibrariesMissing => - 'GTK 3.0 development libraries are required for Linux development.\n' - 'They are likely available from your distribution (e.g.: apt install libgtk-3-dev)'; + 'GLib development libraries are required for Linux development.\n' + 'They are likely available from your distribution (e.g.: apt install libglib2.0-dev)'; String get eglinfoMissing => "Unable to access driver information using 'eglinfo'.\n" 'It is likely available from your distribution (e.g.: apt install mesa-utils)'; diff --git a/packages/flutter_tools/lib/src/build_system/targets/web.dart b/packages/flutter_tools/lib/src/build_system/targets/web.dart index 9f5a78f4..12ee35e1 100644 --- a/packages/flutter_tools/lib/src/build_system/targets/web.dart +++ b/packages/flutter_tools/lib/src/build_system/targets/web.dart @@ -684,9 +684,8 @@ class WebReleaseBundle extends Target { targetPlatform: TargetPlatform.web_javascript, buildMode: buildMode, ); - final Depfile bundledDepfile = _bundleLocalRobotoFallback(environment, depfile); final DepfileService depfileService = environment.depFileService; - depfileService.writeToFile(bundledDepfile, environment.buildDir.childFile('flutter_assets.d')); + depfileService.writeToFile(depfile, environment.buildDir.childFile('flutter_assets.d')); final Directory webResources = environment.projectDir.childDirectory('web'); final List inputResourceFiles = webResources @@ -731,61 +730,9 @@ class WebReleaseBundle extends Target { environment.outputDir.childFile('version.json').writeAsStringSync(jsonEncode(versionInfo)); } - Depfile _bundleLocalRobotoFallback(Environment environment, Depfile depfile) { - if (environment.defines[kUseLocalCanvasKitFlag] != 'true') { - return depfile; - } - - final File fontManifestFile = environment.outputDir - .childDirectory('assets') - .childFile(_kFontManifestJsonFile); - final manifestJson = fontManifestFile.existsSync() - ? (jsonDecode(fontManifestFile.readAsStringSync()) as List) - : []; - - final bool hasRobotoFamily = manifestJson.any((Object? entry) { - return entry is Map && entry['family'] == _kBundledFallbackRobotoFamily; - }); - if (hasRobotoFamily) { - return depfile; - } - - final File sourceRobotoFont = environment.fileSystem.file( - environment.fileSystem.path.join( - Cache.flutterRoot!, - 'engine', - 'src', - 'flutter', - 'txt', - 'third_party', - 'fonts', - 'Roboto-Regular.ttf', - ), - ); - if (!sourceRobotoFont.existsSync()) { - throwToolExit('Failed to find the bundled Roboto font at ${sourceRobotoFont.path}.'); - } - - manifestJson.add({ - 'family': _kBundledFallbackRobotoFamily, - 'fonts': >[ - {'asset': _kBundledFallbackRobotoAsset}, - ], - }); - fontManifestFile.parent.createSync(recursive: true); - fontManifestFile.writeAsStringSync(jsonEncode(manifestJson)); - - final File bundledRobotoFont = environment.outputDir - .childDirectory('assets') - .childFile(_kBundledFallbackRobotoAsset); - bundledRobotoFont.parent.createSync(recursive: true); - sourceRobotoFont.copySync(bundledRobotoFont.path); - - return Depfile( - [...depfile.inputs, sourceRobotoFont], - [...depfile.outputs, fontManifestFile, bundledRobotoFont], - ); - } + // flutter_zero never bundles the Roboto fallback font (headless engine, no + // txt/third_party/fonts tree), so the upstream `_bundleLocalRobotoFallback` + // hook is removed entirely. } class WebTemplatedFiles extends Target { diff --git a/packages/flutter_tools/lib/src/linux/linux_doctor.dart b/packages/flutter_tools/lib/src/linux/linux_doctor.dart index 2900f7da..2024b92c 100644 --- a/packages/flutter_tools/lib/src/linux/linux_doctor.dart +++ b/packages/flutter_tools/lib/src/linux/linux_doctor.dart @@ -137,7 +137,7 @@ class LinuxDoctorValidator extends DoctorValidator { kPkgConfigBinary: Version(0, 29, 0), }; - final _requiredGtkLibraries = ['gtk+-3.0', 'glib-2.0', 'gio-2.0']; + final _requiredGLibLibraries = ['glib-2.0', 'gio-2.0']; @override Future validateImpl() async { @@ -234,7 +234,7 @@ class LinuxDoctorValidator extends DoctorValidator { // Messages for libraries. { var libraryMissing = false; - for (final String library in _requiredGtkLibraries) { + for (final String library in _requiredGLibLibraries) { if (!await _libraryIsPresent(library)) { libraryMissing = true; break; diff --git a/packages/flutter_tools/templates/app/linux.tmpl/CMakeLists.txt.tmpl b/packages/flutter_tools/templates/app/linux.tmpl/CMakeLists.txt.tmpl index f710aa3d..ddcafc32 100644 --- a/packages/flutter_tools/templates/app/linux.tmpl/CMakeLists.txt.tmpl +++ b/packages/flutter_tools/templates/app/linux.tmpl/CMakeLists.txt.tmpl @@ -5,7 +5,7 @@ project(runner LANGUAGES CXX) # The name of the executable created for the application. Change this to change # the on-disk name of your application. set(BINARY_NAME "{{projectName}}") -# The unique GTK application identifier for this application. See: +# The unique application identifier for this application. See: # https://wiki.gnome.org/HowDoI/ChooseApplicationID set(APPLICATION_ID "{{linuxIdentifier}}") @@ -52,7 +52,8 @@ add_subdirectory(${FLUTTER_MANAGED_DIR}) # System-level dependencies. find_package(PkgConfig REQUIRED) -pkg_check_modules(GTK REQUIRED IMPORTED_TARGET gtk+-3.0) +pkg_check_modules(GLIB REQUIRED IMPORTED_TARGET glib-2.0) +pkg_check_modules(GIO REQUIRED IMPORTED_TARGET gio-2.0) # Application build; see runner/CMakeLists.txt. add_subdirectory("runner") diff --git a/packages/flutter_tools/templates/app/linux.tmpl/flutter/CMakeLists.txt b/packages/flutter_tools/templates/app/linux.tmpl/flutter/CMakeLists.txt index d5bd0164..5fc74f9c 100644 --- a/packages/flutter_tools/templates/app/linux.tmpl/flutter/CMakeLists.txt +++ b/packages/flutter_tools/templates/app/linux.tmpl/flutter/CMakeLists.txt @@ -22,7 +22,6 @@ endfunction() # === Flutter Library === # System-level dependencies. find_package(PkgConfig REQUIRED) -pkg_check_modules(GTK REQUIRED IMPORTED_TARGET gtk+-3.0) pkg_check_modules(GLIB REQUIRED IMPORTED_TARGET glib-2.0) pkg_check_modules(GIO REQUIRED IMPORTED_TARGET gio-2.0) @@ -63,7 +62,6 @@ target_include_directories(flutter INTERFACE ) target_link_libraries(flutter INTERFACE "${FLUTTER_LIBRARY}") target_link_libraries(flutter INTERFACE - PkgConfig::GTK PkgConfig::GLIB PkgConfig::GIO ) diff --git a/packages/flutter_tools/templates/app/linux.tmpl/runner/CMakeLists.txt b/packages/flutter_tools/templates/app/linux.tmpl/runner/CMakeLists.txt index e97dabc7..bf63b0bd 100644 --- a/packages/flutter_tools/templates/app/linux.tmpl/runner/CMakeLists.txt +++ b/packages/flutter_tools/templates/app/linux.tmpl/runner/CMakeLists.txt @@ -21,6 +21,6 @@ add_definitions(-DAPPLICATION_ID="${APPLICATION_ID}") # Add dependency libraries. Add any application-specific dependencies here. target_link_libraries(${BINARY_NAME} PRIVATE flutter) -target_link_libraries(${BINARY_NAME} PRIVATE PkgConfig::GTK) +target_link_libraries(${BINARY_NAME} PRIVATE PkgConfig::GLIB PkgConfig::GIO) target_include_directories(${BINARY_NAME} PRIVATE "${CMAKE_SOURCE_DIR}") diff --git a/packages/flutter_tools/templates/app/linux.tmpl/runner/my_application.cc.tmpl b/packages/flutter_tools/templates/app/linux.tmpl/runner/my_application.cc.tmpl index 6ff97760..8a5eddb8 100644 --- a/packages/flutter_tools/templates/app/linux.tmpl/runner/my_application.cc.tmpl +++ b/packages/flutter_tools/templates/app/linux.tmpl/runner/my_application.cc.tmpl @@ -1,19 +1,16 @@ #include "my_application.h" #include -#ifdef GDK_WINDOWING_X11 -#include -#endif #include "flutter/generated_plugin_registrant.h" struct _MyApplication { - GtkApplication parent_instance; + GApplication parent_instance; char** dart_entrypoint_arguments; FlEngine *engine; }; -G_DEFINE_TYPE(MyApplication, my_application, GTK_TYPE_APPLICATION) +G_DEFINE_TYPE(MyApplication, my_application, G_TYPE_APPLICATION) // Implements GApplication::activate. static void my_application_activate(GApplication *application) { @@ -95,7 +92,7 @@ static void my_application_init(MyApplication* self) {} MyApplication* my_application_new() { // Set the program name to the application ID, which helps various systems - // like GTK and desktop environments map this running application to its + // like desktop environments map this running application to its // corresponding .desktop file. This ensures better integration by allowing // the application to be recognized beyond its binary name. g_set_prgname(APPLICATION_ID); diff --git a/packages/flutter_tools/templates/app/linux.tmpl/runner/my_application.h b/packages/flutter_tools/templates/app/linux.tmpl/runner/my_application.h index db16367a..43759e8c 100644 --- a/packages/flutter_tools/templates/app/linux.tmpl/runner/my_application.h +++ b/packages/flutter_tools/templates/app/linux.tmpl/runner/my_application.h @@ -1,13 +1,13 @@ #ifndef FLUTTER_MY_APPLICATION_H_ #define FLUTTER_MY_APPLICATION_H_ -#include +#include G_DECLARE_FINAL_TYPE(MyApplication, my_application, MY, APPLICATION, - GtkApplication) + GApplication) /** * my_application_new: diff --git a/packages/flutter_tools/templates/plugin/linux.tmpl/CMakeLists.txt.tmpl b/packages/flutter_tools/templates/plugin/linux.tmpl/CMakeLists.txt.tmpl index 2d8110fe..eb1a2ddf 100644 --- a/packages/flutter_tools/templates/plugin/linux.tmpl/CMakeLists.txt.tmpl +++ b/packages/flutter_tools/templates/plugin/linux.tmpl/CMakeLists.txt.tmpl @@ -39,7 +39,7 @@ target_compile_definitions(${PLUGIN_NAME} PRIVATE FLUTTER_PLUGIN_IMPL) target_include_directories(${PLUGIN_NAME} INTERFACE "${CMAKE_CURRENT_SOURCE_DIR}/include") target_link_libraries(${PLUGIN_NAME} PRIVATE flutter) -target_link_libraries(${PLUGIN_NAME} PRIVATE PkgConfig::GTK) +target_link_libraries(${PLUGIN_NAME} PRIVATE PkgConfig::GLIB PkgConfig::GIO) # List of absolute paths to libraries that should be bundled with the plugin. # This list could contain prebuilt libraries, or libraries created by an @@ -83,7 +83,7 @@ add_executable(${TEST_RUNNER} apply_standard_settings(${TEST_RUNNER}) target_include_directories(${TEST_RUNNER} PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}") target_link_libraries(${TEST_RUNNER} PRIVATE flutter) -target_link_libraries(${TEST_RUNNER} PRIVATE PkgConfig::GTK) +target_link_libraries(${TEST_RUNNER} PRIVATE PkgConfig::GLIB PkgConfig::GIO) target_link_libraries(${TEST_RUNNER} PRIVATE gtest_main gmock) # Enable automatic test discovery. diff --git a/packages/flutter_tools/templates/template_manifest.json b/packages/flutter_tools/templates/template_manifest.json index 0765605b..e6e08d90 100644 --- a/packages/flutter_tools/templates/template_manifest.json +++ b/packages/flutter_tools/templates/template_manifest.json @@ -27,6 +27,7 @@ "templates/app/android-java.tmpl/build.gradle.kts.tmpl", "templates/app/android-java.tmpl/projectName_android.iml.tmpl", "templates/app/android-kotlin.tmpl/app/build.gradle.kts.tmpl", + "templates/app/android-kotlin.tmpl/app/src/main/kotlin/androidIdentifier/Application.kt.tmpl", "templates/app/android-kotlin.tmpl/app/src/main/kotlin/androidIdentifier/MainActivity.kt.tmpl", "templates/app/android-kotlin.tmpl/build.gradle.kts.tmpl", "templates/app/android-kotlin.tmpl/projectName_android.iml.tmpl", diff --git a/packages/flutter_tools/test/general.shard/linux/linux_doctor_test.dart b/packages/flutter_tools/test/general.shard/linux/linux_doctor_test.dart index e0790da9..370bc324 100644 --- a/packages/flutter_tools/test/general.shard/linux/linux_doctor_test.dart +++ b/packages/flutter_tools/test/general.shard/linux/linux_doctor_test.dart @@ -60,13 +60,9 @@ FakeCommand _libraryCheckCommand(String library, {bool exists = true}) { ); } -// Commands that give positive replies for all the GTK library pkg-config queries. +// Commands that give positive replies for all the GLib library pkg-config queries. List _gtkLibrariesPresentCommands() { - return [ - _libraryCheckCommand('gtk+-3.0'), - _libraryCheckCommand('glib-2.0'), - _libraryCheckCommand('gio-2.0'), - ]; + return [_libraryCheckCommand('glib-2.0'), _libraryCheckCommand('gio-2.0')]; } // A command that will return typical-looking 'eglinfo' output @@ -169,12 +165,11 @@ FakeCommand _eglinfoMissingCommand() { ); } -// Commands that give some failures for the GTK library pkg-config queries. +// Commands that give some failures for the GLib library pkg-config queries. List _gtkLibrariesMissingCommands() { return [ - _libraryCheckCommand('gtk+-3.0'), _libraryCheckCommand('glib-2.0', exists: false), - // No more entries, since the first missing GTK library stops the + // No more entries, since the first missing library stops the // checks. ]; } diff --git a/packages/flutter_tools_patches/0001-Linux-project-only-depends-on-glib-not-Gtk.patch b/packages/flutter_tools_patches/0001-Linux-project-only-depends-on-glib-not-Gtk.patch new file mode 100644 index 00000000..e3cf5739 --- /dev/null +++ b/packages/flutter_tools_patches/0001-Linux-project-only-depends-on-glib-not-Gtk.patch @@ -0,0 +1,224 @@ +From d9c8450347bb880b6b59c450775dc8061c0fefb6 Mon Sep 17 00:00:00 2001 +From: Matej Knopp +Date: Tue, 29 Sep 2026 22:06:20 +0200 +Subject: [PATCH] Linux project only depends on glib, not Gtk + +--- + .../flutter_tools/lib/src/base/user_messages.dart | 4 ++-- + .../flutter_tools/lib/src/linux/linux_doctor.dart | 4 ++-- + .../templates/app/linux.tmpl/CMakeLists.txt.tmpl | 5 +++-- + .../templates/app/linux.tmpl/flutter/CMakeLists.txt | 2 -- + .../templates/app/linux.tmpl/runner/CMakeLists.txt | 2 +- + .../app/linux.tmpl/runner/my_application.cc.tmpl | 9 +++------ + .../app/linux.tmpl/runner/my_application.h | 4 ++-- + .../templates/plugin/linux.tmpl/CMakeLists.txt.tmpl | 4 ++-- + .../test/general.shard/linux/linux_doctor_test.dart | 13 ++++--------- + 9 files changed, 19 insertions(+), 28 deletions(-) + +diff --git a/packages/flutter_tools/lib/src/base/user_messages.dart b/packages/flutter_tools/lib/src/base/user_messages.dart +index 608e75b5e0a..40d56b8fd20 100644 +--- a/packages/flutter_tools/lib/src/base/user_messages.dart ++++ b/packages/flutter_tools/lib/src/base/user_messages.dart +@@ -161,8 +161,8 @@ class UserMessages { + String pkgConfigTooOld(String minimumVersion) => + 'pkg-config $minimumVersion or later is required.'; + String get gtkLibrariesMissing => +- 'GTK 3.0 development libraries are required for Linux development.\n' +- 'They are likely available from your distribution (e.g.: apt install libgtk-3-dev)'; ++ 'GLib development libraries are required for Linux development.\n' ++ 'They are likely available from your distribution (e.g.: apt install libglib2.0-dev)'; + String get eglinfoMissing => + "Unable to access driver information using 'eglinfo'.\n" + 'It is likely available from your distribution (e.g.: apt install mesa-utils)'; +diff --git a/packages/flutter_tools/lib/src/linux/linux_doctor.dart b/packages/flutter_tools/lib/src/linux/linux_doctor.dart +index 2900f7dac6d..2024b92c274 100644 +--- a/packages/flutter_tools/lib/src/linux/linux_doctor.dart ++++ b/packages/flutter_tools/lib/src/linux/linux_doctor.dart +@@ -137,7 +137,7 @@ class LinuxDoctorValidator extends DoctorValidator { + kPkgConfigBinary: Version(0, 29, 0), + }; + +- final _requiredGtkLibraries = ['gtk+-3.0', 'glib-2.0', 'gio-2.0']; ++ final _requiredGLibLibraries = ['glib-2.0', 'gio-2.0']; + + @override + Future validateImpl() async { +@@ -234,7 +234,7 @@ class LinuxDoctorValidator extends DoctorValidator { + // Messages for libraries. + { + var libraryMissing = false; +- for (final String library in _requiredGtkLibraries) { ++ for (final String library in _requiredGLibLibraries) { + if (!await _libraryIsPresent(library)) { + libraryMissing = true; + break; +diff --git a/packages/flutter_tools/templates/app/linux.tmpl/CMakeLists.txt.tmpl b/packages/flutter_tools/templates/app/linux.tmpl/CMakeLists.txt.tmpl +index f710aa3d4ef..ddcafc32e2c 100644 +--- a/packages/flutter_tools/templates/app/linux.tmpl/CMakeLists.txt.tmpl ++++ b/packages/flutter_tools/templates/app/linux.tmpl/CMakeLists.txt.tmpl +@@ -5,7 +5,7 @@ project(runner LANGUAGES CXX) + # The name of the executable created for the application. Change this to change + # the on-disk name of your application. + set(BINARY_NAME "{{projectName}}") +-# The unique GTK application identifier for this application. See: ++# The unique application identifier for this application. See: + # https://wiki.gnome.org/HowDoI/ChooseApplicationID + set(APPLICATION_ID "{{linuxIdentifier}}") + +@@ -52,7 +52,8 @@ add_subdirectory(${FLUTTER_MANAGED_DIR}) + + # System-level dependencies. + find_package(PkgConfig REQUIRED) +-pkg_check_modules(GTK REQUIRED IMPORTED_TARGET gtk+-3.0) ++pkg_check_modules(GLIB REQUIRED IMPORTED_TARGET glib-2.0) ++pkg_check_modules(GIO REQUIRED IMPORTED_TARGET gio-2.0) + + # Application build; see runner/CMakeLists.txt. + add_subdirectory("runner") +diff --git a/packages/flutter_tools/templates/app/linux.tmpl/flutter/CMakeLists.txt b/packages/flutter_tools/templates/app/linux.tmpl/flutter/CMakeLists.txt +index d5bd01648a9..5fc74f9cb49 100644 +--- a/packages/flutter_tools/templates/app/linux.tmpl/flutter/CMakeLists.txt ++++ b/packages/flutter_tools/templates/app/linux.tmpl/flutter/CMakeLists.txt +@@ -22,7 +22,6 @@ endfunction() + # === Flutter Library === + # System-level dependencies. + find_package(PkgConfig REQUIRED) +-pkg_check_modules(GTK REQUIRED IMPORTED_TARGET gtk+-3.0) + pkg_check_modules(GLIB REQUIRED IMPORTED_TARGET glib-2.0) + pkg_check_modules(GIO REQUIRED IMPORTED_TARGET gio-2.0) + +@@ -63,7 +62,6 @@ target_include_directories(flutter INTERFACE + ) + target_link_libraries(flutter INTERFACE "${FLUTTER_LIBRARY}") + target_link_libraries(flutter INTERFACE +- PkgConfig::GTK + PkgConfig::GLIB + PkgConfig::GIO + ) +diff --git a/packages/flutter_tools/templates/app/linux.tmpl/runner/CMakeLists.txt b/packages/flutter_tools/templates/app/linux.tmpl/runner/CMakeLists.txt +index e97dabc7028..bf63b0bd7bc 100644 +--- a/packages/flutter_tools/templates/app/linux.tmpl/runner/CMakeLists.txt ++++ b/packages/flutter_tools/templates/app/linux.tmpl/runner/CMakeLists.txt +@@ -21,6 +21,6 @@ add_definitions(-DAPPLICATION_ID="${APPLICATION_ID}") + + # Add dependency libraries. Add any application-specific dependencies here. + target_link_libraries(${BINARY_NAME} PRIVATE flutter) +-target_link_libraries(${BINARY_NAME} PRIVATE PkgConfig::GTK) ++target_link_libraries(${BINARY_NAME} PRIVATE PkgConfig::GLIB PkgConfig::GIO) + + target_include_directories(${BINARY_NAME} PRIVATE "${CMAKE_SOURCE_DIR}") +diff --git a/packages/flutter_tools/templates/app/linux.tmpl/runner/my_application.cc.tmpl b/packages/flutter_tools/templates/app/linux.tmpl/runner/my_application.cc.tmpl +index 6ff97760cce..8a5eddb8624 100644 +--- a/packages/flutter_tools/templates/app/linux.tmpl/runner/my_application.cc.tmpl ++++ b/packages/flutter_tools/templates/app/linux.tmpl/runner/my_application.cc.tmpl +@@ -1,19 +1,16 @@ + #include "my_application.h" + + #include +-#ifdef GDK_WINDOWING_X11 +-#include +-#endif + + #include "flutter/generated_plugin_registrant.h" + + struct _MyApplication { +- GtkApplication parent_instance; ++ GApplication parent_instance; + char** dart_entrypoint_arguments; + FlEngine *engine; + }; + +-G_DEFINE_TYPE(MyApplication, my_application, GTK_TYPE_APPLICATION) ++G_DEFINE_TYPE(MyApplication, my_application, G_TYPE_APPLICATION) + + // Implements GApplication::activate. + static void my_application_activate(GApplication *application) { +@@ -95,7 +92,7 @@ static void my_application_init(MyApplication* self) {} + + MyApplication* my_application_new() { + // Set the program name to the application ID, which helps various systems +- // like GTK and desktop environments map this running application to its ++ // like desktop environments map this running application to its + // corresponding .desktop file. This ensures better integration by allowing + // the application to be recognized beyond its binary name. + g_set_prgname(APPLICATION_ID); +diff --git a/packages/flutter_tools/templates/app/linux.tmpl/runner/my_application.h b/packages/flutter_tools/templates/app/linux.tmpl/runner/my_application.h +index db16367a77d..43759e8c46f 100644 +--- a/packages/flutter_tools/templates/app/linux.tmpl/runner/my_application.h ++++ b/packages/flutter_tools/templates/app/linux.tmpl/runner/my_application.h +@@ -1,13 +1,13 @@ + #ifndef FLUTTER_MY_APPLICATION_H_ + #define FLUTTER_MY_APPLICATION_H_ + +-#include ++#include + + G_DECLARE_FINAL_TYPE(MyApplication, + my_application, + MY, + APPLICATION, +- GtkApplication) ++ GApplication) + + /** + * my_application_new: +diff --git a/packages/flutter_tools/templates/plugin/linux.tmpl/CMakeLists.txt.tmpl b/packages/flutter_tools/templates/plugin/linux.tmpl/CMakeLists.txt.tmpl +index 2d8110fe75c..eb1a2ddf55f 100644 +--- a/packages/flutter_tools/templates/plugin/linux.tmpl/CMakeLists.txt.tmpl ++++ b/packages/flutter_tools/templates/plugin/linux.tmpl/CMakeLists.txt.tmpl +@@ -39,7 +39,7 @@ target_compile_definitions(${PLUGIN_NAME} PRIVATE FLUTTER_PLUGIN_IMPL) + target_include_directories(${PLUGIN_NAME} INTERFACE + "${CMAKE_CURRENT_SOURCE_DIR}/include") + target_link_libraries(${PLUGIN_NAME} PRIVATE flutter) +-target_link_libraries(${PLUGIN_NAME} PRIVATE PkgConfig::GTK) ++target_link_libraries(${PLUGIN_NAME} PRIVATE PkgConfig::GLIB PkgConfig::GIO) + + # List of absolute paths to libraries that should be bundled with the plugin. + # This list could contain prebuilt libraries, or libraries created by an +@@ -83,7 +83,7 @@ add_executable(${TEST_RUNNER} + apply_standard_settings(${TEST_RUNNER}) + target_include_directories(${TEST_RUNNER} PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}") + target_link_libraries(${TEST_RUNNER} PRIVATE flutter) +-target_link_libraries(${TEST_RUNNER} PRIVATE PkgConfig::GTK) ++target_link_libraries(${TEST_RUNNER} PRIVATE PkgConfig::GLIB PkgConfig::GIO) + target_link_libraries(${TEST_RUNNER} PRIVATE gtest_main gmock) + + # Enable automatic test discovery. +diff --git a/packages/flutter_tools/test/general.shard/linux/linux_doctor_test.dart b/packages/flutter_tools/test/general.shard/linux/linux_doctor_test.dart +index e0790da9475..370bc3248cb 100644 +--- a/packages/flutter_tools/test/general.shard/linux/linux_doctor_test.dart ++++ b/packages/flutter_tools/test/general.shard/linux/linux_doctor_test.dart +@@ -60,13 +60,9 @@ FakeCommand _libraryCheckCommand(String library, {bool exists = true}) { + ); + } + +-// Commands that give positive replies for all the GTK library pkg-config queries. ++// Commands that give positive replies for all the GLib library pkg-config queries. + List _gtkLibrariesPresentCommands() { +- return [ +- _libraryCheckCommand('gtk+-3.0'), +- _libraryCheckCommand('glib-2.0'), +- _libraryCheckCommand('gio-2.0'), +- ]; ++ return [_libraryCheckCommand('glib-2.0'), _libraryCheckCommand('gio-2.0')]; + } + + // A command that will return typical-looking 'eglinfo' output +@@ -169,12 +165,11 @@ FakeCommand _eglinfoMissingCommand() { + ); + } + +-// Commands that give some failures for the GTK library pkg-config queries. ++// Commands that give some failures for the GLib library pkg-config queries. + List _gtkLibrariesMissingCommands() { + return [ +- _libraryCheckCommand('gtk+-3.0'), + _libraryCheckCommand('glib-2.0', exists: false), +- // No more entries, since the first missing GTK library stops the ++ // No more entries, since the first missing library stops the + // checks. + ]; + } +-- +2.51.2 + diff --git a/packages/flutter_tools_patches/0005-flutter_tools-List-Application-template-in-the-manifest.patch b/packages/flutter_tools_patches/0005-flutter_tools-List-Application-template-in-the-manifest.patch new file mode 100644 index 00000000..ac36e37f --- /dev/null +++ b/packages/flutter_tools_patches/0005-flutter_tools-List-Application-template-in-the-manifest.patch @@ -0,0 +1,22 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Matej Knopp +Date: Mon, 28 Sep 2026 23:15:00 +0200 +Subject: [PATCH] flutter_tools: List Application template in the manifest. + +The Application.kt template was not listed in template_manifest.json, +so `flutter create` never rendered it while AndroidManifest.xml +referenced it, producing a project that crashes on launch. + +--- +diff --git a/packages/flutter_tools/templates/template_manifest.json b/packages/flutter_tools/templates/template_manifest.json +index 0765605bb2d..e6e08d90881 100644 +--- a/packages/flutter_tools/templates/template_manifest.json ++++ b/packages/flutter_tools/templates/template_manifest.json +@@ -27,6 +27,7 @@ + "templates/app/android-java.tmpl/build.gradle.kts.tmpl", + "templates/app/android-java.tmpl/projectName_android.iml.tmpl", + "templates/app/android-kotlin.tmpl/app/build.gradle.kts.tmpl", ++ "templates/app/android-kotlin.tmpl/app/src/main/kotlin/androidIdentifier/Application.kt.tmpl", + "templates/app/android-kotlin.tmpl/app/src/main/kotlin/androidIdentifier/MainActivity.kt.tmpl", + "templates/app/android-kotlin.tmpl/build.gradle.kts.tmpl", + "templates/app/android-kotlin.tmpl/projectName_android.iml.tmpl", diff --git a/packages/flutter_tools_patches/0006-flutter_tools-Never-bundle-the-Roboto-fallback-on-web.patch b/packages/flutter_tools_patches/0006-flutter_tools-Never-bundle-the-Roboto-fallback-on-web.patch new file mode 100644 index 00000000..3ac8b60b --- /dev/null +++ b/packages/flutter_tools_patches/0006-flutter_tools-Never-bundle-the-Roboto-fallback-on-web.patch @@ -0,0 +1,92 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Matej Knopp +Date: Mon, 28 Sep 2026 23:25:00 +0200 +Subject: [PATCH] flutter_tools: Never bundle the Roboto fallback on web. + +flutter_zero has no txt/third_party/fonts tree (headless engine), and +web builds must not bundle the Roboto fallback font at all. The +upstream `_bundleLocalRobotoFallback` hook (which copied the engine +tree font into the bundle and crashed when it was missing) is removed +entirely. + +--- +diff --git a/packages/flutter_tools/lib/src/build_system/targets/web.dart b/packages/flutter_tools/lib/src/build_system/targets/web.dart +index 9f5a78f4de3..12ee35e110b 100644 +--- a/packages/flutter_tools/lib/src/build_system/targets/web.dart ++++ b/packages/flutter_tools/lib/src/build_system/targets/web.dart +@@ -684,9 +684,8 @@ class WebReleaseBundle extends Target { + targetPlatform: TargetPlatform.web_javascript, + buildMode: buildMode, + ); +- final Depfile bundledDepfile = _bundleLocalRobotoFallback(environment, depfile); + final DepfileService depfileService = environment.depFileService; +- depfileService.writeToFile(bundledDepfile, environment.buildDir.childFile('flutter_assets.d')); ++ depfileService.writeToFile(depfile, environment.buildDir.childFile('flutter_assets.d')); + + final Directory webResources = environment.projectDir.childDirectory('web'); + final List inputResourceFiles = webResources +@@ -731,61 +730,9 @@ class WebReleaseBundle extends Target { + environment.outputDir.childFile('version.json').writeAsStringSync(jsonEncode(versionInfo)); + } + +- Depfile _bundleLocalRobotoFallback(Environment environment, Depfile depfile) { +- if (environment.defines[kUseLocalCanvasKitFlag] != 'true') { +- return depfile; +- } +- +- final File fontManifestFile = environment.outputDir +- .childDirectory('assets') +- .childFile(_kFontManifestJsonFile); +- final manifestJson = fontManifestFile.existsSync() +- ? (jsonDecode(fontManifestFile.readAsStringSync()) as List) +- : []; +- +- final bool hasRobotoFamily = manifestJson.any((Object? entry) { +- return entry is Map && entry['family'] == _kBundledFallbackRobotoFamily; +- }); +- if (hasRobotoFamily) { +- return depfile; +- } +- +- final File sourceRobotoFont = environment.fileSystem.file( +- environment.fileSystem.path.join( +- Cache.flutterRoot!, +- 'engine', +- 'src', +- 'flutter', +- 'txt', +- 'third_party', +- 'fonts', +- 'Roboto-Regular.ttf', +- ), +- ); +- if (!sourceRobotoFont.existsSync()) { +- throwToolExit('Failed to find the bundled Roboto font at ${sourceRobotoFont.path}.'); +- } +- +- manifestJson.add({ +- 'family': _kBundledFallbackRobotoFamily, +- 'fonts': >[ +- {'asset': _kBundledFallbackRobotoAsset}, +- ], +- }); +- fontManifestFile.parent.createSync(recursive: true); +- fontManifestFile.writeAsStringSync(jsonEncode(manifestJson)); +- +- final File bundledRobotoFont = environment.outputDir +- .childDirectory('assets') +- .childFile(_kBundledFallbackRobotoAsset); +- bundledRobotoFont.parent.createSync(recursive: true); +- sourceRobotoFont.copySync(bundledRobotoFont.path); +- +- return Depfile( +- [...depfile.inputs, sourceRobotoFont], +- [...depfile.outputs, fontManifestFile, bundledRobotoFont], +- ); +- } ++ // flutter_zero never bundles the Roboto fallback font (headless engine, no ++ // txt/third_party/fonts tree), so the upstream `_bundleLocalRobotoFallback` ++ // hook is removed entirely. + } + + class WebTemplatedFiles extends Target { diff --git a/scripts/update_github_workflow.sh b/scripts/update_github_workflow.sh index 81e2ce9a..d4a404f6 100755 --- a/scripts/update_github_workflow.sh +++ b/scripts/update_github_workflow.sh @@ -19,4 +19,5 @@ ${REPO_PATH}/bin/dart flutter/tools/pkg/github_workflow_generator/bin/run.dart \ -i flutter/ci/builders/linux_android_aot_engine.json \ -i flutter/ci/builders/linux_android_debug_engine.json \ -i flutter/ci/builders/linux_web_engine_build.json \ + -t flutter/tools/pkg/github_workflow_generator/artifact_tests.json \ -o "${REPO_PATH}/.github/workflows/build-and-upload-engine-artifacts.yml"