1. はじめに

このブログ(Cloud Steps)は、CloudFront+S3の構成で静的サイトを運用しています。

ブログを更新する際、S3にファイルをアップロードする必要がありますが、

ブログ更新の度にS3コマンドやAWSマネジメントコンソールからファイルアップロードするのは、少し面倒です。

なので、GitHubへのpushを検知し、CodeFamilyで自動的にS3にファイルの変更を自動で反映できるようしました。

2. Hugoとは

Hugoは、オープンソースの静的サイト生成ツールです。

マークダウンファイルを記述すれば、静的ファイルを生成することができ、簡単に、柔軟に、静的サイトを作成することができます。

サイトのデザインはコントリビューターが作成したテーマを適応すれば、自由に変更することができます。また、自分自身でテーマを作成することも可能なので、デザインにこだわりがある人はテーマを作成するのもいいでしょう。

※ Hugoの導入方法や利用方法は、この記事では対象外とします。

3. CodeFamilyとは

CodeFamilyとは、AWSが提供するソフトウェア開発とデプロイメントのライフサイクルを支援するサービス群の総称です。CodeFamilyは、公式なサービス名ではなく、一般的に以下のような 「Code」から始まるAWSサービス群 を指すことが多いです。

  • CodeFamily
    • CodePipeline
    • CodeBuild
    • CodeDeploy
    • CodeStar(非推奨)

このページでは、CodePipeline, CodeBuildについて書いていきます。

3.1 CodeBuild

CodeBuildは、フルマネージドの継続的インテグレーションサービスです。

アプリケーションコードのコンパイル、テストを実行などのビルド環境を提供するサービスです。

CodeBuildは、フルマネージドなサービスのため、ユーザーがビルドサーバーのプロビジョニングの必要なく、サーバーのパッチ適用などのメンテナンス作業を必要としません。

3.2 CodePipeline

CodePipeline は、継続的インテグレーション(CI)と継続的デリバリー(CD) を自動化するための パイプライン構築サービス です。アプリケーションのコードの変更が本番環境に届くまでの一連の流れ(ビルド、テスト、デプロイなど)をステージごとに視覚的に構成して自動化できます。

4. 構成図

hugo_codepipeline

5. パイプライン構築手順

  • 作成するリソース
    • AWSとGithubの接続
    • CodePipeline
    • CodeBuild
    • IAM

5.1 GitHubとCodePipelineを接続する

GitHubとCodePipelineの接続は、AWSマネージメントコンソールから行います。

  • AWSマネージメントコンソールの検索欄からCodeBuildと検索>左ペインの設定>接続>接続ボタンをクリック。
  • プロバイダー選択で「GitHub」を選択する。
  • 「GitHubアプリ接続を作成する」に任意の接続名を入力し、「GitHubに接続する」をクリックする。
  • GitHubの認証情報をきかれるので入力する。

5.2 CodePipelineを作成する

CodePipelineでステージを作成する。

Pipeline:
    Type: AWS::CodePipeline::Pipeline
    Properties:
      Name: !Sub "${ProjectName}-pipeline"
      RoleArn: !GetAtt PipelineRole.Arn
      ArtifactStore:
        Type: S3
        Location: !Ref ArtifactBucket
      Stages:
        - Name: Source
          Actions:
            - Name: GitHub_Source
              ActionTypeId:
                Category: Source
                Owner: AWS
                Provider: CodeStarSourceConnection
                Version: 1
              OutputArtifacts:
                - Name: SourceOutput
              Configuration:
                ConnectionArn: !Ref CodeStarConnectionArn
                FullRepositoryId: !Ref GitHubRepo
                BranchName: main
                DetectChanges: true
              RunOrder: 1
        - Name: Build
          Actions:
            - Name: CodeBuild
              ActionTypeId:
                Category: Build
                Owner: AWS
                Provider: CodeBuild
                Version: 1
              InputArtifacts:
                - Name: SourceOutput
              OutputArtifacts:
                - Name: BuildOutput
              Configuration:
                ProjectName: !Ref CodeBuildProject
              RunOrder: 1

5.3 CodeBuildを作成する


CodeBuildProject:
  Type: AWS::CodeBuild::Project
  Properties:
    Name: !Sub '${ProjectName}-hugo-deploy'
    ServiceRole: !GetAtt CodeBuildServiceRole.Arn
    Artifacts:
      Type: CODEPIPELINE
    Environment:
      Type: LINUX_CONTAINER
      ComputeType: BUILD_GENERAL1_SMALL
      Image: aws/codebuild/standard:7.0
    Source:
      Type: CODEPIPELINE
      BuildSpec: buildspec.yml

5.4 buildspec.yamlを作成する

buildspec.yamlとは、そもそもなんでしょうか。

CodeBuild のビルド仕様に関するリファレンスより

CodeBuild がビルドを実行するために使用するオペレーティングシステム、プログラミング言語ランタイム、およびツールの組み合わせを表します。

利用するbuildspec.yamlです。

version: 0.2

phases:
  install:
    runtime-versions:
      python: 3.12
    commands:
  build:
    commands:
      - echo "Uploading to S3..."
      # public配下のデータとバケットを同期する
      - aws s3 sync src/public/ s3://sre-blog-static-hosting/ --delete
  post_build:
    on-failure: ABORT
    # CloudFronのキャッシュ削除
    commands:
      aws cloudfront create-invalidation --distribution-id E3O57BDJL8K2FC  --paths "/*"

5.5 IAMロールを作成する


# Codepipeline用
PipelineRole:
  Type: AWS::IAM::Role
  Properties:
    AssumeRolePolicyDocument:
      Version: '2012-10-17'
      Statement:
        - Effect: Allow
          Principal:
            Service: codepipeline.amazonaws.com
          Action: sts:AssumeRole
    Policies:
      - PolicyName: CodePipelineCustomPolicy
        PolicyDocument:
          Version: '2012-10-17'
          Statement:
            - Effect: Allow
              Action:
                - codebuild:*
                - s3:*
                - codestar-connections:UseConnection
              Resource: "*"


# Codebuildのサービスロール
CodeBuildServiceRole:
    Type: AWS::IAM::Role
    DependsOn: ArtifactBucket
    Properties:
      RoleName: !Sub "CodeBuildServiceRole-${AWS::StackName}"
      AssumeRolePolicyDocument:
        Version: "2012-10-17"
        Statement:
          - Effect: Allow
            Principal:
              Service: codebuild.amazonaws.com
            Action: sts:AssumeRole
      Policies:
        - PolicyName: CodeBuildS3Access
          PolicyDocument:
            Version: "2012-10-17"
            Statement:
              - Effect: Allow
                Action:
                  - s3:ListBucket
                Resource: !Sub "arn:aws:s3:::${S3BucketName}"
              - Effect: Allow
                Action:
                  - s3:PutObject
                  - s3:DeleteObject
                  - s3:GetObject
                Resource: !Sub "arn:aws:s3:::${S3BucketName}/*"
              - Effect: Allow
                Action:
                  - s3:GetObject
                Resource: !Sub "arn:aws:s3:::${S3ArtifactBucketName}/*"
              - Effect: Allow
                Action: logs:*
                Resource: "*"
              - Effect: Allow
                Action: 
                  - cloudfront:CreateInvalidation 
                Resource: !Sub "arn:aws:cloudfront::${AWS::AccountId}:distribution/{CloudFrontDistributionID}"
              

ファイルを作成してgit pushすると作成されたパイプラインが自動的に作動します。

7. まとめ

Hugoで生成した静的サイトをAWSのCodePipelineとCodeBuildを使ってS3に自動デプロイを作成しました。GitHubへのpushをトリガーに、ビルドとS3アップロード、CloudFrontキャッシュの削除までを自動化できました。ファイルのアップロード作業が面倒になっていたので、ブログの運営が快適になりました。

8. 参考ページ