relkit


Namerelkit JSON
Version 1.5.0 PyPI version JSON
download
home_pageNone
SummaryOpinionated release toolkit for modern Python projects
upload_time2025-08-13 21:38:32
maintainerNone
docs_urlNone
authorFredrik Angelsen
requires_python>=3.12
licenseMIT
keywords release workflow changelog versioning monorepo automation
VCS
bugtrack_url
requirements No requirements were recorded.
Travis-CI No Travis.
coveralls test coverage No coveralls.
            # 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

```bash
# 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

```bash
# 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

```bash
# 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)
```toml
[project]
name = "mypackage"
version = "1.0.0"
```
- Commands work without `--package` flag
- Tags: `v1.0.0`

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

### 3. Hybrid Workspace
```toml
[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**
```bash
# Editing version in pyproject.toml directly is blocked
git commit -am "bump version"  # BLOCKED by pre-commit hook
```

❌ **Manual tag creation**
```bash
git tag v1.0.0  # BLOCKED by git hook
# Tags must be created via: relkit bump
```

❌ **Dirty working directory**
```bash
# 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`:

```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

```bash
# 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.
            

Raw data

            {
    "_id": null,
    "home_page": null,
    "name": "relkit",
    "maintainer": null,
    "docs_url": null,
    "requires_python": ">=3.12",
    "maintainer_email": null,
    "keywords": "release, workflow, changelog, versioning, monorepo, automation",
    "author": "Fredrik Angelsen",
    "author_email": "Fredrik Angelsen <fredrikangelsen@gmail.com>",
    "download_url": "https://files.pythonhosted.org/packages/80/9d/dc2563514bb3319630acd9020e2dd44d48c909796f30074405874b3fcbc4/relkit-1.5.0.tar.gz",
    "platform": null,
    "description": "# relkit: Opinionated Release Toolkit for Modern Python Projects\n\n**\"This Way or No Way\"** - A strict, opinionated release workflow enforcer for Python projects using uv.\n\n## Features\n\n- \ud83d\ude80 **Workspace Support**: Per-package versioning in monorepos\n- \ud83d\udd12 **Atomic Releases**: Version, changelog, commit, tag, and push in one command\n- \ud83c\udfaf **Explicit Operations**: No magic, every action is intentional\n- \u2705 **Pre-flight Checks**: Validates everything before release\n- \ud83d\udcdd **Changelog Enforcement**: Required for all releases\n- \ud83c\udff7\ufe0f **Smart Tagging**: `v1.0.0` for single packages, `package-v1.0.0` for workspaces\n- \ud83d\udeab **Safety First**: Blocks dangerous operations before they happen\n\n## Installation\n\n```bash\n# Add to your project as a dev dependency\nuv add --dev relkit\n\n# Or install from GitHub\nuv add --dev git+https://github.com/angelsen/relkit.git\n```\n\n## Quick Start\n\n### Single Package Projects\n\n```bash\n# Initialize git hooks (recommended)\nrelkit init-hooks\n\n# Check project status\nrelkit status\n\n# Make changes, update CHANGELOG.md, then bump version\nrelkit bump patch  # or minor/major\n\n# Full release workflow\nrelkit release\n```\n\n### Workspace Projects\n\n```bash\n# Show workspace overview\nrelkit status\n\n# Work with specific packages (--package is required)\nrelkit status --package termtap\nrelkit bump patch --package termtap\nrelkit build --package termtap\nrelkit publish --package termtap\n\n# Package-specific tags are created automatically\n# e.g., termtap-v1.0.0, webtap-v2.1.0\n```\n\n## Commands\n\n### Core Commands\n\n- `relkit status [--package NAME]` - Show release readiness\n- `relkit bump <major|minor|patch> [--package NAME]` - Atomic version bump with changelog, commit, and tag\n- `relkit release [--package NAME]` - Complete release workflow\n- `relkit version` - Show current version\n\n### Build & Publish\n\n- `relkit build [--package NAME]` - Build distribution packages\n- `relkit test` - Test built packages\n- `relkit publish [--package NAME]` - Publish to PyPI (requires confirmation)\n\n### Development Tools\n\n- `relkit check <all|git|changelog|format|lint|types> [--fix]` - Run quality checks\n- `relkit init-hooks` - Install git hooks\n\n### Git Wrappers\n\n- `relkit git <command>` - Pass-through to git with awareness\n\n## Workspace Support\n\nRelkit seamlessly handles three project types:\n\n### 1. Single Package (default)\n```toml\n[project]\nname = \"mypackage\"\nversion = \"1.0.0\"\n```\n- Commands work without `--package` flag\n- Tags: `v1.0.0`\n\n### 2. Pure Workspace\n```toml\n[tool.uv.workspace]\nmembers = [\"packages/*\"]\n# No [project] section in root\n```\n- All commands require `--package` flag\n- Tags: `package-v1.0.0`\n\n### 3. Hybrid Workspace\n```toml\n[project]\nname = \"root-package\"\nversion = \"2.0.0\"\n\n[tool.uv.workspace]\nmembers = [\"packages/*\"]\n```\n- Root package and workspace members\n- Use `--package root-package` or `--package member-name`\n- Tags: `v2.0.0` for root, `member-v1.0.0` for members\n\n## Philosophy\n\n### Explicit Over Magic\n- Workspace operations require explicit `--package` selection\n- No automatic dependency cascades\n- Clear errors when package selection is ambiguous\n\n### Separation of Concerns\n- **uv**: Manages dependencies and workspace setup\n- **relkit**: Manages releases and versioning\n- **git**: Version control (wrapped for safety)\n\n### Atomic Operations\nThe `bump` command is atomic - it handles everything in one transaction:\n1. Updates version in pyproject.toml\n2. Updates CHANGELOG.md\n3. Commits changes\n4. Syncs lockfile if needed\n5. Creates appropriate tag\n6. Pushes to remote\n\n## Safety Features\n\n### Blocked Operations\n\n\u274c **Direct version edits**\n```bash\n# Editing version in pyproject.toml directly is blocked\ngit commit -am \"bump version\"  # BLOCKED by pre-commit hook\n```\n\n\u274c **Manual tag creation**\n```bash\ngit tag v1.0.0  # BLOCKED by git hook\n# Tags must be created via: relkit bump\n```\n\n\u274c **Dirty working directory**\n```bash\n# With uncommitted changes:\nrelkit bump patch  # BLOCKED - requires clean git\n```\n\n### Required Confirmations\n\n- Publishing to PyPI requires explicit confirmation\n- Major version bumps trigger breaking change warning\n- All operations show clear next steps on failure\n\n## Configuration\n\nRelkit reads from `pyproject.toml`:\n\n```toml\n[project]\nname = \"your-package\"\nversion = \"0.1.0\"  # Never edit directly!\n\n[tool.uv.workspace]\nmembers = [\"packages/*\"]  # Optional workspace config\n```\n\nEach package maintains its own:\n- `pyproject.toml` with version\n- `CHANGELOG.md` with release notes\n- Git tags with appropriate naming\n\n## Error Messages\n\nAll errors are actionable:\n\n```\n\u2717 Workspace requires --package\n\n  Available packages: termtap, webtap, logtap\n\nNext steps:\n  1. Specify a package: relkit bump patch --package <name>\n  2. Use package name from pyproject.toml [project] section\n```\n\n## Development\n\n```bash\n# Clone repository\ngit clone https://github.com/angelsen/relkit.git\ncd relkit\n\n# Install in development mode\nuv sync\n\n# Run tests\nuv run pytest\n\n# Check types\nuv run pyright\n```\n\n## Contributing\n\nThis tool is intentionally opinionated. We welcome contributions that:\n- Improve error messages\n- Add safety checks\n- Enhance workspace support\n- Fix bugs\n\nWe generally reject:\n- Features that add \"escape hatches\"\n- Options to bypass safety checks\n- Implicit or magical behaviors\n\n## License\n\nMIT\n\n## Credits\n\nCreated by Fredrik Angelsen. Built with Python 3.12+ and uv.",
    "bugtrack_url": null,
    "license": "MIT",
    "summary": "Opinionated release toolkit for modern Python projects",
    "version": "1.5.0",
    "project_urls": null,
    "split_keywords": [
        "release",
        " workflow",
        " changelog",
        " versioning",
        " monorepo",
        " automation"
    ],
    "urls": [
        {
            "comment_text": null,
            "digests": {
                "blake2b_256": "2b0483d7d631292cf342775438e6a6150bc968097e341ddb45ed782f8e6ae8f7",
                "md5": "f6628e03e3266b06538da52921a53775",
                "sha256": "747df3c43929800482f463a8612f450883210bcb9734f81c467990036055ae1c"
            },
            "downloads": -1,
            "filename": "relkit-1.5.0-py3-none-any.whl",
            "has_sig": false,
            "md5_digest": "f6628e03e3266b06538da52921a53775",
            "packagetype": "bdist_wheel",
            "python_version": "py3",
            "requires_python": ">=3.12",
            "size": 54302,
            "upload_time": "2025-08-13T21:38:31",
            "upload_time_iso_8601": "2025-08-13T21:38:31.480441Z",
            "url": "https://files.pythonhosted.org/packages/2b/04/83d7d631292cf342775438e6a6150bc968097e341ddb45ed782f8e6ae8f7/relkit-1.5.0-py3-none-any.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": null,
            "digests": {
                "blake2b_256": "809ddc2563514bb3319630acd9020e2dd44d48c909796f30074405874b3fcbc4",
                "md5": "87b57762bd27dd6bac6330e3f99cefe1",
                "sha256": "bf80463c0f010316fcb71d76befbf1d2c819914973c75b65de72eca35cebec03"
            },
            "downloads": -1,
            "filename": "relkit-1.5.0.tar.gz",
            "has_sig": false,
            "md5_digest": "87b57762bd27dd6bac6330e3f99cefe1",
            "packagetype": "sdist",
            "python_version": "source",
            "requires_python": ">=3.12",
            "size": 40057,
            "upload_time": "2025-08-13T21:38:32",
            "upload_time_iso_8601": "2025-08-13T21:38:32.976972Z",
            "url": "https://files.pythonhosted.org/packages/80/9d/dc2563514bb3319630acd9020e2dd44d48c909796f30074405874b3fcbc4/relkit-1.5.0.tar.gz",
            "yanked": false,
            "yanked_reason": null
        }
    ],
    "upload_time": "2025-08-13 21:38:32",
    "github": false,
    "gitlab": false,
    "bitbucket": false,
    "codeberg": false,
    "lcname": "relkit"
}
        
Elapsed time: 1.43847s