Skip to content
EgyKode
08 · Continuous deliveryLab 46 / 59
Guided labjenkins

Enterprise Multibranch CI/CD Pipeline with SonarQube & Trivy

Make a commit build, get scanned for code and image vulnerabilities, and deploy itself — with gates that block.

Time
31 min
Level
Advanced
Objectives
4 objectives
Cost
Low cost

Where this fits in the platform

Before you start

CostLow cost

for the Jenkins instance itself; SonarQube wants ~2 GB of RAM, so a `t3.small` (~$15/month) is realistic. ECR storage for the images the pipeline pushes is inside the free tier at this scale.

How to clean up

The scenario#

The pipeline is green. It is also building latest, pushing before it scans, and finishing the moment kubectl set image returns — so a deploy that never becomes ready reports success.

A gate that reports instead of blocking is a dashboard, not a gate.

Hands-on environment

Run it on your own machine

Run this lab on your own machine. One command starts the environment, with everything the lab needs already installed:

Stages 1–7 run locally: checkout, build, unit tests, SonarQube analysis, quality gate, image build and Trivy scan all work against the local registry. The last stages push to ECR and deploy to EKS, and those need an AWS account.

You will need:

  • docker
git clone https://github.com/EgyKode/EgyKode-lab.git
cd EgyKode-lab
./egykode start cicd
./egykode shell

You need Docker and Git installed. Everything else runs inside the environment. The first start downloads it and takes a few minutes; later starts are seconds.

Not sure what you already have? Run: npm run doctor — it checks and changes nothing.

Run it on AWS

This lab builds real cloud infrastructure, so it needs your own AWS account. Follow the cost and cleanup notes above — the resources are yours, and so is the bill.

Anything you tick here is your own record. EgyKode cannot see inside that terminal, so the success criteria stay self-assessed even when the environment checks your work for you.

The Jenkinsfile

Step 1 of 3

What you are building#

text
  checkout -> unit tests -> SonarQube gate -> build image -> Trivy scan
                                                                |
                                        CRITICAL+fixable? ------+--> FAIL, no push
                                                                |
                                                                v
                                                    push to ECR -> deploy -> wait

Order is the design. Scan before the push, because scanning afterwards means the vulnerable image is already in the registry and someone can pull it. Cheap checks first, so an expensive scan only runs on code that compiles.


Build it#

Verify it worked#

Terminal
# The image was tagged by commit, never latest
aws ecr describe-images --repository-name platform/api \
  --query 'sort_by(imageDetails,&imagePushedAt)[-1].imageTags'
 
# The running image matches what the pipeline pushed
kubectl get deploy api -n platform \
  -o jsonpath='{.spec.template.spec.containers[0].image}'

Prove each gate blocks, rather than trusting it:

Terminal
# 1. A knowingly vulnerable base — the build must FAIL at Scan, with no push
#    A frozen point release, NOT an end-of-life distribution: an EOL distro
#    ships no fixes, so --ignore-unfixed discards nearly everything it carries.
#    Measured: debian:12.5-slim 15 findings, debian:10 exactly 1, ubuntu:18.04 none.
echo "FROM debian:12.5-slim" > Dockerfile.vuln
docker build -f Dockerfile.vuln -t probe:vuln .
trivy image --severity HIGH,CRITICAL --ignore-unfixed --exit-code 1 probe:vuln
echo "exit=$?"     # 1
 
# 2. The image must NOT be in the registry after a failed build
aws ecr describe-images --repository-name platform/api \
  --query 'imageDetails[].imageTags' | grep vuln || echo "never pushed — correct"
 
# 3. Break the quality gate deliberately and confirm the pipeline stops
#    (add a blocker-level issue, or lower the gate threshold in SonarQube)

A gate you have never seen fail is a gate you cannot claim works.


Clean up#

Terminal
docker image prune -af
aws ecr list-images --repository-name platform/api --filter tagStatus=UNTAGGED \
  --query 'imageIds[]' --output json > /tmp/untagged.json
aws ecr batch-delete-image --repository-name platform/api --image-ids file:///tmp/untagged.json

Cost of this lab: Low. The Jenkins host and the cluster bill anyway. ECR storage is $0.10/GB-month, which is why the lifecycle policy from the ECR lab matters.

Maintained by others, on Killercoda. Useful for extra repetition on one tool — it does not complete this lab or settle any criterion above.

Success criteria

0 of 4

The concept behind it

Ready to try it without help?Do the challenge

Next up

Lab 46 of 59 on the project path

GitHub Actions: Build, Scan and Deploy to EKSThe same pipeline as the Jenkins lab, with no server to maintain and no stored AWS credentials.55 minIntermediateBillable — destroy resources when you finish

Previous: Jenkins Pipeline: Build, Scan and Push an Image