From 0e389811d1d9cdf4d9a516741a7405c182758a03 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Fri, 23 Oct 2026 16:05:02 +0100 Subject: [PATCH 1/5] fix: ship complete type declarations from version, notes, publish and release The `external: [/^[^.]/]` pattern in version's, notes' and publish's tsup configs also matched the resolved absolute paths the declaration build checks, so their own modules were left as imports of `.ts` files missing from dist, and every export typed as `any` for other packages. The pattern now skips absolute paths and @releasekit/*. Release declares types but built none, so it now builds them. With real types, release's typecheck caught two bugs, fixed here: - `backfill --config` ignored the path when loading the publish config. - The failure report left out pub.dev results. An integration test now checks every published package's declarations: the declared types file exists, and each import is a file in dist or a declared dependency. Closes #711 Closes #710 Co-Authored-By: Claude Opus 5.5 --- packages/notes/tsup.config.ts | 3 +- packages/publish/tsup.config.ts | 3 +- .../release/src/commands/backfill-command.ts | 14 ++--- .../src/failure-report/failure-report.ts | 8 +-- .../unit/commands/backfill-command.spec.ts | 30 +++++++++++ .../release/test/unit/failure-report.spec.ts | 10 ++++ packages/release/tsup.config.ts | 5 +- packages/version/tsup.config.ts | 3 +- test/integration/type-declarations.spec.ts | 53 +++++++++++++++++++ 9 files changed, 114 insertions(+), 15 deletions(-) create mode 100644 packages/release/test/unit/commands/backfill-command.spec.ts create mode 100644 test/integration/type-declarations.spec.ts diff --git a/packages/notes/tsup.config.ts b/packages/notes/tsup.config.ts index 37343f0f..e6a5df6d 100644 --- a/packages/notes/tsup.config.ts +++ b/packages/notes/tsup.config.ts @@ -5,5 +5,6 @@ export default defineConfig({ format: ['esm'], dts: { resolve: ['@releasekit/core', '@releasekit/config', '@releasekit/forge', '@releasekit/git'] }, noExternal: ['@releasekit/core', '@releasekit/config', '@releasekit/forge', '@releasekit/git'], - external: [/^[^.]/], + // Bare package names only: the declaration build also checks resolved absolute paths, and @releasekit/* is bundled. + external: [/^(?![./]|[A-Za-z]:[\\/]|@releasekit\/)/], }); diff --git a/packages/publish/tsup.config.ts b/packages/publish/tsup.config.ts index de8ab679..bcec4fb0 100644 --- a/packages/publish/tsup.config.ts +++ b/packages/publish/tsup.config.ts @@ -5,5 +5,6 @@ export default defineConfig({ format: ['esm'], dts: { resolve: ['@releasekit/core', '@releasekit/config', '@releasekit/git'] }, noExternal: ['@releasekit/core', '@releasekit/config', '@releasekit/git'], - external: [/^[^.]/], + // Bare package names only: the declaration build also checks resolved absolute paths, and @releasekit/* is bundled. + external: [/^(?![./]|[A-Za-z]:[\\/]|@releasekit\/)/], }); diff --git a/packages/release/src/commands/backfill-command.ts b/packages/release/src/commands/backfill-command.ts index 64ae9f1a..1eca4db4 100644 --- a/packages/release/src/commands/backfill-command.ts +++ b/packages/release/src/commands/backfill-command.ts @@ -89,9 +89,9 @@ export function createBackfillCommand(): Command { const updateReleases: boolean = options.updateReleases === true; const onlyMissing: boolean = options.onlyMissing === true; const notesConfig = loadNotesConfig(cwd, options.config); - const publishConfig = loadPublishConfig(cwd, options.config); - const releaseNotesEnabled = notesConfig.releaseNotes !== false && notesConfig.releaseNotes !== undefined; - const dir = releaseNotesEnabled ? notesConfig.releaseNotes?.file?.dir : undefined; + const publishConfig = loadPublishConfig({ cwd, configPath: options.config }); + const releaseNotes = notesConfig.releaseNotes === false ? undefined : notesConfig.releaseNotes; + const dir = releaseNotes?.file?.dir; if (!dir && !updateReleases) { error( 'Backfill needs an output: pass --update-releases to update GitHub release bodies, or set ' + @@ -99,7 +99,7 @@ export function createBackfillCommand(): Command { ); process.exit(EXIT_CODES.GENERAL_ERROR); } - if (updateReleases && !releaseNotesEnabled) { + if (updateReleases && !releaseNotes) { error('--update-releases needs notes.releaseNotes enabled in your config to render the bodies.'); process.exit(EXIT_CODES.GENERAL_ERROR); } @@ -147,9 +147,9 @@ export function createBackfillCommand(): Command { } // Estimate and warn about LLM cost if not in --no-llm mode and LLM is enabled - const llmEnabled = !noLlm && notesConfig.releaseNotes?.llm; + const llmEnabled = !noLlm && releaseNotes?.llm; if (llmEnabled && totalReleaseCount > 0) { - const llmConfig = notesConfig.releaseNotes?.llm; + const llmConfig = releaseNotes?.llm; const enabledTasks = countEnabledLlmTasks(llmConfig?.tasks); warn( `Estimated cost: ~${totalReleaseCount} release(s) × ${enabledTasks} LLM task(s). ` + @@ -196,7 +196,7 @@ export function createBackfillCommand(): Command { // Override LLM config if --no-llm is set const adjustedNotesConfig = noLlm - ? { ...notesConfig, releaseNotes: { ...notesConfig.releaseNotes, llm: undefined } } + ? { ...notesConfig, releaseNotes: { ...releaseNotes, llm: undefined } } : notesConfig; // Render one version per pipeline call (single context each). The pipeline's nesting decision diff --git a/packages/release/src/failure-report/failure-report.ts b/packages/release/src/failure-report/failure-report.ts index da0a3bba..a993619b 100644 --- a/packages/release/src/failure-report/failure-report.ts +++ b/packages/release/src/failure-report/failure-report.ts @@ -1,5 +1,5 @@ import { markerData, type VersionOutput } from '@releasekit/core'; -import type { PublishOutput } from '@releasekit/publish'; +import type { PublishOutput, PublishResult } from '@releasekit/publish'; import { ATTRIBUTION_FOOTER } from '../attribution.js'; import { publishableUpdates, syncVersionDisplay } from '../version-display.js'; @@ -71,8 +71,8 @@ export interface LedgerEntry { packageName: string; version: string; status: LedgerStatus; - /** Registry the result came from (npm/cargo), when known. */ - registry?: 'npm' | 'cargo'; + /** Registry the result came from, when known. */ + registry?: PublishResult['registry']; /** Human-readable detail — the skip reason or failure reason. */ detail?: string; } @@ -101,7 +101,7 @@ const STATUS_LABEL: Record = { */ export function buildLedger(versionOutput: VersionOutput, publishOutput: PublishOutput | undefined): LedgerEntry[] { const updates = publishableUpdates(versionOutput); - const results = [...(publishOutput?.npm ?? []), ...(publishOutput?.cargo ?? [])]; + const results = [...(publishOutput?.npm ?? []), ...(publishOutput?.cargo ?? []), ...(publishOutput?.pub ?? [])]; // Index results by package name. A package may appear once (single registry) — when it appears // on multiple registries, prefer a failed/published entry over a skipped one so the headline diff --git a/packages/release/test/unit/commands/backfill-command.spec.ts b/packages/release/test/unit/commands/backfill-command.spec.ts new file mode 100644 index 00000000..bd1359d7 --- /dev/null +++ b/packages/release/test/unit/commands/backfill-command.spec.ts @@ -0,0 +1,30 @@ +import { afterEach, describe, expect, it, vi } from 'vitest'; + +vi.mock('@releasekit/version', () => ({ loadConfig: vi.fn() })); +vi.mock('@releasekit/notes', () => ({ + loadConfig: vi.fn(() => ({ releaseNotes: false })), + runPipeline: vi.fn(), + versionOutputToChangelogInput: vi.fn(), +})); +vi.mock('@releasekit/publish', () => ({ loadConfig: vi.fn(() => ({ githubRelease: {} })) })); + +import { loadConfig as loadPublishConfig } from '@releasekit/publish'; +import { createBackfillCommand } from '../../../src/commands/backfill-command.js'; + +describe('backfill command', () => { + afterEach(() => { + vi.restoreAllMocks(); + }); + + it('should load the publish config from --config', async () => { + vi.spyOn(process, 'exit').mockImplementation(() => { + throw new Error('exit'); + }); + + await expect(createBackfillCommand().parseAsync(['--config', 'custom.json'], { from: 'user' })).rejects.toThrow( + 'exit', + ); + + expect(loadPublishConfig).toHaveBeenCalledWith({ cwd: process.cwd(), configPath: 'custom.json' }); + }); +}); diff --git a/packages/release/test/unit/failure-report.spec.ts b/packages/release/test/unit/failure-report.spec.ts index ff36e4e2..8ff314c5 100644 --- a/packages/release/test/unit/failure-report.spec.ts +++ b/packages/release/test/unit/failure-report.spec.ts @@ -104,6 +104,16 @@ describe('buildLedger', () => { const ledger = buildLedger(versionOutput, publishOutput); expect(ledger[0]?.status).toBe('failed'); }); + + it('should include pub.dev results', () => { + const versionOutput = versionOutputFor([{ name: 'my_package', version: '1.0.0' }]); + const publishOutput = publishOutputFor([]); + publishOutput.pub = [ + { packageName: 'my_package', version: '1.0.0', registry: 'pub', success: false, skipped: false, reason: 'boom' }, + ]; + + expect(buildLedger(versionOutput, publishOutput)[0]).toMatchObject({ status: 'failed', registry: 'pub' }); + }); }); describe('renderFailureReport', () => { diff --git a/packages/release/tsup.config.ts b/packages/release/tsup.config.ts index 563215bd..d2939147 100644 --- a/packages/release/tsup.config.ts +++ b/packages/release/tsup.config.ts @@ -9,7 +9,10 @@ var require = __createRequire(import.meta.url);`.trim(), format: ['esm'], platform: 'node', bundle: true, - dts: false, + dts: { + entry: 'src/index.ts', + resolve: ['@releasekit/core', '@releasekit/config', '@releasekit/forge', '@releasekit/git'], + }, minify: false, splitting: false, external: ['minimatch'], diff --git a/packages/version/tsup.config.ts b/packages/version/tsup.config.ts index 42aaa30e..5f1b64a1 100644 --- a/packages/version/tsup.config.ts +++ b/packages/version/tsup.config.ts @@ -7,5 +7,6 @@ export default defineConfig({ bundle: true, dts: { resolve: ['@releasekit/core', '@releasekit/config', '@releasekit/git'] }, noExternal: ['@releasekit/core', '@releasekit/config', '@releasekit/git'], - external: [/^[^.]/], + // Bare package names only: the declaration build also checks resolved absolute paths, and @releasekit/* is bundled. + external: [/^(?![./]|[A-Za-z]:[\\/]|@releasekit\/)/], } as Options); diff --git a/test/integration/type-declarations.spec.ts b/test/integration/type-declarations.spec.ts new file mode 100644 index 00000000..37fc2f24 --- /dev/null +++ b/test/integration/type-declarations.spec.ts @@ -0,0 +1,53 @@ +import { existsSync, readdirSync, readFileSync } from 'node:fs'; +import { builtinModules } from 'node:module'; +import { join } from 'node:path'; +import { fileURLToPath } from 'node:url'; +import { describe, expect, it } from 'vitest'; + +const PACKAGES = fileURLToPath(new URL('../../packages/', import.meta.url)); + +interface Manifest { + name: string; + private?: boolean; + types?: string; + dependencies?: Record; + peerDependencies?: Record; +} + +const published = readdirSync(PACKAGES) + .map((dir) => ({ dir, manifest: JSON.parse(readFileSync(join(PACKAGES, dir, 'package.json'), 'utf-8')) as Manifest })) + .filter(({ manifest }) => !manifest.private && manifest.types); + +const packageName = (spec: string): string => + spec + .split('/') + .slice(0, spec.startsWith('@') ? 2 : 1) + .join('/'); + +describe.each(published)('$manifest.name type declarations', ({ dir, manifest }) => { + it('should ship the declarations its package.json points to', () => { + expect(existsSync(join(PACKAGES, dir, manifest.types ?? ''))).toBe(true); + }); + + it('should import only files in dist and declared dependencies', () => { + const dist = join(PACKAGES, dir, 'dist'); + const dependencies = new Set(Object.keys({ ...manifest.dependencies, ...manifest.peerDependencies })); + const problems: string[] = []; + for (const file of readdirSync(dist).filter((name) => name.endsWith('.d.ts'))) { + for (const [, spec] of readFileSync(join(dist, file), 'utf-8').matchAll(/(?:from|import)\s+'([^']+)'/g)) { + if (spec.startsWith('.')) { + if (!existsSync(join(dist, spec.replace(/\.js$/, '.d.ts')))) { + problems.push(`${file} imports ${spec}, which isn't in dist`); + } + } else if ( + !spec.startsWith('node:') && + !builtinModules.includes(spec) && + !dependencies.has(packageName(spec)) + ) { + problems.push(`${file} imports ${spec}, which isn't a dependency`); + } + } + } + expect(problems).toEqual([]); + }); +}); From 5883a7e8d475244106e2717e421dc473037626e7 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Fri, 23 Oct 2026 16:13:32 +0100 Subject: [PATCH 2/5] fix(publish): record the version step's package name on each publish result A hybrid package's crate or Dart package can have its own name (`my_package` next to npm's `my-package`), and publish results carried only that registry name, so the failure report couldn't match a cargo or pub.dev result to its update and showed a failure as published or not attempted. Each target and result now carries `updatePackageName`, and the ledger matches on it. Co-Authored-By: Claude Opus 5.5 --- packages/publish/src/registry/cargo.ts | 5 ++- packages/publish/src/registry/dispatcher.ts | 1 + packages/publish/src/registry/npm.ts | 1 + packages/publish/src/registry/pub.ts | 5 ++- packages/publish/src/registry/types.ts | 2 ++ packages/publish/src/types.ts | 2 ++ .../test/unit/stages/pub-publish.spec.ts | 19 ++++++++++++ .../src/failure-report/failure-report.ts | 6 ++-- .../test/unit/failure-report-post.spec.ts | 29 +++++++++++++++-- .../release/test/unit/failure-report.spec.ts | 31 +++++++++++++++---- .../release/test/unit/standing-pr.spec.ts | 10 +++++- 11 files changed, 96 insertions(+), 15 deletions(-) diff --git a/packages/publish/src/registry/cargo.ts b/packages/publish/src/registry/cargo.ts index 7c0ddf43..646f22cf 100644 --- a/packages/publish/src/registry/cargo.ts +++ b/packages/publish/src/registry/cargo.ts @@ -115,7 +115,9 @@ export const cargoRegistry: Registry = { }, }; -function findCrates(updates: Array<{ newVersion: string; filePath: string; dir: string }>): CargoTarget[] { +function findCrates( + updates: Array<{ packageName: string; newVersion: string; filePath: string; dir: string }>, +): CargoTarget[] { const crates: CargoTarget[] = []; for (const update of updates) { @@ -137,6 +139,7 @@ function findCrates(updates: Array<{ newVersion: string; filePath: string; dir: crates.push({ packageName: cargo.package.name, + updatePackageName: update.packageName, version: update.newVersion, dir: update.dir, manifestPath: cargoPath, diff --git a/packages/publish/src/registry/dispatcher.ts b/packages/publish/src/registry/dispatcher.ts index 5f63cdbb..3e7997a2 100644 --- a/packages/publish/src/registry/dispatcher.ts +++ b/packages/publish/src/registry/dispatcher.ts @@ -46,6 +46,7 @@ export async function runPublishStage( for (const target of targets) { const result: PublishResult = { packageName: target.packageName, + updatePackageName: target.updatePackageName, version: target.version, registry: registry.id, success: false, diff --git a/packages/publish/src/registry/npm.ts b/packages/publish/src/registry/npm.ts index f623a83a..bbc2a727 100644 --- a/packages/publish/src/registry/npm.ts +++ b/packages/publish/src/registry/npm.ts @@ -110,6 +110,7 @@ export const npmRegistry: Registry = { async discover(ctx: PipelineContext): Promise { const targets = ctx.input.updates.map((u) => ({ packageName: u.packageName, + updatePackageName: u.packageName, version: u.newVersion, filePath: u.filePath, })); diff --git a/packages/publish/src/registry/pub.ts b/packages/publish/src/registry/pub.ts index 0f711a21..73b575eb 100644 --- a/packages/publish/src/registry/pub.ts +++ b/packages/publish/src/registry/pub.ts @@ -87,7 +87,9 @@ export const pubRegistry: Registry = { }, }; -function findPubPackages(updates: Array<{ newVersion: string; filePath: string; dir: string }>): PubTarget[] { +function findPubPackages( + updates: Array<{ packageName: string; newVersion: string; filePath: string; dir: string }>, +): PubTarget[] { const packages: PubTarget[] = []; const seen = new Set(); @@ -106,6 +108,7 @@ function findPubPackages(updates: Array<{ newVersion: string; filePath: string; packages.push({ packageName: pubspec.name, + updatePackageName: update.packageName, version: update.newVersion, dir: update.dir, command: detectPubCommand(pubspec.environment as Record | undefined), diff --git a/packages/publish/src/registry/types.ts b/packages/publish/src/registry/types.ts index acc648b7..028cdf40 100644 --- a/packages/publish/src/registry/types.ts +++ b/packages/publish/src/registry/types.ts @@ -6,6 +6,8 @@ export type RegistryId = 'npm' | 'cargo' | 'pub'; /** The minimum a publishable unit must expose for the shared dispatcher. */ export interface RegistryTarget { packageName: string; + /** The `VersionOutput` update's name; a crate or Dart package can have its own `packageName`. */ + updatePackageName: string; version: string; } diff --git a/packages/publish/src/types.ts b/packages/publish/src/types.ts index 3e9cdb95..ff92a840 100644 --- a/packages/publish/src/types.ts +++ b/packages/publish/src/types.ts @@ -90,6 +90,8 @@ export interface PublishCliOptions { export interface PublishResult { packageName: string; + /** The `VersionOutput` update this result belongs to; `packageName` is the registry's name for it. */ + updatePackageName: string; version: string; registry: 'npm' | 'cargo' | 'pub'; success: boolean; diff --git a/packages/publish/test/unit/stages/pub-publish.spec.ts b/packages/publish/test/unit/stages/pub-publish.spec.ts index 3aab2abc..98ac5ab8 100644 --- a/packages/publish/test/unit/stages/pub-publish.spec.ts +++ b/packages/publish/test/unit/stages/pub-publish.spec.ts @@ -159,6 +159,25 @@ describe('pub-publish stage', () => { expect(ctx.output.pub[0]?.success).toBe(true); }); + it("should record a hybrid package's result under its update's name", async () => { + const dir = createTmpDir(); + const pkgDir = path.join(dir, 'packages', 'my-package'); + fs.mkdirSync(pkgDir, { recursive: true }); + writePubspec(pkgDir, 'my_package'); + + const ctx = createContext(dir, { + input: { + dryRun: false, + updates: [{ packageName: 'my-package', newVersion: '0.5.0', filePath: 'packages/my-package/package.json' }], + changelogs: [], + tags: [], + }, + }); + await runPubPublishStage(ctx); + + expect(ctx.output.pub[0]).toMatchObject({ packageName: 'my_package', updatePackageName: 'my-package' }); + }); + it('should publish a package only once when multiple updates share the same dir', async () => { const { execCommand } = await import('../../../src/utils/exec.js'); const dir = createTmpDir(); diff --git a/packages/release/src/failure-report/failure-report.ts b/packages/release/src/failure-report/failure-report.ts index a993619b..fb704af8 100644 --- a/packages/release/src/failure-report/failure-report.ts +++ b/packages/release/src/failure-report/failure-report.ts @@ -120,9 +120,9 @@ export function buildLedger(versionOutput: VersionOutput, publishOutput: Publish status = 'published'; } - const existing = byPackage.get(r.packageName); + const existing = byPackage.get(r.updatePackageName); const entry: LedgerEntry = { - packageName: r.packageName, + packageName: r.updatePackageName, version: r.version, status, registry: r.registry, @@ -131,7 +131,7 @@ export function buildLedger(versionOutput: VersionOutput, publishOutput: Publish // Significance order: failed > published > skipped. Keep the more significant outcome. const significance: Record = { failed: 3, published: 2, skipped: 1, 'not-attempted': 0 }; if (!existing || significance[status] > significance[existing.status]) { - byPackage.set(r.packageName, entry); + byPackage.set(r.updatePackageName, entry); } } diff --git a/packages/release/test/unit/failure-report-post.spec.ts b/packages/release/test/unit/failure-report-post.spec.ts index 7cbcf71d..37a6e1d0 100644 --- a/packages/release/test/unit/failure-report-post.spec.ts +++ b/packages/release/test/unit/failure-report-post.spec.ts @@ -37,8 +37,23 @@ function publishOutputFor(npm: PublishResult[]): PublishOutput { function pipelineErrorFor(versionOutput: VersionOutput): PipelineError { const publishOutput = publishOutputFor([ - { packageName: '@scope/a', version: '0.24.0', registry: 'npm', success: true, skipped: false }, - { packageName: '@scope/b', version: '0.24.0', registry: 'npm', success: false, skipped: false, reason: 'npm 403' }, + { + packageName: '@scope/a', + updatePackageName: '@scope/a', + version: '0.24.0', + registry: 'npm', + success: true, + skipped: false, + }, + { + packageName: '@scope/b', + updatePackageName: '@scope/b', + version: '0.24.0', + registry: 'npm', + success: false, + skipped: false, + reason: 'npm 403', + }, ]); void versionOutput; return new PipelineError('Failed to publish to npm: npm 403', 'npm-publish', publishOutput); @@ -135,9 +150,17 @@ describe('detectUnresolvedFailure', () => { const report = renderFailureReport({ versionOutput, publishOutput: publishOutputFor([ - { packageName: '@scope/a', version: '0.24.0', registry: 'npm', success: true, skipped: false }, + { + packageName: '@scope/a', + updatePackageName: '@scope/a', + version: '0.24.0', + registry: 'npm', + success: true, + skipped: false, + }, { packageName: '@scope/b', + updatePackageName: '@scope/b', version: '0.24.0', registry: 'npm', success: false, diff --git a/packages/release/test/unit/failure-report.spec.ts b/packages/release/test/unit/failure-report.spec.ts index 8ff314c5..d0aaee22 100644 --- a/packages/release/test/unit/failure-report.spec.ts +++ b/packages/release/test/unit/failure-report.spec.ts @@ -32,6 +32,7 @@ function versionOutputFor( function npmResult(partial: Partial & { packageName: string; version: string }): PublishResult { return { registry: 'npm', + updatePackageName: partial.packageName, success: true, skipped: false, ...partial, @@ -99,20 +100,38 @@ describe('buildLedger', () => { npmResult({ packageName: '@scope/a', version: '1.0.0', success: true, alreadyPublished: true }), ]); publishOutput.cargo = [ - { packageName: '@scope/a', version: '1.0.0', registry: 'cargo', success: false, skipped: false, reason: 'boom' }, + { + packageName: '@scope/a', + updatePackageName: '@scope/a', + version: '1.0.0', + registry: 'cargo', + success: false, + skipped: false, + reason: 'boom', + }, ]; const ledger = buildLedger(versionOutput, publishOutput); expect(ledger[0]?.status).toBe('failed'); }); - it('should include pub.dev results', () => { - const versionOutput = versionOutputFor([{ name: 'my_package', version: '1.0.0' }]); - const publishOutput = publishOutputFor([]); + it("should match a hybrid package's pub.dev result by its update's name", () => { + const versionOutput = versionOutputFor([{ name: 'my-package', version: '1.0.0' }]); + const publishOutput = publishOutputFor([npmResult({ packageName: 'my-package', version: '1.0.0' })]); publishOutput.pub = [ - { packageName: 'my_package', version: '1.0.0', registry: 'pub', success: false, skipped: false, reason: 'boom' }, + { + packageName: 'my_package', + updatePackageName: 'my-package', + version: '1.0.0', + registry: 'pub', + success: false, + skipped: false, + reason: 'boom', + }, ]; - expect(buildLedger(versionOutput, publishOutput)[0]).toMatchObject({ status: 'failed', registry: 'pub' }); + expect(buildLedger(versionOutput, publishOutput)).toEqual([ + { packageName: 'my-package', version: '1.0.0', status: 'failed', registry: 'pub', detail: 'boom' }, + ]); }); }); diff --git a/packages/release/test/unit/standing-pr.spec.ts b/packages/release/test/unit/standing-pr.spec.ts index 3e8e11e0..8a3f4091 100644 --- a/packages/release/test/unit/standing-pr.spec.ts +++ b/packages/release/test/unit/standing-pr.spec.ts @@ -1722,9 +1722,17 @@ describe('runStandingPRUpdate', () => { dryRun: false, git: { committed: true, tags: [], pushed: false }, npm: [ - { packageName: '@scope/core', version: '0.24.0', registry: 'npm', success: true, skipped: false }, + { + packageName: '@scope/core', + updatePackageName: '@scope/core', + version: '0.24.0', + registry: 'npm', + success: true, + skipped: false, + }, { packageName: '@scope/utils', + updatePackageName: '@scope/utils', version: '0.24.0', registry: 'npm', success: false, From 7a3a7ef24950e2696d267f9aadbcc23b0d9611d6 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Fri, 23 Oct 2026 16:26:46 +0100 Subject: [PATCH 3/5] chore: say what the declaration build matches against the external pattern Co-Authored-By: Claude Opus 5.5 --- packages/notes/tsup.config.ts | 2 +- packages/publish/tsup.config.ts | 2 +- packages/version/tsup.config.ts | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/notes/tsup.config.ts b/packages/notes/tsup.config.ts index e6a5df6d..cd5ec7ef 100644 --- a/packages/notes/tsup.config.ts +++ b/packages/notes/tsup.config.ts @@ -5,6 +5,6 @@ export default defineConfig({ format: ['esm'], dts: { resolve: ['@releasekit/core', '@releasekit/config', '@releasekit/forge', '@releasekit/git'] }, noExternal: ['@releasekit/core', '@releasekit/config', '@releasekit/forge', '@releasekit/git'], - // Bare package names only: the declaration build also checks resolved absolute paths, and @releasekit/* is bundled. + // Bare package names only. The declaration build also matches resolved paths against this; @releasekit/* is bundled. external: [/^(?![./]|[A-Za-z]:[\\/]|@releasekit\/)/], }); diff --git a/packages/publish/tsup.config.ts b/packages/publish/tsup.config.ts index bcec4fb0..e3a8ed63 100644 --- a/packages/publish/tsup.config.ts +++ b/packages/publish/tsup.config.ts @@ -5,6 +5,6 @@ export default defineConfig({ format: ['esm'], dts: { resolve: ['@releasekit/core', '@releasekit/config', '@releasekit/git'] }, noExternal: ['@releasekit/core', '@releasekit/config', '@releasekit/git'], - // Bare package names only: the declaration build also checks resolved absolute paths, and @releasekit/* is bundled. + // Bare package names only. The declaration build also matches resolved paths against this; @releasekit/* is bundled. external: [/^(?![./]|[A-Za-z]:[\\/]|@releasekit\/)/], }); diff --git a/packages/version/tsup.config.ts b/packages/version/tsup.config.ts index 5f1b64a1..2a9b958c 100644 --- a/packages/version/tsup.config.ts +++ b/packages/version/tsup.config.ts @@ -7,6 +7,6 @@ export default defineConfig({ bundle: true, dts: { resolve: ['@releasekit/core', '@releasekit/config', '@releasekit/git'] }, noExternal: ['@releasekit/core', '@releasekit/config', '@releasekit/git'], - // Bare package names only: the declaration build also checks resolved absolute paths, and @releasekit/* is bundled. + // Bare package names only. The declaration build also matches resolved paths against this; @releasekit/* is bundled. external: [/^(?![./]|[A-Za-z]:[\\/]|@releasekit\/)/], } as Options); From 0277c54dda78e9fab8cb994de1dfd7daed221076 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Fri, 23 Oct 2026 16:38:39 +0100 Subject: [PATCH 4/5] chore: say what the external pattern matches; one doc for updatePackageName Co-Authored-By: Claude Opus 5.5 --- packages/notes/tsup.config.ts | 2 +- packages/publish/src/registry/types.ts | 2 +- packages/publish/src/types.ts | 2 +- packages/publish/tsup.config.ts | 2 +- packages/version/tsup.config.ts | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/packages/notes/tsup.config.ts b/packages/notes/tsup.config.ts index cd5ec7ef..6989e026 100644 --- a/packages/notes/tsup.config.ts +++ b/packages/notes/tsup.config.ts @@ -5,6 +5,6 @@ export default defineConfig({ format: ['esm'], dts: { resolve: ['@releasekit/core', '@releasekit/config', '@releasekit/forge', '@releasekit/git'] }, noExternal: ['@releasekit/core', '@releasekit/config', '@releasekit/forge', '@releasekit/git'], - // Bare package names only. The declaration build also matches resolved paths against this; @releasekit/* is bundled. + // Externalize npm packages, but not the bundled @releasekit/* or local files (relative or absolute paths). external: [/^(?![./]|[A-Za-z]:[\\/]|@releasekit\/)/], }); diff --git a/packages/publish/src/registry/types.ts b/packages/publish/src/registry/types.ts index 028cdf40..2a892d60 100644 --- a/packages/publish/src/registry/types.ts +++ b/packages/publish/src/registry/types.ts @@ -6,7 +6,7 @@ export type RegistryId = 'npm' | 'cargo' | 'pub'; /** The minimum a publishable unit must expose for the shared dispatcher. */ export interface RegistryTarget { packageName: string; - /** The `VersionOutput` update's name; a crate or Dart package can have its own `packageName`. */ + /** The name in `VersionOutput`. `packageName` is the registry's name, which differs for some crates and Dart packages. */ updatePackageName: string; version: string; } diff --git a/packages/publish/src/types.ts b/packages/publish/src/types.ts index ff92a840..a9a6cdcd 100644 --- a/packages/publish/src/types.ts +++ b/packages/publish/src/types.ts @@ -90,7 +90,7 @@ export interface PublishCliOptions { export interface PublishResult { packageName: string; - /** The `VersionOutput` update this result belongs to; `packageName` is the registry's name for it. */ + /** The name in `VersionOutput`. `packageName` is the registry's name, which differs for some crates and Dart packages. */ updatePackageName: string; version: string; registry: 'npm' | 'cargo' | 'pub'; diff --git a/packages/publish/tsup.config.ts b/packages/publish/tsup.config.ts index e3a8ed63..0bc3bb55 100644 --- a/packages/publish/tsup.config.ts +++ b/packages/publish/tsup.config.ts @@ -5,6 +5,6 @@ export default defineConfig({ format: ['esm'], dts: { resolve: ['@releasekit/core', '@releasekit/config', '@releasekit/git'] }, noExternal: ['@releasekit/core', '@releasekit/config', '@releasekit/git'], - // Bare package names only. The declaration build also matches resolved paths against this; @releasekit/* is bundled. + // Externalize npm packages, but not the bundled @releasekit/* or local files (relative or absolute paths). external: [/^(?![./]|[A-Za-z]:[\\/]|@releasekit\/)/], }); diff --git a/packages/version/tsup.config.ts b/packages/version/tsup.config.ts index 2a9b958c..52473f8b 100644 --- a/packages/version/tsup.config.ts +++ b/packages/version/tsup.config.ts @@ -7,6 +7,6 @@ export default defineConfig({ bundle: true, dts: { resolve: ['@releasekit/core', '@releasekit/config', '@releasekit/git'] }, noExternal: ['@releasekit/core', '@releasekit/config', '@releasekit/git'], - // Bare package names only. The declaration build also matches resolved paths against this; @releasekit/* is bundled. + // Externalize npm packages, but not the bundled @releasekit/* or local files (relative or absolute paths). external: [/^(?![./]|[A-Za-z]:[\\/]|@releasekit\/)/], } as Options); From 488d499591017cda1bbcc6bc5334943d45e9cec9 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Fri, 23 Oct 2026 16:38:55 +0100 Subject: [PATCH 5/5] chore: shorten the updatePackageName doc to fit the line limit Co-Authored-By: Claude Opus 5.5 --- packages/publish/src/registry/types.ts | 2 +- packages/publish/src/types.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/publish/src/registry/types.ts b/packages/publish/src/registry/types.ts index 2a892d60..712c82d0 100644 --- a/packages/publish/src/registry/types.ts +++ b/packages/publish/src/registry/types.ts @@ -6,7 +6,7 @@ export type RegistryId = 'npm' | 'cargo' | 'pub'; /** The minimum a publishable unit must expose for the shared dispatcher. */ export interface RegistryTarget { packageName: string; - /** The name in `VersionOutput`. `packageName` is the registry's name, which differs for some crates and Dart packages. */ + /** The name in `VersionOutput`. Some crates and Dart packages have a different registry `packageName`. */ updatePackageName: string; version: string; } diff --git a/packages/publish/src/types.ts b/packages/publish/src/types.ts index a9a6cdcd..bdd435f7 100644 --- a/packages/publish/src/types.ts +++ b/packages/publish/src/types.ts @@ -90,7 +90,7 @@ export interface PublishCliOptions { export interface PublishResult { packageName: string; - /** The name in `VersionOutput`. `packageName` is the registry's name, which differs for some crates and Dart packages. */ + /** The name in `VersionOutput`. Some crates and Dart packages have a different registry `packageName`. */ updatePackageName: string; version: string; registry: 'npm' | 'cargo' | 'pub';