CI/CD Pipeline Tutorial for Developers

CI/CD pipeline tutorial hero graphic with build, test and deploy stages connected by arrows

CI/CD Pipeline Tutorial for Developers

This CI/CD pipeline tutorial for developers shows how to go from “I run tests manually on my laptop” to “every push triggers automated checks and deploys safely.” Instead of staying abstract, we will build a small CI/CD pipeline around a Node.js backend, Git, and a GitHub Actions workflow (the same ideas map to GitLab CI, Azure Pipelines, CircleCI, etc.).

In this CI/CD pipeline tutorial you will:

  • Understand what Continuous Integration (CI) and Continuous Delivery/Deployment (CD) actually mean
  • Prepare a repo with a small Node.js API and automated tests
  • Define a CI workflow that runs on every push
  • Add a CD step that deploys on main branch changes
  • Read basic pipeline “health” from logs and simple metrics

To see how this fits into your stack, pair it with:
Git version control tutorial,
Node.js backend basics tutorial,
PHP backend basics tutorial,
Linux basics for developers,
Kubernetes basics tutorial,
and the
Azure cloud basics tutorial.

For platform-specific details, keep docs like
GitHub Actions,
GitLab CI/CD,
or
CircleCI
open in another tab.


1. CI/CD pipeline tutorial: core concepts

Before writing YAML, this CI/CD pipeline tutorial starts with a quick mental model:

  • Continuous Integration (CI) – every push triggers automated checks (lint, tests, build) so broken changes surface quickly.
  • Continuous Delivery (CD) – every passing build is deployable with a button or simple command.
  • Continuous Deployment – every passing change goes live automatically, often behind feature flags.

In practice, a CI/CD pipeline is just a series of automated steps wired to events in your Git repository—pushes, pull requests, tags, and scheduled runs.


2. Prepare a small backend for the pipeline

This CI/CD pipeline tutorial uses a tiny Node.js service (the same structure works for PHP, Python, Java, etc.). You can start with the app from the Node.js backend basics tutorial or create a fresh demo project.

2.1 Minimal Node.js service

mkdir ci-cd-demo
cd ci-cd-demo

npm init -y
npm install express

mkdir src

Create src/server.js:

import express from "express";

const app = express();
const port = process.env.PORT || 3000;

app.get("/health", (req, res) => {
  res.json({ status: "ok", service: "ci-cd-demo" });
});

app.listen(port, () => {
  console.log(`CI/CD demo API listening on http://localhost:${port}`);
});

2.2 Add a simple test

Now add a tiny Jest test so the CI stage has something real to run.

npm install --save-dev jest supertest

Create src/server.test.js:

import request from "supertest";
import express from "express";

function createApp() {
  const app = express();
  app.get("/health", (req, res) => {
    res.json({ status: "ok" });
  });
  return app;
}

test("GET /health returns ok", async () => {
  const app = createApp();
  const res = await request(app).get("/health");
  expect(res.status).toBe(200);
  expect(res.body.status).toBe("ok");
});

Finally, update package.json to add scripts and enable ES modules:

{
  "name": "ci-cd-demo",
  "version": "1.0.0",
  "type": "module",
  "scripts": {
    "start": "node src/server.js",
    "test": "jest"
  },
  "dependencies": {
    "express": "^4.19.0"
  },
  "devDependencies": {
    "jest": "^29.7.0",
    "supertest": "^7.0.0"
  }
}

With this in place, npm test should pass locally. That’s the baseline your CI stage will enforce.


3. Add Git and branch strategy

Because every CI/CD pipeline tutorial depends on Git, the next step is wiring your project into a remote repo and deciding on a branch strategy.

3.1 Initialize Git and push to remote

git init
git add .
git commit -m "Initial CI/CD demo service"

git remote add origin git@github.com:YOURUSER/ci-cd-demo.git
git push -u origin main

If you need a refresher on Git concepts, see the
Git version control tutorial.

3.2 Simple branch model

For this CI/CD pipeline tutorial, we will assume:

  • main – always deployable; CI must be green before changes merge.
  • Feature branches – open pull requests that must pass CI before merging into main.

This keeps the pipeline logic straightforward while still reflecting how real teams work.


4. Define a CI workflow (GitHub Actions)

Now we create a CI workflow that runs tests on every push and pull request. The same ideas apply if you prefer GitLab CI or another engine; only the syntax changes.

4.1 Workflow file

Create .github/workflows/ci.yml in your repo:

name: CI

on:
  push:
    branches: ["main"]
  pull_request:
    branches: ["main"]

jobs:
  test:
    runs-on: ubuntu-latest

    steps:
      - name: Checkout code
        uses: actions/checkout@v4

      - name: Use Node.js 20
        uses: actions/setup-node@v4
        with:
          node-version: "20"

      - name: Install dependencies
        run: npm ci

      - name: Run tests
        run: npm test

Commit and push this file. On GitHub, you should see a CI run kick off under the “Actions” tab every time you push.

4.2 Make CI visible in pull requests

Once you have at least one successful CI run, you can enable branch protection on main so that pull requests cannot merge unless the CI workflow is green. This is one of the highest-impact uses of CI/CD for teams.


5. Add a simple CD step for deployments

Next, this CI/CD pipeline tutorial adds a basic delivery step that runs after tests pass on the main branch. The exact deployment command depends on your hosting (Docker, Kubernetes, bare VM, PaaS, etc.). Here we’ll use a placeholder deploy script to keep it generic.

5.1 Deployment script

Add a deploy.sh script at the project root:

#!/usr/bin/env bash
set -euo pipefail

echo "Starting deploy of ci-cd-demo..."

# Example steps (replace with your real ones):
# 1) Build Docker image and push to registry
# docker build -t registry.example.com/ci-cd-demo:latest .
# docker push registry.example.com/ci-cd-demo:latest
#
# 2) Trigger Kubernetes rollout
# kubectl set image deployment/ci-cd-demo \
#   api=registry.example.com/ci-cd-demo:latest
# kubectl rollout status deployment/ci-cd-demo

echo "Deploy script finished (no-op in tutorial)."

Make it executable:

chmod +x deploy.sh

5.2 Extend the workflow with a deploy job

Now extend .github/workflows/ci.yml to add a deploy job that runs only on main and only after tests pass:

name: CI/CD

on:
  push:
    branches: ["main"]
  pull_request:
    branches: ["main"]

jobs:
  test:
    runs-on: ubuntu-latest
    steps:
      - name: Checkout code
        uses: actions/checkout@v4

      - name: Use Node.js 20
        uses: actions/setup-node@v4
        with:
          node-version: "20"

      - name: Install dependencies
        run: npm ci

      - name: Run tests
        run: npm test

  deploy:
    needs: test
    runs-on: ubuntu-latest
    if: github.ref == 'refs/heads/main' && github.event_name == 'push'

    steps:
      - name: Checkout code
        uses: actions/checkout@v4

      - name: Run deploy script
        run: ./deploy.sh

In a real environment you would add secrets (e.g. registry tokens, SSH keys) via the CI platform UI and reference them with ${{ secrets.NAME }} in the workflow.


6. Tiny pipeline health “chart”

Finally, to make the effect of your CI/CD pipeline more tangible, this CI/CD pipeline tutorial includes a tiny “pipeline health” chart using a simple HTML table. In a real system you’d wire this into Grafana or a dashboard, but the pattern is the same.

run_id,status,duration_sec,tests_passed
101,success,45,12
102,failed,18,8
103,success,39,12
104,success,42,12
Run ID Status Duration (s) Tests Passed Relative “Cost”
101 Success 45 12
102 Failed 18 8
103 Success 39 12
104 Success 42 12

Even in this simplistic view, you can start to reason about how long a CI/CD pipeline run takes, how often tests fail and whether you might want to split heavy jobs into parallel stages.

With this CI/CD pipeline tutorial as a baseline, you can now plug in real deployment targets (Docker, Kubernetes, Adobe Commerce, Odoo, etc.), integrate code quality tools, and connect your CI/CD pipeline to observability stacks like Prometheus, Grafana and centralized logging.

Leave a Comment

Your email address will not be published. Required fields are marked *

Scroll to Top