Skip to content

ci: skip build/test/scan jobs for docs-only changes#180

Open
MCGPPeters wants to merge 1 commit intomainfrom
chore/ci-docs-skip
Open

ci: skip build/test/scan jobs for docs-only changes#180
MCGPPeters wants to merge 1 commit intomainfrom
chore/ci-docs-skip

Conversation

@MCGPPeters
Copy link
Copy Markdown
Contributor

What

Add docs-only change detection to 7 CI workflows so that PRs touching only documentation files (.squad/, docs/, instructions/, *.md, LICENSE, etc.) skip all expensive code-quality checks.

Why

Squad update PRs and docs-only changes were triggering the full CI pipeline — up to 120+ minutes of build, test, and scan time — for changes that cannot possibly break code. This wasted CI resources and slowed docs-only merges.

How

Two patterns are used depending on whether the workflow is a required branch protection check:

detect-changes job (for required checks — cd, e2e, codeql, pr-validation): A small first job diffs changed file paths against a docs-only regex and outputs docs_only=true/false. Expensive jobs use needs: [detect-changes] + if: ...docs_only == 'false'. Skipped jobs post "skipped" status which satisfies required branch protection rules without blocking the PR.

paths-ignore (for non-required scans — semgrep, trivy, zap-baseline): Added to both pull_request and push triggers. The workflow simply doesn't start for docs-only changes.

secrets-scan.yml is intentionally unchanged — gitleaks should scan all commits regardless of file type.

Workflows changed

  • cd.yml — detect-changes job gates the build job (dotnet build + 8 test suites)
  • e2e.yml — detect-changes job gates the e2e job (120-min Playwright suite)
  • codeql.yml — detect-changes gates the analyze job on push/PR; weekly schedule always runs
  • pr-validation.yml — detect-changes gates lint-check, security-scan, template-smoke-test, bundle-size-check, check-todos; pr-validation-summary updated to always() && !failure() so it runs on skipped-job paths
  • semgrep.yml — paths-ignore on both triggers
  • trivy.yml — paths-ignore on both triggers
  • zap-baseline.yml — paths-ignore on both triggers

Testing

The detect-changes job logic uses standard git diff --name-only and a regex filter. The skip path is exercised naturally by any docs-only PR (like squad update PRs).

Add a detect-changes job to cd, e2e, codeql, and pr-validation workflows
that detects whether a push/PR contains only documentation changes
(.squad/, docs/, instructions/, *.md, LICENSE, etc.).

When only docs change:
- build job (cd.yml) is skipped - saves full dotnet build + 8 test suites
- e2e job (e2e.yml) is skipped - saves up to 120 minutes of Playwright tests
- analyze job (codeql.yml) is skipped for push/PR; schedule always runs
- lint-check, security-scan, template-smoke-test, bundle-size-check,
  check-todos (pr-validation.yml) are all skipped

Skipped jobs post skipped status which satisfies required branch protection
checks. pr-validation-summary uses always() && !failure() so it still
runs when jobs are skipped, maintaining the required gate check.

For non-required workflows (semgrep, trivy, zap-baseline), paths-ignore
is added to both pull_request and push triggers.

secrets-scan.yml is intentionally unchanged - gitleaks should scan
all commits regardless of file type.
Copilot AI review requested due to automatic review settings March 23, 2026 17:04
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR adds “docs-only change” detection to CI so documentation-only pull requests don’t trigger long-running build/test/security jobs, reducing wasted CI time while keeping required workflows green.

Changes:

  • Add paths-ignore filters to non-required security workflows (Semgrep, Trivy, ZAP baseline) so the workflows don’t start for docs-only changes.
  • Add a detect-changes job to required workflows (CD, E2E, CodeQL, PR validation) and gate expensive jobs based on a docs_only output.
  • Adjust PR validation summary gating so it can still run when upstream jobs are skipped (docs-only path).

Reviewed changes

Copilot reviewed 7 out of 7 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
.github/workflows/zap-baseline.yml Add paths-ignore so ZAP baseline doesn’t run on docs-only changes.
.github/workflows/trivy.yml Add paths-ignore so Trivy doesn’t run on docs-only changes.
.github/workflows/semgrep.yml Add paths-ignore so Semgrep doesn’t run on docs-only changes.
.github/workflows/pr-validation.yml Add docs-only detection job and gate multiple expensive validation jobs; update summary job condition.
.github/workflows/e2e.yml Add docs-only detection job and gate the 120-minute E2E job.
.github/workflows/codeql.yml Add docs-only detection job and gate CodeQL analysis except on scheduled runs.
.github/workflows/cd.yml Add docs-only detection job and gate build/test/pack/publish work.

Comment on lines +14 to +38
# Detect whether this is a docs-only PR to skip expensive code-quality jobs
detect-changes:
name: Detect Changes
runs-on: ubuntu-latest
if: github.event.pull_request.draft == false
outputs:
docs_only: ${{ steps.check.outputs.docs_only }}
steps:
- uses: actions/checkout@v6
with:
fetch-depth: 0
- name: Check for non-docs changes
id: check
run: |
CHANGED=$(git diff --name-only origin/${{ github.base_ref }}...HEAD)
NON_DOCS=$(echo "$CHANGED" | grep -vE '^(docs/|\.squad/|\.github/instructions/|README|CHANGELOG|CONTRIBUTING|SECURITY|LICENSE|BENCHMARK_PR_STATUS|.*\.md$)' | grep -v '^$' || true)
if [ -z "$NON_DOCS" ]; then
echo "docs_only=true" >> $GITHUB_OUTPUT
echo "📚 Docs-only PR — lint, security scan, and template smoke test will be skipped"
echo "$CHANGED" | head -20
else
echo "docs_only=false" >> $GITHUB_OUTPUT
echo "🔨 Code changes detected — running full PR validation"
echo "$NON_DOCS" | head -20
fi
Copy link

Copilot AI Mar 23, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

jobs: children are inconsistently indented: detect-changes is indented deeper than the other job keys (e.g., validate-pr-title). YAML requires sibling keys to be at the same indentation level; as written this is likely to make the workflow invalid or nest detect-changes incorrectly. Align detect-changes to the same indentation as the other jobs (two spaces under jobs:).

Suggested change
# Detect whether this is a docs-only PR to skip expensive code-quality jobs
detect-changes:
name: Detect Changes
runs-on: ubuntu-latest
if: github.event.pull_request.draft == false
outputs:
docs_only: ${{ steps.check.outputs.docs_only }}
steps:
- uses: actions/checkout@v6
with:
fetch-depth: 0
- name: Check for non-docs changes
id: check
run: |
CHANGED=$(git diff --name-only origin/${{ github.base_ref }}...HEAD)
NON_DOCS=$(echo "$CHANGED" | grep -vE '^(docs/|\.squad/|\.github/instructions/|README|CHANGELOG|CONTRIBUTING|SECURITY|LICENSE|BENCHMARK_PR_STATUS|.*\.md$)' | grep -v '^$' || true)
if [ -z "$NON_DOCS" ]; then
echo "docs_only=true" >> $GITHUB_OUTPUT
echo "📚 Docs-only PR — lint, security scan, and template smoke test will be skipped"
echo "$CHANGED" | head -20
else
echo "docs_only=false" >> $GITHUB_OUTPUT
echo "🔨 Code changes detected — running full PR validation"
echo "$NON_DOCS" | head -20
fi
# Detect whether this is a docs-only PR to skip expensive code-quality jobs
detect-changes:
name: Detect Changes
runs-on: ubuntu-latest
if: github.event.pull_request.draft == false
outputs:
docs_only: ${{ steps.check.outputs.docs_only }}
steps:
- uses: actions/checkout@v6
with:
fetch-depth: 0
- name: Check for non-docs changes
id: check
run: |
CHANGED=$(git diff --name-only origin/${{ github.base_ref }}...HEAD)
NON_DOCS=$(echo "$CHANGED" | grep -vE '^(docs/|\.squad/|\.github/instructions/|README|CHANGELOG|CONTRIBUTING|SECURITY|LICENSE|BENCHMARK_PR_STATUS|.*\.md$)' | grep -v '^$' || true)
if [ -z "$NON_DOCS" ]; then
echo "docs_only=true" >> $GITHUB_OUTPUT
echo "📚 Docs-only PR — lint, security scan, and template smoke test will be skipped"
echo "$CHANGED" | head -20
else
echo "docs_only=false" >> $GITHUB_OUTPUT
echo "🔨 Code changes detected — running full PR validation"
echo "$NON_DOCS" | head -20
fi

Copilot uses AI. Check for mistakes.
Comment on lines +633 to 636
# always() + !failure() = run even when dependencies were skipped (docs-only),
# but not when any dependency explicitly failed.
if: always() && !cancelled() && !failure() && github.event.pull_request.draft == false
needs: [validate-pr-title, validate-pr-description, check-pr-size, lint-check, security-scan, template-smoke-test, bundle-size-check, check-todos]
Copy link

Copilot AI Mar 23, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

With the updated if: this summary job now runs even when lint-check/security-scan/template-smoke-test/etc are skipped (docs-only). The subsequent summary output still prints "✅" lines for checks that may not have executed, which can mislead reviewers and makes CI output harder to interpret. Consider including detect-changes in needs (or using needs.<job>.result) and printing an explicit "skipped (docs-only)" status for gated jobs.

Copilot uses AI. Check for mistakes.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants