Improve test and build workflow with conditional execution (#381) #1287
Workflow file for this run
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: Build | |
| on: | |
| push: | |
| branches: | |
| - "main" | |
| # this fires for the temporary branch the merge queue creates | |
| merge_group: | |
| pull_request: | |
| branches: | |
| - "main" | |
| # workflow_call trigger to make this workflow reusable | |
| workflow_call: | |
| inputs: | |
| force_full_build: | |
| type: boolean | |
| default: true | |
| jobs: | |
| # Determine when a full build should run | |
| gatekeeper: | |
| runs-on: ubuntu-latest | |
| outputs: | |
| run_all: ${{ steps.detect-changes.outputs.run_all }} | |
| steps: | |
| - name: Checkout repository | |
| uses: actions/checkout@v4 | |
| with: | |
| fetch-depth: 0 | |
| - name: Detect changes that should trigger a full build | |
| id: detect-changes | |
| shell: bash | |
| run: | | |
| if [[ "${{ inputs.force_full_build }}" == "true" ]]; then | |
| echo "🔥 Forcing full build on workflow_call." | |
| echo "run_all=true" >> "$GITHUB_OUTPUT" | |
| exit 0 | |
| fi | |
| if [[ "${{ github.ref_name }}" = "main" ]]; then | |
| echo "🔥 Forcing full build on push/merge to main." | |
| echo "run_all=true" >> "$GITHUB_OUTPUT" | |
| exit 0 | |
| fi | |
| # Determine the base commit SHA to compare changes against | |
| # Supporting pull request, merge, and push | |
| BASE_REF="${{ | |
| github.event.pull_request.base.sha || | |
| github.event.merge_group.base_sha || | |
| github.event.before | |
| }}" | |
| # Fallback for new branch, manual run, or new tag | |
| if [[ -z "$BASE_REF" ]] || [[ "$BASE_REF" =~ ^0+$ ]]; then | |
| echo "🔥 Forcing full build for new branch, manual run, or new tag" | |
| echo "run_all=true" >> "$GITHUB_OUTPUT" | |
| exit 0 | |
| fi | |
| # 🔍 Files and directories that require a full build when modified | |
| WATCH_PATHS=( | |
| "src/" | |
| "builder/" | |
| "exts/" | |
| "tests/rust-examples/" | |
| ".github/workflows/build-guidelines.yml" | |
| ".github/workflows/check-rust-examples.yml" | |
| "scripts/extract_rust_examples.py" | |
| "scripts/migrate_rust_examples.py" | |
| "pyproject.toml" | |
| "uv.lock" | |
| "make.py" | |
| "spec.loc" | |
| ) | |
| if git diff --quiet "$BASE_REF" HEAD -- "${WATCH_PATHS[@]}"; then | |
| echo "⚠️ Skipping full build: no relevant changes detected." | |
| echo "run_all=false" >> "$GITHUB_OUTPUT" | |
| else | |
| echo "🔥 Forcing full build: relevant changes detected." | |
| echo "run_all=true" >> "$GITHUB_OUTPUT" | |
| fi | |
| # Check Rust examples compile before building docs | |
| check-rust-examples: | |
| needs: gatekeeper | |
| if: needs.gatekeeper.outputs.run_all == 'true' | |
| uses: ./.github/workflows/check-rust-examples.yml | |
| build: | |
| needs: [gatekeeper, check-rust-examples] | |
| # Always run so that 'build' (the required status check) explicitly fails | |
| # when check-rust-examples fails, rather than being skipped. | |
| # Skipped jobs don't block merge queue, but failed jobs do. | |
| if: | | |
| always() && | |
| needs.gatekeeper.outputs.run_all == 'true' | |
| runs-on: ubuntu-latest | |
| steps: | |
| - name: Fail if example checks failed | |
| if: needs.check-rust-examples.result != 'success' | |
| run: | | |
| echo "::error::check-rust-examples workflow failed with result: ${{ needs.check-rust-examples.result }}" | |
| echo "One or more Rust example checks did not pass. See the check-rust-examples job for details." | |
| exit 1 | |
| - name: Checkout repository | |
| uses: actions/checkout@v4 | |
| - name: Install uv | |
| uses: astral-sh/setup-uv@v6 | |
| - name: Build documentation | |
| run: | | |
| mkdir -p build | |
| ./make.py 2>&1 | tee build/build.log | |
| # Check for a wide range of error indicators in the log | |
| if grep -q -E "Traceback" build/build.log; then | |
| echo "::error::Build errors detected in log" | |
| # Extract error contexts and annotate them in the GitHub Actions UI | |
| echo "=== ERROR DETAILS ===" | |
| # Check for the Sphinx temp error file reference and extract it if present | |
| TEMP_ERROR_FILE=$(grep -o '/tmp/sphinx-err-[^ ]*\.log' build/build.log | head -1) | |
| if [ ! -z "$TEMP_ERROR_FILE" ] && [ -f "$TEMP_ERROR_FILE" ]; then | |
| # Save this traceback for artifacts | |
| echo "=== TRACEBACK ===" | |
| echo "Saving traceback to build/sphinx_traceback.log" | |
| cp "$TEMP_ERROR_FILE" build/sphinx_traceback.log | |
| fi | |
| # Check for FLS differences file reference and extract it if present | |
| FLS_DIFF_FILE=$(grep -o '/tmp/fls_diff_[^ ]*\.txt' build/build.log | head -1) | |
| if [ ! -z "$FLS_DIFF_FILE" ] && [ -f "$FLS_DIFF_FILE" ]; then | |
| # Save this differences file for artifacts | |
| echo "=== SPEC LOCK FILE DIFFERENCES ===" | |
| echo "Saving spec lock file differences to to build/spec_lock_file_differences.log" | |
| cp "$FLS_DIFF_FILE" build/spec_lock_file_differences.txt | |
| fi | |
| exit 1 | |
| else | |
| # Even if there's no error, still check for FLS differences file | |
| FLS_DIFF_FILE=$(grep -o '/tmp/fls_diff_[^ ]*\.txt' build/build.log | head -1) | |
| if [ ! -z "$FLS_DIFF_FILE" ] && [ -f "$FLS_DIFF_FILE" ]; then | |
| echo "=== SPEC LOCK FILE DIFFERENCES, NO BUILD ERROR ===" | |
| echo "Saving spec lock file differences to to build/spec_lock_file_differences.log" | |
| cp "$FLS_DIFF_FILE" build/spec_lock_file_differences.txt | |
| fi | |
| fi | |
| - name: Archive build artifacts | |
| uses: actions/upload-artifact@v4 | |
| if: always() | |
| with: | |
| name: build-artifacts | |
| path: build | |
| retention-days: 7 | |
| compression-level: 6 # Default compression level for a good balance of speed and size | |
| check-typos: | |
| runs-on: ubuntu-latest | |
| steps: | |
| - name: Checkout repository | |
| uses: actions/checkout@v4 | |
| - name: Check for typos | |
| uses: crate-ci/typos@v1.40.0 |