Files
actions-template/.gitea/workflows/update_stats_badge.yml
T
csh 18c4dfa811 🔒 fix(ci): 修复 token 明文插值并加固脚本健壮性
- 安全: curl 的 Authorization 头改用 shell 变量 ${ACCESS_TOKEN},
  避免 secret 经 ${{ }} 明文展开进脚本文本(changelog、stats)
- 修复: stats 分支清理 find 显式排除 .git,与注释一致,
  不再依赖 linked worktree 中 .git 为文件的隐含前提
- 健壮性: echo -e 前用 esc() 转义用户 message/body 中的反斜杠,
  防止字面 \n \t 被误展开破坏 Markdown
- 健壮性: 千分位格式化改用不依赖 locale 的 sed 实现,
  替换 printf "%'d"
- 健壮性: git log 的 range 变量补全引号
- 优化: prepare.yml 的 push 触发限定 main/master 分支与 tag,
  避免其它分支空跑
- 文档: route-release 标注 workflow_run.path 为 Gitea 特有字段
2026-07-21 11:13:52 +08:00

665 lines
26 KiB
YAML
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
name: 📊 代码统计徽章
on:
workflow_run:
workflows: ["🧰 准备环境"]
types:
- completed
concurrency:
group: stats-${{ github.repository }}
cancel-in-progress: false
# ==========================================
# 🔧 配置区域 - 根据你的项目修改
# ==========================================
env:
# ===== Token 配置 =====
# 请在 Settings -> Secrets 中配置 WORKFLOW secret
ACCESS_TOKEN: ${{ secrets.WORKFLOW }}
# ===== 工作区配置 =====
WORKSPACE_ROOT: "/data/workspace"
WORKSPACE_SLOT: "stats"
SOURCE_BRANCH: ${{ github.event.workflow_run.head_branch }}
SOURCE_SHA: ${{ github.event.workflow_run.head_sha }}
# ===== 分支配置 =====
# 徽章数据存储分支(可配置)
BADGE_BRANCH: "stats"
# 徽章文件存储目录
BADGE_DIR: "badges"
# ===== 排除配置 =====
# 全局排除的目录(这些目录会被完全忽略)
EXCLUDE_DIRS: "node_modules,dist,build,out,target,vendor,.venv,venv,__pycache__,.git,.github"
# 特殊包含规则(即使在排除目录中,也统计这些扩展名的文件)
# 格式: 目录:扩展名列表
# 例如: 'dist:js,css' 表示即使 dist 被排除,也统计其中的 .js 和 .css 文件
SPECIAL_INCLUDES: ""
# 示例: 'dist:js,css|vendor:go,mod'
# ===== SVG 徽章颜色配置 =====
COLOR_TOTAL: "blue"
COLOR_FILES: "green"
COLOR_LANGUAGE_COUNT: "purple"
# ===== 输出配置 =====
# 是否输出到 workflow summary
OUTPUT_TO_SUMMARY: "true"
# 最小代码行数阈值(低于此值的语言不生成徽章)
MIN_LINES_THRESHOLD: "10"
# ===== Git 配置 =====
GIT_USER_NAME: "ci[bot]"
GIT_USER_EMAIL: "ci[bot]@tinysoft.com.cn"
# ==========================================
# 🎨 语言分组配置
# 格式: 组名:后缀列表:显示名称:颜色:图标(可选)
# 图标使用 simple-icons 的名称,如 cplusplus, typescript 等
# ==========================================
LANGUAGE_GROUPS: |
cpp:hpp,cpp,cxx,cc,h,c:C/C++:00599C:cplusplus
python:py:Python:3572A5:python
typescript:ts,tsx:TypeScript:3178c6:typescript
javascript:js,jsx:JavaScript:F7DF1E:javascript
java:java:Java:007396:java
go:go:Go:00ADD8:go
rust:rs:Rust:CE412B:rust
shell:sh,bash:Shell:4EAA25:gnubash
yaml:yml,yaml:YAML:CB171E
tsf:tsl,tsf:TSF:9945FF
jobs:
update-stats:
if: ${{ github.event.workflow_run.conclusion == 'success' && (github.event.workflow_run.head_branch == 'main' || github.event.workflow_run.head_branch == 'master') }}
runs-on: standard-ubuntu-22
permissions:
contents: write
steps:
- name: 🔐 验证 Token 配置
id: validate_token
run: |
echo "🔐 验证访问令牌..."
if [ -z "$ACCESS_TOKEN" ]; then
echo "❌ 错误: 未配置访问令牌"
echo "请在 Settings -> Secrets 中配置 WORKFLOW secret"
exit 1
fi
echo "✅ 使用 WORKFLOW secret"
echo "token_type=WORKFLOW" >> $GITHUB_OUTPUT
echo "🔗 仓库: ${{ github.repository }}"
echo "🌿 上游分支: ${{ env.SOURCE_BRANCH }}"
echo "📝 上游提交: ${{ env.SOURCE_SHA }}"
- name: 📥 对齐统计 Worktree
id: prepare_worktree
shell: bash
run: |
set -euo pipefail
for command in git python3 bc flock realpath; do
if ! command -v "$command" >/dev/null 2>&1; then
echo "Prepare 成功后仍缺少统计所需命令: $command" >&2
exit 1
fi
done
REPO_NAME="${{ github.event.repository.name }}"
HEAD_SHA="${{ env.SOURCE_SHA }}"
REPOSITORY_DIR="${WORKSPACE_ROOT}/${REPO_NAME}/repository.git"
WORKTREE_DIR="${WORKSPACE_ROOT}/${REPO_NAME}/worktrees/stats"
WORKTREE_LOCK="${WORKSPACE_ROOT}/${REPO_NAME}/worktree-admin.lock"
case "$HEAD_SHA" in
''|*[!0-9a-fA-F]*)
echo "无效的上游提交 SHA: $HEAD_SHA" >&2
exit 1
;;
esac
if [ ! -d "$REPOSITORY_DIR" ] || \
[ "$(git --git-dir="$REPOSITORY_DIR" rev-parse --is-bare-repository 2>/dev/null)" != "true" ]; then
echo "Prepare 未创建有效共享 bare 仓库: $REPOSITORY_DIR" >&2
exit 1
fi
if ! git --git-dir="$REPOSITORY_DIR" cat-file -e "${HEAD_SHA}^{commit}"; then
echo "共享仓库中不存在上游提交: $HEAD_SHA" >&2
exit 1
fi
if [ ! -f "$WORKTREE_DIR/.git" ]; then
exec 9>"$WORKTREE_LOCK"
flock 9
if [ ! -f "$WORKTREE_DIR/.git" ]; then
if [ -e "$WORKTREE_DIR" ]; then
echo "统计 Worktree 路径已存在但不是 linked worktree: $WORKTREE_DIR" >&2
exit 1
fi
mkdir -p "$(dirname "$WORKTREE_DIR")"
git --git-dir="$REPOSITORY_DIR" worktree add --detach "$WORKTREE_DIR" "$HEAD_SHA"
fi
flock -u 9
fi
common_dir=$(git -C "$WORKTREE_DIR" rev-parse --path-format=absolute --git-common-dir)
if [ "$common_dir" != "$(realpath "$REPOSITORY_DIR")" ]; then
echo "统计 Worktree 不属于共享仓库: $WORKTREE_DIR" >&2
exit 1
fi
git -C "$WORKTREE_DIR" checkout --detach --force "$HEAD_SHA"
git -C "$WORKTREE_DIR" reset --hard "$HEAD_SHA"
git -C "$WORKTREE_DIR" clean -ffdx
actual_sha=$(git -C "$WORKTREE_DIR" rev-parse HEAD)
if [ "$actual_sha" != "$HEAD_SHA" ]; then
echo "统计 Worktree 提交不匹配: 期望 $HEAD_SHA,实际 $actual_sha" >&2
exit 1
fi
git -C "$WORKTREE_DIR" config user.name "${{ env.GIT_USER_NAME }}"
git -C "$WORKTREE_DIR" config user.email "${{ env.GIT_USER_EMAIL }}"
echo "REPOSITORY_DIR=$REPOSITORY_DIR" >> "$GITHUB_ENV"
echo "REPO_DIR=$WORKTREE_DIR" >> "$GITHUB_ENV"
echo "REPO_NAME=$REPO_NAME" >> "$GITHUB_ENV"
echo "统计 Worktree: $WORKTREE_DIR @ $actual_sha"
- name: 🌿 准备统计分支
id: prepare_stats_branch
run: |
set -euo pipefail
REPOSITORY_DIR="${{ env.REPOSITORY_DIR }}"
WORKTREE_DIR="${{ env.REPO_DIR }}"
BADGE_BRANCH="${{ env.BADGE_BRANCH }}"
SOURCE_SHA="${{ env.SOURCE_SHA }}"
if git --git-dir="$REPOSITORY_DIR" show-ref --verify --quiet "refs/remotes/origin/${BADGE_BRANCH}"; then
git -C "$WORKTREE_DIR" checkout --force -B "$BADGE_BRANCH" "refs/remotes/origin/${BADGE_BRANCH}"
echo "branch_exists=true" >> "$GITHUB_OUTPUT"
else
if git --git-dir="$REPOSITORY_DIR" show-ref --verify --quiet "refs/heads/${BADGE_BRANCH}"; then
git -C "$WORKTREE_DIR" branch -D "$BADGE_BRANCH"
fi
echo "branch_exists=false" >> "$GITHUB_OUTPUT"
fi
git -C "$WORKTREE_DIR" checkout --detach --force "$SOURCE_SHA"
- name: 🌱 创建统计分支
if: steps.prepare_stats_branch.outputs.branch_exists == 'false'
run: |
echo "======================================"
echo "🆕 创建新的统计分支"
echo "======================================"
cd "${{ env.REPO_DIR }}"
git rev-parse --is-inside-work-tree >/dev/null
# 创建孤立分支(orphan branch
# 📝 说明:孤立分支与主分支没有共同的提交历史,适合存储独立的数据
echo "🌱 创建孤立分支..."
git checkout --orphan "${{ env.BADGE_BRANCH }}"
# 🧹 清空所有文件(但保留 .git 目录)
# ❓ 为什么要删除?
# - stats 分支是独立的数据存储分支,不需要主分支的代码文件
# - 只需要存储徽章 JSON 文件和统计报告
# - 保持分支干净,避免混淆
#
# ✅ 能否复用仓库?
# - 可以!.git 目录包含所有分支的完整信息
# - 切换到主分支时,主分支的文件会恢复
# - 各分支独立,互不影响
echo "🧹 清理文件(保护 .git 和 .gitea..."
# 步骤 1: 使用 git rm 清理已跟踪的文件
git rm -rf . 2>/dev/null || true
# 步骤 2: 安全地删除剩余文件
# 使用更严格的保护,确保不会误删 .git
echo "🔍 查找需要删除的文件..."
find . -maxdepth 1 -type f ! -name '.git' ! -name '.gitignore' -delete 2>/dev/null || true
find . -maxdepth 1 -type d ! -name '.' ! -name '..' ! -name '.git' ! -name '.gitea' -exec rm -rf {} + 2>/dev/null || true
# 🔴 最终检查:确认 .git 仍然完好
echo "🔍 最终检查..."
git rev-parse --is-inside-work-tree >/dev/null
echo "✓ .git 目录完好"
echo "✓ 文件清理完成"
echo ""
# 创建初始 README
cat > README.md << 'EOF'
# 📊 代码统计徽章数据
> 此分支由 Gitea Actions 自动生成和维护
>
> ⚠️ **请勿手动修改此分支的内容!**
## 📁 目录结构
```
README.md # 详细统计报告
badges/
├── total-lines.svg # 总代码行数徽章
├── total-files.svg # 总文件数徽章
├── language-count.svg # 语言种类徽章
└── {language}-lines.svg # 各语言代码行数徽章
```
## 🔄 更新机制
- ✅ 主分支的 Prepare 成功后自动更新
- ✅ 可在 main/master 上手动运行 Prepare
## 📊 数据来源
所有统计数据基于主分支的最新代码自动生成。
---
*🤖 由 Gitea Actions 自动维护*
EOF
# 创建徽章目录
mkdir -p "${{ env.BADGE_DIR }}"
# 添加并提交
git add .
git commit -m ":bar_chart: chore(stats): 初始化统计分支"
# 推送到远程
git -C "${{ env.REPO_DIR }}" \
-c credential.helper= \
-c 'credential.helper=!f() { test "$1" = get || exit 0; printf "%s\n" username=oauth2; printf "%s\n" "password=${ACCESS_TOKEN}"; }; f' \
-c credential.interactive=never \
push origin "${{ env.BADGE_BRANCH }}"
echo "✅ 统计分支创建完成"
echo "======================================"
echo ""
echo "🔄 返回上游提交: ${{ env.SOURCE_SHA }}"
git checkout --detach --force "${{ env.SOURCE_SHA }}"
echo "✓ 已返回上游提交"
echo ""
- name: 📊 统计总代码量
id: total
run: |
echo "======================================"
echo "📊 统计总代码量"
echo "======================================"
cd "${{ env.REPO_DIR }}"
ACTUAL_SHA=$(git rev-parse HEAD)
if [ "$ACTUAL_SHA" != "${{ env.SOURCE_SHA }}" ]; then
echo "源码 Worktree 不在上游提交: 期望 ${{ env.SOURCE_SHA }},实际 $ACTUAL_SHA" >&2
exit 1
fi
# 构建排除参数
EXCLUDE_FIND_ARGS=()
IFS=',' read -ra EXCLUDES <<< "${{ env.EXCLUDE_DIRS }}"
for dir in "${EXCLUDES[@]}"; do
EXCLUDE_FIND_ARGS+=(-not -path "*/$dir/*")
done
# 获取所有文件
echo "🔍 扫描文件..."
# 统计总文件数
TOTAL_FILES=$(find . -type f "${EXCLUDE_FIND_ARGS[@]}" | wc -l)
# 统计总代码行数(排除空行)
TOTAL_CODE=$(find . -type f "${EXCLUDE_FIND_ARGS[@]}" -exec grep -cHv '^[[:space:]]*$' {} + 2>/dev/null | awk -F: '{sum+=$2} END {print sum+0}')
echo "📊 统计结果:"
echo " - 总文件数: $TOTAL_FILES"
echo " - 总代码行: $TOTAL_CODE"
# 格式化数字(添加千分位)
# 用 sed 手工加千分位,避免依赖 localeprintf "%'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
echo "total_code=$TOTAL_CODE" >> $GITHUB_OUTPUT
echo "formatted_files=$FORMATTED_FILES" >> $GITHUB_OUTPUT
echo "formatted_code=$FORMATTED_CODE" >> $GITHUB_OUTPUT
echo "======================================"
echo ""
- name: 📋 统计各语言代码量
id: languages
run: |
echo "======================================"
echo "📋 统计各语言代码量"
echo "======================================"
cd "${{ env.REPO_DIR }}"
ACTUAL_SHA=$(git rev-parse HEAD)
if [ "$ACTUAL_SHA" != "${{ env.SOURCE_SHA }}" ]; then
echo "源码 Worktree 不在上游提交: 期望 ${{ env.SOURCE_SHA }},实际 $ACTUAL_SHA" >&2
exit 1
fi
# 创建临时目录
mkdir -p /tmp/lang_stats
# 用 sed 手工加千分位,避免依赖 localeprintf "%'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 }}"
for dir in "${EXCLUDES[@]}"; do
EXCLUDE_FIND_ARGS+=(-not -path "*/$dir/*")
done
LANGUAGE_COUNT=0
# 读取语言配置并统计
echo "${{ env.LANGUAGE_GROUPS }}" | while IFS= read -r line; do
[ -z "$line" ] && continue
# 解析配置行: 组名:后缀列表:显示名称:颜色:图标
IFS=':' read -r lang_id extensions display_name color icon <<< "$line"
echo "🔍 统计 $display_name..."
# 构建扩展名查找条件
LANG_FIND_ARGS=()
IFS=',' read -ra EXTS <<< "$extensions"
for ext in "${EXTS[@]}"; do
if [ "${#LANG_FIND_ARGS[@]}" -eq 0 ]; then
LANG_FIND_ARGS+=(-name "*.$ext")
else
LANG_FIND_ARGS+=(-o -name "*.$ext")
fi
done
# 统计文件数
FILE_COUNT=$(find . -type f \( "${LANG_FIND_ARGS[@]}" \) "${EXCLUDE_FIND_ARGS[@]}" | wc -l)
if [ "$FILE_COUNT" -gt 0 ]; then
# 统计代码行数
CODE_LINES=$(find . -type f \( "${LANG_FIND_ARGS[@]}" \) "${EXCLUDE_FIND_ARGS[@]}" -exec grep -cHv '^[[:space:]]*$' {} + 2>/dev/null | awk -F: '{sum+=$2} END {print sum+0}')
# 只保存超过阈值的语言
if [ "$CODE_LINES" -ge "${{ env.MIN_LINES_THRESHOLD }}" ]; then
FORMATTED_LINES=$(add_thousands "$CODE_LINES")
echo " - 文件数: $FILE_COUNT"
echo " - 代码行: $FORMATTED_LINES"
# 保存到临时文件
echo "$lang_id|$display_name|$CODE_LINES|$FORMATTED_LINES|$FILE_COUNT|$color|$icon" >> /tmp/lang_stats/${lang_id}.txt
LANGUAGE_COUNT=$((LANGUAGE_COUNT + 1))
else
echo " ⏩ 跳过(少于 ${{ env.MIN_LINES_THRESHOLD }} 行)"
fi
else
echo " ⏩ 未找到文件"
fi
echo ""
done
# 汇总所有语言数据
cat /tmp/lang_stats/*.txt 2>/dev/null | sort -t'|' -k3 -nr > /tmp/lang_summary.txt || touch /tmp/lang_summary.txt
# 计算实际找到的语言数
ACTUAL_COUNT=$(wc -l < /tmp/lang_summary.txt)
echo "language_count=$ACTUAL_COUNT" >> $GITHUB_OUTPUT
echo "✅ 找到 $ACTUAL_COUNT 种语言"
echo "======================================"
echo ""
- name: 🎨 生成 SVG 徽章与统计报告
id: generate_badges
run: |
echo "======================================"
echo "🎨 生成 SVG 徽章与统计报告"
echo "======================================"
cd "${{ env.REPO_DIR }}"
# 在上游提交渲染产物,避免依赖 stats 分支中的脚本文件
git checkout --detach --force "${{ env.SOURCE_SHA }}"
RENDER_ROOT=$(mktemp -d)
UPDATED_AT=$(date -u '+%Y-%m-%d %H:%M:%S UTC')
python3 .gitea/ci/render_stats_svgs.py \
--output-dir "$RENDER_ROOT/${{ env.BADGE_DIR }}" \
--readme-path "$RENDER_ROOT/README.md" \
--repo "${{ github.repository }}" \
--generated-by "Gitea Actions" \
--updated-at "$UPDATED_AT" \
--total-color "${{ env.COLOR_TOTAL }}" \
--files-color "${{ env.COLOR_FILES }}" \
--language-count-color "${{ env.COLOR_LANGUAGE_COUNT }}" \
--total-code "${{ steps.total.outputs.total_code }}" \
--formatted-total-code "${{ steps.total.outputs.formatted_code }}" \
--total-files "${{ steps.total.outputs.total_files }}" \
--formatted-total-files "${{ steps.total.outputs.formatted_files }}" \
--language-count "${{ steps.languages.outputs.language_count }}" \
--exclude-dirs "${{ env.EXCLUDE_DIRS }}" \
--min-lines-threshold "${{ env.MIN_LINES_THRESHOLD }}" \
--lang-summary /tmp/lang_summary.txt
git checkout --force "${{ env.BADGE_BRANCH }}"
rm -rf "${{ env.BADGE_DIR }}"
mkdir -p "${{ env.BADGE_DIR }}"
cp -f "$RENDER_ROOT/README.md" README.md
cp -f "$RENDER_ROOT/${{ env.BADGE_DIR }}"/* "${{ env.BADGE_DIR }}/"
GENERATED_COUNT=$(find "$RENDER_ROOT/${{ env.BADGE_DIR }}" -maxdepth 1 -type f | wc -l | tr -d ' ')
rm -rf "$RENDER_ROOT"
echo ""
echo "generated_count=$GENERATED_COUNT" >> $GITHUB_OUTPUT
echo "✅ 已生成 $GENERATED_COUNT 个 SVG 徽章"
echo "======================================"
echo ""
- name: 📤 提交并推送到统计分支
id: commit
run: |
echo "======================================"
echo "📤 提交并推送更新"
echo "======================================"
cd "${{ env.REPO_DIR }}"
# 确保在统计分支
git checkout ${{ env.BADGE_BRANCH }}
# 配置 Git 用户信息
git config user.name "${{ env.GIT_USER_NAME }}"
git config user.email "${{ env.GIT_USER_EMAIL }}"
# 添加所有更改
git add README.md ${{ env.BADGE_DIR }}/
# 检查是否有变更
if git diff --staged --quiet; then
echo "📌 没有变更,跳过提交"
echo "changed=false" >> $GITHUB_OUTPUT
echo ""
else
echo "📝 准备提交..."
# 生成提交信息
COMMIT_MSG=":bar_chart: chore(stats): 更新代码统计 [$(date '+%Y-%m-%d %H:%M')]
📊 统计摘要:
- 总代码: ${{ steps.total.outputs.formatted_code }} 行
- 总文件: ${{ steps.total.outputs.formatted_files }} 个
- 语言数: ${{ steps.languages.outputs.language_count }} 种
- 徽章数: ${{ steps.generate_badges.outputs.generated_count }} 个
🔗 触发提交: ${{ env.SOURCE_SHA }}
🤖 由 Gitea Actions 自动生成"
git commit -m "$COMMIT_MSG"
echo "📤 推送到远程 ${{ env.BADGE_BRANCH }} 分支..."
# 推送到远程(使用 TOKEN)
if git -C "${{ env.REPO_DIR }}" \
-c credential.helper= \
-c 'credential.helper=!f() { test "$1" = get || exit 0; printf "%s\n" username=oauth2; printf "%s\n" "password=${ACCESS_TOKEN}"; }; f' \
-c credential.interactive=never \
push origin "${{ env.BADGE_BRANCH }}"; then
echo "✅ 推送成功"
echo "changed=true" >> $GITHUB_OUTPUT
else
echo "❌ 推送失败"
exit 1
fi
fi
echo "======================================"
echo ""
- name: 📋 生成 Workflow Summary
if: env.OUTPUT_TO_SUMMARY == 'true' && success()
run: |
cat >> $GITHUB_STEP_SUMMARY << 'EOFSUMMARY'
# 📊 代码统计完成
## ✅ 执行结果
| 项目 | 结果 |
|------|------|
| 🔐 Token 类型 | **${{ steps.validate_token.outputs.token_type }}** |
| 🌿 来源分支 | `${{ env.SOURCE_BRANCH }}` |
| 📝 来源提交 | `${{ env.SOURCE_SHA }}` |
| 📊 总代码行数 | **${{ steps.total.outputs.formatted_code }}** 行 |
| 📁 总文件数 | **${{ steps.total.outputs.formatted_files }}** 个 |
| 🌐 语言种类 | **${{ steps.languages.outputs.language_count }}** 种 |
| 🎨 生成徽章 | **${{ steps.generate_badges.outputs.generated_count }}** 个 |
| 📤 提交状态 | ${{ steps.commit.outputs.changed == 'true' && '✅ 已更新' || '📌 无变更' }} |
## 🔗 快速链接
- 📊 [查看详细统计报告](${GITHUB_SERVER_URL}/${GITHUB_REPOSITORY}/src/branch/${{ env.BADGE_BRANCH }}/README.md)
- 🎨 [浏览徽章文件](${GITHUB_SERVER_URL}/${GITHUB_REPOSITORY}/src/branch/${{ env.BADGE_BRANCH }}/${{ env.BADGE_DIR }})
- 🔧 [查看 Workflow 配置](${GITHUB_SERVER_URL}/${GITHUB_REPOSITORY}/src/branch/${{ env.SOURCE_BRANCH }}/.gitea/workflows/update_stats_badge.yml)
## 📝 语言分布
EOFSUMMARY
# 添加语言分布表格
if [ -f /tmp/lang_summary.txt ] && [ -s /tmp/lang_summary.txt ]; then
cat >> $GITHUB_STEP_SUMMARY << 'EOFTABLE'
| 语言 | 代码行数 | 文件数 | 占比 |
|------|----------|--------|------|
EOFTABLE
TOTAL_CODE=${{ steps.total.outputs.total_code }}
sort -t'|' -k3 -nr /tmp/lang_summary.txt | head -10 | while IFS='|' read -r lang_id display_name code_lines formatted_lines file_count color icon; do
[ -z "$lang_id" ] && continue
if [ "$TOTAL_CODE" -gt 0 ]; then
PERCENT=$(echo "scale=1; $code_lines * 100 / $TOTAL_CODE" | bc)
else
PERCENT="0.0"
fi
echo "| **${display_name}** | ${formatted_lines} | ${file_count} | ${PERCENT}% |" >> $GITHUB_STEP_SUMMARY
done
else
echo "" >> $GITHUB_STEP_SUMMARY
echo "> ⚠️ 未找到符合条件的语言文件" >> $GITHUB_STEP_SUMMARY
fi
# 添加工作区信息
cat >> $GITHUB_STEP_SUMMARY << 'EOFWS'
## 📂 工作区信息
| 项目 | 值 |
|------|-----|
| 📁 仓库名称 | `${{ env.REPO_NAME }}` |
| 📍 工作目录 | `${{ env.REPO_DIR }}` |
| 🌿 统计分支 | `${{ env.BADGE_BRANCH }}` |
| 📂 徽章目录 | `${{ env.BADGE_DIR }}` |
EOFWS
echo "" >> $GITHUB_STEP_SUMMARY
echo "---" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "*⏱️ 执行时间: $(date '+%Y-%m-%d %H:%M:%S %Z')*" >> $GITHUB_STEP_SUMMARY
- name: 💡 输出使用说明
if: success()
run: |
echo "================================================"
echo "✅ 代码统计任务执行完成!"
echo "================================================"
echo ""
echo "🔐 Token 信息:"
echo " - 使用: ${{ steps.validate_token.outputs.token_type }}"
echo ""
# 根据实际结果输出
if [ "${{ steps.commit.outputs.changed }}" == "true" ]; then
echo "📊 统计结果:"
echo " - 总代码: ${{ steps.total.outputs.formatted_code }} 行"
echo " - 总文件: ${{ steps.total.outputs.formatted_files }} 个"
echo " - 语言数: ${{ steps.languages.outputs.language_count }} 种"
echo " - 徽章数: ${{ steps.generate_badges.outputs.generated_count }} 个"
echo ""
echo "📤 已推送更新到分支: ${{ env.BADGE_BRANCH }}"
else
echo "📌 统计数据无变更,未产生新的提交"
fi
echo ""
echo "📂 工作区信息:"
echo " - 仓库目录: ${{ env.REPO_DIR }}"
echo " - 统计分支: ${{ env.BADGE_BRANCH }}"
echo ""
echo "🔗 查看详细报告:"
echo " ${GITHUB_SERVER_URL}/${GITHUB_REPOSITORY}/src/branch/${{ env.BADGE_BRANCH }}/README.md"
echo ""
echo "🎨 徽章目录:"
echo " ${GITHUB_SERVER_URL}/${GITHUB_REPOSITORY}/src/branch/${{ env.BADGE_BRANCH }}/${{ env.BADGE_DIR }}"
echo ""
echo "================================================"
if [ "${{ steps.languages.outputs.language_count }}" == "0" ]; then
echo ""
echo "⚠️ 警告: 未找到符合条件的语言文件"
echo " 请检查 LANGUAGE_GROUPS 配置和 MIN_LINES_THRESHOLD 设置"
fi
- name: 🧹 清理工作区
if: always()
run: |
echo "🧹 清理临时文件..."
rm -rf /tmp/lang_stats /tmp/lang_summary.txt
echo "✅ 清理完成"