|
| 1 | +# Documentation infrastructure |
| 2 | + |
| 3 | +This repo is the **umbrella** of OWID's technical documentation. Its content is small (a landing page plus links into the subprojects). What makes it special is that it owns the custom domain and acts as a **router** in front of subproject Pages projects, so one URL transparently serves docs from multiple GitHub repos. |
| 4 | + |
| 5 | +``` |
| 6 | + docs-cf.owid.io (later: docs.owid.io) |
| 7 | + │ |
| 8 | + ▼ |
| 9 | + ┌──────────────────────────────┐ |
| 10 | + │ Cloudflare Pages project │ |
| 11 | + │ owid-docs (this repo) │ |
| 12 | + │ ───────────────────────── │ |
| 13 | + │ _worker.js (router) │ |
| 14 | + └──────────────┬───────────────┘ |
| 15 | + │ |
| 16 | + ┌──────────────────┼──────────────────────────┐ |
| 17 | + │ │ │ |
| 18 | + ▼ ▼ ▼ |
| 19 | + /projects/etl/* /projects/owid-grapher-py/* everything else |
| 20 | + │ │ │ |
| 21 | + ▼ ▼ ▼ |
| 22 | + owid-etl-docs owid-grapher-py-docs this repo's |
| 23 | + .pages.dev .pages.dev static assets |
| 24 | + (owid/etl) (owid/owid-grapher-py) |
| 25 | +``` |
| 26 | + |
| 27 | +## Repos involved |
| 28 | + |
| 29 | +| Repo | Pages project | Path prefix | |
| 30 | +|---|---|---| |
| 31 | +| `owid/owid-docs` (this) | `owid-docs` | `/` (umbrella + router) | |
| 32 | +| `owid/etl` | `owid-etl-docs` | `/projects/etl/` | |
| 33 | +| `owid/owid-grapher-py` | `owid-grapher-py-docs` | `/projects/owid-grapher-py/` | |
| 34 | + |
| 35 | +Each subproject repo owns: |
| 36 | +- a `.github/workflows/deploy-docs-cf.yml` that builds the docs and uploads to its Pages project via `wrangler pages deploy` |
| 37 | +- a sed-override of `site_url` in CI so the canonical/sitemap URLs reflect the production path on `docs-cf.owid.io/projects/<short>/` |
| 38 | + |
| 39 | +Per-PR previews still work on each project's own `*.pages.dev` URL — the umbrella router is only invoked for traffic to the custom domain. |
| 40 | + |
| 41 | +## `_worker.js` — the router |
| 42 | + |
| 43 | +Lives at repo root, copied into `site/` by the deploy workflow so CF Pages picks it up at the deployment root. When present, it intercepts every request to the Pages project. |
| 44 | + |
| 45 | +Responsibilities, in order: |
| 46 | + |
| 47 | +1. **Legacy URL rewrite** — strip the `/en/latest` segment baked into old ReadTheDocs links and 301 to the canonical path. |
| 48 | +2. **Subproject routing** — match a `SUBPROJECTS` prefix, `fetch()` the same path on the target Pages project, and stream the response back. |
| 49 | +3. **Fallback** — `env.ASSETS.fetch(request)` serves this repo's own static assets (umbrella landing page, CSS, etc.). |
| 50 | + |
| 51 | +To add a new subproject, append one line to the `SUBPROJECTS` map. |
| 52 | + |
| 53 | +## Adding a new subproject |
| 54 | + |
| 55 | +Concrete example: a hypothetical `owid/foo-docs` repo serving its docs at `docs.owid.io/projects/foo/`. |
| 56 | + |
| 57 | +1. **Create the CF Pages project** (use CLI — the dashboard's "Upload static files" flow now creates a Worker, not a Pages project): |
| 58 | + |
| 59 | + ```bash |
| 60 | + npx wrangler pages project create foo-docs --production-branch=master |
| 61 | + ``` |
| 62 | + |
| 63 | +2. **Add a workflow** in `owid/foo` mirroring [`.github/workflows/deploy-docs-cf.yml`](./.github/workflows/deploy-docs-cf.yml) from this repo or from `owid/etl`. Two things to adjust: |
| 64 | + - sed-replace `site_url` to `https://docs-cf.owid.io/projects/foo/` (later `docs.owid.io/projects/foo/`). |
| 65 | + - Stage the build into `staging/projects/foo/` before `wrangler pages deploy`. |
| 66 | + |
| 67 | +3. **Add repo secrets** in `owid/foo`: `CLOUDFLARE_API_TOKEN`, `CLOUDFLARE_ACCOUNT_ID` (same values used by the other repos). |
| 68 | + |
| 69 | +4. **Open a PR on this repo** appending the new prefix to `_worker.js`: |
| 70 | + |
| 71 | + ```js |
| 72 | + const SUBPROJECTS = { |
| 73 | + "/projects/etl/": "https://owid-etl-docs.pages.dev", |
| 74 | + "/projects/owid-grapher-py/": "https://owid-grapher-py-docs.pages.dev", |
| 75 | + "/projects/foo/": "https://foo-docs.pages.dev", // new |
| 76 | + }; |
| 77 | + ``` |
| 78 | + |
| 79 | +5. **Merge order** — `owid/foo` PR first (so the target Pages project gets its first production deploy), then this repo's worker PR. Reverse order is safe but `/projects/foo/*` will 404 in the interim. |
| 80 | + |
| 81 | +## Common operations |
| 82 | + |
| 83 | +### Cache purge (after risky changes) |
| 84 | + |
| 85 | +CF aggressively caches both static assets and worker responses (including 301s). If something looks stale after a deploy: |
| 86 | + |
| 87 | +CF dashboard → **owid.io zone** → Caching → Configuration → Purge Cache → Custom Purge → enter the specific URL(s) → Purge. |
| 88 | + |
| 89 | +### Swapping the custom domain |
| 90 | + |
| 91 | +Currently `docs-cf.owid.io` is bound to the `owid-docs` Pages project. To re-attach to another project (e.g., during emergency rollback), detach from the source first, wait ~30 s, then attach to the target. |
| 92 | + |
| 93 | +### Production branch |
| 94 | + |
| 95 | +Production deploys on a Pages project are only those uploaded with `--branch=<production-branch>`. The production branch is set when creating the project (`--production-branch=master|main`); changing it later via the dashboard requires re-deploying because CF does not auto-promote the latest deploy on the new branch. |
| 96 | + |
| 97 | +### Required repo secrets |
| 98 | + |
| 99 | +Each subproject repo + this one needs: |
| 100 | + |
| 101 | +- `CLOUDFLARE_API_TOKEN` — custom token scoped to `Account › Cloudflare Pages › Edit` + `User › User Details › Read`. |
| 102 | +- `CLOUDFLARE_ACCOUNT_ID` — visible in the CF dashboard URL. |
| 103 | + |
| 104 | +One token + account ID pair works for all repos. |
| 105 | + |
| 106 | +## Related deployments (unchanged today) |
| 107 | + |
| 108 | +- **ReadTheDocs** — still serves `https://docs.owid.io/` and the subprojects. Builds untouched. Will be decommissioned once the CF mirror has been validated and `docs.owid.io` DNS is repointed. |
| 109 | +- **GitHub Pages** — `.github/workflows/docs.yml` in this repo still publishes a copy. No active consumer; can be removed after the cut-over. |
0 commit comments