Extract release notes from markdown changelog that follow keep a changelog or common changelog format.
Hed, pronounced "head" (/hɛd/),
is journalistic shorthand referring to the "headline" of a news story.
pip install hedWith uv:
uv tool install hed- Extract
--changeloglines between--capture-start(included) and--capture-end(not included). - Normalize the extracted headings so the topmost heading becomes h1,
e.g.,
## Titlebecomes# Title.
Depending on how it was configured, hed can apply some transformations
to the extracted release notes:
- If
--titleis provided, update the h1. - If
--diff-urlis provided, adds a link to compare between tags at the end. If--previous-tagis also provided, this tag is used to build the comparison link, otherwise,hedwill try to find the closest reachable tag from--tag.
Some command-line options can be configured via hed.toml or pyproject.toml,
under the tool.hed namespace.
See https://toml.io/ for how to write TOML.
[tool.hed]
changelog = "CHANGELOG.md"
capture-end = '^## {tag}'
capture-start = '^## '
diff-url = "https://github.com/owner/repo/compare/{prev}...{tag}"
softbreak = true
title = "{tag}"Given a CHANGELOG.md file similar to this:
# Changelog
## [1.0.1](https://github.com/owner/repo/releases/tag/1.0.1) - 2026-01-10
### Bug fixes
- Fixed a thing! (#1235)
## [1.0.0](https://github.com/owner/repo/releases/tag/1.0.0) - 2026-01-9
### Breaking changes
- Removed a deprecated feature. (#1234)Extract and normalize release notes:
$ hed --tag 1.0.1
# [1.0.1](https://github.com/owner/repo/releases/tag/1.0.1) - 2026-01-10
## Bug fixes
- Fixed a thing! (#1235)
Change the title:
$ hed --tag 1.0.1 --title "{tag} Release Notes"
# 1.0.1 Release Notes
## Bug fixes
- Fixed a thing! (#1235)
Add a link to compare between releases:
$ hed --tag 1.0.1 --previous-tag 1.0.0 --diff-url "https://github.com/owner/repo/compare/{prev}...{tag}"
# [1.0.1](https://github.com/owner/repo/releases/tag/1.0.1) - 2026-01-10
## Bug fixes
- Fixed a thing! (#1235)
**Full Changelog:** [1.0.0...1.0.1](https://github.com/owner/repo/compare/1.0.0...1.0.1)
Create a GitLab release using the release keyword.
gitlab-release:
stage: deploy
image: registry.gitlab.com/gitlab-org/cli:latest
rules:
- if: $CI_COMMIT_TAG
script:
- apk update && apk add curl
- curl -LsSf https://astral.sh/uv/install.sh | sh
- source $HOME/.local/bin/env
- uvx hed --tag $CI_COMMIT_TAG > RELEASE_NOTES.md
release:
tag_name: '$CI_COMMIT_TAG'
name: '$CI_COMMIT_TAG'
description: 'RELEASE_NOTES.md'Create a GitHub release using softprops/action-gh-release.
jobs:
draft-release:
name: Create Release
runs-on: ubuntu-latest
if: github.ref_type == 'tag'
permissions:
contents: write
steps:
- uses: astral-sh/setup-uv@v7
- run: uvx hed --tag "${{ github.ref_name }}" > RELEASE_NOTES.md
- uses: softprops/action-gh-release@v2
with:
body_path: 'RELEASE_NOTES.md'For guidance on setting up a development environment and contributing, see CONTRIBUTING.md.