From 8da20027c47c26f4c243df8af932f6311c18021f Mon Sep 17 00:00:00 2001 From: max <40643627+quotentiroler@users.noreply.github.com> Date: Sat, 7 Feb 2026 14:43:47 -0800 Subject: [PATCH] CI: skip heavy jobs on docs-only changes (#11328) --- .github/actions/detect-docs-only/action.yml | 41 +++++++ .github/workflows/ci.yml | 112 ++++++++++++++++++-- .github/workflows/install-smoke.yml | 16 +++ 3 files changed, 162 insertions(+), 7 deletions(-) create mode 100644 .github/actions/detect-docs-only/action.yml diff --git a/.github/actions/detect-docs-only/action.yml b/.github/actions/detect-docs-only/action.yml new file mode 100644 index 000000000..5bdc5d7d8 --- /dev/null +++ b/.github/actions/detect-docs-only/action.yml @@ -0,0 +1,41 @@ +name: Detect docs-only changes +description: > + Outputs docs_only=true when all changed files are under docs/ or are + markdown (.md/.mdx). Fail-safe: if detection fails, outputs false (run + everything). Uses git diff — no API calls, no extra permissions needed. + +outputs: + docs_only: + description: "'true' if all changes are docs/markdown, 'false' otherwise" + value: ${{ steps.check.outputs.docs_only }} + +runs: + using: composite + steps: + - name: Detect docs-only changes + id: check + shell: bash + run: | + if [ "${{ github.event_name }}" = "push" ]; then + BASE="${{ github.event.before }}" + else + # Use the exact base SHA from the event payload — stable regardless + # of base branch movement (avoids origin/ drift). + BASE="${{ github.event.pull_request.base.sha }}" + fi + + # Fail-safe: if we can't diff, assume non-docs (run everything) + CHANGED=$(git diff --name-only "$BASE" HEAD 2>/dev/null || echo "UNKNOWN") + if [ "$CHANGED" = "UNKNOWN" ] || [ -z "$CHANGED" ]; then + echo "docs_only=false" >> "$GITHUB_OUTPUT" + exit 0 + fi + + # Check if all changed files are docs or markdown + NON_DOCS=$(echo "$CHANGED" | grep -vE '^docs/|\.md$|\.mdx$' || true) + if [ -z "$NON_DOCS" ]; then + echo "docs_only=true" >> "$GITHUB_OUTPUT" + echo "Docs-only change detected — skipping heavy jobs" + else + echo "docs_only=false" >> "$GITHUB_OUTPUT" + fi diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index caa148a9b..c12a9e09a 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -10,7 +10,26 @@ concurrency: cancel-in-progress: true jobs: + # Detect docs-only changes to skip heavy jobs (test, build, Windows, macOS, Android). + # Lint and format always run. Fail-safe: if detection fails, run everything. + docs-scope: + runs-on: ubuntu-latest + outputs: + docs_only: ${{ steps.check.outputs.docs_only }} + steps: + - name: Checkout + uses: actions/checkout@v4 + with: + fetch-depth: 0 + submodules: false + + - name: Detect docs-only changes + id: check + uses: ./.github/actions/detect-docs-only + install-check: + needs: [docs-scope] + if: needs.docs-scope.outputs.docs_only != 'true' runs-on: blacksmith-4vcpu-ubuntu-2404 steps: - name: Checkout @@ -71,6 +90,8 @@ jobs: pnpm install --frozen-lockfile --ignore-scripts=false --config.engine-strict=false --config.enable-pre-post-scripts=true checks: + needs: [docs-scope] + if: needs.docs-scope.outputs.docs_only != 'true' runs-on: blacksmith-4vcpu-ubuntu-2404 strategy: fail-fast: false @@ -79,18 +100,12 @@ jobs: - runtime: node task: tsgo command: pnpm tsgo - - runtime: node - task: lint - command: pnpm build && pnpm lint - runtime: node task: test command: pnpm canvas:a2ui:bundle && pnpm test - runtime: node task: protocol command: pnpm protocol:check - - runtime: node - task: format - command: pnpm format - runtime: bun task: test command: pnpm canvas:a2ui:bundle && bunx vitest run @@ -161,6 +176,84 @@ jobs: - name: Run ${{ matrix.task }} (${{ matrix.runtime }}) run: ${{ matrix.command }} + # Lint and format always run, even on docs-only changes. + checks-lint: + runs-on: blacksmith-4vcpu-ubuntu-2404 + strategy: + fail-fast: false + matrix: + include: + - task: lint + command: pnpm build && pnpm lint + - task: format + command: pnpm format + steps: + - name: Checkout + uses: actions/checkout@v4 + with: + submodules: false + + - name: Checkout submodules (retry) + run: | + set -euo pipefail + git submodule sync --recursive + for attempt in 1 2 3 4 5; do + if git -c protocol.version=2 submodule update --init --force --depth=1 --recursive; then + exit 0 + fi + echo "Submodule update failed (attempt $attempt/5). Retrying…" + sleep $((attempt * 10)) + done + exit 1 + + - name: Setup Node.js + uses: actions/setup-node@v4 + with: + node-version: 22.x + check-latest: true + + - name: Setup pnpm (corepack retry) + run: | + set -euo pipefail + corepack enable + for attempt in 1 2 3; do + if corepack prepare pnpm@10.23.0 --activate; then + pnpm -v + exit 0 + fi + echo "corepack prepare failed (attempt $attempt/3). Retrying..." + sleep $((attempt * 10)) + done + exit 1 + + - name: Setup Bun + uses: oven-sh/setup-bun@v2 + with: + bun-version: latest + + - name: Runtime versions + run: | + node -v + npm -v + bun -v + pnpm -v + + - name: Capture node path + run: echo "NODE_BIN=$(dirname \"$(node -p \"process.execPath\")\")" >> "$GITHUB_ENV" + + - name: Install dependencies + env: + CI: true + run: | + export PATH="$NODE_BIN:$PATH" + which node + node -v + pnpm -v + pnpm install --frozen-lockfile --ignore-scripts=false --config.engine-strict=false --config.enable-pre-post-scripts=true || pnpm install --frozen-lockfile --ignore-scripts=false --config.engine-strict=false --config.enable-pre-post-scripts=true + + - name: Run ${{ matrix.task }} + run: ${{ matrix.command }} + secrets: runs-on: blacksmith-4vcpu-ubuntu-2404 steps: @@ -187,6 +280,8 @@ jobs: fi checks-windows: + needs: [docs-scope] + if: needs.docs-scope.outputs.docs_only != 'true' runs-on: blacksmith-4vcpu-windows-2025 env: NODE_OPTIONS: --max-old-space-size=4096 @@ -300,7 +395,8 @@ jobs: # running 4 separate jobs per PR (as before) starved the queue. One job # per PR allows 5 PRs to run macOS checks simultaneously. macos: - if: github.event_name == 'pull_request' + needs: [docs-scope] + if: github.event_name == 'pull_request' && needs.docs-scope.outputs.docs_only != 'true' runs-on: macos-latest steps: - name: Checkout @@ -585,6 +681,8 @@ jobs: PY android: + needs: [docs-scope] + if: needs.docs-scope.outputs.docs_only != 'true' runs-on: blacksmith-4vcpu-ubuntu-2404 strategy: fail-fast: false diff --git a/.github/workflows/install-smoke.yml b/.github/workflows/install-smoke.yml index ec1209d42..1f42d8f40 100644 --- a/.github/workflows/install-smoke.yml +++ b/.github/workflows/install-smoke.yml @@ -11,7 +11,23 @@ concurrency: cancel-in-progress: true jobs: + docs-scope: + runs-on: ubuntu-latest + outputs: + docs_only: ${{ steps.check.outputs.docs_only }} + steps: + - name: Checkout + uses: actions/checkout@v4 + with: + fetch-depth: 0 + + - name: Detect docs-only changes + id: check + uses: ./.github/actions/detect-docs-only + install-smoke: + needs: [docs-scope] + if: needs.docs-scope.outputs.docs_only != 'true' runs-on: ubuntu-latest steps: - name: Checkout CLI