Wednesday, March 8, 2017

Create an Angular app using Angular CLI and Deploy it using the AWS suite

Some months ago I found my self learning Angular 2, the final release wasn't available yet and I struggle to find a way to publish the app that I was developing in a easy and quick way.

We are going to do that just now. We will create an angular project first and after we will use AWS to deploy the code to a S3 bucket. Let's start.

We first need to create an Angular project. To do that, I found that the easiest way was using angular cli. As a result, that is what we are going to use to create the project.

Lets make some assumptions. I am going to assume that you are using a Mac. Also that you know how to use the terminal and that you have brew installed.

To begin with we need to install nodejs. To do that, we need to go to the terminal and run the following command.
brew install nodejs
After having nodejs installed we will use the NodeJS package manager npm for short, to install angular cli. Lets go to the terminal again and run.
npm install -g @angular cli
If that is successful you will be able to use the ng command in the terminal to see what version of node and angular cli you just install in my case is:
ng --version

node: 7.7.1
@angular-cli: 1.0.0-rc.1
We now should be ready to create our first angular project and run it locally. To create our first project run the following command, my project will be called hello-angular.
ng new hello-angular
This will create your project with all the files that it needs. Also it will download all the dependencies needed for your project to run. If everything goes well you will be able to run your project using the following command.
ng serve
After that you can go to http://localhost:4200 in your browser and you will see a lovely message in my case app works!
Now that we have create our first angular app and it is up an running. However, I want to release my app somewhere because I want everyone to see how awesome it is.
To do that, we need to add our code to a repository. We need it there in order to use CodePipeline to deploy the code to our S3 bucket, for those how didn't know we can use AWS S3 to host a website. Also why CodePipeline, well it is because we want to publish the app immediately every time that we commit any changes. 
If you are as lucky as me the angular cli command also create a local git repository. As a result, the only thing that I need to do is to add a remote to your local repository and push the code into origin. I am going to use GitHub as it is one of the options that CodePipeline gives me as Source Provider
I have create a project called hello-angular in my GitHub account, the same as above. After that, I need to add the remote and push the code. I will do that using the terminal with the following commands.
git remote add origin https://github.com/acastano/hello-angular.git

git push -u origin master
My GitHub account is acastano replace it with yours, I am using https to make it easier You just need to enter the username and password in the terminal. That way you don't have to deal with setting up SSH, I encourage you to do it your own way this is just for simplicity.
If everything went smoothly now the code is in the repository and we are ready to create our pipeline. But hold on, we are still missing something. We need to add the buildspec.yml file in the root directory of the project as we are going to use CodeBuildfrom AWS to get our artefacts to be deployed on S3.

Here is mine, I am not going to explain what everything means just change the bucket name for yours:
version: 0.1
environment_variables:
    plaintext:
        S3_BUCKET: "hello-world.andrescastano.com"
        BUILD_ENV: "prod"
phases:
    install:
        commands:
            - echo Installing source NPM dependencies...
            - npm install
            - npm install -g @angular/cli
    build:
        commands:
            - echo Build started on `date`
            - ng build --env=${BUILD_ENV}
    post_build:
         commands:
            - aws s3 cp dist s3://${S3_BUCKET} --recursive
            - echo Build completed on `date`
artifacts:
    files:
        - '**/*'
    base-directory: 'dist*'
    discard-paths: yes
Don't forget to add the file to the repository, in the terminal do
git add buildspec.yml
git commit -m "master - adding buildspec.yml"
git push -u origin master
Finally, we are ready to deploy. Lets go to the AWS console. The first thing that we are going to do is to setup our S3 bucket. For that, we need to open the S3 section and press create, my bucket name will be hello-word.andrescastano.com as state above, it is important to highlight that the bucket name needs to be what your website url is going to look like in my case is hello-world.andrescastano.com
After we created the bucket there is two things to do.
First, enable the bucket to allow website hosting. Go to properties and select Static Website Hosting, enable website hosting and use index.html for the index document and error document. Press save. You will see the endpoint that AWS has generated for you grab that because you are going to need later. Mine is hello-world.andrescastano.com.s3-website-eu-west-1.amazonaws.com.
Second, we need to attach a policy to allow external access. Go to permissions and click on add bucket policy. Paste the following and press save. Remember to change the bucket name for yours
{
 "Version": "2012-10-17",
 "Statement": [
  {
   "Sid": "2",
   "Effect": "Allow",
   "Principal": "*",
   "Action": "s3:GetObject",
   "Resource": "arn:aws:s3:::hello-world.andrescastano.com/*"
  }
 ]
}
This is pretty exciting we are ready now to create our pipeline. Lets go to the CodePipeline section. First hit create and add a name for your pipeline. After that you will have to pick the source in our case is GitHub. Select the project that you used above and the branch that you want to deploy. In my case is hello-angular and master. You will have to allow Amazon to access your GitHub account. Hit next. 
After that, we need to select our build provider, we are going to use AWS CodeBuildfor that. Select create a new build project, give it a name and select the environment image in our case we will leave the default one. Use an image managed by AWS CodeBuild. We will have to select an Operating System at the moment there is just one, Ubunto. Later, to build the app we need a runtime. Select Node.js as we are build and angular app. 
Lastly, you need to select a version, in my case aws/codebuild/nodejs:7.0.0, and create a service role in your account just leave the default value and take note of the name, mine is code-build-hello-angular-service-role. We will have to add some permissionsto that role to allow CodeBuild to push the artefacts for us to S3. Press save build project to continue. 
Before we continue let's go and add the access to that role, if we don't the pipeline will fail. Lets open a new tab in the browser and go to the IAM section, find the roles section and edit the the role that you created above. For convenience, I am going to add full S3 access to that role but you should just allow access to that specific S3 bucketthat you are using. To add the permissions I go to Permissions and select Attach Policy. Find AmazonS3FullAccess select and add it.
Let's go back to the Pipeline creation. We are going now to hit next step. You are going to be asked to select a deployment provider, here we select no deployment because we are already doing that with code build using our buildspec.yml file. The following is the line that does that.
    - aws s3 cp dist s3://${S3_BUCKET} --recursive
Lastly, you will have to select or create a AWS Service Role. Hit create role give it a name and leave all the default values. Select that role and hit next.
We are finally here. Now we can review everything that we have done but if we did everything right there is nothing to review. Just hit Create pipeline
If everything goes smoothly your pipeline should be running and the artefacts will be deployed to you S3 bucket. However, there is one thing that you need to do. I don't want to give my users the AWS url. As a result, you need to add a CNAME record to your domain. I will be using hello-world as host and the url that will point to is hello-world.andrescastano.com.s3-website-eu-west-1.amazonaws.com that is my bucket url. Remember, sometimes it takes a while for DNS records to get propagated.
If you have done everything correctly you should be able to see you website using your own domain. Until next time.