fix(release): [REL-02] accept Yarn directory entries in candidate archives

This commit is contained in:
Harvey Zhao committed 2026-09-16 01:52:36 +08:00
1 parent e54fc998ea
commit 1b81888347
11 files changed
+425 -19

No files matched your search

+17
View File
@@ -0,0 +1,17 @@
import assert from 'node:assert/strict'
import { execFileSync } from 'node:child_process'
export function packedFiles(archive) {
const args = { encoding: 'utf8', windowsHide: true }
const names = execFileSync('tar', ['-tzf', archive], args).trim().split(/\r?\n/)
const entries = execFileSync('tar', ['-tvzf', archive], args).trim().split(/\r?\n/)
assert.equal(names.length, entries.length, 'Archive listing mismatch')
assert.equal(new Set(names).size, names.length, 'Duplicate archive members')
return names.filter((name, index) => {
const type = entries[index][0]
assert(['d', '-'].includes(type), 'Package links and special files are unsupported')
assert((type === 'd' && name === 'package') || name.startsWith('package/'), 'Invalid package root')
assert(!name.includes('\\') && !name.split('/').includes('..'), 'Unsafe package member')
return type === '-'
}).sort()
}
+3 -15
View File
@@ -7,8 +7,11 @@ import { fileURLToPath } from 'node:url'
import { ensureArchive, hash, readMember } from '../refactor/scripts/releases.mjs'
import { installedPackages } from './browser-validation/scope.ts'
import { installedPluginTypes } from './consumers/packages.ts'
import { packedFiles } from './package-archive.mjs'
import { consumerDirectory, names as defaultNames, readJson, removeConsumer, run, runtimeConsumer, typeConsumers, workspace, writeJson } from './package-consumer.mjs'
export { packedFiles } from './package-archive.mjs'
export function packageOptions(args) {
assert(args.every(arg => ['--release', '--browser'].includes(arg) || arg.startsWith('--include=')), 'Unknown package-check option')
const includes = args.filter(arg => arg.startsWith('--include='))
@@ -60,21 +63,6 @@ export function historicalDistributionFiles(name, { baseline, sources }) {
return members
}
export function packedFiles(archive) {
const args = { encoding: 'utf8', windowsHide: true }
const names = execFileSync('tar', ['-tzf', archive], args).trim().split(/\r?\n/)
const entries = execFileSync('tar', ['-tvzf', archive], args).trim().split(/\r?\n/)
assert.equal(names.length, entries.length, 'Archive listing mismatch')
assert.equal(new Set(names).size, names.length, 'Duplicate archive members')
return names.filter((name, index) => {
const type = entries[index][0]
assert(['d', '-'].includes(type), 'Package links and special files are unsupported')
assert((type === 'd' && name === 'package') || name.startsWith('package/'), 'Invalid package root')
assert(!name.includes('\\') && !name.split('/').includes('..'), 'Unsafe package member')
return type === '-'
}).sort()
}
export async function publishedConsumer() {
const dir = consumerDirectory()
const releases = readJson(path.join(workspace, 'refactor/baselines/releases.json')).releases
+6
View File
@@ -28,6 +28,12 @@ reports are not evidence that an ArtPlayer package is ready to publish.
## Responsibilities
- `../package-archive.mjs` checks actual tar entry types and paths for both
package installation checks and candidate registration. It accepts Yarn's
directory entries without a trailing slash while rejecting links, special
files, duplicate members and paths outside `package/`. The legacy
`package-check.mjs` export forwards to this helper for existing scripts.
- `../prepare-release.mjs` is the Node entry and failure exit-code boundary.
- `prepare.ts` parses the explicit package batch/tag, requires the canonical
Node/Yarn, and checks clean Git state before both ledger reads. Ignored generated