1# Documentation: https://git-cliff.org/docs/configuration
2[changelog]
3header = """# Changelog
4
5All notable changes to the project will be documented in this file. It is
6non-exhaustive by design, and only contains public-facing application and API
7changes. Internal, developer-centric changes can be seen by looking at the
8commit log.
9"""
10body = """
11{% if version %}
12 {% set git_log_ref = version -%}
13 {% set v = version | trim_start_matches(pat="v") -%}
14 {% set ts = timestamp | date(format="%Y-%m-%d") -%}
15 ## {{ v ~ " (" ~ ts ~ ")" }}
16 {% if message %}\n{{ message | trim_start_matches(pat="v") }}\n{% endif -%}
17{%- else -%}
18 {% set git_log_ref = "origin/HEAD" %}
19 ## Unreleased
20
21 This section documents the commits which are not yet associated with a
22 released version.
23{% endif %}
24To view the full set of changes, including internal developer-centric changes,
25run the following command:
26
27```
28git log --oneline {%- raw %} {% endraw -%}
29 {% if previous.version %}{{ previous.version }}..{% endif -%}
30 {{ git_log_ref }}
31```
32{% for group, commits in commits
33| filter(attribute="merge_commit",value=false)
34| group_by(attribute="group") %}
35 ### {{ group | striptags | trim | upper_first }}
36 {% for commit in commits
37 | filter(attribute="breaking",value=true)
38 | filter(attribute="scope")
39 | sort(attribute="scope") %}
40 - **BREAKING CHANGE**: **{{ commit.scope }}**:{% raw %} {% endraw -%}
41 {{ commit.message | trim }}{% raw %} {% endraw -%}
42 {%- if commit.remote.username and commit.remote.pr_number -%}
43 by @{{ commit.remote.username }} in #{{ commit.remote.pr_number }}
44 {%- else -%}
45 ({{ commit.id | truncate(length=8,end="") }})
46 {%- endif -%}
47 {%- if commit.breaking_description != commit.message %}
48 {% raw %} - {% endraw -%}
49 {{ commit.breaking_description | trim | indent(prefix=" ",blank=true) }}
50 {%- endif -%}
51 {% endfor %}
52 {%- for commit in commits | filter(attribute="breaking",value=true) -%}
53 {% if not commit.scope %}
54 - **BREAKING CHANGE**: {{ commit.message | trim }}{% raw %} {% endraw -%}
55 {%- if commit.remote.username and commit.remote.pr_number -%}
56 by @{{ commit.remote.username }} in #{{ commit.remote.pr_number }}
57 {%- else -%}
58 ({{ commit.id | truncate(length=8,end="") }})
59 {%- endif -%}
60 {%- if commit.breaking_description != commit.message %}
61 {% raw %} - {% endraw -%}
62 {{ commit.breaking_description | trim | indent(prefix=" ",blank=true) }}
63 {%- endif -%}
64 {%- endif -%}
65 {% endfor %}
66 {%- for commit in commits
67 | filter(attribute="scope")
68 | sort(attribute="scope") -%}
69 {% if not commit.breaking %}
70 - **{{commit.scope}}**:{% raw %} {% endraw -%}
71 {{ commit.message | trim }}{% raw %} {% endraw -%}
72 {%- if commit.remote.username and commit.remote.pr_number -%}
73 by @{{ commit.remote.username }} in #{{ commit.remote.pr_number }}
74 {%- else -%}
75 ({{ commit.id | truncate(length=8,end="") }})
76 {%- endif -%}
77 {%- endif -%}
78 {%- endfor -%}
79 {%- for commit in commits -%}
80 {% if not commit.scope and not commit.breaking %}
81 - {{ commit.message | trim }}{% raw %} {% endraw -%}
82 {%- if commit.remote.username and commit.remote.pr_number -%}
83 by @{{ commit.remote.username }} in #{{ commit.remote.pr_number }}
84 {%- else -%}
85 ({{ commit.id | truncate(length=8,end="") }})
86 {%- endif -%}
87 {%- endif -%}
88 {% endfor %}
89{% endfor -%}
90"""
91trim = true
92
93[bump]
94features_always_bump_minor = true
95breaking_always_bump_major = false # TODO: set this to true for 1.0.0
96
97[git]
98conventional_commits = true
99filter_unconventional = true
100protect_breaking_commits = true
101sort_commits = "oldest"
102topo_order = true
103
104commit_preprocessors = [
105 # map various older scopes to new scopes
106 # TODO: remove after init (because we will enforce an append-only workflow)
107 { pattern = '^([^\(]+)\(commands\):', replace = '$1 (cli):' },
108 { pattern = '^[^\(]+\(ci\)', replace = 'ci:' },
109 { pattern = '^[^\(]+\(TestCache\)', replace = 'test:' },
110 { pattern = '^doc: (.+ \(#1395\))', replace = 'docs(dev-infra): $1' },
111 { pattern = '^fix: (.+ \(#1403\))', replace = 'fix(completion): $1' },
112 { pattern = '^docs: (correct mispelled words)', replace = 'fix(dev-infra): $1' },
113 { pattern = '^(.+) \[fix\]$', replace = 'docs: $1' },
114 { pattern = '^fix ', replace = 'fix: ' },
115
116 # remove errata from old commit messages
117 # TODO: remove after init (because we will enforce an append-only workflow)
118 { pattern = '^([^\(]+)\((?:#?\d+|opencollective|git-bug-863)\)', replace = '$1' },
119 { pattern = ', fix https://.+/issues/653', replace = '' },
120
121 # remove quotes from reversions
122 # we do this to clean up the changelog output, since the raw message would
123 # otherwise be surrounded in quotes
124 { pattern = '^[Rr]evert: "(.+)"', replace = 'revert: $1' },
125
126 # convert quotes in subjects to graves
127 # TODO: remove after init (because we will enforce an append-only workflow)
128 { pattern = '"', replace = '`' },
129
130 # escape backslashes
131 # we do this because mdformat will remove isolated backslashes, and there is a
132 # historical commit that contains one
133 # TODO: remove after init (because we will enforce an append-only workflow)
134 { pattern = '\\', replace = '\\' },
135
136 # remove PR references from commit messages, to remove a hard dependency on
137 # github. by default, we show the commit hash (although github usernames and
138 # PR references are added in dynamically during release, for the changes
139 # shown on the release page)
140 { pattern = '\s+\(\#[0-9]+\)', replace = '' },
141]
142
143# these matches are applied in order, so be conscious of any changes you make
144commit_parsers = [
145 # skip commits generated by bots
146 { message = '^[^(]+\(changelog\)', skip = true },
147 { message = '^build\(deps(-dev)?\)', skip = true },
148 { message = '^deps?', skip = true },
149
150 # skip internal changes (non-consumer-facing changes)
151 # note that breaking changes will still be shown
152 { message = '^(?:revert: )?(?:ci|build|test|refactor)', skip = true },
153 { message = '^(?:revert: )?.+\(dev-infra\)', skip = true },
154
155 # assign group based on type
156 { message = '^docs?', group = 'Documentation' },
157 { message = '^feat', group = 'Features' },
158 { message = '^fix', group = 'Bug fixes' },
159 { message = '^perf', group = 'Performance' },
160 { message = '^revert', group = 'Reversions' },
161
162 # catch all other commits
163 { message = '^.+', group = 'Other changes' },
164]