This document describes the complete workflow for releasing packages to npm in the @epa-wg/cem monorepo.
The repository uses a develop 🠊 main 🠊 publish workflow:
developbranch: Active development and feature workmainbranch: Release-ready code- GitHub Actions: Automated publishing to npm
All development work should happen on the develop branch:
# Ensure you're on develop and up to date
git checkout develop
git fetch origin
git pull origin develop
# Make your changes
# ... edit files ...
# Commit with conventional commit messages
git add .
git commit -m "fix: description of bug fix"
# or
git commit -m "feat: description of new feature"
# Push to develop
git push origin developImportant: Use Conventional Commits format:
fix:- Patch version bump (0.0.x)feat:- Minor version bump (0.x.0)feat!:orBREAKING CHANGE:- Major version bump (x.0.0)
When ready for release, create a PR from develop to main:
-
Via GitHub UI:
- Go to https://github.com/EPA-WG/cem/pulls
- Click "New Pull Request"
- Base:
main🠈 Compare:develop - Create the PR
-
Or via GitHub CLI:
gh pr create --base main --head develop --title "Release: merge develop to main" --body "Preparing for release"
-
Review and Merge:
- Wait for CI checks to pass
- Review the changes
- Merge the PR (use "Merge commit" or "Squash and merge")
After the PR is merged to main, prepare the release locally:
# Switch to main and update
git checkout main
git fetch origin
git pull origin main
# Run exactly one release preparation command.
#
# Normal conventional-commit release:
yarn publish:prepare
# For the 0.1.0 release, use this instead because most release commits are
# not conventional-commit formatted:
yarn publish:prepare 0.1.0What yarn publish:prepare does:
- 🔎 Validates published npm package metadata
- 🔙 Restores
workspace:*protocols for local dependencies - 📦 Runs
nx release- bumps versions from conventional commits or the explicit specifier argument - ❓ Generates/updates CHANGELOG.md files
- 🔄 Replaces
workspace:*with semantic versions (e.g.,^0.1.0) - 🔒 Updates
yarn.lock - ✏️ Amends the release commit
- 🏷️ Creates git tag (e.g.,
0.1.0) - ⬆️ Pushes commit and tag to GitHub
Example output:
🚀 Starting release preparation...
🔙 Restoring workspace protocol for release...
✓ Workspace protocol restoration complete
📦 Running Nx release...
@epa-wg/cem
✍️ New version 0.0.5 written to manifest: package.json
...
✅ Release preparation complete!
🎉 Ready to publish via CI/CD
After pushing, GitHub Actions automatically publishes to npm:
-
Monitor the workflow:
- Go to https://github.com/EPA-WG/cem/actions/workflows/publish.yml
- Find the workflow run for your tag (e.g.,
0.0.5)
-
Check the status:
- ✅ Success - Packages published to npm
- L Failure - Check logs for errors
-
Verify on npm:
npm view @epa-wg/cem-theme version npm view @epa-wg/cem-components version npm view @epa-wg/cem-elements version npm view @epa-wg/custom-element version
Or visit:
After @epa-wg/cem-theme is published, refresh the native Figma library so the CEM UI Kit uses the released token
artifacts, not a local build.
-
Confirm the released package version is available:
npm view @epa-wg/cem-theme version
-
Open the Figma refresh prompt: Developer Prompt: Refresh Native Figma Variables
-
Refresh the
CEM Tokenscollection in theCEM UI Kitfrom the released npm CDN files:https://unpkg.com/@epa-wg/cem-theme@<version>/dist/lib/tokens/figma/cem-light.tokens.json https://unpkg.com/@epa-wg/cem-theme@<version>/dist/lib/tokens/figma/cem-dark.tokens.json https://unpkg.com/@epa-wg/cem-theme@<version>/dist/lib/tokens/figma/cem-contrast-light.tokens.json https://unpkg.com/@epa-wg/cem-theme@<version>/dist/lib/tokens/figma/cem-contrast-dark.tokens.json https://unpkg.com/@epa-wg/cem-theme@<version>/dist/lib/tokens/figma/cem-native.tokens.json -
Validate the
01 Tokenspage in Figma: CEM UI Kit Tokens page
After a successful release, the main branch is ahead of develop. Sync them:
# Switch to develop
git checkout develop
# Fetch latest changes
git fetch origin
# Merge main into develop
git merge origin/main
# Push updated develop
git push origin developThis preserves the complete history and is the safest approach.
If you want a linear history and comfortable with rebasing:
# Switch to develop
git checkout develop
# Fetch latest changes
git fetch origin
# Rebase develop onto main
git rebase origin/main
# Force push (only if no one else is working on develop!)
git push origin develop --force-with-leaseWarning: Only use rebase if:
- You're the only one working on
develop, or - You've coordinated with your team
If develop has no unique commits and should match main exactly:
# Switch to develop
git checkout develop
# Reset to match main
git reset --hard origin/main
# Force push
git push origin develop --force-with-leaseWarning: This discards all commits on develop not in main.
If the release script fails because the tag exists:
# Delete local and remote tag
git tag -d 0.0.5
git push origin :refs/tags/0.0.5
# Run publish:prepare again
yarn publish:prepareIf you need to change the version:
# Manually edit version in package.json files
# Then commit and create tag manually
git add package.json packages/*/package.json
git commit -m "chore(release): publish 0.0.5"
git tag 0.0.5
git push origin main --tagsCheck the logs at: https://github.com/EPA-WG/cem/actions/workflows/publish.yml
Common issues:
- NPM_ACCESS_TOKEN expired - Update secret in GitHub settings
- Version already published - Can't republish the same version
- Build failed - Fix code issues and create a new release
After syncing from main:
git checkout develop
git fetch origin
git merge origin/main
# If conflicts occur:
# 1. Resolve conflicts in your editor
# 2. Stage resolved files
git add .
# 3. Complete the merge
git commit
# 4. Push
git push origin develop- All changes committed to
develop - PR from
developtomaincreated and reviewed - PR merged to
main - Checked out
mainand pulled latest - Ran
yarn publish:prepare 0.1.0locally for this release - Verified GitHub Actions workflow succeeded
- Verified packages on npm
- Refreshed the CEM UI Kit native Figma variables from the published npm CDN files
- Validated the CEM UI Kit
01 Tokenspage - Synced
developbranch withmain - Continued development on
develop
Version bumps are determined by commit messages:
| Commit Type | Example | Version Bump |
|---|---|---|
fix: |
fix: correct button alignment |
0.0.x (patch) |
feat: |
feat: add dark mode |
0.x.0 (minor) |
feat!: |
feat!: redesign API |
x.0.0 (major) |
BREAKING CHANGE: |
See below | x.0.0 (major) |
Example with breaking change:
feat: redesign API
BREAKING CHANGE: The old API has been removed.
Use the new `createTheme()` function instead.
Prepares and pushes a release (versions, changelog, tag).
Location: ./tools/scripts/publish-prepare.sh
Steps:
- Validates package metadata
- Restores workspace protocols
- Bumps versions via
nx release - Replaces workspace protocols with semantic versions
- Updates lockfile
- Amends commit and recreates tag
- Pushes to remote
-
tools/scripts/restore-workspace-protocol.cjsConverts semantic versions back toworkspace:* -
tools/scripts/replace-workspace-protocol.cjsConvertsworkspace:*to semantic versions (e.g.,^0.0.5) -
tools/scripts/sync-release-version.cjsSynchronizes versions across packages (called by Nx)