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="\"${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 ---
*📊 由 [GitHub Actions](${GITHUB_SERVER_URL}/${GITHUB_REPOSITORY}/actions) 自动生成和更新* *🤖 生成时间: $(date -u '+%Y-%m-%d %H:%M:%S UTC')*
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 "✅ 清理完成"