From b09ced056f3a6d240dd86e9f915f2176ca7855de Mon Sep 17 00:00:00 2001 From: James Maes Date: Tue, 13 Oct 2026 14:18:41 -0500 Subject: [PATCH] feat: scan container images in PR pipelines New munitor/docker_scan job (image-scan) in the pr-checks workflow of java-webapp, gradle-webapp, node-api and node-webapp: builds the app image and every supplemental image, runs the same Trivy 0.69.3 HIGH/CRITICAL --exit-code 1 scan as the release pipeline (same .trivyignore), stores the JSON results, and never pushes. build_push_supplemental gains push (default true, unchanged behavior). Co-Authored-By: Claude Opus 5.5 --- CONTRIBUTING.md | 1 + README.md | 11 ++- docs/SESSION-STATE.md | 18 ++++ docs/TODO.md | 3 + src/commands/build_push_supplemental.yml | 14 ++- src/jobs/docker_scan.yml | 49 +++++++++++ src/scripts/build_push_supplemental.sh | 27 ++++-- src/scripts/packed_generate_config.sh | 56 ++++++++++++ src/scripts/templates/gradle-webapp.yml.tpl | 14 +++ src/scripts/templates/java-webapp.yml.tpl | 14 +++ src/scripts/templates/node-api.yml.tpl | 14 +++ src/scripts/templates/node-webapp.yml.tpl | 14 +++ tests/test_docker_scan.sh | 97 +++++++++++++++++++++ tests/test_generate_config.sh | 30 +++++++ 14 files changed, 350 insertions(+), 12 deletions(-) create mode 100644 src/jobs/docker_scan.yml create mode 100644 tests/test_docker_scan.sh diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 57cd176..40b36f1 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -332,6 +332,7 @@ These components are shared across all modules -- you don't need to recreate the | `secrets_scan` job | Gitleaks (all modules) | | `sast_scan` job | Semgrep (all modules, opt-in) | | `docker_build_push` job | Build + health check + Trivy scan + GHCR push | +| `docker_scan` job | PR image build + Trivy scan (including supplemental images), JSON artifacts, no publishing | | `health_check` command | Container health check smoke test (all Docker modules) | | `update_cd_repo` job | GitOps CD repo update | | `github_release` job | Annotated git tags + GitHub Releases (auto-enabled with `contexts.github`) | diff --git a/README.md b/README.md index ff46867..130c84a 100644 --- a/README.md +++ b/README.md @@ -490,7 +490,7 @@ Each workflow runs on specific branches and includes jobs based on your config: | Workflow | Branches | Jobs | |----------|----------|------| -| `pr-checks` | `feature/*`, `hotfix/*` | Build, test, lint, coverage, security scans | +| `pr-checks` | `feature/*`, `hotfix/*` | Build, test, lint, coverage, security scans, container image scan (Docker modules) | | `develop` | `develop` | All pr-checks + Docker build/push + CD update (dev env) | | `staging` | `staging` | All pr-checks + Docker build/push + CD update (staging env) | | `release-candidate` | `release/*` | All pr-checks + Docker, CD (staging), SonarCloud, SBOM, GitHub Release (pre-release) | @@ -498,11 +498,20 @@ Each workflow runs on specific branches and includes jobs based on your config: For `validate-cd-repo` and `argocd-apps`, all three workflows (`pr-checks`, `develop`, `release`) run the same 5-job set: yaml-lint, kustomize-validate, kubesec-scan, kube-linter, secrets-scan. +For `java-webapp`, `gradle-webapp`, `node-api`, and `node-webapp`, PRs run +`image-scan` after `build-and-test`: build the application and any supplemental +images locally, then fail on HIGH/CRITICAL CVEs with the same Trivy policy and +repository-root `.trivyignore` as release builds. JSON reports are saved as +artifacts. This job does not log in, publish images, reserve tags, or update CD. +Release candidates already scan through `docker-build-push` and do not run a +second image scan job. + ### Job Dependency Graph (node-api pr-checks) ``` checkout --> build-and-test + --> image-scan (local build + Trivy, including supplemental images) --> code-quality --> coverage --> security-scan diff --git a/docs/SESSION-STATE.md b/docs/SESSION-STATE.md index fef7010..a796468 100644 --- a/docs/SESSION-STATE.md +++ b/docs/SESSION-STATE.md @@ -1,5 +1,23 @@ # Munitor session state +## PR container scanning (2026-10-13) + +Uncommitted work on `feature/pr-image-scan` adds `docker_scan` after +`build-and-test` in the four application PR templates. It restores the existing +feature/hotfix version metadata, builds locally, and applies the release Trivy +HIGH/CRITICAL policy from the repository root. Supplemental images use +`push: false`; the command defaults to publishing for existing callers. Main +and supplemental JSON reports are artifacts. Release candidates already scan +through `docker_build_push`, so no duplicate job was added. + +Verified: native CircleCI orb pack/validate, ShellCheck on all source scripts +and the changed tests, template structure/filters/parameter wiring, packed +template synchronization, and `git diff --check`. Requested make and BATS runs +were attempted but Git Bash cannot start in this sandbox (CreateFileMapping, +Win32 error 5); yamllint is not installed. New behavioral tests therefore need +a Linux/CI run, including real Docker/Trivy integration. No commit or publish. +The Second Brain vault is outside writable roots; continuity is recorded here. + ## Release 0.3.3 (2026-10-11) PR22 (00f349c) fixes release version collisions. Website-Backend #65/#66 (0.1.24) diff --git a/docs/TODO.md b/docs/TODO.md index d48fbda..4d1d0e3 100644 --- a/docs/TODO.md +++ b/docs/TODO.md @@ -2,6 +2,9 @@ ## Pending +- [ ] Run PR image-scan script/template/BATS tests on Linux and verify a consumer PR with Docker/Trivy before publishing. +- [x] Add PR-only image scans for the four application templates, supplemental scan-only mode, JSON artifacts, and regression tests (uncommitted). + - [x] Review publishing CI fixes and merge PR19 to develop. - [x] Publish v0.3.2 from main. - [ ] Publish v0.3.3 (atomic release versions); bump Website-Backend/Frontend pins to 0.3.3. diff --git a/src/commands/build_push_supplemental.yml b/src/commands/build_push_supplemental.yml index ed5b9b0..a819907 100644 --- a/src/commands/build_push_supplemental.yml +++ b/src/commands/build_push_supplemental.yml @@ -1,8 +1,12 @@ 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). + Each supplemental image shares the same version tag. Requires run_trivy_image first + for Trivy installation, and docker_push_ghcr for registry auth only when push is true. parameters: + push: + type: boolean + default: true + description: Publish scanned images to the registry. Disable for PR scans. supplemental_images: type: string default: "[]" @@ -16,9 +20,13 @@ parameters: description: Container registry URL. steps: - run: - name: Build and push supplemental images + name: Build and scan supplemental images (optionally push) environment: + PUSH_IMAGES: << parameters.push >> SUPPLEMENTAL_IMAGES_JSON: << parameters.supplemental_images >> IMAGE_NAME: << parameters.image_name >> REGISTRY: << parameters.registry >> command: << include(scripts/build_push_supplemental.sh) >> + - store_artifacts: + path: /tmp/trivy-supplemental-results + destination: trivy-supplemental-scans diff --git a/src/jobs/docker_scan.yml b/src/jobs/docker_scan.yml new file mode 100644 index 0000000..1b773e3 --- /dev/null +++ b/src/jobs/docker_scan.yml @@ -0,0 +1,49 @@ +description: > + Build and scan application and supplemental images without publishing. + Requires the source and version metadata workspace from build-and-test. +parameters: + image_name: + type: string + description: Docker image name (without registry prefix). + registry: + type: string + default: ghcr.io/KofTwentyTwo + description: Container registry URL. + resource_class: + type: enum + enum: + - medium + - large + default: large + description: Machine resource class. + docker_layer_caching: + 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 and scan. +executor: + name: machine + resource_class: << parameters.resource_class >> + docker_layer_caching: << parameters.docker_layer_caching >> +steps: + - attach_workspace: + at: . + - run: + name: Restore version metadata + command: <> + - generate_dockerfile + - docker_build: + image_name: << parameters.image_name >> + registry: << parameters.registry >> + - restore_trivy_cache + - run_trivy_image: + image_tag: << parameters.registry >>/<< parameters.image_name >>:${DOCKER_TAG} + - save_trivy_cache + - build_push_supplemental: + supplemental_images: << parameters.supplemental_images >> + image_name: << parameters.image_name >> + registry: << parameters.registry >> + push: false diff --git a/src/scripts/build_push_supplemental.sh b/src/scripts/build_push_supplemental.sh index eddc8b8..6c42bfc 100644 --- a/src/scripts/build_push_supplemental.sh +++ b/src/scripts/build_push_supplemental.sh @@ -27,6 +27,10 @@ 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:-}" +PUSH_IMAGES="${PUSH_IMAGES:-true}" +# run_trivy_image installs here in a previous CircleCI step. +export PATH="${HOME}/bin:${PATH}" +mkdir -p /tmp/trivy-supplemental-results COUNT=$(echo "${IMAGES_JSON}" | jq 'length') echo "Found ${COUNT} supplemental image(s) to build." @@ -76,26 +80,33 @@ for i in $(seq 0 $((COUNT - 1))); do fi docker build "${BUILD_ARGS[@]}" . - if [[ -n "${ENV_TAG}" ]]; then + if [[ "${PUSH_IMAGES}" == "true" && -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}" + trivy image --format json --output "/tmp/trivy-supplemental-results/${NAME}.json" \ + --severity HIGH,CRITICAL --exit-code 1 "${FULL_TAG}" || { + EXIT_CODE=$? + trivy image --severity HIGH,CRITICAL "${FULL_TAG}" + exit "${EXIT_CODE}" + } # Push - echo "Pushing ${FULL_TAG} ..." - docker push "${FULL_TAG}" + if [[ "${PUSH_IMAGES}" == "true" ]]; then + echo "Pushing ${FULL_TAG} ..." + docker push "${FULL_TAG}" - if [[ -n "${ENV_TAG}" ]]; then - echo "Pushing ${ENV_FULL_TAG} ..." - docker push "${ENV_FULL_TAG}" + if [[ -n "${ENV_TAG}" ]]; then + echo "Pushing ${ENV_FULL_TAG} ..." + docker push "${ENV_FULL_TAG}" + fi fi echo "--- Done: ${DERIVED_NAME} ---" done echo "" -echo "All supplemental images built, scanned, and pushed." +echo "All supplemental images built and scanned (push=${PUSH_IMAGES})." diff --git a/src/scripts/packed_generate_config.sh b/src/scripts/packed_generate_config.sh index 1bdee91..60cc71d 100755 --- a/src/scripts/packed_generate_config.sh +++ b/src/scripts/packed_generate_config.sh @@ -366,6 +366,20 @@ workflows: only: - /feature\/.*/ - /hotfix\/.*/ + - munitor/docker_scan: + name: image-scan + image_name: ${MUNITOR_IMAGE_NAME} + registry: ${MUNITOR_DOCKER_REGISTRY} + ##IF_SUPPLEMENTAL## + supplemental_images: '${MUNITOR_SUPPLEMENTAL_IMAGES_JSON}' + ##ENDIF_SUPPLEMENTAL## + requires: + - build-and-test + filters: + branches: + only: + - /feature\/.*/ + - /hotfix\/.*/ - munitor/secrets_scan: name: secrets-scan filters: @@ -694,6 +708,20 @@ workflows: only: - /feature\/.*/ - /hotfix\/.*/ + - munitor/docker_scan: + name: image-scan + image_name: ${MUNITOR_IMAGE_NAME} + registry: ${MUNITOR_DOCKER_REGISTRY} + ##IF_SUPPLEMENTAL## + supplemental_images: '${MUNITOR_SUPPLEMENTAL_IMAGES_JSON}' + ##ENDIF_SUPPLEMENTAL## + requires: + - build-and-test + filters: + branches: + only: + - /feature\/.*/ + - /hotfix\/.*/ - munitor/secrets_scan: name: secrets-scan filters: @@ -1037,6 +1065,20 @@ workflows: only: - /feature\/.*/ - /hotfix\/.*/ + - munitor/docker_scan: + name: image-scan + image_name: ${MUNITOR_IMAGE_NAME} + registry: ${MUNITOR_DOCKER_REGISTRY} + ##IF_SUPPLEMENTAL## + supplemental_images: '${MUNITOR_SUPPLEMENTAL_IMAGES_JSON}' + ##ENDIF_SUPPLEMENTAL## + requires: + - build-and-test + filters: + branches: + only: + - /feature\/.*/ + - /hotfix\/.*/ - munitor/secrets_scan: name: secrets-scan filters: @@ -1406,6 +1448,20 @@ workflows: only: - /feature\/.*/ - /hotfix\/.*/ + - munitor/docker_scan: + name: image-scan + image_name: ${MUNITOR_IMAGE_NAME} + registry: ${MUNITOR_DOCKER_REGISTRY} + ##IF_SUPPLEMENTAL## + supplemental_images: '${MUNITOR_SUPPLEMENTAL_IMAGES_JSON}' + ##ENDIF_SUPPLEMENTAL## + requires: + - build-and-test + filters: + branches: + only: + - /feature\/.*/ + - /hotfix\/.*/ - munitor/secrets_scan: name: secrets-scan filters: diff --git a/src/scripts/templates/gradle-webapp.yml.tpl b/src/scripts/templates/gradle-webapp.yml.tpl index c652f1c..dabb89a 100644 --- a/src/scripts/templates/gradle-webapp.yml.tpl +++ b/src/scripts/templates/gradle-webapp.yml.tpl @@ -16,6 +16,20 @@ workflows: only: - /feature\/.*/ - /hotfix\/.*/ + - munitor/docker_scan: + name: image-scan + image_name: ${MUNITOR_IMAGE_NAME} + registry: ${MUNITOR_DOCKER_REGISTRY} + ##IF_SUPPLEMENTAL## + supplemental_images: '${MUNITOR_SUPPLEMENTAL_IMAGES_JSON}' + ##ENDIF_SUPPLEMENTAL## + requires: + - build-and-test + filters: + branches: + only: + - /feature\/.*/ + - /hotfix\/.*/ - munitor/secrets_scan: name: secrets-scan filters: diff --git a/src/scripts/templates/java-webapp.yml.tpl b/src/scripts/templates/java-webapp.yml.tpl index afe26c1..34665d7 100644 --- a/src/scripts/templates/java-webapp.yml.tpl +++ b/src/scripts/templates/java-webapp.yml.tpl @@ -16,6 +16,20 @@ workflows: only: - /feature\/.*/ - /hotfix\/.*/ + - munitor/docker_scan: + name: image-scan + image_name: ${MUNITOR_IMAGE_NAME} + registry: ${MUNITOR_DOCKER_REGISTRY} + ##IF_SUPPLEMENTAL## + supplemental_images: '${MUNITOR_SUPPLEMENTAL_IMAGES_JSON}' + ##ENDIF_SUPPLEMENTAL## + requires: + - build-and-test + filters: + branches: + only: + - /feature\/.*/ + - /hotfix\/.*/ - munitor/secrets_scan: name: secrets-scan filters: diff --git a/src/scripts/templates/node-api.yml.tpl b/src/scripts/templates/node-api.yml.tpl index ce49cef..162d65d 100644 --- a/src/scripts/templates/node-api.yml.tpl +++ b/src/scripts/templates/node-api.yml.tpl @@ -31,6 +31,20 @@ workflows: only: - /feature\/.*/ - /hotfix\/.*/ + - munitor/docker_scan: + name: image-scan + image_name: ${MUNITOR_IMAGE_NAME} + registry: ${MUNITOR_DOCKER_REGISTRY} + ##IF_SUPPLEMENTAL## + supplemental_images: '${MUNITOR_SUPPLEMENTAL_IMAGES_JSON}' + ##ENDIF_SUPPLEMENTAL## + requires: + - build-and-test + filters: + branches: + only: + - /feature\/.*/ + - /hotfix\/.*/ - munitor/secrets_scan: name: secrets-scan filters: diff --git a/src/scripts/templates/node-webapp.yml.tpl b/src/scripts/templates/node-webapp.yml.tpl index 805dae6..580b672 100644 --- a/src/scripts/templates/node-webapp.yml.tpl +++ b/src/scripts/templates/node-webapp.yml.tpl @@ -31,6 +31,20 @@ workflows: only: - /feature\/.*/ - /hotfix\/.*/ + - munitor/docker_scan: + name: image-scan + image_name: ${MUNITOR_IMAGE_NAME} + registry: ${MUNITOR_DOCKER_REGISTRY} + ##IF_SUPPLEMENTAL## + supplemental_images: '${MUNITOR_SUPPLEMENTAL_IMAGES_JSON}' + ##ENDIF_SUPPLEMENTAL## + requires: + - build-and-test + filters: + branches: + only: + - /feature\/.*/ + - /hotfix\/.*/ - munitor/secrets_scan: name: secrets-scan filters: diff --git a/tests/test_docker_scan.sh b/tests/test_docker_scan.sh new file mode 100644 index 0000000..3ebf7b4 --- /dev/null +++ b/tests/test_docker_scan.sh @@ -0,0 +1,97 @@ +#!/usr/bin/env bash +# Exercise image scanning with local tool stubs; no Docker daemon or network needed. +set -euo pipefail + +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +SRC_SCRIPTS="$(cd "${SCRIPT_DIR}/../src/scripts" && pwd)" +WORK=$(mktemp -d) +trap 'rm -rf "${WORK}"' EXIT +PASS=0 +FAIL=0 +pass() { echo "PASS"; PASS=$((PASS + 1)); } +fail() { echo "FAIL"; FAIL=$((FAIL + 1)); } + +mkdir -p "${WORK}/bin" "${WORK}/home/bin" "${WORK}/repo" +cat > "${WORK}/bin/docker" <<'EOF' +#!/usr/bin/env bash +printf 'docker %s\n' "$*" >> "${CALL_LOG}" +EOF +cat > "${WORK}/home/bin/trivy" <<'EOF' +#!/usr/bin/env bash +[[ -f .trivyignore ]] || exit 99 +printf 'trivy %s\n' "$*" >> "${CALL_LOG}" +# Redirect the production /tmp output path into the test workspace. +while [[ $# -gt 0 ]]; do + if [[ "$1" == --output ]]; then + printf '{"Results":[]}\n' > "${REPORT_DIR}/$(basename "$2")" + fi + shift +done +exit "${SCAN_EXIT:-0}" +EOF +chmod +x "${WORK}/bin/docker" "${WORK}/home/bin/trivy" +export PATH="${WORK}/bin:${PATH}" HOME="${WORK}/home" +export CALL_LOG="${WORK}/calls" REPORT_DIR="${WORK}" +export IMAGE_NAME=app REGISTRY=ghcr.io/example CIRCLE_SHA1=abcdef123456 +export SUPPLEMENTAL_IMAGES_JSON='[{"name":"migrations","dockerfile":"Dockerfile.migrations"},{"name":"worker","base":"example/base:1"}]' +cd "${WORK}/repo" +touch .trivyignore + +echo "=== PR image scan tests ===" +echo -n " TEST: feature metadata survives workspace restore and supplies Docker scan tag... " +export BASH_ENV="${WORK}/build-env" CIRCLE_BRANCH=feature/image-scan +export GITVERSION_MAJOR=1 GITVERSION_MINOR=2 GITVERSION_PATCH=3 +export GITVERSION_SHA=abcdef123456 +bash "${SRC_SCRIPTS}/export_version_vars.sh" > "${WORK}/version.log" +bash "${SRC_SCRIPTS}/persist_version_metadata.sh" >> "${WORK}/version.log" +export BASH_ENV="${WORK}/scan-env" +bash "${SRC_SCRIPTS}/restore_version_metadata.sh" >> "${WORK}/version.log" +bash "${SRC_SCRIPTS}/docker_build.sh" >> "${WORK}/version.log" +# shellcheck disable=SC1090 +source "${BASH_ENV}" +export IMAGE_TAG='ghcr.io/example/app:${DOCKER_TAG}' +if bash "${SRC_SCRIPTS}/run_trivy_image.sh" >> "${WORK}/version.log" && + grep -q 'trivy image .*--severity HIGH,CRITICAL --exit-code 1 ghcr.io/example/app:1.2.3-image-scan-abcdef123456-SNAPSHOT' "${CALL_LOG}"; then + pass +else + fail +fi + +echo -n " TEST: push=false builds and scans every supplemental without publishing... " +: > "${CALL_LOG}" +echo 'export DOCKER_ENV_TAG=develop' >> "${BASH_ENV}" +if PUSH_IMAGES=false bash "${SRC_SCRIPTS}/build_push_supplemental.sh" > "${WORK}/supplemental.log" && + [[ $(grep -c '^docker build ' "${CALL_LOG}") == 2 ]] && + [[ $(grep -c '^trivy image .*--severity HIGH,CRITICAL --exit-code 1 ' "${CALL_LOG}") == 2 ]] && + ! grep -Eq '^docker (push|login|tag|buildx) ' "${CALL_LOG}" && + [[ -s "${WORK}/migrations.json" && -s "${WORK}/worker.json" ]]; then + pass +else + fail +fi + +echo -n " TEST: default push still publishes version and environment tags... " +: > "${CALL_LOG}" +unset PUSH_IMAGES +if bash "${SRC_SCRIPTS}/build_push_supplemental.sh" > "${WORK}/supplemental.log" && + [[ $(grep -c '^docker push ' "${CALL_LOG}") == 4 ]]; then + pass +else + fail +fi + +for push in false true; do + echo -n " TEST: push=${push} fails on HIGH/CRITICAL findings before any push... " + : > "${CALL_LOG}" + rm -f "${WORK}/migrations.json" + if SCAN_EXIT=1 PUSH_IMAGES="${push}" bash "${SRC_SCRIPTS}/build_push_supplemental.sh" > "${WORK}/supplemental.log" 2>&1; then + fail + elif ! grep -q '^docker push ' "${CALL_LOG}" && [[ -s "${WORK}/migrations.json" ]]; then + pass + else + fail + fi +done + +echo "Results: ${PASS} passed, ${FAIL} failed" +[[ ${FAIL} -eq 0 ]] diff --git a/tests/test_generate_config.sh b/tests/test_generate_config.sh index 65003f3..79ce8e9 100755 --- a/tests/test_generate_config.sh +++ b/tests/test_generate_config.sh @@ -157,6 +157,36 @@ run_negative_context_test() { echo "=== Template Rendering Tests ===" +# Container scans belong only to PR jobs; RC already builds and scans before release. +for module in java-webapp gradle-webapp node-api node-webapp; do + fixture="${FIXTURES_DIR}/${module}.munitor.yml" + run_context_test "${module}: PR builds and scans the image" \ + "${fixture}" "pr-checks:" " develop:" 'munitor/docker_scan:' + run_context_test "${module}: image scan is named image-scan" \ + "${fixture}" "munitor/docker_scan:" "munitor/secrets_scan:" 'name: image-scan' + run_context_test "${module}: image scan waits for build-and-test" \ + "${fixture}" "munitor/docker_scan:" "munitor/secrets_scan:" '\- build-and-test' + run_negative_context_test "${module}: no duplicate scan outside PR workflow" \ + "${fixture}" " develop:" "END_OF_CONFIG" 'munitor/docker_scan:' + run_context_test "${module}: RC already builds and scans" \ + "${fixture}" "release-candidate:" "production:" 'munitor/docker_build_push:' + + echo -n " TEST: ${module}: every image scan has exactly the PR branch filters... " + output=$(render_fixture "${fixture}") + filters=$(yq -o=json -I=0 '[.workflows[].jobs[] | select(has("munitor/docker_scan")) | ."munitor/docker_scan".filters.branches.only]' <<< "${output}") + if [[ "${filters}" == '[["/feature\\/.*/","/hotfix\\/.*/"]]' ]]; then + echo "PASS" + PASS=$((PASS + 1)) + else + echo "FAIL (unexpected scan filters: ${filters})" + FAIL=$((FAIL + 1)) + fi +done + +run_context_test "supplemental images are wired into the PR image scan" \ + "${FIXTURES_DIR}/java-webapp-supplemental.munitor.yml" \ + "munitor/docker_scan:" "munitor/secrets_scan:" 'supplemental_images:.*migrations' + # Test java-webapp renders with correct values run_test "java-webapp: renders image_name" \ "${FIXTURES_DIR}/java-webapp.munitor.yml" \ -- 2.54.0