Skip to content

Latest commit

 

History

History
437 lines (313 loc) · 10.6 KB

File metadata and controls

437 lines (313 loc) · 10.6 KB

Release Guide for Antipasta

This guide provides detailed instructions for releasing new versions of antipasta to PyPI.

Quick Start

Pre-flight check:

make release-doctor  # Check system health and prerequisites

Safe one-command releases (recommended):

make release-patch-safe  # Bug fixes (X.Y.Z -> X.Y.(Z+1)) with safety checks
make release-minor-safe  # New features (X.Y.Z -> X.(Y+1).0) with safety checks
make release-major-safe  # Breaking changes (X.0.0) with safety checks

Standard releases (without safety checks):

make release-patch  # Bug fixes (X.Y.Z -> X.Y.(Z+1))
make release-minor  # New features (X.Y.Z -> X.(Y+1).0)
make release-major  # Breaking changes (X.0.0)

These commands handle everything: version bump → commit → push → GitHub release → PyPI deployment.

Testing before release:

# Test what will happen (dry-run)
make release-dry-patch  # Simulate patch release
make release-dry-minor  # Simulate minor release
make release-dry-major  # Simulate major release
make gh-release-dry     # Simulate GitHub release creation

# Deploy to TestPyPI first
make gh-release-test    # Safe testing on TestPyPI

Release Methods

Antipasta supports two release methods:

  1. GitHub Actions (Recommended): Automated deployment via GitHub Releases
  2. Manual Release: Direct upload from your local machine

Pre-Release Health Check

Before any release, run the release doctor to check your system:

make release-doctor

This comprehensive health check verifies:

  • ✅ GitHub CLI installation and authentication
  • ✅ Git repository state (uncommitted changes, branch)
  • ✅ Version status and available tags
  • ✅ Python environment and build tools
  • ✅ GitHub repository and workflow configuration

Testing Your Release (Dry-Run)

Before making an actual release, test what will happen:

# See what a patch release would do
make release-dry-patch

# Test GitHub release creation
make gh-release-dry

# Run pre-release safety checks
make release-safety-check

These commands simulate the entire release process without making any changes.

Method 1: GitHub Actions (Recommended)

Prerequisites

  1. GitHub Repository Access: Push access to the antipasta repository
  2. Trusted Publishing: Already configured in PyPI project settings (no tokens needed!)

Quick Release Commands

The easiest and safest way to release is using the safe all-in-one commands:

# Safe releases with automatic safety checks (recommended)
make release-patch-safe  # Bug fixes (X.Y.Z -> X.Y.(Z+1))
make release-minor-safe  # New features (X.Y.Z -> X.(Y+1).0)
make release-major-safe  # Breaking changes (X.0.0)

# Or standard releases without safety checks
make release-patch       # Bug fixes (X.Y.Z -> X.Y.(Z+1))
make release-minor       # New features (X.Y.Z -> X.(Y+1).0)
make release-major       # Breaking changes (X.0.0)

These commands automatically:

  1. Bump the version
  2. Commit changes
  3. Push to GitHub
  4. Create a GitHub release
  5. Trigger PyPI deployment

Step-by-Step Workflow

For more control over the release process:

  1. Check System Health:

    make release-doctor      # Comprehensive pre-flight check
    make release-safety-check  # Quick safety validation
  2. Test First (Optional but Recommended):

    make release-dry-patch   # Simulate the release
    make gh-release-dry      # Check if release would succeed
  3. Bump Version:

    make version-bump-patch  # or minor/major
  4. Create GitHub Release:

    # Safe release with checks (recommended)
    make gh-release-safe
    
    # Standard release
    make gh-release
    
    # Or create a draft to review first
    make gh-release-draft
  5. Monitor Deployment:

    • The command outputs links to:
      • GitHub Actions progress
      • PyPI package page
    • Package appears on PyPI within minutes

Alternative Methods

GitHub UI

  • Navigate to your repo → Releases → "Draft a new release"
  • Click "Choose a tag" → Create new tag: v1.1.1 (match your version)
  • Release title: v1.1.1
  • Click "Generate release notes" for automatic changelog
  • Click "Publish release"

GitHub CLI (manual)

gh release create v1.1.1 --generate-notes --title "v1.1.1"

Testing with GitHub Actions

Before a production release, test on TestPyPI:

Using Makefile (Recommended)

make gh-release-test

This triggers the TestPyPI workflow and provides installation instructions.

Using GitHub UI

  1. Go to Actions → "Publish to PyPI" workflow
  2. Click "Run workflow"
  3. Select testpypi as target
  4. Run the workflow

Test Installation

pip install -i https://test.pypi.org/simple/ --extra-index-url https://pypi.org/simple/ antipasta

Method 2: Manual Release

Prerequisites

  1. PyPI Account: Create an account at pypi.org
  2. TestPyPI Account (optional): Create an account at test.pypi.org
  3. API Tokens: Generate API tokens for both PyPI and TestPyPI
  4. Configure Authentication: Set up your ~/.pypirc file:
[distutils]
index-servers =
    pypi
    testpypi

[pypi]
username = __token__
password = pypi-YOUR-TOKEN-HERE

[testpypi]
username = __token__
password = pypi-YOUR-TEST-TOKEN-HERE
repository = https://test.pypi.org/legacy/
  1. Clean Git State: Ensure your working directory is clean and you're on the main branch

Release Workflow

Step 1: Pre-release Checks

Run the release checklist to ensure everything is ready:

make release-check

This displays a checklist of items to verify before releasing:

  • All tests passing
  • Code formatted properly
  • Type checks passing
  • Version bumped appropriately
  • CHANGELOG updated (if applicable)
  • Git working directory clean
  • On the correct branch

Step 2: Run Quality Checks

Ensure all quality checks pass:

make check

This runs:

  • Linting (ruff)
  • Type checking (mypy)
  • Tests (pytest)

Step 3: Update Version

Choose the appropriate version bump based on your changes:

Patch Release (Bug Fixes)

For backward-compatible bug fixes (X.Y.Z -> X.Y.(Z+1)):

make version-bump-patch

Minor Release (New Features)

For backward-compatible new features (X.Y.Z -> X.(Y+1).0):

make version-bump-minor

Major Release (Breaking Changes)

For incompatible API changes (X.0.0):

make version-bump-major

The version will be updated in both src/antipasta/__version__.py and pyproject.toml.

Step 4: Build and Verify

Build the distribution packages and verify they're correct:

make build-check

This will:

  1. Clean any previous build artifacts
  2. Build both source distribution (.tar.gz) and wheel (.whl)
  3. Run twine check to validate the packages

You can also do a dry run to see what will be uploaded:

make release-dry-run

Step 5: Test Release (Optional but Recommended)

Test your release on TestPyPI first:

make release-test

Then install and test from TestPyPI:

pip install --index-url https://test.pypi.org/simple/ --extra-index-url https://pypi.org/simple/ antipasta

Step 6: Production Release

Once you're confident everything works, release to PyPI:

make release

This uploads your packages to the official PyPI repository.

Step 7: Git Tag and Push

After a successful release, create a git tag:

# Commit the version changes
git add -A
git commit -m "chore: release v$(make version-show 2>&1 | grep "Current version" | cut -d: -f2 | xargs)"

# Create and push tag
git tag -a v$(make version-show 2>&1 | grep "Current version" | cut -d: -f2 | xargs) -m "Release v$(make version-show 2>&1 | grep "Current version" | cut -d: -f2 | xargs)"
git push origin main --tags

Step 8: Verify Installation

Test that the new version can be installed from PyPI:

pip install --upgrade antipasta
antipasta --version

Troubleshooting

Authentication Errors

If you get authentication errors:

  1. Verify your .pypirc file has the correct API tokens
  2. Ensure tokens start with pypi-
  3. Check that tokens have upload permissions

Package Validation Errors

If twine check fails:

  1. Run make clean to remove old artifacts
  2. Ensure README.md is valid markdown
  3. Check that all required fields are in pyproject.toml

Version Already Exists

If PyPI reports the version already exists:

  1. You cannot overwrite an existing version on PyPI
  2. Bump the version again (even for a patch)
  3. Delete local build artifacts: make clean

TestPyPI Issues

TestPyPI may have missing dependencies. When testing installation:

pip install --index-url https://test.pypi.org/simple/ --extra-index-url https://pypi.org/simple/ antipasta

The --extra-index-url ensures dependencies are pulled from production PyPI.

Version Numbering Guidelines

Follow Semantic Versioning:

  • MAJOR (X.0.0): Incompatible API changes

    • Removing features
    • Changing function signatures
    • Major behavior changes
  • MINOR (X.Y.Z -> X.(Y+1).0): Backward-compatible functionality

    • New features
    • New configuration options
    • Deprecations (but not removals)
  • PATCH (X.Y.Z -> X.Y.(Z+1)): Backward-compatible bug fixes

    • Bug fixes
    • Performance improvements
    • Documentation updates

Release Checklist

Use the built-in checklist command:

make release-check

This displays the current version and a checklist of items to verify:

  • All tests passing (make test)
  • Code formatted (make format)
  • Type checks passing (make type-check)
  • Version bumped appropriately
  • CHANGELOG.md updated (if exists)
  • Git working directory clean
  • On correct branch (main/master)

For a complete quality check before release:

make check  # Runs lint, type-check, and tests

Automating Releases

For frequent releases, consider:

  1. GitHub Actions: Automate releases on tag push
  2. Semantic Release: Automatic version management based on commit messages
  3. Pre-commit Hooks: Ensure quality checks before commits

Emergency Rollback

If a critical issue is found after release:

  1. Do NOT delete the release from PyPI (it's not allowed)
  2. Yank the release (marks it as broken):
    pip install twine
    twine yank antipasta==X.Y.Z
  3. Fix the issue and release a new patch version
  4. Communicate with users about the issue

Additional Resources