Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
5f708237a7 | ||
|
|
d9735fb3ce | ||
|
|
cb26668ae7 | ||
|
|
f9070fdad0 | ||
|
|
9bc3bcefbd | ||
|
|
8466d2daa3 | ||
|
|
becc94fa1d | ||
|
|
8dcdfc1f43 | ||
|
|
1f829edc81 | ||
|
|
94e3ded47d |
No files matched your search
@@ -0,0 +1,24 @@
|
||||
description: >
|
||||
Build, scan, and push supplemental Docker images alongside the main application image.
|
||||
Each supplemental image shares the same version tag. Requires docker_push_ghcr to have
|
||||
run first (for registry auth and Trivy installation).
|
||||
parameters:
|
||||
supplemental_images:
|
||||
type: string
|
||||
default: "[]"
|
||||
description: JSON array of supplemental image definitions.
|
||||
image_name:
|
||||
type: string
|
||||
description: Docker image name (without registry prefix).
|
||||
registry:
|
||||
type: string
|
||||
default: ghcr.io/KofTwentyTwo
|
||||
description: Container registry URL.
|
||||
steps:
|
||||
- run:
|
||||
name: Build and push supplemental images
|
||||
environment:
|
||||
SUPPLEMENTAL_IMAGES_JSON: << parameters.supplemental_images >>
|
||||
IMAGE_NAME: << parameters.image_name >>
|
||||
REGISTRY: << parameters.registry >>
|
||||
command: << include(scripts/build_push_supplemental.sh) >>
|
||||
@@ -15,6 +15,14 @@ parameters:
|
||||
type: string
|
||||
default: "false"
|
||||
description: Start a PostgreSQL sidecar for apps that require a database to boot.
|
||||
health_migrations:
|
||||
type: string
|
||||
default: ""
|
||||
description: Name of supplemental image to run as migrations before the app (e.g. "migrations").
|
||||
health_smoke_paths:
|
||||
type: string
|
||||
default: ""
|
||||
description: Comma-separated API paths to smoke test after health check passes (e.g. "/api/v1/site/query").
|
||||
steps:
|
||||
- run:
|
||||
name: Health check
|
||||
@@ -22,4 +30,6 @@ steps:
|
||||
HEALTH_PATH: << parameters.health_path >>
|
||||
HEALTH_PORT: << parameters.health_port >>
|
||||
HEALTH_DB: << parameters.health_db >>
|
||||
HEALTH_MIGRATIONS: << parameters.health_migrations >>
|
||||
HEALTH_SMOKE_PATHS: << parameters.health_smoke_paths >>
|
||||
command: << include(scripts/health_check.sh) >>
|
||||
@@ -4,7 +4,7 @@ description: >
|
||||
steps:
|
||||
- run:
|
||||
name: Write Trivy version file
|
||||
command: echo "${TRIVY_VERSION:-0.58.2}" > .trivy-version
|
||||
command: echo "${TRIVY_VERSION:-0.69.3}" > .trivy-version
|
||||
- restore_cache:
|
||||
keys:
|
||||
- trivy-bin-v1-{{ checksum ".trivy-version" }}
|
||||
|
||||
@@ -6,7 +6,7 @@ parameters:
|
||||
description: Full image tag to scan (registry/name:tag).
|
||||
trivy_version:
|
||||
type: string
|
||||
default: "0.58.2"
|
||||
default: "0.69.3"
|
||||
description: Trivy version to install.
|
||||
steps:
|
||||
- run:
|
||||
|
||||
@@ -3,7 +3,7 @@ description: >
|
||||
steps:
|
||||
- run:
|
||||
name: Write Trivy version file
|
||||
command: echo "${TRIVY_VERSION:-0.58.2}" > .trivy-version
|
||||
command: echo "${TRIVY_VERSION:-0.69.3}" > .trivy-version
|
||||
- save_cache:
|
||||
key: trivy-bin-v1-{{ checksum ".trivy-version" }}
|
||||
paths:
|
||||
|
||||
@@ -38,6 +38,12 @@ parameters:
|
||||
type: string
|
||||
default: ""
|
||||
description: Git author name for CD repo commits.
|
||||
supplemental_images:
|
||||
type: string
|
||||
default: "[]"
|
||||
description: >
|
||||
JSON array of supplemental images. Each entry may contain cd.image_key (Helm)
|
||||
or cd.image_name (Kustomize) for updating the CD repo with supplemental image tags.
|
||||
steps:
|
||||
- run:
|
||||
name: Update CD repo
|
||||
@@ -50,4 +56,5 @@ steps:
|
||||
CD_IMAGE_NAME: << parameters.cd_image_name >>
|
||||
CI_GIT_EMAIL: << parameters.ci_git_email >>
|
||||
CI_GIT_NAME: << parameters.ci_git_name >>
|
||||
SUPPLEMENTAL_IMAGES_JSON: << parameters.supplemental_images >>
|
||||
command: << include(scripts/update_cd_repo.sh) >>
|
||||
@@ -20,6 +20,14 @@ parameters:
|
||||
type: string
|
||||
default: "false"
|
||||
description: Start a PostgreSQL sidecar for apps that require a database to boot.
|
||||
health_migrations:
|
||||
type: string
|
||||
default: ""
|
||||
description: Name of supplemental image to run as migrations before the app (e.g. "migrations").
|
||||
health_smoke_paths:
|
||||
type: string
|
||||
default: ""
|
||||
description: Comma-separated API paths to smoke test after health check passes.
|
||||
resource_class:
|
||||
type: enum
|
||||
enum:
|
||||
@@ -31,6 +39,10 @@ parameters:
|
||||
type: boolean
|
||||
default: true
|
||||
description: Enable Docker Layer Caching for faster builds.
|
||||
supplemental_images:
|
||||
type: string
|
||||
default: "[]"
|
||||
description: JSON array of supplemental images to build, scan, and push alongside the main image.
|
||||
executor:
|
||||
name: machine
|
||||
resource_class: << parameters.resource_class >>
|
||||
@@ -49,8 +61,14 @@ steps:
|
||||
health_path: << parameters.health_path >>
|
||||
health_port: << parameters.health_port >>
|
||||
health_db: << parameters.health_db >>
|
||||
health_migrations: << parameters.health_migrations >>
|
||||
health_smoke_paths: << parameters.health_smoke_paths >>
|
||||
- restore_trivy_cache
|
||||
- run_trivy_image:
|
||||
image_tag: << parameters.registry >>/<< parameters.image_name >>:${DOCKER_TAG}
|
||||
- save_trivy_cache
|
||||
- docker_push_ghcr
|
||||
- build_push_supplemental:
|
||||
supplemental_images: << parameters.supplemental_images >>
|
||||
image_name: << parameters.image_name >>
|
||||
registry: << parameters.registry >>
|
||||
@@ -32,6 +32,12 @@ parameters:
|
||||
type: string
|
||||
default: ""
|
||||
description: Git author name for CD repo commits.
|
||||
supplemental_images:
|
||||
type: string
|
||||
default: "[]"
|
||||
description: >
|
||||
JSON array of supplemental images. Each entry may contain cd.image_key (Helm)
|
||||
or cd.image_name (Kustomize) for updating the CD repo with supplemental image tags.
|
||||
executor: base
|
||||
steps:
|
||||
- attach_workspace:
|
||||
@@ -48,3 +54,4 @@ steps:
|
||||
cd_image_name: << parameters.cd_image_name >>
|
||||
ci_git_email: << parameters.ci_git_email >>
|
||||
ci_git_name: << parameters.ci_git_name >>
|
||||
supplemental_images: << parameters.supplemental_images >>
|
||||
@@ -0,0 +1,97 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
# Source shared helpers
|
||||
MUNITOR_HELPERS="${MUNITOR_HELPERS:-$(cd "$(dirname "${BASH_SOURCE[0]:-$0}")" && pwd)/munitor_helpers.sh}"
|
||||
# shellcheck source=munitor_helpers.sh
|
||||
if [[ -f "${MUNITOR_HELPERS}" ]]; then source "${MUNITOR_HELPERS}"
|
||||
elif ! type munitor_header &>/dev/null; then
|
||||
munitor_header() { echo "=== Munitor: ${1:-unknown} ==="; }
|
||||
munitor_check_tool() { command -v "$1" &>/dev/null || { echo "ERROR: $1 not found"; exit 1; }; }
|
||||
munitor_download_with_retry() { curl -fsSL --retry 3 "$1" -o "$2"; }
|
||||
fi
|
||||
|
||||
munitor_header "build_push_supplemental"
|
||||
munitor_check_tool jq --version
|
||||
munitor_check_tool docker --version
|
||||
|
||||
IMAGES_JSON="${SUPPLEMENTAL_IMAGES_JSON:-[]}"
|
||||
|
||||
# Skip if no supplemental images defined
|
||||
if [[ "${IMAGES_JSON}" == "[]" || "${IMAGES_JSON}" == "null" || -z "${IMAGES_JSON}" ]]; then
|
||||
echo "No supplemental images defined, skipping."
|
||||
exit 0
|
||||
fi
|
||||
|
||||
IMAGE="${IMAGE_NAME:?IMAGE_NAME not set}"
|
||||
REGISTRY="${REGISTRY:-ghcr.io/KofTwentyTwo}"
|
||||
VERSION="${PROJECT_VERSION:?PROJECT_VERSION not set -- run export_version_vars first}"
|
||||
ENV_TAG="${DOCKER_ENV_TAG:-}"
|
||||
|
||||
COUNT=$(echo "${IMAGES_JSON}" | jq 'length')
|
||||
echo "Found ${COUNT} supplemental image(s) to build."
|
||||
|
||||
for i in $(seq 0 $((COUNT - 1))); do
|
||||
ENTRY=$(echo "${IMAGES_JSON}" | jq -c ".[$i]")
|
||||
|
||||
NAME=$(echo "${ENTRY}" | jq -r '.name')
|
||||
BASE=$(echo "${ENTRY}" | jq -r '.base // empty')
|
||||
DOCKERFILE=$(echo "${ENTRY}" | jq -r '.dockerfile // empty')
|
||||
|
||||
DERIVED_NAME="${IMAGE}-${NAME}"
|
||||
FULL_TAG="${REGISTRY}/${DERIVED_NAME}:${VERSION}"
|
||||
|
||||
echo ""
|
||||
echo "--- Supplemental image: ${DERIVED_NAME} ---"
|
||||
|
||||
if [[ -n "${DOCKERFILE}" ]]; then
|
||||
echo "Using provided Dockerfile: ${DOCKERFILE}"
|
||||
elif [[ -n "${BASE}" ]]; then
|
||||
# Auto-generate Dockerfile
|
||||
DOCKERFILE="Dockerfile.${NAME}"
|
||||
echo "Auto-generating ${DOCKERFILE} from base: ${BASE}"
|
||||
|
||||
{
|
||||
echo "FROM ${BASE}"
|
||||
COPY_COUNT=$(echo "${ENTRY}" | jq '.copy // [] | length')
|
||||
for j in $(seq 0 $((COPY_COUNT - 1))); do
|
||||
SRC=$(echo "${ENTRY}" | jq -r ".copy[$j].src")
|
||||
DEST=$(echo "${ENTRY}" | jq -r ".copy[$j].dest")
|
||||
echo "COPY ${SRC} ${DEST}"
|
||||
done
|
||||
} > "${DOCKERFILE}"
|
||||
|
||||
echo "Generated ${DOCKERFILE}:"
|
||||
cat "${DOCKERFILE}"
|
||||
else
|
||||
echo "ERROR: Supplemental image '${NAME}' must specify either 'dockerfile' or 'base'."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Build
|
||||
echo "Building ${FULL_TAG} ..."
|
||||
docker build -f "${DOCKERFILE}" -t "${FULL_TAG}" .
|
||||
|
||||
if [[ -n "${ENV_TAG}" ]]; then
|
||||
ENV_FULL_TAG="${REGISTRY}/${DERIVED_NAME}:${ENV_TAG}"
|
||||
docker tag "${FULL_TAG}" "${ENV_FULL_TAG}"
|
||||
fi
|
||||
|
||||
# Trivy scan
|
||||
echo "Scanning ${FULL_TAG} with Trivy ..."
|
||||
trivy image --severity HIGH,CRITICAL --exit-code 1 "${FULL_TAG}"
|
||||
|
||||
# Push
|
||||
echo "Pushing ${FULL_TAG} ..."
|
||||
docker push "${FULL_TAG}"
|
||||
|
||||
if [[ -n "${ENV_TAG}" ]]; then
|
||||
echo "Pushing ${ENV_FULL_TAG} ..."
|
||||
docker push "${ENV_FULL_TAG}"
|
||||
fi
|
||||
|
||||
echo "--- Done: ${DERIVED_NAME} ---"
|
||||
done
|
||||
|
||||
echo ""
|
||||
echo "All supplemental images built, scanned, and pushed."
|
||||
@@ -27,7 +27,7 @@ BUILD_CMD=(docker build -f "${DOCKERFILE}" -t "${FULL_IMAGE}:${VERSION}")
|
||||
if [[ -n "${ENV_TAG}" ]]; then
|
||||
BUILD_CMD+=(-t "${FULL_IMAGE}:${ENV_TAG}")
|
||||
fi
|
||||
BUILD_CMD+=(--build-arg "VERSION=${VERSION}" .)
|
||||
BUILD_CMD+=(--build-arg "VERSION=${VERSION}" --build-arg "GIT_COMMIT_SHA=${CIRCLE_SHA1:-}" .)
|
||||
|
||||
"${BUILD_CMD[@]}"
|
||||
|
||||
|
||||
@@ -164,6 +164,19 @@ extract_munitor_vars() {
|
||||
esac
|
||||
fi
|
||||
MUNITOR_HEALTH_DB=$(yq '.health.db // false' "${config_file}")
|
||||
MUNITOR_HEALTH_MIGRATIONS=$(yq '.health.migrations // ""' "${config_file}")
|
||||
if [[ "${MUNITOR_HEALTH_MIGRATIONS}" == "null" ]]; then MUNITOR_HEALTH_MIGRATIONS=""; fi
|
||||
MUNITOR_HEALTH_SMOKE_PATHS=$(yq '.health.smoke_paths // [] | join(",")' "${config_file}")
|
||||
if [[ "${MUNITOR_HEALTH_SMOKE_PATHS}" == "null" ]]; then MUNITOR_HEALTH_SMOKE_PATHS=""; fi
|
||||
|
||||
# Supplemental images (e.g., migrations, db-backup)
|
||||
MUNITOR_SUPPLEMENTAL_IMAGES_JSON=$(yq -o=json -I=0 '.supplemental_images // []' "${config_file}")
|
||||
if [[ "${MUNITOR_SUPPLEMENTAL_IMAGES_JSON}" == "[]" || "${MUNITOR_SUPPLEMENTAL_IMAGES_JSON}" == "null" ]]; then
|
||||
MUNITOR_SUPPLEMENTAL="false"
|
||||
MUNITOR_SUPPLEMENTAL_IMAGES_JSON="[]"
|
||||
else
|
||||
MUNITOR_SUPPLEMENTAL="true"
|
||||
fi
|
||||
|
||||
# Derived flags
|
||||
if [[ -n "${MUNITOR_SONAR_PROJECT_KEY}" ]]; then
|
||||
@@ -202,12 +215,13 @@ extract_munitor_vars() {
|
||||
export MUNITOR_KUBE_LINTER_CONFIG MUNITOR_YAMLLINT_PATHS
|
||||
export MUNITOR_NODE_FRAMEWORK MUNITOR_PACKAGE_MANAGER
|
||||
export MUNITOR_CI_EMAIL MUNITOR_CI_NAME MUNITOR_NPM_DEFAULT_SCOPE MUNITOR_ORB_SLUG
|
||||
export MUNITOR_HEALTH_PATH MUNITOR_HEALTH_PORT MUNITOR_HEALTH_DB
|
||||
export MUNITOR_HEALTH_PATH MUNITOR_HEALTH_PORT MUNITOR_HEALTH_DB MUNITOR_HEALTH_MIGRATIONS MUNITOR_HEALTH_SMOKE_PATHS
|
||||
export MUNITOR_SUPPLEMENTAL MUNITOR_SUPPLEMENTAL_IMAGES_JSON
|
||||
export MUNITOR_SONAR MUNITOR_CD MUNITOR_NVD
|
||||
}
|
||||
|
||||
# Build the envsubst variable list
|
||||
get_envsubst_vars() {
|
||||
# shellcheck disable=SC2016
|
||||
echo '${MUNITOR_PIPELINE} ${MUNITOR_ORB_VERSION} ${MUNITOR_IMAGE_NAME} ${MUNITOR_JAVA_VERSION} ${MUNITOR_NODE_VERSION} ${MUNITOR_SONAR_PROJECT_KEY} ${MUNITOR_DOCKER_REGISTRY} ${MUNITOR_CD_REPO} ${MUNITOR_CD_FORMAT} ${MUNITOR_CD_ENV_DEVELOP} ${MUNITOR_CD_ENV_STAGING} ${MUNITOR_CD_ENV_PROD} ${MUNITOR_CD_ENV_RELEASE} ${MUNITOR_COVERAGE_MIN} ${MUNITOR_E2E} ${MUNITOR_SBOM} ${MUNITOR_OWASP} ${MUNITOR_CONTEXT_REGISTRY} ${MUNITOR_CONTEXT_GITHUB} ${MUNITOR_CONTEXT_SONAR} ${MUNITOR_CONTEXT_NVD} ${MUNITOR_NPM_AUTH} ${MUNITOR_NPM_SCOPES} ${MUNITOR_SERVICES_JSON} ${MUNITOR_TEST_SETUP_SCRIPT} ${MUNITOR_TEST_COMMANDS_JSON} ${MUNITOR_COVERAGE_TOOL} ${MUNITOR_COVERAGE_COMMAND} ${MUNITOR_GITHUB_RELEASE} ${MUNITOR_SAST} ${MUNITOR_SAST_FAIL_ON_FINDINGS} ${MUNITOR_HEALTH_PATH} ${MUNITOR_HEALTH_PORT} ${MUNITOR_HEALTH_DB} ${MUNITOR_TF_PATH} ${MUNITOR_TF_LIVE_PATH} ${MUNITOR_TF_ENVIRONMENTS} ${MUNITOR_CHECKOV_SKIP} ${MUNITOR_KUSTOMIZE_VERSION} ${MUNITOR_KUSTOMIZE_BASE_PATH} ${MUNITOR_KUSTOMIZE_LOAD_RESTRICTOR} ${MUNITOR_KUSTOMIZE_SCAN_OVERLAY} ${MUNITOR_KUSTOMIZE_OVERLAYS} ${MUNITOR_KUSTOMIZE_OVERLAY_DIR} ${MUNITOR_KUBE_LINTER_CONFIG} ${MUNITOR_YAMLLINT_PATHS} ${MUNITOR_CI_EMAIL} ${MUNITOR_CI_NAME} ${MUNITOR_NPM_DEFAULT_SCOPE} ${MUNITOR_ORB_SLUG} ${MUNITOR_PACKAGE_MANAGER}'
|
||||
echo '${MUNITOR_PIPELINE} ${MUNITOR_ORB_VERSION} ${MUNITOR_IMAGE_NAME} ${MUNITOR_JAVA_VERSION} ${MUNITOR_NODE_VERSION} ${MUNITOR_SONAR_PROJECT_KEY} ${MUNITOR_DOCKER_REGISTRY} ${MUNITOR_CD_REPO} ${MUNITOR_CD_FORMAT} ${MUNITOR_CD_ENV_DEVELOP} ${MUNITOR_CD_ENV_STAGING} ${MUNITOR_CD_ENV_PROD} ${MUNITOR_CD_ENV_RELEASE} ${MUNITOR_COVERAGE_MIN} ${MUNITOR_E2E} ${MUNITOR_SBOM} ${MUNITOR_OWASP} ${MUNITOR_CONTEXT_REGISTRY} ${MUNITOR_CONTEXT_GITHUB} ${MUNITOR_CONTEXT_SONAR} ${MUNITOR_CONTEXT_NVD} ${MUNITOR_NPM_AUTH} ${MUNITOR_NPM_SCOPES} ${MUNITOR_SERVICES_JSON} ${MUNITOR_TEST_SETUP_SCRIPT} ${MUNITOR_TEST_COMMANDS_JSON} ${MUNITOR_COVERAGE_TOOL} ${MUNITOR_COVERAGE_COMMAND} ${MUNITOR_GITHUB_RELEASE} ${MUNITOR_SAST} ${MUNITOR_SAST_FAIL_ON_FINDINGS} ${MUNITOR_HEALTH_PATH} ${MUNITOR_HEALTH_PORT} ${MUNITOR_HEALTH_DB} ${MUNITOR_HEALTH_MIGRATIONS} ${MUNITOR_HEALTH_SMOKE_PATHS} ${MUNITOR_TF_PATH} ${MUNITOR_TF_LIVE_PATH} ${MUNITOR_TF_ENVIRONMENTS} ${MUNITOR_CHECKOV_SKIP} ${MUNITOR_KUSTOMIZE_VERSION} ${MUNITOR_KUSTOMIZE_BASE_PATH} ${MUNITOR_KUSTOMIZE_LOAD_RESTRICTOR} ${MUNITOR_KUSTOMIZE_SCAN_OVERLAY} ${MUNITOR_KUSTOMIZE_OVERLAYS} ${MUNITOR_KUSTOMIZE_OVERLAY_DIR} ${MUNITOR_KUBE_LINTER_CONFIG} ${MUNITOR_YAMLLINT_PATHS} ${MUNITOR_CI_EMAIL} ${MUNITOR_CI_NAME} ${MUNITOR_NPM_DEFAULT_SCOPE} ${MUNITOR_ORB_SLUG} ${MUNITOR_PACKAGE_MANAGER} ${MUNITOR_SUPPLEMENTAL_IMAGES_JSON}'
|
||||
}
|
||||
@@ -94,7 +94,7 @@ validate_required_fields "${PIPELINE_TYPE}" "${CONFIG_FILE}"
|
||||
# --------------------------------------------------------------------------
|
||||
# Warn about unknown top-level keys (catches typos like java_verion)
|
||||
# --------------------------------------------------------------------------
|
||||
KNOWN_KEYS="pipeline orb_version image_name java_version node_version sonar docker cd coverage e2e sbom owasp contexts npm node services test terraform sast health kustomize kube_linter_config package_manager yamllint_paths"
|
||||
KNOWN_KEYS="pipeline orb_version image_name java_version node_version sonar docker cd coverage e2e sbom owasp contexts npm node services test terraform sast health kustomize kube_linter_config package_manager yamllint_paths supplemental_images"
|
||||
ACTUAL_KEYS=$(yq 'keys | .[]' "${CONFIG_FILE}" 2>/dev/null || true)
|
||||
for key in ${ACTUAL_KEYS}; do
|
||||
if ! echo "${KNOWN_KEYS}" | grep -qw "${key}"; then
|
||||
@@ -198,7 +198,7 @@ process_conditionals() {
|
||||
cp "${input}" "${tmpfile}"
|
||||
|
||||
# Process each conditional flag
|
||||
for flag in E2E SBOM SONAR NPM_AUTH SERVICES TEST_SETUP CUSTOM_TEST COVERAGE_CMD GITHUB_RELEASE SAST CD OWASP NVD; do
|
||||
for flag in E2E SBOM SONAR NPM_AUTH SERVICES TEST_SETUP CUSTOM_TEST COVERAGE_CMD GITHUB_RELEASE SAST CD OWASP NVD SUPPLEMENTAL; do
|
||||
local var_name="MUNITOR_${flag}"
|
||||
local value="${!var_name:-false}"
|
||||
local flag_file
|
||||
|
||||
@@ -53,6 +53,8 @@ WORKDIR /app
|
||||
COPY --from=deps /app/node_modules ./node_modules
|
||||
COPY . .
|
||||
ENV STANDALONE=true
|
||||
ARG GIT_COMMIT_SHA
|
||||
ENV GIT_COMMIT_SHA=\${GIT_COMMIT_SHA}
|
||||
RUN npm run build
|
||||
|
||||
FROM node:${MUNITOR_NODE_VERSION}-alpine AS runner
|
||||
@@ -154,6 +156,8 @@ WORKDIR /app
|
||||
COPY package*.json ./
|
||||
RUN npm ci
|
||||
COPY . .
|
||||
ARG GIT_COMMIT_SHA
|
||||
ENV GIT_COMMIT_SHA=\${GIT_COMMIT_SHA}
|
||||
RUN npm run build
|
||||
|
||||
FROM gcr.io/distroless/nodejs${MUNITOR_NODE_VERSION}-debian12 AS runner
|
||||
|
||||
@@ -14,6 +14,8 @@ fi
|
||||
HEALTH_PATH="${HEALTH_PATH:-/api/health}"
|
||||
HEALTH_PORT="${HEALTH_PORT:-3000}"
|
||||
HEALTH_DB="${HEALTH_DB:-false}"
|
||||
HEALTH_MIGRATIONS="${HEALTH_MIGRATIONS:-}"
|
||||
HEALTH_SMOKE_PATHS="${HEALTH_SMOKE_PATHS:-}"
|
||||
|
||||
# DOCKER_IMAGE and DOCKER_TAG are exported to BASH_ENV by docker_build.sh
|
||||
IMAGE="${DOCKER_IMAGE:?DOCKER_IMAGE not set -- run docker_build first}"
|
||||
@@ -64,6 +66,23 @@ if [[ "${HEALTH_DB}" == "true" ]]; then
|
||||
sleep 1
|
||||
done
|
||||
|
||||
# Run migrations if a migrations image is specified
|
||||
if [[ -n "${HEALTH_MIGRATIONS}" ]]; then
|
||||
MIGRATIONS_IMAGE="${DOCKER_IMAGE}-${HEALTH_MIGRATIONS}:${TAG}"
|
||||
echo "Running migrations image: ${MIGRATIONS_IMAGE}"
|
||||
docker run --rm \
|
||||
--name "munitor-health-migrations-$$" \
|
||||
--network "${NETWORK_NAME}" \
|
||||
-e RDBMS_HOSTNAME="${DB_CONTAINER_NAME}" \
|
||||
-e RDBMS_PORT=5432 \
|
||||
-e RDBMS_DATABASE_NAME=postgres \
|
||||
-e RDBMS_USERNAME=postgres \
|
||||
-e RDBMS_PASSWORD=postgres \
|
||||
-e LB_CONTEXTS=dev \
|
||||
"${MIGRATIONS_IMAGE}"
|
||||
echo "Migrations completed."
|
||||
fi
|
||||
|
||||
# Start app container on the same network with DB env vars
|
||||
docker run -d \
|
||||
--name "${CONTAINER_NAME}" \
|
||||
@@ -129,3 +148,40 @@ if [[ "${HEALTHY}" != "true" ]]; then
|
||||
echo "--- End container logs ---"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# --- API smoke tests ---
|
||||
if [[ -n "${HEALTH_SMOKE_PATHS}" ]]; then
|
||||
echo ""
|
||||
echo "Running API smoke tests..."
|
||||
SMOKE_FAILED=false
|
||||
|
||||
IFS=',' read -ra SMOKE_ENDPOINTS <<< "${HEALTH_SMOKE_PATHS}"
|
||||
for endpoint in "${SMOKE_ENDPOINTS[@]}"; do
|
||||
endpoint=$(echo "${endpoint}" | xargs) # trim whitespace
|
||||
SMOKE_URL="http://localhost:${HEALTH_PORT}${endpoint}"
|
||||
echo " Smoke test: GET ${endpoint}"
|
||||
|
||||
SMOKE_CODE=$(curl -s -o /tmp/smoke_response.txt -w "%{http_code}" "${SMOKE_URL}" 2>/dev/null || echo "000")
|
||||
|
||||
if [[ "${SMOKE_CODE}" == "200" ]]; then
|
||||
echo " PASSED (HTTP ${SMOKE_CODE})"
|
||||
else
|
||||
BODY=$(cat /tmp/smoke_response.txt 2>/dev/null || echo "")
|
||||
echo " FAILED (HTTP ${SMOKE_CODE})"
|
||||
echo " Response: ${BODY:0:500}"
|
||||
SMOKE_FAILED=true
|
||||
fi
|
||||
done
|
||||
|
||||
if [[ "${SMOKE_FAILED}" == "true" ]]; then
|
||||
echo ""
|
||||
echo "ERROR: API smoke tests FAILED"
|
||||
echo ""
|
||||
echo "--- Container logs (last 50 lines) ---"
|
||||
docker logs --tail 50 "${CONTAINER_NAME}" 2>&1 || true
|
||||
echo "--- End container logs ---"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "All smoke tests PASSED."
|
||||
fi
|
||||
@@ -12,7 +12,7 @@ elif ! type munitor_header &>/dev/null; then
|
||||
fi
|
||||
|
||||
# tfsec is deprecated/archived -- use trivy config instead
|
||||
TRIVY_VERSION="${TRIVY_VERSION:-0.58.2}"
|
||||
TRIVY_VERSION="${TRIVY_VERSION:-0.69.3}"
|
||||
INSTALL_DIR="${HOME}/bin"
|
||||
export PATH="${INSTALL_DIR}:${PATH}"
|
||||
|
||||
|
||||
@@ -262,6 +262,15 @@ extract_munitor_vars() {
|
||||
fi
|
||||
MUNITOR_HEALTH_DB=$(yq '.health.db // false' "${config_file}")
|
||||
|
||||
# Supplemental images (e.g., migrations, db-backup)
|
||||
MUNITOR_SUPPLEMENTAL_IMAGES_JSON=$(yq '.supplemental_images // [] | tojson' "${config_file}")
|
||||
if [[ "${MUNITOR_SUPPLEMENTAL_IMAGES_JSON}" == "[]" || "${MUNITOR_SUPPLEMENTAL_IMAGES_JSON}" == "null" ]]; then
|
||||
MUNITOR_SUPPLEMENTAL="false"
|
||||
MUNITOR_SUPPLEMENTAL_IMAGES_JSON="[]"
|
||||
else
|
||||
MUNITOR_SUPPLEMENTAL="true"
|
||||
fi
|
||||
|
||||
# Derived flags
|
||||
if [[ -n "${MUNITOR_SONAR_PROJECT_KEY}" ]]; then
|
||||
MUNITOR_SONAR="true"
|
||||
@@ -300,13 +309,14 @@ extract_munitor_vars() {
|
||||
export MUNITOR_NODE_FRAMEWORK MUNITOR_PACKAGE_MANAGER
|
||||
export MUNITOR_CI_EMAIL MUNITOR_CI_NAME MUNITOR_NPM_DEFAULT_SCOPE MUNITOR_ORB_SLUG
|
||||
export MUNITOR_HEALTH_PATH MUNITOR_HEALTH_PORT MUNITOR_HEALTH_DB
|
||||
export MUNITOR_SUPPLEMENTAL MUNITOR_SUPPLEMENTAL_IMAGES_JSON
|
||||
export MUNITOR_SONAR MUNITOR_CD MUNITOR_NVD
|
||||
}
|
||||
|
||||
# Build the envsubst variable list
|
||||
get_envsubst_vars() {
|
||||
# shellcheck disable=SC2016
|
||||
echo '${MUNITOR_PIPELINE} ${MUNITOR_ORB_VERSION} ${MUNITOR_IMAGE_NAME} ${MUNITOR_JAVA_VERSION} ${MUNITOR_NODE_VERSION} ${MUNITOR_SONAR_PROJECT_KEY} ${MUNITOR_DOCKER_REGISTRY} ${MUNITOR_CD_REPO} ${MUNITOR_CD_FORMAT} ${MUNITOR_CD_ENV_DEVELOP} ${MUNITOR_CD_ENV_STAGING} ${MUNITOR_CD_ENV_PROD} ${MUNITOR_CD_ENV_RELEASE} ${MUNITOR_COVERAGE_MIN} ${MUNITOR_E2E} ${MUNITOR_SBOM} ${MUNITOR_OWASP} ${MUNITOR_CONTEXT_REGISTRY} ${MUNITOR_CONTEXT_GITHUB} ${MUNITOR_CONTEXT_SONAR} ${MUNITOR_CONTEXT_NVD} ${MUNITOR_NPM_AUTH} ${MUNITOR_NPM_SCOPES} ${MUNITOR_SERVICES_JSON} ${MUNITOR_TEST_SETUP_SCRIPT} ${MUNITOR_TEST_COMMANDS_JSON} ${MUNITOR_COVERAGE_TOOL} ${MUNITOR_COVERAGE_COMMAND} ${MUNITOR_GITHUB_RELEASE} ${MUNITOR_SAST} ${MUNITOR_SAST_FAIL_ON_FINDINGS} ${MUNITOR_HEALTH_PATH} ${MUNITOR_HEALTH_PORT} ${MUNITOR_HEALTH_DB} ${MUNITOR_TF_PATH} ${MUNITOR_TF_LIVE_PATH} ${MUNITOR_TF_ENVIRONMENTS} ${MUNITOR_CHECKOV_SKIP} ${MUNITOR_KUSTOMIZE_VERSION} ${MUNITOR_KUSTOMIZE_BASE_PATH} ${MUNITOR_KUSTOMIZE_LOAD_RESTRICTOR} ${MUNITOR_KUSTOMIZE_SCAN_OVERLAY} ${MUNITOR_KUSTOMIZE_OVERLAYS} ${MUNITOR_KUSTOMIZE_OVERLAY_DIR} ${MUNITOR_KUBE_LINTER_CONFIG} ${MUNITOR_YAMLLINT_PATHS} ${MUNITOR_CI_EMAIL} ${MUNITOR_CI_NAME} ${MUNITOR_NPM_DEFAULT_SCOPE} ${MUNITOR_ORB_SLUG} ${MUNITOR_PACKAGE_MANAGER}'
|
||||
echo '${MUNITOR_PIPELINE} ${MUNITOR_ORB_VERSION} ${MUNITOR_IMAGE_NAME} ${MUNITOR_JAVA_VERSION} ${MUNITOR_NODE_VERSION} ${MUNITOR_SONAR_PROJECT_KEY} ${MUNITOR_DOCKER_REGISTRY} ${MUNITOR_CD_REPO} ${MUNITOR_CD_FORMAT} ${MUNITOR_CD_ENV_DEVELOP} ${MUNITOR_CD_ENV_STAGING} ${MUNITOR_CD_ENV_PROD} ${MUNITOR_CD_ENV_RELEASE} ${MUNITOR_COVERAGE_MIN} ${MUNITOR_E2E} ${MUNITOR_SBOM} ${MUNITOR_OWASP} ${MUNITOR_CONTEXT_REGISTRY} ${MUNITOR_CONTEXT_GITHUB} ${MUNITOR_CONTEXT_SONAR} ${MUNITOR_CONTEXT_NVD} ${MUNITOR_NPM_AUTH} ${MUNITOR_NPM_SCOPES} ${MUNITOR_SERVICES_JSON} ${MUNITOR_TEST_SETUP_SCRIPT} ${MUNITOR_TEST_COMMANDS_JSON} ${MUNITOR_COVERAGE_TOOL} ${MUNITOR_COVERAGE_COMMAND} ${MUNITOR_GITHUB_RELEASE} ${MUNITOR_SAST} ${MUNITOR_SAST_FAIL_ON_FINDINGS} ${MUNITOR_HEALTH_PATH} ${MUNITOR_HEALTH_PORT} ${MUNITOR_HEALTH_DB} ${MUNITOR_TF_PATH} ${MUNITOR_TF_LIVE_PATH} ${MUNITOR_TF_ENVIRONMENTS} ${MUNITOR_CHECKOV_SKIP} ${MUNITOR_KUSTOMIZE_VERSION} ${MUNITOR_KUSTOMIZE_BASE_PATH} ${MUNITOR_KUSTOMIZE_LOAD_RESTRICTOR} ${MUNITOR_KUSTOMIZE_SCAN_OVERLAY} ${MUNITOR_KUSTOMIZE_OVERLAYS} ${MUNITOR_KUSTOMIZE_OVERLAY_DIR} ${MUNITOR_KUBE_LINTER_CONFIG} ${MUNITOR_YAMLLINT_PATHS} ${MUNITOR_CI_EMAIL} ${MUNITOR_CI_NAME} ${MUNITOR_NPM_DEFAULT_SCOPE} ${MUNITOR_ORB_SLUG} ${MUNITOR_PACKAGE_MANAGER} ${MUNITOR_SUPPLEMENTAL_IMAGES_JSON}'
|
||||
}
|
||||
MUNITOR_EXTRACT_EOF
|
||||
|
||||
@@ -490,6 +500,9 @@ workflows:
|
||||
health_path: ${MUNITOR_HEALTH_PATH}
|
||||
health_port: "${MUNITOR_HEALTH_PORT}"
|
||||
health_db: "${MUNITOR_HEALTH_DB}"
|
||||
##IF_SUPPLEMENTAL##
|
||||
supplemental_images: '${MUNITOR_SUPPLEMENTAL_IMAGES_JSON}'
|
||||
##ENDIF_SUPPLEMENTAL##
|
||||
requires:
|
||||
- code-quality
|
||||
- coverage
|
||||
@@ -538,6 +551,9 @@ workflows:
|
||||
environment: ${MUNITOR_CD_ENV_RELEASE}
|
||||
cd_format: ${MUNITOR_CD_FORMAT}
|
||||
cd_image_name: ${MUNITOR_DOCKER_REGISTRY}/${MUNITOR_IMAGE_NAME}
|
||||
##IF_SUPPLEMENTAL##
|
||||
supplemental_images: '${MUNITOR_SUPPLEMENTAL_IMAGES_JSON}'
|
||||
##ENDIF_SUPPLEMENTAL##
|
||||
ci_git_email: '${MUNITOR_CI_EMAIL}'
|
||||
ci_git_name: '${MUNITOR_CI_NAME}'
|
||||
requires:
|
||||
@@ -579,6 +595,9 @@ workflows:
|
||||
health_path: ${MUNITOR_HEALTH_PATH}
|
||||
health_port: "${MUNITOR_HEALTH_PORT}"
|
||||
health_db: "${MUNITOR_HEALTH_DB}"
|
||||
##IF_SUPPLEMENTAL##
|
||||
supplemental_images: '${MUNITOR_SUPPLEMENTAL_IMAGES_JSON}'
|
||||
##ENDIF_SUPPLEMENTAL##
|
||||
requires:
|
||||
- build-and-test
|
||||
context:
|
||||
@@ -593,6 +612,9 @@ workflows:
|
||||
environment: ${MUNITOR_CD_ENV_PROD}
|
||||
cd_format: ${MUNITOR_CD_FORMAT}
|
||||
cd_image_name: ${MUNITOR_DOCKER_REGISTRY}/${MUNITOR_IMAGE_NAME}
|
||||
##IF_SUPPLEMENTAL##
|
||||
supplemental_images: '${MUNITOR_SUPPLEMENTAL_IMAGES_JSON}'
|
||||
##ENDIF_SUPPLEMENTAL##
|
||||
ci_git_email: '${MUNITOR_CI_EMAIL}'
|
||||
ci_git_name: '${MUNITOR_CI_NAME}'
|
||||
requires:
|
||||
@@ -810,6 +832,9 @@ workflows:
|
||||
health_path: ${MUNITOR_HEALTH_PATH}
|
||||
health_port: "${MUNITOR_HEALTH_PORT}"
|
||||
health_db: "${MUNITOR_HEALTH_DB}"
|
||||
##IF_SUPPLEMENTAL##
|
||||
supplemental_images: '${MUNITOR_SUPPLEMENTAL_IMAGES_JSON}'
|
||||
##ENDIF_SUPPLEMENTAL##
|
||||
requires:
|
||||
- code-quality
|
||||
- coverage
|
||||
@@ -852,6 +877,9 @@ workflows:
|
||||
environment: ${MUNITOR_CD_ENV_RELEASE}
|
||||
cd_format: ${MUNITOR_CD_FORMAT}
|
||||
cd_image_name: ${MUNITOR_DOCKER_REGISTRY}/${MUNITOR_IMAGE_NAME}
|
||||
##IF_SUPPLEMENTAL##
|
||||
supplemental_images: '${MUNITOR_SUPPLEMENTAL_IMAGES_JSON}'
|
||||
##ENDIF_SUPPLEMENTAL##
|
||||
ci_git_email: '${MUNITOR_CI_EMAIL}'
|
||||
ci_git_name: '${MUNITOR_CI_NAME}'
|
||||
requires:
|
||||
@@ -907,6 +935,9 @@ workflows:
|
||||
health_path: ${MUNITOR_HEALTH_PATH}
|
||||
health_port: "${MUNITOR_HEALTH_PORT}"
|
||||
health_db: "${MUNITOR_HEALTH_DB}"
|
||||
##IF_SUPPLEMENTAL##
|
||||
supplemental_images: '${MUNITOR_SUPPLEMENTAL_IMAGES_JSON}'
|
||||
##ENDIF_SUPPLEMENTAL##
|
||||
requires:
|
||||
- build-and-test
|
||||
context:
|
||||
@@ -921,6 +952,9 @@ workflows:
|
||||
environment: ${MUNITOR_CD_ENV_PROD}
|
||||
cd_format: ${MUNITOR_CD_FORMAT}
|
||||
cd_image_name: ${MUNITOR_DOCKER_REGISTRY}/${MUNITOR_IMAGE_NAME}
|
||||
##IF_SUPPLEMENTAL##
|
||||
supplemental_images: '${MUNITOR_SUPPLEMENTAL_IMAGES_JSON}'
|
||||
##ENDIF_SUPPLEMENTAL##
|
||||
ci_git_email: '${MUNITOR_CI_EMAIL}'
|
||||
ci_git_name: '${MUNITOR_CI_NAME}'
|
||||
requires:
|
||||
@@ -1138,6 +1172,9 @@ workflows:
|
||||
health_path: ${MUNITOR_HEALTH_PATH}
|
||||
health_port: "${MUNITOR_HEALTH_PORT}"
|
||||
health_db: "${MUNITOR_HEALTH_DB}"
|
||||
##IF_SUPPLEMENTAL##
|
||||
supplemental_images: '${MUNITOR_SUPPLEMENTAL_IMAGES_JSON}'
|
||||
##ENDIF_SUPPLEMENTAL##
|
||||
requires:
|
||||
- code-quality
|
||||
- coverage
|
||||
@@ -1180,6 +1217,9 @@ workflows:
|
||||
environment: ${MUNITOR_CD_ENV_RELEASE}
|
||||
cd_format: ${MUNITOR_CD_FORMAT}
|
||||
cd_image_name: ${MUNITOR_DOCKER_REGISTRY}/${MUNITOR_IMAGE_NAME}
|
||||
##IF_SUPPLEMENTAL##
|
||||
supplemental_images: '${MUNITOR_SUPPLEMENTAL_IMAGES_JSON}'
|
||||
##ENDIF_SUPPLEMENTAL##
|
||||
ci_git_email: '${MUNITOR_CI_EMAIL}'
|
||||
ci_git_name: '${MUNITOR_CI_NAME}'
|
||||
requires:
|
||||
@@ -1235,6 +1275,9 @@ workflows:
|
||||
health_path: ${MUNITOR_HEALTH_PATH}
|
||||
health_port: "${MUNITOR_HEALTH_PORT}"
|
||||
health_db: "${MUNITOR_HEALTH_DB}"
|
||||
##IF_SUPPLEMENTAL##
|
||||
supplemental_images: '${MUNITOR_SUPPLEMENTAL_IMAGES_JSON}'
|
||||
##ENDIF_SUPPLEMENTAL##
|
||||
requires:
|
||||
- build-and-test
|
||||
context:
|
||||
@@ -1249,6 +1292,9 @@ workflows:
|
||||
environment: ${MUNITOR_CD_ENV_PROD}
|
||||
cd_format: ${MUNITOR_CD_FORMAT}
|
||||
cd_image_name: ${MUNITOR_DOCKER_REGISTRY}/${MUNITOR_IMAGE_NAME}
|
||||
##IF_SUPPLEMENTAL##
|
||||
supplemental_images: '${MUNITOR_SUPPLEMENTAL_IMAGES_JSON}'
|
||||
##ENDIF_SUPPLEMENTAL##
|
||||
ci_git_email: '${MUNITOR_CI_EMAIL}'
|
||||
ci_git_name: '${MUNITOR_CI_NAME}'
|
||||
requires:
|
||||
@@ -1811,6 +1857,9 @@ cat > /tmp/munitor/templates/partials/java-webapp-deploy.yml.tpl << 'MUNITOR_PAR
|
||||
health_path: ${MUNITOR_HEALTH_PATH}
|
||||
health_port: "${MUNITOR_HEALTH_PORT}"
|
||||
health_db: "${MUNITOR_HEALTH_DB}"
|
||||
##IF_SUPPLEMENTAL##
|
||||
supplemental_images: '${MUNITOR_SUPPLEMENTAL_IMAGES_JSON}'
|
||||
##ENDIF_SUPPLEMENTAL##
|
||||
requires:
|
||||
- code-quality
|
||||
- coverage
|
||||
@@ -1857,6 +1906,9 @@ cat > /tmp/munitor/templates/partials/java-webapp-deploy.yml.tpl << 'MUNITOR_PAR
|
||||
environment: __CD_ENVIRONMENT__
|
||||
cd_format: ${MUNITOR_CD_FORMAT}
|
||||
cd_image_name: ${MUNITOR_DOCKER_REGISTRY}/${MUNITOR_IMAGE_NAME}
|
||||
##IF_SUPPLEMENTAL##
|
||||
supplemental_images: '${MUNITOR_SUPPLEMENTAL_IMAGES_JSON}'
|
||||
##ENDIF_SUPPLEMENTAL##
|
||||
ci_git_email: '${MUNITOR_CI_EMAIL}'
|
||||
ci_git_name: '${MUNITOR_CI_NAME}'
|
||||
requires:
|
||||
@@ -1961,6 +2013,9 @@ cat > /tmp/munitor/templates/partials/node-api-deploy.yml.tpl << 'MUNITOR_PARTIA
|
||||
health_path: ${MUNITOR_HEALTH_PATH}
|
||||
health_port: "${MUNITOR_HEALTH_PORT}"
|
||||
health_db: "${MUNITOR_HEALTH_DB}"
|
||||
##IF_SUPPLEMENTAL##
|
||||
supplemental_images: '${MUNITOR_SUPPLEMENTAL_IMAGES_JSON}'
|
||||
##ENDIF_SUPPLEMENTAL##
|
||||
requires:
|
||||
- code-quality
|
||||
- coverage
|
||||
@@ -2001,6 +2056,9 @@ cat > /tmp/munitor/templates/partials/node-api-deploy.yml.tpl << 'MUNITOR_PARTIA
|
||||
environment: __CD_ENVIRONMENT__
|
||||
cd_format: ${MUNITOR_CD_FORMAT}
|
||||
cd_image_name: ${MUNITOR_DOCKER_REGISTRY}/${MUNITOR_IMAGE_NAME}
|
||||
##IF_SUPPLEMENTAL##
|
||||
supplemental_images: '${MUNITOR_SUPPLEMENTAL_IMAGES_JSON}'
|
||||
##ENDIF_SUPPLEMENTAL##
|
||||
ci_git_email: '${MUNITOR_CI_EMAIL}'
|
||||
ci_git_name: '${MUNITOR_CI_NAME}'
|
||||
requires:
|
||||
@@ -2105,6 +2163,9 @@ cat > /tmp/munitor/templates/partials/node-webapp-deploy.yml.tpl << 'MUNITOR_PAR
|
||||
health_path: ${MUNITOR_HEALTH_PATH}
|
||||
health_port: "${MUNITOR_HEALTH_PORT}"
|
||||
health_db: "${MUNITOR_HEALTH_DB}"
|
||||
##IF_SUPPLEMENTAL##
|
||||
supplemental_images: '${MUNITOR_SUPPLEMENTAL_IMAGES_JSON}'
|
||||
##ENDIF_SUPPLEMENTAL##
|
||||
requires:
|
||||
- code-quality
|
||||
- coverage
|
||||
@@ -2145,6 +2206,9 @@ cat > /tmp/munitor/templates/partials/node-webapp-deploy.yml.tpl << 'MUNITOR_PAR
|
||||
environment: __CD_ENVIRONMENT__
|
||||
cd_format: ${MUNITOR_CD_FORMAT}
|
||||
cd_image_name: ${MUNITOR_DOCKER_REGISTRY}/${MUNITOR_IMAGE_NAME}
|
||||
##IF_SUPPLEMENTAL##
|
||||
supplemental_images: '${MUNITOR_SUPPLEMENTAL_IMAGES_JSON}'
|
||||
##ENDIF_SUPPLEMENTAL##
|
||||
ci_git_email: '${MUNITOR_CI_EMAIL}'
|
||||
ci_git_name: '${MUNITOR_CI_NAME}'
|
||||
requires:
|
||||
@@ -2258,7 +2322,7 @@ validate_required_fields "${PIPELINE_TYPE}" "${CONFIG_FILE}"
|
||||
# --------------------------------------------------------------------------
|
||||
# Warn about unknown top-level keys (catches typos like java_verion)
|
||||
# --------------------------------------------------------------------------
|
||||
KNOWN_KEYS="pipeline orb_version image_name java_version node_version sonar docker cd coverage e2e sbom owasp contexts npm node services test terraform sast health kustomize kube_linter_config package_manager yamllint_paths"
|
||||
KNOWN_KEYS="pipeline orb_version image_name java_version node_version sonar docker cd coverage e2e sbom owasp contexts npm node services test terraform sast health kustomize kube_linter_config package_manager yamllint_paths supplemental_images"
|
||||
ACTUAL_KEYS=$(yq 'keys | .[]' "${CONFIG_FILE}" 2>/dev/null || true)
|
||||
for key in ${ACTUAL_KEYS}; do
|
||||
if ! echo "${KNOWN_KEYS}" | grep -qw "${key}"; then
|
||||
@@ -2362,7 +2426,7 @@ process_conditionals() {
|
||||
cp "${input}" "${tmpfile}"
|
||||
|
||||
# Process each conditional flag
|
||||
for flag in E2E SBOM SONAR NPM_AUTH SERVICES TEST_SETUP CUSTOM_TEST COVERAGE_CMD GITHUB_RELEASE SAST CD OWASP NVD; do
|
||||
for flag in E2E SBOM SONAR NPM_AUTH SERVICES TEST_SETUP CUSTOM_TEST COVERAGE_CMD GITHUB_RELEASE SAST CD OWASP NVD SUPPLEMENTAL; do
|
||||
local var_name="MUNITOR_${flag}"
|
||||
local value="${!var_name:-false}"
|
||||
local flag_file
|
||||
|
||||
@@ -262,6 +262,15 @@ extract_munitor_vars() {
|
||||
fi
|
||||
MUNITOR_HEALTH_DB=$(yq '.health.db // false' "${config_file}")
|
||||
|
||||
# Supplemental images (e.g., migrations, db-backup)
|
||||
MUNITOR_SUPPLEMENTAL_IMAGES_JSON=$(yq '.supplemental_images // [] | tojson' "${config_file}")
|
||||
if [[ "${MUNITOR_SUPPLEMENTAL_IMAGES_JSON}" == "[]" || "${MUNITOR_SUPPLEMENTAL_IMAGES_JSON}" == "null" ]]; then
|
||||
MUNITOR_SUPPLEMENTAL="false"
|
||||
MUNITOR_SUPPLEMENTAL_IMAGES_JSON="[]"
|
||||
else
|
||||
MUNITOR_SUPPLEMENTAL="true"
|
||||
fi
|
||||
|
||||
# Derived flags
|
||||
if [[ -n "${MUNITOR_SONAR_PROJECT_KEY}" ]]; then
|
||||
MUNITOR_SONAR="true"
|
||||
@@ -300,13 +309,14 @@ extract_munitor_vars() {
|
||||
export MUNITOR_NODE_FRAMEWORK MUNITOR_PACKAGE_MANAGER
|
||||
export MUNITOR_CI_EMAIL MUNITOR_CI_NAME MUNITOR_NPM_DEFAULT_SCOPE MUNITOR_ORB_SLUG
|
||||
export MUNITOR_HEALTH_PATH MUNITOR_HEALTH_PORT MUNITOR_HEALTH_DB
|
||||
export MUNITOR_SUPPLEMENTAL MUNITOR_SUPPLEMENTAL_IMAGES_JSON
|
||||
export MUNITOR_SONAR MUNITOR_CD MUNITOR_NVD
|
||||
}
|
||||
|
||||
# Build the envsubst variable list
|
||||
get_envsubst_vars() {
|
||||
# shellcheck disable=SC2016
|
||||
echo '${MUNITOR_PIPELINE} ${MUNITOR_ORB_VERSION} ${MUNITOR_IMAGE_NAME} ${MUNITOR_JAVA_VERSION} ${MUNITOR_NODE_VERSION} ${MUNITOR_SONAR_PROJECT_KEY} ${MUNITOR_DOCKER_REGISTRY} ${MUNITOR_CD_REPO} ${MUNITOR_CD_FORMAT} ${MUNITOR_CD_ENV_DEVELOP} ${MUNITOR_CD_ENV_STAGING} ${MUNITOR_CD_ENV_PROD} ${MUNITOR_CD_ENV_RELEASE} ${MUNITOR_COVERAGE_MIN} ${MUNITOR_E2E} ${MUNITOR_SBOM} ${MUNITOR_OWASP} ${MUNITOR_CONTEXT_REGISTRY} ${MUNITOR_CONTEXT_GITHUB} ${MUNITOR_CONTEXT_SONAR} ${MUNITOR_CONTEXT_NVD} ${MUNITOR_NPM_AUTH} ${MUNITOR_NPM_SCOPES} ${MUNITOR_SERVICES_JSON} ${MUNITOR_TEST_SETUP_SCRIPT} ${MUNITOR_TEST_COMMANDS_JSON} ${MUNITOR_COVERAGE_TOOL} ${MUNITOR_COVERAGE_COMMAND} ${MUNITOR_GITHUB_RELEASE} ${MUNITOR_SAST} ${MUNITOR_SAST_FAIL_ON_FINDINGS} ${MUNITOR_HEALTH_PATH} ${MUNITOR_HEALTH_PORT} ${MUNITOR_HEALTH_DB} ${MUNITOR_TF_PATH} ${MUNITOR_TF_LIVE_PATH} ${MUNITOR_TF_ENVIRONMENTS} ${MUNITOR_CHECKOV_SKIP} ${MUNITOR_KUSTOMIZE_VERSION} ${MUNITOR_KUSTOMIZE_BASE_PATH} ${MUNITOR_KUSTOMIZE_LOAD_RESTRICTOR} ${MUNITOR_KUSTOMIZE_SCAN_OVERLAY} ${MUNITOR_KUSTOMIZE_OVERLAYS} ${MUNITOR_KUSTOMIZE_OVERLAY_DIR} ${MUNITOR_KUBE_LINTER_CONFIG} ${MUNITOR_YAMLLINT_PATHS} ${MUNITOR_CI_EMAIL} ${MUNITOR_CI_NAME} ${MUNITOR_NPM_DEFAULT_SCOPE} ${MUNITOR_ORB_SLUG} ${MUNITOR_PACKAGE_MANAGER}'
|
||||
echo '${MUNITOR_PIPELINE} ${MUNITOR_ORB_VERSION} ${MUNITOR_IMAGE_NAME} ${MUNITOR_JAVA_VERSION} ${MUNITOR_NODE_VERSION} ${MUNITOR_SONAR_PROJECT_KEY} ${MUNITOR_DOCKER_REGISTRY} ${MUNITOR_CD_REPO} ${MUNITOR_CD_FORMAT} ${MUNITOR_CD_ENV_DEVELOP} ${MUNITOR_CD_ENV_STAGING} ${MUNITOR_CD_ENV_PROD} ${MUNITOR_CD_ENV_RELEASE} ${MUNITOR_COVERAGE_MIN} ${MUNITOR_E2E} ${MUNITOR_SBOM} ${MUNITOR_OWASP} ${MUNITOR_CONTEXT_REGISTRY} ${MUNITOR_CONTEXT_GITHUB} ${MUNITOR_CONTEXT_SONAR} ${MUNITOR_CONTEXT_NVD} ${MUNITOR_NPM_AUTH} ${MUNITOR_NPM_SCOPES} ${MUNITOR_SERVICES_JSON} ${MUNITOR_TEST_SETUP_SCRIPT} ${MUNITOR_TEST_COMMANDS_JSON} ${MUNITOR_COVERAGE_TOOL} ${MUNITOR_COVERAGE_COMMAND} ${MUNITOR_GITHUB_RELEASE} ${MUNITOR_SAST} ${MUNITOR_SAST_FAIL_ON_FINDINGS} ${MUNITOR_HEALTH_PATH} ${MUNITOR_HEALTH_PORT} ${MUNITOR_HEALTH_DB} ${MUNITOR_TF_PATH} ${MUNITOR_TF_LIVE_PATH} ${MUNITOR_TF_ENVIRONMENTS} ${MUNITOR_CHECKOV_SKIP} ${MUNITOR_KUSTOMIZE_VERSION} ${MUNITOR_KUSTOMIZE_BASE_PATH} ${MUNITOR_KUSTOMIZE_LOAD_RESTRICTOR} ${MUNITOR_KUSTOMIZE_SCAN_OVERLAY} ${MUNITOR_KUSTOMIZE_OVERLAYS} ${MUNITOR_KUSTOMIZE_OVERLAY_DIR} ${MUNITOR_KUBE_LINTER_CONFIG} ${MUNITOR_YAMLLINT_PATHS} ${MUNITOR_CI_EMAIL} ${MUNITOR_CI_NAME} ${MUNITOR_NPM_DEFAULT_SCOPE} ${MUNITOR_ORB_SLUG} ${MUNITOR_PACKAGE_MANAGER} ${MUNITOR_SUPPLEMENTAL_IMAGES_JSON}'
|
||||
}
|
||||
MUNITOR_EXTRACT_EOF
|
||||
|
||||
@@ -368,6 +378,8 @@ WORKDIR /app
|
||||
COPY --from=deps /app/node_modules ./node_modules
|
||||
COPY . .
|
||||
ENV STANDALONE=true
|
||||
ARG GIT_COMMIT_SHA
|
||||
ENV GIT_COMMIT_SHA=\${GIT_COMMIT_SHA}
|
||||
RUN npm run build
|
||||
|
||||
FROM node:${MUNITOR_NODE_VERSION}-alpine AS runner
|
||||
@@ -469,6 +481,8 @@ WORKDIR /app
|
||||
COPY package*.json ./
|
||||
RUN npm ci
|
||||
COPY . .
|
||||
ARG GIT_COMMIT_SHA
|
||||
ENV GIT_COMMIT_SHA=\${GIT_COMMIT_SHA}
|
||||
RUN npm run build
|
||||
|
||||
FROM gcr.io/distroless/nodejs${MUNITOR_NODE_VERSION}-debian12 AS runner
|
||||
|
||||
@@ -11,7 +11,7 @@ elif ! type munitor_header &>/dev/null; then
|
||||
munitor_download_with_retry() { curl -fsSL --retry 3 "$1" -o "$2"; }
|
||||
fi
|
||||
|
||||
TRIVY_VERSION="${TRIVY_VERSION:-0.58.2}"
|
||||
TRIVY_VERSION="${TRIVY_VERSION:-0.69.3}"
|
||||
INSTALL_DIR="${HOME}/bin"
|
||||
mkdir -p "${INSTALL_DIR}"
|
||||
export PATH="${INSTALL_DIR}:${PATH}"
|
||||
|
||||
@@ -11,7 +11,7 @@ elif ! type munitor_header &>/dev/null; then
|
||||
munitor_download_with_retry() { curl -fsSL --retry 3 "$1" -o "$2"; }
|
||||
fi
|
||||
|
||||
TRIVY_VERSION="${TRIVY_VERSION:-0.58.2}"
|
||||
TRIVY_VERSION="${TRIVY_VERSION:-0.69.3}"
|
||||
INSTALL_DIR="${HOME}/bin"
|
||||
mkdir -p "${INSTALL_DIR}"
|
||||
export PATH="${INSTALL_DIR}:${PATH}"
|
||||
|
||||
@@ -177,6 +177,11 @@ workflows:
|
||||
health_path: ${MUNITOR_HEALTH_PATH}
|
||||
health_port: "${MUNITOR_HEALTH_PORT}"
|
||||
health_db: "${MUNITOR_HEALTH_DB}"
|
||||
health_migrations: "${MUNITOR_HEALTH_MIGRATIONS}"
|
||||
health_smoke_paths: "${MUNITOR_HEALTH_SMOKE_PATHS}"
|
||||
##IF_SUPPLEMENTAL##
|
||||
supplemental_images: '${MUNITOR_SUPPLEMENTAL_IMAGES_JSON}'
|
||||
##ENDIF_SUPPLEMENTAL##
|
||||
requires:
|
||||
- code-quality
|
||||
- coverage
|
||||
@@ -225,6 +230,9 @@ workflows:
|
||||
environment: ${MUNITOR_CD_ENV_RELEASE}
|
||||
cd_format: ${MUNITOR_CD_FORMAT}
|
||||
cd_image_name: ${MUNITOR_DOCKER_REGISTRY}/${MUNITOR_IMAGE_NAME}
|
||||
##IF_SUPPLEMENTAL##
|
||||
supplemental_images: '${MUNITOR_SUPPLEMENTAL_IMAGES_JSON}'
|
||||
##ENDIF_SUPPLEMENTAL##
|
||||
ci_git_email: '${MUNITOR_CI_EMAIL}'
|
||||
ci_git_name: '${MUNITOR_CI_NAME}'
|
||||
requires:
|
||||
@@ -266,6 +274,11 @@ workflows:
|
||||
health_path: ${MUNITOR_HEALTH_PATH}
|
||||
health_port: "${MUNITOR_HEALTH_PORT}"
|
||||
health_db: "${MUNITOR_HEALTH_DB}"
|
||||
health_migrations: "${MUNITOR_HEALTH_MIGRATIONS}"
|
||||
health_smoke_paths: "${MUNITOR_HEALTH_SMOKE_PATHS}"
|
||||
##IF_SUPPLEMENTAL##
|
||||
supplemental_images: '${MUNITOR_SUPPLEMENTAL_IMAGES_JSON}'
|
||||
##ENDIF_SUPPLEMENTAL##
|
||||
requires:
|
||||
- build-and-test
|
||||
context:
|
||||
@@ -280,6 +293,9 @@ workflows:
|
||||
environment: ${MUNITOR_CD_ENV_PROD}
|
||||
cd_format: ${MUNITOR_CD_FORMAT}
|
||||
cd_image_name: ${MUNITOR_DOCKER_REGISTRY}/${MUNITOR_IMAGE_NAME}
|
||||
##IF_SUPPLEMENTAL##
|
||||
supplemental_images: '${MUNITOR_SUPPLEMENTAL_IMAGES_JSON}'
|
||||
##ENDIF_SUPPLEMENTAL##
|
||||
ci_git_email: '${MUNITOR_CI_EMAIL}'
|
||||
ci_git_name: '${MUNITOR_CI_NAME}'
|
||||
requires:
|
||||
|
||||
@@ -191,6 +191,9 @@ workflows:
|
||||
health_path: ${MUNITOR_HEALTH_PATH}
|
||||
health_port: "${MUNITOR_HEALTH_PORT}"
|
||||
health_db: "${MUNITOR_HEALTH_DB}"
|
||||
##IF_SUPPLEMENTAL##
|
||||
supplemental_images: '${MUNITOR_SUPPLEMENTAL_IMAGES_JSON}'
|
||||
##ENDIF_SUPPLEMENTAL##
|
||||
requires:
|
||||
- code-quality
|
||||
- coverage
|
||||
@@ -233,6 +236,9 @@ workflows:
|
||||
environment: ${MUNITOR_CD_ENV_RELEASE}
|
||||
cd_format: ${MUNITOR_CD_FORMAT}
|
||||
cd_image_name: ${MUNITOR_DOCKER_REGISTRY}/${MUNITOR_IMAGE_NAME}
|
||||
##IF_SUPPLEMENTAL##
|
||||
supplemental_images: '${MUNITOR_SUPPLEMENTAL_IMAGES_JSON}'
|
||||
##ENDIF_SUPPLEMENTAL##
|
||||
ci_git_email: '${MUNITOR_CI_EMAIL}'
|
||||
ci_git_name: '${MUNITOR_CI_NAME}'
|
||||
requires:
|
||||
@@ -288,6 +294,9 @@ workflows:
|
||||
health_path: ${MUNITOR_HEALTH_PATH}
|
||||
health_port: "${MUNITOR_HEALTH_PORT}"
|
||||
health_db: "${MUNITOR_HEALTH_DB}"
|
||||
##IF_SUPPLEMENTAL##
|
||||
supplemental_images: '${MUNITOR_SUPPLEMENTAL_IMAGES_JSON}'
|
||||
##ENDIF_SUPPLEMENTAL##
|
||||
requires:
|
||||
- build-and-test
|
||||
context:
|
||||
@@ -302,6 +311,9 @@ workflows:
|
||||
environment: ${MUNITOR_CD_ENV_PROD}
|
||||
cd_format: ${MUNITOR_CD_FORMAT}
|
||||
cd_image_name: ${MUNITOR_DOCKER_REGISTRY}/${MUNITOR_IMAGE_NAME}
|
||||
##IF_SUPPLEMENTAL##
|
||||
supplemental_images: '${MUNITOR_SUPPLEMENTAL_IMAGES_JSON}'
|
||||
##ENDIF_SUPPLEMENTAL##
|
||||
ci_git_email: '${MUNITOR_CI_EMAIL}'
|
||||
ci_git_name: '${MUNITOR_CI_NAME}'
|
||||
requires:
|
||||
|
||||
@@ -191,6 +191,9 @@ workflows:
|
||||
health_path: ${MUNITOR_HEALTH_PATH}
|
||||
health_port: "${MUNITOR_HEALTH_PORT}"
|
||||
health_db: "${MUNITOR_HEALTH_DB}"
|
||||
##IF_SUPPLEMENTAL##
|
||||
supplemental_images: '${MUNITOR_SUPPLEMENTAL_IMAGES_JSON}'
|
||||
##ENDIF_SUPPLEMENTAL##
|
||||
requires:
|
||||
- code-quality
|
||||
- coverage
|
||||
@@ -233,6 +236,9 @@ workflows:
|
||||
environment: ${MUNITOR_CD_ENV_RELEASE}
|
||||
cd_format: ${MUNITOR_CD_FORMAT}
|
||||
cd_image_name: ${MUNITOR_DOCKER_REGISTRY}/${MUNITOR_IMAGE_NAME}
|
||||
##IF_SUPPLEMENTAL##
|
||||
supplemental_images: '${MUNITOR_SUPPLEMENTAL_IMAGES_JSON}'
|
||||
##ENDIF_SUPPLEMENTAL##
|
||||
ci_git_email: '${MUNITOR_CI_EMAIL}'
|
||||
ci_git_name: '${MUNITOR_CI_NAME}'
|
||||
requires:
|
||||
@@ -288,6 +294,9 @@ workflows:
|
||||
health_path: ${MUNITOR_HEALTH_PATH}
|
||||
health_port: "${MUNITOR_HEALTH_PORT}"
|
||||
health_db: "${MUNITOR_HEALTH_DB}"
|
||||
##IF_SUPPLEMENTAL##
|
||||
supplemental_images: '${MUNITOR_SUPPLEMENTAL_IMAGES_JSON}'
|
||||
##ENDIF_SUPPLEMENTAL##
|
||||
requires:
|
||||
- build-and-test
|
||||
context:
|
||||
@@ -302,6 +311,9 @@ workflows:
|
||||
environment: ${MUNITOR_CD_ENV_PROD}
|
||||
cd_format: ${MUNITOR_CD_FORMAT}
|
||||
cd_image_name: ${MUNITOR_DOCKER_REGISTRY}/${MUNITOR_IMAGE_NAME}
|
||||
##IF_SUPPLEMENTAL##
|
||||
supplemental_images: '${MUNITOR_SUPPLEMENTAL_IMAGES_JSON}'
|
||||
##ENDIF_SUPPLEMENTAL##
|
||||
ci_git_email: '${MUNITOR_CI_EMAIL}'
|
||||
ci_git_name: '${MUNITOR_CI_NAME}'
|
||||
requires:
|
||||
|
||||
@@ -82,6 +82,9 @@
|
||||
health_path: ${MUNITOR_HEALTH_PATH}
|
||||
health_port: "${MUNITOR_HEALTH_PORT}"
|
||||
health_db: "${MUNITOR_HEALTH_DB}"
|
||||
##IF_SUPPLEMENTAL##
|
||||
supplemental_images: '${MUNITOR_SUPPLEMENTAL_IMAGES_JSON}'
|
||||
##ENDIF_SUPPLEMENTAL##
|
||||
requires:
|
||||
- code-quality
|
||||
- coverage
|
||||
@@ -128,6 +131,9 @@
|
||||
environment: __CD_ENVIRONMENT__
|
||||
cd_format: ${MUNITOR_CD_FORMAT}
|
||||
cd_image_name: ${MUNITOR_DOCKER_REGISTRY}/${MUNITOR_IMAGE_NAME}
|
||||
##IF_SUPPLEMENTAL##
|
||||
supplemental_images: '${MUNITOR_SUPPLEMENTAL_IMAGES_JSON}'
|
||||
##ENDIF_SUPPLEMENTAL##
|
||||
ci_git_email: '${MUNITOR_CI_EMAIL}'
|
||||
ci_git_name: '${MUNITOR_CI_NAME}'
|
||||
requires:
|
||||
|
||||
@@ -89,6 +89,9 @@
|
||||
health_path: ${MUNITOR_HEALTH_PATH}
|
||||
health_port: "${MUNITOR_HEALTH_PORT}"
|
||||
health_db: "${MUNITOR_HEALTH_DB}"
|
||||
##IF_SUPPLEMENTAL##
|
||||
supplemental_images: '${MUNITOR_SUPPLEMENTAL_IMAGES_JSON}'
|
||||
##ENDIF_SUPPLEMENTAL##
|
||||
requires:
|
||||
- code-quality
|
||||
- coverage
|
||||
@@ -129,6 +132,9 @@
|
||||
environment: __CD_ENVIRONMENT__
|
||||
cd_format: ${MUNITOR_CD_FORMAT}
|
||||
cd_image_name: ${MUNITOR_DOCKER_REGISTRY}/${MUNITOR_IMAGE_NAME}
|
||||
##IF_SUPPLEMENTAL##
|
||||
supplemental_images: '${MUNITOR_SUPPLEMENTAL_IMAGES_JSON}'
|
||||
##ENDIF_SUPPLEMENTAL##
|
||||
ci_git_email: '${MUNITOR_CI_EMAIL}'
|
||||
ci_git_name: '${MUNITOR_CI_NAME}'
|
||||
requires:
|
||||
|
||||
@@ -89,6 +89,9 @@
|
||||
health_path: ${MUNITOR_HEALTH_PATH}
|
||||
health_port: "${MUNITOR_HEALTH_PORT}"
|
||||
health_db: "${MUNITOR_HEALTH_DB}"
|
||||
##IF_SUPPLEMENTAL##
|
||||
supplemental_images: '${MUNITOR_SUPPLEMENTAL_IMAGES_JSON}'
|
||||
##ENDIF_SUPPLEMENTAL##
|
||||
requires:
|
||||
- code-quality
|
||||
- coverage
|
||||
@@ -129,6 +132,9 @@
|
||||
environment: __CD_ENVIRONMENT__
|
||||
cd_format: ${MUNITOR_CD_FORMAT}
|
||||
cd_image_name: ${MUNITOR_DOCKER_REGISTRY}/${MUNITOR_IMAGE_NAME}
|
||||
##IF_SUPPLEMENTAL##
|
||||
supplemental_images: '${MUNITOR_SUPPLEMENTAL_IMAGES_JSON}'
|
||||
##ENDIF_SUPPLEMENTAL##
|
||||
ci_git_email: '${MUNITOR_CI_EMAIL}'
|
||||
ci_git_name: '${MUNITOR_CI_NAME}'
|
||||
requires:
|
||||
|
||||
@@ -92,6 +92,42 @@ else
|
||||
git add "${VALUES}"
|
||||
fi
|
||||
|
||||
# Update supplemental image tags (if any)
|
||||
SUPP_JSON="${SUPPLEMENTAL_IMAGES_JSON:-[]}"
|
||||
if [[ "${SUPP_JSON}" != "[]" && "${SUPP_JSON}" != "null" ]]; then
|
||||
SUPP_COUNT=$(echo "${SUPP_JSON}" | jq 'length')
|
||||
echo "Updating ${SUPP_COUNT} supplemental image tag(s)..."
|
||||
|
||||
for ((i = 0; i < SUPP_COUNT; i++)); do
|
||||
SUPP_NAME=$(echo "${SUPP_JSON}" | jq -r ".[$i].name")
|
||||
|
||||
if [[ "${FORMAT}" == "kustomize" ]]; then
|
||||
SUPP_CD_IMAGE=$(echo "${SUPP_JSON}" | jq -r ".[$i].cd.image_name // \"\"")
|
||||
if [[ -z "${SUPP_CD_IMAGE}" ]]; then
|
||||
SUPP_CD_IMAGE="${IMAGE_NAME}-${SUPP_NAME}"
|
||||
fi
|
||||
echo " Kustomize: ${SUPP_CD_IMAGE} -> ${VERSION}"
|
||||
# Upsert: add entry if it doesn't exist, then update
|
||||
EXISTING=$(yq ".images[] | select(.name == \"${SUPP_CD_IMAGE}\") | .name" "${KUST_FILE}")
|
||||
if [[ -z "${EXISTING}" ]]; then
|
||||
echo " (creating new image entry)"
|
||||
yq -i ".images += [{\"name\": \"${SUPP_CD_IMAGE}\", \"newTag\": \"${VERSION}\"}]" "${KUST_FILE}"
|
||||
else
|
||||
yq -i "(.images[] | select(.name == \"${SUPP_CD_IMAGE}\")).newTag = \"${VERSION}\"" "${KUST_FILE}"
|
||||
yq -i "del((.images[] | select(.name == \"${SUPP_CD_IMAGE}\")).digest)" "${KUST_FILE}"
|
||||
fi
|
||||
git add "${KUST_FILE}"
|
||||
else
|
||||
SUPP_IMAGE_KEY=$(echo "${SUPP_JSON}" | jq -r ".[$i].cd.image_key // \"\"")
|
||||
if [[ -n "${SUPP_IMAGE_KEY}" ]]; then
|
||||
echo " Helm: ${SUPP_IMAGE_KEY} -> ${VERSION}"
|
||||
yq -i ".${SUPP_IMAGE_KEY} = \"${VERSION}\"" "${VALUES}"
|
||||
git add "${VALUES}"
|
||||
fi
|
||||
fi
|
||||
done
|
||||
fi
|
||||
|
||||
# Commit and push
|
||||
git config user.email "${CI_GIT_EMAIL:-munitor-ci@koftwentytwo.com}"
|
||||
git config user.name "${CI_GIT_NAME:-Munitor CI}"
|
||||
|
||||
@@ -0,0 +1,35 @@
|
||||
pipeline: java-webapp
|
||||
orb_version: dev:snapshot
|
||||
|
||||
image_name: me-health-portal
|
||||
java_version: "21"
|
||||
|
||||
sonar:
|
||||
project_key: dmdbrands_me-health-portal
|
||||
|
||||
docker:
|
||||
registry: ghcr.io/dmdbrands
|
||||
|
||||
cd:
|
||||
repo: dmdbrands/me-health-portal-cd-pipeline
|
||||
|
||||
coverage:
|
||||
min_instruction: 80
|
||||
|
||||
e2e: true
|
||||
sbom: true
|
||||
|
||||
contexts:
|
||||
registry: ghcr
|
||||
github: github
|
||||
sonar: sonarcloud
|
||||
nvd: nvd
|
||||
|
||||
supplemental_images:
|
||||
- name: migrations
|
||||
base: liquibase/liquibase:4.31
|
||||
copy:
|
||||
- src: db/changelog/
|
||||
dest: /liquibase/changelog/
|
||||
cd:
|
||||
image_key: migrations.image.tag
|
||||
@@ -263,6 +263,30 @@ assert_eq "health_port default 3000" "3000" "${MUNITOR_HEALTH_PORT}"
|
||||
assert_eq "coverage min default" "70" "${MUNITOR_COVERAGE_MIN}"
|
||||
assert_eq "package_manager default" "npm" "${MUNITOR_PACKAGE_MANAGER}"
|
||||
|
||||
# --------------------------------------------------------------------------
|
||||
# supplemental_images (enabled)
|
||||
# --------------------------------------------------------------------------
|
||||
echo ""
|
||||
echo "=== extract_munitor_vars: supplemental_images (enabled) ==="
|
||||
extract_munitor_vars "${FIXTURES_DIR}/java-webapp-supplemental.munitor.yml"
|
||||
|
||||
assert_eq "supplemental flag" "true" "${MUNITOR_SUPPLEMENTAL}"
|
||||
assert_eq "supplemental JSON is non-empty" "true" "$([[ "${MUNITOR_SUPPLEMENTAL_IMAGES_JSON}" != "[]" ]] && echo true || echo false)"
|
||||
assert_eq "supplemental JSON is single-line" "1" "$(echo "${MUNITOR_SUPPLEMENTAL_IMAGES_JSON}" | wc -l | tr -d ' ')"
|
||||
assert_eq "supplemental JSON has migrations" "true" "$(echo "${MUNITOR_SUPPLEMENTAL_IMAGES_JSON}" | jq -r '.[0].name' 2>/dev/null | grep -q migrations && echo true || echo false)"
|
||||
assert_eq "supplemental migrations base" "liquibase/liquibase:4.31" "$(echo "${MUNITOR_SUPPLEMENTAL_IMAGES_JSON}" | jq -r '.[0].base')"
|
||||
assert_eq "supplemental migrations cd.image_key" "migrations.image.tag" "$(echo "${MUNITOR_SUPPLEMENTAL_IMAGES_JSON}" | jq -r '.[0].cd.image_key')"
|
||||
|
||||
# --------------------------------------------------------------------------
|
||||
# supplemental_images (default: disabled)
|
||||
# --------------------------------------------------------------------------
|
||||
echo ""
|
||||
echo "=== extract_munitor_vars: supplemental_images (default disabled) ==="
|
||||
extract_munitor_vars "${FIXTURES_DIR}/java-webapp.munitor.yml"
|
||||
|
||||
assert_eq "supplemental flag default" "false" "${MUNITOR_SUPPLEMENTAL}"
|
||||
assert_eq "supplemental JSON default empty" "[]" "${MUNITOR_SUPPLEMENTAL_IMAGES_JSON}"
|
||||
|
||||
# --------------------------------------------------------------------------
|
||||
# Missing config file
|
||||
# --------------------------------------------------------------------------
|
||||
@@ -326,6 +350,15 @@ else
|
||||
FAIL=$((FAIL + 1))
|
||||
fi
|
||||
|
||||
echo -n " TEST: get_envsubst_vars includes MUNITOR_SUPPLEMENTAL_IMAGES_JSON... "
|
||||
if echo "${VARS}" | grep -q 'MUNITOR_SUPPLEMENTAL_IMAGES_JSON'; then
|
||||
echo "PASS"
|
||||
PASS=$((PASS + 1))
|
||||
else
|
||||
echo "FAIL"
|
||||
FAIL=$((FAIL + 1))
|
||||
fi
|
||||
|
||||
# --------------------------------------------------------------------------
|
||||
echo ""
|
||||
echo "=== Results: ${PASS} passed, ${FAIL} failed ==="
|
||||
|
||||
@@ -1080,6 +1080,57 @@ run_negative_test "validate-cd-repo: no overlay_dir param (regression)" \
|
||||
"${FIXTURES_DIR}/validate-cd-repo.munitor.yml" \
|
||||
"overlay_dir:"
|
||||
|
||||
# --------------------------------------------------------------------------
|
||||
# Supplemental Images Tests
|
||||
# --------------------------------------------------------------------------
|
||||
echo ""
|
||||
echo "=== Supplemental Images Template Tests ==="
|
||||
|
||||
# java-webapp-supplemental: supplemental_images parameter appears in docker-build-push
|
||||
run_context_test "java-webapp-supplemental: docker-build-push has supplemental_images param" \
|
||||
"${FIXTURES_DIR}/java-webapp-supplemental.munitor.yml" \
|
||||
"name: docker-build-push" \
|
||||
"context:" \
|
||||
"supplemental_images:"
|
||||
|
||||
# java-webapp-supplemental: supplemental_images parameter appears in update-cd-repo
|
||||
run_context_test "java-webapp-supplemental: update-cd-repo has supplemental_images param" \
|
||||
"${FIXTURES_DIR}/java-webapp-supplemental.munitor.yml" \
|
||||
"name: update-cd-repo" \
|
||||
"context:" \
|
||||
"supplemental_images:"
|
||||
|
||||
# java-webapp (no supplemental): supplemental_images should NOT appear
|
||||
run_negative_test "java-webapp: no supplemental_images param when not configured" \
|
||||
"${FIXTURES_DIR}/java-webapp.munitor.yml" \
|
||||
"supplemental_images:"
|
||||
|
||||
# java-webapp-minimal: supplemental_images should NOT appear
|
||||
run_negative_test "java-webapp-minimal: no supplemental_images param" \
|
||||
"${FIXTURES_DIR}/java-webapp-minimal.munitor.yml" \
|
||||
"supplemental_images:"
|
||||
|
||||
# java-webapp-supplemental: still has all normal features (regression)
|
||||
run_test "java-webapp-supplemental: still has e2e" \
|
||||
"${FIXTURES_DIR}/java-webapp-supplemental.munitor.yml" \
|
||||
"e2e-tests"
|
||||
|
||||
run_test "java-webapp-supplemental: still has sonar" \
|
||||
"${FIXTURES_DIR}/java-webapp-supplemental.munitor.yml" \
|
||||
"sonar-scan"
|
||||
|
||||
run_test "java-webapp-supplemental: still has update-cd-repo" \
|
||||
"${FIXTURES_DIR}/java-webapp-supplemental.munitor.yml" \
|
||||
"update-cd-repo"
|
||||
|
||||
run_test "java-webapp-supplemental: has release-candidate workflow" \
|
||||
"${FIXTURES_DIR}/java-webapp-supplemental.munitor.yml" \
|
||||
"release-candidate:"
|
||||
|
||||
run_test "java-webapp-supplemental: has production workflow" \
|
||||
"${FIXTURES_DIR}/java-webapp-supplemental.munitor.yml" \
|
||||
"production:"
|
||||
|
||||
echo ""
|
||||
echo "=== Results: ${PASS} passed, ${FAIL} failed ==="
|
||||
|
||||
|
||||
@@ -327,6 +327,58 @@ else
|
||||
fail "should delete digest field to prevent kustomize from ignoring newTag"
|
||||
fi
|
||||
|
||||
echo -n " TEST: upserts supplemental images (creates new entry)... "
|
||||
if grep -q '.images += \[{' "${SRC_SCRIPTS}/update_cd_repo.sh"; then
|
||||
pass
|
||||
else
|
||||
fail "should create new image entries for supplemental images"
|
||||
fi
|
||||
|
||||
echo -n " TEST: checks for existing entry before upsert... "
|
||||
if grep -q 'EXISTING=' "${SRC_SCRIPTS}/update_cd_repo.sh" && grep -q 'if \[\[ -z "${EXISTING}"' "${SRC_SCRIPTS}/update_cd_repo.sh"; then
|
||||
pass
|
||||
else
|
||||
fail "should check if image entry exists before deciding to create or update"
|
||||
fi
|
||||
|
||||
# Functional test: verify upsert creates entries in a real kustomization file
|
||||
echo -n " TEST: upsert creates new image entry in kustomization (functional)... "
|
||||
UPSERT_TMPDIR=$(mktemp -d)
|
||||
cat > "${UPSERT_TMPDIR}/kustomization.yaml" <<'KUSTYAML'
|
||||
apiVersion: kustomize.config.k8s.io/v1beta1
|
||||
kind: Kustomization
|
||||
images:
|
||||
- name: ghcr.io/koftwentytwo/website-backend
|
||||
newTag: "0.1.0"
|
||||
KUSTYAML
|
||||
SUPP_CD_IMAGE="ghcr.io/koftwentytwo/website-backend-migrations"
|
||||
VERSION_TEST="0.2.0-SNAPSHOT.abc1234"
|
||||
EXISTING=$(yq ".images[] | select(.name == \"${SUPP_CD_IMAGE}\") | .name" "${UPSERT_TMPDIR}/kustomization.yaml")
|
||||
if [[ -z "${EXISTING}" ]]; then
|
||||
yq -i ".images += [{\"name\": \"${SUPP_CD_IMAGE}\", \"newTag\": \"${VERSION_TEST}\"}]" "${UPSERT_TMPDIR}/kustomization.yaml"
|
||||
fi
|
||||
RESULT_TAG=$(yq ".images[] | select(.name == \"${SUPP_CD_IMAGE}\") | .newTag" "${UPSERT_TMPDIR}/kustomization.yaml")
|
||||
if [[ "${RESULT_TAG}" == "${VERSION_TEST}" ]]; then
|
||||
pass
|
||||
else
|
||||
fail "expected newTag=${VERSION_TEST}, got ${RESULT_TAG}"
|
||||
fi
|
||||
|
||||
echo -n " TEST: upsert updates existing image entry in kustomization (functional)... "
|
||||
VERSION_TEST2="0.3.0-SNAPSHOT.def5678"
|
||||
EXISTING=$(yq ".images[] | select(.name == \"${SUPP_CD_IMAGE}\") | .name" "${UPSERT_TMPDIR}/kustomization.yaml")
|
||||
if [[ -n "${EXISTING}" ]]; then
|
||||
yq -i "(.images[] | select(.name == \"${SUPP_CD_IMAGE}\")).newTag = \"${VERSION_TEST2}\"" "${UPSERT_TMPDIR}/kustomization.yaml"
|
||||
fi
|
||||
RESULT_TAG2=$(yq ".images[] | select(.name == \"${SUPP_CD_IMAGE}\") | .newTag" "${UPSERT_TMPDIR}/kustomization.yaml")
|
||||
ENTRY_COUNT=$(yq "[.images[] | select(.name == \"${SUPP_CD_IMAGE}\")] | length" "${UPSERT_TMPDIR}/kustomization.yaml")
|
||||
if [[ "${RESULT_TAG2}" == "${VERSION_TEST2}" && "${ENTRY_COUNT}" == "1" ]]; then
|
||||
pass
|
||||
else
|
||||
fail "expected newTag=${VERSION_TEST2} with 1 entry, got tag=${RESULT_TAG2} count=${ENTRY_COUNT}"
|
||||
fi
|
||||
rm -rf "${UPSERT_TMPDIR}"
|
||||
|
||||
# =============================================================================
|
||||
# Test: docker_build.sh - DOCKER_ENV_TAG support
|
||||
# =============================================================================
|
||||
@@ -638,6 +690,89 @@ else
|
||||
fail "should skip missing directories"
|
||||
fi
|
||||
|
||||
# =============================================================================
|
||||
# Test: build_push_supplemental.sh - Supplemental image build
|
||||
# =============================================================================
|
||||
echo ""
|
||||
echo "=== build_push_supplemental.sh Tests ==="
|
||||
|
||||
echo -n " TEST: sources munitor_helpers... "
|
||||
if grep -q 'MUNITOR_HELPERS' "${SRC_SCRIPTS}/build_push_supplemental.sh"; then
|
||||
pass
|
||||
else
|
||||
fail "should source munitor_helpers"
|
||||
fi
|
||||
|
||||
echo -n " TEST: calls munitor_header... "
|
||||
if grep -q 'munitor_header' "${SRC_SCRIPTS}/build_push_supplemental.sh"; then
|
||||
pass
|
||||
else
|
||||
fail "should call munitor_header"
|
||||
fi
|
||||
|
||||
echo -n " TEST: reads SUPPLEMENTAL_IMAGES_JSON... "
|
||||
if grep -q 'SUPPLEMENTAL_IMAGES_JSON' "${SRC_SCRIPTS}/build_push_supplemental.sh"; then
|
||||
pass
|
||||
else
|
||||
fail "should read SUPPLEMENTAL_IMAGES_JSON"
|
||||
fi
|
||||
|
||||
echo -n " TEST: skips when JSON is empty... "
|
||||
if grep -q 'exit 0' "${SRC_SCRIPTS}/build_push_supplemental.sh"; then
|
||||
pass
|
||||
else
|
||||
fail "should exit 0 when no supplemental images"
|
||||
fi
|
||||
|
||||
echo -n " TEST: uses jq to parse JSON... "
|
||||
if grep -q 'jq' "${SRC_SCRIPTS}/build_push_supplemental.sh"; then
|
||||
pass
|
||||
else
|
||||
fail "should use jq"
|
||||
fi
|
||||
|
||||
echo -n " TEST: builds Docker images... "
|
||||
if grep -q 'docker build' "${SRC_SCRIPTS}/build_push_supplemental.sh"; then
|
||||
pass
|
||||
else
|
||||
fail "should run docker build"
|
||||
fi
|
||||
|
||||
echo -n " TEST: scans with Trivy... "
|
||||
if grep -q 'trivy image' "${SRC_SCRIPTS}/build_push_supplemental.sh"; then
|
||||
pass
|
||||
else
|
||||
fail "should scan with trivy"
|
||||
fi
|
||||
|
||||
echo -n " TEST: pushes images... "
|
||||
if grep -q 'docker push' "${SRC_SCRIPTS}/build_push_supplemental.sh"; then
|
||||
pass
|
||||
else
|
||||
fail "should push images"
|
||||
fi
|
||||
|
||||
echo -n " TEST: supports custom Dockerfile... "
|
||||
if grep -q 'dockerfile' "${SRC_SCRIPTS}/build_push_supplemental.sh"; then
|
||||
pass
|
||||
else
|
||||
fail "should support custom dockerfile"
|
||||
fi
|
||||
|
||||
echo -n " TEST: auto-generates Dockerfile from base+copy... "
|
||||
if grep -q 'Dockerfile\.' "${SRC_SCRIPTS}/build_push_supplemental.sh" && grep -q 'FROM' "${SRC_SCRIPTS}/build_push_supplemental.sh"; then
|
||||
pass
|
||||
else
|
||||
fail "should auto-generate Dockerfile"
|
||||
fi
|
||||
|
||||
echo -n " TEST: uses set -euo pipefail... "
|
||||
if grep -q 'set -euo pipefail' "${SRC_SCRIPTS}/build_push_supplemental.sh"; then
|
||||
pass
|
||||
else
|
||||
fail "should use strict mode"
|
||||
fi
|
||||
|
||||
# =============================================================================
|
||||
# Test: Scripts have proper error handling
|
||||
# =============================================================================
|
||||
@@ -736,6 +871,52 @@ else
|
||||
fail "missing munitor_header:${MISSING_HEADER}"
|
||||
fi
|
||||
|
||||
# =============================================================================
|
||||
# Test: External download URLs are reachable
|
||||
# =============================================================================
|
||||
echo ""
|
||||
echo "=== External Download URL Tests ==="
|
||||
|
||||
# Extract pinned versions from scripts (single source of truth)
|
||||
extract_version() { sed -n "s/.*${1}:-\([v0-9.]*\).*/\1/p" "$2" | head -1; }
|
||||
TRIVY_VER=$(extract_version TRIVY_VERSION "${SRC_SCRIPTS}/run_trivy.sh")
|
||||
GH_VER=$(extract_version GH_VERSION "${SRC_SCRIPTS}/install_gh.sh")
|
||||
GITLEAKS_VER=$(extract_version GITLEAKS_VERSION "${SRC_SCRIPTS}/install_gitleaks.sh")
|
||||
KUBE_LINTER_VER=$(extract_version KUBE_LINTER_VERSION "${SRC_SCRIPTS}/install_kube_linter.sh")
|
||||
TERRAGRUNT_VER=$(extract_version TERRAGRUNT_VERSION "${SRC_SCRIPTS}/install_terragrunt.sh")
|
||||
YQ_VER=$(extract_version YQ_VERSION "${SRC_SCRIPTS}/install_yq.sh")
|
||||
KUSTOMIZE_VER=$(extract_version KUSTOMIZE_VERSION "${SRC_SCRIPTS}/install_kustomize.sh")
|
||||
KUBESEC_VER=$(extract_version KUBESEC_VERSION "${SRC_SCRIPTS}/install_kubesec.sh")
|
||||
TFSEC_TRIVY_VER=$(extract_version TRIVY_VERSION "${SRC_SCRIPTS}/install_tfsec.sh")
|
||||
SONAR_VER=$(extract_version SONAR_SCANNER_VERSION "${SRC_SCRIPTS}/npm_sonar.sh")
|
||||
|
||||
# All URLs target linux/amd64 -- matches the CI executor
|
||||
URLS=(
|
||||
"Trivy ${TRIVY_VER}|https://github.com/aquasecurity/trivy/releases/download/v${TRIVY_VER}/trivy_${TRIVY_VER}_Linux-64bit.tar.gz"
|
||||
"Trivy/tfsec ${TFSEC_TRIVY_VER}|https://github.com/aquasecurity/trivy/releases/download/v${TFSEC_TRIVY_VER}/trivy_${TFSEC_TRIVY_VER}_Linux-64bit.tar.gz"
|
||||
"gh ${GH_VER}|https://github.com/cli/cli/releases/download/v${GH_VER}/gh_${GH_VER}_linux_amd64.tar.gz"
|
||||
"gitleaks ${GITLEAKS_VER}|https://github.com/gitleaks/gitleaks/releases/download/v${GITLEAKS_VER}/gitleaks_${GITLEAKS_VER}_linux_x64.tar.gz"
|
||||
"kube-linter ${KUBE_LINTER_VER}|https://github.com/stackrox/kube-linter/releases/download/v${KUBE_LINTER_VER}/kube-linter-linux.tar.gz"
|
||||
"terragrunt ${TERRAGRUNT_VER}|https://github.com/gruntwork-io/terragrunt/releases/download/v${TERRAGRUNT_VER}/terragrunt_linux_amd64"
|
||||
"yq ${YQ_VER}|https://github.com/mikefarah/yq/releases/download/${YQ_VER}/yq_linux_amd64"
|
||||
"kustomize ${KUSTOMIZE_VER}|https://github.com/kubernetes-sigs/kustomize/releases/download/kustomize%2Fv${KUSTOMIZE_VER}/kustomize_v${KUSTOMIZE_VER}_linux_amd64.tar.gz"
|
||||
"kubesec ${KUBESEC_VER}|https://github.com/controlplaneio/kubesec/releases/download/v${KUBESEC_VER}/kubesec_linux_amd64.tar.gz"
|
||||
"OpenTofu installer|https://get.opentofu.org/install-opentofu.sh"
|
||||
"sonar-scanner ${SONAR_VER}|https://binaries.sonarsource.com/Distribution/sonar-scanner-cli/sonar-scanner-cli-${SONAR_VER}-linux-x64.zip"
|
||||
)
|
||||
|
||||
for entry in "${URLS[@]}"; do
|
||||
LABEL="${entry%%|*}"
|
||||
URL="${entry##*|}"
|
||||
echo -n " TEST: ${LABEL} download URL is reachable... "
|
||||
HTTP_CODE=$(curl -sI -o /dev/null -w "%{http_code}" -L --retry 2 "${URL}" 2>/dev/null || echo "000")
|
||||
if [[ "${HTTP_CODE}" == "200" ]]; then
|
||||
pass
|
||||
else
|
||||
fail "HTTP ${HTTP_CODE} for ${URL}"
|
||||
fi
|
||||
done
|
||||
|
||||
# =============================================================================
|
||||
# Summary
|
||||
# =============================================================================
|
||||
|
||||
Reference in new issue
Block a user