18 Commits
Author SHA1 Message Date
csh 1b7eed5d93 🐛 不行就先放弃了
Hello from ImmortalWrt / say-hello (push) Successful in 0s
2025-11-03 14:29:15 +08:00
csh 3a17dc4b52 🐛 ok了嘛 2025-11-03 14:21:19 +08:00
csh e71d9d01fd 🐛 修复过滤转义失败
Hello from ImmortalWrt / say-hello (push) Successful in 0s
2025-11-03 14:08:57 +08:00
csh 160c5ebade 🐛 匹配逻辑
Hello from ImmortalWrt / say-hello (push) Successful in 0s
2025-11-03 12:04:12 +08:00
csh fb4e7f3b1f Merge branch 'main' of https://git.mytsl.cn/csh/actions-template
Hello from ImmortalWrt / say-hello (push) Successful in 0s
2025-11-03 12:00:29 +08:00
csh 9a472a4271 🐛 修复匹配正则问题 2025-11-03 12:00:14 +08:00
github-actions[bot] 0d3ccadfef 📝 Auto update CHANGELOG for 0.0.3-rc1 [skip ci]
Hello from ImmortalWrt / say-hello (push) Successful in 0s
2025-11-03 03:38:53 +00:00
csh fa21511d1a 🐛 fix bug
Hello from ImmortalWrt / say-hello (push) Successful in 0s
2025-11-03 11:38:30 +08:00
csh 7373553270 更新 CHANGELOG.md [skip ci]
Hello from ImmortalWrt / say-hello (push) Successful in 0s
2025-11-03 11:28:25 +08:00
github-actions[bot] 3308b4354c 📝 Auto update CHANGELOG for 0.0.3-rc1 [skip ci]
Hello from ImmortalWrt / say-hello (push) Successful in 0s
2025-11-03 03:25:11 +00:00
csh f422a75c1c Merge branch 'main' of https://git.mytsl.cn/csh/actions-template
Hello from ImmortalWrt / say-hello (push) Successful in 0s
2025-11-03 11:24:45 +08:00
csh fc76a1f625 🐛 fix bug 2025-11-03 11:24:41 +08:00
csh 4ed8099158 更新 CHANGELOG.md
Hello from ImmortalWrt / say-hello (push) Successful in 0s
2025-11-03 11:22:06 +08:00
csh bf6698ab3e 🐛 修复commit信息提取错误
Hello from ImmortalWrt / say-hello (push) Successful in 0s
2025-11-03 11:19:46 +08:00
github-actions[bot] b57c0cc9d6 📝 Auto update CHANGELOG for 0.0.3-rc1 [skip ci]
Hello from ImmortalWrt / say-hello (push) Successful in 0s
2025-11-03 02:44:03 +00:00
csh 1f535e0675 ♻️ 重构changelog_and_release.yml
Hello from ImmortalWrt / say-hello (push) Successful in 0s
2025-11-03 10:40:26 +08:00
csh 9961226704 🐛 移除默认上传CHANGELOG.md
Hello from ImmortalWrt / say-hello (push) Successful in 0s
2025-11-02 23:17:07 +08:00
github-actions[bot] b4c47c4085 📝 Auto update CHANGELOG for 0.0.2-rc1 [skip ci]
Hello from ImmortalWrt / say-hello (push) Successful in 0s
2025-11-02 15:15:01 +00:00
2 changed files with 460 additions and 275 deletions
+413 -275
View File
@@ -5,6 +5,10 @@ on:
tags: tags:
- "[0-9]*" - "[0-9]*"
concurrency:
group: release-${{ github.repository }}
cancel-in-progress: false
# ========================================== # ==========================================
# 🔧 配置区域 - 根据你的项目修改 # 🔧 配置区域 - 根据你的项目修改
# ========================================== # ==========================================
@@ -33,7 +37,7 @@ env:
# ===== 分支配置 ===== # ===== 分支配置 =====
# 主分支名称(用于推送 CHANGELOG 更新) # 主分支名称(用于推送 CHANGELOG 更新)
# 如果留空,会自动检测(main 或 master # 如果留空,会自动检测(main 或 master
MAIN_BRANCH: "" MAIN_BRANCH: "main"
# ===== 服务器配置 ===== # ===== 服务器配置 =====
# Gitea 服务器地址(用于生成头像链接和 API 调用) # Gitea 服务器地址(用于生成头像链接和 API 调用)
@@ -63,6 +67,8 @@ env:
# - "true": 创建为草稿,不会立即发布 # - "true": 创建为草稿,不会立即发布
# - "false": 立即发布 Release # - "false": 立即发布 Release
RELEASE_IS_DRAFT: "false" RELEASE_IS_DRAFT: "false"
# 统一管理 pre-release 关键词
PRERELEASE_KEYWORDS: "alpha|beta|rc|pre|preview|dev|test"
# 额外要上传到 Release 的文件(空格分隔) # 额外要上传到 Release 的文件(空格分隔)
# 例如: "README.md LICENSE docs/guide.pdf" # 例如: "README.md LICENSE docs/guide.pdf"
ADDITIONAL_RELEASE_FILES: "" ADDITIONAL_RELEASE_FILES: ""
@@ -88,8 +94,8 @@ env:
IGNORE_PATTERNS: >- IGNORE_PATTERNS: >-
^Merge | ^Merge |
^:memo: Auto update CHANGELOG| ^:memo: Auto update CHANGELOG|
\[skip ci\]\s*$| \\[skip ci\\]|
\[ci skip\]\s*$| \\[ci skip\\]|
^Bump version| ^Bump version|
^Release v| ^Release v|
^chore: update config$| ^chore: update config$|
@@ -137,10 +143,14 @@ jobs:
# 从环境变量读取配置 # 从环境变量读取配置
VERSION="${{ github.ref_name }}" VERSION="${{ github.ref_name }}"
KEYWORDS="${{ env.PRERELEASE_KEYWORDS }}"
STRIP_REGEX="-($KEYWORDS)[0-9]*$" # 用于 sed 删除后缀
MATCH_REGEX="($KEYWORDS)" # 用于 bash =~ 匹配
# 处理 CHANGELOG 版本号 # 处理 CHANGELOG 版本号
if [[ "${{ env.CHANGELOG_VERSION_MODE }}" == "strip" ]]; then if [[ "${{ env.CHANGELOG_VERSION_MODE }}" == "strip" ]]; then
# 去除 pre-release 后缀(-beta, -rc1, -alpha 等) # 去除 pre-release 后缀(-beta, -rc1, -alpha 等)
CHANGELOG_VERSION=$(echo "$VERSION" | sed -E 's/-(alpha|beta|rc|pre|preview|dev|test)[0-9]*$//') CHANGELOG_VERSION=$(echo "$VERSION" | sed -E "s/${STRIP_REGEX}//")
echo "📝 CHANGELOG version mode: strip" echo "📝 CHANGELOG version mode: strip"
echo " Tag: $VERSION → CHANGELOG: $CHANGELOG_VERSION" echo " Tag: $VERSION → CHANGELOG: $CHANGELOG_VERSION"
else else
@@ -160,7 +170,7 @@ jobs:
# 智能判断 pre-release # 智能判断 pre-release
if [[ "${{ env.RELEASE_PRERELEASE_MODE }}" == "auto" ]]; then if [[ "${{ env.RELEASE_PRERELEASE_MODE }}" == "auto" ]]; then
if [[ "$VERSION" =~ (alpha|beta|rc|pre|preview|dev|test) ]]; then if [[ "$VERSION" =~ $MATCH_REGEX ]]; then
RELEASE_IS_PRERELEASE="true" RELEASE_IS_PRERELEASE="true"
PRERELEASE_DETECTED="yes (auto-detected: $VERSION contains pre-release keyword)" PRERELEASE_DETECTED="yes (auto-detected: $VERSION contains pre-release keyword)"
else else
@@ -172,34 +182,44 @@ jobs:
PRERELEASE_DETECTED="${{ env.RELEASE_PRERELEASE_MODE }} (manually configured)" PRERELEASE_DETECTED="${{ env.RELEASE_PRERELEASE_MODE }} (manually configured)"
fi fi
# 处理忽略模式(去除空格,保持管道分隔格式)
echo "🔧 处理忽略模式..."
PROCESSED_PATTERNS=""
IFS='|' read -ra PATTERNS_ARRAY <<< "${{ env.IGNORE_PATTERNS }}"
for pattern in "${PATTERNS_ARRAY[@]}"; do
# 使用 sed 去除首尾空格,保留转义字符
pattern=$(echo "$pattern" | sed 's/^[[:space:]]*//;s/[[:space:]]*$//')
if [ -n "$pattern" ]; then
if [ -z "$PROCESSED_PATTERNS" ]; then
PROCESSED_PATTERNS="$pattern"
else
PROCESSED_PATTERNS="$PROCESSED_PATTERNS|$pattern"
fi
fi
done
echo "✅ 已处理 $(echo "$PROCESSED_PATTERNS" | grep -o '|' | wc -l | awk '{print $1+1}') 个忽略模式"
# 导出处理后的配置到 GitHub 环境变量 # 导出处理后的配置到 GitHub 环境变量
echo "CHANGELOG_VERSION=$CHANGELOG_VERSION" >> $GITHUB_ENV echo "CHANGELOG_VERSION=$CHANGELOG_VERSION" >> $GITHUB_ENV
echo "RELEASE_TITLE_PROCESSED=$RELEASE_TITLE_PROCESSED" >> $GITHUB_ENV echo "RELEASE_TITLE_PROCESSED=$RELEASE_TITLE_PROCESSED" >> $GITHUB_ENV
echo "RELEASE_IS_PRERELEASE=$RELEASE_IS_PRERELEASE" >> $GITHUB_ENV echo "RELEASE_IS_PRERELEASE=$RELEASE_IS_PRERELEASE" >> $GITHUB_ENV
echo "COMMIT_MSG=$COMMIT_MSG" >> $GITHUB_ENV echo "COMMIT_MSG=$COMMIT_MSG" >> $GITHUB_ENV
# 处理忽略模式(转换为数组) echo "PRERELEASE_STRIP_REGEX=$STRIP_REGEX" >> $GITHUB_ENV
IFS='|' read -ra PATTERNS_ARRAY <<< "${{ env.IGNORE_PATTERNS }}" echo "PRERELEASE_MATCH_REGEX=$MATCH_REGEX" >> $GITHUB_ENV
IGNORE_JSON="["
for pattern in "${PATTERNS_ARRAY[@]}"; do echo "IGNORE_PATTERNS_PROCESSED=$PROCESSED_PATTERNS" >> $GITHUB_ENV
# 去除首尾空格
pattern=$(echo "$pattern" | xargs)
if [ -n "$pattern" ]; then
IGNORE_JSON="${IGNORE_JSON}\"${pattern}\","
fi
done
IGNORE_JSON="${IGNORE_JSON%,}]"
echo "IGNORE_PATTERNS_JSON=$IGNORE_JSON" >> $GITHUB_ENV
# 显示配置摘要 # 显示配置摘要
echo "" echo ""
echo "📋 Configuration Summary:" echo "📋 Configuration Summary:"
echo " 🏷️ Tag version: $VERSION" echo " 🏷️ Tag version: $VERSION"
echo " 📝 CHANGELOG version: $CHANGELOG_VERSION" echo " 📝 CHANGELOG version: $CHANGELOG_VERSION"
echo " 🌐 Gitea Server: ${{ env.GITEA_SERVER }}" echo " 🌐 Gitea Server: ${{ env.GITEA_SERVER }}"
echo " 📄 CHANGELOG Title: ${{ env.CHANGELOG_SECTION_TITLE }}" echo " 📄 CHANGELOG Title: ${{ env.CHANGELOG_SECTION_TITLE }}"
echo " 🚀 Release Title: $RELEASE_TITLE_PROCESSED" echo " 🚀 Release Title: $RELEASE_TITLE_PROCESSED"
echo " 🏷️ Pre-release: $PRERELEASE_DETECTED" echo " 🏷️ Pre-release: $PRERELEASE_DETECTED"
echo " 📄 Draft: ${{ env.RELEASE_IS_DRAFT }}" echo " 📄 Draft: ${{ env.RELEASE_IS_DRAFT }}"
echo " 💬 Commit Message: $COMMIT_MSG" echo " 💬 Commit Message: $COMMIT_MSG"
echo " 📎 Additional Files: ${ADDITIONAL_RELEASE_FILES:-none}" echo " 📎 Additional Files: ${ADDITIONAL_RELEASE_FILES:-none}"
@@ -259,6 +279,13 @@ jobs:
if [ $? -ne 0 ]; then if [ $? -ne 0 ]; then
echo "❌ 克隆失败" echo "❌ 克隆失败"
cat /tmp/git_clone.log
# 清理残留
if [ -d "$REPO_DIR" ]; then
rm -rf "$REPO_DIR"
fi
exit 1 exit 1
fi fi
@@ -283,26 +310,37 @@ jobs:
fi fi
fi fi
# 检测主分支名称
echo "" echo ""
echo "🔍 检测主分支名称..." echo "🔍 验证主分支配置..."
if [ -n "${{ env.MAIN_BRANCH }}" ]; then
MAIN_BRANCH="${{ env.MAIN_BRANCH }}" # 检查是否配置了主分支
echo "✓ 使用配置的主分支: $MAIN_BRANCH" if [ -z "${{ env.MAIN_BRANCH }}" ]; then
else echo "❌ 错误: 未配置主分支"
# 自动检测 main 或 master echo ""
if git show-ref --verify --quiet refs/remotes/origin/main; then echo "请在 workflow 配置文件的 env 区域设置 MAIN_BRANCH:"
MAIN_BRANCH="main" echo ""
echo "✓ 自动检测到主分支: main" echo "env:"
elif git show-ref --verify --quiet refs/remotes/origin/master; then echo " MAIN_BRANCH: \"main\" # 或 \"master\""
MAIN_BRANCH="master" echo ""
echo "✓ 自动检测到主分支: master" exit 1
else
echo "❌ 错误: 无法检测主分支(main 或 master"
exit 1
fi
fi fi
MAIN_BRANCH="${{ env.MAIN_BRANCH }}"
echo "✓ 使用配置的主分支: $MAIN_BRANCH"
# 验证分支是否存在
if ! git show-ref --verify --quiet refs/remotes/origin/$MAIN_BRANCH; then
echo "❌ 错误: 配置的分支 '$MAIN_BRANCH' 不存在"
echo ""
echo "可用的远程分支:"
git branch -r | grep -v HEAD
echo ""
echo "请在 workflow 配置文件中修改 MAIN_BRANCH 为正确的分支名"
exit 1
fi
echo "✓ 分支 '$MAIN_BRANCH' 已验证存在"
# 切换到主分支 # 切换到主分支
echo "" echo ""
echo "🌿 切换到主分支: $MAIN_BRANCH" echo "🌿 切换到主分支: $MAIN_BRANCH"
@@ -346,38 +384,9 @@ jobs:
echo "======================================" echo "======================================"
echo "" echo ""
- name: 🔍 检查版本是否已存在
id: check_version
if: steps.check_bot.outputs.is_bot_commit != 'true'
run: |
echo "======================================"
echo "🔍 检查 CHANGELOG 版本"
echo "======================================"
cd ${{ env.REPO_DIR }}
if [ ! -f "CHANGELOG.md" ]; then
echo "📝 CHANGELOG.md 不存在,将创建新文件"
echo "version_exists=false" >> $GITHUB_OUTPUT
else
CHANGELOG_VERSION="${{ env.CHANGELOG_VERSION }}"
echo "📝 检查版本: $CHANGELOG_VERSION"
if grep -q "## :bookmark: $CHANGELOG_VERSION" CHANGELOG.md; then
echo "⚠️ 版本 $CHANGELOG_VERSION 已存在于 CHANGELOG.md"
echo "version_exists=true" >> $GITHUB_OUTPUT
else
echo "✅ 版本 $CHANGELOG_VERSION 不存在,可以继续"
echo "version_exists=false" >> $GITHUB_OUTPUT
fi
fi
echo "======================================"
echo ""
- name: 📝 生成 CHANGELOG - name: 📝 生成 CHANGELOG
id: changelog id: changelog
if: steps.check_bot.outputs.is_bot_commit != 'true' && steps.check_version.outputs.version_exists != 'true' if: steps.check_bot.outputs.is_bot_commit != 'true'
run: | run: |
echo "======================================" echo "======================================"
echo "📝 生成 CHANGELOG" echo "📝 生成 CHANGELOG"
@@ -407,7 +416,7 @@ jobs:
# 对每个 tag 执行 strip 操作(去除 pre-release 后缀) # 对每个 tag 执行 strip 操作(去除 pre-release 后缀)
if [[ "${{ env.CHANGELOG_VERSION_MODE }}" == "strip" ]]; then if [[ "${{ env.CHANGELOG_VERSION_MODE }}" == "strip" ]]; then
tag_stripped=$(echo "$tag" | sed -E 's/-(alpha|beta|rc|pre|preview|dev|test)[0-9]*$//') tag_stripped=$(echo "$tag" | sed -E "s/${{ env.PRERELEASE_STRIP_REGEX }}//")
else else
tag_stripped="$tag" tag_stripped="$tag"
fi fi
@@ -420,248 +429,394 @@ jobs:
done <<< "$ALL_TAGS" done <<< "$ALL_TAGS"
if [ -z "$PREVIOUS_TAG" ]; then if [ -z "$PREVIOUS_TAG" ]; then
echo "No previous tag found, using all commits" echo "未找到前一个tag,将使用所有提交"
COMMIT_RANGE="" COMMIT_RANGE="HEAD"
else else
echo "📍 Previous tag: $PREVIOUS_TAG" echo "📍 前一个tag: $PREVIOUS_TAG"
# 对 previous tag 也执行 strip,显示对应的 CHANGELOG 版本 # 对 previous tag 也执行 strip,显示对应的 CHANGELOG 版本
if [[ "${{ env.CHANGELOG_VERSION_MODE }}" == "strip" ]]; then if [[ "${{ env.CHANGELOG_VERSION_MODE }}" == "strip" ]]; then
PREV_CHANGELOG_VERSION=$(echo "$PREVIOUS_TAG" | sed -E 's/-(alpha|beta|rc|pre|preview|dev|test)[0-9]*$//') PREV_CHANGELOG_VERSION=$(echo "$PREVIOUS_TAG" | sed -E "s/${{ env.PRERELEASE_STRIP_REGEX }}//")
echo " (对应 CHANGELOG 版本: $PREV_CHANGELOG_VERSION)" echo " (对应 CHANGELOG 版本: $PREV_CHANGELOG_VERSION)"
fi fi
COMMIT_RANGE="${PREVIOUS_TAG}..${VERSION}" COMMIT_RANGE="${PREVIOUS_TAG}..${VERSION}"
fi fi
# 获取提交记录
echo "" echo ""
echo "📋 获取提交记录..." echo "🔍 扫描提交记录..."
if [ -z "$COMMIT_RANGE" ]; then
git log --pretty=format:'%H|%s' > /tmp/commits.txt TEMP_COMMITS=$(mktemp)
else git log $COMMIT_RANGE --no-merges --reverse --format="COMMIT_START%n%H%n%an%n%s%nBODY_START%n%b%nBODY_END" > "$TEMP_COMMITS"
git log --pretty=format:'%H|%s' "$COMMIT_RANGE" > /tmp/commits.txt
declare -a COMMITS_HASH
declare -a COMMITS_AUTHOR
declare -a COMMITS_MESSAGE
declare -a COMMITS_BODY
# 从环境变量加载忽略模式 (转换为 bash 数组)
IFS='|' read -ra IGNORE_PATTERNS <<< "${{ env.IGNORE_PATTERNS_PROCESSED }}"
echo "📋 已加载 ${#IGNORE_PATTERNS[@]} 个忽略模式"
COMMIT_INDEX=0
CURRENT_HASH=""
CURRENT_AUTHOR=""
CURRENT_MESSAGE=""
CURRENT_BODY=""
IN_BODY=false
SKIPPED_COUNT=0
while IFS= read -r line; do
if [[ "$line" == "COMMIT_START" ]]; then
# 处理前一个 commit
if [ -n "$CURRENT_HASH" ]; then
SHOULD_SKIP=false
for pattern in "${IGNORE_PATTERNS[@]}"; do
[ -z "$pattern" ] && continue
if echo "$CURRENT_MESSAGE" | grep -qiE "$pattern"; then
SHOULD_SKIP=true
echo " ⏭️ 跳过: ${CURRENT_MESSAGE:0:70}... (匹配: ${pattern})"
SKIPPED_COUNT=$((SKIPPED_COUNT + 1))
break
fi
done
if [ "$SHOULD_SKIP" = false ]; then
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))
fi
fi
# 重置状态
CURRENT_HASH=""
CURRENT_AUTHOR=""
CURRENT_MESSAGE=""
CURRENT_BODY=""
IN_BODY=false
STATE="HASH"
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"
# 处理最后一个 commit
if [ -n "$CURRENT_HASH" ]; then
SHOULD_SKIP=false
for pattern in "${IGNORE_PATTERNS[@]}"; do
[ -z "$pattern" ] && continue
if echo "$CURRENT_MESSAGE" | grep -qiE "$pattern"; then
SHOULD_SKIP=true
echo " ⏭️ 跳过: ${CURRENT_MESSAGE:0:70}... (匹配: ${pattern})"
SKIPPED_COUNT=$((SKIPPED_COUNT + 1))
break
fi
done
if [ "$SHOULD_SKIP" = false ]; then
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))
fi
fi fi
TOTAL_COMMITS=$(wc -l < /tmp/commits.txt) rm -f "$TEMP_COMMITS"
echo "✓ 找到 $TOTAL_COMMITS 个提交"
# Python 脚本生成 CHANGELOG VALID_COUNT=$COMMIT_INDEX
python3 << 'PYSCRIPT'
import re
import json
import sys
from datetime import datetime
# 读取配置 echo ""
changelog_version = "${{ env.CHANGELOG_VERSION }}" echo "📊 提交统计:"
gitea_server = "${{ env.GITEA_SERVER }}" echo " ✅ 有效提交: $VALID_COUNT"
repo = "${{ github.repository }}" echo " ⏭️ 已跳过: $SKIPPED_COUNT"
section_title = "${{ env.CHANGELOG_SECTION_TITLE }}" echo " 📝 总计: $((VALID_COUNT + SKIPPED_COUNT))"
contributors_title = "${{ env.CHANGELOG_CONTRIBUTORS_TITLE }}" echo ""
# 读取忽略模式 if [ $VALID_COUNT -eq 0 ]; then
ignore_patterns = json.loads('${{ env.IGNORE_PATTERNS_JSON }}') echo "⚠️ 未找到有效的提交"
print(f"🔍 Loaded {len(ignore_patterns)} ignore patterns:") echo "changelog_updated=false" >> $GITHUB_OUTPUT
for pattern in ignore_patterns: echo "content_changed=false" >> $GITHUB_OUTPUT
print(f" - {pattern}") exit 0
print() fi
# 读取提交 # ============================================
with open('/tmp/commits.txt', 'r', encoding='utf-8') as f: # 构建 CHANGELOG 条目
lines = f.readlines() # ============================================
echo "📄 构建 CHANGELOG 条目..."
commits = [] REPO_URL="${{ github.server_url }}/${{ github.repository }}"
skipped_commits = []
for line in lines:
line = line.strip()
if not line or '|' not in line:
continue
commit_hash, message = line.split('|', 1) # 初始化条目内容
NEW_ENTRY="## :bookmark: ${CHANGELOG_VERSION}\n\n"
NEW_ENTRY="${NEW_ENTRY}${CHANGELOG_SECTION_TITLE}\n\n"
# 检查是否应该忽略 # 处理每个提交
should_ignore = False for ((i=0; i<$VALID_COUNT; i++)); do
matched_pattern = None hash="${COMMITS_HASH[$i]}"
for pattern in ignore_patterns: author="${COMMITS_AUTHOR[$i]}"
if re.search(pattern, message): message="${COMMITS_MESSAGE[$i]}"
should_ignore = True body="${COMMITS_BODY[$i]}"
matched_pattern = pattern
break
if should_ignore: echo " [$((i+1))/$VALID_COUNT] ${hash:0:7}: ${message:0:60}..."
skipped_commits.append((message, matched_pattern))
else:
commits.append({'hash': commit_hash, 'message': message})
# 输出统计 # 构建提交链接 - 使用短 hash 格式
print(f"📊 Commit Statistics:") short_hash="${hash:0:7}"
print(f" Total: {len(lines)}") COMMIT_LINK="([${short_hash}](${REPO_URL}/commit/${hash}))"
print(f" Valid: {len(commits)}")
print(f" Skipped: {len(skipped_commits)}")
print()
if skipped_commits: # 构建作者信息
print("⏭️ Skipped Commits:") AUTHOR_INFO=""
for msg, pattern in skipped_commits: if [ -n "$author" ]; then
print(f" ⏭️ Skipping: {msg[:80]}... (matched: {pattern})") AUTHOR_INFO=" by @${author}"
print() fi
if not commits: # 处理 body (如果存在)
print("⚠️ No valid commits found") if [ -n "$body" ]; then
with open('/tmp/changelog_updated.txt', 'w') as f: # 移除首尾空行
f.write('false') cleaned_body=$(echo "$body" | sed -e :a -e '/^\s*$/d;')
sys.exit(0)
# 收集贡献者 if [ -n "$cleaned_body" ]; then
contributors = set() # 有 body: 主题在第一行,body 内容缩进显示,链接和作者放在一起
for commit in commits: NEW_ENTRY="${NEW_ENTRY}- ${message} \n"
# 从提交消息中提取可能的用户名(如果使用了 @username 格式)
# 这里简化处理,实际可以通过 git log --format='%an|%ae' 获取
pass
# 生成 CHANGELOG 内容 # 将 body 按行添加,每行缩进两个空格,使用 Markdown 换行
changelog_content = f"## :bookmark: {changelog_version}\n\n" while IFS= read -r line; do
changelog_content += f"*Released on {datetime.now().strftime('%Y-%m-%d')}*\n\n" [ -z "$line" ] && continue
changelog_content += f"{section_title}\n\n" NEW_ENTRY="${NEW_ENTRY} ${line} \n"
done <<< "$cleaned_body"
for commit in commits: # 链接和作者放在缩进行
short_hash = commit['hash'][:7] NEW_ENTRY="${NEW_ENTRY} ${COMMIT_LINK}${AUTHOR_INFO}\n"
message = commit['message'] else
changelog_content += f"- {message} ([`{short_hash}`](https://github.com/{repo}/commit/{commit['hash']}))\n" # body 为空 (只有空白): 单行格式
NEW_ENTRY="${NEW_ENTRY}- ${message} ${COMMIT_LINK}${AUTHOR_INFO}\n"
fi
else
# 没有 body: 单行格式
NEW_ENTRY="${NEW_ENTRY}- ${message} ${COMMIT_LINK}${AUTHOR_INFO}\n"
fi
done
# 如果有贡献者信息,可以在这里添加 echo ""
# changelog_content += f"\n{contributors_title}\n\n" echo "👥 收集贡献者..."
changelog_content += "\n---\n\n" # 收集贡献者 (去除 bot)
if [ "$COMMIT_RANGE" = "HEAD" ]; then
CONTRIBUTORS=$(git log --pretty=format:"%an" --no-merges | \
grep -v "github-actions\[bot\]" | \
grep -v "dependabot\[bot\]" | \
grep -v "renovate\[bot\]" | \
sort -u)
else
CONTRIBUTORS=$(git log $COMMIT_RANGE --pretty=format:"%an" --no-merges | \
grep -v "github-actions\[bot\]" | \
grep -v "dependabot\[bot\]" | \
grep -v "renovate\[bot\]" | \
sort -u)
fi
if [ -n "$CONTRIBUTORS" ]; then
CONTRIBUTOR_COUNT=$(echo "$CONTRIBUTORS" | wc -l)
echo "✓ 找到 ${CONTRIBUTOR_COUNT} 个贡献者"
NEW_ENTRY="${NEW_ENTRY}\n${{ env.CHANGELOG_CONTRIBUTORS_TITLE }}\n\n"
while IFS= read -r name; do
[ -z "$name" ] && continue
NEW_ENTRY="${NEW_ENTRY}<a href=\"${{ env.GITEA_SERVER }}/${name}\">\n"
NEW_ENTRY="${NEW_ENTRY} <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"
NEW_ENTRY="${NEW_ENTRY}</a>\n"
done <<< "$CONTRIBUTORS"
fi
NEW_ENTRY="${NEW_ENTRY}\n---\n"
echo ""
echo "💾 写入 CHANGELOG.md..."
# 切换到主分支
git checkout ${{ env.MAIN_BRANCH }}
# ============================================
# 更新或创建 CHANGELOG.md # 更新或创建 CHANGELOG.md
changelog_file = 'CHANGELOG.md' # ============================================
try:
with open(changelog_file, 'r', encoding='utf-8') as f:
existing_content = f.read()
except FileNotFoundError:
existing_content = "# :memo: CHANGELOG\n\n"
# 检查版本是否已存在 if [ -f CHANGELOG.md ]; then
if f"## :bookmark: {changelog_version}" in existing_content: # CHANGELOG 文件已存在
print(f"️ Version {changelog_version} already exists, appending commits") if grep -q "^## :bookmark: ${CHANGELOG_VERSION}$" CHANGELOG.md; then
# 找到版本区块,在其中追加新的提交 # 版本已存在 - 内容叠加模式
pattern = rf'(## :bookmark: {re.escape(changelog_version)}.*?\n{re.escape(section_title)}\n\n)(.*?)(\n---|\n## :bookmark: |\Z)' echo "🔄 版本 ${CHANGELOG_VERSION} 已存在,执行内容叠加..."
match = re.search(pattern, existing_content, re.DOTALL)
if match: # 提取现有版本区域中的 commit hashes (用于去重)
existing_commits = match.group(2).strip() EXISTING_HASHES=$(awk -v version="${CHANGELOG_VERSION}" '
new_commits = changelog_content.split(f"{section_title}\n\n")[1].split("\n---")[0].strip() BEGIN { in_version=0 }
/^## :bookmark: / && $0 ~ version"$" { in_version=1; next }
/^## :bookmark: / && in_version { in_version=0 }
in_version && /\(\[[0-9a-f]{7}\]/ {
if (match($0, /\[([0-9a-f]{7})\]/)) {
hash = substr($0, RSTART+1, RLENGTH-2)
print hash
}
}
' CHANGELOG.md | sort -u)
# 合并提交,去重 # 找出真正的新 commits (基于 hash 去重)
all_commits_text = existing_commits + "\n" + new_commits NEW_COMMIT_ENTRIES=""
# 简单去重(基于完整行) NEW_COMMIT_COUNT=0
unique_lines = []
seen = set()
for line in all_commits_text.split('\n'):
if line.strip() and line not in seen:
unique_lines.append(line)
seen.add(line)
merged_commits = '\n'.join(unique_lines) for ((i=0; i<$VALID_COUNT; i++)); do
hash="${COMMITS_HASH[$i]}"
short_hash="${hash:0:7}"
# 重新组装版本区块 # 检查这个 commit 是否已存在
updated_section = match.group(1) + merged_commits + "\n\n---\n" if echo "$EXISTING_HASHES" | grep -q "^${short_hash}$"; then
new_content = existing_content[:match.start()] + updated_section + existing_content[match.end():] echo " ️ 跳过已存在: ${short_hash} ${COMMITS_MESSAGE[$i]:0:50}..."
else: continue
print("⚠️ Could not find version section, prepending new content") fi
# 尝试匹配各种可能的 CHANGELOG 标题格式
header_pattern = r'^#\s*(?::[\w_]+:)?\s*CHANGELOG\s*\n'
match = re.search(header_pattern, existing_content, re.IGNORECASE | re.MULTILINE)
if match: # 这是一个新的 commit,添加它
insert_pos = match.end() author="${COMMITS_AUTHOR[$i]}"
if not existing_content[insert_pos:insert_pos+1] == '\n': message="${COMMITS_MESSAGE[$i]}"
new_content = existing_content[:insert_pos] + '\n' + changelog_content + existing_content[insert_pos:] body="${COMMITS_BODY[$i]}"
else:
new_content = existing_content[:insert_pos] + '\n' + changelog_content + existing_content[insert_pos+1:]
else:
# 没有找到标题,在开头插入
new_content = f"# :memo: CHANGELOG\n\n{changelog_content}{existing_content}"
else:
# 插入新版本
# 尝试匹配各种可能的 CHANGELOG 标题格式
# 支持: # CHANGELOG, # :memo: CHANGELOG, # Changelog 等
# 尝试找到 CHANGELOG 标题(不区分大小写,可选 emoji) COMMIT_LINK="([${short_hash}](${REPO_URL}/commit/${hash}))"
header_pattern = r'^#\s*(?::[\w_]+:)?\s*CHANGELOG\s*\n'
match = re.search(header_pattern, existing_content, re.IGNORECASE | re.MULTILINE)
if match: # 构建作者信息
# 找到了 CHANGELOG 标题,在其后插入 AUTHOR_INFO=""
insert_pos = match.end() if [ -n "$author" ]; then
# 确保标题后有空行 AUTHOR_INFO=" by @${author}"
if not existing_content[insert_pos:insert_pos+1] == '\n': fi
new_content = existing_content[:insert_pos] + '\n' + changelog_content + existing_content[insert_pos:]
else:
new_content = existing_content[:insert_pos] + '\n' + changelog_content + existing_content[insert_pos+1:]
else:
# 没有找到 CHANGELOG 标题,在文件开头插入标题和内容
if existing_content.strip():
# 文件有内容但没有 CHANGELOG 标题
new_content = f"# :memo: CHANGELOG\n\n{changelog_content}{existing_content}"
else:
# 文件为空
new_content = f"# :memo: CHANGELOG\n\n{changelog_content}"
# 检查内容是否真的改变 if [ -n "$body" ]; then
content_changed = (new_content != existing_content) cleaned_body=$(echo "$body" | sed -e :a -e '/^\s*$/d;')
version_exists = f"## :bookmark: {changelog_version}" in existing_content if [ -n "$cleaned_body" ]; then
NEW_COMMIT_ENTRIES="${NEW_COMMIT_ENTRIES}- ${message} \n"
while IFS= read -r line; do
[ -z "$line" ] && continue
NEW_COMMIT_ENTRIES="${NEW_COMMIT_ENTRIES} ${line} \n"
done <<< "$cleaned_body"
NEW_COMMIT_ENTRIES="${NEW_COMMIT_ENTRIES} ${COMMIT_LINK}${AUTHOR_INFO}\n"
else
NEW_COMMIT_ENTRIES="${NEW_COMMIT_ENTRIES}- ${message} ${COMMIT_LINK}${AUTHOR_INFO}\n"
fi
else
NEW_COMMIT_ENTRIES="${NEW_COMMIT_ENTRIES}- ${message} ${COMMIT_LINK}${AUTHOR_INFO}\n"
fi
if content_changed: NEW_COMMIT_COUNT=$((NEW_COMMIT_COUNT + 1))
with open(changelog_file, 'w', encoding='utf-8') as f: done
f.write(new_content)
print(f"✅ CHANGELOG updated successfully") if [ $NEW_COMMIT_COUNT -gt 0 ]; then
print(f" Added {len(commits)} commits to version {changelog_version}") echo "✓ 发现 ${NEW_COMMIT_COUNT} 个新的commits需要添加"
with open('/tmp/changelog_updated.txt', 'w') as f: # 在 Contributors 部分之前插入新的 commits
f.write('true') TEMP_FILE=$(mktemp)
with open('/tmp/content_changed.txt', 'w') as f: IN_VERSION=false
f.write('true') ADDED=false
elif version_exists:
# 内容没有变化,但版本已存在
# 这通常发生在重建已删除的 tag
# 我们仍然应该创建 Release(从现有 CHANGELOG 提取内容)
print(f"️ No new content to add")
print(f" Version {changelog_version} already contains all {len(commits)} commits")
print(f" This usually happens when recreating a deleted tag")
print(f" Will still create Release from existing CHANGELOG content")
with open('/tmp/changelog_updated.txt', 'w') as f: while IFS= read -r line; do
f.write('true') # 返回 true 以触发 Release 创建 # 检测版本标题
with open('/tmp/content_changed.txt', 'w') as f: if [[ "$line" =~ ^##[[:space:]]:bookmark:[[:space:]]${CHANGELOG_VERSION}$ ]]; then
f.write('false') # 但文件没有变化,不需要提交 echo "$line" >> "$TEMP_FILE"
else: IN_VERSION=true
# 既没有新内容,版本也不存在(不应该发生) # 检测到 Contributors 标题,在它之前插入新 commits
print(f"⚠️ Unexpected state: no content change and version doesn't exist") elif [[ "$line" =~ ^###[[:space:]]:busts_in_silhouette: ]] && [ "$IN_VERSION" = true ] && [ "$ADDED" = false ]; then
echo "" >> "$TEMP_FILE"
echo -e "${NEW_COMMIT_ENTRIES}" >> "$TEMP_FILE"
echo "$line" >> "$TEMP_FILE"
ADDED=true
# 遇到下一个版本标题
elif [[ "$line" =~ ^##[[:space:]]:bookmark: ]] && [ "$IN_VERSION" = true ]; then
# 如果还没添加(可能没有 Contributors 部分)
if [ "$ADDED" = false ]; then
echo "" >> "$TEMP_FILE"
echo -e "${NEW_COMMIT_ENTRIES}" >> "$TEMP_FILE"
ADDED=true
fi
echo "$line" >> "$TEMP_FILE"
IN_VERSION=false
else
echo "$line" >> "$TEMP_FILE"
fi
done < CHANGELOG.md
with open('/tmp/changelog_updated.txt', 'w') as f: # 如果到文件末尾还没添加(版本在最后且没有 Contributors
f.write('false') if [ "$IN_VERSION" = true ] && [ "$ADDED" = false ]; then
with open('/tmp/content_changed.txt', 'w') as f: echo "" >> "$TEMP_FILE"
f.write('false') echo -e "${NEW_COMMIT_ENTRIES}" >> "$TEMP_FILE"
PYSCRIPT fi
UPDATED=$(cat /tmp/changelog_updated.txt) mv "$TEMP_FILE" CHANGELOG.md
CONTENT_CHANGED=$(cat /tmp/content_changed.txt 2>/dev/null || echo "false") echo "✅ 已追加 ${NEW_COMMIT_COUNT} 个新commits到现有版本"
echo "changelog_updated=$UPDATED" >> $GITHUB_OUTPUT echo "changelog_updated=true" >> $GITHUB_OUTPUT
echo "content_changed=$CONTENT_CHANGED" >> $GITHUB_OUTPUT echo "content_changed=true" >> $GITHUB_OUTPUT
else
echo "️ 所有commits都已存在于CHANGELOG中"
echo " (通常发生在重建已删除的 tag)"
echo " 将从现有内容创建 Release"
if [ "$UPDATED" = "true" ]; then echo "changelog_updated=true" >> $GITHUB_OUTPUT
echo "" echo "content_changed=false" >> $GITHUB_OUTPUT
echo "✅ CHANGELOG 生成完成" fi
else
# 版本不存在 - 添加新版本条目
echo " 添加新版本条目: ${CHANGELOG_VERSION}"
TEMP_FILE=$(mktemp)
# 读取第一行 (CHANGELOG 标题)
head -n 1 CHANGELOG.md > "$TEMP_FILE"
echo "" >> "$TEMP_FILE"
# 插入新条目
echo -e "${NEW_ENTRY}" >> "$TEMP_FILE"
# 追加剩余内容 (从第3行开始,跳过标题后的空行)
tail -n +3 CHANGELOG.md >> "$TEMP_FILE"
mv "$TEMP_FILE" CHANGELOG.md
echo "✅ 已添加新的CHANGELOG条目"
echo "changelog_updated=true" >> $GITHUB_OUTPUT
echo "content_changed=true" >> $GITHUB_OUTPUT
fi
else else
echo "" # CHANGELOG 文件不存在 - 创建新文件
echo "️ 没有有效的提交,跳过 CHANGELOG 更新" echo "📄 创建新的 CHANGELOG.md"
echo "# :memo: CHANGELOG" > CHANGELOG.md
echo "" >> CHANGELOG.md
echo -e "${NEW_ENTRY}" >> CHANGELOG.md
echo "✅ 已创建新的CHANGELOG.md"
echo "changelog_updated=true" >> $GITHUB_OUTPUT
echo "content_changed=true" >> $GITHUB_OUTPUT
fi fi
echo ""
echo "✅ CHANGELOG 生成完成"
echo "======================================" echo "======================================"
echo "" echo ""
@@ -828,10 +983,6 @@ jobs:
id: upload_assets id: upload_assets
if: steps.changelog.outputs.changelog_updated == 'true' if: steps.changelog.outputs.changelog_updated == 'true'
run: | run: |
echo "======================================"
echo "📎 上传 Release 附件"
echo "======================================"
cd ${{ env.REPO_DIR }} cd ${{ env.REPO_DIR }}
echo "🔍 提取 Release ID..." echo "🔍 提取 Release ID..."
@@ -862,19 +1013,6 @@ jobs:
echo "✓ Release ID: $RELEASE_ID" echo "✓ Release ID: $RELEASE_ID"
echo "" echo ""
# 上传 CHANGELOG.md
echo "📤 上传 CHANGELOG.md..."
HTTP_CODE=$(curl -s -o /tmp/upload_response_changelog.json -w "%{http_code}" -X POST \
-H "Authorization: token ${{ env.ACCESS_TOKEN }}" \
-F "attachment=@CHANGELOG.md" \
"${{ github.server_url }}/api/v1/repos/${{ github.repository }}/releases/$RELEASE_ID/assets?name=CHANGELOG.md")
if [ "$HTTP_CODE" = "201" ] || [ "$HTTP_CODE" = "200" ]; then
echo "✅ CHANGELOG.md 上传成功"
else
echo "⚠️ 警告: CHANGELOG.md 上传失败 (HTTP $HTTP_CODE)"
fi
# 上传额外的文件 # 上传额外的文件
if [ -n "${{ env.ADDITIONAL_RELEASE_FILES }}" ]; then if [ -n "${{ env.ADDITIONAL_RELEASE_FILES }}" ]; then
echo "" echo ""
+47
View File
@@ -1,5 +1,52 @@
# CHANGELOG # CHANGELOG
## :bookmark: 0.0.3
### :pencil: What's Changed
- :bug: 移除默认上传`CHANGELOG.md` ([9961226](https://git.mytsl.cn/csh/actions-template/commit/99612267047e4d5c48d55888eeb0d05ba12c5da1)) by @csh
- :recycle: 重构`changelog_and_release.yml` ([1f535e0](https://git.mytsl.cn/csh/actions-template/commit/1f535e0675efe166b5d38f0f0778f40d8663d318)) by @csh
- :bug: 修复commit信息提取错误 ([bf6698a](https://git.mytsl.cn/csh/actions-template/commit/bf6698ab3e7f2020dcee899f6a06166b0e6a5168)) by @csh
- 更新 CHANGELOG.md ([4ed8099](https://git.mytsl.cn/csh/actions-template/commit/4ed8099158f0f753b53a526ccba7dfc7aaad739a)) by @csh
- :bug: fix bug ([fc76a1f](https://git.mytsl.cn/csh/actions-template/commit/fc76a1f625c4c6cb42e50cadb487b7607a8d2f0a)) by @csh
- 更新 CHANGELOG.md [skip ci] ([7373553](https://git.mytsl.cn/csh/actions-template/commit/7373553270d20357a225aaf41334919086f7687d)) by @csh
- :bug: fix bug ([fa21511](https://git.mytsl.cn/csh/actions-template/commit/fa21511d1ab98e415036046bc6950f8a3b322f25)) 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.2
*Released on 2025-11-02*
### :pencil: What's Changed
- :art: 代码格式化 ([`ec5785c`](https://github.com/csh/actions-template/commit/ec5785cc6af3267285623090e19b5c215d89d37f))
- :bug: 修复tag获取错误问题 ([`84e2751`](https://github.com/csh/actions-template/commit/84e275166844d9fd410a7aba3e32807683784970))
- :bug: 修复bug ([`0bb627f`](https://github.com/csh/actions-template/commit/0bb627fd34ce47e2baaf9b3856d12564da2423d9))
- :recycle: 重构`changelog_and_release` ([`9cde246`](https://github.com/csh/actions-template/commit/9cde246b208afe25ac6ecca67ecf4e7ad2e56ecc))
- :bug: 修复日期 ([`aaeed0d`](https://github.com/csh/actions-template/commit/aaeed0d9197af8f9c732ab9e4a2ae5dc99a40c00))
- :bug: 修复`update_state_badge.yml`自动生成的`README`日期错误 ([`f57e698`](https://github.com/csh/actions-template/commit/f57e6984c048f6dbfc5e8083dd68c8910a923487))
- :memo: 更新`WORKFLOW`说明 ([`2ac94af`](https://github.com/csh/actions-template/commit/2ac94aff1c499ca12bbe29652532bd4a8bef425d))
- :bug: help me ([`d7a0c7a`](https://github.com/csh/actions-template/commit/d7a0c7a85b04a3177790a8a74ebb1c5154e136de))
- :bug: 继续修修 ([`948bcfa`](https://github.com/csh/actions-template/commit/948bcfa7875b0276b649851c7445367b13c95438))
- :bug: 继续修复测试 ([`23a7fb5`](https://github.com/csh/actions-template/commit/23a7fb5a285c3f6f16071c82f6ba24137507a10d))
- :bug: 修`update_stats_badge.yml`,还没跑起来 ([`b616573`](https://github.com/csh/actions-template/commit/b616573bfd8374a8b007e8066cfcd053191d9717))
- :bug: 修复`update_stats_badge.yml` 克隆bug ([`5b3629f`](https://github.com/csh/actions-template/commit/5b3629fb732ecfdd78496736f1f861ec0f8d9eee))
- :bug: 修复token配置错误 ([`38e6c82`](https://github.com/csh/actions-template/commit/38e6c823948662e18e60bdc483112a2957352ffb))
- :bug: 修复runs-on错误 ([`376c1a2`](https://github.com/csh/actions-template/commit/376c1a28666378ff11c7d0669a61c4c980ca6261))
- :sparkles: 新增:代码统计徽章 action: `update_stats_badge.yml` ([`d5a7d55`](https://github.com/csh/actions-template/commit/d5a7d5506ec0f7d128c60f908bbd17198308c587))
- :demo: 文档更新 ([`c0aef0f`](https://github.com/csh/actions-template/commit/c0aef0f5316aa0fba1ae5686b8d7cc8c770e816e))
- :package: workflows的文件进行更名,并且调整后缀为`yml` ([`a21adb9`](https://github.com/csh/actions-template/commit/a21adb9fcc79839ddd717f862abe69e7e232fbca))
- :wastebasket: 移除发布Release时候自动上传CHANGELOG.md ([`8971cbf`](https://github.com/csh/actions-template/commit/8971cbffc3023891852a14d9917c8b9b2b7f8272))
---
## :bookmark: 0.0.1 ## :bookmark: 0.0.1
### :pencil: What's Changed ### :pencil: What's Changed