TL;DR A CI/CD pipeline automates code changes from development to production, consisting of four stages: source, build, test, and deploy. This article guides you through building a simple pipeline for a Node.js application using GitHub Actions and Docker. The pipeline automates the build, test, and deployment of the app to Heroku, demonstrating the concepts of Continuous Integration and Continuous Deployment.
Building a Simple CI/CD Pipeline: A Step-by-Step Guide
As a full-stack developer, you're well aware of the importance of efficient and automated workflows in software development. One such workflow is Continuous Integration and Continuous Deployment (CI/CD), which ensures that your code changes are automatically built, tested, and deployed to production. In this article, we'll delve into the world of CI/CD pipelines and build a simple one from scratch.
What is a CI/CD Pipeline?
Before we dive into the implementation, let's quickly understand what a CI/CD pipeline is. A CI/CD pipeline is a series of automated processes that take your code changes from development to production. The pipeline consists of several stages:
- Source: Where your code lives.
- Build: Compiling and packaging your code.
- Test: Verifying your code works as expected.
- Deploy: Releasing your code to production.
Our Simple CI/CD Pipeline Example
For this example, we'll use a simple Node.js application that prints "Hello, World!" to the console. We'll create a pipeline that automates the build, test, and deployment of our app.
Step 1: Setting up the Source Stage
We'll start by creating a new Node.js project with a single file app.js containing our "Hello, World!" code:
console.log("Hello, World!");
Next, we'll create a new repository on GitHub and initialize it with our app.js file. This will be our source stage.
Step 2: Creating the Build Stage
For the build stage, we'll use Docker to create a container that can run our Node.js application. We'll create a new file called Dockerfile in our repository:
FROM node:14
WORKDIR /app
COPY package*.json ./
RUN npm install
COPY . .
CMD ["node", "app.js"]
This Dockerfile instructs Docker to:
- Use the official Node.js 14 image.
- Create a new working directory
/app. - Copy our
package.jsonfile into the container. - Install dependencies using
npm install. - Copy our application code into the container.
- Set the default command to run our
app.jsfile with Node.js.
Step 3: Configuring the Test Stage
For the test stage, we'll create a simple test that verifies our "Hello, World!" output. We'll add a new file called test.js to our repository:
const app = require('./app');
describe('App', () => {
it('prints Hello, World!', () => {
const output = app();
expect(output).toBe("Hello, World!\n");
});
});
This test uses Jest to verify that our app.js file outputs "Hello, World!" when executed.
Step 4: Setting up the Deploy Stage
For the deploy stage, we'll use GitHub Actions to automate the deployment of our containerized application to a cloud platform like Heroku. We'll create a new file called .github/workflows/deploy.yml in our repository:
name: Deploy to Heroku
on:
push:
branches:
- main
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v2
- name: Login to Heroku
uses: heroku-actions/login@v1
with:
api-key: ${{ secrets.HEROKU_API_KEY }}
- name: Deploy to Heroku
run: |
docker build -t my-app .
docker tag my-app registry.heroku.com/my-app
docker push registry.heroku.com/my-app
This workflow file defines a job that:
- Triggers on pushes to the
mainbranch. - Checks out our code using GitHub Actions.
- Logs in to Heroku using an API key stored as a secret.
- Builds and deploys our Docker container to Heroku.
Putting it all Together
With our pipeline stages defined, let's trigger the workflow by pushing changes to our repository. GitHub Actions will automatically detect the .github/workflows/deploy.yml file and execute the pipeline.
As the pipeline runs, you'll see each stage executing in sequence: source, build, test, and deploy. Finally, your "Hello, World!" application will be live on Heroku!
Conclusion
In this article, we've built a simple CI/CD pipeline that automates the build, test, and deployment of a Node.js application to Heroku using GitHub Actions and Docker. This pipeline demonstrates the foundational concepts of Continuous Integration and Continuous Deployment.
While our example is basic, it lays the groundwork for more complex pipelines that integrate with multiple services and tools. As you continue to develop your skills as a full-stack developer, remember to automate and streamline your workflows using CI/CD pipelines.
Key Use Case
Here's a workflow or use-case example:
E-commerce Website Deployment
An e-commerce company wants to automate the deployment of its website updates. The development team makes frequent code changes, and manual testing and deployment are time-consuming and prone to errors.
Using a CI/CD pipeline, the team can automate the following stages:
- Source: GitHub repository with website code.
- Build: Create a containerized environment using Docker for consistent builds.
- Test: Run automated tests to ensure website functionality and performance.
- Deploy: Automatically deploy the updated website to a cloud platform like AWS.
With this pipeline, the team can focus on writing code while the CI/CD pipeline handles testing and deployment, reducing errors and increasing efficiency.
Finally
As we've seen, building a simple CI/CD pipeline requires careful planning and execution of each stage. By automating the build, test, and deployment processes, developers can focus on writing code rather than worrying about the logistics of getting it to production. This not only saves time but also reduces the likelihood of human error, ultimately leading to faster and more reliable software delivery.
Recommended Books
Here are some recommended books for further learning:
• "Continuous Delivery" by Jez Humble and David Farley • "CI/CD Pipelines" by Michael Noll • "Docker: Up & Running" by Karl Matthias and Sean P. Kane • "Automate the Boring Stuff with Python" by Al Sweigart
