はじめに
ブログサイトを1から作ってみたの続き。
CloudFront + S3 で作ったブログサイトのデプロイを GitHub Actions で自動化してみた。
具体的にはブログサイトの GitHub リポジトリの main ブランチにマークダウンの追加・変更をプッシュしたら、 GitHub Actions で Hugo コマンドを実行して静的サイトを生成し、生成されたファイルを S3 バケットに自動的にアップロードする。
権限周りの準備
準備として、GitHub の公式ドキュメント Configuring OpenID Connect in Amazon Web Services にしたがって、OIDC provider を登録し IAM ロールを作成する。
この IAM ロールを GitHub Actions で Assume Role することで、S3 へのアクセス権を得る。
GitHub OIDC provider を IAM に追加
AWS コンソール > IAM > IDプロバイダ からIDプロバイダを追加する。
- プロバイダのタイプ: OpenID Connect
- プロバイダのURL:
https://token.actions.githubusercontent.com
- 対象者:
sts.amazonaws.com
※ Amazon が出している 公式の Action を使う場合は、対象者に sts.amazonaws.com
を指定すると書いてある。
ロール作成
GitHub Actions が Assume Role するロールを作成する。
AWS コンソール > IAM > ロール からロールを作成する。
- 信頼されたエンティティタイプ: ウェブアイデンティティ
- アイデンティティプロバイダー:
https://token.actions.githubusercontent.com
- Audience:
sts.amazonaws.com
- ポリシーは後からつけるのでこの画面では付けなかった。
- ロール名は
github-actions-role
で作成した。
ロールにポリシーを追加
作成したロールに次のようなポリシーをインラインポリシーで追加した。
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"s3:ListBucket",
"s3:ListObjectsV2",
"s3:DeleteObject",
"s3:PutObject"
],
"Resource": [
"arn:aws:s3:::{バケット名}",
"arn:aws:s3:::{バケット名}/*"
]
}
]
}
ロールの信頼ポリシーを編集
作成したロールの信頼ポリシーの Condition に StringLike
の条件を追加した。
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"Federated": "arn:aws:iam::{accountId}:oidc-provider/token.actions.githubusercontent.com"
},
"Action": "sts:AssumeRoleWithWebIdentity",
"Condition": {
"StringEquals": {
"token.actions.githubusercontent.com:aud": "sts.amazonaws.com"
},
"StringLike": {
"token.actions.githubusercontent.com:sub": "repo:nshmura/website:*"
}
}
}
]
}
GitHub Actions でのデプロイ
GitHub Actions Workflow ファイルを追加
.github/workflow/deploy.yaml
という名前で Worflow ファイルを作成する。
name: deploy blog site
on:
push:
branches:
- main
paths:
- "website/**"
workflow_dispatch:
env:
AWS_REGION: ap-northeast-1
AWS_ROLE_ARN: arn:aws:iam::${{ secrets.AWS_ACCOUNT_ID }}:role/github-actions-role
AWS_TARGET_S3_BUCKET: ${{ secrets.AWS_TARGET_S3_BUCKET }}
jobs:
deploy:
runs-on: ubuntu-latest
permissions:
id-token: write
contents: read
steps:
- name: Checkout
uses: actions/checkout@v3
- name: Setup Hugo
uses: peaceiris/actions-hugo@v2
with:
hugo-version: "0.110.0"
- name: Build
run: |
cd website
HUGO_ENV=production hugo --minify
- name: Configure AWS credentials from IAM Role
uses: aws-actions/configure-aws-credentials@v1-node16
with:
role-to-assume: ${{ env.AWS_ROLE_ARN }}
aws-region: ${{ env.AWS_REGION }}
- name: Upload file to S3
run: aws s3 sync --delete website/public s3://${{ env.AWS_TARGET_S3_BUCKET }}/website/public
AWS_ACCOUNT_ID
とAWS_TARGET_S3_BUCKET
はシークレットとした。private リポジトリなのでベタで書いても問題ない気はする。- AWSの権限は、AWS 公式の
aws-actions/configure-aws-credentials@v1-node16
に任せる。
GitHub Actions Secrets 追加
GitHub リポジトリ > Settings > Secrets and variables > Actions に進んで「New repository secret」からシークレットを追加する。
AWS_ACCOUNT_ID
AWS_TARGET_S3_BUCKET
GitHub Actions 実行
ワークフローのトリガーに workflow_dispatch
を入れているので手動でも起動ができる。
GitHub リポジトリ > Actions > deploy blog site > Run workflow からワークフローを実行すると、無事に Huge によるビルドと S3 へのアップロードができた。
通常は main
ブランチにプッシュすることでデプロイが始まる。
おわりに
AWSの IDプロバイダ周りの設定は初めてで、心理的なハードルが高かったが、やってみれば簡単だった。
早い段階でデプロイ自動化できた。これでブログ更新が捗ると良いな。