CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/pypi-commitizen

Python commitizen client tool for standardized commit conventions and automated version management

Pending

Quality

Pending

Does it follow best practices?

Impact

Pending

No eval scenarios have been run

Overview
Eval results
Files

plugins.mddocs/

Plugin Development

Extensible plugin system for creating custom commit message rules, version providers, changelog formats, and version schemes. Commitizen's plugin architecture enables teams to define their own commit conventions and integrate with various project types and workflows.

Capabilities

Plugin Discovery

Automatic discovery and registration of commitizen plugins installed via entry points.

def discover_plugins() -> None:
    """
    Discover and register all available commitizen plugins.
    
    Searches for plugins in the 'commitizen.plugin' entry point group
    and registers them in the global plugin registry.
    """

registry: dict[str, type[BaseCommitizen]]
"""Global plugin registry mapping plugin names to plugin classes."""

Plugin Factory

Factory function for creating commitizen plugin instances based on configuration.

def commiter_factory(config: BaseConfig) -> BaseCommitizen:
    """
    Create commitizen plugin instance based on configuration.
    
    Parameters:
    - config: Configuration object containing plugin name
    
    Returns:
    BaseCommitizen instance for the configured plugin
    
    Raises:
    NoCommitizenFoundException: If plugin is not found
    """

Base Plugin Class

Abstract base class that all commitizen plugins must inherit from.

class BaseCommitizen:
    """
    Abstract base class for all commitizen plugins.
    
    Defines the interface that plugins must implement for commit message
    generation, validation, and version bump logic.
    """
    def __init__(self, config: BaseConfig):
        """
        Initialize plugin with configuration.
        
        Parameters:
        - config: Configuration object
        """
    
    def questions(self) -> Questions:
        """
        Return interactive questions for commit creation.
        
        Returns:
        List of question dictionaries for questionary prompts
        """
    
    def message(self, answers: dict[str, Any]) -> str:
        """
        Generate commit message from user answers.
        
        Parameters:
        - answers: Dictionary of answers from interactive questions
        
        Returns:
        Formatted commit message string
        """
    
    def example(self) -> str:
        """
        Return example commit message.
        
        Returns:
        Example commit message following plugin rules
        """
    
    def schema(self) -> str:
        """
        Return commit message schema description.
        
        Returns:
        Human-readable schema description
        """
    
    def schema_pattern(self) -> str:
        """
        Return regex pattern for commit message validation.
        
        Returns:
        Regex pattern string for validation
        """
    
    def info(self) -> str:
        """
        Return plugin information.
        
        Returns:
        Plugin description and usage information
        """
    
    def process_commit(self, commit: str) -> str:
        """
        Process commit message for changelog generation.
        
        Parameters:
        - commit: Raw commit message
        
        Returns:
        Processed commit message for changelog
        """
    
    def changelog_pattern(self) -> str:
        """
        Return regex pattern for changelog parsing.
        
        Returns:
        Regex pattern for extracting changelog information
        """
    
    def change_type_map(self) -> dict[str, str]:
        """
        Return mapping of change types to display names.
        
        Returns:
        Dictionary mapping change types to changelog section names
        """
    
    def change_type_order(self) -> list[str]:
        """
        Return ordered list of change types for changelog.
        
        Returns:
        List of change types in display order
        """
    
    def bump_pattern(self) -> str:
        """
        Return regex pattern for version bump detection.
        
        Returns:
        Regex pattern for determining version increments
        """
    
    def bump_map(self) -> dict[str, str]:
        """
        Return mapping of patterns to version increments.
        
        Returns:
        Dictionary mapping regex groups to increment types (MAJOR, MINOR, PATCH)
        """

Built-in Plugins

Conventional Commits Plugin

Standard plugin implementing the Conventional Commits specification.

class ConventionalCommitsCz(BaseCommitizen):
    """
    Plugin implementing the Conventional Commits specification.
    
    Supports standard commit types: feat, fix, docs, style, refactor, test, chore.
    Includes BREAKING CHANGE detection for major version bumps.
    """
    def questions(self) -> Questions:
        """
        Interactive questions for conventional commits.
        
        Prompts for commit type, scope, description, body, and breaking changes.
        """
    
    def message(self, answers: dict[str, Any]) -> str:
        """
        Generate conventional commit message.
        
        Format: <type>[optional scope]: <description>
        
        [optional body]
        
        [optional footer(s)]
        """

Jira Smart Plugin

Plugin for integrating with Jira issue tracking.

class JiraSmartCz(BaseCommitizen):
    """
    Plugin for Jira integration with smart branch detection.
    
    Automatically detects Jira issue keys from branch names and includes
    them in commit messages.
    """
    def questions(self) -> Questions:
        """
        Interactive questions with Jira issue integration.
        
        Includes Jira issue key detection and linking.
        """

Customizable Plugin

Highly configurable plugin for teams with specific commit conventions.

class CustomizeCommitsCz(BaseCommitizen):
    """
    Customizable plugin supporting user-defined commit conventions.
    
    Allows complete customization of questions, message format, and validation
    through configuration file settings.
    """
    def questions(self) -> Questions:
        """
        Questions defined in configuration [tool.commitizen.customize.questions].
        
        Supports all questionary question types with full customization.
        """

Plugin Development Guide

Creating a Custom Plugin

from commitizen.cz.base import BaseCommitizen
from commitizen.defaults import Questions

class MyCustomCz(BaseCommitizen):
    """Custom commitizen plugin for my team's conventions."""
    
    def questions(self) -> Questions:
        return [
            {
                "type": "list",
                "name": "type",
                "message": "Select the type of change:",
                "choices": [
                    {"value": "feature", "name": "feature: New feature"},
                    {"value": "bugfix", "name": "bugfix: Bug fix"},
                    {"value": "docs", "name": "docs: Documentation"},
                    {"value": "refactor", "name": "refactor: Code refactoring"}
                ]
            },
            {
                "type": "input",
                "name": "scope",
                "message": "Scope (optional):"
            },
            {
                "type": "input", 
                "name": "subject",
                "message": "Short description:",
                "validate": lambda x: len(x) > 0 and len(x) <= 50
            },
            {
                "type": "input",
                "name": "body",
                "message": "Longer description (optional):"
            }
        ]
    
    def message(self, answers: dict[str, Any]) -> str:
        scope = f"({answers['scope']})" if answers.get('scope') else ""
        message = f"{answers['type']}{scope}: {answers['subject']}"
        
        if answers.get('body'):
            message += f"\n\n{answers['body']}"
            
        return message
    
    def example(self) -> str:
        return "feature(auth): add OAuth2 integration"
    
    def schema(self) -> str:
        return "<type>[(scope)]: <subject>\n\n[body]"
    
    def schema_pattern(self) -> str:
        return r"^(feature|bugfix|docs|refactor)(\(.+\))?: .{1,50}$"
    
    def info(self) -> str:
        return "Custom plugin for MyTeam commit conventions"
    
    def bump_pattern(self) -> str:
        return r"^(feature|BREAKING)"
    
    def bump_map(self) -> dict[str, str]:
        return {
            "BREAKING": "MAJOR",
            "feature": "MINOR",
            "bugfix": "PATCH"
        }
    
    def change_type_map(self) -> dict[str, str]:
        return {
            "feature": "Features",
            "bugfix": "Bug Fixes", 
            "docs": "Documentation",
            "refactor": "Refactoring"
        }

Plugin Entry Points

setup.py Entry Points

from setuptools import setup, find_packages

setup(
    name="my-commitizen-plugin",
    version="1.0.0",
    packages=find_packages(),
    install_requires=["commitizen>=3.0.0"],
    entry_points={
        "commitizen.plugin": [
            "my_custom_cz = my_plugin:MyCustomCz"
        ]
    }
)

pyproject.toml Entry Points

[build-system]
requires = ["poetry-core"]
build-backend = "poetry.core.masonry.api"

[tool.poetry]
name = "my-commitizen-plugin"
version = "1.0.0"
description = "Custom commitizen plugin"

[tool.poetry.dependencies]
python = "^3.8"
commitizen = "^3.0.0"

[tool.poetry.plugins."commitizen.plugin"]
my_custom_cz = "my_plugin:MyCustomCz"

Version Provider Plugins

Custom version providers for different project types.

class VersionProvider:
    """Abstract base class for version providers."""
    
    def get_version(self) -> str:
        """
        Get current version from provider source.
        
        Returns:
        Current version string
        """
    
    def set_version(self, version: str) -> None:
        """
        Set version in provider source.
        
        Parameters:
        - version: New version string
        """
    
    @property
    def keyword(self) -> str:
        """
        Provider keyword for entry point registration.
        
        Returns:
        String identifier for the provider
        """

class CustomProvider(VersionProvider):
    """Example custom version provider."""
    
    @property
    def keyword(self) -> str:
        return "custom"
    
    def get_version(self) -> str:
        # Read version from custom source
        with open("VERSION.txt") as f:
            return f.read().strip()
    
    def set_version(self, version: str) -> None:
        # Write version to custom source
        with open("VERSION.txt", "w") as f:
            f.write(version)

Changelog Format Plugins

Custom changelog formats for different documentation styles.

class ChangelogFormat(Protocol):
    """Protocol for changelog format implementations."""
    
    def get_changelog(
        self,
        tree: dict[str, Any],
        header_format: str = "",
        **kwargs: Any
    ) -> str:
        """
        Generate changelog content from commit tree.
        
        Parameters:
        - tree: Parsed commit tree structure
        - header_format: Header format template
        - kwargs: Additional format-specific options
        
        Returns:
        Formatted changelog content
        """

class CustomChangelogFormat:
    """Example custom changelog format."""
    
    def get_changelog(
        self,
        tree: dict[str, Any], 
        header_format: str = "",
        **kwargs: Any
    ) -> str:
        # Generate custom format changelog
        content = []
        
        for version, changes in tree.items():
            content.append(f"## Version {version}")
            
            for change_type, items in changes.items():
                content.append(f"### {change_type.title()}")
                for item in items:
                    content.append(f"- {item}")
                content.append("")
        
        return "\n".join(content)

Plugin Configuration

Using Custom Plugins

[tool.commitizen]
name = "my_custom_cz"  # Plugin entry point name
version = "1.0.0"

# Plugin-specific configuration
[tool.commitizen.customize]
# Custom plugin settings go here

Plugin Testing

import pytest
from commitizen.config import BaseConfig
from my_plugin import MyCustomCz

def test_plugin_questions():
    config = BaseConfig({"name": "my_custom_cz"})
    plugin = MyCustomCz(config)
    
    questions = plugin.questions()
    assert len(questions) > 0
    assert questions[0]["name"] == "type"

def test_plugin_message():
    config = BaseConfig({"name": "my_custom_cz"})
    plugin = MyCustomCz(config)
    
    answers = {
        "type": "feature",
        "subject": "add new feature"
    }
    
    message = plugin.message(answers)
    assert message == "feature: add new feature"

def test_plugin_validation():
    config = BaseConfig({"name": "my_custom_cz"})
    plugin = MyCustomCz(config)
    
    pattern = plugin.schema_pattern()
    import re
    
    assert re.match(pattern, "feature: valid message")
    assert not re.match(pattern, "invalid message format")

Install with Tessl CLI

npx tessl i tessl/pypi-commitizen

docs

commands.md

configuration.md

git-operations.md

index.md

plugins.md

version-management.md

tile.json