@norskvideo/ctl-dev-kit 0.2.93 → 0.2.95
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/conventions/docs-site.md
CHANGED
|
@@ -177,9 +177,9 @@ ln -s ../../../../../docs/generated/<slug> website/src/content/docs/guides/<slug
|
|
|
177
177
|
|
|
178
178
|
`docs:site` runs the dev-kit's `docs/guide-stubs.ts stub` first, so the site
|
|
179
179
|
builds on a checkout that has never captured. The captures come from the
|
|
180
|
-
product's nightly `publish-docs.yml`, which
|
|
181
|
-
|
|
182
|
-
the newest
|
|
180
|
+
product's nightly `publish-docs.yml`, which keeps `docs/generated` as the
|
|
181
|
+
`docs-captures` artifact after a passing engine tier; `publish-docs-site.yml`
|
|
182
|
+
downloads the newest one before its build (and runs when `publish-docs` completes, so a
|
|
183
183
|
fresh capture publishes without waiting for a push). It then runs
|
|
184
184
|
`guide-stubs.ts check` and refuses to deploy while any guide is still a
|
|
185
185
|
placeholder: until the guide has been captured once, the publish stops rather
|
|
@@ -214,9 +214,11 @@ where the repo has a site and is not a turnkey. On every push to `main` (and on
|
|
|
214
214
|
demand) it installs `website/`, builds the public variant and deploys
|
|
215
215
|
`website/dist-public` to Cloudflare Pages with `wrangler`. It never cancels a
|
|
216
216
|
run in flight, because a cancelled deploy is a half-published site. Before the
|
|
217
|
-
build it
|
|
218
|
-
|
|
219
|
-
|
|
217
|
+
build it downloads the newest recorded-guide captures (the `docs-captures`
|
|
218
|
+
artifact `publish-docs.yml` keeps for 30 days, not the Actions cache, whose
|
|
219
|
+
entries are versioned by a compression that varies across runners); a site
|
|
220
|
+
with no recorded guides restores nothing it reads, and builds from its
|
|
221
|
+
committed prose.
|
|
220
222
|
|
|
221
223
|
Where it may exist is the gate's business (ADR-0012, and the documentation
|
|
222
224
|
plan): a repo with `website/astro.config.mjs` may carry it; a repo without a
|
|
@@ -229,10 +231,11 @@ What the repo needs, per site, and none of it to build or review one locally:
|
|
|
229
231
|
|
|
230
232
|
1. **A Cloudflare Pages project**, e.g. `norsk-acme-docs`.
|
|
231
233
|
2. **A custom domain** on it — `<product>.norsk.video` — and the DNS record.
|
|
232
|
-
3. **
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
`CLOUDFLARE_ACCOUNT_ID`.
|
|
234
|
+
3. **The Cloudflare credentials reaching the repo.** The secret
|
|
235
|
+
`CLOUDFLARE_API_TOKEN`, a Pages:Edit token that covers the new project
|
|
236
|
+
(Pages permissions are account-wide), and the variable
|
|
237
|
+
`CLOUDFLARE_ACCOUNT_ID`. Both are org-level, shared with selected
|
|
238
|
+
repositories: add the repo to each. The workflow verifies the token at the API (both the
|
|
236
239
|
user-owned and the account-owned endpoint), never with `wrangler whoami`,
|
|
237
240
|
which a Pages:Edit token cannot answer.
|
|
238
241
|
4. **One repo variable.** `NORSK_DOCS_SITE_PROJECT`, the project name from
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
# rides every push (conventions/docs-site.md, "Two documentation channels").
|
|
9
9
|
# A site that also symlinks RECORDED guides (website/src/content/docs/guides/
|
|
10
10
|
# <slug> -> docs/generated/<slug>) publishes them from the captures that nightly
|
|
11
|
-
# run
|
|
11
|
+
# run keeps as an artifact: they are restored before the build, which
|
|
12
12
|
# stubs only a guide never captured, and the gate below refuses to deploy a
|
|
13
13
|
# stub. So the site also runs when publish-docs completes, to publish a fresh
|
|
14
14
|
# capture without waiting for the next push.
|
|
@@ -26,7 +26,9 @@
|
|
|
26
26
|
# site publishes the day the variable is
|
|
27
27
|
# set, with no change here.
|
|
28
28
|
# secret CLOUDFLARE_API_TOKEN a Pages:Edit token covering that project
|
|
29
|
-
#
|
|
29
|
+
# variable CLOUDFLARE_ACCOUNT_ID the account the project lives in: not a
|
|
30
|
+
# secret, and the org already shares it as
|
|
31
|
+
# a variable (norsk-ctl reads it the same way)
|
|
30
32
|
#
|
|
31
33
|
# The site is BUILT whether or not it will be deployed: if the build is only
|
|
32
34
|
# exercised on the day the Pages project appears, that day is when we find out
|
|
@@ -50,6 +52,7 @@ on:
|
|
|
50
52
|
|
|
51
53
|
permissions:
|
|
52
54
|
contents: read
|
|
55
|
+
actions: read # the newest docs-captures artifact, from the capture run
|
|
53
56
|
|
|
54
57
|
# Never cancel in flight: a cancelled `wrangler pages deploy` is a half-published
|
|
55
58
|
# site, and the next push rebuilds from the same inputs anyway. Queue instead.
|
|
@@ -122,17 +125,28 @@ jobs:
|
|
|
122
125
|
clean: true
|
|
123
126
|
|
|
124
127
|
# The recorded guides' captures, from the product's nightly capture run
|
|
125
|
-
# (publish-docs.yml
|
|
126
|
-
#
|
|
127
|
-
# a site that records no guides,
|
|
128
|
-
#
|
|
129
|
-
# deploy a stub.
|
|
128
|
+
# (publish-docs.yml keeps docs/generated as the docs-captures artifact
|
|
129
|
+
# after a passing engine tier): the newest unexpired one, put where
|
|
130
|
+
# docs:site:public expects it. None yet -- a site that records no guides,
|
|
131
|
+
# or before the first capture -- restores nothing; the build stubs what is
|
|
132
|
+
# missing and the gate below refuses to deploy a stub. gh comes from the
|
|
133
|
+
# build shell (the runners have no system gh).
|
|
130
134
|
- name: Restore the recorded guides' captures
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
135
|
+
env:
|
|
136
|
+
GH_TOKEN: ${{ github.token }}
|
|
137
|
+
run: |
|
|
138
|
+
nix develop .#build --command bash -c '
|
|
139
|
+
set -euo pipefail
|
|
140
|
+
run="$(gh api "repos/$GITHUB_REPOSITORY/actions/artifacts?name=docs-captures&per_page=20" \
|
|
141
|
+
--jq "[.artifacts[] | select(.expired | not)][0].workflow_run.id // empty")"
|
|
142
|
+
if [ -z "$run" ]; then
|
|
143
|
+
echo "no docs-captures artifact yet: nothing to restore"
|
|
144
|
+
exit 0
|
|
145
|
+
fi
|
|
146
|
+
mkdir -p docs/generated
|
|
147
|
+
gh run download "$run" --repo "$GITHUB_REPOSITORY" --name docs-captures --dir docs/generated
|
|
148
|
+
echo "restored the recorded guides captured by run $run"
|
|
149
|
+
'
|
|
136
150
|
|
|
137
151
|
# website/ is a STANDALONE package -- its own bun.lock, outside the root
|
|
138
152
|
# workspaces -- so the repo-root install never covers it, and the build
|
|
@@ -197,7 +211,7 @@ jobs:
|
|
|
197
211
|
- name: Deploy to Cloudflare Pages
|
|
198
212
|
env:
|
|
199
213
|
CLOUDFLARE_API_TOKEN: ${{ secrets.CLOUDFLARE_API_TOKEN }}
|
|
200
|
-
CLOUDFLARE_ACCOUNT_ID: ${{
|
|
214
|
+
CLOUDFLARE_ACCOUNT_ID: ${{ vars.CLOUDFLARE_ACCOUNT_ID }}
|
|
201
215
|
NORSK_DOCS_SITE_PROJECT: ${{ vars.NORSK_DOCS_SITE_PROJECT }}
|
|
202
216
|
PAGES_BRANCH: ${{ github.ref_name }}
|
|
203
217
|
run: |
|
|
@@ -210,13 +224,13 @@ jobs:
|
|
|
210
224
|
echo " 1. Create a Cloudflare Pages project for this site (e.g. $(basename "$GITHUB_REPOSITORY")-docs)."
|
|
211
225
|
echo " 2. Add its custom domain${origin:+ (${origin#https://})} and the DNS record."
|
|
212
226
|
echo " 3. Make sure CLOUDFLARE_API_TOKEN (Pages:Edit) covers that project, and that"
|
|
213
|
-
echo "
|
|
227
|
+
echo " the variable CLOUDFLARE_ACCOUNT_ID reaches this repo."
|
|
214
228
|
echo " 4. Set the repo variable NORSK_DOCS_SITE_PROJECT to the project name."
|
|
215
229
|
echo " Nothing in this workflow changes. See @norskvideo/ctl-dev-kit conventions/docs-site.md, Publishing."
|
|
216
230
|
exit 0
|
|
217
231
|
fi
|
|
218
232
|
if [ -z "${CLOUDFLARE_API_TOKEN:-}" ] || [ -z "${CLOUDFLARE_ACCOUNT_ID:-}" ]; then
|
|
219
|
-
echo "::error::NORSK_DOCS_SITE_PROJECT=$NORSK_DOCS_SITE_PROJECT is set, but
|
|
233
|
+
echo "::error::NORSK_DOCS_SITE_PROJECT=$NORSK_DOCS_SITE_PROJECT is set, but this repo needs both the secret CLOUDFLARE_API_TOKEN and the variable CLOUDFLARE_ACCOUNT_ID"
|
|
220
234
|
exit 1
|
|
221
235
|
fi
|
|
222
236
|
cf_verify() {
|
|
@@ -319,16 +319,21 @@ jobs:
|
|
|
319
319
|
run: nix develop .#build --command bun run docs:manual
|
|
320
320
|
|
|
321
321
|
# The captures, for the product's own docs site: publish-docs-site.yml
|
|
322
|
-
#
|
|
323
|
-
# the only one that can make them. Only after a
|
|
324
|
-
# site never takes a half-captured set over the
|
|
325
|
-
#
|
|
326
|
-
|
|
322
|
+
# downloads the newest docs-captures artifact, so its recorded guides
|
|
323
|
+
# publish from this run, the only one that can make them. Only after a
|
|
324
|
+
# passing engine tier, so a site never takes a half-captured set over the
|
|
325
|
+
# last good one. An artifact, not actions/cache: a cache entry is
|
|
326
|
+
# versioned by its compression, and the runner pool mixes machines with
|
|
327
|
+
# and without zstd, so a save on one never matched a restore on another
|
|
328
|
+
# (relay, 2026-10-21: saved on ashton-nuc, missed on test2-runner-1).
|
|
329
|
+
- name: Keep the guide captures for the docs site
|
|
327
330
|
if: ${{ steps.engine.outcome == 'success' }}
|
|
328
|
-
uses: actions/
|
|
331
|
+
uses: actions/upload-artifact@v4
|
|
329
332
|
with:
|
|
333
|
+
name: docs-captures
|
|
330
334
|
path: docs/generated
|
|
331
|
-
|
|
335
|
+
retention-days: 30
|
|
336
|
+
if-no-files-found: error
|
|
332
337
|
|
|
333
338
|
# Said three ways, so a failure is never silent: a warning on the run, a
|
|
334
339
|
# line in its summary, and the cell's detail (the notify job).
|