Skip to content

Commit 383f0d6

Browse files
authored
chore(ci): add changelog.yml workflow (#13)
1 parent 0fa0e06 commit 383f0d6

File tree

3 files changed

+347
-23
lines changed

3 files changed

+347
-23
lines changed

.github/workflows/changelog.yml

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
name: update-changelog
2+
on:
3+
push:
4+
branches:
5+
- main
6+
permissions:
7+
contents: write
8+
jobs:
9+
changelog:
10+
name: Update CHANGELOG
11+
runs-on: ubuntu-latest
12+
timeout-minutes: 15
13+
if: |
14+
!startsWith(github.event.head_commit.message, '[Release]') &&
15+
!startsWith(github.event.head_commit.message, 'chore(changelog): update CHANGELOG.md') &&
16+
github.event.head_commit.author.name != 'github-actions[bot]'
17+
steps:
18+
- uses: actions/checkout@v6
19+
with:
20+
fetch-depth: 0
21+
- uses: jdx/mise-action@v3
22+
with:
23+
experimental: true
24+
- name: Generate CHANGELOG.md
25+
env:
26+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
27+
run: git cliff --config ./cliff.toml -o ./CHANGELOG.md
28+
- name: Check for CHANGELOG changes
29+
id: changelog-changes
30+
run: |
31+
if git diff --quiet CHANGELOG.md; then
32+
echo "No changes in CHANGELOG.md"
33+
echo "has-changes=false" >> $GITHUB_OUTPUT
34+
else
35+
echo "CHANGELOG.md has changes"
36+
echo "has-changes=true" >> $GITHUB_OUTPUT
37+
fi
38+
- name: Commit CHANGELOG
39+
uses: stefanzweifel/git-auto-commit-action@v7
40+
if: steps.changelog-changes.outputs.has-changes == 'true'
41+
with:
42+
commit_message: "chore(changelog): update CHANGELOG.md"
43+
commit_options: '--no-verify'
44+
file_pattern: CHANGELOG.md
45+
commit_user_name: github-actions[bot]
46+
commit_user_email: github-actions[bot]@users.noreply.github.com

CHANGELOG.md

Lines changed: 33 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,33 +1,43 @@
1-
# Change Log
1+
# Changelog
2+
23
All notable changes to this project will be documented in this file.
34

5+
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
6+
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7+
48
#### 1.x Releases
5-
- `1.1.x` Release Candidates - [1.1.0-rc.1](#110-rc1)
69
- `1.0.x` Releases - [1.0.0](#100)
710

8-
## [1.1.0-rc.2](https://github.com/space-code/network-layer/releases/tag/1.1.0-rc.2)
9-
Released on 2025-05-30.
10-
11-
#### Fixed
12-
- Fix adapting a request during retry.
13-
- Fixed in Pull Request [#2](https://github.com/space-code/network-layer/pull/7).
11+
---
12+
## [Unreleased]
13+
14+
### Miscellaneous Tasks
15+
- Update danger.yml
16+
- Contributed by [@ns-vasilev](https://github.com/ns-vasilev) in Pull Request [#12](https://github.com/space-code/network-layer/pull/12).
17+
18+
### Uncategorized Changes
19+
- Fix adapting a request during retry
20+
- Contributed by [@ns-vasilev](https://github.com/ns-vasilev) in Pull Request [#8](https://github.com/space-code/network-layer/pull/8).
21+
- Fix adapting a request during retry
22+
- Contributed by [@ns-vasilev](https://github.com/ns-vasilev) in Pull Request [#7](https://github.com/space-code/network-layer/pull/7).
23+
- Release `1.1.0-rc.1`
24+
- Contributed by [@ns-vasilev](https://github.com/ns-vasilev) in Pull Request [#5](https://github.com/space-code/network-layer/pull/5).
25+
- Remove `Package.resolved`
26+
- Contributed by [@ns-vasilev](https://github.com/ns-vasilev) in Pull Request [#6](https://github.com/space-code/network-layer/pull/6).
27+
- Update `CHANGELOG.md`
28+
- Contributed by [@ns-vasilev](https://github.com/ns-vasilev) in Pull Request [#4](https://github.com/space-code/network-layer/pull/4).
29+
- Bump the Swift version to 6.0
30+
- Contributed by [@ns-vasilev](https://github.com/ns-vasilev) in Pull Request [#3](https://github.com/space-code/network-layer/pull/3).
31+
- Update `IAuthenticator`
32+
- Contributed by [@ns-vasilev](https://github.com/ns-vasilev) in Pull Request [#2](https://github.com/space-code/network-layer/pull/2).
1433

15-
## [1.1.0-rc.1](https://github.com/space-code/network-layer/releases/tag/1.1.0-rc.1)
16-
Released on 2024-12-25.
34+
## [1.0.0](https://github.com/space-code/network-layer/releases/tag/1.0.0)
1735

18-
#### Added
19-
- Bump the Swift version to 6.0.
20-
- Added in Pull Request [#3](https://github.com/space-code/network-layer/pull/3).
36+
Released on 2023-12-04. All issues associated with this milestone can be found using this [filter](https://github.com/space-code/network-layer/milestones?state=closed&q=1.0.0).
2137

22-
#### Fixed
23-
- Fix the `inout` parameter in the `IAuthenticator` protocol
24-
- Fixed in Pull Request [#2](https://github.com/space-code/network-layer/pull/2).
25-
- Fix the package builiding.
26-
- Fixed in Pull Request [#6](https://github.com/space-code/network-layer/pull/6).
38+
### Uncategorized Changes
39+
- Implement `network-layer` package
40+
- Contributed by [@ns-vasilev](https://github.com/ns-vasilev) in Pull Request [#1](https://github.com/space-code/network-layer/pull/1).
2741

28-
## [1.0.0](https://github.com/space-code/network-layer/releases/tag/1.0.0)
29-
Released on 2023-12-04.
42+
[unreleased]: https://github.com/space-code/network-layer/compare/1.0.0..HEAD
3043

31-
#### Added
32-
- Initial release of `network-layer`.
33-
- Added by [Nikita Vasilev](https://github.com/nik3212).

cliff.toml

Lines changed: 268 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,268 @@
1+
# git-cliff ~ configuration file
2+
# https://git-cliff.org/docs/configuration
3+
4+
[remote.github]
5+
owner = "space-code"
6+
repo = "network-layer"
7+
# If you are using a token to fetch GitHub usernames, uncomment below:
8+
# token = "${GITHUB_TOKEN}"
9+
10+
[changelog]
11+
# GUARANTEE: Skip releases if they contain no commits (for tagged versions)
12+
skip_empty_releases = true
13+
# Maximum number of releases to display in the changelog
14+
# number_of_releases = 10
15+
16+
header = """
17+
# Changelog
18+
19+
All notable changes to this project will be documented in this file.
20+
21+
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
22+
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
23+
24+
{#- LOGIC: Generate table of contents - group versions by major version -#}
25+
{%- set_global major_versions = [] -%}
26+
{%- for release in releases -%}
27+
{%- if release.version -%}
28+
{%- set version_clean = release.version | trim_start_matches(pat="v") -%}
29+
{%- set major = version_clean | split(pat=".") | first -%}
30+
{%- if major not in major_versions -%}
31+
{%- set_global major_versions = major_versions | concat(with=major) -%}
32+
{%- endif -%}
33+
{%- endif -%}
34+
{%- endfor -%}
35+
{%- set sorted_majors = major_versions | sort | reverse -%}
36+
37+
{#- MAIN LOOP: Iterate over major versions -#}
38+
{%- for major in sorted_majors -%}
39+
{#- VISUAL: Add double newline before the header to separate from previous block -#}
40+
{{ "\n\n" }}#### {{ major }}.x Releases
41+
42+
{#- LOGIC: Filter releases for the current major version -#}
43+
{%- set_global major_releases = [] -%}
44+
{%- for release in releases -%}
45+
{%- if release.version -%}
46+
{%- set version_clean = release.version | trim_start_matches(pat="v") -%}
47+
{%- set rel_major = version_clean | split(pat=".") | first -%}
48+
{%- if rel_major == major -%}
49+
{%- set_global major_releases = major_releases | concat(with=version_clean) -%}
50+
{%- endif -%}
51+
{%- endif -%}
52+
{%- endfor -%}
53+
54+
{#- LOGIC: Separate into Stable, RC, and Beta -#}
55+
{%- set_global stable_versions = [] -%}
56+
{%- set_global rc_versions = [] -%}
57+
{%- set_global beta_versions = [] -%}
58+
{%- for version in major_releases -%}
59+
{%- if version is containing("-rc") -%}
60+
{%- set_global rc_versions = rc_versions | concat(with=version) -%}
61+
{%- elif version is containing("-beta") -%}
62+
{%- set_global beta_versions = beta_versions | concat(with=version) -%}
63+
{%- else -%}
64+
{%- set_global stable_versions = stable_versions | concat(with=version) -%}
65+
{%- endif -%}
66+
{%- endfor -%}
67+
68+
{#- LOGIC: Group stable versions by minor version -#}
69+
{%- set_global minor_versions = [] -%}
70+
{%- for version in stable_versions -%}
71+
{%- set parts = version | split(pat=".") -%}
72+
{%- set minor_key = parts | slice(end=2) | join(sep=".") -%}
73+
{%- if minor_key not in minor_versions -%}
74+
{%- set_global minor_versions = minor_versions | concat(with=minor_key) -%}
75+
{%- endif -%}
76+
{%- endfor -%}
77+
{%- set sorted_minors = minor_versions | sort | reverse -%}
78+
79+
{#- OUTPUT: Stable releases -#}
80+
{%- for minor_key in sorted_minors -%}
81+
{%- set_global minor_release_versions = [] -%}
82+
{%- for version in stable_versions -%}
83+
{%- set parts = version | split(pat=".") -%}
84+
{%- set ver_minor = parts | slice(end=2) | join(sep=".") -%}
85+
{%- if ver_minor == minor_key -%}
86+
{%- set_global minor_release_versions = minor_release_versions | concat(with=version) -%}
87+
{%- endif -%}
88+
{%- endfor -%}
89+
{%- set versions_list = minor_release_versions | sort | reverse -%}
90+
{{ "\n" }}- `{{ minor_key }}.x` Releases - {% for version in versions_list -%}
91+
[{{ version }}](#{{ version | replace(from=".", to="") | replace(from="-", to="") | lower }})
92+
{%- if not loop.last %} | {% endif -%}
93+
{%- endfor -%}
94+
{%- endfor -%}
95+
96+
{#- OUTPUT: RC versions -#}
97+
{%- if rc_versions | length > 0 -%}
98+
{%- set rc_versions_sorted = rc_versions | sort | reverse -%}
99+
{%- set rc_base = rc_versions_sorted | first | split(pat="-") | first -%}
100+
{{ "\n" }}- `{{ rc_base }}` Release Candidates - {% for version in rc_versions_sorted -%}
101+
[{{ version }}](#{{ version | replace(from=".", to="") | replace(from="-", to="") | lower }})
102+
{%- if not loop.last %} | {% endif -%}
103+
{%- endfor -%}
104+
{%- endif -%}
105+
106+
{#- OUTPUT: Beta versions -#}
107+
{%- if beta_versions | length > 0 -%}
108+
{%- set beta_versions_sorted = beta_versions | sort | reverse -%}
109+
{%- set beta_base = beta_versions_sorted | first | split(pat="-") | first -%}
110+
{{ "\n" }}- `{{ beta_base }}` Betas - {% for version in beta_versions_sorted -%}
111+
[{{ version }}](#{{ version | replace(from=".", to="") | replace(from="-", to="") | lower }})
112+
{%- if not loop.last %} | {% endif -%}
113+
{%- endfor -%}
114+
{%- endif -%}
115+
{%- endfor -%}{{ "\n" }}
116+
---
117+
"""
118+
119+
body = """
120+
{%- macro remote_url() -%}
121+
https://github.com/{{ remote.github.owner }}/{{ remote.github.repo }}
122+
{%- endmacro -%}
123+
124+
{%- set_global renderable_commits = [] -%}
125+
{%- for commit in commits -%}
126+
{# Filter commits that have a Conventional Commit type or a PR number (your rendering condition) #}
127+
{%- if commit.conventional or commit.remote.pr_number -%}
128+
{%- set_global renderable_commits = renderable_commits | concat(with=commit) -%}
129+
{%- endif -%}
130+
{%- endfor -%}
131+
132+
{%- if renderable_commits | length > 0 -%}
133+
{#- LOGIC: Version Header with Link -#}
134+
{%- if version -%}
135+
{{ "\n" }}
136+
## [{{ version | trim_start_matches(pat="v") }}]({{ self::remote_url() }}/releases/tag/{{ version | trim_start_matches(pat="v") }})
137+
{{ "\n" }}Released on {{ timestamp | date(format="%Y-%m-%d") }}. All issues associated with this milestone can be found using this [filter]({{ self::remote_url() }}/milestones?state=closed&q={{ version }}).
138+
{%- else -%}
139+
## [Unreleased]
140+
{%- endif -%}
141+
142+
{#- LOGIC: Loop through commit groups -#}
143+
{%- for group, commits_in_group in renderable_commits | group_by(attribute="group") -%}
144+
{%- if group == "Uncategorized Changes" and commits_in_group | length == 0 -%}
145+
{%- continue -%}
146+
{%- endif -%}
147+
148+
{# We also check that it is not the system group 'Other', which might be empty #}
149+
{%- if group == "Other" and commits_in_group | length == 0 -%}
150+
{%- continue -%}
151+
{%- endif -%}
152+
153+
{%- set action_verb = "Contributed by" -%}
154+
{%- if group == "Features" -%}
155+
{%- set action_verb = "Implemented by" -%}
156+
{%- elif group == "Bug Fixes" -%}
157+
{%- set action_verb = "Fixed by" -%}
158+
{%- elif group == "Performance" -%}
159+
{%- set action_verb = "Optimized by" -%}
160+
{%- elif group == "Documentation" -%}
161+
{%- set action_verb = "Documented by" -%}
162+
{%- endif -%}
163+
164+
{{ "\n" }}{{ "\n" }}### {{ group | upper_first }}
165+
166+
{#- THE LOOP NOW USES FILTERED COMMITS AND DOESN'T NEED AN INNER IF -#}
167+
{%- for commit in commits_in_group -%}
168+
{%- set message = commit.message | split(pat="\n") | first | upper_first | trim -%}
169+
170+
{#- VISUAL: Commit message line -#}
171+
{{ "\n" }}- {{ message }}
172+
173+
{%- if commit.remote.username and commit.remote.pr_number -%}
174+
{#- VISUAL: Dynamic verb line -#}
175+
{{ "\n" }} - {{ action_verb }} [@{{ commit.remote.username }}](https://github.com/{{ commit.remote.username }}) in Pull Request [#{{ commit.remote.pr_number }}]({{ self::remote_url() }}/pull/{{ commit.remote.pr_number }}).
176+
{%- endif -%}
177+
{%- endfor -%}
178+
{%- endfor -%}
179+
180+
{#- LOGIC: New Contributors Section -#}
181+
{%- set new_contributors = github.contributors | filter(attribute="is_first_time", value=true) -%}
182+
183+
{%- if new_contributors | length > 0 -%}
184+
{%- set_global real_new_contributors = [] -%}
185+
{%- for contributor in new_contributors -%}
186+
{#- IMPORTANT: Filtering out your login "ns-vasilev" and Renovate -#}
187+
{%- set username_lower = contributor.username | default(value="") | lower | trim -%}
188+
{%- if username_lower != "ns-vasilev" and username_lower != "renovate" -%}
189+
{%- set_global real_new_contributors = real_new_contributors | concat(with=contributor) -%}
190+
{%- endif -%}
191+
{%- endfor -%}
192+
193+
{%- if real_new_contributors | length > 0 -%}
194+
{{ "\n" }}{{ "\n" }}### New Contributors
195+
{%- for contributor in real_new_contributors -%}
196+
{{ "\n" }}* @{{ contributor.username }} made their first contribution in{{ " " }}
197+
{%- if contributor.pr_number -%}
198+
[#{{ contributor.pr_number }}]({{ self::remote_url() }}/pull/{{ contributor.pr_number }})
199+
{%- endif -%}
200+
{%- endfor -%}
201+
{%- endif -%}
202+
{%- endif -%}
203+
{%- endif -%}
204+
"""
205+
206+
footer = """
207+
{%- macro remote_url() -%}
208+
https://github.com/{{ remote.github.owner }}/{{ remote.github.repo }}
209+
{%- endmacro -%}
210+
211+
{{ "\n" }}
212+
{% for release in releases -%}
213+
{% if release.version -%}
214+
{% if release.previous.version -%}
215+
[{{ release.version | trim_start_matches(pat="v") }}]: \
216+
{{ self::remote_url() }}/compare/{{ release.previous.version }}..{{ release.version }}
217+
{% endif -%}
218+
{% else -%}
219+
[unreleased]: {{ self::remote_url() }}/compare/{{ release.previous.version }}..HEAD
220+
{% endif -%}
221+
{% endfor %}
222+
"""
223+
trim = true
224+
postprocessors = []
225+
226+
[git]
227+
conventional_commits = true
228+
# SET TO false to include old (unconventional) commits
229+
filter_unconventional = false
230+
split_commits = false
231+
commit_preprocessors = [
232+
{ pattern = '\((\w+\s)?#([0-9]+)\)', replace = "" },
233+
]
234+
commit_parsers = [
235+
{ message = "^chore\\(changelog\\)", skip = true },
236+
{ message = "^chore.*changelog", skip = true },
237+
{ message = "^docs: update CHANGELOG\\.md \\[skip ci\\]$", skip = true },
238+
{ message = "^feat", group = "Features" },
239+
{ message = "^fix", group = "Bug Fixes" },
240+
{ message = "^doc", group = "Documentation" },
241+
{ message = "^perf", group = "Performance" },
242+
{ message = "^refactor", group = "Refactor" },
243+
{ message = "^style", group = "Styling" },
244+
{ message = "^test", group = "Testing" },
245+
{ message = "^chore\\(spm.*\\)", skip = false },
246+
{ message = "^chore\\(deps.*\\)", skip = true },
247+
{ message = "^chore\\(pr\\)", skip = true },
248+
{ message = "^chore\\(pull\\)", skip = true },
249+
{ message = "^chore\\(release\\): prepare for", skip = true },
250+
{ message = "^chore|^ci", group = "Miscellaneous Tasks" },
251+
{ body = ".*security", group = "Security" },
252+
# CATCH-ALL PARSER for old (unconventional) commits
253+
{ message = ".*", group = "Uncategorized Changes" },
254+
]
255+
256+
# SET TO false to avoid filtering out Uncategorized Changes
257+
filter_commits = false
258+
protect_breaking_commits = false
259+
tag_pattern = "^[0-9].*"
260+
skip_tags = "beta|alpha|cli-.*"
261+
ignore_tags = "rc|web-.*"
262+
topo_order = false
263+
sort_commits = "newest"
264+
265+
[bump]
266+
breaking_always_bump_major = true
267+
features_always_bump_minor = true
268+
initial_tag = "0.1.0"

0 commit comments

Comments
 (0)