Releasing django-rls
This document describes the release process for django-rls.
Release Types
django-rls follows Semantic Versioning:
- Major (X.0.0): Breaking changes
- Minor (0.X.0): New features, backwards compatible
- Patch (0.0.X): Bug fixes, backwards compatible
- Pre-release: Alpha, Beta, RC versions (e.g., 1.0.0-alpha.1)
Automated Release Process
The preferred method is using GitHub Actions:
1. Via GitHub UI
- Go to Actions → Release to PyPI
- Click "Run workflow"
- Select version bump type:
patch: Bug fixes (0.1.0 → 0.1.1)minor: New features (0.1.0 → 0.2.0)major: Breaking changes (0.1.0 → 1.0.0)pre: Pre-release versions
- For pre-releases, select type:
alpha,beta, orrc - Click "Run workflow"
The workflow will:
- Run all tests
- Bump version
- Create git tag
- Build packages
- Upload to TestPyPI
- Test installation
- Upload to PyPI (for stable releases)
- Create GitHub release
2. Via Git Tags
Push a version tag to trigger release:
git tag v1.0.0
git push origin v1.0.0
Manual Release Process
For local testing or manual releases:
1. Check Release Readiness
./scripts/release.sh check
This will:
- Verify git status is clean
- Check you're on main branch
- Run all tests
- Check coverage (>90%)
2. Bump Version
# Patch release (bug fixes)
./scripts/release.sh bump patch
# Minor release (new features)
./scripts/release.sh bump minor
# Major release (breaking changes)
./scripts/release.sh bump major
# Pre-release
./scripts/release.sh bump pre --pre-release alpha
./scripts/release.sh bump pre --pre-release beta
./scripts/release.sh bump pre --pre-release rc
3. Build Distribution
./scripts/release.sh build
4. Upload to TestPyPI
./scripts/release.sh test-pypi
Test installation:
pip install --index-url https://test.pypi.org/simple/ --extra-index-url https://pypi.org/simple django-rls==VERSION
5. Upload to PyPI
./scripts/release.sh pypi
Version Bumping Examples
Current version: 0.1.0
patch→ 0.1.1minor→ 0.2.0major→ 1.0.0pre --pre-release alpha→ 0.1.1-alpha.1pre --pre-release alpha(again) → 0.1.1-alpha.2pre --pre-release beta→ 0.1.1-beta.1patch(from pre-release) → 0.1.1
Pre-release Workflow
-
Create alpha releases for early testing:
./scripts/release.sh bump pre --pre-release alpha -
Progress to beta when feature-complete:
./scripts/release.sh bump pre --pre-release beta -
Release candidates for final testing:
./scripts/release.sh bump pre --pre-release rc -
Final release:
./scripts/release.sh bump patch
GitHub Environments
The release workflow uses two environments:
-
test-release: For TestPyPI uploads
- No additional secrets required
- Automatic approval
-
release: For PyPI uploads
- Requires PyPI API token
- Manual approval for major versions
Setting Up PyPI Tokens
- Create account on PyPI
- Generate API token: Account settings → API tokens
- Add to GitHub secrets:
- Go to Settings → Secrets → Actions
- Add
PYPI_API_TOKEN
For TestPyPI:
- Create account on TestPyPI
- Generate API token
- Add
TEST_PYPI_API_TOKENto GitHub secrets
Post-Release Checklist
After a successful release:
- Verify package on PyPI: https://pypi.org/project/django-rls/
- Test installation:
pip install django-rls==VERSION - Check documentation is updated: https://django-rls.com
- Update changelog if needed
- Announce release (if major/minor)
Troubleshooting
Build Failures
# Clean build artifacts
rm -rf dist/ build/ *.egg-info
# Rebuild
poetry build
Version Conflicts
# Check current version
python -c "from django_rls.__version__ import __version__; print(__version__)"
# Reset to tag
git reset --hard v0.1.0
Failed TestPyPI Upload
- Check if version already exists
- Use
--skip-existingflag - Bump version and retry
Failed PyPI Upload
- Verify API token is correct
- Check version doesn't exist
- Ensure all tests pass
Emergency Rollback
If a bad release is published:
- Yank the release on PyPI (doesn't delete, just marks as "yanked")
- Fix the issue
- Release a new patch version
Note: Never delete or reuse version numbers!