@norskvideo/ctl-dev-kit 0.1.80 → 0.1.82
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.md +37 -7
- package/conventions/publish-docs.yml +61 -0
- package/doc-guide/build-manual.d.ts +11 -0
- package/doc-guide/bundle.d.ts +14 -2
- package/doc-guide/bundle.js +29 -4
- package/doc-guide/docs-release.d.ts +41 -0
- package/doc-guide/docs-release.js +104 -0
- package/package.json +2 -1
package/conventions/docs.md
CHANGED
|
@@ -138,16 +138,46 @@ single-sourced here and drift-gated:
|
|
|
138
138
|
image as the proof. No upload, no write permission on the repo, no token. A
|
|
139
139
|
turnkey (`norsk-ctl-turnkey-*`) carries this and nothing else: its
|
|
140
140
|
documentation reaches exactly one customer, inside the image they already run.
|
|
141
|
-
- **`publish-docs.yml` — public.** The same build, then
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
141
|
+
- **`publish-docs.yml` — public.** The same build, then three things on one
|
|
142
|
+
moving `docs-latest` GitHub Release:
|
|
143
|
+
- `manual.html`, clobbered each night — what norsk-ctl's docs site fetches and
|
|
144
|
+
mounts at `/products/<slug>/`
|
|
145
|
+
(`https://github.com/<owner>/<repo>/releases/download/docs-latest/manual.html`).
|
|
146
|
+
- `bundle-<version>.tar.gz`, the whole bundle, named by the product commit it
|
|
147
|
+
was built from, plus `latest.json` naming the current one. Versioned assets
|
|
148
|
+
on ONE release rather than a release per commit: a release per commit would
|
|
149
|
+
leave hundreds of prereleases on the repo, and a single clobbered asset would
|
|
150
|
+
leave nothing to roll back to. Only the pointer moves, so a rollback is a
|
|
151
|
+
pointer edit and the site never reads an asset being overwritten underneath
|
|
152
|
+
it. `BUNDLE_KEEP` older bundles are pruned, never the one the pointer names.
|
|
153
|
+
- a `product-docs-published` `repository_dispatch` to `id3as/norsk-ctl`, so the
|
|
154
|
+
public site rebuilds rather than waiting for its own cron. The payload
|
|
155
|
+
carries the repo, not a product key — norsk-ctl resolves the key through
|
|
156
|
+
ci-workflows' registry, so a new product needs no new mapping.
|
|
157
|
+
|
|
158
|
+
**Only a repo GitHub calls `norsk-ctl-product-*` may carry it.** `check:drift` refuses it anywhere else,
|
|
148
159
|
refuses a repo carrying both, and refuses the public variant when it cannot
|
|
149
160
|
tell the repo's name (`GITHUB_REPOSITORY` in CI, the origin remote locally).
|
|
150
161
|
|
|
162
|
+
### Per-page visibility
|
|
163
|
+
|
|
164
|
+
Every page in `bundle.json` carries a `visibility`, `public` or `possession`,
|
|
165
|
+
defaulting to the bundle's own (`buildBundle(spec, { visibility })`, itself
|
|
166
|
+
`public`). The public fetcher stages only the public pages; the image serves all
|
|
167
|
+
of them either way, so `possession` means "reaches customers only inside the
|
|
168
|
+
image they already run".
|
|
169
|
+
|
|
170
|
+
**No page is special-cased — mark `possession` only when you mean it.** In
|
|
171
|
+
particular `known-limitations` is not the page to hide: a candid limitations
|
|
172
|
+
page is a trust asset for a public product, and hiding the honest page is an odd
|
|
173
|
+
signal to an evaluator.
|
|
174
|
+
|
|
175
|
+
This is not what protects a turnkey, and must not be read as if it were. Turnkey
|
|
176
|
+
privacy is a repo/bundle-level guarantee — the `^norsk-ctl-product-` repo-name
|
|
177
|
+
rule, the registry's `docsVisibility`, the per-repo workflow variant, and the
|
|
178
|
+
fetcher's own gate. A turnkey's whole bundle never reaches the public plane
|
|
179
|
+
whatever its pages say.
|
|
180
|
+
|
|
151
181
|
Either way the image serves the bundle at `/docs` (SDK `serveDocs`), reached
|
|
152
182
|
through the daemon at `/products/<name>/docs/` behind its auth guard and linked
|
|
153
183
|
from the product's hub via `ui.sidebarEntries`. That is the sole channel for a
|
|
@@ -177,3 +177,64 @@ jobs:
|
|
|
177
177
|
gh release upload docs-latest "$RUNNER_TEMP/manual.html" --clobber
|
|
178
178
|
echo "published -> docs-latest/manual.html"
|
|
179
179
|
'
|
|
180
|
+
|
|
181
|
+
# The docs BUNDLE, versioned, behind a moving pointer on the SAME release
|
|
182
|
+
# (fleet review 03 s3.5 slice 6). `manual.html` above is unchanged -- it is
|
|
183
|
+
# what today's ctl docs site mounts at /products/<key>/ -- and this is what
|
|
184
|
+
# the public plane ingests as pages.
|
|
185
|
+
#
|
|
186
|
+
# Versioned assets on one release, not a release per commit: a release per
|
|
187
|
+
# commit would leave hundreds of prereleases on each product repo, and a
|
|
188
|
+
# single clobbered asset would leave nothing to roll back to. Only
|
|
189
|
+
# latest.json moves, so a rollback is a pointer edit and the ctl site never
|
|
190
|
+
# reads an asset being overwritten underneath it.
|
|
191
|
+
#
|
|
192
|
+
# Bun.resolveSync rather than a node_modules path: it honours the package's
|
|
193
|
+
# exports map, so this works whether ctl-dev-kit is the published package or
|
|
194
|
+
# a workspace link (scripts/set-ctl-source.ts local mode).
|
|
195
|
+
- name: Publish the versioned docs bundle and move the pointer
|
|
196
|
+
env:
|
|
197
|
+
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
198
|
+
# How many bundles to keep on the release, the current one included.
|
|
199
|
+
BUNDLE_KEEP: "5"
|
|
200
|
+
run: |
|
|
201
|
+
nix develop .#build --command bash -c '
|
|
202
|
+
set -euo pipefail
|
|
203
|
+
bundle="docs/generated/bundle"
|
|
204
|
+
[ -s "$bundle/bundle.json" ] || { echo "::error::no docs bundle at $bundle/bundle.json"; exit 1; }
|
|
205
|
+
rel="$(bun -e "console.log(Bun.resolveSync(\"@norskvideo/ctl-dev-kit/doc-guide/docs-release\", process.cwd()))")"
|
|
206
|
+
version="$(bun "$rel" version "$GITHUB_SHA")"
|
|
207
|
+
asset="$(bun "$rel" asset "$version")"
|
|
208
|
+
tar -czf "$RUNNER_TEMP/$asset" -C "$bundle" .
|
|
209
|
+
gh release upload docs-latest "$RUNNER_TEMP/$asset" --clobber
|
|
210
|
+
bun "$rel" pointer --version "$version" --sha "$GITHUB_SHA" \
|
|
211
|
+
--run-id "$GITHUB_RUN_ID" --built-at "$(date -u +%Y-%m-%dT%H:%M:%SZ)" > "$RUNNER_TEMP/latest.json"
|
|
212
|
+
gh release upload docs-latest "$RUNNER_TEMP/latest.json" --clobber
|
|
213
|
+
gh release view docs-latest --json assets \
|
|
214
|
+
--jq "[.assets[] | {name: .name, createdAt: .createdAt}]" \
|
|
215
|
+
| bun "$rel" prune "$BUNDLE_KEEP" "$asset" \
|
|
216
|
+
| while read -r old; do
|
|
217
|
+
echo "pruning $old"
|
|
218
|
+
gh release delete-asset docs-latest "$old" --yes
|
|
219
|
+
done
|
|
220
|
+
echo "published -> docs-latest/$asset, pointer moved"
|
|
221
|
+
'
|
|
222
|
+
|
|
223
|
+
# Wake the public docs site rather than making it wait for its own cron.
|
|
224
|
+
# CI_DISPATCH_TOKEN, not GITHUB_TOKEN: repository_dispatch to ANOTHER repo
|
|
225
|
+
# needs Contents: write there, and the built-in token is scoped to this one.
|
|
226
|
+
# The payload carries the repo, not a product key: norsk-ctl resolves the
|
|
227
|
+
# key through ci-workflows' registry, so a new product needs no new mapping
|
|
228
|
+
# here. Not wrapped in nix -- plain curl, and the quoting stays readable.
|
|
229
|
+
- name: Tell norsk-ctl a new bundle is published
|
|
230
|
+
env:
|
|
231
|
+
DISPATCH_TOKEN: ${{ secrets.CI_DISPATCH_TOKEN }}
|
|
232
|
+
run: |
|
|
233
|
+
set -euo pipefail
|
|
234
|
+
body="$(printf '{"event_type":"product-docs-published","client_payload":{"repo":"%s"}}' "$GITHUB_REPOSITORY")"
|
|
235
|
+
code="$(curl -sS -o /dev/null -w '%{http_code}' -X POST \
|
|
236
|
+
-H "Authorization: Bearer $DISPATCH_TOKEN" \
|
|
237
|
+
-H "Accept: application/vnd.github+json" \
|
|
238
|
+
"https://api.github.com/repos/id3as/norsk-ctl/dispatches" -d "$body")"
|
|
239
|
+
[ "$code" = "204" ] || { echo "::error::docs-published dispatch to norsk-ctl failed (HTTP $code)"; exit 1; }
|
|
240
|
+
echo "dispatched product-docs-published -> id3as/norsk-ctl"
|
|
@@ -4,6 +4,13 @@ export type Step = {
|
|
|
4
4
|
head: string;
|
|
5
5
|
desc: string;
|
|
6
6
|
};
|
|
7
|
+
/** Where a page may be read. `public` reaches the public docs site; `possession`
|
|
8
|
+
* reaches customers only inside the image they already run. PUBLIC is the
|
|
9
|
+
* default and no page is special-cased -- a candid limitations page is a trust
|
|
10
|
+
* asset, and hiding the honest page is an odd signal to an evaluator (fleet
|
|
11
|
+
* review 03 open question 3). Turnkey privacy is a repo/bundle-level
|
|
12
|
+
* guarantee, never this field. */
|
|
13
|
+
export type PageVisibility = "public" | "possession";
|
|
7
14
|
export type ManualPage = {
|
|
8
15
|
id: string;
|
|
9
16
|
nav: string;
|
|
@@ -14,6 +21,8 @@ export type ManualPage = {
|
|
|
14
21
|
steps: Step[];
|
|
15
22
|
links: string[];
|
|
16
23
|
thin?: boolean;
|
|
24
|
+
/** Overrides the bundle's visibility for this page alone. */
|
|
25
|
+
visibility?: PageVisibility;
|
|
17
26
|
};
|
|
18
27
|
export interface ManualOverview {
|
|
19
28
|
/** The overview <h1>. */
|
|
@@ -50,6 +59,8 @@ export interface ManualDocument {
|
|
|
50
59
|
nav: string;
|
|
51
60
|
title: string;
|
|
52
61
|
markdown: string;
|
|
62
|
+
/** Overrides the bundle's visibility for this page alone. */
|
|
63
|
+
visibility?: PageVisibility;
|
|
53
64
|
}
|
|
54
65
|
export interface ManualSpec {
|
|
55
66
|
/** Sidebar wordmark + document brand. */
|
package/doc-guide/bundle.d.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
import { type BuildManualResult, type ManualLink, type ManualSpec, type Provenance } from "./build-manual.js";
|
|
2
|
-
export
|
|
1
|
+
import { type BuildManualResult, type ManualLink, type ManualSpec, type PageVisibility, type Provenance } from "./build-manual.js";
|
|
2
|
+
export type { PageVisibility };
|
|
3
|
+
export declare const BUNDLE_SCHEMA_VERSION = 2;
|
|
3
4
|
export interface BundlePageEntry {
|
|
4
5
|
id: string;
|
|
5
6
|
nav: string;
|
|
@@ -7,11 +8,15 @@ export interface BundlePageEntry {
|
|
|
7
8
|
kind: "overview" | "fn" | "ex" | "doc";
|
|
8
9
|
/** Relative to the bundle directory. */
|
|
9
10
|
file: string;
|
|
11
|
+
/** Resolved: the page's own value, else the bundle's. */
|
|
12
|
+
visibility: PageVisibility;
|
|
10
13
|
}
|
|
11
14
|
export interface BundleManifest {
|
|
12
15
|
schemaVersion: number;
|
|
13
16
|
brand: string;
|
|
14
17
|
title: string;
|
|
18
|
+
/** The default every page inherits when it declares none. */
|
|
19
|
+
visibility: PageVisibility;
|
|
15
20
|
provenance: Provenance;
|
|
16
21
|
links: ManualLink[];
|
|
17
22
|
pages: BundlePageEntry[];
|
|
@@ -29,9 +34,16 @@ export interface BuildBundleOptions {
|
|
|
29
34
|
/** Where the bundle is written; created if absent. */
|
|
30
35
|
outDir: string;
|
|
31
36
|
provenance?: Provenance;
|
|
37
|
+
/** Default visibility for every page that declares none. Public: turnkey
|
|
38
|
+
* privacy is enforced at the repo and bundle level, not page by page. */
|
|
39
|
+
visibility?: PageVisibility;
|
|
32
40
|
}
|
|
33
41
|
export interface BuildBundleResult extends BuildManualResult {
|
|
34
42
|
manifest: BundleManifest;
|
|
35
43
|
outDir: string;
|
|
36
44
|
}
|
|
37
45
|
export declare function buildBundle(spec: ManualSpec, opts: BuildBundleOptions): BuildBundleResult;
|
|
46
|
+
/** What the public fetcher may stage. A page entry from a version-1 bundle
|
|
47
|
+
* carries no visibility at all; that reads as `public`, so an older bundle
|
|
48
|
+
* stages exactly as it did before this field existed. */
|
|
49
|
+
export declare function publicPages(manifest: BundleManifest): BundlePageEntry[];
|
package/doc-guide/bundle.js
CHANGED
|
@@ -13,10 +13,14 @@
|
|
|
13
13
|
import { mkdirSync, writeFileSync } from "node:fs";
|
|
14
14
|
import { join } from "node:path";
|
|
15
15
|
import { buildManual, } from "./build-manual.js";
|
|
16
|
-
|
|
16
|
+
// 2: every page entry carries a `visibility`, and the manifest carries the
|
|
17
|
+
// bundle's own. A version-1 bundle has neither; `publicPages` reads an absent
|
|
18
|
+
// value as `public`, so an old bundle stages exactly as it did before.
|
|
19
|
+
export const BUNDLE_SCHEMA_VERSION = 2;
|
|
17
20
|
const yamlString = (s) => JSON.stringify(s);
|
|
18
21
|
export function buildBundle(spec, opts) {
|
|
19
22
|
const { docsRoot, outDir } = opts;
|
|
23
|
+
const visibility = opts.visibility ?? "public";
|
|
20
24
|
const provenance = { builtAt: new Date().toISOString(), ...opts.provenance };
|
|
21
25
|
mkdirSync(join(outDir, "pages"), { recursive: true });
|
|
22
26
|
const manual = buildManual(spec, {
|
|
@@ -78,9 +82,23 @@ export function buildBundle(spec, opts) {
|
|
|
78
82
|
].join("\n");
|
|
79
83
|
const documentMarkdown = (d) => ["---", `title: ${yamlString(d.title)}`, `nav: ${yamlString(d.nav)}`, "kind: doc", "---", "", d.markdown].join("\n");
|
|
80
84
|
const pages = [
|
|
81
|
-
{ id: "overview", nav: "Overview", title: ov.headline, kind: "overview", file: "pages/overview.md" },
|
|
82
|
-
...all.map((p) => ({
|
|
83
|
-
|
|
85
|
+
{ id: "overview", nav: "Overview", title: ov.headline, kind: "overview", file: "pages/overview.md", visibility },
|
|
86
|
+
...all.map((p) => ({
|
|
87
|
+
id: p.id,
|
|
88
|
+
nav: p.nav,
|
|
89
|
+
title: p.title,
|
|
90
|
+
kind: p.kind,
|
|
91
|
+
file: `pages/${p.id}.md`,
|
|
92
|
+
visibility: p.visibility ?? visibility,
|
|
93
|
+
})),
|
|
94
|
+
...docs.map((d) => ({
|
|
95
|
+
id: d.id,
|
|
96
|
+
nav: d.nav,
|
|
97
|
+
title: d.title,
|
|
98
|
+
kind: "doc",
|
|
99
|
+
file: `pages/${d.id}.md`,
|
|
100
|
+
visibility: d.visibility ?? visibility,
|
|
101
|
+
})),
|
|
84
102
|
];
|
|
85
103
|
writeFileSync(join(outDir, "pages/overview.md"), overviewMarkdown);
|
|
86
104
|
for (const p of all)
|
|
@@ -94,6 +112,7 @@ export function buildBundle(spec, opts) {
|
|
|
94
112
|
schemaVersion: BUNDLE_SCHEMA_VERSION,
|
|
95
113
|
brand: spec.brand,
|
|
96
114
|
title: spec.title,
|
|
115
|
+
visibility,
|
|
97
116
|
provenance,
|
|
98
117
|
links: spec.links ?? [],
|
|
99
118
|
pages,
|
|
@@ -103,3 +122,9 @@ export function buildBundle(spec, opts) {
|
|
|
103
122
|
writeFileSync(join(outDir, "bundle.json"), `${JSON.stringify(manifest, null, 2)}\n`);
|
|
104
123
|
return { ...manual, manifest, outDir };
|
|
105
124
|
}
|
|
125
|
+
/** What the public fetcher may stage. A page entry from a version-1 bundle
|
|
126
|
+
* carries no visibility at all; that reads as `public`, so an older bundle
|
|
127
|
+
* stages exactly as it did before this field existed. */
|
|
128
|
+
export function publicPages(manifest) {
|
|
129
|
+
return manifest.pages.filter((p) => (p.visibility ?? "public") === "public");
|
|
130
|
+
}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
#!/usr/bin/env bun
|
|
2
|
+
/**
|
|
3
|
+
* How a product publishes its docs bundle for the public plane to fetch
|
|
4
|
+
* (fleet review 03 s3.5 slice 6, product half). Used by
|
|
5
|
+
* conventions/publish-docs.yml, which every public product repo copies
|
|
6
|
+
* verbatim.
|
|
7
|
+
*
|
|
8
|
+
* Versioned assets behind a moving pointer, all on the ONE `docs-latest`
|
|
9
|
+
* release. A release per commit would leave hundreds of prereleases on each
|
|
10
|
+
* product repo; a single clobbered asset would leave nothing to roll back to.
|
|
11
|
+
* Only the pointer moves, so a rollback is a pointer edit and the ctl site
|
|
12
|
+
* never reads an asset being overwritten underneath it.
|
|
13
|
+
*
|
|
14
|
+
* `manual.html` stays on the same release, clobbered as before: it is what the
|
|
15
|
+
* current ctl fetcher mounts at /products/<key>/, and it keeps working
|
|
16
|
+
* unchanged while the bundle ingestion is built.
|
|
17
|
+
*/
|
|
18
|
+
export interface BundlePointer {
|
|
19
|
+
/** Short product commit — the bundle's identity. */
|
|
20
|
+
version: string;
|
|
21
|
+
/** The release asset holding that bundle. */
|
|
22
|
+
asset: string;
|
|
23
|
+
/** Full product commit the bundle was built from. */
|
|
24
|
+
sha: string;
|
|
25
|
+
runId?: string;
|
|
26
|
+
builtAt: string;
|
|
27
|
+
}
|
|
28
|
+
export declare const DOCS_RELEASE_TAG = "docs-latest";
|
|
29
|
+
export declare const POINTER_ASSET = "latest.json";
|
|
30
|
+
export declare function bundleVersion(sha: string): string;
|
|
31
|
+
export declare function bundleAssetName(version: string): string;
|
|
32
|
+
export declare function pointerJson(p: BundlePointer): string;
|
|
33
|
+
export declare function parsePointer(json: string): BundlePointer;
|
|
34
|
+
/** Which versioned bundles to delete, newest `keep` kept. Only ever names
|
|
35
|
+
* `bundle-<version>.tar.gz` assets — `manual.html` and the pointer are the
|
|
36
|
+
* release's fixtures — and never the one the pointer currently names, which
|
|
37
|
+
* would leave the site fetching a 404. */
|
|
38
|
+
export declare function assetsToPrune(assets: readonly {
|
|
39
|
+
name: string;
|
|
40
|
+
createdAt: string;
|
|
41
|
+
}[], keep: number, current: string): string[];
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
#!/usr/bin/env bun
|
|
2
|
+
/**
|
|
3
|
+
* How a product publishes its docs bundle for the public plane to fetch
|
|
4
|
+
* (fleet review 03 s3.5 slice 6, product half). Used by
|
|
5
|
+
* conventions/publish-docs.yml, which every public product repo copies
|
|
6
|
+
* verbatim.
|
|
7
|
+
*
|
|
8
|
+
* Versioned assets behind a moving pointer, all on the ONE `docs-latest`
|
|
9
|
+
* release. A release per commit would leave hundreds of prereleases on each
|
|
10
|
+
* product repo; a single clobbered asset would leave nothing to roll back to.
|
|
11
|
+
* Only the pointer moves, so a rollback is a pointer edit and the ctl site
|
|
12
|
+
* never reads an asset being overwritten underneath it.
|
|
13
|
+
*
|
|
14
|
+
* `manual.html` stays on the same release, clobbered as before: it is what the
|
|
15
|
+
* current ctl fetcher mounts at /products/<key>/, and it keeps working
|
|
16
|
+
* unchanged while the bundle ingestion is built.
|
|
17
|
+
*/
|
|
18
|
+
export const DOCS_RELEASE_TAG = "docs-latest";
|
|
19
|
+
export const POINTER_ASSET = "latest.json";
|
|
20
|
+
const VERSION_LENGTH = 12;
|
|
21
|
+
const BUNDLE_ASSET_RE = /^bundle-[0-9a-f]{12}\.tar\.gz$/;
|
|
22
|
+
export function bundleVersion(sha) {
|
|
23
|
+
return sha.slice(0, VERSION_LENGTH);
|
|
24
|
+
}
|
|
25
|
+
export function bundleAssetName(version) {
|
|
26
|
+
return `bundle-${version}.tar.gz`;
|
|
27
|
+
}
|
|
28
|
+
export function pointerJson(p) {
|
|
29
|
+
return `${JSON.stringify(p, null, 2)}\n`;
|
|
30
|
+
}
|
|
31
|
+
export function parsePointer(json) {
|
|
32
|
+
const parsed = JSON.parse(json);
|
|
33
|
+
if (typeof parsed !== "object" || parsed === null || Array.isArray(parsed))
|
|
34
|
+
throw new Error("docs pointer: expected an object");
|
|
35
|
+
const p = parsed;
|
|
36
|
+
for (const field of ["version", "asset", "sha", "builtAt"])
|
|
37
|
+
if (typeof p[field] !== "string")
|
|
38
|
+
throw new Error(`docs pointer: missing ${field}`);
|
|
39
|
+
return {
|
|
40
|
+
version: p.version,
|
|
41
|
+
asset: p.asset,
|
|
42
|
+
sha: p.sha,
|
|
43
|
+
builtAt: p.builtAt,
|
|
44
|
+
...(p.runId === undefined ? {} : { runId: p.runId }),
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
/** Which versioned bundles to delete, newest `keep` kept. Only ever names
|
|
48
|
+
* `bundle-<version>.tar.gz` assets — `manual.html` and the pointer are the
|
|
49
|
+
* release's fixtures — and never the one the pointer currently names, which
|
|
50
|
+
* would leave the site fetching a 404. */
|
|
51
|
+
export function assetsToPrune(assets, keep, current) {
|
|
52
|
+
const bundles = assets
|
|
53
|
+
.filter((a) => BUNDLE_ASSET_RE.test(a.name) && a.name !== current)
|
|
54
|
+
.sort((a, b) => b.createdAt.localeCompare(a.createdAt));
|
|
55
|
+
// The current bundle is always kept and counts towards `keep`, so only
|
|
56
|
+
// `keep - 1` of the older ones survive.
|
|
57
|
+
return bundles
|
|
58
|
+
.slice(Math.max(0, keep - 1))
|
|
59
|
+
.map((a) => a.name)
|
|
60
|
+
.sort();
|
|
61
|
+
}
|
|
62
|
+
if (import.meta.main) {
|
|
63
|
+
const argv = process.argv.slice(2);
|
|
64
|
+
const [cmd, a, b] = argv;
|
|
65
|
+
const flag = (name) => {
|
|
66
|
+
const i = argv.indexOf(`--${name}`);
|
|
67
|
+
return i === -1 ? undefined : argv[i + 1];
|
|
68
|
+
};
|
|
69
|
+
if (cmd === "version" && a) {
|
|
70
|
+
console.log(bundleVersion(a));
|
|
71
|
+
}
|
|
72
|
+
else if (cmd === "asset" && a) {
|
|
73
|
+
console.log(bundleAssetName(a));
|
|
74
|
+
}
|
|
75
|
+
else if (cmd === "pointer") {
|
|
76
|
+
const version = flag("version");
|
|
77
|
+
const sha = flag("sha");
|
|
78
|
+
const builtAt = flag("built-at");
|
|
79
|
+
if (!version || !sha || !builtAt) {
|
|
80
|
+
console.error("docs-release pointer: --version, --sha and --built-at are required");
|
|
81
|
+
process.exit(2);
|
|
82
|
+
}
|
|
83
|
+
const runId = flag("run-id");
|
|
84
|
+
process.stdout.write(pointerJson({
|
|
85
|
+
version,
|
|
86
|
+
asset: bundleAssetName(version),
|
|
87
|
+
sha,
|
|
88
|
+
builtAt,
|
|
89
|
+
...(runId ? { runId } : {}),
|
|
90
|
+
}));
|
|
91
|
+
}
|
|
92
|
+
else if (cmd === "prune" && a && b) {
|
|
93
|
+
const chunks = [];
|
|
94
|
+
for await (const c of process.stdin)
|
|
95
|
+
chunks.push(c);
|
|
96
|
+
const assets = JSON.parse(Buffer.concat(chunks).toString("utf8"));
|
|
97
|
+
for (const name of assetsToPrune(assets, Number(a), b))
|
|
98
|
+
console.log(name);
|
|
99
|
+
}
|
|
100
|
+
else {
|
|
101
|
+
console.error("usage: docs-release.ts version <sha> | asset <version> | pointer --version <v> --sha <sha> [--run-id <id>] --built-at <iso> | prune <keep> <currentAsset>");
|
|
102
|
+
process.exit(2);
|
|
103
|
+
}
|
|
104
|
+
}
|
package/package.json
CHANGED
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@norskvideo/ctl-dev-kit",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.82",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"exports": {
|
|
6
6
|
"./create-product": "./create-product/create-product.ts",
|
|
7
7
|
"./doc-guide": "./doc-guide/doc-guide.js",
|
|
8
8
|
"./doc-guide/build-manual": "./doc-guide/build-manual.js",
|
|
9
9
|
"./doc-guide/bundle": "./doc-guide/bundle.js",
|
|
10
|
+
"./doc-guide/docs-release": "./doc-guide/docs-release.js",
|
|
10
11
|
"./doc-guide/guides-config": "./doc-guide/guides-config.js",
|
|
11
12
|
"./doc-guide/instance-proxy": "./doc-guide/instance-proxy.js",
|
|
12
13
|
"./doc-guide/live-browser": "./doc-guide/live-browser.js",
|