Part 2: Intermediate

🦊 GitLab CI/CD Intermediate

เทคนิคระดับกลางสำหรับสร้าง Pipeline มืออาชีพ

30 นาที Intermediate 8 หัวข้อ

ในบทความ Part 1 เราได้เรียนรู้พื้นฐานของ GitLab CI/CD ตั้งแต่การสร้าง Pipeline, Stage, Job และการใช้ Docker Images มาถึง Part 2 นี้ เราจะเจาะลึกเทคนิคระดับกลางที่จะทำให้ Pipeline ของคุณทำงานได้ฉลาดขึ้น เร็วขึ้น และปลอดภัยขึ้น

💡 สิ่งที่คุณจะได้เรียนรู้
  • การใช้ Variables อย่างมีประสิทธิภาพ
  • Artifacts และ Cache ต่างกันอย่างไร
  • Rules และ Conditions สำหรับควบคุมการทำงาน
  • DAG Pipelines ด้วย needs
  • Matrix Jobs สำหรับทดสอบหลาย Version

1 Variables (ตัวแปร)

Variables เป็นหัวใจสำคัญของ CI/CD Pipeline ที่ยืดหยุ่น ช่วยให้เราสามารถเก็บข้อมูลที่เปลี่ยนแปลงได้ เช่น API Keys, Configuration Settings หรือค่าต่างๆ ที่ไม่อยากเขียนลงในโค้ดโดยตรง

🔤 Predefined Variables

GitLab มีตัวแปรที่กำหนดไว้ล่วงหน้ามากมายที่พร้อมใช้งาน:

ตัวอย่างการใช้ Predefined Variables YAML
job_show_vars: stage: test script: # ข้อมูล Commit - echo "Commit SHA = $CI_COMMIT_SHA" - echo "Short SHA = $CI_COMMIT_SHORT_SHA" - echo "Commit Message = $CI_COMMIT_MESSAGE" - echo "Commit Author = $CI_COMMIT_AUTHOR" # ข้อมูล Branch/Tag - echo "Branch = $CI_COMMIT_BRANCH" - echo "Tag = $CI_COMMIT_TAG" - echo "Ref Name = $CI_COMMIT_REF_NAME" # ข้อมูล Pipeline - echo "Pipeline ID = $CI_PIPELINE_ID" - echo "Pipeline URL = $CI_PIPELINE_URL" - echo "Pipeline Source = $CI_PIPELINE_SOURCE" # ข้อมูล Project - echo "Project ID = $CI_PROJECT_ID" - echo "Project Name = $CI_PROJECT_NAME" - echo "Project URL = $CI_PROJECT_URL" # ข้อมูล Runner - echo "Runner ID = $CI_RUNNER_ID" - echo "Runner Tags = $CI_RUNNER_TAGS" # ข้อมูล Environment - echo "Environment = $CI_ENVIRONMENT_NAME" - echo "Environment URL = $CI_ENVIRONMENT_URL"

📊 ตาราง Predefined Variables ที่ใช้บ่อย

Variable คำอธิบาย ตัวอย่างค่า
CI_COMMIT_SHA Commit hash เต็ม aa218c562a...
CI_COMMIT_SHORT_SHA Commit hash แบบสั้น (8 ตัว) aa218c56
CI_COMMIT_BRANCH ชื่อ Branch main, develop
CI_COMMIT_TAG ชื่อ Tag (ถ้ามี) v1.0.0
CI_PIPELINE_ID ID ของ Pipeline 123456
CI_PROJECT_NAME ชื่อ Project my-awesome-app
CI_REGISTRY URL ของ GitLab Registry registry.gitlab.com

⚙️ Custom Variables

เราสามารถสร้างตัวแปรเองได้ 3 ระดับ:

การกำหนด Custom Variables YAML
# 1. Variables ในไฟล์ .gitlab-ci.yml variables: APP_NAME: "my-application" DOCKER_REGISTRY: "registry.example.com" DEPLOY_ENV: "staging" BUILD_OPTS: "--production --no-source-maps" # 2. Variables ระดับ Job build_production: variables: DEPLOY_ENV: "production" NODE_ENV: "production" script: - echo "Building for $DEPLOY_ENV" - npm run build $BUILD_OPTS # 3. Variables แบบ Global (แทนที่ทุกที่) variables: GIT_STRATEGY: "fetch" GIT_DEPTH: "10"
💡 ลำดับความสำคัญของ Variables

เมื่อมีการกำหนดตัวแปรชื่อซ้ำกัน GitLab จะใช้ลำดับความสำคัญนี้ (จากสูงไปต่ำ):

  1. Trigger variables (จาก API trigger)
  2. Manual pipeline variables
  3. Scheduled pipeline variables
  4. Variables ใน .gitlab-ci.yml (ระดับ Job)
  5. Protected variables
  6. Group variables
  7. Project variables
  8. Variables ใน .gitlab-ci.yml (ระดับ Global)

🔒 Protected Variables

Protected Variables จะถูกส่งไปยัง Pipeline เฉพาะเมื่อรันบน Protected Branch (เช่น main, production) หรือ Protected Tag เท่านั้น

การตั้งค่า Protected Variables การตั้งค่า
# ตั้งค่าที่ Settings > CI/CD > Variables Variable: PRODUCTION_API_KEY Value: sk_live_xxxxxxxxxxxx Type: Variable Protect variable: ✓ เปิดใช้งาน Mask variable: ✓ เปิดใช้งาน # ผลลัพธ์: # - รันบน branch 'main' → ได้รับ PRODUCTION_API_KEY ✓ # - รันบน branch 'feature/xxx' → ไม่ได้รับ PRODUCTION_API_KEY ✗

🎭 Masked Variables

Masked Variables จะถูกซ่อนใน Logs เพื่อความปลอดภัย:

ตัวอย่าง Masked Variable ใน Logs Log
# ก่อน Mask $ echo $SECRET_API_KEY sk_live_abc123xyz789 # หลัง Mask $ echo $SECRET_API_KEY [MASKED] # ตัวอย่างการใช้งาน deploy_job: script: - echo "Deploying with API Key..." - curl -H "Authorization: Bearer $SECRET_API_KEY" https://api.example.com/deploy - echo "Deploy completed!" # Log Output: # $ echo "Deploying with API Key..." # Deploying with API Key... # $ curl -H "Authorization: Bearer $SECRET_API_KEY" https://api.example.com/deploy # [MASKED] ← Token ถูกซ่อน # {"status": "success"}
⚠️ ข้อจำกัดของ Masked Variables
  • ต้องมีความยาวอย่างน้อย 8 ตัวอักษร
  • ใช้ได้เฉพาะตัวอักษรที่ Base64 รองรับ (a-z, A-Z, 0-9, +, /, =, @, :, ., -, _)
  • จะไม่ถูก Mask ถ้าอยู่ใน Format อื่น เช่น JSON object

📁 File Variables

File Variables เก็บค่าเป็นไฟล์แทนที่จะเป็น String:

การใช้ File Variables YAML
# ตั้งค่าที่ Settings > CI/CD > Variables Variable: KUBE_CONFIG Type: File Value: (เนื้อหาไฟล์ kubeconfig) # การใช้งานใน Pipeline deploy_kubernetes: image: bitnami/kubectl:latest script: # File variable จะถูกสร้างเป็นไฟล์ชั่วคราว - export KUBECONFIG=$KUBE_CONFIG - kubectl get pods - kubectl apply -f deployment.yaml # ตัวอย่าง: SSH Key Variable: SSH_PRIVATE_KEY Type: File deploy_ssh: script: - mkdir -p ~/.ssh - cp $SSH_PRIVATE_KEY ~/.ssh/id_rsa - chmod 600 ~/.ssh/id_rsa - ssh user@server 'deploy.sh'

2 Artifacts (ผลลัพธ์)

Artifacts เป็นไฟล์หรือโฟลเดอร์ที่ถูกสร้างโดย Job หนึ่ง และสามารถส่งต่อให้ Job อื่นใช้งานได้ เหมาะสำหรับเก็บ Build outputs, Test reports, หรือไฟล์ที่ต้องการ download

📦 การสร้าง Artifacts

ตัวอย่างการใช้ Artifacts YAML
stages: - build - test - deploy build_app: stage: build image: node:20 script: - npm ci - npm run build artifacts: paths: - dist/ # เก็บโฟลเดอร์ dist - build/ # เก็บโฟลเดอร์ build exclude: - dist/**/*.map # ยกเว้นไฟล์ .map expire_in: 1 week when: always name: "build-$CI_COMMIT_SHORT_SHA" test_app: stage: test image: node:20 script: - npm ci - npm test artifacts: paths: - coverage/ - junit.xml reports: junit: junit.xml coverage_report: coverage_format: jacoco path: coverage/jacoco.xml expire_in: 30 days

📊 Artifacts Options

Option คำอธิบาย ตัวอย่าง
paths ไฟล์/โฟลเดอร์ที่จะเก็บ dist/, build/
exclude ไฟล์ที่จะยกเว้น *.map, *.log
expire_in ระยะเวลาเก็บ (ค่า default: 30 days) 1 week, 1 hour, never
when เก็บเมื่อไร on_success, on_failure, always
name ชื่อไฟล์ archive build-$CI_COMMIT_SHA

🔄 การใช้ Artifacts ข้าม Jobs

Build → Test → Deploy Pipeline YAML
build: stage: build script: - npm run build artifacts: paths: - dist/ expire_in: 1 week test: stage: test script: # dist/ จะถูก download มาอัตโนมัติ - ls -la dist/ - npm run test:e2e artifacts: paths: - test-results/ deploy: stage: deploy script: # dist/ จะยังคงอยู่ - rsync -avz dist/ server:/var/www/app/
💡 Artifacts ถูกส่งต่ออัตโนมัติ

Artifacts จะถูกส่งจาก Job หนึ่งไปยังทุก Jobs ใน Stages ถัดไปโดยอัตโนมัติ แต่ถ้าต้องการควบคุมว่าจะรับ artifacts จาก job ไหน ให้ใช้ dependencies หรือ needs:artifacts

3 Cache (แคช)

Cache ใช้สำหรับเก็บ dependencies ที่ใช้บ่อย เพื่อให้ Pipeline รันเร็วขึ้น เช่น node_modules, .m2/repository, pip cache

📊 Cache vs Artifacts: ต่างกันอย่างไร?
📦 Cache 🎯 เก็บ Dependencies ⚡ เร่งความเร็ว Pipeline 🔄 ใช้ซ้ำได้หลาย Pipelines 🗑️ อาจถูกลบได้ทุกเวลา node_modules/, .cache/ ~/.m2/repository/ 🎨 Artifacts 🏗️ เก็บ Build Outputs 📋 ส่งต่อระหว่าง Jobs 💾 ดาวน์โหลดได้จาก UI ⏰ กำหนด expire_in ได้ dist/, build/, target/ coverage/, test-results/

🔑 Cache Keys

Cache Key กำหนดว่าจะใช้ Cache ร่วมกันหรือแยกกัน:

Cache Key Strategies YAML
# 1. Cache เดียวกันทุก Branches cache: key: global-cache paths: - node_modules/ # 2. Cache แยกตาม Branch cache: key: ${CI_COMMIT_REF_SLUG} paths: - node_modules/ # 3. Cache ตามไฟล์ lock (แนะนำ!) cache: key: files: - package-lock.json - yarn.lock paths: - node_modules/ # 4. Cache แบบ prefix + lock file cache: key: prefix: ${CI_JOB_NAME} files: - composer.lock paths: - vendor/

📝 ตัวอย่าง: Cache node_modules และ pip packages

ตัวอย่างการใช้ Cache YAML
# Node.js Project .node_template: image: node:20 cache: key: files: - package-lock.json paths: - node_modules/ - .npm/ install: extends: .node_template stage: prepare script: - npm ci --cache .npm --prefer-offline test: extends: .node_template stage: test script: # node_modules มีอยู่แล้วจาก cache - npm test # Python Project .python_template: image: python:3.11 cache: key: files: - requirements.txt paths: - .cache/pip/ - venv/ before_script: - pip install --cache-dir .cache/pip -r requirements.txt pytest: extends: .python_template script: - pytest tests/

4 Rules และ Conditions

Rules ช่วยให้เราควบคุมได้ว่า Job ไหนจะรัน หรือไม่รัน ภายใต้เงื่อนไขใด ถือเป็นฟีเจอร์ที่ทรงพลังที่สุดอย่างหนึ่งใน GitLab CI/CD

🎯 rules:if - เงื่อนไข

การใช้ rules:if YAML
# รันเฉพาะ main branch deploy_production: stage: deploy rules: - if: $CI_COMMIT_BRANCH == "main" script: - ./deploy.sh production # รันเฉพาะ Tags release: stage: deploy rules: - if: $CI_COMMIT_TAG script: - ./release.sh # รันเฉพาะ Merge Requests code_review: stage: test rules: - if: $CI_PIPELINE_SOURCE == "merge_request_event" script: - npm run lint - npm run test:coverage # Multiple conditions deploy_staging: stage: deploy rules: - if: $CI_COMMIT_BRANCH == "develop" - if: $CI_COMMIT_BRANCH =~ /^release\// # release/* branches - if: $CI_COMMIT_BRANCH =~ /^feature\/.*/ && $RUN_STAGING == "true" script: - ./deploy.sh staging

📁 rules:changes - ตรวจจับไฟล์เปลี่ยน

การใช้ rules:changes YAML
# รันเฉพาะเมื่อมีการเปลี่ยนแปลงในโฟลเดอร์ src/ test_frontend: stage: test rules: - changes: - src/**/* - package.json - package-lock.json script: - npm test # รันเฉพาะเมื่อไฟล์ Terraform เปลี่ยน terraform_plan: stage: test rules: - changes: - terraform/**/*.tf script: - terraform plan # รันเฉพาะเมื่อ Dockerfile เปลี่ยน build_docker: stage: build rules: - changes: - Dockerfile - docker-compose*.yml script: - docker build -t myapp .

📋 rules:exists - ตรวจสอบไฟล์มีอยู่

การใช้ rules:exists YAML
# รันเฉพาะถ้ามี Dockerfile docker_build: rules: - exists: - Dockerfile script: - docker build -t $CI_REGISTRY_IMAGE . # รันเฉพาะถ้าเป็น Node.js project npm_test: rules: - exists: - package.json script: - npm test # รันเฉพาะถ้าเป็น Python project pytest: rules: - exists: - requirements.txt - setup.py script: - pytest

🔢 rules:variables - กำหนดตัวแปรตามเงื่อนไข

การใช้ rules:variables YAML
deploy: stage: deploy rules: - if: $CI_COMMIT_BRANCH == "main" variables: DEPLOY_ENV: "production" APP_URL: "https://app.example.com" - if: $CI_COMMIT_BRANCH == "develop" variables: DEPLOY_ENV: "staging" APP_URL: "https://staging.example.com" - if: $CI_COMMIT_BRANCH =~ /^feature\// variables: DEPLOY_ENV: "review" APP_URL: "https://$CI_COMMIT_REF_SLUG.example.com" when: manual script: - echo "Deploying to $DEPLOY_ENV" - echo "App URL: $APP_URL" - ./deploy.sh $DEPLOY_ENV
⚠️ only/except (Legacy)

only และ except เป็น syntax เก่าที่ GitLab ไม่แนะนำให้ใช้แล้ว ให้เปลี่ยนมาใช้ rules แทน ซึ่งยืดหยุ่นและทรงพลังกว่า:

# ❌ Legacy (ไม่แนะนำ)
job:
  only:
    - main
    - tags

# ✅ Modern (แนะนำ)
job:
  rules:
    - if: $CI_COMMIT_BRANCH == "main"
    - if: $CI_COMMIT_TAG

⚙️ Workflow Rules

Workflow rules ควบคุม Pipeline ทั้งหมดว่าจะสร้างหรือไม่:

การใช้ Workflow Rules YAML
# สร้าง Pipeline เฉพาะ main, develop และ MRs workflow: rules: - if: $CI_COMMIT_BRANCH == "main" - if: $CI_COMMIT_BRANCH == "develop" - if: $CI_MERGE_REQUEST_IID - if: $CI_COMMIT_TAG # ป้องกัน duplicate pipelines workflow: rules: - if: $CI_PIPELINE_SOURCE == "push" && $CI_COMMIT_BRANCH - if: $CI_PIPELINE_SOURCE == "merge_request_event" - if: $CI_COMMIT_TAG

5 Needs (DAG Pipelines)

needs ช่วยให้เราสร้าง Directed Acyclic Graph (DAG) Pipelines ได้ ทำให้ Jobs รันพร้อมกันได้โดยไม่ต้องรอ Stage ก่อนหน้า เร่งความเร็ว Pipeline ได้มาก

📊 DAG Pipeline vs Traditional Stage Pipeline
Traditional Stage Pipeline Stage: Build Stage: Test Stage: Security Stage: Deploy ⏱️ Total: ~10 นาที DAG Pipeline (needs) build test:unit test:e2e security lint deploy 🚀 Total: ~4 นาที (60% เร็วขึ้น!)

⚡ การใช้ needs

ตัวอย่าง DAG Pipeline YAML
stages: - build - test - security - deploy build: stage: build script: - npm run build artifacts: paths: - dist/ # ทั้ง 4 jobs นี้จะรันพร้อมกันหลัง build เสร็จ # ไม่ต้องรอ Stage test ทั้งหมด test_unit: stage: test needs: [build] script: - npm run test:unit test_e2e: stage: test needs: [build] script: - npm run test:e2e security_scan: stage: security needs: [build] script: - npm audit - trivy fs . lint: stage: test needs: [build] script: - npm run lint # Deploy รอทุก jobs ที่ needs deploy: stage: deploy needs: - build - test_unit - test_e2e - security_scan - lint script: - ./deploy.sh

📦 needs:artifacts

ควบคุมว่าจะรับ artifacts จาก job ไหน:

การใช้ needs:artifacts YAML
build_linux: stage: build script: - make build-linux artifacts: paths: - bin/linux/ build_windows: stage: build script: - make build-windows artifacts: paths: - bin/windows/ build_macos: stage: build script: - make build-macos artifacts: paths: - bin/macos/ # Release รับ artifacts จากทุก build jobs release: stage: deploy needs: - job: build_linux artifacts: true - job: build_windows artifacts: true - job: build_macos artifacts: true script: - ls -la bin/ - ./create-release.sh # Test ไม่ต้องการ artifacts จาก build unit_test: stage: test needs: - job: build_linux artifacts: false # เร็วขึ้นเพราะไม่ต้อง download script: - npm test

6 Environment Variables

📄 การสร้าง .env files

การสร้าง .env จาก Variables YAML
create_env_file: stage: prepare script: # สร้าง .env file จาก CI/CD Variables - | cat > .env << EOF NODE_ENV=${NODE_ENV} API_URL=${API_URL} DATABASE_URL=${DATABASE_URL} SECRET_KEY=${SECRET_KEY} EOF artifacts: paths: - .env deploy: stage: deploy needs: [create_env_file] script: # .env จะถูก download มาอัตโนมัติ - docker run --env-file .env myapp:latest

📝 dotenv Artifact

GitLab สามารถโหลด environment variables จากไฟล์ dotenv:

การใช้ dotenv Artifacts YAML
generate_env: stage: build script: # สร้างไฟล์ dotenv - echo "BUILD_VERSION=$(date +%Y%m%d)-$CI_COMMIT_SHORT_SHA" >> build.env - echo "BUILD_DATE=$(date -I)" >> build.env - echo "DEPLOY_URL=https://$CI_COMMIT_REF_SLUG.example.com" >> build.env artifacts: reports: dotenv: build.env deploy: stage: deploy needs: [generate_env] script: # Variables จาก build.env พร้อมใช้งาน - echo "Deploying version $BUILD_VERSION" - echo "Deploy URL: $DEPLOY_URL" - kubectl set image deployment/app app=myapp:$BUILD_VERSION

🔄 envsubst - แทนที่ Variables ในไฟล์

การใช้ envsubst YAML
# config.template.yaml apiVersion: v1 kind: ConfigMap metadata: name: app-config data: APP_NAME: "${APP_NAME}" ENVIRONMENT: "${DEPLOY_ENV}" VERSION: "${CI_COMMIT_SHORT_SHA}" # .gitlab-ci.yml deploy: variables: APP_NAME: "my-awesome-app" DEPLOY_ENV: "production" script: # แทนที่ $VAR ด้วยค่าจริง - envsubst < k8s/config.template.yaml > k8s/config.yaml - cat k8s/config.yaml # ดูผลลัพธ์ - kubectl apply -f k8s/config.yaml

7 Matrix Jobs

Matrix Jobs ช่วยให้เรารัน Job เดียวกันหลายครั้งด้วยตัวแปรต่างกัน เหมาะสำหรับ testing หลาย versions, browsers, หรือ platforms พร้อมกัน

🔢 parallel:matrix

Testing หลาย Node.js Versions YAML
test: image: node:${NODE_VERSION} parallel: matrix: - NODE_VERSION: ["16", "18", "20", "21"] script: - node --version - npm ci - npm test # ผลลัพธ์: 4 jobs รันพร้อมกัน # - test: [NODE_VERSION: 16] # - test: [NODE_VERSION: 18] # - test: [NODE_VERSION: 20] # - test: [NODE_VERSION: 21]

🎯 Multi-dimensional Matrix

Matrix หลายมิติ YAML
test_e2e: image: mcr.microsoft.com/playwright:${BROWSER}-${PW_VERSION} parallel: matrix: - BROWSER: ["chromium", "firefox", "webkit"] PW_VERSION: ["v1.40.0", "v1.41.0"] script: - npx playwright test --project=${BROWSER} # ผลลัพธ์: 3 x 2 = 6 jobs # [chromium, v1.40.0], [chromium, v1.41.0] # [firefox, v1.40.0], [firefox, v1.41.0] # [webkit, v1.40.0], [webkit, v1.41.0] # ตัวอย่าง: Build multi-architecture Docker images build_docker: image: docker:latest parallel: matrix: - ARCH: ["amd64", "arm64", "arm/v7"] script: - docker build --platform linux/${ARCH} -t myapp:${ARCH} . - docker push myapp:${ARCH}

📋 Matrix กับ Variables

การใช้ Matrix Variables YAML
deploy: stage: deploy parallel: matrix: - ENVIRONMENT: [staging, production] environment: name: ${ENVIRONMENT} url: https://${ENVIRONMENT}.example.com rules: - if: $ENVIRONMENT == "production" && $CI_COMMIT_BRANCH != "main" when: never # ไม่ deploy production จาก branch อื่น - when: on_success script: - echo "Deploying to ${ENVIRONMENT}" - kubectl apply -f k8s/${ENVIRONMENT}/

8 Trigger (Multi-project Pipelines)

trigger ช่วยให้เราเรียก Pipeline ใน project อื่นได้ เหมาะสำหรับ Microservices architecture หรือการแยก concerns ระหว่าง projects

🔗 การใช้ trigger

Multi-project Pipeline YAML
# ใน project หลัก (frontend) stages: - build - test - trigger_downstream build: stage: build script: - npm run build # Trigger pipeline ใน project อื่น trigger_backend: stage: trigger_downstream trigger: project: my-group/backend-api # project path branch: main strategy: depend # รอให้เสร็จก่อน # Trigger พร้อมส่ง variables trigger_deploy: stage: trigger_downstream trigger: project: my-group/deployment branch: main variables: FRONTEND_VERSION: ${CI_COMMIT_SHA} DEPLOY_ENV: "production"

🏗️ ตัวอย่าง: Microservices Pipeline

Orchestrator Pipeline สำหรับ Microservices YAML
# ใน orchestrator project stages: - build - test - integration - deploy # Build ทุก services build_services: stage: build parallel: matrix: - SERVICE: [auth, user, order, payment, notification] trigger: project: my-group/${SERVICE}-service branch: ${CI_COMMIT_REF_NAME} strategy: depend # Integration tests integration_test: stage: integration needs: [build_services] trigger: project: my-group/integration-tests strategy: depend # Deploy ทุก services deploy_all: stage: deploy needs: [integration_test] trigger: project: my-group/deployment branch: main variables: DEPLOY_VERSION: ${CI_COMMIT_SHA} DEPLOY_ALL: "true"

📊 Trigger Strategies

Strategy คำอธิบาย Use Case
depend รอให้ downstream pipeline เสร็จ และสถานะตามไปด้วย ต้องการให้ pipeline นี้ fail ถ้า downstream fail
ไม่ระบุ Trigger แล้วไปเลย ไม่รอผล Fire-and-forget downstream tasks

📝 สรุป

📦 สิ่งที่ควรใช้ Cache

  • Dependencies (node_modules, vendor)
  • Build caches (.cache, .npm)
  • ไฟล์ที่ใช้ซ้ำบ่อย
  • ไม่สำคัญถ้าหาย

🎨 สิ่งที่ควรใช้ Artifacts

  • Build outputs (dist, build)
  • Test reports, coverage
  • ไฟล์ที่ต้อง download
  • สำคัญต้องเก็บไว้
🎯 Key Takeaways
  • Variables: ใช้ Protected + Masked สำหรับ secrets
  • Artifacts: เก็บ outputs, กำหนด expire_in
  • Cache: เก็บ dependencies, ใช้ key ตาม lock file
  • Rules: ควบคุม job execution อย่างยืดหยุ่น
  • Needs: สร้าง DAG pipeline เร่งความเร็ว
  • Matrix: รันหลาย versions/platforms พร้อมกัน
  • Trigger: เชื่อมโยง pipelines ระหว่าง projects