Skip to content

Commit 29952a0

Browse files
committed
ci: refactor changelog parsing into reusable script
1 parent b8f630c commit 29952a0

2 files changed

Lines changed: 54 additions & 65 deletions

File tree

.github/scripts/parse_changelog.py

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
#!/usr/bin/env python3
2+
"""Parse CHANGELOG.md and extract the latest version and release notes."""
3+
4+
import json
5+
import re
6+
import sys
7+
8+
9+
def parse_changelog(filepath="CHANGELOG.md"):
10+
"""Extract the latest version and its content from CHANGELOG.md."""
11+
with open(filepath) as f:
12+
content = f.read()
13+
14+
# Match version headers like ## [0.3.1] - 2026-02-10
15+
version_pattern = r"^## \[([^\]]+)\] - (\d{4}-\d{2}-\d{2})"
16+
matches = list(re.finditer(version_pattern, content, re.MULTILINE))
17+
18+
if not matches:
19+
print("Error: No version found in CHANGELOG.md", file=sys.stderr)
20+
sys.exit(1)
21+
22+
# Get the first (latest) version
23+
first_match = matches[0]
24+
version = first_match.group(1)
25+
date = first_match.group(2)
26+
27+
# Extract content between first and second version headers
28+
start_pos = first_match.end()
29+
if len(matches) > 1:
30+
end_pos = matches[1].start()
31+
body = content[start_pos:end_pos].strip()
32+
else:
33+
# If only one version, get everything after it until the end or separator
34+
remaining = content[start_pos:]
35+
separator_match = re.search(r"^---$", remaining, re.MULTILINE)
36+
if separator_match:
37+
body = remaining[: separator_match.start()].strip()
38+
else:
39+
body = remaining.strip()
40+
41+
return {"version": version, "tag": f"v{version}", "date": date, "body": body}
42+
43+
44+
if __name__ == "__main__":
45+
result = parse_changelog()
46+
print(json.dumps(result))

.github/workflows/auto-release.yaml

Lines changed: 8 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,8 @@ on:
44
push:
55
branches:
66
- main
7-
paths:
8-
- 'CHANGELOG.md'
7+
# paths:
8+
# - 'CHANGELOG.md'
99

1010
jobs:
1111
create-release:
@@ -22,66 +22,10 @@ jobs:
2222
- name: Parse Changelog
2323
id: changelog
2424
run: |
25-
# Extract the latest version and its content from CHANGELOG.md
26-
python3 << 'EOF'
27-
import re
28-
import sys
29-
30-
with open('CHANGELOG.md', 'r') as f:
31-
content = f.read()
32-
33-
# Match version headers like ## [0.3.1] - 2026-02-10
34-
version_pattern = r'^## \[([^\]]+)\] - (\d{4}-\d{2}-\d{2})'
35-
matches = list(re.finditer(version_pattern, content, re.MULTILINE))
36-
37-
if not matches:
38-
print("No version found in CHANGELOG.md", file=sys.stderr)
39-
sys.exit(1)
40-
41-
# Get the first (latest) version
42-
first_match = matches[0]
43-
version = first_match.group(1)
44-
date = first_match.group(2)
45-
46-
# Extract content between first and second version headers
47-
start_pos = first_match.end()
48-
if len(matches) > 1:
49-
end_pos = matches[1].start()
50-
body = content[start_pos:end_pos].strip()
51-
else:
52-
# If only one version, get everything after it until the end or separator
53-
remaining = content[start_pos:]
54-
separator_match = re.search(r'^---$', remaining, re.MULTILINE)
55-
if separator_match:
56-
body = remaining[:separator_match.start()].strip()
57-
else:
58-
body = remaining.strip()
59-
60-
# Clean up the body - remove leading/trailing whitespace
61-
body = body.strip()
62-
63-
# Write outputs
64-
with open('version.txt', 'w') as f:
65-
f.write(version)
66-
with open('body.txt', 'w') as f:
67-
f.write(body)
68-
69-
print(f"Version: {version}")
70-
print(f"Date: {date}")
71-
print(f"Body length: {len(body)} characters")
72-
EOF
73-
74-
# Set outputs
75-
VERSION=$(cat version.txt)
76-
echo "version=$VERSION" >> $GITHUB_OUTPUT
77-
echo "tag=v$VERSION" >> $GITHUB_OUTPUT
78-
79-
# For multiline output, use delimiter
80-
{
81-
echo 'body<<EOF_CHANGELOG'
82-
cat body.txt
83-
echo EOF_CHANGELOG
84-
} >> $GITHUB_OUTPUT
25+
RESULT=$(python3 .github/scripts/parse_changelog.py)
26+
echo "version=$(echo "$RESULT" | jq -r '.version')" >> $GITHUB_OUTPUT
27+
echo "tag=$(echo "$RESULT" | jq -r '.tag')" >> $GITHUB_OUTPUT
28+
echo "body=$(echo "$RESULT" | jq -r '.body')" >> $GITHUB_OUTPUT
8529
8630
- name: Check if release exists
8731
id: check_release
@@ -90,7 +34,6 @@ jobs:
9034
run: |
9135
TAG="${{ steps.changelog.outputs.tag }}"
9236
93-
# Check if release exists
9437
if gh release view "$TAG" &>/dev/null; then
9538
echo "Release $TAG already exists"
9639
echo "exists=true" >> $GITHUB_OUTPUT
@@ -106,11 +49,11 @@ jobs:
10649
run: |
10750
TAG="${{ steps.changelog.outputs.tag }}"
10851
VERSION="${{ steps.changelog.outputs.version }}"
52+
BODY="${{ steps.changelog.outputs.body }}"
10953
110-
# Create release with changelog body
11154
gh release create "$TAG" \
11255
--title "Release $VERSION" \
113-
--notes "${{ steps.changelog.outputs.body }}" \
56+
--notes "$BODY" \
11457
--verify-tag
11558
11659
- name: Skip Release

0 commit comments

Comments
 (0)