Skip to content

Improve test and build workflow with conditional execution (#381) #1277

Improve test and build workflow with conditional execution (#381)

Improve test and build workflow with conditional execution (#381) #1277

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