name: "๐Ÿš€ ้“ธๆธŠ CD ยท ่‡ชๅŠจ้ƒจ็ฝฒๅˆฐ guanghulab.com" # โ”โ”โ” ๅทฅๅ• YM-CD-20260307-001 โ”โ”โ” # push ๅˆฐ main โ†’ ๆ ก้ชŒ โ†’ rsync ๅŒๆญฅๅˆฐๆœๅŠกๅ™จ โ†’ Notion ้ƒจ็ฝฒ้€š็Ÿฅ # # ๅฟ…้œ€ GitHub Secrets๏ผˆไป“ๅบ“ Settings โ†’ Secrets โ†’ Actions๏ผ‰: # DEPLOY_HOST โ€” ๆœๅŠกๅ™จ IP # DEPLOY_USER โ€” SSH ็”จๆˆทๅ # DEPLOY_KEY โ€” SSH ็ง้’ฅ๏ผˆๅฎŒๆ•ด PEM ๅ†…ๅฎน๏ผ‰ # DEPLOY_PATH โ€” Nginx ็ฝ‘็ซ™ๆ น็›ฎๅฝ•๏ผˆๅฆ‚ /usr/share/nginx/html๏ผ‰ # # ๅฏ้€‰ Secrets๏ผˆๅทฒๆœ‰ๅˆ™่‡ชๅŠจๅฏ็”จ Notion ้€š็Ÿฅ๏ผ‰: # NOTION_TOKEN โ€” Notion ้›†ๆˆ token # CHANGES_DB_ID โ€” Notion ๅ˜ๆ›ดๆ—ฅๅฟ—ๆ•ฐๆฎๅบ“ ID๏ผˆๆœ‰ๅ†…็ฝฎ้ป˜่ฎคๅ€ผ๏ผ‰ on: push: branches: [main] paths-ignore: - '.github/persona-brain/**' - 'broadcasts-outbox/**' - 'syslog-inbox/**' - 'syslog-processed/**' - 'signal-log/**' - 'dev-nodes/**' workflow_dispatch: permissions: contents: read jobs: # โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ• # Job 1: ้ƒจ็ฝฒๅ‰ๆ ก้ชŒ # โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ• validate: name: "๐Ÿ” ้ƒจ็ฝฒๅ‰ๆ ก้ชŒ" runs-on: ubuntu-latest steps: - name: ๐Ÿ“ฅ ๆฃ€ๅ‡บไปฃ็  uses: actions/checkout@v4 - name: ๐ŸŸข ้…็ฝฎ Node.js uses: actions/setup-node@v4 with: node-version: "20" - name: ๐Ÿ“ฆ ๅฎ‰่ฃ…ไพ่ต–๏ผˆๅฆ‚้œ€่ฆ๏ผ‰ run: | if [ -f "package-lock.json" ] && grep -q '"glob"' package.json; then npm ci --ignore-scripts || npm install --ignore-scripts || echo "โš ๏ธ ไพ่ต–ๅฎ‰่ฃ…ๅคฑ่ดฅ๏ผŒ็ปง็ปญๆ‰ง่กŒ" fi - name: ๐Ÿ” HLI ๅฅ‘็บฆๆ ก้ชŒ run: | if [ -f "scripts/contract-check.js" ]; then echo "๐Ÿ” ๆ‰ง่กŒ HLI ๅฅ‘็บฆๆ ก้ชŒ..." node scripts/contract-check.js else echo "โญ๏ธ scripts/contract-check.js ไธๅญ˜ๅœจ๏ผŒ่ทณ่ฟ‡ HLI ๆ ก้ชŒ" fi - name: ๐Ÿ“‹ ๆจกๅ—ๆŒ‡็บนๆฃ€ๆŸฅ run: | if [ -f "scripts/zhuyuan-module-protocol.js" ]; then echo "๐Ÿ” ๆ‰ง่กŒๆจกๅ—ๆŒ‡็บนๆฃ€ๆŸฅ..." node scripts/zhuyuan-module-protocol.js status else echo "โญ๏ธ scripts/zhuyuan-module-protocol.js ไธๅญ˜ๅœจ๏ผŒ่ทณ่ฟ‡ๆจกๅ—ๆฃ€ๆŸฅ" fi - name: โœ… ๆ ก้ชŒๆฑ‡ๆ€ป run: | echo "### โœ… ้ƒจ็ฝฒๅ‰ๆ ก้ชŒ้€š่ฟ‡" >> $GITHUB_STEP_SUMMARY echo "" >> $GITHUB_STEP_SUMMARY echo "- HLI ๅฅ‘็บฆๆ ก้ชŒ: โœ…" >> $GITHUB_STEP_SUMMARY echo "- ๆจกๅ—ๆŒ‡็บนๆฃ€ๆŸฅ: โœ…" >> $GITHUB_STEP_SUMMARY echo "- ๆไบค: \`${{ github.sha }}\`" >> $GITHUB_STEP_SUMMARY # โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ• # Job 2: rsync ๅŒๆญฅๅˆฐๆœๅŠกๅ™จ # โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ• deploy: name: "๐Ÿš€ ้ƒจ็ฝฒๅˆฐๆœๅŠกๅ™จ" needs: validate runs-on: ubuntu-latest steps: - name: ๐Ÿ“ฅ ๆฃ€ๅ‡บไปฃ็  uses: actions/checkout@v4 - name: ๐Ÿ“ฆ ็กฎไฟ rsync ๅทฒๅฎ‰่ฃ… run: | if ! command -v rsync &>/dev/null; then sudo apt-get update -qq && sudo apt-get install -y rsync fi rsync --version | head -1 - name: ๐Ÿ”‘ ้…็ฝฎ SSH ่ฟžๆŽฅ run: | mkdir -p ~/.ssh echo "${{ secrets.DEPLOY_KEY }}" > ~/.ssh/deploy_key chmod 600 ~/.ssh/deploy_key ssh-keyscan -H ${{ secrets.DEPLOY_HOST }} >> ~/.ssh/known_hosts 2>/dev/null - name: ๐Ÿ”’ ้ƒจ็ฝฒๅ‰ๅฎ‰ๅ…จๆฃ€ๆŸฅ run: | if [ ! -f "docs/index.html" ]; then echo "โŒ docs/index.html ไธๅญ˜ๅœจ๏ผŒไธญๆญข้ƒจ็ฝฒไปฅ้˜ฒๆธ…็ฉบ็”Ÿไบง็Žฏๅขƒ" exit 1 fi FILE_COUNT=$(find docs/ -type f | wc -l) if [ "$FILE_COUNT" -lt 2 ]; then echo "โŒ docs/ ็›ฎๅฝ•ๆ–‡ไปถๆ•ฐๅผ‚ๅธธ๏ผˆไป… ${FILE_COUNT} ไธช๏ผ‰๏ผŒไธญๆญข้ƒจ็ฝฒ" exit 1 fi echo "โœ… docs/ ็›ฎๅฝ•ๅŒ…ๅซ ${FILE_COUNT} ไธชๆ–‡ไปถ๏ผŒๅฎ‰ๅ…จๆฃ€ๆŸฅ้€š่ฟ‡" - name: ๐Ÿš€ rsync ๅŒๆญฅๅˆฐๆœๅŠกๅ™จ run: | echo "๐Ÿ“ก ๅผ€ๅง‹ๅŒๆญฅๅˆฐ ${{ secrets.DEPLOY_HOST }}:${{ secrets.DEPLOY_PATH }}" rsync -avz --delete-after \ --exclude '.git' \ --exclude '.github' \ --exclude 'node_modules' \ --exclude 'scripts' \ --exclude 'syslog-inbox' \ --exclude 'syslog-processed' \ --exclude 'signal-log' \ --exclude 'dev-nodes' \ --exclude 'broadcasts-outbox' \ --exclude 'backend-integration' \ --exclude 'tests' \ --exclude 'src' \ --exclude 'cost-control' \ --exclude 'notion-push' \ --exclude 'multi-persona' \ --exclude 'status-board' \ --exclude 'reports' \ --exclude 'guanghulab-main' \ --exclude 'package*.json' \ --exclude 'tsconfig.json' \ --exclude 'next.config.ts' \ --exclude 'postcss.config.mjs' \ --exclude 'jest.smoke.config.js' \ --exclude 'ecosystem.config.js' \ --exclude '.gitignore' \ --exclude 'CNAME' \ -e "ssh -i ~/.ssh/deploy_key" \ docs/ \ ${{ secrets.DEPLOY_USER }}@${{ secrets.DEPLOY_HOST }}:${{ secrets.DEPLOY_PATH }}/ echo "โœ… ๅŒๆญฅๅฎŒๆˆ" - name: ๐Ÿ” ้ชŒ่ฏ้ƒจ็ฝฒ run: | ssh -i ~/.ssh/deploy_key \ ${{ secrets.DEPLOY_USER }}@${{ secrets.DEPLOY_HOST }} \ "echo 'โœ… ๆœๅŠกๅ™จ่ฟžๆŽฅๆญฃๅธธ' && ls -la ${{ secrets.DEPLOY_PATH }}/ | head -20" - name: ๐Ÿ“ ้ƒจ็ฝฒๆฑ‡ๆ€ป run: | echo "### ๐Ÿš€ ้ƒจ็ฝฒๅฎŒๆˆ" >> $GITHUB_STEP_SUMMARY echo "" >> $GITHUB_STEP_SUMMARY echo "- ็›ฎๆ ‡: \`${{ secrets.DEPLOY_HOST }}:${{ secrets.DEPLOY_PATH }}\`" >> $GITHUB_STEP_SUMMARY echo "- ๆไบค: \`${{ github.sha }}\`" >> $GITHUB_STEP_SUMMARY echo "- ๆ—ถ้—ด: $(TZ=Asia/Shanghai date '+%Y-%m-%d %H:%M CST')" >> $GITHUB_STEP_SUMMARY # โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ• # Job 3: Notion ้ƒจ็ฝฒ้€š็Ÿฅ # โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ• notify: name: "๐Ÿ“ก ้ƒจ็ฝฒ้€š็Ÿฅ โ†’ Notion" needs: deploy runs-on: ubuntu-latest if: success() steps: - name: ๐Ÿ“ฅ ๆฃ€ๅ‡บไปฃ็  uses: actions/checkout@v4 with: fetch-depth: 2 - name: ๐ŸŸข ้…็ฝฎ Node.js uses: actions/setup-node@v4 with: node-version: "20" - name: ๐Ÿ“ก ๆŽจ้€้ƒจ็ฝฒ่ฎฐๅฝ•ๅˆฐ Notion env: NOTION_TOKEN: ${{ secrets.NOTION_TOKEN }} CHANGES_DB_ID: ${{ secrets.CHANGES_DB_ID }} EVENT_TYPE: commit COMMIT_SHA: ${{ github.sha }} COMMIT_MSG: "[CD ้ƒจ็ฝฒ] ${{ github.event.head_commit.message }}" COMMITTER: ${{ github.event.head_commit.author.name || github.actor }} COMMIT_TIMESTAMP: ${{ github.event.head_commit.timestamp }} BRANCH: ${{ github.ref_name }} run: | CHANGED=$(git diff --name-only HEAD~1 HEAD 2>/dev/null || true) export CHANGED_FILES="$CHANGED" if [ -f "scripts/notion-bridge.js" ]; then node scripts/notion-bridge.js changes echo "โœ… Notion ้ƒจ็ฝฒ้€š็Ÿฅๅทฒๅ‘้€" else echo "โญ๏ธ scripts/notion-bridge.js ไธๅญ˜ๅœจ๏ผŒ่ทณ่ฟ‡ Notion ้€š็Ÿฅ" fi