Skip to main content
Version: 1.0

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

  1. Go to Actions → Release to PyPI
  2. Click "Run workflow"
  3. 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
  4. For pre-releases, select type: alpha, beta, or rc
  5. 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

Documentation versioning

The docs site uses Docusaurus versioning. When you release a new stable version:

cd documentation
npm ci
npm run docusaurus docs:version 1.0.0 # snapshots docs/ → versioned_docs/version-1.0.0/
  • docs/ — in-development docs (labeled "Next" on the site)
  • versioned_docs/version-X.Y.Z/ — frozen docs for that release
  • versions.json — version order (newest first)

After snapshotting, sync link fixes into the new version folder if needed, then npm run build before deploy.

Older releases (e.g. 0.4.1) remain available under the version dropdown with an "unmaintained" banner.

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.1
  • minor → 0.2.0
  • major → 1.0.0
  • pre --pre-release alpha → 0.1.1-alpha.1
  • pre --pre-release alpha (again) → 0.1.1-alpha.2
  • pre --pre-release beta → 0.1.1-beta.1
  • patch (from pre-release) → 0.1.1

Pre-release Workflow

  1. Create alpha releases for early testing:

    ./scripts/release.sh bump pre --pre-release alpha
  2. Progress to beta when feature-complete:

    ./scripts/release.sh bump pre --pre-release beta
  3. Release candidates for final testing:

    ./scripts/release.sh bump pre --pre-release rc
  4. Final release:

    ./scripts/release.sh bump patch

GitHub Environments

The release workflow uses two environments:

  1. test-release: For TestPyPI uploads

    • No additional secrets required
    • Automatic approval
  2. release: For PyPI uploads

    • Requires PyPI API token
    • Manual approval for major versions

Setting Up PyPI Tokens

  1. Create account on PyPI
  2. Generate API token: Account settings → API tokens
  3. Add to GitHub secrets:
    • Go to Settings → Secrets → Actions
    • Add PYPI_API_TOKEN

For TestPyPI:

  1. Create account on TestPyPI
  2. Generate API token
  3. Add TEST_PYPI_API_TOKEN to GitHub secrets

Post-Release Checklist

After a successful release:

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-existing flag
  • 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:

  1. Yank the release on PyPI (doesn't delete, just marks as "yanked")
  2. Fix the issue
  3. Release a new patch version

Note: Never delete or reuse version numbers!