Blog

Deploy S3 hosted application using CodePipeline

14 Mar, 2023
Xebia Background Header Wave

A while ago I wrote how you can host your own single page application on S3. But how will you get your application on the S3 bucket? There are a couple of options here, you could upload it by hand? But we both know that is not the real solution here. No we want to automate this process! In this blog post I will show you how you can automate this using AWS CodePipeline.

The Pipeline

AWS Codepipeline uses different stages, I often use Source, Build and Deploy stages. In some cases I split the Deploy stage into a Development, Testing, Acceptance and Production deployment (also known as DTAP). If you want to know more about how you can set this up you can read my building applications with pipelines blog. But in the end it is up to you and what makes sense to your use-case.

When you deploy your infrastructure using CloudFormation. You can make use of the outputs within the CodePipeline. Another option is to use a naming convention. I like to use the outputs as it removes the need to define a name upfront. Making it more robust when you re-use snippets or deploy your infrastructure more than once.

Outputs:
  ApplicationBucketName:
    Value: !Ref ApplicationBucket

The next thing you need to define is a namespace on the action that deploys your infrastructure.

- Name: ExecuteChangeSet
  Region: eu-west-1
  RunOrder: 2
  RoleArn: !Sub arn:aws:iam::${DevelopmentAccountId}:role/cross-account-role
  Namespace: DevelopmentVariables
  ActionTypeId:
      Category: Deploy
      Owner: AWS
      Provider: CloudFormation
      Version: "1"
  Configuration:
      ActionMode: CHANGE_SET_EXECUTE
      RoleArn: !Sub arn:aws:iam::${DevelopmentAccountId}:role/cloudformation-execution-role
      StackName: !Sub ${ProjectName}-development
      ChangeSetName: !Sub ${ProjectName}-development-ChangeSet

By default CodePipeline will load the outputs in the given namespace. In this example that is DevelopmentVariables, so the ApplicationBucketName is available as: #{DevelopmentVariables.ApplicationBucketName}.

Deploy to S3

AWS provides a S3 Deploy action you can use this action to deploy an artifact in your pipeline to S3. You can create this artifact in a  CodeBuild Project or you can use the source artifact. 

I am using a cross account deployment strategy. For this reason I need to allow my cross-account-role to allow uploads to the S3 buckets. I am using a BucketPolicy for this:

- Sid: AllowPipelineToUpload
  Effect: Allow
  Action: s3:PutObject
  Principal:
    AWS: !Sub arn:aws:iam::${AWS::AccountId}:role/cross-account-role
  Resource: !Sub ${ApplicationBucket.Arn}/*

Note that the role and the bucket are living in the same account. The pipeline lives in my build/deployment account. So in the pipeline we need to configure the upload to S3:

- Name: Ireland-Uploadapplication
  Region: eu-west-1
  RunOrder: 3
  RoleArn: !Sub arn:aws:iam::${DevelopmentAccountId}:role/cross-account-role
  InputArtifacts:
    - Name: application
  ActionTypeId:
    Category: Deploy
    Owner: AWS
    Provider: S3
    Version: "1"
  Configuration:
    BucketName: "#{DevelopmentVariables.ApplicationBucketName}"
    Extract: true
    CacheControl: max-age=0, no-cache, no-store, must-revalidate

In this example I will use my artifact called application and extract the content in the S3 bucket. It will assume the role that we specify as RoleArn to perform the upload. I will also set the CacheControl so that CloudFront knows that it needs to serve the new content.

Conclusion

It is easy to use the S3 Deploy action to upload your content to a S3 bucket. It removes the need of using a CodeBuild project to upload the content. This will reduce cost and complexity, by not maintaining an extra CodeBuild project.

Joris Conijn
Joris has been working with the AWS cloud since 2009 and focussing on building event driven architectures. While working with the cloud from (almost) the start he has seen most of the services being launched. Joris strongly believes in automation and infrastructure as code and is open to learn new things and experiment with them, because that is the way to learn and grow. In his spare time he enjoys running and runs a small micro brewery from his home.
Questions?

Get in touch with us to learn more about the subject and related solutions

Explore related posts