Professional Documents
Culture Documents
Creating A CICD For Your Ionic 4 App in AWS in 5 Minutes
Creating A CICD For Your Ionic 4 App in AWS in 5 Minutes
5 minutes
January 19, 2019
aws, cicd, ionic, s3
Author: Matthew Bonig (@mattbonig)
Ionic 4 just hit RC2 and I am playing around with a simple Task app for a friend. He wants
mobile apps and a
website, so a perfect fit for Ionic, since it can be deployed as a static
website pretty easily.
By the end of this blog, you should be able to deploy your own CodeCommit/Github
repository to the public web
entirely by CICD.
We're going to start with a basic Ionic 4 application. I assume you already have the Ionic cli
installed (
npm i -g ionic if not), so let's bootstrap a new project:
You can verify the build for the web app works:
When done you should now see a bunch of compiled files in the
./www/
directory. These are
Ionic's deployable web assets.
Let's make this a process we can easily run with npm. Update your package.json, adding a
new "build:prod" to
your scripts config:
"scripts": {
"ng": "ng",
Now let's add a buildspec.yml file to the root of the project. We're going to point
CodeBuild
at this later.
version: 0.2
phases:
pre_build:
commands:
- npm i
build:
commands:
artifacts:
files:
- '**/*'
base-directory: www
That's all we need to do to the code, so now push this to your repo, either AWS CodeCommit
or Github.
Fill out the source, in this case I'm using a Github repository. Click Next. Now we
setup the
Build State, the CodeBuild step:
Do the build
Click Create Project. In the new window start to fill out some basic CodeBuild info:
CodeBuild project details
Ionic is Node-based, hence using a Node Runtime. Your mileage may vary.
We'll be using a Node-based container for our build environment. You can leave everything
else on the
defaults:
Defaults are good** here.
**If you want to log the build output - which I suggest you do but is not required - go ahead
and fill out
CloudWatch specifics (the correct CloudWatch policies will NOT automatically
be added to the related service
role. You'll need to add those yourself).
When you're all done, click Continue to CodePipeline. Your CodeBuild project should now
be
selected.
Bucket time!
You can accept all defaults if you want, the bucket does not need to be, and shouldn't be,
public.
Review and Create the bucket. Now go back to your other tab, where you have setup the
CodeBuild project in CodePipeline and hit Next.
Review all your settings one last time and then hit Create Pipeline:
Once created, CodePipeline will automatically run the first build. No need to push anything
to the
repository.
Now, if you picked to log your CodeBuild project but didn't remember to setup the
permissions manually, or didn't
get to it quick enough, you're going to see an error:
Even though AWS setup the service role for you, it did not give it permissions to write
CloudWatch logs. Read here if you are unsure how to do this. For my testing, I just attached
the
CloudWatchAgentServerPolicy
to my service role.
And if you check your S3 bucket, you should see files similar to this:
Great! We're almost done. Now we just need a CloudFront distribution in front of this. Now, I
know what you're
wondering:
"But can't I just use S3 Static Website Hosting" - me, at the start of this
You'd think, and if you didn't care about SSL, you probably could. However, any good website
should have SSL and
CloudFront also solves a few issues around routing for us, so let's
continue...
Pick your S3 bucket as the origin domain name. We want to restrict bucket access, so that
we don't have to make
our S3 bucket public. Let CloudFront take care of granting the
permissions in the bucket policy. The only other
default you should have to change is the
Default Root Object near the bottom, set that
to "index.html".
I'm not going to setup a CNAME alternative for this (for custom domain names) but you
probably will want to, so
read up on it here. When you're satisfied, go ahead and create the
distribution.
It'll take a few minutes, but once complete you should be able to load the site at the Domain
Name
CloudFront generated for your distribution.
And that's generally it. You should now have a functioning website based on the Ionic
starter template. Any
updates you push to your repository will be deployed out after a few
minutes of the CICD process running.
However, since we're using CloudFront, the cache will
still show the old files. That's not good. You COULD let
the cache naturally expire, or
invalidate it yourself, but one requires waiting FAR too long to see the new
code, and the
other is manual. Both are gross.
We need a way to tell CloudFront to invalidate the files after they've been redeployed to S3.
So, let's take a
look at our options. If we go into editing the CodePipeline, let's take a look at
what kind of actions we can
take after the S3 push:
I don't see anything that says CloudFront
Ah ha, Lambda! The Swiss Army Knife of AWS. Since we can call a Lambda we can easily
create one that will
invalidate the CloudFront cache:
console.log('event:', event);
console.log('job_data:', job_data);
DistributionId: distribution_id,
InvalidationBatch: {
Quantity: 1,
Items: ['/*']
}).promise();
await codepipeline.putJobSuccessResult({
jobId: job_id
}).promise();
return {
statusCode: 200,
body: ''
};
};
I'm not going to cover all the steps in creating this Lambda. Just don't forget to give it an
execution role
that Allows the cloudfront:CreateInvalidation and
codepipeline:PutJobSuccessResult
Actions. Let's go ahead and
setup a new Action Group on
the Deploy stage of our CodePipeline and add the Lambda:
Add a new action group below the S3 deploy
For the UserParameter, pass the CloudFront Distribution ID you find over in the
CloudFront
console.
Alright, now if you Release the CodePipeline, you should see the S3 files get deployed
and
then our CloudFront
cache is invalidated.
Deploy + Invalidate
Invalidated!
Great! Now we have this fully deployable application when we do a git push to 'master'.
Try
it out now, change something significant (and obvious) in your Ionic project and then push
to your
repository.
CICD!
As you can imagine, this process would work with any static website, since nothing we did
here was specific to
Ionic 4, other than our buildspec.yml file and some config when we
setup the CodeBuild
project.
**Now, as you probably noticed, this was likely a little more than 5 minutes. I think if you
knew the process and
weren't following the guide, 5 minutes could be enough time. So, yes,
"5 minutes" was clickbait in my title. Sue
me. But, since that's still too long and I now have
guilt, I created a Terraform module
you can use to create all of this in just a minute. Check it
out here:
https://github.com/mbonig/simple-aws-cicd