fix(release): make August 1 handoff reproducible
This commit is contained in:
@@ -0,0 +1,89 @@
|
||||
import assert from 'node:assert/strict'
|
||||
import { mkdtemp, readFile, rm, writeFile } from 'node:fs/promises'
|
||||
import os from 'node:os'
|
||||
import path from 'node:path'
|
||||
import { fileURLToPath } from 'node:url'
|
||||
import { spawnSync } from 'node:child_process'
|
||||
import test from 'node:test'
|
||||
|
||||
const testDir = path.dirname(fileURLToPath(import.meta.url))
|
||||
const projectRoot = path.resolve(testDir, '..', '..')
|
||||
const verifierPath = path.join(projectRoot, 'scripts', 'verify-aug1-content-candidates.mjs')
|
||||
const candidatePath = path.join(
|
||||
projectRoot,
|
||||
'docs',
|
||||
'content-candidates',
|
||||
'aug1-life-advisor-content-candidates-v0.1.json',
|
||||
)
|
||||
const baseCandidate = JSON.parse(await readFile(candidatePath, 'utf8'))
|
||||
|
||||
const cloneCandidate = () => structuredClone(baseCandidate)
|
||||
|
||||
async function verifyCandidate(candidate) {
|
||||
const tempDir = await mkdtemp(path.join(os.tmpdir(), 'aug1-content-'))
|
||||
const fixturePath = path.join(tempDir, 'candidate.json')
|
||||
try {
|
||||
await writeFile(fixturePath, JSON.stringify(candidate), 'utf8')
|
||||
return spawnSync(process.execPath, [verifierPath, fixturePath], {
|
||||
cwd: projectRoot,
|
||||
encoding: 'utf8',
|
||||
})
|
||||
} finally {
|
||||
await rm(tempDir, { recursive: true, force: true })
|
||||
}
|
||||
}
|
||||
|
||||
test('accepts the reviewed disabled candidate structure through an explicit package path', async () => {
|
||||
const result = await verifyCandidate(cloneCandidate())
|
||||
assert.equal(result.status, 0, result.stderr)
|
||||
assert.match(result.stdout, /verification passed/)
|
||||
})
|
||||
|
||||
test('rejects sensitive locators, credentials and mobile numbers', async (t) => {
|
||||
const cases = [
|
||||
['precise room', (candidate) => {
|
||||
candidate.scenarios[0].scenarioDraft.openingText = '住户住在3栋2单元501室。'
|
||||
}],
|
||||
['access credential', (candidate) => {
|
||||
candidate.scenarios[0].scenarioDraft.openingText = '门禁口令 ABCD。'
|
||||
}],
|
||||
['mobile phone', (candidate) => {
|
||||
candidate.policyQuestionCandidates[0].question = ['联系号码', '13', '9000', '00000'].join('')
|
||||
}],
|
||||
]
|
||||
|
||||
for (const [name, mutate] of cases) {
|
||||
await t.test(name, async () => {
|
||||
const candidate = cloneCandidate()
|
||||
mutate(candidate)
|
||||
const result = await verifyCandidate(candidate)
|
||||
assert.notEqual(result.status, 0)
|
||||
})
|
||||
}
|
||||
})
|
||||
|
||||
test('rejects publishable content, answers and duplicate IDs before formal sign-off', async (t) => {
|
||||
const cases = [
|
||||
['publishable root', (candidate) => {
|
||||
candidate.publishable = true
|
||||
}],
|
||||
['embedded answer', (candidate) => {
|
||||
candidate.policyQuestionCandidates[0].answer = 'not allowed before formal sourcing'
|
||||
}],
|
||||
['duplicate scenario ID', (candidate) => {
|
||||
candidate.scenarios[1].candidateId = candidate.scenarios[0].candidateId
|
||||
}],
|
||||
['duplicate question ID', (candidate) => {
|
||||
candidate.policyQuestionCandidates[1].id = candidate.policyQuestionCandidates[0].id
|
||||
}],
|
||||
]
|
||||
|
||||
for (const [name, mutate] of cases) {
|
||||
await t.test(name, async () => {
|
||||
const candidate = cloneCandidate()
|
||||
mutate(candidate)
|
||||
const result = await verifyCandidate(candidate)
|
||||
assert.notEqual(result.status, 0)
|
||||
})
|
||||
}
|
||||
})
|
||||
@@ -15,10 +15,14 @@ $requiredFragments = @(
|
||||
"'operations/release-backend.sh'",
|
||||
"'operations/release-preflight.sh'",
|
||||
"'operations/verify-aug1-production-api-readonly.sh'",
|
||||
"'operations/verify-aug1-authenticated-production.sh'",
|
||||
"'operations/verify-aug1-content-candidates.mjs'",
|
||||
"'operations/capture-android-acceptance.ps1'",
|
||||
"'operations/go-no-go.md'",
|
||||
"'operations/business-content-and-five-channel-signoff.md'",
|
||||
'Release package already exists and will not be overwritten',
|
||||
'Release package expected 14 files',
|
||||
'Release package expected 17 files',
|
||||
'ZIP verification expected 17 entries',
|
||||
'ZIP entry hash mismatch',
|
||||
'package_verified=true',
|
||||
'authenticatedFixedCodeSmokePassed = $true',
|
||||
|
||||
Reference in New Issue
Block a user