From 8de8b470386cf9f21cec660ba71d840ea6786231 Mon Sep 17 00:00:00 2001 From: "Max P." Date: Sat, 27 Sep 2025 21:44:20 +0200 Subject: [PATCH] feat(ci)!: enhance changelog generation with context augmentation --- action.yml | 5 ++ cliff.toml | 33 +++++++------ scripts/augment_context.py | 59 ++++++++++++++++++++++++ scripts/generate-unreleased-changelog.sh | 4 +- scripts/install-python.sh | 9 ++++ scripts/release-from-version.sh | 4 +- 6 files changed, 99 insertions(+), 15 deletions(-) create mode 100755 scripts/augment_context.py create mode 100755 scripts/install-python.sh diff --git a/action.yml b/action.yml index 472200d..6afbbe1 100644 --- a/action.yml +++ b/action.yml @@ -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: | diff --git a/cliff.toml b/cliff.toml index f6707c7..275a02e 100644 --- a/cliff.toml +++ b/cliff.toml @@ -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 = '', 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() -%} /{{ 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 %} - - {% 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 %} + ### {{ 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 }}))\ + {% endif %} + {% endfor %}\ {% endfor %}\n """ -# template for the changelog footer footer = """ """ diff --git a/scripts/augment_context.py b/scripts/augment_context.py new file mode 100755 index 0000000..92d1d6e --- /dev/null +++ b/scripts/augment_context.py @@ -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) diff --git a/scripts/generate-unreleased-changelog.sh b/scripts/generate-unreleased-changelog.sh index 6019b50..23c1eda 100755 --- a/scripts/generate-unreleased-changelog.sh +++ b/scripts/generate-unreleased-changelog.sh @@ -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 diff --git a/scripts/install-python.sh b/scripts/install-python.sh new file mode 100755 index 0000000..6a70504 --- /dev/null +++ b/scripts/install-python.sh @@ -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" \ No newline at end of file diff --git a/scripts/release-from-version.sh b/scripts/release-from-version.sh index 5ad6f1a..6682569 100755 --- a/scripts/release-from-version.sh +++ b/scripts/release-from-version.sh @@ -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')"