使用可重複使用的工作流程來處理環境之間的相似處

已完成

當您將變更部署到多個環境時,部署到每個環境所涉及的步驟都很類似,或甚至相同。 在此單元中,您將了解如何設計工作流程以避免重複,並讓工作流程的程式碼可重複使用。

部署到多個環境

與網站小組的同事談過之後,您決定將下列工作流程用在您玩具公司的網站上:

此圖顯示一連串工作流程作業,並包括測試和實際執行環境部署。

  1. 工作流程會執行 Bicep Linter,來檢查 Bicep 程式碼是否有效且遵循最佳做法。

    對 Bicep 程式碼執行 Lint 分析不需要連線至 Azure,因此部署至多少個環境無所謂。 它只會執行一次。

  2. 工作流程會部署到測試環境,並要求:

    1. 執行 Azure Resource Manager 預檢驗證。
    2. 部署 Bicep 程式碼。
    3. 對測試環境執行一些測試。
  3. 如果工作流程的任何部分失敗,則整個工作流程就會停止,以方便您調查並解決問題。 但若一切順利,工作流程就會繼續部署到實際執行環境:

    1. 工作流程包含一個預覽步驟,其會在實際執行環境上執行假設狀況作業,以列出將對您生產 Azure 資源所做的變更。 假設狀況作業也會驗證部署,因此不需要對實際執行環境另外執行驗證步驟。
    2. 工作流程會暫停,以進行手動驗證。
    3. 如果獲准,工作流程就會對實際執行環境執行部署和煙霧測試。

這其中一些工作會在測試與實際執行環境之間重複,而有些僅會針對特定環境執行:

Task 環境
Lint 兩者皆否 - 不會對環境執行 Lint 分析
Validate 僅測試
預覽 僅生產
部署 這兩個環境
煙霧測試 這兩個環境

若您必須在工作流程中重複步驟,複製再貼上步驟定義不是很好的做法。 當您複製工作流程的程式碼時,一不小心就會發生難以察覺的錯誤,或造成不同步的情況。 日後需要變更步驟時,您必須想起在很多地方套用變更。 較佳的做法是利用可重複使用的工作流程。

可重複使用的工作流程

GitHub Actions 讓您能夠透過建立可定義步驟或作業的個別工作流程 YAML 檔案,來建立可重複使用的工作流程定義區段。 您可以建立 YAML 檔案,以便在單一工作流程內,甚至在多個工作流程中,多次重複使用工作流程的各個部分。 您重複使用的工作流程是「已呼叫的工作流程」,而包含該工作流程的工作流程為「呼叫者工作流程」。 以概念來看,您可以將它們視為類似於 Bicep 模組。

當您建立可重複使用的工作流程時,可以使用 workflow_call 觸發程序來告訴 GitHub Actions,可透過其他工作流程呼叫該工作流程。 以下是可重複使用工作流程的基本範例,其儲存於名為 script.yml 的檔案中:

on:
  workflow_call:

jobs:
  say-hello:
    runs-on: ubuntu-latest
    steps:
    - run: |
        echo Hello world!

在呼叫者工作流程中,您可以透過包含 uses: 關鍵字並指定已在目前存放庫中呼叫的工作流程路徑,來參考已呼叫的工作流程:

on: 
  workflow_dispatch:

jobs:
  job:
    uses: ./.github/workflows/script.yml

您也可以參考另一個存放庫中的工作流程定義檔。

已呼叫的工作流程輸入和祕密

您可以使用「輸入」和「祕密」,讓您的已呼叫工作流程更容易重複使用,因為您可以在使用它們時允許工作流程中的微小差異。

當您建立已呼叫的工作流程時,可以在檔案頂端註明其輸入和祕密:

on:
  workflow_call:
    inputs:
      environmentType:
        required: true
        type: string
    secrets:
      AZURE_CLIENT_ID:
        required: true
      AZURE_TENANT_ID:
        required: true
      AZURE_SUBSCRIPTION_ID:
        required: true

您可以視需要定義任意多個的輸入和祕密。 但就像 Bicep 參數一樣,盡量不要過度使用工作流程輸入。 您應該讓其他人不需指定太多設定,就能輕鬆地重複使用您的工作流程。

輸入可以有數個屬性,包括:

  • 輸入「名稱」,您用來表示工作流程定義中的輸入。
  • 輸入「類型」。 輸入支援「字串」、「數字」和「布林值」的值。
  • 輸入的「預設值」,這是選用的。 如果您未指定預設值,則必須在呼叫者工作流程中使用工作流程時提供值。

祕密具有名稱,但沒有類型或預設值。

在範例中,工作流程會定義名為 environmentType 的強制字串輸入,以及三個名為 AZURE_CLIENT_IDAZURE_TENANT_IDAZURE_SUBSCRIPTION_ID 的強制祕密。

在您的工作流程中,使用了特殊語法來參考參數的值,如下列範例所示:

jobs:
  say-hello:
    runs-on: ubuntu-latest
    steps:
    - run: |
        echo Hello ${{ inputs.environmentType }}!

您使用 with 關鍵字,將輸入的值傳入已呼叫的工作流程。 您必須定義 with 區段中每個輸入的值,您無法使用 env 關鍵字來參考工作流程的環境變數。 您使用 secrets 關鍵字,將祕密值傳入已呼叫的工作流程。

on: 
  workflow_dispatch:

permissions:
  id-token: write
  contents: read

jobs:
  job-test:
    uses: ./.github/workflows/script.yml
    with:
      environmentType: Test
    secrets:
      AZURE_CLIENT_ID: ${{ secrets.AZURE_CLIENT_ID_TEST }}
      AZURE_TENANT_ID: ${{ secrets.AZURE_TENANT_ID }}
      AZURE_SUBSCRIPTION_ID: ${{ secrets.AZURE_SUBSCRIPTION_ID }}

  job-production:
    uses: ./.github/workflows/script.yml
    with:
      environmentType: Production
    secrets:
      AZURE_CLIENT_ID: ${{ secrets.AZURE_CLIENT_ID_PRODUCTION }}
      AZURE_TENANT_ID: ${{ secrets.AZURE_TENANT_ID }}
      AZURE_SUBSCRIPTION_ID: ${{ secrets.AZURE_SUBSCRIPTION_ID }}

使用來自已呼叫工作流程的工作負載身分識別

當您使用已呼叫的工作流程時,通常會在多個工作流程定義檔案之間定義一些部署動作。 您必須將權限授與呼叫者工作流程,然後確保每個已呼叫的工作流程都能存取工作流程的身分識別,並向 Azure 進行驗證:

on: 
  workflow_dispatch:

permissions:
  id-token: write
  contents: read

jobs:
  job-test:
    uses: ./.github/workflows/script.yml
    with:
      environmentType: Test
    secrets:
      AZURE_CLIENT_ID: ${{ secrets.AZURE_CLIENT_ID_TEST }}
      AZURE_TENANT_ID: ${{ secrets.AZURE_TENANT_ID }}
      AZURE_SUBSCRIPTION_ID: ${{ secrets.AZURE_SUBSCRIPTION_ID }}

  job-production:
    uses: ./.github/workflows/script.yml
    with:
      environmentType: Production
    secrets:
      AZURE_CLIENT_ID: ${{ secrets.AZURE_CLIENT_ID_PRODUCTION }}
      AZURE_TENANT_ID: ${{ secrets.AZURE_TENANT_ID }}
      AZURE_SUBSCRIPTION_ID: ${{ secrets.AZURE_SUBSCRIPTION_ID }}

條件

您可以使用工作流程「條件」,來指定步驟或作業是否應根據您指定的規則來執行。 您可以合併輸入和工作流程條件來自訂部署流程,以因應多種情況。

例如,假設您定義了一個用於執行指令碼步驟的工作流程。 您打算對每個環境重複使用範本。 當您部署實際執行環境時,您希望執行另一個步驟。 以下是可對步驟使用 if 條件來達成該目標的方式:

jobs:
  say-hello:
    runs-on: ubuntu-latest
    steps:
    - run: |
        echo Hello ${{ inputs.environmentType }}!

    - run: |
        echo This step only runs for production deployments.
      if: inputs.environmentType == 'Production'

此處的條件可翻譯為:「如果 environmentType 參數的值等於 'Production',則執行步驟」

雖然條件可以增加工作流程的彈性,但太多條件可能會使工作流程複雜化而難以理解。 如果您在所謂的工作流程中有許多條件,您可能會想要重新設計工作流程。

此外,請使用 YAML 註解說明您使用的條件,以及工作流程中可能需要進一步說明的其他任何層面。 註解有助於讓工作流程變得更加簡單易懂,日後更易於使用。 在這整個課程模組的練習中,提供了一些 YAML 註解範例。