Static site deployment manually with a shell script, S3, and CloudFront
How to script testing, compiling, and deploying a static site to AWS S3 and CloudFront from your laptop.
In a previous article we showed you how to automate testing, compiling, and deploying a static site to AWS S3 and CloudFront using CircleCI. What if you don’t like CircleCI? What if you don’t want to depend on a continuous integration service? What if you just want to quickly deploy a static site manually from your laptop?
We’re using harpjs “The static web server with built-in preprocessing” to compile our static site.
Create S3 and CloudFront resources
Create an S3 bucket
Create a CloudFront Distribution
Create an IAM user
Create an IAM user with the appropriate IAM policy access to S3 and CloudFront. We’ll interact with S3 and CloudFront using this IAM user.
Here’s an example IAM policy
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"s3:List*"
],
"Resource": "arn:aws:s3:::*"
},
{
"Effect": "Allow",
"Action": [
"s3:*"
],
"Resource": "arn:aws:s3:::example.com"
},
{
"Effect": "Allow",
"Action": [
"s3:*"
],
"Resource": "arn:aws:s3:::example.com/*"
},
{
"Effect": "Allow",
"Action": [
"s3:*"
],
"Resource": "arn:aws:s3:::staging.example.com"
},
{
"Effect": "Allow",
"Action": [
"s3:*"
],
"Resource": "arn:aws:s3:::staging.example.com/*"
},
{
"Effect": "Allow",
"Action": [
"s3:*"
],
"Resource": "arn:aws:s3:::acceptance.example.com"
},
{
"Effect": "Allow",
"Action": [
"s3:*"
],
"Resource": "arn:aws:s3:::acceptance.example.com/*"
},
{
"Effect": "Allow",
"Action": [
"cloudfront:CreateInvalidation"
],
"Resource": "*"
}
]
}
Install the AWS Command Line Interface
Run the command pip install awscli
to install the aws cli using pip.
Configure the AWS Command Line Interface
Configure the aws cli with the appropriate credentials and configuration options.
Run the command aws configure set preview.cloudfront true
to enable the cloudfront preview service.
Run the command aws configure set preview.create-invalidation true
to enable the create-invalidation preview service.
Write a script
We’ll write a simple shell script containing all of the commands needed to test, compile, and deploy our static site.
Notes about our example shell script
-
npm test
runs our tests -
npm run compile
simply runs the commandharp compile
-
We’re invalidating all of the objects in the distribution with the wildcard
*
-
The
CallerReference
value has to be unique each time you create a CloudFront cache invalidation. We create a unique value each time by executing thedate
command.
Here’s an example shell script
#/bin/bash
set -x
# Run this script from the root of your repository
test () {
npm test
}
prepare () {
rm -rf www/
npm run compile
}
sync () {
if [ ! -d "www" ]; then
echo 'Exiting because the directory www does not exist.'
exit
fi
aws s3 sync www/. s3://$1 --delete --size-only --cache-control max-age=$2
}
invalidate () {
aws cloudfront create-invalidation --cli-input-json "{\"DistributionId\":\"$1\",\"InvalidationBatch\":{\"Paths\":{\"Quantity\":1,\"Items\":[\"/*\"]},\"CallerReference\":\"$(date +%s)\"}}"
}
case "$1" in
"acceptance" | "")
test
prepare
sync acceptance.example.com 0
;;
"staging")
test
prepare
sync staging.example.com 60
;;
"production")
test
prepare
sync example.com 1800
invalidate ABCDEFGHIJKLMNOP
;;
*)
echo "Error: Something went wrong."
echo "Usage: ./script.sh <environment> i.e. ./script.sh acceptance"
exit 1
;;
esac
Troubleshooting
If you have any trouble try to simplify things, for instance, running the individual commands from your laptop. You might run into issues with IAM policies, awscli configuration, or command quoting.
Run the script
Of course you’ll need to customize the example script, write your own script in your favorite language, put it where you want, and execute it how you want. If you use a script like the one above, you’ll just cd
into the appropriate directory and run the script ./script.sh acceptance