Files
deepseek-harness/scripts/release/tarball.ts
T
winewill 766eee63eb fix(release): run pnpm and tar portably on Windows
spawnSync cannot start the pnpm .cmd shim without a shell, so the bump
step's lockfile refresh failed with ENOENT on Windows after rewriting
every manifest. Resolve pnpm to a JavaScript entry executed by the
current Node: the run-script's npm_execpath when present, otherwise the
workspace's own pnpm dependency (located on disk because pnpm's manifest
does not export its bin entry).

GNU tar parses the colon in an absolute Windows path as a remote-host
separator and aborts, so the tarball readers now run tar in the
tarball's directory and pass only its file name.
2026-09-21 13:30:12 +08:00

55 lines
2.1 KiB
TypeScript

/**
* Reading packed npm tarballs and the order file that accompanies them.
*
* The release steps after pack treat a directory of tarballs as the unit of
* work, so they read what a tarball declares rather than what the checkout
* currently says.
*/
import { readFileSync } from 'node:fs'
import { basename, dirname, join } from 'node:path'
import { capture } from './process.ts'
/** Name of the file recording the order in which a packed family uploads. */
export const PUBLISH_ORDER_FILE = 'publish-order.txt'
/** What a packed tarball calls itself. */
export interface PackedIdentity {
/** Package name from the packed manifest. */
readonly name: string
/** Package version from the packed manifest. */
readonly version: string
}
/**
* List a tarball's members.
* @param tarball - absolute tarball path.
* @returns Every path inside the archive.
*/
export function tarballFiles(tarball: string): string[] {
// GNU tar reads the colon in a Windows drive path as a remote-host separator, so tar runs beside the tarball.
return capture('tar', ['-tzf', basename(tarball)], { cwd: dirname(tarball) }).split(/\r?\n/u).filter(line => line !== '')
}
/**
* Read a packed tarball's own manifest.
* @param tarball - absolute tarball path.
* @returns The name and version the tarball declares.
*/
export function packedIdentity(tarball: string): PackedIdentity {
const manifest: unknown = JSON.parse(capture('tar', ['-xOzf', basename(tarball), 'package/package.json'], { cwd: dirname(tarball) }))
if (manifest === null || typeof manifest !== 'object') throw new Error(`${tarball} has no manifest`)
const { name, version } = manifest as Record<string, unknown>
if (typeof name !== 'string' || typeof version !== 'string') throw new Error(`${tarball} manifest lacks name/version`)
return { name, version }
}
/**
* Read a packed directory's upload order.
* @param directory - absolute path of a pack output directory.
* @returns Tarball filenames in upload order.
*/
export function readPublishOrder(directory: string): string[] {
return readFileSync(join(directory, PUBLISH_ORDER_FILE), 'utf8').split('\n').filter(line => line !== '')
}