Workshop: สร้าง CI/CD Pipeline ด้วย GitHub Actions ตั้งแต่เริ่มต้น

CI/CD (Continuous Integration / Continuous Deployment) เป็นแนวปฏิบัติสำคัญในการพัฒนาซอฟต์แวร์ที่ช่วยให้ทีมพัฒนาสามารถส่งมอบโค้ดอย่างรวดเร็ว มั่นคง และมีประสิทธิภาพ ด้วยการสร้าง GitHub Actions CI/CD Pipeline คุณสามารถอัตโนมัติขั้นตอนการทดสอบ สร้าง และปรับใช้แอปพลิเคชนของคุณได้ บทความนี้จะแนะนำวิธีสร้าง CI/CD Pipeline ตั้งแต่เริ่มต้นโดยใช้ GitHub Actions พร้อมการปรับใช้แอปพลิเคชน Node.js ไปยัง ผู้ให้บริการโฮสติ้ง Cloud VPS

CI/CD คืออะไร และเหตุใดจึงสำคัญ

Continuous Integration (CI) หมายถึงการรวมโค้ดจากหลายคนเข้าด้วยกันอย่างสม่ำเสมอ โดยทีมจะทำการ commit โค้ดไปยัง repository หลายครั้งในแต่ละวัน เมื่อมีการ commit ใหม่ ระบบจะทำการสร้าง (build) และทดสอบ (test) โค้ดโดยอัตโนมัติเพื่อตรวจหาข้อผิดพลาด

Continuous Deployment (CD) คือการปรับใช้โค้ดไปยังสภาพแวดล้อมการผลิตโดยอัตโนมัติ เมื่อการทดสอบทั้งหมดผ่านสำเร็จ ระบบจะทำการ deploy ออกไปในเซิร์ฟเวอร์จริงทันที ทำให้ผู้ใช้สามารถใช้ฟีเจอร์ใหม่ได้ดวนที่สุด

ประโยชน์ของ CI/CD:

  • ลดข้อผิดพลาด – การทดสอบอัตโนมัติช่วยจับข้อผิดพลาดได้เร็ว
  • เพิ่มความเร็ว – การปรับใช้อัตโนมัติทำให้ release ใหม่ได้เร็วขึ้น
  • ปรับปรุงคุณภาพ – การทดสอบอย่างสม่ำเสมอรักษาคุณภาพโค้ด
  • ลดค่าใช้จ่าย – อัตโนมัติลดการทำงานด้วยมือและความผิดพลาดของมนุษย์
  • ส่งมอบได้เร็ว – ฟีเจอร์ใหม่ไปถึงผู้ใช้ได้เร็วกว่า

GitHub Actions คืออะไร

GitHub Actions เป็นแพลตฟอร์มการทำ workflow automation ที่สร้างเข้ามาในตัว GitHub ช่วยให้คุณสามารถสร้าง CI/CD pipeline โดยไม่ต้องใช้บริการภายนอก GitHub Actions ทำงานโดยการสร้างไฟล์ YAML ในโฟลเดอร์ .github/workflows/ ของ repository

แนวคิดหลักของ GitHub Actions:

  • Workflow – ลำดับการทำงานโดยอัตโนมัติ บ้านใน .github/workflows/ เป็นไฟล์ YAML
  • Event – สิ่งที่ทำให้ workflow ทำงาน เช่น push, pull_request, schedule
  • Job – ชุดของขั้นตอน (steps) ที่ทำงานในเซิร์ฟเวอร์เดียวกัน
  • Step – งานแต่ละงานในการทำงาน เช่น install dependencies, run tests
  • Action – แอปพลิเคชันที่ใช้บ่อยสำหรับการทำงาน เช่น actions/checkout, actions/setup-node

Workshop: สร้าง CI/CD Pipeline ด้วย GitHub Actions

ในส่วนนี้ เราจะสร้าง CI/CD Pipeline สำหรับแอปพลิเคชน Node.js และปรับใช้ไปยัง ผู้ให้บริการโฮสติ้ง Cloud VPS ทีละขั้นตอน

ขั้นตอนที่ 1: สร้างไฟล์ Workflow

สร้างโฟลเดอร์และไฟล์ workflow ดังนี้:

mkdir -p .github/workflows
touch .github/workflows/deploy.yml

ไฟล์นี้จะเป็นหัวใจของ CI/CD Pipeline ของเรา

ขั้นตอนที่ 2: กำหนด Event Trigger

กำหนดให้ workflow ทำงานเมื่อมีการ push ไปยัง branch main หรือเมื่อมี pull request:

name: Deploy to Cloud VPS

on:
  push:
    branches:
      - main
  pull_request:
    branches:
      - main

jobs:
  deploy:
    runs-on: ubuntu-latest

on: กำหนด event ที่ทำให้ workflow ทำงาน ในที่นี้ตั้งให้ทำงานเมื่อ push ไปยัง main หรือมี pull request ไปยัง main runs-on: กำหนดระบบปฏิบัติการที่ใช้รัน job นี้

ขั้นตอนที่ 3: ติดตั้ง Dependencies และรัน Tests

เพิ่ม steps ในการ checkout โค้ด ติดตั้ง Node.js และ dependencies แล้วรันการทดสอบ:

    steps:
      - name: Checkout code
        uses: actions/checkout@v3

      - name: Setup Node.js
        uses: actions/setup-node@v3
        with:
          node-version: '18'
          cache: 'npm'

      - name: Install dependencies
        run: npm ci

      - name: Run tests
        run: npm test

      - name: Build application
        run: npm run build

ขั้นตอนนี้ใช้ GitHub Actions ที่สร้างเตรียมไว้แล้วเพื่อ checkout โค้ด setup Node.js และรันคำสั่ง npm

ขั้นตอนที่ 4: สร้าง Docker Image

ถ้าใช้ Docker สำหรับแพคเกจแอปพลิเคชน ให้เพิ่มขั้นตอนนี้:

      - name: Build Docker image
        run: |
          docker build -t myapp:${{ github.sha }} .
          docker tag myapp:${{ github.sha }} myapp:latest

${{ github.sha }} คือตัวแปรพิเศษที่ GitHub Actions มีให้ เก็บ commit hash ของ push ปัจจุบัน

      - name: Deploy to VPS
        uses: appleboy/ssh-action@master
        with:
          host: ${{ secrets.VPS_HOST }}
          username: ${{ secrets.VPS_USER }}
          key: ${{ secrets.VPS_SSH_KEY }}
          port: ${{ secrets.VPS_PORT }}
          script: |
            cd /var/www/myapp
            git pull origin main
            npm ci --production
            npm run build
            pm2 restart myapp || pm2 start npm --name myapp -- start

Action นี้ใช้ SSH เพื่อเชื่อมต่อไปยัง Cloud VPS และรันคำสั่งเพื่อ deploy แอปพลิเคชน

การจัดการ Secrets สำหรับความปลอดภัย

ข้อมูลที่ละเอียดอ่อนเช่น SSH key, server IP, และ port ต้องเก็บไว้ในการตั้งค่า Secrets ของ GitHub ไม่ใช่ในไฟล์ workflow

ในการตั้งค่า Secrets:

  • ไปยัง GitHub repository ของคุณ
  • คลิก Settings > Secrets and variables > Actions
  • คลิก “New repository secret”
  • เพิ่ม secrets ต่อไปนี้:
VPS_HOST: your-vps-ip-address
VPS_USER: your-ssh-username
VPS_PORT: 22
VPS_SSH_KEY: your-private-ssh-key-content

สร้าง SSH key pair ถ้ายังไม่มี:

ssh-keygen -t ed25519 -C "[email protected]"

# เพิ่ม public key ไปยัง ~/.ssh/authorized_keys ในเซิร์ฟเวอร์
cat ~/.ssh/id_ed25519.pub | ssh user@your-vps "cat >> ~/.ssh/authorized_keys"

Workflow File ตัวอย่างสมบูรณ์

นี่คือไฟล์ .github/workflows/deploy.yml สมบูรณ์สำหรับการ deploy Node.js ไปยัง ผู้ให้บริการโฮสติ้ง Cloud VPS:

name: Deploy to Cloud VPS

on:
  push:
    branches:
      - main
  pull_request:
    branches:
      - main

jobs:
  test-and-build:
    runs-on: ubuntu-latest
    
    steps:
      - name: Checkout code
        uses: actions/checkout@v3

      - name: Setup Node.js
        uses: actions/setup-node@v3
        with:
          node-version: '18'
          cache: 'npm'

      - name: Install dependencies
        run: npm ci

      - name: Run linting
        run: npm run lint --if-present

      - name: Run tests
        run: npm test --if-present

      - name: Build application
        run: npm run build

  deploy:
    needs: test-and-build
    runs-on: ubuntu-latest
    if: github.ref == 'refs/heads/main' && github.event_name == 'push'
    
    steps:
      - name: Checkout code
        uses: actions/checkout@v3

      - name: Deploy to VPS
        uses: appleboy/ssh-action@master
        with:
          host: ${{ secrets.VPS_HOST }}
          username: ${{ secrets.VPS_USER }}
          key: ${{ secrets.VPS_SSH_KEY }}
          port: ${{ secrets.VPS_PORT }}
          script: |
            cd /var/www/myapp
            git pull origin main
            npm ci --production
            npm run build
            pm2 restart myapp || pm2 start npm --name myapp -- start

      - name: Send Slack notification
        uses: slackapi/[email protected]
        with:
          payload: |
            {"text": "Deployment to Cloud VPS completed successfully!"}
        if: success()

      - name: Send Slack notification on failure
        uses: slackapi/[email protected]
        with:
          payload: |
            {"text": "Deployment to Cloud VPS failed!"}
        if: failure()

การแจ้งเตือน Slack สำหรับผลการ Deploy

การแจ้งเตือน Slack ช่วยให้ทีมทราบผลการ deploy ทันที ก่อนอื่นให้ตั้งค่า Slack Webhook URL:

  • ไปยัง Slack workspace ของคุณ
  • ไปที่ Apps > Create New App
  • เลือก “From scratch” และตั้งชื่อ app เป็น “GitHub Notifications”
  • ไปที่ Incoming Webhooks และเปิดใช้งาน
  • คลิก “Add New Webhook to Workspace” และเลือก channel ที่ต้องการ
  • คัดลอก Webhook URL ไปยัง GitHub Secrets เป็น SLACK_WEBHOOK_URL

จากนั้นใน workflow file ให้อัพเดท Slack notification step:

      - name: Send Slack notification
        uses: slackapi/[email protected]
        with:
          webhook-url: ${{ secrets.SLACK_WEBHOOK_URL }}
          payload: |
            {
              "text": "GitHub Action",
              "blocks": [
                {
                  "type": "section",
                  "text": {
                    "type": "mrkdwn",
                    "text": "*Deploy Status*\nRepository: ${{ github.repository }}\nBranch: ${{ github.ref }}\nStatus: ${{ job.status }}"
                  }
                }
              ]
            }
        if: always()

1. ใช้ Environment Protection

สำหรับสภาพแวดล้อม production ให้ตั้งค่า environment protection เพื่อต้องการการอนุมัติก่อน deploy:

jobs:
  deploy:
    environment:
      name: production
      url: https://your-app.de.co.th
    runs-on: ubuntu-latest

สตระหว่าง GitHub repository Settings ให้ไปที่ Environments และตั้งค่า “Required reviewers” สำหรับ production environment

2. กำหนดเวลา Manual Approval

เพิ่ม step สำหรับการอนุมัติด้วยมือก่อน deploy ไปยัง production:

  deploy:
    needs: test-and-build
    environment:
      name: production
    runs-on: ubuntu-latest
    if: github.event_name == 'push' && github.ref == 'refs/heads/main'

GitHub จะรอการอนุมัติจากผู้ตรวจสอบที่ตั้งค่าไว้โดยอัตโนมัติ

3. เก็บ Logs และทำการ Monitoring

เก็บบันทึก (logs) ของ workflow เพื่อการ troubleshooting:

      - name: Upload logs
        if: always()
        uses: actions/upload-artifact@v3
        with:
          name: workflow-logs
          path: logs/
          retention-days: 30

4. ใช้ Caching เพื่อเพิ่มความเร็ว

ใช้ cache สำหรับ node_modules เพื่อลดเวลาในการติดตั้ง dependencies:

      - name: Setup Node.js
        uses: actions/setup-node@v3
        with:
          node-version: '18'
          cache: 'npm'  # GitHub จะ cache node_modules โดยอัตโนมัติ

5. ใช้ Conditional Steps

รันบาง steps เฉพาะในเงื่อนไขบางอย่าง:

      - name: Deploy only on main branch
        if: github.ref == 'refs/heads/main'
        run: ./deploy.sh

การแก้ไขปัญหา CI/CD Pipeline

ปัญหา: GitHub Actions ไม่เริ่มทำงาน

วิธีแก้:

  • ตรวจสอบว่าไฟล์ workflow อยู่ในโฟลเดอร์ .github/workflows/ ที่ถูกต้อง
  • ตรวจสอบ YAML syntax โดยใช้เครื่องมือ YAML validator
  • ตรวจสอบ trigger event กำหนดถูกต้องหรือไม่ (push, pull_request, schedule)
  • ดูที่ Actions tab ใน GitHub repository เพื่อดูรายละเอียดข้อผิดพลาด

ปัญหา: Deploy ล้มเหลวเนื่องจาก SSH authentication error

วิธีแก้:

  • ตรวจสอบว่า SSH key ถูกสร้างและเพิ่มไปยัง ~/.ssh/authorized_keys ในเซิร์ฟเวอร์เรียบร้อยแล้ว
  • ตรวจสอบว่า private key ถูกเก็บไว้ใน GitHub Secrets ที่ชื่อ VPS_SSH_KEY
  • ลองรัน SSH connection ด้วยตนเองเพื่อยืนยันว่าทำงาน
  • ตรวจสอบ host key fingerprint โดยรัน ssh-keyscan

ปัญหา: Tests ไม่ผ่าน แต่ deploy ยังคงดำเนินการ

วิธีแก้:

  • ตรวจสอบว่า deploy job มี needs: test-and-build เพื่อให้ test ต้องผ่านก่อน
  • ใส่ if: success() ใน deploy step เพื่อให้ deploy เฉพาะเมื่อ test ผ่าน

ขั้นตอนถัดไป: ขยาย CI/CD Pipeline

เมื่อ pipeline พื้นฐานทำงานได้เรียบร้อย คุณสามารถขยายด้วยเพิ่มเติม:

  • Code Coverage Reports – ใช้ codecov หรือ codeclimate เพื่อติดตามความครอบคลุมของการทดสอบ
  • Security Scanning – ใช้ Snyk หรือ GitHub Dependabot เพื่อตรวจหาช่องโหว่ในโครงการ
  • Performance Testing – เพิ่ม load testing เพื่อตรวจสอบประสิทธิภาพ
  • Blue-Green Deployment – ปรับใช้ไปยังสภาพแวดล้อมสำรองและสลับเมื่อ ready
  • Database Migrations – รันการอัปเดตฐานข้อมูลก่อน deploy แอปพลิเคชน

บทสรุป

GitHub Actions CI/CD Pipeline เป็นเครื่องมือที่มีประสิทธิภาพสำหรับอัตโนมัติกระบวนการพัฒนาและปรับใช้ แอปพลิเคชน ด้วยการสร้าง workflow ที่ดีคุณสามารถตรวจสอบคุณภาพของโค้ด ทำการทดสอบอัตโนมัติ และปรับใช้ไปยัง ผู้ให้บริการโฮสติ้ง Cloud VPS ด้วยความมั่นใจ

ในการเริ่มต้นให้เลือกจากขั้นตอนพื้นฐานที่อธิบายไว้ในบทความนี้ แล้วค่อยขยาย pipeline ของคุณด้วยฟีเจอร์เพิ่มเติมเมื่อทีมเติบโตและความต้องการเปลี่ยนแปลง