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側の手順に記載がある、URLAudienceを入力しサムプリントを取得を押し、ページ下部プロバイダを追加にてプロバイダを作成する。

create openid provider

3.2 GitHubが使用する IAMロール作成

IAMロール作成

awsが公開してくれてるロールを使う。変更点は2点だけ。

  1. federatedを自分のawsアカウントIDに変える
  2. このロールにアクセス可能な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: writecontents: 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 のサイトに対する認識を理解し、改善できるようになります。

Search Console の概要

サイトを登録するにはサイトを所有することを証明する必要がある。証明方法はいくつかあるが、今回は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 "/*"