再利用可能なワークフローを使用して、環境間の類似に対応する

完了

変更を複数の環境にデプロイする場合、各環境へのデプロイに関連するステップは、似ているか、まったく同じです。 このユニットでは、繰り返しを回避し、ワークフロー コードを再利用するために、ワークフローを設計する方法について学習します。

複数の環境へのデプロイ

Web サイト チームの同僚と話し合ってから、あなたは玩具会社の Web サイトで次のワークフローを使用することに決めました。

Diagram that shows a series of workflow jobs and includes test and production deployments.

  1. ワークフローでは、Bicep リンターを実行して、Bicep コードが有効でベスト プラクティスに従っていることをチェックします。

    リンティングは、Azure に接続せずに Bicep コードに対して実行できるため、いくつの環境にデプロイしようとしているかに関わらず、 一度だけ実行されます。

  2. ワークフローはテスト環境にデプロイされ、次のものが必要です。

    1. Azure Resource Manager プレフライト検証の実行。
    2. Bicep コードのデプロイ。
    3. テスト環境に対する、いくつかのテストの実行。
  3. ワークフローの一部が失敗すると、問題を調査して解決できるようにワークフロー全体が停止します。 すべてが成功した場合、ワークフローでは運用環境へのデプロイが継続されます。

    1. ワークフローにはプレビュー ステージが含まれます。このステージでは、運用環境に対して What-If 操作を実行し、運用環境用の Azure リソースに対して行われる変更を一覧表示します。 What-If 操作ではデプロイの検証も行われるため、運用環境に対して別の検証ステップを実行する必要はありません。
    2. ワークフローは手動検証のために一時停止します。
    3. 承認が得られたら、ワークフローでは運用環境に対してデプロイとスモーク テストを実行します。

これらのタスクには、テスト環境と運用環境で繰り返されるものや、特定の環境に対してのみ実行されるものがあります。

タスク 環境
リント どちらでもない - リンティングは、環境に対して動作しません
検証 テスト環境のみ
プレビュー 運用環境のみ
デプロイ 両方の環境
スモーク テスト 両方の環境

ワークフロー内でステップを繰り返す必要がある場合、ステップの定義をコピーして貼り付けることもできます。 ただし、あまり良い方法ではありません。 わずかな間違いが入り込むおそれがあり、また、ワークフローのコードを複製するときに一部が同期されなくなってしまうこともありえます。 また、将来ステップを変更する必要が生じたときに、変更を複数の場所に適用しなければならなくなります。

再利用可能なワークフロー

GitHub Actions を使用すると、ステップまたはジョブを定義する別個のワークフロー YAML ファイルを作成することにより、ワークフロー定義の再利用可能なセクションを作成できます。 YAML ファイルを作成して、1 つのワークフロー内または複数のワークフロー内でワークフローの一部を複数回再利用できます。 再利用するワークフローは "呼び出し対象のワークフロー" で、それを含むワークフローは "呼び出し元のワークフロー" です。 概念的には、これらは 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 という名前の 3 つの必須シークレットを定義しています。

ワークフローでは、次の例のように、特殊な構文を使用してパラメーターの値を参照します。

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 }}

呼び出されたワークフローのワークロード ID を使用する

呼び出されたワークフローを使用する際、多くの場合、複数のワークフロー定義ファイルにデプロイ アクションの一部を定義します。 呼び出し元ワークフローにアクセス許可を付与する必要があります。これにより、呼び出されたすべてのワークフローがワークフローの 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 コメントの例があります。