Files
playbook/.gitea/workflows/sync-tsl-playbook.yml
T
csh 699b431cac feat(workflow): adopt Matt Pocock ticket workflow
Replace the Superpowers plan pipeline with grill-with-docs, specs, local tickets, and ticket-native execution.

BREAKING CHANGE: Remove the legacy Plan CLI, prompt templates, and Superpowers skills.
2026-08-10 16:55:46 +08:00

219 lines
8.0 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: 📦 发布 TSL Playbook
on:
workflow_run:
workflows: ["🧰 准备环境"]
types:
- completed
concurrency:
group: sync-tsl-playbook-${{ github.repository }}
cancel-in-progress: false
# ==========================================
# 🔧 配置区域
# ==========================================
env:
# Prepare 维护共享仓库并读取代码;此处 token 仅用于推送。
ACCESS_TOKEN: ${{ secrets.WORKFLOW }}
# ===== 工作区配置 =====
WORKSPACE_ROOT: "/data/workspace"
WORKSPACE_SLOT: "tsl-playbook"
SOURCE_BRANCH: ${{ github.event.workflow_run.head_branch }}
SOURCE_SHA: ${{ github.event.workflow_run.head_sha }}
# ===== 分支与构建配置 =====
TARGET_BRANCH: "tsl-playbook"
BUILD_SCRIPT: "scripts/build_tsl_playbook.py"
# ===== Git 配置 =====
GIT_USER_NAME: "ci[bot]"
GIT_USER_EMAIL: "ci[bot]@tinysoft.com.cn"
jobs:
sync:
# 仅在 Prepare 于主分支成功后触发;排除 schedule:每日 cron 仅为刷新
# thirdpartymain 代码未变,重建 tsl-playbook 属纯浪费(幂等空推)。
if: ${{ github.event.workflow_run.conclusion == 'success' && (github.event.workflow_run.head_branch == 'main' || github.event.workflow_run.head_branch == 'master') && github.event.workflow_run.event != 'schedule' }}
name: 🔨 构建并发布 tsl-playbook
runs-on: standard-ubuntu-22
permissions:
contents: write
steps:
- name: 🔐 验证 Token 配置
shell: bash
run: |
set -euo pipefail
if [ -z "$ACCESS_TOKEN" ]; then
echo "❌ 未配置 WORKFLOW secret,无法推送 $TARGET_BRANCH" >&2
exit 1
fi
echo "✅ Token 已配置"
echo "🌿 上游分支: ${{ env.SOURCE_BRANCH }}"
echo "📝 上游提交: ${{ env.SOURCE_SHA }}"
- name: 📥 对齐 Worktree
id: prepare_worktree
shell: bash
run: |
set -euo pipefail
REPO_NAME="${{ github.event.repository.name }}"
HEAD_SHA="${{ env.SOURCE_SHA }}"
REPOSITORY_DIR="${WORKSPACE_ROOT}/${REPO_NAME}/repository.git"
WORKTREE_DIR="${WORKSPACE_ROOT}/${REPO_NAME}/worktrees/${WORKSPACE_SLOT}"
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
if ! git --git-dir="$REPOSITORY_DIR" cat-file -e "${HEAD_SHA}^{commit}"; then
echo "共享仓库中不存在上游提交: $HEAD_SHA" >&2
exit 1
fi
if [ ! -f "$WORKTREE_DIR/.git" ]; then
exec 9>"$WORKTREE_LOCK"
flock 9
if [ ! -f "$WORKTREE_DIR/.git" ]; then
if [ -e "$WORKTREE_DIR" ]; then
echo "发布 Worktree 路径已存在但不是 linked worktree: $WORKTREE_DIR" >&2
exit 1
fi
mkdir -p "$(dirname "$WORKTREE_DIR")"
git --git-dir="$REPOSITORY_DIR" worktree add --detach "$WORKTREE_DIR" "$HEAD_SHA"
fi
flock -u 9
fi
common_dir=$(git -C "$WORKTREE_DIR" rev-parse --path-format=absolute --git-common-dir)
if [ "$common_dir" != "$(realpath "$REPOSITORY_DIR")" ]; then
echo "发布 Worktree 不属于共享仓库: $WORKTREE_DIR" >&2
exit 1
fi
git -C "$WORKTREE_DIR" checkout --detach --force "$HEAD_SHA"
git -C "$WORKTREE_DIR" reset --hard "$HEAD_SHA"
git -C "$WORKTREE_DIR" clean -ffdx
actual_sha=$(git -C "$WORKTREE_DIR" rev-parse HEAD)
if [ "$actual_sha" != "$HEAD_SHA" ]; then
echo "发布 Worktree 提交不匹配: 期望 $HEAD_SHA,实际 $actual_sha" >&2
exit 1
fi
echo "REPOSITORY_DIR=$REPOSITORY_DIR" >> "$GITHUB_ENV"
echo "REPO_DIR=$WORKTREE_DIR" >> "$GITHUB_ENV"
echo "REPO_NAME=$REPO_NAME" >> "$GITHUB_ENV"
echo "发布 Worktree: $WORKTREE_DIR @ $actual_sha"
- name: 📦 构建并发布 tsl-playbook
shell: bash
run: |
set -euo pipefail
REPO_DIR="${REPO_DIR}"
REPOSITORY_DIR="${REPOSITORY_DIR}"
TARGET_BRANCH="${TARGET_BRANCH:-tsl-playbook}"
BUILD_SCRIPT="${BUILD_SCRIPT:-scripts/build_tsl_playbook.py}"
cd "$REPO_DIR"
echo "========================================"
echo "🔨 Build bundle and sync $TARGET_BRANCH"
echo "========================================"
git config user.name "$GIT_USER_NAME"
git config user.email "$GIT_USER_EMAIL"
# 校验仍在上游提交,构建的是正确源码。
actual_sha="$(git rev-parse HEAD)"
if [ "$actual_sha" != "${{ env.SOURCE_SHA }}" ]; then
echo "源码 Worktree 不在上游提交: 期望 ${{ env.SOURCE_SHA }},实际 $actual_sha" >&2
exit 1
fi
source_short="$(git rev-parse --short HEAD)"
# 在仓库外构建 bundle,切换分支时不会被清理。
build_dir="$(mktemp -d)"
cleanup() {
rm -rf "$build_dir"
}
trap cleanup EXIT
bundle="$build_dir/tsl-playbook"
python3 "$BUILD_SCRIPT" --output "$bundle"
# 本 workflow 在目标分支上仅拥有以下路径。
managed_paths=(
"AGENTS.md"
"package.json"
"package-lock.json"
".prettierrc.json"
".prettierignore"
"docs/tsl"
"skills/tsl-syntax-reference"
"skills/tsl-api-reference"
"tools/tsl-codegen"
)
for path in "${managed_paths[@]}"; do
if [ ! -e "$bundle/$path" ]; then
echo "ERROR: bundle is missing expected path: $path" >&2
exit 1
fi
done
# 目标分支的引用由 Prepare fetch 到共享仓库;此处无需再 fetch。
if git --git-dir="$REPOSITORY_DIR" show-ref --verify --quiet "refs/remotes/origin/$TARGET_BRANCH"; then
git checkout --force -B "$TARGET_BRANCH" "refs/remotes/origin/$TARGET_BRANCH"
else
# 目标分支尚不存在:创建孤儿分支,清空索引但保留工作树文件。
git checkout --orphan "$TARGET_BRANCH"
git rm -rf --cached --quiet . >/dev/null 2>&1 || true
fi
rm -rf -- "${managed_paths[@]}"
for path in "${managed_paths[@]}"; do
mkdir -p "$(dirname "$path")"
cp -R -- "$bundle/$path" "$path"
done
git add -f -A -- "${managed_paths[@]}"
if git diff --cached --quiet; then
echo "No tsl-playbook changes to publish."
exit 0
fi
git commit -m ":package: deps(tsl): sync tsl-playbook from ${source_short}
Source-Commit: ${{ env.SOURCE_SHA }}"
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 \
push origin "$TARGET_BRANCH"
echo "✅ Published tsl-playbook @ ${source_short}"
- name: 🧹 重置 Worktree
if: always()
shell: bash
run: |
# 持久化 worktree 由下次运行前的 detached checkout + reset + clean 复用,
# 此处仅在结束时 detach,避免留下已检出的分支阻塞其它 worktree。
if [ -n "${REPO_DIR:-}" ] && [ -f "$REPO_DIR/.git" ]; then
git -C "$REPO_DIR" checkout --detach --force "${SOURCE_SHA}" 2>/dev/null || true
fi