AWS CodePipeline Step by Step with .NET Core - Repository の作成

Pipelineの作成に伴いまずはRepositoryが必要となるので、今回はCodeCommitを利用。

AWSTemplateFormatVersion: 2010-09-09
Description: AWS CI/CD - CodeCommit

Parameters:
  RepositoryDescription:
    Type: String
    Default: Repository for CI/CD Blog
  RepositoryName:
    Type: String
    Default: ci_cd_blog
  UserName:
    Type: String
    Default: ci_cd_blog_user

Resources:
  Repository:
    Type: AWS::CodeCommit::Repository
    Properties:
      RepositoryDescription: !Ref RepositoryDescription
      RepositoryName: !Ref RepositoryName

  User:
    Type: AWS::IAM::User
    Properties:
      Policies: 
        - PolicyName: !Sub ${UserName}_policy
          PolicyDocument:
            Version: 2012-10-17
            Statement:
                - Effect: Allow
                  Action:
                    - codecommit:GitPull
                    - codecommit:GitPush
                  Resource: !GetAtt Repository.Arn
      UserName: !Ref UserName

Outputs:
  CiCdBlogRepositoryId:
    Value: !Ref Repository
    Export:
      Name: CiCdBlogRepositoryId
  CiCdBlogRepositoryArn:
    Value: !GetAtt Repository.Arn
    Export:
      Name: CiCdBlogRepositoryArn
  CiCdBlogRepositoryCloneUrlHttp:
    Value: !GetAtt Repository.CloneUrlHttp
    Export:
      Name: CiCdBlogRepositoryCloneUrlHttp
  CiCdBlogRepositoryCloneUrlSsh:
    Value: !GetAtt Repository.CloneUrlSsh
    Export:
      Name: CiCdBlogRepositoryCloneUrlSsh
  CiCdBlogRepositoryName:
    Value: !GetAtt Repository.Name
    Export:
      Name: CiCdBlogRepositoryName

そこに対してPushするコードは、今回は.NET Core でLambda Templateを使用。

dotnet.microsoft.com

docs.aws.amazon.com

.NET Core をインストール後、LambdaのTemplateをインストールし、Projectを作成

dotnet new serverless.image.AspNetCoreWebAPI -n web

.NET のビルドをLocalでは行わないので、とりあえずコードのみ欲しい場合は下記のTemplateをCloudFormationで流してCodeCommitにコードを投入。コード作成後、不要になる為Stack毎消すことをお勧めします。

AWSTemplateFormatVersion: 2010-09-09
Description: AWS CI/CD - Repository Initialize

Parameters:
  ImageId:
    Type: AWS::EC2::Image::Id
    Default: ami-09b23e84684bb7149
    Description: ubuntu22.04
  InstanceType:
    Type: String
    Default: t4g.micro
  RepositoryName:
    Type: String
    Default: ci_cd_blog

Resources:
  Instance:
    Type: AWS::EC2::Instance
    Properties: 
      BlockDeviceMappings: 
        - DeviceName: /dev/sda1
          Ebs: 
            VolumeType: gp3
            DeleteOnTermination: true
            VolumeSize: 8
      CreditSpecification: 
        CPUCredits: standard
      ImageId: !Ref ImageId
      IamInstanceProfile: !Ref InstanceProfile
      InstanceType: !Ref InstanceType
      SecurityGroupIds: 
        - !Ref SecurityGroup
      UserData: 
        Fn::Base64:
          !Sub | 
            #!/bin/bash
            apt-get update
            apt-get -y upgrade
            apt-get install -y git unzip dotnet-sdk-6.0
            curl "https://awscli.amazonaws.com/awscli-exe-linux-aarch64.zip" -o "awscliv2.zip"
            unzip -q awscliv2.zip
            ./aws/install
            export HOME=/home/ubuntu
            dotnet new -i Amazon.Lambda.Templates
            mkdir $HOME/work && cd $HOME/work
            dotnet new serverless.image.AspNetCoreWebAPI -n web
            dotnet new gitignore
            git config --global user.name ubuntu
            git config --global user.email ubuntu@example.com
            git config --global credential.helper '!aws codecommit credential-helper $@'
            git config --global credential.UseHttpPath true
            git init -b main
            git add -A
            git commit -m "Newly Created"
            git remote add origin https://git-codecommit.${AWS::Region}.amazonaws.com/v1/repos/${RepositoryName}
            git push origin main
            shutdown -h now
  SecurityGroup:
    Type: AWS::EC2::SecurityGroup
    Properties:
      GroupDescription: ci_cd_blog_sg

  InstanceProfile:
    Type: AWS::IAM::InstanceProfile
    Properties:
      Roles: 
        - !Ref RoleForInstanceProfile

  RoleForInstanceProfile:
    Type: AWS::IAM::Role
    Properties:
      AssumeRolePolicyDocument:
        Version: 2012-10-17
        Statement: 
          - Effect: Allow
            Principal: 
              Service: 
                - ec2.amazonaws.com
            Action: 
              - sts:AssumeRole

  PolicyForEc2:
    Type: AWS::IAM::Policy
    Properties:
      PolicyDocument:
        Version: 2012-10-17
        Statement:
          -  Effect: Allow
             Action:
                - codecommit:GitPull
                - codecommit:GitPush
             Resource: !Sub arn:${AWS::Partition}:codecommit:${AWS::Region}:${AWS::AccountId}:${RepositoryName}
      PolicyName: ci_cd_blog_iam_policy
      Roles: 
        - !Ref RoleForInstanceProfile

  # Schedule for Stop Ec2
  ScheduleGroup:
    Type: AWS::Scheduler::ScheduleGroup

  Schedule:
    Type: AWS::Scheduler::Schedule
    Properties:
      FlexibleTimeWindow: 
        Mode: 'OFF'
      GroupName: !Ref ScheduleGroup
      ScheduleExpression: cron(00 20 ? * * *)
      ScheduleExpressionTimezone: Japan
      State: ENABLED
      Target: 
        Arn: !Sub arn:${AWS::Partition}:scheduler:::aws-sdk:ec2:stopInstances
        Input:
          !Sub
          - | 
            {
              "InstanceIds": ["${InstanceId1}"]
            }
          - InstanceId1: !Ref Instance
        RoleArn: !GetAtt RoleForSchedule.Arn

  RoleForSchedule:
    Type: AWS::IAM::Role
    Properties:
      AssumeRolePolicyDocument:
        Version: 2012-10-17
        Statement: 
          - Effect: Allow
            Principal: 
              Service: 
                - scheduler.amazonaws.com
            Action: 
              - sts:AssumeRole

  PolicyForSchedule:
    Type: AWS::IAM::Policy
    Properties:
      PolicyDocument:
        Version: 2012-10-17
        Statement:
          -  Effect: Allow
             Action:
                - ec2:StopInstances
             Resource: !Sub arn:${AWS::Partition}:ec2:${AWS::Region}:${AWS::AccountId}:instance/${Instance}
      PolicyName: ci_cd_blog_iam_policy
      Roles: 
        - !Ref RoleForSchedule

Code Commitにコードが投入されていれば下準備は完了。