* 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
96 lines
5.9 KiB
JavaScript
96 lines
5.9 KiB
JavaScript
import assert from 'node:assert/strict'
|
|
import { execFileSync } from 'node:child_process'
|
|
import { mkdtempSync, mkdirSync, readFileSync, rmSync, writeFileSync } from 'node:fs'
|
|
import { tmpdir } from 'node:os'
|
|
import path from 'node:path'
|
|
import { test } from 'node:test'
|
|
import { determineTestScope } from './ts-test-scope.mjs'
|
|
|
|
test('PR scope stays pinned when main advances; global changes and missing bases run everything', () => {
|
|
const dir = mkdtempSync(path.join(tmpdir(), 'ci-scope-'))
|
|
const origin = path.join(dir, 'origin')
|
|
const checkout = path.join(dir, 'checkout')
|
|
const git = (cwd, ...args) => execFileSync('git', args, { cwd, encoding: 'utf8', stdio: ['ignore', 'pipe', 'pipe'] }).trim()
|
|
const commit = (cwd, file, content) => {
|
|
mkdirSync(path.dirname(path.join(cwd, file)), { recursive: true })
|
|
writeFileSync(path.join(cwd, file), content)
|
|
git(cwd, 'add', '.')
|
|
git(cwd, '-c', 'user.name=Test', '-c', 'user.email=test@example.invalid', '-c', 'commit.gpgsign=false', 'commit', '-m', 'test')
|
|
return git(cwd, 'rev-parse', 'HEAD')
|
|
}
|
|
try {
|
|
mkdirSync(origin)
|
|
git(origin, 'init', '-b', 'main')
|
|
commit(origin, 'pnpm11/example/src/index.ts', 'base')
|
|
const base = commit(origin, 'global-test-config.json', 'original config')
|
|
git(dir, 'clone', origin, checkout)
|
|
git(checkout, 'switch', '-c', 'pr')
|
|
commit(checkout, 'pnpr/docs/introduction.md', 'registry docs')
|
|
assert.equal(determineTestScope({ event: 'pull_request', base, cwd: checkout }).full_tests, 'false', 'registry docs alone do not require all TS tests')
|
|
git(checkout, 'reset', '--hard', 'HEAD^')
|
|
commit(checkout, 'pnpm11/example/src/index.ts', 'pr')
|
|
commit(origin, 'pnpm11/unrelated/src/index.ts', 'new main')
|
|
const scope = () => determineTestScope({ event: 'pull_request', base, cwd: checkout })
|
|
assert.equal(scope().full_tests, 'false')
|
|
assert.equal(git(checkout, 'rev-parse', 'origin/main'), base)
|
|
assert.equal(git(checkout, 'diff', '--name-only', 'origin/main', 'HEAD'), 'pnpm11/example/src/index.ts')
|
|
commit(checkout, '.changeset/fix-example.md', 'Release note')
|
|
assert.equal(scope().full_tests, 'false', 'TS code plus release notes remain affected')
|
|
commit(checkout, 'pnpm/crates/example/src/lib.rs', 'rust')
|
|
assert.equal(scope().full_tests, 'false', 'TS code plus pacquet sources remain affected')
|
|
for (const file of ['package.json', 'pnpm-lock.yaml', '.pnpmfile.cjs', 'pnpm-workspace.yaml', '__patches__/dependency.patch', '.github/scripts/new-helper.mjs', '.changeset/config.json', 'pnpr/crates/example/src/lib.rs', 'pnpr/.fixtures/packages/example/package.json', 'Cargo.lock']) {
|
|
commit(checkout, file, 'global input')
|
|
assert.equal(scope().full_tests, 'true', file)
|
|
git(checkout, 'reset', '--hard', 'HEAD^')
|
|
}
|
|
git(checkout, 'mv', 'global-test-config.json', 'pnpm11/example/moved-config.json')
|
|
git(checkout, '-c', 'user.name=Test', '-c', 'user.email=test@example.invalid', '-c', 'commit.gpgsign=false', 'commit', '-m', 'rename global config')
|
|
assert.equal(scope().full_tests, 'true', 'moving a global input into a package still affects all tests')
|
|
git(checkout, 'reset', '--hard', 'HEAD^')
|
|
git(checkout, 'rm', 'global-test-config.json')
|
|
git(checkout, '-c', 'user.name=Test', '-c', 'user.email=test@example.invalid', '-c', 'commit.gpgsign=false', 'commit', '-m', 'delete global config')
|
|
assert.equal(scope().full_tests, 'true', 'deleted global inputs still affect all tests')
|
|
assert.equal(determineTestScope({ event: 'pull_request', base: 'f'.repeat(40), cwd: checkout }).full_tests, 'true')
|
|
} finally {
|
|
rmSync(dir, { recursive: true, force: true })
|
|
}
|
|
})
|
|
|
|
test('merge queues, main, manual and unknown events cannot narrow tests', () => {
|
|
for (const event of ['merge_group', 'push', 'workflow_dispatch', 'unknown', undefined]) {
|
|
assert.equal(determineTestScope({ event, base: 'a'.repeat(40) }).full_tests, 'true')
|
|
}
|
|
for (const base of [undefined, '', 'main', '--upload-pack=evil', 'a'.repeat(39)]) {
|
|
assert.equal(determineTestScope({ event: 'pull_request', base }).full_tests, 'true')
|
|
}
|
|
})
|
|
|
|
test('Rust gate configuration keeps exclusions limited to approved documentation', () => {
|
|
const workflow = readFileSync(new URL('../workflows/pacquet-ci.yml', import.meta.url), 'utf8')
|
|
const filters = workflow.slice(workflow.indexOf(' predicate-quantifier:'), workflow.indexOf('\n test:'))
|
|
assert.match(filters, /predicate-quantifier: some-with-excludes/)
|
|
const patterns = filters.split(' rust:\n')[1].split('\n').map(line => line.match(/- '([^']+)'/)?.[1]).filter(Boolean)
|
|
const docs = filters.split(' docs:\n')[1].split(' rust:\n')[0].split('\n').map(line => line.match(/- '([^']+)'/)?.[1]).filter(Boolean)
|
|
assert.deepEqual(patterns.filter(pattern => pattern.startsWith('!')), [
|
|
'!pnpm/docs/**',
|
|
'!pnpr/docs/**',
|
|
'!pnpm/*.md',
|
|
'!pnpm/plans/*.md',
|
|
'!pnpm/scripts/*.md',
|
|
'!pnpm/crates/*/*.md',
|
|
'!pnpm/tasks/*/*.md',
|
|
'!pnpr/*.md',
|
|
'!pnpr/crates/*/*.md',
|
|
'!pnpr/docker/*.md',
|
|
'!pnpr/client/*.md',
|
|
])
|
|
// Markdown under pnpr/.fixtures ships inside registry fixtures.
|
|
const recursiveDocs = new Set(['!pnpm/docs/**', '!pnpr/docs/**'])
|
|
assert.ok(!patterns.some(pattern => pattern.startsWith('!') && pattern.includes('**') && !recursiveDocs.has(pattern)), 'recursive exclusions only cover product documentation')
|
|
for (const pattern of ['pnpm/**', 'pnpr/**', '.config/nextest.toml', 'fixtures/**', 'pnpm11/installing/deps-installer/test/fixtures/patch-pkg/**', 'pnpm11/deps/compliance/commands/test/sbom/fixtures/**']) {
|
|
assert.ok(patterns.includes(pattern), `required test input: ${pattern}`)
|
|
}
|
|
assert.deepEqual(docs, patterns.filter(pattern => pattern.startsWith('!')).map(pattern => pattern.slice(1)), 'docs covers every exclusion, so the spell check still runs')
|
|
assert.match(workflow.slice(workflow.indexOf('\n typos:'), workflow.indexOf('\n deny:')), /needs.changes.outputs.docs == 'true'/)
|
|
})
|