Publish Package CI/CD
Automated npm publishing for Bun monorepos using Changesets + npm Trusted Publishers (OIDC). No npm tokens needed - GitHub Actions authenticates via OIDC.
Core Workflow
1. Create Changeset (Manual File Creation)
CRITICAL: Never run bunx changeset interactively. Create changeset files manually to avoid the interactive CLI:
cat > .changeset/your-change-name.md << 'EOF' --- "package-name": patch --- Description of the change EOF
Version bump types:
- •
patch- Bug fixes, minor updates (0.0.x) - •
minor- New features, backwards compatible (0.x.0) - •
major- Breaking changes (x.0.0)
2. Commit and Push
git add .changeset/your-change-name.md git commit -m "feat: your feature description" git push origin main
3. Automated Release Flow
- •Changesets Action (
.github/workflows/ci.yml) detects changeset file - •Creates/updates "chore: release packages" PR with version bumps + CHANGELOG
- •On PR merge → triggers publish workflow (
.github/workflows/publish.yml) - •Publishes to npm via OIDC (no npm token)
Trusted Publishers (OIDC) Setup
Initial Package Setup (One-Time)
For each package to publish:
- •
Publish v0.1.0 manually:
bashcd packages/your-package npm publish --access public
- •
Configure Trusted Publisher:
- •Go to https://www.npmjs.com/package/your-package/access
- •Click "Trusted Publishers" → "Add"
- •Fill in:
- •Organization:
your-github-org - •Repository:
your-repo-name - •Workflow:
publish.yml
- •Organization:
- •Save
- •
Future releases: Fully automated via GitHub Actions
How OIDC Works
- •No
NPM_TOKENsecret required - •GitHub Actions has
id-token: writepermission - •npm packages configured with Trusted Publisher pointing to repo + workflow
- •npm CLI 11.5.1+ auto-detects OIDC environment
- •Provenance attestations generated automatically
workspace:* Protocol Resolution
Problem: workspace:* in package.json dependencies doesn't resolve during npm publish, causing "Cannot find module" errors for consumers.
Solution: Use custom publish script with two-step process:
# 1. Sync lockfile (resolves workspace:* from lockfile) bun install # 2. Pack tarball (resolves workspace:* to actual versions) bun pm pack # 3. Publish tarball (supports npm OIDC) npm publish <tarball>
Why not bun publish? Bun resolves workspace protocols but doesn't support npm OIDC - requires npm login.
See references/publish-script.ts for full implementation.
Ignored Packages (Non-Published)
Exclude packages from publishing in .changeset/config.json:
{
"ignore": ["@swarmtools/web", "docs-app"]
}
Important: Changeset ignore only affects versioning, NOT builds. Must also exclude from turbo:
# In CI, exclude ignored packages from build bun turbo build --filter='!@swarmtools/web'
Common Issues
CLI Bin Script "Cannot find module"
Symptom: Published package works, but CLI bin script fails with Cannot find module '@clack/prompts'.
Root cause: Bin script imports are runtime dependencies, not devDependencies.
Fix: Move ALL bin script imports to dependencies in package.json:
{
"dependencies": {
"@clack/prompts": "^0.7.0", // Used by bin/cli.ts
"commander": "^11.0.0" // Used by bin/cli.ts
}
}
Lockfile Stale After Changeset Bump
Symptom: Publish picks up old versions of workspace:* dependencies.
Root cause: bun pm pack resolves from lockfile, which is stale after version bumps.
Fix: Run bun install BEFORE bun pm pack:
bun install # Sync lockfile with new versions bun pm pack # Now packs with correct versions npm publish <tarball>
See references/publish-script.ts - automatically handles this.
Local bunx changeset version Fails
Symptom: Error: GITHUB_TOKEN not found
Root cause: Changesets needs GitHub API access for PR/changelog generation. Works in CI (has GITHUB_TOKEN), fails locally.
Fix: Don't run bunx changeset version or bunx changeset publish locally. Let CI handle it:
- •Create changeset file manually
- •Push to main
- •CI creates release PR
- •Merge PR → auto-publishes
Bun Publish vs npm Publish
Avoid bun publish - doesn't support npm OIDC (requires npm login).
Use npm publish <tarball> - supports OIDC + resolves workspace protocols when publishing tarball created by bun pm pack.
Reference Files
- •references/publish-workflow.yml - Full GitHub Actions workflow with OIDC + workspace resolution
- •references/changeset-config.json - Changeset configuration with ignored packages
- •references/publish-script.ts - Custom publish script handling workspace:* resolution
Commands Reference
# Create changeset (manual file creation) cat > .changeset/fix-thing.md << 'EOF' --- "pkg-name": patch --- Fixed the thing EOF # Preview version bumps (optional, informational only) bunx changeset status # Build packages (exclude ignored) bun turbo build --filter='!@swarmtools/web' # Publish (in CI only, via publish.yml) bun install # Sync lockfile bun pm pack # Create tarball with resolved workspace:* npm publish <tarball> # Publish with OIDC
Tracking Issues
- •Bun native npm token support: https://github.com/oven-sh/bun/issues/15601
- •When resolved, can switch to
bun publishdirectly - •Currently must use
npm publishfor OIDC support
- •When resolved, can switch to