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 |
@@ -5,6 +5,10 @@ on:
|
|||||||
tags:
|
tags:
|
||||||
- "[0-9]*"
|
- "[0-9]*"
|
||||||
|
|
||||||
|
concurrency:
|
||||||
|
group: release-${{ github.repository }}
|
||||||
|
cancel-in-progress: false
|
||||||
|
|
||||||
# ==========================================
|
# ==========================================
|
||||||
# 🔧 配置区域 - 根据你的项目修改
|
# 🔧 配置区域 - 根据你的项目修改
|
||||||
# ==========================================
|
# ==========================================
|
||||||
@@ -33,7 +37,7 @@ env:
|
|||||||
# ===== 分支配置 =====
|
# ===== 分支配置 =====
|
||||||
# 主分支名称(用于推送 CHANGELOG 更新)
|
# 主分支名称(用于推送 CHANGELOG 更新)
|
||||||
# 如果留空,会自动检测(main 或 master)
|
# 如果留空,会自动检测(main 或 master)
|
||||||
MAIN_BRANCH: ""
|
MAIN_BRANCH: "main"
|
||||||
|
|
||||||
# ===== 服务器配置 =====
|
# ===== 服务器配置 =====
|
||||||
# Gitea 服务器地址(用于生成头像链接和 API 调用)
|
# Gitea 服务器地址(用于生成头像链接和 API 调用)
|
||||||
@@ -63,14 +67,16 @@ env:
|
|||||||
# - "true": 创建为草稿,不会立即发布
|
# - "true": 创建为草稿,不会立即发布
|
||||||
# - "false": 立即发布 Release
|
# - "false": 立即发布 Release
|
||||||
RELEASE_IS_DRAFT: "false"
|
RELEASE_IS_DRAFT: "false"
|
||||||
|
# 统一管理 pre-release 关键词
|
||||||
|
PRERELEASE_KEYWORDS: "alpha|beta|rc|pre|preview|dev|test"
|
||||||
# 额外要上传到 Release 的文件(空格分隔)
|
# 额外要上传到 Release 的文件(空格分隔)
|
||||||
# 例如: "README.md LICENSE docs/guide.pdf"
|
# 例如: "README.md LICENSE docs/guide.pdf"
|
||||||
ADDITIONAL_RELEASE_FILES: ""
|
ADDITIONAL_RELEASE_FILES: ""
|
||||||
|
|
||||||
# ===== Git 提交配置 =====
|
# ===== Git 提交配置 =====
|
||||||
# Git 用户配置
|
# Git 用户配置
|
||||||
GIT_USER_NAME: "github-actions[bot]"
|
GIT_USER_NAME: "ci[bot]"
|
||||||
GIT_USER_EMAIL: "github-actions[bot]@users.noreply.github.com"
|
GIT_USER_EMAIL: "ci[bot]@tinysoft.com.cn"
|
||||||
# Git 提交消息模板
|
# Git 提交消息模板
|
||||||
# 可用变量: {version} - 将被替换为实际的版本号
|
# 可用变量: {version} - 将被替换为实际的版本号
|
||||||
# [skip ci] 标记防止触发无限循环
|
# [skip ci] 标记防止触发无限循环
|
||||||
@@ -88,8 +94,8 @@ env:
|
|||||||
IGNORE_PATTERNS: >-
|
IGNORE_PATTERNS: >-
|
||||||
^Merge |
|
^Merge |
|
||||||
^:memo: Auto update CHANGELOG|
|
^:memo: Auto update CHANGELOG|
|
||||||
\[skip ci\]\s*$|
|
\\[skip ci\\]|
|
||||||
\[ci skip\]\s*$|
|
\\[ci skip\\]|
|
||||||
^Bump version|
|
^Bump version|
|
||||||
^Release v|
|
^Release v|
|
||||||
^chore: update config$|
|
^chore: update config$|
|
||||||
@@ -137,10 +143,14 @@ jobs:
|
|||||||
# 从环境变量读取配置
|
# 从环境变量读取配置
|
||||||
VERSION="${{ github.ref_name }}"
|
VERSION="${{ github.ref_name }}"
|
||||||
|
|
||||||
|
KEYWORDS="${{ env.PRERELEASE_KEYWORDS }}"
|
||||||
|
STRIP_REGEX="-($KEYWORDS)[0-9]*$" # 用于 sed 删除后缀
|
||||||
|
MATCH_REGEX="($KEYWORDS)" # 用于 bash =~ 匹配
|
||||||
|
|
||||||
# 处理 CHANGELOG 版本号
|
# 处理 CHANGELOG 版本号
|
||||||
if [[ "${{ env.CHANGELOG_VERSION_MODE }}" == "strip" ]]; then
|
if [[ "${{ env.CHANGELOG_VERSION_MODE }}" == "strip" ]]; then
|
||||||
# 去除 pre-release 后缀(-beta, -rc1, -alpha 等)
|
# 去除 pre-release 后缀(-beta, -rc1, -alpha 等)
|
||||||
CHANGELOG_VERSION=$(echo "$VERSION" | sed -E 's/-(alpha|beta|rc|pre|preview|dev|test)[0-9]*$//')
|
CHANGELOG_VERSION=$(echo "$VERSION" | sed -E "s/${STRIP_REGEX}//")
|
||||||
echo "📝 CHANGELOG version mode: strip"
|
echo "📝 CHANGELOG version mode: strip"
|
||||||
echo " Tag: $VERSION → CHANGELOG: $CHANGELOG_VERSION"
|
echo " Tag: $VERSION → CHANGELOG: $CHANGELOG_VERSION"
|
||||||
else
|
else
|
||||||
@@ -160,7 +170,7 @@ jobs:
|
|||||||
|
|
||||||
# 智能判断 pre-release
|
# 智能判断 pre-release
|
||||||
if [[ "${{ env.RELEASE_PRERELEASE_MODE }}" == "auto" ]]; then
|
if [[ "${{ env.RELEASE_PRERELEASE_MODE }}" == "auto" ]]; then
|
||||||
if [[ "$VERSION" =~ (alpha|beta|rc|pre|preview|dev|test) ]]; then
|
if [[ "$VERSION" =~ $MATCH_REGEX ]]; then
|
||||||
RELEASE_IS_PRERELEASE="true"
|
RELEASE_IS_PRERELEASE="true"
|
||||||
PRERELEASE_DETECTED="yes (auto-detected: $VERSION contains pre-release keyword)"
|
PRERELEASE_DETECTED="yes (auto-detected: $VERSION contains pre-release keyword)"
|
||||||
else
|
else
|
||||||
@@ -172,34 +182,44 @@ jobs:
|
|||||||
PRERELEASE_DETECTED="${{ env.RELEASE_PRERELEASE_MODE }} (manually configured)"
|
PRERELEASE_DETECTED="${{ env.RELEASE_PRERELEASE_MODE }} (manually configured)"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
# 处理忽略模式(去除空格,保持管道分隔格式)
|
||||||
|
echo "🔧 处理忽略模式..."
|
||||||
|
PROCESSED_PATTERNS=""
|
||||||
|
IFS='|' read -ra PATTERNS_ARRAY <<< "${{ env.IGNORE_PATTERNS }}"
|
||||||
|
|
||||||
|
for pattern in "${PATTERNS_ARRAY[@]}"; do
|
||||||
|
# 使用 sed 去除首尾空格,保留转义字符
|
||||||
|
pattern=$(echo "$pattern" | sed 's/^[[:space:]]*//;s/[[:space:]]*$//')
|
||||||
|
if [ -n "$pattern" ]; then
|
||||||
|
if [ -z "$PROCESSED_PATTERNS" ]; then
|
||||||
|
PROCESSED_PATTERNS="$pattern"
|
||||||
|
else
|
||||||
|
PROCESSED_PATTERNS="$PROCESSED_PATTERNS|$pattern"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
echo "✅ 已处理 $(echo "$PROCESSED_PATTERNS" | grep -o '|' | wc -l | awk '{print $1+1}') 个忽略模式"
|
||||||
|
|
||||||
# 导出处理后的配置到 GitHub 环境变量
|
# 导出处理后的配置到 GitHub 环境变量
|
||||||
echo "CHANGELOG_VERSION=$CHANGELOG_VERSION" >> $GITHUB_ENV
|
echo "CHANGELOG_VERSION=$CHANGELOG_VERSION" >> $GITHUB_ENV
|
||||||
echo "RELEASE_TITLE_PROCESSED=$RELEASE_TITLE_PROCESSED" >> $GITHUB_ENV
|
echo "RELEASE_TITLE_PROCESSED=$RELEASE_TITLE_PROCESSED" >> $GITHUB_ENV
|
||||||
echo "RELEASE_IS_PRERELEASE=$RELEASE_IS_PRERELEASE" >> $GITHUB_ENV
|
echo "RELEASE_IS_PRERELEASE=$RELEASE_IS_PRERELEASE" >> $GITHUB_ENV
|
||||||
echo "COMMIT_MSG=$COMMIT_MSG" >> $GITHUB_ENV
|
echo "COMMIT_MSG=$COMMIT_MSG" >> $GITHUB_ENV
|
||||||
|
|
||||||
# 处理忽略模式(转换为数组)
|
echo "PRERELEASE_STRIP_REGEX=$STRIP_REGEX" >> $GITHUB_ENV
|
||||||
IFS='|' read -ra PATTERNS_ARRAY <<< "${{ env.IGNORE_PATTERNS }}"
|
echo "PRERELEASE_MATCH_REGEX=$MATCH_REGEX" >> $GITHUB_ENV
|
||||||
IGNORE_JSON="["
|
|
||||||
for pattern in "${PATTERNS_ARRAY[@]}"; do
|
echo "IGNORE_PATTERNS_PROCESSED=$PROCESSED_PATTERNS" >> $GITHUB_ENV
|
||||||
# 去除首尾空格
|
|
||||||
pattern=$(echo "$pattern" | xargs)
|
|
||||||
if [ -n "$pattern" ]; then
|
|
||||||
IGNORE_JSON="${IGNORE_JSON}\"${pattern}\","
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
IGNORE_JSON="${IGNORE_JSON%,}]"
|
|
||||||
echo "IGNORE_PATTERNS_JSON=$IGNORE_JSON" >> $GITHUB_ENV
|
|
||||||
|
|
||||||
# 显示配置摘要
|
# 显示配置摘要
|
||||||
echo ""
|
echo ""
|
||||||
echo "📋 Configuration Summary:"
|
echo "📋 Configuration Summary:"
|
||||||
echo " 🏷️ Tag version: $VERSION"
|
echo " 🏷️ Tag version: $VERSION"
|
||||||
echo " 📝 CHANGELOG version: $CHANGELOG_VERSION"
|
echo " 📝 CHANGELOG version: $CHANGELOG_VERSION"
|
||||||
echo " 🌐 Gitea Server: ${{ env.GITEA_SERVER }}"
|
echo " 🌐 Gitea Server: ${{ env.GITEA_SERVER }}"
|
||||||
echo " 📄 CHANGELOG Title: ${{ env.CHANGELOG_SECTION_TITLE }}"
|
echo " 📄 CHANGELOG Title: ${{ env.CHANGELOG_SECTION_TITLE }}"
|
||||||
echo " 🚀 Release Title: $RELEASE_TITLE_PROCESSED"
|
echo " 🚀 Release Title: $RELEASE_TITLE_PROCESSED"
|
||||||
echo " 🏷️ Pre-release: $PRERELEASE_DETECTED"
|
echo " 🏷️ Pre-release: $PRERELEASE_DETECTED"
|
||||||
echo " 📄 Draft: ${{ env.RELEASE_IS_DRAFT }}"
|
echo " 📄 Draft: ${{ env.RELEASE_IS_DRAFT }}"
|
||||||
echo " 💬 Commit Message: $COMMIT_MSG"
|
echo " 💬 Commit Message: $COMMIT_MSG"
|
||||||
echo " 📎 Additional Files: ${ADDITIONAL_RELEASE_FILES:-none}"
|
echo " 📎 Additional Files: ${ADDITIONAL_RELEASE_FILES:-none}"
|
||||||
@@ -259,6 +279,13 @@ jobs:
|
|||||||
|
|
||||||
if [ $? -ne 0 ]; then
|
if [ $? -ne 0 ]; then
|
||||||
echo "❌ 克隆失败"
|
echo "❌ 克隆失败"
|
||||||
|
cat /tmp/git_clone.log
|
||||||
|
|
||||||
|
# 清理残留
|
||||||
|
if [ -d "$REPO_DIR" ]; then
|
||||||
|
rm -rf "$REPO_DIR"
|
||||||
|
fi
|
||||||
|
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
@@ -283,26 +310,37 @@ jobs:
|
|||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# 检测主分支名称
|
|
||||||
echo ""
|
echo ""
|
||||||
echo "🔍 检测主分支名称..."
|
echo "🔍 验证主分支配置..."
|
||||||
if [ -n "${{ env.MAIN_BRANCH }}" ]; then
|
|
||||||
MAIN_BRANCH="${{ env.MAIN_BRANCH }}"
|
# 检查是否配置了主分支
|
||||||
echo "✓ 使用配置的主分支: $MAIN_BRANCH"
|
if [ -z "${{ env.MAIN_BRANCH }}" ]; then
|
||||||
else
|
echo "❌ 错误: 未配置主分支"
|
||||||
# 自动检测 main 或 master
|
echo ""
|
||||||
if git show-ref --verify --quiet refs/remotes/origin/main; then
|
echo "请在 workflow 配置文件的 env 区域设置 MAIN_BRANCH:"
|
||||||
MAIN_BRANCH="main"
|
echo ""
|
||||||
echo "✓ 自动检测到主分支: main"
|
echo "env:"
|
||||||
elif git show-ref --verify --quiet refs/remotes/origin/master; then
|
echo " MAIN_BRANCH: \"main\" # 或 \"master\""
|
||||||
MAIN_BRANCH="master"
|
echo ""
|
||||||
echo "✓ 自动检测到主分支: master"
|
exit 1
|
||||||
else
|
|
||||||
echo "❌ 错误: 无法检测主分支(main 或 master)"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
MAIN_BRANCH="${{ env.MAIN_BRANCH }}"
|
||||||
|
echo "✓ 使用配置的主分支: $MAIN_BRANCH"
|
||||||
|
|
||||||
|
# 验证分支是否存在
|
||||||
|
if ! git show-ref --verify --quiet refs/remotes/origin/$MAIN_BRANCH; then
|
||||||
|
echo "❌ 错误: 配置的分支 '$MAIN_BRANCH' 不存在"
|
||||||
|
echo ""
|
||||||
|
echo "可用的远程分支:"
|
||||||
|
git branch -r | grep -v HEAD
|
||||||
|
echo ""
|
||||||
|
echo "请在 workflow 配置文件中修改 MAIN_BRANCH 为正确的分支名"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "✓ 分支 '$MAIN_BRANCH' 已验证存在"
|
||||||
|
|
||||||
# 切换到主分支
|
# 切换到主分支
|
||||||
echo ""
|
echo ""
|
||||||
echo "🌿 切换到主分支: $MAIN_BRANCH"
|
echo "🌿 切换到主分支: $MAIN_BRANCH"
|
||||||
@@ -346,38 +384,9 @@ jobs:
|
|||||||
echo "======================================"
|
echo "======================================"
|
||||||
echo ""
|
echo ""
|
||||||
|
|
||||||
- name: 🔍 检查版本是否已存在
|
|
||||||
id: check_version
|
|
||||||
if: steps.check_bot.outputs.is_bot_commit != 'true'
|
|
||||||
run: |
|
|
||||||
echo "======================================"
|
|
||||||
echo "🔍 检查 CHANGELOG 版本"
|
|
||||||
echo "======================================"
|
|
||||||
|
|
||||||
cd ${{ env.REPO_DIR }}
|
|
||||||
|
|
||||||
if [ ! -f "CHANGELOG.md" ]; then
|
|
||||||
echo "📝 CHANGELOG.md 不存在,将创建新文件"
|
|
||||||
echo "version_exists=false" >> $GITHUB_OUTPUT
|
|
||||||
else
|
|
||||||
CHANGELOG_VERSION="${{ env.CHANGELOG_VERSION }}"
|
|
||||||
echo "📝 检查版本: $CHANGELOG_VERSION"
|
|
||||||
|
|
||||||
if grep -q "## :bookmark: $CHANGELOG_VERSION" CHANGELOG.md; then
|
|
||||||
echo "⚠️ 版本 $CHANGELOG_VERSION 已存在于 CHANGELOG.md"
|
|
||||||
echo "version_exists=true" >> $GITHUB_OUTPUT
|
|
||||||
else
|
|
||||||
echo "✅ 版本 $CHANGELOG_VERSION 不存在,可以继续"
|
|
||||||
echo "version_exists=false" >> $GITHUB_OUTPUT
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
|
|
||||||
echo "======================================"
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
- name: 📝 生成 CHANGELOG
|
- name: 📝 生成 CHANGELOG
|
||||||
id: changelog
|
id: changelog
|
||||||
if: steps.check_bot.outputs.is_bot_commit != 'true' && steps.check_version.outputs.version_exists != 'true'
|
if: steps.check_bot.outputs.is_bot_commit != 'true'
|
||||||
run: |
|
run: |
|
||||||
echo "======================================"
|
echo "======================================"
|
||||||
echo "📝 生成 CHANGELOG"
|
echo "📝 生成 CHANGELOG"
|
||||||
@@ -407,7 +416,7 @@ jobs:
|
|||||||
|
|
||||||
# 对每个 tag 执行 strip 操作(去除 pre-release 后缀)
|
# 对每个 tag 执行 strip 操作(去除 pre-release 后缀)
|
||||||
if [[ "${{ env.CHANGELOG_VERSION_MODE }}" == "strip" ]]; then
|
if [[ "${{ env.CHANGELOG_VERSION_MODE }}" == "strip" ]]; then
|
||||||
tag_stripped=$(echo "$tag" | sed -E 's/-(alpha|beta|rc|pre|preview|dev|test)[0-9]*$//')
|
tag_stripped=$(echo "$tag" | sed -E "s/${{ env.PRERELEASE_STRIP_REGEX }}//")
|
||||||
else
|
else
|
||||||
tag_stripped="$tag"
|
tag_stripped="$tag"
|
||||||
fi
|
fi
|
||||||
@@ -420,248 +429,397 @@ jobs:
|
|||||||
done <<< "$ALL_TAGS"
|
done <<< "$ALL_TAGS"
|
||||||
|
|
||||||
if [ -z "$PREVIOUS_TAG" ]; then
|
if [ -z "$PREVIOUS_TAG" ]; then
|
||||||
echo "ℹ️ No previous tag found, using all commits"
|
echo "ℹ️ 未找到前一个tag,将使用所有提交"
|
||||||
COMMIT_RANGE=""
|
COMMIT_RANGE="HEAD"
|
||||||
else
|
else
|
||||||
echo "📍 Previous tag: $PREVIOUS_TAG"
|
echo "📍 前一个tag: $PREVIOUS_TAG"
|
||||||
|
|
||||||
# 对 previous tag 也执行 strip,显示对应的 CHANGELOG 版本
|
# 对 previous tag 也执行 strip,显示对应的 CHANGELOG 版本
|
||||||
if [[ "${{ env.CHANGELOG_VERSION_MODE }}" == "strip" ]]; then
|
if [[ "${{ env.CHANGELOG_VERSION_MODE }}" == "strip" ]]; then
|
||||||
PREV_CHANGELOG_VERSION=$(echo "$PREVIOUS_TAG" | sed -E 's/-(alpha|beta|rc|pre|preview|dev|test)[0-9]*$//')
|
PREV_CHANGELOG_VERSION=$(echo "$PREVIOUS_TAG" | sed -E "s/${{ env.PRERELEASE_STRIP_REGEX }}//")
|
||||||
echo " (对应 CHANGELOG 版本: $PREV_CHANGELOG_VERSION)"
|
echo " (对应 CHANGELOG 版本: $PREV_CHANGELOG_VERSION)"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
COMMIT_RANGE="${PREVIOUS_TAG}..${VERSION}"
|
COMMIT_RANGE="${PREVIOUS_TAG}..${VERSION}"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# 获取提交记录
|
|
||||||
echo ""
|
echo ""
|
||||||
echo "📋 获取提交记录..."
|
echo "🔍 扫描提交记录..."
|
||||||
if [ -z "$COMMIT_RANGE" ]; then
|
|
||||||
git log --pretty=format:'%H|%s' > /tmp/commits.txt
|
TEMP_COMMITS=$(mktemp)
|
||||||
else
|
git log $COMMIT_RANGE --no-merges --reverse --format="COMMIT_START%n%H%n%an%n%s%nBODY_START%n%b%nBODY_END" > "$TEMP_COMMITS"
|
||||||
git log --pretty=format:'%H|%s' "$COMMIT_RANGE" > /tmp/commits.txt
|
|
||||||
|
declare -a COMMITS_HASH
|
||||||
|
declare -a COMMITS_AUTHOR
|
||||||
|
declare -a COMMITS_MESSAGE
|
||||||
|
declare -a COMMITS_BODY
|
||||||
|
|
||||||
|
# 从环境变量加载忽略模式 (转换为 bash 数组)
|
||||||
|
IFS='|' read -ra IGNORE_PATTERNS <<< "${{ env.IGNORE_PATTERNS_PROCESSED }}"
|
||||||
|
echo "📋 已加载 ${#IGNORE_PATTERNS[@]} 个忽略模式"
|
||||||
|
|
||||||
|
COMMIT_INDEX=0
|
||||||
|
CURRENT_HASH=""
|
||||||
|
CURRENT_AUTHOR=""
|
||||||
|
CURRENT_MESSAGE=""
|
||||||
|
CURRENT_BODY=""
|
||||||
|
IN_BODY=false
|
||||||
|
SKIPPED_COUNT=0
|
||||||
|
|
||||||
|
while IFS= read -r line; do
|
||||||
|
if [[ "$line" == "COMMIT_START" ]]; then
|
||||||
|
# 处理前一个 commit
|
||||||
|
if [ -n "$CURRENT_HASH" ]; then
|
||||||
|
SHOULD_SKIP=false
|
||||||
|
for pattern in "${IGNORE_PATTERNS[@]}"; do
|
||||||
|
[ -z "$pattern" ] && continue
|
||||||
|
if echo "$CURRENT_MESSAGE" | grep -qiE "$pattern"; then
|
||||||
|
SHOULD_SKIP=true
|
||||||
|
echo " ⏭️ 跳过: ${CURRENT_MESSAGE:0:70}... (匹配: ${pattern})"
|
||||||
|
SKIPPED_COUNT=$((SKIPPED_COUNT + 1))
|
||||||
|
break
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
if [ "$SHOULD_SKIP" = false ]; then
|
||||||
|
COMMITS_HASH[$COMMIT_INDEX]="$CURRENT_HASH"
|
||||||
|
COMMITS_AUTHOR[$COMMIT_INDEX]="$CURRENT_AUTHOR"
|
||||||
|
COMMITS_MESSAGE[$COMMIT_INDEX]="$CURRENT_MESSAGE"
|
||||||
|
COMMITS_BODY[$COMMIT_INDEX]="$CURRENT_BODY"
|
||||||
|
COMMIT_INDEX=$((COMMIT_INDEX + 1))
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
# 重置状态
|
||||||
|
CURRENT_HASH=""
|
||||||
|
CURRENT_AUTHOR=""
|
||||||
|
CURRENT_MESSAGE=""
|
||||||
|
CURRENT_BODY=""
|
||||||
|
IN_BODY=false
|
||||||
|
STATE="HASH"
|
||||||
|
|
||||||
|
elif [[ "$line" == "BODY_START" ]]; then
|
||||||
|
IN_BODY=true
|
||||||
|
CURRENT_BODY=""
|
||||||
|
elif [[ "$line" == "BODY_END" ]]; then
|
||||||
|
IN_BODY=false
|
||||||
|
elif [ "$IN_BODY" = true ]; then
|
||||||
|
if [ -n "$CURRENT_BODY" ]; then
|
||||||
|
CURRENT_BODY="${CURRENT_BODY}"$'\n'"${line}"
|
||||||
|
else
|
||||||
|
CURRENT_BODY="$line"
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
if [ -z "$CURRENT_HASH" ]; then
|
||||||
|
CURRENT_HASH="$line"
|
||||||
|
elif [ -z "$CURRENT_AUTHOR" ]; then
|
||||||
|
CURRENT_AUTHOR="$line"
|
||||||
|
elif [ -z "$CURRENT_MESSAGE" ]; then
|
||||||
|
CURRENT_MESSAGE="$line"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
done < "$TEMP_COMMITS"
|
||||||
|
|
||||||
|
# 处理最后一个 commit
|
||||||
|
if [ -n "$CURRENT_HASH" ]; then
|
||||||
|
SHOULD_SKIP=false
|
||||||
|
for pattern in "${IGNORE_PATTERNS[@]}"; do
|
||||||
|
[ -z "$pattern" ] && continue
|
||||||
|
if echo "$CURRENT_MESSAGE" | grep -qiE "$pattern"; then
|
||||||
|
SHOULD_SKIP=true
|
||||||
|
echo " ⏭️ 跳过: ${CURRENT_MESSAGE:0:70}... (匹配: ${pattern})"
|
||||||
|
SKIPPED_COUNT=$((SKIPPED_COUNT + 1))
|
||||||
|
break
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
if [ "$SHOULD_SKIP" = false ]; then
|
||||||
|
COMMITS_HASH[$COMMIT_INDEX]="$CURRENT_HASH"
|
||||||
|
COMMITS_AUTHOR[$COMMIT_INDEX]="$CURRENT_AUTHOR"
|
||||||
|
COMMITS_MESSAGE[$COMMIT_INDEX]="$CURRENT_MESSAGE"
|
||||||
|
COMMITS_BODY[$COMMIT_INDEX]="$CURRENT_BODY"
|
||||||
|
COMMIT_INDEX=$((COMMIT_INDEX + 1))
|
||||||
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
TOTAL_COMMITS=$(wc -l < /tmp/commits.txt)
|
rm -f "$TEMP_COMMITS"
|
||||||
echo "✓ 找到 $TOTAL_COMMITS 个提交"
|
|
||||||
|
|
||||||
# Python 脚本生成 CHANGELOG
|
VALID_COUNT=$COMMIT_INDEX
|
||||||
python3 << 'PYSCRIPT'
|
|
||||||
import re
|
|
||||||
import json
|
|
||||||
import sys
|
|
||||||
from datetime import datetime
|
|
||||||
|
|
||||||
# 读取配置
|
echo ""
|
||||||
changelog_version = "${{ env.CHANGELOG_VERSION }}"
|
echo "📊 提交统计:"
|
||||||
gitea_server = "${{ env.GITEA_SERVER }}"
|
echo " ✅ 有效提交: $VALID_COUNT"
|
||||||
repo = "${{ github.repository }}"
|
echo " ⏭️ 已跳过: $SKIPPED_COUNT"
|
||||||
section_title = "${{ env.CHANGELOG_SECTION_TITLE }}"
|
echo " 📝 总计: $((VALID_COUNT + SKIPPED_COUNT))"
|
||||||
contributors_title = "${{ env.CHANGELOG_CONTRIBUTORS_TITLE }}"
|
echo ""
|
||||||
|
|
||||||
# 读取忽略模式
|
if [ $VALID_COUNT -eq 0 ]; then
|
||||||
ignore_patterns = json.loads('${{ env.IGNORE_PATTERNS_JSON }}')
|
echo "⚠️ 未找到有效的提交"
|
||||||
print(f"🔍 Loaded {len(ignore_patterns)} ignore patterns:")
|
echo "changelog_updated=false" >> $GITHUB_OUTPUT
|
||||||
for pattern in ignore_patterns:
|
echo "content_changed=false" >> $GITHUB_OUTPUT
|
||||||
print(f" - {pattern}")
|
exit 0
|
||||||
print()
|
fi
|
||||||
|
|
||||||
# 读取提交
|
# ============================================
|
||||||
with open('/tmp/commits.txt', 'r', encoding='utf-8') as f:
|
# 构建 CHANGELOG 条目
|
||||||
lines = f.readlines()
|
# ============================================
|
||||||
|
echo "📄 构建 CHANGELOG 条目..."
|
||||||
|
|
||||||
commits = []
|
REPO_URL="${{ github.server_url }}/${{ github.repository }}"
|
||||||
skipped_commits = []
|
|
||||||
for line in lines:
|
|
||||||
line = line.strip()
|
|
||||||
if not line or '|' not in line:
|
|
||||||
continue
|
|
||||||
|
|
||||||
commit_hash, message = line.split('|', 1)
|
# 初始化条目内容
|
||||||
|
NEW_ENTRY="## :bookmark: ${CHANGELOG_VERSION}\n\n"
|
||||||
|
NEW_ENTRY="${NEW_ENTRY}${CHANGELOG_SECTION_TITLE}\n\n"
|
||||||
|
|
||||||
# 检查是否应该忽略
|
# 处理每个提交
|
||||||
should_ignore = False
|
for ((i=0; i<$VALID_COUNT; i++)); do
|
||||||
matched_pattern = None
|
hash="${COMMITS_HASH[$i]}"
|
||||||
for pattern in ignore_patterns:
|
author="${COMMITS_AUTHOR[$i]}"
|
||||||
if re.search(pattern, message):
|
message="${COMMITS_MESSAGE[$i]}"
|
||||||
should_ignore = True
|
body="${COMMITS_BODY[$i]}"
|
||||||
matched_pattern = pattern
|
|
||||||
break
|
|
||||||
|
|
||||||
if should_ignore:
|
echo " [$((i+1))/$VALID_COUNT] ${hash:0:7}: ${message:0:60}..."
|
||||||
skipped_commits.append((message, matched_pattern))
|
|
||||||
else:
|
|
||||||
commits.append({'hash': commit_hash, 'message': message})
|
|
||||||
|
|
||||||
# 输出统计
|
# 构建提交链接 - 使用短 hash 格式
|
||||||
print(f"📊 Commit Statistics:")
|
short_hash="${hash:0:7}"
|
||||||
print(f" Total: {len(lines)}")
|
COMMIT_LINK="([${short_hash}](${REPO_URL}/commit/${hash}))"
|
||||||
print(f" Valid: {len(commits)}")
|
|
||||||
print(f" Skipped: {len(skipped_commits)}")
|
|
||||||
print()
|
|
||||||
|
|
||||||
if skipped_commits:
|
# 构建作者信息
|
||||||
print("⏭️ Skipped Commits:")
|
AUTHOR_INFO=""
|
||||||
for msg, pattern in skipped_commits:
|
if [ -n "$author" ]; then
|
||||||
print(f" ⏭️ Skipping: {msg[:80]}... (matched: {pattern})")
|
AUTHOR_INFO=" by @${author}"
|
||||||
print()
|
fi
|
||||||
|
|
||||||
if not commits:
|
# 处理 body (如果存在)
|
||||||
print("⚠️ No valid commits found")
|
if [ -n "$body" ]; then
|
||||||
with open('/tmp/changelog_updated.txt', 'w') as f:
|
# 移除首尾空行
|
||||||
f.write('false')
|
cleaned_body=$(echo "$body" | sed -e :a -e '/^\s*$/d;')
|
||||||
sys.exit(0)
|
|
||||||
|
|
||||||
# 收集贡献者
|
if [ -n "$cleaned_body" ]; then
|
||||||
contributors = set()
|
# 有 body: 主题在第一行,body 内容缩进显示,链接和作者放在一起
|
||||||
for commit in commits:
|
NEW_ENTRY="${NEW_ENTRY}- ${message} \n"
|
||||||
# 从提交消息中提取可能的用户名(如果使用了 @username 格式)
|
|
||||||
# 这里简化处理,实际可以通过 git log --format='%an|%ae' 获取
|
|
||||||
pass
|
|
||||||
|
|
||||||
# 生成 CHANGELOG 内容
|
# 将 body 按行添加,每行缩进两个空格,使用 Markdown 换行
|
||||||
changelog_content = f"## :bookmark: {changelog_version}\n\n"
|
while IFS= read -r line; do
|
||||||
changelog_content += f"*Released on {datetime.now().strftime('%Y-%m-%d')}*\n\n"
|
[ -z "$line" ] && continue
|
||||||
changelog_content += f"{section_title}\n\n"
|
NEW_ENTRY="${NEW_ENTRY} ${line} \n"
|
||||||
|
done <<< "$cleaned_body"
|
||||||
|
|
||||||
for commit in commits:
|
# 链接和作者放在缩进行
|
||||||
short_hash = commit['hash'][:7]
|
NEW_ENTRY="${NEW_ENTRY} ${COMMIT_LINK}${AUTHOR_INFO}\n"
|
||||||
message = commit['message']
|
else
|
||||||
changelog_content += f"- {message} ([`{short_hash}`](https://github.com/{repo}/commit/{commit['hash']}))\n"
|
# body 为空 (只有空白): 单行格式
|
||||||
|
NEW_ENTRY="${NEW_ENTRY}- ${message} ${COMMIT_LINK}${AUTHOR_INFO}\n"
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
# 没有 body: 单行格式
|
||||||
|
NEW_ENTRY="${NEW_ENTRY}- ${message} ${COMMIT_LINK}${AUTHOR_INFO}\n"
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
# 如果有贡献者信息,可以在这里添加
|
echo ""
|
||||||
# changelog_content += f"\n{contributors_title}\n\n"
|
echo "👥 收集贡献者..."
|
||||||
|
|
||||||
changelog_content += "\n---\n\n"
|
# 收集贡献者 (去除 bot)
|
||||||
|
# 动态过滤配置的 bot 用户名
|
||||||
|
if [ "$COMMIT_RANGE" = "HEAD" ]; then
|
||||||
|
CONTRIBUTORS=$(git log --pretty=format:"%an" --no-merges | \
|
||||||
|
grep -v "github-actions\[bot\]" | \
|
||||||
|
grep -v "dependabot\[bot\]" | \
|
||||||
|
grep -v "renovate\[bot\]" | \
|
||||||
|
grep -v "^${{ env.GIT_USER_NAME }}$" | \
|
||||||
|
sort -u)
|
||||||
|
else
|
||||||
|
CONTRIBUTORS=$(git log $COMMIT_RANGE --pretty=format:"%an" --no-merges | \
|
||||||
|
grep -v "github-actions\[bot\]" | \
|
||||||
|
grep -v "dependabot\[bot\]" | \
|
||||||
|
grep -v "renovate\[bot\]" | \
|
||||||
|
grep -v "^${{ env.GIT_USER_NAME }}$" | \
|
||||||
|
sort -u)
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ -n "$CONTRIBUTORS" ]; then
|
||||||
|
CONTRIBUTOR_COUNT=$(echo "$CONTRIBUTORS" | wc -l)
|
||||||
|
echo "✓ 找到 ${CONTRIBUTOR_COUNT} 个贡献者"
|
||||||
|
|
||||||
|
NEW_ENTRY="${NEW_ENTRY}\n${{ env.CHANGELOG_CONTRIBUTORS_TITLE }}\n\n"
|
||||||
|
|
||||||
|
while IFS= read -r name; do
|
||||||
|
[ -z "$name" ] && continue
|
||||||
|
NEW_ENTRY="${NEW_ENTRY}<a href=\"${{ env.GITEA_SERVER }}/${name}\">\n"
|
||||||
|
NEW_ENTRY="${NEW_ENTRY} <img src=\"${{ env.GITEA_SERVER }}/${name}.png\" alt=\"${name}\" width=\"35\" height=\"35\" style=\"border-radius: 50%;\" onerror=\"this.src='${{ env.GITEA_SERVER }}/assets/img/avatar_default.png'\" />\n"
|
||||||
|
NEW_ENTRY="${NEW_ENTRY}</a>\n"
|
||||||
|
done <<< "$CONTRIBUTORS"
|
||||||
|
fi
|
||||||
|
|
||||||
|
NEW_ENTRY="${NEW_ENTRY}\n---\n"
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "💾 写入 CHANGELOG.md..."
|
||||||
|
|
||||||
|
# 切换到主分支
|
||||||
|
git checkout ${{ env.MAIN_BRANCH }}
|
||||||
|
|
||||||
|
# ============================================
|
||||||
# 更新或创建 CHANGELOG.md
|
# 更新或创建 CHANGELOG.md
|
||||||
changelog_file = 'CHANGELOG.md'
|
# ============================================
|
||||||
try:
|
|
||||||
with open(changelog_file, 'r', encoding='utf-8') as f:
|
|
||||||
existing_content = f.read()
|
|
||||||
except FileNotFoundError:
|
|
||||||
existing_content = "# :memo: CHANGELOG\n\n"
|
|
||||||
|
|
||||||
# 检查版本是否已存在
|
if [ -f CHANGELOG.md ]; then
|
||||||
if f"## :bookmark: {changelog_version}" in existing_content:
|
# CHANGELOG 文件已存在
|
||||||
print(f"ℹ️ Version {changelog_version} already exists, appending commits")
|
if grep -q "^## :bookmark: ${CHANGELOG_VERSION}$" CHANGELOG.md; then
|
||||||
# 找到版本区块,在其中追加新的提交
|
# 版本已存在 - 内容叠加模式
|
||||||
pattern = rf'(## :bookmark: {re.escape(changelog_version)}.*?\n{re.escape(section_title)}\n\n)(.*?)(\n---|\n## :bookmark: |\Z)'
|
echo "🔄 版本 ${CHANGELOG_VERSION} 已存在,执行内容叠加..."
|
||||||
match = re.search(pattern, existing_content, re.DOTALL)
|
|
||||||
|
|
||||||
if match:
|
# 提取现有版本区域中的 commit hashes (用于去重)
|
||||||
existing_commits = match.group(2).strip()
|
EXISTING_HASHES=$(awk -v version="${CHANGELOG_VERSION}" '
|
||||||
new_commits = changelog_content.split(f"{section_title}\n\n")[1].split("\n---")[0].strip()
|
BEGIN { in_version=0 }
|
||||||
|
/^## :bookmark: / && $0 ~ version"$" { in_version=1; next }
|
||||||
|
/^## :bookmark: / && in_version { in_version=0 }
|
||||||
|
in_version && /\(\[[0-9a-f]{7}\]/ {
|
||||||
|
if (match($0, /\[([0-9a-f]{7})\]/)) {
|
||||||
|
hash = substr($0, RSTART+1, RLENGTH-2)
|
||||||
|
print hash
|
||||||
|
}
|
||||||
|
}
|
||||||
|
' CHANGELOG.md | sort -u)
|
||||||
|
|
||||||
# 合并提交,去重
|
# 找出真正的新 commits (基于 hash 去重)
|
||||||
all_commits_text = existing_commits + "\n" + new_commits
|
NEW_COMMIT_ENTRIES=""
|
||||||
# 简单去重(基于完整行)
|
NEW_COMMIT_COUNT=0
|
||||||
unique_lines = []
|
|
||||||
seen = set()
|
|
||||||
for line in all_commits_text.split('\n'):
|
|
||||||
if line.strip() and line not in seen:
|
|
||||||
unique_lines.append(line)
|
|
||||||
seen.add(line)
|
|
||||||
|
|
||||||
merged_commits = '\n'.join(unique_lines)
|
for ((i=0; i<$VALID_COUNT; i++)); do
|
||||||
|
hash="${COMMITS_HASH[$i]}"
|
||||||
|
short_hash="${hash:0:7}"
|
||||||
|
|
||||||
# 重新组装版本区块
|
# 检查这个 commit 是否已存在
|
||||||
updated_section = match.group(1) + merged_commits + "\n\n---\n"
|
if echo "$EXISTING_HASHES" | grep -q "^${short_hash}$"; then
|
||||||
new_content = existing_content[:match.start()] + updated_section + existing_content[match.end():]
|
echo " ℹ️ 跳过已存在: ${short_hash} ${COMMITS_MESSAGE[$i]:0:50}..."
|
||||||
else:
|
continue
|
||||||
print("⚠️ Could not find version section, prepending new content")
|
fi
|
||||||
# 尝试匹配各种可能的 CHANGELOG 标题格式
|
|
||||||
header_pattern = r'^#\s*(?::[\w_]+:)?\s*CHANGELOG\s*\n'
|
|
||||||
match = re.search(header_pattern, existing_content, re.IGNORECASE | re.MULTILINE)
|
|
||||||
|
|
||||||
if match:
|
# 这是一个新的 commit,添加它
|
||||||
insert_pos = match.end()
|
author="${COMMITS_AUTHOR[$i]}"
|
||||||
if not existing_content[insert_pos:insert_pos+1] == '\n':
|
message="${COMMITS_MESSAGE[$i]}"
|
||||||
new_content = existing_content[:insert_pos] + '\n' + changelog_content + existing_content[insert_pos:]
|
body="${COMMITS_BODY[$i]}"
|
||||||
else:
|
|
||||||
new_content = existing_content[:insert_pos] + '\n' + changelog_content + existing_content[insert_pos+1:]
|
|
||||||
else:
|
|
||||||
# 没有找到标题,在开头插入
|
|
||||||
new_content = f"# :memo: CHANGELOG\n\n{changelog_content}{existing_content}"
|
|
||||||
else:
|
|
||||||
# 插入新版本
|
|
||||||
# 尝试匹配各种可能的 CHANGELOG 标题格式
|
|
||||||
# 支持: # CHANGELOG, # :memo: CHANGELOG, # Changelog 等
|
|
||||||
|
|
||||||
# 尝试找到 CHANGELOG 标题(不区分大小写,可选 emoji)
|
COMMIT_LINK="([${short_hash}](${REPO_URL}/commit/${hash}))"
|
||||||
header_pattern = r'^#\s*(?::[\w_]+:)?\s*CHANGELOG\s*\n'
|
|
||||||
match = re.search(header_pattern, existing_content, re.IGNORECASE | re.MULTILINE)
|
|
||||||
|
|
||||||
if match:
|
# 构建作者信息
|
||||||
# 找到了 CHANGELOG 标题,在其后插入
|
AUTHOR_INFO=""
|
||||||
insert_pos = match.end()
|
if [ -n "$author" ]; then
|
||||||
# 确保标题后有空行
|
AUTHOR_INFO=" by @${author}"
|
||||||
if not existing_content[insert_pos:insert_pos+1] == '\n':
|
fi
|
||||||
new_content = existing_content[:insert_pos] + '\n' + changelog_content + existing_content[insert_pos:]
|
|
||||||
else:
|
|
||||||
new_content = existing_content[:insert_pos] + '\n' + changelog_content + existing_content[insert_pos+1:]
|
|
||||||
else:
|
|
||||||
# 没有找到 CHANGELOG 标题,在文件开头插入标题和内容
|
|
||||||
if existing_content.strip():
|
|
||||||
# 文件有内容但没有 CHANGELOG 标题
|
|
||||||
new_content = f"# :memo: CHANGELOG\n\n{changelog_content}{existing_content}"
|
|
||||||
else:
|
|
||||||
# 文件为空
|
|
||||||
new_content = f"# :memo: CHANGELOG\n\n{changelog_content}"
|
|
||||||
|
|
||||||
# 检查内容是否真的改变
|
if [ -n "$body" ]; then
|
||||||
content_changed = (new_content != existing_content)
|
cleaned_body=$(echo "$body" | sed -e :a -e '/^\s*$/d;')
|
||||||
version_exists = f"## :bookmark: {changelog_version}" in existing_content
|
if [ -n "$cleaned_body" ]; then
|
||||||
|
NEW_COMMIT_ENTRIES="${NEW_COMMIT_ENTRIES}- ${message} \n"
|
||||||
|
while IFS= read -r line; do
|
||||||
|
[ -z "$line" ] && continue
|
||||||
|
NEW_COMMIT_ENTRIES="${NEW_COMMIT_ENTRIES} ${line} \n"
|
||||||
|
done <<< "$cleaned_body"
|
||||||
|
NEW_COMMIT_ENTRIES="${NEW_COMMIT_ENTRIES} ${COMMIT_LINK}${AUTHOR_INFO}\n"
|
||||||
|
else
|
||||||
|
NEW_COMMIT_ENTRIES="${NEW_COMMIT_ENTRIES}- ${message} ${COMMIT_LINK}${AUTHOR_INFO}\n"
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
NEW_COMMIT_ENTRIES="${NEW_COMMIT_ENTRIES}- ${message} ${COMMIT_LINK}${AUTHOR_INFO}\n"
|
||||||
|
fi
|
||||||
|
|
||||||
if content_changed:
|
NEW_COMMIT_COUNT=$((NEW_COMMIT_COUNT + 1))
|
||||||
with open(changelog_file, 'w', encoding='utf-8') as f:
|
done
|
||||||
f.write(new_content)
|
|
||||||
|
|
||||||
print(f"✅ CHANGELOG updated successfully")
|
if [ $NEW_COMMIT_COUNT -gt 0 ]; then
|
||||||
print(f" Added {len(commits)} commits to version {changelog_version}")
|
echo "✓ 发现 ${NEW_COMMIT_COUNT} 个新的commits需要添加"
|
||||||
|
|
||||||
with open('/tmp/changelog_updated.txt', 'w') as f:
|
# 在 Contributors 部分之前插入新的 commits
|
||||||
f.write('true')
|
TEMP_FILE=$(mktemp)
|
||||||
with open('/tmp/content_changed.txt', 'w') as f:
|
IN_VERSION=false
|
||||||
f.write('true')
|
ADDED=false
|
||||||
elif version_exists:
|
|
||||||
# 内容没有变化,但版本已存在
|
|
||||||
# 这通常发生在重建已删除的 tag
|
|
||||||
# 我们仍然应该创建 Release(从现有 CHANGELOG 提取内容)
|
|
||||||
print(f"ℹ️ No new content to add")
|
|
||||||
print(f" Version {changelog_version} already contains all {len(commits)} commits")
|
|
||||||
print(f" This usually happens when recreating a deleted tag")
|
|
||||||
print(f" Will still create Release from existing CHANGELOG content")
|
|
||||||
|
|
||||||
with open('/tmp/changelog_updated.txt', 'w') as f:
|
while IFS= read -r line; do
|
||||||
f.write('true') # 返回 true 以触发 Release 创建
|
# 检测版本标题
|
||||||
with open('/tmp/content_changed.txt', 'w') as f:
|
if [[ "$line" =~ ^##[[:space:]]:bookmark:[[:space:]]${CHANGELOG_VERSION}$ ]]; then
|
||||||
f.write('false') # 但文件没有变化,不需要提交
|
echo "$line" >> "$TEMP_FILE"
|
||||||
else:
|
IN_VERSION=true
|
||||||
# 既没有新内容,版本也不存在(不应该发生)
|
# 检测到 Contributors 标题,在它之前插入新 commits
|
||||||
print(f"⚠️ Unexpected state: no content change and version doesn't exist")
|
elif [[ "$line" =~ ^###[[:space:]]:busts_in_silhouette: ]] && [ "$IN_VERSION" = true ] && [ "$ADDED" = false ]; then
|
||||||
|
echo "" >> "$TEMP_FILE"
|
||||||
|
echo -e "${NEW_COMMIT_ENTRIES}" >> "$TEMP_FILE"
|
||||||
|
echo "$line" >> "$TEMP_FILE"
|
||||||
|
ADDED=true
|
||||||
|
# 遇到下一个版本标题
|
||||||
|
elif [[ "$line" =~ ^##[[:space:]]:bookmark: ]] && [ "$IN_VERSION" = true ]; then
|
||||||
|
# 如果还没添加(可能没有 Contributors 部分)
|
||||||
|
if [ "$ADDED" = false ]; then
|
||||||
|
echo "" >> "$TEMP_FILE"
|
||||||
|
echo -e "${NEW_COMMIT_ENTRIES}" >> "$TEMP_FILE"
|
||||||
|
ADDED=true
|
||||||
|
fi
|
||||||
|
echo "$line" >> "$TEMP_FILE"
|
||||||
|
IN_VERSION=false
|
||||||
|
else
|
||||||
|
echo "$line" >> "$TEMP_FILE"
|
||||||
|
fi
|
||||||
|
done < CHANGELOG.md
|
||||||
|
|
||||||
with open('/tmp/changelog_updated.txt', 'w') as f:
|
# 如果到文件末尾还没添加(版本在最后且没有 Contributors)
|
||||||
f.write('false')
|
if [ "$IN_VERSION" = true ] && [ "$ADDED" = false ]; then
|
||||||
with open('/tmp/content_changed.txt', 'w') as f:
|
echo "" >> "$TEMP_FILE"
|
||||||
f.write('false')
|
echo -e "${NEW_COMMIT_ENTRIES}" >> "$TEMP_FILE"
|
||||||
PYSCRIPT
|
fi
|
||||||
|
|
||||||
UPDATED=$(cat /tmp/changelog_updated.txt)
|
mv "$TEMP_FILE" CHANGELOG.md
|
||||||
CONTENT_CHANGED=$(cat /tmp/content_changed.txt 2>/dev/null || echo "false")
|
echo "✅ 已追加 ${NEW_COMMIT_COUNT} 个新commits到现有版本"
|
||||||
|
|
||||||
echo "changelog_updated=$UPDATED" >> $GITHUB_OUTPUT
|
echo "changelog_updated=true" >> $GITHUB_OUTPUT
|
||||||
echo "content_changed=$CONTENT_CHANGED" >> $GITHUB_OUTPUT
|
echo "content_changed=true" >> $GITHUB_OUTPUT
|
||||||
|
else
|
||||||
|
echo "ℹ️ 所有commits都已存在于CHANGELOG中"
|
||||||
|
echo " (通常发生在重建已删除的 tag)"
|
||||||
|
echo " 将从现有内容创建 Release"
|
||||||
|
|
||||||
if [ "$UPDATED" = "true" ]; then
|
echo "changelog_updated=true" >> $GITHUB_OUTPUT
|
||||||
echo ""
|
echo "content_changed=false" >> $GITHUB_OUTPUT
|
||||||
echo "✅ CHANGELOG 生成完成"
|
fi
|
||||||
|
else
|
||||||
|
# 版本不存在 - 添加新版本条目
|
||||||
|
echo "➕ 添加新版本条目: ${CHANGELOG_VERSION}"
|
||||||
|
|
||||||
|
TEMP_FILE=$(mktemp)
|
||||||
|
|
||||||
|
# 读取第一行 (CHANGELOG 标题)
|
||||||
|
head -n 1 CHANGELOG.md > "$TEMP_FILE"
|
||||||
|
echo "" >> "$TEMP_FILE"
|
||||||
|
|
||||||
|
# 插入新条目
|
||||||
|
echo -e "${NEW_ENTRY}" >> "$TEMP_FILE"
|
||||||
|
|
||||||
|
# 追加剩余内容 (从第3行开始,跳过标题后的空行)
|
||||||
|
tail -n +3 CHANGELOG.md >> "$TEMP_FILE"
|
||||||
|
|
||||||
|
mv "$TEMP_FILE" CHANGELOG.md
|
||||||
|
echo "✅ 已添加新的CHANGELOG条目"
|
||||||
|
|
||||||
|
echo "changelog_updated=true" >> $GITHUB_OUTPUT
|
||||||
|
echo "content_changed=true" >> $GITHUB_OUTPUT
|
||||||
|
fi
|
||||||
else
|
else
|
||||||
echo ""
|
# CHANGELOG 文件不存在 - 创建新文件
|
||||||
echo "ℹ️ 没有有效的提交,跳过 CHANGELOG 更新"
|
echo "📄 创建新的 CHANGELOG.md"
|
||||||
|
|
||||||
|
echo "# :memo: CHANGELOG" > CHANGELOG.md
|
||||||
|
echo "" >> CHANGELOG.md
|
||||||
|
echo -e "${NEW_ENTRY}" >> CHANGELOG.md
|
||||||
|
|
||||||
|
echo "✅ 已创建新的CHANGELOG.md"
|
||||||
|
|
||||||
|
echo "changelog_updated=true" >> $GITHUB_OUTPUT
|
||||||
|
echo "content_changed=true" >> $GITHUB_OUTPUT
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "✅ CHANGELOG 生成完成"
|
||||||
echo "======================================"
|
echo "======================================"
|
||||||
echo ""
|
echo ""
|
||||||
|
|
||||||
@@ -828,10 +986,6 @@ jobs:
|
|||||||
id: upload_assets
|
id: upload_assets
|
||||||
if: steps.changelog.outputs.changelog_updated == 'true'
|
if: steps.changelog.outputs.changelog_updated == 'true'
|
||||||
run: |
|
run: |
|
||||||
echo "======================================"
|
|
||||||
echo "📎 上传 Release 附件"
|
|
||||||
echo "======================================"
|
|
||||||
|
|
||||||
cd ${{ env.REPO_DIR }}
|
cd ${{ env.REPO_DIR }}
|
||||||
|
|
||||||
echo "🔍 提取 Release ID..."
|
echo "🔍 提取 Release ID..."
|
||||||
@@ -862,19 +1016,6 @@ jobs:
|
|||||||
echo "✓ Release ID: $RELEASE_ID"
|
echo "✓ Release ID: $RELEASE_ID"
|
||||||
echo ""
|
echo ""
|
||||||
|
|
||||||
# 上传 CHANGELOG.md
|
|
||||||
echo "📤 上传 CHANGELOG.md..."
|
|
||||||
HTTP_CODE=$(curl -s -o /tmp/upload_response_changelog.json -w "%{http_code}" -X POST \
|
|
||||||
-H "Authorization: token ${{ env.ACCESS_TOKEN }}" \
|
|
||||||
-F "attachment=@CHANGELOG.md" \
|
|
||||||
"${{ github.server_url }}/api/v1/repos/${{ github.repository }}/releases/$RELEASE_ID/assets?name=CHANGELOG.md")
|
|
||||||
|
|
||||||
if [ "$HTTP_CODE" = "201" ] || [ "$HTTP_CODE" = "200" ]; then
|
|
||||||
echo "✅ CHANGELOG.md 上传成功"
|
|
||||||
else
|
|
||||||
echo "⚠️ 警告: CHANGELOG.md 上传失败 (HTTP $HTTP_CODE)"
|
|
||||||
fi
|
|
||||||
|
|
||||||
# 上传额外的文件
|
# 上传额外的文件
|
||||||
if [ -n "${{ env.ADDITIONAL_RELEASE_FILES }}" ]; then
|
if [ -n "${{ env.ADDITIONAL_RELEASE_FILES }}" ]; then
|
||||||
echo ""
|
echo ""
|
||||||
|
|||||||
@@ -1,33 +0,0 @@
|
|||||||
name: Hello from ImmortalWrt
|
|
||||||
|
|
||||||
on:
|
|
||||||
push:
|
|
||||||
branches:
|
|
||||||
- main
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
say-hello:
|
|
||||||
runs-on: company
|
|
||||||
|
|
||||||
steps:
|
|
||||||
- name: 打印问候
|
|
||||||
run: echo "Hello form ImmortalWrt Router!"
|
|
||||||
|
|
||||||
- name: 显示系统信息
|
|
||||||
run: |
|
|
||||||
echo "===== 系统信息 ====="
|
|
||||||
uname -a
|
|
||||||
cat /etc/openwrt_release || echo "不是 OpenWrt 环境"
|
|
||||||
|
|
||||||
- name: 显示 CPU 和内存
|
|
||||||
run: |
|
|
||||||
echo "===== CPU 信息 ====="
|
|
||||||
cat /proc/cpuinfo | grep "model name" | head -1 || echo "ARM 架构"
|
|
||||||
echo "===== 内存信息 ====="
|
|
||||||
free -h
|
|
||||||
|
|
||||||
- name: 显示磁盘空间
|
|
||||||
run: df -h
|
|
||||||
|
|
||||||
- name: 列出当前目录
|
|
||||||
run: ls -la
|
|
||||||
@@ -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
|
||||||
@@ -50,8 +50,8 @@ env:
|
|||||||
MIN_LINES_THRESHOLD: "10"
|
MIN_LINES_THRESHOLD: "10"
|
||||||
|
|
||||||
# ===== Git 配置 =====
|
# ===== Git 配置 =====
|
||||||
GIT_USER_NAME: "github-actions[bot]"
|
GIT_USER_NAME: "ci[bot]"
|
||||||
GIT_USER_EMAIL: "github-actions[bot]@users.noreply.github.com"
|
GIT_USER_EMAIL: "ci[bot]@tinysoft.com.cn"
|
||||||
|
|
||||||
# ===== 平台配置 =====
|
# ===== 平台配置 =====
|
||||||
# 平台类型: github 或 gitea
|
# 平台类型: github 或 gitea
|
||||||
|
|||||||
@@ -1,5 +1,102 @@
|
|||||||
# CHANGELOG
|
# 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
|
## :bookmark: 0.0.1
|
||||||
|
|
||||||
### :pencil: What's Changed
|
### :pencil: What's Changed
|
||||||
|
|||||||
@@ -1,69 +0,0 @@
|
|||||||
# 模板说明
|
|
||||||
|
|
||||||
## :label: 图例说明
|
|
||||||
|
|
||||||
| 图标 | 代码 | 说明 | 图标 | 代码 | 说明 |
|
|
||||||
| :-----------: | :-------------- | :------- | :-------------------: | :---------------------- | :------------ |
|
|
||||||
| :tada: | `:tada:` | 首次发布 | :sparkles: | `:sparkles:` | 新功能 |
|
|
||||||
| :bug: | `:bug:` | Bug 修复 | :rocket: | `:rocket:` | 性能优化 |
|
|
||||||
| :art: | `:art:` | 代码样式 | :recycle: | `:recycle:` | 代码重构 |
|
|
||||||
| :package: | `:package:` | 依赖更新 | :lock: | `:lock:` | 安全修复 |
|
|
||||||
| :warning: | `:warning:` | 废弃警告 | :wrench: | `:wrench:` | 配置变更 |
|
|
||||||
| :wastebasket: | `:wastebasket:` | 删除功能 | :busts_in_silhouette: | `:busts_in_silhouette:` | 贡献者 |
|
|
||||||
| :memo: | `:memo:` | 文档更新 | :bookmark: | `:bookmark:` | 发行/版本标签 |
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## :pushpin: 版本号规范
|
|
||||||
|
|
||||||
### SemVer - 语义版本号
|
|
||||||
|
|
||||||
#### 格式
|
|
||||||
|
|
||||||
```txt
|
|
||||||
MAJOR.MINOR.PATCH
|
|
||||||
```
|
|
||||||
|
|
||||||
#### 字段说明
|
|
||||||
|
|
||||||
| 字段 | 说明 | 何时递增 |
|
|
||||||
| --------- | -------- | ------------------ |
|
|
||||||
| **MAJOR** | 主版本号 | 不兼容的 API 修改 |
|
|
||||||
| **MINOR** | 次版本号 | 向后兼容的功能新增 |
|
|
||||||
| **PATCH** | 修订号 | 向后兼容的问题修正 |
|
|
||||||
|
|
||||||
#### 更新规则
|
|
||||||
|
|
||||||
- **MAJOR(主版本)**:破坏性变更,不向后兼容。递增后 MINOR 和 PATCH 重置为 0
|
|
||||||
- **MINOR(次版本)**:新增功能但保持兼容。递增后 PATCH 重置为 0
|
|
||||||
- **PATCH(修订)**:仅修复 bug,不新增功能
|
|
||||||
|
|
||||||
#### 示例
|
|
||||||
|
|
||||||
```txt
|
|
||||||
1.0.0 # 首个稳定版
|
|
||||||
1.1.0 # 新增功能
|
|
||||||
1.1.1 # Bug 修复
|
|
||||||
2.0.0 # 破坏性变更
|
|
||||||
```
|
|
||||||
|
|
||||||
#### Pre-release 版本
|
|
||||||
|
|
||||||
```txt
|
|
||||||
1.0.0-alpha.1
|
|
||||||
1.0.0-beta
|
|
||||||
1.0.0-rc.1
|
|
||||||
1.0.0
|
|
||||||
```
|
|
||||||
|
|
||||||
#### 初始开发阶段
|
|
||||||
|
|
||||||
```txt
|
|
||||||
0.1.0 # 初始版本
|
|
||||||
0.2.0 # API 未稳定
|
|
||||||
1.0.0 # 首个稳定版 ✅
|
|
||||||
```
|
|
||||||
|
|
||||||
**注意**:`0.x.x` 版本可以随时破坏兼容性
|
|
||||||
|
|
||||||
---
|
|
||||||
+304
-1449
File diff suppressed because it is too large
Load Diff
@@ -46,17 +46,3 @@
|
|||||||
👉 **实用的 Actions 工作流,可直接复制使用**
|
👉 **实用的 Actions 工作流,可直接复制使用**
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
### 📝 [Conventions](./CONVENTIONS.md)
|
|
||||||
|
|
||||||
**文档编写规范和版本命名规则**
|
|
||||||
|
|
||||||
包含内容:
|
|
||||||
|
|
||||||
- 📊 Emoji 图标使用规范
|
|
||||||
- 🔢 版本号命名规则(SemVer)
|
|
||||||
- 📝 [CHANGELOG](./CHANGELOG.md) 模板
|
|
||||||
|
|
||||||
👉 **维护项目文档的统一规范,贡献者必读**
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|||||||
@@ -1,28 +0,0 @@
|
|||||||
services:
|
|
||||||
gitea-runner:
|
|
||||||
build: .
|
|
||||||
container_name: gitea-runner
|
|
||||||
restart: unless-stopped
|
|
||||||
privileged: true
|
|
||||||
volumes:
|
|
||||||
- ./runner-data:/data
|
|
||||||
- ./setup.sh:/data/setup.sh:ro
|
|
||||||
- ./register.sh:/data/register.sh:ro
|
|
||||||
- ./manage.sh:/data/manage.sh:ro
|
|
||||||
- ./entrypoint.sh:/data/entrypoint.sh:ro
|
|
||||||
- /var/run/docker.sock:/var/run/docker.sock
|
|
||||||
|
|
||||||
environment:
|
|
||||||
- TZ=Asia/Shanghai
|
|
||||||
|
|
||||||
# 如果需要使用代理,取消下面的注释并修改为你的代理地址
|
|
||||||
# 注意:容器内访问宿主机需要使用 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"
|
|
||||||
@@ -1,321 +0,0 @@
|
|||||||
#!/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
|
|
||||||
read -p "Enter Gitea instance URL (e.g., https://gitea.example.com): " GITEA_INSTANCE
|
|
||||||
|
|
||||||
# 验证 URL 格式
|
|
||||||
if [[ ! "$GITEA_INSTANCE" =~ ^https?:// ]]; then
|
|
||||||
echo "✗ Error: URL must start with http:// or https://"
|
|
||||||
echo ""
|
|
||||||
continue
|
|
||||||
fi
|
|
||||||
|
|
||||||
# 移除末尾的斜杠
|
|
||||||
GITEA_INSTANCE="${GITEA_INSTANCE%/}"
|
|
||||||
echo "✓ URL validated: $GITEA_INSTANCE"
|
|
||||||
break
|
|
||||||
done
|
|
||||||
|
|
||||||
read -p "Enter registration token: " GITEA_TOKEN
|
|
||||||
|
|
||||||
if [ -z "$GITEA_TOKEN" ]; then
|
|
||||||
echo "✗ Error: Token cannot be empty!"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
read -p "Enter runner name (default: docker-runner): " RUNNER_NAME
|
|
||||||
RUNNER_NAME=${RUNNER_NAME:-docker-runner}
|
|
||||||
|
|
||||||
# 多个 label(逗号分隔,无空格)
|
|
||||||
# ubuntu-22.04:host://ubuntu:22.04,ubuntu-20.04:host://ubuntu:20.04,node:docker://node:18
|
|
||||||
read -p "Enter runner labels (default: ubuntu-22.04:docker://ubuntu:22.04): " RUNNER_LABELS
|
|
||||||
RUNNER_LABELS=${RUNNER_LABELS:-ubuntu-22.04:host://ubuntu:22.04}
|
|
||||||
|
|
||||||
# 创建 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
|
|
||||||
@@ -10,111 +10,134 @@ PERSISTENT_BIN="/data/bin"
|
|||||||
RUNNER_PATH="$PERSISTENT_BIN/act_runner"
|
RUNNER_PATH="$PERSISTENT_BIN/act_runner"
|
||||||
SYSTEM_LINK="/usr/local/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 /data/runners
|
||||||
mkdir -p "$PERSISTENT_BIN"
|
mkdir -p "$PERSISTENT_BIN"
|
||||||
mkdir -p /data/buildx
|
|
||||||
mkdir -p /var/log/supervisor
|
mkdir -p /var/log/supervisor
|
||||||
mkdir -p /var/run
|
mkdir -p /var/run
|
||||||
|
|
||||||
# ============================================
|
# ============================================
|
||||||
# 初始化 Docker Buildx 支持
|
# 初始化 Docker Buildx 支持(可选)
|
||||||
# ============================================
|
# ============================================
|
||||||
echo ""
|
if [ "$ENABLE_BUILDX" = "true" ]; then
|
||||||
echo "Initializing Docker 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..."
|
|
||||||
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
|
|
||||||
}
|
|
||||||
|
|
||||||
# 验证多架构支持
|
|
||||||
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 ""
|
||||||
echo "Setting up Buildx for the first time..."
|
echo "Initializing Docker Buildx..."
|
||||||
|
mkdir -p /data/buildx
|
||||||
|
|
||||||
# 创建 BuildKit 配置
|
# 启动 Docker 守护进程(如果使用主机 socket 则跳过)
|
||||||
cat > /data/buildx/buildkitd.toml <<EOF
|
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]
|
[worker.oci]
|
||||||
max-parallelism = 4
|
max-parallelism = 4
|
||||||
EOF
|
EOF
|
||||||
|
|
||||||
# 创建 Buildx builder
|
# 创建 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 \
|
docker buildx create \
|
||||||
--name gitea-multiarch \
|
--name gitea-multiarch \
|
||||||
--driver docker-container \
|
--driver docker-container \
|
||||||
--bootstrap \
|
--bootstrap \
|
||||||
--use 2>/dev/null
|
--use \
|
||||||
}
|
--config /data/buildx/buildkitd.toml 2>/dev/null || \
|
||||||
fi
|
docker buildx use gitea-multiarch 2>/dev/null
|
||||||
|
|
||||||
echo ""
|
# 验证
|
||||||
|
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 安装
|
# 检查 act_runner 安装
|
||||||
@@ -20,12 +20,17 @@ echo ""
|
|||||||
|
|
||||||
# 获取注册信息并验证
|
# 获取注册信息并验证
|
||||||
while true; do
|
while true; do
|
||||||
read -p "Enter Gitea instance URL (e.g., https://gitea.example.com): " GITEA_INSTANCE
|
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 格式
|
# 验证 URL 格式
|
||||||
if [[ ! "$GITEA_INSTANCE" =~ ^https?:// ]]; then
|
if [[ ! "$GITEA_INSTANCE" =~ ^https?:// ]]; then
|
||||||
echo "✗ Error: URL must start with http:// or https://"
|
echo "✗ Error: URL must start with http:// or https://"
|
||||||
echo ""
|
echo ""
|
||||||
|
unset GITEA_INSTANCE
|
||||||
continue
|
continue
|
||||||
fi
|
fi
|
||||||
|
|
||||||
@@ -35,20 +40,26 @@ while true; do
|
|||||||
break
|
break
|
||||||
done
|
done
|
||||||
|
|
||||||
read -p "Enter registration token: " GITEA_TOKEN
|
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
|
if [ -z "$GITEA_TOKEN" ]; then
|
||||||
echo "✗ Error: Token cannot be empty!"
|
echo "✗ Error: Token cannot be empty!"
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
read -p "Enter runner name (default: docker-runner): " RUNNER_NAME
|
DEFAULT_NAME="${DEFAULT_RUNNER_NAME:-docker-runner}"
|
||||||
RUNNER_NAME=${RUNNER_NAME:-docker-runner}
|
read -p "Enter runner name (default: $DEFAULT_NAME): " RUNNER_NAME
|
||||||
|
RUNNER_NAME=${RUNNER_NAME:-$DEFAULT_NAME}
|
||||||
|
|
||||||
# 多个 label(逗号分隔,无空格)
|
# 多个 label(逗号分隔,无空格)
|
||||||
# ubuntu-22.04:host://ubuntu:22.04,ubuntu-20.04:host://ubuntu:20.04,node:docker://node:18
|
# ubuntu-22.04:host://ubuntu:22.04,ubuntu-20.04:host://ubuntu:20.04,node:docker://node:18
|
||||||
read -p "Enter runner labels (default: ubuntu-22.04:docker://ubuntu:22.04): " RUNNER_LABELS
|
DEFAULT_LABEL="${DEFAULT_RUNNER_LABEL:-ubuntu-22.04:host://ubuntu:22.04}"
|
||||||
RUNNER_LABELS=${RUNNER_LABELS:-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 目录
|
||||||
RUNNER_DIR="/data/runners/${RUNNER_NAME}"
|
RUNNER_DIR="/data/runners/${RUNNER_NAME}"
|
||||||
@@ -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"
|
||||||
+15
-3
@@ -15,12 +15,24 @@ RUN apt-get update && apt-get install -y \
|
|||||||
lsb-release \
|
lsb-release \
|
||||||
qemu-user-static \
|
qemu-user-static \
|
||||||
binfmt-support \
|
binfmt-support \
|
||||||
|
apt-transport-https \
|
||||||
&& rm -rf /var/lib/apt/lists/*
|
&& rm -rf /var/lib/apt/lists/*
|
||||||
|
|
||||||
# 安装 Docker(包含 Buildx 插件)
|
# 安装 Docker(包含 Buildx 插件)
|
||||||
RUN curl -fsSL https://get.docker.com -o get-docker.sh && \
|
RUN install -m 0755 -d /etc/apt/keyrings && \
|
||||||
sh get-docker.sh && \
|
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | gpg --dearmor -o /etc/apt/keyrings/docker.gpg && \
|
||||||
rm get-docker.sh
|
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 && \
|
RUN docker --version && \
|
||||||
@@ -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"
|
||||||
+1
@@ -18,6 +18,7 @@ RUN apt-get update && apt-get install -y \
|
|||||||
jq \
|
jq \
|
||||||
python3 \
|
python3 \
|
||||||
python3-yaml \
|
python3-yaml \
|
||||||
|
lsb-release \
|
||||||
supervisor \
|
supervisor \
|
||||||
ca-certificates \
|
ca-certificates \
|
||||||
&& rm -rf /var/lib/apt/lists/*
|
&& rm -rf /var/lib/apt/lists/*
|
||||||
@@ -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"
|
||||||
@@ -1,30 +0,0 @@
|
|||||||
services:
|
|
||||||
gitea-runner:
|
|
||||||
build: .
|
|
||||||
container_name: gitea-runner
|
|
||||||
restart: unless-stopped
|
|
||||||
volumes:
|
|
||||||
- ./runner-data:/data
|
|
||||||
- ./setup.sh:/data/setup.sh:ro
|
|
||||||
- ./register.sh:/data/register.sh:ro
|
|
||||||
- ./manage.sh:/data/manage.sh:ro
|
|
||||||
- ./entrypoint.sh:/data/entrypoint.sh:ro
|
|
||||||
- /var/run/docker.sock:/var/run/docker.sock
|
|
||||||
|
|
||||||
environment:
|
|
||||||
- TZ=Asia/Shanghai
|
|
||||||
|
|
||||||
# 如果需要使用代理,取消下面的注释并修改为你的代理地址
|
|
||||||
# 注意:容器内访问宿主机需要使用 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"
|
|
||||||
|
|
||||||
# 如果需要使用主机网络,取消下面的注释
|
|
||||||
# network_mode: host
|
|
||||||
@@ -1,134 +0,0 @@
|
|||||||
#!/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"
|
|
||||||
|
|
||||||
# 创建必要目录
|
|
||||||
mkdir -p /data/runners
|
|
||||||
mkdir -p "$PERSISTENT_BIN"
|
|
||||||
mkdir -p /var/log/supervisor
|
|
||||||
mkdir -p /var/run
|
|
||||||
|
|
||||||
# 创建主 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
|
|
||||||
# 没有找到 act_runner
|
|
||||||
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 "This will download and install the Gitea Runner to persistent storage."
|
|
||||||
echo "Container is waiting..."
|
|
||||||
|
|
||||||
# 等待 act_runner 安装
|
|
||||||
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
|
|
||||||
|
|
||||||
# 为每个已注册的 runner 创建 supervisor 配置
|
|
||||||
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"
|
|
||||||
|
|
||||||
# 创建该 runner 的 supervisor 配置
|
|
||||||
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
|
|
||||||
user=root
|
|
||||||
environment=HOME="/root"
|
|
||||||
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 ""
|
|
||||||
echo "Container will continue running and wait for runners..."
|
|
||||||
fi
|
|
||||||
|
|
||||||
echo "Total runners configured: $RUNNER_COUNT"
|
|
||||||
echo ""
|
|
||||||
echo "==================================="
|
|
||||||
echo "Starting Supervisor..."
|
|
||||||
echo "==================================="
|
|
||||||
|
|
||||||
# 启动 supervisord(使用主配置文件)
|
|
||||||
exec /usr/bin/supervisord -c /etc/supervisor/supervisord.conf
|
|
||||||
@@ -1,288 +0,0 @@
|
|||||||
#!/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
|
|
||||||
@@ -1,141 +0,0 @@
|
|||||||
#!/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
|
|
||||||
Reference in New Issue
Block a user