Skip to content

Commit 5aaba5f

Browse files
committed
fix(auto-release-notes.py): fix duplicate blank-line
Signed-off-by: samzong <[email protected]>
1 parent 716e633 commit 5aaba5f

File tree

2 files changed

+100
-123
lines changed

2 files changed

+100
-123
lines changed

.github/workflows/auto-release-notes.yaml

Lines changed: 34 additions & 85 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ name: Scheduled Update of Release Notes
33
on:
44
workflow_dispatch:
55
schedule:
6-
- cron: "0 2 * * 3" # 每周三UTC时间2点运行一次,即北京时间10点
6+
- cron: "0 2 * * 3" # Runs every Wednesday at 2:00 UTC (10:00 Beijing Time)
77

88
permissions:
99
contents: write
@@ -12,125 +12,74 @@ permissions:
1212
jobs:
1313
run-script:
1414
runs-on: ubuntu-latest
15+
timeout-minutes: 15
16+
env:
17+
RELEASE_NOTES_FILE: ${{ secrets.RELEASE_NOTES_FILE }}
1518

1619
steps:
1720
- name: Checkout repo
18-
uses: actions/checkout@v3
21+
uses: actions/checkout@v4
1922
with:
2023
fetch-depth: 0
24+
ref: main
2125

2226
- name: Setup Python
23-
uses: actions/setup-python@v4
27+
uses: actions/setup-python@v5
2428
with:
25-
python-version: 3.9
29+
python-version: "3.9"
30+
cache: pip
2631

2732
- name: Install dependencies
28-
run: pip install requests pandas pyyaml jq
33+
run: pip install requests pandas pyyaml jq mdformat
2934

3035
- name: Prepare branch
3136
id: prepare_branch
3237
run: |
33-
DATE=$(date +%Y%m%d)
34-
BRANCH="update-rel-notes-$DATE"
35-
git fetch origin "$BRANCH" || true
36-
37-
if git show-ref --verify --quiet "refs/remotes/origin/$BRANCH"; then
38-
git checkout -b "$BRANCH" "origin/$BRANCH"
39-
else
40-
git checkout -b "$BRANCH"
41-
fi
38+
BRANCH="update-rel-notes-${{ github.run_id }}"
39+
git switch -c "$BRANCH"
4240
echo "branch=$BRANCH" >> $GITHUB_OUTPUT
4341
44-
- name: Run auto-release-notes.py script
42+
- name: Run Script
43+
id: run_script
4544
env:
4645
FEISHU_SECRET: ${{ secrets.FEISHU_SECRET }}
47-
RELEASE_NOTES_FILE: ${{ secrets.RELEASE_NOTES_FILE }}
4846
run: |
47+
set -e
4948
IFS=',' read -r APP_ID APP_SECRET URL <<< "$FEISHU_SECRET"
50-
export APP_ID APP_SECRET URL
51-
export FILENAME="${RELEASE_NOTES_FILE}"
49+
export APP_ID APP_SECRET URL FILENAME="$RELEASE_NOTES_FILE"
5250
python scripts/auto-release-notes.py
53-
54-
- name: Check if release notes file changed and commit
51+
52+
- name: Check Changes
5553
id: check_changes
56-
env:
57-
RELEASE_NOTES_FILE: ${{ secrets.RELEASE_NOTES_FILE }}
5854
run: |
59-
echo "File to check: $RELEASE_NOTES_FILE"
60-
61-
# Show git status for context
62-
echo "Current git status:"
63-
git status --porcelain
64-
65-
# Check if file has changes compared to origin/main
55+
if [ ! -f "$RELEASE_NOTES_FILE" ]; then
56+
echo "❌ Release notes file not found: $RELEASE_NOTES_FILE"
57+
exit 1
58+
fi
6659
if git diff --quiet origin/main -- "$RELEASE_NOTES_FILE"; then
67-
echo "No changes detected in release notes file"
68-
echo "File content is identical to origin/main"
6960
echo "files_are_same=true" >> $GITHUB_OUTPUT
7061
else
71-
echo "Changes detected in release notes file!"
72-
echo "Showing diff summary:"
73-
git diff --stat origin/main -- "$RELEASE_NOTES_FILE"
74-
echo ""
75-
echo "Detailed changes:"
76-
git diff origin/main -- "$RELEASE_NOTES_FILE" | head -50
7762
echo "files_are_same=false" >> $GITHUB_OUTPUT
63+
git diff --stat origin/main -- "$RELEASE_NOTES_FILE"
7864
fi
79-
80-
echo "Check completed. files_are_same=$(git diff --quiet origin/main -- "$RELEASE_NOTES_FILE" && echo 'true' || echo 'false')"
81-
82-
- name: Skip commit - No changes detected
83-
if: steps.check_changes.outputs.files_are_same == 'true'
84-
run: |
85-
echo "Skipping commit and PR creation - no changes detected"
8665
87-
- name: Commit and push release notes update
66+
- name: Commit and Push If Changes Exist
67+
id: commit_and_push
8868
if: steps.check_changes.outputs.files_are_same == 'false'
8969
uses: stefanzweifel/git-auto-commit-action@v5
9070
with:
9171
commit_message: Update rel-notes.md via automation
9272
file_pattern: ${{ secrets.RELEASE_NOTES_FILE }}
73+
skip_dirty_check: true
9374
push_options: --set-upstream
9475
branch: ${{ steps.prepare_branch.outputs.branch }}
95-
env:
96-
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
9776

98-
# 使用这个有问题,会覆盖分支且不提交pr
99-
# - name: Create Pull Request
100-
# if: steps.check_changes.outputs.files_are_same == 'false'
101-
# uses: peter-evans/create-pull-request@v7
102-
# with:
103-
# token: ${{ secrets.GITHUB_TOKEN }}
104-
# title: "Automated update of rel-notes.md"
105-
# body: "This PR updates rel-notes.md automatically."
106-
# base: main
107-
# branch: ${{ steps.prepare_branch.outputs.branch }} # 你新建的分支名
108-
# draft: true # 以草稿状态创建,避免自动合并
109-
110-
- name: Skip PR creation - No changes detected
111-
if: steps.check_changes.outputs.files_are_same == 'true'
112-
run: |
113-
echo "Skipping PR creation - no changes detected"
114-
115-
- name: Create Pull Request via API
116-
if: steps.check_changes.outputs.files_are_same == 'false'
117-
env:
118-
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
77+
- name: Create Pull Request If Push Succeeded
78+
if: steps.commit_and_push.outcome == 'success'
11979
run: |
120-
echo "Creating Pull Request for branch: ${{ steps.prepare_branch.outputs.branch }}"
121-
122-
PR_RESPONSE=$(curl -s -X POST -H "Authorization: token $GITHUB_TOKEN" \
123-
-H "Accept: application/vnd.github+json" \
124-
https://api.github.com/repos/${{ github.repository }}/pulls \
125-
-d @- << EOF
126-
{
127-
"title": "Automated update of rel-notes.md",
128-
"head": "${{ steps.prepare_branch.outputs.branch }}",
129-
"base": "main",
130-
"body": "This PR updates rel-notes.md automatically."
131-
}
132-
EOF
133-
)
134-
135-
echo "Pull Request Response:"
136-
echo "$PR_RESPONSE" | jq -r '"PR #" + (.number | tostring) + " created successfully: " + .html_url' 2>/dev/null || echo "$PR_RESPONSE"
80+
gh pr create \
81+
--title "Automated update of rel-notes.md" \
82+
--body "This PR updates rel-notes.md automatically." \
83+
--base main \
84+
--head "${{ steps.prepare_branch.outputs.branch }}" \
85+
--repo "${{ github.repository }}"

scripts/auto-release-notes.py

Lines changed: 66 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
import re
99
import logging
1010
import os
11+
import subprocess
1112
from textwrap import dedent
1213

1314

@@ -195,15 +196,9 @@ def get_release_info(data, filename="rel-notes.md"):
195196
"无更新类型": "",
196197
}
197198

198-
# 定义模板
199199
header_template = Template(
200200
dedent(
201201
"""\
202-
---
203-
hide:
204-
- toc
205-
---
206-
207202
# Release Notes
208203
209204
本页列出 d.run 各项功能的一些重要变更。
@@ -217,56 +212,89 @@ def get_release_info(data, filename="rel-notes.md"):
217212
entry_with_baseline_template = Template("- [$primary_func] $baseline")
218213
entry_without_baseline_template = Template("- [$primary_func]")
219214

220-
def ensure_blank_line(lines_list):
215+
def emit(lines_list, line=""):
216+
"""Add a line to the list, stripping trailing whitespace"""
217+
if line:
218+
lines_list.append(line.rstrip())
219+
220+
def ensure_single_blank_line(lines_list):
221+
"""Ensure there's exactly one blank line before adding new content"""
221222
if lines_list and lines_list[-1] != "":
222223
lines_list.append("")
224+
elif len(lines_list) > 1 and lines_list[-1] == "" and lines_list[-2] == "":
225+
lines_list.pop()
223226

224227
lines = header_template.substitute().splitlines()
225-
ensure_blank_line(lines)
226228

227229
for pub_date, modules in result.items():
228-
ensure_blank_line(lines)
229-
lines.append(pub_date_template.substitute(pub_date=pub_date))
230-
ensure_blank_line(lines)
230+
ensure_single_blank_line(lines)
231+
emit(lines, pub_date_template.substitute(pub_date=pub_date))
231232
for module, versions in modules.items():
232233
for version, update_types in versions.items():
233-
lines.append(
234-
module_version_template.substitute(module=module, version=version)
234+
ensure_single_blank_line(lines)
235+
emit(
236+
lines,
237+
module_version_template.substitute(module=module, version=version),
235238
)
236-
ensure_blank_line(lines)
237239
for update_type in ["新功能", "增强优化", "故障修复", "无更新类型"]:
238-
if update_type in update_types:
239-
entries = update_types[update_type]
240-
if update_type != "无更新类型":
241-
lines.append(
242-
update_type_template.substitute(
243-
emoji_title=emoji_map[update_type]
244-
)
240+
if update_type not in update_types:
241+
continue
242+
entries = update_types[update_type]
243+
if not entries:
244+
continue
245+
if update_type != "无更新类型":
246+
ensure_single_blank_line(lines)
247+
emit(
248+
lines,
249+
update_type_template.substitute(
250+
emoji_title=emoji_map[update_type]
251+
),
252+
)
253+
ensure_single_blank_line(lines)
254+
for primary_func, entry in entries:
255+
baseline = entry.get("基线参数", "")
256+
if baseline:
257+
emit(
258+
lines,
259+
entry_with_baseline_template.substitute(
260+
primary_func=primary_func, baseline=baseline
261+
),
262+
)
263+
else:
264+
emit(
265+
lines,
266+
entry_without_baseline_template.substitute(
267+
primary_func=primary_func
268+
),
245269
)
246-
ensure_blank_line(lines)
247-
for primary_func, entry in entries:
248-
baseline = entry.get("基线参数", "")
249-
if baseline:
250-
lines.append(
251-
entry_with_baseline_template.substitute(
252-
primary_func=primary_func, baseline=baseline
253-
)
254-
)
255-
else:
256-
lines.append(
257-
entry_without_baseline_template.substitute(
258-
primary_func=primary_func
259-
)
260-
)
261-
ensure_blank_line(lines)
262-
if lines and lines[-1] == "":
270+
271+
while lines and lines[-1] == "":
263272
lines.pop()
264273

265274
md_content = "\n".join(lines) + "\n"
266275
try:
267276
with open(filename, "w", encoding="utf-8") as f:
268277
f.write(md_content)
269278
logging.info("Release notes已保存到 %s", filename)
279+
280+
# Format Markdown file using mdformat
281+
try:
282+
result = subprocess.run(
283+
["mdformat", filename],
284+
capture_output=True,
285+
text=True,
286+
timeout=30,
287+
)
288+
if result.returncode == 0:
289+
logging.info("✅ Markdown文件已格式化")
290+
else:
291+
logging.warning("Markdown格式化警告: %s", result.stderr)
292+
except FileNotFoundError:
293+
logging.warning("mdformat未安装,跳过格式化步骤。可通过 'pip install mdformat' 安装")
294+
except subprocess.TimeoutExpired:
295+
logging.warning("Markdown格式化超时,跳过格式化步骤")
296+
except Exception as e:
297+
logging.warning("Markdown格式化失败: %s", e)
270298
except Exception as e:
271299
logging.error("写入release notes文件失败: %s", e)
272300

0 commit comments

Comments
 (0)