7 Commits
Author SHA1 Message Date
csh 3054338cf7 feat(ci): Release Notes 改为增量展示,正式版覆盖整个版本周期
CHANGELOG.md 仍保持整个版本累积(strip 模式),但 Release Notes 改为:
- 预发布(rc):只展示相对紧邻上一个 tag 的增量(如 rc1→rc2 新提交),
  避免同版本各 rc 之间大量重复。
- 正式版:跳过同版本 rc,基准落到上一个不同版本 tag,
  覆盖整个版本开发周期的全量提交。
基准 tag 按 RELEASE_IS_PRERELEASE 区分,Release Notes 独立用 git log 重新生成。
2026-07-20 18:13:58 +08:00
ci[bot] c3a6e6dcb6 📝 Auto update CHANGELOG for 0.0.5-rc2 [skip ci] 2026-07-20 09:46:56 +00:00
csh 207588ae36 🐛 fix(ci): 修复 mawk 不支持区间量词导致 CHANGELOG 去重失效
去重用的 awk 正则含 [0-9a-f]{7} 区间量词,ubuntu:22.04 默认的
mawk 不支持区间表达式,会把 {7} 当字面量,导致 EXISTING_HASHES
恒为空、去重完全失效,rc2 把 rc1 的提交整批重复插入。
改用不依赖区间的等价写法,并清理 0.0.5 段已产生的重复内容。
2026-07-20 17:32:13 +08:00
csh df8a9ead9c 🐛 fix(changelog): 清除 0.0.5 段残留的 ci[bot] 贡献者 2026-07-20 17:18:00 +08:00
ci[bot] 799b1c319c 📝 Auto update CHANGELOG for 0.0.5-rc2 [skip ci] 2026-07-20 09:14:50 +00:00
csh d6654b4d6d 🐛 fix(ci): 修复贡献者列表未过滤 ci[bot] 的问题
grep 正则中 [bot] 被解析为字符类,导致 ^ci[bot]$ 无法匹配字面量。
改用 grep -vxF 按字面整行匹配过滤 bot 用户名。
2026-07-20 17:13:07 +08:00
ci[bot] a83c52ec2c 📝 Auto update CHANGELOG for 0.0.5-rc1 [skip ci] 2026-07-20 09:07:44 +00:00
2 changed files with 224 additions and 28 deletions
+159 -28
View File
@@ -490,6 +490,38 @@ jobs:
COMMIT_RANGE="${PREVIOUS_TAG}..${VERSION}" COMMIT_RANGE="${PREVIOUS_TAG}..${VERSION}"
fi fi
# 计算 Release Notes 的增量基准 tag,规则按当前发布是否为预发布(rc)区分:
# - 预发布(rc):基准 = 紧邻的上一个 tag(不跳过同版本 rc)
# 例如 0.0.5-rc2 的基准是 0.0.5-rc1Release Notes 只展示 rc1→rc2 的新提交,
# 避免同一版本各 rc 之间大量重复。
# - 正式版:基准 = 上一个"不同 CHANGELOG 版本"的 tag(即上面的 PREVIOUS_TAG
# 例如 0.0.5 正式版会跳过 0.0.5-rc1/rc2,基准落到 0.0.4-rc2
# Release Notes 覆盖整个 0.0.5 开发周期的全量提交。
# 注意:CHANGELOG.md 始终是整个版本的累积(strip 模式),与此处无关。
if [[ "${RELEASE_IS_PRERELEASE}" == "true" ]]; then
NOTES_BASE_TAG=""
while IFS= read -r tag; do
[ -z "$tag" ] && continue
if [ "$tag" != "$VERSION" ]; then
NOTES_BASE_TAG="$tag"
break
fi
done <<< "$ALL_TAGS"
echo "🏷️ 预发布:Release Notes 基准 = 紧邻上一个 tag"
else
NOTES_BASE_TAG="$PREVIOUS_TAG"
echo "🏷️ 正式版:Release Notes 基准 = 上一个不同版本 tag(覆盖整个版本周期)"
fi
if [ -z "$NOTES_BASE_TAG" ]; then
echo "️ 未找到基准 tagRelease Notes 将包含全部提交"
RELEASE_NOTES_RANGE="HEAD"
else
echo "📍 Release Notes 增量基准: $NOTES_BASE_TAG"
RELEASE_NOTES_RANGE="${NOTES_BASE_TAG}..${VERSION}"
fi
echo "RELEASE_NOTES_RANGE=$RELEASE_NOTES_RANGE" >> $GITHUB_ENV
echo "" echo ""
echo "🔍 扫描提交记录..." echo "🔍 扫描提交记录..."
@@ -674,14 +706,14 @@ jobs:
grep -v "github-actions\[bot\]" | \ grep -v "github-actions\[bot\]" | \
grep -v "dependabot\[bot\]" | \ grep -v "dependabot\[bot\]" | \
grep -v "renovate\[bot\]" | \ grep -v "renovate\[bot\]" | \
grep -v "^${{ env.GIT_USER_NAME }}$" | \ grep -vxF "${{ env.GIT_USER_NAME }}" | \
sort -u) sort -u)
else else
CONTRIBUTORS=$(git log $COMMIT_RANGE --pretty=format:"%an" --no-merges | \ CONTRIBUTORS=$(git log $COMMIT_RANGE --pretty=format:"%an" --no-merges | \
grep -v "github-actions\[bot\]" | \ grep -v "github-actions\[bot\]" | \
grep -v "dependabot\[bot\]" | \ grep -v "dependabot\[bot\]" | \
grep -v "renovate\[bot\]" | \ grep -v "renovate\[bot\]" | \
grep -v "^${{ env.GIT_USER_NAME }}$" | \ grep -vxF "${{ env.GIT_USER_NAME }}" | \
sort -u) sort -u)
fi fi
@@ -726,8 +758,8 @@ jobs:
BEGIN { in_version=0 } BEGIN { in_version=0 }
/^## :bookmark: / && $0 ~ version"$" { in_version=1; next } /^## :bookmark: / && $0 ~ version"$" { in_version=1; next }
/^## :bookmark: / && in_version { in_version=0 } /^## :bookmark: / && in_version { in_version=0 }
in_version && /\(\[[0-9a-f]{7}\]/ { in_version && /\(\[[0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f]\]/ {
if (match($0, /\[([0-9a-f]{7})\]/)) { if (match($0, /\[[0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f]\]/)) {
hash = substr($0, RSTART+1, RLENGTH-2) hash = substr($0, RSTART+1, RLENGTH-2)
print hash print hash
} }
@@ -918,40 +950,139 @@ jobs:
if: steps.changelog.outputs.changelog_updated == 'true' if: steps.changelog.outputs.changelog_updated == 'true'
run: | run: |
echo "======================================" echo "======================================"
echo "📄 提取 Release Notes" echo "📄 生成增量 Release Notes"
echo "======================================" echo "======================================"
cd ${{ env.REPO_DIR }} cd ${{ env.REPO_DIR }}
python3 << 'PYSCRIPT' # Release Notes 只展示本次 rc 相对上一个 tag 的增量提交
import re # CHANGELOG.md 仍是整个版本的累积,二者用途不同)
RELEASE_NOTES_RANGE="${{ env.RELEASE_NOTES_RANGE }}"
REPO_URL="${{ github.server_url }}/${{ github.repository }}"
echo "📊 增量范围: $RELEASE_NOTES_RANGE"
changelog_version = "${{ env.CHANGELOG_VERSION }}" TEMP_COMMITS=$(mktemp)
git log $RELEASE_NOTES_RANGE --no-merges --reverse \
--format="COMMIT_START%n%H%n%an%n%s%nBODY_START%n%b%nBODY_END" > "$TEMP_COMMITS"
with open('CHANGELOG.md', 'r', encoding='utf-8') as f: declare -a COMMITS_HASH
content = f.read() declare -a COMMITS_AUTHOR
declare -a COMMITS_MESSAGE
declare -a COMMITS_BODY
# 匹配版本区块 IFS='|' read -ra IGNORE_PATTERNS <<< "${{ env.IGNORE_PATTERNS_PROCESSED }}"
pattern = rf'## :bookmark: {re.escape(changelog_version)}\s*\n(.*?)(?=\n---\n|\n## :bookmark: |\Z)'
match = re.search(pattern, content, re.DOTALL)
if match: COMMIT_INDEX=0
version_content = match.group(1).strip() CURRENT_HASH=""
# 清理多余的空行 CURRENT_AUTHOR=""
version_content = re.sub(r'\n\s*\n\s*\n+', '\n\n', version_content).strip() CURRENT_MESSAGE=""
# 移除可能的分隔线 CURRENT_BODY=""
version_content = re.sub(r'^-{3,}\s*\n', '', version_content) IN_BODY=false
print(f"✓ Found changelog for version {changelog_version}")
print(f"📊 Content length: {len(version_content)} characters")
else:
version_content = "⚠️ No changelog found for this version"
print(f"⚠️ WARNING: Version {changelog_version} not found in CHANGELOG")
with open('/tmp/release-body.txt', 'w', encoding='utf-8') as f: flush_commit() {
f.write(version_content) [ -z "$CURRENT_HASH" ] && return
for pattern in "${IGNORE_PATTERNS[@]}"; do
[ -z "$pattern" ] && continue
if echo "$CURRENT_MESSAGE" | grep -qiE "$pattern"; then
return
fi
done
COMMITS_HASH[$COMMIT_INDEX]="$CURRENT_HASH"
COMMITS_AUTHOR[$COMMIT_INDEX]="$CURRENT_AUTHOR"
COMMITS_MESSAGE[$COMMIT_INDEX]="$CURRENT_MESSAGE"
COMMITS_BODY[$COMMIT_INDEX]="$CURRENT_BODY"
COMMIT_INDEX=$((COMMIT_INDEX + 1))
}
print("✅ Release notes generated successfully") while IFS= read -r line; do
PYSCRIPT if [[ "$line" == "COMMIT_START" ]]; then
flush_commit
CURRENT_HASH=""
CURRENT_AUTHOR=""
CURRENT_MESSAGE=""
CURRENT_BODY=""
IN_BODY=false
elif [[ "$line" == "BODY_START" ]]; then
IN_BODY=true
CURRENT_BODY=""
elif [[ "$line" == "BODY_END" ]]; then
IN_BODY=false
elif [ "$IN_BODY" = true ]; then
if [ -n "$CURRENT_BODY" ]; then
CURRENT_BODY="${CURRENT_BODY}"$'\n'"${line}"
else
CURRENT_BODY="$line"
fi
else
if [ -z "$CURRENT_HASH" ]; then
CURRENT_HASH="$line"
elif [ -z "$CURRENT_AUTHOR" ]; then
CURRENT_AUTHOR="$line"
elif [ -z "$CURRENT_MESSAGE" ]; then
CURRENT_MESSAGE="$line"
fi
fi
done < "$TEMP_COMMITS"
flush_commit
rm -f "$TEMP_COMMITS"
VALID_COUNT=$COMMIT_INDEX
echo "✅ 增量有效提交: $VALID_COUNT"
NOTES="${CHANGELOG_SECTION_TITLE}\n\n"
for ((i=0; i<$VALID_COUNT; i++)); do
hash="${COMMITS_HASH[$i]}"
author="${COMMITS_AUTHOR[$i]}"
message="${COMMITS_MESSAGE[$i]}"
body="${COMMITS_BODY[$i]}"
short_hash="${hash:0:7}"
COMMIT_LINK="([${short_hash}](${REPO_URL}/commit/${hash}))"
AUTHOR_INFO=""
[ -n "$author" ] && AUTHOR_INFO=" by @${author}"
if [ -n "$body" ]; then
cleaned_body=$(echo "$body" | sed -e :a -e '/^\s*$/d;')
else
cleaned_body=""
fi
if [ -n "$cleaned_body" ]; then
NOTES="${NOTES}- ${message} \n"
while IFS= read -r bline; do
[ -z "$bline" ] && continue
NOTES="${NOTES} ${bline} \n"
done <<< "$cleaned_body"
NOTES="${NOTES} ${COMMIT_LINK}${AUTHOR_INFO}\n"
else
NOTES="${NOTES}- ${message} ${COMMIT_LINK}${AUTHOR_INFO}\n"
fi
done
# 增量贡献者(同样过滤 bot)
if [ "$RELEASE_NOTES_RANGE" = "HEAD" ]; then
CONTRIBUTORS=$(git log --pretty=format:"%an" --no-merges)
else
CONTRIBUTORS=$(git log $RELEASE_NOTES_RANGE --pretty=format:"%an" --no-merges)
fi
CONTRIBUTORS=$(echo "$CONTRIBUTORS" | \
grep -v "github-actions\[bot\]" | \
grep -v "dependabot\[bot\]" | \
grep -v "renovate\[bot\]" | \
grep -vxF "${{ env.GIT_USER_NAME }}" | \
sort -u)
if [ -n "$CONTRIBUTORS" ]; then
NOTES="${NOTES}\n${{ env.CHANGELOG_CONTRIBUTORS_TITLE }}\n\n"
while IFS= read -r name; do
[ -z "$name" ] && continue
NOTES="${NOTES}<a href=\"${{ env.GITEA_SERVER }}/${name}\">\n"
NOTES="${NOTES} <img src=\"${{ env.GITEA_SERVER }}/${name}.png\" alt=\"${name}\" width=\"35\" height=\"35\" style=\"border-radius: 50%;\" onerror=\"this.src='${{ env.GITEA_SERVER }}/assets/img/avatar_default.png'\" />\n"
NOTES="${NOTES}</a>\n"
done <<< "$CONTRIBUTORS"
fi
echo -e "$NOTES" > /tmp/release-body.txt
echo "✅ Release notes 生成完成 ($(wc -c < /tmp/release-body.txt) 字节)"
echo "======================================" echo "======================================"
echo "" echo ""
+65
View File
@@ -1,5 +1,70 @@
# CHANGELOG # CHANGELOG
## :bookmark: 0.0.5
### :pencil: What's Changed
- :sparkles: 新增 act_runner 自动升级脚本并同步最新版本探测 ([9d4c4a1](https://git.mytsl.cn/csh/actions-template/commit/9d4c4a1f7341f1ecbf663cf2a03c3434fc6ee314)) by @csh
- :recycle: 迁移 docker compose 并修复 runner 升级版本识别 ([34480c1](https://git.mytsl.cn/csh/actions-template/commit/34480c16e2e1d8a9cc38a9eb9f98a0d7b8ff544c)) by @csh
- :recycle: 隔离 workflow 工作区并提升默认 runner 并发 ([ac05621](https://git.mytsl.cn/csh/actions-template/commit/ac0562181762501eff49dde9231f65fccf2d7da4)) by @csh
- :wrench: 参数化实例配置并补充 preset env 示例 ([a4d09c9](https://git.mytsl.cn/csh/actions-template/commit/a4d09c906381f4cde4490074a950a1aaa7679ade)) by @csh
- :wrench: 统一 stats workflow 的 token 契约 ([2b5eaf2](https://git.mytsl.cn/csh/actions-template/commit/2b5eaf27c9b51ca676d24a23da044abfe14dfccc)) by @csh
- :memo: 修正 workflow 文档文件名与链接路径 ([124b953](https://git.mytsl.cn/csh/actions-template/commit/124b953d38b47f243524f8adf9f713143de1ba18)) by @csh
- :wrench: 收紧本地脚本与 runner 产物边界 ([95402f4](https://git.mytsl.cn/csh/actions-template/commit/95402f483054ea3a550fe9469cb4c1e864978e54)) by @csh
- :memo: 收紧文档入口与导航层次 ([61e512c](https://git.mytsl.cn/csh/actions-template/commit/61e512c2aef133cc5aa2263acca1cab006296317)) by @csh
- :wrench: 为 runner preset 显式设置系统 hostname ([173526b](https://git.mytsl.cn/csh/actions-template/commit/173526be7929dd2e05347bd4a4847a3b4d8e4f1a)) by @csh
- :recycle: 改用 shared mirror clone 准备 job 工作副本 ([beab4e5](https://git.mytsl.cn/csh/actions-template/commit/beab4e5696e209fb91ac321beb310526b5a5cc42)) by @csh
- :memo: 调整文档分层并补充 workflow 运行模型 ([0579c2d](https://git.mytsl.cn/csh/actions-template/commit/0579c2dc9754b67148cf4d2fe057a163f6e4483a)) by @csh
- :bug: fix(docker_runner): validate act_runner binary arch ([e5db752](https://git.mytsl.cn/csh/actions-template/commit/e5db752c55d320c3cddc663fff65d18376a41af8)) by @csh
- :wrench: chore(runner): allow preset identity overrides via env ([40fa747](https://git.mytsl.cn/csh/actions-template/commit/40fa747a941cffe87239eca31391545a0d330984)) by @csh
- :recycle: refactor(runner): simplify shell helpers and workflow scripts ([ebd0f94](https://git.mytsl.cn/csh/actions-template/commit/ebd0f94053603eb024ebd2b1d0d73d6981649ba9)) by @csh
- :bug: fix(buildx_runner): verify multiarch with explicit platforms ([8445c6a](https://git.mytsl.cn/csh/actions-template/commit/8445c6a36363381d17246923d7312ee7041c9493)) by @csh
- :memo: docs(readme): align document navigation headings ([d4fa498](https://git.mytsl.cn/csh/actions-template/commit/d4fa498a4a737c88f283d9fad3756a682d4ec362)) by @csh
- :bug: fix(stats): switch badges to self-hosted svg ([1259495](https://git.mytsl.cn/csh/actions-template/commit/1259495cbb0ebccd0972df1c0817b53e8e6e7736)) by @csh
- :art: refine(stats): simplify summary and badge colors ([6552f8b](https://git.mytsl.cn/csh/actions-template/commit/6552f8be47aa48dad26ebbc685284e14a56f4611)) by @csh
- :art: refine(stats): rebalance summary badge styling ([550e226](https://git.mytsl.cn/csh/actions-template/commit/550e226a2b6bdd3ca8b2e80f782abf2e35546b8b)) by @csh
- :wrench: chore(stats): add emoji commit prefixes for generated updates ([7782975](https://git.mytsl.cn/csh/actions-template/commit/778297543ab9cfe42d792d7c3fef9ffef9b6e193)) by @csh
- :recycle: refactor(ci): use fixed workflow slots ([610c2b3](https://git.mytsl.cn/csh/actions-template/commit/610c2b3e743f34a6a9e4ee6061e55037ecacad4c)) by @csh
- :recycle: refactor(ci): 重构为 Prepare 上游 + workflow_run 下游消费者模型
- 新增 prepare.yml:统一检查/安装公共工具并集中 fetch 到共享 bare 仓库
- 统计与发布改为消费成功的 Prepare workflow_run,各自维护 stats/release worktree
- 四个 workflow name 统一为带 emoji 的中文,同步 workflow_run 触发引用
- 系统信息 workflow 保持独立直接触发
- 删除 tests/ 手动验证脚本
([50efc4b](https://git.mytsl.cn/csh/actions-template/commit/50efc4bbfad9a897e931e9e6c1b2c2825d4d025b)) by @csh
- :bug: fix(ci): 补全 prepare.yml 缺失的 GIT_CONFIG_VALUE_1
GIT_CONFIG_COUNT=3 但 env 段漏写 GIT_CONFIG_KEY_1/VALUE_1
credential helper 函数串被错放到 KEY_1,导致 git 报
missing config value GIT_CONFIG_VALUE_1 而无法 fetch。
([2dcf9f7](https://git.mytsl.cn/csh/actions-template/commit/2dcf9f7da481cfe9e18550faf11068fef2688f72)) by @csh
- :recycle: refactor(ci): 将 GIT_CONFIG 环境变量改为内联 -c 认证
- 删除三个 workflow env 段的 GIT_CONFIG_COUNT/KEY/VALUE 变量
- 在需要认证的 git 命令上内联 -c credential.helper/interactive
- prepare fetch、stats 两处 push、release push 各自内联
- 保留 ACCESS_TOKENhelper 运行时取用
([ac8a781](https://git.mytsl.cn/csh/actions-template/commit/ac8a7816567344f48d97e86cd2c7a9ed2a43bcd1)) by @csh
- :bug: fix(ci): 修复贡献者列表未过滤 ci[bot] 的问题
grep 正则中 [bot] 被解析为字符类,导致 ^ci[bot]$ 无法匹配字面量。
改用 grep -vxF 按字面整行匹配过滤 bot 用户名。
([d6654b4](https://git.mytsl.cn/csh/actions-template/commit/d6654b4d6d7b03f7188cb9c1f49ce4c377eca235)) by @csh
- :bug: fix(changelog): 清除 0.0.5 段残留的 ci[bot] 贡献者 ([df8a9ea](https://git.mytsl.cn/csh/actions-template/commit/df8a9ead9c286652e1cfb8bc6dd4ae79ccfb0f8a)) by @csh
- :bug: fix(ci): 修复 mawk 不支持区间量词导致 CHANGELOG 去重失效
去重用的 awk 正则含 [0-9a-f]{7} 区间量词,ubuntu:22.04 默认的
mawk 不支持区间表达式,会把 {7} 当字面量,导致 EXISTING_HASHES
恒为空、去重完全失效,rc2 把 rc1 的提交整批重复插入。
改用不依赖区间的等价写法,并清理 0.0.5 段已产生的重复内容。
([207588a](https://git.mytsl.cn/csh/actions-template/commit/207588ae369d045c1ec3178ce4f6969b3b499981)) by @csh
### :busts_in_silhouette: Contributors
<a href="https://git.mytsl.cn/csh">
<img src="https://git.mytsl.cn/csh.png" alt="csh" width="35" height="35" style="border-radius: 50%;" onerror="this.src='https://git.mytsl.cn/assets/img/avatar_default.png'" />
</a>
---
## :bookmark: 0.0.4 ## :bookmark: 0.0.4
### :pencil: What's Changed ### :pencil: What's Changed