DataTalksClub / DataTalksClub/website

Run non-blocking read-only smoke against the deployed development release

Open
#239 4 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

Product outcome

After a successful development deployment, a separate non-blocking workflow proves that the exact sealed release is still healthy through the reviewed read-only browser boundary. Its evidence is exact-release, bounded, redacted, and valid for four hours. A failure is visible to on-call but cannot rewrite the deployment result, roll back the release, or delay the next push's verification start.

This is #228 Slice B. Slice A remains shipped and accepted at feature commit 109a108b33f106029530dda95fbd85896dd084c7, merged as 373e77e920e3978c718d6bde2921a2d01581548b; this issue must not reopen it.

Normative authority

  • _docs/PROCESS.md: lifecycle, evidence, independent testing, and on-call acceptance.
  • _docs/specs/07-security-privacy-operations.md: least privilege, auditability, redaction, rollback, and incident ownership.
  • _docs/specs/10-verification-strategy.md: release-critical local tests and distinct deployed-environment verification.
  • _docs/ci/change-selective-ci.md: aggregate gate and release ordering; a red gate never deploys.
  • _docs/ci/playwright-flake-policy.md: complete terminal evidence and no automatic retry.
  • Parent #228 and its accepted Slice A evidence.

Current contract and evidence

  • Deployment already runs migrations, health/readiness checks, safe HTTP smoke, and the guarded browser smoke synchronously. Those checks remain authoritative and unchanged.
  • A successful deploy publishes development-successful-release-<source_sha>-attempt-<attempt> containing .tmp/deployment/successful-release.json; the record binds release identity and is emitted only after deployment and evidence finalization succeed.
  • make test-remote-readonly currently collects exactly three nodes from playwright_tests/test_deployed_smoke.py: parameterized public/Studio coverage plus health/admin API coverage.
  • Remote execution is allowed only with DTC_TEST_SAFETY_COMMAND=remote_readonly, the isolated-development target class, bounded namespace, and the exact allowed origin.
  • The copied e2e/ suite is mutating and is outside this issue.
  • Current-main push/scheduled evidence is red on the separate #232/#236 homepage blocker, so no current run establishes this issue's live baseline.

Scope

1. Dedicated post-deploy workflow

Add one dedicated workflow triggered by workflow_run completion of workflow CI. Its qualification gate may proceed to artifact download and live execution only when:

  • the triggering event was push;
  • the head branch is main;
  • the triggering repository is this repository;
  • the triggering run conclusion is success;
  • the triggering source run has run_attempt == 1.

A completed manually re-run source workflow (run_attempt > 1) is handled only by the provenance/rejection path: it emits infrastructure_error without artifact download or live access, then fails. On-call waits for the next natural successful deployment instead.

Do not add a schedule or manual dispatch in this first bounded slice.

The workflow must:

  • use only contents: read and actions: read; it receives no write permission, OIDC, environment deployment authority, AWS credential, GitHub App credential, or application secret;
  • have a dedicated concurrency group separate from website-development-release, with cancel-in-progress: true; a newer natural qualifying deployment may cancel stale read-only work, and this lane cannot serialize or block the next push's classification, quality, container, Django, or Playwright start;
  • check out and execute the exact trusted triggering main SHA, not mutable main;
  • preserve the existing in-deploy migration, health/readiness, HTTP, browser smoke, artifact, and release-record behavior.
2. Resolve one exact successful release

From the exact triggering workflow run and attempt, download exactly one unexpired artifact named:

development-successful-release-<head_sha>-attempt-<run_attempt>

Fail safely on zero, multiple, expired, malformed, oversized, ambiguous, or inaccessible matches. Validate bounded archive size, entry count, exact allowed path, duplicate names, traversal, symlink/non-regular entries, decompression size, JSON schema, and provenance before use.

Do not change ReleaseRecord or the deployment artifact schema. The unchanged record remains the sealed runtime identity. A separate versioned smoke-result provenance section must bind the exact triggering repository, workflow name/path, run ID, run attempt, event, branch, and head SHA; the exact successful-release artifact name and payload SHA-256; and the validated record's identity schema, source SHA, version, and image digest. Its source SHA must equal the triggering head SHA, and the pre/post live identity must equal those record fields. Any missing binding or mismatch is infrastructure_error before a pass. Never fall back to the latest artifact, another attempt, another SHA, or current live identity.

3. Guarded read-only execution

Run only make test-remote-readonly with:

  • DTC_TEST_SAFETY_COMMAND=remote_readonly;
  • DTC_TEST_TARGET_CLASS=isolated_development;
  • a bounded per-run namespace derived from triggering run and attempt;
  • DTC_TEST_BASE_URL=https://web.dtcdev.click;
  • expected version, source SHA, and image digest from the validated successful-release record;
  • screenshots/output beneath project-local .tmp/.

Collection is pinned to the current three reviewed deployed-smoke nodes. Before any browser assertion and again after the suite, read the live health/readiness identity and require it to match the sealed release record. State-changing methods and wrong host/target/namespace/configuration are denied before network access.

If the live identity advances during the check, report superseded, not pass; do not attribute the old release's browser result as a current product failure. A terminal detected superseded verdict completes the Actions job successfully so expected release overlap is not paged as a product failure, but the summary and artifact must say superseded and on-call must treat it as unresolved/non-green. Only the next natural qualifying deployment can produce the authoritative pass.

4. Bounded, redacted evidence

The workflow job has an explicit 30-minute outer timeout. For every terminal run that was not canceled, a bounded finalizer must run with if: always() && !cancelled() and attempt evidence upload in a step bounded to 2 minutes and within artifact limits. Upload is best-effort under GitHub cancellation: cancel-in-progress may stop the runner before the finalizer, so a canceled run is allowed to have no artifact and can never be counted as pass. If a completed finalizer detects that a successor made the run stale, any uploaded result is superseded, never pass. The finalizer uploads:

  • one versioned machine-readable result;
  • bounded command/test output;
  • only the existing reviewed public homepage/courses/Studio-sign-in screenshots when produced.

The result contains:

  • schema version and verdict: pass, fail, superseded, or infrastructure_error;
  • triggering repository, workflow run ID/attempt, event/branch, and exact head SHA;
  • validated release version/source SHA/image digest;
  • started/completed timestamps and expires_at = completed_at + 4 hours;
  • exact command, collected/attempted/passed/failed/skipped counts, and output/artifact digests;
  • a safe failure category and exact failed node ID when applicable.

The Actions summary may expose those reviewed non-secret identity fields, counts, durations, verdict, and safe failure category. It must not expose credentials, cookies, authorization headers, query strings, registration data, user data, response bodies, artifact URLs, or unreviewed screenshots/log fragments. Artifact retention may exceed four hours for diagnosis, but the live verification claim expires after four hours and cannot be reused as current release evidence.

5. Failure and on-call semantics

A fail or infrastructure_error result fails its own Actions workflow and is visible and actionable. A terminal detected superseded result has Actions conclusion success only to avoid a false product-failure alert; it is explicitly non-green in the summary/result and must be replaced by the next natural qualifying run. A concurrency-canceled run has Actions conclusion cancelled; evidence upload is best-effort and its absence is unresolved, never pass. A source run_attempt > 1 is an unsupported rerun: reject it before artifact/live access as infrastructure_error, fail that smoke workflow, and wait for the next natural deployment. None of these outcomes:

  • change the already completed CI/deploy conclusion;
  • trigger rollback or redeployment automatically;
  • authorize a release;
  • suppress or delay the next push;
  • become a pass through retry.

On-call records the exact sealed identity, safe category, and failed node, then routes product failures through the issue lifecycle. A superseded run is replaced only by the natural workflow for the newer successful deployment.

Dependencies and readiness

Depends on #232 and #236. Do not start engineering while either issue is open.

Before those issue-local dependencies can close, the shared recovery baseline must complete in order #261 → #253 → #279 → #223 → #270, including the external-source prerequisite and re-grooming required by #253. A changed base invalidates prior plans and evidence.

Readiness requires this exact sequence:

  1. #232 receives independent tester PASS and PM acceptance on the ordered combined tree.
  2. #236 receives independent tester PASS and PM acceptance on that exact ordered tree.
  3. Focused commits merge in #232 then #236 order and are pushed as one accepted main state.
  4. That exact combined SHA records playwright, screenshots, ci-gate, publish, and deploy successful.
  5. https://web.dtcdev.click reports that sealed source/version/image identity healthy and ready.

#222 is shipped and is not a code dependency. The same first green natural release may satisfy #222's outstanding live observation, but that does not broaden this issue.

Non-goals

  • No schedule, manual dispatch, pull-request trigger, production target, automatic issue creation, or manual/source-workflow retry path in this slice.
  • No ReleaseRecord, deploy-controller, successful-release artifact schema, deployment job, or rollback behavior change.
  • No change to playwright_tests/, shared Playwright fixtures, the three reviewed node contracts, or Playwright Make targets. The new workflow consumes the existing make test-remote-readonly boundary unchanged.
  • No mutating E2E/provisioning, enrollment, homework, project, teardown, email, live-provider, remote_mutation, or copied e2e/ collection.
  • No signed-in synthetic-user flow, credential creation, database mutation, cleanup, or provider side effect.
  • No removal or weakening of deployment-time migrations, health/readiness, HTTP/browser smoke, aggregate gate, publish/deploy authorization, safety guards, assertions, or evidence.
  • No application/template/CSS/JavaScript/API/domain behavior change.
  • No automatic retry, rollback, redeploy, or treatment of missing/stale evidence as success.
  • No engineer/tester live workflow dispatch or real remote probe to manufacture acceptance evidence.

Acceptance criteria

Trigger, privilege, and concurrency
  • Workflow contract tests prove only a successful same-repository CI push to main at attempt 1 can enter artifact/live execution; a completed later attempt can enter only the no-network rejection path.
  • Permissions are exactly read-only contents/actions; no environment, OIDC, deploy, cloud, app, or application credential is available.
  • Its dedicated cancelable concurrency cannot share the deployment group or block the next push's verification jobs.
  • Exact triggering SHA is checked out and all artifact/API lookups are bound to the triggering run and attempt; run_attempt > 1 is rejected before artifact download or live access and cannot fall back to attempt 1.
Provenance and safety
  • Tests cover exact artifact success plus zero/multiple/expired/oversized/malformed/traversal/symlink/duplicate/wrong-path/wrong-schema/wrong-SHA/wrong-attempt cases.
  • The separate smoke-result provenance binds repository/workflow/run/attempt/event/branch/head SHA to the exact artifact name and payload digest; the unchanged validated ReleaseRecord and pre/post live identity match exact source/version/image before execution.
  • The final identity check prevents a pass when live changes mid-run and emits superseded.
  • Safety tests prove wrong origin, target class, namespace, command, identity, and state-changing HTTP methods fail before network access.
  • Collection is exactly the three reviewed remote_readonly nodes and excludes every mutation/email/provider/copied-e2e marker and path.
  • One complete no-retry record satisfies attempted = passed + failed + skipped; partial/timeout/malformed output fails.
Evidence and operations
  • Result schema, four-hour validity, bounded artifact/output/screenshot policy, digests, and all four verdicts are deterministic and tested.
  • Logs, summaries, and fixtures pass redaction tests for credentials, cookies, auth headers, query/registration/user data, response bodies, URLs, and unreviewed screenshots.
  • fail/infrastructure_error fail this workflow; detected superseded completes Actions successfully but is visibly non-green; concurrency cancellation concludes cancelled, may omit evidence, and is unresolved. None changes prior deploy status, triggers rollback, or blocks the next push.
  • Existing deployment tests prove its synchronous release checks and successful-release artifact are unchanged.
  • Focused workflow/safety/provenance/result tests, make test-ci, lint, format, typecheck, security, and repository workflow contracts pass.
  • Versioned verification classifies all changed components once. This bounded implementation does not change playwright_tests/, browser fixtures, Playwright Make targets, or product render inputs, so tester screenshots are not_applicable only when the computed plan confirms no render impact. If implementation touches any such input, the N/A claim is invalid and graph-required screenshot evidence must be completed or the scope returned to PM; no planner exception is added.
  • Independent tester uses fake GitHub/API/artifact/HTTP fixtures only; no real deployment or live call is made during candidate verification.
  • PM accepts the frozen candidate from the release-operator perspective.
  • [ON-CALL] The first natural successful qualifying attempt-1 deployment triggers the workflow without manual intervention, collects exactly three nodes, matches identity before and after, and produces an unexpired pass. superseded, cancelled, rejected rerun, missing evidence, or any failure returns through the lifecycle and is not called green; no rerun is used to manufacture acceptance.

Scenarios

  1. Repository — valid release: exact run/attempt artifact validates, identity is stable, three read-only nodes pass, and bounded evidence reports pass.
  2. Repository — malformed provenance: missing/duplicate artifact, unsafe archive entry, schema mismatch, or wrong SHA fails before remote access.
  3. Repository — safety denial: wrong host/target/namespace or attempted POST/PUT/PATCH/DELETE is denied before network access.
  4. Repository — route failure: one reviewed route fails; evidence names its node and safe category without leaking response/user data.
  5. Operations — superseded: a newer release becomes live during execution; final identity mismatch reports superseded, never pass.
  6. Operations — overlap: a newer natural qualifying run cancels stale read-only work without sharing deployment concurrency or delaying new push verification; the old Actions run is cancelled with best-effort/no guaranteed artifact, or completes with explicit non-green superseded, never pass.
  7. Operations — unsupported rerun: source run_attempt > 1 is rejected before artifact/live access as infrastructure_error; attempt 1 evidence is never reused and on-call waits for the next natural deployment.
  8. On-call — green: the natural workflow for the first accepted combined #232/#236 deployment produces an exact-identity, three-node, four-hour-valid pass.

Lifecycle handoff

After dependencies close, engineer implements in an isolated worktree without commit/push/workflow dispatch, generates the versioned plan, runs local fixture-backed gates, and freezes. Independent tester recomputes the plan and verifies trigger, provenance, safety, redaction, collection, and verdict behavior without a real live call. PM accepts. The focused commit uses Closes #239; orchestrator merges/pushes; on-call alone observes the natural post-deploy workflow.

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

Start with _docs/PROCESS.md, the security/privacy and verification strategy specs, and the change-selective CI and Playwright flake-policy docs. Then inspect the existing CI/deployment workflow, make test-remote-readonly, and playwright_tests/test_deployed_smoke.py. Done means the acceptance criteria prove exact-release provenance, guarded read-only execution, bounded redacted evidence, and the required failure and concurrency semantics after #232 and #236 are accepted.

Written by the indexing model from the issue text.

Assessment

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

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.