GitLab CI/CD Basics

CI/CD stands for Continuous Integration and Continuous Delivery. GitLab CI/CD automatically builds, tests, and deploys your code every time someone pushes a change. It replaces manual, error-prone steps with a reliable automated process.

The Problem CI/CD Solves

  WITHOUT CI/CD:
  Dev pushes code → manually runs tests (or forgets to) →
  manually builds the app → manually uploads to server →
  hopes nothing broke in production 😬

  WITH CI/CD:
  Dev pushes code → GitLab automatically runs tests →
  builds the app → deploys to server →
  reports success or failure with details ✅

Continuous Integration vs Continuous Delivery

TermWhat It MeansExample
Continuous Integration (CI)Every push triggers automated tests immediatelyRun unit tests on every commit
Continuous Delivery (CD)Successfully tested code is prepared for deployment automaticallyBuild a Docker image and upload to registry
Continuous DeploymentCode goes live automatically after all tests passDeploy to production server without human approval

The .gitlab-ci.yml File

GitLab CI/CD is configured entirely through a file named .gitlab-ci.yml in the root of your repository. This file tells GitLab what to run, when to run it, and in what order.

  Repository root:
  ├── src/
  ├── tests/
  ├── README.md
  └── .gitlab-ci.yml   ← CI/CD instructions live here

Every time you push code, GitLab reads this file and executes the instructions automatically.

Your First .gitlab-ci.yml File

Here is the simplest possible CI/CD file — it runs one test job:

  run-tests:
    script:
      - echo "Running tests..."
      - npm test

Breaking it down:

  • run-tests — the name you give this job (can be anything)
  • script — the list of shell commands to execute

Stages — Controlling the Order

Stages define the order in which jobs run. All jobs in the same stage run in parallel. The next stage starts only after all jobs in the current stage pass.

  stages:
    - build
    - test
    - deploy

  build-app:
    stage: build
    script:
      - npm run build

  run-unit-tests:
    stage: test
    script:
      - npm test

  deploy-to-staging:
    stage: deploy
    script:
      - ./deploy.sh staging

Visual Pipeline Flow

  Push code
     ↓
  ┌──────────┐   ┌──────────┐   ┌──────────┐
  │  build   │ → │   test   │ → │  deploy  │
  │ build-app│   │unit-tests│   │ staging  │
  └──────────┘   └──────────┘   └──────────┘
   2 min ✅        4 min ✅        1 min ✅
                                        ↓
                               App is live on staging

Images — The Environment Your Jobs Run In

Each job runs inside a Docker container. The image keyword specifies which container image to use.

  run-tests:
    image: node:20        ← use a container with Node.js 20
    script:
      - npm install
      - npm test

  build-java:
    image: maven:3.9      ← use a container with Java and Maven
    script:
      - mvn package

This means every job gets a clean, consistent environment regardless of what software is installed on the server running it.

Variables — Storing Configuration Values

Variables store values your scripts need without hardcoding them into the YAML file.

  variables:
    NODE_ENV: "production"
    API_URL: "https://api.example.com"

  deploy:
    script:
      - echo "Deploying to $API_URL"

Sensitive values like passwords and tokens go into CI/CD variables in GitLab settings (not in the YAML file), where they are stored encrypted and masked in logs.

Viewing a Pipeline Run

After pushing code, go to Build → Pipelines. You see a list of recent pipeline runs. Click any run to see the stages and jobs inside it.

  Pipeline #112   ●  running    main   Riya  2 min ago
  Pipeline #111   ✅ passed     main   Arjun 1 hour ago
  Pipeline #110   ❌ failed     fix/bug Sara  3 hours ago

Click a failed pipeline to see which job failed and read its log output to find the error.

Reading a Job Log

Click any job inside a pipeline to see its full terminal output. The log shows every command that ran and what it printed.

  Job: run-unit-tests
  ─────────────────────────────────────────
  $ npm install
  added 240 packages in 12s

  $ npm test
  PASS  tests/auth.test.js
  PASS  tests/search.test.js
  FAIL  tests/payment.test.js
    ● Payment › should validate card number
      Expected: true
      Received: false

  Tests: 1 failed, 2 passed
  ─────────────────────────────────────────
  Job failed ❌

Only and Except — Controlling When Jobs Run

Use only to run a job only on specific branches, or except to skip it on certain branches.

  deploy-production:
    stage: deploy
    script:
      - ./deploy.sh production
    only:
      - main          ← this job runs ONLY when code is pushed to main

  run-tests:
    stage: test
    script:
      - npm test
    except:
      - docs/*        ← skip tests for documentation-only branches

Rules — The Modern Alternative to Only/Except

The rules keyword gives more precise control. It evaluates conditions in order and applies the first match.

  deploy:
    script:
      - ./deploy.sh
    rules:
      - if: '$CI_COMMIT_BRANCH == "main"'
        when: on_success
      - when: never        ← do not run on any other branch

Artifacts — Saving Job Output

An artifact is a file or folder that a job produces and saves so other jobs (or you) can download it later.

  build-app:
    stage: build
    script:
      - npm run build       ← produces the dist/ folder
    artifacts:
      paths:
        - dist/             ← save dist/ for later jobs
      expire_in: 1 week     ← delete after 1 week

  deploy:
    stage: deploy
    script:
      - cp -r dist/ /var/www/html   ← use the saved dist/ from build

Artifacts also appear as downloadable files on the pipeline page so developers can inspect build outputs directly.

Leave a Comment

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