ข้ามไปยังเนื้อหา

CI กับ GitHub Actions

ถ้าคุณเคยตั้ง CI สำหรับ TypeScript project มาก่อน คุณเข้าใจโครงสร้างอยู่แล้ว: checkout code, ตั้ง language runtime, ติดตั้ง dependencies, รัน checks ฝั่ง Go แทบเหมือนกันเลย — แถมง่ายขึ้นในหลายจุดที่น่าพอใจ

สร้าง .github/workflows/ci.yml ใน repository ของคุณ:

name: Go CI
on:
push:
branches: [main, dev]
pull_request:
branches: [main, dev]
jobs:
test:
name: Test & Lint
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Set up Go
uses: actions/setup-go@v5
with:
go-version: "1.22"
cache: true # cache module download cache
- name: Download dependencies
run: go mod download
- name: Verify dependencies
run: go mod verify
- name: Run go vet
run: go vet ./...
- name: Run golangci-lint
uses: golangci/golangci-lint-action@v6
with:
version: latest
- name: Run tests
run: go test -race -coverprofile=coverage.out -covermode=atomic ./...
- name: Upload coverage report
uses: codecov/codecov-action@v4
with:
file: coverage.out
fail_ci_if_error: false
build:
name: Build Binary
runs-on: ubuntu-latest
needs: test
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Set up Go
uses: actions/setup-go@v5
with:
go-version: "1.22"
cache: true
- name: Build
run: CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -ldflags="-s -w" -o bin/app ./cmd/app
- name: Upload binary artifact
uses: actions/upload-artifact@v4
with:
name: app-linux-amd64
path: bin/app

flags สำคัญใน test step:

  • -race เปิด Go race detector — จับ data races ใน concurrent code ด้วย runtime cost ~2–20x (ยอมรับได้ใน CI)
  • -coverprofile=coverage.out เขียน coverage data สำหรับอัปโหลด
  • -covermode=atomic จำเป็นสำหรับ coverage ที่แม่นยำเมื่อใช้ -race
name: Node CI
on:
push:
branches: [main, dev]
pull_request:
branches: [main, dev]
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Set up Node
uses: actions/setup-node@v4
with:
node-version: "20"
cache: "npm"
- name: Install dependencies
run: npm ci
- name: Type-check
run: npx tsc --noEmit
- name: Lint
run: npx eslint src --ext .ts
- name: Test
run: npx jest --coverage
build:
runs-on: ubuntu-latest
needs: test
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: "20"
cache: "npm"
- run: npm ci --omit=dev
- run: npm run build
TypeScript
# Node CI: ต้องการ setup-node + npm ci
# Type-check: tsc --noEmit (step แยก)
# Lint: ESLint (step แยก + config file)
# Test: Jest (step แยก + config)
# Build: tsc/webpack output เป็นไฟล์ JS
steps:
- uses: actions/setup-node@v4
with:
node-version: "20"
cache: "npm"
- run: npm ci
- run: npx tsc --noEmit
- run: npx eslint src --ext .ts
- run: npx jest --coverage
- run: npm run build
Go
# Go CI: ต้องการ setup-go + go mod download
# Type-check: อยู่ใน go build/vet แล้ว
# Lint: go vet + golangci-lint-action
# Test: go test -race (built-in)
# Build: single static binary
steps:
- uses: actions/setup-go@v5
with:
go-version: "1.22"
cache: true
- run: go mod download
- run: go vet ./...
- uses: golangci/golangci-lint-action@v6
- run: go test -race -coverprofile=coverage.out ./...
- run: CGO_ENABLED=0 GOOS=linux go build -o bin/app ./cmd/app

เซฟไฟล์นี้เป็น .github/workflows/ci.yml ใน repository ของคุณ Push ขึ้น branch แล้วดูที่ Actions tab — ไม่ต้องตั้งค่าอะไรในเครื่องเพื่อยืนยัน workflow

Terminal window
# รัน tests ทั้งหมดพร้อม race detector
go test -race ./...
# รันพร้อม coverage และเขียนลงไฟล์
go test -race -coverprofile=coverage.out -covermode=atomic ./...
# แสดง coverage summary ใน stdout
go tool cover -func=coverage.out
# Fail ถ้า coverage ต่ำกว่า threshold (มีประโยชน์ใน CI)
go test ./... && go tool cover -func=coverage.out | tail -1 | awk '{if ($3+0 < 80) exit 1}'
# รันเฉพาะ tests ที่ตรงกับ pattern
go test ./... -run TestUser
# รัน tests พร้อม verbose output
go test -v ./...
flag `go test` ไหนเปิด concurrent race detector?
`go mod verify` ตรวจสอบอะไรใน CI pipeline?
ใน Go CI workflow ทำไมจึงใช้ `-covermode=atomic` ควบคู่กับ `-race`?
GitHub Action ไหนตั้งค่า Go toolchain ใน CI?