Skip to content
KofTwentyTwoPublic

About

"fortifier" or "one who builds defenses," from munire (to fortify, secure).

Topics

Resources

Code of conduct

Contributing

Security policy

Stars

0 stars

Watchers

0 watching

Forks

Munitor

Latin: munitor (fortifier, protector) -- KofTwentyTwo's unified CircleCI orb for building, testing, and deploying all repositories. Pipeline changes happen in one place instead of 80+ repos.

Tier Internal until classified -- listed under Awaiting classification in the KofTwentyTwo standards MAINTAINERS.md; Product-tier requirements are being adopted
Standards Targets KofTwentyTwo standards 1.0.0
Orb kof22/munitor, latest stable 0.3.11
Security SECURITY.md
Contributing CONTRIBUTING.md

How It Works

Munitor uses CircleCI's dynamic configuration to generate your full CI/CD pipeline at runtime. Each repo has a minimal .circleci/config.yml that triggers Munitor, and a .munitor.yml that declares what your project needs. Munitor reads your config, selects the right template, and generates a complete CircleCI workflow.

repo/.munitor.yml  -->  Munitor setup job  -->  Generated pipeline  -->  Build/Test/Deploy

Quick Start

1. Add .circleci/config.yml

This file is identical across all repos:

version: 2.1
setup: true
orbs:
  munitor: kof22/munitor@0.3
workflows:
  setup:
    jobs:
      - munitor/generate_pipeline

2. Add .munitor.yml

Pick your pipeline type and create the config in your repo root. See Pipeline Types below.

3. Ensure branch naming follows GitFlow

Munitor validates branch names and will fail on non-conforming names.

Pattern Purpose
main Production releases
develop Integration
staging Staging environment branch
feature/<name> Feature work
release/<version> Release prep
hotfix/<name> Production fixes

Optional docs-only Java checks

The new java-webapp docs-only path is opt-in and must be adopted after the aggregate required check is published and verified. Do not enable it against an older orb or while individual build jobs remain required:

ci:
  docs_only: true

Only changes confined to root README.md, CHANGELOG.md, CONTRIBUTING.md, or Markdown files under docs/ (including nested directories) qualify. Feature and hotfix branches use their complete diff from the merge base with main; main uses its first-parent diff. Tags, release and other branches, shallow history, failed comparisons, empty diffs, and any uncertain classification keep the full pipeline. The docs path retains secret scanning and emits the aggregate gate; it does not build or deploy an image.

Migration order: publish the gate-capable orb, adopt it with docs-only disabled, and verify the real GitHub context ci/circleci: ci-ready on a consumer run. Then replace that repository's required-check list with the verified aggregate gate, preserving all other branch rules. A single adoption PR may update both orb pins and enable ci.docs_only: those config changes force full CI. Verify the gate and migrate required checks before merging it or opening a docs-only PR. Munitor's own native no-op gate reports ci/circleci: lint-pack/ci-ready. Both features ship in 0.3.11. Verify each consumer's actual successful context before changing its rules; see the adoption record.

Use native Website-Backend Insights, PR timings, and Test Insights to measure results. Compare matching branches/windows and track the docs-checks median separately from full builds. The historical local report C:/Users/james/.cache/ci-insights-report.md ends October 17 and does not establish the speed of this change. No additional reporting job is needed.

Native auto-cancel is enabled for Website-Backend, whose default main is exempt. It remains disabled for Munitor: its default is develop, so main release work would not receive that exemption.

Prerequisites

  1. CircleCI project: Add your repo at https://app.circleci.com
  2. Enable dynamic config: Project Settings > Advanced > "Enable dynamic config using setup workflows"
  3. Allow uncertified orbs: Organization Settings > Security > "Allow uncertified orbs"
  4. CircleCI contexts (Organization Settings > Contexts):
Context Secrets Used By
ghcr GHCR_TOKEN, GHCR_USERNAME Docker push to GitHub Container Registry
github GITHUB_TOKEN Git operations, CD repo updates, SBOM, GitHub Releases
sonarcloud SONAR_TOKEN SonarCloud analysis
nvd NVD_API_KEY OWASP dependency check (Java only, optional)

Adopting in another app

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 (section 7 covers release tooling).

Version. Use kof22/munitor@0.3.11 (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, pinned to kof22/munitor@0.3.11.
  • .munitor.yml: pick a pipeline type. A Java service is java-webapp. KofTwentyTwo's Website-Backend is a working example; a generalized version:
pipeline: java-webapp
orb_version: "0.3.11"
image_name: my-service
java_version: "21"
docker:
  registry: ghcr.io/my-org        # the org default is ghcr.io/KofTwentyTwo -- always set this
cd:
  repo: my-org/my-gitops-repo     # omit to skip GitOps write-back
  format: kustomize               # default is helm (image.tag in values.yaml)
  path: apps/my-service/kustomization.yaml   # optional explicit file in a consolidated repo
  production_only: true           # only main updates the GitOps repo
supplemental_images:              # optional extra images built from the same commit and version
  - name: migrations
    dockerfile: docker/Dockerfile.migrations
    cd:
      image_name: ghcr.io/my-org/my-service-migrations
health:
  path: /health
  port: "8000"
  db: "true"                      # start a PostgreSQL sidecar for the health gate
  migrations: migrations          # run the <image>-migrations image against it first
  smoke_paths: [/health]
sonar:
  project_key: my-org_my-service  # omit to skip SonarCloud
contexts:
  registry: ghcr
  github: github
  sonar: sonarcloud               # required only with sonar.project_key
  nvd: nvd                        # optional
org:                              # organization defaults (see Known limitations)
  ci_email: ci@example.com
  ci_name: My CI
  • A health endpoint that returns HTTP 200 within 30 seconds of container start (see Health Check Requirement).
  • A Dockerfile only for node-webapp (docker.use_repo_dockerfile: true) or for supplemental_images; java-webapp and node-api generate theirs.

2. CircleCI project settings

See Prerequisites: enable dynamic config (setup workflows) and allow uncertified orbs in the consuming organization.

3. Contexts and secrets

CircleCI organization contexts; the context names are set through contexts.*.

Context Variables Needed for
registry (e.g. ghcr) GHCR_USERNAME, GHCR_TOKEN (write:packages) Pushing images and inspecting existing tags; the immutable-tag guard fails closed without registry access
github GITHUB_TOKEN with contents write on the app repository and on the GitOps repository Reserving vX.Y.Z tags on main (required by production), GitHub Releases, GitOps write-back
sonar (optional) SONAR_TOKEN; SonarCloud organization from SONAR_ORG (default KofTwentyTwo) SonarCloud analysis
nvd (optional) NVD_API_KEY OWASP dependency check; owasp: false disables the check

4. Branch model

Branch names are enforced: main, develop, staging, feature/*, release/*, hotfix/*. A merge to main is a production release: it reserves the next vX.Y.Z tag, pushes the image, updates the GitOps repository and creates the GitHub Release. Protect main accordingly.

5. Deployment infrastructure (outside Munitor)

Munitor stops at the GitOps commit. The consumer provides:

  • a GitOps repository whose kustomization.yaml (an images[] entry named <registry>/<image_name>) or Helm values.yaml (image.tag) Munitor edits;
  • Argo CD (or another controller) syncing that repository, with pull access to the registry;
  • the runtime database and its backups. KofTwentyTwo's website uses a CloudNativePG cluster with an object-store backup and a ScheduledBackup, declared in KofTwentyTwo/cluster-gitops (tenants/kof22/website). Munitor only starts a throwaway PostgreSQL sidecar for the CI health gate and never touches a real database;
  • schema migrations. Either the application migrates at start-up, or the deployment runs the migrations supplemental image (the KofTwentyTwo website runs a pre-migration backup image and then the migrations image as init containers). health.migrations only exercises that image in CI.

6. Known limitations

  • Organization defaults point at KofTwentyTwo: registry ghcr.io/KofTwentyTwo, npm scope @koftwentytwo, CI email munitor-ci@koftwentytwo.com, SonarCloud organization KofTwentyTwo. Set docker.registry, the org.* keys and SONAR_ORG explicitly. The org block is read, but the unknown-key check prints a harmless Unknown key 'org' warning.
  • production builds on main skip the quality gates, which run on release/* and hotfix/* pull requests. Do not merge unreviewed branches straight to main.
  • CircleCI only; there is no GitHub Actions equivalent. Docker jobs use machine executors.

7. Upgrade notes

0.3.3 reserves release tags atomically on main (needs the github context on build-and-test, which generated production workflows include), refuses to overwrite a version image tag built from another commit, and checks tag ownership before the GitOps bump. A consumer moving from a Munitor-derived orb with a tag-driven production trigger should compare that model with Munitor's merge-to-main model before switching.

Pipeline Types

node-api

For Node.js/Next.js applications with Docker deployment.

Minimal config:

pipeline: node-api
orb_version: "0.3"
image_name: my-app
docker:
  registry: ghcr.io/KofTwentyTwo
contexts:
  registry: ghcr
  github: github

Full config with all options:

pipeline: node-api
orb_version: "0.3"
image_name: my-app
node_version: "22"                    # default: 20

sonar:
  project_key: KofTwentyTwo_my-app       # omit to skip SonarCloud

docker:
  registry: ghcr.io/KofTwentyTwo

cd:
  repo: KofTwentyTwo/my-app-cd           # omit to skip GitOps CD updates
  env:
    release: staging                   # default: staging (CD target for release/* branches)

coverage:
  min_instruction: 80                 # default: 70

e2e: true                             # default: false (Playwright)
sbom: true                            # default: false
sast: true                            # default: false (Semgrep)

health:
  path: /api/health                   # default: /api/health
  port: 3000                          # default: 3000 (node-api), 8080 (java-webapp)

npm:
  private_registry: true              # authenticate to private npm before install

services:                             # start containers before tests
  - image: postgres:17
    port: 5432
    healthcheck: "pg_isready -U test -d mydb"
    env:
      POSTGRES_USER: test
      POSTGRES_PASSWORD: test
      POSTGRES_DB: mydb

test:
  setup: scripts/ci-setup.sh          # script to run before tests
  commands:                            # replaces default Jest runner
    - npx playwright install --with-deps chromium
    - npx playwright test
  coverage:
    tool: nyc                          # default: jest
    command: npm run coverage          # custom coverage command
    min_instruction: 80                # overrides top-level coverage.min_instruction

contexts:
  registry: ghcr
  github: github
  sonar: sonarcloud

Dockerfile: Auto-generated multi-stage build. Default framework is nextjs, targeting Next.js standalone output (requires output: 'standalone' in next.config.js). Set node: { framework: express } for Express apps (production deps only, uses node . entrypoint). If you need full control over the Dockerfile, use node-webapp instead.

node-webapp

For Node.js applications that provide their own Dockerfile (unlike node-api which auto-generates one). Use this when your app needs a custom Docker build process.

Minimal config:

pipeline: node-webapp
orb_version: "0.3"
image_name: my-webapp
docker:
  registry: ghcr.io/KofTwentyTwo
  use_repo_dockerfile: true
contexts:
  registry: ghcr
  github: github

Full config with all options:

pipeline: node-webapp
orb_version: "0.3"
image_name: my-webapp
node_version: "22"                    # default: 20

sonar:
  project_key: KofTwentyTwo_my-webapp    # omit to skip SonarCloud

docker:
  registry: ghcr.io/KofTwentyTwo
  use_repo_dockerfile: true              # preserve the repository Dockerfile

cd:
  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)

coverage:
  min_instruction: 80                 # default: 70

e2e: true                             # default: false (Playwright)
sbom: true                            # default: false
sast: true                            # default: false (Semgrep)

health:
  path: /api/health                   # default: /api/health
  port: 3000                          # default: 3000

npm:
  private_registry: true              # authenticate to private npm before install

services:                             # start containers before tests
  - image: postgres:17
    port: 5432
    healthcheck: "pg_isready -U test -d mydb"
    env:
      POSTGRES_USER: test
      POSTGRES_PASSWORD: test
      POSTGRES_DB: mydb

test:
  setup: scripts/ci-setup.sh          # script to run before tests
  commands:                            # replaces default Jest runner
    - npx playwright install --with-deps chromium
    - npx playwright test
  coverage:
    tool: nyc                          # default: jest
    command: npm run coverage          # custom coverage command
    min_instruction: 80                # overrides top-level coverage.min_instruction

contexts:
  registry: ghcr
  github: github
  sonar: sonarcloud

Dockerfile: Set docker.use_repo_dockerfile: true and provide Dockerfile in the repo root when the application owns its runtime contract. Munitor preserves and builds it, runs a health check, scans with Trivy, and pushes to the registry. Without the option, Munitor retains the legacy generated Dockerfile behavior. Use node-api when an always-generated framework Dockerfile is preferred.

java-webapp

For Java/Maven applications with Docker deployment.

Minimal config:

pipeline: java-webapp
orb_version: "0.3"
image_name: my-service
docker:
  registry: ghcr.io/KofTwentyTwo
contexts:
  registry: ghcr
  github: github
  nvd: nvd                            # optional, for OWASP dependency check

Full config with all options:

pipeline: java-webapp
orb_version: "0.3"
image_name: my-service
java_version: "21"                    # default: 21

sonar:
  project_key: KofTwentyTwo_my-service   # omit to skip SonarCloud

docker:
  registry: ghcr.io/KofTwentyTwo

cd:
  repo: KofTwentyTwo/my-service-cd       # omit to skip GitOps CD updates
  env:
    release: staging                   # default: staging (CD target for release/* branches)

coverage:
  min_instruction: 80                 # default: 70

e2e: true                             # default: false
sbom: true                            # default: false
sast:                                 # or just `sast: true` to fail on findings
  fail_on_findings: false             # warn-only mode during migration

health:
  path: /api/health                   # default: /api/health
  port: 8080                          # default: 8080

contexts:
  registry: ghcr
  github: github
  sonar: sonarcloud
  nvd: nvd                            # optional, for OWASP dependency check

What runs: Maven build/test, Checkstyle, SpotBugs, PMD, JaCoCo coverage, OWASP + Trivy security, Docker build/push (Dockerfile auto-generated), gitleaks. OWASP dependency check requires the nvd context; if omitted, the security scan runs without NVD database enrichment.

Dockerfile: Auto-generated production-ready image using Eclipse Temurin JRE Alpine. Includes non-root user (uid 1001), JVM container tuning flags, Docker HEALTHCHECK, and configurable port via health.port. The pre-built JAR from CI is copied directly (no redundant Maven build stage). PR and release image builds pull the current base and bypass Docker layer caching for generated Java/Gradle runtime images, ensuring the Alpine package upgrade runs on every build. Node builds retain their layer cache. Trivy gates remain required.

terraform

For Terraform/Terragrunt infrastructure repos.

Minimal config:

pipeline: terraform
orb_version: "0.3"
terraform:
  path: terraform/

Full config:

pipeline: terraform
orb_version: "0.3"
terraform:
  path: terraform/                     # default: terraform/
  live_path: terraform/live            # default: terraform/live
  environments:                        # default: [production]
    - production
    - staging
  checkov_skip: "CKV_AWS_144,CKV_AWS_145"

sast: true                             # default: false (Semgrep)

What runs: tofu fmt check, terragrunt init/validate per environment, Checkov, tfsec, Trivy, gitleaks.

validate-cd-repo

For CD/GitOps repositories containing Kubernetes manifests, Kustomize overlays, sealed secrets, and ArgoCD application definitions. No application code, no Docker builds, no CD updates.

Minimal config:

pipeline: validate-cd-repo
orb_version: "0.3"

Full config:

pipeline: validate-cd-repo
orb_version: "0.3"

kustomize:
  version: "5.5.0"                      # default: 5.5.0
  base_path: base/                       # default: base/
  overlays:                              # default: auto-detect from overlays/*/kustomization.yaml
    - dev
    - staging
    - production
  load_restrictor: true                  # default: true (--load-restrictor LoadRestrictionsNone)
  scan_overlay: production               # default: production

kube_linter_config: .kube-linter.yaml    # default: none (auto-detect if file exists)

What runs: YAML lint, kustomize build validation (base + all overlays), kubesec security scan, kube-linter best practices check, gitleaks secrets scan.

argocd-apps

For ArgoCD app-of-apps repositories that use environment directories (envs/) instead of the standard base/ + overlays/ kustomize layout. Functionally identical to validate-cd-repo but with a different default directory structure.

Minimal config:

pipeline: argocd-apps
orb_version: "0.3"

Full config:

pipeline: argocd-apps
orb_version: "0.3"

kustomize:
  version: "5.5.0"                      # default: 5.5.0
  base_path: ""                          # empty string skips base build
  overlay_dir: envs                      # default: overlays
  overlays:                              # default: auto-detect from {overlay_dir}/*/kustomization.yaml
    - dev
    - staging
    - production
  load_restrictor: true                  # default: true (--load-restrictor LoadRestrictionsNone)
  scan_overlay: production               # default: production

kube_linter_config: .kube-linter.yaml    # default: none
yamllint_paths: "envs/ apps/"            # default: bootstrap/ projects/ credentials/ envs/ apps/ infra/

What runs: YAML lint, kustomize build validation (overlays only when base_path is empty), kubesec security scan, kube-linter best practices check, gitleaks secrets scan.

sdk-distribution

For SDK packaging and GitHub Releases. Triggered by semver tags (v1.2.3).

pipeline: sdk-distribution
orb_version: "0.3"
contexts:
  github: github

What runs: Tag validation, SDK assembly/scrub/validate/package, SHA-256 checksums, GitHub Release with artifacts.

Workflow Matrix

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, 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)
production main Build + Docker + CD (prod) + GitHub Release (no quality gates)

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
        --> e2e-tests (if enabled)
  --> secrets-scan (parallel)
  --> sast-scan (parallel)

For release-candidate workflows, docker-build-push runs after all quality checks pass, followed by sbom, update-cd-repo (targeting staging), and github-release (marked as pre-release). For production workflows, docker-build-push runs directly after build-and-test (no quality gates -- those were enforced on the release branch), followed by update-cd-repo (targeting prod) and github-release (full release). The github-release job creates the GitHub Release for the version tag reserved during build-and-test (see Release version integrity).

Release version integrity

Production versions on main are unique per commit, even when merges land minutes apart:

  • Atomic reservation -- build-and-test on main reserves vX.Y.Z by creating the git tag through the GitHub API before the version is baked into artifacts. Tag creation is create-if-absent, so concurrent pipelines serialize on it: if another commit already owns the tag, the build takes the next patch version. A rerun of the same commit reuses its tag. Existing tags are never moved. Requires the GitHub context on build-and-test (present in the generated production workflows).
  • Immutable image tags -- images carry an org.opencontainers.image.revision label. docker-build-push refuses to push a version tag (main or supplemental) that already exists for a different commit, and fails closed if the registry cannot be inspected. Environment tags such as develop stay mutable.
  • Ownership-checked GitOps bump -- update-cd-repo verifies that vX.Y.Z points at the pipeline's commit before writing the version to the CD repository.
  • Signed GitOps commits -- update-cd-repo creates the CD repository commit through the GitHub GraphQL API (createCommitOnBranch) instead of git push. GitHub signs API-created commits, so they show as Verified and pass a CD repository ruleset that requires signed commits, with no bypass actor. The commit is authored by the identity behind GITHUB_TOKEN; the source repository and commit are recorded in the commit body. Concurrent bumps retry against the new branch head (expectedHeadOid). The ci_git_email/ci_git_name parameters and org.ci_email/org.ci_name no longer affect these commits.
  • Release targets the built commit -- github-release targets CIRCLE_SHA1, not the moving main head, and refuses if the tag points elsewhere.

cd_path is rendered into generated pipelines only when cd.path is set, so manifests that pin an older orb_version keep validating.

Release Workflow

Munitor follows a three-environment GitFlow model: dev, staging, prod. Release candidates on staging serve as the QA/UAT gate -- there is no separate UAT environment.

Environments

Environment Branch Version Format Purpose
Dev develop X.Y.Z-SNAPSHOT.SHA Integration testing, continuous builds
Staging release/* X.Y.Z-RC.N QA validation, UAT, release candidate testing
Prod main X.Y.Z Production release

How to release

  1. Develop -- Merge feature branches into develop. Each push builds a SNAPSHOT image and deploys to the dev environment.
  2. Create release branch -- When ready to release, create release/X.Y.Z from develop. This triggers the release-candidate workflow:
    • Full quality pipeline (build, test, lint, coverage, security, SAST, SonarCloud)
    • Docker image tagged X.Y.Z-RC.1 pushed to registry
    • CD repo updated targeting staging environment
    • GitHub pre-release created (vX.Y.Z-RC.1)
  3. QA on staging -- Test the RC on staging. If fixes are needed, commit directly to the release branch. Each push increments the RC number (RC.2, RC.3, etc.) and re-deploys to staging.
  4. Promote to production -- Merge the release branch into main. This triggers the production workflow:
    • Build + Docker image tagged X.Y.Z (no quality gates -- already passed on the release branch)
    • CD repo updated targeting prod environment
    • Full GitHub Release created (vX.Y.Z)
  5. Back-merge -- Merge main back into develop to carry forward the version bump.

Hotfixes

For emergency production fixes: create hotfix/<name> from main, fix, then merge directly to main. The production workflow runs the same fast-path (build + Docker + CD + release). Back-merge to develop after.

Versioning

Munitor manages versioning automatically via GitVersion. You do not need a GitVersion.yml in your repo -- Munitor writes a standard SDLC-compliant config at CI time. Version bumps follow commit conventions:

  • Patch (default): every merge to main
  • Minor: feature branch merge to develop
  • Major: commit message containing +semver: major

Tags follow the format vX.Y.Z (git tag) and X.Y.Z (Docker tag). Tags are immutable and only created on main (full releases) or release branches (pre-releases).

.munitor.yml Reference

Field Type Default Pipelines Description
pipeline string required all Pipeline type: node-api, node-webapp, java-webapp, terraform, sdk-distribution, validate-cd-repo, argocd-apps
orb_version string required all Orb version for the generated pipeline (e.g., "0.3.3", "0.3", dev:snapshot)
image_name string required* node-api, node-webapp, java-webapp Docker image name (without registry prefix)
node_version string 20 node-api, node-webapp Node.js major version
java_version string 21 java-webapp Java major version
sonar.project_key string -- node-api, node-webapp, java-webapp SonarCloud project key. Omit to skip
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
cd.env.develop / cd.env.staging / cd.env.prod string develop / staging / prod node-api, node-webapp, java-webapp CD target environment names for the develop, staging and main workflows
cd.format string helm node-api, node-webapp, java-webapp helm (sets image.tag in values.yaml, per environment under environments/<env>/ when present) or kustomize (sets images[].newTag)
server_module string -- gradle-webapp Gradle module whose build/libs JAR goes into the generated image (multi-module builds)
owasp bool true java-webapp Run the OWASP dependency check
package_manager string npm node-api, node-webapp npm or pnpm
supplemental_images list [] node-api, node-webapp, java-webapp Extra images (name, dockerfile, cd.image_name) built and tagged with the same version
health.db bool false node-api, node-webapp, java-webapp Start a PostgreSQL sidecar for the health check
health.migrations string -- node-api, node-webapp, java-webapp Supplemental image suffix run against the sidecar before the health check
health.smoke_paths list [] node-api, node-webapp, java-webapp Extra paths that must return HTTP 200 during the health check
test.coverage.summary_path string coverage/coverage-summary.json node-api, node-webapp Coverage summary file read by the coverage gate
org.docker_registry / org.npm_scope / org.ci_email / org.ci_name / org.orb_slug string KofTwentyTwo values all Organization defaults; see Adopting in another app
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
sbom bool false node-api, node-webapp, java-webapp Enable SBOM generation
sast bool/object false all except sdk Enable Semgrep SAST scanning. Use true/false or object form
sast.fail_on_findings bool true all except sdk Fail build on SAST findings. Set false for warn-only mode
node.framework string nextjs node-api Node framework: nextjs or express (not used by node-webapp)
health.path string /api/health node-api, node-webapp, java-webapp Health check endpoint path
health.port int 3000/8080 node-api, node-webapp, java-webapp Health check port (3000 for node-, 8080 for java-)
npm.private_registry bool false node-api, node-webapp Authenticate to private npm registry
services list [] node-api, node-webapp Service containers to start before tests
test.setup string -- node-api, node-webapp Script to run before tests
test.commands list [] node-api, node-webapp Custom test commands (replaces default Jest)
test.coverage.tool string jest node-api, node-webapp Coverage tool (jest or nyc)
test.coverage.command string -- node-api, node-webapp Custom coverage generation command
terraform.path string terraform/ terraform Root Terraform directory
terraform.live_path string terraform/live terraform Terragrunt live directory
terraform.environments list [production] terraform Environments to validate
terraform.checkov_skip string -- terraform Comma-separated Checkov rules to skip
kustomize.version string 5.5.0 validate-cd-repo, argocd-apps Kustomize version to install
kustomize.base_path string base/ validate-cd-repo, argocd-apps Path to kustomize base directory. Empty string skips base build
kustomize.overlay_dir string overlays validate-cd-repo, argocd-apps Directory containing overlay subdirectories (e.g. overlays, envs)
kustomize.overlays list auto-detect validate-cd-repo, argocd-apps Overlay names to validate
kustomize.load_restrictor bool true validate-cd-repo, argocd-apps Use --load-restrictor LoadRestrictionsNone
kustomize.scan_overlay string production validate-cd-repo, argocd-apps Overlay to scan with kubesec/kube-linter
kube_linter_config string -- validate-cd-repo, argocd-apps Path to kube-linter config file
yamllint_paths string pipeline-dependent validate-cd-repo, argocd-apps Space-separated directories for YAML linting
contexts.registry string -- node-api, node-webapp, java-webapp CircleCI context for Docker push (e.g., ghcr)
contexts.github string -- all CircleCI context for Git/GitHub operations. Enables GitHub Releases when set
contexts.sonar string -- node-api, node-webapp, java-webapp CircleCI context for SonarCloud. Required if sonar.project_key is set
contexts.nvd string -- java-webapp CircleCI context for OWASP NVD database. Optional; security scan runs without it

* Required for pipelines that build Docker images.

Health Check Requirement

Every container built by Munitor must expose a health endpoint. After the Docker image is built, Munitor starts the container and validates the endpoint returns HTTP 200. This is a mandatory gate; builds fail if the health check does not pass within 30 seconds.

Default endpoint: GET /api/health on port 3000 (node-api, node-webapp) or 8080 (java-webapp). Override via health.path and health.port in .munitor.yml.

Troubleshooting

"Missing required fields: orb_version" -- Add orb_version to your .munitor.yml. Use dev:snapshot for unreleased feature testing or 0.3 for the current stable line.

"munitor_header: command not found" -- You're using an older orb version. Update to dev:snapshot or wait for the next stable release.

Empty output + exit code 1 on npm ci -- Usually a PATH issue. Munitor exports node/npm to BASH_ENV; if this breaks, all subsequent steps fail silently. Check that install_node succeeded in the build logs.

"Unknown key 'xxx' in .munitor.yml" -- Munitor warns on unrecognized top-level keys to catch typos. Check spelling against the reference table above.

Interactive prompt hangs (debconf/dpkg) -- If test commands install system packages via apt, add DEBIAN_FRONTEND=noninteractive as a prefix. Munitor sets this automatically in the test runner, but explicit is safer for custom commands.

"No template found for pipeline type" -- The pipeline field must be one of: node-api, node-webapp, java-webapp, terraform, sdk-distribution, validate-cd-repo, argocd-apps.

Setup succeeds but no continuation workflow appears -- The generated config may contain invalid YAML that CircleCI accepts but can't execute. Common cause: an empty context list item from an unset optional context (e.g., contexts.nvd). Check the generated config by running make publish-snapshot and retriggering.

Branch name rejected -- Munitor enforces GitFlow naming. Rename your branch to match an allowed pattern.

Tests pass locally but fail in CI -- Check Node/Java version alignment. Add an .nvmrc file to keep local and CI versions in sync. Munitor will warn if .nvmrc and .munitor.yml versions differ.

Development (Munitor Contributors)

make lint             # yamllint + shellcheck
make validate         # pack + circleci validate
make test-scripts     # structural + unit tests
make test-templates   # template rendering tests
make all              # run everything

Pushes to develop auto-publish kof22/munitor@dev:snapshot. Production releases are tagged on main (v1.2.3).

Architecture

src/
  @orb.yml              # Orb metadata
  commands/*.yml         # 56 reusable commands (each wraps a script)
  jobs/*.yml             # 22 jobs composing commands into workflows
  executors/*.yml        # Machine executor definitions
  scripts/
    *.sh                 # 55+ bash scripts (the actual logic)
    munitor_helpers.sh     # Shared library (header, tool checks, download retry)
    templates/*.yml.tpl  # Pipeline templates with conditional blocks
    templates/partials/  # Reusable deploy workflow fragments

Pipeline generation flow:

  1. generate_pipeline job runs generate_config.sh
  2. Reads .munitor.yml, extracts variables via extract_munitor_vars.sh
  3. Selects template based on pipeline type
  4. Expands ##INCLUDE_DEPLOY## markers with partial templates
  5. Runs envsubst for variable substitution
  6. Processes ##IF_*## / ##ENDIF_*## conditional blocks
  7. Validates output YAML and passes to CircleCI continuation

Temporary npm audit exceptions

The default npm audit gate remains unchanged. For a reviewed development-only HIGH advisory with no patched package release, a repository may commit .npm-audit-exceptions.json with schemaVersion 1 and an exceptions array. Each entry requires a register ID, exact GHSA advisory ID, package, version, development scope and UTC expiry date. See Website-Frontend's EX-0008 for the first consumer.

The full npm audit runs alongside a production audit. All production HIGH/CRITICAL and all CRITICAL findings fail. Only the named advisory and its propagated HIGH findings can pass, and every affected lockfile path must have dev true and the exact excepted version. Audit errors, unknown chains and expired exceptions fail. A new upstream package release also fails and requires review. Trivy remains unchanged. This mechanism requires npm audit report version 2 and a package-path lockfile; unsupported reports fail. BATS and Node are required for the audit regression tests.

Security

Report vulnerabilities privately; see SECURITY.md.

Contributing

See CONTRIBUTING.md.

License

GPL-3.0

About

"fortifier" or "one who builds defenses," from munire (to fortify, secure).

Topics

Resources

Code of conduct

Contributing

Security policy

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Used by

Contributors

Languages