From 251210d517b593d61b007c045920cf418d7cbf41 Mon Sep 17 00:00:00 2001 From: Tianyi Cui <53024+tianyicui@users.noreply.github.com> Date: Sat, 12 Sep 2026 20:28:39 +0800 Subject: [PATCH] test(release): cover baseline package discovery --- scripts/npm-baseline-packages.spec.ts | 73 +++++++++++++++++++++++++++ scripts/npm-baseline-packages.ts | 26 ++++++++++ scripts/publish-npm-baseline.ts | 13 +---- 3 files changed, 101 insertions(+), 11 deletions(-) create mode 100644 scripts/npm-baseline-packages.spec.ts create mode 100644 scripts/npm-baseline-packages.ts diff --git a/scripts/npm-baseline-packages.spec.ts b/scripts/npm-baseline-packages.spec.ts new file mode 100644 index 0000000000..c79595e8d9 --- /dev/null +++ b/scripts/npm-baseline-packages.spec.ts @@ -0,0 +1,73 @@ +/** Baseline package selection through Node's real filesystem glob implementation. */ + +import { mkdirSync, mkdtempSync, rmSync, writeFileSync } from 'node:fs' +import { tmpdir } from 'node:os' +import { dirname, join } from 'node:path' +import { describe, expect, it, onTestFinished } from 'vitest' +import { PRIVATE_EXPERIMENTAL_PACKAGE_DIRECTORIES } from './experimental-package-policy.ts' +import { discoverNpmBaselineManifests } from './npm-baseline-packages.ts' + +function fixture(manifests: readonly string[]): string { + const root = mkdtempSync(join(tmpdir(), 'dsh-baseline-discovery-')) + onTestFinished(() => { rmSync(root, { recursive: true, force: true }) }) + for (const manifest of manifests) { + const file = join(root, manifest) + mkdirSync(dirname(file), { recursive: true }) + writeFileSync(file, '{}\n') + } + return root +} + +describe('npm baseline package discovery', () => { + it('discovers ordinary package roots and unlisted experimental packages', () => { + const expected = [ + 'apps/cli/package.json', + 'packages/core/session/package.json', + 'packages/experimental/agent-team/package.json', + 'packages/experimental/new-prototype/package.json', + 'vendor/cordis/package.json', + ] + const root = fixture([ + ...expected, + 'package.json', + 'packages/experimental/new-prototype/nested/package.json', + 'website/package.json', + ]) + + expect(discoverNpmBaselineManifests(root)).toEqual(expected) + }) + + it('excludes every directory in the current publication denylist', () => { + const allowed = 'packages/experimental/new-prototype/package.json' + const root = fixture([ + allowed, + ...PRIVATE_EXPERIMENTAL_PACKAGE_DIRECTORIES.map(directory => `${directory}/package.json`), + ]) + + expect(discoverNpmBaselineManifests(root)).toEqual([allowed]) + }) + + it('excludes an exact configured directory without excluding nearby names', () => { + const root = fixture([ + 'packages/experimental/internal/package.json', + 'packages/experimental/internal-tools/package.json', + 'packages/experimental/other/package.json', + ]) + expect(discoverNpmBaselineManifests(root, ['packages/experimental/internal'])).toEqual([ + 'packages/experimental/internal-tools/package.json', + 'packages/experimental/other/package.json', + ]) + }) + + it('retains experimental packages when the configured denylist is empty', () => { + const manifests = [ + 'packages/experimental/inspector/package.json', + 'packages/experimental/new-prototype/package.json', + ] + expect(discoverNpmBaselineManifests(fixture(manifests), [])).toEqual(manifests) + }) + + it('leaves an empty package set for the baseline caller to reject', () => { + expect(discoverNpmBaselineManifests(fixture([]))).toEqual([]) + }) +}) diff --git a/scripts/npm-baseline-packages.ts b/scripts/npm-baseline-packages.ts new file mode 100644 index 0000000000..49c5bf60ce --- /dev/null +++ b/scripts/npm-baseline-packages.ts @@ -0,0 +1,26 @@ +/** Manifest discovery for the npm baseline's vendor, harness, and application packages. */ + +import { globSync } from 'node:fs' +import { PRIVATE_EXPERIMENTAL_PACKAGE_DIRECTORIES } from './experimental-package-policy.ts' + +const PACKAGE_PATTERNS = [ + 'vendor/*/package.json', + 'packages/*/*/package.json', + 'apps/*/package.json', +] as const + +/** + * Discover baseline manifests while excluding the configured private experimental directories. + * @param root - repository root to scan. + * @param privateDirectories - repository-relative experimental directories excluded from publication. + * @returns Sorted repository-relative manifest paths with forward slashes. + */ +export function discoverNpmBaselineManifests( + root: string, + privateDirectories: readonly string[] = PRIVATE_EXPERIMENTAL_PACKAGE_DIRECTORIES, +): string[] { + return globSync(PACKAGE_PATTERNS, { + cwd: root, + exclude: privateDirectories.map(directory => `${directory}/package.json`), + }).map(path => path.replaceAll('\\', '/')).sort() +} diff --git a/scripts/publish-npm-baseline.ts b/scripts/publish-npm-baseline.ts index 0559dc18c1..755d1cf1df 100644 --- a/scripts/publish-npm-baseline.ts +++ b/scripts/publish-npm-baseline.ts @@ -4,7 +4,6 @@ import { spawnSync, type SpawnSyncReturns } from 'node:child_process' import { createHash } from 'node:crypto' import { existsSync, - globSync, mkdirSync, mkdtempSync, readFileSync, @@ -18,16 +17,11 @@ import { basename, dirname, isAbsolute, join, normalize, relative, resolve, sep import { createInterface } from 'node:readline/promises' import { pathToFileURL } from 'node:url' import { parseArgs } from 'node:util' -import { PRIVATE_EXPERIMENTAL_PACKAGE_DIRECTORIES } from './experimental-package-policy.ts' +import { discoverNpmBaselineManifests } from './npm-baseline-packages.ts' import { validateTarballPayload } from './publication-payload.ts' const DEFAULT_REGISTRY = 'https://registry.npm.harnessment.com' const DEFAULT_OUTPUT_DIRECTORY = '.artifacts/npm-baseline' -const PACKAGE_PATTERNS = [ - 'vendor/*/package.json', - 'packages/*/*/package.json', - 'apps/*/package.json', -] as const const DEPENDENCY_SECTIONS = [ 'dependencies', 'devDependencies', @@ -243,10 +237,7 @@ class WorkspacePackageSet { ) {} static discover(root: string): WorkspacePackageSet { - const manifestPaths = globSync(PACKAGE_PATTERNS, { - cwd: root, - exclude: PRIVATE_EXPERIMENTAL_PACKAGE_DIRECTORIES.map(directory => `${directory}/package.json`), - }).sort() + const manifestPaths = discoverNpmBaselineManifests(root) if (manifestPaths.length === 0) { throw new Error('no package manifests found under vendor/, packages/, or apps/') }