Skip to main content

Opinionated release toolkit for modern Python projects

Project description

relkit: Opinionated Release Toolkit for Modern Python Projects

"This Way or No Way" - A strict, opinionated release workflow enforcer for Python projects using uv.

Features

  • 🚀 Workspace Support: Per-package versioning in monorepos
  • 🔒 Atomic Releases: Version, changelog, commit, tag, and push in one command
  • 🎯 Explicit Operations: No magic, every action is intentional
  • Pre-flight Checks: Validates everything before release
  • 📝 Changelog Enforcement: Required for all releases
  • 🏷️ Smart Tagging: v1.0.0 for single packages, package-v1.0.0 for workspaces
  • 🚫 Safety First: Blocks dangerous operations before they happen

Installation

# Add to your project as a dev dependency
uv add --dev relkit

# Or install from GitHub
uv add --dev git+https://github.com/angelsen/relkit.git

Quick Start

Single Package Projects

# Initialize git hooks (recommended)
relkit init-hooks

# Check project status
relkit status

# Make changes, update CHANGELOG.md, then bump version
relkit bump patch  # or minor/major

# Full release workflow
relkit release

Workspace Projects

# Show workspace overview
relkit status

# Work with specific packages (--package is required)
relkit status --package termtap
relkit bump patch --package termtap
relkit build --package termtap
relkit publish --package termtap

# Package-specific tags are created automatically
# e.g., termtap-v1.0.0, webtap-v2.1.0

Commands

Core Commands

  • relkit status [--package NAME] - Show release readiness
  • relkit bump <major|minor|patch> [--package NAME] - Atomic version bump with changelog, commit, and tag
  • relkit release [--package NAME] - Complete release workflow
  • relkit version - Show current version

Build & Publish

  • relkit build [--package NAME] - Build distribution packages
  • relkit test - Test built packages
  • relkit publish [--package NAME] - Publish to PyPI (requires confirmation)

Development Tools

  • relkit check <all|git|changelog|format|lint|types> [--fix] - Run quality checks
  • relkit init-hooks - Install git hooks

Git Wrappers

  • relkit git <command> - Pass-through to git with awareness

Workspace Support

Relkit seamlessly handles three project types:

1. Single Package (default)

[project]
name = "mypackage"
version = "1.0.0"
  • Commands work without --package flag
  • Tags: v1.0.0

2. Pure Workspace

[tool.uv.workspace]
members = ["packages/*"]
# No [project] section in root
  • All commands require --package flag
  • Tags: package-v1.0.0

3. Hybrid Workspace

[project]
name = "root-package"
version = "2.0.0"

[tool.uv.workspace]
members = ["packages/*"]
  • Root package and workspace members
  • Use --package root-package or --package member-name
  • Tags: v2.0.0 for root, member-v1.0.0 for members

Philosophy

Explicit Over Magic

  • Workspace operations require explicit --package selection
  • No automatic dependency cascades
  • Clear errors when package selection is ambiguous

Separation of Concerns

  • uv: Manages dependencies and workspace setup
  • relkit: Manages releases and versioning
  • git: Version control (wrapped for safety)

Atomic Operations

The bump command is atomic - it handles everything in one transaction:

  1. Updates version in pyproject.toml
  2. Updates CHANGELOG.md
  3. Commits changes
  4. Syncs lockfile if needed
  5. Creates appropriate tag
  6. Pushes to remote

Safety Features

Blocked Operations

Direct version edits

# Editing version in pyproject.toml directly is blocked
git commit -am "bump version"  # BLOCKED by pre-commit hook

Manual tag creation

git tag v1.0.0  # BLOCKED by git hook
# Tags must be created via: relkit bump

Dirty working directory

# With uncommitted changes:
relkit bump patch  # BLOCKED - requires clean git

Required Confirmations

  • Publishing to PyPI requires explicit confirmation
  • Major version bumps trigger breaking change warning
  • All operations show clear next steps on failure

Configuration

Relkit reads from pyproject.toml:

[project]
name = "your-package"
version = "0.1.0"  # Never edit directly!

[tool.uv.workspace]
members = ["packages/*"]  # Optional workspace config

Each package maintains its own:

  • pyproject.toml with version
  • CHANGELOG.md with release notes
  • Git tags with appropriate naming

Error Messages

All errors are actionable:

✗ Workspace requires --package

  Available packages: termtap, webtap, logtap

Next steps:
  1. Specify a package: relkit bump patch --package <name>
  2. Use package name from pyproject.toml [project] section

Development

# Clone repository
git clone https://github.com/angelsen/relkit.git
cd relkit

# Install in development mode
uv sync

# Run tests
uv run pytest

# Check types
uv run pyright

Contributing

This tool is intentionally opinionated. We welcome contributions that:

  • Improve error messages
  • Add safety checks
  • Enhance workspace support
  • Fix bugs

We generally reject:

  • Features that add "escape hatches"
  • Options to bypass safety checks
  • Implicit or magical behaviors

License

MIT

Credits

Created by Fredrik Angelsen. Built with Python 3.12+ and uv.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

relkit-1.5.1.tar.gz (40.1 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

relkit-1.5.1-py3-none-any.whl (54.4 kB view details)

Uploaded Python 3

File details

Details for the file relkit-1.5.1.tar.gz.

File metadata

  • Download URL: relkit-1.5.1.tar.gz
  • Upload date:
  • Size: 40.1 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.8.9

File hashes

Hashes for relkit-1.5.1.tar.gz
Algorithm Hash digest
SHA256 1fee9c04bfe1161d6e563695364b82bbf7616add8acbaeee0f4c06ce85559b6c
MD5 ba5a20964e30351da954fa2bd6172f27
BLAKE2b-256 ceca6117f5dbc6b34956ace6f8f39c85c55fb3086a8137b26c522c6a1bf31347

See more details on using hashes here.

File details

Details for the file relkit-1.5.1-py3-none-any.whl.

File metadata

  • Download URL: relkit-1.5.1-py3-none-any.whl
  • Upload date:
  • Size: 54.4 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.8.9

File hashes

Hashes for relkit-1.5.1-py3-none-any.whl
Algorithm Hash digest
SHA256 fcf828d57a8355a39ab04d95a3b02d630010e11432c280faf6fefea940cd96cb
MD5 53754706cb738b4658157d4721b190c1
BLAKE2b-256 a8fc8081b2545f802496cbd2d2405b0f1ffb87b5b582503e50ebe9cc2dc0d98c

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page