CodeCommitにPushする度に、S3にバックアップする

CodeCommitにPushする度にS3にバックアップする

CodeCommitにPushする度に、S3にバックアップする

以下のAWS公式ページで、 CodeCommitの内容をS3にバックアップする方法が紹介されています。

https://docs.aws.amazon.com/ja_jp/prescriptive-guidance/latest/patterns/automate-event-driven-backups-from-codecommit-to-amazon-s3-using-codebuild-and-cloudwatch-events.html

この構成の意義ですが、以下のように説明されています。

このパターンは、 CodeCommit リポジトリに変更が加えられた後、Amazon Simple Storage Service (Amazon S3) バケットに自動的にバックアップする方法を示しています。 CodeCommit リポジトリが後で削除されても、 point-in-time このバックアップ戦略は回復オプションを提供します。

CodeBuild とイベントを使用して、から Amazon S3 CodeCommit CloudWatch へのイベント駆動型バックアップを自動化

本ページでは、上記を参考にした構成をご紹介します。

構築する環境

Diagram of backup to S3 every time you push to CodeCommit.

ソースコードリポジトリとして、CodeCommitを使用します。

CodeBuildでは、CodeCommit内のソースコードをcloneします。
取得したファイルをZIP化して、S3バケットに保存します。

CodeBuildが実行されるきっかけですが、EventBridgeを使用します。
CodeCommitのmasterブランチが更新される度に、CodeBuildを実行するように、EventBridgeルールを設定します。

CloudFormationテンプレートファイル

上記の構成をCloudFormationで構築します。
以下のURLにCloudFormationテンプレートを配置しています。

https://github.com/awstut-an-r/awstut-fa/tree/main/136

テンプレートファイルのポイント解説

S3バケット

Resources:
  Bucket:
    Type: AWS::S3::Bucket
    Properties:
      BucketName: !Ref Prefix
      AccessControl: Private
Code language: YAML (yaml)

ソースコードのバックアップ先として使用するS3バケットです。

特別な設定は不要です。

CodeCommit

Resources:
  CodeCommitRepository:
    Type: AWS::CodeCommit::Repository
    Properties:
      RepositoryName: !Ref Prefix
Code language: YAML (yaml)

ソースコードリポジトリです。

こちらも特別な設定は不要です。

CodeBuild

Resources:
  CodeBuildProject:
    Type: AWS::CodeBuild::Project
    Properties:
      Artifacts:
        Type: NO_ARTIFACTS
      Cache:
        Type: NO_CACHE
      Environment:
        ComputeType: !Ref ProjectEnvironmentComputeType
        EnvironmentVariables:
          - Name: BRANCH_NAME
            Type: PLAINTEXT
            Value: !Ref BranchName
          - Name: BUCKET_NAME
            Type: PLAINTEXT
            Value: !Ref BucketName
          - Name: REPO_REGION
            Type: PLAINTEXT
            Value: !Ref AWS::Region
          - Name: REPOSITORY_NAME
            Type: PLAINTEXT
            Value: !GetAtt CodeCommitRepository.Name
        Image: !Ref ProjectEnvironmentImage
        ImagePullCredentialsType: CODEBUILD
        Type: !Ref ProjectEnvironmentType
        PrivilegedMode: true
      LogsConfig:
        CloudWatchLogs:
          Status: DISABLED
        S3Logs:
          Status: DISABLED
      Name: !Ref Prefix
      ServiceRole: !GetAtt CodeBuildRole.Arn
      Source:
        Type: NO_SOURCE
        BuildSpec: !Sub |
          version: 0.2

          phases:
            install:
              commands:
                - pip install git-remote-codecommit
            build:
              commands:
                - env
                - git clone -b $BRANCH_NAME codecommit::$REPO_REGION://$REPOSITORY_NAME
                - dt=$(date '+%d-%m-%Y-%H:%M:%S');
                - echo "$dt"
                - zip -yr $dt-$REPOSITORY_NAME-backup.zip ./
                - aws s3 cp $dt-$REPOSITORY_NAME-backup.zip s3://$BUCKET_NAME/
      Visibility: PRIVATE
Code language: YAML (yaml)

CodeBuildに関する基本的な事項は、以下のページをご確認ください。

あわせて読みたい
CodePipelineを使ってCodeCommitプッシュをトリガーにしてECRにイメージをプッシュする 【CodePipelineを使ってCodeCommitプッシュをトリガーにしてECRにイメージをプッシュする】 CodePipelineを使用することによって、CI/CD構成を構築することができます。...

ポイントを3つ取り上げます。

1点目はArtifactsプロパティです。
今回はアーティファクトはありませんので、本プロパティに「NO_ARTIFACTS」を指定します。

2点目はEnvironmentVariablesプロパティです。
CodeBuild内の環境変数を設定できます。
今回は先述のS3バケット名や、CodeCommitリポジトリ名等を指定します。

3点目はBuildSpecプロパティです。
本プロパティでBuildSpec.ymlの内容を直接記述することができます。
こちらについては、以下のページを参考に記載しています。

https://docs.aws.amazon.com/ja_jp/prescriptive-guidance/latest/patterns/automate-event-driven-backups-from-codecommit-to-amazon-s3-using-codebuild-and-cloudwatch-events.html#automate-event-driven-backups-from-codecommit-to-amazon-s3-using-codebuild-and-cloudwatch-events-additional

実行する内容ですが、git-remote-codecommitをインストール後、CodeCommitからソースコードをcloneします。
取得したコード類をZIP化し、S3バケットにアップロードします。

以下はCodeBuild用のIAMロールです。

Resources:
  CodeBuildRole:
    Type: AWS::IAM::Role
    Properties:
      AssumeRolePolicyDocument:
        Version: 2012-10-17
        Statement:
          - Effect: Allow
            Principal:
              Service:
                - codebuild.amazonaws.com
            Action:
              - sts:AssumeRole
      Policies:
        - PolicyName: CodeBuildExecutionPolicy
          PolicyDocument:
            Version: 2012-10-17
            Statement:
              - Effect: Allow
                Action:
                  - s3:PutObject
                Resource:
                  - !Sub "arn:aws:s3:::${BucketName}/*"
              - Effect: Allow
                Action:
                  - codecommit:GitPull
                Resource:
                  - !GetAtt CodeCommitRepository.Arn
Code language: YAML (yaml)

CodeCommitからソースコードを取得する権限と、S3にオブジェクトをアップロードする権限を与えます。

EventBridge

Resources:
  EventsRule:
    Type: AWS::Events::Rule
    Properties:
      EventPattern:
        source:
          - aws.codecommit
        detail-type:
          - CodeCommit Repository State Change
        resources:
          - !GetAtt CodeCommitRepository.Arn
        detail:
          event:
            - referenceCreated
            - referenceUpdated
          referenceType:
            - branch
          referenceName:
            - !Ref BranchName
      Name: !Ref Prefix
      Targets:
        - Arn: !GetAtt CodeBuildProject.Arn
          Id: !Sub "${Prefix}-CodeBuild"
          InputTransformer:
            InputPathsMap:
              account: $.account
              referenceType: $.detail.referenceType
              referenceName: $.detail.referenceName
              region: $.region
              repositoryName: $.detail.repositoryName
            InputTemplate: |
              {"referenceType":"<referenceType>","region":"<region>","repositoryName":"<repositoryName>","account":"<account>","referenceName":"<referenceName>"}
          RoleArn: !GetAtt EventsRuleRole.Arn
Code language: YAML (yaml)

CodeCommitのmasterブランチに変更があった場合、これをトリガーにしてCodeBuildを実行させます。

ルールや入力トランスフォーマーに関する記述についても、以下のページを参考にしました。

https://docs.aws.amazon.com/ja_jp/prescriptive-guidance/latest/patterns/automate-event-driven-backups-from-codecommit-to-amazon-s3-using-codebuild-and-cloudwatch-events.html#automate-event-driven-backups-from-codecommit-to-amazon-s3-using-codebuild-and-cloudwatch-events-additional

以下がEventBridge用のIAMロールです。

Resources:
  EventsRuleRole:
    Type: AWS::IAM::Role
    Properties:
      AssumeRolePolicyDocument:
        Version: 2012-10-17
        Statement:
          - Effect: Allow
            Principal:
              Service:
                - events.amazonaws.com
            Action:
              - sts:AssumeRole
      Policies:
        - PolicyName: PipelineExecutionPolicy
          PolicyDocument:
            Version: 2012-10-17
            Statement:
              - Effect: Allow
                Action:
                  - codebuild:StartBuild
                Resource:
                  - !GetAtt CodeBuildProject.Arn
Code language: YAML (yaml)

CodeBuildを開始するための権限を与えます。

環境構築

CloudFormationを使用して、本環境を構築し、実際の挙動を確認します。

CloudFormationスタックを作成し、スタック内のリソースを確認する

CloudFormationスタックを作成します。
スタックの作成および各スタックの確認方法については、以下のページをご確認ください。

あわせて読みたい
CloudFormationのネストされたスタックで環境を構築する 【CloudFormationのネストされたスタックで環境を構築する方法】 CloudFormationにおけるネストされたスタックを検証します。 CloudFormationでは、スタックをネストす...

各スタックのリソースを確認した結果、今回作成された主要リソースの情報は以下の通りです。

  • S3バケット:fa-136
  • CodeCommit:fa-136
  • CodeBuild:fa-136
  • EventBridge:fa-136

作成されたリソースをAWS Management Consoleから確認します。

CodeCommitを確認します。

Detail of CodeCommit 1.

確かにリポジトリが作成されています。

EventBridgeを確認します。

Detail of EventBridge 1.
Detail of EventBridge 2.

CodeCommitの作成・更新がトリガーの条件に設定されています。
ターゲットには、CodeBuildが指定されていることもわかります。

CodeBuildを確認します。

Detail of CodeBuild 1.

CloudFormationテンプレートで指定した通りに設定されていることがわかります。

動作確認

準備が整いました。

まずCodeCommitをプルします。

$ git clone https://git-codecommit.ap-northeast-1.amazonaws.com/v1/repos/fa-136
Cloning into 'fa-136'...
warning: You appear to have cloned an empty repository.
Code language: Bash (bash)

空のリポジトリがプルされました。

リポジトリにテストファイルを加えます。

touch ./fa-136/test.txt
Code language: Bash (bash)

テストファイルをCodeCommitにプッシュします。

(master) $ git add .

(master) $ git commit -m "first commit"
[master (root-commit) 5a16cf1] first commit
...
 1 file changed, 9 insertions(+)
 create mode 100644 test.txt

(master) $ git push
...
 * [new branch]      master -> master
Code language: Bash (bash)

正常にプッシュできました。

改めてCodeCommitを確認します。

Detail of CodeCommit 2.

確かにテストファイルがプッシュされています。
ファイルのプッシュをトリガーとして、EventBridgeが動作して、CodeBuildが開始されるはずです。

しばらく待機してからCodeBuildを確認します。

Detail of CodeBuild 2.

確かにCodeBuildの実行が正常に完了しています。

S3バケットを確認します。

Detail of S3 1.

確かにZIPファイルがアップロードされています。

ダウンロードして、内容を確認します。

$ aws s3 cp s3://fa-136/25-05-2023-11:40:34-fa-136-backup.zip .
download: s3://fa-136/25-05-2023-11:40:34-fa-136-backup.zip to ./25-05-2023-11:40:34-fa-136-backup.zip

$ unzip -l 25-05-2023-11:40:34-fa-136-backup.zip
Archive:  25-05-2023-11:40:34-fa-136-backup.zip
  Length      Date    Time    Name
---------  ---------- -----   ----
        0  05-25-2023 11:40   fa-136/
        0  05-25-2023 11:40   fa-136/.git/
        0  05-25-2023 11:40   fa-136/.git/branches/
       73  05-25-2023 11:40   fa-136/.git/description
        0  05-25-2023 11:40   fa-136/.git/hooks/
      478  05-25-2023 11:40   fa-136/.git/hooks/applypatch-msg.sample
      896  05-25-2023 11:40   fa-136/.git/hooks/commit-msg.sample
     4726  05-25-2023 11:40   fa-136/.git/hooks/fsmonitor-watchman.sample
      189  05-25-2023 11:40   fa-136/.git/hooks/post-update.sample
      424  05-25-2023 11:40   fa-136/.git/hooks/pre-applypatch.sample
     1643  05-25-2023 11:40   fa-136/.git/hooks/pre-commit.sample
      416  05-25-2023 11:40   fa-136/.git/hooks/pre-merge-commit.sample
     1374  05-25-2023 11:40   fa-136/.git/hooks/pre-push.sample
     4898  05-25-2023 11:40   fa-136/.git/hooks/pre-rebase.sample
      544  05-25-2023 11:40   fa-136/.git/hooks/pre-receive.sample
     1492  05-25-2023 11:40   fa-136/.git/hooks/prepare-commit-msg.sample
     2783  05-25-2023 11:40   fa-136/.git/hooks/push-to-checkout.sample
     3650  05-25-2023 11:40   fa-136/.git/hooks/update.sample
        0  05-25-2023 11:40   fa-136/.git/info/
      240  05-25-2023 11:40   fa-136/.git/info/exclude
        0  05-25-2023 11:40   fa-136/.git/refs/
        0  05-25-2023 11:40   fa-136/.git/refs/heads/
       41  05-25-2023 11:40   fa-136/.git/refs/heads/master
        0  05-25-2023 11:40   fa-136/.git/refs/tags/
        0  05-25-2023 11:40   fa-136/.git/refs/remotes/
        0  05-25-2023 11:40   fa-136/.git/refs/remotes/origin/
       32  05-25-2023 11:40   fa-136/.git/refs/remotes/origin/HEAD
       23  05-25-2023 11:40   fa-136/.git/HEAD
      260  05-25-2023 11:40   fa-136/.git/config
        0  05-25-2023 11:40   fa-136/.git/objects/
        0  05-25-2023 11:40   fa-136/.git/objects/pack/
        0  05-25-2023 11:40   fa-136/.git/objects/info/
        0  05-25-2023 11:40   fa-136/.git/objects/e6/
       15  05-25-2023 11:40   fa-136/.git/objects/e6/9de29bb2d1d6434b8b29ae775ad8c2e48c5391
        0  05-25-2023 11:40   fa-136/.git/objects/ac/
      159  05-25-2023 11:40   fa-136/.git/objects/ac/24cc10720d0e07a8d3fbd16767ef704663d5ee
        0  05-25-2023 11:40   fa-136/.git/objects/5e/
       53  05-25-2023 11:40   fa-136/.git/objects/5e/fb9bc29c482e023e40e0a2b3b7e49cec842034
      114  05-25-2023 11:40   fa-136/.git/packed-refs
        0  05-25-2023 11:40   fa-136/.git/logs/
        0  05-25-2023 11:40   fa-136/.git/logs/refs/
        0  05-25-2023 11:40   fa-136/.git/logs/refs/remotes/
        0  05-25-2023 11:40   fa-136/.git/logs/refs/remotes/origin/
      179  05-25-2023 11:40   fa-136/.git/logs/refs/remotes/origin/HEAD
        0  05-25-2023 11:40   fa-136/.git/logs/refs/heads/
      179  05-25-2023 11:40   fa-136/.git/logs/refs/heads/master
      179  05-25-2023 11:40   fa-136/.git/logs/HEAD
      137  05-25-2023 11:40   fa-136/.git/index
        0  05-25-2023 11:40   fa-136/test.txt
---------                     -------
    25197                     49 filesCode language: JavaScript (javascript)

確かにテストファイルを含むリポジトリの内容がバックアップされていることがわかります。

まとめ

CodeCommitにPushする度に、S3にバックアップを取る方法を確認しました。