// CI/CD publishing workflow for npm packages using Changesets + npm Trusted Publishers (OIDC). Use when setting up automated npm publishing for monorepos, configuring GitHub Actions for releases, troubleshooting workspace:* protocol resolution issues, fixing "Cannot find module" errors in published packages, or debugging npm OIDC authentication. Covers Bun + Turborepo + Changesets + npm Trusted Publishers with workspace protocol resolution.
| name | publish-package-cicd |
| description | CI/CD publishing workflow for npm packages using Changesets + npm Trusted Publishers (OIDC). Use when setting up automated npm publishing for monorepos, configuring GitHub Actions for releases, troubleshooting workspace:* protocol resolution issues, fixing "Cannot find module" errors in published packages, or debugging npm OIDC authentication. Covers Bun + Turborepo + Changesets + npm Trusted Publishers with workspace protocol resolution. |
Automated npm publishing for Bun monorepos using Changesets + npm Trusted Publishers (OIDC). No npm tokens needed - GitHub Actions authenticates via OIDC.
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)git add .changeset/your-change-name.md
git commit -m "feat: your feature description"
git push origin main
.github/workflows/ci.yml) detects changeset file.github/workflows/publish.yml)For each package to publish:
Publish v0.1.0 manually:
cd packages/your-package
npm publish --access public
Configure Trusted Publisher:
your-github-orgyour-repo-namepublish.ymlFuture releases: Fully automated via GitHub Actions
NPM_TOKEN secret requiredid-token: write permissionProblem: 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.
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'
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
}
}
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.
bunx changeset version FailsSymptom: 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:
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.
# 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
bun publish directlynpm publish for OIDC support