feat(ci)!: enhance changelog generation with context augmentation
All checks were successful
Auto Changelog & Release / release (push) Successful in 13s

This commit is contained in:
2025-09-27 21:44:20 +02:00
parent 313ace34fe
commit 8de8b47038
6 changed files with 99 additions and 15 deletions

View File

@@ -44,6 +44,11 @@ runs:
run: |
${{ github.action_path }}/scripts/install-git-cliff.sh "${{ steps.cliff_version.outputs.version }}"
- name: Install Python
shell: bash
run: |
${{ github.action_path }}/scripts/install-python.sh
- name: Set up git
shell: bash
run: |

View File

@@ -1,4 +1,4 @@
# CLIFF_VERSION=2.8.0
# CLIFF_VERSION=2.10.1
# git-cliff ~ default configuration file
# https://git-cliff.org/docs/configuration
#
@@ -10,18 +10,15 @@ owner = "actions"
repo = "auto-changelog-release-action"
[changelog]
# postprocessors
postprocessors = [
{ pattern = '<GITEA_URL>', replace = "https://git.0xmax42.io" }, # replace gitea url
]
# template for the changelog header
header = """
# Changelog\n
All notable changes to this project will be documented in this file.\n
"""
# template for the changelog body
# https://keats.github.io/tera/docs/#introduction
body = """
{%- macro remote_url() -%}
<GITEA_URL>/{{ remote.gitea.owner }}/{{ remote.gitea.repo }}
@@ -38,16 +35,26 @@ body = """
## [unreleased]
{% endif %}\
{% for group, commits in commits | group_by(attribute="group") %}
### {{ group | striptags | trim | upper_first }}
{% for commit in commits %}
### {{ group | striptags | trim | upper_first }}\n
{% for commit in commits %}\
{% if commit.merge_commit %}\
- 🔀 **{{ commit.message | upper_first }}** - \
([{{ commit.id | truncate(length=7, end="") }}]({{ self::remote_url() }}/commit/{{ commit.id }}))\
{% for child in commit.extra.children %}
{{ " " | safe }}- {% if child.scope %}*({{ child.scope }})* {% endif %}\
{% if child.breaking %}[**breaking**] {% endif %}\
{{ child.message | upper_first }} - \
([{{ child.id | truncate(length=7, end="") }}]({{ self::remote_url() }}/commit/{{ child.id }}))\
{% endfor %}\
{% else %}\
- {% if commit.scope %}*({{ commit.scope }})* {% endif %}\
{% if commit.breaking %}[**breaking**] {% endif %}\
{{ commit.message | upper_first }} - \
([{{ commit.id | truncate(length=7, end="") }}]({{ self::remote_url() }}/commit/{{ commit.id }}))\
{% endfor %}
{% endif %}
{% endfor %}\
{% endfor %}\n
"""
# template for the changelog footer
footer = """
"""

59
scripts/augment_context.py Executable file
View File

@@ -0,0 +1,59 @@
#!/usr/bin/env python3
import json
import subprocess
import sys
def git_commits_between(parent, merge):
"""Return list of commit hashes between parent and merge (exclusive of parent, inclusive of merge)."""
out = subprocess.check_output(
["git", "rev-list", f"{parent}..{merge}", "--no-merges"],
text=True
)
return [line.strip() for line in out.splitlines() if line.strip()]
def load_context(path=None):
if path:
with open(path) as f:
return json.load(f)
else:
return json.load(sys.stdin)
def main(path=None):
context = load_context(path)
commits = context[0]["commits"]
commits_by_id = {c["id"]: c for c in commits}
new_commits = []
consumed = set()
for c in commits:
if c.get("merge_commit"):
parents = subprocess.check_output(
["git", "rev-list", "--parents", "-n", "1", c["id"]],
text=True
).strip().split()
merge_id, *parent_ids = parents
if len(parent_ids) >= 2:
mainline = parent_ids[0]
children_ids = git_commits_between(mainline, merge_id)
children = []
for cid in children_ids:
if cid in commits_by_id:
children.append(commits_by_id[cid])
consumed.add(cid)
if not c.get("extra") or not isinstance(c["extra"], dict):
c["extra"] = {}
c["extra"]["children"] = children
new_commits.append(c)
filtered = [c for c in new_commits if c["id"] not in consumed]
context[0]["commits"] = filtered
json.dump(context, sys.stdout, indent=4)
if __name__ == "__main__":
main(sys.argv[1] if len(sys.argv) > 1 else None)

View File

@@ -8,7 +8,9 @@ GIT_BRANCH="${GITHUB_REF##refs/heads/}"
# === Step 1: Generate Changelog (only if file exists or on main) ===
if [[ -f "$CHANGELOG_FILE" || "$GIT_BRANCH" == "main" ]]; then
echo "📄 Generating $CHANGELOG_FILE using git-cliff..."
git-cliff -c "$CLIFF_CONFIG" -o "$CHANGELOG_FILE"
git-cliff -c "$CLIFF_CONFIG" --context \
| "${GITHUB_ACTION_PATH}/scripts/augment_context.py" \
| git-cliff -c "$CLIFF_CONFIG" --from-context - -o "$CHANGELOG_FILE"
else
echo "ℹ️ $CHANGELOG_FILE does not exist and branch is not 'main'. Skipping generation."
exit 0

9
scripts/install-python.sh Executable file
View File

@@ -0,0 +1,9 @@
#!/usr/bin/env bash
# install-python.sh – installs the latest Python version through apt
# Usage: sudo ./install-python.sh
set -euo pipefail
apt update
apt install -y python3
echo "✅ Python $(python3 --version) installed"

View File

@@ -64,7 +64,9 @@ echo "📦 Version: $VERSION"
# === Step 2: Generate changelog for release ===
echo "📄 Generating changelog for tag v$VERSION"
git-cliff -c "$CLIFF_CONFIG" -t "v$VERSION" -o "$CHANGELOG_FILE"
git-cliff -c "$CLIFF_CONFIG" -t "v$VERSION" --context \
"${GITHUB_ACTION_PATH}/scripts/augment_context.py" \
git-cliff -c "$CLIFF_CONFIG" -t "v$VERSION" --from-context - -o "$CHANGELOG_FILE"
ESCAPED_VERSION="$(echo "$VERSION" | sed 's/\./\\./g')"