Skip to main content

How to set up a GitLab CI/CD pipeline

Set up a GitLab CI/CD pipeline with test, build, and deploy stages. Covers stages, job artifacts, and running deploys only on the default branch.

Difficulty
Beginner
Duration
40 minutes
Steps
6

What and why

GitLab CI/CD runs pipelines defined in a single file at the repository root. Pipelines group jobs into ordered stages, so tests run before builds and builds before deploys. Because the configuration lives in the repository, the pipeline is versioned with your code: a change to the build is reviewed and merged like any other change. This tutorial creates a practical three-stage pipeline that tests, builds, and deploys an application.

GitLab executes jobs on runners. On GitLab.com shared runners are available immediately; self-managed instances can register their own. Either way, the YAML you write is identical, which makes the pipeline portable across GitLab installations.

Prerequisites

  • A GitLab project with CI/CD enabled (shared runners are available by default on GitLab.com).
  • An application with commands to test and build it.
  • Basic YAML knowledge, since indentation is significant.

Steps

1. Create .gitlab-ci.yml

Add a file named .gitlab-ci.yml to the repository root. GitLab detects this file automatically and begins running pipelines on the next push. You can validate the syntax before committing using the pipeline editor in the GitLab UI, which catches indentation and keyword errors early.

2. Define stages

Stages run in the order they are listed. Jobs assigned to the same stage run in parallel, and the next stage starts only after all jobs in the current one succeed.

stages:
  - test
  - build
  - deploy

default:
  image: node:20

The default.image sets the container image every job runs in unless a job overrides it. Pinning a specific image tag keeps builds reproducible.

3. Add a test job

unit-test:
  stage: test
  script:
    - npm ci
    - npm test

A job belongs to a stage and runs the commands under script in sequence. A non-zero exit from any command fails the job, which in turn blocks later stages. Keep test jobs focused so a failure points clearly at what broke.

4. Add a build job with artifacts

build:
  stage: build
  script:
    - npm ci
    - npm run build
  artifacts:
    paths:
      - dist/
    expire_in: 1 week

Artifacts pass files from one stage to the next and are downloadable from the pipeline UI. Here the compiled dist/ output is preserved so the deploy stage can ship the exact bytes that were built, rather than rebuilding. The expire_in setting keeps storage in check.

5. Add a conditional deploy job

deploy:
  stage: deploy
  script:
    - ./deploy.sh
  rules:
    - if: '$CI_COMMIT_BRANCH == "main"'

The rules block decides whether a job is added to the pipeline. This rule runs deploy only on the default branch, so feature branches run test and build but stop before deploying. GitLab exposes many predefined variables like CI_COMMIT_BRANCH that you can branch logic on.

Verification

Commit and push, then open Build > Pipelines in GitLab. You should see the test, build, and deploy stages laid out in sequence. Click the build job and confirm its artifacts are downloadable. Push to a feature branch and confirm the deploy job does not appear, proving the rule works. A failed test should mark the whole pipeline as failed and stop later stages.

Next Steps

Add a cache key to reuse node_modules between runs and speed up installs. Add manual approval to the deploy job with when: manual so a human gates production. Extract repeated configuration into extends or YAML anchors to keep the file maintainable. For multiple environments, define separate deploy jobs scoped by branch or tag.

Prerequisites

  • A GitLab project
  • An app with test and build commands
  • Basic YAML knowledge

Steps

  • 1
    Create .gitlab-ci.yml
  • 2
    Define stages
  • 3
    Add a test job
  • 4
    Add a build job with artifacts
  • 5
    Add a conditional deploy job
  • 6
    Verify the pipeline

Category

CI/CD