Release Automation Commands

The release command provides semantic versioning and PyPI publishing automation for streamlined release workflows.

Overview

Release commands are provided by the structum-cli-tools plugin:

pip install structum-cli-tools

Automates version bumping, changelog generation, and PyPI publishing based on Conventional Commits.

Commands

release prepare

Prepare a new release: analyze commits, bump version, generate changelog.

Options:

--dry-run

Preview changes without modifying files

Examples:

# Preview next release
structum release prepare --dry-run

# Create release
structum release prepare

Conventional Commits Format:

  • feat:: New feature → minor version bump (0.X.0)

  • fix:: Bug fix → patch version bump (0.0.X)

  • BREAKING CHANGE:: Breaking → major version bump (X.0.0)

  • docs:, chore:, style: → No version bump

Example Commit Messages:

feat: add user authentication

Implements JWT-based authentication with refresh tokens.

---

fix: resolve memory leak in cache

Closes #123

---

feat!: refactor API endpoints

BREAKING CHANGE: /api/v1/users endpoint removed, use /api/v2/users

Tools: python-semantic-release

release validate

Validate project readiness before publishing.

Validation Checks:

  1. ✅ Tests pass (pytest)

  2. ✅ Code quality (ruff + black)

  3. ✅ Security scan (bandit)

  4. ✅ Documentation builds (sphinx)

  5. ✅ Git working directory clean

Examples:

structum release validate

Output:

✅ Validating Release Readiness

1. Running tests...
   ✅ All tests passed

2. Checking code quality...
   ✅ Code quality passed

3. Security scan...
   ✅ No security issues

4. Building documentation...
   ✅ Documentation builds cleanly

5. Checking git state...
   ✅ Git working directory clean

✅ Ready for Release

Exit Codes:

  • 0: All checks passed

  • 1: One or more checks failed

release publish

Publish package to PyPI (or TestPyPI).

Options:

--test-pypi

Publish to TestPyPI instead of production PyPI

Examples:

# Test on TestPyPI first (recommended)
structum release publish --test-pypi

# Production release
structum release publish

Prerequisites:

  1. PyPI account created

  2. API token configured in ~/.pypirc

  3. Version tagged in git

  4. release validate passed

PyPI Token Setup:

Create ~/.pypirc:

[pypi]
username = __token__
password = pypi-YOUR_API_TOKEN_HERE

[testpypi]
repository = https://test.pypi.org/legacy/
username = __token__
password = pypi-YOUR_TEST_API_TOKEN_HERE

Tools: twine

Workflow

Complete Release Process

# 1. Prepare release (bump version, changelog)
structum release prepare

# 2. Review changes
git diff

# 3. Commit release
git add .
git commit -m "chore: release v0.2.0"

# 4. Create tag
git tag v0.2.0

# 5. Validate readiness
structum release validate

# 6. Test on TestPyPI
structum release publish --test-pypi

# 7. Verify installation
pip install --index-url https://test.pypi.org/simple/ yourpackage

# 8. Publish to production
structum release publish

# 9. Push git
git push origin main --tags

Configuration

Semantic Release Config

Create .releaserc.json or configure in pyproject.toml:

[tool.semantic_release]
version_variable = "src/mypackage/__init__.py:__version__"
upload_to_pypi = false  # Use structum release publish instead
commit_subject = "chore: release v{version}"

[tool.semantic_release.branches.main]
match = "main"
prerelease = false

Changelog Configuration

Customize changelog generation:

[tool.towncrier]
package = "mypackage"
filename = "CHANGELOG.md"
directory = "changelog/"
template = "changelog/template.md"

CI/CD Integration

GitHub Actions Release

name: Release

on:
  workflow_dispatch:
    inputs:
      release_type:
        description: 'Release type'
        required: true
        type: choice
        options:
          - patch
          - minor
          - major

jobs:
  release:
    runs-on: ubuntu-latest
    permissions:
      contents: write

    steps:
      - uses: actions/checkout@v3
        with:
          fetch-depth: 0

      - name: Install tools
        run: pip install structum-cli-tools

      - name: Validate
        run: structum release validate

      - name: Prepare release
        run: structum release prepare

      - name: Commit and tag
        run: |
          git config user.name "github-actions"
          git config user.email "actions@github.com"
          git add .
          git commit -m "chore: release"
          git tag $(cat VERSION)

      - name: Publish to PyPI
        env:
          TWINE_USERNAME: __token__
          TWINE_PASSWORD: ${{ secrets.PYPI_TOKEN }}
        run: structum release publish

      - name: Push
        run: git push origin main --tags

Automated Release

Trigger on every merge to main:

on:
  push:
    branches: [main]

Best Practices

Version Strategy

  • Patch (0.0.X): Bug fixes, documentation

  • Minor (0.X.0): New features (backwards compatible)

  • Major (X.0.0): Breaking changes

Pre-release Testing

  1. Always validate before releasing

  2. Test on TestPyPI first

  3. Install and verify package works

  4. Check changelog accuracy

Git Workflow

  1. Use conventional commits consistently

  2. Tag releases with v prefix (v0.2.0)

  3. Keep CHANGELOG.md updated

  4. Document breaking changes thoroughly

Troubleshooting

Validation Fails

Fix issues before proceeding:

# Fix tests
structum test --cov

# Fix code quality
structum check

# Fix security
structum security scan

PyPI Upload Fails

Common issues:

  1. Version already exists: Bump version

  2. Invalid token: Check ~/.pypirc

  3. Package name taken: Choose different name

Git Not Clean

Commit or stash changes:

git status
git add .
git commit -m "chore: prepare for release"

See Also