Skip to content

Commit 83f5979

Browse files
committed
misc: Use git-cliff to generate release changelog
git-cliff allows for more flexible release changelog generation. Add another workflow to show the changelog for all unreleased changes. This allows for checking the changes before making a new release and to decide which release type needs to be applied.
1 parent 4b6f42e commit 83f5979

File tree

4 files changed

+197
-8
lines changed

4 files changed

+197
-8
lines changed

.github/workflows/changelog.yml

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
name: Show changelog since last release
2+
3+
on:
4+
workflow_dispatch:
5+
6+
jobs:
7+
changelog:
8+
name: Show changelog since last release
9+
runs-on: 'ubuntu-latest'
10+
steps:
11+
- name: Checkout code
12+
uses: actions/checkout@v4
13+
with:
14+
fetch-depth: 0 # for conventional commits and getting all git tags
15+
persist-credentials: false
16+
- name: Install git-cliff
17+
uses: greenbone/actions/uv@v3
18+
with:
19+
install: git-cliff
20+
- name: Determine changelog
21+
env:
22+
GITHUB_REPO: ${{ github.repository }}
23+
GITHUB_TOKEN: ${{ github.token }}
24+
run: |
25+
git-cliff -v --strip header --unreleased -o /tmp/changelog.md
26+
- name: Show changelog
27+
run: |
28+
cat /tmp/changelog.md
29+
cat /tmp/changelog.md >> $GITHUB_STEP_SUMMARY

.github/workflows/release.yml

Lines changed: 57 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -19,9 +19,60 @@ on:
1919
jobs:
2020
build-and-release:
2121
name: Create a new release
22-
uses: greenbone/workflows/.github/workflows/release-generic.yml@main
23-
with:
24-
versioning-scheme: semver
25-
release-type: ${{ inputs.release-type }}
26-
release-version: ${{ inputs.release-version }}
27-
secrets: inherit
22+
# If the event is a workflow_dispatch or on of the labels 'pre release',
23+
# 'patch release', 'minor release' or 'major release' is set and PR is
24+
# closed because of a merge
25+
# NOTE: priority of set labels will be alpha > release-candidate > patch > minor > major,
26+
# so if 'major' and 'patch' labels are set, it will create a patch release.
27+
if: |
28+
( github.event_name == 'workflow_dispatch') || (
29+
( contains(github.event.pull_request.labels.*.name, 'alpha release') ||
30+
contains(github.event.pull_request.labels.*.name, 'rc release') ||
31+
contains(github.event.pull_request.labels.*.name, 'patch release') ||
32+
contains(github.event.pull_request.labels.*.name, 'minor release') ||
33+
contains(github.event.pull_request.labels.*.name, 'major release')) &&
34+
github.event.pull_request.merged == true )
35+
runs-on: "ubuntu-latest"
36+
steps:
37+
- name: Selecting the Release type
38+
id: release-type
39+
uses: greenbone/actions/release-type@v3
40+
with:
41+
release-type-input: ${{ inputs.release-type }}
42+
- name: Checkout code
43+
uses: actions/checkout@v4
44+
with:
45+
fetch-depth: 0 # for conventional commits and getting all git tags
46+
persist-credentials: false
47+
ref: ${{ steps.release-type.outputs.release-ref }}
48+
- name: Determine release version
49+
id: release-version
50+
uses: greenbone/actions/release-version@v3
51+
with:
52+
release-type: ${{ steps.release-type.outputs.release-type }}
53+
release-version: ${{ inputs.release-version }}
54+
versioning-scheme: "semver"
55+
- name: Install git-cliff
56+
uses: greenbone/actions/uv@v3
57+
with:
58+
install: git-cliff
59+
- name: Determine changelog
60+
env:
61+
GITHUB_REPO: ${{ github.repository }}
62+
GITHUB_TOKEN: ${{ github.token }}
63+
run: |
64+
git-cliff -v --strip header -o /tmp/changelog.md --unreleased --tag ${{ steps.release-version.outputs.release-version }} ${{ steps.release-version.outputs.last-release-version }}..HEAD
65+
- name: Release with release action
66+
id: release
67+
uses: greenbone/actions/release@v3
68+
with:
69+
github-user: ${{ secrets.GREENBONE_BOT }}
70+
github-user-mail: ${{ secrets.GREENBONE_BOT_MAIL }}
71+
github-user-token: ${{ secrets.GREENBONE_BOT_TOKEN }}
72+
gpg-key: ${{ secrets.GPG_KEY }}
73+
gpg-fingerprint: ${{ secrets.GPG_FINGERPRINT }}
74+
gpg-passphrase: ${{ secrets.GPG_PASSPHRASE }}
75+
release-version: ${{ steps.release-version.outputs.release-version }}
76+
changelog: /tmp/changelog.md
77+
ref: ${{ steps.release-type.outputs.release-ref }}
78+
versioning-scheme: "semver"

poetry.lock

Lines changed: 22 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

pyproject.toml

Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ pontos = ">=22.7.2"
4444
furo = ">=2022.6.21"
4545
lxml-stubs = "^0.5.1"
4646
types-paramiko = "^3.4.0.20240205"
47+
git-cliff = "^2.8.0"
4748

4849
[tool.black]
4950
line-length = 80
@@ -85,3 +86,91 @@ files = "gvm"
8586
ignore_missing_imports = true
8687
explicit_package_bases = true
8788
allow_redefinition = true
89+
90+
[tool.git-cliff.changelog]
91+
# template for the changelog header
92+
header = """
93+
# Changelog\n
94+
All notable changes to this project will be documented in this file.
95+
96+
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
97+
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).\n
98+
"""
99+
# template for the changelog body
100+
# https://keats.github.io/tera/docs/#introduction
101+
body = """
102+
{%- macro remote_url() -%}
103+
https://github.com/{{ remote.github.owner }}/{{ remote.github.repo }}
104+
{%- endmacro -%}
105+
106+
{% if version -%}
107+
## [{{ version | trim_start_matches(pat="v") }}] - {{ timestamp | date(format="%Y-%m-%d") }}
108+
{% else -%}
109+
## [Unreleased]
110+
{% endif -%}
111+
112+
{% for group, commits in commits | group_by(attribute="group") %}
113+
### {{ group | upper_first }}
114+
{% for commit in commits %}
115+
- {{ commit.message | split(pat="\n") | first | upper_first | trim }}\
116+
{% if commit.remote.username %} by [@{{ commit.remote.username }}](https://github.com/{{ commit.remote.username }}){%- endif -%}
117+
{% if commit.remote.pr_number %} in \
118+
[#{{ commit.remote.pr_number }}]({{ self::remote_url() }}/pull/{{ commit.remote.pr_number }}) \
119+
{% elif commit.id %} in \
120+
[{{ commit.id | truncate(length=7, end="") }}]({{ self::remote_url() }}/commit/{{ commit.id }})\
121+
{%- endif -%}
122+
{% endfor %}
123+
{% endfor -%}
124+
"""
125+
# template for the changelog footer
126+
footer = """
127+
{%- macro remote_url() -%}
128+
https://github.com/{{ remote.github.owner }}/{{ remote.github.repo }}
129+
{%- endmacro -%}
130+
131+
{% for release in releases %}
132+
{% if release.version -%}
133+
{% if release.previous.version -%}
134+
[{{ release.version | trim_start_matches(pat="v") }}]: \
135+
{{ self::remote_url() }}/compare/{{ release.previous.version }}..{{ release.version }}
136+
{% endif -%}
137+
{% else -%}
138+
[unreleased]: {{ self::remote_url() }}/compare/{{ release.previous.version }}..HEAD
139+
{% endif -%}
140+
{%- endfor -%}
141+
"""
142+
# remove the leading and trailing whitespace from the templates
143+
trim = true
144+
145+
[tool.git-cliff.git]
146+
# parse the commits based on https://www.conventionalcommits.org
147+
conventional_commits = true
148+
# filter out the commits that are not following the conventional commits format
149+
filter_unconventional = false
150+
# process each line of a commit as an individual commit
151+
split_commits = false
152+
# regex for preprocessing the commit messages
153+
commit_preprocessors = [
154+
# remove issue numbers from commits
155+
{ pattern = '\((\w+\s)?#([0-9]+)\)', replace = "" },
156+
]
157+
# regex for parsing and grouping commits
158+
commit_parsers = [
159+
{ message = "^[a|A]dd", group = "<!-- 1 -->:sparkles: Added" },
160+
{ message = "^[c|C]hange", group = "<!-- 2 -->:construction_worker: Changed" },
161+
{ message = "^[f|F]ix", group = "<!-- 3 -->:bug: Bug Fixes" },
162+
{ message = "^[r|R]emove", group = "<!-- 4 -->:fire: Removed" },
163+
{ message = "^[d|D]rop", group = "<!-- 4 -->:fire: Removed" },
164+
{ message = "^[d|D]oc", group = "<!-- 5 -->:books: Documentation" },
165+
{ message = "^[t|T]est", group = "<!-- 6 -->:white_check_mark: Testing" },
166+
{ message = "^[c|C]hore", group = "<!-- 7 -->:wrench: Miscellaneous" },
167+
{ message = "^[c|C]i", group = "<!-- 7 -->️:wrench: Miscellaneous" },
168+
{ message = "^[m|M]isc", group = "<!-- 7 -->:wrench: Miscellaneous" },
169+
{ message = "^[d|D]eps", group = "<!-- 8 -->:ship: Dependencies" },
170+
]
171+
# filter out the commits that are not matched by commit parsers
172+
filter_commits = true
173+
# sort the tags topologically
174+
topo_order = false
175+
# sort the commits inside sections by oldest/newest order
176+
sort_commits = "oldest"

0 commit comments

Comments
 (0)