- Python 95.5%
- Dockerfile 4.5%
|
|
||
|---|---|---|
| .forgejo | ||
| docs | ||
| images | ||
| src | ||
| tests | ||
| .gitignore | ||
| .pre-commit-config.yaml | ||
| action.yaml | ||
| CHANGELOG.md | ||
| CODE_OF_CONDUCT.md | ||
| CONTRIBUTING.md | ||
| delete.txt | ||
| Dockerfile | ||
| LICENSE | ||
| pyproject.toml | ||
| README.md | ||
| tox.ini | ||
| version.toml | ||
git-herald 
A Forgejo Action that parses conventional commits from a pull request and automatically updates your changelog, version files, and any other files you specify.
Features
Commit parsing
- Parses conventional commits (
feat,fix,chore, etc.) from PR commits - Three accepted forms for breaking changes:
BREAKINGprefix,!marker, orBREAKING CHANGE:footer trailer - Footer trailer support for
Closes,Fixes,Resolves,Refs, andSee also— multiple issues per line, colon optional - Optional
[dev-notes]and[doc-notes]blocks in commit bodies for dev- and doc-audience context - Automatic revert handling
Output formatting
- Groups entries by type under a CalVer version heading (
YYYY.MM.DD.N) - Highlights breaking changes in a dedicated section with migration detail when provided
- Hyperlinks issue references to your Forgejo or GitHub instance
- Falls back to the PR number when no issue reference is present in the commit subject
Version file updates
- Updates any number of version files using a sentinel marker — no hardcoded paths
- Writes
version.tomlwith a configurable section key - Supports
.py,.toml,.cfg,.ini,.txt,.rst, and.mdfiles
Platform support
- Compatible with Forgejo and GitHub Actions
- Installs its own Python — no
setup-pythonstep needed in your workflow
Requirements
- A Linux runner (glibc or musl) with network access to
github.comreleases. git-herald uses uv internally to install Python on first run, and uv downloads Python builds from GitHub releases. - If uv is already installed on the runner, git-herald uses it in place. Otherwise it installs uv for the duration of the step.
- No prior
setup-pythonstep is needed — in fact, adding one can cause conflicts on slim container images wheresetup-pythonfails to detect the distro.
Usage
Add to your .forgejo/workflows/ workflow file. Use the full URL so the
runner always resolves to the correct instance regardless of
DEFAULT_ACTIONS_URL.
Minimal complete example
A working workflow you can paste as-is and adapt:
name: Update Changelog
on:
pull_request:
branches: [main]
jobs:
update_changelog:
runs-on: docker
permissions:
contents: write
pull-requests: read
steps:
- uses: https://code.forgejo.org/actions/checkout@v5
with:
fetch-depth: 0
token: ${{ secrets.FORGEJO_TOKEN }}
- uses: https://forge.tail7f01cb.ts.net/dunwright/git-herald@v1
with:
token: ${{ secrets.FORGEJO_TOKEN }}
version-files: |
pyproject.toml
myapp/__init__.py
FORGEJO_TOKEN is a PAT with read/write repo access. The auto-generated
GITHUB_TOKEN also works if you only need access to the current repo and
are not on a protected branch.
Custom bot identity
By default git-herald commits as git-herald <action@forgejo.com>. You can
override this to match your organisation's conventions:
- uses: https://forge.tail7f01cb.ts.net/dunwright/git-herald@v1
with:
token: ${{ secrets.FORGEJO_TOKEN }}
git-user-name: "mycompany-bot"
git-user-email: "ci-bot@mycompany.com"
version-files: |
pyproject.toml
README.md
Version bump commits are unsigned by default. If your repo requires signed commits, configure GPG signing in a step before calling git-herald.
GitHub Actions
GitHub Actions supports referencing actions hosted on external instances using the full URL — the same pattern as Forgejo. No mirroring or checkout workaround needed.
- uses: https://forge.tail7f01cb.ts.net/dunwright/git-herald@v1
with:
token: ${{ secrets.GITHUB_TOKEN }}
version-files: |
pyproject.toml
myapp/__init__.py
docs/source/conf.py
README.rst
version-toml-key: "tb.version"
Inputs
| Input | Required | Default | Description |
|---|---|---|---|
token |
✅ | — | Forgejo/GitHub token with write access |
changelog-path |
❌ | CHANGELOG.md |
Path to changelog file |
version-toml-path |
❌ | version.toml |
Path to version TOML file |
version-toml-key |
❌ | version |
Section name in version.toml, e.g. tb.version |
version-files |
❌ | "" |
Newline-separated list of additional files to update |
python-version |
❌ | 3.13 |
Python version used to run the action's script. Installed on-demand by uv — no separate setup step required |
git-user-email |
❌ | action@forgejo.com |
Email used for the version bump commit |
git-user-name |
❌ | git-herald |
Display name used for the version bump commit |
Outputs
| Output | Description |
|---|---|
changes-made |
"true" if the changelog was updated, "false" if no relevant commits found |
version |
The version string written, e.g. 2026.04.13.1 |
commit-sha |
SHA of the version bump commit pushed to the PR branch. Empty if no changes were made |
First-run setup
Before the first run, two files must exist in your repository:
version.toml— tracks the current version between runs.CHANGELOG.md— contains a placeholder marking where new versions should be inserted.
Create version.toml
Place this at the root of your repository:
[version]
__version__ = "2026.01.01.1"
The section name (version by default) is controlled by the
version-toml-key input. For example, version-toml-key: "tb.version"
means your file should be:
[tb.version]
__version__ = "2026.01.01.1"
git-herald overwrites this file on every run with the new version — you do not need to update it manually after the first run.
Add the CHANGELOG placeholder
In CHANGELOG.md, add this comment on the line where new versions should
be inserted:
<!--next-version-placeholder-->
Every new version is written directly below this line, so the most recent release appears at the top of the changelog.
Commit format
Commits must follow this pattern to be picked up:
type(scope): description #ISSUE_NUMBER
The type and scope are required. The #ISSUE_NUMBER is optional — when
omitted, git-herald falls back to the PR number and renders the entry as
PR #nn. See Issue reference and PR fallback
below.
Supported types:
| Type | Changelog section |
|---|---|
feat |
Features |
fix |
Bug Fixes |
perf |
Performance |
refactor |
Code Refactoring |
docs |
Documentation |
style |
Formatting |
test |
Testing |
chore |
Maintenance |
Breaking changes
Any of three forms will flip the breaking-change flag; you can combine them if you like:
1. Legacy prefix — prepend BREAKING to the subject:
BREAKING feat(api): remove legacy endpoint #42
2. Bang marker — append ! after the scope:
feat(api)!: remove legacy endpoint #42
3. Footer trailer — add a BREAKING CHANGE: line in the commit footer.
The description text is rendered in the changelog alongside the entry:
feat(api): remove legacy endpoint #42
BREAKING CHANGE: /v1 endpoints are gone. Migrate callers to /v2 —
see docs/migration.md for the field renames.
Breaking changes appear in a dedicated ⚠ BREAKING CHANGES section at the
top of the version entry, and also in their normal type section.
Issue reference and PR fallback
The #nn reference in the subject is optional but strongly preferred. When
present, the entry links to the issue. When absent, git-herald falls back to
the PR number and renders the entry as PR #nn linking to the pull request.
The fallback exists for commits where no issue was filed — typo fixes, routine chore work, emergency hotfixes. When you do have an issue, reference it: issues are durable across PRs, branch renames, and merge-squash rewrites, making the changelog more useful for archaeology.
Footer trailers
git-herald recognises standard git footer trailers. All trailer keys are case-insensitive and the colon is optional:
| Trailer | Purpose | Rendered as |
|---|---|---|
Closes #n / Fixes #n / Resolves #n |
Issue-closing references | > Closes: [#n](...) |
Refs #n / See also #n |
Non-closing references | > Refs: [#n](...) |
BREAKING CHANGE: desc |
Breaking change with description | > ⚠ desc + flags the entry |
Multiple issues per trailer line are supported:
Closes #17, #23, #42
Optional body blocks
Add context for developers and doc writers by including one or both blocks in the commit body. Both are optional and can appear in any order.
feat(payments): add stripe checkout button #42
Introduces a Stripe checkout flow with support for saved cards.
[dev-notes]:
"""
PaymentContext now exposes a usePaymentButton hook.
"""
[doc-notes]:
"""
A new payment button is available in the checkout flow.
"""
Closes #17, #23
BREAKING CHANGE: payload shape changed, migrate callers to v2
Refs #51
Rendered examples
The basic form renders as a single bullet:
- add payment button (ui) [#42](https://forge.example.com/dunwright/myapp/issues/42)
When no issue is referenced, the PR fallback kicks in:
- bump actions/checkout to v5 (ci) [PR #99](https://forge.example.com/dunwright/myapp/pulls/99)
A fully-loaded commit with breaking change, body blocks, and footer trailers
renders with blockquote detail beneath. Each block (breaking description,
dev notes, doc notes, closes, refs) is separated by a blank > line so
CommonMark renderers display each on its own visual line:
- BREAKING: add stripe checkout button (payments) [#42](https://forge.example.com/dunwright/myapp/issues/42)
> ⚠ payload shape changed, migrate callers to v2
>
> 🔧 PaymentContext now exposes a usePaymentButton hook.
>
> 📝 A new payment button is available in the checkout flow.
>
> Closes: [#17](https://forge.example.com/dunwright/myapp/issues/17), [#23](https://forge.example.com/dunwright/myapp/issues/23)
>
> Refs: [#51](https://forge.example.com/dunwright/myapp/issues/51)
Sentinel marker
For each file listed in version-files, place a sentinel comment on the
line immediately above your version string. On each run git-herald
finds the sentinel and updates the line directly below it:
- If that line already contains a version (a
YYYY.MM.DD.NCalVer string), git-herald replaces only the version, leaving the rest of the line intact. This is what lets the version live inside richer formatting such as a badge URL. - If no version is present yet, git-herald writes the default version line for that file type, shown in the examples below.
| Extension | Sentinel to add |
|---|---|
.py .toml .cfg .ini .txt |
# {{version}} |
.rst |
.. {{version}} |
.md |
<!-- {{version}} --> |
Examples
pyproject.toml
[project]
name = "myapp"
# {{version}}
version = "2026.01.01.1"
myapp/__init__.py
# {{version}}
__version__ = "2026.01.01.1"
docs/source/conf.py
# {{version}}
__version__ = "2026.01.01.1"
README.rst
.. {{version}}
**Version = 2026.01.01.1**
Version badges
Because git-herald swaps only the CalVer substring when one is already present, you can embed the version inside a shields.io badge and the number stays current on every run. Add the badge once with a starting version — any valid CalVer — directly below the sentinel. From there git-herald takes over bumping it.
README.md — the badge can share the heading line, since markdown allows
inline images:
<!-- {{version}} -->
# myproject [](https://forge.example.com/you/myproject/src/branch/main/CHANGELOG.md)
README.rst — reStructuredText can't place an image inside an underlined
heading, so put the badge above or below the title on its own:
.. {{version}}
.. image:: https://img.shields.io/badge/version-2026.01.01.1-blue
:target: https://forge.example.com/you/myproject/src/branch/main/CHANGELOG.md
:alt: Version
In both cases the line carrying the version must sit immediately below the
sentinel — for RST that is the image:: line, and its :target: and :alt:
options are left untouched on every run. The badge label and colour are
yours to choose; only the CalVer is rewritten.
Versioning this action
Pin to a tag or branch:
# Track the main branch — receives updates immediately.
uses: https://forge.tail7f01cb.ts.net/dunwright/git-herald@main
# Pin to a specific release tag — stable, updated only when you bump.
uses: https://forge.tail7f01cb.ts.net/dunwright/git-herald@v1.2.0
A formal release cadence will be published once the action stabilises. For now, pinning to a commit SHA is the safest choice if you need full reproducibility:
uses: https://forge.tail7f01cb.ts.net/dunwright/git-herald@abc1234
License
MIT © Dunwright