GitHub Actionsでオンデマンドに環境を再現する
何の話か
GitHubでインフラや環境を作るコードを管理している人は多いと多います。そして最近はGitHub Actionsを使ったワークフローに取り組むケースも増えてきました。
- プルリクエストイベントをトリガーにコードの検証やテストを行い、マージの判断に使う
- マージされたら、ステージングや本番環境へデプロイする
こんなワークフローが一般的と思います。ですが一時的に「コードは変えてないけど、一時的に環境を再現したい」なんてこともあります。不具合対応とか。環境を作るコードはあるので、どこかにコードを持っていって実行すればいいのですが、せっかくGitHub Actionsで仕組みを作った手前、チョイっといじってできるなら、そうしたい。
アイデア
GitHub Actionsを使ってコードから環境をデプロイする環境はすでにある、という前提なので、論点は「どのトリガーを使うか」です。
トリガーにできるイベントは多くありますが「コードは変えない」という条件だと、悩みます。プルリクやプッシュでの発火がわかりやすいからといって、そのためのフラグファイル的なものを作りたくもありません。
GitHubでコミュニケーションしているのであれば、環境を再現したいような事案発生時にはIssueを作るでしょう。であれば、特定のキーワードを含むIssueを作った/消したタイミングで発火させましょうか。でもこのやり口では、チェックなしで環境が作られてしまいます。それがプライベートリポジトリであっても、気前良すぎ良太郎な感は否めません。
そこで、Issueイベントのタイプ labeled/unlabeled を使ってみましょう。ラベルを付与できるのはTriage以上の権限を持った人です。権限を持った人がIssueに「環境を再現」するラベルを付け/外しした時に発火するようなワークフローを作ります。
ワークフロー例
以下、Azureで環境を作る例です。ラベルがIssueに付く、外れるのを契機にワークフローが流れ、条件を満たした場合に環境のデプロイか削除を行います。インフラのコード化はAzure Resource Managerテンプレートでされており、ファイルはリポジトリの deployment/azuredeploy.json に置かれている、というサンプルです。
name: gh-actions-trigger-labeled
on:
issues:
types:
- labeled
- unlabeled
env:
AZURE_GROUP_NAME: rg-repro-gh-actions-trigger-label
YOUR_PARAM: hoge
jobs:
deploy-or-delete:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@master
- uses: azure/login@v1
with:
creds: ${{ secrets.AZURE_CREDENTIALS }}
- if: github.event.label.name == 'repro' && github.event.action == 'labeled'
run: |
az group create -n ${{ env.AZURE_GROUP_NAME }} -l japaneast
az group deployment create -n repro -g ${{ env.AZURE_GROUP_NAME }} --template-file deployment/azuredeploy.json --parameters name=${{ env.YOUR_PARAM }}
- if: github.event.label.name == 'repro' && github.event.action == 'unlabeled'
run: |
az group delete -n ${{ env.AZURE_GROUP_NAME }} -y
- run: |
az logout
ポイントは以下の通りです。
- ラベル「repro」を作っておく(環境を再現してるという意図が分かればなんでも)
- if文でステップ実行の条件を書く
- ラベルがIssueに付与され、それがreproだった場合にAzure CLIでリソースグループ作成、テンプレートデプロイが実行される
- ラベルが外され、それがreproだった場合にAzure CLIでリソースグループごと削除する
- 環境の違いはパラメーターで注入する
- この例ではenvで定義したパラメーターをテンプレートデプロイのパラメーターとして渡している
- Issueトリガーで対象となるブランチはデフォルトブランチ
- この例は再現環境をリポジトリで1つとしたケース
- 他のIssueでラベルを付けられてもいいように、繰り返し実行可能な作りにする
- Azure Resource Manager テンプレートデプロイは既存リソースがあった時、投入内容が同じであれば実行されないが、動的にパラメーターを作っている場合は気を付ける
- Issueごとに環境をつくりたい場合は、github.event.issue.idなどイベントのペイロードを活用してリソースを作る
- イベントのペイロードは公式サイトを参考に
Terraformでも同じようにやりたいところですが、残念ながら terraform-github-actions がdestroyに未対応です。プルリクは出ているので期待しましょう。なお、GitHub Actionsは発火までにして、以降のデプロイはAzure Pipelinesに任せてしまう、という手もあります。
ラベルを駆使するリポジトリでは、その度にワークフローが走ってしまうのが気になる方法ではありますが、ご参考になれば。