aboutsummaryrefslogtreecommitdiff
path: root/website/scripts
diff options
context:
space:
mode:
Diffstat (limited to 'website/scripts')
-rw-r--r--website/scripts/check-built-docs.mjs4
-rw-r--r--website/scripts/docs-snapshot.mjs4
-rw-r--r--website/scripts/docs-versions.integration.test.ts75
-rw-r--r--website/scripts/docs-versions.mjs51
-rw-r--r--website/scripts/prepare-docs.mjs22
5 files changed, 100 insertions, 56 deletions
diff --git a/website/scripts/check-built-docs.mjs b/website/scripts/check-built-docs.mjs
index 8841bf74..66e904e4 100644
--- a/website/scripts/check-built-docs.mjs
+++ b/website/scripts/check-built-docs.mjs
@@ -48,7 +48,7 @@ assertIncludes(preview, 'name="robots" content="noindex, nofollow"');
assertIncludes(archived, `data-pagefind-filter="version[content]" content="${versions.current}"`);
assertIncludes(archived, 'name="robots" content="noindex, nofollow"');
if (archived.includes(`This page documents Herdr ${versions.current}`)) {
- throw new Error('the current immutable snapshot must not be labeled as outdated');
+ throw new Error('the current documentation version must not be labeled as outdated');
}
const versionSelect = stable.match(/<select[^>]*aria-label="Documentation version"[^>]*>([\s\S]*?)<\/select>/)?.[1];
if (!versionSelect) throw new Error('stable docs are missing the version selector');
@@ -68,7 +68,7 @@ if (previous) {
const sitemap = await readFile(resolve(distDir, 'sitemap-0.xml'), 'utf8');
assertIncludes(sitemap, 'https://herdr.dev/docs/');
if (nonCanonicalDocsUrl.test(sitemap)) {
- throw new Error('preview or immutable documentation URLs must not appear in the sitemap');
+ throw new Error('preview or versioned documentation URLs must not appear in the sitemap');
}
const build = await inspectFiles(distDir);
diff --git a/website/scripts/docs-snapshot.mjs b/website/scripts/docs-snapshot.mjs
index b85557a1..e9eaf92c 100644
--- a/website/scripts/docs-snapshot.mjs
+++ b/website/scripts/docs-snapshot.mjs
@@ -73,7 +73,7 @@ export async function compareGitTree(git, ref, sourceRoot, snapshotRoot) {
assertRelativePath(relativePath, entry.path);
expected.set(relativePath, entry);
}
- const actualPaths = await listSnapshotPaths(snapshotRoot);
+ const actualPaths = await listDocumentationPaths(snapshotRoot);
const expectedPaths = [...expected.keys()].sort();
if (JSON.stringify(actualPaths) !== JSON.stringify(expectedPaths)) {
throw new Error(`${snapshotRoot} file list differs from ${ref}:${sourceRoot}`);
@@ -89,7 +89,7 @@ export async function compareGitTree(git, ref, sourceRoot, snapshotRoot) {
}
}
-async function listSnapshotPaths(root) {
+export async function listDocumentationPaths(root) {
const paths = [];
async function walk(directory) {
for (const entry of await readdir(directory, { withFileTypes: true })) {
diff --git a/website/scripts/docs-versions.integration.test.ts b/website/scripts/docs-versions.integration.test.ts
index 5e2d36a5..052d9ca2 100644
--- a/website/scripts/docs-versions.integration.test.ts
+++ b/website/scripts/docs-versions.integration.test.ts
@@ -1,6 +1,6 @@
import { afterEach, describe, expect, test } from 'bun:test';
import { execFileSync } from 'node:child_process';
-import { mkdtemp, mkdir, readFile, rm, writeFile } from 'node:fs/promises';
+import { mkdtemp, mkdir, readFile, rm, symlink, writeFile } from 'node:fs/promises';
import { join, resolve } from 'node:path';
import { tmpdir } from 'node:os';
@@ -21,7 +21,8 @@ describe('documentation release publishing', () => {
await write(root, 'website/latest.json', '{"version":"0.9.0"}\n');
await write(root, 'README.md', 'stable readme\n');
await write(root, 'README.zh-CN.md', 'stable readme zh-cn\n');
- await write(root, 'docs/next/website/src/content/docs/index.mdx', 'next docs\n');
+ const nextDocs = '---\ntitle: Documentation\n---\n\nnext docs\n';
+ await write(root, 'docs/next/website/src/content/docs/index.mdx', nextDocs);
await write(root, 'docs/next/website/src/data/config-reference.json', '{"next":true}\n');
await write(root, 'docs/next/README.md', 'next readme\n');
await write(root, 'docs/next/README.zh-CN.md', 'next readme zh-cn\n');
@@ -40,7 +41,7 @@ describe('documentation release publishing', () => {
await expect(read(root, 'website/src/data/config-reference.json')).rejects.toThrow();
expect(await read(root, 'README.md')).toBe('next readme\n');
expect(await read(root, 'README.zh-CN.md')).toBe('next readme zh-cn\n');
- expect(await read(root, 'docs/versions/1.0.0/website/src/content/docs/index.mdx')).toBe('next docs\n');
+ expect(await read(root, 'docs/versions/1.0.0/website/src/content/docs/index.mdx')).toBe(nextDocs);
const manifest = JSON.parse(await read(root, 'docs/versions/manifest.json'));
expect(manifest.current).toBe('1.0.0');
@@ -65,7 +66,19 @@ describe('documentation release publishing', () => {
`${JSON.stringify({ build_id: 'preview-test', commit: previewCommit })}\n`,
);
runPrepare(root);
- expect(await read(root, 'website/src/content/docs/index.mdx')).toBe('next docs\n');
+ const stableDocs = await read(root, 'website/src/content/docs/index.mdx');
+ expect(stableDocs).toContain('next docs');
+ expect(stableDocs).toContain(
+ 'editUrl: https://github.com/herdrdev/herdr/blob/master/docs/versions/1.0.0/website/src/content/docs/index.mdx',
+ );
+ const versionedDocs = await read(
+ root,
+ 'website/src/content/docs/_versions/1.0.0/index.mdx',
+ );
+ expect(versionedDocs).toContain('next docs');
+ expect(versionedDocs).toContain(
+ 'editUrl: https://github.com/herdrdev/herdr/blob/master/docs/versions/1.0.0/website/src/content/docs/index.mdx',
+ );
expect(await read(root, 'website/src/content/docs/preview/index.mdx')).toContain(
'Preview build `preview-test`',
);
@@ -74,10 +87,36 @@ describe('documentation release publishing', () => {
await write(root, 'website/latest.json', '{"version":"1.0.0"}\n');
runScript(root, ['check']);
+ const correctedDocs = '---\ntitle: Documentation\n---\n\ncorrected docs\n';
+ await write(
+ root,
+ 'docs/versions/1.0.0/website/src/content/docs/index.mdx',
+ correctedDocs,
+ );
+ await write(
+ root,
+ 'docs/versions/1.0.0/website/src/data/config-reference.json',
+ '{"corrected":true}\n',
+ );
+ runScript(root, ['check']);
+
await write(root, 'README.md', 'post-release correction\n');
runScript(root, ['publish', 'v1.0.0']);
expect(await read(root, 'README.md')).toBe('post-release correction\n');
+ runPrepare(root);
+ expect(await read(root, 'website/src/content/docs/index.mdx')).toContain('corrected docs');
+ expect(await read(root, 'website/src/content/docs/_versions/1.0.0/index.mdx')).toContain(
+ 'corrected docs',
+ );
+ expect(await read(root, 'website/src/data/config-reference.json')).toBe(
+ '{"corrected":true}\n',
+ );
+ const versionReferences = JSON.parse(
+ await read(root, 'website/src/data/config-reference-versions.json'),
+ );
+ expect(versionReferences['1.0.0']).toEqual({ corrected: true });
+
runScript(root, ['publish', 'v0.9.0']);
const archivedManifest = JSON.parse(await read(root, 'docs/versions/manifest.json'));
expect(archivedManifest.current).toBe('1.0.0');
@@ -85,6 +124,34 @@ describe('documentation release publishing', () => {
expect(await read(root, 'README.md')).toBe('post-release correction\n');
runScript(root, ['check']);
+ const correctedArchivedDocs = '---\ntitle: Documentation\n---\n\ncorrected archived docs\n';
+ await write(
+ root,
+ 'docs/versions/0.9.0/website/src/content/docs/index.mdx',
+ correctedArchivedDocs,
+ );
+ runScript(root, ['publish', 'v0.9.0']);
+ expect(await read(root, 'docs/versions/0.9.0/website/src/content/docs/index.mdx')).toBe(
+ correctedArchivedDocs,
+ );
+
+ const archivedDocsRoot = resolve(
+ root,
+ 'docs/versions/0.9.0/website/src/content/docs',
+ );
+ await rm(archivedDocsRoot, { recursive: true, force: true });
+ expect(() => runScript(root, ['check'])).toThrow();
+ await write(
+ root,
+ 'docs/versions/0.9.0/website/src/content/docs/index.mdx',
+ correctedArchivedDocs,
+ );
+ const linkedPage = resolve(archivedDocsRoot, 'linked.mdx');
+ await symlink('index.mdx', linkedPage);
+ expect(() => runScript(root, ['check'])).toThrow();
+ await rm(linkedPage);
+ runScript(root, ['check']);
+
delete archivedManifest.versions[0].commit;
await write(root, 'docs/versions/manifest.json', `${JSON.stringify(archivedManifest)}\n`);
expect(() => runScript(root, ['check'])).toThrow();
diff --git a/website/scripts/docs-versions.mjs b/website/scripts/docs-versions.mjs
index 30cb099d..0923d683 100644
--- a/website/scripts/docs-versions.mjs
+++ b/website/scripts/docs-versions.mjs
@@ -2,11 +2,11 @@ import { mkdir, readFile, rm, writeFile } from 'node:fs/promises';
import { dirname, resolve } from 'node:path';
import { fileURLToPath, pathToFileURL } from 'node:url';
import {
- compareGitTree,
createGit,
extractGitTree,
gitPathExists,
gitTreesEqual,
+ listDocumentationPaths,
resolveCommit,
} from './docs-snapshot.mjs';
@@ -167,38 +167,26 @@ export async function checkVersions() {
if (!['website/src/content/docs', 'docs/next/website/src/content/docs'].includes(entry.source)) {
throw new Error(`docs version ${entry.version} has unsupported source ${entry.source}`);
}
- const sourceRoot = entry.source;
- const snapshotRoot = resolve(versionsDir, entry.version, 'website/src/content/docs');
- await compareGitTree(git, entry.tag, sourceRoot, snapshotRoot);
- const referenceSource = sourceRoot.includes('docs/next/')
- ? 'docs/next/website/src/data/config-reference.json'
- : 'website/src/data/config-reference.json';
- const referenceSnapshot = resolve(
- versionsDir,
- entry.version,
- 'website/src/data/config-reference.json',
+ const versionRoot = resolve(versionsDir, entry.version, 'website');
+ const documentationPaths = await listDocumentationPaths(
+ resolve(versionRoot, 'src/content/docs'),
);
- if (gitPathExists(git, entry.tag, referenceSource)) {
- const actualReference = await readFile(referenceSnapshot);
- const taggedReference = git(['show', `${entry.tag}:${referenceSource}`], { binary: true });
- if (!actualReference.equals(taggedReference)) {
- throw new Error(`${entry.version} config reference differs from ${entry.tag}:${referenceSource}`);
- }
- } else {
- try {
- await readFile(referenceSnapshot);
- throw new Error(`${entry.version} has an unexpected config reference snapshot`);
- } catch (error) {
- if (error.code !== 'ENOENT') throw error;
- }
+ if (!documentationPaths.includes('index.md') && !documentationPaths.includes('index.mdx')) {
+ throw new Error(`docs version ${entry.version} has no root index`);
+ }
+
+ try {
+ JSON.parse(await readFile(resolve(versionRoot, 'src/data/config-reference.json'), 'utf8'));
+ } catch (error) {
+ if (error.code !== 'ENOENT') throw error;
}
}
if (!seen.has(manifest.current)) {
throw new Error(`current docs version ${manifest.current} has no snapshot`);
}
- process.stdout.write(`validated ${manifest.versions.length} documentation snapshots\n`);
+ process.stdout.write(`validated ${manifest.versions.length} documentation versions\n`);
}
export async function publishVersion(tag) {
@@ -217,8 +205,7 @@ export async function publishVersion(tag) {
if (!existing?.commit || existing.commit !== release.commit) {
throw new Error(`published documentation ${release.version} has mismatched commit provenance`);
}
- await compareGitTree(git, release.commit, existing.source, resolve(versionsDir, release.version, 'website/src/content/docs'));
- process.stdout.write(`documentation snapshot ${release.tag} is already published\n`);
+ process.stdout.write(`documentation ${release.tag} is already published\n`);
return;
}
if (manifest.current && compareVersions(release.version, manifest.current) < 0) {
@@ -229,13 +216,7 @@ export async function publishVersion(tag) {
if (existing.commit && existing.commit !== release.commit) {
throw new Error(`version ${release.version} has mismatched commit provenance`);
}
- await compareGitTree(
- git,
- release.commit,
- existing.source,
- resolve(versionsDir, release.version, 'website/src/content/docs'),
- );
- process.stdout.write(`documentation snapshot ${release.tag} is already archived\n`);
+ process.stdout.write(`documentation ${release.tag} is already archived\n`);
return;
}
const archived = await snapshotTag(tag, 'docs/next/website/src/content/docs');
@@ -251,7 +232,7 @@ export async function publishVersion(tag) {
return;
}
if (existing) {
- throw new Error(`version ${release.version} already has a documentation snapshot`);
+ throw new Error(`version ${release.version} already has published documentation`);
}
const metadata = await snapshotTag(tag, 'docs/next/website/src/content/docs');
diff --git a/website/scripts/prepare-docs.mjs b/website/scripts/prepare-docs.mjs
index a96e2c41..074ef36d 100644
--- a/website/scripts/prepare-docs.mjs
+++ b/website/scripts/prepare-docs.mjs
@@ -44,7 +44,6 @@ if (process.argv[2] === '--rewrite-preview-doc-fixture') {
rewriteVersionDocContent(Buffer.concat(chunks).toString('utf8'), {
version: process.argv[3] ?? '0.7.5',
tag: `v${process.argv[3] ?? '0.7.5'}`,
- sourceRoot: 'docs/next/website/src/content/docs',
relativePath: 'index.mdx',
}),
);
@@ -118,8 +117,8 @@ async function prepareDocs({ draft }) {
stableDocsDir,
(content, relativePath) =>
rewriteStableDocContent(content, {
+ version: currentEntry.version,
tag: currentEntry.tag,
- sourceRoot: currentEntry.source,
relativePath,
}),
);
@@ -162,7 +161,6 @@ async function prepareDocs({ draft }) {
rewriteVersionDocContent(content, {
version,
tag: entry.tag,
- sourceRoot: entry.source,
relativePath,
}),
);
@@ -269,24 +267,22 @@ export function rewritePreviewDocContent(
return insertPreviewNotice(withSourceLink, relativePath, { buildId, commit });
}
-export function rewriteStableDocContent(content, { tag, sourceRoot, relativePath }) {
+export function rewriteStableDocContent(content, { version, tag, relativePath }) {
const taggedContent = rewriteRepositoryLinks(content, tag);
- return setGeneratedEditUrl(
- taggedContent,
- `https://github.com/herdrdev/herdr/blob/${tag}/${sourceRoot}/${relativePath}`,
- );
+ return setGeneratedEditUrl(taggedContent, versionedDocSourceUrl(version, relativePath));
}
-export function rewriteVersionDocContent(content, { version, tag, sourceRoot, relativePath }) {
+export function rewriteVersionDocContent(content, { version, tag, relativePath }) {
const taggedContent = rewriteRepositoryLinks(
content.replaceAll('/docs/', `/docs/${version}/`),
tag,
);
const rewritten = rewriteRelativeDocPaths(taggedContent, 2);
- return setGeneratedEditUrl(
- rewritten,
- `https://github.com/herdrdev/herdr/blob/${tag}/${sourceRoot}/${relativePath}`,
- );
+ return setGeneratedEditUrl(rewritten, versionedDocSourceUrl(version, relativePath));
+}
+
+function versionedDocSourceUrl(version, relativePath) {
+ return `https://github.com/herdrdev/herdr/blob/master/docs/versions/${version}/website/src/content/docs/${relativePath}`;
}
function rewriteRepositoryLinks(content, ref) {