diff --git a/README.md b/README.md index 0fcd1f6..436be33 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,7 @@ Latin: *munitor* (fortifier, protector) -- KofTwentyTwo's unified CircleCI orb f | --- | --- | | **Tier** | Internal until classified -- listed under *Awaiting classification* in the KofTwentyTwo standards [MAINTAINERS.md](https://github.com/KofTwentyTwo/standards/blob/main/MAINTAINERS.md); Product-tier requirements are being adopted | | **Standards** | Targets [KofTwentyTwo standards](https://github.com/KofTwentyTwo/standards) 1.0.0 | -| **Orb** | [`kof22/munitor`](https://circleci.com/developer/orbs/orb/kof22/munitor), latest stable `0.3.5` | +| **Orb** | [`kof22/munitor`](https://circleci.com/developer/orbs/orb/kof22/munitor), latest stable `0.3.6` | | **Security** | [SECURITY.md](SECURITY.md) | | **Contributing** | [CONTRIBUTING.md](CONTRIBUTING.md) | @@ -70,16 +70,16 @@ Munitor validates branch names and will fail on non-conforming names. Munitor is a public CircleCI orb: any CircleCI organization can use it without forking. This checklist covers what a new consumer needs, for example a Java/Maven web service. A QQQ application should also read the [QQQ adoption checklist](https://github.com/QRun-IO/qqq/blob/develop/docs/migration/adoption-checklist.adoc) (section 7 covers release tooling). -**Version.** Use `kof22/munitor@0.3.5` (or `@0.3` to float on the 0.3 line) in `.circleci/config.yml`, and the same value as `orb_version` in `.munitor.yml`. Keep the setup orb and the generated pipeline on the same line. +**Version.** Use `kof22/munitor@0.3.6` (or `@0.3` to float on the 0.3 line) in `.circleci/config.yml`, and the same value as `orb_version` in `.munitor.yml`. Keep the setup orb and the generated pipeline on the same line. ### 1. Repository files -- `.circleci/config.yml`: the setup config from [Quick Start](#quick-start), pinned to `kof22/munitor@0.3.5`. +- `.circleci/config.yml`: the setup config from [Quick Start](#quick-start), pinned to `kof22/munitor@0.3.6`. - `.munitor.yml`: pick a [pipeline type](#pipeline-types). A Java service is `java-webapp`. KofTwentyTwo's Website-Backend is a working example; a generalized version: ```yaml pipeline: java-webapp -orb_version: "0.3.5" +orb_version: "0.3.6" image_name: my-service java_version: "21" docker: diff --git a/src/scripts/build_push_supplemental.sh b/src/scripts/build_push_supplemental.sh index 6c42bfc..22670ce 100644 --- a/src/scripts/build_push_supplemental.sh +++ b/src/scripts/build_push_supplemental.sh @@ -27,7 +27,16 @@ 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}" +# CircleCI renders a boolean orb parameter as "1"/"0" in a step environment, not +# "true"/"false", so accept both spellings. Unset means push (release builds). +case "$(echo "${PUSH_IMAGES-true}" | tr '[:upper:]' '[:lower:]')" in + true | 1 | yes | on) PUSH_IMAGES=true ;; + false | 0 | no | off | "") PUSH_IMAGES=false ;; + *) + echo "ERROR: PUSH_IMAGES must be true/false (or 1/0), got '${PUSH_IMAGES}'" >&2 + exit 1 + ;; +esac # run_trivy_image installs here in a previous CircleCI step. export PATH="${HOME}/bin:${PATH}" mkdir -p /tmp/trivy-supplemental-results diff --git a/tests/test_docker_scan.sh b/tests/test_docker_scan.sh index 3ebf7b4..ab20f3d 100644 --- a/tests/test_docker_scan.sh +++ b/tests/test_docker_scan.sh @@ -80,6 +80,43 @@ else fail fi +# Regression (0.3.5): CircleCI renders the boolean "push" parameter as "1"/"0" in +# the step environment, and release builds silently skipped the push. +for push in 1 true TRUE; do + echo -n " TEST: push=${push} (release builds) publishes every supplemental image... " + : > "${CALL_LOG}" + if PUSH_IMAGES="${push}" bash "${SRC_SCRIPTS}/build_push_supplemental.sh" > "${WORK}/supplemental.log" && + [[ $(grep -c '^docker push ' "${CALL_LOG}") == 4 ]] && + grep -q '^docker push ghcr.io/example/app-migrations:' "${CALL_LOG}" && + grep -q '^docker push ghcr.io/example/app-worker:' "${CALL_LOG}" && + grep -q 'push=true' "${WORK}/supplemental.log"; then + pass + else + fail + fi +done + +for push in 0 false ""; do + echo -n " TEST: push='${push}' (PR scans) publishes nothing... " + : > "${CALL_LOG}" + if PUSH_IMAGES="${push}" bash "${SRC_SCRIPTS}/build_push_supplemental.sh" > "${WORK}/supplemental.log" && + ! grep -Eq '^docker (push|tag) ' "${CALL_LOG}"; then + pass + else + fail + fi +done + +echo -n " TEST: an unrecognised push value fails instead of guessing... " +: > "${CALL_LOG}" +if PUSH_IMAGES=maybe bash "${SRC_SCRIPTS}/build_push_supplemental.sh" > "${WORK}/supplemental.log" 2>&1; then + fail +elif ! grep -Eq '^docker (build|tag|push) ' "${CALL_LOG}" && grep -q "must be true/false" "${WORK}/supplemental.log"; 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}"