CI/CD Versioning Migration Guide
This document provides a complete guide for migrating from git-based versioning to per-service semantic versioning with Changesets.
Table of Contents
Section titled “Table of Contents”- Overview
- What Changed
- Implementation Status
- Migration Timeline
- Testing Plan
- Rollback Plan
- Post-Migration Tasks
Overview
Section titled “Overview”Problem Statement
Section titled “Problem Statement”The current CI/CD pipeline rebuilds all Docker images on every push, regardless of which services actually changed. Images are tagged with git-based versions (e.g., staging-a1b2c3d) that don’t convey semantic meaning about changes.
Solution
Section titled “Solution”Implement per-service semantic versioning using Changesets:
- Each app gets independent semantic versions (1.2.3 format)
- Only services with changes get new versions and Docker builds
- Developers document changes via changeset files
- Automated changelog generation
- Enforced change documentation via pre-commit hooks
What Changed
Section titled “What Changed”Files Created
Section titled “Files Created”.changeset/├── config.json # Changesets configuration└── README.md # Changesets documentation
.github/├── workflows/│ ├── version-aware-build.yml # New CI/CD pipeline│ └── release.yml # Automated release workflow└── workflows-backup/ └── ci-cd-pipeline-legacy.yml # Backup of old pipeline (disabled)
.husky/└── pre-commit # Git hook to enforce changesets
docs/├── DEVELOPER_WORKFLOW.md # Developer guide└── ci-cd-versioning-migration.md # This file
apps/pdf-api/└── package.json # New - enables Changesets tracking
apps/pdf-worker/└── package.json # New - enables Changesets trackingFiles Modified
Section titled “Files Modified”package.json # Added Changesets, Husky, lint-stagedapps/webapp/package.json # Changed name to @erp-unlocked/webappapps/crm/package.json # Changed name to @erp-unlocked/crmapps/marketing/package.json # Changed name to @erp-unlocked/marketingNew Dependencies
Section titled “New Dependencies”{ "devDependencies": { "@changesets/cli": "^2.27.1", "@changesets/changelog-github": "^0.5.0", "husky": "^9.0.0", "lint-staged": "^15.0.0" }}New Scripts
Section titled “New Scripts”{ "scripts": { "changeset": "changeset", "changeset:version": "changeset version", "changeset:status": "changeset status", "changeset:pre-check": "changeset status --check", "version:check": "changeset status", "version:preview": "changeset status --verbose", "version:apply": "changeset version", "release:prepare": "pnpm version:apply && pnpm install", "release:publish": "pnpm build && changeset publish", "prepare": "husky install" }}Implementation Status
Section titled “Implementation Status”✅ Completed
Section titled “✅ Completed”- Install and configure Changesets
- Create
.changeset/config.json - Update app package.json files with new names
- Create package.json for Python services (pdf-api, pdf-worker)
- Install Husky and lint-staged
- Create pre-commit hook for changeset enforcement
- Create version-aware CI/CD workflow
- Create automated release workflow
- Create developer documentation
- Backup existing CI/CD pipeline
🔄 Pending
Section titled “🔄 Pending”- Test changeset workflow on feature branch
- Test version-aware build on staging
- Verify Docker image tagging works correctly
- Test deployment to staging environment
- Update team documentation
- Train team on new workflow
- Deploy to production
Migration Timeline
Section titled “Migration Timeline”Phase 1: Foundation (Week 1)
Section titled “Phase 1: Foundation (Week 1)”Day 1-2: Setup
- Install dependencies
- Configure Changesets
- Update package configurations
- Create documentation
Day 3-4: Testing
- Create test branch
- Make sample changes
- Generate changesets
- Verify changeset status output
Day 5: Review
- Team review of changes
- Documentation review
- Pre-commit hook testing
Phase 2: Staging Deployment (Week 2)
Section titled “Phase 2: Staging Deployment (Week 2)”Day 1-2: Branch Testing
- Merge changes to staging branch
- Verify version-aware build runs
- Check Docker image tags
- Verify only changed services build
Day 3-4: Deployment Testing
- Test staging deployments
- Verify webhook calls work
- Check service versions in deployment
- Test rollback procedures
Day 5: Validation
- Full end-to-end test
- Documentation updates
- Team training session
Phase 3: Production Deployment (Week 3)
Section titled “Phase 3: Production Deployment (Week 3)”Day 1-2: Preparation
- Create production changeset
- Generate version bump PR
- Review and approve PR
Day 3: Production Deploy
- Merge to main
- Monitor automated release
- Verify production deployments
- Check Docker image versions
Day 4-5: Stabilization
- Monitor for issues
- Address any problems
- Update documentation based on learnings
Phase 4: Cleanup (Week 4)
Section titled “Phase 4: Cleanup (Week 4)”- Delete old CI/CD pipeline
- Archive legacy documentation
- Update README files
- Collect team feedback
Testing Plan
Section titled “Testing Plan”1. Local Testing
Section titled “1. Local Testing”Test the changeset workflow locally before pushing:
# Create a feature branchgit checkout -b test/changeset-workflow
# Make a small change to webappecho "// test change" >> apps/webapp/src/pages/index.astro
# Create changesetpnpm changeset# Select: @erp-unlocked/webapp# Type: patch# Summary: Test changeset workflow
# Try to commit without changeset (should fail)git add apps/webapp/src/pages/index.astrogit commit -m "test: change"# Expected: Pre-commit hook should block
# Commit with changeset (should succeed)git add .changeset/*.mdgit commit -m "test: verify changeset workflow"# Expected: Commit succeeds
# Check changeset statuspnpm version:check# Expected: Shows webapp with patch version bump
# Push and create PRgit push origin test/changeset-workflow2. PR Build Testing
Section titled “2. PR Build Testing”After creating a PR to staging:
# Monitor GitHub Actions# Expected outcomes:# - detect-versions job runs successfully# - webapp-changed = true, webapp-version = pr-{sha}# - build-and-push job builds only webapp# - Other services not built3. Staging Deployment Testing
Section titled “3. Staging Deployment Testing”After merging to staging:
# Monitor GitHub Actions# Expected outcomes:# - Changeset status shows pending releases# - Docker images built with PR version# - Staging webhook called for changed services# - Services deployed to staging environment4. Production Release Testing
Section titled “4. Production Release Testing”Test the full release cycle:
# Merge to main# Expected outcomes:# - release.yml workflow creates "Version Packages" PR# - PR updates package.json versions# - PR generates CHANGELOG.md entries# - Changesets consumed and removed
# Merge Version Packages PR# Expected outcomes:# - version-aware-build.yml triggers# - Docker images tagged with semantic versions (1.2.3)# - Production webhooks called# - Services deployed to productionRollback Plan
Section titled “Rollback Plan”If issues arise during migration, follow this rollback procedure:
Quick Rollback (< 1 hour)
Section titled “Quick Rollback (< 1 hour)”-
Restore old CI/CD pipeline
Terminal window mv .github/workflows-backup/ci-cd-pipeline-legacy.yml .github/workflows/ci-cd-pipeline.ymlmv .github/workflows/version-aware-build.yml .github/workflows-backup/version-aware-build-disabled.ymlgit add .github/git commit -m "rollback: restore legacy CI/CD pipeline"git push -
Disable pre-commit hook
Terminal window mv .husky/pre-commit .husky/pre-commit.disabledgit add .husky/git commit -m "rollback: disable changeset pre-commit hook"git push -
Notify team
- Send Slack message about rollback
- Document issues encountered
- Plan remediation
Full Rollback (if needed)
Section titled “Full Rollback (if needed)”# Create rollback branchgit checkout -b rollback/changesets-migration
# Revert all changeset-related changesgit revert <migration-commit-range>
# Or reset to pre-migration commitgit reset --hard <pre-migration-commit>
# Force push (only if necessary and approved)git push origin rollback/changesets-migration --force
# Create emergency PR# Merge after approvalRollback Verification
Section titled “Rollback Verification”After rollback:
- CI/CD pipeline building all services
- Docker tags using git-based versions
- Deployments working correctly
- No breaking changes for developers
Post-Migration Tasks
Section titled “Post-Migration Tasks”Documentation Updates
Section titled “Documentation Updates”-
Update README.md
- Add section on changesets workflow
- Link to DEVELOPER_WORKFLOW.md
- Update contribution guidelines
-
Update CONTRIBUTING.md (create if doesn’t exist)
- Add changeset requirements
- Explain version types
- Provide examples
-
Update PR Template (create if doesn’t exist)
## Changes- [ ] I have created a changeset describing my changes- [ ] I have selected the appropriate version type (patch/minor/major)## Changeset Summary<!-- Paste your changeset summary here -->
Team Training
Section titled “Team Training”-
Training Session (1 hour)
- Overview of changesets
- Live demo of workflow
- Q&A session
-
Training Materials
- Record training session
- Create video walkthrough
- Update onboarding docs
-
Support Channel
- Create #changesets-help Slack channel
- Designate changeset champions
- Document FAQs
Monitoring and Alerts
Section titled “Monitoring and Alerts”-
Set up monitoring
- Track CI/CD run times (should decrease)
- Monitor Docker build frequency per service
- Track changeset compliance rate
-
Create alerts
- Alert if builds fail
- Alert if changesets missing in merged PRs
- Alert if releases fail
Process Improvements
Section titled “Process Improvements”-
Weekly Review (First Month)
- Review changeset quality
- Identify pain points
- Update documentation
-
Monthly Metrics
- CI/CD time savings
- Number of deployments per service
- Changeset compliance rate
- Team satisfaction
Expected Outcomes
Section titled “Expected Outcomes”Before Migration
Section titled “Before Migration”- ❌ All 5 services rebuilt on every change
- ❌ Docker tags:
staging-a1b2c3d,main-b4c5d6e - ❌ Manual changelog management
- ❌ No version enforcement
- ❌ ~15 minute CI/CD runs
After Migration
Section titled “After Migration”- ✅ Only changed services rebuilt
- ✅ Docker tags:
1.2.3,2.0.1,latest - ✅ Automatic changelog generation
- ✅ Enforced change documentation
- ✅ ~5-10 minute CI/CD runs (for single service)
- ✅ Clear release history per service
- ✅ Semantic versioning for all images
Risk Mitigation
Section titled “Risk Mitigation”Risk: Breaking changes in Changesets
Section titled “Risk: Breaking changes in Changesets”Mitigation:
- Keep legacy pipeline as backup
- Test thoroughly on staging
- Document rollback procedures
- Have team available during migration
Risk: Team adoption challenges
Section titled “Risk: Team adoption challenges”Mitigation:
- Comprehensive documentation
- Training sessions
- Support channel
- Gradual rollout
Risk: CI/CD failures
Section titled “Risk: CI/CD failures”Mitigation:
- Test on feature branches first
- Monitor closely during rollout
- Quick rollback plan ready
- Team on standby
Risk: Docker image versioning issues
Section titled “Risk: Docker image versioning issues”Mitigation:
- Test version detection thoroughly
- Verify image tags before deploying
- Keep legacy tags initially
- Document version mapping
Success Metrics
Section titled “Success Metrics”Track these metrics to measure migration success:
-
CI/CD Efficiency
- Average build time per push
- Number of services built per push
- Cost savings (compute time)
-
Developer Experience
- Time to create changeset (< 2 minutes)
- Changeset compliance rate (target: 100%)
- Pre-commit hook bypass rate (< 5%)
- Developer satisfaction score
-
Release Quality
- Changelog completeness
- Version bump accuracy
- Number of version-related incidents
- Deployment success rate
-
Operational
- Number of unnecessary builds eliminated
- Deployment frequency per service
- Rollback frequency
- Time to resolve issues
Q: Do I need a changeset for every commit?
Section titled “Q: Do I need a changeset for every commit?”A: No, only for commits that change code in apps/ or packages/. Config changes, documentation updates, and CI changes typically don’t need changesets.
Q: Can I skip the pre-commit hook?
Section titled “Q: Can I skip the pre-commit hook?”A: Yes, using git commit --no-verify, but this should be rare. Most code changes should have a changeset.
Q: What if multiple people create changesets?
Section titled “Q: What if multiple people create changesets?”A: That’s fine! Each changeset is a separate file. They’ll all be processed during the next release.
Q: How do I know what version type to use?
Section titled “Q: How do I know what version type to use?”A: Follow semantic versioning:
- patch: Bug fixes, no new features
- minor: New features, backward compatible
- major: Breaking changes
Q: What happens to old Docker images?
Section titled “Q: What happens to old Docker images?”A: They remain in the registry. You can clean up old images manually or set up retention policies in GHCR.
Q: Can I change a version type after creating a changeset?
Section titled “Q: Can I change a version type after creating a changeset?”A: Yes, just edit the .changeset/*.md file and change patch, minor, or major.
Q: What if I forget to create a changeset?
Section titled “Q: What if I forget to create a changeset?”A: The pre-commit hook will remind you. If you’ve already pushed, create a changeset in a follow-up commit.
Support
Section titled “Support”For questions or issues:
- Check Developer Workflow Guide
- Search existing issues
- Ask in #changesets-help (Slack)
- Create an issue in the repository
References
Section titled “References”- Changesets Documentation
- Semantic Versioning
- Developer Workflow Guide
- ERP-Unlocked Monorepo Guide
- GitHub Actions Documentation
Last Updated: 2025-10-11
Migration Status: ✅ Implementation Complete - Ready for Testing
Maintainers: Development Team