Deploy from CI, plus maintainer and handover docs - #3
Merged
Conversation
Production deploys currently only happen by running `npm run deploy` locally with personal wrangler credentials, so nobody else can ship a corrected drug dose. This moves publishing to CI on push to main. Guarded by a credential-check step rather than a job-level condition: the secrets context is not available in `if:` expressions, so the job promotes the token to job-level env and gates the build and deploy steps on a step output. With no CLOUDFLARE_API_TOKEN configured the job succeeds and logs that it skipped, so CI stays green until the token exists. `npm run deploy` is retained as the break-glass path. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Neither repo documented how to run, ship, or inherit this app. Written for a successor who is not the original author. MAINTAINERS.md covers local setup, the test commands, and both deploy paths. HANDOVER.md inventories every account, domain, secret and token, who owns each, whether the app needs it, and how to rotate it — Cloudflare, the personal dream.yuson.au domain and its pages.dev fallback, Sentry and Supabase (both optional at runtime), and the PasswordGate PIN. Also records, as a known issue to fix separately, that the research submissions migration grants the anon role INSERT, SELECT and DELETE on all rows. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The e2e job installs dependencies and Playwright, then Playwright starts `npm run preview` (because CI is set), which serves dist/. Nothing in that job ever built dist/, so the preview server had nothing to serve and all 59 tests timed out waiting for the app to render. This has been failing on every release since the job was added, giving the appearance of e2e coverage without any. It also blocks the new deploy job, which is gated on `needs: [test, e2e]`. Reproduced locally: the suite passes with dist/ present and fails identically to CI with dist/ moved aside. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The TTL expiry test seeds the clock at 2026-07-14T10:00:00+10:00 and asserts the banner reads "expires at 10:29". The app formats that in browser-local time, so the assertion only held on a machine set to Sydney and failed on CI runners, which are UTC — 00:29, exactly ten hours off. Pinning timezoneId makes every test deterministic regardless of runner locale, and matches where the app is actually used. Verified: full chromium suite 59/59 passing with TZ=UTC, up from 0/59 before the missing-build fix and 58/59 after it. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Why
Production deploys only happen by running
npm run deploylocally with personal wrangler credentials. If the current maintainer stops working on this, nobody can ship a corrected drug dose — regardless of who can edit one. That is the binding continuity risk, not editing access.What
ci:deploy job on push tomain, aftertestande2epass.Guarded by a credential-check step rather than a job-level condition: the
secretscontext is not available inif:expressions, so the job promotes the token to job-levelenvand gates the build and deploy steps on a step output. With noCLOUDFLARE_API_TOKENconfigured the job succeeds and logs that it skipped, so CI stays green until the token exists.npm run deployis retained as the break-glass path.docs:MAINTAINERS.md + HANDOVER.md — neither repo documented how to run, ship, or inherit this app.MAINTAINERS.md— local setup, test commands, both deploy paths.HANDOVER.md— every account, domain, secret and token; who owns each, whether the app needs it, how to rotate it. Covers the personaldream.yuson.audomain and itspages.devfallback, Sentry and Supabase (both optional at runtime), and thePasswordGatePIN.Known issue recorded, not fixed here
supabase/migrations/001_research_submissions.sqlgrants theanonrole INSERT, SELECT and DELETE on all rows — anyone holding the anon key can read or delete every research submission. Documented in HANDOVER.md; worth a separate fix.Before this can actually deploy
Add
CLOUDFLARE_API_TOKENandCLOUDFLARE_ACCOUNT_IDas repo secrets. Until then the deploy job is inert by design.🤖 Generated with Claude Code