CI:
sampleapp-cicd / ci (push) Failing after 20s
sampleapp-cicd / deploy (push) Skipped
sampleapp-cicd / notify (push) Successful in 2s

This commit is contained in:
2026-07-18 21:01:06 +02:00
parent 44d0d83366
commit 12fb361466
+34 -31
View File
@@ -35,46 +35,49 @@ jobs:
set -e
docker build -t "${IMAGE}:${GITHUB_SHA}" -t "${IMAGE}:latest" .
# --- Feature 4: Trivy vulnerability scan (gate) --------------------------
# Install the Trivy binary from the official script (the runner reaches the
# internet; a pinned binary is more reproducible here than the
# trivy-action, which resolves from github.com/master). The scan runs
# against the locally-built image over the runner's docker.sock.
- name: Install Trivy
run: |
set -e
curl -sfL https://raw.githubusercontent.com/aquasecurity/trivy/main/contrib/install.sh \
| sh -s -- -b /usr/local/bin v0.58.1
trivy --version
# Gate: fail ci on any fixable CRITICAL/HIGH so a vulnerable image never
# gets pushed or deployed. ignore-unfixed keeps the gate real but avoids
# failing on distro CVEs with no available fix (nginx:alpine currently has
# zero fixable CRITICAL/HIGH — the gate passes clean but is genuinely
# enforcing). --scanners vuln keeps it to CVEs (no secret/misconfig noise).
# --- Feature 4: Trivy vulnerability scan (gate) + SBOM ------------------
# Trivy runs from its official container over the runner's docker.sock, so
# there is no fragile binary install and it can scan the locally-built
# image. A shared cache + shared workdir are bind-mounted; the SBOM is
# written to the job workspace so the upload step can find it. A single
# `docker run` per action keeps the runner-in-runner path simple.
- name: Trivy scan (gate CRITICAL,HIGH)
run: |
set -e
trivy image \
--exit-code 1 \
--severity CRITICAL,HIGH \
--ignore-unfixed \
--scanners vuln \
--no-progress \
"${IMAGE}:${GITHUB_SHA}"
# Gate: fail ci on any fixable CRITICAL/HIGH so a vulnerable image never
# gets pushed or deployed. ignore-unfixed keeps the gate real but avoids
# failing on distro CVEs with no available fix (nginx:alpine currently
# has zero fixable CRITICAL/HIGH — the gate passes clean but is
# genuinely enforcing). --scanners vuln keeps it to CVEs.
docker run --rm \
-v /var/run/docker.sock:/var/run/docker.sock \
-v trivy-cache:/root/.cache/ \
aquasec/trivy:0.58.1 image \
--exit-code 1 \
--severity CRITICAL,HIGH \
--ignore-unfixed \
--scanners vuln \
--no-progress \
"${IMAGE}:${GITHUB_SHA}"
echo "trivy gate passed (no fixable CRITICAL/HIGH)"
# --- Feature 4: SBOM (CycloneDX) generation + artifact upload -----------
- name: Generate SBOM (CycloneDX)
if: always()
run: |
set -e
trivy image \
--format cyclonedx \
--scanners vuln \
--no-progress \
--output sbom.cdx.json \
"${IMAGE}:${GITHUB_SHA}"
# Write the SBOM to trivy's stdout and redirect it into the job
# workspace. A bind-mounted --output would land on the HOST path
# (docker.sock is the host daemon, so a sibling container's -v resolves
# host-side, not inside this job container); the stdout redirect writes
# straight into the job filesystem where the upload step can find it.
docker run --rm \
-v /var/run/docker.sock:/var/run/docker.sock \
-v trivy-cache:/root/.cache/ \
aquasec/trivy:0.58.1 image \
--format cyclonedx \
--scanners vuln \
--no-progress \
"${IMAGE}:${GITHUB_SHA}" > sbom.cdx.json
echo "SBOM components: $(python3 -c 'import json; print(len(json.load(open("sbom.cdx.json")).get("components",[])))' 2>/dev/null || echo n/a)"
ls -l sbom.cdx.json