Files
playbook/.gitea/workflows/checks.yml
T
csh 736d1a8ad7 feat(tsl-syntax-reference): harden retrieval contracts
Add stable section IDs, structural and routing regressions, quickstart consistency checks, and CI enforcement.

BREAKING CHANGE: replace heading-derived Section IDs with explicit syntax-NN-NNN identifiers.
2026-07-31 10:05:15 +08:00

175 lines
7.6 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 "📦 安装锁定的 Node.js 校验工具"
npm ci --ignore-scripts --no-audit --no-fund --no-bin-links
echo "📋 覆盖:CLI、subtree/snapshot 部署路线、模板同步、文档一致性"
python3 -m unittest discover -s test -p "test_*.py" -v
echo "✅ Python 测试通过"
echo "========================================"
echo "🧭 TSL Syntax Reference 结构检查"
echo "========================================"
python3 skills/tsl-syntax-reference/scripts/lookup.py --check
echo "✅ TSL Syntax Reference 结构检查通过"
echo "========================================"
echo "🎨 TSL Syntax Reference 格式检查"
echo "========================================"
node node_modules/prettier/bin/prettier.cjs --check skills/tsl-syntax-reference
echo "✅ TSL Syntax Reference 格式检查通过"
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