mirror of
https://github.com/zhw2590582/ArtPlayer.git
synced 2026-10-09 03:17:46 -08:00
79 lines
6.0 KiB
JavaScript
79 lines
6.0 KiB
JavaScript
import assert from 'node:assert/strict'
|
||
import fs from 'node:fs'
|
||
import path from 'node:path'
|
||
import process from 'node:process'
|
||
import { fileURLToPath } from 'node:url'
|
||
import { ensureArchive, readMember } from './releases.mjs'
|
||
|
||
const root = fileURLToPath(new URL('../../', import.meta.url))
|
||
assert(['--write', '--check'].includes(process.argv[2]) && process.argv.length === 3, 'Use --write or --check')
|
||
const read = file => JSON.parse(fs.readFileSync(path.join(root, file), 'utf8'))
|
||
const ledger = read('refactor/release-ledger.json')
|
||
const rows = []
|
||
for (const pkg of ledger.packages) {
|
||
const baseline = read(pkg.history.file)
|
||
const release = pkg.history.selector?.split('.').reduce((value, key) => value?.[key], baseline)
|
||
const current = read(`packages/${pkg.name}/package.json`)
|
||
const row = { name: pkg.name, targetVersion: pkg.targetVersion, distribution: pkg.distribution, history: pkg.history, currentDependencies: current.dependencies || {}, currentPeers: current.peerDependencies || {}, currentOptionalDependencies: current.optionalDependencies || {} }
|
||
if (pkg.distribution === 'site') {
|
||
const recovery = read('refactor/baselines/pages-recovery-validation.json')
|
||
assert.equal(recovery.localRestorationPassed, true)
|
||
assert.equal(recovery.remoteRestorationVerified, false)
|
||
rows.push({ ...row, restore: 'Preserve the canonical old Pages ZIP and its Git-blob report; local recovery verified, remote deployment restoration still requires its own gate. npm rollback does not apply.', status: 'local-restore-verified-remote-gate-open', evidence: 'refactor/baselines/pages-recovery-validation.json', localRecovery: { commit: recovery.archive.commit, archiveSha256: recovery.archive.sha256, files: recovery.files.count } })
|
||
continue
|
||
}
|
||
if (pkg.distribution === 'recovered-npm') {
|
||
assert(release, 'Missing recovered history')
|
||
rows.push({ ...row, restore: 'No intact historical npm tarball. Preserve a complete pre-upgrade application/artifact snapshot and verify it before any candidate deployment.', status: 'complete-rollback-artifact-required', evidence: pkg.history.file })
|
||
continue
|
||
}
|
||
assert(release?.integrity && release.sha256 && release.files, `Missing frozen rollback archive: ${pkg.name}`)
|
||
const archive = await ensureArchive(release)
|
||
const manifest = JSON.parse(readMember(archive, 'package/package.json'))
|
||
assert.equal(manifest.name, release.name)
|
||
assert.equal(manifest.version, release.version)
|
||
rows.push({
|
||
...row,
|
||
previous: { name: release.name, version: release.version, tarball: release.tarball, integrity: release.integrity, sha256: release.sha256, memberCount: Object.keys(release.files).length, dependencies: manifest.dependencies || {}, peerDependencies: manifest.peerDependencies || {}, optionalDependencies: manifest.optionalDependencies || {} },
|
||
exactDependency: { [release.name]: release.version },
|
||
restore: pkg.distribution === 'renamed-npm'
|
||
? 'Restore application import code, old package name and saved lock together; npm alias alone does not restore the old export/helper surface.'
|
||
: 'Restore the saved application manifest/lock and matching artifacts, then frozen-install the previous exact version with its tested core/plugin combination.',
|
||
status: 'archive-verified-batch-rehearsal-required',
|
||
})
|
||
}
|
||
assert.equal(rows.length, 22)
|
||
const result = { task: 'REL-04', source: 'refactor/release-ledger.json and frozen historical archives', registryAvailabilityRefreshed: false, mutableTagPolicy: 'Use exact versions and saved lock/artifact hashes. No latest/next/rollback tag is assumed or changed.', packages: rows }
|
||
const json = `${JSON.stringify(result, null, 2)}\n`
|
||
const dependencies = value => Object.entries(value).map(([name, version]) => `${name}@${version}`).join(', ') || '无声明'
|
||
const lines = [
|
||
'# 逐包回退清单',
|
||
'',
|
||
'由 `node refactor/scripts/rollback-inventory.mjs --write` 生成;`--check` 校验同步并复核冻结 tarball 完整性。',
|
||
'',
|
||
'本表核对 20 份完整历史 archive 的 SHA-512/SHA-256 和 manifest。它不表示当前 registry 可用,',
|
||
'也不表示全部包的实际回退已验收。机器清单同时保存旧/新 dependencies、peerDependencies 与精确 integrity。',
|
||
'',
|
||
'| 当前包 | 目标版本 | 恢复版本/对象 | 旧包运行依赖 | 恢复状态 |',
|
||
'| --- | --- | --- | --- | --- |',
|
||
...rows.map(row => `| ${row.name} | ${row.targetVersion} | ${row.previous ? `${row.previous.name}@${row.previous.version}` : row.distribution === 'site' ? '已验证 Pages 产物' : '完整旧产物尚缺'} | ${row.previous ? dependencies(row.previous.dependencies) : '见原有门槛'} | ${row.status} |`),
|
||
'',
|
||
'每包优先恢复升级前已验证的应用代码、package.json 和 yarn.lock,再执行 `yarn install --frozen-lockfile`;',
|
||
'离线恢复还需保存所需 tarball/依赖缓存。单独把版本改回去并重新解析依赖,不能替代已测试锁文件。',
|
||
'外部播放器 SDK、worker/WASM、远端媒体和平台能力也要恢复对应配置,npm 依赖表不覆盖它们。',
|
||
'',
|
||
'iframe 必须同步恢复旧包名、CommonJS `.default`、helper 路径和应用代码;不将 npm alias 当作兼容门面。',
|
||
'Thumbnail 完整原包缺失以及站点部署恢复仍是发布门槛。正式每批重新绑定候选和回退内容,不能直接复用早期演练结果。',
|
||
'',
|
||
'来源:[机器清单](baselines/rollback-inventory.json)、[维护入口](rollback-rehearsal.md)、[发布台账](release-ledger.md)。',
|
||
'',
|
||
]
|
||
const markdown = lines.join('\n')
|
||
for (const [file, contents] of [['refactor/baselines/rollback-inventory.json', json], ['refactor/rollback-inventory.md', markdown]]) {
|
||
if (process.argv[2] === '--write')
|
||
fs.writeFileSync(path.join(root, file), contents)
|
||
else
|
||
assert.equal(fs.readFileSync(path.join(root, file), 'utf8').replaceAll('\r\n', '\n'), contents, `Stale rollback inventory: ${file}`)
|
||
}
|
||
console.log(`Rollback inventory: ${rows.length} packages, ${rows.filter(row => row.previous).length} verified historical archives, remaining batch gates retained`)
|