Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
99b3560b88 | ||
|
|
db75d0ebc5 | ||
|
|
1b5611cf3e | ||
|
|
44e92ab89a | ||
|
|
eaedcd3bb2 | ||
|
|
0e89b21c41 | ||
|
|
39820e656a | ||
|
|
4829434408 | ||
|
|
9c572b64d1 | ||
|
|
49f11fb2d8 | ||
|
|
5ec0af5883 | ||
|
|
c81aac970c | ||
|
|
566a1754a7 | ||
|
|
1b7eed5d93 | ||
|
|
3a17dc4b52 | ||
|
|
e71d9d01fd | ||
|
|
160c5ebade | ||
|
|
fb4e7f3b1f | ||
|
|
9a472a4271 | ||
|
|
0d3ccadfef | ||
|
|
fa21511d1a | ||
|
|
7373553270 | ||
|
|
3308b4354c | ||
|
|
f422a75c1c | ||
|
|
fc76a1f625 | ||
|
|
4ed8099158 | ||
|
|
bf6698ab3e | ||
|
|
b57c0cc9d6 | ||
|
|
1f535e0675 | ||
|
|
9961226704 | ||
|
|
b4c47c4085 | ||
|
|
ec5785cc6a | ||
|
|
84e2751668 | ||
|
|
0bb627fd34 | ||
|
|
9cde246b20 | ||
|
|
aaeed0d919 | ||
|
|
f57e6984c0 | ||
|
|
2ac94aff1c | ||
|
|
d7a0c7a85b | ||
|
|
948bcfa787 | ||
|
|
23a7fb5a28 | ||
|
|
b616573bfd | ||
|
|
5b3629fb73 | ||
|
|
38e6c82394 | ||
|
|
376c1a2866 | ||
|
|
d5a7d5506e | ||
|
|
c0aef0f531 | ||
|
|
a21adb9fcc | ||
|
|
8971cbffc3 | ||
|
|
cae1f4d4a7 | ||
|
|
27f35a6c63 | ||
|
|
b651daf225 | ||
|
|
29cd19ec5b | ||
|
|
d50ee5d5cc | ||
|
|
094587752c | ||
|
|
4b34b9e0f3 | ||
|
|
082194acba |
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,102 @@
|
|||||||
|
name: Ubuntu System Information
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches:
|
||||||
|
- main
|
||||||
|
workflow_dispatch: # 允许手动触发
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
show-system-info:
|
||||||
|
runs-on: ubuntu-22.04
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- name: 打印问候
|
||||||
|
run: |
|
||||||
|
echo "====================================="
|
||||||
|
echo " Ubuntu System Information Check "
|
||||||
|
echo "====================================="
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
- name: 显示系统信息
|
||||||
|
run: |
|
||||||
|
echo "===== 系统版本 ====="
|
||||||
|
cat /etc/os-release
|
||||||
|
echo ""
|
||||||
|
echo "===== 内核信息 ====="
|
||||||
|
uname -a
|
||||||
|
echo ""
|
||||||
|
echo "===== 主机名 ====="
|
||||||
|
hostname
|
||||||
|
echo ""
|
||||||
|
echo "===== 系统启动时间 ====="
|
||||||
|
uptime
|
||||||
|
|
||||||
|
- name: 显示 CPU 信息
|
||||||
|
run: |
|
||||||
|
echo "===== CPU 详细信息 ====="
|
||||||
|
lscpu
|
||||||
|
echo ""
|
||||||
|
echo "===== CPU 型号 ====="
|
||||||
|
cat /proc/cpuinfo | grep "model name" | head -1
|
||||||
|
echo ""
|
||||||
|
echo "===== CPU 核心数 ====="
|
||||||
|
nproc
|
||||||
|
|
||||||
|
- name: 显示内存信息
|
||||||
|
run: |
|
||||||
|
echo "===== 内存使用情况 ====="
|
||||||
|
free -h
|
||||||
|
echo ""
|
||||||
|
echo "===== 内存详细信息 ====="
|
||||||
|
cat /proc/meminfo | grep -E 'MemTotal|MemFree|MemAvailable'
|
||||||
|
|
||||||
|
- name: 显示磁盘信息
|
||||||
|
run: |
|
||||||
|
echo "===== 磁盘使用情况 ====="
|
||||||
|
df -h
|
||||||
|
echo ""
|
||||||
|
echo "===== 磁盘分区信息 ====="
|
||||||
|
lsblk
|
||||||
|
|
||||||
|
- name: 显示网络信息
|
||||||
|
run: |
|
||||||
|
echo "===== 网络接口 ====="
|
||||||
|
cat /proc/net/dev
|
||||||
|
echo ""
|
||||||
|
echo "===== 路由表 ====="
|
||||||
|
cat /proc/net/route
|
||||||
|
echo ""
|
||||||
|
echo "===== DNS 配置 ====="
|
||||||
|
cat /etc/resolv.conf
|
||||||
|
|
||||||
|
- name: 显示已安装的软件
|
||||||
|
run: |
|
||||||
|
echo "===== Python 版本 ====="
|
||||||
|
python3 --version
|
||||||
|
echo ""
|
||||||
|
echo "===== Node.js 版本 ====="
|
||||||
|
node --version || echo "Node.js 未安装"
|
||||||
|
echo ""
|
||||||
|
echo "===== Docker 版本 ====="
|
||||||
|
docker --version || echo "Docker 未安装"
|
||||||
|
echo ""
|
||||||
|
echo "===== Git 版本 ====="
|
||||||
|
git --version
|
||||||
|
|
||||||
|
- name: 显示环境变量
|
||||||
|
run: |
|
||||||
|
echo "===== 重要环境变量 ====="
|
||||||
|
echo "PATH: $PATH"
|
||||||
|
echo "HOME: $HOME"
|
||||||
|
echo "USER: $USER"
|
||||||
|
echo "SHELL: $SHELL"
|
||||||
|
echo "PWD: $PWD"
|
||||||
|
|
||||||
|
- name: 显示当前目录
|
||||||
|
run: |
|
||||||
|
echo "===== 当前工作目录 ====="
|
||||||
|
pwd
|
||||||
|
echo ""
|
||||||
|
echo "===== 目录内容 ====="
|
||||||
|
ls -lah
|
||||||
@@ -0,0 +1,976 @@
|
|||||||
|
name: 📊 代码统计徽章
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches: [main, master]
|
||||||
|
workflow_dispatch:
|
||||||
|
|
||||||
|
# ==========================================
|
||||||
|
# 🔧 配置区域 - 根据你的项目修改
|
||||||
|
# ==========================================
|
||||||
|
env:
|
||||||
|
# ===== Token 配置 =====
|
||||||
|
# 建议在 Settings -> Secrets 中配置 STATS_TOKEN 以获得更好的权限控制
|
||||||
|
ACCESS_TOKEN: ${{ secrets.WORKFLOW }}
|
||||||
|
|
||||||
|
# ===== 工作区配置 =====
|
||||||
|
# 完整克隆的工作目录
|
||||||
|
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: "ci[bot]"
|
||||||
|
GIT_USER_EMAIL: "ci[bot]@tinysoft.com.cn"
|
||||||
|
|
||||||
|
# ===== 平台配置 =====
|
||||||
|
# 平台类型: github 或 gitea
|
||||||
|
PLATFORM: "gitea"
|
||||||
|
# Git 服务器 URL(Gitea 示例: https://gitea.example.com)
|
||||||
|
GIT_SERVER_URL: "https://git.mytsl.cn"
|
||||||
|
# 仓库路径(格式: owner/repo)
|
||||||
|
REPO_PATH: "${{ github.repository }}"
|
||||||
|
# Raw 文件基础 URL
|
||||||
|
# GitHub: https://raw.githubusercontent.com/{owner}/{repo}/{branch}/{path}
|
||||||
|
# Gitea: https://gitea.example.com/{owner}/{repo}/raw/branch/{branch}/{path}
|
||||||
|
RAW_URL_BASE: 'https://git.mytsl.cn/${{ github.repository }}/raw/branch'
|
||||||
|
|
||||||
|
# ==========================================
|
||||||
|
# 🎨 语言分组配置
|
||||||
|
# 格式: 组名:后缀列表:显示名称:颜色:图标(可选)
|
||||||
|
# 图标使用 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-22.04
|
||||||
|
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: check_deps
|
||||||
|
run: |
|
||||||
|
echo "======================================"
|
||||||
|
echo "🔍 检查依赖工具"
|
||||||
|
echo "======================================"
|
||||||
|
|
||||||
|
MISSING_TOOLS=()
|
||||||
|
|
||||||
|
# 检查 bc(用于数字计算)
|
||||||
|
if ! command -v bc &> /dev/null; then
|
||||||
|
echo "⚠️ bc 未安装"
|
||||||
|
MISSING_TOOLS+=("bc")
|
||||||
|
else
|
||||||
|
echo "✓ bc 已安装"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# 检查 jq(用于 JSON 处理)
|
||||||
|
if ! command -v jq &> /dev/null; then
|
||||||
|
echo "⚠️ jq 未安装"
|
||||||
|
MISSING_TOOLS+=("jq")
|
||||||
|
else
|
||||||
|
echo "✓ jq 已安装"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# 如果有缺失的工具,安装它们
|
||||||
|
if [ ${#MISSING_TOOLS[@]} -gt 0 ]; then
|
||||||
|
echo ""
|
||||||
|
echo "📦 安装缺失的工具: ${MISSING_TOOLS[*]}"
|
||||||
|
|
||||||
|
# 🔧 智能判断是否需要 sudo
|
||||||
|
# Docker 环境通常以 root 运行,不需要 sudo
|
||||||
|
if [ "$EUID" -eq 0 ] || [ "$(id -u)" -eq 0 ]; then
|
||||||
|
# 当前是 root 用户,直接执行
|
||||||
|
echo "🔑 检测到 root 权限,直接安装"
|
||||||
|
apt-get update -qq
|
||||||
|
apt-get install -y -qq "${MISSING_TOOLS[@]}"
|
||||||
|
elif command -v sudo &> /dev/null; then
|
||||||
|
# 有 sudo 命令,使用 sudo
|
||||||
|
echo "🔑 使用 sudo 安装"
|
||||||
|
sudo apt-get update -qq
|
||||||
|
sudo apt-get install -y -qq "${MISSING_TOOLS[@]}"
|
||||||
|
else
|
||||||
|
# 既不是 root 也没有 sudo
|
||||||
|
echo "❌ 错误:没有足够权限安装工具"
|
||||||
|
echo "请在 Docker 镜像中预装以下工具:"
|
||||||
|
echo " ${MISSING_TOOLS[*]}"
|
||||||
|
echo ""
|
||||||
|
echo "方案1: 使用包含这些工具的镜像"
|
||||||
|
echo "方案2: 在 Dockerfile 中添加:"
|
||||||
|
echo " RUN apt-get update && apt-get install -y bc jq"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "installed=true" >> $GITHUB_OUTPUT
|
||||||
|
echo "✅ 工具安装完成"
|
||||||
|
else
|
||||||
|
echo "installed=false" >> $GITHUB_OUTPUT
|
||||||
|
echo "✅ 所有工具已就绪"
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "======================================"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
- 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 "🌿 分支: ${{ github.ref_name }}"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# 检查仓库状态
|
||||||
|
if [ -d "$REPO_DIR" ]; then
|
||||||
|
echo "📂 目录已存在,检查 Git 仓库状态..."
|
||||||
|
|
||||||
|
if [ -d "$REPO_DIR/.git" ]; then
|
||||||
|
# 目录存在且是有效的 Git 仓库
|
||||||
|
echo "✓ 发现有效的 Git 仓库,执行增量更新..."
|
||||||
|
cd "$REPO_DIR"
|
||||||
|
|
||||||
|
# 清理工作区
|
||||||
|
git clean -fdx
|
||||||
|
git reset --hard
|
||||||
|
|
||||||
|
# 获取最新代码
|
||||||
|
echo "📥 拉取最新代码..."
|
||||||
|
git fetch --all --tags --force
|
||||||
|
|
||||||
|
echo "✓ 仓库已更新"
|
||||||
|
else
|
||||||
|
# 目录存在但不是 Git 仓库(可能之前运行失败)
|
||||||
|
echo "⚠️ 目录存在但不是有效的 Git 仓库"
|
||||||
|
echo "🧹 清理损坏的目录..."
|
||||||
|
rm -rf "$REPO_DIR"
|
||||||
|
echo "✓ 已清理"
|
||||||
|
|
||||||
|
# 重新克隆
|
||||||
|
echo "📥 克隆仓库..."
|
||||||
|
mkdir -p "${{ env.WORKSPACE_DIR }}"
|
||||||
|
|
||||||
|
git clone \
|
||||||
|
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 "✓ 仓库已克隆"
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
# 目录不存在,首次克隆
|
||||||
|
echo "📥 克隆仓库(首次)..."
|
||||||
|
mkdir -p "${{ env.WORKSPACE_DIR }}"
|
||||||
|
|
||||||
|
git clone \
|
||||||
|
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 "✓ 仓库已克隆"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# 切换到目标分支
|
||||||
|
echo "🏷️ 切换到分支: ${{ github.ref_name }}"
|
||||||
|
git checkout -f ${{ github.ref_name }}
|
||||||
|
|
||||||
|
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 }}"
|
||||||
|
|
||||||
|
# 🔴 安全检查:确认在正确的目录
|
||||||
|
echo "🔍 当前目录: $(pwd)"
|
||||||
|
echo "🔍 .git 状态: $([ -d .git ] && echo '✓ 存在' || echo '✗ 不存在')"
|
||||||
|
|
||||||
|
if [ ! -d .git ]; then
|
||||||
|
echo "❌ 错误:.git 目录不存在,无法创建分支"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# 创建孤立分支(orphan branch)
|
||||||
|
# 📝 说明:孤立分支与主分支没有共同的提交历史,适合存储独立的数据
|
||||||
|
echo "🌱 创建孤立分支..."
|
||||||
|
git checkout --orphan ${{ env.BADGE_BRANCH }}
|
||||||
|
|
||||||
|
# 🔴 再次确认 .git 仍然存在
|
||||||
|
if [ ! -d .git ]; then
|
||||||
|
echo "❌ 严重错误:.git 目录丢失!"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# 🧹 清空所有文件(但保留 .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 '.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 "🔍 最终检查..."
|
||||||
|
if [ ! -d .git ]; then
|
||||||
|
echo "❌ 致命错误:.git 目录在清理过程中被删除!"
|
||||||
|
echo "这不应该发生,请检查 find 命令"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
echo "✓ .git 目录完好"
|
||||||
|
echo "✓ 文件清理完成"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# 创建初始 README
|
||||||
|
cat > README.md << 'EOF'
|
||||||
|
# 📊 代码统计徽章数据
|
||||||
|
|
||||||
|
> 此分支由 GitHub Actions 自动生成和维护
|
||||||
|
>
|
||||||
|
> ⚠️ **请勿手动修改此分支的内容!**
|
||||||
|
|
||||||
|
## 📁 目录结构
|
||||||
|
|
||||||
|
```
|
||||||
|
badges/
|
||||||
|
├── total-lines.json # 总代码行数徽章
|
||||||
|
├── total-files.json # 总文件数徽章
|
||||||
|
├── {language}-lines.json # 各语言代码行数徽章
|
||||||
|
├── {language}-files.json # 各语言文件数徽章
|
||||||
|
└── README.md # 详细统计报告
|
||||||
|
```
|
||||||
|
|
||||||
|
## 🔄 更新机制
|
||||||
|
|
||||||
|
- ✅ 每次 push 到主分支时自动更新
|
||||||
|
- ✅ 可通过 workflow_dispatch 手动触发
|
||||||
|
|
||||||
|
## 📊 数据来源
|
||||||
|
|
||||||
|
所有统计数据基于主分支的最新代码自动生成。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
*🤖 由 GitHub Actions 自动维护*
|
||||||
|
EOF
|
||||||
|
|
||||||
|
# 创建徽章目录
|
||||||
|
mkdir -p ${{ env.BADGE_DIR }}
|
||||||
|
|
||||||
|
# 添加并提交
|
||||||
|
git add .
|
||||||
|
git commit -m "chore: 初始化统计分支"
|
||||||
|
|
||||||
|
# 推送到远程
|
||||||
|
git push https://oauth2:${{ env.ACCESS_TOKEN }}@${GITHUB_SERVER_URL#https://}/${{ github.repository }}.git ${{ env.BADGE_BRANCH }}
|
||||||
|
|
||||||
|
echo "✅ 统计分支创建完成"
|
||||||
|
echo "======================================"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# 🔴 重要:返回主分支,后续统计需要在主分支进行
|
||||||
|
echo "🔄 切换回主分支: ${{ github.ref_name }}"
|
||||||
|
git checkout ${{ github.ref_name }}
|
||||||
|
echo "✓ 已切换回主分支"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
- name: 📊 统计总代码量
|
||||||
|
id: total
|
||||||
|
run: |
|
||||||
|
echo "======================================"
|
||||||
|
echo "📊 统计总代码量"
|
||||||
|
echo "======================================"
|
||||||
|
|
||||||
|
cd "${{ env.REPO_DIR }}"
|
||||||
|
|
||||||
|
# 🔴 重要:确保在主分支进行统计(不要统计 stats 分支)
|
||||||
|
echo "🔍 确认当前分支..."
|
||||||
|
CURRENT_BRANCH=$(git branch --show-current)
|
||||||
|
if [ "$CURRENT_BRANCH" != "${{ github.ref_name }}" ]; then
|
||||||
|
echo "⚠️ 当前在分支: $CURRENT_BRANCH,切换到主分支: ${{ github.ref_name }}"
|
||||||
|
git checkout ${{ github.ref_name }}
|
||||||
|
else
|
||||||
|
echo "✓ 已在主分支: $CURRENT_BRANCH"
|
||||||
|
fi
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# 构建排除参数
|
||||||
|
EXCLUDE_PARAMS=""
|
||||||
|
IFS=',' read -ra EXCLUDES <<< "${{ env.EXCLUDE_DIRS }}"
|
||||||
|
for dir in "${EXCLUDES[@]}"; do
|
||||||
|
EXCLUDE_PARAMS="$EXCLUDE_PARAMS -not -path '*/$dir/*'"
|
||||||
|
done
|
||||||
|
|
||||||
|
# 获取所有文件
|
||||||
|
echo "🔍 扫描文件..."
|
||||||
|
|
||||||
|
# 统计总文件数
|
||||||
|
TOTAL_FILES=$(eval "find . -type f $EXCLUDE_PARAMS" | wc -l)
|
||||||
|
|
||||||
|
# 统计总代码行数(排除空行)
|
||||||
|
TOTAL_CODE=$(eval "find . -type f $EXCLUDE_PARAMS -exec grep -cHv '^[[:space:]]*$' {} + 2>/dev/null" | awk -F: '{sum+=$2} END {print sum+0}')
|
||||||
|
|
||||||
|
echo "📊 统计结果:"
|
||||||
|
echo " - 总文件数: $TOTAL_FILES"
|
||||||
|
echo " - 总代码行: $TOTAL_CODE"
|
||||||
|
|
||||||
|
# 格式化数字(添加千分位)
|
||||||
|
FORMATTED_FILES=$(printf "%'d" $TOTAL_FILES)
|
||||||
|
FORMATTED_CODE=$(printf "%'d" $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 }}"
|
||||||
|
|
||||||
|
# 🔴 重要:确保在主分支进行统计
|
||||||
|
echo "🔍 确认当前分支..."
|
||||||
|
CURRENT_BRANCH=$(git branch --show-current)
|
||||||
|
if [ "$CURRENT_BRANCH" != "${{ github.ref_name }}" ]; then
|
||||||
|
echo "⚠️ 当前在分支: $CURRENT_BRANCH,切换到主分支: ${{ github.ref_name }}"
|
||||||
|
git checkout ${{ github.ref_name }}
|
||||||
|
else
|
||||||
|
echo "✓ 已在主分支: $CURRENT_BRANCH"
|
||||||
|
fi
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# 创建临时目录
|
||||||
|
mkdir -p /tmp/lang_stats
|
||||||
|
|
||||||
|
# 构建排除参数
|
||||||
|
EXCLUDE_PARAMS=""
|
||||||
|
IFS=',' read -ra EXCLUDES <<< "${{ env.EXCLUDE_DIRS }}"
|
||||||
|
for dir in "${EXCLUDES[@]}"; do
|
||||||
|
EXCLUDE_PARAMS="$EXCLUDE_PARAMS -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..."
|
||||||
|
|
||||||
|
# 构建扩展名查找条件
|
||||||
|
FIND_CONDITIONS=""
|
||||||
|
IFS=',' read -ra EXTS <<< "$extensions"
|
||||||
|
for ext in "${EXTS[@]}"; do
|
||||||
|
if [ -z "$FIND_CONDITIONS" ]; then
|
||||||
|
FIND_CONDITIONS="-name '*.$ext'"
|
||||||
|
else
|
||||||
|
FIND_CONDITIONS="$FIND_CONDITIONS -o -name '*.$ext'"
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
# 统计文件数
|
||||||
|
FILE_COUNT=$(eval "find . -type f \( $FIND_CONDITIONS \) $EXCLUDE_PARAMS" | wc -l)
|
||||||
|
|
||||||
|
if [ "$FILE_COUNT" -gt 0 ]; then
|
||||||
|
# 统计代码行数
|
||||||
|
CODE_LINES=$(eval "find . -type f \( $FIND_CONDITIONS \) $EXCLUDE_PARAMS -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=$(printf "%'d" $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: 🎨 生成徽章数据
|
||||||
|
id: generate_badges
|
||||||
|
run: |
|
||||||
|
echo "======================================"
|
||||||
|
echo "🎨 生成徽章数据"
|
||||||
|
echo "======================================"
|
||||||
|
|
||||||
|
cd "${{ env.REPO_DIR }}"
|
||||||
|
|
||||||
|
# 确保在统计分支
|
||||||
|
git checkout ${{ env.BADGE_BRANCH }}
|
||||||
|
|
||||||
|
# 确保徽章目录存在
|
||||||
|
mkdir -p ${{ env.BADGE_DIR }}
|
||||||
|
|
||||||
|
GENERATED_COUNT=0
|
||||||
|
|
||||||
|
# 生成总代码行数徽章
|
||||||
|
echo "📊 生成总代码行数徽章..."
|
||||||
|
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 "📁 生成总文件数徽章..."
|
||||||
|
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))
|
||||||
|
|
||||||
|
# 生成各语言徽章
|
||||||
|
if [ -f /tmp/lang_summary.txt ] && [ -s /tmp/lang_summary.txt ]; then
|
||||||
|
echo ""
|
||||||
|
echo "🌐 生成语言徽章..."
|
||||||
|
|
||||||
|
while IFS='|' read -r lang_id display_name code_lines formatted_lines file_count color icon; do
|
||||||
|
[ -z "$lang_id" ] && continue
|
||||||
|
|
||||||
|
echo " - $display_name"
|
||||||
|
|
||||||
|
# 生成代码行数徽章(使用 heredoc)
|
||||||
|
if [ -n "$icon" ]; then
|
||||||
|
# 带图标的徽章
|
||||||
|
cat > ${{ env.BADGE_DIR }}/${lang_id}-lines.json << EOFJSON
|
||||||
|
{
|
||||||
|
"schemaVersion": 1,
|
||||||
|
"label": "$display_name",
|
||||||
|
"message": "$formatted_lines 行",
|
||||||
|
"color": "$color",
|
||||||
|
"style": "${{ env.BADGE_STYLE }}",
|
||||||
|
"namedLogo": "$icon"
|
||||||
|
}
|
||||||
|
EOFJSON
|
||||||
|
else
|
||||||
|
# 不带图标的徽章
|
||||||
|
cat > ${{ env.BADGE_DIR }}/${lang_id}-lines.json << EOFJSON
|
||||||
|
{
|
||||||
|
"schemaVersion": 1,
|
||||||
|
"label": "$display_name",
|
||||||
|
"message": "$formatted_lines 行",
|
||||||
|
"color": "$color",
|
||||||
|
"style": "${{ env.BADGE_STYLE }}"
|
||||||
|
}
|
||||||
|
EOFJSON
|
||||||
|
fi
|
||||||
|
GENERATED_COUNT=$((GENERATED_COUNT + 1))
|
||||||
|
|
||||||
|
# 生成文件数徽章
|
||||||
|
cat > ${{ env.BADGE_DIR }}/${lang_id}-files.json << EOFJSON
|
||||||
|
{
|
||||||
|
"schemaVersion": 1,
|
||||||
|
"label": "$display_name 文件",
|
||||||
|
"message": "$file_count 个",
|
||||||
|
"color": "$color",
|
||||||
|
"style": "${{ env.BADGE_STYLE }}"
|
||||||
|
}
|
||||||
|
EOFJSON
|
||||||
|
GENERATED_COUNT=$((GENERATED_COUNT + 1))
|
||||||
|
done < /tmp/lang_summary.txt
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "generated_count=$GENERATED_COUNT" >> $GITHUB_OUTPUT
|
||||||
|
echo "✅ 已生成 $GENERATED_COUNT 个徽章"
|
||||||
|
echo "======================================"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
- name: 📝 生成详细统计报告
|
||||||
|
if: env.GENERATE_DETAILED_REPORT == 'true'
|
||||||
|
run: |
|
||||||
|
echo "======================================"
|
||||||
|
echo "📝 生成详细统计报告"
|
||||||
|
echo "======================================"
|
||||||
|
|
||||||
|
cd "${{ env.REPO_DIR }}"
|
||||||
|
|
||||||
|
# 确保在统计分支
|
||||||
|
git checkout ${{ env.BADGE_BRANCH }}
|
||||||
|
|
||||||
|
# 生成 README
|
||||||
|
cat > ${{ env.BADGE_DIR }}/README.md << 'EOFMD'
|
||||||
|
# 📊 代码统计详细报告
|
||||||
|
|
||||||
|
> 🤖 由 GitHub Actions 自动生成
|
||||||
|
>
|
||||||
|
> 📅 更新时间: TIMESTAMP_PLACEHOLDER
|
||||||
|
|
||||||
|
## 📈 总体统计
|
||||||
|
|
||||||
|
| 统计项 | 数值 | 徽章 |
|
||||||
|
|--------|------|------|
|
||||||
|
| 💻 总代码行数 | **TOTAL_CODE_PLACEHOLDER** 行 |  |
|
||||||
|
| 📁 总文件数 | **TOTAL_FILES_PLACEHOLDER** 个 |  |
|
||||||
|
| 🌐 语言种类 | **LANG_COUNT_PLACEHOLDER** 种 | - |
|
||||||
|
|
||||||
|
## 🌈 语言分布
|
||||||
|
|
||||||
|
EOFMD
|
||||||
|
|
||||||
|
# 替换占位符
|
||||||
|
sed -i "s|TIMESTAMP_PLACEHOLDER|$(date -u '+%Y-%m-%d %H:%M:%S UTC')|g" ${{ env.BADGE_DIR }}/README.md
|
||||||
|
sed -i "s|TOTAL_CODE_PLACEHOLDER|${{ steps.total.outputs.formatted_code }}|g" ${{ env.BADGE_DIR }}/README.md
|
||||||
|
sed -i "s|TOTAL_FILES_PLACEHOLDER|${{ steps.total.outputs.formatted_files }}|g" ${{ env.BADGE_DIR }}/README.md
|
||||||
|
sed -i "s|LANG_COUNT_PLACEHOLDER|${{ steps.languages.outputs.language_count }}|g" ${{ env.BADGE_DIR }}/README.md
|
||||||
|
sed -i "s|REPO_PLACEHOLDER|${{ github.repository }}|g" ${{ env.BADGE_DIR }}/README.md
|
||||||
|
sed -i "s|BRANCH_PLACEHOLDER|${{ env.BADGE_BRANCH }}|g" ${{ env.BADGE_DIR }}/README.md
|
||||||
|
sed -i "s|BADGE_DIR_PLACEHOLDER|${{ env.BADGE_DIR }}|g" ${{ env.BADGE_DIR }}/README.md
|
||||||
|
sed -i "s|RAW_URL_PLACEHOLDER|${{ env.RAW_URL_BASE }}|g" ${{ env.BADGE_DIR }}/README.md
|
||||||
|
|
||||||
|
# 添加语言统计表格
|
||||||
|
if [ -f /tmp/lang_summary.txt ] && [ -s /tmp/lang_summary.txt ]; then
|
||||||
|
cat >> ${{ env.BADGE_DIR }}/README.md << 'EOFTABLE'
|
||||||
|
| 语言 | 代码行数 | 文件数 | 占比 | 徽章 |
|
||||||
|
|------|----------|--------|------|------|
|
||||||
|
EOFTABLE
|
||||||
|
|
||||||
|
TOTAL_CODE=${{ steps.total.outputs.total_code }}
|
||||||
|
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
|
||||||
|
|
||||||
|
cat >> ${{ env.BADGE_DIR }}/README.md << EOFLANG
|
||||||
|
| **${display_name}** | ${formatted_lines} | ${file_count} | ${PERCENT}% |  |
|
||||||
|
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 "✅ 清理完成"
|
||||||
+20
@@ -0,0 +1,20 @@
|
|||||||
|
# ---> Vim
|
||||||
|
# Swap
|
||||||
|
[._]*.s[a-v][a-z]
|
||||||
|
!*.svg # comment out if you don't need vector files
|
||||||
|
[._]*.sw[a-p]
|
||||||
|
[._]s[a-rt-v][a-z]
|
||||||
|
[._]ss[a-gi-z]
|
||||||
|
[._]sw[a-p]
|
||||||
|
|
||||||
|
# Session
|
||||||
|
Session.vim
|
||||||
|
Sessionx.vim
|
||||||
|
|
||||||
|
# Temporary
|
||||||
|
.netrwhist
|
||||||
|
*~
|
||||||
|
# Auto-generated tag files
|
||||||
|
tags
|
||||||
|
# Persistent undo
|
||||||
|
[._]*.un~
|
||||||
+118
@@ -0,0 +1,118 @@
|
|||||||
|
# CHANGELOG
|
||||||
|
|
||||||
|
## :bookmark: 0.0.4
|
||||||
|
|
||||||
|
### :pencil: What's Changed
|
||||||
|
|
||||||
|
- :rocket: 优化bot名字,更具辨识度 ([4829434](https://git.mytsl.cn/csh/actions-template/commit/4829434408f46ebfad41293c46c9de1d94b157f3)) by @csh
|
||||||
|
- :recycle: 重构代码和`docker-runner`项目结构
|
||||||
|
:sparkles: 支持`docker`部署`archlinux`,预装`clang`跨平台编译工具链
|
||||||
|
([39820e6](https://git.mytsl.cn/csh/actions-template/commit/39820e656a9822e3b31df93d0abc33c02b2e56d1)) by @csh
|
||||||
|
- :bug: 修复`lsb_release`命令报错 ([0e89b21](https://git.mytsl.cn/csh/actions-template/commit/0e89b21c415bb62e02bace18038195c82d6374c7)) by @csh
|
||||||
|
- :bug: Bug修复 ([eaedcd3](https://git.mytsl.cn/csh/actions-template/commit/eaedcd3bb21e9ec8ed58e03b63ad85761a77cb48)) by @csh
|
||||||
|
|
||||||
|
### :busts_in_silhouette: Contributors
|
||||||
|
|
||||||
|
<a href="https://git.mytsl.cn/ci-bot">
|
||||||
|
<img src="https://git.mytsl.cn/ci-bot.png" alt="ci-bot" width="35" height="35" style="border-radius: 50%;" onerror="this.src='https://git.mytsl.cn/assets/img/avatar_default.png'" />
|
||||||
|
</a>
|
||||||
|
<a href="https://git.mytsl.cn/csh">
|
||||||
|
<img src="https://git.mytsl.cn/csh.png" alt="csh" width="35" height="35" style="border-radius: 50%;" onerror="this.src='https://git.mytsl.cn/assets/img/avatar_default.png'" />
|
||||||
|
</a>
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## :bookmark: 0.0.3
|
||||||
|
|
||||||
|
### :pencil: What's Changed
|
||||||
|
|
||||||
|
- :bug: 移除默认上传`CHANGELOG.md` ([9961226](https://git.mytsl.cn/csh/actions-template/commit/99612267047e4d5c48d55888eeb0d05ba12c5da1)) by @csh
|
||||||
|
- :recycle: 重构`changelog_and_release.yml` ([1f535e0](https://git.mytsl.cn/csh/actions-template/commit/1f535e0675efe166b5d38f0f0778f40d8663d318)) by @csh
|
||||||
|
- :bug: 修复commit信息提取错误 ([bf6698a](https://git.mytsl.cn/csh/actions-template/commit/bf6698ab3e7f2020dcee899f6a06166b0e6a5168)) by @csh
|
||||||
|
- 更新 CHANGELOG.md ([4ed8099](https://git.mytsl.cn/csh/actions-template/commit/4ed8099158f0f753b53a526ccba7dfc7aaad739a)) by @csh
|
||||||
|
- :bug: fix bug ([fc76a1f](https://git.mytsl.cn/csh/actions-template/commit/fc76a1f625c4c6cb42e50cadb487b7607a8d2f0a)) by @csh
|
||||||
|
- 更新 CHANGELOG.md [skip ci] ([7373553](https://git.mytsl.cn/csh/actions-template/commit/7373553270d20357a225aaf41334919086f7687d)) by @csh
|
||||||
|
- :bug: fix bug ([fa21511](https://git.mytsl.cn/csh/actions-template/commit/fa21511d1ab98e415036046bc6950f8a3b322f25)) by @csh
|
||||||
|
|
||||||
|
|
||||||
|
- :bug: 移除默认上传`CHANGELOG.md` ([9961226](https://git.mytsl.cn/csh/actions-template/commit/99612267047e4d5c48d55888eeb0d05ba12c5da1)) by @csh
|
||||||
|
- :recycle: 重构`changelog_and_release.yml` ([1f535e0](https://git.mytsl.cn/csh/actions-template/commit/1f535e0675efe166b5d38f0f0778f40d8663d318)) by @csh
|
||||||
|
- :bug: 修复commit信息提取错误 ([bf6698a](https://git.mytsl.cn/csh/actions-template/commit/bf6698ab3e7f2020dcee899f6a06166b0e6a5168)) by @csh
|
||||||
|
- 更新 CHANGELOG.md ([4ed8099](https://git.mytsl.cn/csh/actions-template/commit/4ed8099158f0f753b53a526ccba7dfc7aaad739a)) by @csh
|
||||||
|
- :bug: fix bug ([fc76a1f](https://git.mytsl.cn/csh/actions-template/commit/fc76a1f625c4c6cb42e50cadb487b7607a8d2f0a)) by @csh
|
||||||
|
- :bug: fix bug ([fa21511](https://git.mytsl.cn/csh/actions-template/commit/fa21511d1ab98e415036046bc6950f8a3b322f25)) by @csh
|
||||||
|
- :bug: 修复匹配正则问题 ([9a472a4](https://git.mytsl.cn/csh/actions-template/commit/9a472a42711746ecb739eee4475b4a4125c75312)) by @csh
|
||||||
|
- :bug: 匹配逻辑 ([160c5eb](https://git.mytsl.cn/csh/actions-template/commit/160c5ebade5bf9e1a1e99412026ccd7d1cca6996)) by @csh
|
||||||
|
- :bug: 修复过滤转义失败 ([e71d9d0](https://git.mytsl.cn/csh/actions-template/commit/e71d9d01fdbbd19c24dcf57382ec52fb42e228be)) by @csh
|
||||||
|
- :bug: ok了嘛 ([3a17dc4](https://git.mytsl.cn/csh/actions-template/commit/3a17dc4b52163fbea3c2fe60c617acfe7d8cd19c)) by @csh
|
||||||
|
- :bug: 不行就先放弃了 ([1b7eed5](https://git.mytsl.cn/csh/actions-template/commit/1b7eed5d93af889b7d8ed7d862899e36cbddaaf1)) by @csh
|
||||||
|
|
||||||
|
|
||||||
|
- :bug: 移除默认上传`CHANGELOG.md` ([9961226](https://git.mytsl.cn/csh/actions-template/commit/99612267047e4d5c48d55888eeb0d05ba12c5da1)) by @csh
|
||||||
|
- :recycle: 重构`changelog_and_release.yml` ([1f535e0](https://git.mytsl.cn/csh/actions-template/commit/1f535e0675efe166b5d38f0f0778f40d8663d318)) by @csh
|
||||||
|
- :bug: 修复commit信息提取错误 ([bf6698a](https://git.mytsl.cn/csh/actions-template/commit/bf6698ab3e7f2020dcee899f6a06166b0e6a5168)) by @csh
|
||||||
|
- 更新 CHANGELOG.md ([4ed8099](https://git.mytsl.cn/csh/actions-template/commit/4ed8099158f0f753b53a526ccba7dfc7aaad739a)) by @csh
|
||||||
|
- :bug: fix bug ([fc76a1f](https://git.mytsl.cn/csh/actions-template/commit/fc76a1f625c4c6cb42e50cadb487b7607a8d2f0a)) by @csh
|
||||||
|
- :bug: fix bug ([fa21511](https://git.mytsl.cn/csh/actions-template/commit/fa21511d1ab98e415036046bc6950f8a3b322f25)) by @csh
|
||||||
|
- :bug: 修复匹配正则问题 ([9a472a4](https://git.mytsl.cn/csh/actions-template/commit/9a472a42711746ecb739eee4475b4a4125c75312)) by @csh
|
||||||
|
- :bug: 匹配逻辑 ([160c5eb](https://git.mytsl.cn/csh/actions-template/commit/160c5ebade5bf9e1a1e99412026ccd7d1cca6996)) by @csh
|
||||||
|
- :bug: 修复过滤转义失败 ([e71d9d0](https://git.mytsl.cn/csh/actions-template/commit/e71d9d01fdbbd19c24dcf57382ec52fb42e228be)) by @csh
|
||||||
|
- :bug: ok了嘛 ([3a17dc4](https://git.mytsl.cn/csh/actions-template/commit/3a17dc4b52163fbea3c2fe60c617acfe7d8cd19c)) by @csh
|
||||||
|
- :bug: 不行就先放弃了 ([1b7eed5](https://git.mytsl.cn/csh/actions-template/commit/1b7eed5d93af889b7d8ed7d862899e36cbddaaf1)) by @csh
|
||||||
|
- :wrench: `docker`的默认配置变更 ([c81aac9](https://git.mytsl.cn/csh/actions-template/commit/c81aac970cd50f7a3a08ccb4d7790a374efae721)) by @csh
|
||||||
|
- :wrench: 工作流的bot名字变更为`ci-bot` ([49f11fb](https://git.mytsl.cn/csh/actions-template/commit/49f11fb2d814e1fc59f8b05120bdd57fa44b9bad)) by @csh
|
||||||
|
|
||||||
|
### :busts_in_silhouette: Contributors
|
||||||
|
|
||||||
|
<a href="https://git.mytsl.cn/csh">
|
||||||
|
<img src="https://git.mytsl.cn/csh.png" alt="csh" width="35" height="35" style="border-radius: 50%;" onerror="this.src='https://git.mytsl.cn/assets/img/avatar_default.png'" />
|
||||||
|
</a>
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## :bookmark: 0.0.2
|
||||||
|
|
||||||
|
*Released on 2025-11-02*
|
||||||
|
|
||||||
|
### :pencil: What's Changed
|
||||||
|
|
||||||
|
- :art: 代码格式化 ([`ec5785c`](https://github.com/csh/actions-template/commit/ec5785cc6af3267285623090e19b5c215d89d37f))
|
||||||
|
- :bug: 修复tag获取错误问题 ([`84e2751`](https://github.com/csh/actions-template/commit/84e275166844d9fd410a7aba3e32807683784970))
|
||||||
|
- :bug: 修复bug ([`0bb627f`](https://github.com/csh/actions-template/commit/0bb627fd34ce47e2baaf9b3856d12564da2423d9))
|
||||||
|
- :recycle: 重构`changelog_and_release` ([`9cde246`](https://github.com/csh/actions-template/commit/9cde246b208afe25ac6ecca67ecf4e7ad2e56ecc))
|
||||||
|
- :bug: 修复日期 ([`aaeed0d`](https://github.com/csh/actions-template/commit/aaeed0d9197af8f9c732ab9e4a2ae5dc99a40c00))
|
||||||
|
- :bug: 修复`update_state_badge.yml`自动生成的`README`日期错误 ([`f57e698`](https://github.com/csh/actions-template/commit/f57e6984c048f6dbfc5e8083dd68c8910a923487))
|
||||||
|
- :memo: 更新`WORKFLOW`说明 ([`2ac94af`](https://github.com/csh/actions-template/commit/2ac94aff1c499ca12bbe29652532bd4a8bef425d))
|
||||||
|
- :bug: help me ([`d7a0c7a`](https://github.com/csh/actions-template/commit/d7a0c7a85b04a3177790a8a74ebb1c5154e136de))
|
||||||
|
- :bug: 继续修修 ([`948bcfa`](https://github.com/csh/actions-template/commit/948bcfa7875b0276b649851c7445367b13c95438))
|
||||||
|
- :bug: 继续修复测试 ([`23a7fb5`](https://github.com/csh/actions-template/commit/23a7fb5a285c3f6f16071c82f6ba24137507a10d))
|
||||||
|
- :bug: 修`update_stats_badge.yml`,还没跑起来 ([`b616573`](https://github.com/csh/actions-template/commit/b616573bfd8374a8b007e8066cfcd053191d9717))
|
||||||
|
- :bug: 修复`update_stats_badge.yml` 克隆bug ([`5b3629f`](https://github.com/csh/actions-template/commit/5b3629fb732ecfdd78496736f1f861ec0f8d9eee))
|
||||||
|
- :bug: 修复token配置错误 ([`38e6c82`](https://github.com/csh/actions-template/commit/38e6c823948662e18e60bdc483112a2957352ffb))
|
||||||
|
- :bug: 修复runs-on错误 ([`376c1a2`](https://github.com/csh/actions-template/commit/376c1a28666378ff11c7d0669a61c4c980ca6261))
|
||||||
|
- :sparkles: 新增:代码统计徽章 action: `update_stats_badge.yml` ([`d5a7d55`](https://github.com/csh/actions-template/commit/d5a7d5506ec0f7d128c60f908bbd17198308c587))
|
||||||
|
- :demo: 文档更新 ([`c0aef0f`](https://github.com/csh/actions-template/commit/c0aef0f5316aa0fba1ae5686b8d7cc8c770e816e))
|
||||||
|
- :package: workflows的文件进行更名,并且调整后缀为`yml` ([`a21adb9`](https://github.com/csh/actions-template/commit/a21adb9fcc79839ddd717f862abe69e7e232fbca))
|
||||||
|
- :wastebasket: 移除发布Release时候自动上传CHANGELOG.md ([`8971cbf`](https://github.com/csh/actions-template/commit/8971cbffc3023891852a14d9917c8b9b2b7f8272))
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## :bookmark: 0.0.1
|
||||||
|
|
||||||
|
### :pencil: What's Changed
|
||||||
|
|
||||||
|
- :wastebasket: 删除CHANGELOG,让工作流自动执行 ([d50ee5d](https://git.mytsl.cn/csh/actions-template/commit/d50ee5d)) by @csh
|
||||||
|
- :wrench: gitignore新增CHANGELOG.md ([29cd19e](https://git.mytsl.cn/csh/actions-template/commit/29cd19e)) by @csh
|
||||||
|
- :bug: 修复生成的CHANGELOG格式不对
|
||||||
|
:sparkles: 过滤commit新增`Initial commit`
|
||||||
|
:art: 代码格式化 ([b651daf](https://git.mytsl.cn/csh/actions-template/commit/b651daf)) by @csh
|
||||||
|
- :wastebasket: gitignore移除CHANGELOG.md,会导致工作流提交失败 ([27f35a6](https://git.mytsl.cn/csh/actions-template/commit/27f35a6)) by @csh
|
||||||
|
|
||||||
|
### :busts_in_silhouette: Contributors
|
||||||
|
|
||||||
|
<a href="https://git.mytsl.cn/csh">
|
||||||
|
<img src="https://git.mytsl.cn/csh.png" alt="csh" width="35" height="35" style="border-radius: 50%;" onerror="this.src='https://git.mytsl.cn/assets/img/avatar_default.png'" />
|
||||||
|
</a>
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
+606
@@ -0,0 +1,606 @@
|
|||||||
|
# 🚀 Gitea Runner Docker 部署教程
|
||||||
|
|
||||||
|
## 📋 目录
|
||||||
|
|
||||||
|
- [简介](#-简介)
|
||||||
|
- [目录结构](#-目录结构)
|
||||||
|
- [版本选择](#-版本选择)
|
||||||
|
- [部署步骤](#-部署步骤)
|
||||||
|
- [管理命令](#-管理命令)
|
||||||
|
- [Buildx 多架构构建示例](#-buildx-多架构构建示例)
|
||||||
|
- [版本对比](#️-版本对比)
|
||||||
|
- [常见问题](#-常见问题)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 💡 简介
|
||||||
|
|
||||||
|
Gitea Runner 是 Gitea 的 CI/CD 执行器,类似于 GitLab Runner 或 GitHub Actions Runner,用于执行 Gitea Actions 工作流。
|
||||||
|
|
||||||
|
本项目提供了标准版和 Buildx 版两种部署方案,通过预设配置快速部署。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 📂 目录结构
|
||||||
|
|
||||||
|
```txt
|
||||||
|
docker-runner/
|
||||||
|
├── common/ # 通用脚本(所有版本共用)
|
||||||
|
│ ├── check_crlf.sh # Windows 换行符检查工具
|
||||||
|
│ ├── entrypoint.sh # 容器启动脚本
|
||||||
|
│ ├── setup.sh # Runner 安装脚本
|
||||||
|
│ ├── register.sh # Runner 注册脚本
|
||||||
|
│ └── manage.sh # Runner 管理脚本
|
||||||
|
│
|
||||||
|
└── presets/ # 预设配置(选择一个使用)
|
||||||
|
├── standard-ubuntu-22/ # 标准版 (Ubuntu 22.04)
|
||||||
|
│ ├── Dockerfile
|
||||||
|
│ └── docker-compose.yml
|
||||||
|
├── buildx-ubuntu-22/ # Buildx 版 (Ubuntu 22.04)
|
||||||
|
│ ├── Dockerfile
|
||||||
|
│ └── docker-compose.yml
|
||||||
|
└── buildx-archlinux/ # Buildx 版 (Arch Linux)
|
||||||
|
├── Dockerfile
|
||||||
|
└── docker-compose.yml
|
||||||
|
```
|
||||||
|
|
||||||
|
**说明:**
|
||||||
|
|
||||||
|
- `common/` 目录中的脚本由所有版本共享,通过 docker-compose.yml 挂载到容器
|
||||||
|
- `presets/` 目录中每个子目录是一个完整的预设配置,包含 Dockerfile 和 docker-compose.yml
|
||||||
|
- 数据持久化在 `runner-data/` 目录(自动创建),包含 runner 配置、缓存和 act_runner 二进制文件
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🎯 版本选择
|
||||||
|
|
||||||
|
### 📦 标准版(推荐)
|
||||||
|
|
||||||
|
**适合场景:**
|
||||||
|
|
||||||
|
- ✅ 大多数日常使用场景
|
||||||
|
- ✅ 只需在当前架构上运行应用
|
||||||
|
- ✅ 简单的 CI/CD 流程
|
||||||
|
- ✅ 不需要构建多架构容器镜像
|
||||||
|
|
||||||
|
**特点:**
|
||||||
|
|
||||||
|
- 🪶 轻量级,镜像体积约 400MB
|
||||||
|
- ⚡ 配置简单,启动快速(5-10 秒)
|
||||||
|
- 🔒 无需特权模式,更安全
|
||||||
|
- 🎯 易于维护
|
||||||
|
|
||||||
|
**预设:** `presets/standard-ubuntu-22/`
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 🚀 Buildx 多架构版
|
||||||
|
|
||||||
|
**适合场景:**
|
||||||
|
|
||||||
|
- ✅ 需要构建 arm64 + amd64 双架构镜像
|
||||||
|
- ✅ 发布容器镜像到公共仓库
|
||||||
|
- ✅ 跨平台应用开发和测试
|
||||||
|
- ✅ 高级 CI/CD 需求
|
||||||
|
|
||||||
|
**特点:**
|
||||||
|
|
||||||
|
- 🌐 支持 Docker Buildx 多架构构建
|
||||||
|
- 🔧 内置 QEMU 跨架构模拟
|
||||||
|
- 🤖 自动配置 Buildx builder
|
||||||
|
- ⚠️ 需要特权模式和 Docker socket
|
||||||
|
|
||||||
|
**预设选择:**
|
||||||
|
|
||||||
|
- `presets/buildx-ubuntu-22/` - Ubuntu 22.04 基础(推荐)
|
||||||
|
- `presets/buildx-archlinux/` - Arch Linux 滚动更新版本
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🚀 部署步骤
|
||||||
|
|
||||||
|
### 标准版部署
|
||||||
|
|
||||||
|
#### 1. 进入预设目录
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cd docker-runner/presets/standard-ubuntu-22/
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 2. (可选)检查换行符
|
||||||
|
|
||||||
|
如果从 Windows 复制文件,建议检查换行符:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
../../common/check_crlf.sh
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 3. 构建并启动容器
|
||||||
|
|
||||||
|
```bash
|
||||||
|
docker-compose build
|
||||||
|
docker-compose up -d
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 4. 安装 Runner
|
||||||
|
|
||||||
|
```bash
|
||||||
|
docker-compose exec gitea-runner /data/setup.sh
|
||||||
|
```
|
||||||
|
|
||||||
|
按照提示选择版本(默认 0.2.13)和架构(自动检测)。
|
||||||
|
|
||||||
|
#### 5. 注册 Runner
|
||||||
|
|
||||||
|
```bash
|
||||||
|
docker-compose exec gitea-runner /data/register.sh
|
||||||
|
```
|
||||||
|
|
||||||
|
输入你的 Gitea 实例 URL 和注册令牌。
|
||||||
|
|
||||||
|
Runner 注册后会自动启动,无需重启容器。
|
||||||
|
|
||||||
|
#### 6. 验证运行状态
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 查看容器日志
|
||||||
|
docker-compose logs -f
|
||||||
|
|
||||||
|
# 查看 runner 状态
|
||||||
|
docker-compose exec gitea-runner /data/manage.sh status
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### Buildx 版部署
|
||||||
|
|
||||||
|
#### 1. 选择并进入预设目录
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Ubuntu 22.04 版本(推荐)
|
||||||
|
cd docker-runner/presets/buildx-ubuntu-22/
|
||||||
|
|
||||||
|
# 或 Arch Linux 版本
|
||||||
|
cd docker-runner/presets/buildx-archlinux/
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 2. (可选)配置代理
|
||||||
|
|
||||||
|
如果需要代理,编辑 `docker-compose.yml` 取消注释并修改代理地址:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
environment:
|
||||||
|
- http_proxy=http://host.docker.internal:20122
|
||||||
|
- https_proxy=http://host.docker.internal:20122
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 3. 构建并启动
|
||||||
|
|
||||||
|
```bash
|
||||||
|
docker-compose build
|
||||||
|
docker-compose up -d
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 4. 验证 Buildx 初始化
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 查看日志,应该看到:
|
||||||
|
# ✓ Docker daemon is ready
|
||||||
|
# ✓ arm64 support verified
|
||||||
|
# ✓ amd64 support verified
|
||||||
|
# ✓ Buildx configured successfully!
|
||||||
|
docker-compose logs -f
|
||||||
|
|
||||||
|
# 进入容器验证
|
||||||
|
docker-compose exec gitea-runner docker buildx ls
|
||||||
|
# 应该看到 gitea-multiarch builder
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 5. 安装和注册
|
||||||
|
|
||||||
|
```bash
|
||||||
|
docker-compose exec gitea-runner /data/setup.sh
|
||||||
|
docker-compose exec gitea-runner /data/register.sh
|
||||||
|
```
|
||||||
|
|
||||||
|
Runner 注册后会自动启动。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🔧 管理命令
|
||||||
|
|
||||||
|
所有版本的管理命令相同(脚本位于 `common/` 目录):
|
||||||
|
|
||||||
|
### 查看状态
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 列出所有 runners
|
||||||
|
docker-compose exec gitea-runner /data/manage.sh list
|
||||||
|
|
||||||
|
# 查看所有 runners 状态
|
||||||
|
docker-compose exec gitea-runner /data/manage.sh status
|
||||||
|
```
|
||||||
|
|
||||||
|
### 日志管理
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 查看日志(最后 50 行)
|
||||||
|
docker-compose exec gitea-runner /data/manage.sh logs <runner-name>
|
||||||
|
|
||||||
|
# 指定行数
|
||||||
|
docker-compose exec gitea-runner /data/manage.sh logs <runner-name> 100
|
||||||
|
|
||||||
|
# 实时跟踪日志
|
||||||
|
docker-compose exec gitea-runner /data/manage.sh follow <runner-name>
|
||||||
|
```
|
||||||
|
|
||||||
|
### Runner 控制
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 启动 runner
|
||||||
|
docker-compose exec gitea-runner /data/manage.sh start <runner-name>
|
||||||
|
|
||||||
|
# 停止 runner
|
||||||
|
docker-compose exec gitea-runner /data/manage.sh stop <runner-name>
|
||||||
|
|
||||||
|
# 重启 runner
|
||||||
|
docker-compose exec gitea-runner /data/manage.sh restart <runner-name>
|
||||||
|
|
||||||
|
# 删除 runner
|
||||||
|
docker-compose exec gitea-runner /data/manage.sh delete <runner-name>
|
||||||
|
```
|
||||||
|
|
||||||
|
### 添加多个 Runners
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 注册新的 runner(使用不同名称)
|
||||||
|
docker-compose exec gitea-runner /data/register.sh
|
||||||
|
```
|
||||||
|
|
||||||
|
### 交互式管理
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 运行交互式菜单
|
||||||
|
docker-compose exec gitea-runner /data/manage.sh
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🔧 Buildx 多架构构建示例
|
||||||
|
|
||||||
|
### 示例 1: 基础构建
|
||||||
|
|
||||||
|
在 Gitea Actions workflow 中使用:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
name: Multi-Arch Build
|
||||||
|
|
||||||
|
on: [push]
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
build:
|
||||||
|
runs-on: ubuntu-22.04
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v3
|
||||||
|
|
||||||
|
- name: Set up QEMU
|
||||||
|
uses: docker/setup-qemu-action@v2
|
||||||
|
|
||||||
|
- name: Set up Buildx
|
||||||
|
uses: docker/setup-buildx-action@v2
|
||||||
|
|
||||||
|
- name: Build and Push
|
||||||
|
uses: docker/build-push-action@v4
|
||||||
|
with:
|
||||||
|
context: .
|
||||||
|
platforms: linux/amd64,linux/arm64
|
||||||
|
tags: myapp:latest
|
||||||
|
push: true
|
||||||
|
```
|
||||||
|
|
||||||
|
### 示例 2: Go 应用优化构建
|
||||||
|
|
||||||
|
使用交叉编译可以大幅提升构建速度:
|
||||||
|
|
||||||
|
```dockerfile
|
||||||
|
FROM --platform=$BUILDPLATFORM golang:1.21 AS builder
|
||||||
|
ARG TARGETOS TARGETARCH
|
||||||
|
WORKDIR /app
|
||||||
|
COPY . .
|
||||||
|
RUN CGO_ENABLED=0 GOOS=$TARGETOS GOARCH=$TARGETARCH go build -o app
|
||||||
|
|
||||||
|
FROM alpine
|
||||||
|
COPY --from=builder /app/app /app
|
||||||
|
CMD ["/app"]
|
||||||
|
```
|
||||||
|
|
||||||
|
### 示例 3: 启用构建缓存
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
- name: Build with cache
|
||||||
|
uses: docker/build-push-action@v4
|
||||||
|
with:
|
||||||
|
context: .
|
||||||
|
platforms: linux/amd64,linux/arm64
|
||||||
|
cache-from: type=registry,ref=myimage:buildcache
|
||||||
|
cache-to: type=registry,ref=myimage:buildcache,mode=max
|
||||||
|
tags: myimage:latest
|
||||||
|
push: true
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## ⚖️ 版本对比
|
||||||
|
|
||||||
|
### 功能对比表
|
||||||
|
|
||||||
|
| 功能 | 标准版 | Buildx 版 |
|
||||||
|
| ---------------- | ------- | --------- |
|
||||||
|
| 基础 Runner 功能 | ✅ | ✅ |
|
||||||
|
| 当前架构原生构建 | ✅ | ✅ |
|
||||||
|
| 跨架构模拟构建 | ❌ | ✅ |
|
||||||
|
| 多架构镜像 | ❌ | ✅ |
|
||||||
|
| Buildx 支持 | ❌ | ✅ |
|
||||||
|
| QEMU 内置 | ❌ | ✅ |
|
||||||
|
| 特权模式要求 | ❌ | ✅ 必需 |
|
||||||
|
| Docker socket | 可选 | ✅ 必需 |
|
||||||
|
| 镜像大小 | ~400MB | ~850MB |
|
||||||
|
| 启动时间 | 5-10 秒 | 15-20 秒 |
|
||||||
|
| 复杂度 | 简单 | 中等 |
|
||||||
|
|
||||||
|
### 性能对比(Buildx 版)
|
||||||
|
|
||||||
|
在 ARM64 主机上使用 Buildx 构建不同架构的性能:
|
||||||
|
|
||||||
|
| 项目类型 | ARM64(原生) | AMD64(QEMU) | 双架构并行 |
|
||||||
|
| ------------ | ----------- | ----------- | ---------- |
|
||||||
|
| Alpine 镜像 | 5s | 15s | 18s |
|
||||||
|
| Node.js 应用 | 2min | 8min | 9min |
|
||||||
|
| Go 应用 | 1.5min | 6min | 7min |
|
||||||
|
| Go(交叉编译) | 1min | 1.5min | 2min |
|
||||||
|
|
||||||
|
**关键发现:**
|
||||||
|
|
||||||
|
- 🏆 原生架构构建最快
|
||||||
|
- 🐌 跨架构模拟慢 3-4 倍(QEMU)
|
||||||
|
- ⚡ 交叉编译比纯 QEMU 快 4 倍
|
||||||
|
- 💾 使用缓存可提速 80-90%
|
||||||
|
|
||||||
|
### 🎯 选择建议
|
||||||
|
|
||||||
|
#### 选择标准版
|
||||||
|
|
||||||
|
- ✅ 只需要在当前架构上运行应用
|
||||||
|
- ✅ 不需要发布多架构镜像
|
||||||
|
- ✅ 追求简单和轻量
|
||||||
|
- ✅ 不需要 Docker-in-Docker
|
||||||
|
|
||||||
|
#### 选择 Buildx 版
|
||||||
|
|
||||||
|
- ✅ 需要构建多架构镜像(如 amd64 + arm64)
|
||||||
|
- ✅ 发布到 Docker Hub 等公共仓库
|
||||||
|
- ✅ 跨平台应用开发
|
||||||
|
- ✅ CI/CD 需要多架构支持
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## ❓ 常见问题
|
||||||
|
|
||||||
|
### Q1: 如何更新 Runner 版本?
|
||||||
|
|
||||||
|
```bash
|
||||||
|
docker-compose exec gitea-runner /data/setup.sh
|
||||||
|
# 脚本会检测到已安装并询问是否升级
|
||||||
|
```
|
||||||
|
|
||||||
|
### Q2: 如何添加多个 Runners?
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 多次运行注册脚本,每次使用不同名称
|
||||||
|
docker-compose exec gitea-runner /data/register.sh
|
||||||
|
|
||||||
|
# 查看所有 runners
|
||||||
|
docker-compose exec gitea-runner /data/manage.sh list
|
||||||
|
```
|
||||||
|
|
||||||
|
### Q3: 容器启动失败 "exec format error"
|
||||||
|
|
||||||
|
**原因:** Windows 换行符问题(CRLF vs LF)
|
||||||
|
|
||||||
|
**解决:**
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 方法 1: 使用提供的检查工具
|
||||||
|
cd docker-runner/presets/<your-preset>/
|
||||||
|
../../common/check_crlf.sh
|
||||||
|
|
||||||
|
# 方法 2: 手动转换
|
||||||
|
sed -i 's/\r$//' ../../common/*.sh
|
||||||
|
|
||||||
|
# 重新构建
|
||||||
|
docker-compose down
|
||||||
|
docker-compose build --no-cache
|
||||||
|
docker-compose up -d
|
||||||
|
```
|
||||||
|
|
||||||
|
### Q4: 如何完全重置?
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 停止并删除容器和卷
|
||||||
|
docker-compose down -v
|
||||||
|
|
||||||
|
# 删除数据目录
|
||||||
|
rm -rf runner-data
|
||||||
|
|
||||||
|
# 重新构建
|
||||||
|
docker-compose build --no-cache
|
||||||
|
docker-compose up -d
|
||||||
|
```
|
||||||
|
|
||||||
|
### Q5: 如何查看日志?
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 容器日志
|
||||||
|
docker-compose logs -f
|
||||||
|
|
||||||
|
# Runner 日志
|
||||||
|
docker-compose exec gitea-runner /data/manage.sh logs <runner-name>
|
||||||
|
|
||||||
|
# 实时跟踪日志
|
||||||
|
docker-compose exec gitea-runner /data/manage.sh follow <runner-name>
|
||||||
|
```
|
||||||
|
|
||||||
|
### Q6: Buildx 版 - 构建速度慢?
|
||||||
|
|
||||||
|
**优化方法:**
|
||||||
|
|
||||||
|
#### 1. 启用缓存
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
- name: Build with cache
|
||||||
|
uses: docker/build-push-action@v4
|
||||||
|
with:
|
||||||
|
cache-from: type=registry,ref=myimage:buildcache
|
||||||
|
cache-to: type=registry,ref=myimage:buildcache,mode=max
|
||||||
|
platforms: linux/amd64,linux/arm64
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 2. 使用交叉编译
|
||||||
|
|
||||||
|
对于 Go、Rust 等支持交叉编译的语言,优先使用交叉编译而非 QEMU 模拟:
|
||||||
|
|
||||||
|
```dockerfile
|
||||||
|
FROM --platform=$BUILDPLATFORM golang:1.21 AS builder
|
||||||
|
ARG TARGETOS TARGETARCH
|
||||||
|
RUN CGO_ENABLED=0 GOOS=$TARGETOS GOARCH=$TARGETARCH go build -o app
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 3. 按需构建
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
# 开发分支只构建当前架构,生产分支构建双架构
|
||||||
|
platforms: ${{ github.ref == 'refs/heads/main' && 'linux/amd64,linux/arm64' || 'linux/arm64' }}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Q7: Buildx 版 - 如何验证 Buildx?
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 进入容器
|
||||||
|
docker-compose exec gitea-runner bash
|
||||||
|
|
||||||
|
# 检查 builder
|
||||||
|
docker buildx ls
|
||||||
|
|
||||||
|
# 测试构建
|
||||||
|
echo 'FROM alpine' | docker buildx build --platform linux/amd64,linux/arm64 -
|
||||||
|
```
|
||||||
|
|
||||||
|
### Q8: 如何清理 Docker 资源?
|
||||||
|
|
||||||
|
#### 清理未使用的镜像
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 清理悬空镜像(dangling images)
|
||||||
|
docker image prune
|
||||||
|
|
||||||
|
# 清理所有未使用的镜像
|
||||||
|
docker image prune -a
|
||||||
|
|
||||||
|
# 查看镜像占用空间
|
||||||
|
docker system df
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 清理 Buildx 缓存(仅 Buildx 版)
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 进入容器
|
||||||
|
docker-compose exec gitea-runner bash
|
||||||
|
|
||||||
|
# 清理构建缓存(保留 builder)
|
||||||
|
docker buildx prune
|
||||||
|
|
||||||
|
# 清理所有构建缓存
|
||||||
|
docker buildx prune -a -f
|
||||||
|
|
||||||
|
# 删除 builder(会自动清理相关容器和镜像)
|
||||||
|
docker buildx rm gitea-multiarch
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 完整清理流程
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 1. 停止所有容器
|
||||||
|
docker-compose down
|
||||||
|
|
||||||
|
# 2. 清理 Buildx(如果使用 Buildx 版)
|
||||||
|
docker-compose exec gitea-runner docker buildx rm gitea-multiarch
|
||||||
|
|
||||||
|
# 3. 清理未使用的镜像
|
||||||
|
docker image prune -a
|
||||||
|
|
||||||
|
# 4. 清理系统(慎用!会清理所有未使用资源)
|
||||||
|
docker system prune -a --volumes
|
||||||
|
|
||||||
|
# 5. 查看清理效果
|
||||||
|
docker system df
|
||||||
|
```
|
||||||
|
|
||||||
|
⚠️ **注意:** `docker system prune -a` 会删除所有未使用的镜像,包括其他项目的。
|
||||||
|
|
||||||
|
### Q9: 数据持久化在哪里?
|
||||||
|
|
||||||
|
所有数据持久化在 `runner-data/` 目录:
|
||||||
|
|
||||||
|
```txt
|
||||||
|
runner-data/
|
||||||
|
├── bin/
|
||||||
|
│ └── act_runner # Runner 可执行文件(持久化)
|
||||||
|
├── runners/ # Runner 配置目录
|
||||||
|
│ └── <runner-name>/
|
||||||
|
│ ├── .runner # 注册信息
|
||||||
|
│ ├── config.yaml # 配置文件
|
||||||
|
│ └── cache/ # 构建缓存
|
||||||
|
└── buildx/ # Buildx 配置(仅 Buildx 版)
|
||||||
|
└── .configured
|
||||||
|
```
|
||||||
|
|
||||||
|
容器重启或重建后,数据不会丢失。
|
||||||
|
|
||||||
|
### Q10: 如何切换不同预设?
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 1. 停止当前容器
|
||||||
|
cd docker-runner/presets/<current-preset>/
|
||||||
|
docker-compose down
|
||||||
|
|
||||||
|
# 2. 切换到新预设
|
||||||
|
cd ../buildx-ubuntu-22/
|
||||||
|
|
||||||
|
# 3. 复制数据目录(可选,保留旧数据)
|
||||||
|
cp -r ../standard-ubuntu-22/runner-data .
|
||||||
|
|
||||||
|
# 4. 启动新预设
|
||||||
|
docker-compose build
|
||||||
|
docker-compose up -d
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 📚 参考资源
|
||||||
|
|
||||||
|
- 📖 [Gitea Actions 官方文档](https://docs.gitea.com/usage/actions/overview)
|
||||||
|
- 🚀 [Gitea Runner 下载](https://dl.gitea.com/act_runner/)
|
||||||
|
- 🐳 [Docker Buildx 文档](https://docs.docker.com/reference/cli/docker/buildx/)
|
||||||
|
- 🔧 [Act Runner GitHub](https://gitea.com/gitea/act_runner)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 💬 反馈与支持
|
||||||
|
|
||||||
|
如果你在使用过程中遇到问题,欢迎:
|
||||||
|
|
||||||
|
- 📝 提交 Issue
|
||||||
|
- 💡 分享你的使用经验
|
||||||
|
- 🌟 给项目点个 Star
|
||||||
|
|
||||||
|
---
|
||||||
@@ -1,50 +1,48 @@
|
|||||||
# 📊 代码统计详细报告
|
# 🎯 Gitea Runner Template
|
||||||
|
|
||||||
> 此分支由 Gitea Actions 自动生成和维护
|
[](https://www.docker.com/)
|
||||||
>
|
|
||||||
> ⚠️ **请勿手动修改此分支的内容!**
|
|
||||||
>
|
|
||||||
> 🤖 由 Gitea Actions 自动生成
|
|
||||||
>
|
|
||||||
> 📅 更新时间: 2026-07-21 03:15:02 UTC
|
|
||||||
|
|
||||||
## 📈 总体统计
|
> 🚀 Gitea Runner Docker 部署模板 + Actions Workflow 示例 + 文档规范
|
||||||
|
|
||||||
| 统计项 | 数值 | 徽章 |
|
## 📖 项目简介
|
||||||
|--------|------|------|
|
|
||||||
| 💻 总代码行数 | **4,490** 行 |  |
|
|
||||||
| 📁 总文件数 | **26** 个 |  |
|
|
||||||
| 🌐 语言种类 | **3** 种 |  |
|
|
||||||
|
|
||||||
## 🌈 语言分布
|
这是一个完整的 Gitea Runner 模板项目,提供:
|
||||||
|
|
||||||
| 语言 | 代码行数 | 文件数 | 占比 | 徽章 |
|
- 🐳 **Docker 部署方案**:开箱即用的 Runner 容器化部署
|
||||||
|------|----------|--------|------|------|
|
- 📝 **Workflow 示例**:自动化 CHANGELOG 和 Release 工作流
|
||||||
| **YAML** | 2,064 | 7 | 46.0% |  |
|
- 📚 **文档规范**:统一的文档格式和版本管理规范
|
||||||
| **Shell** | 1,251 | 6 | 27.9% |  |
|
- 🔧 **配置指南**:详细的配置说明和最佳实践
|
||||||
| **Python** | 218 | 1 | 4.9% |  |
|
|
||||||
|
## 📂 文档导航
|
||||||
|
|
||||||
|
### 🚀 Runner
|
||||||
|
|
||||||
|
#### [DEPLOYMENT.md](./DEPLOYMENT.md)
|
||||||
|
|
||||||
|
**Gitea Runner Docker 部署完整教程**
|
||||||
|
|
||||||
|
包含内容:
|
||||||
|
|
||||||
|
- 📦 标准版 vs Buildx 多架构版选择
|
||||||
|
- 📝 Dockerfile 和 docker-compose.yml 配置
|
||||||
|
- 🔧 安装、注册、管理脚本详解
|
||||||
|
- ⚙️ 完整的部署流程
|
||||||
|
- ❓ 常见问题和故障排除
|
||||||
|
|
||||||
|
👉 **完整的 Runner 部署教程,从零开始搭建**
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## ⚙️ 配置说明
|
### 📋 [Workflow](./WORKFLOW.md)
|
||||||
|
|
||||||
### Token 配置
|
**Gitea Actions 自动化工作流示例**
|
||||||
|
|
||||||
- 当前使用: **WORKFLOW**
|
包含内容:
|
||||||
- 需要在 Settings -> Actions -> Secrets 中配置 `WORKFLOW`
|
|
||||||
|
|
||||||
### 排除规则
|
- 💡 工作流配置说明
|
||||||
|
- 🔧 如何使用和定制
|
||||||
|
- 🔄 案例:`changelog_and_release.yml` - 自动更新 CHANGELOG 和自动创建 Release
|
||||||
|
|
||||||
当前排除的目录:
|
👉 **实用的 Actions 工作流,可直接复制使用**
|
||||||
```
|
|
||||||
node_modules,dist,build,out,target,vendor,.venv,venv,__pycache__,.git,.github
|
|
||||||
```
|
|
||||||
|
|
||||||
### 阈值设置
|
|
||||||
|
|
||||||
- 最小代码行数阈值: **10** 行
|
|
||||||
- 低于此阈值的语言不会生成徽章
|
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
*📊 统计仓库:`csh/actions-template`*
|
|
||||||
|
|||||||
+163
@@ -0,0 +1,163 @@
|
|||||||
|
# Workflow
|
||||||
|
|
||||||
|
本目录包含 Gitea Actions 的自动化工作流示例,展示如何使用 Gitea Actions 实现 CI/CD 自动化。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 📂 文件结构
|
||||||
|
|
||||||
|
```txt
|
||||||
|
.gitea/workflows/
|
||||||
|
├── changelog-and-release.yml # CHANGELOG 生成 + Release 创建
|
||||||
|
├── update_stats_badge.yml # 代码行数的统计
|
||||||
|
└── ... # 更多 workflow 待添加
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🎯 功能列表
|
||||||
|
|
||||||
|
### ✅ 已实现
|
||||||
|
|
||||||
|
#### 1. 📦 自动发布工作流 (`changelog-and-release.yml`)
|
||||||
|
|
||||||
|
**功能**:在推送 tag 时自动生成 CHANGELOG 并创建 Release
|
||||||
|
|
||||||
|
**特性**:
|
||||||
|
|
||||||
|
- 🏷️ 自动识别语义版本号(SemVer)
|
||||||
|
- 📝 智能生成 CHANGELOG 条目
|
||||||
|
- 🔄 支持多个开发版本内容叠加
|
||||||
|
- 👥 自动提取贡献者列表
|
||||||
|
- 🚀 创建 GitHub/Gitea Release
|
||||||
|
- 📎 上传附件到 Release
|
||||||
|
- 🏷️ 自动识别 Pre-release 标记
|
||||||
|
|
||||||
|
**触发方式**:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
git tag 1.0.0
|
||||||
|
git push origin 1.0.0
|
||||||
|
```
|
||||||
|
|
||||||
|
**文件**:[changelog-and-release.yml](.gitea/workflows/changelog_and_release.yml)
|
||||||
|
|
||||||
|
💡 **详细配置**:查看 `changelog-and-release.yml` 文件顶部的 `env` 区域,所有配置项都有详细注释说明
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
#### 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引用格式**: ``
|
||||||
|
|
||||||
|
💡 **详细配置**:查看 `update-stats-badge.yml` 文件顶部的 `env` 区域,包含语言分组、颜色、排除目录等配置
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 🔜 待扩展
|
||||||
|
|
||||||
|
更多自动化场景:
|
||||||
|
|
||||||
|
- 🧪 **自动测试** - 推送代码时运行单元测试
|
||||||
|
- 🏗️ **自动构建** - 构建并发布 Docker 镜像
|
||||||
|
- 📊 **代码质量** - 运行代码检查和静态分析
|
||||||
|
- 🌐 **自动部署** - 部署到生产环境
|
||||||
|
- 📧 **通知集成** - 发送构建结果到 Slack/邮件
|
||||||
|
- 🔐 **安全扫描** - 依赖漏洞扫描
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## ❓ 常见问题
|
||||||
|
|
||||||
|
### Q1: 如何配置 Token?
|
||||||
|
|
||||||
|
**步骤**:
|
||||||
|
|
||||||
|
1. Gitea → 设置 → 应用 → 生成新令牌
|
||||||
|
2. 权限:勾选 **repo**
|
||||||
|
3. 仓库 → Settings → Actions → Secrets → 添加 Secret
|
||||||
|
4. 名称:`WORKFLOW`,值:你的 Token
|
||||||
|
|
||||||
|
💡 **提示**:一个 Token 即可完成所有操作(Git + API)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### Q2: `changelog_and_release` 没有触发?
|
||||||
|
|
||||||
|
**检查清单**:
|
||||||
|
|
||||||
|
- [ ] Workflow 文件在 `.gitea/workflows/` 目录
|
||||||
|
- [ ] 文件名正确(如 `changelog-and-release.yml`)
|
||||||
|
- [ ] Token 已正确配置(Secret 名称为 `WORKFLOW`)
|
||||||
|
- [ ] Tag 格式正确(数字开头,如 `1.0.0`)
|
||||||
|
- [ ] Gitea Actions 已启用
|
||||||
|
- [ ] Runner 正常运行
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### Q3: `changelog_and_release` 版本号格式有要求吗?
|
||||||
|
|
||||||
|
推荐使用**语义化版本号(SemVer)**:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
✅ 推荐格式:
|
||||||
|
1.0.0 # 正式版本
|
||||||
|
1.0.0-beta1 # 预发布版本
|
||||||
|
|
||||||
|
❌ 不推荐:
|
||||||
|
v1.0.0 # 不要使用 v 前缀
|
||||||
|
1.0.0-b1 # 后缀要完整
|
||||||
|
```
|
||||||
|
|
||||||
|
详细规范请参考 workflow 文件中的注释说明。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### Q4: 如何查看执行日志?
|
||||||
|
|
||||||
|
仓库 → Actions → 点击对应的 workflow 运行记录 → 查看详细日志
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### Q5: Token 权限不足怎么办?
|
||||||
|
|
||||||
|
确保 Token 具有以下权限:
|
||||||
|
|
||||||
|
- ✅ **repo** - 完整仓库访问权限
|
||||||
|
- 用于读取代码
|
||||||
|
- 用于推送提交
|
||||||
|
- 用于创建 Release
|
||||||
|
|
||||||
|
如果还是失败,尝试重新生成 Token。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🤝 贡献
|
||||||
|
|
||||||
|
欢迎提交更多实用的 Workflow 示例!
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 📄 许可 MIT
|
||||||
@@ -1,9 +0,0 @@
|
|||||||
<svg xmlns="http://www.w3.org/2000/svg" width="118" height="20" role="img" aria-label="语言: 3 种">
|
|
||||||
<title>语言: 3 种</title>
|
|
||||||
<rect width="118" height="20" rx="10" fill="#f6f8fa" stroke="#d0d7de" />
|
|
||||||
<rect x="64" y="3" width="44" height="14" rx="7" fill="#purple" />
|
|
||||||
<g text-anchor="middle" font-family="DejaVu Sans,Verdana,Geneva,sans-serif" font-size="11">
|
|
||||||
<text x="32.0" y="14" fill="#24292f">语言</text>
|
|
||||||
<text x="86.0" y="14" fill="#ffffff">3 种</text>
|
|
||||||
</g>
|
|
||||||
</svg>
|
|
||||||
|
Before Width: | Height: | Size: 495 B |
@@ -1,10 +0,0 @@
|
|||||||
<svg xmlns="http://www.w3.org/2000/svg" width="124" height="20" role="img" aria-label="Python: 218 行">
|
|
||||||
<title>Python: 218 行</title>
|
|
||||||
<rect width="62" height="20" fill="#555555" />
|
|
||||||
<rect x="62" width="62" height="20" fill="#3572A5" />
|
|
||||||
<rect width="124" height="20" rx="3" fill="transparent" />
|
|
||||||
<g fill="#ffffff" text-anchor="middle" font-family="DejaVu Sans,Verdana,Geneva,sans-serif" font-size="11">
|
|
||||||
<text x="31.0" y="14">Python</text>
|
|
||||||
<text x="93.0" y="14">218 行</text>
|
|
||||||
</g>
|
|
||||||
</svg>
|
|
||||||
|
Before Width: | Height: | Size: 508 B |
@@ -1,10 +0,0 @@
|
|||||||
<svg xmlns="http://www.w3.org/2000/svg" width="131" height="20" role="img" aria-label="Shell: 1,251 行">
|
|
||||||
<title>Shell: 1,251 行</title>
|
|
||||||
<rect width="55" height="20" fill="#555555" />
|
|
||||||
<rect x="55" width="76" height="20" fill="#4EAA25" />
|
|
||||||
<rect width="131" height="20" rx="3" fill="transparent" />
|
|
||||||
<g fill="#ffffff" text-anchor="middle" font-family="DejaVu Sans,Verdana,Geneva,sans-serif" font-size="11">
|
|
||||||
<text x="27.5" y="14">Shell</text>
|
|
||||||
<text x="93.0" y="14">1,251 行</text>
|
|
||||||
</g>
|
|
||||||
</svg>
|
|
||||||
|
Before Width: | Height: | Size: 511 B |
@@ -1,9 +0,0 @@
|
|||||||
<svg xmlns="http://www.w3.org/2000/svg" width="125" height="20" role="img" aria-label="文件: 26 个">
|
|
||||||
<title>文件: 26 个</title>
|
|
||||||
<rect width="125" height="20" rx="10" fill="#f6f8fa" stroke="#d0d7de" />
|
|
||||||
<rect x="64" y="3" width="51" height="14" rx="7" fill="#green" />
|
|
||||||
<g text-anchor="middle" font-family="DejaVu Sans,Verdana,Geneva,sans-serif" font-size="11">
|
|
||||||
<text x="32.0" y="14" fill="#24292f">文件</text>
|
|
||||||
<text x="89.5" y="14" fill="#ffffff">26 个</text>
|
|
||||||
</g>
|
|
||||||
</svg>
|
|
||||||
|
Before Width: | Height: | Size: 497 B |
@@ -1,9 +0,0 @@
|
|||||||
<svg xmlns="http://www.w3.org/2000/svg" width="146" height="20" role="img" aria-label="代码: 4,490 行">
|
|
||||||
<title>代码: 4,490 行</title>
|
|
||||||
<rect width="146" height="20" rx="10" fill="#f6f8fa" stroke="#d0d7de" />
|
|
||||||
<rect x="64" y="3" width="72" height="14" rx="7" fill="#blue" />
|
|
||||||
<g text-anchor="middle" font-family="DejaVu Sans,Verdana,Geneva,sans-serif" font-size="11">
|
|
||||||
<text x="32.0" y="14" fill="#24292f">代码</text>
|
|
||||||
<text x="100.0" y="14" fill="#ffffff">4,490 行</text>
|
|
||||||
</g>
|
|
||||||
</svg>
|
|
||||||
|
Before Width: | Height: | Size: 506 B |
@@ -1,10 +0,0 @@
|
|||||||
<svg xmlns="http://www.w3.org/2000/svg" width="124" height="20" role="img" aria-label="YAML: 2,064 行">
|
|
||||||
<title>YAML: 2,064 行</title>
|
|
||||||
<rect width="48" height="20" fill="#555555" />
|
|
||||||
<rect x="48" width="76" height="20" fill="#CB171E" />
|
|
||||||
<rect width="124" height="20" rx="3" fill="transparent" />
|
|
||||||
<g fill="#ffffff" text-anchor="middle" font-family="DejaVu Sans,Verdana,Geneva,sans-serif" font-size="11">
|
|
||||||
<text x="24.0" y="14">YAML</text>
|
|
||||||
<text x="86.0" y="14">2,064 行</text>
|
|
||||||
</g>
|
|
||||||
</svg>
|
|
||||||
|
Before Width: | Height: | Size: 508 B |
@@ -0,0 +1,115 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
echo "=========================================="
|
||||||
|
echo " 文件格式快速修复工具"
|
||||||
|
echo "=========================================="
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# 颜色定义
|
||||||
|
RED='\033[0;31m'
|
||||||
|
GREEN='\033[0;32m'
|
||||||
|
YELLOW='\033[1;33m'
|
||||||
|
NC='\033[0m'
|
||||||
|
|
||||||
|
# 要检查的文件列表
|
||||||
|
SCRIPT_FILES=(
|
||||||
|
"entrypoint.sh"
|
||||||
|
"setup.sh"
|
||||||
|
"register.sh"
|
||||||
|
"manage.sh"
|
||||||
|
)
|
||||||
|
|
||||||
|
FIXED_COUNT=0
|
||||||
|
TOTAL_FILES=0
|
||||||
|
|
||||||
|
echo "🔍 检查并修复以下文件:"
|
||||||
|
printf '%s\n' "${SCRIPT_FILES[@]}" | sed 's/^/ - /'
|
||||||
|
echo ""
|
||||||
|
echo "----------------------------------------"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
for file in "${SCRIPT_FILES[@]}"; do
|
||||||
|
TOTAL_FILES=$((TOTAL_FILES + 1))
|
||||||
|
|
||||||
|
# 检查文件是否存在
|
||||||
|
if [ ! -f "$file" ]; then
|
||||||
|
echo -e "${RED}✗ $file - 文件不存在,跳过${NC}"
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
|
||||||
|
NEEDS_FIX=false
|
||||||
|
|
||||||
|
# 检查换行符
|
||||||
|
HAS_CRLF=false
|
||||||
|
if file "$file" | grep -qi "CRLF\|with CR"; then
|
||||||
|
HAS_CRLF=true
|
||||||
|
NEEDS_FIX=true
|
||||||
|
fi
|
||||||
|
|
||||||
|
# 检查权限
|
||||||
|
NEEDS_CHMOD=false
|
||||||
|
if [ ! -x "$file" ]; then
|
||||||
|
NEEDS_CHMOD=true
|
||||||
|
NEEDS_FIX=true
|
||||||
|
fi
|
||||||
|
|
||||||
|
# 显示状态
|
||||||
|
echo -n "📄 $file ... "
|
||||||
|
|
||||||
|
if [ "$NEEDS_FIX" = false ]; then
|
||||||
|
echo -e "${GREEN}OK${NC}"
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
|
||||||
|
# 修复换行符
|
||||||
|
if [ "$HAS_CRLF" = true ]; then
|
||||||
|
sed -i 's/\r$//' "$file" 2>/dev/null || sed -i '' 's/\r$//' "$file" 2>/dev/null
|
||||||
|
echo -n -e "${YELLOW}[换行符已修复]${NC} "
|
||||||
|
fi
|
||||||
|
|
||||||
|
# 修复权限
|
||||||
|
if [ "$NEEDS_CHMOD" = true ]; then
|
||||||
|
chmod +x "$file"
|
||||||
|
echo -n -e "${YELLOW}[权限已修复]${NC} "
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo -e "${GREEN}✓${NC}"
|
||||||
|
FIXED_COUNT=$((FIXED_COUNT + 1))
|
||||||
|
done
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "=========================================="
|
||||||
|
echo "修复完成"
|
||||||
|
echo "=========================================="
|
||||||
|
echo "检查文件: $TOTAL_FILES"
|
||||||
|
echo "修复文件: $FIXED_COUNT"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
if [ $FIXED_COUNT -gt 0 ]; then
|
||||||
|
echo -e "${GREEN}✓ 所有问题已自动修复!${NC}"
|
||||||
|
echo ""
|
||||||
|
echo "建议执行以下命令重启容器:"
|
||||||
|
echo " docker-compose down"
|
||||||
|
echo " docker-compose build --no-cache"
|
||||||
|
echo " docker-compose up -d"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# 询问是否立即重启
|
||||||
|
read -p "是否立即重启容器? (y/N): " -n 1 -r
|
||||||
|
echo ""
|
||||||
|
if [[ $REPLY =~ ^[Yy]$ ]]; then
|
||||||
|
echo "正在重启容器..."
|
||||||
|
docker-compose down
|
||||||
|
docker-compose build --no-cache
|
||||||
|
docker-compose up -d
|
||||||
|
sleep 3
|
||||||
|
echo ""
|
||||||
|
echo "容器状态:"
|
||||||
|
docker-compose ps
|
||||||
|
echo ""
|
||||||
|
echo "查看日志:"
|
||||||
|
docker logs gitea-runner --tail=30
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
echo -e "${GREEN}✓ 所有文件格式正确,无需修复!${NC}"
|
||||||
|
fi
|
||||||
@@ -0,0 +1,257 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
set -e
|
||||||
|
|
||||||
|
echo "==================================="
|
||||||
|
echo "Gitea Runner Container Starting..."
|
||||||
|
echo "==================================="
|
||||||
|
|
||||||
|
# 定义路径
|
||||||
|
PERSISTENT_BIN="/data/bin"
|
||||||
|
RUNNER_PATH="$PERSISTENT_BIN/act_runner"
|
||||||
|
SYSTEM_LINK="/usr/local/bin/act_runner"
|
||||||
|
|
||||||
|
# 读取环境变量配置
|
||||||
|
ENABLE_BUILDX="${ENABLE_BUILDX:-false}"
|
||||||
|
BINFMT_METHOD="${BINFMT_METHOD:-update-binfmts}" # update-binfmts 或 tonistiigi
|
||||||
|
|
||||||
|
# 创建必要目录
|
||||||
|
mkdir -p /data/runners
|
||||||
|
mkdir -p "$PERSISTENT_BIN"
|
||||||
|
mkdir -p /var/log/supervisor
|
||||||
|
mkdir -p /var/run
|
||||||
|
|
||||||
|
# ============================================
|
||||||
|
# 初始化 Docker Buildx 支持(可选)
|
||||||
|
# ============================================
|
||||||
|
if [ "$ENABLE_BUILDX" = "true" ]; then
|
||||||
|
echo ""
|
||||||
|
echo "Initializing Docker Buildx..."
|
||||||
|
mkdir -p /data/buildx
|
||||||
|
|
||||||
|
# 启动 Docker 守护进程(如果使用主机 socket 则跳过)
|
||||||
|
if [ -S /var/run/docker.sock ]; then
|
||||||
|
echo "✓ Using host Docker socket"
|
||||||
|
else
|
||||||
|
echo "Starting Docker daemon..."
|
||||||
|
dockerd > /var/log/dockerd.log 2>&1 &
|
||||||
|
sleep 5
|
||||||
|
fi
|
||||||
|
|
||||||
|
# 等待 Docker 就绪
|
||||||
|
echo "Waiting for Docker daemon..."
|
||||||
|
for i in {1..30}; do
|
||||||
|
if docker info > /dev/null 2>&1; then
|
||||||
|
echo "✓ Docker daemon is ready"
|
||||||
|
break
|
||||||
|
fi
|
||||||
|
if [ $i -eq 30 ]; then
|
||||||
|
echo "✗ Docker daemon failed to start"
|
||||||
|
[ -f /var/log/dockerd.log ] && cat /var/log/dockerd.log
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
sleep 1
|
||||||
|
done
|
||||||
|
|
||||||
|
# 注册 QEMU binfmt
|
||||||
|
echo ""
|
||||||
|
echo "Registering QEMU binary formats..."
|
||||||
|
|
||||||
|
if [ "$BINFMT_METHOD" = "tonistiigi" ]; then
|
||||||
|
# 使用 tonistiigi/binfmt(更可靠)
|
||||||
|
if docker run --privileged --rm tonistiigi/binfmt --install arm64,amd64 > /var/log/binfmt-install.log 2>&1; then
|
||||||
|
echo "✓ Installed binfmt via tonistiigi/binfmt"
|
||||||
|
grep -m1 "Installed" /var/log/binfmt-install.log || true
|
||||||
|
else
|
||||||
|
echo "⚠ binfmt install via tonistiigi/binfmt failed, trying local tools..."
|
||||||
|
if command -v update-binfmts > /dev/null 2>&1; then
|
||||||
|
update-binfmts --enable 2>/dev/null || true
|
||||||
|
else
|
||||||
|
echo "⚠ update-binfmts not available; multi-arch emulation may be limited"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
# 使用 update-binfmts(传统方法)
|
||||||
|
update-binfmts --enable 2>/dev/null || {
|
||||||
|
echo "⚠ binfmt_misc not available, trying to mount..."
|
||||||
|
mount binfmt_misc -t binfmt_misc /proc/sys/fs/binfmt_misc 2>/dev/null || true
|
||||||
|
update-binfmts --enable
|
||||||
|
}
|
||||||
|
fi
|
||||||
|
|
||||||
|
# 验证多架构支持
|
||||||
|
echo "Verifying multi-arch support..."
|
||||||
|
if docker run --rm arm64v8/alpine uname -m > /dev/null 2>&1; then
|
||||||
|
echo " ✓ arm64 support verified"
|
||||||
|
else
|
||||||
|
echo " ⚠ arm64 verification failed"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if docker run --rm amd64/alpine uname -m > /dev/null 2>&1; then
|
||||||
|
echo " ✓ amd64 support verified"
|
||||||
|
else
|
||||||
|
echo " ⚠ amd64 verification failed"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# 配置 Buildx
|
||||||
|
if [ ! -f "/data/buildx/.configured" ]; then
|
||||||
|
echo ""
|
||||||
|
echo "Setting up Buildx for the first time..."
|
||||||
|
|
||||||
|
# 创建 BuildKit 配置
|
||||||
|
cat > /data/buildx/buildkitd.toml <<EOF
|
||||||
|
[worker.oci]
|
||||||
|
max-parallelism = 4
|
||||||
|
EOF
|
||||||
|
|
||||||
|
# 创建 Buildx builder
|
||||||
|
docker buildx create \
|
||||||
|
--name gitea-multiarch \
|
||||||
|
--driver docker-container \
|
||||||
|
--bootstrap \
|
||||||
|
--use \
|
||||||
|
--config /data/buildx/buildkitd.toml 2>/dev/null || \
|
||||||
|
docker buildx use gitea-multiarch 2>/dev/null
|
||||||
|
|
||||||
|
# 验证
|
||||||
|
echo "Verifying Buildx..."
|
||||||
|
docker buildx inspect --bootstrap > /dev/null 2>&1
|
||||||
|
|
||||||
|
# 标记为已配置
|
||||||
|
touch /data/buildx/.configured
|
||||||
|
|
||||||
|
echo "✓ Buildx configured successfully!"
|
||||||
|
docker buildx inspect | grep "Platforms:" | head -1
|
||||||
|
else
|
||||||
|
echo "✓ Buildx already configured"
|
||||||
|
|
||||||
|
# 确保 builder 可用
|
||||||
|
docker buildx use gitea-multiarch 2>/dev/null || {
|
||||||
|
echo "⚠ Recreating Buildx builder..."
|
||||||
|
docker buildx rm gitea-multiarch 2>/dev/null || true
|
||||||
|
docker buildx create \
|
||||||
|
--name gitea-multiarch \
|
||||||
|
--driver docker-container \
|
||||||
|
--bootstrap \
|
||||||
|
--use 2>/dev/null
|
||||||
|
}
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
fi
|
||||||
|
|
||||||
|
# ============================================
|
||||||
|
# 检查 act_runner 安装
|
||||||
|
# ============================================
|
||||||
|
# 创建主 supervisor 配置文件
|
||||||
|
cat > /etc/supervisor/supervisord.conf <<EOF
|
||||||
|
[supervisord]
|
||||||
|
nodaemon=true
|
||||||
|
logfile=/var/log/supervisor/supervisord.log
|
||||||
|
pidfile=/var/run/supervisord.pid
|
||||||
|
|
||||||
|
[unix_http_server]
|
||||||
|
file=/var/run/supervisor.sock
|
||||||
|
chmod=0700
|
||||||
|
|
||||||
|
[supervisorctl]
|
||||||
|
serverurl=unix:///var/run/supervisor.sock
|
||||||
|
|
||||||
|
[rpcinterface:supervisor]
|
||||||
|
supervisor.rpcinterface_factory = supervisor.rpcinterface:make_main_rpcinterface
|
||||||
|
|
||||||
|
[include]
|
||||||
|
files = /etc/supervisor/conf.d/*.conf
|
||||||
|
EOF
|
||||||
|
|
||||||
|
# 检查持久化目录中的 act_runner
|
||||||
|
if [ -f "$RUNNER_PATH" ]; then
|
||||||
|
echo "✓ Found act_runner in persistent storage"
|
||||||
|
echo " Location: $RUNNER_PATH"
|
||||||
|
|
||||||
|
if [ ! -L "$SYSTEM_LINK" ] || [ ! -e "$SYSTEM_LINK" ]; then
|
||||||
|
ln -sf "$RUNNER_PATH" "$SYSTEM_LINK"
|
||||||
|
echo " Created system link: $SYSTEM_LINK -> $RUNNER_PATH"
|
||||||
|
fi
|
||||||
|
|
||||||
|
RUNNER_VERSION=$("$SYSTEM_LINK" --version 2>/dev/null || echo "unknown")
|
||||||
|
echo " Version: $RUNNER_VERSION"
|
||||||
|
elif [ -f "$SYSTEM_LINK" ]; then
|
||||||
|
echo "⚠ Found act_runner in system path, migrating to persistent storage..."
|
||||||
|
cp "$SYSTEM_LINK" "$RUNNER_PATH"
|
||||||
|
chmod +x "$RUNNER_PATH"
|
||||||
|
ln -sf "$RUNNER_PATH" "$SYSTEM_LINK"
|
||||||
|
echo " ✓ Migrated to: $RUNNER_PATH"
|
||||||
|
else
|
||||||
|
echo "⚠ act_runner not installed yet!"
|
||||||
|
echo ""
|
||||||
|
echo "Please run the setup script first:"
|
||||||
|
echo " docker-compose exec gitea-runner /data/setup.sh"
|
||||||
|
echo ""
|
||||||
|
echo "Container is waiting..."
|
||||||
|
|
||||||
|
while [ ! -f "$RUNNER_PATH" ] && [ ! -f "$SYSTEM_LINK" ]; do
|
||||||
|
sleep 10
|
||||||
|
done
|
||||||
|
|
||||||
|
if [ -f "$RUNNER_PATH" ]; then
|
||||||
|
ln -sf "$RUNNER_PATH" "$SYSTEM_LINK"
|
||||||
|
echo "✓ act_runner detected and linked!"
|
||||||
|
elif [ -f "$SYSTEM_LINK" ]; then
|
||||||
|
cp "$SYSTEM_LINK" "$RUNNER_PATH"
|
||||||
|
ln -sf "$RUNNER_PATH" "$SYSTEM_LINK"
|
||||||
|
echo "✓ act_runner detected and migrated!"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
# ============================================
|
||||||
|
# 配置已注册的 Runners
|
||||||
|
# ============================================
|
||||||
|
echo ""
|
||||||
|
echo "Scanning for registered runners..."
|
||||||
|
RUNNER_COUNT=0
|
||||||
|
|
||||||
|
if [ -d "/data/runners" ]; then
|
||||||
|
for runner_dir in /data/runners/*/; do
|
||||||
|
if [ -d "$runner_dir" ]; then
|
||||||
|
runner_name=$(basename "$runner_dir")
|
||||||
|
|
||||||
|
if [ -f "$runner_dir/.runner" ] && [ -f "$runner_dir/config.yaml" ]; then
|
||||||
|
echo "Found runner: $runner_name"
|
||||||
|
|
||||||
|
cat > "/etc/supervisor/conf.d/runner-${runner_name}.conf" <<EOF
|
||||||
|
[program:runner-${runner_name}]
|
||||||
|
command=/usr/local/bin/act_runner daemon --config ${runner_dir}/config.yaml
|
||||||
|
directory=${runner_dir}
|
||||||
|
autostart=true
|
||||||
|
autorestart=true
|
||||||
|
stderr_logfile=/var/log/supervisor/runner-${runner_name}.err.log
|
||||||
|
stdout_logfile=/var/log/supervisor/runner-${runner_name}.out.log
|
||||||
|
stdout_logfile_maxbytes=50MB
|
||||||
|
stdout_logfile_backups=10
|
||||||
|
stderr_logfile_maxbytes=50MB
|
||||||
|
stderr_logfile_backups=10
|
||||||
|
user=root
|
||||||
|
environment=HOME="/root",PATH="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
|
||||||
|
EOF
|
||||||
|
RUNNER_COUNT=$((RUNNER_COUNT + 1))
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ $RUNNER_COUNT -eq 0 ]; then
|
||||||
|
echo "⚠ No runners registered yet!"
|
||||||
|
echo ""
|
||||||
|
echo "Please run the register script to add a runner:"
|
||||||
|
echo " docker-compose exec gitea-runner /data/register.sh"
|
||||||
|
echo ""
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "Total runners configured: $RUNNER_COUNT"
|
||||||
|
echo ""
|
||||||
|
echo "==================================="
|
||||||
|
echo "Starting Supervisor..."
|
||||||
|
echo "==================================="
|
||||||
|
|
||||||
|
# 启动 supervisord
|
||||||
|
exec /usr/bin/supervisord -c /etc/supervisor/supervisord.conf
|
||||||
@@ -0,0 +1,288 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
echo "=========================================="
|
||||||
|
echo " Gitea Runner Management Tool "
|
||||||
|
echo "=========================================="
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# 函数:列出所有 runners
|
||||||
|
list_runners() {
|
||||||
|
echo "Registered Runners:"
|
||||||
|
echo "-------------------------------------------"
|
||||||
|
|
||||||
|
if [ ! -d "/data/runners" ] || [ -z "$(ls -A /data/runners 2>/dev/null)" ]; then
|
||||||
|
echo "No runners registered yet."
|
||||||
|
return
|
||||||
|
fi
|
||||||
|
|
||||||
|
printf "%-20s %-15s %-30s\n" "Name" "Status" "Log File"
|
||||||
|
echo "-------------------------------------------"
|
||||||
|
|
||||||
|
for runner_dir in /data/runners/*/; do
|
||||||
|
if [ -d "$runner_dir" ]; then
|
||||||
|
runner_name=$(basename "$runner_dir")
|
||||||
|
|
||||||
|
if [ -f "$runner_dir/.runner" ]; then
|
||||||
|
# 获取状态
|
||||||
|
status=$(supervisorctl status "runner-${runner_name}" 2>/dev/null | awk '{print $2}')
|
||||||
|
[ -z "$status" ] && status="NOT_LOADED"
|
||||||
|
|
||||||
|
log_file="/var/log/supervisor/runner-${runner_name}.out.log"
|
||||||
|
|
||||||
|
printf "%-20s %-15s %-30s\n" "$runner_name" "$status" "$log_file"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
echo ""
|
||||||
|
}
|
||||||
|
|
||||||
|
# 函数:查看 runner 详细信息
|
||||||
|
show_runner() {
|
||||||
|
local runner_name=$1
|
||||||
|
local runner_dir="/data/runners/${runner_name}"
|
||||||
|
|
||||||
|
if [ ! -d "$runner_dir" ]; then
|
||||||
|
echo "✗ Runner '$runner_name' not found!"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "Runner Details: $runner_name"
|
||||||
|
echo "-------------------------------------------"
|
||||||
|
echo "Directory: $runner_dir"
|
||||||
|
|
||||||
|
if [ -f "$runner_dir/config.yaml" ]; then
|
||||||
|
echo ""
|
||||||
|
echo "Configuration:"
|
||||||
|
cat "$runner_dir/config.yaml"
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "Status:"
|
||||||
|
supervisorctl status "runner-${runner_name}" 2>/dev/null | awk '{print $2}'
|
||||||
|
echo ""
|
||||||
|
}
|
||||||
|
|
||||||
|
# 函数:删除 runner
|
||||||
|
delete_runner() {
|
||||||
|
local runner_name=$1
|
||||||
|
local runner_dir="/data/runners/${runner_name}"
|
||||||
|
|
||||||
|
if [ ! -d "$runner_dir" ]; then
|
||||||
|
echo "✗ Runner '$runner_name' not found!"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "⚠ Warning: This will permanently delete runner '$runner_name'"
|
||||||
|
read -p "Are you sure? (y/N): " -n 1 -r
|
||||||
|
echo
|
||||||
|
|
||||||
|
if [[ ! $REPLY =~ ^[Yy]$ ]]; then
|
||||||
|
echo "Deletion cancelled."
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "Stopping runner..."
|
||||||
|
supervisorctl stop "runner-${runner_name}" 2>/dev/null || true
|
||||||
|
|
||||||
|
echo "Removing configuration..."
|
||||||
|
rm -f "/etc/supervisor/conf.d/runner-${runner_name}.conf"
|
||||||
|
|
||||||
|
echo "Deleting runner directory..."
|
||||||
|
rm -rf "$runner_dir"
|
||||||
|
|
||||||
|
echo "Updating supervisor..."
|
||||||
|
supervisorctl reread
|
||||||
|
supervisorctl update
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "✓ Runner '$runner_name' deleted successfully!"
|
||||||
|
}
|
||||||
|
|
||||||
|
# 函数:查看 runner 日志
|
||||||
|
logs_runner() {
|
||||||
|
local runner_name=$1
|
||||||
|
local lines=${2:-50}
|
||||||
|
|
||||||
|
local log_file="/var/log/supervisor/runner-${runner_name}.out.log"
|
||||||
|
|
||||||
|
if [ ! -f "$log_file" ]; then
|
||||||
|
echo "✗ Log file not found for runner '$runner_name'"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "Showing last $lines lines of '$runner_name' logs:"
|
||||||
|
echo "-------------------------------------------"
|
||||||
|
tail -n "$lines" "$log_file"
|
||||||
|
}
|
||||||
|
|
||||||
|
# 函数:实时查看日志
|
||||||
|
follow_logs() {
|
||||||
|
local runner_name=$1
|
||||||
|
local log_file="/var/log/supervisor/runner-${runner_name}.out.log"
|
||||||
|
|
||||||
|
if [ ! -f "$log_file" ]; then
|
||||||
|
echo "✗ Log file not found for runner '$runner_name'"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "Following logs for '$runner_name' (Press Ctrl+C to exit):"
|
||||||
|
echo "-------------------------------------------"
|
||||||
|
tail -f "$log_file"
|
||||||
|
}
|
||||||
|
|
||||||
|
# 函数:启动/停止/重启 runner
|
||||||
|
control_runner() {
|
||||||
|
local action=$1
|
||||||
|
local runner_name=$2
|
||||||
|
|
||||||
|
case $action in
|
||||||
|
start|stop|restart)
|
||||||
|
echo "${action^}ing runner '$runner_name'..."
|
||||||
|
supervisorctl "$action" "runner-${runner_name}"
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
echo "✗ Invalid action: $action"
|
||||||
|
return 1
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
}
|
||||||
|
|
||||||
|
# 函数:显示所有 runner 状态
|
||||||
|
status_all() {
|
||||||
|
echo "All Runners Status:"
|
||||||
|
echo "-------------------------------------------"
|
||||||
|
supervisorctl status | grep "^runner-" || echo "No runners running."
|
||||||
|
echo ""
|
||||||
|
}
|
||||||
|
|
||||||
|
# 主菜单
|
||||||
|
show_menu() {
|
||||||
|
echo "Choose an action:"
|
||||||
|
echo " 1) List all runners"
|
||||||
|
echo " 2) Show runner details"
|
||||||
|
echo " 3) Add new runner"
|
||||||
|
echo " 4) Delete runner"
|
||||||
|
echo " 5) Start runner"
|
||||||
|
echo " 6) Stop runner"
|
||||||
|
echo " 7) Restart runner"
|
||||||
|
echo " 8) View runner logs"
|
||||||
|
echo " 9) Follow runner logs (real-time)"
|
||||||
|
echo " 10) Show all runners status"
|
||||||
|
echo " 0) Exit"
|
||||||
|
echo ""
|
||||||
|
}
|
||||||
|
|
||||||
|
# 主程序
|
||||||
|
if [ $# -eq 0 ]; then
|
||||||
|
# 交互模式
|
||||||
|
while true; do
|
||||||
|
show_menu
|
||||||
|
read -p "Enter your choice: " choice
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
case $choice in
|
||||||
|
1)
|
||||||
|
list_runners
|
||||||
|
;;
|
||||||
|
2)
|
||||||
|
read -p "Enter runner name: " runner_name
|
||||||
|
show_runner "$runner_name"
|
||||||
|
;;
|
||||||
|
3)
|
||||||
|
echo "Starting registration process..."
|
||||||
|
/data/register.sh
|
||||||
|
;;
|
||||||
|
4)
|
||||||
|
read -p "Enter runner name to delete: " runner_name
|
||||||
|
delete_runner "$runner_name"
|
||||||
|
;;
|
||||||
|
5)
|
||||||
|
read -p "Enter runner name to start: " runner_name
|
||||||
|
control_runner start "$runner_name"
|
||||||
|
;;
|
||||||
|
6)
|
||||||
|
read -p "Enter runner name to stop: " runner_name
|
||||||
|
control_runner stop "$runner_name"
|
||||||
|
;;
|
||||||
|
7)
|
||||||
|
read -p "Enter runner name to restart: " runner_name
|
||||||
|
control_runner restart "$runner_name"
|
||||||
|
;;
|
||||||
|
8)
|
||||||
|
read -p "Enter runner name: " runner_name
|
||||||
|
read -p "Number of lines (default 50): " lines
|
||||||
|
logs_runner "$runner_name" "${lines:-50}"
|
||||||
|
;;
|
||||||
|
9)
|
||||||
|
read -p "Enter runner name: " runner_name
|
||||||
|
follow_logs "$runner_name"
|
||||||
|
;;
|
||||||
|
10)
|
||||||
|
status_all
|
||||||
|
;;
|
||||||
|
0)
|
||||||
|
echo "Goodbye!"
|
||||||
|
exit 0
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
echo "Invalid choice!"
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
read -p "Press Enter to continue..."
|
||||||
|
clear
|
||||||
|
done
|
||||||
|
else
|
||||||
|
# 命令行模式
|
||||||
|
case $1 in
|
||||||
|
list|ls)
|
||||||
|
list_runners
|
||||||
|
;;
|
||||||
|
show|info)
|
||||||
|
show_runner "$2"
|
||||||
|
;;
|
||||||
|
add|register)
|
||||||
|
/data/register.sh
|
||||||
|
;;
|
||||||
|
delete|rm|remove)
|
||||||
|
delete_runner "$2"
|
||||||
|
;;
|
||||||
|
start)
|
||||||
|
control_runner start "$2"
|
||||||
|
;;
|
||||||
|
stop)
|
||||||
|
control_runner stop "$2"
|
||||||
|
;;
|
||||||
|
restart)
|
||||||
|
control_runner restart "$2"
|
||||||
|
;;
|
||||||
|
logs)
|
||||||
|
logs_runner "$2" "${3:-50}"
|
||||||
|
;;
|
||||||
|
follow)
|
||||||
|
follow_logs "$2"
|
||||||
|
;;
|
||||||
|
status)
|
||||||
|
status_all
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
echo "Usage: $0 [command] [runner_name]"
|
||||||
|
echo ""
|
||||||
|
echo "Commands:"
|
||||||
|
echo " list - List all runners"
|
||||||
|
echo " show <name> - Show runner details"
|
||||||
|
echo " add - Add new runner"
|
||||||
|
echo " delete <name> - Delete a runner"
|
||||||
|
echo " start <name> - Start a runner"
|
||||||
|
echo " stop <name> - Stop a runner"
|
||||||
|
echo " restart <name> - Restart a runner"
|
||||||
|
echo " logs <name> [lines] - View runner logs"
|
||||||
|
echo " follow <name> - Follow runner logs (real-time)"
|
||||||
|
echo " status - Show all runners status"
|
||||||
|
echo ""
|
||||||
|
echo "Or run without arguments for interactive mode."
|
||||||
|
exit 1
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
fi
|
||||||
@@ -0,0 +1,332 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
set -e
|
||||||
|
|
||||||
|
echo "=========================================="
|
||||||
|
echo " Gitea Runner Registration Script "
|
||||||
|
echo "=========================================="
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# 检查 act_runner 是否安装
|
||||||
|
if ! command -v act_runner &> /dev/null; then
|
||||||
|
echo "✗ act_runner is not installed!"
|
||||||
|
echo ""
|
||||||
|
echo "Please run the setup script first:"
|
||||||
|
echo " docker-compose exec gitea-runner /data/setup.sh"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "✓ act_runner found: $(act_runner --version)"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# 获取注册信息并验证
|
||||||
|
while true; do
|
||||||
|
if [ -n "${GITEA_INSTANCE:-}" ]; then
|
||||||
|
echo "Using Gitea instance from env: $GITEA_INSTANCE"
|
||||||
|
else
|
||||||
|
read -p "Enter Gitea instance URL (e.g., https://gitea.example.com): " GITEA_INSTANCE
|
||||||
|
fi
|
||||||
|
|
||||||
|
# 验证 URL 格式
|
||||||
|
if [[ ! "$GITEA_INSTANCE" =~ ^https?:// ]]; then
|
||||||
|
echo "✗ Error: URL must start with http:// or https://"
|
||||||
|
echo ""
|
||||||
|
unset GITEA_INSTANCE
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
|
||||||
|
# 移除末尾的斜杠
|
||||||
|
GITEA_INSTANCE="${GITEA_INSTANCE%/}"
|
||||||
|
echo "✓ URL validated: $GITEA_INSTANCE"
|
||||||
|
break
|
||||||
|
done
|
||||||
|
|
||||||
|
if [ -n "${GITEA_TOKEN:-}" ]; then
|
||||||
|
echo "Using registration token from env."
|
||||||
|
else
|
||||||
|
read -p "Enter registration token: " GITEA_TOKEN
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ -z "$GITEA_TOKEN" ]; then
|
||||||
|
echo "✗ Error: Token cannot be empty!"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
DEFAULT_NAME="${DEFAULT_RUNNER_NAME:-docker-runner}"
|
||||||
|
read -p "Enter runner name (default: $DEFAULT_NAME): " RUNNER_NAME
|
||||||
|
RUNNER_NAME=${RUNNER_NAME:-$DEFAULT_NAME}
|
||||||
|
|
||||||
|
# 多个 label(逗号分隔,无空格)
|
||||||
|
# ubuntu-22.04:host://ubuntu:22.04,ubuntu-20.04:host://ubuntu:20.04,node:docker://node:18
|
||||||
|
DEFAULT_LABEL="${DEFAULT_RUNNER_LABEL:-ubuntu-22.04:host://ubuntu:22.04}"
|
||||||
|
read -p "Enter runner labels (default: $DEFAULT_LABEL): " RUNNER_LABELS
|
||||||
|
RUNNER_LABELS=${RUNNER_LABELS:-$DEFAULT_LABEL}
|
||||||
|
|
||||||
|
# 创建 runner 目录
|
||||||
|
RUNNER_DIR="/data/runners/${RUNNER_NAME}"
|
||||||
|
mkdir -p "$RUNNER_DIR"
|
||||||
|
cd "$RUNNER_DIR"
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "Registration Information:"
|
||||||
|
echo " Instance: $GITEA_INSTANCE"
|
||||||
|
echo " Name: $RUNNER_NAME"
|
||||||
|
echo " Labels: $RUNNER_LABELS"
|
||||||
|
echo " Directory: $RUNNER_DIR"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# 检查是否已经注册
|
||||||
|
if [ -f ".runner" ] || [ -f "config.yaml" ]; then
|
||||||
|
echo "⚠ Runner already exists in this directory!"
|
||||||
|
read -p "Do you want to re-register? This will overwrite existing configuration. (y/N): " -n 1 -r
|
||||||
|
echo
|
||||||
|
if [[ ! $REPLY =~ ^[Yy]$ ]]; then
|
||||||
|
echo "Registration cancelled."
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "Cleaning up existing runner..."
|
||||||
|
|
||||||
|
# 停止现有 runner
|
||||||
|
echo "Stopping existing runner..."
|
||||||
|
supervisorctl stop "runner-${RUNNER_NAME}" 2>/dev/null || true
|
||||||
|
|
||||||
|
# 删除 supervisor 配置
|
||||||
|
rm -f "/etc/supervisor/conf.d/runner-${RUNNER_NAME}.conf"
|
||||||
|
|
||||||
|
# 重新加载 supervisor
|
||||||
|
supervisorctl reread 2>/dev/null || true
|
||||||
|
supervisorctl update 2>/dev/null || true
|
||||||
|
|
||||||
|
# 删除日志
|
||||||
|
rm -f "/var/log/supervisor/runner-${RUNNER_NAME}".*.log*
|
||||||
|
|
||||||
|
# 删除旧配置和缓存
|
||||||
|
rm -f .runner config.yaml
|
||||||
|
rm -rf cache
|
||||||
|
fi
|
||||||
|
|
||||||
|
# 执行注册
|
||||||
|
echo ""
|
||||||
|
echo "Registering runner..."
|
||||||
|
act_runner register \
|
||||||
|
--instance "$GITEA_INSTANCE" \
|
||||||
|
--token "$GITEA_TOKEN" \
|
||||||
|
--name "$RUNNER_NAME" \
|
||||||
|
--labels "$RUNNER_LABELS" \
|
||||||
|
--no-interactive
|
||||||
|
|
||||||
|
if [ ! -f ".runner" ]; then
|
||||||
|
echo ""
|
||||||
|
echo "✗ Registration failed! .runner file not created."
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "✓ Registration successful!"
|
||||||
|
|
||||||
|
# 生成配置文件
|
||||||
|
echo ""
|
||||||
|
echo "Generating config.yaml..."
|
||||||
|
act_runner generate-config > config.yaml
|
||||||
|
|
||||||
|
echo "✓ Configuration file generated!"
|
||||||
|
|
||||||
|
# 创建缓存目录
|
||||||
|
mkdir -p cache
|
||||||
|
|
||||||
|
# 使用 Python 修改配置(最可靠的方法)
|
||||||
|
echo ""
|
||||||
|
echo "Configuring runner settings..."
|
||||||
|
|
||||||
|
if command -v python3 &> /dev/null; then
|
||||||
|
python3 << PYEOF
|
||||||
|
import yaml
|
||||||
|
import sys
|
||||||
|
|
||||||
|
try:
|
||||||
|
# 读取生成的配置
|
||||||
|
with open('config.yaml', 'r') as f:
|
||||||
|
config = yaml.safe_load(f)
|
||||||
|
|
||||||
|
# 读取 .runner 获取实际注册的 labels
|
||||||
|
import json
|
||||||
|
with open('.runner', 'r') as f:
|
||||||
|
runner_data = json.load(f)
|
||||||
|
|
||||||
|
# 使用 .runner 中的 labels(这是实际注册的)
|
||||||
|
registered_labels = runner_data.get('labels', [])
|
||||||
|
|
||||||
|
# 修改配置
|
||||||
|
if 'runner' not in config:
|
||||||
|
config['runner'] = {}
|
||||||
|
|
||||||
|
# 使用实际注册的 labels
|
||||||
|
config['runner']['labels'] = registered_labels
|
||||||
|
config['runner']['capacity'] = 2
|
||||||
|
|
||||||
|
# 启用缓存
|
||||||
|
if 'cache' not in config:
|
||||||
|
config['cache'] = {}
|
||||||
|
config['cache']['enabled'] = True
|
||||||
|
config['cache']['dir'] = './cache'
|
||||||
|
|
||||||
|
# 保存配置
|
||||||
|
with open('config.yaml', 'w') as f:
|
||||||
|
yaml.dump(config, f, default_flow_style=False, sort_keys=False)
|
||||||
|
|
||||||
|
print("✓ Configuration updated using Python")
|
||||||
|
print(f" - Labels: {registered_labels}")
|
||||||
|
print(f" - Capacity: 2")
|
||||||
|
print(f" - Cache enabled: ./cache")
|
||||||
|
sys.exit(0)
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
print(f"✗ Python configuration failed: {e}", file=sys.stderr)
|
||||||
|
sys.exit(1)
|
||||||
|
PYEOF
|
||||||
|
|
||||||
|
PYTHON_EXIT=$?
|
||||||
|
|
||||||
|
if [ $PYTHON_EXIT -ne 0 ]; then
|
||||||
|
echo ""
|
||||||
|
echo "⚠ Python configuration failed, using basic sed..."
|
||||||
|
|
||||||
|
# 基本的 sed 修改(只修改简单的值,不动 labels)
|
||||||
|
sed -i 's/capacity: 1/capacity: 2/g' config.yaml || true
|
||||||
|
sed -i 's/enabled: false/enabled: true/g' config.yaml || true
|
||||||
|
sed -i 's|dir: ""|dir: ./cache|g' config.yaml || true
|
||||||
|
|
||||||
|
echo "✓ Basic configuration applied"
|
||||||
|
echo " Note: Please manually verify labels in config.yaml match .runner"
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
echo "⚠ Python3 not found, applying basic configuration..."
|
||||||
|
|
||||||
|
# 基本的 sed 修改
|
||||||
|
sed -i 's/capacity: 1/capacity: 2/g' config.yaml || true
|
||||||
|
sed -i 's/enabled: false/enabled: true/g' config.yaml || true
|
||||||
|
sed -i 's|dir: ""|dir: ./cache|g' config.yaml || true
|
||||||
|
|
||||||
|
echo "✓ Basic configuration applied"
|
||||||
|
echo " Note: Labels will use act_runner defaults"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# 验证配置文件
|
||||||
|
echo ""
|
||||||
|
echo "Validating configuration..."
|
||||||
|
|
||||||
|
# 检查 YAML 语法
|
||||||
|
if command -v python3 &> /dev/null; then
|
||||||
|
python3 << PYEOF
|
||||||
|
import yaml
|
||||||
|
import sys
|
||||||
|
try:
|
||||||
|
with open('config.yaml', 'r') as f:
|
||||||
|
yaml.safe_load(f)
|
||||||
|
print("✓ config.yaml syntax is valid")
|
||||||
|
sys.exit(0)
|
||||||
|
except Exception as e:
|
||||||
|
print(f"✗ config.yaml syntax error: {e}", file=sys.stderr)
|
||||||
|
sys.exit(1)
|
||||||
|
PYEOF
|
||||||
|
|
||||||
|
if [ $? -ne 0 ]; then
|
||||||
|
echo ""
|
||||||
|
echo "✗ Configuration file has syntax errors!"
|
||||||
|
echo " Backup available at: config.yaml.bak"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
# 显示配置摘要
|
||||||
|
echo ""
|
||||||
|
echo "Configuration Summary:"
|
||||||
|
echo "-------------------------------------------"
|
||||||
|
echo ".runner labels:"
|
||||||
|
cat .runner | grep -A 10 '"labels"' | head -15
|
||||||
|
echo ""
|
||||||
|
echo "config.yaml labels:"
|
||||||
|
grep -A 5 "^ labels:" config.yaml | head -10
|
||||||
|
|
||||||
|
# 创建 supervisor 配置
|
||||||
|
echo ""
|
||||||
|
echo "Creating supervisor configuration..."
|
||||||
|
cat > "/etc/supervisor/conf.d/runner-${RUNNER_NAME}.conf" <<EOF
|
||||||
|
[program:runner-${RUNNER_NAME}]
|
||||||
|
command=/usr/local/bin/act_runner daemon --config ${RUNNER_DIR}/config.yaml
|
||||||
|
directory=${RUNNER_DIR}
|
||||||
|
autostart=true
|
||||||
|
autorestart=true
|
||||||
|
stderr_logfile=/var/log/supervisor/runner-${RUNNER_NAME}.err.log
|
||||||
|
stdout_logfile=/var/log/supervisor/runner-${RUNNER_NAME}.out.log
|
||||||
|
stdout_logfile_maxbytes=50MB
|
||||||
|
stdout_logfile_backups=10
|
||||||
|
stderr_logfile_maxbytes=50MB
|
||||||
|
stderr_logfile_backups=10
|
||||||
|
user=root
|
||||||
|
environment=HOME="/root"
|
||||||
|
EOF
|
||||||
|
|
||||||
|
echo "✓ Supervisor configuration created"
|
||||||
|
|
||||||
|
# 重新加载 supervisor
|
||||||
|
echo ""
|
||||||
|
echo "Reloading supervisor..."
|
||||||
|
supervisorctl reread
|
||||||
|
supervisorctl update
|
||||||
|
|
||||||
|
echo "Starting runner..."
|
||||||
|
sleep 2
|
||||||
|
# 启动 runner
|
||||||
|
supervisorctl restart "runner-${RUNNER_NAME}" 2>/dev/null || \
|
||||||
|
supervisorctl start "runner-${RUNNER_NAME}"
|
||||||
|
|
||||||
|
# 等待启动
|
||||||
|
sleep 3
|
||||||
|
|
||||||
|
# 显示状态
|
||||||
|
RUNNER_STATUS=$(supervisorctl status "runner-${RUNNER_NAME}" 2>/dev/null || echo "UNKNOWN")
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "=========================================="
|
||||||
|
echo "✓ Runner registered and started!"
|
||||||
|
echo "=========================================="
|
||||||
|
echo ""
|
||||||
|
echo "Runner Information:"
|
||||||
|
echo " Name: $RUNNER_NAME"
|
||||||
|
echo " Directory: $RUNNER_DIR"
|
||||||
|
echo " Status: $RUNNER_STATUS"
|
||||||
|
echo ""
|
||||||
|
echo "Configuration files:"
|
||||||
|
echo " .runner: $(ls -lh .runner 2>/dev/null | awk '{print $5}' || echo 'N/A')"
|
||||||
|
echo " config.yaml: $(ls -lh config.yaml 2>/dev/null | awk '{print $5}' || echo 'N/A')"
|
||||||
|
echo ""
|
||||||
|
echo "Useful commands:"
|
||||||
|
echo " View logs: docker-compose exec gitea-runner /data/manage.sh logs ${RUNNER_NAME}"
|
||||||
|
echo " Follow logs: docker-compose exec gitea-runner /data/manage.sh follow ${RUNNER_NAME}"
|
||||||
|
echo " Check status: docker-compose exec gitea-runner /data/manage.sh status"
|
||||||
|
echo " Restart: docker-compose exec gitea-runner /data/manage.sh restart ${RUNNER_NAME}"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# 显示最近的日志
|
||||||
|
if [ -f "/var/log/supervisor/runner-${RUNNER_NAME}.out.log" ]; then
|
||||||
|
echo "Recent logs:"
|
||||||
|
echo "-------------------------------------------"
|
||||||
|
tail -n 20 "/var/log/supervisor/runner-${RUNNER_NAME}.out.log" 2>/dev/null || echo "No logs yet"
|
||||||
|
echo ""
|
||||||
|
fi
|
||||||
|
|
||||||
|
# 检查是否有错误
|
||||||
|
if [ -f "/var/log/supervisor/runner-${RUNNER_NAME}.err.log" ]; then
|
||||||
|
# 只查找 error/fatal/panic 级别的日志
|
||||||
|
ERR_CONTENT=$(grep -E 'level=(error|fatal|panic)' \
|
||||||
|
"/var/log/supervisor/runner-${RUNNER_NAME}.err.log" | tail -n 5 2>/dev/null)
|
||||||
|
|
||||||
|
if [ -n "$ERR_CONTENT" ]; then
|
||||||
|
echo "❌ Recent errors detected:"
|
||||||
|
echo "-------------------------------------------"
|
||||||
|
echo "$ERR_CONTENT"
|
||||||
|
echo ""
|
||||||
|
echo "Check full error log with:"
|
||||||
|
echo " docker-compose exec gitea-runner cat /var/log/supervisor/runner-${RUNNER_NAME}.err.log"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
@@ -0,0 +1,141 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
echo "=========================================="
|
||||||
|
echo " Gitea Runner Installation Script "
|
||||||
|
echo "=========================================="
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# 持久化安装路径
|
||||||
|
INSTALL_PATH="/data/bin/act_runner"
|
||||||
|
SYSTEM_PATH="/usr/local/bin/act_runner"
|
||||||
|
|
||||||
|
# 创建目录
|
||||||
|
mkdir -p /data/bin
|
||||||
|
|
||||||
|
# 检查是否已安装
|
||||||
|
if [ -f "$INSTALL_PATH" ]; then
|
||||||
|
CURRENT_VERSION=$($INSTALL_PATH --version 2>/dev/null | grep -oP 'version \K[0-9.]+' || echo "unknown")
|
||||||
|
echo "⚠ act_runner already installed (version: $CURRENT_VERSION)"
|
||||||
|
echo " Location: $INSTALL_PATH"
|
||||||
|
echo ""
|
||||||
|
read -p "Do you want to reinstall/upgrade? (y/N): " -n 1 -r
|
||||||
|
echo
|
||||||
|
if [[ ! $REPLY =~ ^[Yy]$ ]]; then
|
||||||
|
echo "Installation cancelled."
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
rm -f "$INSTALL_PATH" "$SYSTEM_PATH"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# 获取要安装的版本
|
||||||
|
echo "Available versions: https://dl.gitea.com/act_runner/"
|
||||||
|
echo ""
|
||||||
|
read -p "Enter version to install (default: 0.2.13): " RUNNER_VERSION
|
||||||
|
RUNNER_VERSION=${RUNNER_VERSION:-0.2.13}
|
||||||
|
|
||||||
|
ARCH=$(uname -m)
|
||||||
|
case "$ARCH" in
|
||||||
|
x86_64)
|
||||||
|
RUNNER_ARCH="amd64"
|
||||||
|
;;
|
||||||
|
aarch64|arm64)
|
||||||
|
RUNNER_ARCH="arm64"
|
||||||
|
;;
|
||||||
|
armv7l)
|
||||||
|
RUNNER_ARCH="arm-7"
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
echo "⚠ Unknown architecture: $ARCH"
|
||||||
|
RUNNER_ARCH="arm64"
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
# 确认架构
|
||||||
|
echo ""
|
||||||
|
echo "Detected architecture: $ARCH -> $RUNNER_ARCH"
|
||||||
|
read -p "Is this correct? (Y/n): " -n 1 -r
|
||||||
|
echo
|
||||||
|
if [[ $REPLY =~ ^[Nn]$ ]]; then
|
||||||
|
echo ""
|
||||||
|
echo "Available architectures:"
|
||||||
|
echo " 1. amd64 (x86_64)"
|
||||||
|
echo " 2. arm64 (aarch64)"
|
||||||
|
echo " 3. arm-7 (armv7l)"
|
||||||
|
read -p "Select architecture (1-3): " ARCH_CHOICE
|
||||||
|
case "$ARCH_CHOICE" in
|
||||||
|
1) RUNNER_ARCH="amd64" ;;
|
||||||
|
2) RUNNER_ARCH="arm64" ;;
|
||||||
|
3) RUNNER_ARCH="arm-7" ;;
|
||||||
|
*)
|
||||||
|
echo "Invalid choice. Exiting."
|
||||||
|
exit 1
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
fi
|
||||||
|
|
||||||
|
DOWNLOAD_URL="https://dl.gitea.com/act_runner/${RUNNER_VERSION}/act_runner-${RUNNER_VERSION}-linux-${RUNNER_ARCH}"
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "Download Configuration:"
|
||||||
|
echo " Version: $RUNNER_VERSION"
|
||||||
|
echo " Architecture: $RUNNER_ARCH"
|
||||||
|
echo " URL: $DOWNLOAD_URL"
|
||||||
|
echo " Install Location: $INSTALL_PATH (persistent)"
|
||||||
|
echo ""
|
||||||
|
read -p "Proceed with download? (Y/n): " -n 1 -r
|
||||||
|
echo
|
||||||
|
if [[ $REPLY =~ ^[Nn]$ ]]; then
|
||||||
|
echo "Installation cancelled."
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "Downloading act_runner..."
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# 下载到持久化目录
|
||||||
|
if curl -L "$DOWNLOAD_URL" -o "$INSTALL_PATH"; then
|
||||||
|
chmod +x "$INSTALL_PATH"
|
||||||
|
|
||||||
|
# 同时创建软链接到系统路径
|
||||||
|
ln -sf "$INSTALL_PATH" "$SYSTEM_PATH"
|
||||||
|
|
||||||
|
# 验证安装
|
||||||
|
if $INSTALL_PATH --version; then
|
||||||
|
echo ""
|
||||||
|
echo "=========================================="
|
||||||
|
echo "✓ act_runner installed successfully!"
|
||||||
|
echo "=========================================="
|
||||||
|
echo ""
|
||||||
|
echo "Version: $($INSTALL_PATH --version)"
|
||||||
|
echo "Location: $INSTALL_PATH (persistent storage)"
|
||||||
|
echo ""
|
||||||
|
echo "Next steps:"
|
||||||
|
echo "1. Register the runner:"
|
||||||
|
echo " docker-compose exec gitea-runner /data/register.sh"
|
||||||
|
echo ""
|
||||||
|
echo "2. Restart the container:"
|
||||||
|
echo " docker-compose restart"
|
||||||
|
echo ""
|
||||||
|
echo "Note: act_runner is saved in persistent storage"
|
||||||
|
echo " and will survive container restarts."
|
||||||
|
echo ""
|
||||||
|
else
|
||||||
|
echo ""
|
||||||
|
echo "✗ Installation verification failed!"
|
||||||
|
rm -f "$INSTALL_PATH" "$SYSTEM_PATH"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
echo ""
|
||||||
|
echo "✗ Download failed!"
|
||||||
|
echo "Please check:"
|
||||||
|
echo " - Internet connection"
|
||||||
|
echo " - Version number is correct: $RUNNER_VERSION"
|
||||||
|
echo " - Architecture is correct: $RUNNER_ARCH"
|
||||||
|
echo " - URL is accessible: $DOWNLOAD_URL"
|
||||||
|
echo ""
|
||||||
|
echo "You can check available versions at:"
|
||||||
|
echo " https://dl.gitea.com/act_runner/"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
@@ -0,0 +1,74 @@
|
|||||||
|
FROM archlinux:latest
|
||||||
|
|
||||||
|
SHELL ["/bin/bash", "-o", "pipefail", "-c"]
|
||||||
|
|
||||||
|
# 初始化密钥和软件源
|
||||||
|
RUN pacman-key --init && \
|
||||||
|
pacman-key --populate archlinux && \
|
||||||
|
sed -i 's/^#ParallelDownloads/ParallelDownloads/' /etc/pacman.conf && \
|
||||||
|
printf "\n[archlinuxcn]\nServer = https://mirrors.ustc.edu.cn/archlinuxcn/\$arch\n" >> /etc/pacman.conf && \
|
||||||
|
pacman -Syy --noconfirm
|
||||||
|
|
||||||
|
# 安装基础工具、Buildx 支持和开发环境
|
||||||
|
RUN pacman -Syu --noconfirm && \
|
||||||
|
pacman -S --noconfirm --disable-download-timeout archlinuxcn-keyring && \
|
||||||
|
pacman -S --noconfirm --needed \
|
||||||
|
base-devel \
|
||||||
|
ca-certificates \
|
||||||
|
clang \
|
||||||
|
lld \
|
||||||
|
libc++ \
|
||||||
|
libc++abi \
|
||||||
|
cmake \
|
||||||
|
ninja \
|
||||||
|
curl \
|
||||||
|
git \
|
||||||
|
nodejs \
|
||||||
|
npm \
|
||||||
|
python \
|
||||||
|
python-pyyaml \
|
||||||
|
python-pip \
|
||||||
|
paru \
|
||||||
|
sudo \
|
||||||
|
vim \
|
||||||
|
supervisor \
|
||||||
|
qemu-user-static \
|
||||||
|
qemu-user-static-binfmt \
|
||||||
|
fakeroot \
|
||||||
|
docker \
|
||||||
|
docker-buildx \
|
||||||
|
&& pacman -Scc --noconfirm
|
||||||
|
|
||||||
|
# AUR 用户(paru 需非 root 运行)
|
||||||
|
RUN useradd -m aur && \
|
||||||
|
echo "aur ALL=(ALL) NOPASSWD: ALL" > /etc/sudoers.d/aur && \
|
||||||
|
chmod 0440 /etc/sudoers.d/aur
|
||||||
|
|
||||||
|
# 安装额外的 AUR 工具
|
||||||
|
USER aur
|
||||||
|
WORKDIR /home/aur
|
||||||
|
RUN paru -S --noconfirm --needed --noprogressbar conan-bin llvm-mingw-w64-toolchain-ucrt-bin && \
|
||||||
|
paru -Scc --noconfirm && \
|
||||||
|
rm -rf ~/.cache/paru
|
||||||
|
|
||||||
|
# 切换回 root
|
||||||
|
USER root
|
||||||
|
WORKDIR /root
|
||||||
|
|
||||||
|
# 交叉工具链可用:确保 windres 在 PATH,避免 CMake 查找失败
|
||||||
|
ENV PATH="/opt/llvm-mingw/llvm-mingw-ucrt/bin:${PATH}"
|
||||||
|
ENV RC="/opt/llvm-mingw/llvm-mingw-ucrt/bin/x86_64-w64-mingw32-windres"
|
||||||
|
|
||||||
|
# 验证 qemu 和 docker 安装
|
||||||
|
RUN qemu-aarch64-static --version && \
|
||||||
|
qemu-x86_64-static --version && \
|
||||||
|
docker --version
|
||||||
|
|
||||||
|
# 创建必要目录
|
||||||
|
RUN mkdir -p /data /etc/supervisor/conf.d /var/log/supervisor
|
||||||
|
|
||||||
|
# 设置工作目录
|
||||||
|
WORKDIR /data
|
||||||
|
|
||||||
|
# 使用自定义入口点
|
||||||
|
ENTRYPOINT ["/data/entrypoint.sh"]
|
||||||
@@ -0,0 +1,38 @@
|
|||||||
|
services:
|
||||||
|
gitea-runner:
|
||||||
|
build: .
|
||||||
|
container_name: gitea-runner-buildx-archlinux
|
||||||
|
restart: unless-stopped
|
||||||
|
network_mode: "host" # 使用宿主机网络
|
||||||
|
privileged: true # Buildx 需要 privileged 模式
|
||||||
|
volumes:
|
||||||
|
- ./runner-data:/data
|
||||||
|
- ../../common/setup.sh:/data/setup.sh:ro
|
||||||
|
- ../../common/register.sh:/data/register.sh:ro
|
||||||
|
- ../../common/manage.sh:/data/manage.sh:ro
|
||||||
|
- ../../common/check_crlf.sh:/data/check_crlf.sh:ro
|
||||||
|
- ../../common/entrypoint.sh:/data/entrypoint.sh:ro
|
||||||
|
- /var/run/docker.sock:/var/run/docker.sock
|
||||||
|
|
||||||
|
environment:
|
||||||
|
- TZ=Asia/Shanghai
|
||||||
|
|
||||||
|
# Arch Linux Buildx 配置 - 使用 tonistiigi/binfmt
|
||||||
|
- ENABLE_BUILDX=true
|
||||||
|
- BINFMT_METHOD=tonistiigi
|
||||||
|
- GITEA_INSTANCE=https://git.mytsl.cn
|
||||||
|
- GITEA_TOKEN=
|
||||||
|
- DEFAULT_RUNNER_NAME=buildx-archlinux
|
||||||
|
- DEFAULT_RUNNER_LABEL=archlinux:host://archlinux:latest,company-server:host://archlinux:latest,buildx-archlinux:host://archlinux:latest
|
||||||
|
|
||||||
|
# 如果需要使用代理,取消下面的注释并修改为你的代理地址
|
||||||
|
# 注意:容器内访问宿主机需要使用 host.docker.internal 或宿主机IP
|
||||||
|
# - http_proxy=http://host.docker.internal:20122
|
||||||
|
# - https_proxy=http://host.docker.internal:20122
|
||||||
|
# - HTTP_PROXY=http://host.docker.internal:20122
|
||||||
|
# - HTTPS_PROXY=http://host.docker.internal:20122
|
||||||
|
# - no_proxy=localhost,127.0.0.1
|
||||||
|
|
||||||
|
# Linux 系统需要取消下面的注释以支持 host.docker.internal
|
||||||
|
# extra_hosts:
|
||||||
|
# - "host.docker.internal:host-gateway"
|
||||||
@@ -0,0 +1,49 @@
|
|||||||
|
FROM ubuntu:22.04
|
||||||
|
|
||||||
|
# 设置环境变量避免交互式安装
|
||||||
|
ENV DEBIAN_FRONTEND=noninteractive
|
||||||
|
|
||||||
|
# 更新系统并安装必要软件
|
||||||
|
RUN apt-get update && apt-get install -y \
|
||||||
|
curl \
|
||||||
|
git \
|
||||||
|
python3 \
|
||||||
|
python3-yaml \
|
||||||
|
supervisor \
|
||||||
|
ca-certificates \
|
||||||
|
gnupg \
|
||||||
|
lsb-release \
|
||||||
|
qemu-user-static \
|
||||||
|
binfmt-support \
|
||||||
|
apt-transport-https \
|
||||||
|
&& rm -rf /var/lib/apt/lists/*
|
||||||
|
|
||||||
|
# 安装 Docker(包含 Buildx 插件)
|
||||||
|
RUN install -m 0755 -d /etc/apt/keyrings && \
|
||||||
|
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | gpg --dearmor -o /etc/apt/keyrings/docker.gpg && \
|
||||||
|
chmod a+r /etc/apt/keyrings/docker.gpg && \
|
||||||
|
echo \
|
||||||
|
"deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu \
|
||||||
|
$(lsb_release -cs) stable" > /etc/apt/sources.list.d/docker.list && \
|
||||||
|
apt-get update && \
|
||||||
|
apt-get install -y \
|
||||||
|
docker-ce \
|
||||||
|
docker-ce-cli \
|
||||||
|
containerd.io \
|
||||||
|
docker-buildx-plugin \
|
||||||
|
docker-compose-plugin \
|
||||||
|
&& rm -rf /var/lib/apt/lists/*
|
||||||
|
|
||||||
|
# 验证安装
|
||||||
|
RUN docker --version && \
|
||||||
|
qemu-aarch64-static --version && \
|
||||||
|
qemu-x86_64-static --version
|
||||||
|
|
||||||
|
# 创建必要目录
|
||||||
|
RUN mkdir -p /data /etc/supervisor/conf.d /var/log/supervisor
|
||||||
|
|
||||||
|
# 设置工作目录
|
||||||
|
WORKDIR /data
|
||||||
|
|
||||||
|
# 使用自定义入口点
|
||||||
|
ENTRYPOINT ["/data/entrypoint.sh"]
|
||||||
@@ -0,0 +1,37 @@
|
|||||||
|
services:
|
||||||
|
gitea-runner:
|
||||||
|
build: .
|
||||||
|
container_name: gitea-runner-buildx-ubuntu-22
|
||||||
|
restart: unless-stopped
|
||||||
|
network_mode: "host" # 使用宿主机网络
|
||||||
|
privileged: true # Buildx 需要 privileged 模式
|
||||||
|
volumes:
|
||||||
|
- ./runner-data:/data
|
||||||
|
- ../../common/setup.sh:/data/setup.sh:ro
|
||||||
|
- ../../common/register.sh:/data/register.sh:ro
|
||||||
|
- ../../common/manage.sh:/data/manage.sh:ro
|
||||||
|
- ../../common/check_crlf.sh:/data/check_crlf.sh:ro
|
||||||
|
- ../../common/entrypoint.sh:/data/entrypoint.sh:ro
|
||||||
|
- /var/run/docker.sock:/var/run/docker.sock
|
||||||
|
|
||||||
|
environment:
|
||||||
|
- TZ=Asia/Shanghai
|
||||||
|
|
||||||
|
# Buildx 配置 - 启用多架构构建
|
||||||
|
- ENABLE_BUILDX=true
|
||||||
|
- GITEA_INSTANCE=https://git.mytsl.cn
|
||||||
|
- GITEA_TOKEN=
|
||||||
|
- DEFAULT_RUNNER_NAME=buildx-ubuntu-22
|
||||||
|
- DEFAULT_RUNNER_LABEL=ubuntu-22.04:host://ubuntu:22.04,company-server:host://ubuntu:22.04,buildx-ubuntu-22:host://ubuntu:22.04
|
||||||
|
|
||||||
|
# 如果需要使用代理,取消下面的注释并修改为你的代理地址
|
||||||
|
# 注意:容器内访问宿主机需要使用 host.docker.internal 或宿主机IP
|
||||||
|
# - http_proxy=http://host.docker.internal:20122
|
||||||
|
# - https_proxy=http://host.docker.internal:20122
|
||||||
|
# - HTTP_PROXY=http://host.docker.internal:20122
|
||||||
|
# - HTTPS_PROXY=http://host.docker.internal:20122
|
||||||
|
# - no_proxy=localhost,127.0.0.1
|
||||||
|
|
||||||
|
# Linux 系统需要取消下面的注释以支持 host.docker.internal
|
||||||
|
# extra_hosts:
|
||||||
|
# - "host.docker.internal:host-gateway"
|
||||||
@@ -0,0 +1,33 @@
|
|||||||
|
FROM ubuntu:22.04
|
||||||
|
|
||||||
|
# 设置环境变量避免交互式安装
|
||||||
|
ENV DEBIAN_FRONTEND=noninteractive
|
||||||
|
|
||||||
|
# RUN apt-get update && \
|
||||||
|
# apt-get install -y ca-certificates && \
|
||||||
|
# update-ca-certificates && \
|
||||||
|
# rm -rf /var/lib/apt/lists/*
|
||||||
|
|
||||||
|
# RUN sed -i 's@//.*archive.ubuntu.com@//mirrors.ustc.edu.cn@g' /etc/apt/sources.list && \
|
||||||
|
# sed -i 's@//.*security.ubuntu.com@//mirrors.ustc.edu.cn@g' /etc/apt/sources.list
|
||||||
|
|
||||||
|
# 更新系统并安装必要软件
|
||||||
|
RUN apt-get update && apt-get install -y \
|
||||||
|
curl \
|
||||||
|
git \
|
||||||
|
jq \
|
||||||
|
python3 \
|
||||||
|
python3-yaml \
|
||||||
|
lsb-release \
|
||||||
|
supervisor \
|
||||||
|
ca-certificates \
|
||||||
|
&& rm -rf /var/lib/apt/lists/*
|
||||||
|
|
||||||
|
# 创建必要目录
|
||||||
|
RUN mkdir -p /data /etc/supervisor/conf.d /var/log/supervisor
|
||||||
|
|
||||||
|
# 设置工作目录
|
||||||
|
WORKDIR /data
|
||||||
|
|
||||||
|
# 使用自定义入口点
|
||||||
|
ENTRYPOINT ["/data/entrypoint.sh"]
|
||||||
@@ -0,0 +1,35 @@
|
|||||||
|
services:
|
||||||
|
gitea-runner:
|
||||||
|
build: .
|
||||||
|
container_name: gitea-runner-standard-ubuntu-22
|
||||||
|
restart: unless-stopped
|
||||||
|
network_mode: "host" # 使用宿主机网络
|
||||||
|
volumes:
|
||||||
|
- ./runner-data:/data
|
||||||
|
- ../../common/setup.sh:/data/setup.sh:ro
|
||||||
|
- ../../common/register.sh:/data/register.sh:ro
|
||||||
|
- ../../common/manage.sh:/data/manage.sh:ro
|
||||||
|
- ../../common/entrypoint.sh:/data/entrypoint.sh:ro
|
||||||
|
- /var/run/docker.sock:/var/run/docker.sock
|
||||||
|
|
||||||
|
environment:
|
||||||
|
- TZ=Asia/Shanghai
|
||||||
|
|
||||||
|
# Standard 配置 - 不启用 Buildx
|
||||||
|
- ENABLE_BUILDX=false
|
||||||
|
- GITEA_INSTANCE=https://git.mytsl.cn
|
||||||
|
- GITEA_TOKEN=
|
||||||
|
- DEFAULT_RUNNER_NAME=standard-ubuntu-22
|
||||||
|
- DEFAULT_RUNNER_LABEL=ubuntu-22.04:host://ubuntu:22.04,company-server:host://ubuntu:22.04,standard-ubuntu-22:host://ubuntu:22.04
|
||||||
|
|
||||||
|
# 如果需要使用代理,取消下面的注释并修改为你的代理地址
|
||||||
|
# 注意:容器内访问宿主机需要使用 host.docker.internal 或宿主机IP
|
||||||
|
# - http_proxy=http://host.docker.internal:20122
|
||||||
|
# - https_proxy=http://host.docker.internal:20122
|
||||||
|
# - HTTP_PROXY=http://host.docker.internal:20122
|
||||||
|
# - HTTPS_PROXY=http://host.docker.internal:20122
|
||||||
|
# - no_proxy=localhost,127.0.0.1
|
||||||
|
|
||||||
|
# Linux 系统需要取消下面的注释以支持 host.docker.internal
|
||||||
|
# extra_hosts:
|
||||||
|
# - "host.docker.internal:host-gateway"
|
||||||
Reference in New Issue
Block a user