新增:代码统计徽章 action: `update_stats_badge.yml`
Update Stats Badege / update-stats (push) Waiting to run Details
Hello from ImmortalWrt / say-hello (push) Successful in 0s Details

📝 新增:`update_stats_badge`的简要说明
This commit is contained in:
csh 2025-11-02 20:35:04 +08:00
parent c0aef0f531
commit d5a7d5506e
2 changed files with 960 additions and 0 deletions

View File

@ -0,0 +1,929 @@
name: Update Stats Badege
on:
push:
branches: [main, master]
workflow_dispatch:
# ==========================================
# 🔧 配置区域 - 根据你的项目修改
# ==========================================
env:
# ===== Token 配置 =====
# 优先使用 STATS_TOKEN不存在则使用 GITHUB_TOKEN
# 建议在 Settings -> Secrets 中配置 STATS_TOKEN 以获得更好的权限控制
ACCESS_TOKEN: ${{ secrets.STATS_TOKEN }}
# ===== 工作区配置 =====
# 完整克隆的工作目录
WORKSPACE_DIR: '/home/workspace/'
# ===== 分支配置 =====
# 徽章数据存储分支(可配置)
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'
# ===== 徽章颜色配置 =====
COLOR_TOTAL: 'blue'
COLOR_FILES: 'green'
COLOR_DEFAULT: 'brightgreen'
# ===== 徽章样式配置 =====
BADGE_STYLE: 'flat' # 可选: flat, flat-square, plastic, for-the-badge, social
# ===== 输出配置 =====
# 是否生成详细报告
GENERATE_DETAILED_REPORT: 'true'
# 是否输出到 workflow summary
OUTPUT_TO_SUMMARY: 'true'
# 最小代码行数阈值(低于此值的语言不生成徽章)
MIN_LINES_THRESHOLD: '10'
# ===== Git 配置 =====
GIT_USER_NAME: 'github-actions[bot]'
GIT_USER_EMAIL: 'github-actions[bot]@users.noreply.github.com'
# ==========================================
# 🎨 语言分组配置
# 格式: 组名:后缀列表:显示名称:颜色:图标(可选)
# 图标使用 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:
runs-on: ubuntu-latest
permissions:
contents: write
steps:
- name: 🔍 验证 Token 配置
id: validate_token
run: |
echo "🔐 验证访问令牌..."
if [ -z "${{ env.ACCESS_TOKEN }}" ]; then
echo "❌ 错误: 未配置访问令牌"
echo "请在 Settings -> Secrets 中配置 STATS_TOKEN 或确保 GITHUB_TOKEN 可用"
exit 1
fi
# 检测使用的是哪个 token
if [ -n "${{ secrets.STATS_TOKEN }}" ]; then
echo "✅ 使用自定义 STATS_TOKEN"
echo "token_type=STATS_TOKEN" >> $GITHUB_OUTPUT
else
echo "✅ 使用默认 GITHUB_TOKEN"
echo "token_type=GITHUB_TOKEN" >> $GITHUB_OUTPUT
fi
echo "🔗 仓库: ${{ github.repository }}"
echo "🌿 分支: ${{ github.ref_name }}"
echo "📝 提交: ${GITHUB_SHA:0:7}"
- name: 📥 克隆主仓库(完整模式)
id: clone_main
run: |
echo "======================================"
echo "🚀 开始克隆主仓库"
echo "======================================"
REPO_NAME="${{ github.event.repository.name }}"
REPO_DIR="${{ env.WORKSPACE_DIR }}/$REPO_NAME"
echo "📁 仓库名称: $REPO_NAME"
echo "📍 目标目录: $REPO_DIR"
echo "🌐 服务器: ${GITHUB_SERVER_URL}"
echo ""
# 清理旧的工作目录
if [ -d "$REPO_DIR" ]; then
echo "🧹 清理已存在的目录..."
rm -rf "$REPO_DIR"
fi
# 创建工作目录
mkdir -p "${{ env.WORKSPACE_DIR }}"
# 克隆仓库(使用 TOKEN
echo "📥 克隆仓库..."
git clone \
--depth 0 \
--single-branch \
--branch ${{ github.ref_name }} \
https://oauth2:${{ env.ACCESS_TOKEN }}@${GITHUB_SERVER_URL#https://}/${{ github.repository }}.git \
"$REPO_DIR"
if [ $? -ne 0 ]; then
echo "❌ 克隆失败"
exit 1
fi
cd "$REPO_DIR"
echo "✅ 仓库克隆成功"
echo ""
# 配置 Git 用户信息
echo "⚙️ 配置 Git 用户信息..."
git config user.name "${{ env.GIT_USER_NAME }}"
git config user.email "${{ env.GIT_USER_EMAIL }}"
# 显示仓库信息
echo "📊 仓库信息:"
echo " - 当前分支: $(git branch --show-current)"
echo " - 最新提交: $(git log -1 --oneline)"
echo " - 远程地址: $(git remote get-url origin | sed 's/oauth2:.*@/oauth2:***@/')"
echo ""
# 导出环境变量
echo "REPO_DIR=$REPO_DIR" >> $GITHUB_ENV
echo "REPO_NAME=$REPO_NAME" >> $GITHUB_ENV
echo "✅ 主仓库准备完成"
echo "======================================"
echo ""
- name: 🔧 准备统计分支
id: prepare_stats_branch
run: |
echo "======================================"
echo "🔧 准备统计分支"
echo "======================================"
cd "${{ env.REPO_DIR }}"
# 获取所有远程分支
git fetch origin --prune
# 检查统计分支是否存在
if git ls-remote --heads origin ${{ env.BADGE_BRANCH }} | grep -q ${{ env.BADGE_BRANCH }}; then
echo "✅ 统计分支 '${{ env.BADGE_BRANCH }}' 已存在"
# 检出统计分支
git fetch origin ${{ env.BADGE_BRANCH }}:${{ env.BADGE_BRANCH }}
git checkout ${{ env.BADGE_BRANCH }}
echo "📂 当前分支内容:"
ls -la
# 返回主分支
git checkout ${{ github.ref_name }}
echo "branch_exists=true" >> $GITHUB_OUTPUT
else
echo "🆕 统计分支 '${{ env.BADGE_BRANCH }}' 不存在,将创建"
echo "branch_exists=false" >> $GITHUB_OUTPUT
fi
echo "======================================"
echo ""
- name: 🆕 创建统计分支(如需要)
if: steps.prepare_stats_branch.outputs.branch_exists == 'false'
run: |
echo "======================================"
echo "🆕 创建新的统计分支"
echo "======================================"
cd "${{ env.REPO_DIR }}"
# 创建孤立分支
git checkout --orphan ${{ env.BADGE_BRANCH }}
# 清空所有文件
git rm -rf . 2>/dev/null || true
rm -rf * .* 2>/dev/null || true
# 创建初始 README
cat > README.md << 'EOF'
# 📊 代码统计徽章数据
> 此分支由 GitHub Actions 自动生成和维护
>
> ⚠️ **请勿手动修改此分支的内容!**
## 📁 目录结构
```
badges/
├── total-lines.json # 总代码行数徽章
├── total-files.json # 总文件数徽章
├── {language}-lines.json # 各语言代码行数徽章
├── {language}-files.json # 各语言文件数徽章
└── README.md # 详细统计报告
```
## 🔄 更新机制
- ✅ 每次 push 到主分支时自动更新
- ✅ 每天 UTC 02:00 定时更新
- ✅ 可通过 workflow_dispatch 手动触发
## 📊 数据来源
统计数据由 [cloc](https://github.com/AlDanial/cloc) 工具生成,包含以下信息:
- 代码行数(不含注释和空行)
- 文件数量
- 各编程语言占比
## 🎨 徽章使用
请查看 `badges/README.md` 获取详细的徽章使用说明。
---
*🤖 自动生成于: $(date -u '+%Y-%m-%d %H:%M:%S UTC')*
EOF
# 添加并提交
git add README.md
git commit -m "chore: 初始化统计分支 ${{ env.BADGE_BRANCH }}"
# 推送到远程
echo "📤 推送到远程..."
git push https://oauth2:${{ env.ACCESS_TOKEN }}@${GITHUB_SERVER_URL#https://}/${{ github.repository }}.git ${{ env.BADGE_BRANCH }}
if [ $? -eq 0 ]; then
echo "✅ 统计分支创建成功"
else
echo "❌ 推送失败"
exit 1
fi
# 返回主分支
git checkout ${{ github.ref_name }}
echo "======================================"
echo ""
- name: 🔍 检查并安装依赖
id: check_deps
run: |
echo "======================================"
echo "🔍 检查必要的工具"
echo "======================================"
MISSING_TOOLS=()
# 检查 cloc
if ! command -v cloc &> /dev/null; then
echo "⚠️ cloc 未安装"
MISSING_TOOLS+=("cloc")
else
echo "✅ cloc 已安装: $(cloc --version | head -n1)"
fi
# 检查 jq
if ! command -v jq &> /dev/null; then
echo "⚠️ jq 未安装"
MISSING_TOOLS+=("jq")
else
echo "✅ jq 已安装: $(jq --version)"
fi
# 检查 bc
if ! command -v bc &> /dev/null; then
echo "⚠️ bc 未安装"
MISSING_TOOLS+=("bc")
else
echo "✅ bc 已安装"
fi
echo ""
# 如果有缺失的工具,进行安装
if [ ${#MISSING_TOOLS[@]} -gt 0 ]; then
echo "📦 安装缺失的工具: ${MISSING_TOOLS[*]}"
sudo apt-get update -qq
sudo apt-get install -y ${MISSING_TOOLS[@]}
echo "✅ 工具安装完成"
echo "installed=true" >> $GITHUB_OUTPUT
else
echo "✅ 所有必要工具已就绪"
echo "installed=false" >> $GITHUB_OUTPUT
fi
echo ""
echo "📋 最终工具版本:"
echo " - cloc: $(cloc --version | head -n1)"
echo " - jq: $(jq --version)"
echo " - bc: $(bc --version | head -n1)"
echo "======================================"
echo ""
- name: 📊 统计总代码行数
id: total
run: |
echo "======================================"
echo "📊 统计总代码行数"
echo "======================================"
cd "${{ env.REPO_DIR }}"
# 构建排除参数
EXCLUDE_ARG=""
if [ -n "${{ env.EXCLUDE_DIRS }}" ]; then
EXCLUDE_ARG="--exclude-dir=$(echo "${{ env.EXCLUDE_DIRS }}" | sed 's/ //g')"
fi
echo "🔍 统计参数:"
echo " - 目录: $(pwd)"
echo " - 排除: ${{ env.EXCLUDE_DIRS }}"
echo ""
# 执行统计
echo "⏳ 正在统计..."
cloc . $EXCLUDE_ARG --json > /tmp/total_stats.json || {
echo "⚠️ cloc 执行失败,使用备用方案"
echo '{"SUM":{"code":0},"header":{"n_files":0}}' > /tmp/total_stats.json
}
TOTAL_CODE=$(jq '.SUM.code // 0' /tmp/total_stats.json)
TOTAL_FILES=$(jq '.header.n_files // 0' /tmp/total_stats.json)
# 格式化数字(添加千位分隔符)
format_num() {
printf "%'d" "$1" 2>/dev/null || echo "$1"
}
echo "total_code=$TOTAL_CODE" >> $GITHUB_OUTPUT
echo "total_files=$TOTAL_FILES" >> $GITHUB_OUTPUT
echo "formatted_code=$(format_num $TOTAL_CODE)" >> $GITHUB_OUTPUT
echo "formatted_files=$(format_num $TOTAL_FILES)" >> $GITHUB_OUTPUT
echo ""
echo "📈 统计结果:"
echo " - 总代码行数: $(format_num $TOTAL_CODE) 行"
echo " - 总文件数: $(format_num $TOTAL_FILES) 个"
# 保存原始数据供后续使用
cat /tmp/total_stats.json | jq '.' > /tmp/total_stats_backup.json
echo "======================================"
echo ""
- name: 📊 按语言分组统计
id: languages
run: |
echo "======================================"
echo "📊 按语言分组统计"
echo "======================================"
cd "${{ env.REPO_DIR }}"
# 构建排除参数
EXCLUDE_ARG=""
if [ -n "${{ env.EXCLUDE_DIRS }}" ]; then
EXCLUDE_ARG="--exclude-dir=$(echo "${{ env.EXCLUDE_DIRS }}" | sed 's/ //g')"
fi
# 创建临时目录
mkdir -p /tmp/lang_stats
rm -f /tmp/lang_summary.txt
# 格式化数字函数
format_num() {
printf "%'d" "$1" 2>/dev/null || echo "$1"
}
# 读取语言分组配置并统计
LANG_COUNT=0
MIN_THRESHOLD=${{ env.MIN_LINES_THRESHOLD }}
echo "⚙️ 配置信息:"
echo " - 最小阈值: $MIN_THRESHOLD 行"
echo ""
echo "${{ env.LANGUAGE_GROUPS }}" | while IFS= read -r line; do
[ -z "$line" ] && continue
# 解析配置: 组名:后缀:显示名:颜色:图标(可选)
LANG_ID=$(echo "$line" | cut -d':' -f1 | tr -d ' ')
EXTENSIONS=$(echo "$line" | cut -d':' -f2 | tr -d ' ')
DISPLAY_NAME=$(echo "$line" | cut -d':' -f3 | tr -d ' ')
COLOR=$(echo "$line" | cut -d':' -f4 | tr -d ' ')
ICON=$(echo "$line" | cut -d':' -f5 | tr -d ' ')
[ -z "$LANG_ID" ] && continue
echo "📝 统计 $DISPLAY_NAME ($EXTENSIONS)..."
# 统计该语言组
cloc . $EXCLUDE_ARG \
--include-ext="$EXTENSIONS" \
--json > /tmp/lang_stats/${LANG_ID}.json 2>/dev/null || {
echo " ⚠️ 统计失败,跳过"
continue
}
CODE_LINES=$(jq '.SUM.code // 0' /tmp/lang_stats/${LANG_ID}.json)
FILE_COUNT=$(jq '.header.n_files // 0' /tmp/lang_stats/${LANG_ID}.json)
# 如果代码行数低于阈值,跳过
if [ "$CODE_LINES" -lt "$MIN_THRESHOLD" ]; then
echo " ⏭️ 代码行数 ($CODE_LINES) 低于阈值,跳过"
continue
fi
FORMATTED_LINES=$(format_num $CODE_LINES)
echo " ✅ ${DISPLAY_NAME}: $FORMATTED_LINES 行 ($FILE_COUNT 文件)"
# 保存数据(添加图标字段)
echo "${LANG_ID}|${DISPLAY_NAME}|${CODE_LINES}|${FORMATTED_LINES}|${FILE_COUNT}|${COLOR}|${ICON}" >> /tmp/lang_summary.txt
done
echo ""
# 统计有效语言数量
if [ -f /tmp/lang_summary.txt ]; then
VALID_LANG_COUNT=$(wc -l < /tmp/lang_summary.txt)
echo "language_count=$VALID_LANG_COUNT" >> $GITHUB_OUTPUT
echo "✅ 语言统计完成: $VALID_LANG_COUNT 种语言"
else
echo "language_count=0" >> $GITHUB_OUTPUT
echo "⚠️ 未找到符合条件的语言"
fi
echo "======================================"
echo ""
- name: 🎨 生成徽章数据
id: generate_badges
run: |
echo "======================================"
echo "🎨 生成徽章数据"
echo "======================================"
cd "${{ env.REPO_DIR }}"
# 切换到统计分支
echo "🔄 切换到统计分支..."
git fetch origin ${{ env.BADGE_BRANCH }}:${{ env.BADGE_BRANCH }}
git checkout ${{ env.BADGE_BRANCH }}
# 创建徽章目录
mkdir -p ${{ env.BADGE_DIR }}
# 清理旧的徽章文件
echo "🧹 清理旧徽章..."
rm -f ${{ env.BADGE_DIR }}/*.json
GENERATED_COUNT=0
echo ""
echo "📝 生成徽章文件..."
# 1. 总代码行数徽章
cat > ${{ env.BADGE_DIR }}/total-lines.json << EOF
{
"schemaVersion": 1,
"label": "总代码",
"message": "${{ steps.total.outputs.formatted_code }} 行",
"color": "${{ env.COLOR_TOTAL }}",
"style": "${{ env.BADGE_STYLE }}"
}
EOF
GENERATED_COUNT=$((GENERATED_COUNT + 1))
echo " ✅ total-lines.json"
# 2. 总文件数徽章
cat > ${{ env.BADGE_DIR }}/total-files.json << EOF
{
"schemaVersion": 1,
"label": "文件数",
"message": "${{ steps.total.outputs.formatted_files }} 个",
"color": "${{ env.COLOR_FILES }}",
"style": "${{ env.BADGE_STYLE }}"
}
EOF
GENERATED_COUNT=$((GENERATED_COUNT + 1))
echo " ✅ total-files.json"
# 3. 为每个语言生成徽章
if [ -f /tmp/lang_summary.txt ]; then
while IFS='|' read -r lang_id display_name code_lines formatted_lines file_count color icon; do
[ -z "$lang_id" ] && continue
# 使用默认颜色(如果未指定)
[ -z "$color" ] && color="${{ env.COLOR_DEFAULT }}"
# 语言代码行数徽章
cat > ${{ env.BADGE_DIR }}/${lang_id}-lines.json << EOF
{
"schemaVersion": 1,
"label": "${display_name}",
"message": "${formatted_lines} 行",
"color": "${color}",
"style": "${{ env.BADGE_STYLE }}"
}
EOF
GENERATED_COUNT=$((GENERATED_COUNT + 1))
# 语言文件数徽章
cat > ${{ env.BADGE_DIR }}/${lang_id}-files.json << EOF
{
"schemaVersion": 1,
"label": "${display_name} 文件",
"message": "${file_count} 个",
"color": "${color}",
"style": "${{ env.BADGE_STYLE }}"
}
EOF
GENERATED_COUNT=$((GENERATED_COUNT + 1))
echo " ✅ ${lang_id}-lines.json, ${lang_id}-files.json"
done < /tmp/lang_summary.txt
fi
echo "generated_count=$GENERATED_COUNT" >> $GITHUB_OUTPUT
echo ""
echo "📊 生成统计:"
echo " - 总计: $GENERATED_COUNT 个徽章文件"
echo ""
echo "📂 徽章文件列表:"
ls -lh ${{ env.BADGE_DIR }}/*.json 2>/dev/null || echo " ⚠️ 未找到徽章文件"
echo "======================================"
echo ""
- name: 📄 生成统计报告
if: env.GENERATE_DETAILED_REPORT == 'true'
run: |
echo "======================================"
echo "📄 生成详细统计报告"
echo "======================================"
cd "${{ env.REPO_DIR }}"
TOTAL_CODE=${{ steps.total.outputs.total_code }}
REPO_NAME="${{ env.REPO_NAME }}"
REPO_OWNER="${{ github.repository_owner }}"
echo "📝 生成 README.md..."
# 生成 Markdown 报告
cat > ${{ env.BADGE_DIR }}/README.md << EOFMD
# 📊 ${REPO_NAME} 代码统计报告
> 最后更新: $(date '+%Y-%m-%d %H:%M:%S %Z')
>
> 分支: \`${{ github.ref_name }}\` | 提交: [\`${GITHUB_SHA:0:7}\`](${GITHUB_SERVER_URL}/${GITHUB_REPOSITORY}/commit/${GITHUB_SHA})
## 📈 总览
| 指标 | 数值 |
|------|------|
| 💻 **总代码行数** | ${{ steps.total.outputs.formatted_code }} |
| 📁 **总文件数** | ${{ steps.total.outputs.formatted_files }} |
| 🌐 **语言种类** | ${{ steps.languages.outputs.language_count }} |
| 🎨 **徽章数量** | ${{ steps.generate_badges.outputs.generated_count }} |
## 🎨 各语言统计
EOFMD
# 检查是否有语言数据
if [ -f /tmp/lang_summary.txt ] && [ -s /tmp/lang_summary.txt ]; then
cat >> ${{ env.BADGE_DIR }}/README.md << 'EOFMD'
| 语言 | 代码行数 | 文件数 | 占比 | 进度条 |
|------|----------|--------|------|--------|
EOFMD
# 添加各语言数据(按代码行数排序)
sort -t'|' -k3 -nr /tmp/lang_summary.txt | 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
# 生成进度条每2%一个方块)
BAR_LENGTH=$(echo "scale=0; $PERCENT / 2" | bc)
BAR_LENGTH=${BAR_LENGTH:-0}
if [ "$BAR_LENGTH" -gt 0 ]; then
BAR=$(printf '█%.0s' $(seq 1 $BAR_LENGTH))
else
BAR="░"
fi
# 添加图标(如果有)
ICON_DISPLAY=""
if [ -n "$icon" ]; then
ICON_DISPLAY="<img src=\"https://cdn.simpleicons.org/${icon}/${color}\" width=\"16\" height=\"16\" alt=\"${display_name}\"/> "
fi
echo "| ${ICON_DISPLAY}**${display_name}** | ${formatted_lines} | ${file_count} | ${PERCENT}% | ${BAR} |" >> ${{ env.BADGE_DIR }}/README.md
done
else
echo "" >> ${{ env.BADGE_DIR }}/README.md
echo "> ⚠️ 未找到符合统计条件的语言文件" >> ${{ env.BADGE_DIR }}/README.md
fi
# 添加使用说明
cat >> ${{ env.BADGE_DIR }}/README.md << EOFMD
---
## 📖 徽章使用指南
### 🎯 总览徽章
\`\`\`markdown
![总代码行数](https://img.shields.io/endpoint?url=${GITHUB_SERVER_URL}/${GITHUB_REPOSITORY}/raw/branch/${{ env.BADGE_BRANCH }}/${{ env.BADGE_DIR }}/total-lines.json)
![总文件数](https://img.shields.io/endpoint?url=${GITHUB_SERVER_URL}/${GITHUB_REPOSITORY}/raw/branch/${{ env.BADGE_BRANCH }}/${{ env.BADGE_DIR }}/total-files.json)
\`\`\`
**效果预览:**
![总代码行数](https://img.shields.io/endpoint?url=${GITHUB_SERVER_URL}/${GITHUB_REPOSITORY}/raw/branch/${{ env.BADGE_BRANCH }}/${{ env.BADGE_DIR }}/total-lines.json)
![总文件数](https://img.shields.io/endpoint?url=${GITHUB_SERVER_URL}/${GITHUB_REPOSITORY}/raw/branch/${{ env.BADGE_BRANCH }}/${{ env.BADGE_DIR }}/total-files.json)
### 🌐 各语言徽章
EOFMD
# 添加各语言徽章使用示例
if [ -f /tmp/lang_summary.txt ] && [ -s /tmp/lang_summary.txt ]; then
while IFS='|' read -r lang_id display_name code_lines formatted_lines file_count color icon; do
[ -z "$lang_id" ] && continue
cat >> ${{ env.BADGE_DIR }}/README.md << EOFLANG
**${display_name}:**
\`\`\`markdown
![${display_name} 代码行数](https://img.shields.io/endpoint?url=${GITHUB_SERVER_URL}/${GITHUB_REPOSITORY}/raw/branch/${{ env.BADGE_BRANCH }}/${{ env.BADGE_DIR }}/${lang_id}-lines.json)
![${display_name} 文件数](https://img.shields.io/endpoint?url=${GITHUB_SERVER_URL}/${GITHUB_REPOSITORY}/raw/branch/${{ env.BADGE_BRANCH }}/${{ env.BADGE_DIR }}/${lang_id}-files.json)
\`\`\`
![${display_name} 代码行数](https://img.shields.io/endpoint?url=${GITHUB_SERVER_URL}/${GITHUB_REPOSITORY}/raw/branch/${{ env.BADGE_BRANCH }}/${{ env.BADGE_DIR }}/${lang_id}-lines.json)
![${display_name} 文件数](https://img.shields.io/endpoint?url=${GITHUB_SERVER_URL}/${GITHUB_REPOSITORY}/raw/branch/${{ env.BADGE_BRANCH }}/${{ env.BADGE_DIR }}/${lang_id}-files.json)
EOFLANG
done < /tmp/lang_summary.txt
fi
# 添加配置说明
cat >> ${{ env.BADGE_DIR }}/README.md << 'EOFMD'
---
## ⚙️ 配置说明
### Token 配置
- 当前使用: **${{ steps.validate_token.outputs.token_type }}**
- 推荐配置自定义 `STATS_TOKEN` 以获得更好的权限控制
### 排除规则
当前排除的目录:
\`\`\`
${{ env.EXCLUDE_DIRS }}
\`\`\`
### 阈值设置
- 最小代码行数阈值: **${{ env.MIN_LINES_THRESHOLD }}** 行
- 低于此阈值的语言将不会生成徽章
### 徽章样式
- 当前样式: **${{ env.BADGE_STYLE }}**
- 可选样式: flat, flat-square, plastic, for-the-badge, social
---
<div align="center">
*📊 由 [GitHub Actions](${GITHUB_SERVER_URL}/${GITHUB_REPOSITORY}/actions) 自动生成和更新*
*🤖 生成时间: $(date -u '+%Y-%m-%d %H:%M:%S UTC')*
</div>
EOFMD
echo "✅ 详细统计报告已生成"
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 ${{ env.BADGE_DIR }}/
# 检查是否有变更
if git diff --staged --quiet; then
echo "📌 没有变更,跳过提交"
echo "changed=false" >> $GITHUB_OUTPUT
echo ""
else
echo "📝 准备提交..."
# 生成提交信息
COMMIT_MSG="chore: 更新代码统计 [$(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 }} 个
🔗 触发提交: ${GITHUB_SHA:0:7}
🤖 由 GitHub Actions 自动生成"
git commit -m "$COMMIT_MSG"
echo "📤 推送到远程 ${{ env.BADGE_BRANCH }} 分支..."
# 推送到远程(使用 TOKEN
git push https://oauth2:${{ env.ACCESS_TOKEN }}@${GITHUB_SERVER_URL#https://}/${{ github.repository }}.git ${{ env.BADGE_BRANCH }}
if [ $? -eq 0 ]; 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 }}** |
| 🔧 依赖检查 | ${{ steps.check_deps.outputs.installed == 'true' && '✅ 已安装缺失工具' || '✅ 所有工具就绪' }} |
| 📊 总代码行数 | **${{ 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 }}/${{ env.BADGE_DIR }}/README.md)
- 🎨 [浏览徽章文件](${GITHUB_SERVER_URL}/${GITHUB_REPOSITORY}/src/branch/${{ env.BADGE_BRANCH }}/${{ env.BADGE_DIR }})
- 🔧 [查看 Workflow 配置](${GITHUB_SERVER_URL}/${GITHUB_REPOSITORY}/blob/${{ github.ref_name }}/.github/workflows/update_stats_badge.yaml)
## 📝 语言分布
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 }}/${{ env.BADGE_DIR }}/README.md"
echo ""
echo "🎨 徽章目录:"
echo " ${GITHUB_SERVER_URL}/${GITHUB_REPOSITORY}/src/branch/${{ env.BADGE_BRANCH }}/${{ env.BADGE_DIR }}"
echo ""
echo "================================================"
# 如果有警告或特殊情况,也输出
if [ "${{ steps.check_deps.outputs.installed }}" == "true" ]; then
echo ""
echo " 本次运行安装了缺失的依赖工具"
fi
if [ "${{ steps.languages.outputs.language_count }}" == "0" ]; then
echo ""
echo "⚠️ 警告: 未找到符合条件的语言文件"
echo " 请检查 LANGUAGE_GROUPS 配置和 MIN_LINES_THRESHOLD 设置"
fi
# 清理工作区(可选)
if [ "${{ env.CLEANUP_WORKSPACE }}" == "true" ]; then
echo ""
echo "🧹 清理工作区..."
rm -rf "${{ env.WORKSPACE_DIR }}"
echo "✅ 清理完成"
fi
- name: 🧹 清理工作区
if: always()
run: |
echo "🧹 清理临时文件..."
rm -rf /tmp/lang_stats /tmp/lang_summary.txt /tmp/total_stats*.json
echo "✅ 清理完成"

View File

@ -9,6 +9,7 @@
```txt
.gitea/workflows/
├── changelog-and-release.yml # CHANGELOG 生成 + Release 创建
├── update_stats_badge.yml # 代码行数的统计
└── ... # 更多 workflow 待添加
```
@ -45,6 +46,36 @@ git push origin 1.0.0
---
#### 2. 📊 代码统计徽章工作流 (`update-stats-badge.yml`)
**功能**:自动统计代码行数并生成徽章数据
**特性**
- 📈 统计总代码行数和文件数
- 🌐 按语言分组统计
- 🎨 自动生成徽章 JSON 数据
- 📊 生成统计摘要JSON 格式)
- 🚫 灵活的目录排除配置
**触发方式**
```bash
# 推送到主分支时自动触发
git push origin main
# 手动触发
# 仓库 → Actions → Update Code Statistics Badge → Run workflow
```
**配置文件**[update-stats-badge.yml](.gitea/workflows/update_stats_badge.yaml)
**markdown引用格式**: `![C++](https://img.shields.io/endpoint?url=https://你的gitea/用户名/仓库/raw/分支/stats/badges/cpp-lines.json)`
💡 **详细配置**:查看 `update-stats-badge.yml` 文件顶部的 `env` 区域,包含语言分组、颜色、排除目录等配置
---
### 🔜 待扩展
更多自动化场景: