From 1437f3f134296c0d6131527145d6bcdd62126be6 Mon Sep 17 00:00:00 2001 From: Ammar Bandukwala Date: Tue, 23 Sep 2025 14:30:07 -0500 Subject: [PATCH 1/4] ci: skip tests/clippy/udeps for docs-only changes Implemented a DRY approach using a composite action that detects when only documentation files have changed. This speeds up CI for docs-only PRs while keeping all checks green. - Created reusable composite action '.github/actions/check-docs-only' - Refactored workflow to use the composite action across all jobs - Tests, clippy, and udeps checks now pass immediately for docs-only changes --- .github/actions/check-docs-only/action.yml | 34 +++++++++++ .github/workflows/tests.yml | 65 +++++++++++++++++++++- 2 files changed, 98 insertions(+), 1 deletion(-) create mode 100644 .github/actions/check-docs-only/action.yml diff --git a/.github/actions/check-docs-only/action.yml b/.github/actions/check-docs-only/action.yml new file mode 100644 index 00000000..a980674e --- /dev/null +++ b/.github/actions/check-docs-only/action.yml @@ -0,0 +1,34 @@ +name: 'Check Docs Only Changes' +description: 'Check if only documentation files were changed' +outputs: + docs-only: + description: "True if only documentation files were changed" + value: ${{ steps.check.outputs.docs_only }} +runs: + using: "composite" + steps: + - name: Check if only docs changed + id: check + shell: bash + run: | + # Determine the base SHA for comparison + if [ "${{ github.event_name }}" = "pull_request" ]; then + # For PRs, compare against the base branch + BASE_SHA="${{ github.event.pull_request.base.sha }}" + FILES_CHANGED=$(git diff --name-only "${BASE_SHA}"...HEAD) + else + # For pushes, compare with previous commit + FILES_CHANGED=$(git diff --name-only HEAD~1...HEAD 2>/dev/null || echo "") + fi + + # Check if all changed files are in docs/ directory + if [ -z "$FILES_CHANGED" ]; then + echo "docs_only=false" >> $GITHUB_OUTPUT + echo "No files changed" + elif echo "$FILES_CHANGED" | grep -vE '^docs/' > /dev/null; then + echo "docs_only=false" >> $GITHUB_OUTPUT + echo "Non-documentation files changed" + else + echo "docs_only=true" >> $GITHUB_OUTPUT + echo "All changes are in docs/ folder, checks will pass automatically" + fi \ No newline at end of file diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index c1daec97..5cd0b168 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -19,31 +19,54 @@ jobs: steps: - uses: actions/checkout@v4 + with: + fetch-depth: 0 + + - name: Check for docs-only changes + id: docs-check + uses: ./.github/actions/check-docs-only - name: Install Rust + if: steps.docs-check.outputs.docs-only != 'true' uses: dtolnay/rust-toolchain@stable with: toolchain: stable - name: Setup Rust cache + if: steps.docs-check.outputs.docs-only != 'true' uses: Swatinem/rust-cache@v2 with: shared-key: ${{ runner.os }} - name: Install nextest + if: steps.docs-check.outputs.docs-only != 'true' uses: taiki-e/install-action@nextest with: tool: nextest - name: Run all tests + if: steps.docs-check.outputs.docs-only != 'true' run: cargo nextest run --profile ci + - name: Skip tests for docs-only changes + if: steps.docs-check.outputs.docs-only == 'true' + run: echo "✅ Skipping tests - only documentation changed" + test-linux: name: Linux Tests runs-on: [self-hosted, linux] steps: + - uses: actions/checkout@v4 + with: + fetch-depth: 0 + + - name: Check for docs-only changes + id: docs-check + uses: ./.github/actions/check-docs-only + - name: Fix permissions from previous runs + if: steps.docs-check.outputs.docs-only != 'true' run: | # Clean up any files left from previous sudo runs before checkout # Use GITHUB_WORKSPACE parent directory or current working directory @@ -55,14 +78,15 @@ jobs: if [ -d /home/ci/.cargo ]; then sudo chown -R ci:ci /home/ci/.cargo || true fi - - uses: actions/checkout@v4 - name: Install Rust + if: steps.docs-check.outputs.docs-only != 'true' uses: dtolnay/rust-toolchain@stable with: toolchain: stable - name: Fix permissions on current directory + if: steps.docs-check.outputs.docs-only != 'true' run: | # Clean up any files left from previous sudo runs if [ -d target ]; then @@ -78,45 +102,57 @@ jobs: fi - name: Setup Rust cache + if: steps.docs-check.outputs.docs-only != 'true' uses: Swatinem/rust-cache@v2 with: shared-key: ${{ runner.os }} - name: Setup Rust environment + if: steps.docs-check.outputs.docs-only != 'true' run: | source ~/.cargo/env rustup default stable - name: Install nextest + if: steps.docs-check.outputs.docs-only != 'true' uses: taiki-e/install-action@nextest with: tool: nextest - name: Fix target directory permissions from previous runs + if: steps.docs-check.outputs.docs-only != 'true' run: | if [ -d target ]; then sudo chown -R ci:ci target || true fi - name: Run all tests (non-root) + if: steps.docs-check.outputs.docs-only != 'true' run: | source ~/.cargo/env cargo nextest run --profile ci --verbose -E 'not (binary(linux_integration) or binary(weak_integration))' - name: Install dependencies for weak mode (curl) + if: steps.docs-check.outputs.docs-only != 'true' run: sudo apt-get update && sudo apt-get install -y curl - name: Run weak mode integration tests (Linux) + if: steps.docs-check.outputs.docs-only != 'true' run: | source ~/.cargo/env cargo nextest run --profile ci --test weak_integration - name: Run Linux jail integration tests (sudo) + if: steps.docs-check.outputs.docs-only != 'true' run: | source ~/.cargo/env # Run Linux-specific jail tests with sudo to satisfy root requirements sudo -E $(which cargo) nextest run --profile ci --test linux_integration --verbose + - name: Skip tests for docs-only changes + if: steps.docs-check.outputs.docs-only == 'true' + run: echo "✅ Skipping tests - only documentation changed" + clippy: name: Clippy (${{ matrix.os }}) runs-on: ${{ matrix.os }} @@ -126,21 +162,34 @@ jobs: steps: - uses: actions/checkout@v4 + with: + fetch-depth: 0 + + - name: Check for docs-only changes + id: docs-check + uses: ./.github/actions/check-docs-only - name: Install Rust + if: steps.docs-check.outputs.docs-only != 'true' uses: dtolnay/rust-toolchain@stable with: toolchain: stable components: clippy - name: Setup Rust cache + if: steps.docs-check.outputs.docs-only != 'true' uses: Swatinem/rust-cache@v2 with: shared-key: ${{ runner.os }} - name: Run clippy + if: steps.docs-check.outputs.docs-only != 'true' run: cargo clippy --all-targets -- -D warnings + - name: Skip clippy for docs-only changes + if: steps.docs-check.outputs.docs-only == 'true' + run: echo "✅ Skipping clippy - only documentation changed" + fmt: name: Format runs-on: ubuntu-latest-8-cores @@ -168,21 +217,31 @@ jobs: steps: - uses: actions/checkout@v4 + with: + fetch-depth: 0 + + - name: Check for docs-only changes + id: docs-check + uses: ./.github/actions/check-docs-only - name: Install Rust (nightly for cargo-udeps) + if: steps.docs-check.outputs.docs-only != 'true' uses: dtolnay/rust-toolchain@stable with: toolchain: nightly - name: Setup Rust cache + if: steps.docs-check.outputs.docs-only != 'true' uses: Swatinem/rust-cache@v2 with: shared-key: ${{ runner.os }} - name: Install cargo-udeps + if: steps.docs-check.outputs.docs-only != 'true' uses: taiki-e/install-action@cargo-udeps - name: Check for unused dependencies + if: steps.docs-check.outputs.docs-only != 'true' run: | set -euo pipefail # Run with nightly; capture output without failing the step @@ -206,3 +265,7 @@ jobs: echo "Unused dependencies detected" exit 1 fi + + - name: Skip udeps for docs-only changes + if: steps.docs-check.outputs.docs-only == 'true' + run: echo "✅ Skipping unused dependency check - only documentation changed" \ No newline at end of file From a8149fd2e370e0afc1958dc19b0853419de599ff Mon Sep 17 00:00:00 2001 From: Ammar Bandukwala Date: Tue, 23 Sep 2025 14:39:58 -0500 Subject: [PATCH 2/4] refactor: use detection job pattern to eliminate if duplication Refactored the workflow to use a cleaner pattern with: - Single 'detect-docs-only' job that runs first - Job-level conditions (single if per job) instead of step-level - Placeholder jobs for skipped checks to ensure status remains green - No more repetitive if statements on every step This approach is more maintainable and follows GitHub Actions best practices for conditional job execution. --- .github/workflows/tests.yml | 120 +++++++++++++++++++----------------- 1 file changed, 65 insertions(+), 55 deletions(-) diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 5cd0b168..48fc34bc 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -13,10 +13,13 @@ env: RUST_BACKTRACE: 1 jobs: - test-macos: - name: macOS Integration Tests - runs-on: macos-15-xlarge - + # Detection job that runs first and determines if only docs changed + detect-docs-only: + name: Detect docs-only changes + runs-on: ubuntu-latest + outputs: + docs-only: ${{ steps.docs-check.outputs.docs-only }} + run-tests: ${{ steps.docs-check.outputs.docs-only != 'true' }} steps: - uses: actions/checkout@v4 with: @@ -26,47 +29,57 @@ jobs: id: docs-check uses: ./.github/actions/check-docs-only + - name: Display detection result + run: | + if [[ "${{ steps.docs-check.outputs.docs-only }}" == "true" ]]; then + echo "📚 Documentation-only changes detected - expensive checks will be skipped" + else + echo "🔧 Code changes detected - all checks will run" + fi + + test-macos: + name: macOS Integration Tests + runs-on: macos-15-xlarge + needs: detect-docs-only + if: needs.detect-docs-only.outputs.run-tests == 'true' + steps: + - uses: actions/checkout@v4 + - name: Install Rust - if: steps.docs-check.outputs.docs-only != 'true' uses: dtolnay/rust-toolchain@stable with: toolchain: stable - name: Setup Rust cache - if: steps.docs-check.outputs.docs-only != 'true' uses: Swatinem/rust-cache@v2 with: shared-key: ${{ runner.os }} - name: Install nextest - if: steps.docs-check.outputs.docs-only != 'true' uses: taiki-e/install-action@nextest with: tool: nextest - name: Run all tests - if: steps.docs-check.outputs.docs-only != 'true' run: cargo nextest run --profile ci + # Placeholder job that runs when tests are skipped + test-macos-skip: + name: macOS Integration Tests + runs-on: ubuntu-latest + needs: detect-docs-only + if: needs.detect-docs-only.outputs.docs-only == 'true' + steps: - name: Skip tests for docs-only changes - if: steps.docs-check.outputs.docs-only == 'true' - run: echo "✅ Skipping tests - only documentation changed" + run: echo "✅ Skipping macOS tests - only documentation changed" test-linux: name: Linux Tests runs-on: [self-hosted, linux] - + needs: detect-docs-only + if: needs.detect-docs-only.outputs.run-tests == 'true' steps: - - uses: actions/checkout@v4 - with: - fetch-depth: 0 - - - name: Check for docs-only changes - id: docs-check - uses: ./.github/actions/check-docs-only - - name: Fix permissions from previous runs - if: steps.docs-check.outputs.docs-only != 'true' run: | # Clean up any files left from previous sudo runs before checkout # Use GITHUB_WORKSPACE parent directory or current working directory @@ -78,15 +91,15 @@ jobs: if [ -d /home/ci/.cargo ]; then sudo chown -R ci:ci /home/ci/.cargo || true fi + + - uses: actions/checkout@v4 - name: Install Rust - if: steps.docs-check.outputs.docs-only != 'true' uses: dtolnay/rust-toolchain@stable with: toolchain: stable - name: Fix permissions on current directory - if: steps.docs-check.outputs.docs-only != 'true' run: | # Clean up any files left from previous sudo runs if [ -d target ]; then @@ -102,93 +115,93 @@ jobs: fi - name: Setup Rust cache - if: steps.docs-check.outputs.docs-only != 'true' uses: Swatinem/rust-cache@v2 with: shared-key: ${{ runner.os }} - name: Setup Rust environment - if: steps.docs-check.outputs.docs-only != 'true' run: | source ~/.cargo/env rustup default stable - name: Install nextest - if: steps.docs-check.outputs.docs-only != 'true' uses: taiki-e/install-action@nextest with: tool: nextest - name: Fix target directory permissions from previous runs - if: steps.docs-check.outputs.docs-only != 'true' run: | if [ -d target ]; then sudo chown -R ci:ci target || true fi - name: Run all tests (non-root) - if: steps.docs-check.outputs.docs-only != 'true' run: | source ~/.cargo/env cargo nextest run --profile ci --verbose -E 'not (binary(linux_integration) or binary(weak_integration))' - name: Install dependencies for weak mode (curl) - if: steps.docs-check.outputs.docs-only != 'true' run: sudo apt-get update && sudo apt-get install -y curl - name: Run weak mode integration tests (Linux) - if: steps.docs-check.outputs.docs-only != 'true' run: | source ~/.cargo/env cargo nextest run --profile ci --test weak_integration - name: Run Linux jail integration tests (sudo) - if: steps.docs-check.outputs.docs-only != 'true' run: | source ~/.cargo/env # Run Linux-specific jail tests with sudo to satisfy root requirements sudo -E $(which cargo) nextest run --profile ci --test linux_integration --verbose + # Placeholder job that runs when tests are skipped + test-linux-skip: + name: Linux Tests + runs-on: ubuntu-latest + needs: detect-docs-only + if: needs.detect-docs-only.outputs.docs-only == 'true' + steps: - name: Skip tests for docs-only changes - if: steps.docs-check.outputs.docs-only == 'true' - run: echo "✅ Skipping tests - only documentation changed" + run: echo "✅ Skipping Linux tests - only documentation changed" clippy: name: Clippy (${{ matrix.os }}) runs-on: ${{ matrix.os }} + needs: detect-docs-only + if: needs.detect-docs-only.outputs.run-tests == 'true' strategy: matrix: os: [ubuntu-latest-8-cores, macos-latest] steps: - uses: actions/checkout@v4 - with: - fetch-depth: 0 - - - name: Check for docs-only changes - id: docs-check - uses: ./.github/actions/check-docs-only - name: Install Rust - if: steps.docs-check.outputs.docs-only != 'true' uses: dtolnay/rust-toolchain@stable with: toolchain: stable components: clippy - name: Setup Rust cache - if: steps.docs-check.outputs.docs-only != 'true' uses: Swatinem/rust-cache@v2 with: shared-key: ${{ runner.os }} - name: Run clippy - if: steps.docs-check.outputs.docs-only != 'true' run: cargo clippy --all-targets -- -D warnings + # Placeholder job that runs when clippy is skipped + clippy-skip: + name: Clippy (${{ matrix.os }}) + runs-on: ubuntu-latest + needs: detect-docs-only + if: needs.detect-docs-only.outputs.docs-only == 'true' + strategy: + matrix: + os: [ubuntu-latest-8-cores, macos-latest] + steps: - name: Skip clippy for docs-only changes - if: steps.docs-check.outputs.docs-only == 'true' - run: echo "✅ Skipping clippy - only documentation changed" + run: echo "✅ Skipping clippy on ${{ matrix.os }} - only documentation changed" fmt: name: Format @@ -214,34 +227,25 @@ jobs: udeps: name: Unused dependency check runs-on: ubuntu-latest-8-cores - + needs: detect-docs-only + if: needs.detect-docs-only.outputs.run-tests == 'true' steps: - uses: actions/checkout@v4 - with: - fetch-depth: 0 - - - name: Check for docs-only changes - id: docs-check - uses: ./.github/actions/check-docs-only - name: Install Rust (nightly for cargo-udeps) - if: steps.docs-check.outputs.docs-only != 'true' uses: dtolnay/rust-toolchain@stable with: toolchain: nightly - name: Setup Rust cache - if: steps.docs-check.outputs.docs-only != 'true' uses: Swatinem/rust-cache@v2 with: shared-key: ${{ runner.os }} - name: Install cargo-udeps - if: steps.docs-check.outputs.docs-only != 'true' uses: taiki-e/install-action@cargo-udeps - name: Check for unused dependencies - if: steps.docs-check.outputs.docs-only != 'true' run: | set -euo pipefail # Run with nightly; capture output without failing the step @@ -266,6 +270,12 @@ jobs: exit 1 fi + # Placeholder job that runs when udeps is skipped + udeps-skip: + name: Unused dependency check + runs-on: ubuntu-latest + needs: detect-docs-only + if: needs.detect-docs-only.outputs.docs-only == 'true' + steps: - name: Skip udeps for docs-only changes - if: steps.docs-check.outputs.docs-only == 'true' run: echo "✅ Skipping unused dependency check - only documentation changed" \ No newline at end of file From 5a8fe95e9253918bb50db409f0f7d065502bc879 Mon Sep 17 00:00:00 2001 From: Ammar Bandukwala Date: Tue, 23 Sep 2025 14:43:44 -0500 Subject: [PATCH 3/4] fix: ensure required status checks stay green with conditional steps Jobs must run (not be skipped) to satisfy GitHub's required status checks. This approach: - Keeps all job names the same (satisfies required checks) - Uses conditional steps instead of skipping entire jobs - Jobs run but complete quickly when docs-only changes detected - All required status checks will show as passed, not pending --- .github/workflows/tests.yml | 71 +++++++++++++++++-------------------- 1 file changed, 32 insertions(+), 39 deletions(-) diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 48fc34bc..3de5118d 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -19,7 +19,6 @@ jobs: runs-on: ubuntu-latest outputs: docs-only: ${{ steps.docs-check.outputs.docs-only }} - run-tests: ${{ steps.docs-check.outputs.docs-only != 'true' }} steps: - uses: actions/checkout@v4 with: @@ -41,45 +40,46 @@ jobs: name: macOS Integration Tests runs-on: macos-15-xlarge needs: detect-docs-only - if: needs.detect-docs-only.outputs.run-tests == 'true' steps: - uses: actions/checkout@v4 + if: needs.detect-docs-only.outputs.docs-only != 'true' - name: Install Rust + if: needs.detect-docs-only.outputs.docs-only != 'true' uses: dtolnay/rust-toolchain@stable with: toolchain: stable - name: Setup Rust cache + if: needs.detect-docs-only.outputs.docs-only != 'true' uses: Swatinem/rust-cache@v2 with: shared-key: ${{ runner.os }} - name: Install nextest + if: needs.detect-docs-only.outputs.docs-only != 'true' uses: taiki-e/install-action@nextest with: tool: nextest - name: Run all tests + if: needs.detect-docs-only.outputs.docs-only != 'true' run: cargo nextest run --profile ci - # Placeholder job that runs when tests are skipped - test-macos-skip: - name: macOS Integration Tests - runs-on: ubuntu-latest - needs: detect-docs-only - if: needs.detect-docs-only.outputs.docs-only == 'true' - steps: - name: Skip tests for docs-only changes + if: needs.detect-docs-only.outputs.docs-only == 'true' run: echo "✅ Skipping macOS tests - only documentation changed" test-linux: name: Linux Tests runs-on: [self-hosted, linux] needs: detect-docs-only - if: needs.detect-docs-only.outputs.run-tests == 'true' steps: + - uses: actions/checkout@v4 + if: needs.detect-docs-only.outputs.docs-only != 'true' + - name: Fix permissions from previous runs + if: needs.detect-docs-only.outputs.docs-only != 'true' run: | # Clean up any files left from previous sudo runs before checkout # Use GITHUB_WORKSPACE parent directory or current working directory @@ -91,15 +91,15 @@ jobs: if [ -d /home/ci/.cargo ]; then sudo chown -R ci:ci /home/ci/.cargo || true fi - - - uses: actions/checkout@v4 - name: Install Rust + if: needs.detect-docs-only.outputs.docs-only != 'true' uses: dtolnay/rust-toolchain@stable with: toolchain: stable - name: Fix permissions on current directory + if: needs.detect-docs-only.outputs.docs-only != 'true' run: | # Clean up any files left from previous sudo runs if [ -d target ]; then @@ -115,92 +115,87 @@ jobs: fi - name: Setup Rust cache + if: needs.detect-docs-only.outputs.docs-only != 'true' uses: Swatinem/rust-cache@v2 with: shared-key: ${{ runner.os }} - name: Setup Rust environment + if: needs.detect-docs-only.outputs.docs-only != 'true' run: | source ~/.cargo/env rustup default stable - name: Install nextest + if: needs.detect-docs-only.outputs.docs-only != 'true' uses: taiki-e/install-action@nextest with: tool: nextest - name: Fix target directory permissions from previous runs + if: needs.detect-docs-only.outputs.docs-only != 'true' run: | if [ -d target ]; then sudo chown -R ci:ci target || true fi - name: Run all tests (non-root) + if: needs.detect-docs-only.outputs.docs-only != 'true' run: | source ~/.cargo/env cargo nextest run --profile ci --verbose -E 'not (binary(linux_integration) or binary(weak_integration))' - name: Install dependencies for weak mode (curl) + if: needs.detect-docs-only.outputs.docs-only != 'true' run: sudo apt-get update && sudo apt-get install -y curl - name: Run weak mode integration tests (Linux) + if: needs.detect-docs-only.outputs.docs-only != 'true' run: | source ~/.cargo/env cargo nextest run --profile ci --test weak_integration - name: Run Linux jail integration tests (sudo) + if: needs.detect-docs-only.outputs.docs-only != 'true' run: | source ~/.cargo/env # Run Linux-specific jail tests with sudo to satisfy root requirements sudo -E $(which cargo) nextest run --profile ci --test linux_integration --verbose - # Placeholder job that runs when tests are skipped - test-linux-skip: - name: Linux Tests - runs-on: ubuntu-latest - needs: detect-docs-only - if: needs.detect-docs-only.outputs.docs-only == 'true' - steps: - name: Skip tests for docs-only changes + if: needs.detect-docs-only.outputs.docs-only == 'true' run: echo "✅ Skipping Linux tests - only documentation changed" clippy: name: Clippy (${{ matrix.os }}) runs-on: ${{ matrix.os }} needs: detect-docs-only - if: needs.detect-docs-only.outputs.run-tests == 'true' strategy: matrix: os: [ubuntu-latest-8-cores, macos-latest] - steps: - uses: actions/checkout@v4 + if: needs.detect-docs-only.outputs.docs-only != 'true' - name: Install Rust + if: needs.detect-docs-only.outputs.docs-only != 'true' uses: dtolnay/rust-toolchain@stable with: toolchain: stable components: clippy - name: Setup Rust cache + if: needs.detect-docs-only.outputs.docs-only != 'true' uses: Swatinem/rust-cache@v2 with: shared-key: ${{ runner.os }} - name: Run clippy + if: needs.detect-docs-only.outputs.docs-only != 'true' run: cargo clippy --all-targets -- -D warnings - # Placeholder job that runs when clippy is skipped - clippy-skip: - name: Clippy (${{ matrix.os }}) - runs-on: ubuntu-latest - needs: detect-docs-only - if: needs.detect-docs-only.outputs.docs-only == 'true' - strategy: - matrix: - os: [ubuntu-latest-8-cores, macos-latest] - steps: - name: Skip clippy for docs-only changes + if: needs.detect-docs-only.outputs.docs-only == 'true' run: echo "✅ Skipping clippy on ${{ matrix.os }} - only documentation changed" fmt: @@ -228,24 +223,28 @@ jobs: name: Unused dependency check runs-on: ubuntu-latest-8-cores needs: detect-docs-only - if: needs.detect-docs-only.outputs.run-tests == 'true' steps: - uses: actions/checkout@v4 + if: needs.detect-docs-only.outputs.docs-only != 'true' - name: Install Rust (nightly for cargo-udeps) + if: needs.detect-docs-only.outputs.docs-only != 'true' uses: dtolnay/rust-toolchain@stable with: toolchain: nightly - name: Setup Rust cache + if: needs.detect-docs-only.outputs.docs-only != 'true' uses: Swatinem/rust-cache@v2 with: shared-key: ${{ runner.os }} - name: Install cargo-udeps + if: needs.detect-docs-only.outputs.docs-only != 'true' uses: taiki-e/install-action@cargo-udeps - name: Check for unused dependencies + if: needs.detect-docs-only.outputs.docs-only != 'true' run: | set -euo pipefail # Run with nightly; capture output without failing the step @@ -270,12 +269,6 @@ jobs: exit 1 fi - # Placeholder job that runs when udeps is skipped - udeps-skip: - name: Unused dependency check - runs-on: ubuntu-latest - needs: detect-docs-only - if: needs.detect-docs-only.outputs.docs-only == 'true' - steps: - name: Skip udeps for docs-only changes + if: needs.detect-docs-only.outputs.docs-only == 'true' run: echo "✅ Skipping unused dependency check - only documentation changed" \ No newline at end of file From 7a55a40b42d3fb6e14fbbfe3ca22e0fad0bbb71c Mon Sep 17 00:00:00 2001 From: Ammar Bandukwala Date: Tue, 23 Sep 2025 14:51:41 -0500 Subject: [PATCH 4/4] refactor: use single required job pattern with DAG dependencies Implemented the 'all-checks-pass' pattern using re-actors/alls-green action. This approach: - Uses a single required status check 'All checks pass' - Allows jobs to be genuinely skipped for docs-only changes - Eliminates repetitive if conditions on every step - Provides cleaner workflow with job-level conditions only - Better GitHub UI experience showing skipped vs passed Branch protection should be updated to only require 'All checks pass' status instead of individual job statuses. --- .github/workflows/tests.yml | 68 +++++++++++++------------------------ 1 file changed, 24 insertions(+), 44 deletions(-) diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 3de5118d..7c30a630 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -40,46 +40,35 @@ jobs: name: macOS Integration Tests runs-on: macos-15-xlarge needs: detect-docs-only + if: needs.detect-docs-only.outputs.docs-only != 'true' steps: - uses: actions/checkout@v4 - if: needs.detect-docs-only.outputs.docs-only != 'true' - name: Install Rust - if: needs.detect-docs-only.outputs.docs-only != 'true' uses: dtolnay/rust-toolchain@stable with: toolchain: stable - name: Setup Rust cache - if: needs.detect-docs-only.outputs.docs-only != 'true' uses: Swatinem/rust-cache@v2 with: shared-key: ${{ runner.os }} - name: Install nextest - if: needs.detect-docs-only.outputs.docs-only != 'true' uses: taiki-e/install-action@nextest with: tool: nextest - name: Run all tests - if: needs.detect-docs-only.outputs.docs-only != 'true' run: cargo nextest run --profile ci - - name: Skip tests for docs-only changes - if: needs.detect-docs-only.outputs.docs-only == 'true' - run: echo "✅ Skipping macOS tests - only documentation changed" - test-linux: name: Linux Tests runs-on: [self-hosted, linux] needs: detect-docs-only + if: needs.detect-docs-only.outputs.docs-only != 'true' steps: - - uses: actions/checkout@v4 - if: needs.detect-docs-only.outputs.docs-only != 'true' - - name: Fix permissions from previous runs - if: needs.detect-docs-only.outputs.docs-only != 'true' run: | # Clean up any files left from previous sudo runs before checkout # Use GITHUB_WORKSPACE parent directory or current working directory @@ -91,15 +80,15 @@ jobs: if [ -d /home/ci/.cargo ]; then sudo chown -R ci:ci /home/ci/.cargo || true fi + + - uses: actions/checkout@v4 - name: Install Rust - if: needs.detect-docs-only.outputs.docs-only != 'true' uses: dtolnay/rust-toolchain@stable with: toolchain: stable - name: Fix permissions on current directory - if: needs.detect-docs-only.outputs.docs-only != 'true' run: | # Clean up any files left from previous sudo runs if [ -d target ]; then @@ -115,93 +104,74 @@ jobs: fi - name: Setup Rust cache - if: needs.detect-docs-only.outputs.docs-only != 'true' uses: Swatinem/rust-cache@v2 with: shared-key: ${{ runner.os }} - name: Setup Rust environment - if: needs.detect-docs-only.outputs.docs-only != 'true' run: | source ~/.cargo/env rustup default stable - name: Install nextest - if: needs.detect-docs-only.outputs.docs-only != 'true' uses: taiki-e/install-action@nextest with: tool: nextest - name: Fix target directory permissions from previous runs - if: needs.detect-docs-only.outputs.docs-only != 'true' run: | if [ -d target ]; then sudo chown -R ci:ci target || true fi - name: Run all tests (non-root) - if: needs.detect-docs-only.outputs.docs-only != 'true' run: | source ~/.cargo/env cargo nextest run --profile ci --verbose -E 'not (binary(linux_integration) or binary(weak_integration))' - name: Install dependencies for weak mode (curl) - if: needs.detect-docs-only.outputs.docs-only != 'true' run: sudo apt-get update && sudo apt-get install -y curl - name: Run weak mode integration tests (Linux) - if: needs.detect-docs-only.outputs.docs-only != 'true' run: | source ~/.cargo/env cargo nextest run --profile ci --test weak_integration - name: Run Linux jail integration tests (sudo) - if: needs.detect-docs-only.outputs.docs-only != 'true' run: | source ~/.cargo/env # Run Linux-specific jail tests with sudo to satisfy root requirements sudo -E $(which cargo) nextest run --profile ci --test linux_integration --verbose - - name: Skip tests for docs-only changes - if: needs.detect-docs-only.outputs.docs-only == 'true' - run: echo "✅ Skipping Linux tests - only documentation changed" - clippy: name: Clippy (${{ matrix.os }}) runs-on: ${{ matrix.os }} needs: detect-docs-only + if: needs.detect-docs-only.outputs.docs-only != 'true' strategy: matrix: os: [ubuntu-latest-8-cores, macos-latest] steps: - uses: actions/checkout@v4 - if: needs.detect-docs-only.outputs.docs-only != 'true' - name: Install Rust - if: needs.detect-docs-only.outputs.docs-only != 'true' uses: dtolnay/rust-toolchain@stable with: toolchain: stable components: clippy - name: Setup Rust cache - if: needs.detect-docs-only.outputs.docs-only != 'true' uses: Swatinem/rust-cache@v2 with: shared-key: ${{ runner.os }} - name: Run clippy - if: needs.detect-docs-only.outputs.docs-only != 'true' run: cargo clippy --all-targets -- -D warnings - - name: Skip clippy for docs-only changes - if: needs.detect-docs-only.outputs.docs-only == 'true' - run: echo "✅ Skipping clippy on ${{ matrix.os }} - only documentation changed" - fmt: name: Format runs-on: ubuntu-latest-8-cores - + # Format always runs - even for docs changes we want consistent formatting steps: - uses: actions/checkout@v4 @@ -223,28 +193,24 @@ jobs: name: Unused dependency check runs-on: ubuntu-latest-8-cores needs: detect-docs-only + if: needs.detect-docs-only.outputs.docs-only != 'true' steps: - uses: actions/checkout@v4 - if: needs.detect-docs-only.outputs.docs-only != 'true' - name: Install Rust (nightly for cargo-udeps) - if: needs.detect-docs-only.outputs.docs-only != 'true' uses: dtolnay/rust-toolchain@stable with: toolchain: nightly - name: Setup Rust cache - if: needs.detect-docs-only.outputs.docs-only != 'true' uses: Swatinem/rust-cache@v2 with: shared-key: ${{ runner.os }} - name: Install cargo-udeps - if: needs.detect-docs-only.outputs.docs-only != 'true' uses: taiki-e/install-action@cargo-udeps - name: Check for unused dependencies - if: needs.detect-docs-only.outputs.docs-only != 'true' run: | set -euo pipefail # Run with nightly; capture output without failing the step @@ -269,6 +235,20 @@ jobs: exit 1 fi - - name: Skip udeps for docs-only changes - if: needs.detect-docs-only.outputs.docs-only == 'true' - run: echo "✅ Skipping unused dependency check - only documentation changed" \ No newline at end of file + # Single required job that depends on all others + # This should be the ONLY required status check in branch protection + all-checks-pass: + name: All checks pass + if: always() + needs: + - test-macos + - test-linux + - clippy + - fmt + - udeps + runs-on: ubuntu-latest + steps: + - name: Decide whether the needed jobs succeeded or failed + uses: re-actors/alls-green@release/v1 + with: + jobs: ${{ toJSON(needs) }} \ No newline at end of file