Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 29 additions & 1 deletion docs/architecture.md
Original file line number Diff line number Diff line change
Expand Up @@ -643,12 +643,40 @@ ids and progress in `.env.trial-<slug>-wizard` at the repo root, beside the tria
those secrets files are the only copy, since Cloudflare cannot read a secret back. Only
`scripts/deploy_trial.py` changes that file after the wizard: it records the image it staged
there, so a later wizard run renders that image and not the first one, and the commit each of the
rss and vote Workers was last deployed from, so the next staging knows whether to redeploy them. A
rss, vote and newsletter Workers was last deployed from, so the next staging knows whether to redeploy
them. A trial whose state holds `TRIAL_NEWSLETTER_KV_ID` has that third Worker: `render` writes its
`workers/newsletter/wrangler.trial-<slug>.toml`, `load_rendered` checks it for production names and drift
as it does the other three, `deploy_trial.py` renders it again and deploys it, and `reset_trial.py` clears
its `NEWSLETTERS` KV. The state's id alone says whether a trial has that Worker, in all three scripts. A trial wired
before it has no id, and each script leaves the Worker out. A config on disk with no id is a state to report, not to
act on: `load_rendered` neither reads nor validates it, so a stray one cannot stop either script, and `reset_trial.py` and
`deploy_trial.py` each print the same one line saying that the config and its KV are left alone and that the id belongs
in the wizard state; the reset finishes the rest of its work and the deploy deploys the other Workers. An id with no
config on disk is refused by `reset_trial.py` before any call, naming the `provision_trial.py render` command built from
the state's values (the one the wizard's stage 8 runs) and a full deploy as the alternative, each on a line of its
own, or, when the state lacks a value that command needs, naming each missing key and the wizard stage that saves it,
and rendered again by
`deploy_trial.py`. A config whose KV id differs from the state's stops `reset_trial.py` before any KV delete.
`deploy_trial.py` runs `cyris doctor` on the trial's D1 settings once `/api/build` names the deployed commit, because a D1
missing a required key serves that commit while every run exits at once. It reads `.env.trial-<slug>` once, before any
deploy and in a `--dry-run` as in a real run, to build the `.env` doctor runs on; a dry run also reads
`.env.trial-<slug>.access` as a real run does, and refuses a missing service token. Doctor applies the schema to the
database that file names, so the script first checks that it names the state's `TRIAL_D1_ID`, reading the value as
cyris does (stripped, the first line winning), and stops before any deploy when it does not, or when the file holds
`CYRIS_STORE_DATABASE_ID` on more than one line. A
trial's reader content can also come from production: `scripts/seed_trial.py save` copies
production's rows of the tables `scripts/reset_trial.py` clears into `~/cyris-trial-seeds/`,
outside the repo, and `restore` writes them into a trial's D1, never its `settings` or
`pages_*` rows, which name production's notification targets and Pages project.

The trial's newsletter Worker takes the same bearer as its rss Worker and its app, `TRIAL_WORKER_TOKEN`,
which the app presents as `CYRIS_WORKER_TOKEN`. That is deliberate and follows production: `WorkerConfig`
reads one `CYRIS_WORKER_TOKEN` for both server-to-server Workers, so a second value would have nowhere to
go in the app, and [ADR-0008](decisions/0008-worker-bearers-split-by-published-versus-secret.md) records
that the two were held apart before and it "bought independent rotation of keys nobody rotates", since the
same `.env` and the same Worker secret store hold both. The vote Worker's bearer stays separate, because
that one was once published.

### One store, one truth

`D1ArticleStore` satisfies `ArticleRepository`, and `[store] backend` picks where its tables are:
Expand Down
5 changes: 3 additions & 2 deletions docs/operations.md
Original file line number Diff line number Diff line change
Expand Up @@ -94,14 +94,15 @@ before it. This project's trial is `trial1`.
1. Merge to `main`. The release runs, and its deploy job deploys production.
2. From the checkout that provisioned the trial, with that commit checked out, run
`scripts/deploy_trial.py`. It deploys the image the release recorded, and fails
unless the trial reports that commit. To check onboarding from its first step,
unless the trial reports that commit and `cyris doctor`, run locally on the trial's
`.env.trial-<slug>` against its D1, reports no error. To check onboarding from its first step,
clear the trial with `scripts/reset_trial.py` first. To check it from real content,
restore a seed of production's with `scripts/seed_trial.py` first. Each script
describes itself under `--help`.
3. Check the release on the trial. If it is wrong, take production back as *Going back*
describes.

The rss and vote Workers deploy outside any workflow. `deploy_trial.py` deploys the
The rss, vote and newsletter Workers deploy outside any workflow. `deploy_trial.py` deploys the
trial's copies when their code changed, and production's copies then need the same
deploy by hand.

Expand Down
3 changes: 2 additions & 1 deletion docs/trial-deployment.md
Original file line number Diff line number Diff line change
Expand Up @@ -148,7 +148,8 @@ The wizard writes these at the repo root, all gitignored:

A trial started before the newsletter Worker existed re-runs from stage 5, with `--from 5`,
to create its newsletter KV namespace. Without it, stages 8, 9, 14 and 15 skip the
newsletter Worker and print that command. Its stage 13 pushes the settings alone, and
newsletter Worker and print that command, and `deploy_trial.py` and `reset_trial.py` leave it
out too. Its stage 13 pushes the settings alone, and
`cyris settings push` never overwrites a row, so the tester's sources and `/settings` edits
stay as they are. `trial1` was wired by hand before then and is left as it is, with no
migration path.
Expand Down
Loading
Loading