Hands-on Lab

#Lab: Complete GitLab CI/CD Pipeline

Build a full CI/CD pipeline with GitLab CI.

#🎯 Objectives

  • Create multi-stage GitLab pipeline
  • Implement environment deployments
  • Use caching and artifacts
  • Set up manual approvals

#📋 Prerequisites

  • GitLab repository

#⏱️ Duration: 45 minutes


#Task 1: Basic Pipeline Structure (10 min)

Create .gitlab-ci.yml:

yaml
1stages:
2  - build
3  - test
4  - security
5  - deploy
6
7variables:
8  DOCKER_IMAGE: $CI_REGISTRY_IMAGE:$CI_COMMIT_SHORT_SHA
9
10# Default settings
11default:
12  image: node:20-alpine
13  cache:
14    key: ${CI_COMMIT_REF_SLUG}
15    paths:
16      - node_modules/
17
18# Build job
19build:
20  stage: build
21  script:
22    - npm ci
23    - npm run build
24  artifacts:
25    paths:
26      - dist/
27    expire_in: 1 hour
28
29# Unit tests
30unit-test:
31  stage: test
32  script:
33    - npm ci
34    - npm test
35  coverage: '/Coverage: \d+\.\d+%/'
36
37# Integration tests
38integration-test:
39  stage: test
40  services:
41    - postgres:15
42  variables:
43    POSTGRES_DB: test
44    POSTGRES_PASSWORD: test
45  script:
46    - npm ci
47    - npm run test:integration

#Task 2: Docker Build and Push (10 min)

yaml
1docker-build:
2  stage: build
3  image: docker:24
4  services:
5    - docker:24-dind
6  variables:
7    DOCKER_TLS_CERTDIR: "/certs"
8  before_script:
9    - docker login -u $CI_REGISTRY_USER -p $CI_REGISTRY_PASSWORD $CI_REGISTRY
10  script:
11    - docker build -t $DOCKER_IMAGE .
12    - docker push $DOCKER_IMAGE
13  only:
14    - main
15    - develop

#Task 3: Environment Deployments (15 min)

yaml
1# Deploy to staging
2deploy-staging:
3  stage: deploy
4  image: bitnami/kubectl:latest
5  environment:
6    name: staging
7    url: https://staging.example.com
8  script:
9    - kubectl set image deployment/app app=$DOCKER_IMAGE
10  only:
11    - develop
12
13# Deploy to production (manual approval)
14deploy-production:
15  stage: deploy
16  image: bitnami/kubectl:latest
17  environment:
18    name: production
19    url: https://example.com
20  script:
21    - kubectl set image deployment/app app=$DOCKER_IMAGE
22  when: manual
23  only:
24    - main
25  needs:
26    - job: deploy-staging
27      optional: true

#Task 4: Security Scanning (10 min)

yaml
1# SAST scanning
2sast:
3  stage: security
4  image: 
5    name: semgrep/semgrep:latest
6    entrypoint: [""]
7  script:
8    - semgrep --config auto --json -o semgrep.json .
9  artifacts:
10    reports:
11      sast: semgrep.json
12    when: always
13
14# Container scanning
15container-scan:
16  stage: security
17  image:
18    name: aquasec/trivy:latest
19    entrypoint: [""]
20  script:
21    - trivy image --exit-code 0 --severity HIGH,CRITICAL $DOCKER_IMAGE
22  needs:
23    - docker-build
24  only:
25    - main

#Complete Pipeline Example

yaml
1stages:
2  - build
3  - test
4  - security
5  - staging
6  - production
7
8variables:
9  DOCKER_IMAGE: $CI_REGISTRY_IMAGE:$CI_COMMIT_SHORT_SHA
10
11default:
12  image: node:20-alpine
13  cache:
14    key: ${CI_COMMIT_REF_SLUG}
15    paths:
16      - node_modules/
17
18build:
19  stage: build
20  script:
21    - npm ci
22    - npm run build
23  artifacts:
24    paths:
25      - dist/
26    expire_in: 1 day
27
28test:
29  stage: test
30  script:
31    - npm ci
32    - npm test
33
34deploy-staging:
35  stage: staging
36  environment:
37    name: staging
38  script:
39    - echo "Deploying to staging"
40  only:
41    - main
42
43deploy-production:
44  stage: production
45  environment:
46    name: production
47  script:
48    - echo "Deploying to production"
49  when: manual
50  only:
51    - main

#✅ Success Criteria

  • Multi-stage pipeline created
  • Docker image builds and pushes
  • Environment deployments configured
  • Manual approval for production