GitHub Actionsでタグを指定してリリースできるようにする
はじめに
この記事では弊プロダクト「えんさがそっ♪」の Laravelアプリケーションを GitHub Actions を利用してタグ(バージョン)を指定してECS にデプロイする方法についてまとめます。
前提
- イメージのビルド・プッシュするアクションは定義済み
- この記事で扱うデプロイとは別のフローになっている
- GitHub の Release 機能を利用して tag をバージョン(リリースの単位)としている
- task-definition の説明は端折る
- task-definition.json をGit管理に含めたい
全体の流れ
- GitHub Actionの手動実行時に、タグ(バージョン)を入力する
-
aws-actions/amazon-ecs-render-task-definition
アクションで、タグ(バージョン)を指定したイメージのタスク定義(のJSON文字列)を生成する - aws cli で、2. で生成したタスク定義で ECS サービスを更新する
task-definition.json を用意する
イメージ(タグ)の指定をするにはどうするかというと、タスク定義でイメージのパスを指定する必要があります。そのためタスク定義を構成する task-definition.json
を利用してイメージの指定を実現します。
もし他にもやり方があったらコメント等で教えて頂けますと嬉しいです🙇
どうやって用意するか
やり方はいろいろあるみたいなのですが、task-definition.json をGit管理に含めたいというところもあり今回は愚直に「ダウンロードしてきて必要なものを整理する」という方法を採用しました。
主にこちらの記事を参考にさせていただいてので詳しくはこちらを見ていただければと思います。
GitHub Actions の実行時にタグを指定する
指定の仕方をどうするか検討する中で、タグをデータにしたセレクターみたいなものを表示できたらいいよなーとか思いましたがパッとできそうではなかった(?)ので今回はシンプルなテキスト入力を設けてそこにリリースしたいバージョン(タグ)を入力する形式としました。
yaml を更新します。
on:
workflow_dispatch:
inputs:
tag:
description: 'Enter the version (tag) to deploy'
required: true
inputs
を追加しました。
これで、GitHub Actions の「Run workflow」の UI にタグを指定する入力欄ができました。
こんなかんじ。
タグの指定を受け取ってデプロイする
aws-actions/amazon-ecs-render-task-definition
アクションを利用して、指定されたバージョンを task-definition.json にフィルします。
指定されたバージョンは、inputs.tag
で受け取ることができますので image のパラメータに前のステップの返り値の outputs.registry
、環境変数に入れてる ECR_APP_REPOSITORY
を連結して image のパスを定義します。
- name: "Fill in the image ID in the Amazon ECS task definition"
id: task-def
uses: aws-actions/amazon-ecs-render-task-definition@v1
with:
task-definition: ${{ env.APP_TASK_DEFINITION_PATH }}
container-name: ${{ env.APP_CONTAINER_NAME }}
image: ${{ steps.login-ecr.outputs.registry }}/${{ env.ECR_APP_REPOSITORY }}:${{ inputs.tag }}
前のステップの返り値の outputs.task-definition
で作成された json のパスが返ってくるので jq
で taskDefinitionArn
を取り出して aws ecs register-task-definition
に渡して新しい task-definition を登録します。
よく例でもある aws-actions/amazon-ecs-deploy-task-definition
を使えばよりシンプルにタスクの登録、サービスの更新までできるみたいでしたが、desired-count
の指定ができなかったため aws-cli
でサービスの更新をするようにしました。
- name: "Register task definition & Update ECS service"
env:
IMAGE_ID_FILLED_APP_TASK_DEFINITION: ${{ steps.task-def.outputs.task-definition }}
run: |
set -x
NEW_TASK_DEFINITION_ARN=$(aws ecs register-task-definition \
--family $ECS_APP_TASK_DEFINITION_FAMILY \
--cli-input-json "file://${IMAGE_ID_FILLED_APP_TASK_DEFINITION}" | jq -r '.taskDefinition.taskDefinitionArn')
aws ecs update-service \
--task-definition $NEW_TASK_DEFINITION_ARN \
--force-new-deployment \
--cluster $ECS_CLUSTER \
--service $ECS_APP_SERVICE \
--desired-count 2
指定されたタグのイメージがないときはエラーにする
正直なところ、デプロイができた時点で「ヨシっ!」となってしまっていたのですが想定外なところがありました。存在しないタグが指定された際にもワークフローや、タスク定義が正常終了してしまうということです。
その対策のため、ECR にイメージが存在するかの確認をするステップをタスクを更新する前に追加しました。
- name: "Check if image exists in ECR"
run: |
IMAGES=$(aws ecr list-images --repository-name $ECR_APP_REPOSITORY --query "imageIds[?imageTag=='${{ inputs.tag }}']" --output text)
if [ -z "$IMAGES" ]; then
echo "Image does not exist."
exit 1
fi
aws cli の ecr list-images
コマンドを利用して ECR に指定されたイメージが存在するか確認します。--output text
を指定して文字列で出力するようしています。存在しなければここで exit 1
してワークフローを終了します。
これで存在しないタグが指定されても正常終了せずエラーを発生させることができました。
さいごに
今回の作業の中で masterブランチ以外の workflow ってどうやって実行するんだ?というところで GitHub CLI
を使ってみたりしたのでそのあたりもまた記事できればと考えています。
最後までお読みいただきありがとうございました。
参考にさせていただいた記事
私たち BABY JOB は、子育てを取り巻く社会のあり方を変え、「すべての人が子育てを楽しいと思える社会」の実現を目指すスタートアップ企業です。圧倒的なぬくもりと当事者意識をもって、こどもと向き合う時間、そして心のゆとりが生まれるサービスを創出します。baby-job.co.jp/
Discussion