GitHub Actionsにてhugo記事の生成とs3へのアップロードを自動化
hugoの記事投稿がlocalで公開用html作成しS3へアップロード、必要ならcloud frontのキャッシュを削除する必要がある。面倒なのでgithubへのpushをトリガーにs3へのファイルアップロードをgithub actionsで行う。
目次
- 1.GitHub Actions概要
- 2.hugo build環境構築しGitHub Actionsへ移植
- 3.GitHubとAWS連携
- 4.Google Search Console登録
1. GitHub Actions概要
とりあえず、公式のクイックスタートを眺める。 Githubが提供するコンテナ環境環境でいろいろ動かせる、らしい。動かす命令はGithubのWorkflowが提供する機能で実現するので。処理はstepに書いていけばとりあえず実行してくれそう。
2. hugo build環境構築
面倒なのでmainにpushされたのをトリガーにs3へのアップロードを動かすことにする。 提供されているubuntu-latestでgoが提供されているが、v1.17しか試したことが無いのとlatestは勝手にgoのversionが上がりそうなのでversion指定してインストールさせる。 手元のコンテナ環境でhugoを動かすのに必要そうなものをインストール、hugoのbuildが通ることを確認してからコマンドをそのままGitHub Actionsへ移植した。
name: build-site-and-upload-s3
# main branchへのpushをトリガーとしてアップロード
# https://docs.github.com/ja/actions/using-workflows/workflow-syntax-for-github-actions#onpushbranchestagsbranches-ignoretags-ignore
on:
push:
branches:
- main
jobs:
build-site-and-upload-s3:
runs-on: ubuntu-latest
# workflowのタイムアウトは決め打ちで10分
# https://docs.github.com/ja/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idtimeout-minutes
timeout-minutes: 10
steps:
# レポジトリ チェックアウト
- name: Check out the repository
uses: actions/checkout@v4
# goをインストール。使用hugoは確か1.18は動かなかったから、1.17.12でのbuildを想定する
# https://go.dev/doc/install
- name: install golang
run: |
curl -OL https://go.dev/dl/go1.17.13.linux-amd64.tar.gz
sudo rm -rf /usr/bin/go && sudo tar -C /usr/bin -xzf go1.17.13.linux-amd64.tar.gz
export PATH=$PATH:/usr/bin/go/bin
go version
- name: install hugo
# hugoインストール
# https://gohugo.io/installation/linux/#debian
run: sudo apt install -y hugo
# hugo build
- name: build sites
run: hugo
3. GitHubとAWS連携
githubからawsのリソースを使用するための認証方法はアクセスキーかOpenID Connect。GithubはOpenID Connectを推奨しているためこれを使う。 接続方法をまとめてくれており、また、面倒そうなOpenID周りの処理を担ってくれるActionsも用意してくれてる! ざっくり手順はAWSにGithubとのOIDC providerを設定、Githubが使用するIAMを作成しworkflowにActionsを入れるっぽい。
OpenID Connect
- Good
- GitHub推奨
- キー流出のリスクが少ない
- Bad
- アカウントIDはコンテナにわたす必要がる
アクセスキー
- Good
- よくやるlocalからつなぐ方法と同じ。流用できる
- Bad
- キーが(公開していないとはいえ)インターネットに上がる
3.1 AWSにOIDC provider 作成設定
gihub側の手順に記載がある、URL
とAudience
を入力しサムプリントを取得
を押し、ページ下部プロバイダを追加
にてプロバイダを作成する。
3.2 GitHubが使用する IAMロール作成
IAMロール作成
awsが公開してくれてるロールを使う。変更点は2点だけ。
- federatedを自分のawsアカウントIDに変える
- このロールにアクセス可能なgithuレポジトリを
sub
で指定する- awsの設定だとレポジトリとブランチ両方していする例なので、githug側に載ってるレポジトリだけ指定する方を使う
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"Federated": "arn:aws:iam::123456123456:oidc-provider/token.actions.githubusercontent.com"
},
"Action": "sts:AssumeRoleWithWebIdentity",
"Condition": {
"StringLike": {
"token.actions.githubusercontent.com:sub": "repo:octo-org/octo-repo:*"
},
"StringEquals": {
"token.actions.githubusercontent.com:aud": "sts.amazonaws.com"
}
}
}
]
}
ポリシー追加 ブログ更新のためS3とCloudFrontのポリシーを追加する。
3.3 WorkFlowからawsへつなぐ
OpenId Connect使用のため権限id-token: write
、contents: read
を追加する。
aws-actions/configure-aws-credentials@v3
でクレデンシャル取得する。AWS AccountIDを指定する必要があるが、一応伏せておきたいためGithub側に変数(シークレット)を登録し参照する。
とりあえずつなげたか確認するためs3のバケットを表示してみる
name: build-site-and-upload-s3
# main branchへのpushをトリガーとしてアップロード
# https://docs.github.com/ja/actions/using-workflows/workflow-syntax-for-github-actions#onpushbranchestagsbranches-ignoretags-ignore
on:
push:
branches:
- main
jobs:
build-site-and-upload-s3:
runs-on: ubuntu-latest
permissions:
# OpenID Connectを使用するためid-tokenのwrite権限を付与
# action checkoutのためcontentsのread権限を付与
#
# https://docs.github.com/en/actions/deployment/security-hardening-your-deployments/configuring-openid-connect-in-amazon-web-services#adding-permissions-settings
id-token: write # This is required for requesting the JWT
contents: read # This is required for actions/checkout
# workflowのタイムアウトは決め打ちで10分
# https://docs.github.com/ja/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idtimeout-minutes
timeout-minutes: 10
steps:
# レポジトリ チェックアウト
- name: Check out the repository
uses: actions/checkout@v4
# goをインストール。使用hugoは確か1.18は動かなかったから、1.17.12でのbuildを想定する
# https://go.dev/doc/install
- name: install golang
run: |
curl -OL https://go.dev/dl/go1.17.13.linux-amd64.tar.gz
sudo rm -rf /usr/bin/go && sudo tar -C /usr/bin -xzf go1.17.13.linux-amd64.tar.gz
export PATH=$PATH:/usr/bin/go/bin
go version
- name: install hugo
# hugoインストール
# https://gohugo.io/installation/linux/#debian
run: sudo apt install -y hugo
# hugo build
- name: build sites
run: |
hugo
# awsへ接続
# OpenID Connectを使用してクレデンシャルを取得する
- name: configure aws credentials
uses: aws-actions/configure-aws-credentials@v3
with:
role-to-assume: arn:aws:iam::${{secrets.AWS_ACCOUNT_ID}}:role/OpenID-Provider-Github-blog-hug
role-session-name: ${{ github.sha }}
aws-region: ap-northeast-1
# s3でawsへの接続を確認
- name: ls s3
run: aws s3 ls
3.4 s3へアップロードとCloudFrontのキャッシュ削除
なんだか上手くいってそうなので、hugo
コマンドで生成したサイト(生成された公開用サイトはpublic/
に置かれる)をディレクトリ丸ごとs3へアップロードする。アップロード本から削除したファイルもs3から削除したいため–deleteオプションを付けた。
s3 ⇔ cloudfront間の同期はcloudfront側全削除でs3のファイル上げ直す方法にした。データ少い内は問題ないが…後で改善しとく。
# s3へファイルをアップロード
#
# https://docs.aws.amazon.com/ja_jp/cli/latest/userguide/cli-services-s3-commands.html#using-s3-commands-managing-objects-sync
- name: upload s3
run: aws s3 sync public/ s3://s3-bucket-name --delete
# cloudfront のキャッシュを削除
#
# https://docs.aws.amazon.com/ja_jp/AmazonCloudFront/latest/DeveloperGuide/Invalidation.html
- name: delete cloudfront cache
run: aws cloudfront create-invalidation --distribution-id ${{ secrets.HUGO_CLOUDFRONT_ID }} --paths "/*"
4. Google Search Console登録
googleの検索botにサイトクロールしてもらうためGoogle Search Console
へ登録する。これに登録しなくてもbotが巡回してくれる可能性はあるらしいが、登録しておけば検索の優先順位とかgoogleがサイトをどう見ているかがわかるため登録しておく。一応登録し無くとも検索には出てきた。不思議ッ
Search Console に登録しなくても Google 検索結果にサイトが表示されるようにすることはできますが、Search Console に登録することで、Google のサイトに対する認識を理解し、改善できるようになります。
サイトを登録するにはサイトを所有することを証明する必要がある。証明方法はいくつかあるが、今回はgoogleが登録専用に払い出したhtmlをtop階層に設置する方法を選んだ。詳細は ウェブサイト プロパティを Search Console に追加するを参照。ただ払い出されたhtmlをtop階層に置けばよいので、サイト生成後htmlをコピーした。
# verify site ownership for google
- name: verify site ownership for google
run: |
cp google123456789abxdefg.html public/
完成したworkflow
name: build-site-and-upload-s3
# main branchへのpushをトリガーとしてアップロード
# https://docs.github.com/ja/actions/using-workflows/workflow-syntax-for-github-actions#onpushbranchestagsbranches-ignoretags-ignore
on:
push:
branches:
- main
jobs:
build-site-and-upload-s3:
runs-on: ubuntu-latest
permissions:
# OpenID Connectを使用するためid-tokenのwrite権限を付与
# action checkoutのためcontentsのread権限を付与
#
# https://docs.github.com/en/actions/deployment/security-hardening-your-deployments/configuring-openid-connect-in-amazon-web-services#adding-permissions-settings
id-token: write # This is required for requesting the JWT
contents: read # This is required for actions/checkout
# workflowのタイムアウトは決め打ちで10分
# https://docs.github.com/ja/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idtimeout-minutes
timeout-minutes: 10
steps:
# レポジトリ チェックアウト
- name: Check out the repository
uses: actions/checkout@v4
# goをインストール。使用hugoは確か1.18は動かなかったから、1.17.12でのbuildを想定する
# https://go.dev/doc/install
- name: install golang
run: |
curl -OL https://go.dev/dl/go1.17.13.linux-amd64.tar.gz
sudo rm -rf /usr/bin/go && sudo tar -C /usr/bin -xzf go1.17.13.linux-amd64.tar.gz
export PATH=$PATH:/usr/bin/go/bin
go version
- name: install hugo
# hugoインストール
# https://gohugo.io/installation/linux/#debian
run: sudo apt install -y hugo
# hugo build
- name: build sites
run: |
hugo
# verify site ownership for google
- name: verify site ownership for google
run: |
cp google123456789abxdefg.html public/
# awsへ接続
# OpenID Connectを使用してクレデンシャルを取得する
- name: configure aws credentials
uses: aws-actions/configure-aws-credentials@v3
with:
role-to-assume: arn:aws:iam::${{secrets.AWS_ACCOUNT_ID}}:role/OpenID-Provider-Github-blog-hug
role-session-name: ${{ github.sha }}
aws-region: ap-northeast-1
# s3へファイルをアップロード
#
# https://docs.aws.amazon.com/ja_jp/cli/latest/userguide/cli-services-s3-commands.html#using-s3-commands-managing-objects-sync
- name: upload s3
run: aws s3 sync public/ s3://s3-bucket-name --delete
# cloudfront のキャッシュを削除
#
# https://docs.aws.amazon.com/ja_jp/AmazonCloudFront/latest/DeveloperGuide/Invalidation.html
- name: delete cloudfront cache
run: aws cloudfront create-invalidation --distribution-id ${{ secrets.HUGO_CLOUDFRONT_ID }} --paths "/*"