操作手冊

發一版、看結果、憑證過期、換 build 機

操作手冊

給要發版、或要換 build 機的人看。名詞先講清楚:

  • pipeline:GitLab 上一次完整的自動化執行,由好幾個 job(工作)組成。
  • runner:真正去執行 job 的那台機器上的程式。我們的 runner 裝在 188(192.168.50.188)。
  • artifacts:job 跑完後留在 GitLab 上、可以從網頁下載的檔案。
  • SBOM:軟體物料清單,產品用了哪些套件與版本的「成分表」,給客戶資安稽核用。
§1

發一版

發之前先確認:要發的 commit 已經 push 到 GitLab 的 main。CI 只會拿 GitLab 上有的 commit 來做。

方法一:GitLab 網頁

  1. 打開 BE 專案(compliance-manager-be)的 GitLab 頁面
  2. 左側選單 Build → Pipelines
  3. 右上角 Run pipeline
  4. Branch 選 main
  5. environment 選 e2e
  6. skip_be 依需要勾選(見下方)
  7. 按 Run pipeline

按下去就會部署到 e2e,沒有第二道確認。

方法二:命令列

glab ci run -b main -i environment:e2e -i skip_be:true

要重新編譯 BE 就把 skip_be:true 改成 skip_be:false(或整個 -i skip_be:... 拿掉,預設是不跳過)。glab 要先登入過,見下方「本機 git 設定」。

skip_be 什麼時候勾

這次改了什麼 勾不勾
有改 BE 程式、BE 依賴(pyproject.toml/poetry.lock)、或 BE 版號剛 bump 不勾,要重新編譯
只改 FE、init(migration/seed)、或證據分類服務 可以勾,省掉 BE 編譯的 17 分鐘

勾了之後,BE 會沿用 188 上同版號最新那顆 image。如果這個版號在 188 上從沒編過 BE,build-be 會直接失敗,這時取消勾選重跑即可。

§2

看結果

Pipelines 頁

Build → Pipelines 會列出每一次執行。點進去看到四段(verify/build/package/deploy),每個 job 一個圓圈:綠勾=成功、紅叉=失敗、藍色轉圈=執行中、灰色=因前面失敗沒跑到。全程約 30 分鐘(勾 skip_be 約 15 分鐘)。

deploy 綠了就代表 190 已經升到新版,可以打開 https://192.168.50.190 驗。

SBOM 在哪

點進 verify 或 package job,右側 Job artifacts 區塊按 Browse 或 Download,在 out/sbom/ 底下:

  • *.cdx.json:SBOM 本體(CycloneDX 格式)
  • osv-*.txt:OS 層漏洞報告,只供參考,不會擋發版

artifacts 保留 30 天。安裝包裡的 sbom/ 目錄也有一份同樣的 SBOM。

安裝包在哪、怎麼給客戶

安裝包不在 GitLab 上(約 2.5GB,超過 GitLab 上限),留在 188:

/opt/guidant-ai-be/.build/bundle/guidant-ai-<版號>.tar.gz
/opt/guidant-ai-be/.build/bundle/guidant-ai-<版號>.tar.gz.sha256

package job 的 log 最後一行也會印出這個路徑。要給客戶時,兩個檔一起拿走:

scp jedi@192.168.50.188:/opt/guidant-ai-be/.build/bundle/guidant-ai-<版號>.tar.gz* ./

⚠️ CI 封的是測試包(跳過正式簽章金鑰檢查)。要交給客戶的正式包,請在 188 上另外跑一次不帶 --skip-prod-key-check 的 build_bundle.sh。

⚠️ 同版號每發一次就覆蓋一次。要保留某一包,發下一次之前先複製走。

Harbor 上的 image

位置:harbor.jedicogy.com.tw:8081 的 guidant-ai 專案。tag 長這樣:

guidant-ai-be:1.23.1-a1b2c3d       ← 版號-commit 短 hash
guidant-ai-fe:1.23.1-a1b2c3d
guidant-ai-init:1.23.1-a1b2c3d
evidence-classifier:<分類服務套件版號>   ← 跟自己的套件版號走,不帶 hash

看 hash 就知道是哪一個 commit 打出來的。

§3

失敗了怎麼看

第一步一律是:點那個紅叉的 job,看 log 最後幾十行。腳本失敗時都會印一行 ❌ 開頭的白話原因。

紅在哪 常見原因 怎麼處理
verify ① 相依套件有漏洞(log 有 pip-audit 結果)② 188 的工作樹不乾淨(log 列出哪些檔)③ 188 上有人正在手跑 build ① 升級套件,或確認無害後寫進 scripts/build/audit_ignore.txt(每行要附理由)② 到 188 /opt/guidant-ai-be 看是誰留的改動,處理掉再重跑——CI 不會自動清 ③ 等手跑那條跑完
build-be Nuitka 編譯失敗、smoke 驗證失敗 下載 job artifacts 的 out/logs/,或直接到 188 看 /opt/guidant-ai-be/.build/logs/
build-fe/init/classifier 個別 image 打不起來 看 job log
package 磁碟滿、封包失敗、推 Harbor 失敗 看 job log;推 Harbor 失敗先確認 188 的 Harbor 登入還有效
deploy 安裝包傳輸壞掉、升級失敗、服務沒有全部 healthy 到 190 看升級紀錄:/srv/guidant-ai/log/upgrade-*.log(最新那支);sudo guidantai status 看哪個服務不正常

修好之後重新 Run pipeline 即可;不需要清任何東西。

§4

本機 git 設定

要 push 程式到 GitLab、用 glab 發 pipeline,本機要有兩組各自獨立的登入。

git push 的憑證過期

macOS 會把 GitLab 的登入存在 Keychain(鑰匙圈),憑證到期後的症狀:

  1. git push 回 HTTP Basic: Access denied
  2. 之後 Keychain 會自動把那筆清掉,再 push 就變成 could not read Username

兩個都是同一件事:憑證過期,要開一組新的 PAT。

開 Personal Access Token(PAT)

PAT(個人存取權杖)是拿來代替密碼給 git 用的一組字串。

  1. 打開 https://gitlab.com/-/user_settings/personal_access_tokens
  2. 按 Add new token
  3. 類型選 Legacy token(一組就涵蓋你能存取的所有 repo)
  4. 名稱填 mac-git-push
  5. 到期日設最長(一年)
  6. scopes 勾 read_repository 與 write_repository
  7. 按建立。畫面會顯示一串 glpat- 開頭的字串,只會顯示這一次,先複製起來

這串字串等同密碼:不要貼進任何檔案、文件、聊天訊息或 Notion。

存回 Keychain

在終端機跑一次:

git push origin main

會問兩個問題:

  • Username:填你的 GitLab 帳號
  • Password:貼剛剛複製的 glpat- 字串(畫面不會顯示任何字,貼上直接按 Enter)

push 成功,Keychain 就會自動記住,之後不會再問,直到一年後再次到期。

glab 登入

glab 是 GitLab 的官方命令列工具。登入後 Claude 才能用 glab ci run 幫你發 pipeline。

glab auth login

依序選:

  1. GitLab instance:gitlab.com
  2. 登入方式:Web(會開瀏覽器授權)
  3. git 操作協定:HTTPS

glab 的登入和 git push 的憑證是分開的兩件事:一個過期不影響另一個。git push 失敗照上面重開 PAT;glab 失敗就重跑 glab auth login。

推 tag

git push 預設不會把 tag 一起推上去。定版打完 tag 後要另外推:

git push origin v<X.Y.Z>
§5

換 build 機/重裝 runner

照 scripts/build/README.md 末尾「188 runner 怎麼裝的」那張表逐項做,該表是 canonical。重點順序:

  1. 裝 gitlab-runner(官方 apt repo)

  2. 讓服務以 jedi 使用者跑:gitlab-runner install --user jedi --working-directory /home/jedi/gitlab-runner。poetry、Nuitka、docker 群組、.venv 全在 jedi 底下,預設的 gitlab-runner 帳號什麼都沒有

  3. 註冊:到 GitLab group(auditmanager)的 Runners 頁建一個 runner,取得 glrt- 開頭的註冊 token,然後:

    gitlab-runner register --non-interactive --url https://gitlab.com --token <glrt-...> --executor shell

    名稱 188-guidantai-build、tag guidantai-build、不接沒有 tag 的 job

  4. 改並行數:/etc/gitlab-runner/config.toml 的 concurrent 設 3,build 段的 job 才會平行

  5. 移除 /home/jedi/.bash_logout:不移除的話每個 job 都會在準備環境階段就紅(原因見 design.md「踩過的坑」)

  6. 裝掃描工具:syft、osv-scanner 放 /usr/local/bin(只能從 GitHub release 下載,188 下載很慢要耐心等)

  7. 登入 Harbor:用 jedi 跑 docker login harbor.jedicogy.com.tw:8081(帳密向管理者索取,不寫進任何檔案)

  8. /etc/hosts 加一行:192.168.50.171 harbor.jedicogy.com.tw

  9. 到 190 的免密 ssh:jedi 能免密碼 ssh jedi@192.168.50.190

  10. 190 的 jedi 要免密 sudo:190 的 sudoers 給 jedi 設 NOPASSWD: ALL,deploy_e2e.sh 要用它跑 install.sh --upgrade

  11. 工作樹:/opt/guidant-ai-be(含 .venv、Prompt Guard 模型、.env)與 /opt/guidant-ai-fe 都要就位,路徑和 .gitlab-ci.yml 頂部的 REPO_ROOT/FE_REPO 一致

裝完先手動 Run 一次 pipeline、勾 skip_be 跑通,再跑一次不勾的完整版。

§6

GitLab 專案層要有的設定

  • group runner 已註冊:runner 註冊在 auditmanager group,BE 專案才看得到。到 BE 專案 Settings → CI/CD → Runners 確認有綠燈的 188-guidantai-build。
  • FE 專案允許 BE 的 job token:FE 專案 Settings → CI/CD → Job token permissions 已加 compliance-manager-be。目前 CI 讀的是 188 上的 FE 本地 clone、不經這個權限,屬於備用設定,換機器不必動它。
  • Cloudflare Pages 的 external 失敗與 CI 無關:GitLab 的 commit 旁有時會出現一個名為 external 的紅叉,那是文件站的 Cloudflare Pages 專案回報的狀態,不是我們的 pipeline。該專案已關閉自動部署,可以忽略。