Status: Superseded Date: 2026-01-10 Authors: Development Team
Reviewers: DevOps Team, Architecture Team Supersedes: N/A Superseded
by: ADR-0073 (the changesets implementation plan below was never executed;
nx release is the mechanism actually wired into release.yml and owns
versioning/publishing)
Context and Problem Statement#
The Oshun monorepo requires a unified versioning and release strategy to manage package versions, generate changelogs, and publish packages across all domains. Currently:
Lilith (Current State):
- No automated versioning or release process
- Manual version bumps in package.json
- No changelog generation
- Version: 0.1.0 (static)
Yemaya (Current State):
- Uses Changesets for versioning (
@changesets/cli) - Configured with GitHub changelog generation
- Scripts:
version-packages,release - Access: restricted (private packages)
- Automated internal dependency updates
We need to standardize on a versioning/release approach that:
- Works well with the Nx monorepo structure
- Supports independent and synchronized versioning
- Generates meaningful changelogs
- Integrates with CI/CD for automated releases
- Handles both public npm packages and private deployable services
The main options are:
- Changesets: Community-driven, battle-tested approach (already used by Yemaya)
- Nx Release: Nx-native release management (newer, integrated with Nx)
Decision Drivers#
- Nx Integration: Seamless integration with Nx workspace
- Changelog Quality: Meaningful, well-formatted changelogs
- Independent Versioning: Ability to version packages independently
- Fixed Versioning: Option to lock certain packages to same version
- Automation: CI/CD integration for automated releases
- Developer Experience: Simple workflow for contributors
- Existing Investment: Yemaya's Changesets configuration
- Ecosystem Support: npm/GitHub integration, community adoption
- Flexibility: Support for various release strategies
Considered Options#
Option 1: Changesets (Recommended)#
Description: Use Changesets for version management and changelog generation. Changesets is a popular approach used by Babel, Atlassian, and many other monorepos.
Workflow:
Developer creates PR
│
▼
Run `pnpm changeset` to create changeset file
│
▼
PR merged with changeset
│
▼
CI runs `changeset version` (bumps versions, updates changelogs)
│
▼
Version PR created/updated
│
▼
Version PR merged
│
▼
CI runs `changeset publish` (publishes to npm)
Pros:
- ✅ Already In Use: Yemaya has working Changesets configuration
- ✅ Battle-Tested: Used by major projects (Babel, Atlassian, Pnpm itself)
- ✅ Flexible: Supports independent, fixed, and linked versioning
- ✅ Rich Ecosystem: Multiple changelog formatters, bot integrations
- ✅ Explicit Intent: Developers explicitly declare change significance
- ✅ Human-Readable Changelogs: Generates quality CHANGELOG.md
- ✅ Works with pnpm: First-class pnpm workspace support
- ✅ GitHub Integration: Changeset bot, PR changelogs
Cons:
- ❌ Learning Curve: Developers need to learn
pnpm changesetworkflow - ❌ Extra Step: Requires changeset creation in each PR
- ❌ Not Nx-Native: Separate tool from Nx ecosystem
- ❌ Two-PR Process: Version bump is a separate PR
Cost: Low - minimal setup, leverage existing Yemaya config Risk: Low - proven at scale Effort: 1-2 days to configure for full monorepo
Option 2: Nx Release#
Description: Use Nx's built-in release management (nx release). Nx Release
is newer but designed specifically for Nx workspaces.
Workflow:
Developer creates PR with conventional commit
│
▼
PR merged
│
▼
CI runs `nx release` (analyzes commits, bumps versions)
│
▼
Git tags created, changelogs updated
│
▼
Packages published to npm
Pros:
- ✅ Nx-Native: Integrated with Nx, uses project graph
- ✅ Conventional Commits: Automatic version bumps from commit messages
- ✅ Single Command:
nx releasehandles everything - ✅ Project Awareness: Understands Nx project dependencies
- ✅ Git Integration: Automatic tagging and changelog
Cons:
- ❌ Newer Tool: Less battle-tested than Changesets
- ❌ Conventional Commit Enforcement: Requires strict commit conventions
- ❌ Less Flexible: Fewer options for changelog customization
- ❌ Would Discard: Yemaya's existing Changesets setup
- ❌ Learning New Tool: Team needs to learn Nx release specifics
Cost: Medium - need to migrate from Changesets Risk: Medium - less proven than Changesets Effort: 3-4 days for setup and migration
Option 3: Manual/Script-Based#
Description: Custom scripts for version management without a dedicated tool.
Pros:
- ✅ Full Control: Complete flexibility
- ✅ No Dependencies: No external tools
Cons:
- ❌ Reinventing Wheel: Solved problem, no need for custom solution
- ❌ Maintenance Burden: Custom code to maintain
- ❌ Error Prone: Manual processes are error-prone
- ❌ No Ecosystem: No bot integrations, changelog generation
Cost: High - significant custom development Risk: High - maintenance burden, errors Effort: 2+ weeks for complete solution
Decision Outcome#
Chosen option: Option 1 - Changesets
Justification:
Changesets is the optimal choice for the Oshun monorepo because:
-
Existing Investment: Yemaya already has a working Changesets configuration. This provides a proven foundation that can be extended to the full monorepo.
-
Maturity: Changesets is battle-tested by major projects including Babel, Atlassian, pnpm itself, and hundreds of open-source monorepos. Nx Release, while promising, is newer and less proven.
-
Explicit Intent: The changeset workflow requires developers to explicitly declare the significance of their changes (major/minor/patch). This produces higher-quality changelogs than automated commit message parsing.
-
Flexibility: Changesets supports multiple versioning strategies:
- Independent: Each package versioned independently
- Fixed: Groups of packages locked to same version
- Linked: Packages always bump together but can have different versions
-
pnpm Integration: Changesets has first-class support for pnpm workspaces, which aligns with ADR-0002.
-
Ecosystem: Rich ecosystem of tools (changeset bot, changelog formatters, GitHub Action) that would take significant effort to replicate with Nx Release.
Nx Compatibility Note: Changesets works well alongside Nx. Nx handles task orchestration (build, test, lint), while Changesets handles versioning and publishing. This separation of concerns is clean and well-established.
Implementation Plan:
-
Phase 1: Root Configuration (Day 1)
- Create
.changeset/config.jsonat oshun root - Configure changelog format (GitHub-linked)
- Define fixed/linked package groups
- Add changeset scripts to root package.json
- Create
-
Phase 2: Package Groups (Day 1)
- Define fixed groups for tightly-coupled packages
- Configure independent versioning for standalone packages
- Set up internal dependency update rules
-
Phase 3: CI/CD Integration (Day 2)
- Configure GitHub Actions for version PR creation
- Set up automated npm publishing
- Configure changeset bot for PR status
-
Phase 4: Documentation (Day 2)
- Create contributor guide for changesets
- Document release process
- Add PR template with changeset reminder
Success Metrics:
- All package releases tracked via changesets
- Changelogs generated for all releases
- Zero manual version bumps
- Release process takes < 5 minutes from merge to publish
- Contributors successfully create changesets in 95% of PRs
Review Schedule: 60 days post-implementation
Implementation Details#
Technical Specifications#
Root Changeset Configuration:
// .changeset/config.json
{
"$schema": "https://unpkg.com/@changesets/config@3.0.0/schema.json",
"changelog": ["@changesets/changelog-github", { "repo": "oshun/oshun" }],
"commit": false,
"fixed": [
// Packages that always share the same version
["@oshun/types", "@oshun/errors", "@oshun/config"],
["@oshun/proto", "@oshun/openapi"]
],
"linked": [
// Packages that bump together but can have different versions
["@oshun/auth", "@oshun/auth-client"],
["@oshun/events", "@oshun/events-client"]
],
"access": "public",
"baseBranch": "main",
"updateInternalDependencies": "patch",
"ignore": [
// Private packages that don't get published
"@oshun/tools-*",
"@lilith/service-*",
"@yemaya/app-*"
],
"___experimentalUnsafeOptions_WILL_CHANGE_IN_PATCH": {
"onlyUpdatePeerDependentsWhenOutOfRange": true
}
}
Root Package.json Scripts:
{
"scripts": {
"changeset": "changeset",
"changeset:add": "changeset add",
"changeset:status": "changeset status",
"version": "changeset version && pnpm install --lockfile-only",
"release": "pnpm build && changeset publish",
"release:dry": "changeset publish --dry-run"
}
}
Package Groups Explanation:
Fixed Groups (same version number):
┌────────────────────────────────────────┐
│ @oshun/types v1.0.0 │
│ @oshun/errors v1.0.0 ──► Always │
│ @oshun/config v1.0.0 same │
└────────────────────────────────────────┘
Linked Groups (bump together, different versions):
┌────────────────────────────────────────┐
│ @oshun/auth v2.3.0 │
│ @oshun/auth-client v1.5.0 ──► Bump │
│ together │
└────────────────────────────────────────┘
Independent (versioned separately):
┌──────────────────┐ ┌──────────────────┐
│ @oshun/isis │ │ @oshun/sophia │
│ v3.2.1 │ │ v1.0.5 │
└──────────────────┘ └──────────────────┘
GitHub Action for Version PR:
# .github/workflows/release.yml
name: Release
on:
push:
branches:
- main
concurrency: ${{ github.workflow }}-${{ github.ref }}
jobs:
release:
name: Release
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Setup pnpm
uses: pnpm/action-setup@v3
with:
version: 10
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: 20
cache: 'pnpm'
- name: Install Dependencies
run: pnpm install
- name: Create Release Pull Request or Publish
id: changesets
uses: changesets/action@v1
with:
version: pnpm run version
publish: pnpm run release
title: 'chore: release packages'
commit: 'chore: release packages'
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
Changeset Bot Configuration:
# .github/changeset-bot.yml
# Automatically comments on PRs missing changesets
sinceMajor: true
PR Template Addition:
<!-- .github/pull_request_template.md -->
## Description
<!-- Describe your changes -->
## Checklist
- [ ] I have added a changeset (`pnpm changeset`) if this PR includes
user-facing changes
- [ ] Tests pass locally
- [ ] Documentation updated if needed
## Changeset
<!--
If this PR affects published packages, run:
pnpm changeset
Then select:
- Which packages are affected
- Semver bump type (major/minor/patch)
- Summary of changes for changelog
-->
Versioning Strategy by Package Type#
| Package Type | Strategy | Example |
|---|---|---|
| Shared Foundation | Fixed | @oshun/types, @oshun/errors, @oshun/config - always same version |
| Contracts | Fixed | @oshun/proto, @oshun/openapi - breaking changes affect all consumers |
| Domain Libraries | Independent | @oshun/isis-, @oshun/sophia- - version based on their own changes |
| Client SDKs | Linked | @oshun/auth + @oshun/auth-client - bump together |
| Internal Tools | Ignored | @oshun/tools-* - not published |
| Services | Ignored | @lilith/service-, @yemaya/app- - deployed, not published |
Semver Guidelines#
MAJOR version: Breaking changes to public API
- Removing exported functions/types
- Changing function signatures
- Removing fields from interfaces
- Changing behavior in incompatible ways
MINOR version: New features, backward-compatible
- Adding new exports
- Adding optional fields
- Adding new functionality
- Deprecating (not removing) features
PATCH version: Bug fixes, backward-compatible
- Bug fixes
- Performance improvements
- Documentation updates
- Internal refactoring
Changelog Format#
# @oshun/types
## 1.2.0
### Minor Changes
- feat: add AssetMetadata type for generation outputs (#123)
Added new AssetMetadata interface that includes provenance, licensing, and
lineage information for generated assets.
- feat: add Result<T, E> utility type (#125)
### Patch Changes
- fix: correct ProjectId branded type (#124)
- Updated dependencies
- @oshun/errors@1.1.0
Migration Strategy#
From Yemaya:
- Copy
.changeset/config.jsonto oshun root - Update repo reference
- Define package groups for new structure
- Test with dry-run publish
For Lilith Packages:
- Add to Changesets scope (remove from ignore if needed)
- Set initial versions
- Create initial changeset if needed
Consequences#
Positive Consequences#
- ✅ Consistent Releases: All packages follow same release process
- ✅ Quality Changelogs: Human-written, meaningful changelogs
- ✅ Automation: CI/CD handles version bumps and publishing
- ✅ Flexibility: Different strategies for different package types
- ✅ Traceability: Each release linked to PRs and commits
- ✅ Proven Process: Battle-tested workflow
Negative Consequences#
- ❌ Extra Step: Developers must create changesets
- ❌ Learning Curve: Team needs to understand changeset workflow
- ❌ Two PRs: Version bump is separate PR
- ❌ Tool Dependency: Relies on external tool
Risks and Mitigation#
| Risk | Probability | Impact | Mitigation Strategy |
|---|---|---|---|
| Forgotten changesets | Medium | Low | Changeset bot comments on PRs, PR template reminder |
| Wrong semver selection | Medium | Medium | PR review, documented guidelines |
| CI publish failures | Low | Medium | Dry-run before publish, manual fallback |
| Package group misconfiguration | Low | High | Test in staging, careful initial setup |
Compliance and Security#
Security Implications#
- npm Tokens: Stored as GitHub secrets, not in code
- Publish Access: Only CI can publish, not individual developers
- Audit Trail: All releases tracked in GitHub, npm, and changelogs
- 2FA: npm publish protected by token, not password
Compliance Requirements#
- Version History: Complete changelog for each package
- Release Tracking: Git tags for each release
- Reproducibility: Lockfile ensures consistent builds
Monitoring and Observability#
Metrics to Track#
- Release Frequency: Releases per week/month
- Changeset Compliance: % of PRs with changesets
- Publish Success Rate: % of successful publishes
- Time to Publish: Time from merge to npm availability
Alerting Strategy#
- Critical: Publish failure, npm token expiration
- Warning: PR missing changeset for affected packages
- Info: New release published, version PR created
Related Decisions#
Upstream Dependencies#
- ADR-0002: pnpm (Changesets uses pnpm workspace protocol)
- ADR-0001: Git Consolidation (single repo for changesets)
Downstream Impacts#
- CI/CD: GitHub Actions for release automation
- Contributors: Must learn changeset workflow
- Consumers: Semantic versions for dependency management
References#
External Resources#
Internal Resources#
- Yemaya changesets config —
yemaya/.changeset/config.json(pre-consolidation source repo) - ADR-0002: Package Manager
Revision History#
| Version | Date | Author | Changes |
|---|---|---|---|
| 1.0 | 2026-01-10 | Development Team | Initial version |