AWS App Runner Advent Calendar 2022の14日目の記事です。
AWS AppRunnerはさまざまな言語に対応し始めていたり、GithHubのブランチを監視して自動デプロイしてくれたり、オートスケールもある程度できたり、インフラの高度な知識がなくてもデプロイができる大変便利なサービスです。
任意のブランチを監視して、コミットされたら自動デプロイされる機能はとても便利なのですが、間にテストなどを挟めないので、バグが残ったままのコードがデプロイされ得る状態です。
今回は、Github Actionsを経由してAppRunnerにデプロイしてみようと思います。
[問題点]
awslabs/amazon-app-runner-deploy
を使っていますが、AutoDeploymentsEnabled
が指定できないため、デフォルトのtrue
となっています。
このままではGithub Actions側でデプロイする際に既にデプロイが開始しているのでコンフリクトしてしまいます。なので、この方法はまだ実運用は非推奨です。
この記事公開後にプルリクエスト をする予定です。近々対応されたら追記します。
前提
- 開発環境と本番環境、そしてレビュー用の環境があるという過程で行います。
- 東京リージョンを使います
- 実行環境はNode.jsです
- 今回はコンテナリポジトリからのデプロイではなくソースコードデプロイを想定します
事前準備
1. GitHubと連携する
この工程は、リポジトリ/Organizationのオーナーが行う必要があります。
2. 開発環境と本番環境のServiceを作る
固定のServiceとして、開発環境と本番環境用のServiceを事前に作っておきます。
サクッとaws cli
から作っちゃいます。
このときに作ったarnを控えておきます。
{{}}
内はご自身の環境に読み替えてください
例えばyarn
を使う僕の場合、BuildCommand
はyarn install && yarn build
、StartCommand
はyarn start:prod
としています
aws apprunner create-service --service-name {{service-name}}_develop --source-configuration \
'{
"AuthenticationConfiguration": {
"ConnectionArn": "{{Github Connection arn}}"
},
"AutoDeploymentsEnabled": false,
"CodeRepository": {
"RepositoryUrl": "{{RepositoryUrl}}",
"SourceCodeVersion": {
"Type": "BRANCH",
"Value": "develop"
},
"CodeConfiguration": {
"ConfigurationSource": "API",
"CodeConfigurationValues": {
"Runtime": "NODEJS_16",
"BuildCommand": "{{依存関係の解決・ビルドコマンド}}",
"StartCommand": "{{アプリケーションを立ち上げるコマンド}}",
"Port": "3000",
"RuntimeEnvironmentVariables":
{
"NODE_ENV": "production"
}
}
}
}
}'
aws apprunner create-service --service-name {{service-name}}_production --source-configuration \
'{
"AuthenticationConfiguration": {
"ConnectionArn": "{{Github Connection arn}}"
},
"AutoDeploymentsEnabled": false,
"CodeRepository": {
"RepositoryUrl": "{{RepositoryUrl}}",
"SourceCodeVersion": {
"Type": "BRANCH",
"Value": "main"
},
"CodeConfiguration": {
"ConfigurationSource": "API",
"CodeConfigurationValues": {
"Runtime": "NODEJS_16",
"BuildCommand": "{{依存関係の解決・ビルドコマンド}}",
"StartCommand": "{{アプリケーションを立ち上げるコマンド}}",
"Port": "3000",
"RuntimeEnvironmentVariables":
{
"NODE_ENV": "main"
}
}
}
}
}'
3. Github Secretを設定する
workflowから読み取る環境情報や、シークレットなどをリポジトリSecretsに設定していきます。
本当は、Environments Secrets
を使った方がいいのですが、読みやすさの便宜上割愛します
AWS_APPRUNNER_ACCESS_KEY_ID
とAWS_APPRUNNER_ACCESS_SECRET_KEY
はそれぞれ、AWSAppRunnerFullAccess
ポリシーを付与したIAMユーザーのアクセスキーとシークレットキーです。
より良い命名があったら教えてください。
Developにマージされたら開発環境のServiceにデプロイする
基本的なことしかしてません。developブランチにコミットされたらテストを実行し、テストがパスしたら先ほど作成した開発環境のServiceにデプロイします。
name: Test & Deploy to develop
on:
push:
branches:
- "develop"
jobs:
test:
permissions:
id-token: write
contents: read
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Setup Node.js environment
uses: actions/setup-node@v3.5.1
with:
node-version: 16.18.0
- name: Run test
run: |
npm install
npm run test
deploy:
needs: test
environment: develop
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Configure AWS Credentials
uses: aws-actions/configure-aws-credentials@v1
with:
aws-region: "ap-northeast-1"
aws-access-key-id: ${{ secrets.AWS_APPRUNNER_ACCESS_KEY_ID }}
aws-secret-access-key: ${{ secrets.AWS_APPRUNNER_ACCESS_SECRET_KEY }}
- name: deploy to app runner
run: |
aws apprunner start-deployment --service-arn ${{ secrets.DEVELOP_APPRUNNER_SERVICE_ARN }}
参考
PullRequestがOpenしたらレビュー用のサービスを作成する&コミットされたら更新する
PullRequestを発行したらレビュー用のサービスを作成します。
デプロイが完了したら、ホスティング先のURLをコメントで残します。
wait-for-service-stability-seconds
でデプロイが完了するのを待機できます。
デプロイにかかる時間はアプリケーションの規模やコード量によって変わりますのでご自身で調整してみてください。
name: Test & Create Review Service
on:
pull_request:
types: [ labeled, ready_for_review ]
jobs:
test:
permissions:
id-token: write
contents: read
if: ${{ github.base_ref != 'main' }}
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Setup Node.js environment
uses: actions/setup-node@v3.5.1
with:
node-version: 16.18.0
- name: Test
run: |
npm install
npm run test
deploy:
runs-on: ubuntu-latest
needs: test
env:
PR_NUMBER: ${{ github.event.number }}
outputs:
service-url: ${{ steps.deploy-apprunner.outputs.service-url }}
steps:
- name: Configure AWS credentials
uses: aws-actions/configure-aws-credentials@v1-node16
with:
aws-region: "ap-northeast-1"
aws-access-key-id: ${{ secrets.AWS_APPRUNNER_ACCESS_KEY_ID }}
aws-secret-access-key: ${{ secrets.AWS_APPRUNNER_ACCESS_SECRET_KEY }}
- name: Deploy to App Runner
id: deploy-apprunner
uses: awslabs/amazon-app-runner-deploy@main
env:
SERVER_PORT: 3000
NODE_ENV: develop
with:
service: review-app_${{ github.event.repository.name }}_${{ env.PR_NUMBER }}
source-connection-arn: ${{ secrets.APPRUNNER_GITHUB_CONNECTION_ARN }}
repo: https://github.com/${{ github.repository }}
branch: ${{ github.head_ref }}
runtime: NODEJS_16
build-command: yarn install && yarn build
start-command: yarn start:prod
port: ${{ env.SERVER_PORT }}
region: ap-northeast-1
cpu : 1
memory : 2
wait-for-service-stability-seconds: 600
copy-env-vars: |
NODE_ENV
comment:
runs-on: ubuntu-latest
permissions: write-all
needs: deploy
env:
PR_NUMBER: ${{ github.event.number }}
steps:
- uses: actions/checkout@v3
- name: Comment Review App URL
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
gh pr comment ${{ env.PR_NUMBER }} --body "App runner URL https://${{ needs.deploy.outputs.service-url }}"
PullRequestがMerge、Closeされたらレビュー用のサービスを削除する
コードレビューが完了し、役目を終えたサービスを削除することでクリーンアップします(そうしないと課金が止まりませんからね)
Runnning状態のものしか停止できません。
name: Delete Review Service
on:
pull_request:
types: [ closed ]
jobs:
delete:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Configure AWS Credentials
uses: aws-actions/configure-aws-credentials@v1
with:
aws-region: "ap-northeast-1"
aws-access-key-id: ${{ secrets.AWS_APPRUNNER_ACCESS_KEY_ID }}
aws-secret-access-key: ${{ secrets.AWS_APPRUNNER_ACCESS_SECRET_KEY }}
- name: Get Service Arn
id: get-service-arn
env:
PR_NUMBER: ${{ github.event.number }}
run: |
SERVICE_ARN=`aws apprunner list-services --query "ServiceSummaryList[?ServiceName=='review-app_${{ github.event.repository.name }}_$PR_NUMBER']|[0].ServiceArn"`
echo "service-arn=$SERVICE_ARN" >> $GITHUB_OUTPUT
- name: Delete AppRunner Service
run: |
aws apprunner delete-service --service-arn ${{ steps.get-service-arn.outputs.service-arn }}
改善箇所
僕がどうにかできることではないですが、デプロイ中は何も操作ができないのは解消されると幅が広がりますね。
参考