diff --git a/.gitea/workflows/changelog_and_release.yml b/.gitea/workflows/changelog_and_release.yml index e7de56f..524f137 100644 --- a/.gitea/workflows/changelog_and_release.yml +++ b/.gitea/workflows/changelog_and_release.yml @@ -129,6 +129,9 @@ env: jobs: route-release: + # ⚠️ 依赖 Gitea 特有的 workflow_run.path 字段格式(形如 "@refs/tags/") + # 该字段非 GitHub Actions 标准,若 Gitea 升级改变其格式,发布会静默不触发。 + # 已在 Gitea 1.22 上验证;升级后请复核此判据,必要时增加 fallback。 if: ${{ github.event.workflow_run.conclusion == 'success' && contains(github.event.workflow_run.path, '@refs/tags/') }} runs-on: standard-ubuntu-22 permissions: @@ -526,7 +529,7 @@ jobs: echo "🔍 扫描提交记录..." TEMP_COMMITS=$(mktemp) - 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 "$COMMIT_RANGE" --no-merges --reverse --format="COMMIT_START%n%H%n%an%n%s%nBODY_START%n%b%nBODY_END" > "$TEMP_COMMITS" declare -a COMMITS_HASH declare -a COMMITS_AUTHOR @@ -647,6 +650,10 @@ jobs: REPO_URL="${{ github.server_url }}/${{ github.repository }}" # 初始化条目内容 + # 转义用户内容中的反斜杠,避免后续 echo -e 误展开 message/body 里的 + # 字面 \n \t \\ 等序列(我们自己插入的 \n 分隔符不经过此函数,仍正常换行) + esc() { printf '%s' "$1" | sed 's/\\/\\\\/g'; } + NEW_ENTRY="## :bookmark: ${CHANGELOG_VERSION}\n\n" NEW_ENTRY="${NEW_ENTRY}${CHANGELOG_SECTION_TITLE}\n\n" @@ -654,10 +661,10 @@ jobs: for ((i=0; i<$VALID_COUNT; i++)); do hash="${COMMITS_HASH[$i]}" author="${COMMITS_AUTHOR[$i]}" - message="${COMMITS_MESSAGE[$i]}" + message=$(esc "${COMMITS_MESSAGE[$i]}") body="${COMMITS_BODY[$i]}" - echo " [$((i+1))/$VALID_COUNT] ${hash:0:7}: ${message:0:60}..." + echo " [$((i+1))/$VALID_COUNT] ${hash:0:7}: ${COMMITS_MESSAGE[$i]:0:60}..." # 构建提交链接 - 使用短 hash 格式 short_hash="${hash:0:7}" @@ -671,8 +678,9 @@ jobs: # 处理 body (如果存在) if [ -n "$body" ]; then - # 移除首尾空行 + # 移除首尾空行,并转义反斜杠 cleaned_body=$(echo "$body" | sed -e :a -e '/^\s*$/d;') + cleaned_body=$(esc "$cleaned_body") if [ -n "$cleaned_body" ]; then # 有 body: 主题在第一行,body 内容缩进显示,链接和作者放在一起 @@ -709,7 +717,7 @@ jobs: grep -vxF "${{ env.GIT_USER_NAME }}" | \ sort -u) 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 "dependabot\[bot\]" | \ grep -v "renovate\[bot\]" | \ @@ -782,7 +790,7 @@ jobs: # 这是一个新的 commit,添加它 author="${COMMITS_AUTHOR[$i]}" - message="${COMMITS_MESSAGE[$i]}" + message=$(esc "${COMMITS_MESSAGE[$i]}") body="${COMMITS_BODY[$i]}" COMMIT_LINK="([${short_hash}](${REPO_URL}/commit/${hash}))" @@ -795,6 +803,7 @@ jobs: if [ -n "$body" ]; then cleaned_body=$(echo "$body" | sed -e :a -e '/^\s*$/d;') + cleaned_body=$(esc "$cleaned_body") if [ -n "$cleaned_body" ]; then NEW_COMMIT_ENTRIES="${NEW_COMMIT_ENTRIES}- ${message} \n" while IFS= read -r line; do @@ -962,7 +971,7 @@ jobs: echo "📊 增量范围: $RELEASE_NOTES_RANGE" TEMP_COMMITS=$(mktemp) - git log $RELEASE_NOTES_RANGE --no-merges --reverse \ + 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" declare -a COMMITS_HASH @@ -1029,11 +1038,14 @@ jobs: VALID_COUNT=$COMMIT_INDEX echo "✅ 增量有效提交: $VALID_COUNT" + # 转义用户内容中的反斜杠,避免后续 echo -e 误展开 message/body 里的字面序列 + esc() { printf '%s' "$1" | sed 's/\\/\\\\/g'; } + 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]}" + message=$(esc "${COMMITS_MESSAGE[$i]}") body="${COMMITS_BODY[$i]}" short_hash="${hash:0:7}" COMMIT_LINK="([${short_hash}](${REPO_URL}/commit/${hash}))" @@ -1042,6 +1054,7 @@ jobs: if [ -n "$body" ]; then cleaned_body=$(echo "$body" | sed -e :a -e '/^\s*$/d;') + cleaned_body=$(esc "$cleaned_body") else cleaned_body="" fi @@ -1062,7 +1075,7 @@ jobs: 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) + CONTRIBUTORS=$(git log "$RELEASE_NOTES_RANGE" --pretty=format:"%an" --no-merges) fi CONTRIBUTORS=$(echo "$CONTRIBUTORS" | \ grep -v "github-actions\[bot\]" | \ @@ -1126,7 +1139,7 @@ jobs: echo "🌐 发送 API 请求..." HTTP_CODE=$(curl -s -o /tmp/release_response.json -w "%{http_code}" -X POST \ - -H "Authorization: token ${{ env.ACCESS_TOKEN }}" \ + -H "Authorization: token ${ACCESS_TOKEN}" \ -H "Content-Type: application/json" \ -d @/tmp/payload.json \ "${{ github.server_url }}/api/v1/repos/${{ github.repository }}/releases") @@ -1192,7 +1205,7 @@ jobs: if [ -f "$file" ]; then echo "📤 [$FILE_INDEX/$TOTAL_FILES] 上传 $(basename $file)..." HTTP_CODE=$(curl -s -o /tmp/upload_response_${FILE_INDEX}.json -w "%{http_code}" -X POST \ - -H "Authorization: token ${{ env.ACCESS_TOKEN }}" \ + -H "Authorization: token ${ACCESS_TOKEN}" \ -F "attachment=@${file}" \ "${{ github.server_url }}/api/v1/repos/${{ github.repository }}/releases/$RELEASE_ID/assets?name=$(basename $file)") diff --git a/.gitea/workflows/prepare.yml b/.gitea/workflows/prepare.yml index c15134e..0524960 100644 --- a/.gitea/workflows/prepare.yml +++ b/.gitea/workflows/prepare.yml @@ -2,6 +2,14 @@ name: 🧰 准备环境 on: push: + # 仅在主分支和 tag 上触发。 + # 下游 stats 只在 main/master 运行、changelog 只在 tag 运行, + # 其它分支(含 ci bot 推送的 stats 分支)跑 Prepare 纯属空耗,故在此过滤。 + branches: + - main + - master + tags: + - "**" workflow_dispatch: concurrency: diff --git a/.gitea/workflows/update_stats_badge.yml b/.gitea/workflows/update_stats_badge.yml index 051cb9e..a4b02ec 100644 --- a/.gitea/workflows/update_stats_badge.yml +++ b/.gitea/workflows/update_stats_badge.yml @@ -85,7 +85,7 @@ jobs: run: | echo "🔐 验证访问令牌..." - if [ -z "${{ env.ACCESS_TOKEN }}" ]; then + if [ -z "$ACCESS_TOKEN" ]; then echo "❌ 错误: 未配置访问令牌" echo "请在 Settings -> Secrets 中配置 WORKFLOW secret" exit 1 @@ -230,7 +230,7 @@ jobs: # 使用更严格的保护,确保不会误删 .git echo "🔍 查找需要删除的文件..." find . -maxdepth 1 -type f ! -name '.git' ! -name '.gitignore' -delete 2>/dev/null || true - find . -maxdepth 1 -type d ! -name '.' ! -name '..' ! -name '.gitea' -exec rm -rf {} + 2>/dev/null || true + find . -maxdepth 1 -type d ! -name '.' ! -name '..' ! -name '.git' ! -name '.gitea' -exec rm -rf {} + 2>/dev/null || true # 🔴 最终检查:确认 .git 仍然完好 echo "🔍 最终检查..." @@ -331,8 +331,10 @@ jobs: echo " - 总代码行: $TOTAL_CODE" # 格式化数字(添加千分位) - FORMATTED_FILES=$(printf "%'d" $TOTAL_FILES) - FORMATTED_CODE=$(printf "%'d" $TOTAL_CODE) + # 用 sed 手工加千分位,避免依赖 locale(printf "%'d" 在 C/POSIX locale 下失效) + add_thousands() { printf '%s' "$1" | sed -E ':a;s/([0-9])([0-9]{3})($|[^0-9])/\1,\2\3/;ta'; } + FORMATTED_FILES=$(add_thousands "$TOTAL_FILES") + FORMATTED_CODE=$(add_thousands "$TOTAL_CODE") # 输出到环境变量 echo "total_files=$TOTAL_FILES" >> $GITHUB_OUTPUT @@ -361,6 +363,9 @@ jobs: # 创建临时目录 mkdir -p /tmp/lang_stats + # 用 sed 手工加千分位,避免依赖 locale(printf "%'d" 在 C/POSIX locale 下失效) + add_thousands() { printf '%s' "$1" | sed -E ':a;s/([0-9])([0-9]{3})($|[^0-9])/\1,\2\3/;ta'; } + # 构建排除参数 EXCLUDE_FIND_ARGS=() IFS=',' read -ra EXCLUDES <<< "${{ env.EXCLUDE_DIRS }}" @@ -399,7 +404,7 @@ jobs: # 只保存超过阈值的语言 if [ "$CODE_LINES" -ge "${{ env.MIN_LINES_THRESHOLD }}" ]; then - FORMATTED_LINES=$(printf "%'d" $CODE_LINES) + FORMATTED_LINES=$(add_thousands "$CODE_LINES") echo " - 文件数: $FILE_COUNT" echo " - 代码行: $FORMATTED_LINES"