GH-200 數位教科書 開啟互動版

D1 模擬題:撰寫與管理工作流程

D1「撰寫與管理工作流程」17 題原創模擬題,附正確答案、解析與常見陷阱。選項順序在互動版會隨機排列。

第 1 題(D1-O1)

你在功能分支新增了一個每 15 分鐘執行的 schedule 工作流程,數小時後都沒有任何執行。最可能的原因是什麼?

單選題,選項:

  • 排程只讀預設分支的檔案,這個檔案還在功能分支
  • 排程的最短間隔是 30 分鐘,所以 15 分鐘的設定被略過
  • 排程要等第一次 push 到該分支後,才會開始計時
  • 排程要等公開 repository 滿 60 天之後才會啟用
看答案與解析

正確答案:排程只讀預設分支的檔案,這個檔案還在功能分支

解析:schedule 只在預設分支的最新 commit 上執行,功能分支上的檔案不會被排程觸發;官方的最短間隔是每 5 分鐘一次,所以 15 分鐘本身有效。

常見陷阱:看到「沒有執行」就檢查 cron 語法是最常見的反應;要先確認檔案所在的分支,因為 schedule、workflow_dispatch 這類事件只讀預設分支的檔案。

依據:Events that trigger workflows

在互動版作答這題

第 2 題(D1-O1)

由 schedule 事件觸發的執行,GITHUB_SHA 與 GITHUB_REF 分別是什麼?

單選題,選項:

  • 最近一次被推送的 commit,與被推送的 ref
  • 預設分支的最後一個 commit,與預設分支
  • 最近一次合併的 PR 合併 commit,與其合併 ref
  • 功能分支上最新的 commit,與該功能分支
看答案與解析

正確答案:預設分支的最後一個 commit,與預設分支

解析:schedule 的 GITHUB_SHA 是預設分支的最後一個 commit,GITHUB_REF 是預設分支;workflow_run 也是同樣的結果。

常見陷阱:pull_request 測的是合併後的結果,push 是被推送的尖端 commit;schedule 與 workflow_run 永遠回到預設分支,所以不會測到尚未合併的修改。

依據:Events that trigger workflows

在互動版作答這題

第 3 題(D1-O1)

由 pull_request 事件觸發的執行,GITHUB_SHA 是該 PR 分支尖端的最後一個 commit。

是非題:判斷敘述是否正確。

看答案與解析

正確答案:錯誤

解析:pull_request 的 GITHUB_SHA 是 PR 合併 ref(refs/pull/編號/merge)上的最後一個合併 commit,測試跑的是合併後的結果。

常見陷阱:PR 分支的尖端 commit 看起來最自然,所以很容易照直覺答「是」;事件拿到的其實是合併 ref,這也是 PR 測試能提早發現衝突的原因。

依據:Events that trigger workflows

在互動版作答這題

第 4 題(D1-O1)

workflow_dispatch 有一個 boolean 類型的 input dry_run,工作流程條件寫 if: github.event.inputs.dry_run == false,結果永遠不成立。應該怎麼修?

單選題,選項:

  • 把 input 改成 choice 型別,讓值以字串比較
  • 在 on 區塊替 input 補上預設值 false
  • 改用 inputs.dry_run,因為它保留 boolean 型別
  • 把條件改成 github.event.inputs.dry_run == 0
看答案與解析

正確答案:改用 inputs.dry_run,因為它保留 boolean 型別

解析:github.event.inputs 會把 boolean 轉成字串,'false' == false 不成立;inputs context 保留 boolean 型別,可以直接當條件。

常見陷阱:補上預設值只決定沒有輸入時的值,不會改變 github.event.inputs 把值轉成字串的行為;改成字串型別則會讓問題更明顯,而不是消除它。

依據:Events that trigger workflows、Workflow syntax

在互動版作答這題

第 5 題(D1-O1)

關於 workflow_dispatch 的 inputs 限制,下列哪些正確?(選 2 項)

複選題,選項:

  • 最多可以定義 25 個頂層 input
  • 最多可以定義 10 個頂層 input
  • inputs 的資料量不能超過 65,535 個字元
  • inputs 的資料量不能超過 1 MiB
看答案與解析

正確答案:最多可以定義 25 個頂層 input;inputs 的資料量不能超過 65,535 個字元

解析:官方的上限是最多 25 個頂層屬性、資料量不超過 65,535 個字元;型別除了 string 還有 boolean、choice、number、environment。

常見陷阱:25 個與 65,535 個字元是官方的上限,另外兩個數字是常被記混的其他限制;型別除了 string 還有 boolean、choice、number、environment。

依據:Events that trigger workflows、Workflow syntax

在互動版作答這題

第 6 題(D1-O1)

工作流程用 GITHUB_TOKEN 推送了一個 commit,預期它會觸發另一個 on: push 的工作流程,卻沒有任何新的執行。下列哪一組事件是這個規則的例外,仍會建立執行?

單選題,選項:

  • workflow_dispatch 與 workflow_call
  • repository_dispatch 與 workflow_run
  • workflow_dispatch 與 repository_dispatch
  • pull_request 與 workflow_dispatch
看答案與解析

正確答案:workflow_dispatch 與 repository_dispatch

解析:由 GITHUB_TOKEN 引發的事件通常不會建立新的工作流程執行,目的是避免遞迴;例外是 workflow_dispatch 與 repository_dispatch。

常見陷阱:需要鏈式觸發時,很容易以為換成另一種 repository 事件就行;實際上要改用這兩個例外事件,或改用 GitHub App 安裝權杖或 PAT 來推送。

依據:Events that trigger workflows、GITHUB_TOKEN (concepts)

在互動版作答這題

第 7 題(D1-O2)

矩陣設定 os: [ubuntu-latest, windows-latest]、version: [16, 18];exclude 一組 {os: windows-latest, version: 16};include 一組 {os: macos-latest, version: 20}。總共會產生幾個 job?

單選題,選項:

  • 3 個
  • 4 個
  • 5 個
  • 6 個
看答案與解析

正確答案:4 個

解析:原本 2×2 共 4 組,exclude 移除 1 組剩 3 組;include 的 macOS 組合與任何既有組合都衝突,無法併入,成為獨立的新組合,所以共 4 個。

常見陷阱:include 不是無條件加在每個組合上;它的 os 值不在原本的清單裡,會與既有組合衝突而另成一組,因此只增加 1 個,而不是把 4 組都擴充。

依據:Running variations of jobs

在互動版作答這題

第 8 題(D1-O2)

job 設了 container: node:20 並宣告 services: postgres,測試程式用 localhost:5432 連不上資料庫。應該怎麼改?

單選題,選項:

  • 在 services 補上 ports: 5432:5432,繼續連 localhost
  • 改連 postgres:5432,用服務標籤當主機名稱
  • 改連 127.0.0.1:5432,並在 container 加上網路設定
  • 改用 service 開頭的 context 取得主機名稱再連線
看答案與解析

正確答案:改連 postgres:5432,用服務標籤當主機名稱

解析:job 跑在容器內時,服務的主機名稱會對應到標籤,不需要設定 ports;只有 job 直接跑在 runner 上時才用 localhost 加 ports 對應。

常見陷阱:ports 對應只在 job 直接跑在 runner 上才需要;job 在容器內時,補上 ports 並不會讓 localhost 變成服務的位址,而且服務容器只支援 Linux。

依據:Use Docker service containers

在互動版作答這題

第 9 題(D1-O2)

步驟 lint 失敗,但設了 continue-on-error: true。後面的步驟寫 if: steps.lint.conclusion == 'failure',它會執行嗎?

單選題,選項:

  • 會執行,因為 conclusion 反映步驟實際的失敗結果
  • 會執行,因為 continue-on-error 只影響整個 job 的結果
  • 不會執行,因為 conclusion 要等 job 結束後才有值
  • 不會執行,因為 conclusion 是套用 continue-on-error 之後的結果
看答案與解析

正確答案:不會執行,因為 conclusion 是套用 continue-on-error 之後的結果

解析:outcome 是套用 continue-on-error 之前的結果,conclusion 是之後的結果;這個步驟 outcome 是 failure、conclusion 是 success,所以條件不成立。

常見陷阱:兩個欄位名稱很像,常被互換;要偵測「步驟其實失敗過」該讀 outcome,而 conclusion 讀到的是被容許後的結果。

依據:Contexts

在互動版作答這題

第 10 題(D1-O2)

下列哪些 context 可以用在 jobs.<job_id>.if?(選 3 項)

複選題,選項:

  • github(工作流程與事件資訊)
  • needs(相依 job 的輸出與結果)
  • secrets(儲存的加密機密)
  • vars(組織或 repository 的變數)
看答案與解析

正確答案:github(工作流程與事件資訊);needs(相依 job 的輸出與結果);vars(組織或 repository 的變數)

解析:jobs.<job_id>.if 可用的 context 有 github、needs、vars、inputs,不含 secrets 與 env。

常見陷阱:步驟層級的 if 又多了 env、steps 等 context,容易把兩處混為一談;但 secrets 在兩個 if 都不能直接使用,要先放進環境變數再判斷。

依據:Contexts

在互動版作答這題

第 11 題(D1-O2)

job deploy 設了 needs: test,而 test 失敗了。要讓 deploy 無論 test 的結果都會執行,應該怎麼做?

單選題,選項:

  • 在 test 的矩陣設定 fail-fast: false
  • 在 deploy 的 if 裡使用 always()
  • 在 deploy 加上 continue-on-error: true
  • 把 deploy 的 needs 改成 needs.test.result
看答案與解析

正確答案:在 deploy 的 if 裡使用 always()

解析:被需要的 job 失敗或被略過時,依賴它的 job 也會被略過;在 job 的 if 使用 always(),就會無論相依 job 的結果如何都執行。

常見陷阱:fail-fast 只管矩陣內部的取消行為,與 job 之間的相依無關;移除 needs 則會讓兩個 job 平行執行,不再有先後關係。

依據:Workflow syntax

在互動版作答這題

第 12 題(D1-O2)

矩陣啟用了 fail-fast,其中一個 continue-on-error 為 false 的組合失敗了。其他組合會怎樣?

單選題,選項:

  • 所有進行中與排隊中的 job 都會被取消
  • 只有進行中的 job 被取消,排隊中的繼續執行
  • 只有使用同一種作業系統的組合會被取消
  • 全部繼續執行,整體在最後才標成失敗
看答案與解析

正確答案:所有進行中與排隊中的 job 都會被取消

解析:fail-fast 啟用時,只要一個 continue-on-error: false 的 job 失敗,所有進行中與排隊的 job 都會被取消。

常見陷阱:取消的範圍是整個矩陣,不分作業系統或版本;想讓實驗性組合失敗而不連累其他組合,要用 continue-on-error 而不是調整 fail-fast。

依據:Running variations of jobs

在互動版作答這題

第 13 題(D1-O3)

快取還原時,沒有找到與 key 完全相同的項目。接下來依什麼順序比對?

單選題,選項:

  • 先比對 restore-keys,再比對 key 的前綴
  • 先比對 key 的前綴,再依序比對 restore-keys
  • 只比對與 key 完全相同的項目,找不到就不還原
  • 先比對預設分支,再比對目前分支的 key
看答案與解析

正確答案:先比對 key 的前綴,再依序比對 restore-keys

解析:查找順序是:與 key 完全相同、key 的前綴、restore-keys 依列出順序;同一個 restore key 符合多個項目時,使用最近建立的。

常見陷阱:restore-keys 是備援而不是優先;若把順序顛倒,就會誤判快取命中的來源,並且錯估為什麼拿到的是舊內容。

依據:Dependency caching

在互動版作答這題

第 14 題(D1-O3)

步驟 build 執行 echo "version=1.2" >> "$GITHUB_ENV",同一個步驟接著 echo $version,卻是空的。原因是什麼?

單選題,選項:

  • 寫入的值只對之後的步驟可見,寫入當下看不到
  • 值要在同一步驟用 ${{ env.version }} 讀取才有效
  • 步驟必須先設定 id,之後的步驟才讀得到
  • 寫入的值會等到下一個 job 才開始生效
看答案與解析

正確答案:寫入的值只對之後的步驟可見,寫入當下看不到

解析:寫入 GITHUB_ENV 的環境變數,之後的所有步驟都看得到,但寫入的那一步看不到;要在同一步驟使用,就直接用 shell 變數。

常見陷阱:需要 id 的是 GITHUB_OUTPUT(用 steps.<id>.outputs 讀取),不是 GITHUB_ENV;兩者的用法容易混淆,但生效時間點並不是整個 job 結束之後。

依據:Workflow commands

在互動版作答這題

第 15 題(D1-O3)

在 upload-artifact v4,同一次執行中用同樣的名稱再上傳一次,可以更新先前那個成品的內容。

是非題:判斷敘述是否正確。

看答案與解析

正確答案:錯誤

解析:v4 的成品是不可變的;要保存新的內容,應該替每個階段使用新的成品名稱,而不是用同名成品當作更新。

常見陷阱:從檔案系統的角度看,「覆寫同一個檔名」很直覺;成品是不可變的,這個直覺在 v4 並不成立。

依據:Store and share data

在互動版作答這題

第 16 題(D1-O3)

某個步驟寫入 $GITHUB_STEP_SUMMARY 的內容超過 1 MiB。會發生什麼事?

單選題,選項:

  • 整個 job 被標成失敗,之後的步驟被取消
  • 摘要被截斷到 1 MiB,只顯示最前面的部分
  • 摘要改以成品形式保存,並附上下載連結
  • 該步驟的摘要上傳失敗並產生錯誤註解,狀態不變
看答案與解析

正確答案:該步驟的摘要上傳失敗並產生錯誤註解,狀態不變

解析:每個步驟的摘要上限是 1 MiB;超過時該步驟的摘要上傳失敗並建立錯誤註解,但不會改變步驟或 job 的狀態。

常見陷阱:超限會有錯誤註解,容易被誤認為 job 失敗;實際上它不會改變狀態,也不會自動截斷,所以重要的測試摘要要自己控制大小。

依據:Workflow commands

在互動版作答這題

第 17 題(D1-O3)

在一般分支上執行的工作流程,可以還原哪些分支的快取?(選 2 項)

複選題,選項:

  • 目前這次執行所在的分支
  • 同一個 repository 的兄弟分支
  • 該 repository 的預設分支
  • 從目前分支切出去的子分支
看答案與解析

正確答案:目前這次執行所在的分支;該 repository 的預設分支

解析:一次執行可以還原目前分支與預設分支的快取;PR 的執行還可以還原基底分支的快取。兄弟分支與子分支的快取都拿不到。

常見陷阱:把「同一個 repository 的快取共用」想成全部共用是常見的誤解;實際上分支之間有隔離,只有目前分支、預設分支與(PR 的)基底分支可以存取。

依據:Dependency caching

在互動版作答這題