From 8d3aafb12cbc8de201a37c58534bf32bdf67ffb3 Mon Sep 17 00:00:00 2001 From: Gary Hsu <19158740+bghgary@users.noreply.github.com> Date: Wed, 19 Aug 2026 16:04:35 -0700 Subject: [PATCH 1/2] Harden Linux apt step and add a ci-complete gate job Bound apt's retries and transfer timeouts so a degraded in-datacenter mirror fails fast instead of stalling silently for hours, and cap every job with timeout-minutes so a future stall is a fast diagnosable failure rather than a 6h timeout. Install clang-14 alone; clang++-14 is not a package name, so apt fell through to regex matching and pulled in 20 packages where 2 were meant. ci-complete aggregates the four jobs behind one stable check name that branch protection can require, leaving the matrix-generated names free to change. if: always() is required or the job is skipped when a dependency fails, and a skipped required check satisfies the requirement. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> --- .github/workflows/ci.yml | 42 ++++++++++++++++++++++++++++++++++++++-- 1 file changed, 40 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index bdad03e..3c7f6ae 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -10,6 +10,7 @@ jobs: windows: name: Windows runs-on: windows-latest + timeout-minutes: 20 strategy: matrix: config: [Debug, Release] @@ -34,6 +35,7 @@ jobs: macos: name: macOS runs-on: macos-latest + timeout-minutes: 20 strategy: matrix: config: [Debug, Release] @@ -58,6 +60,7 @@ jobs: ios: name: iOS runs-on: macos-latest + timeout-minutes: 20 strategy: matrix: config: [Debug, Release] @@ -78,6 +81,7 @@ jobs: linux: name: Linux runs-on: ubuntu-latest + timeout-minutes: 20 strategy: matrix: config: [Debug, Release] @@ -86,17 +90,24 @@ jobs: - compiler: gcc-11 cc: gcc-11 cxx: g++-11 + packages: gcc-11 g++-11 - compiler: clang-14 cc: clang-14 cxx: clang++-14 + # clang-14 ships the clang++-14 binary; there is no clang++-14 package + packages: clang-14 steps: - uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4.4.0 - name: Install dependencies run: | - sudo apt-get update - sudo apt-get install -y ${{ matrix.cc }} ${{ matrix.cxx }} + # Bound apt's own retries and transfer timeouts. When the in-datacenter + # mirror is degraded, apt otherwise falls back to archive.ubuntu.com and + # can stall there silently for hours: actions/runner-images#14594 + APT_OPTS="-o Acquire::Retries=1 -o Acquire::http::Timeout=10 -o Acquire::https::Timeout=10" + sudo apt-get update $APT_OPTS + sudo apt-get install -y $APT_OPTS ${{ matrix.packages }} - name: Configure CMake run: | @@ -115,3 +126,30 @@ jobs: # working-directory: Build # run: | # ctest -C ${{ matrix.config }} --output-on-failure --verbose + + ci-complete: + name: ci-complete + # Single aggregate check for branch protection to require, so the 14 + # matrix-generated check names stay free to change. + # + # `if: always()` is load-bearing: without it this job is skipped whenever a + # dependency fails, and a skipped required check satisfies the requirement -- + # inverting the gate. The step below then asserts every result is success, so + # failed, cancelled and skipped dependencies all fail the gate. + if: always() + needs: [windows, macos, ios, linux] + runs-on: ubuntu-latest + timeout-minutes: 5 + + steps: + - name: Verify all jobs succeeded + env: + RESULTS: ${{ join(needs.*.result, ' ') }} + run: | + echo "Job results: $RESULTS" + for result in $RESULTS; do + if [ "$result" != "success" ]; then + echo "::error::CI did not succeed (results: $RESULTS)" + exit 1 + fi + done From 486551697051872b24c17ffa82003fd1a5f64b8d Mon Sep 17 00:00:00 2001 From: Gary Hsu <19158740+bghgary@users.noreply.github.com> Date: Wed, 19 Aug 2026 16:24:45 -0700 Subject: [PATCH 2/2] Drop the per-repo apt workaround The runner image deliberately sets APT::Acquire::Retries 10; overriding it to 1 trades resilience against ordinary transient failures for a faster fail in one pathological case. actions/runner-images#14596 fixes the root cause image-side by demoting the azure mirror, which a workflow cannot do. timeout-minutes already bounds the hang, and it bounds every other hang too. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> --- .github/workflows/ci.yml | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 3c7f6ae..50a6064 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -102,12 +102,8 @@ jobs: - name: Install dependencies run: | - # Bound apt's own retries and transfer timeouts. When the in-datacenter - # mirror is degraded, apt otherwise falls back to archive.ubuntu.com and - # can stall there silently for hours: actions/runner-images#14594 - APT_OPTS="-o Acquire::Retries=1 -o Acquire::http::Timeout=10 -o Acquire::https::Timeout=10" - sudo apt-get update $APT_OPTS - sudo apt-get install -y $APT_OPTS ${{ matrix.packages }} + sudo apt-get update + sudo apt-get install -y ${{ matrix.packages }} - name: Configure CMake run: |