Release Guide¶
This guide covers the complete release process for MIDI Markdown, from version bumping to publishing releases.
Table of Contents¶
- Version Numbering
- Pre-Release Checklist
- Release Process
- Post-Release Tasks
- Hotfix Releases
- Troubleshooting
Version Numbering¶
MIDI Markdown follows Semantic Versioning 2.0.0:
Version Components¶
- MAJOR: Incompatible API/syntax changes (breaking changes)
- MINOR: New features (backwards-compatible)
- PATCH: Bug fixes (backwards-compatible)
Examples¶
0.1.0→0.1.1- Patch (bug fix)0.1.0→0.2.0- Minor (new feature)0.1.0→1.0.0- Major (breaking change)1.0.0-alpha.1- Pre-release version1.0.0-beta.2- Beta release
Pre-1.0.0 Releases¶
During initial development (0.x.y): - Breaking changes can occur in minor versions - The API is not yet stable - Production use is not recommended
Release Types¶
| Type | When to Use | Example |
|---|---|---|
| Patch | Bug fixes, documentation, internal refactoring | 0.1.0 → 0.1.1 |
| Minor | New features, deprecations (with warnings) | 0.1.0 → 0.2.0 |
| Major | Breaking changes, API redesign | 0.9.0 → 1.0.0 |
| Alpha | Early testing, incomplete features | 1.0.0-alpha.1 |
| Beta | Feature-complete, testing phase | 1.0.0-beta.1 |
| RC | Release candidate, final testing | 1.0.0-rc.1 |
Pre-Release Checklist¶
Before starting a release, ensure all these items are complete:
1. Code Quality¶
- All tests pass:
just test - Code is formatted:
just fmt-check - No linting errors:
just lint - Type checking passes:
just typecheck - Coverage is maintained or improved:
just test-cov
2. Documentation¶
- CHANGELOG.md updated with all changes in [Unreleased] section
- README.md is up-to-date
- All examples compile successfully:
just validate-examples - Device libraries validate:
just validate-devices - Documentation builds:
just docs-build - User guides reflect new features
- Developer guides updated if architecture changed
3. Examples and Devices¶
- All example files work:
just validate-examples - Device libraries are valid:
just validate-devices - New features have example files
- Example README.md is updated
4. Git Repository¶
- All changes committed to main branch
- Branch is up-to-date with origin:
git pull origin main - No uncommitted changes:
git status - CI/CD passes on GitHub Actions
5. Version Planning¶
- Decide version number (major/minor/patch)
- Review all changes since last release
- Ensure CHANGELOG.md categorizes changes correctly:
- Added (new features)
- Changed (changes in existing functionality)
- Deprecated (features marked for removal)
- Removed (removed features)
- Fixed (bug fixes)
- Security (security fixes)
Release Process¶
Step 1: Update Unreleased Changes¶
Ensure CHANGELOG.md has all changes documented under [Unreleased]:
Step 2: Run Pre-Release Checks¶
# Run comprehensive checks
just check
just test-cov
just validate-all
# Verify executables build (optional, CI will do this)
just build-exe
just test-exe
Step 3: Bump Version¶
Use the version bump script to update versions across the project:
# For patch release (0.1.0 -> 0.1.1)
python scripts/bump_version.py patch
# For minor release (0.1.0 -> 0.2.0)
python scripts/bump_version.py minor
# For major release (0.1.0 -> 1.0.0)
python scripts/bump_version.py major
# Or specify exact version
python scripts/bump_version.py 1.2.3
What this script does:
1. Updates pyproject.toml with new version
2. Updates src/midi_markdown/__init__.py with new version
3. Moves [Unreleased] changes to new version section in CHANGELOG.md
4. Creates git commit: "Release version X.Y.Z"
5. Creates git tag: "vX.Y.Z"
Preview changes first:
Step 4: Push Changes¶
Push the commit and tag to GitHub:
# Push commits
git push origin main
# Push tag (this triggers the release workflow)
git push origin v0.1.1 # Replace with your version
Alternative: Push everything at once
Step 5: Monitor CI/CD¶
Once you push the tag, GitHub Actions will automatically:
- Run Tests - Verify everything passes
- Build Executables - Create binaries for Linux, Windows, macOS
- Create GitHub Release - Generate release with notes
- Upload Assets - Attach executables and checksums
Monitor progress: - Go to: https://github.com/cjgdev/midi-markdown/actions - Find the "Release" workflow run - Check for any failures
Typical build time: 15-20 minutes for all platforms
Step 6: Verify Release¶
Once CI completes:
- Check GitHub Release:
- Go to: https://github.com/cjgdev/midi-markdown/releases
- Verify release notes look correct
-
Verify all executables are attached:
mmdc-linux-x86_64.tar.gz+.sha256mmdc-windows-x86_64.zip+.sha256mmdc-macos-universal.zip+.sha256
-
Test Executables:
- Download one executable for your platform
- Verify checksum matches
- Run
./mmdc --version -
Test with a simple example
-
Verify Documentation:
- Check that docs site is updated (if auto-deployed)
- Verify links work
Step 7: Publish to PyPI (Optional)¶
To publish the package to PyPI for pip install midi-markdown:
# Build distributions
just build
# Upload to TestPyPI first (recommended)
uv run twine upload --repository testpypi dist/*
# Test installation from TestPyPI
pip install --index-url https://test.pypi.org/simple/ midi-markdown
# If everything works, upload to real PyPI
uv run twine upload dist/*
Note: You need PyPI credentials configured. See PyPI Publishing section.
Step 8: Announce Release¶
- Update project README.md if needed
- Post announcement in GitHub Discussions (if enabled)
- Notify users in relevant channels (Discord, Twitter, etc.)
- Update documentation site
Post-Release Tasks¶
After a successful release:
1. Verify Installation¶
Test that users can install the new version:
# Via pip (if published to PyPI)
pip install midi-markdown==0.1.1
# Via pipx
pipx install midi-markdown==0.1.1
# Test it works
mmdc --version
2. Monitor Issues¶
Watch for bug reports related to the new release: - Check GitHub Issues: https://github.com/cjgdev/midi-markdown/issues - Monitor for installation problems - Respond quickly to critical bugs
3. Update Development Branch¶
Start work on the next version:
# Add [Unreleased] section back to CHANGELOG.md
# (This should already be there from bump_version.py)
# Start tracking new changes
git checkout -b feature/next-feature
4. Update Project Status¶
- Update README badges if needed
- Update project status (Alpha → Beta → Stable)
- Update roadmap/milestones
Hotfix Releases¶
For critical bug fixes that need immediate release:
Process¶
-
Create hotfix branch from tag:
-
Fix the bug:
-
Update CHANGELOG.md:
-
Bump version:
-
Merge back to main:
PyPI Publishing¶
To enable automatic PyPI publishing, add PyPI credentials to GitHub Secrets:
One-Time Setup¶
- Create PyPI Account:
- Go to https://pypi.org/account/register/
-
Verify email
-
Generate API Token:
- Go to https://pypi.org/manage/account/token/
- Create token with name "github-actions-midi-markdown"
- Scope: Project (midi-markdown) or Account
-
Save the token securely (starts with
pypi-) -
Add to GitHub Secrets:
- Go to: https://github.com/cjgdev/midi-markdown/settings/secrets/actions
- Click "New repository secret"
- Name:
PYPI_API_TOKEN - Value: Paste your
pypi-token -
Click "Add secret"
-
Update release.yml workflow:
Add this job to .github/workflows/release.yml:
publish-pypi:
name: Publish to PyPI
needs: create-release
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: '3.12'
- name: Install uv
run: pip install uv
- name: Build distributions
run: uv build
- name: Publish to PyPI
env:
TWINE_USERNAME: __token__
TWINE_PASSWORD: ${{ secrets.PYPI_API_TOKEN }}
run: |
uv pip install twine
uv run twine upload dist/*
Manual PyPI Publishing¶
If you prefer to publish manually:
# Install twine
uv pip install twine
# Build distributions
just build
# Upload to PyPI
uv run twine upload dist/*
Troubleshooting¶
Tag Already Exists¶
Problem: You created a tag but need to update it.
Solution:
# Delete local tag
git tag -d v0.1.1
# Delete remote tag
git push origin :refs/tags/v0.1.1
# Recreate tag
git tag -a v0.1.1 -m "Release 0.1.1"
git push origin v0.1.1
CI Build Fails¶
Problem: GitHub Actions workflow fails during release.
Solution: 1. Check the workflow logs: https://github.com/cjgdev/midi-markdown/actions 2. Fix the issue in main branch 3. Delete the tag and recreate:
Version Mismatch¶
Problem: Versions in pyproject.toml and init.py don't match.
Solution:
# Use the bump script (it keeps them in sync)
python scripts/bump_version.py patch
# Or manually fix:
# 1. Edit pyproject.toml
# 2. Edit src/midi_markdown/__init__.py
# 3. Commit changes
CHANGELOG Not Updated¶
Problem: Forgot to update CHANGELOG before release.
Solution:
# If tag not pushed yet:
git tag -d v0.1.1
# Edit CHANGELOG.md
git add CHANGELOG.md
git commit --amend
git tag -a v0.1.1 -m "Release 0.1.1"
# If tag already pushed:
# 1. Delete remote tag: git push origin :refs/tags/v0.1.1
# 2. Update CHANGELOG
# 3. Commit and retag
Executable Doesn't Work¶
Problem: Built executable fails to run.
Solution:
1. Check PyInstaller spec file: mmdc.spec
2. Test locally: just build-exe && just test-exe
3. Check for missing dependencies
4. Verify hidden imports in spec file
PyPI Upload Fails¶
Problem: Twine fails to upload to PyPI.
Solution:
1. Verify API token is correct
2. Check package name isn't taken
3. Verify version number is unique (can't reupload same version)
4. Try TestPyPI first: twine upload --repository testpypi dist/*
Release Workflow Summary¶
Quick Reference:
# 1. Prepare
just check && just test-cov && just validate-all
# 2. Bump version
python scripts/bump_version.py minor # or patch/major
# 3. Push (triggers release)
git push origin main --tags
# 4. Monitor CI
# Visit: https://github.com/cjgdev/midi-markdown/actions
# 5. Verify release
# Visit: https://github.com/cjgdev/midi-markdown/releases
# 6. (Optional) Publish to PyPI
just build
uv run twine upload dist/*
Reference¶
Files Modified by Release¶
pyproject.toml- Version numbersrc/midi_markdown/__init__.py- version stringCHANGELOG.md- Move [Unreleased] to version section- Git tag -
vX.Y.Z
Tools Used¶
scripts/bump_version.py- Version managementjust- Task runneruv- Package managerpytest- Testingruff- Linting/formattingmypy- Type checkingtwine- PyPI publishingpyinstaller- Executable building- GitHub Actions - CI/CD
Links¶
- Releases: https://github.com/cjgdev/midi-markdown/releases
- Actions: https://github.com/cjgdev/midi-markdown/actions
- PyPI (future): https://pypi.org/project/midi-markdown/
- Semantic Versioning: https://semver.org/
- Keep a Changelog: https://keepachangelog.com/
Last Updated: 2025-11-11 Maintainer: Christopher Gilbert (@cjgdev)