目的
本記事ではGithub Actionsのワークフロー学習のため取り組んだ内容を、備忘録的に記事にします。
初心者の私が実際に作ってみること、動かしてみること、そして公式ドキュメントを参考にワークフローの構文を1つずつ理解していくことを目的に取り組みました。
スペシャルサンクス
ワークフローの内容は、下記2つの記事を参考にさせていただきました。
大変勉強になりました、ありがとうございます!
実行環境
$ terraform providers -version
Terraform v1.10.4
on linux_amd64
+ provider registry.terraform.io/hashicorp/google v6.16.0
+ provider registry.terraform.io/hashicorp/google-beta v6.16.0
Cloud Runのコンテナイメージをデプロイする
まずはGoogle Cloudで利用頻度が高いであろうCloud Runとの連携です。
早速構築したワークフローをみていきます。
on:
トリガー
on:
push:
branches:
- "master"
on を使用してワークフローを実行する原因となるイベントを定義します
今回の例では、次の条件でワークフローが実行されます。
- master ブランチにコードが直接プッシュ/mergeされた場合
env:
環境変数の設定
env:
GCP_REGION: ${{ secrets.GCP_REGION_PRD }}
IMAGE: ${{ secrets.GCP_REGION_PRD }}-docker.pkg.dev/${{ secrets.GCP_PROJECT_ID_PRD }}/${{ secrets.REPO_NAME }}/hello_cloudrun:${{ github.sha }}
GOOGLE_IAM_WORKLOAD_IDENTITY_POOL_PROVIDER: ${{ secrets.GOOGLE_IAM_WORKLOAD_IDENTITY_POOL_PROVIDER }}
SERVICE_ACCOUNT_EMAIL: ${{ secrets.SERVICE_ACCOUNT_EMAIL }}
単一のワークフローにカスタム環境変数を設定するには、ワークフローファイル内の env キーを使用して環境変数を定義できます。
- ワークフロー全体 (ワークフロー ファイルの最上位レベルで env を使用)
ここでは、上記の通り、ワークフロー全体で利用可能な環境変数をenv
ブロックで定義しています。
また、※secrets
を事前に定義しておき環境変数の値に利用しています。
※シークレットは、組織、リポジトリ、またはリポジトリ環境内に作成する変数です。
jobs
ブロック
jobs:
build:
runs-on: ubuntu-latest
permissions:
contents: 'read'
id-token: 'write'
jobs.<job_id>.runs-on
jobs.<job_id>.runs-on
を使って、ジョブを実行するマシンの種類を定義します。
ここではubuntu OSの最新バージョンを指定しています。
jobs.<job_id>.permissions
jobs.<job_id>.permissions
を使用して GITHUB_TOKEN に付与された既定のアクセス許可を変更し、必要に応じてアクセスを追加または削除することで、必要最小限のアクセスのみを許可することができます。
-
contents: 'read'
により、リポジトリの内容への読み取り権限が付与されています。 -
id-token: 'write'
により、GitHub Actionsがこの権限を持つことで、トークンを使った認証を可能にし、Google CloudがGitHub Actionsに対して必要なリソースへのアクセスを許可します。
steps
ブロック
steps:
- name: Checkout the repository
uses: actions/checkout@v3
- id: "auth"
uses: "google-github-actions/auth@v2"
with:
workload_identity_provider: "${{ env.GOOGLE_IAM_WORKLOAD_IDENTITY_POOL_PROVIDER }}"
service_account: "${{ env.SERVICE_ACCOUNT_EMAIL }}"
- name: Set up Cloud SDK
uses: google-github-actions/setup-gcloud@v2
- name: Authorize Docker push
run: gcloud auth configure-docker ${{ secrets.GCP_REGION_PRD }}-docker.pkg.dev
- name: Build a docker image
run: docker build -t ${{ env.IMAGE }} -f Dockerfile .
- name: Push the docker image
run: docker push ${{ env.IMAGE }}
- name: Deploy to Cloud Run
id: deploy
uses: google-github-actions/deploy-cloudrun@v0
with:
service: XXX
image: ${{ env.IMAGE }}
region: ${{ env.GCP_REGION }}
jobs.<job_id>.steps[*]
1 つのジョブには、steps と呼ばれる一連のタスクがあります。 ステップでは、コマンドを実行する、設定タスクを実行する、あるいはリポジトリやパブリックリポジトリ、Dockerレジストリで公開されたアクションを実行することができます。
-
jobs.<job_id>.steps[*].id
- 後続のステップでidを指定することで、当該コンテキストを参照可能となります。
-
jobs.<job_id>.steps[*].name
- GitHubで表示されるステップの名前を定義しています。
-
jobs.<job_id>.steps[*].uses
- アクションを定義しています。アクションとは再利用可能なコードの単位で、公開されているアクション、カスタムアクション、または Docker イメージをステップ内で利用することができます。
- ここでは GitHub ActionのGoogle Cloudに対する認証や、Cloud Runへのデプロイアクションを利用しています。
-
jobs.<job_id>.steps[*].run
- シェルを使用して、21,000 文字を超えないコマンド ライン プログラムが実行可能です。
- ここでは、
gcloud auth configure-docker
でDockerの認証を行い、さらに指定されたリポジトリへのアクセスを許可します。またbuild
やpush
などのdocker
コマンドが実行されています。
Terraformリソースの自動デプロイする
続いてはTerraformで作成したリソースのデプロイをワークフローで実現するケースです。
Cloud Runのワークフローでは見られなかった、特徴的なワークフロー構文に限定して内容を整理していきます。
on:
トリガー
on:
push:
branches:
- master
pull_request:
この例では、次の2つ条件でワークフローが実行されます。
- master ブランチにコードが直接プッシュ/mergeされた場合
- すべてのブランチで、pull requestが発生した場合
イベント発生条件を制御することで、CI/CDそれぞれで実行したいステップを分けて実装可能です。
steps
ブロック
イベント発生条件を制御したon
トリガーの元で、次のjobs.steps
を構成しています。
jobs:
terraform-workflow:
runs-on: ubuntu-latest
steps:
- name: Terraform fmt
id: fmt
run: terraform fmt -check -recursive
continue-on-error: true
...
# プルリクエスト発生時にのみ実行されるステップ
- name: Comment Terraform Plan
uses: actions/github-script@v6
if: github.event_name == 'pull_request'
env:
PLAN: "terraform\n${{ steps.plan.outputs.stdout }}"
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
script: |
const output = `#### Terraform Format and Style \`${{ steps.fmt.outcome }}\`
<details><summary>Show Plan</summary>
${process.env.PLAN}
</details>
# main ブランチに pushされた場合にのみ実行されるステップ
- name: Terraform Apply
if: github.ref == 'refs/heads/master' && github.event_name == 'push'
run: terraform apply -auto-approve -input=false
env:
TF_VAR_project: ${{ secrets.TF_VAR_project }}
jobs.<job_id>.steps[*]
-
jobs.<job_id>.steps[*].if
-
条件が満たされなければ、ステップを実行しないよう制御します。ここでは、イベントが
pull_request
の場合のみに実行されるステップ、そしてmaster
ブランチへのpush
イベントの場合のみに実行されるステップが定義されています。 -
これによりCIステップ、CDステップを分けることができ、安全なデプロイサイクルを回すことができます。
-
-
jobs.<job_id>.steps[*].with
- アクションの入力パラメータでキー:値ペアで定義されます。
-
jobs.<job_id>.steps[*].env
-
TF_VAR_project
を環境変数に登録しています。 - この環境変数を利用するように
terraform
のソースが構成されています。
-
-
jobs.<job_id>.steps[*].continue-on-error
-
true
にしていることで、このステップが失敗してもジョブ全体を失敗としない設定が可能になります。
-
最後に
実際に作ってみて、そのワークフローをドキュメントと照合しながら学ぶGithub Actionsでした。
学びたいことはまだまだ尽きず、on
トリガーの微細な制御や、actions/github-script
を利用したリポジトリやプルリクエスト、Issueの操作などCI/CDに必要・便利な運用方法を学んでいきたいです。
公式ドキュメント
説明はかなりかりやすく、また直感的でよいUIだなと感じました!
https://docs.github.com/ja/actions/writing-workflows/workflow-syntax-for-github-actions