This blog has covered gitleaks, tfsec/Checkov, Trivy, and SBOM generation individually. This guide combines all four into a single, ordered CI/CD pipeline — commit to production — so each gate catches its category of problem before the next stage even starts, ending with an ArgoCD sync as the final deployment step.
Step 1: The Full Pipeline Shape
The pipeline runs as an ordered sequence of gates, each one blocking the next on failure: secrets scan → IaC scan → build → image scan → SBOM generation → push → deploy. Ordering matters — catching a leaked secret before spending build minutes on an image that will fail scanning anyway saves pipeline time, and fixing IaC issues before image concerns keeps failure feedback focused on one category at a time.

Step 2: Secrets Scan Stage
First stage, runs against the commit before anything else: gitleaks detect --source . --exit-code 1. This is deliberately the very first gate — a leaked credential is the most urgent class of finding, and there’s no reason to spend compute building or scanning an image from a commit that already needs to be blocked and the secret rotated.

Step 3: IaC Scan Stage
If the repo includes Terraform (as with our Proxmox Terraform setup), run tfsec . and checkov -d . next, before any application build — infrastructure misconfigurations are independent of the application code and shouldn’t wait behind a build step to be caught.

Step 4: Build Stage
Only after both prior gates pass does the pipeline build the actual container image (docker build -t registry.example.com/app:$CI_COMMIT_SHA .) — building is often the slowest step, so gating it behind the fast secrets/IaC checks avoids wasting that time on commits that were already going to be rejected.

Step 5: Image Scan Stage
Immediately after build: trivy image --severity CRITICAL,HIGH --exit-code 1 registry.example.com/app:$CI_COMMIT_SHA. This is the gate that catches vulnerable base images and dependencies baked into the container — failing here means the image never gets pushed to the registry at all.

Step 6: SBOM Generation Stage
Once the image passes scanning, generate its SBOM: syft registry.example.com/app:$CI_COMMIT_SHA -o cyclonedx-json > sbom.json, then upload it as a pipeline artifact or attach it to the image in Harbor. This runs after the scan gate, not before — no reason to catalog an image that just failed and won’t be pushed anyway.

Step 7: Push and Deploy Stages
Push the now-scanned, now-catalogued image to the registry, then trigger deployment — in a GitOps flow, this typically means updating the image tag in the manifests repo that ArgoCD watches, letting ArgoCD’s own sync (automatic or triggered with argocd app sync) handle the actual cluster rollout rather than the CI pipeline pushing to Kubernetes directly.

Step 8: Rolling This Out Without Breaking Every Build on Day One
Enabling every gate as a hard failure simultaneously on an existing codebase usually surfaces a backlog of pre-existing findings that blocks every single build immediately. Roll out in report-only mode first (run each tool, log findings, but don’t fail the build) for a week or two, triage the backlog with documented exceptions (.trivyignore, tfsec inline suppressions, gitleaks allowlist entries), and only then flip each gate to hard-fail once the baseline is actually clean.

Example combined GitLab CI pipeline
stages: [secrets-scan, iac-scan, build, image-scan, sbom, deploy]
secrets-scan:
stage: secrets-scan
script: gitleaks detect --source . --exit-code 1
iac-scan:
stage: iac-scan
script:
- tfsec .
- checkov -d .
build:
stage: build
script: docker build -t $IMAGE .
image-scan:
stage: image-scan
script: trivy image --severity CRITICAL,HIGH --exit-code 1 $IMAGE
sbom:
stage: sbom
script: syft $IMAGE -o cyclonedx-json > sbom.json
artifacts: { paths: [sbom.json] }
deploy:
stage: deploy
script:
- docker push $IMAGE
- argocd app sync myapp
Related tutorials
- Secrets Scanning with Gitleaks
- Terraform Security Scanning
- CI/CD Security Scanning with Trivy
- SBOMs with Syft and Grype
- GitOps with ArgoCD
Terminal screenshots are original illustrations created for Gnome IT Solutions (blog.gnomeitsolutions.com).