Files
pnpm/.github/scripts/prepare-docs-sync.test.mjs
T
Zoltan Kochan 07839df5c3 docs: move product documentation beside its implementation (#16385)
* docs: move website documentation into the pnpm repository

* docs: keep v11 and v12 documentation beside their implementations

* docs(pnpr): keep registry documentation beside its implementation

* ci: classify product documentation as documentation changes

* test: cover product documentation in Rust CI exclusions

* ci: isolate documentation publishing and support manual sync

* test: make dependency status fixture timestamps deterministic
2026-09-29 15:56:43 +02:00

121 lines
5.9 KiB
JavaScript

import assert from 'node:assert/strict'
import { execFileSync } from 'node:child_process'
import { mkdtempSync, mkdirSync, rmSync, writeFileSync } from 'node:fs'
import os from 'node:os'
import path from 'node:path'
import { test } from 'node:test'
import { prepareDocsSync } from './prepare-docs-sync.mjs'
function fixture (t, tag = 'v12.8.2') {
const repo = mkdtempSync(path.join(os.tmpdir(), 'pnpm-docs-release-'))
t.after(() => rmSync(repo, { recursive: true, force: true }))
const git = (...args) => execFileSync('git', args, { cwd: repo, encoding: 'utf8', stdio: ['ignore', 'pipe', 'pipe'] }).trim()
const version = tag.startsWith('pnpr@') ? tag.slice(5) : tag.slice(1)
for (const [product, current] of [['pnpm/npm/pnpm', '12.8.2'], ['pnpm11/pnpm', '11.28.2'], ['pnpr/npm/pnpr', '0.1.0-alpha.14']]) {
mkdirSync(path.join(repo, product), { recursive: true })
const productVersion = version.split('.')[0] === current.split('.')[0] ? version : current
writeFileSync(path.join(repo, product, 'package.json'), JSON.stringify({ version: productVersion }))
}
git('init', '--quiet')
git('config', 'commit.gpgsign', 'false')
git('config', 'user.name', 'Test')
git('config', 'user.email', 'test@example.com')
git('add', '.')
git('commit', '--quiet', '-m', 'chore: release')
git('update-ref', `refs/tags/${tag}`, 'HEAD')
const sha = git('rev-parse', 'HEAD')
let verified = false
const options = {
eventName: 'workflow_run',
event: { workflow_run: { head_branch: tag, head_sha: sha } },
git: (...args) => {
if (args[0] === 'verify-tag') { verified = true; return '' }
return git(...args)
},
publicationState: spec => {
assert.equal(verified, true)
assert.equal(spec, `${tag.startsWith('pnpr@') ? '@pnpm/pnpr' : 'pnpm'}@${version}`)
return 'published'
},
}
return { repo, git, sha, options }
}
test('selects only the signed and published release snapshot', t => {
const f = fixture(t)
assert.deepEqual(prepareDocsSync(f.options), {
publish: true, line: '12.x', version: '12.8.2', release_commit: f.sha, docs_commit: f.sha,
})
assert.throws(() => prepareDocsSync({ ...f.options, publicationState: () => 'missing' }), /not been published/)
assert.throws(() => prepareDocsSync({ ...f.options, git: (...args) => args[0] === 'verify-tag' ? f.git(...args) : f.options.git(...args) }))
const event = { workflow_run: { ...f.options.event.workflow_run, head_sha: 'a'.repeat(40) } }
assert.throws(() => prepareDocsSync({ ...f.options, event }), /does not match/)
})
test('ignores verification runs and releases outside stable v11 and v12', () => {
assert.equal(prepareDocsSync({ eventName: 'workflow_run', event: { workflow_run: { head_branch: 'main' } } }), undefined)
assert.equal(prepareDocsSync({ eventName: 'workflow_dispatch', releaseTag: 'v12.9.0-beta.1' }), undefined)
for (const tag of ['v10.30.0', 'v13.0.0']) {
assert.equal(prepareDocsSync({ eventName: 'workflow_run', event: { workflow_run: { head_branch: tag } } }), undefined)
assert.throws(() => prepareDocsSync({ eventName: 'workflow_dispatch', releaseTag: tag }), /v11 and v12/)
}
})
test('manual corrections must contain only the selected version docs', t => {
const f = fixture(t)
mkdirSync(path.join(f.repo, 'pnpm/docs'), { recursive: true })
writeFileSync(path.join(f.repo, 'pnpm/docs/install.md'), 'correction')
f.git('add', '.')
f.git('commit', '--quiet', '-m', 'docs: correction')
const options = { ...f.options, eventName: 'workflow_dispatch', releaseTag: 'v12.8.2', docsRef: f.git('rev-parse', 'HEAD') }
assert.equal(prepareDocsSync(options).docs_commit, options.docsRef)
assert.throws(() => prepareDocsSync({ ...options, docsRef: 'main' }), /full commit SHA/)
writeFileSync(path.join(f.repo, 'unreleased.js'), 'new behavior')
f.git('add', '.')
f.git('commit', '--quiet', '-m', 'feat: unreleased behavior')
assert.throws(() => prepareDocsSync({ ...options, docsRef: f.git('rev-parse', 'HEAD') }), /change only/)
})
test('v11 corrections use the TypeScript product documentation', t => {
const f = fixture(t, 'v11.28.3')
mkdirSync(path.join(f.repo, 'pnpm11/docs'), { recursive: true })
writeFileSync(path.join(f.repo, 'pnpm11/docs/install.md'), 'correction')
f.git('add', '.')
f.git('commit', '--quiet', '-m', 'docs: v11 correction')
const result = prepareDocsSync({ ...f.options, eventName: 'workflow_dispatch', releaseTag: 'v11.28.3', docsRef: f.git('rev-parse', 'HEAD') })
assert.equal(result.line, '11.x')
})
test('pnpr alpha releases and corrections select only the registry documentation', t => {
const f = fixture(t, 'pnpr@0.1.0-alpha.15')
assert.equal(prepareDocsSync(f.options).line, 'pnpr')
mkdirSync(path.join(f.repo, 'pnpr/docs'), { recursive: true })
writeFileSync(path.join(f.repo, 'pnpr/docs/installation.md'), 'correction')
f.git('add', '.')
f.git('commit', '--quiet', '-m', 'docs: registry correction')
const result = prepareDocsSync({ ...f.options, eventName: 'workflow_dispatch', releaseTag: 'pnpr@0.1.0-alpha.15', docsRef: f.git('rev-parse', 'HEAD') })
assert.equal(result.line, 'pnpr')
assert.equal(result.docs_commit, f.git('rev-parse', 'HEAD'))
})
test('manual publication from main needs no release or npm publication', t => {
const f = fixture(t)
assert.deepEqual(prepareDocsSync({
eventName: 'workflow_dispatch',
githubRef: 'refs/heads/main',
git: f.git,
publicationState: () => assert.fail('main publication must not query npm'),
}), { publish: true, main_sync: true, docs_commit: f.sha })
})
test('manual publication without a release is restricted to main and its checked-out snapshot', () => {
for (const githubRef of [undefined, 'refs/heads/feature', 'refs/tags/v12.8.2']) {
assert.throws(() => prepareDocsSync({ eventName: 'workflow_dispatch', githubRef }), /must run from main/)
}
assert.throws(() => prepareDocsSync({
eventName: 'workflow_dispatch', githubRef: 'refs/heads/main', docsRef: 'a'.repeat(40),
}), /docs_commit requires a release_tag/)
})