From 89d430c43ab71d8b2e1fc2319fe77b8d154923cb Mon Sep 17 00:00:00 2001 From: Aidan Daly Date: Wed, 9 Sep 2026 19:35:13 +0000 Subject: [PATCH 1/6] ci(release): use dedicated runner for release preparation --- .github/workflows/release-prepare.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/release-prepare.yml b/.github/workflows/release-prepare.yml index 76a28f7fe..188710aa6 100644 --- a/.github/workflows/release-prepare.yml +++ b/.github/workflows/release-prepare.yml @@ -17,7 +17,7 @@ on: jobs: prepare: - runs-on: ubuntu-latest + runs-on: aws-release-4-core permissions: contents: read steps: From 1ae699034af87d5ca2745d1ec2ca474dd7764041 Mon Sep 17 00:00:00 2001 From: Aidan Daly Date: Wed, 9 Sep 2026 19:36:05 +0000 Subject: [PATCH 2/6] fix(packaging): exclude native binaries from npm tarballs --- package.json | 4 ++- scripts/package.test.ts | 56 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 59 insertions(+), 1 deletion(-) create mode 100644 scripts/package.test.ts diff --git a/package.json b/package.json index db239b23c..8f70509dd 100644 --- a/package.json +++ b/package.json @@ -16,7 +16,9 @@ "node": ">=20.12.0" }, "files": [ - "dist" + "dist/index.js", + "dist/main.js", + "dist/assets" ], "scripts": { "build": "bun scripts/build.ts bundle", diff --git a/scripts/package.test.ts b/scripts/package.test.ts new file mode 100644 index 000000000..d39f63ea1 --- /dev/null +++ b/scripts/package.test.ts @@ -0,0 +1,56 @@ +import { expect, test } from "bun:test"; +import { mkdtemp, rm } from "node:fs/promises"; +import { tmpdir } from "node:os"; +import { join } from "node:path"; +import manifest from "../package.json"; + +test("npm tarball includes only the Node bundle and runtime assets, even after compilation", async () => { + const directory = await mkdtemp(join(tmpdir(), "agentcore-package-")); + try { + const included = [ + "README.md", + "LICENSE", + "dist/index.js", + "dist/main.js", + "dist/assets/cdk/package.json", + "dist/assets/cdk/.prettierrc", + "dist/assets/agent-inspector/index.html.asset", + ]; + const excluded = [ + "dist/bin/agentcore-linux-x64", + "dist/bin/agentcore-windows-x64.exe", + "dist/main.js.map", + "dist/debug.log", + "dist/old-build/index.js", + "src/index.ts", + "scripts/build.ts", + ".github/workflows/release-publish.yml", + ]; + await Bun.write(join(directory, "package.json"), JSON.stringify(manifest)); + for (const file of [...included, ...excluded]) { + await Bun.write(join(directory, file), "fixture\n"); + } + + const tarball = join(directory, "package.tgz"); + const pack = Bun.spawn( + [process.execPath, "pm", "pack", "--ignore-scripts", "--filename", tarball], + { cwd: directory, stdout: "pipe", stderr: "pipe" }, + ); + const [exitCode, stdout, stderr] = await Promise.all([ + pack.exited, + new Response(pack.stdout).text(), + new Response(pack.stderr).text(), + ]); + expect({ exitCode, output: exitCode ? stdout + stderr : "" }).toEqual({ + exitCode: 0, + output: "", + }); + + const files = await new Bun.Archive(await Bun.file(tarball).bytes()).files(); + expect([...files.keys()].sort()).toEqual( + ["package.json", ...included].map((file) => `package/${file}`).sort(), + ); + } finally { + await rm(directory, { recursive: true, force: true }); + } +}); From a78f3fcb4a8b1c487a2e84ce58da60278f69bb58 Mon Sep 17 00:00:00 2001 From: Aidan Daly Date: Wed, 9 Sep 2026 19:36:20 +0000 Subject: [PATCH 3/6] ci(release): publish trusted release merges from push events --- .github/workflows/README.md | 16 ++++ .github/workflows/release-publish.yml | 37 ++++++-- scripts/release-publish.test.ts | 120 ++++++++++++++++++++++++++ 3 files changed, 168 insertions(+), 5 deletions(-) create mode 100644 scripts/release-publish.test.ts diff --git a/.github/workflows/README.md b/.github/workflows/README.md index 5290f8dac..3d49671e5 100644 --- a/.github/workflows/README.md +++ b/.github/workflows/README.md @@ -46,6 +46,22 @@ compose freely. Dispatch `release-prepare` with a bump and a channel, review the release PR it opens, merge it. `release-publish` then publishes the merged package.json version. +Publishing listens for pushes to `refactor` (switch to `main` when the refactor lands), not PR +events. It looks up the pushed commit's associated PRs and proceeds only when that exact commit +is the merge of a `release/v*` PR from this repository into the target branch. Ordinary merges, +fork PRs, and pushes without a matching release PR skip verification and publishing. Every job +uses the pushed SHA, so later commits cannot change what is released. + +The prepare job uses `aws-release-4-core`. The check-release and publish jobs stay on +`ubuntu-latest` until `release-publish.yml` is allowlisted for the dedicated runner group. +The allowlist is scoped to workflow paths and branches; renaming a workflow or changing its +branch requires a runner-group administrator to update it. Keep PR-triggered workflows +and the verification matrix off this release-only pool. + +The npm package includes only `dist/index.js`, `dist/main.js`, and `dist/assets`, plus standard +package metadata. Native binaries in `dist/bin` are separate GitHub release assets, never npm +package contents, even when packing a workspace that has already compiled them. + If publish fails after the merge, rerun the failed `release-publish` jobs. Both the npm publish and the GitHub release steps skip work that already succeeded. Do not re-dispatch `release-prepare`, package.json already holds the new version and it would bump again. diff --git a/.github/workflows/release-publish.yml b/.github/workflows/release-publish.yml index a7ed01d05..e79e3c5e8 100644 --- a/.github/workflows/release-publish.yml +++ b/.github/workflows/release-publish.yml @@ -2,19 +2,46 @@ # release-prepare.yml merges. The version is whatever the merged package.json says. name: release-publish on: - pull_request: - types: [closed] + push: # TODO: switch to main once the refactor lands there. branches: [refactor] jobs: + check-release: + if: "!github.event.deleted" + runs-on: ubuntu-latest + permissions: + pull-requests: read + outputs: + is_release: ${{ steps.check.outputs.is_release }} + steps: + # Push runs the trusted base-branch workflow, but does not carry the merged PR's metadata. + - name: Check for a merged release PR + id: check + env: + GH_TOKEN: ${{ github.token }} + run: | + set -euo pipefail + IS_RELEASE=$(gh api --paginate --slurp "repos/$GITHUB_REPOSITORY/commits/$GITHUB_SHA/pulls" \ + | jq -r --arg repository "$GITHUB_REPOSITORY" --arg ref "$GITHUB_REF_NAME" --arg sha "$GITHUB_SHA" ' + any(.[][]; + .merged_at != null and + .merge_commit_sha == $sha and + .head.repo.full_name == $repository and + .base.repo.full_name == $repository and + .base.ref == $ref and + (.head.ref | startswith("release/v")) + )') + echo "is_release=$IS_RELEASE" >> "$GITHUB_OUTPUT" + verify: - if: github.event.pull_request.merged && startsWith(github.head_ref, 'release/v') + needs: check-release + if: needs.check-release.outputs.is_release == 'true' uses: ./.github/workflows/verify.yml permissions: contents: read with: - ref: ${{ github.event.pull_request.merge_commit_sha }} + ref: ${{ github.sha }} publish: needs: verify @@ -24,7 +51,7 @@ jobs: contents: write id-token: write env: - REF: ${{ github.event.pull_request.merge_commit_sha }} + REF: ${{ github.sha }} steps: - uses: actions/checkout@v7 with: diff --git a/scripts/release-publish.test.ts b/scripts/release-publish.test.ts new file mode 100644 index 000000000..5fcc0a3f9 --- /dev/null +++ b/scripts/release-publish.test.ts @@ -0,0 +1,120 @@ +import { expect, test } from "bun:test"; +import { chmod, mkdtemp, rm } from "node:fs/promises"; +import { tmpdir } from "node:os"; +import { delimiter, join } from "node:path"; + +interface Job { + if?: string; + needs?: string; + "runs-on"?: string; + permissions?: Record; + outputs?: Record; + with?: Record; + env?: Record; + steps?: { id?: string; run?: string }[]; +} + +const workflow = Bun.YAML.parse( + await Bun.file(new URL("../.github/workflows/release-publish.yml", import.meta.url)).text(), +) as { on: { push: { branches: string[] } }; jobs: Record }; +const repository = "aws/agentcore-cli"; +const sha = "0caec7fe932a0d4f8f8ce2d4821fee0664ab77cf"; +const releasePr = { + merged_at: "2026-09-04T22:18:03Z", + merge_commit_sha: sha, + head: { ref: "release/v1.0.0-rc.1", repo: { full_name: repository } }, + base: { ref: "refactor", repo: { full_name: repository } }, +}; + +test("release runs only on target-branch pushes and verifies the exact commit before publishing", () => { + expect(workflow.on).toEqual({ push: { branches: ["refactor"] } }); + const check = workflow.jobs["check-release"]!; + expect(check.if).toBe("!github.event.deleted"); + expect(check["runs-on"]).toBe("ubuntu-latest"); + expect(check.permissions).toEqual({ "pull-requests": "read" }); + expect(check.outputs).toEqual({ is_release: "${{ steps.check.outputs.is_release }}" }); + expect(workflow.jobs.verify).toMatchObject({ + needs: "check-release", + if: "needs.check-release.outputs.is_release == 'true'", + with: { ref: "${{ github.sha }}" }, + }); + expect(workflow.jobs.publish).toMatchObject({ + needs: "verify", + "runs-on": "ubuntu-latest", + env: { REF: "${{ github.sha }}" }, + }); +}); + +// The gate runs on Ubuntu; execute its actual shell script wherever bash and jq are available. +const shellTest = test.skipIf( + process.platform === "win32" || !Bun.which("bash") || !Bun.which("jq"), +); + +async function checkRelease(pages: unknown[][], apiExitCode = 0) { + const directory = await mkdtemp(join(tmpdir(), "agentcore-release-")); + try { + const gh = join(directory, "gh"); + await Bun.write(gh, '#!/bin/sh\nprintf "%s" "$PULL_REQUESTS"\nexit "$API_EXIT_CODE"\n'); + await chmod(gh, 0o755); + const output = join(directory, "output"); + await Bun.write(output, ""); + const script = workflow.jobs["check-release"]!.steps!.find((step) => step.id === "check")!.run!; + const check = Bun.spawn(["bash", "--noprofile", "--norc", "-c", script], { + env: { + ...process.env, + PATH: `${directory}${delimiter}${process.env.PATH}`, + GITHUB_REPOSITORY: repository, + GITHUB_SHA: sha, + GITHUB_REF_NAME: "refactor", + GITHUB_OUTPUT: output, + PULL_REQUESTS: JSON.stringify(pages), + API_EXIT_CODE: String(apiExitCode), + }, + stdout: "pipe", + stderr: "pipe", + }); + const [exitCode, stdout, stderr] = await Promise.all([ + check.exited, + new Response(check.stdout).text(), + new Response(check.stderr).text(), + ]); + return { exitCode, stdout, stderr, output: await Bun.file(output).text() }; + } finally { + await rm(directory, { recursive: true, force: true }); + } +} + +shellTest("accepts the merged in-repository release PR, including later API pages", async () => { + const result = await checkRelease([[{ ...releasePr, merged_at: null }], [releasePr]]); + expect(result).toMatchObject({ exitCode: 0, output: "is_release=true\n" }); +}); + +shellTest.each([ + ["ordinary PR", { ...releasePr, head: { ...releasePr.head, ref: "fix/something" } }], + ["unmerged release PR", { ...releasePr, merged_at: null }], + ["different commit", { ...releasePr, merge_commit_sha: "another-commit" }], + [ + "fork release PR", + { ...releasePr, head: { ...releasePr.head, repo: { full_name: "someone/agentcore-cli" } } }, + ], + ["deleted fork", { ...releasePr, head: { ...releasePr.head, repo: null } }], + ["different target branch", { ...releasePr, base: { ...releasePr.base, ref: "main" } }], + [ + "different target repository", + { ...releasePr, base: { ...releasePr.base, repo: { full_name: "someone/agentcore-cli" } } }, + ], +])("skips %s", async (_name, pr) => { + const result = await checkRelease([[pr]]); + expect(result).toMatchObject({ exitCode: 0, output: "is_release=false\n" }); +}); + +shellTest("skips pushes without an associated PR", async () => { + const result = await checkRelease([[]]); + expect(result).toMatchObject({ exitCode: 0, output: "is_release=false\n" }); +}); + +shellTest("fails closed on a GitHub API error", async () => { + const result = await checkRelease([[releasePr]], 1); + expect(result.exitCode).not.toBe(0); + expect(result.output).toBe(""); +}); From 5cdf14c7dec1a679bdc6ff02089459beea7ef5d5 Mon Sep 17 00:00:00 2001 From: Aidan Daly Date: Wed, 9 Sep 2026 19:47:40 +0000 Subject: [PATCH 4/6] test(release): remove added test scripts --- scripts/package.test.ts | 56 --------------- scripts/release-publish.test.ts | 120 -------------------------------- 2 files changed, 176 deletions(-) delete mode 100644 scripts/package.test.ts delete mode 100644 scripts/release-publish.test.ts diff --git a/scripts/package.test.ts b/scripts/package.test.ts deleted file mode 100644 index d39f63ea1..000000000 --- a/scripts/package.test.ts +++ /dev/null @@ -1,56 +0,0 @@ -import { expect, test } from "bun:test"; -import { mkdtemp, rm } from "node:fs/promises"; -import { tmpdir } from "node:os"; -import { join } from "node:path"; -import manifest from "../package.json"; - -test("npm tarball includes only the Node bundle and runtime assets, even after compilation", async () => { - const directory = await mkdtemp(join(tmpdir(), "agentcore-package-")); - try { - const included = [ - "README.md", - "LICENSE", - "dist/index.js", - "dist/main.js", - "dist/assets/cdk/package.json", - "dist/assets/cdk/.prettierrc", - "dist/assets/agent-inspector/index.html.asset", - ]; - const excluded = [ - "dist/bin/agentcore-linux-x64", - "dist/bin/agentcore-windows-x64.exe", - "dist/main.js.map", - "dist/debug.log", - "dist/old-build/index.js", - "src/index.ts", - "scripts/build.ts", - ".github/workflows/release-publish.yml", - ]; - await Bun.write(join(directory, "package.json"), JSON.stringify(manifest)); - for (const file of [...included, ...excluded]) { - await Bun.write(join(directory, file), "fixture\n"); - } - - const tarball = join(directory, "package.tgz"); - const pack = Bun.spawn( - [process.execPath, "pm", "pack", "--ignore-scripts", "--filename", tarball], - { cwd: directory, stdout: "pipe", stderr: "pipe" }, - ); - const [exitCode, stdout, stderr] = await Promise.all([ - pack.exited, - new Response(pack.stdout).text(), - new Response(pack.stderr).text(), - ]); - expect({ exitCode, output: exitCode ? stdout + stderr : "" }).toEqual({ - exitCode: 0, - output: "", - }); - - const files = await new Bun.Archive(await Bun.file(tarball).bytes()).files(); - expect([...files.keys()].sort()).toEqual( - ["package.json", ...included].map((file) => `package/${file}`).sort(), - ); - } finally { - await rm(directory, { recursive: true, force: true }); - } -}); diff --git a/scripts/release-publish.test.ts b/scripts/release-publish.test.ts deleted file mode 100644 index 5fcc0a3f9..000000000 --- a/scripts/release-publish.test.ts +++ /dev/null @@ -1,120 +0,0 @@ -import { expect, test } from "bun:test"; -import { chmod, mkdtemp, rm } from "node:fs/promises"; -import { tmpdir } from "node:os"; -import { delimiter, join } from "node:path"; - -interface Job { - if?: string; - needs?: string; - "runs-on"?: string; - permissions?: Record; - outputs?: Record; - with?: Record; - env?: Record; - steps?: { id?: string; run?: string }[]; -} - -const workflow = Bun.YAML.parse( - await Bun.file(new URL("../.github/workflows/release-publish.yml", import.meta.url)).text(), -) as { on: { push: { branches: string[] } }; jobs: Record }; -const repository = "aws/agentcore-cli"; -const sha = "0caec7fe932a0d4f8f8ce2d4821fee0664ab77cf"; -const releasePr = { - merged_at: "2026-09-04T22:18:03Z", - merge_commit_sha: sha, - head: { ref: "release/v1.0.0-rc.1", repo: { full_name: repository } }, - base: { ref: "refactor", repo: { full_name: repository } }, -}; - -test("release runs only on target-branch pushes and verifies the exact commit before publishing", () => { - expect(workflow.on).toEqual({ push: { branches: ["refactor"] } }); - const check = workflow.jobs["check-release"]!; - expect(check.if).toBe("!github.event.deleted"); - expect(check["runs-on"]).toBe("ubuntu-latest"); - expect(check.permissions).toEqual({ "pull-requests": "read" }); - expect(check.outputs).toEqual({ is_release: "${{ steps.check.outputs.is_release }}" }); - expect(workflow.jobs.verify).toMatchObject({ - needs: "check-release", - if: "needs.check-release.outputs.is_release == 'true'", - with: { ref: "${{ github.sha }}" }, - }); - expect(workflow.jobs.publish).toMatchObject({ - needs: "verify", - "runs-on": "ubuntu-latest", - env: { REF: "${{ github.sha }}" }, - }); -}); - -// The gate runs on Ubuntu; execute its actual shell script wherever bash and jq are available. -const shellTest = test.skipIf( - process.platform === "win32" || !Bun.which("bash") || !Bun.which("jq"), -); - -async function checkRelease(pages: unknown[][], apiExitCode = 0) { - const directory = await mkdtemp(join(tmpdir(), "agentcore-release-")); - try { - const gh = join(directory, "gh"); - await Bun.write(gh, '#!/bin/sh\nprintf "%s" "$PULL_REQUESTS"\nexit "$API_EXIT_CODE"\n'); - await chmod(gh, 0o755); - const output = join(directory, "output"); - await Bun.write(output, ""); - const script = workflow.jobs["check-release"]!.steps!.find((step) => step.id === "check")!.run!; - const check = Bun.spawn(["bash", "--noprofile", "--norc", "-c", script], { - env: { - ...process.env, - PATH: `${directory}${delimiter}${process.env.PATH}`, - GITHUB_REPOSITORY: repository, - GITHUB_SHA: sha, - GITHUB_REF_NAME: "refactor", - GITHUB_OUTPUT: output, - PULL_REQUESTS: JSON.stringify(pages), - API_EXIT_CODE: String(apiExitCode), - }, - stdout: "pipe", - stderr: "pipe", - }); - const [exitCode, stdout, stderr] = await Promise.all([ - check.exited, - new Response(check.stdout).text(), - new Response(check.stderr).text(), - ]); - return { exitCode, stdout, stderr, output: await Bun.file(output).text() }; - } finally { - await rm(directory, { recursive: true, force: true }); - } -} - -shellTest("accepts the merged in-repository release PR, including later API pages", async () => { - const result = await checkRelease([[{ ...releasePr, merged_at: null }], [releasePr]]); - expect(result).toMatchObject({ exitCode: 0, output: "is_release=true\n" }); -}); - -shellTest.each([ - ["ordinary PR", { ...releasePr, head: { ...releasePr.head, ref: "fix/something" } }], - ["unmerged release PR", { ...releasePr, merged_at: null }], - ["different commit", { ...releasePr, merge_commit_sha: "another-commit" }], - [ - "fork release PR", - { ...releasePr, head: { ...releasePr.head, repo: { full_name: "someone/agentcore-cli" } } }, - ], - ["deleted fork", { ...releasePr, head: { ...releasePr.head, repo: null } }], - ["different target branch", { ...releasePr, base: { ...releasePr.base, ref: "main" } }], - [ - "different target repository", - { ...releasePr, base: { ...releasePr.base, repo: { full_name: "someone/agentcore-cli" } } }, - ], -])("skips %s", async (_name, pr) => { - const result = await checkRelease([[pr]]); - expect(result).toMatchObject({ exitCode: 0, output: "is_release=false\n" }); -}); - -shellTest("skips pushes without an associated PR", async () => { - const result = await checkRelease([[]]); - expect(result).toMatchObject({ exitCode: 0, output: "is_release=false\n" }); -}); - -shellTest("fails closed on a GitHub API error", async () => { - const result = await checkRelease([[releasePr]], 1); - expect(result.exitCode).not.toBe(0); - expect(result.output).toBe(""); -}); From edffd55b0c114fdbde4e1ea8c8cd200e676a0301 Mon Sep 17 00:00:00 2001 From: Aidan Daly Date: Wed, 9 Sep 2026 20:10:59 +0000 Subject: [PATCH 5/6] fix(release): require automation author for release PRs --- .github/workflows/README.md | 7 ++++--- .github/workflows/release-publish.yml | 3 ++- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/.github/workflows/README.md b/.github/workflows/README.md index 3d49671e5..bf42201c8 100644 --- a/.github/workflows/README.md +++ b/.github/workflows/README.md @@ -48,9 +48,10 @@ Dispatch `release-prepare` with a bump and a channel, review the release PR it o Publishing listens for pushes to `refactor` (switch to `main` when the refactor lands), not PR events. It looks up the pushed commit's associated PRs and proceeds only when that exact commit -is the merge of a `release/v*` PR from this repository into the target branch. Ordinary merges, -fork PRs, and pushes without a matching release PR skip verification and publishing. Every job -uses the pushed SHA, so later commits cannot change what is released. +is the merge of a `release/v*` PR opened by `agentcore-devx-automation[bot]` (account ID +`282717993`) from this repository into the target branch. Manually opened release PRs, +ordinary merges, fork PRs, and pushes without a matching release PR skip verification and +publishing. Every job uses the pushed SHA, so later commits cannot change what is released. The prepare job uses `aws-release-4-core`. The check-release and publish jobs stay on `ubuntu-latest` until `release-publish.yml` is allowlisted for the dedicated runner group. diff --git a/.github/workflows/release-publish.yml b/.github/workflows/release-publish.yml index e79e3c5e8..150c17d75 100644 --- a/.github/workflows/release-publish.yml +++ b/.github/workflows/release-publish.yml @@ -25,10 +25,11 @@ jobs: IS_RELEASE=$(gh api --paginate --slurp "repos/$GITHUB_REPOSITORY/commits/$GITHUB_SHA/pulls" \ | jq -r --arg repository "$GITHUB_REPOSITORY" --arg ref "$GITHUB_REF_NAME" --arg sha "$GITHUB_SHA" ' any(.[][]; + # Stable account ID for agentcore-devx-automation[bot]. + .user.id == 282717993 and .merged_at != null and .merge_commit_sha == $sha and .head.repo.full_name == $repository and - .base.repo.full_name == $repository and .base.ref == $ref and (.head.ref | startswith("release/v")) )') From a0a1198fee9590920a16c6617aaa499d1b617cf1 Mon Sep 17 00:00:00 2001 From: Aidan Daly Date: Wed, 9 Sep 2026 20:27:13 +0000 Subject: [PATCH 6/6] fix(packaging): keep dist outputs except native binaries --- .github/workflows/README.md | 7 ++++--- package.json | 5 ++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/.github/workflows/README.md b/.github/workflows/README.md index bf42201c8..38f60028a 100644 --- a/.github/workflows/README.md +++ b/.github/workflows/README.md @@ -59,9 +59,10 @@ The allowlist is scoped to workflow paths and branches; renaming a workflow or c branch requires a runner-group administrator to update it. Keep PR-triggered workflows and the verification matrix off this release-only pool. -The npm package includes only `dist/index.js`, `dist/main.js`, and `dist/assets`, plus standard -package metadata. Native binaries in `dist/bin` are separate GitHub release assets, never npm -package contents, even when packing a workspace that has already compiled them. +The npm package includes `dist` except `dist/bin`, plus standard package metadata. This keeps +additional bundle chunks and runtime assets included as the build evolves. Native binaries in +`dist/bin` are separate GitHub release assets, never npm package contents, even when packing a +workspace that has already compiled them. If publish fails after the merge, rerun the failed `release-publish` jobs. Both the npm publish and the GitHub release steps skip work that already succeeded. Do not re-dispatch diff --git a/package.json b/package.json index 8f70509dd..5ab4d027e 100644 --- a/package.json +++ b/package.json @@ -16,9 +16,8 @@ "node": ">=20.12.0" }, "files": [ - "dist/index.js", - "dist/main.js", - "dist/assets" + "dist", + "!dist/bin" ], "scripts": { "build": "bun scripts/build.ts bundle",