Skip to content
CodeSook
CodeSook

15. Environments, Variables and Secrets


GitHub Actions Variables และ Secrets

Environment variables จะแบ่งเป็น 2 ส่วน

  1. กำหนดไว้ใน Workflow level คือเขียนไว้ใน Workflow file ตรงๆเลย
  2. กำหนดไว้ที่ 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 }}

ความแตกต่าง

ประเภทระดับความลับการเข้าถึง
envWorkflow$VARIABLE
RepositoryVariables Repository${{ vars.NAME }}
RepositorySecrets Repository${{ secrets.NAME }}
EnvironmentVariables Environment${{ vars.NAME }}
EnvironmentSecrets 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
echo.yaml
name: Echo Vars and Secrets
on:
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 Prod
on:
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 แล้วรอดูในเว็ป