Skip to content

Commit 7715bc0

Browse files
Copilotelenafuengar
andcommitted
Add automated release notes generation workflow
Co-authored-by: elenafuengar <[email protected]>
1 parent 0e495ef commit 7715bc0

File tree

1 file changed

+199
-0
lines changed

1 file changed

+199
-0
lines changed
Lines changed: 199 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,199 @@
1+
name: Update Release Notes
2+
3+
on:
4+
push:
5+
branches:
6+
- main
7+
pull_request:
8+
branches:
9+
- main
10+
types: [opened, synchronize, reopened]
11+
12+
jobs:
13+
update-release-notes:
14+
runs-on: ubuntu-latest
15+
permissions:
16+
contents: write
17+
pull-requests: write
18+
19+
steps:
20+
- name: Checkout repository
21+
uses: actions/checkout@v4
22+
with:
23+
fetch-depth: 0 # Fetch all history for proper changelog generation
24+
ref: ${{ github.head_ref || github.ref_name }}
25+
26+
- name: Set up Python
27+
uses: actions/setup-python@v4
28+
with:
29+
python-version: '3.11'
30+
31+
- name: Generate release notes
32+
run: |
33+
# Get the version from setup.py
34+
VERSION=$(python setup.py --version 2>/dev/null || echo "dev")
35+
36+
# Determine the commit range
37+
if [ "${{ github.event_name }}" = "pull_request" ]; then
38+
BASE_REF="${{ github.event.pull_request.base.sha }}"
39+
HEAD_REF="${{ github.event.pull_request.head.sha }}"
40+
COMMIT_RANGE="${BASE_REF}..${HEAD_REF}"
41+
else
42+
# For push events, use the last 20 commits
43+
COMMIT_RANGE="HEAD~20..HEAD"
44+
fi
45+
46+
# Create a temporary file for the new release notes
47+
cat > /tmp/new_release_section.md << 'EOF'
48+
# v${VERSION}
49+
50+
This release includes updates from recent commits.
51+
52+
---
53+
54+
## 🚀 New Features
55+
56+
EOF
57+
58+
# Process commits and categorize them
59+
echo "Processing commits in range: ${COMMIT_RANGE}"
60+
61+
# Extract feature commits
62+
git log ${COMMIT_RANGE} --date=short --pretty=format:"* %ad %s (%aN)" --grep="^feature:" --grep="^feat:" -i > /tmp/features.txt || true
63+
if [ -s /tmp/features.txt ]; then
64+
cat /tmp/features.txt >> /tmp/new_release_section.md
65+
else
66+
echo "* No new features in this update" >> /tmp/new_release_section.md
67+
fi
68+
69+
echo "" >> /tmp/new_release_section.md
70+
echo "---" >> /tmp/new_release_section.md
71+
echo "" >> /tmp/new_release_section.md
72+
echo "## 💗 Other Tag Highlights" >> /tmp/new_release_section.md
73+
echo "" >> /tmp/new_release_section.md
74+
echo "* 🔁 **Tests**" >> /tmp/new_release_section.md
75+
76+
# Extract test commits
77+
git log ${COMMIT_RANGE} --date=short --pretty=format:" * %ad %s (%aN)" --grep="^test:" -i > /tmp/tests.txt || true
78+
if [ -s /tmp/tests.txt ]; then
79+
cat /tmp/tests.txt >> /tmp/new_release_section.md
80+
else
81+
echo " * No test updates" >> /tmp/new_release_section.md
82+
fi
83+
84+
echo "" >> /tmp/new_release_section.md
85+
echo "* 📚 **Documentation**" >> /tmp/new_release_section.md
86+
87+
# Extract doc commits
88+
git log ${COMMIT_RANGE} --date=short --pretty=format:" * %ad %s (%aN)" --grep="^docs:" -i > /tmp/docs.txt || true
89+
if [ -s /tmp/docs.txt ]; then
90+
cat /tmp/docs.txt >> /tmp/new_release_section.md
91+
else
92+
echo " * No documentation updates" >> /tmp/new_release_section.md
93+
fi
94+
95+
echo "" >> /tmp/new_release_section.md
96+
echo "---" >> /tmp/new_release_section.md
97+
echo "" >> /tmp/new_release_section.md
98+
echo "## 🐛 **Bugfixes**" >> /tmp/new_release_section.md
99+
echo "" >> /tmp/new_release_section.md
100+
101+
# Extract bugfix commits
102+
git log ${COMMIT_RANGE} --date=short --pretty=format:"* %ad %s (%aN)" --grep="^fix:" --grep="^bugfix:" -i > /tmp/fixes.txt || true
103+
if [ -s /tmp/fixes.txt ]; then
104+
cat /tmp/fixes.txt >> /tmp/new_release_section.md
105+
else
106+
echo "* No bugfixes in this update" >> /tmp/new_release_section.md
107+
fi
108+
109+
echo "" >> /tmp/new_release_section.md
110+
echo "---" >> /tmp/new_release_section.md
111+
echo "" >> /tmp/new_release_section.md
112+
echo "## 📝 **Full changelog**" >> /tmp/new_release_section.md
113+
echo "" >> /tmp/new_release_section.md
114+
115+
# Count commits by category
116+
TOTAL_COMMITS=$(git log ${COMMIT_RANGE} --oneline | wc -l)
117+
FEAT_COUNT=$(git log ${COMMIT_RANGE} --oneline --grep="^feature:" --grep="^feat:" -i | wc -l || echo 0)
118+
TEST_COUNT=$(git log ${COMMIT_RANGE} --oneline --grep="^test:" -i | wc -l || echo 0)
119+
DOCS_COUNT=$(git log ${COMMIT_RANGE} --oneline --grep="^docs:" -i | wc -l || echo 0)
120+
FIX_COUNT=$(git log ${COMMIT_RANGE} --oneline --grep="^fix:" --grep="^bugfix:" -i | wc -l || echo 0)
121+
STYLE_COUNT=$(git log ${COMMIT_RANGE} --oneline --grep="^style:" -i | wc -l || echo 0)
122+
123+
if [ ${TOTAL_COMMITS} -gt 0 ]; then
124+
FEAT_PCT=$(awk "BEGIN {printf \"%.1f\", (${FEAT_COUNT}/${TOTAL_COMMITS})*100}")
125+
TEST_PCT=$(awk "BEGIN {printf \"%.1f\", (${TEST_COUNT}/${TOTAL_COMMITS})*100}")
126+
DOCS_PCT=$(awk "BEGIN {printf \"%.1f\", (${DOCS_COUNT}/${TOTAL_COMMITS})*100}")
127+
FIX_PCT=$(awk "BEGIN {printf \"%.1f\", (${FIX_COUNT}/${TOTAL_COMMITS})*100}")
128+
STYLE_PCT=$(awk "BEGIN {printf \"%.1f\", (${STYLE_COUNT}/${TOTAL_COMMITS})*100}")
129+
OTHER_COUNT=$((TOTAL_COMMITS - FEAT_COUNT - TEST_COUNT - DOCS_COUNT - FIX_COUNT - STYLE_COUNT))
130+
OTHER_PCT=$(awk "BEGIN {printf \"%.1f\", (${OTHER_COUNT}/${TOTAL_COMMITS})*100}")
131+
else
132+
FEAT_PCT=0
133+
TEST_PCT=0
134+
DOCS_PCT=0
135+
FIX_PCT=0
136+
STYLE_PCT=0
137+
OTHER_PCT=0
138+
fi
139+
140+
cat >> /tmp/new_release_section.md << EOF
141+
| **${TOTAL_COMMITS} commits** | 📚 Docs | 🧪 Tests | 🐛 Fixes | 🎨 Style | ✨ Features | Other |
142+
|-----------------|---------|----------|-----------|------------|--------------|-------|
143+
| % of Commits | ${DOCS_PCT}% | ${TEST_PCT}% | ${FIX_PCT}% | ${STYLE_PCT}% | ${FEAT_PCT}% | ${OTHER_PCT}% |
144+
145+
EOF
146+
147+
echo "" >> /tmp/new_release_section.md
148+
echo '`git log --date=short --pretty=format:"* %ad %s (%aN)"`' >> /tmp/new_release_section.md
149+
echo "" >> /tmp/new_release_section.md
150+
echo "" >> /tmp/new_release_section.md
151+
152+
# Add all commits
153+
git log ${COMMIT_RANGE} --date=short --pretty=format:"* %ad %s (%aN)" >> /tmp/new_release_section.md
154+
155+
echo "" >> /tmp/new_release_section.md
156+
echo "" >> /tmp/new_release_section.md
157+
158+
# Prepend the new section to the existing release.md
159+
if [ -f release.md ]; then
160+
cat /tmp/new_release_section.md > /tmp/updated_release.md
161+
echo "---" >> /tmp/updated_release.md
162+
echo "" >> /tmp/updated_release.md
163+
cat release.md >> /tmp/updated_release.md
164+
mv /tmp/updated_release.md release.md
165+
else
166+
mv /tmp/new_release_section.md release.md
167+
fi
168+
169+
# Replace ${VERSION} placeholder
170+
sed -i "s/\${VERSION}/${VERSION}/g" release.md
171+
172+
- name: Check for changes
173+
id: check_changes
174+
run: |
175+
if git diff --quiet release.md; then
176+
echo "has_changes=false" >> $GITHUB_OUTPUT
177+
echo "No changes to release.md"
178+
else
179+
echo "has_changes=true" >> $GITHUB_OUTPUT
180+
echo "Changes detected in release.md"
181+
fi
182+
183+
- name: Commit and push changes
184+
if: steps.check_changes.outputs.has_changes == 'true' && github.event_name == 'push'
185+
run: |
186+
git config --local user.email "github-actions[bot]@users.noreply.github.com"
187+
git config --local user.name "github-actions[bot]"
188+
git add release.md
189+
git commit -m "chore: auto-update release.md [skip ci]"
190+
git push
191+
192+
- name: Commit changes to PR
193+
if: steps.check_changes.outputs.has_changes == 'true' && github.event_name == 'pull_request'
194+
run: |
195+
git config --local user.email "github-actions[bot]@users.noreply.github.com"
196+
git config --local user.name "github-actions[bot]"
197+
git add release.md
198+
git commit -m "chore: auto-update release.md for PR #${{ github.event.pull_request.number }}"
199+
git push origin HEAD:${{ github.head_ref }}

0 commit comments

Comments
 (0)