The harness packages declare the vendored framework as a peer, so installing only the dsh tarballs left npm resolving @deepseek-ai/cordis from a private registry the credential-free pack job cannot reach. The verification now takes several pack directories and installs every tarball in them, and the dsh workflow packs the vendored family for that purpose while still publishing only its own set. The verification also reads what each tarball declares instead of what the checkout says, which is what let the process and tarball helpers become one home each - the three copies of a spawn wrapper were a duplication finding.
109 lines
4.8 KiB
TypeScript
109 lines
4.8 KiB
TypeScript
/**
|
|
* Install packed tarballs into a throwaway consumer outside the repository and
|
|
* drive the installed executable with plain Node.
|
|
*
|
|
* Every tarball the installed tree needs comes from `--from`, so the only
|
|
* registry traffic is for external dependencies. That matters beyond hermetic
|
|
* verification: the harness packages declare the vendored framework as a peer,
|
|
* and those packages live in another release sequence that this credential-free
|
|
* job cannot fetch from a private registry — so a dsh verification passes the
|
|
* vendored family's pack output too, while publishing only its own
|
|
* ([rationale](../../.agents/notes/proposed/process/2026-08-10-npm-release-sequences.md)).
|
|
*
|
|
* What this proves is that `files` selected a complete payload and that the
|
|
* published dependency ranges resolve. A workspace link or a stale `lib/` in the
|
|
* checkout cannot stand in for a missing file here.
|
|
*/
|
|
|
|
import { mkdtempSync, rmSync, writeFileSync } from 'node:fs'
|
|
import { tmpdir } from 'node:os'
|
|
import { join, resolve } from 'node:path'
|
|
import { pathToFileURL } from 'node:url'
|
|
import { parseArgs } from 'node:util'
|
|
import { releaseFamily } from './families.ts'
|
|
import { capture } from './process.ts'
|
|
import { packedIdentity, readPublishOrder } from './tarball.ts'
|
|
|
|
/**
|
|
* Environment for the installed artifact: no host Node hooks, no host DeepSeek
|
|
* Harness home, and no ambient npm user agent that would confuse npm.
|
|
* @param consumerRoot - the throwaway consumer directory.
|
|
* @returns The child environment.
|
|
*/
|
|
function consumerEnvironment(consumerRoot: string): NodeJS.ProcessEnv {
|
|
const environment = { ...process.env }
|
|
delete environment.npm_config_user_agent
|
|
delete environment.NPM_CONFIG_USER_AGENT
|
|
delete environment.NODE_OPTIONS
|
|
delete environment.NODE_PATH
|
|
environment.DSH_HOME = resolve(consumerRoot, '.dsh')
|
|
environment.DSH_AGENTS_HOME = resolve(consumerRoot, '.agents')
|
|
environment.DSH_TELEMETRY_DISABLED = '1'
|
|
return environment
|
|
}
|
|
|
|
/**
|
|
* Every packed tarball in the given directories, as `file:` dependency entries.
|
|
* @param directories - absolute pack output directories.
|
|
* @returns Package name to tarball file URL, and the version each carries.
|
|
*/
|
|
function packedDependencies(directories: readonly string[]): Map<string, { url: string; version: string }> {
|
|
const dependencies = new Map<string, { url: string; version: string }>()
|
|
for (const directory of directories) {
|
|
for (const filename of readPublishOrder(directory)) {
|
|
const tarball = join(directory, filename)
|
|
const { name, version } = packedIdentity(tarball)
|
|
dependencies.set(name, { url: pathToFileURL(tarball).href, version })
|
|
}
|
|
}
|
|
return dependencies
|
|
}
|
|
|
|
/** Install every tarball under `--from` and drive the `--family` entry. */
|
|
function main(): void {
|
|
const { values } = parseArgs({
|
|
options: { family: { type: 'string' }, from: { type: 'string', multiple: true } },
|
|
allowPositionals: false,
|
|
})
|
|
if (values.family === undefined || values.from === undefined || values.from.length === 0) {
|
|
throw new Error('usage: verify-packed-install.ts --family <dsh|vendor> --from <packed directory> [--from ...]')
|
|
}
|
|
|
|
const family = releaseFamily(values.family)
|
|
const entry = family.installedEntry
|
|
if (entry === undefined) {
|
|
console.log(`release verify-packed-install: family ${family.id} publishes no executable, nothing to drive`)
|
|
return
|
|
}
|
|
|
|
const root = process.cwd()
|
|
const packed = packedDependencies(values.from.map(directory => resolve(root, directory)))
|
|
const expected = packed.get(entry.packageName)
|
|
if (expected === undefined) throw new Error(`${entry.packageName} is not among the packed tarballs`)
|
|
|
|
const consumerRoot = mkdtempSync(join(tmpdir(), `dsh-packed-${family.id}-`))
|
|
try {
|
|
writeFileSync(join(consumerRoot, 'package.json'), `${JSON.stringify({
|
|
name: `dsh-packed-install-${family.id}`,
|
|
version: '0.0.0',
|
|
private: true,
|
|
dependencies: Object.fromEntries([...packed].map(([name, entryPacked]) => [name, entryPacked.url])),
|
|
}, null, 2)}\n`)
|
|
|
|
const environment = consumerEnvironment(consumerRoot)
|
|
console.log(`release verify-packed-install: installing ${String(packed.size)} tarball(s) into ${consumerRoot}`)
|
|
capture('npm', ['install', '--no-audit', '--no-fund', '--package-lock=false'], { cwd: consumerRoot, env: environment })
|
|
|
|
const bin = join(consumerRoot, 'node_modules', ...entry.packageName.split('/'), entry.binPath)
|
|
const version = capture(process.execPath, [bin, '--version'], { cwd: consumerRoot, env: environment })
|
|
if (version !== expected.version) {
|
|
throw new Error(`installed ${entry.packageName} --version reported ${JSON.stringify(version)}, expected ${expected.version}`)
|
|
}
|
|
console.log(`release verify-packed-install: installed ${entry.packageName} reports ${version}`)
|
|
} finally {
|
|
rmSync(consumerRoot, { recursive: true, force: true })
|
|
}
|
|
}
|
|
|
|
main()
|