You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
168 lines
6.8 KiB
168 lines
6.8 KiB
pipeline {
|
|
agent any
|
|
|
|
environment {
|
|
REGISTRY = '192.168.1.11:5000'
|
|
IMAGE_NAME = 'cammonitor'
|
|
// Tag with the short git commit SHA; also push 'latest' on the main branch.
|
|
IMAGE_TAG = sh(script: 'git rev-parse --short HEAD', returnStdout: true).trim()
|
|
// TRIVY_SEVERITY controls which finding levels fail the build.
|
|
// Set to 'CRITICAL' to only fail on critical CVEs, or remove the
|
|
// --exit-code flag entirely to make the scan advisory-only.
|
|
TRIVY_SEVERITY = 'HIGH,CRITICAL'
|
|
}
|
|
|
|
options {
|
|
// Keep only the last 10 builds to save disk space on the Atom server.
|
|
buildDiscarder(logRotator(numToKeepStr: '10'))
|
|
timestamps()
|
|
}
|
|
|
|
stages {
|
|
stage('Checkout') {
|
|
steps {
|
|
checkout scm
|
|
}
|
|
}
|
|
|
|
stage('Build') {
|
|
steps {
|
|
// Builds the image defined in Dockerfile using the same flags
|
|
// that docker compose would use, but targets the registry tag directly.
|
|
sh """
|
|
docker build \
|
|
--tag ${REGISTRY}/${IMAGE_NAME}:${IMAGE_TAG} \
|
|
--tag ${REGISTRY}/${IMAGE_NAME}:latest \
|
|
.
|
|
"""
|
|
}
|
|
}
|
|
|
|
stage('Test') {
|
|
// Spin up a throw-away container and hit /health to confirm the binary
|
|
// starts correctly before we push anything.
|
|
steps {
|
|
sh """
|
|
docker run --rm -d \
|
|
--name cammonitor-ci-${BUILD_NUMBER} \
|
|
-p 19080:8080 \
|
|
-e FOOTAGE_ROOT=/tmp \
|
|
-e DB_PATH=/tmp/cammonitor-ci.db \
|
|
${REGISTRY}/${IMAGE_NAME}:${IMAGE_TAG}
|
|
|
|
# Give the process a moment to bind the port, then check health.
|
|
sleep 3
|
|
curl --fail --silent --show-error http://127.0.0.1:19080/health
|
|
"""
|
|
}
|
|
post {
|
|
always {
|
|
sh 'docker stop cammonitor-ci-${BUILD_NUMBER} || true'
|
|
}
|
|
}
|
|
}
|
|
|
|
stage('Scan') {
|
|
// Trivy scans the locally built image for OS and library CVEs before
|
|
// anything is pushed to the registry.
|
|
//
|
|
// Trivy must be installed on the Jenkins agent:
|
|
// https://aquasecurity.github.io/trivy/latest/getting-started/installation/
|
|
// e.g. apt install trivy or brew install trivy
|
|
//
|
|
// The vulnerability DB is cached at ~/.cache/trivy between builds.
|
|
// On air-gapped networks set TRIVY_NO_PROGRESS=true and pre-download
|
|
// the DB: https://aquasecurity.github.io/trivy/latest/docs/advanced/air-gap/
|
|
steps {
|
|
// --exit-code 1 makes the stage (and build) fail when findings at
|
|
// or above TRIVY_SEVERITY are detected. Remove it to make the scan
|
|
// informational only.
|
|
sh """
|
|
trivy image \
|
|
--severity ${TRIVY_SEVERITY} \
|
|
--exit-code 1 \
|
|
--no-progress \
|
|
--ignore-unfixed \
|
|
--format table \
|
|
${REGISTRY}/${IMAGE_NAME}:${IMAGE_TAG}
|
|
"""
|
|
// --ignore-unfixed suppresses findings where Debian maintainers have
|
|
// marked the CVE as will_not_fix or fix_deferred with no fixed version
|
|
// available in the repo (libexpat1, ncurses, perl-base, zlib1g).
|
|
// These cannot be upgraded away — blocking on them produces no action.
|
|
}
|
|
post {
|
|
always {
|
|
// Also emit a machine-readable SARIF report so results can be
|
|
// ingested by Jenkins Warnings NG or uploaded to GitHub Advanced
|
|
// Security if you ever connect this repo there.
|
|
sh """
|
|
trivy image \
|
|
--severity ${TRIVY_SEVERITY} \
|
|
--exit-code 0 \
|
|
--no-progress \
|
|
--ignore-unfixed \
|
|
--format sarif \
|
|
--output trivy-report.sarif \
|
|
${REGISTRY}/${IMAGE_NAME}:${IMAGE_TAG}
|
|
"""
|
|
archiveArtifacts artifacts: 'trivy-report.sarif', allowEmptyArchive: true
|
|
}
|
|
}
|
|
}
|
|
|
|
stage('Push') {
|
|
// NOTE: 192.168.1.11:5000 is an HTTP registry (no TLS).
|
|
// The Docker daemon on the Jenkins agent must have it listed under
|
|
// "insecure-registries" in /etc/docker/daemon.json:
|
|
//
|
|
// { "insecure-registries": ["192.168.1.11:5000"] }
|
|
//
|
|
// If the registry requires credentials, replace the plain push below
|
|
// with the block commented out underneath it, and add a 'registry-creds'
|
|
// username/password credential in Jenkins > Manage Credentials.
|
|
steps {
|
|
sh "docker push ${REGISTRY}/${IMAGE_NAME}:${IMAGE_TAG}"
|
|
|
|
// Only move the 'latest' pointer when building the main branch.
|
|
script {
|
|
if (env.BRANCH_NAME == 'main') {
|
|
sh "docker push ${REGISTRY}/${IMAGE_NAME}:latest"
|
|
}
|
|
}
|
|
|
|
/* --- With registry credentials (uncomment if needed) ---
|
|
withCredentials([usernamePassword(
|
|
credentialsId: 'registry-creds',
|
|
usernameVariable: 'REG_USER',
|
|
passwordVariable: 'REG_PASS'
|
|
)]) {
|
|
sh """
|
|
docker login ${REGISTRY} -u \$REG_USER -p \$REG_PASS
|
|
docker push ${REGISTRY}/${IMAGE_NAME}:${IMAGE_TAG}
|
|
docker push ${REGISTRY}/${IMAGE_NAME}:latest
|
|
docker logout ${REGISTRY}
|
|
"""
|
|
}
|
|
-------------------------------------------------------- */
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
post {
|
|
always {
|
|
// Remove local copies so the build agent does not fill up.
|
|
sh """
|
|
docker rmi ${REGISTRY}/${IMAGE_NAME}:${IMAGE_TAG} || true
|
|
docker rmi ${REGISTRY}/${IMAGE_NAME}:latest || true
|
|
"""
|
|
}
|
|
success {
|
|
echo "Deployed: ${REGISTRY}/${IMAGE_NAME}:${IMAGE_TAG}"
|
|
}
|
|
failure {
|
|
echo "Build failed — image was NOT pushed or deployed."
|
|
}
|
|
}
|
|
}
|
|
|