Skip to content

docs-only PRs run verify-precommit-config and smoke-test to completion: 84% of runner time on a markdown edit #15299

Closed

Description

@mrveiss

Problem

A docs-only pull request runs two heavy required jobs to completion. PR #15250 changed one markdown file (5 insertions, 5 deletions) and consumed ~34.5 minutes of self-hosted runner time across the first 30 of its 73 workflow runs.

The self-skip design works for almost everything. Measured job durations on docs/visual-arch-align:

Job n total s max s
verify-precommit-config (Enforce Pre-commit Hooks) 2 1142 645
smoke-test (Docker Smoke Test) 1 590 590
Detect changed paths 10 123 14
Unit & Integration Tests 2 8 5
migration-matrix 2 7 4
python-suite 2 7 4
verify-generated-types 2 5 3
api-wiring 1 3 3

Unit & Integration Tests, python-suite, migration-matrix, verify-generated-types and api-wiring all report in 3-5 seconds — they gate their work on changes and self-skip exactly as ci.yml:36-37 describes. That design is correct and is not what this issue proposes changing.

verify-precommit-config and smoke-test do not self-skip. Together they are 1732s of the 2068s measured — 84% of all runner time spent on a markdown edit.

Why a paths: filter is the wrong fix

Both jobs publish required status contexts (verify-precommit-config, smoke-test). Adding pull_request.paths would recreate the deadlock that #14353 removed and that ci.yml:24-31 documents inline: when a filter and the workflow trigger disagree, neither workflow reports the required context and the PR waits forever on a check nobody can produce. enforce-precommit.yml:10 already says its missing filter is deliberate for this reason.

The workflow must keep starting. Only the work should be skipped.

Proposed fix

Apply the pattern the other required contexts already use — a changes detection job, with the expensive steps gated on it, and the context still reported when nothing relevant changed:

  • .github/workflows/enforce-precommit.yml — gate the config-verification steps on a paths check; report verify-precommit-config as passing when the PR touches no .pre-commit-config.yaml, hook, or workflow path
  • .github/workflows/docker-smoke-test.yml — gate smoke-test on changes to Dockerfiles, compose files, and the application source it exercises; a markdown-only PR should report the context without building an image

Acceptance criteria

  • A docs-only PR reports verify-precommit-config and smoke-test as passing in seconds, not minutes
  • Both contexts are still reported on every PR, so branch protection can never deadlock
  • A PR touching .pre-commit-config.yaml, .github/workflows/**, or hook scripts still runs the full pre-commit verification
  • A PR touching Dockerfiles, compose files, or application source still runs the full smoke test
  • Measured: a docs-only PR's total runner time drops by roughly the 1732s identified above

Why this matters on a self-hosted runner

Runner slots are finite. Docs PRs holding them for ~20 minutes per push delays unrelated PRs behind them in the queue. The cost here is contention and latency, not billing.

Evidence

PR #15250: 1 file, +5/-5, docs only
73 workflow runs; first 30 sampled -> 59 jobs, 40 executed, 19 skipped
runner time in successful jobs: 2068s (34.5 min)
verify-precommit-config + smoke-test: 1732s (84%)

Repo-wide context: only 2 of the last 200 workflow runs failed, so this is not a flakiness or retry problem — it is unconditional work on irrelevant changes.

Activity

  1. github-actions commented on Aug 29, 2026

    @github-actions
    Contributor

    PR #15300 (merged to Dev_new_gui) references this issue with a close keyword.

    ci(perf): stop docs-only PRs running the pre-commit sweep and image build (#15299)

    If this issue is fully resolved, close it manually. If work remains, no action is needed.

  2. mrveiss commented on Aug 29, 2026

    @mrveiss
    OwnerAuthor

    Closed by PR #15300, merged as 36a1e7d25f into Dev_new_gui.

    Acceptance criteria — verified against the merged base, not the branch

    AC Evidence
    Docs-only PR reports both contexts in seconds The sweep, its two output-parsing steps are gated on steps.filter.outputs.code; smoke-test gated on needs.changes.outputs.docker. git show origin/Dev_new_gui:.github/workflows/enforce-precommit.yml shows 3 gated steps
    Both contexts still reported on every PR, no deadlock verify-precommit-config's job is never gated — it always runs and reports. smoke-test moves to docker-smoke-required-context.yml:60,68 on the exact complement (docker != 'true')
    Pre-commit config / hook / workflow changes still run the full sweep docs-only-paths.yml code key = ** minus prose, so any .pre-commit-config.yaml, .github/** or hook script edit yields code == 'true'
    Docker / compose / app source still runs the full smoke test .github/filters/docker-paths.yml, present in base, covers every COPY/ADD in the backend, slm and frontend Dockerfiles and every default compose bind-mount
    Runner time drops by roughly the 1732s identified The two gated cost centres were 1008s (sweep) + 590s (image build + compose start) = 1598s. Set up Python (18s) stayed ungated for the reason below, so the realised saving is ~1598s rather than the full 1732s

    Live behaviour, observed on PR #15300 itself

    The smoke-test context appeared twice — pass from the real job and skipping from the shim — which is the intended complement for a PR that touches Docker-relevant paths. This PR touches .github/**, so both gates evaluated true and both jobs ran in full; a docs-only PR is what takes the fast path.

    Review found one blocking bug, fixed before merge

    Gating Set up Python would have broken the required check on exactly the docs-only PRs this issue targets. Two ungated steps run afterwards and call python3 pipeline-scripts/check_workflow_path_filters.py, which does import yaml (:52); PyYAML reaches the runner only as pre-commit's dependency, as enforce-precommit.yml states inline. Skipping the setup step would have produced ModuleNotFoundError: No module named 'yaml'.

    CI could not have caught this — a PR touching .github/** has code == 'true', so the skip path is never exercised by this PR's own run. Fixed in 28361d5a65 by keeping Set up Python ungated; at 18s against the sweep's 1008s it forfeits almost none of the saving.

    Also corrected in review: config/** and autobot-slm-agent/** matched nothing (untracked local directories, not repo paths) and were removed; all 19 remaining directory patterns confirmed tracked.

    Additional fix carried in the same PR

    CodeQL raised 2 medium alerts: docker-smoke-test.yml carried no permissions: block at all — pre-existing, surfaced because the file was touched. Fixed in bb05dd2e6b with contents: read, matching hardened-smoke-test.yml and co-located-smoke.yml.

    CI

    33 success, 16 skipped, 0 failures, verified against the review-fix commit 28361d5a65 rather than an earlier push. CodeQL, verify-precommit-config and smoke-test all green.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions