Skip to content

Re-pin the refreshed homepage subtitle through the deploy contract and fail drift in Django CI #198

Description

@alexeygrigorev

Grooming decision

Filed as a new issue rather than a #179 amendment. The introducing change is the owner's direct-to-main d8d5f27 ("Refresh homepage copy", 2026-08-18), which postdates #179's contract work — 8424b2c (2026-08-17) had already moved the then-current subtitle through the smoke pin and warned about exactly this miss class. #179 also remains held open by an unrelated [human] item (member-story placeholder copy) that this fix cannot discharge, and the durable guard below is new scope. This fix discharges the deploy side of #179's deploy/smoke.py acceptance criterion; #179's acceptance verifies it there.

Problem

The deploy job of run 32226341286 (main CI on b487b1f, the #196 merge push) failed at "Promote or roll back one atomic web-and-worker release" with release failed safely: home page lacks expected content: Free, project-based courses where you learn to build and build to learn. Every other job was green (playwright, django, quality, container, ci-gate, auto-capture-prior, publish) — only the deploy contract failed.

Root cause (verified): deploy/smoke.py run_http_smoke expects three home strings; the first two are current, but the third (line 192) still pins the pre-refresh subtitle. d8d5f27 changed templates/core/home.html's hero-lede to Free, hands-on courses in data and AI, with a clear path, practical work, and a community to help you get unstuck. and updated core/tests/test_homepage.py, but missed the smoke pin — the second instance of the miss class 8424b2c's message warns about. The Django suite cannot catch this class: core/tests/test_deployment_release.py (~line 2686) feeds run_http_smoke synthetic response bodies, so template↔contract drift is invisible until a live deploy.

The failure predates #196 (d8d5f27 is an ancestor of #196's frozen base 397bcd7; #196 changed one spec file only) — the push merely exposed it. This blocks the green push run #193's landing criteria expect.

Grep-verified: the only live pins of the old subtitle are deploy/smoke.py:192 and core/tests/test_deployment_release.py:2690 (other hits are a stale snapshot under .claude/worktrees/, out of scope). HOME_IDENTITY_MARKER (deploy/smoke.py:30) and the title pin are already the refreshed copy.

Scope

  • Update the third expected home string in deploy/smoke.py run_http_smoke to the current hero-lede rendered by templates/core/home.html (exact sentence or opening words is engineering's call; the guard below keeps whichever form in lockstep with the template).
  • Update the synthetic passing-home body in core/tests/test_deployment_release.py (~line 2690) to serve the new subtitle, so the happy path exercises the new pin, and re-pin that file's sha256 in _docs/compatibility/development-terminology-allowlist.json (the 8424b2c precedent).
  • Add the durable guard: a focused Django test that imports the home-page content strings run_http_smoke pins — title, HOME_IDENTITY_MARKER, and the subtitle — from deploy.smoke (single source of truth; extract a module-level tuple if that keeps it honest) and asserts each appears in the Django-rendered / response, and that the adopted course-discovery lede (Learn data skills. For free. Together.) stays absent from it. Template↔contract drift then fails Django CI instead of the deploy job. test_deployment_release.py already imports deploy.smoke, so importability in the Django suite is proven.

Non-goals

  • No template or copy change: d8d5f27's copy is the intended content; the contract follows the template, not the reverse.
  • No change to the rest of the release contract (health, version footer, canonical, /unified/, /courses checks) or to the synthetic-body testing approach beyond the string update.
  • No Playwright changes (playwright was green on b487b1f).
  • No reopening of Rebuild the public homepage on the design 5a mockup #179's design work or its member-stories human item.

Acceptance criteria

  • run_http_smoke's home content pins (title, HOME_IDENTITY_MARKER, subtitle) all match the current rendered homepage; the old subtitle pin is gone from deploy/smoke.py.
  • The synthetic passing-home body in core/tests/test_deployment_release.py contains the new subtitle; the file's terminology-allowlist sha256 is re-pinned and make terminology-check is green.
  • The new Django guard test sources the pinned strings from deploy.smoke (not re-typed literals), asserts each appears in the rendered / response and the course-discovery lede stays absent, and passes at head.
  • Focused Django tests, make test-ci, lint, format-check, and typecheck green; verification plan per _docs/ci/change-selective-ci.md with all component dispositions recorded.
  • Screenshots: not_applicable — no product-page render change (the template is untouched), per _docs/PROCESS.md.

Landing expectation: on-call observes the next main push promote successfully through the deploy job; that green run is also what #193's landing criteria await.

Dependencies: none. Unblocks #193's landing (green push run); discharges the deploy side of #179's smoke criterion.

Normative references: _docs/PROCESS.md (red pipeline attribution), _docs/ci/change-selective-ci.md, _docs/specs/02-url-link-seo-compatibility.md (home canonical/title contract).

Metadata

Metadata

Assignees

No one assigned

    Labels

    P0Must-have or release-blockingbugSomething isn't workinghumanCode complete; manual verification requiredinfraArea: infratestingArea: testing

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions