AWS環境におけるHUGOの自動デプロイ手順

HUGOをAWS環境で自動デプロイするための手順です。デプロイを自動化してみたい方は参考にしてみてください。

Ishiguro Suguru

今までHUGOのデプロイは手動で行っていました。 しかし毎回コマンドを実行してS3にアップロードする作業が面倒になり自動化したくなりました。 今回は自動化を行った際の手順を紹介したいと思います。(前提としてAWS利用)

手動によるHUGOリリース作業概要

手動で行う場合は以下の手順で実施していました。

  1. HUGOプロジェクトのビルド
  2. ビルドして生成したファイルをS3にアップロード
  3. CloudFrontのキャッシュクリア

これらの作業を"CodeBuild”, “CodePipeline"を使用して自動化してみました。 今回紹介する内容は前提として"CodeCommite"を使用しています。

HUGOリリース自動化の作業概要

先ほどの作業を自動化するための手順は以下となります。 詳細について順を追って説明したいと思います。

  1. buildspec.yml作成
  2. CodeBuild設定
  3. CodePipeline設定
  4. IAM Role設定

1. buildspec.yml作成

まずはbuildspec.ymlファイルを作成します。 このファイルはCodeBuildがビルドを実行するために使用します。 詳しくは公式ドキュメントに記載があるため簡単に説明します。

以下のソースがHUGOをビルドするためのbuildspec.ymlファイルになります。 前提としてビルドするAWS環境はS3に静的ファイルを配置して、CloudFront経由でアクセスする構成になっています。

  • buildspec.yml
version: 0.2

env:
  variables:
    # HUGOのバージョン
    hugo_version: "0.61.0"
    # ビルドしたファイルをアップロードするS3バケット名
    bucket_name: "XXXXXXXXX"
    # S3と紐付けているCloudFrontのID
    Distribution_ID: "XXXXXXXX"

phases:
  install:
    runtime-versions:
      golang: 1.13
    commands:
      - curl -Ls https://github.com/gohugoio/hugo/releases/download/v${hugo_version}/hugo_extended_${hugo_version}_Linux-64bit.tar.gz -o /tmp/hugo.tar.gz
      - tar xf /tmp/hugo.tar.gz -C /tmp
      - mv /tmp/hugo /usr/bin/hugo
      - rm -rf /tmp/hugo*
  build:
    commands:
      - hugo --minify
  post_build:
    commands:
      - aws s3 sync --delete public/ s3://${bucket_name}
      - aws cloudfront create-invalidation --distribution-id ${Distribution_ID} --paths "/*"

コードを見ればなんとなくわかる方もいると思いますが、このファイルではCodeBuildが実行するコマンドを記述しています。 CodeBuildのコマンド実行するフェーズは分けることができ、installでビルドするために必要なライブラリなどの環境準備、buildで対象プロジェクトのビルド、post_buildでビルド後の追加処理を記述します。

今回はビルドしたファイルをS3にアップロードしたいため、aws s3 syncを実行します。 このコマンドでCodeBuild側のサーバーにビルドされたファイル(publicフォルダー)とS3の同期をとることができます。 また、CloudFront側のキャッシュを削除する必要があるためaws cloudfront create-invalidationを実行します。

環境に合わせてenvの値を入力して、本ファイルはソースディレクトリのルートに配置してください。 配置したファイルはCodeCommitにプッシュしておきましょう。

2. CodeBuild設定

次にCodeBuildの設定作業を行います。 AWSコンソールからCodeBuildを開き"ビルドプロジェクトを作成する"をクリックします。

画面が長いですがCodeBuildの設定を行っていきます。 デフォルトの設定から変更している項目は以下になります。

  • プロジェクトの設定:任意のプロジェクト名を入力します
  • ソース:CodeCommitにあるプログラムをビルドしたいため”CodeCommit”を選択します
  • 環境:ビルドするサーバー環境を選択します

ソースはCodeCommitの他に以下を選択できます。

  • Amazon S3
  • GitHub
  • Bitbucket
  • GitHub Enterprise

環境についてはどれを選んでも問題ないと思いますが、とりあえず”Amazon Linux 2”を選択して最新のイメージ/バージョンにしています。 設定完了後に"ビルドプロジェクトを作成する"をクリックします。

以下のようにビルドプロジェクト一覧に作成したプロジェクトが表示されます。

3. CodePipeline設定

次にCodePipeline設定作業を行います。 CodePipelineでCodeCommitのプッシュを検知し、CodeBuildをキックします。 AWSコンソールもしくは先ほどの画面のサイドリンク メニューからCodePipelineを開き"パイプラインを作成する"をクリックします。

まずはパイプライン名とロール設定を行います。 今回はロールを新規に作成しています。 設定後”次に”をクリックします。

パイプラインのソースステージを選択します。 CodeCommitを選択して対象のリポジトリ/ブランチを選択して”次に”をクリックします。 ソースプロバイダーは以下からも選択可能です。

  • Amazon ECR
  • Amazon S3
  • Bitbucket
  • GitHub

次にビルド環境の設定を行います。 CodeBuildを選択して先ほど作成したプロジェクト名を設定します。 設定後”次に”をクリックします。

本サイトの場合、デプロイステージの追加は不要のため”導入段階をスキップ”をクリックします。

確認画面が表示されます。 問題なければ”パイプラインを作成する”をクリックします。

以上でパイプラインの作成は完了です。 パイプライン作成後、自動的にパイプラインが実行されますが現時点ではおそらくエラーになるかと思います。 S3とCloudFrontを操作するための権限が不足しているため、IAM Role設定を行う必要があります。

4. IAM Role設定

おそらく現時点だと以下のエラーコードがCodeBuildのビルドログで出力されていると思います。 先ほどCodeBuildで作成したポリシーには権限が不足しているため追加で設定を行いましょう。

Phase context status code: COMMAND_EXECUTION_ERROR Message: Error while executing command: aws s3 sync --delete public/ s3://${bucket_name}. Reason: exit status 1

作成したロールcodebuild-HUGO_BUILD_itsys-tech-service-roleに対して以下のポリシーを設定します。

{
    "Version": "2012-10-17",
    "Statement": [
        /* 中略 */
        {
            "Effect": "Allow",
            "Resource": [
                "arn:aws:s3:::codepipeline-ap-northeast-1-*",
                "arn:aws:s3:::XXXXXXXXXXXX*"
            ],
            "Action": [
                "s3:PutObject",
                "s3:GetObject",
                "s3:GetObjectVersion",
                "s3:GetBucketAcl",
                "s3:GetBucketLocation",
                "s3:DeleteObject",
                "s3:ListBucket"
            ]
        },
        /* 中略 */
        {
            "Sid": "CluoudFrontInvalidation",
            "Effect": "Allow",
            "Action": "cloudfront:CreateInvalidation",
            "Resource": "arn:aws:cloudfront::0000000000:distribution/XXXXXXXXXX"
        }
    ]
}

IAM Role設定を行い、再度パイプラインを実行すれば正常終了すると思います。

最後に

以上でビルドとデプロイの自動化ができました。 CodePipelineを使用せずにCodeBuildから実施する方法もあるみたいですが、このあたりはよくわからなったため時間があれば対応して行きたいといます。 (”プライマリソースのウェブフックイベント”というメニューが見つからなかった…)

comments powered by Disqus