This document describes the complete release process for Legal Markdown JS, including versioning, changelog generation, and deployment procedures.
- Overview
- Conventional Commits
- Semantic Versioning
- Automatic Versioning
- Release Workflow
- Branch Strategy
- Release Commands
- Quality Gates
- Manual Release Override
- Configuration
- GitHub Repository Setup
- Troubleshooting
Legal Markdown JS uses Conventional Commits and semantic-release to automate version generation and changelog creation. This ensures consistent, predictable releases with minimal manual intervention.
- Automated versioning based on commit types
- Changelog generation from commit messages
- NPM package publishing with CI/CD integration
- GitHub releases with detailed release notes
- Quality gates to ensure release stability
feat: New featuresfix: Bug fixesdocs: Documentation changesstyle: Code formatting (whitespace, semicolons, etc.)refactor: Code refactoringperf: Performance improvementstest: Adding or modifying testsbuild: Build system changesci: CI/CD changeschore: Maintenance tasksrevert: Reverting previous commits
<type>[optional scope]: <description>
[optional body]
[optional footer]feat: add new header numbering system
fix: resolve import path resolution issue
docs: update API documentation
feat(cli)!: change default output format to JSON
# Breaking change
feat!: remove deprecated YAML export API
BREAKING CHANGE: The old YAML export method has been removed.
Use the new exportMetadata() function instead.The project uses semantic-versioning with format
MAJOR.MINOR.PATCH:
| Commit Type | Version Increment | Example | Triggers When |
|---|---|---|---|
fix: |
PATCH (1.0.0 → 1.0.1) | Bug fixes | Any fix commit |
feat: |
MINOR (1.0.0 → 1.1.0) | New features | Any feat commit |
feat!: or BREAKING CHANGE: |
MAJOR (1.0.0 → 2.0.0) | Breaking changes | Breaking change detected |
When code is pushed to main, semantic-release follows these steps:
# semantic-release scans all commits since last release
# Example commits since v1.2.0:
git log v1.2.0..HEAD --oneline
# feat: add new export format
# fix: resolve import path issue
# docs: update README
# fix: handle edge case in parser# semantic-release analyzes commit types:
# - feat: triggers MINOR bump
# - fix: triggers PATCH bump
# - No breaking changes: keeps MAJOR same
# Result: 1.2.0 → 1.3.0 (MINOR bump due to feat)# Release notes are auto-generated from commits:
## 1.3.0 (2024-01-15; compare v1.2.0...v1.3.0)
### Features
- add new export format (abc123)
### Bug Fixes
- resolve import path issue (def456)
- handle edge case in parser (ghi789)# semantic-release automatically:
1. Updates package.json version: "1.3.0"
2. Updates CHANGELOG.md with new section
3. Creates git tag: v1.3.0
4. Publishes to NPM registry
5. Creates GitHub release with notes
6. Commits changes back to repo# From main branch
git checkout main
git pull origin main
git checkout -b feature/new-header-system
# Make your changes with conventional commits
git commit -m "feat: add new header numbering system"
git commit -m "test: add tests for header processor"
git commit -m "docs: update header documentation"# Push feature branch
git push origin feature/new-header-system
# Create PR via GitHub UI or CLI
gh pr create --title "feat: add new header numbering system" --body "Description of changes"- Reviewers check the code
- CI/CD runs automatically (tests, linting, build)
- Once approved, merge to
main
When code is merged to main, GitHub Actions automatically:
- Analyzes conventional commits since last release
- Determines new version number (patch/minor/major)
- Generates release notes from commit messages
- Updates CHANGELOG.md
- Creates Git tag
- Publishes to NPM
- Creates GitHub release
# This is done via GitHub UI
# All feature commits become one commit on main
# Final commit message should follow conventional format# Preserves individual commits
# Each commit should follow conventional format
# Release notes include all commits# For urgent production fixes
git checkout main
git checkout -b hotfix/critical-bug-fix
git commit -m "fix: resolve critical parsing issue"
git push origin hotfix/critical-bug-fix
# Create PR, review, and merge immediately
# This triggers automatic patch releasemain: Production-ready code, protected branchdevelop: Integration branch (optional)feature/*: Feature development brancheshotfix/*: Emergency fixes
# Test what next release would be (dry run)
npm run release:dry
# Manual release preparation
npm run prerelease
# Validate commit message
echo "feat: new feature" | npx commitlint# Make commit with interactive help
npm run commit
# Manual version bumping (if needed)
npm version patch # 0.1.0 → 0.1.1
npm version minor # 0.1.0 → 0.2.0
npm version major # 0.1.0 → 1.0.0All PRs must pass:
- ✅ TypeScript compilation
- ✅ ESLint checks
- ✅ Prettier formatting
- ✅ All tests passing
- ✅ Build successful
- ✅ No high/critical security vulnerabilities
You can force specific version bumps:
# Force MINOR release (even with only fixes)
git commit -m "fix: critical security issue
Release-As: minor"
# Force MAJOR release
git commit -m "feat: new feature
Release-As: major".commitlintrc.json:
{
"extends": ["@commitlint/config-conventional"],
"rules": {
"subject-max-length": [2, "always", 100],
"header-max-length": [2, "always", 100],
"body-max-line-length": [2, "always", 200]
}
}.releaserc.json:
{
"branches": ["main"],
"plugins": [
"@semantic-release/commit-analyzer",
"@semantic-release/release-notes-generator",
"@semantic-release/changelog",
"@semantic-release/npm",
"@semantic-release/github",
"@semantic-release/git"
]
}Configure in Settings > Branches:
- Protect
mainbranch:- ✅ Require pull request reviews before merging
- ✅ Require status checks to pass before merging
- ✅
Test (Node 16) - ✅
Test (Node 18) - ✅
Test (Node 20) - ✅
Security Audit
- ✅
- ✅ Require branches to be up to date before merging
- ✅ Include administrators
- ✅ Allow squash merging (recommended)
Configure in Settings > Secrets and Variables > Actions:
- Required secrets:
NPM_TOKEN: NPM token for publishing packagesGITHUB_TOKEN: Created automatically by GitHub
Our workflows trigger on:
- CI Pipeline (
.github/workflows/ci.yml):- Push to
mainordevelop - Pull requests to
mainordevelop
- Push to
- Release Pipeline (
.github/workflows/release.yml):- Push to
mainbranch only - Skipped if commit message contains
[skip ci]
- Push to
Problem: Code merged to main but no release was created.
Solutions:
- Check if commits follow conventional format
- Verify only
docs,style,refactor,test,chorecommits (these don't trigger releases) - Check GitHub Actions logs for errors
Problem: Expected different version bump.
Solutions:
- Review commit messages for breaking changes
- Check for
!in commit type (indicates breaking change) - Verify
BREAKING CHANGE:footer format
Problem: Release process started but failed.
Solutions:
- Check NPM_TOKEN is valid
- Verify all quality gates passed
- Review GitHub Actions logs
# Test release locally
npm run release:dry
# Check what would be released
npx semantic-release --dry-run
# Validate commits
npx commitlint --from HEAD~1 --to HEAD# Revert the release commit
git revert HEAD
# Delete the git tag
git tag -d v1.2.3
git push origin :refs/tags/v1.2.3
# Unpublish from NPM (within 24 hours)
npm unpublish legal-markdown-js@1.2.3# Add [skip ci] to commit message
git commit -m "docs: update README [skip ci]"# Commits since last release (v2.1.0):
git commit -m "feat: add YAML validation"
git commit -m "feat: improve error messages"
git commit -m "fix: memory leak in parser"
git commit -m "docs: update examples"
# Result: v2.1.0 → v2.2.0 (MINOR)
# Reason: feat commits present, no breaking changes# Commits since last release (v2.2.0):
git commit -m "feat!: change default export format to JSON
BREAKING CHANGE: Default export format changed from YAML to JSON.
Use --format=yaml flag to maintain old behavior."
# Result: v2.2.0 → v3.0.0 (MAJOR)
# Reason: Breaking change detected# Commits since last release (v3.0.0):
git commit -m "fix: handle null values in metadata"
git commit -m "fix: improve error handling"
git commit -m "chore: update dependencies"
# Result: v3.0.0 → v3.0.1 (PATCH)
# Reason: Only fixes, chore doesn't trigger releaseThe changelog is automatically generated based on commits:
- Features: Listed under "### Added"
- Fixes: Listed under "### Fixed"
- Breaking Changes: Listed under "### BREAKING CHANGES"
- Performance: Listed under "### Performance"