Change log creator for gitmoji logs
Project description
Girokmoji
Automatic changelog generator with built-in SemVer 2.0 tagging.
Turn your Gitmoji commits into release notes and version bumps. Girokmoji relies solely on pygit2 and runs anywhere
libgit2 is available.
We use minimum dependencies. Currently, only pygit2, which requires no runtime
git executable, good enough binary distributions, is used.
Designed for General Use
Pipeline as a trigger
Pipelines, such as SCM provided ones (e.g., GitHub Actions), dedicated solutions (e.g., Jenkins) are best when you use it as a "trigger".
Do a single thing
Release notes and tagging with Gitmoji flair.
Powered by a SemVer 2.0 parser, the release command tags your repo and outputs the changelog.
Run it with uvx in CI for reproducible builds.
Basic use case
Semantic Version Release
with uv (recommended, especially for release pipelines)
uvx --from "girokmoji@latest" girokmoji release YOU_PROJECT_NAME --bump patch --repo-dir . > release.md
Generate Release Note
with uv (recommended, especially for release pipelines)
uvx --from "girokmoji@latest" girokmoji YOUR_PROJECT_NAME 2025-02-10 your_project_repo_dir v0.1.0 v0.5.2 > release_note.md
You can control how the commit range is determined with --range:
# Auto (default): direct when linear, common-base when diverged
girokmoji YOUR_PROJECT_NAME 2025-02-10 . v1.2.3 v1.3.0 --range auto
# Force raw tail..head range
girokmoji YOUR_PROJECT_NAME 2025-02-10 . v1.2.3 v1.3.0 --range direct
# Force merge-base..head (recommended for hotfix vs latest on different lines)
girokmoji YOUR_PROJECT_NAME 2025-02-10 . v1.2.3-hotfix v1.3.0 --range common-base
# Require linear history and fail if not
girokmoji YOUR_PROJECT_NAME 2025-02-10 . v1.2.3 v1.3.0 --strict-ancestor
Notes:
- Informational notices about range auto-detection (e.g., switching to common-base, or head-only fallback) are printed to stderr. The generated changelog is written to stdout, so you can safely redirect stdout to a file without capturing notices.
Go With Classic Way
Clone
git clone https://github.com/KMilhan/girokmoji.git
with isolated pip
python -m girokmoji YOUR_PROJECT_NAME 2025-02-10 your_project_repo_dir v0.1.0 v0.5.2 > release_note.md
or
girokmoji YOUR_PROJECT_NAME 2025-02-10 your_project_repo_dir v0.1.0 v0.5.2 > release_note.md
Note: Please change repository url with your repository url. Also, clone with enough depth, so libgit2 can
traverse to the past tag.
Installation
with uv (recommended for development)
Install uv and create a virtual
environment:
uv pip install girokmoji
The last command installs this package together with development tools such as
pytest. Use uv pip inside the environment whenever you need to add more
packages.
with isolated pip
If you do not use uv, you can install the project with plain pip in an
already isolated environment:
pip install girokmoji
Show version
girokmoji --version
GitHub Release payload
To create JSON payload for GitHub Release:
girokmoji YOUR_PROJECT_NAME 2025-02-10 your_project_repo_dir v0.1.0 v0.5.2 --github-payload > release.json
Automated release helper
To bump the project version using the built-in versioning (fully compliant with Semantic Versioning 2.0) and output the changelog generated by girokmoji in one go:
girokmoji release YOUR_PROJECT_NAME --bump patch --repo-dir . > release.md
The release command also accepts range-related flags which apply to the generated diff between the last tag and the new tag:
# Default auto behavior (linear histories use direct)
girokmoji release YOUR_PROJECT_NAME --bump patch --repo-dir . --range auto
# Enforce linear history if desired
girokmoji release YOUR_PROJECT_NAME --bump minor --repo-dir . --strict-ancestor
# Quiet or verbose notices
girokmoji release YOUR_PROJECT_NAME --bump patch --repo-dir . --quiet
girokmoji release YOUR_PROJECT_NAME --bump patch --repo-dir . --verbose
Tag selection and hotpatch handling
By default, girokmoji determines the previous tag (tail) for generating release notes and bumping versions using only tags that are reachable from the current HEAD.
- Tail tag selection:
- Only tags whose target commit is an ancestor of HEAD are considered.
- Among those, the largest SemVer tag is chosen.
- Tag formats:
- Both with or without a leading "v" are accepted (e.g., v1.2.3 or 1.2.3).
- Both annotated and lightweight tags are supported.
Hotpatch/global floor:
- To avoid version regressions when a larger SemVer tag exists on another branch (e.g., a hotpatch), the bump baseline uses the maximum of:
- The last reachable SemVer from HEAD, and
- The global maximum SemVer tag across the repository.
- Example: If HEAD’s reachable max is v1.2.3 but there is a v2.0.0 tag on a different branch, a patch bump will produce v2.0.1 by default.
- Library usage (Python API) can opt out of this behavior with:
- auto_release(..., version_floor_scope="reachable") to base the bump only on the reachable tag.
This change affects how the previous tag is chosen and how the new version is computed, while the commit range selection (auto/direct/common-base) continues to work as documented below.
Range Modes (commit selection)
auto(default):- Uses
tail..headwhen the tail is an ancestor of head (linear history). - Otherwise uses
merge-base(tail, head)..head. - If there is no common base, shows commits reachable from
headonly.
- Uses
direct: Alwaystail..head.common-base: Alwaysmerge-base(tail, head)..head(falls back to head-only when no base).
Flags and behavior:
--range/--range-mode {auto,direct,common-base}--strict-ancestor: fail if refs diverge (tail is not ancestor of head)--quiet: suppress informational notices on stderr--verbose: print chosen mode and resolved SHAs to stderr
Examples:
# Notes for a mainline release since the previous mainline tag
girokmoji MyProj 2025-08-17 . v1.2.3 v1.3.0 --range auto
# Notes comparing a hotfix tag and the latest tag on main
girokmoji MyProj 2025-08-17 . v1.2.3-hotfix v1.3.0 --range auto
# Enforce linear history in CI
girokmoji MyProj 2025-08-17 . v1.2.3 v1.3.0 --strict-ancestor
Example
For generated release note, go EXAMPLE.md
Development and Testing
The recommended workflow for local development uses uv for dependency
management. uv creates an isolated virtual environment and installs the
required packages using its own resolver.
# create a virtual environment in `.venv`
uv venv
# install main and development dependencies
uv sync
# run the test suite
uv run pytest
See multiline commit test for multi-line commit examples and how commits are grouped in release notes.
Mutation testing
We use mutmut for mutation testing. For stability, subprocess-based CLI/E2E tests are excluded during mutation runs via pytest markers:
- Markers:
@pytest.mark.clifor tests that invoke the CLI in a separate Python process.- Module-level
pytestmark = pytest.mark.e2efor end-to-end tests.
- Runner filter (configured in
pyproject.toml):pytest -q -m 'not e2e and not cli'tests_dir = ["tests"]so all tests are discovered but filtered by markers.
Commands:
# run the full test suite normally (includes cli/e2e)
uv run pytest -q
# run mutation tests (excludes cli/e2e via marker filter)
uv run mutmut run
# show surviving mutants
uv run mutmut results
Make targets are also available:
make mutation
make mutation-results
Notes:
- Regular pytest remains unchanged and continues to run the full suite, including CLI/E2E.
- Mutation runs intentionally skip CLI/E2E to avoid subprocess-related instability during mutmut’s stats/listing phase.
- If you need to experiment with including CLI/E2E in mutation, adjust the runner filter in
pyproject.tomltemporarily.
Continuous Integration
A typical pipeline installs uv, syncs dependencies and runs girokmoji via uvx:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- uses: astral-sh/setup-uv@v5
- run: uv pip install .
- run: pytest
- run: uvx --from "girokmoji@latest" girokmoji release MyProject --bump patch --repo-dir .
Publishing to PyPI
The "Publish Python Package to PyPI" workflow can be dispatched manually. Provide the
tag input to select which release tag should be built and uploaded. The workflow
checks out the chosen tag, runs tests, builds the package and then deploys it to PyPI.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file girokmoji-0.6.0.tar.gz.
File metadata
- Download URL: girokmoji-0.6.0.tar.gz
- Upload date:
- Size: 77.6 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
f756b704f5fe8a5366d7f993f1265a793dc092a099816386b822fc1c81672f61
|
|
| MD5 |
f1a82079b26733026fccaca5b0384fda
|
|
| BLAKE2b-256 |
a0aa3c5c7ed3d82a6fe0d40d1224e5a5fbd3860b043f3815e771472c1c3ef1d3
|
Provenance
The following attestation bundles were made for girokmoji-0.6.0.tar.gz:
Publisher:
python-publish.yml on KMilhan/girokmoji
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
girokmoji-0.6.0.tar.gz -
Subject digest:
f756b704f5fe8a5366d7f993f1265a793dc092a099816386b822fc1c81672f61 - Sigstore transparency entry: 583953774
- Sigstore integration time:
-
Permalink:
KMilhan/girokmoji@531afe5c6aa5ebf1a04e9016b8bdf48976c93747 -
Branch / Tag:
refs/heads/main - Owner: https://github.com/KMilhan
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
python-publish.yml@531afe5c6aa5ebf1a04e9016b8bdf48976c93747 -
Trigger Event:
workflow_dispatch
-
Statement type:
File details
Details for the file girokmoji-0.6.0-py3-none-any.whl.
File metadata
- Download URL: girokmoji-0.6.0-py3-none-any.whl
- Upload date:
- Size: 32.0 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
a0bee38e3178d3be56358cf9e8b04d9b1ca9fe8a1cab10c9152148acc8d63a2f
|
|
| MD5 |
3fe1bffb13222cf19f2b70f556b16d68
|
|
| BLAKE2b-256 |
4cddd717d2251c79c6df6e4d9ee4725c98822cbc027f61651e4b62617ba30248
|
Provenance
The following attestation bundles were made for girokmoji-0.6.0-py3-none-any.whl:
Publisher:
python-publish.yml on KMilhan/girokmoji
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
girokmoji-0.6.0-py3-none-any.whl -
Subject digest:
a0bee38e3178d3be56358cf9e8b04d9b1ca9fe8a1cab10c9152148acc8d63a2f - Sigstore transparency entry: 583953776
- Sigstore integration time:
-
Permalink:
KMilhan/girokmoji@531afe5c6aa5ebf1a04e9016b8bdf48976c93747 -
Branch / Tag:
refs/heads/main - Owner: https://github.com/KMilhan
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
python-publish.yml@531afe5c6aa5ebf1a04e9016b8bdf48976c93747 -
Trigger Event:
workflow_dispatch
-
Statement type: