CI/CD Pipeline ด้วย GitHub Actions แบบละเอียด

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

บทความนี้จะพาคุณเจาะลึก GitHub Actions อย่างละเอียด ตั้งแต่พื้นฐานของ CI/CD, การทำความเข้าใจส่วนประกอบของ GitHub Actions, การสร้าง Pipeline สำหรับโปรเจกต์จริง, ไปจนถึงเทคนิคขั้นสูงและการดูแลรักษา เพื่อให้คุณสามารถนำไปประยุกต์ใช้กับโปรเจกต์ของคุณได้อย่างมั่นใจครับ ไม่ว่าคุณจะเป็นนักพัฒนา, DevOps Engineer หรือผู้ที่สนใจในกระบวนการพัฒนาซอฟต์แวร์ บทความนี้คือคู่มือฉบับสมบูรณ์สำหรับคุณครับ

สารบัญ

ทำความเข้าใจพื้นฐาน CI/CD

ก่อนที่เราจะดำดิ่งสู่โลกของ GitHub Actions เรามาทำความเข้าใจแนวคิดหลักของ CI/CD กันก่อนนะครับ เพราะนี่คือรากฐานสำคัญที่จะทำให้เราเห็นภาพรวมและคุณค่าของสิ่งที่เรากำลังจะสร้างขึ้นมาครับ

Continuous Integration (CI) คืออะไร?

Continuous Integration (CI) คือหลักปฏิบัติในการพัฒนาซอฟต์แวร์ที่ทีมพัฒนาจะรวมโค้ดที่เขียนขึ้นเข้ากับ Repository หลัก (main/master branch) บ่อยครั้งที่สุดเท่าที่จะทำได้ โดยปกติแล้วคือวันละหลายๆ ครั้งครับ เมื่อโค้ดถูกรวมเข้าไป ระบบ CI จะทำการ สร้าง (build) และ ทดสอบ (test) โค้ดนั้นโดยอัตโนมัติ เพื่อตรวจหาข้อผิดพลาดหรือความขัดแย้งที่อาจเกิดขึ้นได้ตั้งแต่เนิ่นๆ ครับ

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

  • ตรวจพบข้อผิดพลาดได้เร็ว: การรวมโค้ดบ่อยๆ ทำให้ปัญหาถูกค้นพบได้เร็วกว่าการรวมโค้ดครั้งใหญ่ในภายหลัง
  • ลดความขัดแย้งของโค้ด: การรวมโค้ดเล็กๆ น้อยๆ บ่อยๆ ช่วยลดโอกาสและความซับซ้อนในการแก้ไขความขัดแย้ง (merge conflicts)
  • มั่นใจในคุณภาพโค้ด: ทุกครั้งที่มีการรวมโค้ด ระบบจะรันการทดสอบอัตโนมัติ (Unit Tests, Integration Tests) ทำให้มั่นใจว่าโค้ดที่รวมเข้าไปยังคงทำงานได้อย่างถูกต้อง
  • ทีมทำงานร่วมกันได้ดีขึ้น: สมาชิกในทีมเห็นการเปลี่ยนแปลงของโค้ดได้รวดเร็ว และได้รับ Feedback ทันที

Continuous Delivery (CD) และ Continuous Deployment คืออะไร?

หลังจากขั้นตอน CI ที่มั่นใจว่าโค้ดทำงานได้ถูกต้องแล้ว ขั้นตอนต่อไปคือการส่งมอบซอฟต์แวร์ ซึ่งแบ่งออกเป็นสองระดับย่อยคือ Continuous Delivery และ Continuous Deployment ครับ

Continuous Delivery (CD):

Continuous Delivery คือการขยายขีดความสามารถของ CI ไปอีกขั้นครับ โดยหลังจากที่โค้ดผ่านการ Build และ Test ในขั้นตอน CI แล้ว ระบบจะเตรียมโค้ดให้พร้อมสำหรับการ Deploy ไปยัง Production Environment ได้ตลอดเวลา แต่การ Deploy จริงๆ จะยังคงต้องอาศัยการตัดสินใจของมนุษย์ เช่น การกดปุ่มเพื่อ Deploy ครับ นั่นหมายความว่าทีมสามารถส่งมอบซอฟต์แวร์เวอร์ชันใหม่ได้ทุกเมื่อที่ต้องการ โดยที่กระบวนการทั้งหมดตั้งแต่ต้นจนจบถูกทำให้เป็นอัตโนมัติเกือบทั้งหมดแล้ว

Continuous Deployment (CD):

Continuous Deployment คือระดับสูงสุดของการส่งมอบซอฟต์แวร์ครับ โดยขยายจาก Continuous Delivery ด้วยการทำให้ การ Deploy ไปยัง Production Environment เป็นไปโดยอัตโนมัติทั้งหมด หากโค้ดผ่านการทดสอบทั้งหมดในขั้นตอน CI และ CD (Delivery) แล้ว โค้ดนั้นจะถูก Deploy ขึ้นสู่ Production โดยอัตโนมัติทันทีโดยไม่ต้องมีการแทรกแซงจากมนุษย์เลยครับ วิธีนี้ช่วยให้ลูกค้าได้รับฟีเจอร์ใหม่ๆ และการแก้ไขข้อผิดพลาดได้รวดเร็วที่สุด

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

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

ทำไมต้อง CI/CD? ประโยชน์ที่คุณจะได้รับ

การนำ CI/CD มาใช้ในกระบวนการพัฒนาซอฟต์แวร์นั้นมีประโยชน์มหาศาลครับ ไม่ใช่แค่การทำให้งานเสร็จเร็วขึ้นเท่านั้น แต่ยังช่วยยกระดับคุณภาพของผลิตภัณฑ์และประสิทธิภาพของทีมโดยรวมอีกด้วยครับ

  • เพิ่มความเร็วในการส่งมอบ (Speed to Market): ช่วยให้คุณนำฟีเจอร์ใหม่ๆ หรือการแก้ไขข้อผิดพลาดไปสู่ผู้ใช้ได้เร็วกว่าคู่แข่ง ซึ่งเป็นสิ่งสำคัญในตลาดที่มีการแข่งขันสูง
  • ลดความผิดพลาดและข้อบกพร่อง: การทดสอบอัตโนมัติและกระบวนการที่สม่ำเสมอช่วยลดข้อผิดพลาดที่อาจเล็ดลอดไปถึง Production ได้อย่างมากครับ
  • ปรับปรุงคุณภาพซอฟต์แวร์: ด้วยการ Feedback ที่รวดเร็วและต่อเนื่อง ทีมสามารถแก้ไขปัญหาและปรับปรุงคุณภาพโค้ดได้ตลอดเวลา
  • ลดต้นทุนการดำเนินงาน: การทำงานอัตโนมัติช่วยลดเวลาและแรงงานที่ต้องใช้ในงานซ้ำๆ ทำให้ทีมสามารถโฟกัสกับงานที่สร้างมูลค่าได้มากขึ้น
  • สร้างความน่าเชื่อถือและความมั่นใจ: ทีมมีความมั่นใจมากขึ้นในการส่งมอบซอฟต์แวร์ เนื่องจากรู้ว่าทุกการเปลี่ยนแปลงได้ผ่านการทดสอบมาอย่างดีแล้ว
  • เพิ่มความโปร่งใส: ทุกคนในทีมสามารถเห็นสถานะของ Pipeline ได้ ทำให้ทราบว่าโค้ดเวอร์ชันล่าสุดอยู่ในขั้นตอนใดและมีปัญหาอะไรเกิดขึ้นบ้าง

เจาะลึก GitHub Actions: หัวใจของการทำงานอัตโนมัติ

เมื่อเราเข้าใจหลักการของ CI/CD แล้ว ก็ถึงเวลามาทำความรู้จักกับเครื่องมือที่จะช่วยให้หลักการเหล่านี้เป็นจริงได้บน GitHub นั่นคือ GitHub Actions ครับ

GitHub Actions คืออะไร?

GitHub Actions คือแพลตฟอร์มสำหรับ Workflow Automation ที่ถูกผสานรวมเข้ากับ GitHub โดยตรงครับ มันช่วยให้คุณสามารถสร้างกระบวนการอัตโนมัติต่างๆ ได้ภายใน Repository ของคุณเอง ไม่ว่าจะเป็นการสร้าง (Build), ทดสอบ (Test), Deploy ซอฟต์แวร์ หรือแม้แต่การจัดการโปรเจกต์อื่นๆ ที่เกี่ยวข้องกับโค้ดของคุณครับ

หัวใจสำคัญของ GitHub Actions คือการกำหนด Workflows ที่จะทำงานโดยอัตโนมัติเมื่อเกิด Events ที่คุณกำหนดไว้ เช่น เมื่อมีการ Push โค้ด, สร้าง Pull Request, หรือแม้กระทั่งกำหนดเวลาให้ทำงานครับ

ส่วนประกอบสำคัญของ GitHub Actions

การทำความเข้าใจส่วนประกอบหลักของ GitHub Actions จะช่วยให้คุณออกแบบและสร้าง Workflow ได้อย่างมีประสิทธิภาพครับ

  • Workflow:

    คือกระบวนการอัตโนมัติที่คุณกำหนดขึ้นมาครับ Workflow ถูกเขียนด้วยภาษา YAML และจัดเก็บไว้ในไดเรกทอรี .github/workflows/ ภายใน Repository ของคุณครับ Workflow หนึ่งๆ สามารถประกอบด้วยหนึ่งหรือหลาย Job ครับ

    # .github/workflows/ci.yml
    name: CI Pipeline
    
    on: [push, pull_request] # กำหนด Event ที่จะเรียก Workflow นี้
    
    jobs:
      build_and_test: # หนึ่ง Job
        runs-on: ubuntu-latest
        steps:
          - uses: actions/checkout@v4
          - name: Install dependencies
            run: npm ci
          - name: Run tests
            run: npm test
    
  • Event:

    คือเหตุการณ์ที่เกิดขึ้นใน Repository ของคุณ ซึ่งจะ trigger ให้ Workflow ทำงานครับ ตัวอย่าง Event เช่น:

    • push: เมื่อมีการ Push โค้ดไปยัง Branch ที่กำหนด
    • pull_request: เมื่อมีการสร้างหรืออัปเดต Pull Request
    • schedule: กำหนดเวลาให้ Workflow ทำงานเป็นประจำ (เช่น ทุกวันตอนเที่ยงคืน)
    • workflow_dispatch: อนุญาตให้รัน Workflow ด้วยตนเองผ่าน GitHub UI หรือ GitHub API
    • release: เมื่อมีการสร้าง Release ใหม่
    on:
      push:
        branches:
          - main
      pull_request:
        branches:
          - main
      schedule:
        - cron: '0 0 * * *' # รันทุกวันตอนเที่ยงคืน UTC
      workflow_dispatch: # อนุญาตให้รันด้วยตนเอง
    
  • Job:

    คือชุดของ Step ที่จะถูก execute บน Runner ตัวเดียวกันครับ Workflow หนึ่งๆ สามารถมีได้หลาย Job และ Job เหล่านี้สามารถทำงานพร้อมกัน (parallel) หรือเรียงลำดับกัน (sequential) ก็ได้ โดยคุณสามารถกำหนด dependencies ระหว่าง Job ได้ด้วยคีย์เวิร์ด needs ครับ

    jobs:
      build:
        runs-on: ubuntu-latest
        steps:
          - name: Build project
            run: npm run build
    
      deploy:
        runs-on: ubuntu-latest
        needs: build # Job 'deploy' จะทำงานหลังจาก Job 'build' เสร็จสิ้นและสำเร็จ
        steps:
          - name: Deploy to server
            run: echo "Deploying..."
    
  • Runner:

    คือเซิร์ฟเวอร์ที่ GitHub Actions ใช้ในการรัน Job ของคุณครับ GitHub มี Runner ให้เลือกใช้หลายประเภท (เช่น ubuntu-latest, windows-latest, macos-latest) หรือคุณจะใช้ Self-Hosted Runner ของคุณเองก็ได้ครับ

  • Step:

    คือคำสั่งหรือ Action ที่จะถูกรันภายใน Job ครับ แต่ละ Step จะทำหน้าที่เฉพาะอย่าง เช่น การ checkout โค้ด, ติดตั้ง dependency, รัน script, หรือเรียกใช้ Action ที่มีอยู่แล้วครับ

    steps:
      - uses: actions/checkout@v4 # Step ที่ใช้ Action เพื่อ checkout โค้ด
      - name: Run a one-line script # Step ที่รันคำสั่ง bash
        run: echo Hello, world!
      - name: Run a multi-line script
        run: |
          echo Add other actions to build,
          echo test, and deploy your project.
    
  • Action:

    คือแอปพลิเคชันที่สามารถนำกลับมาใช้ใหม่ได้ ซึ่งทำหน้าที่เฉพาะอย่างครับ Action สามารถเป็น JavaScript, Docker Container หรือ Composite Action ที่รวมหลาย Step เข้าไว้ด้วยกันก็ได้ครับ มี Action มากมายให้เลือกใช้ใน GitHub Marketplace หรือคุณจะสร้าง Action ของตัวเองก็ได้ครับ ตัวอย่าง Action ที่พบบ่อยเช่น actions/checkout@v4, actions/setup-node@v4 ครับ

ทำไมต้องเลือก GitHub Actions?

GitHub Actions มีข้อดีหลายประการที่ทำให้มันเป็นตัวเลือกที่น่าสนใจสำหรับการทำ CI/CD ครับ

  • ผสานรวมกับ GitHub ได้อย่างราบรื่น: เนื่องจากเป็นส่วนหนึ่งของ GitHub โดยตรง ทำให้การตั้งค่าและการจัดการ Workflow ง่ายดายและเข้าถึงได้จาก Repository ของคุณเลยครับ
  • มี Actions ให้เลือกใช้มากมาย: GitHub Marketplace มี Actions นับพันให้เลือกใช้สำหรับงานหลากหลายประเภท ไม่ว่าจะเป็นการ Build, Test, Deploy ไปยัง Cloud Providers ต่างๆ ทำให้คุณไม่ต้องเขียนทุกอย่างตั้งแต่เริ่มต้นครับ
  • ปรับแต่งได้สูง: ด้วยภาษา YAML ที่ยืดหยุ่น คุณสามารถสร้าง Workflow ที่ซับซ้อนและปรับแต่งให้เข้ากับความต้องการเฉพาะของโปรเจกต์คุณได้อย่างเต็มที่ครับ
  • ฟรีสำหรับ Public Repository: GitHub Actions ให้บริการฟรีสำหรับ Public Repository และมีโควต้าฟรีจำนวนหนึ่งสำหรับ Private Repository ซึ่งเป็นจุดเริ่มต้นที่ดีสำหรับโปรเจกต์ขนาดเล็กถึงกลางครับ
  • Infrastructure as Code (IaC): Workflow ของคุณถูกจัดเก็บเป็นโค้ดใน Repository ทำให้สามารถติดตามการเปลี่ยนแปลง, ทำเวอร์ชันคอนโทรล, และทบทวนโค้ดได้เหมือนกับโค้ดโปรเจกต์หลักของคุณครับ
  • รองรับหลากหลายภาษาและแพลตฟอร์ม: ไม่ว่าโปรเจกต์ของคุณจะใช้ Node.js, Python, Java, .NET, Go, Ruby หรือ Docker, Kubernetes, GitHub Actions ก็สามารถรองรับได้แทบทั้งหมดครับ

การออกแบบ CI/CD Pipeline ด้วย GitHub Actions สำหรับโปรเจกต์จริง

การสร้าง CI/CD Pipeline ด้วย GitHub Actions ไม่ได้ซับซ้อนอย่างที่คิดครับ แต่การออกแบบที่ดีจะช่วยให้ Pipeline ของคุณมีประสิทธิภาพ, บำรุงรักษาง่าย และปลอดภัยครับ

การวางแผนและพิจารณาก่อนสร้าง Pipeline

ก่อนที่จะเริ่มเขียน Workflow YAML มีหลายสิ่งที่ต้องพิจารณาครับ

  • ประเภทของโปรเจกต์:
    • Web Application (Frontend/Backend): มักจะเกี่ยวข้องกับการ Build โค้ด, รัน Unit/Integration Tests, Linting, การสร้าง Docker Image และการ Deploy ไปยัง Web Server หรือ Container Orchestration System (เช่น Kubernetes, ECS)
    • Mobile Application: อาจเกี่ยวข้องกับการ Build APK/IPA, การรัน UI Tests, และการ Deploy ไปยัง App Store หรือ TestFlight
    • Library/Package: เน้นการ Build, Test, และ Publish ไปยัง Package Registry (เช่น npm, PyPI, Maven Central)
  • เทคโนโลยีที่ใช้:

    ภาษาโปรแกรม (Node.js, Python, Java), Framework (React, Angular, Spring Boot, Django), Database (PostgreSQL, MongoDB), Containerization (Docker), Orchestration (Kubernetes)

  • สภาพแวดล้อม (Environments):

    คุณมีกี่สภาพแวดล้อม? (Development, Staging, Production) การ Deploy ไปยังแต่ละ Environment อาจมีเงื่อนไขและขั้นตอนที่แตกต่างกันครับ

  • กลยุทธ์การ Deploy:

    คุณต้องการ Deploy แบบไหน? (Rolling Update, Blue/Green Deployment, Canary Release) ซึ่งอาจส่งผลต่อความซับซ้อนของ Pipeline ในส่วน CD ครับ

  • ความปลอดภัย:

    คุณจะจัดการกับข้อมูลสำคัญ (API Keys, Credentials) อย่างไร? GitHub Actions มี Secrets สำหรับเรื่องนี้ครับ

โครงสร้างไฟล์ Workflow YAML

ไฟล์ Workflow จะอยู่ในไดเรกทอรี .github/workflows/ ครับ ชื่อไฟล์เป็นอะไรก็ได้ เช่น ci.yml, deploy.yml หรือ main.yml ครับ

# .github/workflows/your-workflow-name.yml
name: Your Workflow Name # ชื่อ Workflow ที่จะแสดงใน GitHub UI

on: # กำหนด Event ที่จะ Trigger Workflow
  push:
    branches:
      - main
      - develop
  pull_request:
    branches:
      - main
      - develop
  workflow_dispatch: # อนุญาตให้รันด้วยตนเอง

jobs: # กำหนด Job ต่างๆ ที่จะรัน
  job-name-1:
    runs-on: ubuntu-latest # Runner ที่จะใช้
    steps: # ขั้นตอนต่างๆ ใน Job นี้
      - uses: actions/checkout@v4 # Action สำหรับ checkout โค้ด
      - name: Your Step 1
        run: echo "Hello from Job 1, Step 1"
      - name: Your Step 2
        run: echo "Hello from Job 1, Step 2"

  job-name-2:
    runs-on: ubuntu-latest
    needs: job-name-1 # Job นี้จะรันหลังจาก job-name-1 สำเร็จ
    steps:
      - name: Your Step 3
        run: echo "Hello from Job 2, Step 3"

ตัวอย่างที่ 1: CI/CD สำหรับ Web Application (Node.js + React + Docker)

ตัวอย่างนี้จะแสดง Pipeline สำหรับโปรเจกต์ Web Application ที่ใช้ Node.js (สำหรับ Backend) และ React (สำหรับ Frontend) โดยใช้ Docker ในการสร้าง Image และ Push ไปยัง GitHub Container Registry (GHCR) ครับ

สมมติว่าโครงสร้างโปรเจกต์ของเราเป็นดังนี้ครับ:

.
├── .github/
│   └── workflows/
│       └── main-ci-cd.yml
├── client/ # React frontend
│   ├── package.json
│   ├── Dockerfile (สำหรับ frontend)
│   └── ...
├── server/ # Node.js backend (Express)
│   ├── package.json
│   ├── Dockerfile (สำหรับ backend)
│   └── ...
├── docker-compose.yml
└── README.md

เราจะสร้าง Workflow เดียวเพื่อจัดการทั้ง CI และ CD ครับ

ขั้นตอน CI: Build, Test, Lint, Docker Image Build

ในส่วน CI เราจะทำการ Linting, Testing และ Building ทั้ง Frontend และ Backend รวมถึงการสร้าง Docker Image สำหรับแต่ละส่วนครับ

# .github/workflows/main-ci-cd.yml
name: Fullstack CI/CD Pipeline

on:
  push:
    branches:
      - main
  pull_request:
    branches:
      - main
  workflow_dispatch: # อนุญาตให้รันด้วยตนเอง

env:
  NODE_VERSION: '18' # กำหนดเวอร์ชัน Node.js
  # กำหนดชื่อ Image และ Tag สำหรับ GHCR
  FRONTEND_IMAGE_NAME: 'fullstack-app-frontend'
  BACKEND_IMAGE_NAME: 'fullstack-app-backend'
  DOCKER_REGISTRY: ghcr.io/${{ github.repository_owner }}

jobs:
  # --- CI Jobs ---

  lint-test-frontend:
    name: Lint & Test Frontend
    runs-on: ubuntu-latest
    steps:
      - name: Checkout Code
        uses: actions/checkout@v4

      - name: Setup Node.js
        uses: actions/setup-node@v4
        with:
          node-version: ${{ env.NODE_VERSION }}
          cache: 'npm'
          cache-dependency-path: client/package-lock.json

      - name: Install Frontend Dependencies
        working-directory: ./client
        run: npm ci

      - name: Run Frontend Lint
        working-directory: ./client
        run: npm run lint

      - name: Run Frontend Tests
        working-directory: ./client
        run: npm test -- --coverage # รันพร้อมรายงาน Coverage

      - name: Archive Test Reports
        uses: actions/upload-artifact@v4
        if: always() # อัปโหลดเสมอแม้ Test ไม่ผ่าน
        with:
          name: frontend-test-reports
          path: ./client/coverage

  lint-test-backend:
    name: Lint & Test Backend
    runs-on: ubuntu-latest
    steps:
      - name: Checkout Code
        uses: actions/checkout@v4

      - name: Setup Node.js
        uses: actions/setup-node@v4
        with:
          node-version: ${{ env.NODE_VERSION }}
          cache: 'npm'
          cache-dependency-path: server/package-lock.json

      - name: Install Backend Dependencies
        working-directory: ./server
        run: npm ci

      - name: Run Backend Lint
        working-directory: ./server
        run: npm run lint

      - name: Run Backend Tests
        working-directory: ./server
        run: npm test -- --coverage # รันพร้อมรายงาน Coverage

      - name: Archive Test Reports
        uses: actions/upload-artifact@v4
        if: always()
        with:
          name: backend-test-reports
          path: ./server/coverage

  build-docker-images:
    name: Build & Tag Docker Images
    runs-on: ubuntu-latest
    needs: [lint-test-frontend, lint-test-backend] # รันหลังจาก CI Jobs อื่นๆ สำเร็จ
    steps:
      - name: Checkout Code
        uses: actions/checkout@v4

      - name: Set up Docker Buildx
        uses: docker/setup-buildx-action@v3

      - name: Login to GHCR
        uses: docker/login-action@v3
        with:
          registry: ${{ env.DOCKER_REGISTRY }}
          username: ${{ github.actor }}
          password: ${{ secrets.GITHUB_TOKEN }} # ใช้ GITHUB_TOKEN ที่ GitHub สร้างให้

      - name: Build and push Frontend Docker image
        uses: docker/build-push-action@v5
        with:
          context: ./client
          file: ./client/Dockerfile
          push: false # ตอนนี้ยังไม่ push แค่ build
          tags: ${{ env.DOCKER_REGISTRY }}/${{ env.FRONTEND_IMAGE_NAME }}:latest,${{ env.DOCKER_REGISTRY }}/${{ env.FRONTEND_IMAGE_NAME }}:${{ github.sha }}
          cache-from: type=gha
          cache-to: type=gha,mode=max

      - name: Build and push Backend Docker image
        uses: docker/build-push-action@v5
        with:
          context: ./server
          file: ./server/Dockerfile
          push: false # ตอนนี้ยังไม่ push แค่ build
          tags: ${{ env.DOCKER_REGISTRY }}/${{ env.BACKEND_IMAGE_NAME }}:latest,${{ env.DOCKER_REGISTRY }}/${{ env.BACKEND_IMAGE_NAME }}:${{ github.sha }}
          cache-from: type=gha
          cache-to: type=gha,mode=max

      - name: Save Docker Images as Artifacts (Optional, for debugging/manual checks)
        run: |
          docker save ${{ env.DOCKER_REGISTRY }}/${{ env.FRONTEND_IMAGE_NAME }}:latest -o frontend.tar
          docker save ${{ env.DOCKER_REGISTRY }}/${{ env.BACKEND_IMAGE_NAME }}:latest -o backend.tar
        if: always()

      - name: Upload Docker Images Artifacts
        uses: actions/upload-artifact@v4
        if: always()
        with:
          name: docker-images
          path: |
            frontend.tar
            backend.tar

คำอธิบาย Workflow CI:

  • name: ชื่อ Workflow
  • on: กำหนดให้ Workflow ทำงานเมื่อมีการ Push ไปยัง main หรือมีการสร้าง/อัปเดต Pull Request ไปยัง main หรือเมื่อสั่งรันด้วยตนเอง
  • env: กำหนดตัวแปรสภาพแวดล้อมที่ใช้ได้ทั่ว Workflow
  • jobs:
    • lint-test-frontend และ lint-test-backend: สอง Job นี้จะทำงานพร้อมกัน (parallel) เพื่อทำการ Lint และ Test โค้ด Frontend และ Backend ตามลำดับ
    • ในแต่ละ Job จะมีการใช้ actions/checkout@v4 เพื่อดึงโค้ด, actions/setup-node@v4 เพื่อตั้งค่า Node.js และจัดการ cache ของ npm dependencies เพื่อความเร็ว
    • npm run lint และ npm test ถูกรันในไดเรกทอรีที่ถูกต้องโดยใช้ working-directory
    • actions/upload-artifact@v4 ใช้สำหรับอัปโหลดรายงานการทดสอบ (coverage reports) เป็น Artifact เพื่อให้สามารถดาวน์โหลดไปตรวจสอบได้ในภายหลัง
    • build-docker-images: Job นี้จะรันหลังจาก lint-test-frontend และ lint-test-backend สำเร็จเท่านั้น
    • มีการใช้ docker/setup-buildx-action@v3 เพื่อตั้งค่า Docker Buildx ซึ่งช่วยให้ Build Docker Image ได้อย่างมีประสิทธิภาพ
    • docker/login-action@v3 ใช้ในการ Login ไปยัง GitHub Container Registry (GHCR) โดยใช้ GITHUB_TOKEN ซึ่งเป็น Secret ที่ GitHub สร้างให้โดยอัตโนมัติ
    • docker/build-push-action@v5 ใช้ในการ Build Docker Image สำหรับทั้ง Frontend และ Backend โดยมีการ Tag Image ด้วย latest และ ${{ github.sha }} (Commit SHA) เพื่อระบุเวอร์ชัน
    • push: false ในขั้นตอนนี้หมายความว่าเราแค่ Build Image แต่ยังไม่ Push ไปยัง Registry ทันที (จะทำในขั้นตอน CD)
    • มีการใช้ cache-from และ cache-to เพื่อใช้ GitHub Actions Cache ในการเร่งความเร็วการ Build Docker Image
    • มีการบันทึก Docker Image เป็นไฟล์ .tar และอัปโหลดเป็น Artifact เพื่อให้สามารถดาวน์โหลดไปตรวจสอบหรือใช้งานแบบ Manual ได้ครับ

สำหรับข้อมูลเพิ่มเติมเกี่ยวกับ GitHub Container Registry คุณสามารถ อ่านเพิ่มเติม ได้ครับ

ขั้นตอน CD: Push Docker Image ไปยัง GitHub Container Registry (GHCR)

หลังจากที่ Docker Image ถูก Build และผ่านการตรวจสอบในขั้นตอน CI แล้ว เราจะทำการ Push Image เหล่านั้นไปยัง GHCR ครับ

# .github/workflows/main-ci-cd.yml (ต่อจากด้านบน)
  push-docker-images-to-ghcr:
    name: Push Docker Images to GHCR
    runs-on: ubuntu-latest
    needs: build-docker-images # รันหลังจาก build-docker-images สำเร็จ
    if: github.ref == 'refs/heads/main' && github.event_name == 'push' # เฉพาะเมื่อมีการ push ไปที่ main branch เท่านั้น
    steps:
      - name: Checkout Code
        uses: actions/checkout@v4

      - name: Set up Docker Buildx
        uses: docker/setup-buildx-action@v3

      - name: Login to GHCR
        uses: docker/login-action@v3
        with:
          registry: ${{ env.DOCKER_REGISTRY }}
          username: ${{ github.actor }}
          password: ${{ secrets.GITHUB_TOKEN }}

      - name: Get Docker Images from Artifacts
        uses: actions/download-artifact@v4
        with:
          name: docker-images
          path: . # ดาวน์โหลดไปยัง root directory

      - name: Load Frontend Docker Image
        run: docker load --input frontend.tar

      - name: Load Backend Docker Image
        run: docker load --input backend.tar

      - name: Push Frontend Docker image to GHCR
        run: |
          docker push ${{ env.DOCKER_REGISTRY }}/${{ env.FRONTEND_IMAGE_NAME }}:latest
          docker push ${{ env.DOCKER_REGISTRY }}/${{ env.FRONTEND_IMAGE_NAME }}:${{ github.sha }}

      - name: Push Backend Docker image to GHCR
        run: |
          docker push ${{ env.DOCKER_REGISTRY }}/${{ env.BACKEND_IMAGE_NAME }}:latest
          docker push ${{ env.DOCKER_REGISTRY }}/${{ env.BACKEND_IMAGE_NAME }}:${{ github.sha }}

คำอธิบาย Workflow CD:

  • push-docker-images-to-ghcr: Job นี้จะรันหลังจาก build-docker-images สำเร็จ
  • if: github.ref == 'refs/heads/main' && github.event_name == 'push': นี่คือเงื่อนไขสำคัญที่ทำให้ Job นี้รันเฉพาะเมื่อมีการ Push โค้ดไปยัง main branch เท่านั้น ซึ่งเป็นหลักการของ Continuous Delivery ที่จะ Push Image ที่พร้อมใช้ไปยัง Registry เมื่อโค้ดใน main ถูกอัปเดต
  • มีการ Login ไปยัง GHCR อีกครั้ง
  • actions/download-artifact@v4 ใช้เพื่อดาวน์โหลด Docker Images ที่ถูก Build ไว้ใน Job ก่อนหน้า (ซึ่งถูกอัปโหลดเป็น Artifact)
  • ใช้ docker load เพื่อโหลด Image จากไฟล์ .tar กลับเข้ามาใน Docker Daemon
  • จากนั้นใช้ docker push เพื่อ Push Image ทั้ง Frontend และ Backend ไปยัง GHCR

การ Deploy ไปยัง Server (แนวคิดและการประยุกต์ใช้)

การ Deploy จริงๆ ไปยัง Server หรือ Cloud Provider นั้นมีความซับซ้อนและหลากหลายขึ้นอยู่กับ Infrastructure ของคุณครับ แต่หลักการคือคุณจะสร้าง Job อีกตัวที่รันหลังจาก push-docker-images-to-ghcr สำเร็จครับ

ตัวอย่างแนวคิดสำหรับการ Deploy (ไม่ได้ใส่โค้ดเต็มเพื่อความกระชับ แต่ให้แนวคิดครับ):

# .github/workflows/main-ci-cd.yml (ต่อจากด้านบน)
  deploy-to-staging:
    name: Deploy to Staging Environment
    runs-on: ubuntu-latest
    needs: push-docker-images-to-ghcr
    environment:
      name: Staging # ใช้ GitHub Environments
    if: github.ref == 'refs/heads/main' && github.event_name == 'push' # Deploy เมื่อ push ไป main
    steps:
      - name: Deploy using SSH
        uses: appleboy/[email protected]
        with:
          host: ${{ secrets.STAGING_SSH_HOST }}
          username: ${{ secrets.STAGING_SSH_USERNAME }}
          key: ${{ secrets.STAGING_SSH_KEY }}
          script: |
            # คำสั่ง SSH เพื่อดึง Docker Image ล่าสุดจาก GHCR และรันบนเซิร์ฟเวอร์
            docker pull ${{ env.DOCKER_REGISTRY }}/${{ env.FRONTEND_IMAGE_NAME }}:latest
            docker pull ${{ env.DOCKER_REGISTRY }}/${{ env.BACKEND_IMAGE_NAME }}:latest
            # สั่งรัน Docker Compose หรือ Kubernetes manifest
            # เช่น docker-compose pull && docker-compose up -d
            # หรือ kubectl apply -f kubernetes-manifests/
            echo "Deployment to Staging complete!"

  deploy-to-production:
    name: Deploy to Production Environment
    runs-on: ubuntu-latest
    needs: deploy-to-staging # รันหลังจาก Staging สำเร็จ
    environment:
      name: Production # ใช้ GitHub Environments
    if: github.ref == 'refs/heads/main' && github.event_name == 'push' && github.event.before == '0000000000000000000000000000000000000000' # ตัวอย่างเงื่อนไขสำหรับ Manual deployment to Production
    # หรืออาจใช้ workflow_dispatch เพื่อให้ Deploy Production แบบ Manual
    steps:
      - name: Deploy to Production
        # ขั้นตอนการ Deploy ที่คล้ายกับ Staging แต่อาจมีขั้นตอนการอนุมัติเพิ่มเติม
        # เช่น ใช้ AWS ECS, Kubernetes, Azure Web Apps
        run: echo "Manual approval required for Production deployment."

แนวคิดการ Deploy:

  • การใช้ SSH: สำหรับเซิร์ฟเวอร์ทั่วไป คุณสามารถใช้ Action เช่น appleboy/ssh-action เพื่อ SSH เข้าไปในเซิร์ฟเวอร์และรันคำสั่ง Docker pull/run หรือ Docker Compose ได้โดยตรง
  • Cloud Provider Specific Actions: หากคุณใช้บริการ Cloud เช่น AWS ECS/EKS, Google Kubernetes Engine (GKE), Azure Kubernetes Service (AKS) หรือ Azure Web Apps จะมี Actions เฉพาะสำหรับบริการเหล่านั้น เช่น aws-actions/amazon-ecs-deploy-task@v1, google-github-actions/deploy-cloudrun@v1 ซึ่งจะทำให้การ Deploy ง่ายขึ้นมากครับ
  • GitHub Environments: ใช้เพื่อจัดการกับสภาพแวดล้อมต่างๆ เช่น Staging, Production ซึ่งคุณสามารถกำหนดกฎการป้องกัน (protection rules) เช่น การต้องมีการอนุมัติจากผู้ดูแลก่อนการ Deploy ไปยัง Production ได้ครับ

ตัวอย่างที่ 2: CI/CD สำหรับ Python Library (Test และ Publish ไปยัง PyPI)

ตัวอย่างนี้จะแสดง Pipeline สำหรับ Python Library ที่จะทำการ Lint, Test และ Build Package จากนั้น Publish ไปยัง PyPI (Python Package Index) เมื่อมีการ Push Tag ใหม่ครับ

สมมติว่าโครงสร้างโปรเจกต์ของเราเป็นดังนี้:

.
├── .github/
│   └── workflows/
│       └── python-publish.yml
├── my_python_lib/ # โค้ดไลบรารี
│   ├── __init__.py
│   └── main.py
├── tests/
│   └── test_main.py
├── pyproject.toml # สำหรับ Build และ Metadata
├── README.md
└── LICENSE

ขั้นตอน CI: Lint, Test, Build Python Package

# .github/workflows/python-publish.yml
name: Python Package CI/CD

on:
  push:
    branches: [ main ]
    tags: # Trigger เมื่อมีการ push tag (สำหรับ CD)
      - 'v*' # เช่น v1.0.0, v1.0.1
  pull_request:
    branches: [ main ]
  workflow_dispatch:

env:
  PYTHON_VERSION: '3.9' # กำหนดเวอร์ชัน Python

jobs:
  build_and_test:
    name: Build and Test Python Package
    runs-on: ubuntu-latest
    steps:
      - name: Checkout Code
        uses: actions/checkout@v4

      - name: Set up Python
        uses: actions/setup-python@v5
        with:
          python-version: ${{ env.PYTHON_VERSION }}

      - name: Install dependencies
        run: |
          python -m pip install --upgrade pip
          pip install poetry # หรือ setuptools, wheel
          poetry install --no-root # ติดตั้ง dependencies ที่ระบุใน pyproject.toml

      - name: Run Linting (Flake8)
        run: |
          pip install flake8
          flake8 . --count --select=E9,F63,F7,F82 --show-source --statistics
          flake8 . --count --exit-zero --max-complexity=10 --max-line-length=127 --statistics

      - name: Run Tests (pytest)
        run: poetry run pytest

      - name: Build Python Package
        run: poetry build
        # หรือ python -m build

      - name: Upload distribution artifacts
        uses: actions/upload-artifact@v4
        with:
          name: python-package-dist
          path: dist/ # โฟลเดอร์ที่เก็บ .whl และ .tar.gz

คำอธิบาย Workflow CI:

  • on.tags: - 'v*': นอกจาก push/pull_request แล้ว เรายังกำหนดให้ Workflow ทำงานเมื่อมีการ Push Tag ที่ขึ้นต้นด้วย ‘v’ (เช่น v1.0.0) ซึ่งจะใช้สำหรับ Trigger การ Publish ในขั้นตอน CD ครับ
  • actions/setup-python@v5: ใช้ในการตั้งค่าสภาพแวดล้อม Python
  • มีการติดตั้ง poetry (หรือ build tools อื่นๆ) เพื่อจัดการ dependency และ Build Package
  • รัน flake8 สำหรับ Linting และ pytest สำหรับ Unit Tests
  • poetry build: คำสั่งสำหรับ Build Python Package (สร้างไฟล์ .whl และ .tar.gz)
  • actions/upload-artifact@v4: อัปโหลดไฟล์ Package ที่ Build ได้เป็น Artifact เพื่อให้ Job ถัดไปสามารถนำไปใช้ได้

ขั้นตอน CD: Publish Package ไปยัง PyPI

Job นี้จะรันเฉพาะเมื่อมีการ Push Tag (ตามที่ระบุใน on.tags) และจะทำการ Publish Package ที่ Build ไว้ไปยัง PyPI ครับ

# .github/workflows/python-publish.yml (ต่อจากด้านบน)
  publish-to-pypi:
    name: Publish Python Package to PyPI
    runs-on: ubuntu-latest
    needs: build_and_test # รันหลังจาก Job build_and_test สำเร็จ
    # เงื่อนไข: รันเฉพาะเมื่อเป็น Event push และเป็น Tag ที่ขึ้นต้นด้วย 'v'
    if: github.event_name == 'push' && startsWith(github.ref, 'refs/tags/v')
    environment:
      name: PyPI # ใช้ GitHub Environment เพื่อจัดการ Secrets และ Protection Rules
    steps:
      - name: Download distribution artifacts
        uses: actions/download-artifact@v4
        with:
          name: python-package-dist
          path: dist/

      - name: Publish package to PyPI
        uses: pypa/gh-action-pypi-publish@release/v1
        with:
          password: ${{ secrets.PYPI_API_TOKEN }} # ใช้ Secret ที่เก็บ PyPI API Token

คำอธิบาย Workflow CD:

  • needs: build_and_test: Job นี้จะรันหลังจาก Job build_and_test สำเร็จ
  • if: github.event_name == 'push' && startsWith(github.ref, 'refs/tags/v'): เงื่อนไขสำคัญเพื่อให้ Job นี้ทำงานเฉพาะเมื่อมีการ Push Tag ที่ขึ้นต้นด้วย ‘v’ เท่านั้นครับ
  • environment: name: PyPI: ใช้ GitHub Environment ชื่อ “PyPI” ซึ่งสามารถกำหนด Protection Rules ได้ เช่น การต้องมีการอนุมัติก่อน Publish หรือการจำกัดว่าใครมีสิทธิ์ Deploy ได้
  • actions/download-artifact@v4: ดาวน์โหลดไฟล์ Package ที่ Build ไว้จาก Artifact
  • pypa/gh-action-pypi-publish@release/v1: Action ที่สะดวกมากสำหรับการ Publish Python Package ไปยัง PyPI ครับ
  • password: ${{ secrets.PYPI_API_TOKEN }}: ใช้ Secret ที่ชื่อ PYPI_API_TOKEN ซึ่งคุณต้องสร้างและเก็บไว้ใน Repository Settings เพื่อให้ Action สามารถ Authenticate กับ PyPI ได้อย่างปลอดภัยครับ

ฟีเจอร์และเทคนิคขั้นสูงของ GitHub Actions

GitHub Actions มีฟีเจอร์และเทคนิคขั้นสูงมากมายที่ช่วยให้คุณสร้าง Pipeline ที่ซับซ้อน, มีประสิทธิภาพ และปลอดภัยมากยิ่งขึ้นครับ

Secrets: การจัดการข้อมูลสำคัญอย่างปลอดภัย

ใน Pipeline ของคุณ มักจะต้องมีการเข้าถึงข้อมูลสำคัญ เช่น API Keys, Database Credentials, Private SSH Keys หรือ Token ต่างๆ ครับ การเก็บข้อมูลเหล่านี้ไว้ใน Workflow YAML โดยตรงเป็นสิ่งที่ไม่ปลอดภัยอย่างยิ่งครับ

GitHub Secrets ช่วยให้คุณสามารถจัดเก็บข้อมูลที่ละเอียดอ่อนเหล่านี้ได้อย่างปลอดภัย โดยข้อมูลจะถูกเข้ารหัสและจะไม่แสดงใน Log ของ Workflow ครับ คุณสามารถเข้าถึง Secrets ได้ผ่านตัวแปร ${{ secrets.YOUR_SECRET_NAME }} ใน Workflow ของคุณครับ

วิธีการใช้งาน:

  1. ไปที่ Repository ของคุณ > Settings > Secrets and variables > Actions.
  2. คลิก “New repository secret” หรือ “New environment secret” (หากใช้ Environments)
  3. ตั้งชื่อ Secret (เช่น PYPI_API_TOKEN, AWS_ACCESS_KEY_ID) และใส่ค่าเข้าไป
  4. ใน Workflow ของคุณ สามารถเรียกใช้ได้โดย ${{ secrets.PYPI_API_TOKEN }}

ข้อควรจำ: Secrets จะถูกเปิดเผยต่อ Job ที่รันเท่านั้น และไม่ควรถูกพิมพ์ออกมาใน Log โดยตรงครับ

Environments: การจัดการสภาพแวดล้อมการทำงาน

GitHub Environments ช่วยให้คุณสามารถกำหนดกฎการป้องกัน (protection rules) และตัวแปรเฉพาะสำหรับสภาพแวดล้อมการ Deploy ต่างๆ (เช่น Development, Staging, Production) ได้ครับ

ประโยชน์:

  • Protection Rules: กำหนดให้ต้องมีการอนุมัติจากผู้ดูแลก่อน Deploy, กำหนดเวลาที่สามารถ Deploy ได้, หรือจำกัด Branch ที่สามารถ Deploy ไปยัง Environment นั้นๆ ได้
  • Environment Secrets: จัดเก็บ Secret ที่ใช้เฉพาะสำหรับ Environment นั้นๆ ทำให้มีความปลอดภัยมากขึ้น และแยก Secret ออกจากกันได้ชัดเจน
  • Environment Variables: กำหนดตัวแปรเฉพาะสำหรับ Environment นั้นๆ

วิธีการใช้งาน:

  1. ไปที่ Repository ของคุณ > Settings > Environments.
  2. คลิก “New environment” และตั้งชื่อ (เช่น Staging, Production)
  3. กำหนด Protection Rules และเพิ่ม Environment Secrets/Variables
  4. ใน Workflow ของคุณ ให้ระบุ environment สำหรับ Job นั้นๆ:
    jobs:
      deploy-to-production:
        runs-on: ubuntu-latest
        environment:
          name: Production
          url: https://your-production-app.com # สามารถระบุ URL ได้
        steps:
          # ...
    

Reusable Workflows: ลดความซ้ำซ้อนด้วย Workflow ที่นำกลับมาใช้ใหม่ได้

หากคุณมีหลาย Repository หรือหลายโปรเจกต์ที่ใช้ CI/CD Pipeline ที่คล้ายคลึงกัน การคัดลอกและวาง Workflow YAML ไปมาเป็นสิ่งที่ไม่ดีครับ Reusable Workflows ช่วยให้คุณสามารถสร้าง Workflow ที่เป็น Template และเรียกใช้จาก Workflow อื่นๆ ได้ ทำให้โค้ดของคุณเป็นระเบียบ, บำรุงรักษาง่าย และลดความซ้ำซ้อนครับ

วิธีการใช้งาน:

  1. สร้าง Workflow หลัก (เช่น .github/workflows/callable-workflow.yml) ที่คุณต้องการนำกลับมาใช้ใหม่
  2. กำหนด on: workflow_call และระบุ inputs และ outputs ที่ Workflow นี้จะรับและส่งกลับไป
  3. ใน Workflow อื่นๆ คุณสามารถเรียกใช้ Workflow นี้ได้โดยใช้ uses: ./.github/workflows/callable-workflow.yml@main หรือ uses: owner/repo/.github/workflows/callable-workflow.yml@main
    # .github/workflows/main-workflow.yml
    name: Main Workflow Calling Reusable
    
    on: [push]
    
    jobs:
      call-build-test:
        uses: ./.github/workflows/callable-workflow.yml # เรียกใช้ Workflow ใน Repo เดียวกัน
        with:
          node-version: '18'
          working-directory: 'my-app'
        secrets:
          my-api-key: ${{ secrets.MY_API_KEY }} # ส่ง secrets ผ่านไปให้
    

Matrix Strategies: การทดสอบข้ามแพลตฟอร์มและเวอร์ชัน

บ่อยครั้งที่เราต้องการทดสอบโค้ดของเรากับหลายๆ เวอร์ชันของภาษาโปรแกรม, หลายๆ ระบบปฏิบัติการ หรือหลายๆ Dependency ครับ Matrix Strategy ช่วยให้คุณสามารถรัน Job เดียวกันหลายๆ ครั้ง โดยใช้ค่าตัวแปรที่แตกต่างกันไปในแต่ละครั้ง ทำให้การทดสอบครอบคลุมและมีประสิทธิภาพมากขึ้นครับ

วิธีการใช้งาน:

jobs:
  test:
    runs-on: ${{ matrix.os }} # Runner จะเปลี่ยนไปตามค่า os
    strategy:
      matrix:
        os: [ubuntu-latest, windows-latest]
        node-version: ['16', '18', '20']
    steps:
      - uses: actions/checkout@v4
      - name: Setup Node.js ${{ matrix.node-version }}
        uses: actions/setup-node@v4
        with:
          node-version: ${{ matrix.node-version }}
      - name: Install dependencies
        run: npm ci
      - name: Run tests
        run: npm test

จากตัวอย่างนี้ Workflow จะรันทั้งหมด 2 (OS) x 3 (Node.js versions) = 6 Job แยกกันครับ

Caching Dependencies: เพิ่มความเร็วในการทำงาน

การติดตั้ง dependency (เช่น npm install, pip install, composer install) อาจใช้เวลานานในแต่ละครั้งที่ Workflow รันครับ GitHub Actions Cache ช่วยให้คุณสามารถเก็บไฟล์ที่ใช้บ่อย (เช่น โฟลเดอร์ node_modules, pip cache) ไว้ใน Cache และดึงกลับมาใช้ใหม่ในการรันครั้งถัดไป ทำให้ประหยัดเวลาได้อย่างมากครับ

วิธีการใช้งาน:

steps:
  - uses: actions/checkout@v4
  - name: Setup Node.js
    uses: actions/setup-node@v4
    with:
      node-version: '18'
      cache: 'npm' # เปิดใช้งาน cache สำหรับ npm
      cache-dependency-path: package-lock.json # ไฟล์ที่จะใช้ในการสร้าง key ของ cache

  - name: Install dependencies
    run: npm ci

Action เช่น actions/setup-node, actions/setup-python มักจะมีพารามิเตอร์ cache ให้ใช้ได้โดยตรง หรือคุณสามารถใช้ actions/cache@v4 โดยตรงได้ครับ

Artifacts: การส่งผ่านข้อมูลระหว่าง Job

Artifacts คือไฟล์หรือโฟลเดอร์ที่คุณสร้างขึ้นใน Job หนึ่ง และต้องการนำไปใช้ใน Job อื่น หรือต้องการเก็บไว้เพื่อดาวน์โหลดในภายหลังครับ ตัวอย่างเช่น คุณอาจ Build ไฟล์ Frontend ใน Job แรก และต้องการนำไฟล์เหล่านั้นไป Deploy ใน Job ที่สอง หรือเก็บรายงานการทดสอบไว้เพื่อการตรวจสอบครับ

วิธีการใช้งาน:

jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - name: Build Frontend
        run: npm run build
      - name: Upload Build Artifact
        uses: actions/upload-artifact@v4
        with:
          name: web-dist
          path: build/ # โฟลเดอร์ที่เก็บไฟล์ที่ Build ได้

  deploy:
    runs-on: ubuntu-latest
    needs: build
    steps:
      - name: Download Build Artifact
        uses: actions/download-artifact@v4
        with:
          name: web-dist
          path: ./dist # โฟลเดอร์ที่จะเก็บไฟล์ที่ดาวน์โหลดมา
      - name: Deploy to server
        run: echo "Deploying files from ./dist"

Self-Hosted Runners: รัน Workflow บนเซิร์ฟเวอร์ส่วนตัว

โดยปกติ GitHub Actions จะรัน Job ของคุณบน Runner ที่ GitHub จัดเตรียมไว้ให้ครับ แต่ในบางกรณี คุณอาจต้องการรัน Job บนเซิร์ฟเวอร์ของคุณเอง (เช่น เพื่อเข้าถึงทรัพยากรภายในเครือข่าย, ใช้ Hardware เฉพาะทาง, หรือประหยัดค่าใช้จ่าย) ซึ่งสามารถทำได้โดยใช้ Self-Hosted Runners ครับ

ประโยชน์:

  • เข้าถึงทรัพยากรภายในเครือข่ายส่วนตัว (VPC)
  • ใช้ Hardware ที่มีประสิทธิภาพสูงหรือเฉพาะทาง
  • ควบคุมสภาพแวดล้อมการรันได้อย่างเต็มที่
  • อาจประหยัดค่าใช้จ่ายสำหรับโปรเจกต์ที่มีการรัน Workflow บ่อยครั้ง

วิธีการใช้งาน:

  1. ติดตั้ง GitHub Actions Runner application บนเซิร์ฟเวอร์ของคุณ (Linux, Windows, macOS)
  2. Runner จะลงทะเบียนกับ GitHub Repository หรือ Organization ของคุณ
  3. ใน Workflow YAML คุณสามารถระบุ Runner ที่คุณต้องการใช้ได้:
    jobs:
      my-custom-job:
        runs-on: [self-hosted, linux, x64] # ระบุ labels ของ Self-Hosted Runner
        steps:
          # ...
    

คุณสามารถ อ่านเพิ่มเติม เกี่ยวกับการตั้งค่า Self-Hosted Runners ได้ที่เอกสารของ GitHub ครับ

Conditional Steps/Jobs: ควบคุม Flow การทำงานอย่างชาญฉลาด

บางครั้งคุณอาจต้องการให้ Step หรือ Job บางอย่างทำงานภายใต้เงื่อนไขเฉพาะเท่านั้น เช่น Deploy ไป Production เฉพาะเมื่อโค้ดอยู่ใน Branch main เท่านั้น Conditional statements ช่วยให้คุณควบคุม Flow การทำงานของ Workflow ได้อย่างยืดหยุ่น

วิธีการใช้งาน:

ใช้คีย์เวิร์ด if ซึ่งรับ Expression ที่เป็น Boolean ครับ

jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - name: Only run on main branch
        if: github.ref == 'refs/heads/main'
        run: echo "This step runs only on main branch"

  deploy-production:
    runs-on: ubuntu-latest
    needs: build
    if: success() && github.ref == 'refs/heads/main' # รันถ้า build สำเร็จและอยู่ใน main branch
    steps:
      # ...

Expression ที่ใช้ใน if สามารถใช้ฟังก์ชันต่างๆ เช่น startsWith(), contains(), success(), failure(), always() ได้ครับ

การดูแลและแก้ไขปัญหา GitHub Actions Pipeline

การสร้าง Pipeline ไม่ได้จบแค่การเขียน YAML ให้รันได้ครั้งแรกครับ การดูแลรักษาและแก้ไขปัญหาเมื่อเกิดขึ้นเป็นส่วนสำคัญที่จะทำให้ Pipeline ของคุณทำงานได้อย่างราบรื่นและยั่งยืนครับ

การอ่านและวิเคราะห์ Log

เมื่อ Workflow ล้มเหลว หรือไม่ทำงานตามที่คุณคาดหวัง สิ่งแรกที่ควรทำคือการตรวจสอบ Log ครับ

  1. ไปที่ Repository ของคุณ > Actions tab.
  2. คลิกที่ Workflow run ที่คุณต้องการตรวจสอบ
  3. คุณจะเห็นรายการ Job และ Step ทั้งหมด คลิกที่ Job หรือ Step ที่มีเครื่องหมาย “x” หรือเครื่องหมายเตือน
  4. Log จะแสดงรายละเอียดของสิ่งที่เกิดขึ้นใน Step นั้นๆ ซึ่งมักจะบอกสาเหตุของปัญหาได้อย่างชัดเจนครับ

เคล็ดลับ: มองหาข้อความ Error, Warning หรือ Stack Trace ที่บ่งชี้ถึงปัญหาครับ บางครั้งปัญหาอาจเกิดจาก Dependency ที่ติดตั้งไม่สำเร็จ, คำสั่งผิดพลาด, หรือการเข้าถึงสิทธิ์ที่ไม่เพียงพอครับ

การ Debug Workflow

บางครั้ง Log ก็ไม่ได้บอกทุกอย่างครับ หากต้องการ Debug Workflow ที่ซับซ้อน อาจต้องใช้วิธีการเพิ่มเติม:

  • เพิ่ม echo หรือ print: ใส่คำสั่ง echo (ใน Bash) หรือ print() (ใน Python) เข้าไปใน Step เพื่อดูค่าตัวแปรหรือสถานะการทำงานในช่วงต่างๆ
  • รัน Workflow ซ้ำ (Re-run jobs): คุณสามารถรัน Job หรือ Workflow ที่ล้มเหลวซ้ำได้โดยตรงจาก GitHub UI ซึ่งมีประโยชน์มากเมื่อคุณแก้ไขโค้ดใน Workflow แล้วต้องการทดสอบทันที
  • ใช้ workflow_dispatch: หากต้องการทดสอบ Workflow ที่ยังไม่พร้อมจะ Trigger ด้วย Push/PR ให้ใช้ workflow_dispatch เพื่อรันด้วยตนเองและสามารถใส่ Input parameters ได้ด้วย
  • ใช้ debug flag: สำหรับ Action บางตัว อาจมี debug flag ที่ช่วยให้แสดงรายละเอียด Log มากขึ้น
  • ตรวจสอบ GitHub Status Page: บางครั้งปัญหาอาจไม่ได้เกิดจาก Workflow ของคุณ แต่อาจเกิดจากปัญหาของ GitHub Actions เอง ตรวจสอบได้ที่ githubstatus.com ครับ

Best Practices สำหรับ GitHub Actions Pipeline

เพื่อให้ Pipeline ของคุณมีประสิทธิภาพ, ปลอดภัย และบำรุงรักษาง่าย ควรปฏิบัติตาม Best Practices เหล่านี้ครับ

  • ความปลอดภัย:
    • ใช้ Secrets อย่างถูกวิธี: อย่า hardcode ข้อมูลสำคัญใน Workflow YAML ใช้ GitHub Secrets เสมอ
    • จำกัดสิทธิ์ (Least Privilege): ให้สิทธิ์แก่ GitHub Actions Token (GITHUB_TOKEN) เท่าที่จำเป็นเท่านั้น (โดยค่าเริ่มต้น GitHub จะให้สิทธิ์ที่เหมาะสมอยู่แล้ว แต่คุณสามารถปรับแต่งได้)
    • ตรวจสอบ Action ที่ใช้: ใช้ Action จากแหล่งที่เชื่อถือได้ (เช่น actions/* จาก GitHub หรือ Action ที่มีชื่อเสียง) และระบุเวอร์ชันของ Action (เช่น actions/checkout@v4) เพื่อหลีกเลี่ยงการเปลี่ยนแปลงที่ไม่คาดคิด
    • ใช้ Environments: สำหรับการ Deploy ไปยัง Staging/Production เพื่อเพิ่ม Protection Rules
  • ประสิทธิภาพ:

จัดส่งรวดเร็วส่งด่วนทั่วประเทศ
รับประกันสินค้าเคลมง่าย มีใบรับประกัน
ผ่อนชำระได้บัตรเครดิต 0% สูงสุด 10 เดือน
สะสมแต้ม รับส่วนลดส่วนลดและคะแนนสะสม

© 2026 SiamLancard — จำหน่ายการ์ดแลน อุปกรณ์ Server และเครื่องพิมพ์ใบเสร็จ

SiamLancard
Logo
Free Forex EA Download — XM Signal · EA Forex ฟรี
iCafeForex.com - สอนเทรด Forex | SiamCafe.net
Shopping cart