CI/CD 十關

LV.4/10

Variables

分清楚內建、全域、job、專案變數的優先順序,並用 dotenv 在 job 之間傳值

基礎約 20 分鐘variables、預定義變數、dotenv、Masked

學習目標

  • 會用 GitLab 內建的 CI_* 變數。
  • 會定義全域變數與 job 變數,知道誰會覆寫誰。
  • 知道密碼與權杖要放在專案設定,不能寫進 repo。
  • 會用 artifacts:reports:dotenv 把一個 job 算出的值交給下一個 job。

觀念:優先順序(高 → 低)

順序來源例子
1手動執行或觸發時帶入的變數「Run pipeline」表單
2專案/群組設定的變數Settings → CI/CD → Variables
3dotenv 報告傳進來的變數本關的 BUILD_VERSION
4job 裡的 variablescustom 的 GREETING: 午安
5全域 variablesGREETING: 早安
6內建變數CI_COMMIT_SHORT_SHA

常用內建變數

變數內容
CI_COMMIT_SHORT_SHAcommit 前 8 碼,常拿來當映像標籤(Lv.10 就是這樣)
CI_COMMIT_REF_NAME/CI_COMMIT_REF_SLUG分支或標籤名稱;slug 是轉成可當網址或資源名稱的版本
CI_COMMIT_BRANCH分支名稱;標籤 pipeline 沒有這個變數
CI_DEFAULT_BRANCH預設分支,通常是 main
CI_PIPELINE_SOURCEpush、web、schedule、merge_request_event、parent_pipeline……
CI_PIPELINE_IID專案內的 pipeline 流水號

機密要怎麼放

  1. 「Settings → CI/CD → Variables」新增變數。
  2. 勾 Masked:紀錄裡會顯示成 [MASKED]。
  3. 勾 Protected:只有受保護分支(例如 main)拿得到,從分支或 MR 偷印出來也拿不到。
  4. 憑證檔用 File 類型,變數內容會是一個暫存檔的路徑。

不要用 echo $TOKEN 測試機密有沒有設好,改用 test -n "$TOKEN"。

動手做

  1. 在「Build → Pipelines → Run pipeline」看到 GREETING 與 DEPLOY_TARGET 兩個欄位,改值後執行。
  2. 在專案設定新增 TUTORIAL_GREETING(一般變數,不是機密),重跑後 custom 會印出它。
  3. 看 use-version 的紀錄,版本號是 make-version 算出來的。

常見錯誤

  • 在 variables 裡用 $(date):不會執行,只會當成字串。要算的值請在 script 裡算,再用 dotenv 傳。
  • 變數值是 yes、on、08:YAML 可能誤判型別,加上引號最保險。

下一關

Lv.5 用 cache 讓安裝套件不用每次重新下載。

範例檔案

資料夾 lv04-variables/ 的全部檔案。.gitlab-ci.yml 可以直接複製到自己的專案根目錄執行。

lv04-variables/.gitlab-ci.yml
lv04-variables/.gitlab-ci.yml
# Lv.4 Variables:內建變數、自訂變數、覆寫順序,以及在 job 之間傳值(dotenv)
# 密碼、權杖不要寫在這裡:一律放「Settings → CI/CD → Variables」,並勾選 Masked、Protected。

stages:
  - info
  - build
  - use

default:
  image: alpine:3.22

# 全域變數:每個 job 都拿得到
variables:
  COURSE_NAME: "GitLab CI/CD 十關"
  LESSON: "Lv.4"
  FULL_TITLE: "$COURSE_NAME - $LESSON"   # 變數可以引用其他變數
  # 有 description 的全域變數,會出現在「手動執行 pipeline」的表單裡
  GREETING:
    value: "早安"
    description: "手動執行 pipeline 時可以改成別的招呼語"
  DEPLOY_TARGET:
    value: "staging"
    options: ["staging", "production"]
    description: "手動執行時只能從這兩個選一個"

predefined:
  stage: info
  script:
    - echo "專案:$CI_PROJECT_PATH"
    - echo "分支:$CI_COMMIT_REF_NAME(slug:$CI_COMMIT_REF_SLUG)"
    - echo "commit:$CI_COMMIT_SHORT_SHA"
    - echo "觸發來源:$CI_PIPELINE_SOURCE"
    - echo "預設分支:$CI_DEFAULT_BRANCH"
    - echo "job 編號:$CI_JOB_ID"

custom:
  stage: info
  # job 變數會覆寫同名的全域變數
  variables:
    GREETING: "午安"
  script:
    - echo "$FULL_TITLE"
    - echo "招呼語:$GREETING(job 覆寫了全域的「早安」)"
    - echo "部署目標:$DEPLOY_TARGET"
    # 專案變數在「Settings → CI/CD → Variables」設定;沒設時用預設值
    - echo "專案變數:${TUTORIAL_GREETING:-尚未設定 TUTORIAL_GREETING}"

make-version:
  stage: build
  script:
    - echo "BUILD_VERSION=1.4.$CI_PIPELINE_IID" > build.env
    - echo "BUILD_TIME=$(date -u +%Y-%m-%dT%H:%M:%SZ)" >> build.env
    - cat build.env
  artifacts:
    reports:
      dotenv: build.env   # 後面的 job 會自動拿到這兩個變數

use-version:
  stage: use
  needs: [make-version]
  script:
    - test -n "$BUILD_VERSION"
    - echo "上一個 job 算出的版本:$BUILD_VERSION,時間:$BUILD_TIME"