From 1cfcf62c252765125fe71b3dfd64cd33b45f9d79 Mon Sep 17 00:00:00 2001 From: Sutu Sebastian Date: Sat, 18 Jul 2026 09:38:07 +0300 Subject: [PATCH 1/2] fix: build and assert dist before npm pack/publish 0.2.0/0.2.1 tarballs shipped without dist because release packed a clean checkout. Build first, refuse pack when export targets are missing, and bump a patch republish. --- .changeset/republish-dist.md | 15 ++++++++++++ .github/workflows/release.yml | 1 + scripts/release.ts | 45 +++++++++++++++++++++++++++++++++-- 3 files changed, 59 insertions(+), 2 deletions(-) create mode 100644 .changeset/republish-dist.md diff --git a/.changeset/republish-dist.md b/.changeset/republish-dist.md new file mode 100644 index 0000000..fd9e83a --- /dev/null +++ b/.changeset/republish-dist.md @@ -0,0 +1,15 @@ +--- +"@stainless-code/layers": patch +"@stainless-code/layers-devtools": patch +"@stainless-code/react-layers-devtools": patch +"@stainless-code/react-layers": patch +"@stainless-code/vue-layers": patch +"@stainless-code/solid-layers": patch +"@stainless-code/svelte-layers": patch +"@stainless-code/preact-layers": patch +"@stainless-code/alpine-layers": patch +"@stainless-code/lit-layers": patch +"@stainless-code/angular-layers": patch +--- + +Republish with built `dist/` artifacts. `0.2.0`/`0.2.1` tarballs were packed without a prior build (exports pointed at missing `./dist/*`). Release now builds and asserts dist files before pack. diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index c86c42d..2a4bfdf 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -41,6 +41,7 @@ jobs: # Opens/updates the Version PR when `.changeset/*.md` exist. When there are none, the action # can still run `publish` (see changesets/action) so a just-merged Version PR can ship. + # `bun run release` builds packages and asserts `dist/` export targets before pack/publish. # `changeset publish` should exit 0 when there is nothing new to publish. If this job fails, # read the step log: common causes are OIDC/trusted-publishing misconfig (`id-token: write`, # the `release` environment, or the npm trusted-publisher binding), registry/network errors, diff --git a/scripts/release.ts b/scripts/release.ts index 04e1790..75467f6 100644 --- a/scripts/release.ts +++ b/scripts/release.ts @@ -1,9 +1,10 @@ #!/usr/bin/env bun -import { readdirSync, readFileSync } from "node:fs"; +import { existsSync, readdirSync, readFileSync } from "node:fs"; import { join } from "node:path"; // Bun cannot perform npm OIDC publishing. Pack with Bun to resolve `workspace:*`, // then publish the tarball with npm for OIDC authentication and provenance. +// Build first so `dist/` exists; refuse to pack when export targets are missing. // Create an annotated git tag, then print `New tag: @` so // changesets/action can push the tag and open a GitHub Release. // Existing registry versions are skipped so partial releases can be retried. @@ -11,6 +12,13 @@ import { $ } from "bun"; const PACKAGES_DIR = "packages"; +interface PackageJson { + name?: string; + version?: string; + private?: boolean; + exports?: unknown; +} + async function isAlreadyPublished( name: string, version: string, @@ -28,12 +36,43 @@ async function ensureReleaseTag(tag: string): Promise { await $`git tag -a ${tag} -m ${tag}`; } +/** Collect `./dist/...` paths referenced by package.json `exports`. */ +function distExportPaths(exportsField: unknown): string[] { + const out = new Set(); + const visit = (value: unknown) => { + if (typeof value === "string") { + if (value.startsWith("./dist/")) out.add(value.slice(2)); + return; + } + if (value && typeof value === "object") { + for (const nested of Object.values(value as Record)) { + visit(nested); + } + } + }; + visit(exportsField); + return [...out].sort(); +} + +function assertDistReady(dir: string, pkg: PackageJson): void { + const missing = distExportPaths(pkg.exports).filter( + (rel) => !existsSync(join(dir, rel)), + ); + if (missing.length === 0) return; + throw new Error( + `${pkg.name}: missing built artifacts (run build before pack):\n - ${missing.join("\n - ")}`, + ); +} + +console.log("release: building packages…"); +await $`bun run build`; + let published = 0; for (const entry of readdirSync(PACKAGES_DIR, { withFileTypes: true })) { if (!entry.isDirectory()) continue; const dir = join(PACKAGES_DIR, entry.name); - let pkg: { name?: string; version?: string; private?: boolean }; + let pkg: PackageJson; try { pkg = JSON.parse(readFileSync(join(dir, "package.json"), "utf8")); } catch { @@ -46,6 +85,8 @@ for (const entry of readdirSync(PACKAGES_DIR, { withFileTypes: true })) { continue; } + assertDistReady(dir, pkg); + const packOut = await $`bun pm pack`.cwd(dir).text(); const tarball = packOut .split("\n") From 7cdeb3e7e6e14c3fc0279b7f613a2edbef7954ed Mon Sep 17 00:00:00 2001 From: Sutu Sebastian Date: Sat, 18 Jul 2026 09:38:52 +0300 Subject: [PATCH 2/2] docs: slim release/changeset prose (authoring-discipline) --- .changeset/republish-dist.md | 2 +- .github/workflows/release.yml | 1 - scripts/release.ts | 13 +++++-------- 3 files changed, 6 insertions(+), 10 deletions(-) diff --git a/.changeset/republish-dist.md b/.changeset/republish-dist.md index fd9e83a..f3c9531 100644 --- a/.changeset/republish-dist.md +++ b/.changeset/republish-dist.md @@ -12,4 +12,4 @@ "@stainless-code/angular-layers": patch --- -Republish with built `dist/` artifacts. `0.2.0`/`0.2.1` tarballs were packed without a prior build (exports pointed at missing `./dist/*`). Release now builds and asserts dist files before pack. +Republish with built `dist/` — prior 0.2.x tarballs omitted it (pack ran without build). diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 2a4bfdf..c86c42d 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -41,7 +41,6 @@ jobs: # Opens/updates the Version PR when `.changeset/*.md` exist. When there are none, the action # can still run `publish` (see changesets/action) so a just-merged Version PR can ship. - # `bun run release` builds packages and asserts `dist/` export targets before pack/publish. # `changeset publish` should exit 0 when there is nothing new to publish. If this job fails, # read the step log: common causes are OIDC/trusted-publishing misconfig (`id-token: write`, # the `release` environment, or the npm trusted-publisher binding), registry/network errors, diff --git a/scripts/release.ts b/scripts/release.ts index 75467f6..4d8babe 100644 --- a/scripts/release.ts +++ b/scripts/release.ts @@ -2,12 +2,10 @@ import { existsSync, readdirSync, readFileSync } from "node:fs"; import { join } from "node:path"; -// Bun cannot perform npm OIDC publishing. Pack with Bun to resolve `workspace:*`, -// then publish the tarball with npm for OIDC authentication and provenance. -// Build first so `dist/` exists; refuse to pack when export targets are missing. -// Create an annotated git tag, then print `New tag: @` so -// changesets/action can push the tag and open a GitHub Release. -// Existing registry versions are skipped so partial releases can be retried. +// Pack with Bun (resolves workspace:*) then npm-publish the tarball — Bun can't do npm OIDC/provenance. +// Build first and assert `exports` dist paths exist (CI checkout has no dist/). +// After publish: annotated `name@version` tag + `New tag:` line for changesets/action (push + GitHub Release). +// Skip versions already on the registry so partial releases can retry. import { $ } from "bun"; const PACKAGES_DIR = "packages"; @@ -36,7 +34,6 @@ async function ensureReleaseTag(tag: string): Promise { await $`git tag -a ${tag} -m ${tag}`; } -/** Collect `./dist/...` paths referenced by package.json `exports`. */ function distExportPaths(exportsField: unknown): string[] { const out = new Set(); const visit = (value: unknown) => { @@ -60,7 +57,7 @@ function assertDistReady(dir: string, pkg: PackageJson): void { ); if (missing.length === 0) return; throw new Error( - `${pkg.name}: missing built artifacts (run build before pack):\n - ${missing.join("\n - ")}`, + `${pkg.name}: missing dist export targets after build:\n - ${missing.join("\n - ")}`, ); }