はじめに
AWS Amplify Console
は、 静的ウェブサイトを簡単かつ迅速にホスティングすることのできるAWSサービス です。Webアプリの構築やデプロイを行うための CI/CDワークフローも提供される ことから、React、Angular、Vue、Ember などの シングルページアプリケーション (SPA) を 簡単にデプロイ することができます。また、AWS CodeCommit
などの コードリポジトリと接続することで、コードコミットのたびにデプロイを実行 することもできます。
Amplify Console
を使い始めるにあたっては、コードリポジトリとの接続やブランチの作成などの 各種セットアップが必要 となります。もちろん、AWSのコンソール画面(AWS Management Console)から、これらのセットアップを行うことも可能ですが、本記事では 「Amplify Console のセットアップをできるだけ簡単に終わらせたい」 という想いから、CloudFormationテンプレートを用いて、 これらのセットアップをクリック1つで完了 させようと思います。
TL;DR
以下の CloudFormation
テンプレートを実行することで、AWS Amplify Console と AWS CodeCommit を用いたCI/CDワークフローをお手軽に実現します。下にあるボタンをクリックすると、自身のAWSアカウント(Asia Pacific Tokyo - ap-northeast-1)で、このCloudFormation
テンプレートを実行することが可能となります。
作成されるAWSリソースとそのアーキテクチャ図はこちら。
AWS Amplify Consoleは、 複数のコードリポジトリに対応していますが、本記事では CloudFormation を使って簡単に環境構築が可能な AWS CodeCommit
をコードリポジトリとして使用しています。
アーキテクチャ
このテンプレートの設定内容は以下の通りです。なお、以下のYAMLコードは、 aws-cloudformation-templates/amplify - GitHub で公開しているCloudFormationテンプレートから、本記事用に一部抜粋したものです。本記事作成用に一部改変を行なっていること、またリポジトリの最新のコードを常に反映している訳ではないことをご了承ください。詳細は、GitHubの 当該リポジトリ をご覧ください。
AWS CodeCommit
リポジトリ名を指定 して、Gitリポジトリを作成します。また、 AWS CodeCommit
で発生した全てのイベントをトリガとして、 Amazon SNS
に 通知が送信 されます。
Parameters:
DomainName:
Type: String
AllowedPattern: .+
Description: Custom domain name for your Amplify Console application [required]
RepositoryName:
Type: String
AllowedPattern: .+
Description: Repository name on CodeCommit [required]
Resources:
CodeCommit:
Type: 'AWS::CodeCommit::Repository'
Properties:
RepositoryDescription: !Ref DomainName
RepositoryName: !Ref RepositoryName
Triggers:
- DestinationArn: !Ref SNSTopic
Events:
- all
Name: Notify all events to SNS
Amazon SNS
AWS CodeCommit
や AWS Amplify
から送信された通知を受け取る Amazon SNS
トピック を作成します。
Resources:
SNSTopic:
Type: 'AWS::SNS::Topic'
Properties:
DisplayName: !Sub SNSTopic-createdby-${AWS::StackName}
TopicName: !Sub SNSTopic-createdby-${AWS::StackName}
AWS Serverless Application Repository にある sns-topic テンプレート を組み込むことで、SNSトピックを作成することも可能です。この方法の場合、 作成したSNSトピックに関連する CloudWatch アラームも同時に作成 することができます。
Resources:
SNSTopic:
Type: 'AWS::Serverless::Application'
Properties:
Location:
ApplicationId: arn:aws:serverlessrepo:us-east-1:172664222583:applications/sns-topic
SemanticVersion: 1.0.18
Parameters:
TopicName: !Sub SNSTopic-createdby-${AWS::StackName}
AWS Amplify Console
IAM Role の作成
AWS Amplify Console
で使用する IAM Role
を作成します。
Resources:
IAMRoleForAmplify:
Type: 'AWS::IAM::Role'
Properties:
AssumeRolePolicyDocument:
Version: 2012-10-17
Statement:
- Effect: Allow
Principal:
Service: amplify.amazonaws.com
Action: 'sts:AssumeRole'
Description: Allows Amplify Backend Deployment to access AWS resources on your behalf.
ManagedPolicyArns:
- arn:aws:iam::aws:policy/AdministratorAccess
RoleName: !Sub '${AWS::StackName}-AmplifyBackend-${AWS::Region}'
AWS Amplify Console の作成
AWS Amplify Console
を作成し、先ほど作成した CodeCommit
を リポジトリに指定 します。また、master
と develop
の2つの ブランチを作成 します。
Parameters:
DomainName:
Type: String
AllowedPattern: .+
Description: Custom domain name for your Amplify Console application [required]
RepositoryName:
Type: String
AllowedPattern: .+
Description: Repository name on CodeCommit [required]
Resources:
AmplifyConsole:
Type: 'AWS::Amplify::App'
Properties:
AutoBranchCreationConfig:
EnableAutoBranchCreation: true
EnableAutoBuild: true
Description: !Ref DomainName
IAMServiceRole: !GetAtt IAMRoleForAmplify.Arn
Name: !Ref RepositoryName
Repository: !GetAtt CodeCommit.CloneUrlHttp
AmplifyBranchDev:
Type: 'AWS::Amplify::Branch'
Properties:
AppId: !GetAtt AmplifyConsole.AppId
BranchName: develop
Description: develop
EnableAutoBuild: true
EnvironmentVariables:
- Name: USER_BRANCH
Value: dev
AmplifyBranchProd:
Type: 'AWS::Amplify::Branch'
Properties:
AppId: !GetAtt AmplifyConsole.AppId
BranchName: master
Description: master
EnableAutoBuild: true
EnvironmentVariables:
- Name: USER_BRANCH
Value: prod
カスタムドメインの指定
Amplify Console では、ブランチごとにデプロイが実行され、個別のURLが付与されます。また、これらのURLを カスタムドメインに差し替える ことが可能で、 指定したドメインのSSL証明書の作成から紐付けまでを自動で行う ことができます。下の例では、 master
ブランチのURLに、自身が指定したカスタムドメインを紐付けています。
Parameters:
DomainName:
Type: String
AllowedPattern: .+
Description: Custom domain name for your Amplify Console application [required]
Resources:
AmplifyDomainProd:
Type: 'AWS::Amplify::Domain'
Properties:
AppId: !GetAtt AmplifyConsole.AppId
DomainName: !Sub ${DomainName}
SubDomainSettings:
- BranchName: !GetAtt AmplifyBranchProd.BranchName
Prefix: ''
Amazon EventBridge
AWS Amplify Console
から送信された通知を Amazon SNS
にルーティングする、Amazon EventBridge
イベントルール を作成します。下の例では、デプロイのステータスが、SUCCEED
, FAILED
, STARTED
であった場合のみ、通知を Amazon SNS
にルーティングします。
EventBridgeForAmplify:
Type: 'AWS::Events::Rule'
Properties:
Description: !Sub Rule for Amplify created by ${AWS::StackName}.
EventPattern:
source:
- aws.amplify
detail-type:
- Amplify Deployment Status Change
detail:
appId:
- !GetAtt AmplifyConsole.AppId
jobStatus:
- SUCCEED
- FAILED
- STARTED
Name: !Sub ${AWS::StackName}-Amplify
State: ENABLED
Targets:
# SNSトピックを直接作成した場合
- Arn: !Ref SNSTopic
# SNSトピックを AWS Serverless Application Repository から作成した場合
- Arn: !GetAtt SNSTopic.Outputs.SNSTopicArn
以上で、AWS Amplify Console
と AWS CodeCommit
を連携して、 CI/CDワークフローを作成することができました。
CodeCommit から Amplify Console へのトリガ設定
ただ、 上記のままだと AWS CodeCommit へのコードのプッシュをトリガにした、AWS Amplify Console のデプロイは実行されません 。なぜなら、上記の CloudFormationテンプレートには、 AWS CodeCommit から AWS Amplify Console へのトリガ設定が含まれていない ためです。CloudFormationテンプレートで、このトリガ設定を記述しようとすると、AWS Amplify と AWS CodeCommit の両リソースの間で 循環参照 が発生してしまいます。
(2020年7月24日追記)
上記の CloudFormation テンプレートを実行し、Amplify の設定内で CodeCommit のリポジトリを指定した時点で、 AWS CodeCommit から AWS Amplify Console へのトリガ設定が自動で作成 されます。したがいまして、 通常であれば下記の設定を行う必要はありません 。トリガ設定を手動で削除してしまった場合など、 トリガを設定し直す必要がある場合のみ下記の手順をお試しください 。
1. 手動でトリガを設定する
AWSのコンソール画面(AWS Management Console)からトリガを 手動追加 します。指定する項目は、「トリガ名」、「イベントの種類」、「SNSトピック名 ( = arn:aws:sns:{region}:{account_id}:amplify_codecommit_topic )」、「カスタムデータ ( = Amlify Console アプリケーションID)」です。
この AWS Amplify アプリケーションID は、 アプリケーション作成後でないと指定できない ため、 最初の CloudFormationデプロイが完了した後 に手動で入力する必要があります。
2.アプリケーションIDを指定できるテンプレートに変更する
スマートさには欠けますが、上述した循環参照を避けるために、AWS CodeCommit 上で指定する AWS Amplify アプリケーションID を手動で指定 します。そのために、上のCloudFormationテンプレートに少し修正を加えます。
Parameters:
AmplifyConsoleAppId:
Type: String
Default: ''
Description: Amplify Console application id this template created
DomainName:
Type: String
AllowedPattern: .+
Description: Custom domain name for your Amplify Console application [required]
RepositoryName:
Type: String
AllowedPattern: .+
Description: Repository name on CodeCommit [required]
Conditions:
CreateCodeCommitTrigger: !Not [ !Equals [ !Ref AmplifyConsoleAppId, ''] ]
Resources:
CodeCommit:
Type: 'AWS::CodeCommit::Repository'
Properties:
RepositoryDescription: !Ref DomainName
RepositoryName: !Ref RepositoryName
Triggers:
- DestinationArn: !Ref SNSTopic
Events:
- all
Name: Notify all events to SNS
- !If
- CreateCodeCommitTrigger
- DestinationArn: !Sub arn:aws:sns:${AWS::Region}:${AWS::AccountId}:amplify_codecommit_topic
CustomData: !Ref AmplifyConsoleAppId
Events:
- all
Name: !Sub AmplifyTrigger-${AmplifyConsoleAppId}
- !Ref AWS::NoValue
AmplifyConsoleAppId
パラメータを手動で指定することでトリガを指定することができますが、この AWS Amplify アプリケーションID は、 アプリケーション作成後でないと指定できない ため、 最初の CloudFormationデプロイ は空白のままで実行 し、AWS Amplify アプリケーションID を指定した上で、 再度CloudFormationデプロイを実行 する必要があります。
以上で、AWS CodeCommit へのコードプッシュのトリガで、AWS Amplify Console のデプロイが実行される、CI/CDワークフローを構築することができました 。