Build a CI/CD Pipeline with AWS

Project 6 of the 6 Day DevOps Challenge. Let's set up a CI/CD pipeline to automate the build and deployment of your web app!

Introduction

⚑️ 30 second Summary

Welcome to Day SIX of the 6 Day DevOps Challenge.

Today, you'll learn how to use AWS CodePipeline to automate your entire CI/CD workflow into one seamless process!

This project brings together everything you've learned in the DevOps Challenge - your source code repository, build process, and deployment process will all work together automatically!

What is a CI/CD pipeline?

A CI/CD pipeline automatically builds, tests, and deploys your code changes. Instead of manually running these steps, CodePipeline manages the entire process from code commit to deployment.

This means faster releases, fewer errors, and more time to focus on writing great code rather than managing the deployment process.

Get ready to:

  1. Create a complete CI/CD pipeline with AWS CodePipeline.
  2. Connect your source code, build, and deployment stages.
  3. Test automatic deployments and learn how to roll back changes!

Want a complete demo of how to do this project, from start to finish? Check out our 🎬 walkthrough with Natasha 🎬

If you're up for a bit of a challenge, quiz yourself on the key concepts up ahead in this project.

This project is part of a series:

  1. Part 1: Set Up a Web App in the Cloud
  2. Part 2: Connect a GitHub Repo with AWS
  3. Part 3: Secure Packages with CodeArtifact
  4. Part 4: Continuous Integration with CodeBuild
  5. Part 5: Deploy a Web App with CodeDeploy
  6. Part 6: You are here!

Before we start Step #1...

In today's project, we're putting together an automated CI/CD pipeline with AWS CodePipeline!

πŸ’‘ What is AWS CodePipeline? Why are we using it?

So far, you've built CodeBuild projects that compile and test your code, and CodeDeploy applications that handle deployment. But there's still a missing piece: how do these services work together automatically?

Right now, you would need to:

  • Manually build your project again if the code changes.
  • Manually track which build artifacts should be deployed.
  • Manually start deployments for new build artifacts.
  • Manually restart the process if something fails.

CodePipeline solves these problems by orchestrating your entire workflow, and giving you visibility into the entire process in one place. It can:

  • βœ… Automatically detect code changes in your GitHub repository.
  • βœ… Automatically trigger CodeBuild to build a new project.
  • βœ… Automatically start CodeDeploy with the new build artifacts.
  • βœ… Automatically roll back a change if something fails.

Using CodePipeline transforms separate tools into a true CI/CD system, making deployments consistent, reliable, and fully automated - with no manual steps required from you!

Here's the game plan...

  1. Across πŸ’» Steps #1-4, we'll set up the foundation for our pipeline. Let's set up the source (GitHub), build (CodeBuild), and deploy (CodeDeploy) stages.
  2. Then, from ✨ Step #5, we'll create and run our pipeline to see automated deployments in action!
  3. Keep an eye out for a πŸ’Ž Secret Mission where you'll learn how to roll back deployments if something goes wrong.

Have you completed Days #1-5 of the 6 Day DevOps Challenge?

Note

Yes, and I've also done Day 6 (CloudFormation)

YOOOO!

We've got a legend on the loose 🫡

Since you've created a CloudFormation template with your CI/CD architecture, let's deploy that now. This will save us heaps of set-up time across Steps 1-4 of this project.

  • Head to the CloudFormation console.
  • Deploy your CloudFormation template in a new stack called NextWorkDevOpsCICD.
  • Off you go! Don't forget to review the list of resources and take note of what you've deployed with your template.

We recommend still starting from Step #1 of this project, and verifying that your deployed resources are set up exactly the same as the guide!

Yes, and I've deleted my resources

Perfect! Welcome back to the challenge, and it's awesome to have you here again.

We're going to assume...

  • You are doing this project with an IAM User.
  • You have VS Code and the SSH extension installed.
  • You have a GitHub repository storing the code from Days 1-5.

See you in πŸ’» Step 1!

Yes, and I kept all my resources

If you've completed all the previous projects and kept all your resources, you can skip the setup steps.

Jump straight to ✨ Step #5! to set up your CodePipeline pipeline. See you thereeeeee.

Nooo, I haven't done those projects!

Haven't tried those projects yet? That's okay!

You can still do the entire project, we've got the steps ready for you (get ready for 30-40 mins extra set up time)!

Set Up Your Development Instance

Let's get started by launching an EC2 instance! This will be our virtual server in the cloud where we'll write the code for our web app.

In this step, you're going to:

  • Launch an EC2 instance using the AWS Management Console.
  • Understand the benefits of using EC2 for this project.
  • Troubleshoot common issues during instance launch.
  • Let's dive right in! We've split up the setup for your development environment into four key milestones.

Note

If you've done projects #1-5 of the 6 Day DevOps Challenge, here's your mini challenge for this step... how many of these milestones can you check off without using the step by step guidance below?

  • Launch an EC2 instance.
  • SSH connect to your EC2 instance via VS Code.
  • Install Maven, Java and Git in your EC2 instance.
  • Clone your web app code on GitHub.

I haven't done Projects 1-5 yet

Then let's do it all step by step together! Ignore the other tabs in this step, and stay right here.

Set up an IAM Admin User

  • Do you have an IAM user?

No

Oooo it's the start of a new era!

If you don't have an IAM user yet - here are the steps to create one (this takes less than 10 mins).

What is an IAM user? Why are we setting one up?

In AWS, a user is a person or a computer that can do things on the AWS cloud.

When you create an AWS account for the first time, the login you get is called the root user of the AWS account. AWS actually recommends to not use your root user for everyday tasks to protect it from security breaches.

You should create IAM users instead. If a root user is a master key to your AWS account, think of IAM users as key copies. IAM users have separate usernames and passwords to your root user, and you can set them to have limited access to your account's resources.

  • Head to your AWS Account as the root user.
  • Open the AWS IAM console.
  • From the left hand navigation panel, choose Users.
  • Choose Create user.
  • For the User name, use enter your name-IAM-Admin‍
  • Make sure to select the checkbox next to Provide user access to the AWS Management Console - optional.‍
Note

This does not apply to all accounts, but if you're prompted with a pop up panel that says Are you providing access to a person?, choose I want to create an IAM user.‍

  • For the console password, choose Custom password.
  • Type in a password that you will be able to remember/access in the future.
Top tip

You will use this password for all future projects, so make sure to choose a secure one!

  • Deselect the checkbox for Users must create a new password at next sign-in - Recommended.
  • Choose Next.
  • In the permissions set up page, choose Attach policies directly.
  • From the list of Permissions policies, select AdministratorAccess.
  • Choose Next.
  • Choose Create user.
  • VoilΓ  - you've just created your new user! Stay on this page.
  • Choose Download .csv file.
  • Copy the Console sign-in URL.
  • Now you're ready to start using your IAM user. 🏁
  • Log out of your root user's AWS Account.
  • Paste and go to your copied console sign-in URL.
  • Open your downloaded .csv file containing your user's access instructions.
  • Log in using your IAM user's username and password in the .csv file.
  • Once you're logged in, you're ready to use your IAM user for this project! Make sure to keep the login details safe - you'll need them for the entire 6 Day DevOps Challenge!

Yes

Note

PLEASE make sure you log in to your IAM Admin User instead of the root user - it's truly best practice for account security.

Launch an EC2 Instance

Before we get into the juicy work of building your web app, we need to set up a home for your web app's files.

Since we want your web app to be entirely created and run on the cloud, we'll use a virtual server (EC2 instance) to house our development work.

  • Head to Amazon EC2.
  • Switch your Region to the one closest to you.

Tip: We recommend using the following regions

Did you know that not all regions have the same number of AWS services available?

There are only 13 AWS Regions that provide ALL the services we'll use in the 6 Day DevOps Challenge. We'd recommend using one of these regions from the very start of the challenge, so all your resources are in the same place. Even if you don't live in these regions, you can still use them:

  • us-east-1 (N.Virginia)
  • us-east-2 (Ohio)
  • us-west-2 (Oregon)
  • eu-west-1 (Ireland)
  • eu-west-2 (London)
  • eu-central-1 (Frankfurt)
  • eu-north-1 (Stockholm)
  • eu-south-1 (Milan)
  • eu-west-3 (Paris)
  • ap-southeast-1 (Singapore)
  • ap-southeast-2 (Sydney)
  • ap-northeast-1 (Tokyo)
  • ap-south-1 (Mumbai)

πŸ™‹β€β™€οΈ Extra for Experts: How do you know only these regions have all the services we need?

By checking out AWS' guidance on services by region! Once you select a region, you can sift through the list and identify whether it has all the services you need.

  • In your EC2 console, select Instances from the left hand navigation panel.
  • Choose Launch instances.
  • Set up your EC2 instance:
    • In Name, enter the value nextwork-devops-enter your name.
    • Choose Amazon Linux 2023 AMI under Amazon Machine Image(AMI).
    • Leave t2.micro under Instance type.
    • Select Create a new key pair and use nextwork-keypair as your key pair's name.
    • Store nextwork-keypair.pem in a new folder called DevOps in your local computer's Desktop.
  • Back to our EC2 instance setup, head to the Network settings section.
  • For Allow SSH traffic from, select the dropdown and choose My IP. This makes sure only you can access your EC2 instance. You can double check your IP by clicking here.
  • Choose Launch instance.

Didn't see a success message?

Share any errors/questions with the NextWork community!

Install VS Code

Do you have VS Code installed on your computer?

No

Let's goooooo! We'll set up VS Code in just a few minutes, and learn why we use it along the way.

What is VS Code?

Visual Studio Code (VS Code) is one of the most popular tools for creating and managing coding projects. You'll often hear people call VS Code an IDE (Integrated Development Environment), which means software that help you write and edit code. It's similar to how Microsoft Word or Google Docs help you write documents!

VS Code also comes with extra tools that we'll use to connect to virtual servers like EC2 instances.

  • Install VS Code by following the installation instructions for your OS e.g. Linux, Mac, Windows.
How can I decide which setting/chip option I should pick?

If you're unsure of which chip/settings option to pick for your device:

  • Mac: Select the Apple icon from the top left hand corner of your computer's menu bar. Select About this Mac, and note whether your Chip says Apple or Intel.
  • Windows: Click the Start button and search for System Information. Note whether your System Type says x64-based or ARM-based PC.
  • Linux: Open a terminal and run uname -m. Note whether the output says x86_64 or aarch64/arm64.
  • Once downloaded, you might need to unzip a zip file to access VS Code.
  • Open VS Code in your local computer (you'll find it in your Downloads folder).
  • If a popup asks you to confirm opening VS Code, select Open.
  • Welcome to VS Code!

Yes

  • Awesome! You're already set up to use VS Code.
  • Open VS Code in your local computer.
  • Select Terminal from the top menu bar.
  • Select New Terminal from the dropdown.

What is a terminal?

A terminal is where you send instructions to your computer using text instead of clicks. For example, instead of right-clicking on your desktop to create a new folder, you can type a simple text command in your terminal instead. It's like sending text messages to your computer's operating system to tell it what to do.

Every computer has a terminal. On Windows, it's often called Command Prompt or PowerShell, while macOS and Linux systems use Terminal.

  • Navigate your terminal to the DevOps folder:
    • cd ~/Desktop/DevOps (Mac/Linux)
    • cd C:\Users\YourUserName\Desktop\DevOps (Windows)
  • Once you’re in the DevOps folder, you might want to check if your .pem file is there. Use ls (Mac/Linux) or dir (Windows).

Change the permissions of your .pem file:

In the terminal, run the following command to allow access to your .pem file.

Mac/Linux

chmod 400 nextwork-keypair.pem
What is chmod?

This command stands for "change mode", and it changes the permissions of your .pem file. Using 400 makes it readable only by you (the owner) and restricts access for everyone else.

We're changing the permissions of your .pem file so that you have access to it when you connect to your EC2 instance later. Blocking out everyone else keeps your .pem file i.e. your secret key secure.

Windows

icacls "nextwork-keypair.pem" /reset
icacls "nextwork-keypair.pem" /grant:r "[[USERNAME="enter your username"]]:R"
icacls "nextwork-keypair.pem" /inheritance:r
What is icacls?

Icacls (which stands for Integrity Control Access Control Lists) is a tool for Windows that lets you decide who can open or change the files on your system. In these icacls commands, you're using:

  • /reset to remove default permission settings on the file
  • /grant:r "USERNAME:R" to give the current user (that's you!) read access to your secret key
  • /inheritance:r to make sure changes in the permissions of other files and the DevOps folder won't change the permission settings for this file.
  • Make sure to replace "USERNAME" with your Windows username. If you don't know your username, run whoami in your terminal to find out.

Connect to your EC2 Instance

Let's use the terminal in VS Code to set up a πŸ”Œ connection πŸ”Œ to your EC2 instance. Once we're connected, we can work inside your EC2 instance to set up that web app.

  • Head back to your AWS Management Console.
  • Click on Instances from the left hand navigation panel.
  • Click on the checkbox next to your EC2 instance to view its details.
  • Under the Details tab, look for Public IPv4 DNS. You'll need this in the next instruction!
  • Head back to VS Code and open your terminal again.
  • Use the following command to connect to your EC2 instance:
ssh -i [[PEMPATH="PATH TO YOUR .PEM FILE"]] ec2-user@[[EC2="YOUR PUBLIC IPV4 DNS"]]

I'm getting an error!

Ah, classic! Many students have run into an error at this step, and we'll get you unstuck. Make sure there are no spaces in your folder names (e.g. the DevOps folder cannot be titled Dev Ops). Still stuck? Share any other errors/questions with the NextWork community!

  • Your terminal will ask if you want to continue connecting to this EC2 instance. Enter yes to continue connecting.
  • Congrats! You've connected your EC2 instance via SSH.

Install Apache Maven and Amazon Corretto 8

Connection DONE. This means your terminal has now entered into your EC2 instance and can use it like a computer that's right in front of you!

Now let's install two tools that are going to help us build Java web apps. Introducing Apache Maven and Amazon Corretto 8 πŸ₯

  • Install Apache Maven using the commands below:
wget https://archive.apache.org/dist/maven/maven-3/3.5.2/binaries/apache-maven-3.5.2-bin.tar.gz

sudo tar -xzf apache-maven-3.5.2-bin.tar.gz -C /opt

echo "export PATH=/opt/apache-maven-3.5.2/bin:$PATH" >> ~/.bashrc

source ~/.bashrc

What is Apache Maven?

Apache Maven is a tool that helps developers build and organize Java software projects. It's also a package manager, which means it automatically download any external pieces of code your project depends on to work.

We're also using Maven today because it's really useful for kick-starting web projects! It uses something called archetypes, which are like templates, to lay out the foundations for different types of projects e.g. web apps.

We'll use Maven later on to help us set up all the necessary web files to create a web app structure, so we can jump straight into the fun part of developing the web app sooner.

  • Now we're going to install Java 8, or more specifically, Amazon Correto 8.
sudo dnf install -y java-1.8.0-amazon-corretto-devel

export JAVA_HOME=/usr/lib/jvm/java-1.8.0-amazon-corretto.x86_64

export PATH=/usr/lib/jvm/java-1.8.0-amazon-corretto.x86_64/jre/bin/:$PATH

What is Java? What is Amazon Correto 8?

Java is a popular programming language used to build different types of applications, from mobile apps to large enterprise systems.

Maven, which we just downloaded, is a tool that NEEDS Java to operate. So if we don't install Java, we won't be able to use Maven to generate/build our web app today

Amazon Corretto 8 is a version of Java that we're using for this project. It's free, reliable and provided by Amazon.

πŸ’‘ Woah! What's all this text popping up in the terminal?

The text you see after these commands is the terminal keeping you updated about it's progress with installing Java. It shows the specific packages it's going to install, downloading status, and even verifying that everything was installed.

  • To verify that Maven is installed correctly, run mvn -v next. Make sure the output mentions a Maven version 3.5.x.
  • To verify that you've installed Java 8 correctly, run java -version.

Important

If the Java version command above doesn't return openjdk version 1.8 (=> Java 8), run the following command that allows you to choose the correct Java version: sudo alternatives --config java

πŸ™‹β€β™€οΈ Seeing error messages while installing Maven/Java?

Share any errors/questions with the NextWork community!

Create the Application

We've assembled both Maven and Java into our EC2 instance. Now let's cut straight to generating the web app!

  • Use mvn to generate a Java web app. To do this, use these commands:
mvn archetype:generate \
   -DgroupId=com.nextwork.app \
   -DartifactId=nextwork-web-project \
   -DarchetypeArtifactId=maven-archetype-webapp \
   -DinteractiveMode=false

Break down these commands for me... What is mvn?

When you run mvn commands, you're asking Maven to perform tasks (like creating a new project or building an existing one).

The mvn archetype:generate command specifically tells Maven to create a new project from a template (which Maven calls an archetype). This command sets up a basic structure for your project, so you don't have to start from scratch.

Extra for Experts: Some of the details you've specified in this command are...

  • -DartifactId=nextwork-web-project names your project
  • -DarchetypeArtifactId=maven-archetype-webapp specifies that you're creating a web application.
  • -DinteractiveMode=false runs the command without pausing for user input, so Maven will go ahead and install everything without waiting for your confirmation.
  • Watch out for a BUILD SUCCESS message in your terminal once your application is all set up.

Connect VS Code with your EC2 Instance

In this step, you'll connect VS Code to your EC2 instance so you can see and edit the web app you've just created.

  • If you don't have Remote - SSH installed in VS Code already, select the Extensions icon at the side of your VS Code window. Search for Remote - SSH and click Install for the extension.

Why are we installing Remote - SSH?

The Remote - SSH extension in VS Code lets you connect directly via SSH to another computer securely over the internet. This lets you use VS Code to work on files or run programs on that server as if you were doing it on your own computer, which will come in handy when we edit the web app in your EC2 instance!

  • Click on the double arrow icon at the bottom left corner of your VS Code window. This button is a shortcut to use Remote - SSH.
  • Select Connect to Host...
  • Select + Add New SSH Host...
  • Enter the SSH command you used to connect to your EC2 instance:
ssh -i [[PEMPATH="PATH TO YOUR .PEM FILE"]] ec2-user@[[EC2="YOUR PUBLIC IPV4 DNS"]]

I'm getting an error!

Ah, classic! Many students have run into an error at this step, and we'll get you unstuck. Make sure there are no spaces in your folder names (e.g. the DevOps folder cannot be titled Dev Ops).

Still stuck? Share any other errors/questions with the NextWork community!

  • Select the configuration file at the top of your window. It should look similar to /Users/username/.ssh/config
  • A Host added! popup will confirm that you've set up your SSH Host - yay!
  • Select the blue Open Config button on that popup.
  • Confirm that all the details in your configuration file look correct:
    • Host should match up with your EC2 instance's IPv4 DNS.
    • IdentityFile should match up to nextwork-keypair.pem's location in your local computer.
    • User should say ec2-user
  • Now you’re ready to connect VS Code with your EC2 instance.
  • Click on the double arrow button on the bottom left corner and select Connect to Host again.
  • You should now see your EC2 instance listed at the top.
  • Select the EC2 instance and off we gooooooooooo to a new VS Code window ✈️
  • Check the bottom right hand corner of your new VS Code window - it should show your EC2 instance's IPV4 DNS.

Now that VS Code is connected to your EC2 instance, let's open up your web app's files.

  • From VS Code's left hand navigation bar, select the Explorer icon.
  • Select Open folder.
  • Enter /home/ec2-user/nextwork-web-project.
  • Press OK.
  • VS Code might show you a popup asking if you trust the authors of the files in this folder. If you see this popup, select Yes, I trust the authors.
  • Check your VS Code window's file explorer again - a folder called nextwork-web-project is here!
  • Try expanding all the subfolders in the file explorer. All folders have a > icon next to their name.

What are all these files and subfolders?

All the files and subfolders you see under nextwork-web-project are parts of a web app! You can start working right away on the content you want to display on your web app, since Maven's taken care of the basic structuring and setup.

Let's get to know some of these web app files/folders:

  • The src (source) folder holds all the source code files that define how your web app looks and works.
  • src is further divided into webapp, which are the web app's files e.g. HTML, CSS, JavaScript, and JSP files, and resources, which are the configuration files a web app might need e.g. connection settings to a database.
  • pom.xml is a Maven Project Object Model file. It stores information and configuration details that Maven will use to build the project. We'll use pom.xml later in this project series!
  • From your file explorer, click into index.jsp.
  • Let's try modifying index.jsp by changing the placeholder code to the code snippet below. Don't forget to replace {YOUR NAME} from the following code with your name:
<html>

<body>

<h2>Hello [[YOURNAME="enter your name"]]!</h2>

<p>This is my NextWork web application working!</p>

</body>

</html>
  • Save the changes you've made to index.jsp by selecting Command/Ctrl + S on your keyboard.

Let's connect our local web app to a remote repository on GitHub. This will let us track changes to our code and collaborate with others!

Install Git

To start using Git, we need to install it on your EC2 instance.

  • Open a new terminal in VS Code (if you don't already have one open in the remote session) by selecting Terminal > New Terminal. This terminal is now connected to your EC2 instance.
  • Run the following commands in the terminal to update the package list and install Git:
sudo dnf update -y

sudo dnf install git -y

Why install Git on the EC2 instance?

Git is a version control system that we'll use to manage our web app's code. We need to install Git on the EC2 instance so we can initialize a Git repository in our project directory, track changes, and push our code to GitHub in the next steps.

  • Off we goooo! Git is installed - you should see a Complete! message like this:
  • To check that Git was installed correctly, run the following command in the terminal:
git --version
  • This command will show you the installed version of Git if it's installed correctly.

Nice, Git is installed! You're ready to track the changes you make to your web app. We're also going to set up a remote repository on GitHub, so your web app code is also stored in the cloud.

Set up your GitHub repository

  • Do you have a GitHub account?

Yes - I'm ready to go!

No - I need to set up a GitHub account

Oooo exciting let's get you set up 🀘 Signing up is free and takes just 5 minutes!

What is Github?

GitHub is a place for engineers to store and share their code and projects online. It's called GitHub because it uses Git to manage your projects' version history.

  • Follow the prompts to create your account by entering your email, creating a password, and choosing a username.
  • Complete one of their bot verification tasks. Switch the task type to Audio if the Visual task crashes your website.
  • Once your account is created, confirm your email address with a verification code sent to your inbox.
  • Log into your GitHub account once you've verified your email.
  • Welcome to your GitHub account!
  • Click on the "+" icon in the top right corner of the page, next to your profile icon.
  • From the dropdown menu, select "New repository".
  • Nice! We're ready to create a new repository. Fill out the Create a new repository page.
  • In the Repository name field, enter nextwork-web-project
  • In the Description (optional) field, add a description like: Java web app set up on an EC2 instance. This web app was set up as a part of the NextWork's CI/CD Pipeline series.
  • Choose Public for the repository visibility.
  • Leave the Initialize this repository with: options unchecked.
  • Click the Create repository button.

What is GitHub?

GitHub is like a social network for code! It's where developers store their projects, track changes, and collaborate with others. At its heart, GitHub uses Git (a version control system) to keep track of every change made to your code. This means you can see who changed what, when they changed it, and even roll back to previous versions if something breaks.

GitHub is also where many companies look when hiring developers - your GitHub profile is essentially your coding portfolio. For our project, we're using GitHub to safely store our code and track all the changes we make as we build our CI/CD pipeline. Plus, you can keep this repository to show off this project to potential employers later!

  • Go back to VS Code, and open the terminal connected to your EC2 instance.
  • Make sure you're in your web app directory - run pwd and make sure it returns /home/ec2-user/nextwork-web-project.
  • Initialize a new Git repository in this directory by running:
git init

What does git init do?

To start using Git for your project, you need to create a local repository on your computer.

When you run git init inside a directory e.g. nextwork-web-project, it sets up the directory as a local Git repository which means changes are now tracked for version control.

πŸ’‘ What's a local repository?

The local repository is where you use Git directly on your own EC2 instance. The edits you make in your local repo is only visible to you and isn't shared with anyone else yet

This is different to the GitHub repository, which is the remote/cloud version of your repo that others can see.

WOAH! I got a bunch of yellow text when I ran this command

This yellow text is just Git giving you a heads-up about naming your main branch master and suggesting that you can choose a different name like 'main' or 'development' if you want.

πŸ’‘ What is a main branch?

You can think of Git branches as parallel versions or 'alternate universes' of the same project. For example, if you wanted to test a change to your code, you can set up a new branch that lets you diverge from the original/main version of your code (called master) so you can experiment with new features or test bug fixes safely. We won't create new branches in this project and we'll save all new changes directly to master, but it's best practice to make all changes in a separate branch and then merge them into master when they're ready.

Add remote origin

Now let's connect your local project folder with your Github repo!

  • Head back to your terminal in VS Code.
  • Add the remote repository as the origin with the following command, replacing <your_github_repo_url> with your repository's URL:
git remote add origin [[REPOURL="<repository_url>"]]

What does 'remote add origin' mean?

Your local and GitHub repositories aren't automatically linked, so you'll need to connect the two so that updates made in your local repo can also reflect in your GitHub repo.

When you set remote add origin, you're telling Git where your GitHub repository is located. Think of origin as a bookmark for your GitHub project's URL, so you don't have to type it out every time you want to send your changes there.

  • To find the URL of your GitHub repository, head back to your Git repository page.
  • In the blue section of the page titled Quick setup - if you've done this kind of thing before, copy the HTTPS URL to your repository page. It will look like https://github.com/username/nextwork-web-project.git
  • To verify that the remote origin has been set up correctly, run the command:
git remote -v
  • This command lists all configured remote repositories!
  • You should see origin listed, with both fetch and push URLs pointing to your GitHub repository URL.

Add, commit, and push your code to GitHub

Now, let's add all the files in your project to the Git repository. To do this, there are three commands you need to run...

  • First, run this command in your terminal:
git add . 

What does this command do?

git add . stages all (marked by the '.') files in nextwork-web-project to be saved in the next version of your project.

πŸ’‘ What does staging mean?

When you stage changes, you're telling Git to put together all your modified files for a final review before you commit them. This is incredibly handy because you get to see all your edits in one spot, which means its much easier to check if there were are mistakes or unwanted changes before you commit.

  • Run this command next in your terminal:
git commit -m "Updated index.jsp with new content"

What does this command do?

git commit -m "Updated index.jsp with new content"saves the staged changes as a snapshot in your project's history. This means your project's version control history has just saved your latest changes in a new version. -m flag lets you leave a message describing what the commit is about, making it easier to review what changed in this version.

  • Finally, run this command:
git push -u origin master

What does this command do?

git push -u origin master uploads i.e. 'pushes' your committed changes to origin, which you've bookmarked as your GitHub repo. 'master' tells Git that these updates should be pushed to the master branch of your GitHub repo. By using -u you're also setting an 'upstream' for your local branch, which means you're telling Git to remember to push to master by default. Next time, you can simply run git push without needing to define origin and master.

  • When you run git push, you might get asked for your GitHub username and password.

Why is Git asking for my username?

Git needs to double check that you have the right to push any changes to the remote origin your local repo is connected with. To do this, Git is now authenticating your identity by asking for your GitHub credentials.

  • Enter your Github username, and press Enter on your keyboard.
  • Next, enter your password. You'll notice that as you type this out, nothing shows on your terminal. This is totally expected - your terminal is hiding your input for your privacy. Press Enter on your keyboard when you've typed out your password, even if you don't see it printed out in your terminal.
  • Hmmmm, now Git is letting us know that it can't actually accept our password.

What does this mean?

GitHub phased out password authentication to connect with repositories over HTTPS - there are too many security risks and passwords can get intercepted over the internet 🀺 You need to use a personal access token instead, which is a more secure method for logging in and interacting with your repos.

πŸ’‘ What is a token?

A token in GitHub is a unique string of characters that looks like a random password. For example, a GitHub token might look like ghp_xHJNmL16GHSZSV88hjP5bQ24PRTg2s3Xk9ll. As you can imagine, tokens are great for security because they're unique and would be very hard to guess.

Set up and use a GitHub Personal Access Token (PAT)

  • To create a PAT, go back to your GitHub account in your web browser.
  • Click on your profile icon in the top right corner.
  • Select Settings from the dropdown menu.
  • In the left sidebar, scroll down and click on Developer settings.
  • Under Developer settings, click on Personal access tokens.
  • Click on Tokens (classic).
  • Click on Generate new token (classic).
  • Now you're on the New personal access token (classic) page!
  • In the Note field, enter the reason why you're generating this token, like Generated for EC2 Instance Access. This is a part of NextWork's 6 Day DevOps Challenge.
  • For Expiration, you can set it to 7 days for this project, or choose a different duration as per your preference.

What is a token expiration limit?

A token expiration limit means how long your personal access token would work for. After this time period, the token expires and no longer grants access, so you'll need to generate a new token. GitHub does this to make sure any tokens that are left lying around for months or years can't get picked up and used by someone else.

  • Under Select scopes, select the checkbox next to repo.

What do all these scopes mean?

We use scopes to decide what kind of permissions your token will grant. Each scope you pick gives the token the ability to do even more things with your GitHub account. In our case, we picked the repo scope, which means the token can even access and control private repositories in your account.

  • Scroll down and click the Generate token button at the bottom of the page.

Copy and use your Personal Access Token

  • Nice, a new token (a long string of random letters) is generated!
  • Make sure to copy the generated token right away - you won't be able to see it again after you leave this page 🍡
  • Click the Copy to clipboard icon next to your new token to copy it, and paste it somewhere safe now.
  • Go back to your VS Code terminal.
  • Re-run the git push -u origin master command - you can use the up ⬆️ key on your keyboard to re-run a previous command.
  • When asked for your username, enter your GitHub username again.
  • βœ‹ PAUSE
  • Do you remember what the GitHub token was generated for?
  • When Git asks for your password, paste in your token instead.
  • When you paste, it'll look like nothing is happening. That's because your terminal won't show your token for privacy reasons.
  • Press Enter on your keyboard once you've pasted your token (even if you don't see it on screen).
  • You'll see output in the terminal telling us that the push was successful, such as "Enumerating objects...", "Writing objects...", and "Branch 'master' set up to track remote branch 'master' from 'origin'".

What do these messages mean?

These messages show the progress of transferring objects (like files and commits).

Once the push is done, you also get messages that tell you that your local branch is now tracking the remote branch after the push. This means you only have to run git push next time, instead of the full git push origin master.

  • Well done! Looks like Github recognises your token and pushed your changes to your repository.

Important Secufrity Note

Treat your Personal Access Token like a password. Keep it secure and do not share it with anyone or commit it into your code. If you accidentally share your token, make sure to delete it straight away and generate a new one.

Verify code in GitHub repository

  • To confirm that your code has been successfully pushed to GitHub, let's refresh your GitHub repository page in your browser.
  • You should now see all your web app files listed in your GitHub repository. SO good!

Congratulations! You've successfully connected your web app to GitHub. Your code is now safely stored in a remote repository, and you can track changes and collaborate more effectively.

To avoid having to enter your username and PAT every time you push to GitHub, you can configure Git to store your credentials.

This is optional but can make your workflow smoother!

YES - let's configure Git

  • Run the following command to configure Git to use the store credential helper:
git config --global credential.helper store
  • After running this command, try pushing again: git push. You might be asked for your credentials one last time. Once entered, Git will store them for future pushes.
  • Refresh your GitHub repository page in your browser again.
  • Open the index.jsp file in your repository on GitHub.
  • Verify that the changes you made (<h2>Hello {YOUR_NAME}!</h2> and the new paragraph) are now visible in the file on GitHub.

Nope - skip configuration

  • No problem, onwards and upwards! You can continue without configuring the credential helper.
  • You'll just need to enter your GitHub username and personal access token each time you push changes to GitHub. Make sure to keep the token safe!

Let's GO! Your web app is now fully connected to GitHub, and you're ready for the next steps in setting up your CI/CD pipeline.

Launch EC2 Instance

To kick things off, we'll need to set up our development EC2 instance and connect to it via SSH!

Launch an EC2 Instance

Tip: We recommend using the following regions

Did you know that not all regions have the same number of AWS services available?

There are only 13 AWS Regions that provide ALL the services we'll use in the 6 Day DevOps Challenge. We'd recommend using one of these regions from the very start of the challenge, so all your resources are in the same place. Even if you don't live in these regions, you can still use them:

  • us-east-1 (N.Virginia)
  • us-east-2 (Ohio)
  • us-west-2 (Oregon)
  • eu-west-1 (Ireland)
  • eu-west-2 (London)
  • eu-central-1 (Frankfurt)
  • eu-north-1 (Stockholm)
  • eu-south-1 (Milan)
  • eu-west-3 (Paris)
  • ap-southeast-1 (Singapore)
  • ap-southeast-2 (Sydney)
  • ap-northeast-1 (Tokyo)
  • ap-south-1 (Mumbai)
  • Head to the EC2 console.

What is Amazon EC2?

Amazon EC2 (Elastic Compute Cloud) gives you virtual servers in the cloud that you can spin up whenever you need them. Think of it like renting computers in AWS's data centers that you can configure and use without having to worry about the physical hardware.

For this project, we're using EC2 as both the place where we'll deploy our application and the environment where we'll build it initially. It's perfect for this because you can easily SSH into it to make changes and see your application running in real-time.

  • Launch an EC2 instance with the following settings:
  • Name: nextwork-devops-enter your name.
  • Application and OS Images (Amazon Machine Image): Amazon Linux 2023
  • Instance type: t2.micro
  • Key pair: nextwork-keypair
  • Network settings: Allow SSH traffic from is set to My IP.
  • Finally, click Launch instance at the bottom right of the page.

Getting an "InsufficientInstanceCapacity" error when launching your EC2 instance?

Don't worry - this is a common issue that many NextWork students encounter! It simply means AWS doesn't have enough capacity for your chosen instance type in that specific data center (Availability Zone) right now. Here's how to fix it:

  • Try a different Availability Zone: Launch your instance in a different Availability Zone within the same region. Each zone is like a separate data center, and some might have more available capacity than others.
  • Choose a different instance type: If you're still having trouble, try selecting a different instance type. Some types are in higher demand than others.
  • Success!

EC2 instance LAUNCHED πŸš€

Next up, it's time to SSH connect to your instance!

SSH to Instance

Now that your EC2 instance is running, let's connect to it securely use SSH so we can start setting up our environment.

Prepare Your Private Key File

Let's get your private key file ready for secure authentication.

  • Locate the private key file (nextwork-keypair.pem) that you downloaded when creating the key pair in the previous step.
  • Move this .pem file to a dedicated folder on your local computer for better organization. For example, create a folder

Configure SSH in VS Code

  • Open VS Code on your local machine.
  • Click on the Remote Explorer icon in the Activity Bar on the side (it looks like a double arrow).
  • If you don't see the Remote Explorer icon, you might need to install the Remote - SSH extension.
  • You can do this by going to the Extensions view (Ctrl+Shift+X or Cmd+Shift+X) and searching for "Remote - SSH".
  • In the Remote Explorer, click on the Configure SSH Hosts... icon (it looks like a gear or settings icon).
  • Select SSH configuration file. Choose the existing config file path (e.g., ~/.ssh/config) from the dropdown menu.

What is SSH Configuration File?

The SSH configuration file (config) is a text file that allows you to define and save settings for SSH connections. By editing this file, you can store connection details for your EC2 instance, making it easier to connect in the future.

  • VS Code will open your SSH config file.
  • Edit the SSH config file - delete the existing setup.
  • Add the following configuration, replacing <your_instance_public_ipv4_dns> with the Public IPv4 DNS of your EC2 instance.
  • Make sure <path_to_pem_file> points to your private key file (.pem file you downloaded when launching the EC2 instance).
Host [[EC2="YOUR PUBLIC IPV4 DNS"]]
    HostName [[EC2="YOUR PUBLIC IPV4 DNS"]]
    User ec2-user
    IdentityFile [[PEMPATH="PATH TO YOUR .PEM FILE"]]

What is SSH (Secure Shell)?

SSH (Secure Shell) is a secure way to connect to and control your remote servers. Think of it like having a super-secure, encrypted phone line directly to your server where you can talk to it using text commands.

When you use SSH, everything you send (commands, passwords, data) is encrypted, so even if someone is eavesdropping on your internet connection, they can't see what you're doing. For developers, SSH is the go-to tool for managing servers remotely, transferring files securely, and running commands on distant machines without having to be physically present.

Need help finding your EC2 instance's IPv4 DNS?

  • In the EC2 console, navigate to Instances and select your running instance.
  • Under the Details tab, find and note down the Public IPv4 DNS. We'll need this to connect to our instance remotely.

What is Public IPv4 DNS?

The Public IPv4 DNS is basically your EC2 instance's address on the internet. You'll use this address whenever you need to connect to your instance from your local machine.

  • Save your updated SSH config file. Save the updated config file in VS Code by pressing Ctrl+S (Windows/Linux) or Cmd+S (Mac).
  • Make sure no unsaved changes indicator (a white circle) is present on the file tab. If you see a white circle, it means your changes are not saved yet.

Connect to EC2 via SSH

  • In VS Code, click on the Remote Explorer icon again.
  • Select Connect to Host.
  • Your EC2 instance's Public IPv4 DNS (which you set as HostName in the config file) should now appear as a configured host in the Remote Explorer panel (under SSH TARGETS).
  • Select your configured EC2 instance.
  • VS Code will open a new window and attempt to connect to your EC2 instance.
  • Continue SSH connection. If prompted with a host key verification, click Continue. This is a security measure to ensure you are connecting to the correct server.
  • If the connection went well, you'll see a new VS Code window connected to your EC2 instance. The bottom left corner of the window should say that you are connected to SSH: ec2-instance.

Seeing a "Permission denied (publickey)" error when trying to connect?

Oops! SSH connections can sometimes be a bit finicky. This usually happens when your private key file has incorrect permissions or you're using the wrong key file. Let's solve this together:

  • Fix your key file permissions: SSH requires secure permissions on your private key
    • Open your terminal
    • Go to where your .pem file is stored
    • MacOS/Linux: Run chmod 400 nextwork-keypair.pem (replace nextwork-keypair.pem with your actual key file name if different). This command sets the permissions so that only the owner (you) can read the file.
    • Windows: Run the following command:
icacls "nextwork-keypair.pem" /reset
icacls "nextwork-keypair.pem" /grant:r "[[USERNAME="enter your username"]]:R"
icacls "nextwork-keypair.pem" /inheritance:r
  • Make sure you're using the correct key: Double-check that the key file you're using matches the one you selected when creating your EC2 instance

After adjusting the permissions and verifying your key pair, try connecting again. You should now be able to establish an SSH connection to your EC2 instance successfully!

Woop woop! Do you know what's next?

It's time to install your development instance's key tools - Maven, Java and Git! Jump to the next tab for the next step!

Install tools

Now that you're connected to your EC2 instance, let's set up the necessary tools and environment to build our web application. We'll install Maven, Java, and Git!

Install Maven

  • In the new VS Code window, open a new terminal (Terminal > New Terminal). The terminal prompt should say that you are now working within your EC2 instance (e.g., ec2-user@your-instance-id ~ $).
  • Run the following commands one by one to download and install Maven:
wget https://archive.apache.org/dist/maven/maven-3/3.5.2/binaries/apache-maven-3.5.2-bin.tar.gz
sudo tar xzf apache-maven-3.5.2-bin.tar.gz -C /opt
echo 'export PATH=/opt/apache-maven-3.5.2/bin:$PATH' >> ~/.bashrc
source ~/.bashrc

What is Apache Maven?

Apache Maven is like a smart assistant for your Java projects. It helps you build your project, manage all the libraries your code depends on, and generate helpful documentation - all using simple commands.

When you're working on a Java project (like we are), Maven saves you from the headache of manually downloading and configuring all those JAR files your application needs. Instead, you just tell Maven what you need in a simple XML file, and it handles the rest. It's a huge time-saver that lets you focus on writing code rather than managing dependencies.

  • Run the command mvn -v to check if Maven is installed correctly and to see its version.
  • Confirm Maven version 3.5.2 is displayed in the output.

Install Java

  • Run the following commands to install Java 8 Amazon Corretto:
sudo dnf install -y java-1.8.0-amazon-corretto-devel
export JAVA_HOME=/usr/lib/jvm/java-1.8.0-amazon-corretto.x86_64
export PATH=$JAVA_HOME/jre/bin/:$PATH

What is Java?

Java is one of the world's most popular programming languages, known for its "write once, run anywhere" capability. You write your code once, and it can run on any device that has a Java Virtual Machine (JVM) - whether that's a laptop, server, or even a smart TV!

Amazon Corretto is AWS's free, production-ready version of Java. It's basically Java with AWS's stamp of approval, meaning they've tested it extensively and support it themselves. We're using it as the foundation for running our web application because it's reliable and doesn't cost a thing.

  • Run the command java -version to check if Java is installed and to see its version.
  • Confirm Java version 1.8.0_442 (or similar Java 8 version) is displayed.

Install Git

  • Run the following commands to update the package manager and install Git:
sudo dnf update -y
sudo dnf install git -y

What is Git?

Git is like a time machine for your code. It keeps track of all the changes you make, lets you rewind to previous versions if something breaks, and helps teams collaborate without overwriting each other's work.

In our project, we'll use Git to grab our web application code from GitHub (a popular service built on Git) and bring it to our EC2 instance. This means you can easily update your code, track changes, and work with others on the same codebase without stepping on each other's toes.

  • Check that you've installed Git by running git -version - you should see a version number!

I don't see a version number

Aha! Check the terminal response - turns out, git -version is not the right command to see your Git version number. Can you tell what is the proper command to find it?

Now that Git is installed, it's ⏰ time ⏰ to set up your web app's code! Jump to the next tab for the next step!

Web App Code

Clone Web App Repository

  • In the EC2 terminal, run the following command, replacing <repository_url> with the URL you just copied:
git clone [[REPOURL="<repository_url>"]]
  • Not sure where to find the repository URL?
  • Navigate to your GitHub repository for the web application in your web browser.
  • On your GitHub repository page, click on the green Code button.
  • A dropdown menu will appear. Copy the HTTPS URL provided in the dropdown.
  • Paste and run the repository URL in your command.

Getting a "git: command not found" error?

No worries - this just means Git isn't installed on your EC2 instance yet. This is super easy to fix:

  • Run this command to install Git: sudo dnf install git -y
  • After installation completes, verify it worked by running: git --version

Open Project Folder in VS Code

  • In VS Code, click Open Folder in the Explorer panel (top left corner).
  • Select the cloned project folder (nextwork-web-project) in your home directory and click OK.
  • You should now see the files and folders of your web application project in the VS Code Explorer.
  • If VS Code prompts Do you trust the authors of the files in this folder?, click Yes, I trust the authors.
  • Close any popup that you might get about installing another extension.
  • To verify that your web app code is present, open src/main/webapp/index.jsp by double-clicking it and check its content.

With Maven, Java, and Git installed and your project opened in VS Code, you're all set to move on to the next step!

Set up CodeArtifact Repository

Let's set up AWS CodeArtifact, a fully managed artifact repository service. This will help us securely store and share software packages used in our CI/CD pipeline.

In this step, you're going to:

  • Set up a CodeArtifact repository to store your web app's packages.
  • Create an IAM policy and role for CodeArtifact access.
  • Configure Maven settings to use CodeArtifact.
  • Build your web app with Maven and verify the connection with CodeArtifact.

Just like the previous step, we've broken down CodeArtifact set up into four key milestones.

How far can you go in each milestone without looking at the step by step instructions?

  • Create your CodeArtifact repository.
  • Set up an IAM policy and role for CodeArtifact access.
  • Give your development EC2 instance access to CodeArtifact.
  • Set up a connection between CodeArtifact and Maven.

Create repository

Let's get started with CodeArtifact!

Navigate to CodeArtifact

  • Open the CodeArtifact console.

What is AWS CodeArtifact?

AWS CodeArtifact is like a secure, private locker for all your software packages and dependencies. Instead of having developers download packages from the public internet (which can be risky and unreliable), you store trusted versions in CodeArtifact.

It works seamlessly with tools you're already using like Maven, npm, and pip. In our CI/CD pipeline, CodeArtifact gives us a central, secure place to store our Maven artifacts so our build and deployment processes can always access exactly what they need. No more "works on my machine" problems - this used to be the case when everyone's using different package versions!

Create CodeArtifact Repository

  • In the CodeArtifact console, click Create repository.
  • On the Create repository page, configure the following:
  • Repository name: nextwork-devops-cicd
  • Description: Repository for NextWork CI/CD artifacts.
  • Package format: Select Maven.
  • Public upstream repositories: Enable Include public upstream repositories and select maven-central-store. This allows CodeArtifact to fetch packages from Maven Central if they are not found in your repository.
  • If prompted to set a domain, set the domain name to nextwork. If a domain already exists, you can use the existing domain.
  • Click Create repository.
  • The CodeArtifact repository nextwork-devops-cicd should be created successfully. You should see it listed in the repositories dashboard.

With your CodeArtifact repository set up and connection details noted, we're ready to configure our EC2 instance to access it.

Jump to the next tab for the next step!

IAM Policy and Role

Create IAM Policy for CodeArtifact Access

First, we'll create an IAM policy that defines the permissions needed to access CodeArtifact.

  • Navigate to the IAM console in a new tab.
  • In the IAM console, click Policies in the left-hand menu.
  • Click Create policy.
  • Switch to the JSON tab.
  • Replace the existing content in the JSON editor with the following policy document. This policy grants permissions to get authorization tokens, repository endpoints, and read from CodeArtifact repositories:
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": [
        "codeartifact:GetAuthorizationToken",
        "codeartifact:GetRepositoryEndpoint",
        "codeartifact:ReadFromRepository"
      ],
      "Resource": "*"
    },
    {
      "Effect": "Allow",
      "Action": "sts:GetServiceBearerToken",
      "Resource": "*",
      "Condition": {
        "StringEquals": {
          "sts:AWSServiceName": "codeartifact.amazonaws.com"
        }
      }
    }
  ]
}
  • Click Next.
  • On the Review policy page, enter the following:
  • Policy name: codeartifact-nextwork-consumer-policy
  • Description: Policy for EC2 instances to access CodeArtifact
  • Click Create policy.
  • Nice! The codeartifact-nextwork-consumer-policy should be created and listed in your IAM policies.

Create IAM Role for EC2 Instance

  • In the IAM console, click Roles in the left-hand menu.
  • Click Create role.
  • Select AWS service as the trusted entity type.
  • Choose EC2 as the service that will use this role.
  • Click Next.
  • In the Attach permissions policies page, search for and select the codeartifact-nextwork-consumer-policy you just created.
  • Click Next.
  • On the Name, review, and create page, enter the following:
  • Role name: ec2-instance-nextwork-cicd
  • Description: IAM role for EC2 instances to access CodeArtifact
  • Click Create role.
  • The ec2-instance-nextwork-cicd should be created and listed in your IAM roles.

Attach IAM Role to EC2 Instance

Now, let's associate the IAM role with your EC2 instance.

  • Navigate back to the EC2 service console and go to the Instances dashboard.
  • Select your running instance (nextwork-devops-enter your name).
  • Click Actions at the top, then select Security, and then Modify IAM role.
  • In the Modify IAM role dialog, from the IAM role dropdown, select the ec2-instance-nextwork-cicd you just created.
  • Click Update IAM role to apply the changes.

Too cool - your EC2 instance's permissions are all set up.

Time to make the connection between CodeArtifact and your web app happen 🀝

Jump to the next tab for the next step!

Connect CodeArtifact and Maven

Get Connection Instructions

We'll need to get the connection instructions to configure Maven to use this repository.

  • Click on the newly created repository nextwork-devops-cicd to view its details.
  • Click on Connection instructions in the repository details page.
  • In the Connection instructions dialog, select Mac and Linux as the operating system and Maven as the package manager.
  • 🚨 Double check that you're using Mac and Linux as the operating system. Even if you're doing this project on a Windows computer, Mac and Linux is the right choice. Your EC2 instance is an Amazon Linux 2023 instance!
  • Copy the command in Step #3 - this command stores an authorization token to your CodeArtifact repository!

Export CodeArtifact Auth Token

  • Go back to your VS Code remote window connected to your EC2 instance.
  • In the terminal, run the command in Step #3 of your CodeArtifact connection instructions window.
  • This should export the CodeArtifact authorization token as an environment variable.

Yay nice work! You've successfully configured IAM permissions to allow your EC2 instance to access CodeArtifact. Let's move on to configuring Maven to use CodeArtifact in the next step.

Create settings.xml

Note

Aready have a settings.xml file in your repo? Nice - skip to building the project!

Let's create the settings.xml file in your Maven project.

What is settings.xml?

The settings.xml file in Maven is used to configure Maven's execution environment. It allows you to customize settings like repository locations, server credentials, and proxy configurations. In our case, we are using it to tell Maven to use our CodeArtifact repository for managing dependencies and deploying artifacts.

  • In your VS Code Explorer, navigate to the root directory of your cloned project (nextwork-web-project).
  • Create a new file
  • Add settings tags in the file:
<settings>

</settings>
  • Copy and paste the code from steps #4-6 of CodeArtifact's connection instructions between the <settings> tags.
  • Save settings.xml.

Question: What is the purpose of configuring settings.xml for Maven?

The settings.xml file is like Maven's address book and passport for accessing repositories. We're setting it up for a couple of important reasons:

First, it tells Maven where to find your AWS CodeArtifact repository - essentially giving Maven the address of your private package library. Without this, Maven would only look in public repositories like Maven Central.

Second, it provides the authentication details Maven needs to access your private repository. The CODEARTIFACT_AUTH_TOKEN environment variable works like a temporary password that proves Maven has permission to access your CodeArtifact repository.

By configuring this file correctly, you're ensuring that Maven can seamlessly download dependencies from and upload artifacts to your private CodeArtifact repository. This creates a secure, controlled environment for your project's packages, which is essential for reliable builds in your CI/CD pipeline.

Build the Project with Maven

  • In the EC2 terminal, navigate to your root project directory (nextwork-web-project) if you are not already there.
  • Run the command to build your project using Maven and the settings.xml file you configured:
mvn compile -s settings.xml

Getting "UnauthorizedException" or "AccessDeniedException" during your Maven build?

Many students encounter this error - it means your EC2 instance doesn't have proper permissions to access CodeArtifact. Let's fix it together:

  • Check your IAM policy: Make sure the codeartifact-nextwork-consumer-policy has all the permissions shown in the steps above
  • Verify the IAM role is attached: Confirm that the ec2-instance-nextwork-cicd role (with the policy attached) is connected to your EC2 instance
  • Review your settings.xml file: Double-check that all placeholders like <your_aws_account_id> have been replaced with your actual values
  • Verify your auth token: Make sure the CODEARTIFACT_AUTH_TOKEN environment variable was exported correctly - run echo $CODEARTIFACT_AUTH_TOKEN to check
  • You should see a BUILD SUCCESS message at the end of the Maven build output in the terminal.
  • The first build might take longer (wait 1-3 minutes) as Maven downloads dependencies from CodeArtifact for the first time.

Verify Artifact Upload to CodeArtifact

  • Go back to the CodeArtifact console.
  • Navigate to Repositories and select your nextwork-devops-cicd repository.
  • Check that packages are uploaded to your CodeArtifact repository. Don't forget to hit the refresh button!

Set up CodeBuild Project

Now, let's automate the build process using AWS CodeBuild. CodeBuild is a fully managed build service that will compile our source code, run tests, and produce deployable software packages.

In this step, you're going to:

  • Set up an S3 bucket to store your CodeBuild artifacts.
  • Create a CodeBuild project.
  • Update CodeBuild's IAM role to include CodeArtifact access.

You guessed it! Here's the CodeBuild set up split into 5 key milestones - which steps can you tackle without step by step guidance?

  • Launch an S3 bucket to store your build artifacts.
  • Set up a CodeBuild project.
  • Update your CodeBuild IAM Role to access CodeArtifact.
  • Create buildspec.yml in your web app repository.
  • Put your CodeBuild setup to the test - build your project!

S3

  • Make sure you're still in the same region where you set up the CodeBuild build project.
  • Let's head to the S3 console. In the AWS Management Console search bar, type S3 and select S3 from the dropdown menu under Services.
  • On the Buckets page, click Create bucket.
  • In the Create bucket page, under General configuration, for Bucket name, enter nextwork-devops-cicd-enter your name.
  • Leave all other settings as default.
  • Click Create bucket at the bottom of the page.

Jump to the next tab to see the next step!

CodeBuild

Create CodeBuild Project

Let's automate our builds with CodeBuild!

  • Open the CodeBuild service.

What is AWS CodeBuild?

AWS CodeBuild is a fully build tool for your code. It takes your source code, compiles it, runs tests, and packages it up. Engineers love continuous integration tools like CodeBuild because you don't have to manually set up and manage any build servers yourself, and you only pay for the compute time you use for building your projects (instead of entire servers that are idle most of the time). Think of it as a super-efficient, scalable, and managed service that handles all the heavy lifting of building and testing your applications.

  • In the CodeBuild console, click Create build project.
  • On the Create build project page, configure the following: Project name: nextwork-devops-cicd

Source

  • In the Source section:
  • Source provider: Select GitHub.
  • Repository: Choose your your repository (<your_github_username>/nextwork-web-project).

I don't see any GitHub connections or repositories!

  • If you haven't connected to GitHub before, click Manage account credentials.
  • Select create a new GitHub connection.
  • In the Create GitHub connection popup, enter a connection name: nextwork-devops-cicd
  • Click Connect to GitHub.
  • Follow the connection steps in the GitHub App, and get redirected back to AWS.
  • Select your GitHub account name under App Installation.
  • Select Connect.
  • Select the refresh button next to the Connection field, then select your new nextwork-devops-cicd connection.
  • Select Save.
  • Once the connection is established, select your repository from the Repository dropdown (<your_github_username>/nextwork-web-project) in your CodeBuild setup.
  • Untick the Webhook checkbox that says "Rebuild every time a code change is pushed to this repository."

Configure Environment

  • In the Environment section:
  • Environment image: Select Managed image.
  • Operating system: Choose Amazon Linux 2.
  • Runtime: Choose Standard.
  • Image: Choose aws/codebuild/amazonlinux2-x86_64-standard:coretto8.
  • Image version: Select Always use the latest image for this runtime version.
  • In the Service role section, let's keep the default and let CodeBuild create a New service role.
  • In the Buildspec section, select Use a buildspec file. This tells CodeBuild to use a buildspec.yml file in your repository to define the build commands.
  • In the Artifacts section:
  • Artifacts type: Select Amazon S3.
  • Bucket name: Enter your S3 bucket name nextwork-devops-cicd-enter your name. You'll need to create this bucket if you don't have it yet!
  • Name: nextwork-devops-cicd-artifact
  • Artifacts packaging: Select zip.
  • In the Logs section:
  • Enable CloudWatch logs if it's not enabled yet.
  • Set the CloudWatch group name to /aws/codebuild/nextwork-devops-cicd
  • Click Create build project.

Sweet! Build project set up. After creating the CodeBuild project, an IAM role is automatically created for it.

We'll need to add permissions to this role, so that CodeBuild can access CodeArtifact!

Jump to the next tab for the next step!

IAM

Update CodeBuild IAM Role

  • Head to the IAM console.
  • Click Roles in the left-hand menu.
  • Search for your CodeBuild service role (e.g., codebuild-nextwork-devops-cicd-service-role) and click on the role name.
  • Click Add permissions, then Attach policies.
  • Search for and select the codeartifact-nextwork-consumer-policy.
  • Click Attach policies.

Alrighty! Now that CodeBuild has access to CodeArtifact, we'll set up buildspec.yml next. This will help CodeDeploy know how to deploy your web app.

Jump to the next tab for the next step!

buildspec.yml

Note

Psssst do you already have a complete buildspec.yml file from cloning the code in your GitHub repository? You're on to it - you can skip to the next tab.

Create buildspec.yml

  • In your VS Code Explorer, navigate to the root directory of your cloned project (nextwork-web-project).
  • Create a new file
  • Open the buildspec.yml file and copy and paste the following content into it.
  • 🚨 Replace <your_aws_account_id> with your actual AWS account ID
  • 🚨 Replace us-east-2 with your region.
version: 0.2

phases:
  install:
    runtime-versions:
      java: corretto8
  pre_build:
    commands:
      - echo Logging in to AWS CodeArtifact...
      - CODEARTIFACT_AUTH_TOKEN=`aws codeartifact get-authorization-token --domain nextwork --domain-owner <your_aws_account_id> --region us-east-2 --query authorizationToken --output text`
      - export CODEARTIFACT_AUTH_TOKEN
  build:
    commands:
      - echo Build started on `date`
      - mvn clean install -s settings.xml
  post_build:
    commands:
      - echo Build completed on `date`
      - echo Packaging artifacts...
      - mvn package -s settings.xml
artifacts:
  files:
    - target/*.war
  discard-paths: no

What is buildspec.yml?

buildspec.yml is a YAML file that defines a set of build commands and settings for AWS CodeBuild. It tells CodeBuild what to do at each phase of the build process, including installing dependencies, running tests, and packaging artifacts. It's essential for automating your build process in CodeBuild.

  • Save buildspec.yml.

CodeBuild setup all DONE πŸ”₯ Let's build our project to check that everything is set up correctly.

Jump to the next tab for the next step!

Push buildspec.yml to GitHub

  • In your EC2 instance terminal, navigate to your project directory (cd ~/nextwork-web-project) if you are not already there.
  • Run git add . to stage all changes, including the newly created buildspec.yml and any modifications to settings.xml.
  • Run git commit -m "Add CodeBuild resources and buildspec.yml" to commit the staged changes with a descriptive message.
  • Run git push origin master to push your local commits to your GitHub repository's master branch.

Seeing errors when pushing your code?

Try resetting your Git credentials, and starting over again! Run these commands in your terminal:

git config --global --unset credential.helper
git config --local --unset credential.helper
git remote set-url origin https://[[GITUSERNAME="<github_username>"]]@github.com/[[GITUSERNAME="<github_username>"]]/[[REPONAME="<repository_name>"]].git
  • Make sure to replace <YOUR_GITHUB_USERNAME> with your GitHub username and <YOUR_REPOSITORY_NAME> with your repository name.
  • Then try git push again and enter your GitHub PAT when prompted for the password. Check the top of your VS Code window if you're not prompted in the terminal.
  • Let's confirm that your changes are reflected in your GitHub repository.
  • After a successful git push, refresh your GitHub repository page in your web browser.
  • You should see the buildspec.yml file and the updated settings.xml file in your repository, confirming that your push was successful!

Build project

Test CodeBuild Project

Let's test your CodeBuild project by starting a build manually.

  • Navigate back to the CodeBuild console and select your nextwork-devops-cicd project.
  • Click Start build to manually trigger a build.
  • The build should start successfully.
  • You will be redirected to the build details page where you can monitor the build progress in real-time in the Build logs section.
  • Wait for the build to complete and check the build logs for any errors.
  • Fingers crossed!

Build success!

  • You can check for a build artifact in your S3 bucket, which would also help verify that the build was a success!
  • Yeehaw! You've successfully set up a CodeBuild project that automates the build process for your web application.
  • In the next steps, we'll set up CodeDeploy to automate the deployment of your application.

Build failed!

Here's your troubleshooting checklist!

  • Is buildspec.yml in your code repository? Check your GitHub repo now!
  • Is settings.xml at the root of your code repository? It should NOT be in any subfolders.
  • Is buildspec.yml at the root of your code repository? It should NOT be in any subfolders.
  • Does your CodeBuild service role have access to CodeArtifact?
  • Does your CodeBuild service role have access to CodeConnection?
  • Does buildspec.yml reference your account ID and region code?
  • Are there any errors if you run mvn compile -s settings.xml locally?
Still Running into CodeBuild errors? Let's solve them!

CodeBuild issues are common, but they're usually quick fixes. Scroll down to your build event's logs, and study the error messages:

If you see YAML_FILE_ERROR: YAML file does not exist

This means CodeBuild can't find your buildspec.yml file. Make sure it's:

  • In the root directory of your repository
  • Committed and pushed to GitHub (run git add buildspec.yml, git commit -m Add buildspec.yml, and git push origin master)

If you see CLIENT_ERROR: Failed to get access token

Your CodeBuild service role needs permission to access CodeConnection! Without permission, it can't access your GitHub repo.

  • Head to the IAM console and find your CodeBuild role (like codebuild-nextwork-devops-cicd-service-role)
  • Attach the AWSCodeStarConnectionsFullAccess policy to it.
  • If that still doesn't work, consider attaching a custom policy that allows access to connection! Note the ARN in your error message, and use that in this policy template:

If you see Domain owner should be your account ID

You need to replace the placeholder account ID:

  • Open buildspec.yml in VS Code
  • Find the line with domain-owner and replace the ID with your actual AWS account ID (found in the top right of AWS console)
  • Save and push your updated code.

Retry CodeBuild Build

Let's retry the CodeBuild build.

  • Go back to the CodeBuild console.
  • Make sure you're in your nextwork-devops-cicd project page.
  • Click Retry build or Start build again to trigger a new build.
  • The build should start successfully.
  • You can also check for a build artifact in your S3 bucket, which would also help verify that the build was a success!
  • If you still run into any issues, share a screenshot of your error message in the NextWork community!

Congratulations! You've successfully set up a CodeBuild project that automates the build process for your web application. In the next steps, we'll set up CodeDeploy to automate the deployment of your application.

Set up CodeDeploy

Let's set up AWS CodeDeploy to automate the deployment of our built web application to our EC2 instance. CodeDeploy will ensure that our application updates are deployed smoothly and efficiently.

In this step, you're going to:

  • Launch a CloudFormation stack for your deployment instance.
  • Set up a CodeDeploy application and deployment group.
  • Configure a CodeDeploy service role.
  • Successfully deploy your web app!

We've broken down your CodeDeploy setup into four key parts (surprise, surprise 🀭).

Challenge yourself! Since you've done these steps before, how far can you do each of these steps without step by step guidance?

  • Launch your deployment instance with this CloudFormation template.
  • Set up your CodeDeploy application.
  • Set up your CodeDeploy deployment group.
  • Launch a deployment!

Deployment Instance

Launch your deployment infrastructure

  • Let's head to the CloudFormation console.
  • On the CloudFormation console dashboard, click Create Stack.
  • Select With new resources (standard) to start creating a new stack.
  • Under Prepare template, select Upload a template file.
  • Click Choose file and upload the nextwork-web-app.yaml template file.
  • Click Next to proceed to stack details.

Specify CloudFormation Stack Details

  • On the Specify stack details page, configure the following:
  • Stack name: nextwork-codedeploy-ec2-stack
  • YourIPAddress: Enter your public IP address followed by /32 (e.g., 203.0.113.5/32).
  • You can find your public IP address by searching what is my ip on Google or using a website like https://checkip.amazonaws.com/.
  • Click Next.
  • On the Configure stack options page, keep the default settings and click Next.
  • On the Review page, scroll down to the bottom, check the box I acknowledge that AWS CloudFormation might create IAM resources, and click Submit.
  • Wait for the CloudFormation stack to reach the CREATE_COMPLETE status. You can monitor the stack creation progress in the CloudFormation console.

CloudFormation stack creation failed?

Don't worry - CloudFormation stacks can fail for lots of different reasons. Let's figure it out together:

  • Check the stack events: This is your best troubleshooting tool! In the CloudFormation console:
    • Go to your stack (nextwork-codedeploy-ec2-stack)
    • Click the Events tab
    • Look for events with CREATE_FAILED status
    • Read the Status reason for specific error details
  • Common issues to check:
    • Parameter values: Make sure you entered correct values (like your IP address)
    • IAM permissions: Make sure you have permission to create all the resources in the template
    • Make sure you don't have any more than 5 VPCs in your AWS Region (that's the max number of VPC's you're allowed to have!)

Still stuck? The NextWork community would love to know - share your error/question, or your question might already be solved in one of the hundreds of posts there!

  • It might take a few minutes until the stack status becomes CREATE_COMPLETE.

In the meantime, let's set up our CodeDeploy application.

Jump to the next tab for the next step!

CodeDeploy App

Create CodeDeploy Application

Let's automate deployments with CodeDeploy!

  • Open the CodeDeploy service.

What is AWS CodeDeploy?

AWS CodeDeploy is AWS' deployment service - it makes sure that when you update the code in your app, the updates reach your servers safely and consistently. In our CI/CD pipeline, CodeDeploy takes the application package that CodeBuild created (and stored in the S3 bucket) and safely deploys it to deployment EC2 instances.

  • On the CodeDeploy console dashboard, click Applications in the left navigation menu.
  • In the CodeDeploy console, click Create application.
  • On the Create application page, configure the following:
  • Application name: nextwork-devops-cicd
  • Compute platform: Choose EC2/On-premises.
  • Click Create application.

That's it for the CodeDeploy application πŸ‘

They key part of your CodeDeploy setup is the deployment group, which we'll do next.

Jump to the next tab for the next step!

Deployment Group

Create Deployment Group

Now, let's create a deployment group within our application to define how deployments will be done.

  • After creating the application, you will be redirected to the application details page.
  • Click Create deployment group.
  • On the Create deployment group page, give your deployment group the name nextwork-devops-cicd-deployment-group
  • Under Service role, you might notice that we don't have a service role ready yet!
  • Let's create one now...

Create CodeDeploy Service Role

  • Head to the IAM console.
  • Select Role from the left hand navigation bar.
  • Select Create role.

Why does CodeDeploy need a service role?

The CodeDeploy service role is like giving CodeDeploy a special ID badge that grants it permission to interact with your AWS resources. Without this role, CodeDeploy would be stopped at the security gate, unable to do its job.

This role specifically allows CodeDeploy to:

  • Access your EC2 instances to deploy your application code
  • Read your deployment configurations to understand how to deploy
  • Perform the actual deployment actions (copying files, running scripts, etc.)

The beauty of using a service role is that it follows the principle of least privilege - CodeDeploy gets only the permissions it actually needs to do its job, not broad administrative access. This is much more secure than using your own admin credentials and helps keep your AWS environment safer.

  • In the IAM console tab that opens, under Select type of trusted entity, choose AWS service.
  • In the IAM console, ensure CodeDeploy is selected under Use cases.
  • Click Next.
  • The AWSCodeDeployRole policy should be pre-selected - that's exactly what we want!
  • Review the permissions and click Next.
  • Enter AWSCodeDeployRole as the role name.
  • Click Create role.

Configure Deployment Settings

  • Head back to the CodeDeploy deployment group creation page.
  • Refresh the page to ensure the newly created service role is available in the dropdown.
  • Give your deployment group the name nextwork-devops-cicd-deployment-group again.
  • This time, under Service role, select the newly created AWSCodeDeployRole from the dropdown menu. Nice!
  • In the Deployment type section, choose In-place. This deployment type updates the application on the existing EC2 instance.
  • In the Environment configuration section, select Amazon EC2 instances.
  • Configure a tag with:
  • Key: role
  • Value: webserver.
  • This tag should match the tag you assigned to your deployment EC2 instance when you launched it with CloudFormation!
  • In the Deployment settings section, under Deployment configuration, keep the default CodeDeployDefault.AllAtOnce.
  • Under Load balancer, uncheck Enable load balancing. We are not using a load balancer in this project.
  • Scroll down to the bottom of the page and click Create deployment group.

Nice work setting up the deployment group! All that's left for our CodeDeploy setup is to run a deployment.

Jump to the next tab for the next step!

Deployment

Create Deployment

  • In the deployment group details page, select Create deployment.
  • Sweet! Some of this deployment configuration is already pre-filled for us.
  • Under Revision type, make sure My application is stored in Amazon S3 is selected. That's because our deployment artifact is inside an S3 bucket!
  • Head back to your S3 bucket called nextwork-devops-cicd.
  • Select the checkbox next to the nextwork-devops-cicd-artifact build artifact.
  • Copy the file's S3 URI.
  • Paste the S3 URI into the Revision location field in CodeDeploy.
  • Select .zip as the Revision file type.

What is a revision location? Why did we use our WAR/zip file?

The revision location is the place where CodeDeploy looks to find your application's build artifacts. We're using the S3 bucket that's storing our WAR file, so CodeDeploy knows where to find the latest version of our web app it's deploying to the deployment EC2 instances!

  • Next, we'll leave Additional deployment behavior settings as default.
  • Select Create deployment.

Set Up your Pipeline

Let's dive right into creating our first pipeline! We'll start by setting up the basic pipeline structure and configuring its settings.

In this step, you're going to:

  • Start creating a new pipeline in CodePipeline.

Start a new pipeline

  • Head to the CodePipeline console.
  • Select the Getting started page. Welcome to CodePipeline!

What is AWS CodePipeline? Why are we using it?

With CodePipeline, you can create a workflow that automatically moves your code changes through the build and deployment stage. In our case, you'll see how a new push to your GitHub repository automtically triggers a build in CodeBuild (continuous integration), and a then a deployment in CodeDeploy (continuous deployment)!

Using CodePipeline makes sure your deployments are consistent, reliable and happen automatically whenever you update your code - with less risk of human errors! It saves you time too.

  • In the CodePipeline dashboard, Select Create pipeline.
  • Select Build custom pipeline.

Why build a custom pipeline?

By choosing to build a custom pipeline, we get to define each stage and action step-by-step. This gives us a deeper understanding of how CodePipeline works and allows us to tailor the pipeline precisely to our needs. For learning purposes, building a custom pipeline from scratch is the best way to go !

  • Click Next.

Configure Pipeline Settings

  • Name your pipeline nextwork-devops-cicd
  • Under Execution mode, select Superseded.

What is Execution mode?

Execution mode determines how CodePipeline handles multiple runs of the same pipeline.

In Superseded mode, if a new pipeline execution is triggered while another execution is already in progress, the newer execution will immediately take over and cancel the older one. This is perfect for making sure only the latest code changes are processed, which is exactly what we want for our CI/CD pipeline!

There are other execution modes available in CodePipeline:

  • In Queued mode, executions are processed one after another. If a pipeline is already running, any new executions will wait in a queue until the current execution finishes.
  • Parallel mode allows multiple executions to run at the same time, completely independently of each other. This can speed up the overall processing time if you have multiple branches or code changes that can be built and deployed concurrently.
  • Under Service role, select New service role. Keep the default role name.

What is a service role?

A service role is a special type of IAM role that AWS services like CodePipeline use to perform actions on your behalf. It's like giving CodePipeline permission to access other AWS resources it needs to run your pipeline, such as S3 buckets for storing artifacts or CodeBuild for building your code.

  • Expand Advanced settings.
  • Leave the default settings for Artifact store, Encryption key, and Variables.

What are Artifact store, Encryption key, and Variables?

  • Artifact store: Without an artifact store, there's no way for your build outputs to be passed to deployment! This S3 bucket is where CodePipeline automatically saves the files created at each stage - like your source code from GitHub and the build artifacts from CodeBuild - making them available to the next stage in your pipeline.
  • Encryption key: By default, CodePipeline encrypts everything in your artifact store using AWS managed keys. This keeps your code and build artifacts secure while they're being stored and transferred between stages. For most projects, this default encryption is perfectly sufficient.
  • Variables: Right now you might be manually tracking information like version numbers or build timestamps. Pipeline variables solve this by letting you pass dynamic values between different stages automatically. While we won't use variables in this project, they become essential in more complex pipelines when you need information generated in one stage (like a build number) to be available in another stage (like deployment).
  • Click Next.

Fantastic! You've configured the basic settings for your pipeline. Let's move on to setting up the Source stage.

Configuring the Source, Build and Deploy Stages

Are you ready to pull together all the different parts of your CI/CD architecture?!

In this step, you're going to:

  • Connect CodePipeline to your GitHub repository and branch.
  • Connect CodePipeline to your CodeBuild project
  • Connect CodePipeline to your CodeDeploy deployment group.
  • Configure webhook events to automatically trigger the pipeline.

Source Stage

Now, let's configure the Source stage of our pipeline. This is where we'll tell CodePipeline where to fetch our source code from.

  • In the Source provider dropdown, select GitHub (via GitHub App).

What is the Source stage?

The Source stage is the very first step in any CI/CD pipeline. Its job is simple but crucial: it fetches the latest version of your code from your chosen repository whenever there are updates. Without this stage, your pipeline would have nothing to build or deploy.

CodePipeline supports various source providers, but for this project, we're using GitHub because that's where our web app's code is stored.

  • Under Connection, select your existing GitHub connection
  • Under Repository name, select nextwork-web-project
  • Under Default branch, select master.

What is a branch in Git?

In Git, a branch is like a parallel timeline of your project. It allows you to work on new features or bug fixes without affecting the main codebase. The master branch is typically considered the main branch, representing the stable, production-ready code.

By specifying the master branch as the default branch, we're telling CodePipeline to monitor this branch for changes and trigger the pipeline whenever there's a commit to it.

  • Under Output artifact format, leave it as CodePipeline default.

What is Output artifact format?

Output artifact format determines how CodePipeline packages the source code it fetches from GitHub.

  • CodePipeline default: This option packages the source code as a ZIP file, which is efficient for most deployment scenarios. It does not include Git metadata about the repository.
  • Full clone: This option provides a full clone of the Git repository as an artifact, including Git history and metadata. This is useful if your build process requires Git history, but it results in a larger artifact size.
  • Make sure that Webhook events is checked under Detect change events.

What are Webhook events?

Webhook events let CodePipeline automatically start your pipeline whenever code is pushed to your specified branch in GitHub. This is what makes our pipeline truly "continuous" – it reacts to code changes in real-time!

πŸ’‘ How do Webhooks work?

Webhooks are like digital notifications. When you enable webhook events, CodePipeline sets up a webhook in your GitHub repository. This webhook is configured to listen for specific events, such as code pushes to the master branch.

Whenever you push code to the master branch, GitHub sends a webhook event (a notification) to CodePipeline. CodePipeline then automatically starts a new pipeline execution in response to this event. It's a seamless way to automate your CI/CD process!

  • Click Next.

Great job! You've set up the Source stage of your pipeline. You're now ready to set up the Build stage.

Build stage

The Build stage is where our source code gets transformed into a deployable build artifact.

We'll tell CodePipeline to use AWS CodeBuild to compile and package our web application.

  • In the Build provider dropdown, select AWS CodeBuild from Other build providers.

What is the Build stage?

The Build stage is where your source code gets compiled and packaged into something that can be deployed.

  • Under Project name, select your existing CodeBuild project
  • In the Project name dropdown, search for and select nextwork-devops-cicd.
  • Leave the default settings for Environment variables, Build type, and Region.
  • Under Input artifacts, SourceArtifact should be selected by default.

What are Input artifacts?

Input artifacts are the outputs from the previous stage that are used as inputs for the current stage. In our Build stage, we're using SourceArtifact, which is the ZIP file containing our source code that was outputted by the Source stage.

  • Click Next.

Let's goooo! You've configured the Build stage of your pipeline. You're now ready to move on to the next stage.

Skip Test Stage

  • On the Add test stage page, click Skip test stage.

What is the Test stage?

The Test stage is where you automate testing your application. This can include different types of tests, likes:

  • Unit tests: Testing individual components or functions of your code.
  • Integration tests: Testing how different parts of your application work together.
  • UI tests: Testing the user interface to make sure it works correctly.

The Test stage helps ensure the quality of your code and catch any issues before they reach production. While we're skipping it for this project to simplify things, in real-world scenarios, a Test stage is essential for maintaining software quality and reliability.

Deploy Stage

  • In the Deploy provider dropdown, select AWS CodeDeploy.

What is the Deploy stage?

The Deploy stage is the final step in our pipeline. It's responsible for taking the application artifacts (the output from the Build stage) and deploying them to the target environment, which in our case is an EC2 instance.

  • Under Input artifacts, BuildArtifact should be selected by default.
  • Under Application name, select your existing CodeDeploy application
  • Under Deployment group, select your existing CodeDeploy deployment group
  • Check the box for Configure automatic rollback on stage failure.

What is automatic rollback?

Automatic rollback is a safety net for your deployments. By enabling it, you're telling CodePipeline that if the Deploy stage fails for any reason, it should automatically revert to the last successful deployment. This helps minimize downtime and ensures that your application remains stable, even if a new deployment goes wrong.

  • Click Next.

Awesome! You've configured the Deploy stage of your pipeline. You're just one step away from creating your pipeline.

Run Your Pipeline!

Let's watch our pipeline run for the first time! This will help us verify that everything is working correctly.

In this step, you're going to:

  • Finish creating your pipeline.
  • Watch your pipeline start up and connect GitHub, CodeBuild and CodeDeploy!

Review Your Pipeline

  • On the Review page, take a moment to review all the settings you've configured for your pipeline.

Confirm that the Pipeline settings are:

  • Pipeline name: nextwork-devops-cicd
  • Pipeline type: V2
  • Execution mode: SUPERSEDED
  • Artifact store location: Default location
  • Service role: New service role

Confirm that the Source stage settings are:

  • Source provider: GitHub (via GitHub App)
  • Output artifact format: CODE_ZIP
  • Detect changes: true
  • Connection ARN: Your CodeConnection ARN
  • Full repository ID: Your GitHub account/nextwork-web-project
  • Default branch: master
  • Enable automatic retry on stage failure: Enabled

Confirm that the Build stage settings are:

  • Action provider: AWS CodeBuild
  • Project name: nextwork-devops-cicd
  • Enable automatic retry on stage failure: Enabled

Confirm that the Deploy stage settings are:

  • Action provider: AWS CodeDeploy
  • Application name: nextwork-devops-cicd
  • Deployment group name: nextwork-devops-cicd-deploymentgroup
  • Configure automatic rollback on stage failure: Enabled
  • Once you've reviewed all the settings and confirmed they are correct, click Create pipeline.

Run Your Pipeline

  • After clicking Create pipeline, you will be taken to the pipeline details page.
  • Note the pipeline diagram at the top of the page.
  • CodePipeline automatically starts executing the pipeline as soon as it's created.
  • You can see the progress of each stage in the pipeline diagram. The stages will transition from grey to blue (in progress) to green (success) as the pipeline executes.

What are all the different kinds of statuses?

As your pipeline runs, each stage will display a status:

  • Grey: Stage has not started yet.
  • Blue: Stage is currently in progress.
  • Green: Stage has completed successfully.
  • Red: Stage has failed.
  • Wait for the pipeline execution to complete. You can monitor the status of each stage in the pipeline diagram.
  • To see more details about each execution, click on the Executions tab above the pipeline diagram.

What are Pipeline executions?

Pipeline executions represent each instance of your pipeline running. Every time your pipeline is triggered (either manually or automatically by a webhook), a new execution is created. Each execution has a unique ID and shows the status and details of each stage in that particular run.

  • To view details of a specific stage execution, click on the Stage ID link in the Executions tab. For example, click on the Source stage ID to see details about the source code retrieval.
  • Wait for all stages in the pipeline diagram to turn green, which means your pipeline is all set up using the latest code change!

Test Your Pipeline!

It's time for the ULTIMATE test for this project... let's see how CodePipeline handles a code change!

Testing with a code change will confirm that our pipeline is automatically triggered and deploys our updates.

In this step, you're going to:

  • Test the pipeline by making a code change and pushing it to GitHub.

Test Pipeline with Code Change

  • Open your web app code in your local IDE (e.g., VS Code).
  • Open the index.jsp file located in src/main/webapp/.
  • Add a new line in the <body> section of index.jsp:
<p>If you see this line, that means your latest changes are automatically deployed into production by CodePipeline!</p>
  • Save the index.jsp file.
  • Open your terminal and navigate to your local git repository for the web app.
  • Commit and push the changes to your GitHub repository using the following commands:
git add .
git commit -m "Update index.jsp with a new line to test CodePipeline"
git push origin master

Seeing errors when pushing your code?

Try resetting your Git credentials, and starting over again! Run these commands in your terminal:

git config --global --unset credential.helper
git config --local --unset credential.helper
git remote set-url origin https://[[GITUSERNAME="<github_username>"]]@github.com/[[GITUSERNAME="<github_username>"]]/[[REPONAME="<repository_name>"]].git
  • Make sure to replace <YOUR_GITHUB_USERNAME> with your GitHub username and <YOUR_REPOSITORY_NAME> with your repository name.
  • Then try git push again and enter your GitHub PAT when prompted for the password. Check the top of your VS Code window if you're not prompted in the terminal.
  • Go back to the CodePipeline console and watch your pipeline react to the code change πŸ‘€
  • You should see a new execution starting automatically after you push the changes to GitHub.
  • Click on the Source stage box in the pipeline diagram.
  • Scroll down in the stage details panel to see the commit message.
  • Click on the Commit ID link in the Source stage details panel.
  • This should open the commit page in your GitHub repository in a new browser tab.
  • Verify that the commit page shows the code changes you just pushed (the new line you added to index.jsp)!
  • Wait for the Build and Deploy stages to complete successfully (turn green) in the CodePipeline console.

Verify Automated Deployment

Let's try accessing the web app to see your code change live!

  • To find the Public IPv4 DNS, in the CodePipeline console, click on the Deploy stage, then click on the CodeDeploy link in the details panel.
  • In the CodeDeploy console, scroll down to Deployment lifecycle events and click on the Instance ID.
  • On the EC2 instance summary page, copy the Public IPv4 DNS.
  • Paste the copied Public IPv4 DNS in a new browser tab and press Enter.
  • You should see your web application with the new line you added:

WOOOOOO πŸ˜­πŸ™ This confirms that your latest code changes were automatically deployed by CodePipeline.

UNREAL! Your CI/CD pipeline is now automatically building and deploying your web application whenever you push changes to GitHub.

Secret mission

Before you finish this project - want to test an important emergency procedure?

Your secret mission, should you choose to accept it, is to trigger a manual rollback in your CI/CD pipeline. This is going to give you hands-on experience with one of the most critical operational procedures in a production environment - handling deployment failures and restoring service quickly!

In this secret mission, you're going to:

  • Manually trigger a rollback in your CodePipeline deploy stage.
  • Verify that your web application reverts correctly to its previous state.
  • Demonstrate your disaster recovery skills for your DevOps portfolio!

Trigger a Rollback in CodePipeline

Delete your resources

Delete your resources

Now that we've successfully built, tested, and rolled back our CI/CD pipeline, it's time to clean up the AWS resources we created to avoid incurring any unnecessary costs.

Resources to delete:

  • The CloudFormation stacks
  • The CodePipeline pipeline
  • The CodeDeploy application
  • The CodeBuild project
  • The CodeArtifact repository
  • The CodeArtifact domain
  • The CodeConnection connection
  • The IAM roles
  • The IAM policies
  • The S3 bucket
  • The development EC2 instance

CloudFormation

Note

If you deployed your CI/CD infrastructure with your own custom CloudFormation template, delete that CloudFormation stack now too! This will save you lots of clean up time ahead.

  • Head to the CloudFormation console.
  • Select your deployment EC2 stack.
  • Click Delete.
  • Confirm the deletion by clicking Delete stack.

Code Services

CodePipeline

  • Head to the CodePipeline console.
  • Select Pipelines from the left-hand menu.
  • Select the pipeline named nextwork-devops-cicd.
  • Select Delete.
  • Type delete in the confirmation field.
  • Select Delete.

CodeDeploy

  • Head to the CodeDeploy console.
  • Select Applications from the left hand menu.
  • Select the nextwork-devops-cicd application.
  • Click Delete application.
  • Confirm the deletion by typing delete and clicking Delete.

CodeBuild

  • Head to the CodeBuild console.
  • Select Build projects from the left hand menu.
  • Select the nextwork-devops-cicd project.
  • Click Delete build project.
  • Confirm the deletion by typing delete and clicking Delete.

CodeArtifact

  • Head to the CodeArtifact console.
  • Select Repositories from the left hand menu.
  • Select the nextwork-devops-cicd repository.
  • Click Delete repository.
  • Confirm the deletion by typing delete and clicking Delete repository.
  • Select Domains from the left hand menu.
  • Select the nextwork domain.
  • Click Delete domain.
  • Confirm the deletion by typing delete and clicking Delete domain.

CodeConnection

  • Expand the Settings arrow at the bottom of the left hand navigation panel.
  • Select Connections.
  • Select your connection.
  • Select Delete
  • Confirm the deletion by typing delete and clicking Delete.

Don't forget to delete your other resources!

IAM

  • Head to the IAM console.
  • Select Roles from the left hand menu.
  • Search for and delete the following roles:
    • ec2-instance-nextwork-cicd
    • aws-codedeploy-role
    • codebuild-nextwork-devops-cicd-service-role
    • AWSCodePipelineServiceRole
  • Select Policies from the left hand menu.
  • Search for and delete the following polcies:
    • codeartifact-nextwork-consumer-policy
    • CodeBuildBasePolicy-nextwork-devops-cicd
    • CodeBuildCloudWatchLogsPolicy-nextwork-devops
    • CodeBuildCodeConnectionsSourceCredentialsPolicy-nextwork
    • AWSCodePipelineServiceRole

EC2

  • Head to the EC2 console.
  • Select Instances from the left hand menu.
  • Select the nextwork-devops-enter your name instance.
  • Click Instance state, then Terminate instance.
  • Confirm termination by clicking Terminate.

S3

  • Head to the S3 console.
  • Select Buckets from the left hand menu.
  • Select the nextwork-devops-cicd S3 bucket (your build artifacts bucket)
  • Click Empty bucket.
  • Confirm emptying the bucket by typing permanently delete and clicking Empty bucket.
  • Once the bucket is empty, select the bucket again and click Delete bucket.
  • Confirm deletion by typing the bucket name and clicking Delete bucket.
  • 🚨 Also delete the bucket created by CloudFormation!
    • CloudFormation automatically creates a new bucket to store templates you upload when you create a new stack. The bucket's name should start with cf
    • CodePipeline also creates a new bucket to store artifacts created in the pipeline. The bucket's name should start with codepipeline

Get your documentation!

Get your documentation!

Nice work! πŸ€– You've just built a fully functional CI/CD pipeline for your web application using AWS CodePipeline.

You've learned how to:

  • πŸš€ Set up a CodePipeline pipeline to automate your software release process.
  • πŸ“¦ Configure a Source stage to fetch code changes from GitHub.
  • πŸ› οΈ Set up a Build stage using AWS CodeBuild to compile your web application.
  • βš™οΈ Configure a Deploy stage using AWS CodeDeploy to deploy your web application to EC2.
  • πŸ’Ž Test rollbacks on the deployment - without affecting your pipeline's Source or Build!

Ready to quiz yourself? You got this! πŸ’ͺ

See you in the FINAL project of the 6 Day DevOps Challenge - Build a CI/CD Pipeline with AWS!

p.s. Does it say "Still tasks to complete!" at the bottom of the screen?

This means you still have screenshots left to upload, or questions left to answer!

  1. Press Ctrl+F (Windows) or Command+F (Mac) on your keyboard.
  2. Search for the text Return to later.
  3. Jump straight to your incomplete tasks!
  4. πŸ™‹β€β™€οΈ Still stuck? Ask the community!