DataTalksClub / DataTalksClub/website

Five-minute release CI: core plus affected tests, full suite off the critical path

Open
#228 11 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

enhancement infra operations P0 testing
Dominant language
Python
Stars
0
Forks
0
PR merge metrics
No merged PRs in 30d

Description

Outcome

Release CI (push to main and workflow_dispatch promote of a main SHA) must finish in about five minutes of wall-clock time when the change is ordinary. It always runs a small core, plus only the tests the change affects. A broken change still fails the run and does not deploy.

The complete Django suite and the large Playwright suite stay on the scheduled path. End-to-end checks against the already deployed host stay on a live/post-deploy path. They must not sit on the critical path of every release.

Why current CI is ~30–50 minutes

#104 already shipped change-selective Django. Follow-ups #210 (Playwright smoke/core/full), #212, and #213 also shipped. That design is still too slow for release because of gaps, not because the selector is missing:

  1. workflow_dispatch is always profile=full / reason=manual_dispatch, with no Git range. A promote of current main therefore selects full Playwright (~49 minutes measured on #206) even when the commit only changed docs.
  2. _browser_profile forces full for manual_dispatch and diff_empty, so the smoke tier never runs on the exact path operators use to ship.
  3. The Django job ignores django_mode. Playwright already skips the suite when playwright_mode != rerun. Django still uv syncs and runs tests. Docs-only plans that mark Django skip still pay the full suite.
  4. Quality failure does not stop siblings. Quality can fail in seconds; Playwright keeps the serialized website-development-release group busy for tens of minutes. Observed on run 32949380835.
  5. courses/ focused closure is most of the suite and used to be slower than full; --parallel --noinput is now on the focused runner, but the closure is still huge.
  6. Concurrency cancel-in-progress: false is correct for an in-flight deploy, but a long failed run still blocks the next release. Fail-fast is the fix for that case.
  7. Live e2e exists (e2e/, playwright_tests/test_deployed_smoke.py, deploy smoke) but is not the scheduled “test the version that is live” lane the release path should rely on.

Do not rebuild the classifier, ownership graph, evidence envelopes, or the four-hour scheduled backstop. Tighten the release lane and keep the full lane scheduled.

Target shape

Lane When What Budget
Release push to main; workflow_dispatch operation=promote of a main SHA Core + affected. Deploy if the aggregate gate is green. ~5 minutes wall clock, jobs in parallel
Scheduled full existing 17 */4 * * * Full Django, full Playwright, quality, container unbounded except current job timeouts
Live e2e after a successful deploy and/or a cheap schedule against https://web.dtcdev.click Deployed smoke / remote-readonly, not in-process Playwright does not block the next commit's compile/test start

Release core (always, in parallel):

  • classification
  • quality contract (lint, types, security, terminology, portability, test-ci)
  • container/image (cache-hit expected after #222)
  • Playwright smoke unless the plan selects core/full for render/harness impact

Release affected:

  • Django focused closure when the first-parent (or push) range is one mapped app
  • Django full only when the existing force-full rules fire (shared core/accounts, migrations, templates, deps, unknown paths, cross-app)
  • Screenshots only on render impact (already planned)

Fail closed: unknown/unsafe range still full. Full on the release lane may miss the 5-minute budget; that is acceptable for migrations/shared runtime. The SLO applies to ordinary application or docs commits.

Scope (implement in slices)

Slice A — this issue's first engineering delivery
  1. Classify promote dispatch from the exact first parent of release_sha (git rev-parse <sha>^1). That SHA is the previous main for a fast-forward or --no-ff merge. Use the same NUL-safe diff and force-full rules as push. operation=rollback and any dispatch whose first parent cannot be proven stay manual_dispatch full.
  2. Allow workflow_dispatch selections to carry a real base and single_application when that range is valid. Stop forcing Playwright full solely because reason=manual_dispatch when the selection is no longer that reason.
  3. Honor django_mode == 'rerun' in the Django job the same way Playwright honors playwright_mode (skip the suite, still record success for an intentional skip).
  4. Fail fast: if the quality job fails, cancel the rest of the same run so Playwright cannot occupy the release group. Document that the run conclusion may be cancelled while the quality log holds the failure. Do not weaken the quality contract.
  5. Contract tests and _docs/ci/change-selective-ci.md for the new dispatch rule, Django skip, and fail-fast step.
Slice B — bounded follow-ups tracked in #238 and #239
  • Default release Playwright to smoke for non-render; keep core for ordinary render; full only for harness/templates. Confirm smoke is a small set (today test_foundation_smoke.py is still a large file).
  • Scheduled or post-deploy live e2e against https://web.dtcdev.click (test_deployed_smoke / e2e remote-readonly), never blocking the next push's compile.
  • Measure wall-clock of green ordinary pushes; report in the existing scheduled observability summary.
Slice C — later, tracked in #240
  • Shrink the courses/ focused closure once reverse-import coverage is trusted.
  • Optional: serialize only after a failed quality job without cancelling (job if:), if cancel-as-conclusion is too noisy.

Non-goals

  • No skipped quality/lint/security on release.
  • No deploy when the aggregate gate is red.
  • No deleting the four-hour full regression.
  • No cancel-in-progress: true on an in-flight deploy.
  • No guessing a dispatch base from HEAD^ of the runner checkout, merge-base with origin, or the last green run. First parent of the sealed release_sha only.
  • No application product behavior changes.

Authority

  • _docs/ci/change-selective-ci.md
  • _docs/audits/2026-08-20-ci-smart-test-selection-audit.md (items 5–6 still relevant; 7–10 largely done)
  • _docs/specs/10-verification-strategy.md
  • _docs/PROCESS.md (smoke/core/full tester tiers)
  • Closed #104, #210, #212, #213 (do not reopen; this issue supersedes their remaining speed gap)

Acceptance criteria

  • workflow_dispatch operation=promote of a reachable main SHA classifies release_sha^1..release_sha when that parent exists and is an ancestor; otherwise manual_dispatch full.
  • Rollback dispatch remains full / manual_dispatch.
  • A one-app promote dispatch can be focused and Playwright smoke/core according to impact, not automatically full Playwright.
  • Django job skips the suite when django_mode != rerun and still succeeds; ci-gate still requires the job outcome success.
  • Quality failure cancels remaining jobs in the same run within a short bound; the quality log remains the failure evidence.
  • Push selection is unchanged: exact github.event.beforeafter.
  • Scheduled full regression still runs local make test and full Playwright as today.
  • Classifier, selection, gate, workflow-contract, and provenance tests cover the new dispatch range, the still-full rollback path, Django skip, and fail-fast permissions/step.
  • Docs: reason glossary for promote-dispatch vs manual_dispatch; 5-minute release budget; scheduled + live e2e lanes.

Scenarios

  • Repository: promote dispatch of a docs-only commit vs first parent selects documentation skip for Django/Playwright suite execution; quality still runs; wall-clock dominated by quality+container.
  • Repository: promote dispatch of courses/** only is focused Django + smoke Playwright, not make test-playwright.
  • Repository: rollback dispatch stays full.
  • Repository: quality portability failure cancels Playwright; run does not sit for 30+ minutes.
  • Operations: scheduled full regression unchanged; live host e2e not required for slice A.

Dependencies

None. #104/#210/#212/#213 are merged. #222 (image cache) helps container time but is not a blocker for slice A.

Current child DAG and lifecycle

Slice A remains shipped and accepted; its checked criteria are not reopened. The remaining #228 children are exactly #238 (P0, groomed), #239 (P0, groomed), and #240 (P1, groomed and deferred). #237 and #241 are neighboring independent issues, not children or dependencies of #228.

Before #238 or #239 starts, establish the shared recovery baseline in order #261 → #253 → #279 → #223 → #270, reconstruct and accept #232 before #236 on one exact fingerprint, land focused commits #232 then #236, and obtain an exact-SHA green publish/deploy with healthy sealed live identity. #238 and #239 are sibling lanes and do not depend on each other. #240 additionally depends on accepted #238 evidence and its exact matching post-#238 green release and scheduled-full anchor.

#238 marker changes require fresh full Playwright and graph-derived independent screenshots. #239 is fixture-only during engineering/testing and may claim screenshots N/A only when its computed plan confirms no render or browser-harness impact; on-call alone observes the natural live workflow. #240 is internal non-render proof and retains its computed screenshot-N/A contract. Changed bases invalidate old plans and evidence.

Authoritative reconciliation: https://github.com/DataTalksClub/website/issues/228#issuecomment-5469130659

Contributor guide

No contributing guide indexed for this repository

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Slice A is marked shipped and accepted; read _docs/ci/change-selective-ci.md and the authoritative reconciliation comment before taking remaining work. Start with child issues #238, #239, and #240 and their named classifier, selection, gate, workflow-contract, and provenance tests. Done means the applicable child acceptance criteria and exact-SHA evidence are complete without reopening Slice A.

Written by the indexing model from the issue text.

Assessment

Tech stack
django, github-actions, playwright, python
Domain
ci-cd, devops, release, testing-qa
Issue type
Feature
Difficulty
5/5
Estimated time
Over a week
Activity status
Active
Clarity
Mostly clear
Newbie friendliness
25/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.