♻️ refactor(runner): simplify shell helpers and workflow scripts
This commit is contained in:
parent
40fa747a94
commit
ebd0f94053
|
|
@ -50,14 +50,6 @@ build_mirror_path() {
|
|||
printf '%s/%s/%s.git\n' "${mirror_root}" "${owner}" "${repo_name}"
|
||||
}
|
||||
|
||||
build_mirror_lock_path() {
|
||||
local mirror_root=$1
|
||||
local owner=$2
|
||||
local repo_name=$3
|
||||
|
||||
printf '%s.lock\n' "$(build_mirror_path "${mirror_root}" "${owner}" "${repo_name}")"
|
||||
}
|
||||
|
||||
build_job_workspace_root() {
|
||||
local workspace_root=$1
|
||||
local owner=$2
|
||||
|
|
|
|||
|
|
@ -433,20 +433,20 @@ jobs:
|
|||
echo ""
|
||||
|
||||
# 构建排除参数
|
||||
EXCLUDE_PARAMS=""
|
||||
EXCLUDE_FIND_ARGS=()
|
||||
IFS=',' read -ra EXCLUDES <<< "${{ env.EXCLUDE_DIRS }}"
|
||||
for dir in "${EXCLUDES[@]}"; do
|
||||
EXCLUDE_PARAMS="$EXCLUDE_PARAMS -not -path '*/$dir/*'"
|
||||
EXCLUDE_FIND_ARGS+=(-not -path "*/$dir/*")
|
||||
done
|
||||
|
||||
# 获取所有文件
|
||||
echo "🔍 扫描文件..."
|
||||
|
||||
# 统计总文件数
|
||||
TOTAL_FILES=$(eval "find . -type f $EXCLUDE_PARAMS" | wc -l)
|
||||
TOTAL_FILES=$(find . -type f "${EXCLUDE_FIND_ARGS[@]}" | wc -l)
|
||||
|
||||
# 统计总代码行数(排除空行)
|
||||
TOTAL_CODE=$(eval "find . -type f $EXCLUDE_PARAMS -exec grep -cHv '^[[:space:]]*$' {} + 2>/dev/null" | awk -F: '{sum+=$2} END {print sum+0}')
|
||||
TOTAL_CODE=$(find . -type f "${EXCLUDE_FIND_ARGS[@]}" -exec grep -cHv '^[[:space:]]*$' {} + 2>/dev/null | awk -F: '{sum+=$2} END {print sum+0}')
|
||||
|
||||
echo "📊 统计结果:"
|
||||
echo " - 总文件数: $TOTAL_FILES"
|
||||
|
|
@ -489,10 +489,10 @@ jobs:
|
|||
mkdir -p /tmp/lang_stats
|
||||
|
||||
# 构建排除参数
|
||||
EXCLUDE_PARAMS=""
|
||||
EXCLUDE_FIND_ARGS=()
|
||||
IFS=',' read -ra EXCLUDES <<< "${{ env.EXCLUDE_DIRS }}"
|
||||
for dir in "${EXCLUDES[@]}"; do
|
||||
EXCLUDE_PARAMS="$EXCLUDE_PARAMS -not -path '*/$dir/*'"
|
||||
EXCLUDE_FIND_ARGS+=(-not -path "*/$dir/*")
|
||||
done
|
||||
|
||||
LANGUAGE_COUNT=0
|
||||
|
|
@ -507,22 +507,22 @@ jobs:
|
|||
echo "🔍 统计 $display_name..."
|
||||
|
||||
# 构建扩展名查找条件
|
||||
FIND_CONDITIONS=""
|
||||
LANG_FIND_ARGS=()
|
||||
IFS=',' read -ra EXTS <<< "$extensions"
|
||||
for ext in "${EXTS[@]}"; do
|
||||
if [ -z "$FIND_CONDITIONS" ]; then
|
||||
FIND_CONDITIONS="-name '*.$ext'"
|
||||
if [ "${#LANG_FIND_ARGS[@]}" -eq 0 ]; then
|
||||
LANG_FIND_ARGS+=(-name "*.$ext")
|
||||
else
|
||||
FIND_CONDITIONS="$FIND_CONDITIONS -o -name '*.$ext'"
|
||||
LANG_FIND_ARGS+=(-o -name "*.$ext")
|
||||
fi
|
||||
done
|
||||
|
||||
# 统计文件数
|
||||
FILE_COUNT=$(eval "find . -type f \( $FIND_CONDITIONS \) $EXCLUDE_PARAMS" | wc -l)
|
||||
FILE_COUNT=$(find . -type f \( "${LANG_FIND_ARGS[@]}" \) "${EXCLUDE_FIND_ARGS[@]}" | wc -l)
|
||||
|
||||
if [ "$FILE_COUNT" -gt 0 ]; then
|
||||
# 统计代码行数
|
||||
CODE_LINES=$(eval "find . -type f \( $FIND_CONDITIONS \) $EXCLUDE_PARAMS -exec grep -cHv '^[[:space:]]*$' {} + 2>/dev/null" | awk -F: '{sum+=$2} END {print sum+0}')
|
||||
CODE_LINES=$(find . -type f \( "${LANG_FIND_ARGS[@]}" \) "${EXCLUDE_FIND_ARGS[@]}" -exec grep -cHv '^[[:space:]]*$' {} + 2>/dev/null | awk -F: '{sum+=$2} END {print sum+0}')
|
||||
|
||||
# 只保存超过阈值的语言
|
||||
if [ "$CODE_LINES" -ge "${{ env.MIN_LINES_THRESHOLD }}" ]; then
|
||||
|
|
|
|||
|
|
@ -90,29 +90,6 @@ echo ""
|
|||
|
||||
if [ $FIXED_COUNT -gt 0 ]; then
|
||||
echo -e "${GREEN}✓ 所有问题已自动修复!${NC}"
|
||||
echo ""
|
||||
echo "建议执行以下命令重启容器:"
|
||||
echo " docker compose down"
|
||||
echo " docker compose build --no-cache"
|
||||
echo " docker compose up -d"
|
||||
echo ""
|
||||
|
||||
# 询问是否立即重启
|
||||
read -p "是否立即重启容器? (y/N): " -n 1 -r
|
||||
echo ""
|
||||
if [[ $REPLY =~ ^[Yy]$ ]]; then
|
||||
echo "正在重启容器..."
|
||||
docker compose down
|
||||
docker compose build --no-cache
|
||||
docker compose up -d
|
||||
sleep 3
|
||||
echo ""
|
||||
echo "容器状态:"
|
||||
docker compose ps
|
||||
echo ""
|
||||
echo "查看日志:"
|
||||
docker logs gitea-runner --tail=30
|
||||
fi
|
||||
else
|
||||
echo -e "${GREEN}✓ 所有文件格式正确,无需修复!${NC}"
|
||||
fi
|
||||
|
|
|
|||
|
|
@ -20,6 +20,24 @@ mkdir -p "$PERSISTENT_BIN"
|
|||
mkdir -p /var/log/supervisor
|
||||
mkdir -p /var/run
|
||||
|
||||
create_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
|
||||
}
|
||||
|
||||
ensure_buildx_builder() {
|
||||
docker buildx use gitea-multiarch 2>/dev/null || {
|
||||
echo "⚠ Recreating Buildx builder..."
|
||||
docker buildx rm gitea-multiarch 2>/dev/null || true
|
||||
create_buildx_builder
|
||||
}
|
||||
}
|
||||
|
||||
# ============================================
|
||||
# 初始化 Docker Buildx 支持(可选)
|
||||
# ============================================
|
||||
|
|
@ -104,13 +122,7 @@ if [ "$ENABLE_BUILDX" = "true" ]; then
|
|||
EOF
|
||||
|
||||
# 创建 Buildx builder
|
||||
docker buildx create \
|
||||
--name gitea-multiarch \
|
||||
--driver docker-container \
|
||||
--bootstrap \
|
||||
--use \
|
||||
--config /data/buildx/buildkitd.toml 2>/dev/null || \
|
||||
docker buildx use gitea-multiarch 2>/dev/null
|
||||
create_buildx_builder
|
||||
|
||||
# 验证
|
||||
echo "Verifying Buildx..."
|
||||
|
|
@ -125,15 +137,7 @@ EOF
|
|||
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
|
||||
}
|
||||
ensure_buildx_builder
|
||||
fi
|
||||
|
||||
echo ""
|
||||
|
|
|
|||
|
|
@ -133,11 +133,10 @@ echo "✓ Configuration file generated!"
|
|||
# 创建缓存目录
|
||||
mkdir -p cache
|
||||
|
||||
# 使用 Python 修改配置(最可靠的方法)
|
||||
# 使用 Python 修改配置
|
||||
echo ""
|
||||
echo "Configuring runner settings..."
|
||||
|
||||
if command -v python3 &> /dev/null; then
|
||||
python3 << PYEOF
|
||||
import yaml
|
||||
import sys
|
||||
|
|
@ -184,32 +183,6 @@ except Exception as e:
|
|||
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: 4/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: 4/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..."
|
||||
|
|
|
|||
|
|
@ -5,10 +5,8 @@ SCRIPT_DIR=$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)
|
|||
UPGRADE_HELPER="${SCRIPT_DIR}/upgrade.sh"
|
||||
DEFAULT_RUNNER_VERSION_FALLBACK="${DEFAULT_RUNNER_VERSION_FALLBACK:-0.2.13}"
|
||||
|
||||
if [ -f "${UPGRADE_HELPER}" ]; then
|
||||
# shellcheck source=/dev/null
|
||||
source "${UPGRADE_HELPER}"
|
||||
fi
|
||||
|
||||
echo "=========================================="
|
||||
echo " Gitea Runner Installation Script "
|
||||
|
|
@ -42,15 +40,13 @@ echo "Available versions: https://dl.gitea.com/act_runner/"
|
|||
echo ""
|
||||
|
||||
DEFAULT_RUNNER_VERSION="${DEFAULT_RUNNER_VERSION_FALLBACK}"
|
||||
if declare -F resolve_latest_version_or_fallback >/dev/null 2>&1; then
|
||||
DEFAULT_RUNNER_VERSION=$(resolve_latest_version_or_fallback "${DEFAULT_RUNNER_VERSION_FALLBACK}")
|
||||
fi
|
||||
|
||||
echo "Default install version: ${DEFAULT_RUNNER_VERSION}"
|
||||
read -p "Enter version to install (default: ${DEFAULT_RUNNER_VERSION}): " RUNNER_VERSION
|
||||
RUNNER_VERSION=${RUNNER_VERSION:-$DEFAULT_RUNNER_VERSION}
|
||||
|
||||
if declare -F validate_version >/dev/null 2>&1 && ! validate_version "${RUNNER_VERSION}"; then
|
||||
if ! validate_version "${RUNNER_VERSION}"; then
|
||||
echo "✗ Invalid version format: ${RUNNER_VERSION}"
|
||||
exit 1
|
||||
fi
|
||||
|
|
@ -118,10 +114,7 @@ echo ""
|
|||
# 下载到持久化目录
|
||||
if curl -L "$DOWNLOAD_URL" -o "$INSTALL_PATH"; then
|
||||
chmod +x "$INSTALL_PATH"
|
||||
|
||||
if declare -F validate_binary_arch_or_fail >/dev/null 2>&1; then
|
||||
validate_binary_arch_or_fail "$INSTALL_PATH" "$RUNNER_ARCH"
|
||||
fi
|
||||
|
||||
# 同时创建软链接到系统路径
|
||||
ln -sf "$INSTALL_PATH" "$SYSTEM_PATH"
|
||||
|
|
|
|||
|
|
@ -38,6 +38,10 @@ test_check_crlf_works_from_preset_directory() {
|
|||
)
|
||||
|
||||
! rg -q "文件不存在" "${output_file}" || fail "check_crlf.sh should inspect sibling common scripts even when invoked from preset directory"
|
||||
! rg -q "是否立即重启容器" "${output_file}" || fail "check_crlf.sh should not prompt to restart containers"
|
||||
! rg -q "docker compose down" "${output_file}" || fail "check_crlf.sh should not include compose restart commands"
|
||||
! rg -q "docker compose build --no-cache" "${output_file}" || fail "check_crlf.sh should not take responsibility for rebuilding containers"
|
||||
! rg -q "docker compose up -d" "${output_file}" || fail "check_crlf.sh should not take responsibility for starting containers"
|
||||
|
||||
for file_name in entrypoint.sh setup.sh upgrade.sh register.sh manage.sh; do
|
||||
! has_crlf "${common_dir}/${file_name}" || fail "${file_name} should have CRLF fixed"
|
||||
|
|
|
|||
|
|
@ -60,10 +60,12 @@ test_workflow_doc_describes_workspace_architecture() {
|
|||
|
||||
file="${REPO_ROOT}/WORKFLOW.md"
|
||||
|
||||
grep -q 'Git bare 镜像 + 工作副本' "${file}" || fail "WORKFLOW.md should explicitly describe the bare mirror plus worktree-style model"
|
||||
grep -q '共享仓库缓存' "${file}" || fail "WORKFLOW.md should describe the shared repository cache model"
|
||||
grep -q '独立工作副本' "${file}" || fail "WORKFLOW.md should describe isolated per-job work copies"
|
||||
grep -q '任务结束后' "${file}" || fail "WORKFLOW.md should mention cleanup after workflow completion"
|
||||
grep -Eq '^## .*运行模型' "${file}" || fail "WORKFLOW.md should include a run model section"
|
||||
grep -q 'bare' "${file}" || fail "WORKFLOW.md should describe the bare mirror model"
|
||||
grep -q '工作副本' "${file}" || fail "WORKFLOW.md should describe isolated work copies"
|
||||
grep -Eq '共享.*缓存|缓存.*共享' "${file}" || fail "WORKFLOW.md should describe the shared cache model"
|
||||
grep -Eq '并发|隔离' "${file}" || fail "WORKFLOW.md should mention concurrency or isolation tradeoffs"
|
||||
grep -Eq '结束后.*清理|清理.*工作副本' "${file}" || fail "WORKFLOW.md should mention cleanup after workflow completion"
|
||||
! rg -q 'bootstrap_workspace\.sh' "${file}" || fail "WORKFLOW.md should describe architecture rather than helper implementation"
|
||||
! rg -q '/data/git-mirrors|/home/workspace/jobs' "${file}" || fail "WORKFLOW.md should avoid implementation-specific workspace paths"
|
||||
}
|
||||
|
|
@ -88,13 +90,13 @@ test_readme_has_project_intro_and_navigation() {
|
|||
|
||||
file="${REPO_ROOT}/README.md"
|
||||
|
||||
grep -q '^## 📖 项目简介$' "${file}" || fail "README.md should provide a project intro section"
|
||||
grep -q '^## 📂 文档导航$' "${file}" || fail "README.md should provide a document navigation section"
|
||||
grep -Eq '^## .*项目简介' "${file}" || fail "README.md should provide a project intro section"
|
||||
grep -Eq '^## .*文档导航' "${file}" || fail "README.md should provide a document navigation section"
|
||||
grep -q '\[DEPLOYMENT.md\](\./DEPLOYMENT.md)' "${file}" || fail "README.md should link to DEPLOYMENT.md"
|
||||
grep -q '\[WORKFLOW.md\](\./WORKFLOW.md)' "${file}" || fail "README.md should link to WORKFLOW.md"
|
||||
grep -q '具体部署步骤.*\[DEPLOYMENT.md\](\./DEPLOYMENT.md)' "${file}" || fail "README.md should delegate deployment details to DEPLOYMENT.md"
|
||||
! rg -q '^## 🚀 快速提示$' "${file}" || fail "README.md should not carry concrete deployment tip sections"
|
||||
! rg -q '^## ⚙️ 当前默认行为$' "${file}" || fail "README.md should not carry default behavior details"
|
||||
! rg -q 'docker compose (build|up|exec)' "${file}" || fail "README.md should stay high-level and leave compose commands to deployment docs"
|
||||
}
|
||||
|
||||
test_deployment_doc_stays_runner_focused() {
|
||||
|
|
@ -152,6 +154,51 @@ test_preset_compose_supports_runner_identity_overrides() {
|
|||
fail "buildx arch preset should allow DEFAULT_RUNNER_LABEL override via env"
|
||||
}
|
||||
|
||||
test_register_requires_python_yaml_path() {
|
||||
local file
|
||||
|
||||
file="${REPO_ROOT}/docker-runner/common/register.sh"
|
||||
|
||||
! rg -q 'Python configuration failed, using basic sed' "${file}" || fail "register.sh should not fall back to basic sed when Python config fails"
|
||||
! rg -q 'Python3 not found, applying basic configuration' "${file}" || fail "register.sh should not continue with basic configuration when Python3 is missing"
|
||||
! rg -q "sed -i 's/capacity: 1/capacity: 4/g' config.yaml" "${file}" || fail "register.sh should not mutate config.yaml via sed fallback"
|
||||
grep -q "python3 << PYEOF" "${file}" || fail "register.sh should keep Python-based config generation"
|
||||
}
|
||||
|
||||
test_setup_requires_upgrade_helper() {
|
||||
local file
|
||||
|
||||
file="${REPO_ROOT}/docker-runner/common/setup.sh"
|
||||
|
||||
grep -q '^# shellcheck source=/dev/null$' "${file}" || fail "setup.sh should source upgrade.sh directly"
|
||||
grep -q '^source "\${UPGRADE_HELPER}"$' "${file}" || fail "setup.sh should require sourcing upgrade.sh"
|
||||
! grep -Fq 'if [ -f "${UPGRADE_HELPER}" ]; then' "${file}" || fail "setup.sh should not treat upgrade helper as optional"
|
||||
! rg -q 'declare -F resolve_latest_version_or_fallback' "${file}" || fail "setup.sh should not guard helper functions with declare -F"
|
||||
! rg -q 'declare -F validate_version' "${file}" || fail "setup.sh should not guard validate_version with declare -F"
|
||||
! rg -q 'declare -F validate_binary_arch_or_fail' "${file}" || fail "setup.sh should not guard binary validation with declare -F"
|
||||
}
|
||||
|
||||
test_entrypoint_uses_shared_buildx_builder_creation() {
|
||||
local file
|
||||
|
||||
file="${REPO_ROOT}/docker-runner/common/entrypoint.sh"
|
||||
|
||||
grep -q '^create_buildx_builder() {$' "${file}" || fail "entrypoint.sh should extract Buildx builder creation into a helper"
|
||||
grep -q '^ensure_buildx_builder() {$' "${file}" || fail "entrypoint.sh should extract Buildx builder selection into a helper"
|
||||
grep -q '^[[:space:]]*create_buildx_builder$' "${file}" || fail "entrypoint.sh should use shared builder creation during initial setup"
|
||||
grep -q '^[[:space:]]*ensure_buildx_builder$' "${file}" || fail "entrypoint.sh should use shared builder selection during reuse"
|
||||
}
|
||||
|
||||
test_stats_workflow_avoids_eval_find() {
|
||||
local file
|
||||
|
||||
file="${REPO_ROOT}/.gitea/workflows/update_stats_badge.yaml"
|
||||
|
||||
! rg -q 'eval "find ' "${file}" || fail "stats workflow should avoid eval when building find commands"
|
||||
grep -q 'EXCLUDE_FIND_ARGS=()' "${file}" || fail "stats workflow should build reusable find exclusion arrays"
|
||||
grep -q 'LANG_FIND_ARGS=()' "${file}" || fail "stats workflow should build language-specific find arguments via arrays"
|
||||
}
|
||||
|
||||
test_preset_compose_uses_env_for_instance
|
||||
test_workflows_do_not_hardcode_company_server
|
||||
test_stats_workflow_uses_workflow_secret_consistently
|
||||
|
|
@ -164,5 +211,9 @@ test_deployment_doc_stays_runner_focused
|
|||
test_presets_define_expected_hostname
|
||||
test_preset_env_examples_exist
|
||||
test_preset_compose_supports_runner_identity_overrides
|
||||
test_register_requires_python_yaml_path
|
||||
test_setup_requires_upgrade_helper
|
||||
test_entrypoint_uses_shared_buildx_builder_creation
|
||||
test_stats_workflow_avoids_eval_find
|
||||
|
||||
echo "template_defaults_test.sh: PASS"
|
||||
|
|
|
|||
|
|
@ -53,14 +53,6 @@ test_sanitize_job_name() {
|
|||
assert_eq "release-notes-job" "${actual}" "job names should be filesystem-safe"
|
||||
}
|
||||
|
||||
test_build_lock_path() {
|
||||
local actual
|
||||
|
||||
actual=$(build_mirror_lock_path "/data/git-mirrors" "csh" "actions-template")
|
||||
|
||||
assert_eq "/data/git-mirrors/csh/actions-template.git.lock" "${actual}" "lock path should sit beside the bare mirror"
|
||||
}
|
||||
|
||||
test_repo_owner_and_name_parsing() {
|
||||
local actual
|
||||
|
||||
|
|
@ -167,7 +159,6 @@ test_presets_do_not_mount_workspace_helper() {
|
|||
test_repo_path_layout
|
||||
test_job_identity_prefers_run_metadata
|
||||
test_sanitize_job_name
|
||||
test_build_lock_path
|
||||
test_repo_owner_and_name_parsing
|
||||
test_prepare_and_cleanup_workspace
|
||||
test_register_default_capacity_is_four
|
||||
|
|
|
|||
Loading…
Reference in New Issue