Continuous Deployment with AWS Code Pipeline, React JS, and s3
Continuous deployment is a fantastic system to automatically deploy your application to a production environment. In this article you’ll learn how to set up a CD pipeline to automatically deploy a React JS application.
Prerequisites
Before you start you’ll need a React JS application with a Github repository, and an Amazon Web Services Account account. If you do not have a React application you can easily make one using create react app.
AWS Services
In this article I’ll be using three different AWS services:
- S3 — Simple storage service, this will hold your React app’s files and will act as a static website host.
- Code Pipeline —This is a sub-service of AWS Developer Tools and will allow you to configure and control your CD workflow.
- Code Build — Another sub-service of Developer Tools, this will automatically build your code into a production state ready for deployment.
Pricing
The services used here are very inexpensive. S3 will charge $0.023 per GB, Code Pipeline will charge $1 per month per active pipeline, and Code Build charges $0.005 per build minute. You can find more information here:
- S3: https://aws.amazon.com/s3/pricing
- Code Pipeline: https://aws.amazon.com/codepipeline/pricing
- Code Build: https://aws.amazon.com/codebuild/pricing
Step 1 — Setting up your s3 bucket
First you need to create an s3 bucket and configure it to host static websites. If you already have this setup then you can skip to step 2.
After navigating to the s3 console you’ll want to click on the “+ Create Bucket” button shown here:
After that you’ll be prompted to enter some basic information about your bucket. The only thing you need to do here is enter a name and click on “Create” at the bottom left of the popup. Keep in mind that s3 bucket names must be globally unique, so you’ll need to enter a name that no one else has used.
Now you can click on your s3 bucket to navigate into it. It’s now time to configure it to host static websites correctly.
The first step is to tell s3 that this bucket should host a static website. To do that you can go to the “Properties” tab, select “Static website hosting,” and select “Use this bucket to host a website.” From there enter “index.html” into both the index and error document fields and then click “Save.” Your window should look like this:
Next you want to allow public access to your s3 bucket. For security reasons s3 will automatically block all public access. To disable this, navigate to “Permissions,” by default you should be at the “Block public access” tab. On the right is an edit button, and after clicking you can uncheck “Block all public access” on the left. Your screen should look like this:
Now save the settings with the “Save” button on the right. Next enter a bucket policy to allow each of your files to be read correctly. Navigate to the “Bucket Policy” tab and copy/paste this policy:
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "PublicReadGetObject",
"Effect": "Allow",
"Principal": "*",
"Action": "s3:GetObject",
"Resource": "arn:aws:s3:::YOUR_BUCKET_NAME_HERE/*"
}
]
}
Replace “YOUR_BUCKET_NAME_HERE” with your actual bucket name. My s3 bucket is named “cd-medium-article” so my working policy would be:
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "PublicReadGetObject",
"Effect": "Allow",
"Principal": "*",
"Action": "s3:GetObject",
"Resource": "arn:aws:s3:::cd-medium-article/*"
}
]
}
The final step in setting up your s3 bucket is to enable CORS. To do that simply navigate to the “CORS Configuration” tab and paste in the following script:
<?xml version="1.0" encoding="UTF-8"?>
<CORSConfiguration xmlns="http://s3.amazonaws.com/doc/2006-03-01/">
<CORSRule>
<AllowedOrigin>*</AllowedOrigin>
<AllowedMethod>GET</AllowedMethod>
</CORSRule>
</CORSConfiguration>
There’s nothing to change here. Simply click on the save button and you’re done configuring your bucket!
Step 2 —Setting up AWS CodePipeline
You should have noticed that you haven’t uploaded your React app to your bucket yet, and you won’t be doing that manually. By the end of this article you’ll have CodePipeline deploying your app to s3 automatically. Before you get started let me explain the steps CodePipeline will take to perform this task.
First you will tell CodePipeline where your code repository lives. This tutorial assumes you’re using Github. Now that CodePipeline knows of your repo and the branch you want to listen to, it will utilize Github webhooks to listen for changes on that branch.
When a change is detected in the branch, it will automatically pull your code to a server and attempt to build your code into a production-ready state. You won’t have to manually setup the server at all, just specify a few details such as the operating system.
If the build is successful then the code will be deployed to your s3 bucket. At this step your website is public and the job is done! So let’s get started.
Creating your pipeline
Navigate to the CodePipeline dashboard and click the orange “Create pipeline” button to get started. From there you can enter the name of your pipeline. For simplicity, I’ll be naming mine the same thing as my bucket: “cd-medium-tutorial” and clicking on the “Next” button.
Now add your “Stage Source.” This is telling CodePipeline where your repo lives. After selecting Github you will be prompted to login with your Github account. From there select your repo and your branch. It should look like this:
Adding a build stage
Next you have to configure AWS CodeBuild, which is another service that handles building your code. You want to select AWS CodeBuild. You’ll be promoted to create a project with the “Create project” button. Your screen should look like this:
Clicking “Create project” will open a new window. This is where you can specify the operating system for the build server, but first you need to specify a name. Mine is “cd-medium-tutorial.”
Under “Environment” I would suggest using “Amazon Linux 2” with a standard runtime and the “x86 3.0 image.” My page looks like this:
Use the default settings for everything else. Scrolling down you’ll find the “Continue to CodePipeline” button which will create the project and close the window.
Select your s3 bucket
You’re almost done. The next step is to tell CodePipeline where your production code should be deployed. Simply select the s3 bucket you created in step 1, and make sure you check “Extract file before deploy.” Without this your code will be in a zipped file that cannot be read by your website visitors. My page now looks like this:
Finally you will be in a review page. Simply scroll down and click on “Create Pipeline.”
You will automatically be sent to your pipeline’s progress page. Here you can watch what it is doing in real time. It will automatically try pulling from your repository and start building your code; however, this will fail. We’re missing one last step, that is configuring our “buildspec.yml” file which tells our build server what to do.
After your project initially fails to build you should see a screen like this:
Clicking on the highlighted ”Details” link will provide some information into what went wrong. Here we see what I previously mentioned. The “buildspec.yml” file does not exist yet.
In your project, create a new file called “buildspec.yml”. Inside the file paste the following configuration:
# Specifies what build spec version this file is.
# This helps AWS CodePipeline parse the file correctly.
# Keep this at 0.2
version: 0.2
# We can listen for specific phases and execute commands per phase.
phases:
# The build server won't have access to our node_modules folder
# This is because we have it inside of our .gitignore file
# To give our build server access, we can simply run "npm install"
pre_build:
commands:
- npm install
# Now we want to actually build our React app
build:
commands:
- npm run build
# Artifacts will specify what files will be uploaded to s3
# This will include all files within the "build" folder
artifacts:
files:
- '**/*'
discard-paths: no
base-directory: build
This configuration should be good to go and won’t require any modifying. You can learn more about how to edit the fine details in the build spec documentation.
Now push this file to your Github repo, which will then cause CodePipeline to automatically pull your code, build it, and deploy it. This time CodeBuild will know what to do and shouldn’t fail. You can use whatever GUI software you prefer; however, I prefer to use the command line:
CodePipeline will automatically detect the changes and will attempt the entire process again. After waiting a few minutes you should see all stages were successful:
Navigating back to s3 we see the bucket has been filled with the production-ready files as expected:
Finally, go into the “Properties” tab and then “Static website hosting.” Click on the URL to navigate to your own React app. Mine is http://cd-medium-article.s3-website-us-east-1.amazonaws.com. Your deployment worked successfully!