
ในโลกของการพัฒนาซอฟต์แวร์ที่เปลี่ยนแปลงอย่างรวดเร็วในปัจจุบัน การส่งมอบผลิตภัณฑ์ที่มีคุณภาพออกสู่ตลาดได้อย่างต่อเนื่องและรวดเร็ว ถือเป็นหัวใจสำคัญของความสำเร็จครับ และหนึ่งในกุญแจสำคัญที่จะช่วยให้ทีมพัฒนาบรรลุเป้าหมายนี้ได้ ก็คือการนำแนวคิด CI/CD Pipeline มาประยุกต์ใช้ โดยเฉพาะอย่างยิ่งเมื่อรวมพลังกับ GitHub Actions ซึ่งเป็นเครื่องมืออันทรงพลังที่ GitHub มอบให้ เราจะสามารถสร้างกระบวนการทำงานอัตโนมัติที่แข็งแกร่งและมีประสิทธิภาพได้อย่างน่าทึ่ง บทความนี้จะพาทุกท่านดำดิ่งสู่โลกของ CI/CD และ GitHub Actions อย่างละเอียด ตั้งแต่พื้นฐานไปจนถึงการสร้างไพป์ไลน์ที่ซับซ้อน เพื่อให้คุณสามารถนำไปปรับใช้กับโปรเจกต์ของคุณได้อย่างมั่นใจครับ
สารบัญ
- ทำความรู้จัก CI/CD Pipeline คืออะไร?
- GitHub Actions: เครื่องมืออัตโนมัติสำหรับนักพัฒนา
- เจาะลึกองค์ประกอบหลักของ GitHub Actions
- Workflows (.github/workflows/*.yml)
- Events (ทริกเกอร์การทำงาน)
- Jobs (ชุดของขั้นตอนที่ทำงานคู่ขนาน)
- Steps (ขั้นตอนย่อยใน Job)
- Actions (หน่วยการทำงานที่นำมาใช้ซ้ำได้)
- Runners (เครื่องมือที่รัน Workflow)
- Contexts และ Secrets (การเข้าถึงข้อมูลและจัดการความปลอดภัย)
- Environments (การจัดการสภาพแวดล้อมและกฎการ Deploy)
- การออกแบบ CI/CD Pipeline ด้วย GitHub Actions
- ตัวอย่างการสร้าง CI/CD Pipeline ด้วย GitHub Actions แบบใช้งานได้จริง
- หัวข้อขั้นสูงและ Best Practices
- ตารางเปรียบเทียบ: GitHub-hosted Runners vs. Self-hosted Runners
- คำถามที่พบบ่อย (FAQ)
- สรุปและ Call-to-Action
ทำความรู้จัก CI/CD Pipeline คืออะไร?
ก่อนที่เราจะลงลึกไปถึง GitHub Actions เรามาทำความเข้าใจพื้นฐานของ CI/CD Pipeline กันก่อนครับ CI/CD ย่อมาจาก Continuous Integration, Continuous Delivery และ Continuous Deployment ซึ่งเป็นชุดของหลักปฏิบัติที่ช่วยให้ทีมพัฒนาซอฟต์แวร์สามารถส่งมอบโค้ดได้อย่างรวดเร็วและน่าเชื่อถือมากขึ้น
Continuous Integration (CI)
Continuous Integration (CI) คือหลักปฏิบัติที่นักพัฒนาจะรวมโค้ดที่เขียนเสร็จแล้วเข้าสู่ Main Repository อย่างสม่ำเสมอ โดยปกติคือวันละหลายครั้ง การรวมโค้ดบ่อยครั้งนี้จะตามมาด้วยการสร้าง (Build) และทดสอบ (Test) โค้ดโดยอัตโนมัติ เพื่อตรวจจับข้อผิดพลาดหรือความขัดแย้งของโค้ดตั้งแต่เนิ่นๆ
ขั้นตอนหลักของ CI:
- การ Commit โค้ด: นักพัฒนาส่งโค้ดใหม่ไปยัง Main Repository
- การ Build อัตโนมัติ: ระบบจะทำการ Build โปรเจกต์โดยอัตโนมัติ เพื่อตรวจสอบว่าโค้ดสามารถคอมไพล์หรือรันได้
- การทดสอบอัตโนมัติ: ระบบจะรันชุดการทดสอบต่างๆ เช่น Unit Tests, Integration Tests เพื่อให้มั่นใจว่าโค้ดใหม่ไม่ได้ทำลายฟังก์ชันการทำงานเดิมที่มีอยู่
- การแจ้งเตือน: หากมีข้อผิดพลาดในการ Build หรือ Test ทีมจะได้รับการแจ้งเตือนทันที เพื่อให้สามารถแก้ไขได้รวดเร็ว
เป้าหมายของ CI คือการลดความเสี่ยงที่เกิดจากการรวมโค้ดจำนวนมากในคราวเดียว และช่วยให้ทีมมั่นใจว่าโค้ดที่อยู่ใน Main Repository นั้นพร้อมใช้งานอยู่เสมอ
Continuous Delivery (CD) และ Continuous Deployment (CD)
หลังจากขั้นตอน CI ที่สำเร็จแล้ว เราจะเข้าสู่ส่วนของ CD ซึ่งมีสองรูปแบบหลักๆ คือ Continuous Delivery และ Continuous Deployment
Continuous Delivery (CD):
คือการขยายจาก CI โดยที่โค้ดที่ผ่านการ Build และ Test แล้ว จะถูกเตรียมพร้อมสำหรับการนำไปใช้งาน (Deployment) เสมอ แต่การ Deploy ไปยัง Production Environment จะยังคงต้องอาศัยการตัดสินใจหรือการอนุมัติด้วยตนเองครับ หมายความว่าโค้ดพร้อมที่จะ Deploy ได้ตลอดเวลา แต่เราเลือกเวลาที่จะ Deploy เอง
- Artifacts: ผลลัพธ์จากการ Build (เช่นไฟล์ .jar, Docker image) จะถูกจัดเก็บไว้ใน Repository ที่พร้อมสำหรับการ Deploy
- Deployment อัตโนมัติไปยัง Staging/Test Environment: โค้ดอาจถูก Deploy ไปยังสภาพแวดล้อมทดสอบโดยอัตโนมัติ เพื่อให้ QA หรือผู้มีส่วนได้ส่วนเสียได้ทดสอบเพิ่มเติม
- การอนุมัติด้วยตนเอง: การ Deploy ไปยัง Production Environment ต้องได้รับการอนุมัติจากมนุษย์
Continuous Deployment (CD):
คือการก้าวไปอีกขั้นจาก Continuous Delivery โดยที่โค้ดที่ผ่านการ Build และ Test ทั้งหมดแล้ว และพร้อมสำหรับการใช้งาน จะถูก Deploy ไปยัง Production Environment โดยอัตโนมัติทั้งหมด โดยไม่มีการแทรกแซงจากมนุษย์เลยครับ นี่คือจุดสูงสุดของ CI/CD ที่ช่วยให้ซอฟต์แวร์ถูกส่งมอบอย่างต่อเนื่องและรวดเร็วที่สุด
- การ Deploy อัตโนมัติไปยัง Production: ทุกครั้งที่โค้ดผ่านการทดสอบทั้งหมด โค้ดจะถูก Deploy ไปยัง Production โดยอัตโนมัติ
- ความเร็วสูงสุด: ช่วยให้ฟีเจอร์ใหม่ๆ หรือการแก้ไขบั๊กไปถึงมือผู้ใช้ได้อย่างรวดเร็วที่สุด
- ต้องการความเชื่อมั่นสูง: จำเป็นต้องมีชุดการทดสอบที่ครอบคลุมและน่าเชื่อถืออย่างมาก
ทำไม CI/CD จึงสำคัญ?
การนำ CI/CD Pipeline มาใช้มีประโยชน์มากมายต่อทีมพัฒนาและองค์กรครับ
- ลดความเสี่ยงและตรวจจับข้อผิดพลาดได้เร็วขึ้น: การรวมโค้ดและทดสอบอย่างสม่ำเสมอช่วยให้ค้นพบและแก้ไขบั๊กได้ตั้งแต่เนิ่นๆ ก่อนที่จะกลายเป็นปัญหาใหญ่
- เพิ่มความเร็วในการส่งมอบซอฟต์แวร์: กระบวนการอัตโนมัติช่วยลดเวลาที่ใช้ในการนำโค้ดจากนักพัฒนาไปสู่ผู้ใช้งานจริง
- เพิ่มคุณภาพของซอฟต์แวร์: การทดสอบอัตโนมัติที่ครอบคลุมช่วยให้มั่นใจว่าซอฟต์แวร์ทำงานได้ถูกต้องและมีคุณภาพสม่ำเสมอ
- ลดต้นทุน: ลดความจำเป็นในการทำงานซ้ำ (rework) และลดเวลาที่ใช้ในการแก้ไขปัญหาหลังการ Deploy
- เพิ่มความร่วมมือในทีม: ทุกคนทำงานบนโค้ดเบสที่อัปเดตอยู่เสมอ ลดปัญหาความขัดแย้งของโค้ด
- สร้างความมั่นใจ: ทีมมีความมั่นใจมากขึ้นในการส่งมอบโค้ดใหม่ๆ เพราะรู้ว่ามีระบบอัตโนมัติช่วยตรวจสอบอยู่แล้ว
ในยุคที่ความเร็วและคุณภาพคือสิ่งสำคัญ การนำ CI/CD มาใช้จึงไม่ใช่แค่ทางเลือก แต่เป็นสิ่งจำเป็นครับ อ่านเพิ่มเติมเกี่ยวกับประโยชน์ของ CI/CD
GitHub Actions: เครื่องมืออัตโนมัติสำหรับนักพัฒนา
เมื่อพูดถึงการสร้าง CI/CD Pipeline ในปัจจุบัน GitHub Actions ได้กลายเป็นหนึ่งในตัวเลือกยอดนิยมสำหรับนักพัฒนาจำนวนมากครับ เนื่องจากมันถูกรวมเข้ากับ GitHub ซึ่งเป็นแพลตฟอร์มที่นักพัฒนาส่วนใหญ่ใช้ในการจัดการโค้ดอยู่แล้ว ทำให้การเริ่มต้นใช้งานเป็นไปอย่างราบรื่นและมีประสิทธิภาพ
องค์ประกอบหลักของ GitHub Actions
GitHub Actions ทำงานโดยการกำหนด Workflows ซึ่งเป็นชุดของคำสั่งที่จะถูกรันเมื่อเกิด Events ที่กำหนดไว้ แต่ละ Workflow ประกอบด้วย Jobs หลายๆ Job ซึ่งแต่ละ Job จะมี Steps ที่ประกอบด้วย Actions หรือคำสั่ง Script ต่างๆ โดยทั้งหมดนี้จะถูกรันบน Runners
ประโยชน์ของการใช้ GitHub Actions สำหรับ CI/CD
- ผสานรวมกับ GitHub ได้อย่างราบรื่น: เนื่องจากเป็นส่วนหนึ่งของ GitHub ทำให้การตั้งค่าและการจัดการ Workflow เป็นเรื่องง่าย ไม่ต้องเชื่อมต่อเครื่องมือภายนอก
- ใช้ภาษา YAML ที่คุ้นเคย: การกำหนด Workflow ใช้ภาษา YAML ซึ่งเป็นที่นิยมและอ่านง่าย
- มี Marketplace ขนาดใหญ่: มี Actions สำเร็จรูปมากมายที่นักพัฒนาทั่วโลกสร้างไว้ให้เลือกใช้ ทำให้ไม่ต้องเขียน Script เองทั้งหมด
- รองรับการทำงานแบบ Multi-Platform: สามารถรัน Workflow บน Linux, Windows และ macOS ได้
- ฟรีสำหรับ Public Repository: GitHub Actions ใช้งานได้ฟรีสำหรับ Public Repository และมี Free Tier สำหรับ Private Repository
- Self-hosted Runners: สามารถใช้เครื่องเซิร์ฟเวอร์ของคุณเองเป็น Runner ได้ หากต้องการควบคุมสภาพแวดล้อมหรือใช้ Hardware เฉพาะ
- Contexts และ Secrets: มีกลไกในการเข้าถึงข้อมูลต่างๆ ของ Repository และจัดการข้อมูลที่ละเอียดอ่อนได้อย่างปลอดภัย
- Environments: ช่วยให้กำหนดกฎการ Deploy และตัวแปรเฉพาะสำหรับแต่ละสภาพแวดล้อม (เช่น Development, Staging, Production) ได้อย่างมีประสิทธิภาพ
เจาะลึกองค์ประกอบหลักของ GitHub Actions
เพื่อให้คุณสามารถสร้าง CI/CD Pipeline ที่มีประสิทธิภาพด้วย GitHub Actions ได้อย่างเต็มที่ เรามาเจาะลึกองค์ประกอบสำคัญแต่ละส่วนกันครับ
Workflows (.github/workflows/*.yml)
Workflow คือกระบวนการอัตโนมัติที่ถูกกำหนดไว้ในไฟล์ YAML และจัดเก็บไว้ในไดเรกทอรี .github/workflows/ ใน Repository ของคุณครับ แต่ละ Repository สามารถมี Workflow ได้หลายไฟล์
# .github/workflows/ci-pipeline.yml
name: CI Pipeline for My App
on:
push:
branches:
- main
- develop
pull_request:
branches:
- main
- develop
jobs:
build_and_test:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '20'
- name: Install dependencies
run: npm install
- name: Run tests
run: npm test
name: ชื่อของ Workflow ที่จะแสดงใน GitHub UIon: กำหนด Event ที่จะทริกเกอร์ Workflow นี้ (เช่นpush,pull_request)jobs: ชุดของ Jobs ที่จะถูกรัน
Events (ทริกเกอร์การทำงาน)
Events คือกิจกรรมที่เกิดขึ้นใน Repository ของคุณ ซึ่งจะกระตุ้นให้ Workflow ทำงานครับ คุณสามารถกำหนด Event ได้หลากหลายรูปแบบ
Events ยอดนิยม:
push: เมื่อมีการ Push โค้ดไปยัง Branch ที่กำหนด (เช่นmain,develop)pull_request: เมื่อมีการสร้าง, อัปเดต, หรือปิด Pull Requestschedule: กำหนดเวลาให้ Workflow ทำงานเป็นประจำ เช่น ทุกคืนหรือทุกวันจันทร์ (ใช้รูปแบบ Cron syntax)workflow_dispatch: อนุญาตให้รัน Workflow ด้วยตนเองจาก GitHub UI หรือ APIrelease: เมื่อมีการสร้าง, แก้ไข, หรือลบ Releaseissue_comment: เมื่อมีการเพิ่ม Comment ใน Issuerepository_dispatch: เมื่อมีการส่ง Webhook จากภายนอกเข้ามายัง GitHub
คุณสามารถกำหนดเงื่อนไขเพิ่มเติมให้กับ Event ได้ เช่น branches, tags, paths เพื่อให้ Workflow ทำงานเฉพาะเมื่อเงื่อนไขเหล่านั้นตรงตามที่กำหนดครับ
Jobs (ชุดของขั้นตอนที่ทำงานคู่ขนาน)
Job คือชุดของ Steps ที่ถูกรันบน Runner เดียวกันครับ ใน Workflow หนึ่งๆ สามารถมีได้หลาย Job และ Job เหล่านี้สามารถทำงานพร้อมกัน (parallel) หรือทำงานตามลำดับโดยใช้คีย์เวิร์ด needs
jobs:
build:
runs-on: ubuntu-latest
steps:
# ... build steps ...
test:
runs-on: ubuntu-latest
needs: build # Job 'test' จะรันหลังจาก 'build' เสร็จสิ้น
steps:
# ... test steps ...
deploy:
runs-on: ubuntu-latest
needs: test # Job 'deploy' จะรันหลังจาก 'test' เสร็จสิ้น
steps:
# ... deploy steps ...
คุณสมบัติสำคัญของ Job:
runs-on: ระบุประเภทของ Runner ที่จะใช้ (เช่นubuntu-latest,windows-latest,macos-latestหรือชื่อของ self-hosted runner)needs: กำหนด Dependency ของ Job ทำให้ Job ทำงานตามลำดับif: กำหนดเงื่อนไขว่า Job จะรันหรือไม่ (เช่นif: github.ref == 'refs/heads/main')environment: ผูก Job กับ Environment ที่กำหนดไว้ เพื่อจัดการ Secrets, ตัวแปร และกฎการ Deploy
Steps (ขั้นตอนย่อยใน Job)
Step คือหน่วยการทำงานย่อยที่สุดใน Job ครับ แต่ละ Job ประกอบด้วย Step อย่างน้อยหนึ่ง Step โดย Step สามารถเป็นได้ทั้งการเรียกใช้ Action หรือการรันคำสั่ง Script
steps:
- name: Checkout code # ชื่อของ Step
uses: actions/checkout@v4 # ใช้ Action จาก Marketplace
- name: Install dependencies
run: npm install # รันคำสั่ง Shell
- name: Build project
run: npm run build --if-present
env: # กำหนด Environment variables สำหรับ Step นี้
NODE_ENV: production
- name: Upload build artifact
uses: actions/upload-artifact@v4
with: # ส่งค่า input ไปยัง Action
name: my-app-build
path: dist/
name: ชื่อที่อ่านง่ายสำหรับ Stepuses: ใช้ Action ที่มีอยู่แล้ว (เช่นactions/checkout@v4)run: รันคำสั่ง Shell (เช่นbash,pwsh)with: กำหนด Input ให้กับ Action ที่ถูกเรียกใช้env: กำหนด Environment variables เฉพาะสำหรับ Step นั้น
Actions (หน่วยการทำงานที่นำมาใช้ซ้ำได้)
Action คือหน่วยการทำงานที่เล็กที่สุดและนำกลับมาใช้ซ้ำได้ใน Workflow ครับ Action สามารถเป็น Script ที่คุณเขียนเอง, Action ที่มาจาก GitHub Marketplace หรือ Action ที่คุณสร้างขึ้นเองใน Repository นั้นๆ
ประเภทของ Actions:
- Community Actions: Action ที่สร้างโดยชุมชนนักพัฒนาและมีให้ใช้งานใน GitHub Marketplace (เช่น
actions/checkout,actions/setup-node) - Docker Container Actions: Action ที่รันภายใน Docker Container
- JavaScript Actions: Action ที่เขียนด้วย JavaScript และรันบน Node.js
- Composite Actions: Action ที่รวมหลาย Steps เข้าด้วยกันเป็น Action เดียว
การใช้ Actions ช่วยลดความซับซ้อนและเพิ่มความเร็วในการสร้าง Workflow เพราะคุณไม่ต้องเขียน Script เองทั้งหมดครับ
Runners (เครื่องมือที่รัน Workflow)
Runner คือเครื่องเซิร์ฟเวอร์ที่รัน Job ใน Workflow ของคุณครับ GitHub Actions มี Runner ให้เลือกใช้ 2 ประเภทหลักๆ
- GitHub-hosted Runners:
- เป็นเครื่อง VM ที่ GitHub จัดเตรียมให้ (Ubuntu Linux, Windows Server, macOS)
- มีการอัปเดตซอฟต์แวร์พื้นฐานที่จำเป็นให้พร้อมใช้งาน
- เหมาะสำหรับโปรเจกต์ส่วนใหญ่ที่ไม่มีข้อกำหนดพิเศษด้าน Hardware หรือสภาพแวดล้อม
- คุณไม่ต้องกังวลเรื่องการบำรุงรักษา
- Self-hosted Runners:
- เป็นเครื่องเซิร์ฟเวอร์ที่คุณติดตั้งและจัดการเอง (ใน Data Center ของคุณ, บน Cloud VM ของคุณ)
- คุณสามารถควบคุมสภาพแวดล้อม ซอฟต์แวร์ และ Hardware ได้อย่างเต็มที่
- เหมาะสำหรับกรณีที่ต้องการรันบน Hardware เฉพาะ (เช่น GPU), ต้องเข้าถึงทรัพยากรภายใน Network ส่วนตัว หรือมีข้อจำกัดด้านความปลอดภัย
- คุณต้องรับผิดชอบในการบำรุงรักษาและดูแลรักษา Runner เอง
Contexts และ Secrets (การเข้าถึงข้อมูลและจัดการความปลอดภัย)
Contexts คือวิธีการเข้าถึงข้อมูลต่างๆ ที่เกี่ยวข้องกับ Workflow, Job, Step, Runner, Event หรือ Environment ครับ เช่น github.sha สำหรับ Commit SHA, github.event_name สำหรับชื่อ Event ที่ทริกเกอร์
Secrets คือตัวแปรที่คุณจัดเก็บข้อมูลที่ละเอียดอ่อน เช่น API Keys, Token, รหัสผ่าน ไว้ใน GitHub Repository หรือ Organization ของคุณได้อย่างปลอดภัยครับ Secrets จะไม่ถูกเปิดเผยใน Log ของ Workflow และสามารถเข้าถึงได้ผ่าน Context secrets เท่านั้น
steps:
- name: Deploy to AWS
uses: aws-actions/configure-aws-credentials@v4
with:
aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
aws-region: ap-southeast-1
การใช้ Secrets เป็นสิ่งสำคัญอย่างยิ่งในการรักษาความปลอดภัยของข้อมูลประจำตัวและข้อมูลที่ละเอียดอ่อนใน CI/CD Pipeline ของคุณครับ
Environments (การจัดการสภาพแวดล้อมและกฎการ Deploy)
Environments ใน GitHub Actions ช่วยให้คุณกำหนดกฎการป้องกันและตัวแปรเฉพาะสำหรับสภาพแวดล้อมการ Deploy ต่างๆ ได้ครับ เช่น Development, Staging, Production
ประโยชน์ของ Environments:
- Deployment Protection Rules: คุณสามารถกำหนดให้ต้องมีการอนุมัติด้วยตนเอง (Manual Approval) ก่อนที่จะ Deploy ไปยัง Production Environment
- Required Reviewers: กำหนดให้บุคคลหรือทีมที่ระบุต้องอนุมัติก่อนการ Deploy
- Wait Timer: กำหนดเวลาหน่วงก่อนการ Deploy (เช่น รอ 30 นาที เพื่อให้มีเวลาตรวจสอบเพิ่มเติม)
- Environment Secrets: จัดเก็บ Secrets ที่เฉพาะเจาะจงสำหรับแต่ละ Environment (เช่น Production API Key จะต่างจาก Staging API Key)
jobs:
deploy_production:
runs-on: ubuntu-latest
environment: production # ผูก Job นี้กับ Environment "production"
steps:
- name: Deploy to Production
run: echo "Deploying to production using ${{ secrets.PRODUCTION_API_KEY }}"
การใช้ Environments ช่วยเพิ่มความปลอดภัยและควบคุมกระบวนการ Deploy ได้อย่างมีประสิทธิภาพ โดยเฉพาะอย่างยิ่งในสภาพแวดล้อม Production ครับ
การออกแบบ CI/CD Pipeline ด้วย GitHub Actions
การออกแบบ CI/CD Pipeline ที่ดีนั้นเป็นมากกว่าแค่การเขียนโค้ด YAML ครับ มันเกี่ยวข้องกับการวางแผนอย่างรอบคอบเพื่อให้กระบวนการทำงานมีประสิทธิภาพและตอบโจทย์ความต้องการของโปรเจกต์
การวางแผนขั้นตอนของ Pipeline
โดยทั่วไปแล้ว CI/CD Pipeline จะแบ่งออกเป็นหลายขั้นตอน (Stages) ซึ่งแต่ละขั้นตอนมีวัตถุประสงค์เฉพาะของตัวเองครับ
- Source (การดึง Source Code):
- วัตถุประสงค์: ดึงโค้ดเวอร์ชันล่าสุดจาก Repository
- GitHub Actions: ใช้
actions/checkout@v4
- Build (การสร้าง):
- วัตถุประสงค์: คอมไพล์โค้ด, ติดตั้ง Dependencies, สร้าง Artifacts ที่พร้อมสำหรับการ Deploy (เช่น Docker Image, ไฟล์ .jar, ไฟล์ JavaScript ที่ Bundled)
- GitHub Actions: ใช้
actions/setup-node,actions/setup-java,docker/build-push-actionและคำสั่งrunเช่นnpm install,npm run build,mvn package
- Test (การทดสอบ):
- วัตถุประสงค์: ตรวจสอบคุณภาพของโค้ดและฟังก์ชันการทำงาน
- ประเภทของการทดสอบ: Unit Tests, Integration Tests, End-to-End Tests, Static Code Analysis, Security Scans
- GitHub Actions: ใช้คำสั่ง
runเพื่อรัน Test Framework (เช่นnpm test,pytest), Actions สำหรับ Code Quality (เช่น SonarCloud), Security Scanners (เช่น Snyk)
- Package (การบรรจุ):
- วัตถุประสงค์: จัดเตรียม Artifacts ที่ผ่านการ Build และ Test แล้ว ให้พร้อมสำหรับการจัดเก็บหรือ Deploy
- GitHub Actions: ใช้
actions/upload-artifactเพื่อจัดเก็บ Artifacts ที่สร้างขึ้น
- Deploy (การนำไปใช้งาน):
- วัตถุประสงค์: นำ Artifacts ไปติดตั้งหรือรันบนสภาพแวดล้อมเป้าหมาย (Development, Staging, Production)
- GitHub Actions: ใช้ Actions ที่เฉพาะเจาะจงสำหรับ Cloud Provider (เช่น
aws-actions/*,azure/webapps-deploy), หรือ Actions สำหรับการ Deploy ไปยัง Kubernetes, Serverless Functions, หรือ FTP - ควรใช้ Environments เพื่อควบคุมการ Deploy ไปยังแต่ละสภาพแวดล้อม
- Monitor (การเฝ้าระวัง):
- วัตถุประสงค์: ตรวจสอบประสิทธิภาพและสถานะของแอปพลิเคชันหลังการ Deploy (แม้จะไม่ใช่ส่วนหนึ่งของ Workflow โดยตรง แต่สำคัญในภาพรวมของ CI/CD)
- GitHub Actions: สามารถใช้ Action เพื่อแจ้งเตือนไปยังเครื่องมือ Monitoring หรือส่งสถานะการ Deploy
การกำหนดลำดับและความสัมพันธ์ของ Job เหล่านี้ด้วย needs จะช่วยให้ Pipeline ทำงานได้อย่างถูกต้องและมีประสิทธิภาพครับ
กลยุทธ์การ Branching ที่เหมาะสม
กลยุทธ์การ Branching ของ Git มีผลอย่างมากต่อการออกแบบ CI/CD Pipeline ของคุณครับ
- GitHub Flow:
- แนวคิด: Branch
mainเป็น Production เสมอ สร้าง Feature Branch จากmainเมื่อเสร็จแล้วทำ Pull Request กลับมาที่main - CI/CD Impact:
- Pull Request ไปยัง
mainจะทริกเกอร์ CI (Build, Test) - เมื่อ Merge เข้า
mainจะทริกเกอร์ CD (Deploy ไป Production)
- Pull Request ไปยัง
- เหมาะสำหรับ: ทีมขนาดเล็กถึงกลาง, โปรเจกต์ที่ต้องการ Deploy บ่อยครั้งและรวดเร็ว
- แนวคิด: Branch
- Git Flow:
- แนวคิด: มี Branch หลักหลายอัน (
mainสำหรับ Production,developสำหรับ Integration) และ Feature, Release, Hotfix Branches - CI/CD Impact:
- Push หรือ Pull Request ไปยัง
developจะทริกเกอร์ CI (Build, Test) และอาจจะ Deploy ไป Staging - Pull Request จาก
releaseไปยังmainจะทริกเกอร์ CD ไป Production (อาจมี Manual Approval) - Push ไปยัง
mainอาจใช้สำหรับ Hotfix หรือการ Deploy Production โดยตรง
- Push หรือ Pull Request ไปยัง
- เหมาะสำหรับ: โปรเจกต์ขนาดใหญ่, โปรเจกต์ที่มี Release Cycles ที่ชัดเจน, มีหลายเวอร์ชัน
- แนวคิด: มี Branch หลักหลายอัน (
การเลือกกลยุทธ์ที่เหมาะสมจะช่วยให้คุณกำหนด on event และเงื่อนไข if ใน Workflow ได้อย่างมีเหตุผลและปลอดภัยครับ
ตัวอย่างการสร้าง CI/CD Pipeline ด้วย GitHub Actions แบบใช้งานได้จริง
มาดูตัวอย่างการสร้าง Workflow สำหรับสถานการณ์จริงกันครับ
ตัวอย่างที่ 1: CI Pipeline สำหรับแอปพลิเคชัน Node.js (Build & Test)
Workflow นี้จะทำงานเมื่อมีการ Push โค้ดไปยัง Branch main หรือ develop หรือเมื่อมีการสร้าง Pull Request ไปยัง Branch เหล่านี้ โดยจะทำการ Checkout โค้ด, ติดตั้ง Node.js, ติดตั้ง Dependencies และรัน Unit Tests
# .github/workflows/nodejs-ci.yml
name: Node.js CI
on:
push:
branches: ["main", "develop"]
pull_request:
branches: ["main", "develop"]
jobs:
build_and_test:
runs-on: ubuntu-latest
strategy:
matrix:
node-version: ["18.x", "20.x"] # ทดสอบกับ Node.js หลายเวอร์ชัน
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Setup Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v4
with:
node-version: ${{ matrix.node-version }}
cache: 'npm' # เปิดใช้งาน Cache สำหรับ npm dependencies
- name: Install dependencies
run: npm ci # ใช้ npm ci เพื่อการติดตั้งที่แม่นยำและรวดเร็วใน CI
- name: Run tests
run: npm test
- name: Build project # หากมีขั้นตอน Build
run: npm run build --if-present
- name: Upload coverage reports # ตัวอย่างการอัปโหลดรายงานการทดสอบ
uses: actions/upload-artifact@v4
with:
name: coverage-report-${{ matrix.node-version }}
path: coverage/
if-no-files-found: ignore
คำอธิบาย:
strategy.matrix: เราใช้ Matrix Build เพื่อทดสอบโค้ดของเรากับ Node.js หลายเวอร์ชันพร้อมกันcache: 'npm': เป็นการเปิดใช้งาน Cache สำหรับ npm dependencies ซึ่งช่วยให้การติดตั้ง Dependencies ในครั้งถัดไปรวดเร็วขึ้นอย่างมากnpm ci: เป็นคำสั่งที่แนะนำให้ใช้ในสภาพแวดล้อม CI/CD เพราะจะติดตั้ง Dependencies ตามpackage-lock.jsonอย่างเคร่งครัด เพื่อให้มั่นใจว่าการ Build ซ้ำๆ จะได้ผลลัพธ์เหมือนเดิมactions/upload-artifact@v4: ใช้สำหรับจัดเก็บไฟล์ที่สร้างขึ้น (เช่น รายงานการทดสอบ, ไฟล์ Build) ซึ่งสามารถดาวน์โหลดไปตรวจสอบได้ในภายหลัง หรือส่งผ่านไปยัง Job อื่นๆ ได้
ตัวอย่างที่ 2: เพิ่ม CD (Continuous Deployment) ไปยัง AWS S3 สำหรับ Static Site
Workflow นี้จะทำงานหลังจาก CI ในตัวอย่างที่ 1 ผ่านไปแล้ว โดยจะทำการ Build Static Site และ Deploy ไปยัง AWS S3 Bucket ครับ
# .github/workflows/static-site-cd.yml
name: Static Site CD to AWS S3
on:
push:
branches: ["main"] # Deploy เฉพาะเมื่อ Push ไปยัง main branch
env: # กำหนด Environment Variables ทั่วทั้ง Workflow
AWS_REGION: ap-southeast-1
S3_BUCKET_NAME: your-static-website-bucket-name
jobs:
build:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '20'
cache: 'npm'
- name: Install dependencies
run: npm ci
- name: Build static site
run: npm run build # คำสั่ง build project ของคุณ (เช่น สร้างไฟล์ในโฟลเดอร์ dist/)
- name: Upload build artifact
uses: actions/upload-artifact@v4
with:
name: website-build
path: dist/ # โฟลเดอร์ที่เก็บไฟล์ที่ Build แล้ว
deploy:
runs-on: ubuntu-latest
needs: build # Job นี้จะรันหลังจาก Job 'build' เสร็จสิ้น
environment: production # กำหนด Environment เป็น production เพื่อใช้ protection rules
steps:
- name: Download build artifact
uses: actions/download-artifact@v4
with:
name: website-build
path: . # ดาวน์โหลด artifact มาไว้ใน root ของ workspace
- name: Configure AWS credentials
uses: aws-actions/configure-aws-credentials@v4
with:
aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }} # ใช้ Secret
aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }} # ใช้ Secret
aws-region: ${{ env.AWS_REGION }}
- name: Deploy static files to S3
run: |
aws s3 sync . s3://${{ env.S3_BUCKET_NAME }} --delete # Sync ไฟล์จากโฟลเดอร์ปัจจุบันไปยัง S3
aws cloudfront create-invalidation --distribution-id ${{ secrets.CLOUDFRONT_DISTRIBUTION_ID }} --paths "/*" # Clear CloudFront cache (ถ้ามี)
คำอธิบาย:
- เราแยก Job เป็น
buildและdeployโดยdeployจะรันหลังจากbuildเสร็จสิ้น actions/upload-artifactใน Jobbuildและactions/download-artifactใน Jobdeployใช้เพื่อส่งผ่านผลลัพธ์จากการ Build ไปยัง Job ถัดไปaws-actions/configure-aws-credentials: Action นี้ใช้สำหรับตั้งค่า AWS Credentials ใน Runner ทำให้สามารถใช้ AWS CLI ได้secrets.AWS_ACCESS_KEY_ID,secrets.AWS_SECRET_ACCESS_KEY,secrets.CLOUDFRONT_DISTRIBUTION_ID: เป็นตัวอย่างของ Secrets ที่คุณต้องตั้งค่าใน GitHub Repository Settings เพื่อความปลอดภัยaws s3 sync: คำสั่ง AWS CLI สำหรับ Sync ไฟล์จาก Local ไปยัง S3 Bucketaws cloudfront create-invalidation: หากคุณใช้ CloudFront เพื่อแคชเว็บไซต์ คุณควรล้างแคชหลังจาก Deploy เพื่อให้ผู้ใช้เห็นเวอร์ชันล่าสุดทันทีenvironment: production: กำหนดให้ Job นี้ผูกกับ Environment “production” ซึ่งคุณสามารถตั้งค่า Protection Rules เช่น Manual Approval ได้ที่นี่ครับ
ตัวอย่างที่ 3: Multi-Stage Pipeline พร้อมการ Deploy ไปยังหลาย Environment และ Manual Approval
Workflow นี้แสดงถึง Pipeline ที่ซับซ้อนขึ้น โดยมีขั้นตอน Build, Test และ Deploy ไปยัง Staging และ Production พร้อมการอนุมัติด้วยตนเองสำหรับ Production
# .github/workflows/multi-stage-cd.yml
name: Multi-Stage CI/CD Pipeline
on:
push:
branches: ["main"]
workflow_dispatch: # อนุญาตให้รัน Workflow ด้วยตนเอง
env:
AWS_REGION: ap-southeast-1
jobs:
build:
runs-on: ubuntu-latest
outputs:
version: ${{ steps.get_version.outputs.VERSION }} # ส่งค่า version ออกไปให้ Job อื่นใช้
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '20'
- name: Get package version
id: get_version
run: echo "VERSION=$(node -p "require('./package.json').version")" >> $GITHUB_OUTPUT
- name: Install dependencies and Build
run: |
npm ci
npm run build
- name: Upload build artifact
uses: actions/upload-artifact@v4
with:
name: my-app-build-${{ steps.get_version.outputs.VERSION }}
path: dist/
test:
runs-on: ubuntu-latest
needs: build
steps:
- name: Download build artifact
uses: actions/download-artifact@v4
with:
name: my-app-build-${{ needs.build.outputs.version }}
path: .
- name: Run tests (e.g., integration tests)
run: npm test # หรือคำสั่งทดสอบอื่นๆ ที่ใช้ artifact ที่ build แล้ว
deploy_staging:
runs-on: ubuntu-latest
needs: test
environment: staging # กำหนด Environment "staging"
steps:
- name: Download build artifact
uses: actions/download-artifact@v4
with:
name: my-app-build-${{ needs.build.outputs.version }}
path: .
- name: Configure AWS credentials for staging
uses: aws-actions/configure-aws-credentials@v4
with:
aws-access-key-id: ${{ secrets.STAGING_AWS_ACCESS_KEY_ID }}
aws-secret-access-key: ${{ secrets.STAGING_AWS_SECRET_ACCESS_KEY }}
aws-region: ${{ env.AWS_REGION }}
- name: Deploy to Staging S3
run: aws s3 sync . s3://${{ secrets.STAGING_S3_BUCKET_NAME }} --delete
deploy_production:
runs-on: ubuntu-latest
needs: deploy_staging # ต้อง Deploy Staging สำเร็จก่อน
environment:
name: production # กำหนด Environment "production"
url: https://www.your-production-app.com # URL ที่จะแสดงใน UI
steps:
- name: Download build artifact
uses: actions/download-artifact@v4
with:
name: my-app-build-${{ needs.build.outputs.version }}
path: .
- name: Configure AWS credentials for production
uses: aws-actions/configure-aws-credentials@v4
with:
aws-access-key-id: ${{ secrets.PRODUCTION_AWS_ACCESS_KEY_ID }}
aws-secret-access-key: ${{ secrets.PRODUCTION_AWS_SECRET_ACCESS_KEY }}
aws-region: ${{ env.AWS_REGION }}
- name: Deploy to Production S3
run: aws s3 sync . s3://${{ secrets.PRODUCTION_S3_BUCKET_NAME }} --delete
คำอธิบาย:
workflow_dispatch: ทำให้คุณสามารถรัน Workflow นี้ด้วยตนเองจากแท็บ “Actions” ใน GitHub UI ซึ่งมีประโยชน์สำหรับการ Deploy ที่ต้องควบคุมด้วยตนเองoutputs: Jobbuildกำหนดoutputs.versionเพื่อส่งค่าเวอร์ชันของแอปพลิเคชันออกไปให้ Job อื่นๆ ใช้needs.build.outputs.version: Jobtest,deploy_staging,deploy_productionสามารถเข้าถึงค่าversionที่ส่งออกมาจาก Jobbuildได้deploy_stagingและdeploy_production: Job ทั้งสองนี้ผูกกับ Environments ที่แตกต่างกัน ซึ่งคุณจะสามารถตั้งค่า Protection Rules สำหรับแต่ละ Environment ได้ (เช่น Manual Approval สำหรับproduction)- Secrets สำหรับ Staging และ Production ควรแยกกันเพื่อเพิ่มความปลอดภัย
ตัวอย่างเหล่านี้เป็นเพียงจุดเริ่มต้นครับ คุณสามารถปรับแต่งและเพิ่มขั้นตอนต่างๆ ได้ตามความต้องการของโปรเจกต์และ Infrastructure ของคุณ เรียนรู้เพิ่มเติมเกี่ยวกับการตั้งค่า Secrets และ Environments
หัวข้อขั้นสูงและ Best Practices
เพื่อเพิ่มประสิทธิภาพและความน่าเชื่อถือให้กับ CI/CD Pipeline ของคุณ มีหลายเทคนิคและแนวปฏิบัติที่ดีที่คุณควรพิจารณาครับ
Matrix Builds (การทดสอบข้ามแพลตฟอร์ม/เวอร์ชัน)
Matrix Builds ช่วยให้คุณรัน Job เดิมซ้ำหลายครั้ง โดยใช้การตั้งค่าที่แตกต่างกัน (เช่น ระบบปฏิบัติการ, เวอร์ชันของภาษาโปรแกรม) ทำให้มั่นใจว่าโค้ดของคุณทำงานได้ดีในหลากหลายสภาพแวดล้อม
jobs:
test:
runs-on: ${{ matrix.os }} # ใช้ค่าจาก matrix สำหรับ runs-on
strategy:
matrix:
os: [ubuntu-latest, windows-latest] # ทดสอบบน Ubuntu และ Windows
node-version: [18.x, 20.x] # ทดสอบกับ Node.js สองเวอร์ชัน
steps:
- name: Setup Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v4
with:
node-version: ${{ matrix.node-version }}
# ... steps for install and test ...
Caching Dependencies (เร่งความเร็วการทำงาน)
การติดตั้ง Dependencies ซ้ำๆ ในทุกครั้งที่รัน Workflow อาจใช้เวลานาน GitHub Actions มี actions/cache Action ที่ช่วยให้คุณแคช Dependencies ที่ดาวน์โหลดมาแล้ว เพื่อลดเวลาการทำงานในครั้งถัดไป
steps:
- name: Cache Node modules
uses: actions/cache@v4
with:
path: ~/.npm # หรือ node_modules/ สำหรับบางกรณี
key: ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }} # Key สำหรับ cache
restore-keys: |
${{ runner.os }}-node-
- name: Install dependencies
run: npm ci
Artifacts (การส่งผ่านข้อมูลระหว่าง Jobs)
Artifacts คือไฟล์หรือโฟลเดอร์ที่คุณสร้างขึ้นใน Job หนึ่ง แล้วต้องการนำไปใช้ใน Job อื่นๆ หรือดาวน์โหลดไปตรวจสอบในภายหลัง ใช้ actions/upload-artifact และ actions/download-artifact
# Job 1: Build
- name: Upload build output
uses: actions/upload-artifact@v4
with:
name: my-app-dist
path: dist/
# Job 2: Deploy (หลังจาก Job 1)
- name: Download build output
uses: actions/download-artifact@v4
with:
name: my-app-dist
path: ./
Reusable Workflows (การนำ Workflow กลับมาใช้ซ้ำ)
หากคุณมี Workflow ที่มีขั้นตอนคล้ายกันในหลายๆ Repository หรือหลายๆ ส่วนของโปรเจกต์ คุณสามารถสร้าง Reusable Workflow เพื่อลดการเขียนโค้ดซ้ำและทำให้การบำรุงรักษาง่ายขึ้น
Workflow ที่ถูกเรียก (e.g., .github/workflows/build-and-test.yml):
name: Reusable Build and Test
on:
workflow_call: # กำหนดให้ Workflow นี้สามารถถูกเรียกได้
inputs:
node_version:
required: true
type: string
description: 'Node.js version to use'
outputs:
build_status:
description: 'Status of the build job'
value: ${{ jobs.build.outputs.status }}
jobs:
build:
runs-on: ubuntu-latest
outputs:
status: ${{ steps.build_step.outcome }}
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Setup Node.js ${{ inputs.node_version }}
uses: actions/setup-node@v4
with:
node-version: ${{ inputs.node_version }}
- name: Install and Build
id: build_step
run: |
npm ci
npm run build
# ... more steps ...
Workflow ที่เรียก (e.g., .github/workflows/main-pipeline.yml):
name: Main App CI/CD
on:
push:
branches: ["main"]
jobs:
call-build-test:
uses: ./.github/workflows/build-and-test.yml@main # เรียกใช้ Reusable Workflow
with:
node_version: '20'
secrets: inherit # ส่ง Secrets จาก Caller ไปยัง Reusable Workflow
outputs:
build_status: ${{ jobs.call-build-test.outputs.build_status }}
deploy:
runs-on: ubuntu-latest
needs: call-build-test
if: ${{ needs.call-build-test.outputs.build_status == 'success' }}
steps:
# ... deploy steps ...
Security Best Practices (ความปลอดภัยใน Pipeline)
- ใช้ Secrets อย่างระมัดระวัง: อย่า hardcode ข้อมูลที่ละเอียดอ่อนในไฟล์ Workflow ใช้ GitHub Secrets เสมอ
- จำกัดสิทธิ์ของ Access Tokens: ใช้ GitHub App Installation Token หรือ OIDC เพื่อขอสิทธิ์ชั่วคราวแทนการใช้ Personal Access Token (PAT) ที่มีสิทธิ์สูงเกินไป
- Least Privilege: ให้สิทธิ์การเข้าถึงทรัพยากร (เช่น AWS IAM Role) แก่ Runner หรือ Action เท่าที่จำเป็นเท่านั้น
- ตรวจสอบ Actions ภายนอก: ใช้ Actions จาก GitHub Marketplace ที่น่าเชื่อถือและตรวจสอบเวอร์ชัน (เช่น
@v4) เพื่อป้องกันการเปลี่ยนแปลงที่ไม่คาดคิด - Code Scanning: ผสานรวมเครื่องมือ Static Application Security Testing (SAST) เข้ากับ CI Pipeline เพื่อตรวจจับช่องโหว่ในโค้ด
- Branch Protection Rules: กำหนดให้ต้องมีการอนุมัติ Pull Request, ผ่าน CI Tests ก่อน Merge เข้า Branch สำคัญ (เช่น
main)
การตรวจสอบและแก้ไขปัญหา
เมื่อ Workflow เกิดข้อผิดพลาด การตรวจสอบและแก้ไขปัญหาเป็นสิ่งสำคัญ
- ดู Log ของ Workflow: GitHub Actions UI แสดง Log โดยละเอียดสำหรับแต่ละ Job และ Step ช่วยให้ระบุจุดที่เกิดปัญหาได้ง่าย
- เพิ่ม Debugging Steps: หากจำเป็น คุณสามารถเพิ่ม Steps ชั่วคราวเพื่อพิมพ์ค่าตัวแปรหรือสถานะต่างๆ ออกมาใน Log