name: ๐งช Playbook ๆต่ฏๅฅไปถ on: push: branches: - main pull_request: branches: - main workflow_dispatch: # ๅ ่ฎธๆๅจ่งฆๅ concurrency: group: test-${{ github.repository }}-${{ github.ref }} cancel-in-progress: true # ========================================== # ๐ง ้ ็ฝฎๅบๅ - ๆต่ฏๅๆฐ # ========================================== env: # ===== ๆต่ฏ็ฏๅข้ ็ฝฎ ===== # ๆต่ฏๅทฅไฝ็ฎๅฝ WORKSPACE_DIR: "/home/workspace" TEST_WORKSPACE: "/home/workspace/playbook-test" jobs: # ========================================== # Job: ๅ จ้ๆต่ฏ # ========================================== test: name: ๐งช ๅ จ้ๆต่ฏ runs-on: ubuntu-22.04 steps: - name: ๐ฅ ๅๅคไปๅบ run: | echo "========================================" echo "๐ฅ ๅๅคไปๅบๅฐ WORKSPACE_DIR" echo "========================================" REPO_NAME="${{ github.event.repository.name }}" REPO_DIR="${{ env.WORKSPACE_DIR }}/$REPO_NAME" TOKEN="${{ secrets.WORKFLOW }}" if [ -n "$TOKEN" ]; then REPO_URL="https://oauth2:${TOKEN}@${GITHUB_SERVER_URL#https://}/${{ github.repository }}.git" else REPO_URL="${GITHUB_SERVER_URL}/${{ github.repository }}.git" fi if [ -d "$REPO_DIR" ]; then if [ -d "$REPO_DIR/.git" ]; then cd "$REPO_DIR" git clean -fdx git reset --hard git fetch --all --tags --force --prune --prune-tags else rm -rf "$REPO_DIR" fi fi if [ ! -d "$REPO_DIR/.git" ]; then mkdir -p "${{ env.WORKSPACE_DIR }}" git clone "$REPO_URL" "$REPO_DIR" cd "$REPO_DIR" fi TARGET_SHA="${{ github.sha }}" TARGET_REF="${{ github.ref }}" if git cat-file -e "$TARGET_SHA^{commit}" 2>/dev/null; then git checkout -f "$TARGET_SHA" else if [ -n "$TARGET_REF" ]; then git fetch origin "$TARGET_REF" git checkout -f FETCH_HEAD else git checkout -f "${{ github.ref_name }}" fi fi git config --global --add safe.directory "$REPO_DIR" echo "REPO_DIR=$REPO_DIR" >> $GITHUB_ENV - name: ๐ง ๅฎ่ฃ ๆต่ฏไพ่ต run: | echo "========================================" echo "๐ง ๅฎ่ฃ ๆต่ฏไพ่ต" echo "========================================" apt-get update apt-get install -y bats cmake clang-format python3-pip python3 -m pip install --upgrade pip python3 -m pip install toml tomli jsonschema yamllint echo "" echo "โ bats ็ๆฌ: $(bats --version)" echo "โ Python ็ๆฌ: $(python3 --version)" echo "========================================" - name: ๐งช ่ฟ่กๅ จ้ๆต่ฏๅนถ็ๆๆฅๅ shell: bash run: | set +e set -o pipefail overall_fail=0 scripts_status="success" templates_status="success" integration_status="success" docs_status="success" echo "========================================" echo "๐ Shell ่ๆฌๆต่ฏ" echo "========================================" cd "$REPO_DIR/tests/scripts" run_bats() { local name="$1" local file="$2" local output="${name}_test_results.tap" if [ ! -f "$file" ]; then echo "โ ๏ธ ๆชๆพๅฐๆต่ฏๆไปถ: $file" scripts_status="failure" overall_fail=1 return fi bats --formatter tap "$file" | tee "$output" if [ $? -ne 0 ]; then echo "โ $name ๆต่ฏๅคฑ่ดฅ" scripts_status="failure" overall_fail=1 else echo "โ $name ๆต่ฏ้่ฟ" fi } run_bats "sync_standards" "test_sync_standards.bats" run_bats "vendor_playbook" "test_vendor_playbook.bats" run_bats "install_codex_skills" "test_install_codex_skills.bats" echo "========================================" echo "๐ ๆจกๆฟ้ช่ฏๆต่ฏ" echo "========================================" cd "$REPO_DIR/tests/templates" run_validator() { local name="$1" local script="$2" if [ ! -f "$script" ]; then echo "โ ๏ธ ๆชๆพๅฐ้ช่ฏ่ๆฌ: $script" templates_status="failure" overall_fail=1 return fi chmod +x "$script" "./$script" if [ $? -ne 0 ]; then echo "โ $name ๆจกๆฟ้ช่ฏๅคฑ่ดฅ" templates_status="failure" overall_fail=1 else echo "โ $name ๆจกๆฟ้ช่ฏ้่ฟ" fi } run_validator "python" "validate_python_templates.sh" run_validator "cpp" "validate_cpp_templates.sh" run_validator "ci" "validate_ci_templates.sh" echo "========================================" echo "๐ ้ๆๆต่ฏ" echo "========================================" mkdir -p "${TEST_WORKSPACE}" cd "${TEST_WORKSPACE}" # ๅๅปบๆต่ฏ้กน็ฎ็ฎๅฝ mkdir -p test-project-tsl mkdir -p test-project-cpp mkdir -p test-project-multi echo "========================================" echo "๐งช ๆต่ฏๅบๆฏ1: TSL ้กน็ฎๆ ๅๅๆญฅ" echo "========================================" cd "${TEST_WORKSPACE}/test-project-tsl" # ๅๅงๅ git ไปๅบ git init git config user.name "Test User" git config user.email "test@example.com" # ๆจกๆ subtree add๏ผๅ ๅซ rulesets ็ญ็น็ฎๅฝ๏ผๆ้ค .git๏ผ mkdir -p docs/standards/playbook tar -C "$REPO_DIR" --exclude .git -cf - . | tar -C docs/standards/playbook -xf - # ่ฟ่กๅๆญฅ่ๆฌ echo "โถ ่ฟ่ก sync_standards.sh tsl" sh docs/standards/playbook/scripts/sync_standards.sh tsl # ้ช่ฏ็ปๆ if [ -d "rulesets/tsl" ] && [ -f "rulesets/tsl/index.md" ]; then echo "โ TSL ่งๅ้ๅๆญฅๆๅ" else echo "โ TSL ่งๅ้ๅๆญฅๅคฑ่ดฅ" integration_status="failure" overall_fail=1 fi if grep -q "# BEGIN playbook .gitattributes" .gitattributes 2>/dev/null \ || grep -q "# Added from playbook .gitattributes" .gitattributes 2>/dev/null \ || grep -q "^\\* text=auto eol=lf" .gitattributes 2>/dev/null; then echo "โ .gitattributes ๆดๆฐๆๅ" else echo "โ .gitattributes ๆดๆฐๅคฑ่ดฅ" integration_status="failure" overall_fail=1 fi echo "========================================" echo "๐งช ๆต่ฏๅบๆฏ2: C++ ้กน็ฎๆ ๅๅๆญฅ" echo "========================================" cd "${TEST_WORKSPACE}/test-project-cpp" git init git config user.name "Test User" git config user.email "test@example.com" mkdir -p docs/standards/playbook tar -C "$REPO_DIR" --exclude .git -cf - . | tar -C docs/standards/playbook -xf - echo "โถ ่ฟ่ก sync_standards.sh cpp" sh docs/standards/playbook/scripts/sync_standards.sh cpp if [ -d "rulesets/cpp" ] && [ -f "rulesets/cpp/index.md" ]; then echo "โ C++ ่งๅ้ๅๆญฅๆๅ" else echo "โ C++ ่งๅ้ๅๆญฅๅคฑ่ดฅ" integration_status="failure" overall_fail=1 fi echo "========================================" echo "๐งช ๆต่ฏๅบๆฏ3: ๅค่ฏญ่จ้กน็ฎๆ ๅๅๆญฅ" echo "========================================" cd "${TEST_WORKSPACE}/test-project-multi" git init git config user.name "Test User" git config user.email "test@example.com" mkdir -p docs/standards/playbook tar -C "$REPO_DIR" --exclude .git -cf - . | tar -C docs/standards/playbook -xf - echo "โถ ่ฟ่ก sync_standards.sh tsl cpp" sh docs/standards/playbook/scripts/sync_standards.sh tsl cpp if [ -d "rulesets/tsl" ] && [ -d "rulesets/cpp" ] && [ -f "rulesets/index.md" ]; then echo "โ ๅค่ฏญ่จ่งๅ้ๅๆญฅๆๅ" else echo "โ ๅค่ฏญ่จ่งๅ้ๅๆญฅๅคฑ่ดฅ" integration_status="failure" overall_fail=1 fi echo "========================================" echo "๐งช ๆต่ฏๅบๆฏ4: vendor_playbook ่ๆฌ" echo "========================================" cd "${TEST_WORKSPACE}" mkdir -p test-project-vendor cd test-project-vendor git init git config user.name "Test User" git config user.email "test@example.com" echo "โถ ่ฟ่ก vendor_playbook.sh" sh "$REPO_DIR/scripts/vendor_playbook.sh" . tsl if [ -d "docs/standards/playbook" ] && [ -d "rulesets/tsl" ]; then echo "โ vendor_playbook ่ๆฌๆง่กๆๅ" else echo "โ vendor_playbook ่ๆฌๆง่กๅคฑ่ดฅ" integration_status="failure" overall_fail=1 fi echo "========================================" echo "๐งน ๆธ ็ๆต่ฏ็ฏๅข..." chmod -R u+w "${TEST_WORKSPACE}" 2>/dev/null || true rm -rf "${TEST_WORKSPACE}" echo "โ ๆธ ็ๅฎๆ" echo "========================================" echo "๐ ๆๆกฃไธ่ดๆงๆฃๆฅ" echo "========================================" cd "$REPO_DIR/tests/integration" if [ -f "check_doc_links.sh" ]; then chmod +x check_doc_links.sh ./check_doc_links.sh if [ $? -eq 0 ]; then echo "โ ๆๆกฃ้พๆฅๆฃๆฅ้่ฟ" else echo "โ ๅ็ฐๆ ๆ้พๆฅ" docs_status="failure" overall_fail=1 fi else echo "โ ๏ธ ๆชๆพๅฐ้พๆฅๆฃๆฅ่ๆฌ๏ผ่ทณ่ฟ" fi echo "========================================" echo "๐ ๆฃๆฅไปฃ็่งๅไธ่ดๆง๏ผไธๅฑๆถๆ๏ผ" echo "========================================" cd "$REPO_DIR" # ๆฃๆฅ rulesets/ ไธๅฑๆถๆๅฎๆดๆง python3 << 'EOF' import sys from pathlib import Path errors = [] warnings = [] print("ๆฃๆฅ Layer 1: rulesets/ (ๆ็ฎ้ๅพ)") print("โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ") # ๆฃๆฅๅ่ฏญ่จ็ rulesets/ ็ฎๅฝ๏ผๅช้ index.md๏ผ agents_base = Path("rulesets") # ๆฃๆฅ rulesets/index.md agents_index = agents_base / "index.md" if not agents_index.exists(): errors.append(f"โ ็ผบๅฐๆไปถ: {agents_index}") elif agents_index.stat().st_size == 0: errors.append(f"โ ๆไปถไธบ็ฉบ: {agents_index}") else: print(f"โ {agents_index}") for lang_dir in ["tsl", "cpp", "python"]: agents_lang = agents_base / lang_dir if not agents_lang.exists(): errors.append(f"โ ็ผบๅฐ็ฎๅฝ: {agents_lang}") continue # ๅชๆฃๆฅ index.md๏ผโค50 ่ก๏ผ index_file = agents_lang / "index.md" if not index_file.exists(): errors.append(f"โ ็ผบๅฐๆไปถ: {index_file}") elif index_file.stat().st_size == 0: errors.append(f"โ ๆไปถไธบ็ฉบ: {index_file}") else: # ๆฃๆฅ่งๆจก๏ผโค50 ่ก๏ผ line_count = len(index_file.read_text(encoding='utf-8').splitlines()) if line_count > 50: warnings.append(f"โ ๏ธ {index_file}: {line_count} ่ก (็ฎๆ : โค50)") else: print(f"โ {index_file} ({line_count} ่ก)") # ๆฃๆฅๆฏๅฆๆๆฎ็็ๆงๆไปถ old_files = ["auth.md", "code_quality.md", "performance.md", "testing.md"] for old_file in old_files: old_path = agents_lang / old_file if old_path.exists(): warnings.append(f"โ ๏ธ ๆฎ็ๆงๆไปถ: {old_path} (ๅบๅ ้ค)") print("") print("ๆฃๆฅ Layer 2: codex/skills/ (ๆ้ๅ ่ฝฝ)") print("โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ") # ๆฃๆฅๅ ณ้ฎ skills skills_base = Path("codex/skills") required_skills = [ ("tsl-guide", ["SKILL.md", "references/primer.md", "references/advanced.md"]), ("performance-optimization", ["SKILL.md"]), ("testing-workflow", ["SKILL.md"]), ] for skill_name, required_files in required_skills: skill_dir = skills_base / skill_name if not skill_dir.exists(): errors.append(f"โ ็ผบๅฐ skill: {skill_dir}") continue for req_file in required_files: file_path = skill_dir / req_file if not file_path.exists(): errors.append(f"โ ็ผบๅฐๆไปถ: {file_path}") elif file_path.stat().st_size == 0: errors.append(f"โ ๆไปถไธบ็ฉบ: {file_path}") else: print(f"โ {file_path}") print("") print("ๆฃๆฅ Layer 3: docs/ (ๆๅจๆๆกฃ)") print("โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ") # ๆฃๆฅๅ ณ้ฎๆๆกฃ่ทฏๅพ docs_paths = [ "docs/tsl/syntax_book/index.md", "docs/tsl/code_style.md", "docs/tsl/naming.md", "docs/cpp/code_style.md", "docs/python/style_guide.md", ] for doc_path in docs_paths: path = Path(doc_path) if not path.exists(): errors.append(f"โ ็ผบๅฐๆๆกฃ: {doc_path}") else: print(f"โ {doc_path}") print("") print("ๆฃๆฅๆถๆๆๆกฃ") print("โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ") # ๆฃๆฅๆฐๅข็ๆถๆๆๆกฃ arch_docs = ["AGENTS.md", "SKILLS.md", "README.md"] for doc in arch_docs: path = Path(doc) if not path.exists(): errors.append(f"โ ็ผบๅฐๆๆกฃ: {doc}") else: print(f"โ {doc}") print("") print("โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ") if warnings: print("\nโ ๏ธ ่ญฆๅ:") for warning in warnings: print(f" {warning}") print("") if errors: print("\nโ ๅ็ฐ้่ฏฏ:") for error in errors: print(f" {error}") sys.exit(1) else: print("โ ไธๅฑๆถๆๅฎๆดๆงๆฃๆฅ้่ฟ") EOF if [ $? -ne 0 ]; then docs_status="failure" overall_fail=1 fi echo "========================================" echo "๐ ็ๆๆต่ฏ็ปผๅๆฅๅ" echo "========================================" format_status() { case "$1" in success) echo "โ ้่ฟ" ;; failure) echo "โ ๅคฑ่ดฅ" ;; *) echo "โ ๆช็ฅ" ;; esac } cat >> $GITHUB_STEP_SUMMARY << EOFSUMMARY # ๐งช Playbook ๆต่ฏๆฅๅ ## ๐ ๆต่ฏๆง่กๆ่ฆ | ๆต่ฏ็ฑปๅ | ็ถๆ | |---------|------| | ๐ Shell ่ๆฌๆต่ฏ | $(format_status "$scripts_status") | | ๐ ๆจกๆฟ้ช่ฏๆต่ฏ | $(format_status "$templates_status") | | ๐ ้ๆๆต่ฏ | $(format_status "$integration_status") | | ๐ ๆๆกฃไธ่ดๆงๆฃๆฅ | $(format_status "$docs_status") | --- ## ๐ ็ธๅ ณ้พๆฅ - ๐ [ๆต่ฏๆๆกฃ](tests/README.md) - ๐ [้ฎ้ขๅ้ฆ](../../issues) - ๐ [ๅผๅๆๅ](docs/index.md) ---