Deploy React application to AWS S3 using GitHub Actions
React is lightweight, S3 is cheap, GitHub Actions make deployment easier. Why don’t we try to use them together?
Why?
React became dominant in frontend development and it became first choice library for front-end development.
S3 is actually very cheap.
GitHub Actions abstract away a lot of complexity inside CI/CD workflows and they give us a chance to create easily understandable workflows faster.
Prerequisites
What we will need to make this work:
- Accounts: GitHub, Amazon Web Services
- Tools: git, nodejs, aws-cli, github-cli
Let’s get started
1. Create React application
npx create-react-app react-github-actions
2. Create GitHub repostory
gh repo create react-github-actions
NOTE: It will ask you if you want to create local project directory, say yes.
3. Push the changes to repo
cd react-github-actions
git push --set-upstream origin master
4. Set AWS credentials
Get AWS_ACCESS_KEY_ID
and AWS_SECRET_ACCESS_KEY
.
You can find out how to do it here.
export AWS_ACCESS_KEY_ID={value_of_access_key_id}
export AWS_SECRET_ACCESS_KEY={value_of_secret_access_key_id}
export AWS_DEFAULT_REGION=us-east-1
5. Set GitHub environment variables
And while we are here, let’s set these environment variables on GitHub repository too, since we will need them in our workflow.
Go to: https://github.com/{YOUR_USERNAME}/{YOUR_REPOSITORY}/settings/secrets
Enter:
AWS_ACCESS_KEY_ID
AWS_SECRET_ACCESS_KEY
AWS_DEFAULT_REGION
- Set them to the same values as in previous step.
6. Create S3 bucket
aws s3 mb s3://react-github-actions
7. Create GitHub workflow
In this scenario we would like to do three things on push of every tag to the git repository.
We define three essential steps, which are jobs inside workflow: build, deploy, release.
Create file workflow file:
touch react-github-actions/.github/workflows/react-github-actions-workflow.yml
You can find the whole workflow here. But I will go through more details in the text:
Let’s start with specifying to for it to run on every new tag push:
on:
push:
tags:
- '*'
The first step would be build
job which also tests the app and if test fail, then whole workflow will be stopped.
jobs:
build:
runs-on: ubuntu-latest steps:
- name: Clone repository
uses: actions/checkout@v2
- name: Use Node.js 12.x
uses: actions/setup-node@v1
with:
node-version: 12.x - name: Install dependencies
run: npm install
- name: Test
run: npm test
env:
CI: true - name: Generate build
run: npm run build # Share artifact inside workflow
- name: Share artifact inside workflow
uses: actions/upload-artifact@v1
with:
name: react-github-actions-build
path: build
Next job is deploy
which will basically take actualbuild
from previous job and upload it to S3 bucket using aws-cli
:
jobs:
build: ...
deploy:
runs-on: ubuntu-latest
# When application is successfully tested and build has been generated
# Then we can start with deployment
needs: build steps:
# Download previously shared build
- name: Get artifact
uses: actions/download-artifact@v1
with:
name: react-github-actions-build # Set the credentials from repository settings/secrets
- name: Configure AWS credentials
uses: aws-actions/configure-aws-credentials@v1
with:
aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
aws-region: ${{ secrets.AWS_DEFAULT_REGION }} # Copy the files from build folder to the S3 bucket
- name: Deploy to S3
run: aws s3 sync . s3://react-github-actions --acl public-read
working-directory: react-github-actions-build
Now we just zip the build
and officially release
it to the GitHub repository:
jobs:
build: ...
deploy: ...
release:
runs-on: ubuntu-latest
# We specify that deploys needs to
# finish before we create a release
needs: deploy steps:
# Download previously shared build
- name: Get artifact
uses: actions/download-artifact@v1
with:
name: react-github-actions-build # Zip the build using external action
- name: Zip build
uses: thedoctor0/zip-release@master
with:
filename: react-github-actions-release-build.zip
path: react-github-actions-build # Upload as an artifact of the current workflow
- name: Upload build zip artifact
uses: actions/upload-artifact@v1
with:
name: react-github-actions-release-build.zip
path: react-github-actions-release-build.zip # Make official GitHub release which will trigger
# sending the mail with link for access
- name: Release
uses: ncipollo/release-action@v1
with:
artifacts: react-github-actions-release-build.zip
body: https://react-github-actions-bucket.s3.amazonaws.com/index.html
token: ${{ secrets.GITHUB_TOKEN }} # Available by default
8. Is it working?
Let’s push the new tag and see:
git add .
git commit -m 'Add workflow'
git tag -a v0.0.1 -m 'First version'
git push origin v0.0.1
Now we wait for an email from GitHub with the link to the React application:
9. Conclusion
What we realize from this article is that GitHub Actions are a nice add-on for creating simpler and easier to understand workflows.
GitHub Actions are simple to use and integrate, and they rely on a lot of existing open source software.
The highest selling point is that Actions are provided inside GitHub repositories by default. In the most of the cases, actions will save you a lot of time.
Of course, there is so much more to do here.
We could introduce CloudFront in order to make it available in more regions, add domain via Route53 and many more things, but that’s material for another article.
Ping me on @ljmocic if you have any questions!
— — — — — — — — — — — — — — — — — — — — — — — — — — — — — —