actions-template/.gitea/workflows/update_stats_badge.yaml

929 lines
35 KiB
YAML
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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: 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 "✅ 清理完成"