Skip to content

Commit c55fcc0

Browse files
committed
ci(common): force scoping commit messages with components
Add simple changelog generator and mdns tag formatter
1 parent c492d87 commit c55fcc0

File tree

3 files changed

+116
-0
lines changed

3 files changed

+116
-0
lines changed

.pre-commit-config.yaml

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ repos:
1616
rev: 5.0.4
1717
hooks:
1818
- id: flake8
19+
args: ['--config=.flake8', '--tee', '--benchmark']
1920
- repo: https://github.com/pre-commit/mirrors-mypy
2021
rev: v0.981
2122
hooks:
@@ -32,6 +33,7 @@ repos:
3233
rev: "v0.32.0"
3334
hooks:
3435
- id: yapf
36+
args: ['style={based_on_style: google, column_limit: 160, indent_width: 4}']
3537
- repo: https://github.com/pre-commit/mirrors-isort
3638
rev: v5.10.1
3739
hooks:
@@ -56,3 +58,11 @@ repos:
5658
- id: commitizen
5759
- id: commitizen-branch
5860
stages: [push]
61+
- repo: local
62+
hooks:
63+
- id: commit message scopes
64+
name: "commit message must be scoped with: mdns, modem, websocket, asio, mqtt_cxx, common"
65+
entry: '\A(?!(feat|fix|ci|bump|test|docs)\((mdns|modem|common|websocket|asio|mqtt_cxx)\)\:)'
66+
language: pygrep
67+
args: [--multiline]
68+
stages: [commit-msg]

ci/changelog.py

Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
# SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD
2+
# SPDX-License-Identifier: Apache-2.0
3+
import argparse
4+
import os
5+
import re
6+
7+
import sh
8+
9+
10+
def main():
11+
parser = argparse.ArgumentParser(
12+
description='Generates a change log from cz commits')
13+
parser.add_argument('component')
14+
args = parser.parse_args()
15+
16+
old_ref = os.environ.get('CZ_PRE_CURRENT_TAG_VERSION')
17+
new_tag = os.environ.get('CZ_PRE_NEW_TAG_VERSION')
18+
new_ref = os.environ.get('CZ_PRE_NEW_VERSION')
19+
component = args.component
20+
21+
root_path = os.path.abspath(os.path.join(os.path.dirname(__file__), '..'))
22+
23+
git = sh.git.bake(_cwd=root_path)
24+
25+
keys = ['breaking', 'major', 'feat', 'fix', 'update']
26+
items = {key: [] for key in keys}
27+
sections = {
28+
'feat': 'Features',
29+
'fix': 'Bug Fixes',
30+
'update': 'Updated',
31+
'breaking': 'Breaking changes',
32+
'major': 'Major changes'
33+
}
34+
brief_log = git.log('--oneline', '{}..HEAD'.format(old_ref), '--', 'components/' + component, _tty_out=False)
35+
for oneline in brief_log.splitlines():
36+
[commit, brief_msg] = oneline.split(' ', 1)
37+
if 'Merge' in str(brief_msg) or brief_msg.startswith('bump('): # skip Merge commits and bumps
38+
continue
39+
find_title = re.findall(r'^(fix|feat|esp_modem|esp-modem|mdns)(\([^\)]+\))?:\s*(.+)$', str(brief_msg))
40+
item_type = '' # default prefix
41+
item_message = brief_msg # default body
42+
if find_title is not None and len(find_title) > 0: # Use scopes & types
43+
item_type = find_title[0][0] # prefix (fix/feat/ci)
44+
item_message = find_title[0][-1] # title body
45+
46+
# Add details in parentheses (commit-id and references from the FOOTER section)
47+
details = '[{}](https://github.com/espressif/esp-protocols/commit/{})'.format(commit, commit)
48+
msg_details = git.show('-s', commit, _tty_out=False)
49+
# check references
50+
if any(str(msg_details) in s for s in ['esp-protocols/issues', 'BREAKING CHANGE', 'MAJOR CHANGE']):
51+
# Closes <issue>
52+
closes = re.findall(r'Closes ([^\d]+/(\d+))', str(msg_details), re.MULTILINE)
53+
if closes and closes[0] is not None:
54+
details += ', [#{}]({})'.format(closes[0][1], closes[0][0])
55+
# Breaking changes
56+
find_breaking = re.findall(r'BREAKING CHANGE:\s*([^\n]*)', str(msg_details), re.MULTILINE)
57+
if find_breaking is not None and len(find_breaking) > 0:
58+
if find_breaking[0] != '':
59+
items['breaking'].append('{} ([{}](https://github.com/espressif/esp-protocols/commit/{}))'.format(find_breaking[0], item_message, commit))
60+
else:
61+
items['breaking'].append('{} ({})'.format(item_message, details))
62+
details += ', !BREAKING'
63+
# Major changes
64+
find_major = re.findall(r'MAJOR CHANGE:\s*([^\n]*)',
65+
str(msg_details), re.MULTILINE)
66+
if find_major is not None and len(
67+
find_major) > 0 and find_major[0] != '':
68+
items['major'].append('{} ([{}](https://github.com/espressif/esp-protocols/commit/{}))'.format(find_major[0], item_message, commit))
69+
if item_type in ['fix', 'feat']:
70+
items[item_type].append('{} ({})'.format(item_message, details))
71+
else:
72+
items['update'].append('{} ({})'.format(item_message, details))
73+
# Generate changelog
74+
changelog = '## [{}](https://github.com/espressif/esp-protocols/commits/{})\n'.format(
75+
new_ref, new_tag)
76+
for section, item in items.items():
77+
if len(item) > 0:
78+
changelog += '\n### {}\n\n'.format(sections[section])
79+
for it in item:
80+
changelog += '- {}\n'.format(it)
81+
changelog += '\n'
82+
filename = os.path.join(root_path, 'components', component, 'CHANGELOG.md')
83+
# insert the actual changelog to the beginning of the file, just after the title (2nd line)
84+
with open(filename, 'r') as orig_changelog:
85+
changelog_title = orig_changelog.readline(
86+
) # expect # Changelog title on the first line
87+
changelog_nl = orig_changelog.readline()
88+
orig_items = orig_changelog.read()
89+
with open(filename, 'w') as updated_changelog:
90+
updated_changelog.write(changelog_title)
91+
updated_changelog.write(changelog_nl)
92+
updated_changelog.write(changelog)
93+
updated_changelog.write(orig_items)
94+
git.add(filename)
95+
96+
97+
if __name__ == '__main__':
98+
main()

components/mdns/.cz.yaml

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
---
2+
commitizen:
3+
bump_message: 'bump(mdns): $current_version -> $new_version'
4+
pre_bump_hooks: python ../../ci/changelog.py mdns
5+
tag_format: mdns-v$version
6+
version: 1.0.8
7+
version_files:
8+
- idf_component.yml

0 commit comments

Comments
 (0)