From 4b11b3acc809c122e7eccc13b68a6d1d8dfd8960 Mon Sep 17 00:00:00 2001 From: James Maes Date: Sun, 12 Jul 2026 05:39:14 -0500 Subject: [PATCH] feat(#9): support consolidated GitOps write-back --- README.md | 7 ++- src/commands/update_cd_repo.yml | 7 +++ src/jobs/update_cd_repo.yml | 5 ++ src/scripts/extract_munitor_vars.sh | 14 ++++- src/scripts/generate_config.sh | 4 +- src/scripts/packed_generate_config.sh | 62 ++++++++++++------- src/scripts/packed_generate_dockerfile.sh | 14 ++++- src/scripts/templates/gradle-webapp.yml.tpl | 6 +- src/scripts/templates/java-webapp.yml.tpl | 6 +- src/scripts/templates/node-api.yml.tpl | 6 +- src/scripts/templates/node-webapp.yml.tpl | 6 +- .../partials/gradle-webapp-deploy.yml.tpl | 5 +- .../partials/java-webapp-deploy.yml.tpl | 5 +- .../partials/node-api-deploy.yml.tpl | 5 +- .../partials/node-webapp-deploy.yml.tpl | 5 +- src/scripts/update_cd_repo.sh | 41 +++++++++--- .../node-webapp-consolidated.munitor.yml | 18 ++++++ tests/test_extract_munitor_vars.sh | 13 ++++ tests/test_generate_config.sh | 33 ++++++++-- tests/test_scripts.sh | 16 +++++ 20 files changed, 219 insertions(+), 59 deletions(-) create mode 100644 tests/fixtures/node-webapp-consolidated.munitor.yml diff --git a/README.md b/README.md index b3e7652..9e67948 100644 --- a/README.md +++ b/README.md @@ -171,7 +171,10 @@ docker: use_repo_dockerfile: true # preserve the repository Dockerfile cd: - repo: KofTwentyTwo/my-webapp-cd # omit to skip GitOps CD updates + repo: KofTwentyTwo/cluster-gitops # omit to skip GitOps CD updates + format: kustomize + production_only: true # only main writes this production target + path: tenants/my-app/website/kustomization.yaml env: release: staging # default: staging (CD target for release/* branches) @@ -469,6 +472,8 @@ Tags follow the format `vX.Y.Z` (git tag) and `X.Y.Z` (Docker tag). Tags are imm | `docker.registry` | string | *required** | node-api, node-webapp, java-webapp | Container registry URL | | `docker.use_repo_dockerfile` | bool | `false` | node-webapp | Preserve and build the repository-root Dockerfile instead of generating one | | `cd.repo` | string | -- | node-api, node-webapp, java-webapp | GitOps CD repo (`org/repo`). Omit to skip | +| `cd.path` | string | -- | node-api, node-webapp, java-webapp | Explicit repository-relative `kustomization.yaml` path for consolidated GitOps repositories | +| `cd.production_only` | bool | `false` | node-api, node-webapp, java-webapp | Disable CD write-back from develop, staging, and release workflows | | `cd.env.release` | string | `staging` | node-api, node-webapp, java-webapp | CD target environment for release branches | | `coverage.min_instruction` | int | `70` | node-api, node-webapp, java-webapp | Minimum coverage percentage | | `e2e` | bool | `false` | node-api, node-webapp, java-webapp | Enable Playwright E2E tests | diff --git a/src/commands/update_cd_repo.yml b/src/commands/update_cd_repo.yml index 92c5dfb..8a7c72c 100644 --- a/src/commands/update_cd_repo.yml +++ b/src/commands/update_cd_repo.yml @@ -30,6 +30,12 @@ parameters: description: > Full image name for Kustomize repos (e.g., ghcr.io/KofTwentyTwo/my-app). Used to select the correct entry in the images[] array. + cd_path: + type: string + default: "" + description: > + Explicit repository-relative kustomization.yaml path. When omitted, + Kustomize mode uses overlays//kustomization.yaml. ci_git_email: type: string default: "" @@ -54,6 +60,7 @@ steps: IMAGE_KEY: << parameters.image_key >> CD_FORMAT: << parameters.cd_format >> CD_IMAGE_NAME: << parameters.cd_image_name >> + CD_PATH: << parameters.cd_path >> CI_GIT_EMAIL: << parameters.ci_git_email >> CI_GIT_NAME: << parameters.ci_git_name >> SUPPLEMENTAL_IMAGES_JSON: << parameters.supplemental_images >> diff --git a/src/jobs/update_cd_repo.yml b/src/jobs/update_cd_repo.yml index 82bdf65..38c33a3 100644 --- a/src/jobs/update_cd_repo.yml +++ b/src/jobs/update_cd_repo.yml @@ -24,6 +24,10 @@ parameters: type: string default: "" description: Full image name for Kustomize repos. + cd_path: + type: string + default: "" + description: Explicit repository-relative kustomization.yaml path. ci_git_email: type: string default: "" @@ -52,6 +56,7 @@ steps: image_key: << parameters.image_key >> cd_format: << parameters.cd_format >> cd_image_name: << parameters.cd_image_name >> + cd_path: << parameters.cd_path >> ci_git_email: << parameters.ci_git_email >> ci_git_name: << parameters.ci_git_name >> supplemental_images: << parameters.supplemental_images >> diff --git a/src/scripts/extract_munitor_vars.sh b/src/scripts/extract_munitor_vars.sh index cc233ec..c625bd4 100644 --- a/src/scripts/extract_munitor_vars.sh +++ b/src/scripts/extract_munitor_vars.sh @@ -38,6 +38,8 @@ extract_munitor_vars() { fi MUNITOR_CD_REPO=$(yq '.cd.repo // ""' "${config_file}") MUNITOR_CD_FORMAT=$(yq '.cd.format // "helm"' "${config_file}") + MUNITOR_CD_PATH=$(yq '.cd.path // ""' "${config_file}") + MUNITOR_CD_PRODUCTION_ONLY=$(yq '.cd.production_only // false' "${config_file}") MUNITOR_CD_ENV_DEVELOP=$(yq '.cd.env.develop // "develop"' "${config_file}") MUNITOR_CD_ENV_STAGING=$(yq '.cd.env.staging // "staging"' "${config_file}") MUNITOR_CD_ENV_PROD=$(yq '.cd.env.prod // "prod"' "${config_file}") @@ -194,8 +196,14 @@ extract_munitor_vars() { if [[ -n "${MUNITOR_CD_REPO}" ]]; then MUNITOR_CD="true" + if [[ "${MUNITOR_CD_PRODUCTION_ONLY}" == "true" ]]; then + MUNITOR_CD_NON_PROD="false" + else + MUNITOR_CD_NON_PROD="true" + fi else MUNITOR_CD="false" + MUNITOR_CD_NON_PROD="false" fi if [[ -n "${MUNITOR_CONTEXT_NVD}" ]]; then @@ -206,7 +214,7 @@ extract_munitor_vars() { # Export all variables export MUNITOR_PIPELINE MUNITOR_ORB_VERSION MUNITOR_IMAGE_NAME MUNITOR_JAVA_VERSION MUNITOR_NODE_VERSION MUNITOR_SERVER_MODULE - export MUNITOR_SONAR_PROJECT_KEY MUNITOR_DOCKER_REGISTRY MUNITOR_CD_REPO MUNITOR_CD_FORMAT + export MUNITOR_SONAR_PROJECT_KEY MUNITOR_DOCKER_REGISTRY MUNITOR_CD_REPO MUNITOR_CD_FORMAT MUNITOR_CD_PATH MUNITOR_CD_PRODUCTION_ONLY export MUNITOR_CD_ENV_DEVELOP MUNITOR_CD_ENV_STAGING MUNITOR_CD_ENV_PROD MUNITOR_CD_ENV_RELEASE export MUNITOR_COVERAGE_MIN MUNITOR_E2E MUNITOR_SBOM MUNITOR_OWASP export MUNITOR_CONTEXT_REGISTRY MUNITOR_CONTEXT_GITHUB MUNITOR_CONTEXT_SONAR MUNITOR_CONTEXT_NVD @@ -224,11 +232,11 @@ extract_munitor_vars() { export MUNITOR_CI_EMAIL MUNITOR_CI_NAME MUNITOR_NPM_DEFAULT_SCOPE MUNITOR_ORB_SLUG 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 + export MUNITOR_SONAR MUNITOR_CD MUNITOR_CD_NON_PROD 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_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} ${MUNITOR_SERVER_MODULE} ${MUNITOR_COVERAGE_SUMMARY_PATH}' + 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_PATH} ${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} ${MUNITOR_SERVER_MODULE} ${MUNITOR_COVERAGE_SUMMARY_PATH}' } diff --git a/src/scripts/generate_config.sh b/src/scripts/generate_config.sh index 0b0271f..7a3a54c 100755 --- a/src/scripts/generate_config.sh +++ b/src/scripts/generate_config.sh @@ -2,7 +2,7 @@ set -euo pipefail CONFIG_FILE="${MUNITOR_CONFIG:-.munitor.yml}" -OUTPUT_FILE="/tmp/generated-config.yml" +OUTPUT_FILE="${MUNITOR_OUTPUT_FILE:-/tmp/generated-config.yml}" # When run via CircleCI << include() >>, BASH_SOURCE is empty. # Fall back to MUNITOR_SCRIPT_DIR set by the command YAML. @@ -201,7 +201,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 SUPPLEMENTAL; do + for flag in E2E SBOM SONAR NPM_AUTH SERVICES TEST_SETUP CUSTOM_TEST COVERAGE_CMD GITHUB_RELEASE SAST CD CD_NON_PROD OWASP NVD SUPPLEMENTAL; do local var_name="MUNITOR_${flag}" local value="${!var_name:-false}" local flag_file diff --git a/src/scripts/packed_generate_config.sh b/src/scripts/packed_generate_config.sh index 2bbe6fb..aca5231 100755 --- a/src/scripts/packed_generate_config.sh +++ b/src/scripts/packed_generate_config.sh @@ -135,6 +135,8 @@ extract_munitor_vars() { fi MUNITOR_CD_REPO=$(yq '.cd.repo // ""' "${config_file}") MUNITOR_CD_FORMAT=$(yq '.cd.format // "helm"' "${config_file}") + MUNITOR_CD_PATH=$(yq '.cd.path // ""' "${config_file}") + MUNITOR_CD_PRODUCTION_ONLY=$(yq '.cd.production_only // false' "${config_file}") MUNITOR_CD_ENV_DEVELOP=$(yq '.cd.env.develop // "develop"' "${config_file}") MUNITOR_CD_ENV_STAGING=$(yq '.cd.env.staging // "staging"' "${config_file}") MUNITOR_CD_ENV_PROD=$(yq '.cd.env.prod // "prod"' "${config_file}") @@ -291,8 +293,14 @@ extract_munitor_vars() { if [[ -n "${MUNITOR_CD_REPO}" ]]; then MUNITOR_CD="true" + if [[ "${MUNITOR_CD_PRODUCTION_ONLY}" == "true" ]]; then + MUNITOR_CD_NON_PROD="false" + else + MUNITOR_CD_NON_PROD="true" + fi else MUNITOR_CD="false" + MUNITOR_CD_NON_PROD="false" fi if [[ -n "${MUNITOR_CONTEXT_NVD}" ]]; then @@ -303,7 +311,7 @@ extract_munitor_vars() { # Export all variables export MUNITOR_PIPELINE MUNITOR_ORB_VERSION MUNITOR_IMAGE_NAME MUNITOR_JAVA_VERSION MUNITOR_NODE_VERSION MUNITOR_SERVER_MODULE - export MUNITOR_SONAR_PROJECT_KEY MUNITOR_DOCKER_REGISTRY MUNITOR_CD_REPO MUNITOR_CD_FORMAT + export MUNITOR_SONAR_PROJECT_KEY MUNITOR_DOCKER_REGISTRY MUNITOR_CD_REPO MUNITOR_CD_FORMAT MUNITOR_CD_PATH MUNITOR_CD_PRODUCTION_ONLY export MUNITOR_CD_ENV_DEVELOP MUNITOR_CD_ENV_STAGING MUNITOR_CD_ENV_PROD MUNITOR_CD_ENV_RELEASE export MUNITOR_COVERAGE_MIN MUNITOR_E2E MUNITOR_SBOM MUNITOR_OWASP export MUNITOR_CONTEXT_REGISTRY MUNITOR_CONTEXT_GITHUB MUNITOR_CONTEXT_SONAR MUNITOR_CONTEXT_NVD @@ -321,13 +329,13 @@ extract_munitor_vars() { export MUNITOR_CI_EMAIL MUNITOR_CI_NAME MUNITOR_NPM_DEFAULT_SCOPE MUNITOR_ORB_SLUG 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 + export MUNITOR_SONAR MUNITOR_CD MUNITOR_CD_NON_PROD 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_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} ${MUNITOR_SERVER_MODULE} ${MUNITOR_COVERAGE_SUMMARY_PATH}' + 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_PATH} ${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} ${MUNITOR_SERVER_MODULE} ${MUNITOR_COVERAGE_SUMMARY_PATH}' } MUNITOR_EXTRACT_EOF @@ -557,13 +565,14 @@ workflows: only: - /release\/.*/ ##ENDIF_SBOM## - ##IF_CD## + ##IF_CD_NON_PROD## - munitor/update_cd_repo: name: update-cd-repo cd_repo: ${MUNITOR_CD_REPO} environment: ${MUNITOR_CD_ENV_RELEASE} cd_format: ${MUNITOR_CD_FORMAT} cd_image_name: ${MUNITOR_DOCKER_REGISTRY}/${MUNITOR_IMAGE_NAME} + cd_path: ${MUNITOR_CD_PATH} ##IF_SUPPLEMENTAL## supplemental_images: '${MUNITOR_SUPPLEMENTAL_IMAGES_JSON}' ##ENDIF_SUPPLEMENTAL## @@ -577,7 +586,7 @@ workflows: branches: only: - /release\/.*/ - ##ENDIF_CD## + ##ENDIF_CD_NON_PROD## ##IF_GITHUB_RELEASE## - munitor/github_release: name: github-release @@ -627,6 +636,7 @@ workflows: environment: ${MUNITOR_CD_ENV_PROD} cd_format: ${MUNITOR_CD_FORMAT} cd_image_name: ${MUNITOR_DOCKER_REGISTRY}/${MUNITOR_IMAGE_NAME} + cd_path: ${MUNITOR_CD_PATH} ##IF_SUPPLEMENTAL## supplemental_images: '${MUNITOR_SUPPLEMENTAL_IMAGES_JSON}' ##ENDIF_SUPPLEMENTAL## @@ -879,13 +889,14 @@ workflows: only: - /release\/.*/ ##ENDIF_SBOM## - ##IF_CD## + ##IF_CD_NON_PROD## - munitor/update_cd_repo: name: update-cd-repo cd_repo: ${MUNITOR_CD_REPO} environment: ${MUNITOR_CD_ENV_RELEASE} cd_format: ${MUNITOR_CD_FORMAT} cd_image_name: ${MUNITOR_DOCKER_REGISTRY}/${MUNITOR_IMAGE_NAME} + cd_path: ${MUNITOR_CD_PATH} ##IF_SUPPLEMENTAL## supplemental_images: '${MUNITOR_SUPPLEMENTAL_IMAGES_JSON}' ##ENDIF_SUPPLEMENTAL## @@ -899,7 +910,7 @@ workflows: branches: only: - /release\/.*/ - ##ENDIF_CD## + ##ENDIF_CD_NON_PROD## ##IF_GITHUB_RELEASE## - munitor/github_release: name: github-release @@ -949,6 +960,7 @@ workflows: environment: ${MUNITOR_CD_ENV_PROD} cd_format: ${MUNITOR_CD_FORMAT} cd_image_name: ${MUNITOR_DOCKER_REGISTRY}/${MUNITOR_IMAGE_NAME} + cd_path: ${MUNITOR_CD_PATH} ##IF_SUPPLEMENTAL## supplemental_images: '${MUNITOR_SUPPLEMENTAL_IMAGES_JSON}' ##ENDIF_SUPPLEMENTAL## @@ -1229,13 +1241,14 @@ workflows: only: - /release\/.*/ ##ENDIF_SBOM## - ##IF_CD## + ##IF_CD_NON_PROD## - munitor/update_cd_repo: name: update-cd-repo cd_repo: ${MUNITOR_CD_REPO} environment: ${MUNITOR_CD_ENV_RELEASE} cd_format: ${MUNITOR_CD_FORMAT} cd_image_name: ${MUNITOR_DOCKER_REGISTRY}/${MUNITOR_IMAGE_NAME} + cd_path: ${MUNITOR_CD_PATH} ##IF_SUPPLEMENTAL## supplemental_images: '${MUNITOR_SUPPLEMENTAL_IMAGES_JSON}' ##ENDIF_SUPPLEMENTAL## @@ -1249,7 +1262,7 @@ workflows: branches: only: - /release\/.*/ - ##ENDIF_CD## + ##ENDIF_CD_NON_PROD## ##IF_GITHUB_RELEASE## - munitor/github_release: name: github-release @@ -1312,6 +1325,7 @@ workflows: environment: ${MUNITOR_CD_ENV_PROD} cd_format: ${MUNITOR_CD_FORMAT} cd_image_name: ${MUNITOR_DOCKER_REGISTRY}/${MUNITOR_IMAGE_NAME} + cd_path: ${MUNITOR_CD_PATH} ##IF_SUPPLEMENTAL## supplemental_images: '${MUNITOR_SUPPLEMENTAL_IMAGES_JSON}' ##ENDIF_SUPPLEMENTAL## @@ -1592,13 +1606,14 @@ workflows: only: - /release\/.*/ ##ENDIF_SBOM## - ##IF_CD## + ##IF_CD_NON_PROD## - munitor/update_cd_repo: name: update-cd-repo cd_repo: ${MUNITOR_CD_REPO} environment: ${MUNITOR_CD_ENV_RELEASE} cd_format: ${MUNITOR_CD_FORMAT} cd_image_name: ${MUNITOR_DOCKER_REGISTRY}/${MUNITOR_IMAGE_NAME} + cd_path: ${MUNITOR_CD_PATH} ##IF_SUPPLEMENTAL## supplemental_images: '${MUNITOR_SUPPLEMENTAL_IMAGES_JSON}' ##ENDIF_SUPPLEMENTAL## @@ -1612,7 +1627,7 @@ workflows: branches: only: - /release\/.*/ - ##ENDIF_CD## + ##ENDIF_CD_NON_PROD## ##IF_GITHUB_RELEASE## - munitor/github_release: name: github-release @@ -1675,6 +1690,7 @@ workflows: environment: ${MUNITOR_CD_ENV_PROD} cd_format: ${MUNITOR_CD_FORMAT} cd_image_name: ${MUNITOR_DOCKER_REGISTRY}/${MUNITOR_IMAGE_NAME} + cd_path: ${MUNITOR_CD_PATH} ##IF_SUPPLEMENTAL## supplemental_images: '${MUNITOR_SUPPLEMENTAL_IMAGES_JSON}' ##ENDIF_SUPPLEMENTAL## @@ -2598,13 +2614,14 @@ cat > /tmp/munitor/templates/partials/java-webapp-deploy.yml.tpl << 'MUNITOR_PAR branches: only: __BRANCH_FILTER__ ##ENDIF_SBOM## - ##IF_CD## + ##IF_CD_NON_PROD## - munitor/update_cd_repo: name: update-cd-repo cd_repo: ${MUNITOR_CD_REPO} environment: __CD_ENVIRONMENT__ cd_format: ${MUNITOR_CD_FORMAT} cd_image_name: ${MUNITOR_DOCKER_REGISTRY}/${MUNITOR_IMAGE_NAME} + cd_path: ${MUNITOR_CD_PATH} ##IF_SUPPLEMENTAL## supplemental_images: '${MUNITOR_SUPPLEMENTAL_IMAGES_JSON}' ##ENDIF_SUPPLEMENTAL## @@ -2617,7 +2634,7 @@ cat > /tmp/munitor/templates/partials/java-webapp-deploy.yml.tpl << 'MUNITOR_PAR filters: branches: only: __BRANCH_FILTER__ - ##ENDIF_CD## + ##ENDIF_CD_NON_PROD## MUNITOR_PARTIAL_EOF cat > /tmp/munitor/templates/partials/gradle-webapp-deploy.yml.tpl << 'MUNITOR_PARTIAL_EOF' @@ -2747,13 +2764,14 @@ cat > /tmp/munitor/templates/partials/gradle-webapp-deploy.yml.tpl << 'MUNITOR_P branches: only: __BRANCH_FILTER__ ##ENDIF_SBOM## - ##IF_CD## + ##IF_CD_NON_PROD## - munitor/update_cd_repo: name: update-cd-repo cd_repo: ${MUNITOR_CD_REPO} environment: __CD_ENVIRONMENT__ cd_format: ${MUNITOR_CD_FORMAT} cd_image_name: ${MUNITOR_DOCKER_REGISTRY}/${MUNITOR_IMAGE_NAME} + cd_path: ${MUNITOR_CD_PATH} ##IF_SUPPLEMENTAL## supplemental_images: '${MUNITOR_SUPPLEMENTAL_IMAGES_JSON}' ##ENDIF_SUPPLEMENTAL## @@ -2766,7 +2784,7 @@ cat > /tmp/munitor/templates/partials/gradle-webapp-deploy.yml.tpl << 'MUNITOR_P filters: branches: only: __BRANCH_FILTER__ - ##ENDIF_CD## + ##ENDIF_CD_NON_PROD## MUNITOR_PARTIAL_EOF cat > /tmp/munitor/templates/partials/node-api-deploy.yml.tpl << 'MUNITOR_PARTIAL_EOF' @@ -2909,13 +2927,14 @@ cat > /tmp/munitor/templates/partials/node-api-deploy.yml.tpl << 'MUNITOR_PARTIA branches: only: __BRANCH_FILTER__ ##ENDIF_SBOM## - ##IF_CD## + ##IF_CD_NON_PROD## - munitor/update_cd_repo: name: update-cd-repo cd_repo: ${MUNITOR_CD_REPO} environment: __CD_ENVIRONMENT__ cd_format: ${MUNITOR_CD_FORMAT} cd_image_name: ${MUNITOR_DOCKER_REGISTRY}/${MUNITOR_IMAGE_NAME} + cd_path: ${MUNITOR_CD_PATH} ##IF_SUPPLEMENTAL## supplemental_images: '${MUNITOR_SUPPLEMENTAL_IMAGES_JSON}' ##ENDIF_SUPPLEMENTAL## @@ -2928,7 +2947,7 @@ cat > /tmp/munitor/templates/partials/node-api-deploy.yml.tpl << 'MUNITOR_PARTIA filters: branches: only: __BRANCH_FILTER__ - ##ENDIF_CD## + ##ENDIF_CD_NON_PROD## MUNITOR_PARTIAL_EOF cat > /tmp/munitor/templates/partials/node-webapp-deploy.yml.tpl << 'MUNITOR_PARTIAL_EOF' @@ -3071,13 +3090,14 @@ cat > /tmp/munitor/templates/partials/node-webapp-deploy.yml.tpl << 'MUNITOR_PAR branches: only: __BRANCH_FILTER__ ##ENDIF_SBOM## - ##IF_CD## + ##IF_CD_NON_PROD## - munitor/update_cd_repo: name: update-cd-repo cd_repo: ${MUNITOR_CD_REPO} environment: __CD_ENVIRONMENT__ cd_format: ${MUNITOR_CD_FORMAT} cd_image_name: ${MUNITOR_DOCKER_REGISTRY}/${MUNITOR_IMAGE_NAME} + cd_path: ${MUNITOR_CD_PATH} ##IF_SUPPLEMENTAL## supplemental_images: '${MUNITOR_SUPPLEMENTAL_IMAGES_JSON}' ##ENDIF_SUPPLEMENTAL## @@ -3090,7 +3110,7 @@ cat > /tmp/munitor/templates/partials/node-webapp-deploy.yml.tpl << 'MUNITOR_PAR filters: branches: only: __BRANCH_FILTER__ - ##ENDIF_CD## + ##ENDIF_CD_NON_PROD## MUNITOR_PARTIAL_EOF echo "Munitor helpers staged to /tmp/munitor/" @@ -3102,7 +3122,7 @@ echo "Munitor helpers staged to /tmp/munitor/" set -euo pipefail CONFIG_FILE="${MUNITOR_CONFIG:-.munitor.yml}" -OUTPUT_FILE="/tmp/generated-config.yml" +OUTPUT_FILE="${MUNITOR_OUTPUT_FILE:-/tmp/generated-config.yml}" # When run via CircleCI << include() >>, BASH_SOURCE is empty. # Fall back to MUNITOR_SCRIPT_DIR set by the command YAML. @@ -3301,7 +3321,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 SUPPLEMENTAL; do + for flag in E2E SBOM SONAR NPM_AUTH SERVICES TEST_SETUP CUSTOM_TEST COVERAGE_CMD GITHUB_RELEASE SAST CD CD_NON_PROD OWASP NVD SUPPLEMENTAL; do local var_name="MUNITOR_${flag}" local value="${!var_name:-false}" local flag_file diff --git a/src/scripts/packed_generate_dockerfile.sh b/src/scripts/packed_generate_dockerfile.sh index d4b49ca..abb2bec 100755 --- a/src/scripts/packed_generate_dockerfile.sh +++ b/src/scripts/packed_generate_dockerfile.sh @@ -135,6 +135,8 @@ extract_munitor_vars() { fi MUNITOR_CD_REPO=$(yq '.cd.repo // ""' "${config_file}") MUNITOR_CD_FORMAT=$(yq '.cd.format // "helm"' "${config_file}") + MUNITOR_CD_PATH=$(yq '.cd.path // ""' "${config_file}") + MUNITOR_CD_PRODUCTION_ONLY=$(yq '.cd.production_only // false' "${config_file}") MUNITOR_CD_ENV_DEVELOP=$(yq '.cd.env.develop // "develop"' "${config_file}") MUNITOR_CD_ENV_STAGING=$(yq '.cd.env.staging // "staging"' "${config_file}") MUNITOR_CD_ENV_PROD=$(yq '.cd.env.prod // "prod"' "${config_file}") @@ -291,8 +293,14 @@ extract_munitor_vars() { if [[ -n "${MUNITOR_CD_REPO}" ]]; then MUNITOR_CD="true" + if [[ "${MUNITOR_CD_PRODUCTION_ONLY}" == "true" ]]; then + MUNITOR_CD_NON_PROD="false" + else + MUNITOR_CD_NON_PROD="true" + fi else MUNITOR_CD="false" + MUNITOR_CD_NON_PROD="false" fi if [[ -n "${MUNITOR_CONTEXT_NVD}" ]]; then @@ -303,7 +311,7 @@ extract_munitor_vars() { # Export all variables export MUNITOR_PIPELINE MUNITOR_ORB_VERSION MUNITOR_IMAGE_NAME MUNITOR_JAVA_VERSION MUNITOR_NODE_VERSION MUNITOR_SERVER_MODULE - export MUNITOR_SONAR_PROJECT_KEY MUNITOR_DOCKER_REGISTRY MUNITOR_CD_REPO MUNITOR_CD_FORMAT + export MUNITOR_SONAR_PROJECT_KEY MUNITOR_DOCKER_REGISTRY MUNITOR_CD_REPO MUNITOR_CD_FORMAT MUNITOR_CD_PATH MUNITOR_CD_PRODUCTION_ONLY export MUNITOR_CD_ENV_DEVELOP MUNITOR_CD_ENV_STAGING MUNITOR_CD_ENV_PROD MUNITOR_CD_ENV_RELEASE export MUNITOR_COVERAGE_MIN MUNITOR_E2E MUNITOR_SBOM MUNITOR_OWASP export MUNITOR_CONTEXT_REGISTRY MUNITOR_CONTEXT_GITHUB MUNITOR_CONTEXT_SONAR MUNITOR_CONTEXT_NVD @@ -321,13 +329,13 @@ extract_munitor_vars() { export MUNITOR_CI_EMAIL MUNITOR_CI_NAME MUNITOR_NPM_DEFAULT_SCOPE MUNITOR_ORB_SLUG 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 + export MUNITOR_SONAR MUNITOR_CD MUNITOR_CD_NON_PROD 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_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} ${MUNITOR_SERVER_MODULE} ${MUNITOR_COVERAGE_SUMMARY_PATH}' + 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_PATH} ${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} ${MUNITOR_SERVER_MODULE} ${MUNITOR_COVERAGE_SUMMARY_PATH}' } MUNITOR_EXTRACT_EOF diff --git a/src/scripts/templates/gradle-webapp.yml.tpl b/src/scripts/templates/gradle-webapp.yml.tpl index f7d4e09..18e2f8c 100644 --- a/src/scripts/templates/gradle-webapp.yml.tpl +++ b/src/scripts/templates/gradle-webapp.yml.tpl @@ -223,13 +223,14 @@ workflows: only: - /release\/.*/ ##ENDIF_SBOM## - ##IF_CD## + ##IF_CD_NON_PROD## - munitor/update_cd_repo: name: update-cd-repo cd_repo: ${MUNITOR_CD_REPO} environment: ${MUNITOR_CD_ENV_RELEASE} cd_format: ${MUNITOR_CD_FORMAT} cd_image_name: ${MUNITOR_DOCKER_REGISTRY}/${MUNITOR_IMAGE_NAME} + cd_path: ${MUNITOR_CD_PATH} ##IF_SUPPLEMENTAL## supplemental_images: '${MUNITOR_SUPPLEMENTAL_IMAGES_JSON}' ##ENDIF_SUPPLEMENTAL## @@ -243,7 +244,7 @@ workflows: branches: only: - /release\/.*/ - ##ENDIF_CD## + ##ENDIF_CD_NON_PROD## ##IF_GITHUB_RELEASE## - munitor/github_release: name: github-release @@ -293,6 +294,7 @@ workflows: environment: ${MUNITOR_CD_ENV_PROD} cd_format: ${MUNITOR_CD_FORMAT} cd_image_name: ${MUNITOR_DOCKER_REGISTRY}/${MUNITOR_IMAGE_NAME} + cd_path: ${MUNITOR_CD_PATH} ##IF_SUPPLEMENTAL## supplemental_images: '${MUNITOR_SUPPLEMENTAL_IMAGES_JSON}' ##ENDIF_SUPPLEMENTAL## diff --git a/src/scripts/templates/java-webapp.yml.tpl b/src/scripts/templates/java-webapp.yml.tpl index 40cf007..468a846 100644 --- a/src/scripts/templates/java-webapp.yml.tpl +++ b/src/scripts/templates/java-webapp.yml.tpl @@ -223,13 +223,14 @@ workflows: only: - /release\/.*/ ##ENDIF_SBOM## - ##IF_CD## + ##IF_CD_NON_PROD## - munitor/update_cd_repo: name: update-cd-repo cd_repo: ${MUNITOR_CD_REPO} environment: ${MUNITOR_CD_ENV_RELEASE} cd_format: ${MUNITOR_CD_FORMAT} cd_image_name: ${MUNITOR_DOCKER_REGISTRY}/${MUNITOR_IMAGE_NAME} + cd_path: ${MUNITOR_CD_PATH} ##IF_SUPPLEMENTAL## supplemental_images: '${MUNITOR_SUPPLEMENTAL_IMAGES_JSON}' ##ENDIF_SUPPLEMENTAL## @@ -243,7 +244,7 @@ workflows: branches: only: - /release\/.*/ - ##ENDIF_CD## + ##ENDIF_CD_NON_PROD## ##IF_GITHUB_RELEASE## - munitor/github_release: name: github-release @@ -293,6 +294,7 @@ workflows: environment: ${MUNITOR_CD_ENV_PROD} cd_format: ${MUNITOR_CD_FORMAT} cd_image_name: ${MUNITOR_DOCKER_REGISTRY}/${MUNITOR_IMAGE_NAME} + cd_path: ${MUNITOR_CD_PATH} ##IF_SUPPLEMENTAL## supplemental_images: '${MUNITOR_SUPPLEMENTAL_IMAGES_JSON}' ##ENDIF_SUPPLEMENTAL## diff --git a/src/scripts/templates/node-api.yml.tpl b/src/scripts/templates/node-api.yml.tpl index 8a4ee5d..08f129a 100644 --- a/src/scripts/templates/node-api.yml.tpl +++ b/src/scripts/templates/node-api.yml.tpl @@ -251,13 +251,14 @@ workflows: only: - /release\/.*/ ##ENDIF_SBOM## - ##IF_CD## + ##IF_CD_NON_PROD## - munitor/update_cd_repo: name: update-cd-repo cd_repo: ${MUNITOR_CD_REPO} environment: ${MUNITOR_CD_ENV_RELEASE} cd_format: ${MUNITOR_CD_FORMAT} cd_image_name: ${MUNITOR_DOCKER_REGISTRY}/${MUNITOR_IMAGE_NAME} + cd_path: ${MUNITOR_CD_PATH} ##IF_SUPPLEMENTAL## supplemental_images: '${MUNITOR_SUPPLEMENTAL_IMAGES_JSON}' ##ENDIF_SUPPLEMENTAL## @@ -271,7 +272,7 @@ workflows: branches: only: - /release\/.*/ - ##ENDIF_CD## + ##ENDIF_CD_NON_PROD## ##IF_GITHUB_RELEASE## - munitor/github_release: name: github-release @@ -334,6 +335,7 @@ workflows: environment: ${MUNITOR_CD_ENV_PROD} cd_format: ${MUNITOR_CD_FORMAT} cd_image_name: ${MUNITOR_DOCKER_REGISTRY}/${MUNITOR_IMAGE_NAME} + cd_path: ${MUNITOR_CD_PATH} ##IF_SUPPLEMENTAL## supplemental_images: '${MUNITOR_SUPPLEMENTAL_IMAGES_JSON}' ##ENDIF_SUPPLEMENTAL## diff --git a/src/scripts/templates/node-webapp.yml.tpl b/src/scripts/templates/node-webapp.yml.tpl index ea30e15..5a63fc0 100644 --- a/src/scripts/templates/node-webapp.yml.tpl +++ b/src/scripts/templates/node-webapp.yml.tpl @@ -251,13 +251,14 @@ workflows: only: - /release\/.*/ ##ENDIF_SBOM## - ##IF_CD## + ##IF_CD_NON_PROD## - munitor/update_cd_repo: name: update-cd-repo cd_repo: ${MUNITOR_CD_REPO} environment: ${MUNITOR_CD_ENV_RELEASE} cd_format: ${MUNITOR_CD_FORMAT} cd_image_name: ${MUNITOR_DOCKER_REGISTRY}/${MUNITOR_IMAGE_NAME} + cd_path: ${MUNITOR_CD_PATH} ##IF_SUPPLEMENTAL## supplemental_images: '${MUNITOR_SUPPLEMENTAL_IMAGES_JSON}' ##ENDIF_SUPPLEMENTAL## @@ -271,7 +272,7 @@ workflows: branches: only: - /release\/.*/ - ##ENDIF_CD## + ##ENDIF_CD_NON_PROD## ##IF_GITHUB_RELEASE## - munitor/github_release: name: github-release @@ -334,6 +335,7 @@ workflows: environment: ${MUNITOR_CD_ENV_PROD} cd_format: ${MUNITOR_CD_FORMAT} cd_image_name: ${MUNITOR_DOCKER_REGISTRY}/${MUNITOR_IMAGE_NAME} + cd_path: ${MUNITOR_CD_PATH} ##IF_SUPPLEMENTAL## supplemental_images: '${MUNITOR_SUPPLEMENTAL_IMAGES_JSON}' ##ENDIF_SUPPLEMENTAL## diff --git a/src/scripts/templates/partials/gradle-webapp-deploy.yml.tpl b/src/scripts/templates/partials/gradle-webapp-deploy.yml.tpl index 3949cd0..23d6894 100644 --- a/src/scripts/templates/partials/gradle-webapp-deploy.yml.tpl +++ b/src/scripts/templates/partials/gradle-webapp-deploy.yml.tpl @@ -124,13 +124,14 @@ branches: only: __BRANCH_FILTER__ ##ENDIF_SBOM## - ##IF_CD## + ##IF_CD_NON_PROD## - munitor/update_cd_repo: name: update-cd-repo cd_repo: ${MUNITOR_CD_REPO} environment: __CD_ENVIRONMENT__ cd_format: ${MUNITOR_CD_FORMAT} cd_image_name: ${MUNITOR_DOCKER_REGISTRY}/${MUNITOR_IMAGE_NAME} + cd_path: ${MUNITOR_CD_PATH} ##IF_SUPPLEMENTAL## supplemental_images: '${MUNITOR_SUPPLEMENTAL_IMAGES_JSON}' ##ENDIF_SUPPLEMENTAL## @@ -143,4 +144,4 @@ filters: branches: only: __BRANCH_FILTER__ - ##ENDIF_CD## + ##ENDIF_CD_NON_PROD## diff --git a/src/scripts/templates/partials/java-webapp-deploy.yml.tpl b/src/scripts/templates/partials/java-webapp-deploy.yml.tpl index eb8205c..7a0c15f 100644 --- a/src/scripts/templates/partials/java-webapp-deploy.yml.tpl +++ b/src/scripts/templates/partials/java-webapp-deploy.yml.tpl @@ -124,13 +124,14 @@ branches: only: __BRANCH_FILTER__ ##ENDIF_SBOM## - ##IF_CD## + ##IF_CD_NON_PROD## - munitor/update_cd_repo: name: update-cd-repo cd_repo: ${MUNITOR_CD_REPO} environment: __CD_ENVIRONMENT__ cd_format: ${MUNITOR_CD_FORMAT} cd_image_name: ${MUNITOR_DOCKER_REGISTRY}/${MUNITOR_IMAGE_NAME} + cd_path: ${MUNITOR_CD_PATH} ##IF_SUPPLEMENTAL## supplemental_images: '${MUNITOR_SUPPLEMENTAL_IMAGES_JSON}' ##ENDIF_SUPPLEMENTAL## @@ -143,4 +144,4 @@ filters: branches: only: __BRANCH_FILTER__ - ##ENDIF_CD## + ##ENDIF_CD_NON_PROD## diff --git a/src/scripts/templates/partials/node-api-deploy.yml.tpl b/src/scripts/templates/partials/node-api-deploy.yml.tpl index 6a62c6a..bf41481 100644 --- a/src/scripts/templates/partials/node-api-deploy.yml.tpl +++ b/src/scripts/templates/partials/node-api-deploy.yml.tpl @@ -137,13 +137,14 @@ branches: only: __BRANCH_FILTER__ ##ENDIF_SBOM## - ##IF_CD## + ##IF_CD_NON_PROD## - munitor/update_cd_repo: name: update-cd-repo cd_repo: ${MUNITOR_CD_REPO} environment: __CD_ENVIRONMENT__ cd_format: ${MUNITOR_CD_FORMAT} cd_image_name: ${MUNITOR_DOCKER_REGISTRY}/${MUNITOR_IMAGE_NAME} + cd_path: ${MUNITOR_CD_PATH} ##IF_SUPPLEMENTAL## supplemental_images: '${MUNITOR_SUPPLEMENTAL_IMAGES_JSON}' ##ENDIF_SUPPLEMENTAL## @@ -156,4 +157,4 @@ filters: branches: only: __BRANCH_FILTER__ - ##ENDIF_CD## + ##ENDIF_CD_NON_PROD## diff --git a/src/scripts/templates/partials/node-webapp-deploy.yml.tpl b/src/scripts/templates/partials/node-webapp-deploy.yml.tpl index 6a62c6a..bf41481 100644 --- a/src/scripts/templates/partials/node-webapp-deploy.yml.tpl +++ b/src/scripts/templates/partials/node-webapp-deploy.yml.tpl @@ -137,13 +137,14 @@ branches: only: __BRANCH_FILTER__ ##ENDIF_SBOM## - ##IF_CD## + ##IF_CD_NON_PROD## - munitor/update_cd_repo: name: update-cd-repo cd_repo: ${MUNITOR_CD_REPO} environment: __CD_ENVIRONMENT__ cd_format: ${MUNITOR_CD_FORMAT} cd_image_name: ${MUNITOR_DOCKER_REGISTRY}/${MUNITOR_IMAGE_NAME} + cd_path: ${MUNITOR_CD_PATH} ##IF_SUPPLEMENTAL## supplemental_images: '${MUNITOR_SUPPLEMENTAL_IMAGES_JSON}' ##ENDIF_SUPPLEMENTAL## @@ -156,4 +157,4 @@ filters: branches: only: __BRANCH_FILTER__ - ##ENDIF_CD## + ##ENDIF_CD_NON_PROD## diff --git a/src/scripts/update_cd_repo.sh b/src/scripts/update_cd_repo.sh index 6074a00..e9fac8d 100755 --- a/src/scripts/update_cd_repo.sh +++ b/src/scripts/update_cd_repo.sh @@ -18,6 +18,7 @@ VERSION="${PROJECT_VERSION:?PROJECT_VERSION not set}" ENVIRONMENT="${CD_ENVIRONMENT:-}" FORMAT="${CD_FORMAT:-helm}" IMAGE_NAME="${CD_IMAGE_NAME:-}" +CONFIGURED_PATH="${CD_PATH:-}" VALUES="${VALUES_FILE:-values.yaml}" KEY="${IMAGE_KEY:-image.tag}" @@ -49,8 +50,15 @@ if [[ "${FORMAT}" == "kustomize" ]]; then exit 1 fi - # Find kustomization.yaml in overlays// - if [[ -n "${ENVIRONMENT}" ]]; then + # Explicit paths support consolidated GitOps repositories. Existing dedicated + # repositories retain the overlays/ convention by default. + if [[ -n "${CONFIGURED_PATH}" ]]; then + if [[ "${CONFIGURED_PATH}" == /* || "${CONFIGURED_PATH}" == *".."* || "${CONFIGURED_PATH}" != *kustomization.yaml ]]; then + echo "ERROR: cd.path must be a relative path to a kustomization.yaml file without '..'." + exit 1 + fi + KUST_FILE="${CONFIGURED_PATH}" + elif [[ -n "${ENVIRONMENT}" ]]; then KUST_FILE="overlays/${ENVIRONMENT}/kustomization.yaml" else KUST_FILE="kustomization.yaml" @@ -58,12 +66,18 @@ if [[ "${FORMAT}" == "kustomize" ]]; then if [[ ! -f "${KUST_FILE}" ]]; then echo "ERROR: Kustomize file '${KUST_FILE}' not found in CD repo." - echo "Available overlays:" - ls overlays/ 2>/dev/null || echo " (no overlays directory)" + if [[ -z "${CONFIGURED_PATH}" ]]; then + echo "Available overlays:" + ls overlays/ 2>/dev/null || echo " (no overlays directory)" + fi exit 1 fi echo "Updating ${KUST_FILE}: ${IMAGE_NAME} -> ${VERSION}" + if ! yq -e ".images[] | select(.name == \"${IMAGE_NAME}\")" "${KUST_FILE}" >/dev/null; then + echo "ERROR: Image '${IMAGE_NAME}' is not declared in ${KUST_FILE}." + exit 1 + fi yq -i "(.images[] | select(.name == \"${IMAGE_NAME}\")).newTag = \"${VERSION}\"" "${KUST_FILE}" yq -i "del((.images[] | select(.name == \"${IMAGE_NAME}\")).digest)" "${KUST_FILE}" git add "${KUST_FILE}" @@ -137,7 +151,20 @@ if git diff --cached --quiet; then exit 0 fi -git commit -m "chore: update image tag to ${VERSION}" -git push origin HEAD +git commit -m "chore: update ${IMAGE_NAME:-image} to ${VERSION}" -echo "CD repo updated successfully." +# Independent pipelines may update a shared GitOps repository concurrently. +for attempt in 1 2 3; do + if git push origin HEAD; then + echo "CD repo updated successfully." + exit 0 + fi + + if [[ "${attempt}" == "3" ]]; then + echo "ERROR: Could not push the GitOps update after ${attempt} attempts." + exit 1 + fi + + echo "Push raced with another GitOps update; rebasing before retry ${attempt}/3." + git pull --rebase origin "$(git branch --show-current)" +done diff --git a/tests/fixtures/node-webapp-consolidated.munitor.yml b/tests/fixtures/node-webapp-consolidated.munitor.yml new file mode 100644 index 0000000..622714f --- /dev/null +++ b/tests/fixtures/node-webapp-consolidated.munitor.yml @@ -0,0 +1,18 @@ +pipeline: node-webapp +orb_version: dev:snapshot +image_name: investinginchester +node_version: "22" + +docker: + registry: ghcr.io/koftwentytwo + use_repo_dockerfile: true + +cd: + repo: KofTwentyTwo/cluster-gitops + format: kustomize + production_only: true + path: tenants/investinginchester/website/kustomization.yaml + +contexts: + registry: ghcr + github: github diff --git a/tests/test_extract_munitor_vars.sh b/tests/test_extract_munitor_vars.sh index 74ae907..4adac57 100644 --- a/tests/test_extract_munitor_vars.sh +++ b/tests/test_extract_munitor_vars.sh @@ -137,6 +137,19 @@ extract_munitor_vars "${FIXTURES_DIR}/java-webapp-sast-warn.munitor.yml" assert_eq "sast object form" "true" "${MUNITOR_SAST}" assert_eq "sast fail_on_findings (object false)" "false" "${MUNITOR_SAST_FAIL_ON_FINDINGS}" +# -------------------------------------------------------------------------- +# node-webapp consolidated GitOps fixture +# -------------------------------------------------------------------------- +echo "" +echo "=== extract_munitor_vars: consolidated GitOps fixture ===" +extract_munitor_vars "${FIXTURES_DIR}/node-webapp-consolidated.munitor.yml" + +assert_eq "consolidated cd repo" "KofTwentyTwo/cluster-gitops" "${MUNITOR_CD_REPO}" +assert_eq "consolidated cd format" "kustomize" "${MUNITOR_CD_FORMAT}" +assert_eq "consolidated cd path" "tenants/investinginchester/website/kustomization.yaml" "${MUNITOR_CD_PATH}" +assert_eq "production-only cd" "true" "${MUNITOR_CD_PRODUCTION_ONLY}" +assert_eq "non-production cd disabled" "false" "${MUNITOR_CD_NON_PROD}" + # -------------------------------------------------------------------------- # node.framework defaults # -------------------------------------------------------------------------- diff --git a/tests/test_generate_config.sh b/tests/test_generate_config.sh index 968e7c2..65003f3 100755 --- a/tests/test_generate_config.sh +++ b/tests/test_generate_config.sh @@ -8,6 +8,8 @@ PASS=0 FAIL=0 GENERATE_SCRIPT="${PROJECT_DIR}/src/scripts/generate_config.sh" +GENERATED_CONFIG=$(mktemp) +trap 'rm -f "${GENERATED_CONFIG}"' EXIT # -------------------------------------------------------------------------- # Helper: render a fixture by calling the real generate_config.sh script @@ -17,8 +19,9 @@ render_fixture() { local fixture="$1" # Run the real script; capture stderr for diagnostics, return generated YAML - MUNITOR_CONFIG="${fixture}" bash "${GENERATE_SCRIPT}" >/dev/null 2>&1 - cat /tmp/generated-config.yml + MUNITOR_CONFIG="${fixture}" MUNITOR_OUTPUT_FILE="${GENERATED_CONFIG}" \ + bash "${GENERATE_SCRIPT}" >/dev/null 2>&1 + cat "${GENERATED_CONFIG}" } run_test() { @@ -36,7 +39,7 @@ run_test() { return } - if echo "${output}" | grep -q "${expected_pattern}"; then + if grep -q "${expected_pattern}" <<< "${output}"; then echo "PASS" PASS=$((PASS + 1)) else @@ -61,7 +64,7 @@ run_negative_test() { return } - if echo "${output}" | grep -q "${forbidden_pattern}"; then + if grep -q "${forbidden_pattern}" <<< "${output}"; then echo "FAIL (found forbidden pattern '${forbidden_pattern}')" FAIL=$((FAIL + 1)) else @@ -103,7 +106,7 @@ run_context_test() { return fi - if echo "${block}" | grep -q "${expected_pattern}"; then + if grep -q "${expected_pattern}" <<< "${block}"; then echo "PASS" PASS=$((PASS + 1)) else @@ -143,7 +146,7 @@ run_negative_context_test() { return fi - if echo "${block}" | grep -q "${forbidden_pattern}"; then + if grep -q "${forbidden_pattern}" <<< "${block}"; then echo "FAIL (found forbidden '${forbidden_pattern}' within block)" FAIL=$((FAIL + 1)) else @@ -451,6 +454,24 @@ run_context_test "node-webapp: docker-build-push includes health_path" \ "context:" \ "health_path: /api/health" +run_context_test "node-webapp consolidated: production targets explicit GitOps path" \ + "${FIXTURES_DIR}/node-webapp-consolidated.munitor.yml" \ + "production:" \ + "github-release:" \ + "cd_path: tenants/investinginchester/website/kustomization.yaml" + +run_negative_context_test "node-webapp consolidated: develop does not update production" \ + "${FIXTURES_DIR}/node-webapp-consolidated.munitor.yml" \ + "develop:" \ + "staging:" \ + "update-cd-repo" + +run_negative_context_test "node-webapp consolidated: release does not update production" \ + "${FIXTURES_DIR}/node-webapp-consolidated.munitor.yml" \ + "release-candidate:" \ + "production:" \ + "update-cd-repo" + # Test node-webapp-minimal: e2e/sbom/sonar should be excluded run_test "node-webapp-minimal: renders node 22" \ "${FIXTURES_DIR}/node-webapp-minimal.munitor.yml" \ diff --git a/tests/test_scripts.sh b/tests/test_scripts.sh index 14b8b50..3ce611c 100755 --- a/tests/test_scripts.sh +++ b/tests/test_scripts.sh @@ -320,6 +320,22 @@ else fail "should resolve environments//values.yaml" fi +echo -n " TEST: supports a validated explicit Kustomize path... " +if grep -q 'CONFIGURED_PATH="${CD_PATH:-}"' "${SRC_SCRIPTS}/update_cd_repo.sh" && + grep -q 'cd.path must be a relative path' "${SRC_SCRIPTS}/update_cd_repo.sh"; then + pass +else + fail "should support and validate an explicit Kustomize path" +fi + +echo -n " TEST: retries concurrent shared-repository pushes... " +if grep -q 'for attempt in 1 2 3' "${SRC_SCRIPTS}/update_cd_repo.sh" && + grep -q 'git pull --rebase' "${SRC_SCRIPTS}/update_cd_repo.sh"; then + pass +else + fail "should rebase and retry shared-repository push races" +fi + echo -n " TEST: deletes digest field when setting newTag (kustomize)... " if grep -q 'del((.images\[\] | select(.name == \\"${IMAGE_NAME}\\")).digest)' "${SRC_SCRIPTS}/update_cd_repo.sh"; then pass -- 2.54.0