0b7dd466ec
- Add verbose logging to see exact error - Use actual RSA host key from git.np-dms.work:2222 - Test SSH connection before clone
181 lines
6.8 KiB
YAML
181 lines
6.8 KiB
YAML
name: CI / CD Pipeline
|
|
|
|
on:
|
|
push:
|
|
branches: [ main, develop ]
|
|
pull_request:
|
|
workflow_dispatch:
|
|
|
|
jobs:
|
|
# ============================================================
|
|
# JOB 1 : CI & Quality Gate
|
|
# ============================================================
|
|
build:
|
|
runs-on: ubuntu-latest
|
|
timeout-minutes: 15
|
|
steps:
|
|
- name: Checkout (SSH)
|
|
run: |
|
|
set -e # Exit on any error
|
|
echo "Setting up SSH..."
|
|
mkdir -p ~/.ssh
|
|
chmod 700 ~/.ssh
|
|
|
|
echo "Adding deploy key..."
|
|
echo "${{ secrets.DEPLOY_KEY }}" > ~/.ssh/id_rsa
|
|
chmod 600 ~/.ssh/id_rsa
|
|
|
|
echo "Testing SSH connection..."
|
|
ssh -T -p 2222 git@git.np-dms.work || true
|
|
|
|
echo "Adding known hosts..."
|
|
ssh-keyscan -p 2222 git.np-dms.work >> ~/.ssh/known_hosts 2>/dev/null || echo "ssh-keyscan failed, trying manual known hosts"
|
|
|
|
# Add actual host key
|
|
echo "[git.np-dms.work]:2222 ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAACAQC3ii1sfG2oUWfO6xW9RNXWJNT4Qnv/jE7b/2u8lqpyrbmFs5GWflj7AwGkYL1OIXb5oamOJVAnPyypDnxPmsqEwCoqBeytkgl4GG5ToDju7nXLFB83C8o8yIgpNjM8hWM8cbbSRo45eRV8uR42F8Z/bfCYAthJCAEXs0g3OBAHOk9nSCxGXbS46WTuV4FhfbnjlJ6a8rfSjYoJ3kRaw9kyCr5vzQfvE4As4nLy4iZWM1g/Nif1G2n+CHBH5wlOCfcjDBkPfjJ7Xmoo99ZiQUqFsYaQ78qZFbtKrcMkGfhPvo1tGAcEJeZJft+gbONHAJy1462nEjqDKcq94V5TYNK10O/Qy+JB1eLrGVeeyjKep+tCtJrIVzeXtniphl0G2TYjUmdSUFVGOO1Ku1v0c+1yIqxVoe8uI/d7PCae3U0wAHPWCoX7G5DILaeW8YpBVqhInugjuXsgIuRPt08xO2AXV3CLM5AKWMfsufz5hIR+gga7sCSofBpYRyR8w6Ov8NdfVVjFix8K1XuAz1R7RCTwtMvI3Ft+HYiICvKbVotx6w8mbI5klpOSc3O76KhcYf6sQS/wu8SDBATFhOzbfoIaS3kaZtDwThKLnjjwDwiE9ivoK2W8p7pCJkB1WVdNkiE4E12q8P+R90Sp984GRGlIdz0uf7EXZIxsSomHh5TarQ==" >> ~/.ssh/known_hosts
|
|
|
|
echo "Cloning repository..."
|
|
git clone --depth 1 ssh://git@git.np-dms.work:2222/np-dms/lcbp3.git .
|
|
|
|
echo "Fetching and resetting to main..."
|
|
git fetch origin main
|
|
git reset --hard origin/main
|
|
|
|
echo "Checkout completed successfully"
|
|
|
|
# ── [1] pnpm ต้องมาก่อน setup-node เสมอ ────────────────
|
|
- name: ⚙️ Install pnpm
|
|
uses: pnpm/action-setup@v4
|
|
# version อ่านจาก packageManager field ใน package.json อัตโนมัติ
|
|
|
|
- name: ⚙️ Setup Node
|
|
uses: actions/setup-node@v4
|
|
with:
|
|
node-version: 20
|
|
# ลบ cache: "pnpm" ออก — ใช้ volume mount บน runner แทน
|
|
|
|
# ── [2] ชี้ store ไปที่ volume ที่ mount ไว้ ─────────────
|
|
- name: 🔧 Set pnpm store path
|
|
run: pnpm config set store-dir /root/.local/share/pnpm
|
|
|
|
- name: 📦 Install deps
|
|
run: pnpm install --frozen-lockfile
|
|
|
|
- name: 🧹 Lint
|
|
run: pnpm lint
|
|
|
|
- name: 🔍 Security & quality checks
|
|
run: |
|
|
# UUID misuse check (ADR-019)
|
|
if grep -r --include="*.ts" --include="*.tsx" --exclude-dir={node_modules,.next,.agents,.git,scripts,test,__tests__} "parseInt(.*uuid" .; then
|
|
echo "❌ UUID misuse detected"
|
|
exit 1
|
|
fi
|
|
# console.log check (Clean Code)
|
|
if grep -r --include="*.ts" --include="*.tsx" --exclude-dir={node_modules,.next,.agents,.git,scripts,test,__tests__} "console.log" .; then
|
|
echo "❌ console.log detected"
|
|
exit 1
|
|
fi
|
|
|
|
# ── [3] แยก step — เห็น failure ได้ชัดขึ้น ──────────────
|
|
- name: 🧪 Test backend
|
|
run: pnpm test
|
|
working-directory: backend
|
|
|
|
- name: 🧪 Test frontend
|
|
run: pnpm test run
|
|
working-directory: frontend
|
|
|
|
# ============================================================
|
|
# JOB 2 : Deploy — Trigger Blue-Green on QNAP
|
|
# ============================================================
|
|
deploy:
|
|
needs: build
|
|
if: github.ref == 'refs/heads/main'
|
|
runs-on: self-hosted
|
|
steps:
|
|
- name: � Checkout
|
|
uses: actions/checkout@v4
|
|
|
|
- name: 🔐 Setup SSH and Deploy to QNAP
|
|
run: |
|
|
# Ensure sshpass is available (install if needed)
|
|
if ! command -v sshpass &> /dev/null; then
|
|
apt-get update -qq && apt-get install -y -qq sshpass
|
|
fi
|
|
|
|
# Create remote deployment script
|
|
REMOTE_SCRIPT=$(cat << 'SCRIPT_EOF'
|
|
set -e
|
|
export PATH="/share/CACHEDEV1_DATA/.qpkg/container-station/bin:/opt/bin:/usr/local/bin:/usr/bin:/bin:$PATH"
|
|
|
|
echo "=========================================="
|
|
echo "Starting QNAP Deployment Process"
|
|
echo "=========================================="
|
|
|
|
# Verify Docker is accessible
|
|
if ! docker version > /dev/null 2>&1; then
|
|
echo "✗ Docker not accessible. Check Container Station."
|
|
exit 1
|
|
fi
|
|
echo "✓ Docker accessible"
|
|
|
|
# Sync scripts first
|
|
echo "📂 Syncing deployment scripts..."
|
|
cd /share/np-dms/app/source/lcbp3
|
|
|
|
# Check if directory exists
|
|
if [ ! -d ".git" ]; then
|
|
echo "✗ Git repository not found at expected path"
|
|
exit 1
|
|
fi
|
|
|
|
git fetch origin main
|
|
git reset --hard origin/main
|
|
echo "✓ Code synced"
|
|
|
|
# Ensure scripts are executable
|
|
chmod +x scripts/deploy.sh scripts/rollback.sh 2>/dev/null || true
|
|
|
|
mkdir -p /share/np-dms/app/logs
|
|
|
|
# Note: Docker build cache is preserved for faster builds
|
|
# Only prune cache manually when needed: docker builder prune -f
|
|
|
|
echo "🚀 Executing deployment..."
|
|
./scripts/deploy.sh
|
|
|
|
echo "✓ Deployment completed successfully"
|
|
SCRIPT_EOF
|
|
)
|
|
|
|
# Retry logic for SSH connection
|
|
max_attempts=3
|
|
attempt=1
|
|
|
|
while [ $attempt -le $max_attempts ]; do
|
|
echo "🚀 Deployment attempt $attempt/$max_attempts..."
|
|
|
|
if echo "$REMOTE_SCRIPT" | sshpass -p "${{ secrets.PASSWORD }}" ssh -o StrictHostKeyChecking=no \
|
|
-o ConnectTimeout=60 \
|
|
-o ServerAliveInterval=30 \
|
|
-o ServerAliveCountMax=60 \
|
|
-o TCPKeepAlive=yes \
|
|
-p ${{ secrets.PORT }} ${{ secrets.USERNAME }}@${{ secrets.HOST }} 'bash -s'; then
|
|
echo "✅ Deployment successful!"
|
|
exit 0
|
|
else
|
|
echo "⚠️ Attempt $attempt failed"
|
|
if [ $attempt -lt $max_attempts ]; then
|
|
echo "⏳ Retrying in 10 seconds..."
|
|
sleep 10
|
|
fi
|
|
fi
|
|
|
|
attempt=$((attempt + 1))
|
|
done
|
|
|
|
echo "❌ All deployment attempts failed"
|
|
exit 1
|
|
timeout-minutes: 20
|