Files
pnpm/.github/scripts/prepare-docs-sync.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

68 lines
3.7 KiB
JavaScript

import { execFileSync } from 'node:child_process'
import { appendFileSync, readFileSync } from 'node:fs'
import path from 'node:path'
import { fileURLToPath } from 'node:url'
export function prepareDocsSync ({ event, eventName, githubRef, releaseTag, docsRef: correction, git = runGit, publicationState = readPublicationState }) {
if (eventName === 'workflow_dispatch' && !releaseTag) {
if (githubRef !== 'refs/heads/main') throw new Error('Manual publication without a release tag must run from main')
if (correction) throw new Error('docs_commit requires a release_tag')
return { publish: true, main_sync: true, docs_commit: git('rev-parse', 'HEAD') }
}
const automatic = eventName === 'workflow_run'
const tag = automatic ? event.workflow_run.head_branch : releaseTag
const match = /^(v|pnpr@)(\d+\.\d+\.\d+(?:-[0-9A-Za-z.-]+)?)$/.exec(tag ?? '')
if (!match) {
if (automatic) return undefined
throw new Error('Expected a pnpm or pnpr release tag such as v12.8.2 or pnpr@0.1.0-alpha.15')
}
const [, prefix, version] = match
if (prefix === 'v' && !['11', '12'].includes(version.split('.')[0])) {
if (automatic) return undefined
throw new Error('Only pnpm v11 and v12 documentation is maintained here')
}
if (prefix === 'v' && version.includes('-')) return undefined
const releaseCommit = git('rev-parse', '--verify', `refs/tags/${tag}^{commit}`)
if (automatic && releaseCommit !== event.workflow_run.head_sha) throw new Error('Release tag does not match the completed workflow')
git('verify-tag', tag)
const manifests = prefix === 'pnpr@' ? ['pnpr/npm/pnpr/package.json'] : ['pnpm/npm/pnpm/package.json', 'pnpm11/pnpm/package.json']
if (!manifests.some(file => JSON.parse(git('show', `${releaseCommit}:${file}`)).version === version)) {
throw new Error(`Tag ${tag} does not match a committed product version`)
}
const packageName = prefix === 'pnpr@' ? '@pnpm/pnpr' : 'pnpm'
const publication = publicationState(`${packageName}@${version}`)
if (publication !== 'published') throw new Error(`${packageName}@${version} has not been published`)
const line = prefix === 'pnpr@' ? 'pnpr' : `${version.split('.')[0]}.x`
const docsRef = automatic ? releaseCommit : correction || releaseCommit
if (!/^[a-f0-9]{40}$/.test(docsRef)) throw new Error('Documentation corrections require a full commit SHA')
const docsCommit = git('rev-parse', '--verify', `${docsRef}^{commit}`)
if (docsCommit !== releaseCommit) {
git('merge-base', '--is-ancestor', releaseCommit, docsCommit)
const docsPath = line === 'pnpr' ? 'pnpr/docs' : line === '11.x' ? 'pnpm11/docs' : 'pnpm/docs'
const changed = git('diff', '--name-only', releaseCommit, docsCommit).split('\n').filter(Boolean)
if (!changed.length || changed.some(file => !file.startsWith(`${docsPath}/`))) {
throw new Error(`Corrections must be based on ${tag} and change only ${docsPath}/`)
}
}
return { publish: true, line, version, release_commit: releaseCommit, docs_commit: docsCommit }
}
function readPublicationState (spec) {
return execFileSync('bash', ['.github/scripts/npm-package-publication-state.sh', spec], { encoding: 'utf8' }).trim()
}
function runGit (...args) {
return execFileSync('git', args, { encoding: 'utf8', stdio: ['ignore', 'pipe', 'pipe'] }).trim()
}
if (process.argv[1] && path.resolve(process.argv[1]) === fileURLToPath(import.meta.url)) {
const result = prepareDocsSync({
event: JSON.parse(readFileSync(process.env.GITHUB_EVENT_PATH, 'utf8')),
eventName: process.env.GITHUB_EVENT_NAME,
githubRef: process.env.GITHUB_REF,
releaseTag: process.env.RELEASE_TAG,
docsRef: process.env.DOCS_COMMIT,
})
if (result) appendFileSync(process.env.GITHUB_OUTPUT, Object.entries(result).map(([key, value]) => `${key}=${value}\n`).join(''))
}