From dec251ae28ab656bb4d472fd33c612fe977a99f9 Mon Sep 17 00:00:00 2001 From: spomichter Date: Tue, 17 Feb 2026 06:54:54 +0000 Subject: [PATCH 1/3] ci: add ci-complete gate for dynamic branch protection MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Adds a ci-complete job that aggregates all CI job results into a single status check. Branch protection only needs to require ci-complete instead of individual jobs. This fixes the issue where MD-only PRs are blocked by branch protection because individual CI jobs are skipped (not passing) when paths-ignore filters them out. With ci-complete using if: always(), it runs regardless and passes when jobs are skipped. Jobs with result 'skipped' are treated as passing — only 'failure' or 'cancelled' results cause ci-complete to fail. --- .github/workflows/docker.yml | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/.github/workflows/docker.yml b/.github/workflows/docker.yml index 5dc19917e5..4664f7f997 100644 --- a/.github/workflows/docker.yml +++ b/.github/workflows/docker.yml @@ -7,8 +7,6 @@ on: paths-ignore: - '**.md' pull_request: - paths-ignore: - - '**.md' permissions: contents: read @@ -269,3 +267,16 @@ jobs: # CI: "true" # run: | # /entrypoint.sh bash -c "pytest -m module" + + ci-complete: + needs: [run-tests, run-heavy-tests, run-lcm-tests, run-integration-tests, run-ros-tests, run-mypy] + runs-on: [self-hosted, Linux] + if: always() + steps: + - name: CI gate + run: | + if [[ "${{ contains(needs.*.result, 'failure') || contains(needs.*.result, 'cancelled') }}" == "true" ]]; then + echo "❌ One or more CI jobs failed or were cancelled" + exit 1 + fi + echo "✅ All CI checks passed or were intentionally skipped" From 76a7b64d4051ce173686894163d1667ff44c3c5d Mon Sep 17 00:00:00 2001 From: spomichter Date: Tue, 17 Feb 2026 10:40:19 +0000 Subject: [PATCH 2/3] fix: use if: condition instead of expression injection in ci-complete Greptile flagged ${{ }} inside run: as expression injection risk. Idiomatic fix: move logic to if: condition on the step, keeping shell script clean. --- .github/workflows/docker.yml | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/.github/workflows/docker.yml b/.github/workflows/docker.yml index 4664f7f997..a769519b8c 100644 --- a/.github/workflows/docker.yml +++ b/.github/workflows/docker.yml @@ -274,9 +274,9 @@ jobs: if: always() steps: - name: CI gate + if: ${{ contains(needs.*.result, 'failure') || contains(needs.*.result, 'cancelled') }} run: | - if [[ "${{ contains(needs.*.result, 'failure') || contains(needs.*.result, 'cancelled') }}" == "true" ]]; then - echo "❌ One or more CI jobs failed or were cancelled" - exit 1 - fi - echo "✅ All CI checks passed or were intentionally skipped" + echo "❌ One or more CI jobs failed or were cancelled" + exit 1 + - name: CI passed + run: echo "✅ All CI checks passed or were intentionally skipped" From 690159bba329c3bab44f195d88f8d66d916adc83 Mon Sep 17 00:00:00 2001 From: spomichter Date: Tue, 17 Feb 2026 11:31:24 +0000 Subject: [PATCH 3/3] fix: gate tests.yml steps on should-run input tests.yml accepted should-run as an input but never checked it. When callers passed should-run=false (e.g. md-only PRs), the run-tests job executed anyway against the fallback :dev image. Gate each step with if: inputs.should-run (same pattern as _docker-build-template.yml). Job itself still runs so the status check reports 'success' instead of 'skipped', keeping the needs chain and ci-complete gate intact. --- .github/workflows/tests.yml | 21 ++++----------------- 1 file changed, 4 insertions(+), 17 deletions(-) diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index e84d7d43d2..1f78a4e4e9 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -20,22 +20,6 @@ permissions: packages: read jobs: - - # cleanup: - # runs-on: dimos-runner-ubuntu-2204 - # steps: - # - name: exit early - # if: ${{ !inputs.should-run }} - # run: | - # exit 0 - - # - name: Free disk space - # run: | - # sudo rm -rf /opt/ghc - # sudo rm -rf /usr/share/dotnet - # sudo rm -rf /usr/local/share/boost - # sudo rm -rf /usr/local/lib/android - run-tests: runs-on: [self-hosted, Linux] container: @@ -47,16 +31,19 @@ jobs: steps: - uses: actions/checkout@v4 + if: ${{ inputs.should-run }} - name: Fix permissions + if: ${{ inputs.should-run }} run: | git config --global --add safe.directory '*' - name: Run tests + if: ${{ inputs.should-run }} run: | /entrypoint.sh bash -c "${{ inputs.cmd }}" - name: check disk space - if: failure() + if: ${{ failure() && inputs.should-run }} run: | df -h