15. Environments, Variables and Secrets
GitHub Actions Variables และ Secrets
Environment variables จะแบ่งเป็น 2 ส่วน
- กำหนดไว้ใน Workflow level คือเขียนไว้ใน Workflow file ตรงๆเลย
- กำหนดไว้ที่ Repository level บน Github ตรงนี้ยังแบ่งเป็น 2 ส่วนย่อยอีก 2.1 Variables เอาไว้เก็บค่าที่เปิดเผยได้ ให้ใครๆดูก็ได้ เช่น URL ของ Public services 2.2 Secrets เอาไว้เก็บค่าที่เปิดเผยไม่ได้ เช่นๆ API Keys ต่างๆ
ในส่วนของ Repository level ยังมีความซับซ้อนขึ้นไปอีก ถ้าเราใช้ร่วมกับระบบ Github actions Environments
Github actions Environments จะใช้ได้กับทุกๆ Public Repository เลย แต่ถ้าเป็น Private Repository จะต้องใช้ Githb Pro ขึ้นไปนะ คือต้อง Subscription อะนะ
เราสามารถแบ่ง Variables กับ Secrets ออกเป็นชุดต่างๆได้ หรือก็คือเป็นการแยก Environments นั่นเอง
ยกตัวอย่างเช่น
เรามี Server สำหรับ Testing เราก็อาจจะมี Secrets สำหรับ Database, API-Keys ต่างๆ ที่ต้องใช้ในการ Testing เวลา Github actions ทำงานมันก็จะไปดึงเอา Variables และ Secrents ของ Testing Environtment มาใช้
ถ้าเรามี Server สำหรับ Production เราก็อาจจะมี Secrets, Variables สำหรับ Server Productions เวลา Github actions ทำงานก็จะใช้ Variables และ Secrets ของ Environment Production มาใช้
ทำให้เราเอา Workflow มาใช้ซ้ำได้ maintain ง่าย, tracing issue ได้ง่ายขึ้น
graph TB subgraph repo ["🏠 GitHub Repository"] subgraph repoLevel ["Repository Level"] rv["📋 Repository Variables vars.API_URL"] rs["🔐 Repository Secrets secrets.DOCKER_PASSWORD"] end subgraph prod ["🚀 Environment: Production"] pv["📋 Prod Variables vars.PROD_DB_URL"] ps["🔐 Prod Secrets secrets.PROD_API_KEY"] end subgraph staging ["🧪 Environment: Staging"] sv["📋 Staging Variables vars.STAGING_DB_URL"] ss["🔐 Staging Secrets secrets.STAGING_API_KEY"] end end subgraph workflow ["📄 Workflow File"] wf["⚙️ Workflow Env NODE_VERSION: '18'"] end subgraph runner ["🏃 GitHub Actions Runner"] step1["Step 1: Build"] step2["Step 2: Deploy Prod"] step3["Step 3: Deploy Staging"] end rv --> step1 rs --> step1 wf --> step1 pv --> step2 ps --> step2 sv --> step3 ss --> step3 %% Catppuccin Mocha Color Classes classDef repoVar fill:#a6e3a1,stroke:#40a02b,stroke-width:2px,color:#11111b classDef repoSecret fill:#f38ba8,stroke:#d20f39,stroke-width:2px,color:#11111b classDef envVar fill:#89b4fa,stroke:#1e66f5,stroke-width:2px,color:#11111b classDef envSecret fill:#cba6f7,stroke:#8839ef,stroke-width:2px,color:#11111b classDef workflowVar fill:#f9e2af,stroke:#df8e1d,stroke-width:2px,color:#11111b classDef execution fill:#fab387,stroke:#fe640b,stroke-width:2px,color:#11111b %% Apply Classes class rv repoVar class rs repoSecret class pv,sv envVar class ps,ss envSecret class wf workflowVar class step1,step2,step3 execution
GitHub Actions Variables และ Secrets
Environment Variables (env)
ตัวแปรที่กำหนดใน workflow file โดยตรง
env: BUN_VERSION: '1.2.18' BUILD_ENV: 'production'
jobs: build: runs-on: ubuntu-latest steps: - name: Use env variable run: echo "Bun version: $BUN_VERSION"
Repository Variables
ตัวแปรที่เก็บไว้ใน repository settings (ไม่เป็นความลับ) เราต้องไป set ใน Github repository นะ


jobs: deploy: runs-on: ubuntu-latest steps: - name: Use repo variable run: echo "API URL: ${{ vars.API_URL }}"
Repository Secrets
ข้อมูลลับที่เก็บไว้ใน repository settings


jobs: deploy: runs-on: ubuntu-latest steps: - name: Deploy with secret run: | docker login -u ${{ secrets.DOCKER_USERNAME }} -p ${{ secrets.DOCKER_PASSWORD }}
Environment Variables (Environment-specific)
ตัวแปรที่กำหนดสำหรับ environment เฉพาะ
ก่อนจะใช้ Environment Variables and Secrets ได้ เราจะต้องสร้าง Environment ขึ้นมาก่อน
ไปที่เว็ป Github



เราสามารถใส่ Variables และ Secrets ที่หน้า Environments ได้เลย

Environment Variables
jobs: deploy: runs-on: ubuntu-latest environment: production steps: - name: Use env variable run: echo "Database: ${{ vars.DATABASE_URL }}"
Environment Secrets
ข้อมูลลับที่กำหนดสำหรับ environment เฉพาะ
jobs: deploy: runs-on: ubuntu-latest environment: production steps: - name: Deploy to prod run: | kubectl apply -f deployment.yaml env: KUBE_TOKEN: ${{ secrets.PROD_KUBE_TOKEN }}
ความแตกต่าง
ประเภท | ระดับ | ความลับ | การเข้าถึง |
---|---|---|---|
env | Workflow | ❌ | $VARIABLE |
Repository | Variables Repository | ❌ | ${{ vars.NAME }} |
Repository | Secrets Repository | ✅ | ${{ secrets.NAME }} |
Environment | Variables Environment | ❌ | ${{ vars.NAME }} |
Environment | Secrets Environment | ✅ | ${{ secrets.NAME }} |
ตัวอย่างการใช้งานรวม
name: Deploy App
env: NODE_VERSION: "18" # workflow-level
on: push: branches: [main]
jobs: deploy: runs-on: ubuntu-latest environment: production
steps: - uses: actions/checkout@v4
- name: Setup Node uses: actions/setup-node@v5 with: node-version: ${{ env.NODE_VERSION }}
- name: Build run: npm run build env: API_URL: ${{ vars.API_URL }} # repository variable
- name: Deploy run: | echo "Deploying to: ${{ vars.DEPLOY_URL }}" # environment variable deploy.sh env: DEPLOY_KEY: ${{ secrets.DEPLOY_KEY }} # environment secret DB_PASSWORD: ${{ secrets.DB_PASSWORD }} # repository secret
มาทดลองใส่ Variables กับ Secrets กัน
ส่วนของ Variables ก็ลองใส่แค่ Bun version ก่อน

ส่วนของ Secrets ก็ทดลองใส่ API_KEY แบบหลอกๆไปก่อน

แล้วก็สร้าง Workflow อันใหม่
workflows/echo.yaml
name: Echo Vars and Secretson: workflow_dispatch:jobs: echo-vars: runs-on: ubuntu-latest env: API_KEY: ${{ secrets.API_KEY }} BUN_VERSION: ${{ vars.BUN_VERSION }}
steps: - name: Echo Variables run: echo "$BUN_VERSION" - name: Echo Secrets run: echo "$API_KEY"
ลอง push code แล้วเปิดดูที่หน้าเว็ป

จะเห็นว่าส่วนของ Secrets จะเปิดดูไม่ได้ มันทำงานได้แหละ แต่เราไม่รู้ว่ามันมีค่าเป็นอะไร เพราะมันเป็น Secret ไงละ 🤣🤣🤣
มาลองใช้ Environments Vars and Secrets กัน
เริ่มที่สร้าง Environment กันก่อน

จากนั้นก็เพิ่ม Secrets แบบนี้


จากนั้นก็เพิ่ม Variables แบบนี้


แล้วเราจะเขียน workflow เพิ่มอีกอัน
workflows/echo-env.yaml
name: Echo Vars and Secrets from Dev and Prodon: workflow_dispatch:jobs: echo-dev: environment: "Development" runs-on: ubuntu-latest env: API_URL: ${{ vars.API_URL }} POSTGRES_URL: ${{ secrets.POSTGRES_URL }}
steps: - name: Echo Variables run: echo "API_URL:\ $API_URL" - name: Echo Secrets run: echo "POSTGRES_URL:\ $POSTGRES_URL"
echo-prod: environment: "Production" runs-on: ubuntu-latest env: API_URL: ${{ vars.API_URL }} POSTGRES_URL: ${{ secrets.POSTGRES_URL }}
steps: - name: Echo Variables run: echo "API_URL:\ $API_URL" - name: Echo Secrets run: echo "POSTGRES_URL:\ $POSTGRES_URL"
ลอง push code แล้วรอดูในเว็ป

