Files
playbook/.gitea/workflows/checks.yml
T
csh d83707de23 🔧 chore(workflows): migrate to prepare + worktree model and merge checks
- add prepare.yml: install tools + maintain shared bare repo, anchors the workflow_run chain
- add checks.yml: merge lint + full test suite into a single workflow_run consumer job
- remove standards-check.yml and test.yml (superseded by checks.yml)
- convert sync-tsl-playbook and update-thirdparty-skills to worktree-model consumers
- unify workflow/job/step display names and emoji
2026-07-21 17:29:24 +08:00

158 lines
6.8 KiB
YAML
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
name: 🔎 校验
on:
workflow_run:
workflows: ["🧰 准备环境"]
types:
- completed
concurrency:
group: checks-${{ github.repository }}-${{ github.event.workflow_run.head_sha }}
cancel-in-progress: true
# ==========================================
# 🔧 配置区域 - 校验参数
# ==========================================
env:
# Prepare 完成后经 workflow_run 触发;Prepare 已装工具 + fetch 到共享 bare 仓库。
# 本 workflow 只做只读校验(lint + 测试),不推任何分支,故 token 仅用于
# 极端情况下补取缺失提交(正常路径 Prepare 已 fetch 到位)。
#
# 安全:ACCESS_TOKEN 不放在 workflow 级 env。lint/test 步骤会执行上游提交
# (PR 场景为不受信输入)的脚本,其环境里不应出现 token;仅下放到
# prepare_worktree 步骤。
WORKSPACE_ROOT: "/data/workspace"
SOURCE_BRANCH: ${{ github.event.workflow_run.head_branch }}
SOURCE_SHA: ${{ github.event.workflow_run.head_sha }}
SOURCE_EVENT: ${{ github.event.workflow_run.event }}
COMMIT_LINT_REQUIRE_EMOJI: "1"
jobs:
checks:
# 仅在 Prepare 成功后触发。Prepare 覆盖 push(main) / pull_request /
# schedule / dispatch,故 checks 在这些场景均会运行。
# lint 与 test 合并为单 job:共用一个临时 worktree,准备一次,顺序执行
# lint 在前 fail-fast,失败即不跑 test)。二者跑同一 SOURCE_SHA、皆只读、
# 无依赖,无需拆分为并行 job(那会重复整段 worktree 准备逻辑 + 多一个 worktree)。
if: ${{ github.event.workflow_run.conclusion == 'success' }}
name: 🔎 规范检查 + 全量测试
runs-on: standard-ubuntu-22
permissions:
contents: read
steps:
- name: 📥 准备临时 Worktree
id: prepare_worktree
shell: bash
env:
ACCESS_TOKEN: ${{ secrets.WORKFLOW }}
run: |
set -euo pipefail
REPO_NAME="${{ github.event.repository.name }}"
HEAD_SHA="${SOURCE_SHA}"
REPOSITORY_DIR="${WORKSPACE_ROOT}/${REPO_NAME}/repository.git"
WORKTREE_DIR="${WORKSPACE_ROOT}/${REPO_NAME}/worktrees/checks-${{ github.run_id }}-${{ github.run_attempt }}"
WORKTREE_LOCK="${WORKSPACE_ROOT}/${REPO_NAME}/worktree-admin.lock"
case "$HEAD_SHA" in
''|*[!0-9a-fA-F]*)
echo "无效的上游提交 SHA: $HEAD_SHA" >&2
exit 1
;;
esac
if [ ! -d "$REPOSITORY_DIR" ] || \
[ "$(git --git-dir="$REPOSITORY_DIR" rev-parse --is-bare-repository 2>/dev/null)" != "true" ]; then
echo "Prepare 未创建有效共享 bare 仓库: $REPOSITORY_DIR" >&2
exit 1
fi
# 正常路径 Prepare 已把上游提交 fetch 到位;极端情况下(bare 仓库被清理
# 重建、或 Prepare 与本 run 之间发生 prune)补取一次,token 仅用于此。
if ! git --git-dir="$REPOSITORY_DIR" cat-file -e "${HEAD_SHA}^{commit}" 2>/dev/null; then
git \
-c credential.helper= \
-c 'credential.helper=!f() { test "$1" = get || exit 0; printf "%s\n" username=oauth2; printf "%s\n" "password=${ACCESS_TOKEN}"; }; f' \
-c credential.interactive=never \
--git-dir="$REPOSITORY_DIR" fetch --prune --force origin \
'+refs/heads/*:refs/remotes/origin/*' || true
fi
if ! git --git-dir="$REPOSITORY_DIR" cat-file -e "${HEAD_SHA}^{commit}"; then
echo "共享仓库中不存在上游提交: $HEAD_SHA(事件: $SOURCE_EVENT" >&2
exit 1
fi
exec 9>"$WORKTREE_LOCK"
flock 9
# 回收陈旧临时 worktree(超过 24h 的 checks-* 目录)。worktree prune 只清理
# 指向已消失目录的 metadata,不删仍存在的陈旧目录,故按 mtime 主动回收。
worktrees_root="$(dirname "$WORKTREE_DIR")"
if [ -d "$worktrees_root" ]; then
find "$worktrees_root" -mindepth 1 -maxdepth 1 -type d -name 'checks-*' \
-mmin +1440 -print 2>/dev/null | while IFS= read -r stale; do
[ "$stale" = "$WORKTREE_DIR" ] && continue
git --git-dir="$REPOSITORY_DIR" worktree remove --force "$stale" 2>/dev/null || rm -rf "$stale"
done
fi
git --git-dir="$REPOSITORY_DIR" worktree prune
if [ -e "$WORKTREE_DIR" ]; then
git --git-dir="$REPOSITORY_DIR" worktree remove --force "$WORKTREE_DIR" 2>/dev/null || rm -rf "$WORKTREE_DIR"
fi
mkdir -p "$(dirname "$WORKTREE_DIR")"
git --git-dir="$REPOSITORY_DIR" worktree add --detach "$WORKTREE_DIR" "$HEAD_SHA"
flock -u 9
git -C "$WORKTREE_DIR" reset --hard "$HEAD_SHA"
git -C "$WORKTREE_DIR" clean -ffdx
echo "REPOSITORY_DIR=$REPOSITORY_DIR" >> "$GITHUB_ENV"
echo "REPO_DIR=$WORKTREE_DIR" >> "$GITHUB_ENV"
echo "✅ Worktree 就绪: $WORKTREE_DIR @ $HEAD_SHA"
- name: 🔍 校验提交信息
shell: bash
run: |
set -euo pipefail
cd "$REPO_DIR"
# 注:经 workflow_run 触发,事件 payload 为 workflow_run,不含 PR title
# lint 脚本会回落到 head commit message 校验(PR 标题本身不再校验)。
echo "🔍 检查 commit message 规范(上游事件: $SOURCE_EVENT..."
python3 .gitea/ci/commit_message_lint.py
echo "✅ Lint 检查通过"
- name: 🧪 运行全量测试
shell: bash
run: |
set -euo pipefail
echo "========================================"
echo "🐍 Python 测试(上游事件: $SOURCE_EVENT"
echo "========================================"
cd "$REPO_DIR"
echo "📋 覆盖:CLI、subtree/snapshot 部署路线、模板同步、文档一致性"
python3 -m unittest discover -s test -p "test_*.py" -v
echo "✅ Python 测试通过"
echo "========================================"
echo "🔗 文档链接检查"
echo "========================================"
python3 test/integration/check_doc_links.py
echo "✅ 文档链接检查通过"
echo "🎉 所有测试完成"
- name: 🧹 清理临时 Worktree
if: always()
shell: bash
run: |
set -uo pipefail
[ -n "${REPOSITORY_DIR:-}" ] || exit 0
[ -n "${REPO_DIR:-}" ] || exit 0
WORKTREE_LOCK="$(dirname "$REPOSITORY_DIR")/worktree-admin.lock"
exec 9>"$WORKTREE_LOCK"
flock 9
git --git-dir="$REPOSITORY_DIR" worktree remove --force "$REPO_DIR" 2>/dev/null || rm -rf "$REPO_DIR"
git --git-dir="$REPOSITORY_DIR" worktree prune
flock -u 9