feat: first-class pnpm support (#5) #6
No files matched your search
+2
-5
@@ -15,8 +15,5 @@ node_modules/
|
||||
.idea/
|
||||
.vscode/
|
||||
|
||||
# Claude Code
|
||||
.claude/
|
||||
docs/TODO.md
|
||||
docs/PLAN-*.md
|
||||
docs/SESSION-STATE.md
|
||||
# Claude Code (keep settings.local.json out -- machine-specific permissions)
|
||||
.claude/settings.local.json
|
||||
@@ -0,0 +1,39 @@
|
||||
# Munitor
|
||||
|
||||
CircleCI orb that generates CI/CD pipeline configurations from a `.munitor.yml` manifest. Supports 8 pipeline types: java-webapp, gradle-webapp, node-api, node-webapp, terraform, validate-cd-repo, sdk-distribution, argocd-apps.
|
||||
|
||||
## Key Commands
|
||||
|
||||
```bash
|
||||
make test # Run all tests (BATS)
|
||||
make pack # Pack orb YAML from src/
|
||||
make all # lint + pack + test
|
||||
make validate # Validate packed orb with CircleCI CLI
|
||||
```
|
||||
|
||||
## Project Structure
|
||||
|
||||
- `src/commands/` - CircleCI orb commands (YAML)
|
||||
- `src/jobs/` - CircleCI orb jobs (YAML)
|
||||
- `src/scripts/` - Shell scripts included by commands/jobs
|
||||
- `src/scripts/templates/` - Pipeline config templates (`.yml.tpl`)
|
||||
- `src/scripts/templates/partials/` - Include partials for templates
|
||||
- `tests/` - BATS test files
|
||||
- `tests/fixtures/` - Test fixture `.munitor.yml` files
|
||||
|
||||
## Issue Tracker
|
||||
|
||||
GitHub Issues (org: KofTwentyTwo). Commit format: `feat(#N): description` or `Closes #N` in body.
|
||||
|
||||
## CircleCI Orb
|
||||
|
||||
- Namespace: `kof22`
|
||||
- Orb: `kof22/munitor`
|
||||
- Latest stable: `kof22/munitor@0.2.0`
|
||||
- Dev snapshot: `kof22/munitor@dev:snapshot`
|
||||
|
||||
## Session Continuity
|
||||
|
||||
- Session state: `docs/SESSION-STATE.md`
|
||||
- Active tasks: `docs/TODO.md`
|
||||
- Plans: `docs/PLAN-*.md`
|
||||
+1
-1
@@ -66,7 +66,7 @@ tests/fixtures/
|
||||
g. Validates output YAML
|
||||
|
||||
3. CircleCI continuation runs the generated pipeline, which references
|
||||
munitor orb jobs/commands by name (e.g., munitor/npm_build_and_test)
|
||||
munitor orb jobs/commands by name (e.g., munitor/node_build_and_test)
|
||||
```
|
||||
|
||||
## Adding a New Module
|
||||
|
||||
@@ -0,0 +1,83 @@
|
||||
# Munitor Session State
|
||||
|
||||
## Last Updated
|
||||
2026-03-27
|
||||
|
||||
## Current Status
|
||||
Feature branch `feature/GH-5-pnpm-support` is at `7519d62`, pushed to origin. 17 commits ahead of `develop`. Dev snapshot published: `kof22/munitor@dev:snapshot`. All 219 tests pass. Ready for PR to develop when consumer repo validation confirms the fixes work.
|
||||
|
||||
## Branch
|
||||
- `feature/GH-5-pnpm-support` at `7519d62` (pushed, 17 commits ahead of develop)
|
||||
- `develop` at `af15015`
|
||||
- `main` at `1e558c1` (2 commits ahead of develop)
|
||||
|
||||
## Tags / Releases
|
||||
- `v0.1.0` at `9247dcc` - Initial stable release (7 pipeline types, 362+ tests)
|
||||
- `v0.1.1` at `5f70823` - Supplemental images, health check, Trivy bump (505+ tests)
|
||||
- `v0.1.2` at `d766747` - Overridable org defaults (PR #1)
|
||||
- `v0.2.0` at `af15015` - Gradle-webapp pipeline type (PR #2), marked as Latest
|
||||
|
||||
All four have GitHub Releases.
|
||||
|
||||
## Key Facts
|
||||
- GitHub org: KofTwentyTwo (repo: KofTwentyTwo/Munitor)
|
||||
- CircleCI namespace: kof22 (orb: kof22/munitor)
|
||||
- Latest stable orb: kof22/munitor@0.2.0
|
||||
- Dev snapshot: kof22/munitor@dev:snapshot (pnpm support, 2026-03-27)
|
||||
- Pipeline types (8): java-webapp, gradle-webapp, node-api, node-webapp, terraform, validate-cd-repo, sdk-distribution, argocd-apps
|
||||
- CI workflows: lint-pack (all), snapshot (develop/feature), test-deploy (tags only)
|
||||
- Default branch: develop (main is release-only)
|
||||
- Test count: 219 assertions passing (across 7 test files)
|
||||
- GitHub Issue: #5 (first-class pnpm support)
|
||||
|
||||
## pnpm Support (GH-5) Implementation Summary
|
||||
|
||||
### What was done (17 commits on feature/GH-5-pnpm-support)
|
||||
|
||||
**Phase 1 - Mechanical rename:**
|
||||
- Renamed all `npm_*` jobs/commands/scripts to `node_*` (except `npm_auth` which stays)
|
||||
- Updated all templates, tests, and CONTRIBUTING.md references
|
||||
|
||||
**Phase 2 - Package manager threading:**
|
||||
- `package_manager` parameter threaded through: `install_node` -> `node_install_deps` -> `node_test` -> cache commands -> `node_build_and_test` job -> all templates
|
||||
- Corepack activation in `install_node.sh` for pnpm/yarn (version detection from `packageManager` field or `engines`)
|
||||
- `node_install_deps.sh` rewritten with npm/pnpm branching + Prisma auto-detection
|
||||
- `node_test.sh` falls back to `pnpm test` for pnpm (instead of `npx jest`)
|
||||
- Cache commands use PM-specific lockfile checksums and cache paths
|
||||
|
||||
**Phase 3 - Supplemental features:**
|
||||
- `run_test_setup.sh` supports inline commands (not just file paths)
|
||||
- `generate_dockerfile.sh` has pnpm Dockerfile variants for node-api (nextjs + express) and node-webapp
|
||||
- Prisma auto-detection runs `prisma generate` after install for all PMs
|
||||
|
||||
**Phase 4 - Secondary job fixes (latest commit):**
|
||||
- All secondary jobs (code-quality, coverage, e2e, security-scan, sonar, sbom) now run `install_node` with `node_version` + `package_manager` to bootstrap corepack/pnpm in their executors
|
||||
- `node_coverage_check` supports configurable `coverage_summary_path` with glob patterns for monorepo weighted-average aggregation
|
||||
- New `.munitor.yml` config: `test.coverage.summary_path` (default: `coverage/coverage-summary.json`)
|
||||
|
||||
### Design decisions
|
||||
- Spec: `ClaudeCode/Munitor/docs/2026-03-27-pnpm-support-design.md`
|
||||
- Plan: `ClaudeCode/Munitor/docs/2026-03-27-pnpm-support-plan.md`
|
||||
- `npm_auth` NOT renamed (genuinely npm-registry-specific, .npmrc auth works for pnpm too)
|
||||
- Monorepo Dockerfile generation out of scope (user provides custom Dockerfile)
|
||||
- Yarn support limited to corepack plumbing (no yarn-specific testing)
|
||||
- Coverage monorepo: glob + weighted average rather than auto-search
|
||||
|
||||
## Consumer Repos - Orb Version Status (updated 2026-03-27)
|
||||
- `KofTwentyTwo/Concilium` - gradle-webapp, develop, **@0.2**, green (PR #41 merged)
|
||||
- `KofTwentyTwo/Website-Backend` - java-webapp, develop, **@0.2** (PR #44 merged)
|
||||
- `KofTwentyTwo/Website-Frontend` - node-webapp, develop, **@0.2** (PR #6 merged) - testing pnpm support via dev:snapshot
|
||||
- `KofTwentyTwo/k8s-app-of-apps` - argocd-apps, develop, green (still on @0.1, compatible)
|
||||
- `KofTwentyTwo/Website-CD` - validate-cd-repo, main, green (still on @0.1, compatible)
|
||||
- `KofTwentyTwo/makers4` - java-webapp, main, **needs CircleCI follow**
|
||||
- `KofTwentyTwo/terraform-proxmox-talos` - terraform, develop, **needs CircleCI follow**
|
||||
|
||||
## Next Steps
|
||||
- Validate dev:snapshot on Website-Frontend (pnpm consumer) - confirm coverage job now works without corepack workaround
|
||||
- Test `coverage_summary_path` glob if Website-Frontend is a monorepo
|
||||
- Create PR #3 targeting develop once consumer validation passes
|
||||
- Merge and release v0.3.0
|
||||
- Bump consumer repos to @0.3
|
||||
- Follow makers4 and terraform-proxmox-talos on CircleCI (manual UI step)
|
||||
- Fix Website-Frontend ESLint error (DebugPanel.tsx:73 setState in effect, pre-existing)
|
||||
- Adopt supplemental images on a consumer repo (e.g., me-health-portal with Liquibase)
|
||||
@@ -0,0 +1,42 @@
|
||||
# TODO: Munitor
|
||||
|
||||
## Pending
|
||||
|
||||
- [ ] Validate dev:snapshot on Website-Frontend (confirm pnpm coverage job fix)
|
||||
- [ ] Create PR #3 for pnpm support (feature/GH-5-pnpm-support -> develop)
|
||||
- [ ] Release v0.3.0 after PR merge
|
||||
- [ ] Bump consumer repos to @0.3
|
||||
- [ ] Follow makers4 and terraform-proxmox-talos on CircleCI (manual step)
|
||||
- [ ] Fix Website-Frontend ESLint error (DebugPanel.tsx:73 setState in effect)
|
||||
- [ ] Adopt supplemental images on a consumer repo (e.g., me-health-portal with Liquibase)
|
||||
- [ ] Bump k8s-app-of-apps and Website-CD to @0.2+ (optional, @0.1 still compatible)
|
||||
|
||||
## Completed
|
||||
|
||||
- [x] Implement first-class pnpm support (GH-5, 17 commits, 219 tests)
|
||||
- [x] Rename all npm_* orb components to node_* (backward-incompatible, pre-1.0)
|
||||
- [x] Thread package_manager through full job/command/script chain
|
||||
- [x] Add corepack activation for pnpm/yarn in install_node
|
||||
- [x] Add pnpm Dockerfile variants for node-api and node-webapp
|
||||
- [x] Add Prisma auto-detection after dependency install
|
||||
- [x] Support inline commands in test.setup
|
||||
- [x] Bootstrap pnpm in secondary jobs (code-quality, coverage, e2e, security-scan, sonar, sbom)
|
||||
- [x] Add configurable coverage_summary_path with monorepo glob support
|
||||
- [x] Publish dev:snapshot with pnpm support
|
||||
- [x] Implement gradle-webapp pipeline type (20 new files, 7 modified, 605+ tests)
|
||||
- [x] Fix pack_generate_config.sh to embed gradle templates
|
||||
- [x] Fix RC009 orb review (extract inline commands to included script)
|
||||
- [x] Fix SC2155 shellcheck warnings in extract_munitor_vars.sh
|
||||
- [x] Add JaCoCo diagnostic output to gradle_jacoco.sh
|
||||
- [x] Merge gradle-webapp PR #2 to develop
|
||||
- [x] Release v0.2.0 and publish kof22/munitor@0.2.0
|
||||
- [x] Create GitHub Release for v0.2.0
|
||||
- [x] Bump Concilium from dev:snapshot to @0.2 (PR #41)
|
||||
- [x] Bump Website-Backend from @0.1 to @0.2 (PR #44)
|
||||
- [x] Bump Website-Frontend from @0.1 to @0.2 (PR #6)
|
||||
- [x] Onboard Concilium as first gradle-webapp consumer
|
||||
- [x] Create GitHub Releases for v0.1.0, v0.1.1, v0.1.2
|
||||
- [x] Publish orb kof22/munitor@0.1.2 (overridable org defaults)
|
||||
- [x] Implement supplemental Docker image support
|
||||
- [x] All 8 pipeline types implemented and tested
|
||||
- [x] Full rebrand from Faber to Munitor
|
||||
@@ -0,0 +1,174 @@
|
||||
# Spec: First-Class Package Manager Support (Issue #5)
|
||||
|
||||
## Goal
|
||||
|
||||
Make `package_manager` a first-class config in Munitor that drives behavior across the full Node.js lifecycle: dependency install, test execution, caching, Dockerfile generation, and post-install hooks (Prisma). Rename all `npm_*` orb jobs/commands to `node_*` to reflect multi-PM support. Release as v0.3.0.
|
||||
|
||||
## Context
|
||||
|
||||
`MUNITOR_PACKAGE_MANAGER` is parsed from `.munitor.yml` and available at config-generation time via envsubst, but no runtime script uses it. All scripts hardcode npm commands. Projects using `package_manager: pnpm` hit `pnpm: command not found` and must work around it with custom test commands.
|
||||
|
||||
## Scope
|
||||
|
||||
### In scope
|
||||
- Rename `npm_*` jobs/commands/scripts to `node_*` (except `npm_auth`)
|
||||
- Thread `package_manager` parameter through job -> command -> script chain
|
||||
- Corepack activation for pnpm (and yarn) in `install_node.sh`
|
||||
- Package-manager-aware dependency install, test fallback, cache, Dockerfile generation
|
||||
- Prisma schema auto-detection and `prisma generate` after install
|
||||
- Fix `test.setup` to support inline commands (not just file paths)
|
||||
- Update all templates, packed scripts, and tests
|
||||
- v0.3.0 release
|
||||
|
||||
### Out of scope
|
||||
- Yarn support beyond basic corepack plumbing (no yarn-specific testing or validation)
|
||||
- Monorepo-aware Dockerfile generation (user provides custom Dockerfile for complex monorepos)
|
||||
- Changes to `npm_auth` (works for all PMs via `.npmrc`)
|
||||
|
||||
## Design
|
||||
|
||||
### 1. Rename Map
|
||||
|
||||
Keep `npm_auth` as-is (genuinely npm-registry-specific; `.npmrc` auth works for pnpm too). Everything else:
|
||||
|
||||
**Jobs:**
|
||||
| Old | New |
|
||||
|---|---|
|
||||
| `npm_build_and_test` | `node_build_and_test` |
|
||||
| `npm_code_quality` | `node_code_quality` |
|
||||
| `npm_coverage` | `node_coverage` |
|
||||
| `npm_security_scan` | `node_security_scan` |
|
||||
| `npm_e2e_test` | `node_e2e_test` |
|
||||
| `npm_sonar_scan` | `node_sonar_scan` |
|
||||
| `npm_sbom` | `node_sbom` |
|
||||
|
||||
**Commands:**
|
||||
| Old | New |
|
||||
|---|---|
|
||||
| `npm_install` | `node_install_deps` |
|
||||
| `npm_test` | `node_test` |
|
||||
| `npm_lint` | `node_lint` |
|
||||
| `npm_audit` | `node_audit` |
|
||||
| `npm_coverage_check` | `node_coverage_check` |
|
||||
| `npm_sonar` | `node_sonar` |
|
||||
| `npm_sbom` (cmd) | `node_sbom` (cmd) |
|
||||
| `restore_npm_cache` | `restore_node_cache` |
|
||||
| `save_npm_cache` | `save_node_cache` |
|
||||
|
||||
**Scripts:** Same pattern, `.sh` suffix (e.g., `npm_install.sh` -> `node_install_deps.sh`).
|
||||
|
||||
### 2. Parameter Threading
|
||||
|
||||
Add `package_manager` (type: string, default: `"npm"`) to:
|
||||
- `node_build_and_test` job
|
||||
- `install_node` command
|
||||
- `node_install_deps` command
|
||||
- `node_test` command
|
||||
- `restore_node_cache` / `save_node_cache` commands
|
||||
|
||||
Templates pass it: `package_manager: "${MUNITOR_PACKAGE_MANAGER}"`.
|
||||
|
||||
At runtime, each command sets `MUNITOR_PACKAGE_MANAGER: << parameters.package_manager >>` in the step's `environment` block, making it available to the included script.
|
||||
|
||||
### 3. Corepack Activation (`install_node.sh`)
|
||||
|
||||
After nvm install/use, when `MUNITOR_PACKAGE_MANAGER != npm`:
|
||||
|
||||
1. Run `corepack enable`
|
||||
2. Detect version from `package.json` with this priority:
|
||||
- `packageManager` field (e.g., `"pnpm@9.15.9"`) -- corepack-native declaration
|
||||
- `engines.<pm>` field (e.g., `"engines": {"pnpm": ">=9"}`)
|
||||
- Fallback: no version specified (corepack uses latest)
|
||||
3. If version found: `corepack prepare <pm>@<version> --activate`
|
||||
4. Print version to build output
|
||||
5. Export PM binary path to `BASH_ENV` so downstream steps have it on PATH
|
||||
|
||||
### 4. Dependency Install (`node_install_deps.sh`, was `npm_install.sh`)
|
||||
|
||||
Branch on `MUNITOR_PACKAGE_MANAGER`:
|
||||
|
||||
**npm (default):** Current behavior unchanged. Check `package-lock.json`, run `npm ci`, lockfile version warning.
|
||||
|
||||
**pnpm:** Check `pnpm-lock.yaml` exists (error message should suggest `pnpm install` to create it, not `npm install`). Run `pnpm install --frozen-lockfile`. Note: `pnpm install` at the repo root handles workspaces natively; `pnpm -r` is NOT needed.
|
||||
|
||||
After install (all PMs): Prisma auto-detection (see section 7).
|
||||
|
||||
### 5. Test Execution (`node_test.sh`, was `npm_test.sh`)
|
||||
|
||||
**Custom commands path:** Unchanged. Already runs arbitrary commands via `bash -c`.
|
||||
|
||||
**Default fallback (no custom commands):**
|
||||
- npm: `npx jest` (current behavior)
|
||||
- pnpm: `pnpm test` (delegates to package.json scripts, where Jest or Vitest is typically configured)
|
||||
|
||||
### 6. Cache (`restore_node_cache.yml` / `save_node_cache.yml`)
|
||||
|
||||
Use CircleCI `when/equal` conditions on `package_manager` parameter:
|
||||
|
||||
**npm:** Checksum `package-lock.json`, cache `~/.npm`.
|
||||
**pnpm:** Checksum `pnpm-lock.yaml`, cache pnpm store (get path via `pnpm store path` at save time, use `~/.local/share/pnpm/store` as restore default).
|
||||
|
||||
Cache key prefix changes per PM to avoid collisions: `npm-v1-` vs `pnpm-v1-`.
|
||||
|
||||
### 7. Prisma Auto-Detection
|
||||
|
||||
Added to `node_install_deps.sh` after the dependency install step:
|
||||
|
||||
1. `find . -path "*/prisma/schema.prisma" -not -path "*/node_modules/*" -not -path "*/dist/*" -not -path "*/build/*"`
|
||||
2. For each found schema, run `<exec> prisma generate --schema=<path>`:
|
||||
- npm: `npx prisma generate --schema=<path>`
|
||||
- pnpm: `pnpm exec prisma generate --schema=<path>`
|
||||
3. If no schemas found, skip silently (no output).
|
||||
4. If schemas found but `prisma` is not in dependencies, log a warning and continue (don't fail the build).
|
||||
|
||||
This is not pnpm-specific; it helps any monorepo where Prisma's postinstall hook can't find the schema at the default location.
|
||||
|
||||
### 8. Dockerfile Generation (`generate_dockerfile.sh`)
|
||||
|
||||
Already has `MUNITOR_PACKAGE_MANAGER` via `extract_munitor_vars.sh`. Changes needed in node-api and node-webapp Dockerfile templates:
|
||||
|
||||
**npm (default):** No change. `COPY package*.json` / `npm ci` / `npm run build`.
|
||||
|
||||
**pnpm:** In builder stage:
|
||||
```dockerfile
|
||||
RUN corepack enable
|
||||
COPY package.json pnpm-lock.yaml ./
|
||||
RUN pnpm install --frozen-lockfile
|
||||
COPY . .
|
||||
RUN pnpm run build
|
||||
```
|
||||
|
||||
Runner stage: strip pnpm (same pattern as stripping npm). For distroless images (node-webapp), pnpm isn't present in the runner anyway since only standalone output is copied.
|
||||
|
||||
**Monorepo note:** Generated Dockerfiles assume single-package or standalone-output builds. Complex monorepo setups should provide a custom Dockerfile (existing escape hatch: place a `Dockerfile` in the repo and Munitor skips generation).
|
||||
|
||||
### 9. test.setup Fix (`run_test_setup.sh`)
|
||||
|
||||
Current behavior: if the value doesn't point to an existing file, exit with "script not found." This silently confuses users who pass command strings.
|
||||
|
||||
Fix: if the value is not a file path, treat it as an inline shell command and run it via `bash -c`. Log clearly which mode was used:
|
||||
- File: `"Running test setup script: ./scripts/setup.sh"`
|
||||
- Inline: `"Running test setup command: corepack enable && ..."`
|
||||
|
||||
This reduces the need for the inline workaround now that pnpm is auto-handled, but prevents future confusion.
|
||||
|
||||
### 10. Template Updates
|
||||
|
||||
All 4 templates (`node-webapp.yml.tpl`, `node-api.yml.tpl`) and 2 deploy partials (`node-webapp-deploy.yml.tpl`, `node-api-deploy.yml.tpl`):
|
||||
- Replace all `munitor/npm_*` references with `munitor/node_*`
|
||||
- Add `package_manager: "${MUNITOR_PACKAGE_MANAGER}"` to `node_build_and_test` invocations
|
||||
|
||||
`packed_generate_config.sh` and `packed_generate_dockerfile.sh`: Regenerated from source (these embed templates).
|
||||
|
||||
### 11. Test Updates
|
||||
|
||||
- `test_generate_config.sh`: Update all `npm_*` assertions to `node_*`. Add pnpm fixture and tests.
|
||||
- `test_extract_munitor_vars.sh`: Already tests `MUNITOR_PACKAGE_MANAGER`. Add pnpm-specific fixture.
|
||||
- `test_scripts.sh`: Update script path references. Add tests for pnpm branching in `node_install_deps.sh` and Prisma detection.
|
||||
- New fixture: `.munitor.yml` with `package_manager: pnpm` for generate_config tests.
|
||||
|
||||
### 12. Version and Release
|
||||
|
||||
- Version: **0.3.0** (breaking rename, pre-1.0)
|
||||
- Consumer repos must regenerate `.circleci/config.yml` after bumping orb version
|
||||
- `generate_config.sh` output automatically uses new job names
|
||||
File diff suppressed because it is too large.
Load diff
@@ -0,0 +1,46 @@
|
||||
# PLAN: Gradle-Webapp Pipeline Type
|
||||
|
||||
## Goal
|
||||
|
||||
Add Gradle build support to Munitor so Gradle-based Java projects can use the same quality gates and deployment workflows as Maven projects.
|
||||
|
||||
## Design Decisions
|
||||
|
||||
1. **Approach A: Full parallel pipeline** - Completely independent pipeline type with its own commands, scripts, jobs, and template. No shared code with Maven.
|
||||
2. **JAR discovery (C)**: Use `server_module` config field to construct path `{server_module}/build/libs/*.jar`, excluding `-plain.jar`, `-sources.jar`, `-javadoc.jar`.
|
||||
3. **No version injection (C)**: Skip Gradle version setting entirely. Rely on `calculate_version` + `export_version_vars` for Docker image tagging.
|
||||
4. **Cache key (B)**: `gradle-wrapper.properties` + `settings.gradle.kts` with `gradle-v1-` fallback.
|
||||
|
||||
## Config Shape
|
||||
|
||||
```yaml
|
||||
pipeline: gradle-webapp
|
||||
orb_version: "0.2"
|
||||
image_name: concilium
|
||||
java_version: "21"
|
||||
server_module: "concilium-server" # optional, for multi-module shadow JAR
|
||||
docker:
|
||||
registry: ghcr.io/koftwentytwo
|
||||
```
|
||||
|
||||
## Files Created (19)
|
||||
|
||||
- Scripts (6): `gradle_build.sh`, `gradle_test.sh`, `gradle_jacoco.sh`, `gradle_checkstyle.sh`, `gradle_spotbugs.sh`, `gradle_pmd.sh`, `collect_gradle_test_results.sh`
|
||||
- Commands (8): `gradle_build.yml`, `gradle_test.yml`, `gradle_jacoco.yml`, `gradle_checkstyle.yml`, `gradle_spotbugs.yml`, `gradle_pmd.yml`, `restore_gradle_cache.yml`, `save_gradle_cache.yml`
|
||||
- Jobs (3): `gradle_build_and_test.yml`, `gradle_code_quality.yml`, `gradle_coverage.yml`
|
||||
- Templates (2): `gradle-webapp.yml.tpl`, `partials/gradle-webapp-deploy.yml.tpl`
|
||||
|
||||
## Files Modified (6+)
|
||||
|
||||
- `extract_munitor_vars.sh` - Added `MUNITOR_SERVER_MODULE`, fixed SC2155 warnings
|
||||
- `generate_config.sh` - Added `gradle-webapp` to case + `server_module` to known keys
|
||||
- `generate_dockerfile.sh` - Added `gradle-webapp` case with shadow JAR discovery
|
||||
- `pack_generate_config.sh` - Added gradle templates to embed loops
|
||||
- Test files (3) - Added gradle-webapp assertions
|
||||
|
||||
## Gotchas Discovered
|
||||
|
||||
1. **pack_generate_config.sh has hardcoded template lists** - New templates must be added to the for loops manually. Not auto-discovered.
|
||||
2. **RC009 orb review** - CircleCI orb-tools review fails on inline commands > 64 chars. Must use `<< include() >>` syntax.
|
||||
3. **Gradle JaCoCo CSV not default** - Gradle's JaCoCo plugin only generates HTML+XML by default. Projects must explicitly enable `csv.required.set(true)`.
|
||||
4. **orb_version resolution** - `orb_version: "0.1"` in `.munitor.yml` resolves to latest stable `@0.1.x`, not `dev:snapshot`. New features only available via `dev:snapshot` until released.
|
||||
@@ -0,0 +1,120 @@
|
||||
# PLAN: Supplemental Images
|
||||
|
||||
## Goal
|
||||
|
||||
Add support for building, scanning, and pushing supplemental Docker images (e.g., Liquibase migrations, database backup containers) alongside the main application image. Each supplemental image shares the same version tag as the app, gets Trivy-scanned, and can update the CD repo.
|
||||
|
||||
## Config Shape
|
||||
|
||||
```yaml
|
||||
# .munitor.yml
|
||||
supplemental_images:
|
||||
- name: migrations
|
||||
# Option A: auto-generate Dockerfile from base + copy
|
||||
base: liquibase/liquibase:4.31
|
||||
copy:
|
||||
- src: db/changelog/
|
||||
dest: /liquibase/changelog/
|
||||
cd:
|
||||
image_key: migrations.image.tag # Helm mode
|
||||
# image_name: ghcr.io/org/app-migrations # Kustomize (auto-derived if omitted)
|
||||
|
||||
- name: db-backup
|
||||
# Option B: use repo-provided Dockerfile
|
||||
dockerfile: docker/Dockerfile.backup
|
||||
cd:
|
||||
image_key: dbBackup.image.tag
|
||||
```
|
||||
|
||||
Image name derivation: `{image_name}-{name}` (e.g., `me-health-portal-migrations`).
|
||||
Version: always same as main app (`PROJECT_VERSION`).
|
||||
Env tag: same as main app (`DOCKER_ENV_TAG`).
|
||||
|
||||
## Architecture
|
||||
|
||||
```
|
||||
docker_build_push job steps:
|
||||
attach_workspace
|
||||
restore_version_metadata
|
||||
generate_dockerfile # Main app Dockerfile
|
||||
docker_build # Build main app image
|
||||
health_check # Verify main app boots
|
||||
restore_trivy_cache
|
||||
run_trivy_image # Scan main app image
|
||||
save_trivy_cache
|
||||
docker_push_ghcr # Push main app (establishes registry auth)
|
||||
build_push_supplemental [NEW] # For each supplemental: generate Dockerfile, build, scan, push
|
||||
```
|
||||
|
||||
CD repo update: `update_cd_repo` receives supplemental_images JSON, updates all tags in a single commit.
|
||||
|
||||
## Files Affected
|
||||
|
||||
### New Files
|
||||
| File | Purpose |
|
||||
|------|---------|
|
||||
| `src/scripts/build_push_supplemental.sh` | Loop: auto-generate Dockerfile, build, Trivy scan, push each supplemental image |
|
||||
| `src/commands/build_push_supplemental.yml` | Orb command wrapping the script |
|
||||
| `tests/fixtures/java-webapp-supplemental.munitor.yml` | Test fixture with supplemental_images config |
|
||||
|
||||
### Modified Files
|
||||
| File | Change |
|
||||
|------|--------|
|
||||
| `src/scripts/extract_munitor_vars.sh` | Parse `supplemental_images` array, export `MUNITOR_SUPPLEMENTAL_IMAGES_JSON` + `MUNITOR_SUPPLEMENTAL` flag |
|
||||
| `src/scripts/generate_config.sh` | Add `SUPPLEMENTAL` to conditional flags, `supplemental_images` to KNOWN_KEYS |
|
||||
| `src/scripts/update_cd_repo.sh` | Read `SUPPLEMENTAL_IMAGES_JSON`, update all supplemental image tags in same commit |
|
||||
| `src/commands/update_cd_repo.yml` | Add `supplemental_images` parameter |
|
||||
| `src/jobs/docker_build_push.yml` | Add `supplemental_images` param + `build_push_supplemental` step |
|
||||
| `src/scripts/templates/java-webapp.yml.tpl` | `##IF_SUPPLEMENTAL##` blocks on docker_build_push + update_cd_repo (release-candidate + production) |
|
||||
| `src/scripts/templates/node-api.yml.tpl` | Same |
|
||||
| `src/scripts/templates/node-webapp.yml.tpl` | Same |
|
||||
| `src/scripts/templates/partials/java-webapp-deploy.yml.tpl` | `##IF_SUPPLEMENTAL##` blocks on docker_build_push + update_cd_repo |
|
||||
| `src/scripts/templates/partials/node-api-deploy.yml.tpl` | Same |
|
||||
| `src/scripts/templates/partials/node-webapp-deploy.yml.tpl` | Same |
|
||||
| `tests/test_extract_munitor_vars.sh` | Test supplemental_images parsing |
|
||||
| `tests/test_generate_config.sh` | Test ##IF_SUPPLEMENTAL## rendering |
|
||||
| `tests/test_scripts.sh` | Test build_push_supplemental.sh structure |
|
||||
|
||||
## Design Decisions
|
||||
|
||||
**Loop in same job, not separate jobs.** Supplemental images are lightweight (FROM base + COPY). Sequential build in the same executor avoids spinning up more machines and reuses Docker auth + Trivy installation.
|
||||
|
||||
**JSON array config.** Variable number of supplemental images (0-N). JSON array parsed with `jq` handles this cleanly. Follows the same pattern as `MUNITOR_SERVICES_JSON`.
|
||||
|
||||
**Auto-generate Dockerfiles.** Most supplemental images are trivial. Auto-generation from `base` + `copy` eliminates boilerplate. Users can still provide custom Dockerfiles.
|
||||
|
||||
**Single CD commit.** All image tags (app + supplemental) are updated atomically so ArgoCD picks them up together.
|
||||
|
||||
**Docker-producing pipelines only.** supplemental_images only applies to java-webapp, node-api, node-webapp. Not terraform, argocd-apps, validate-cd-repo, sdk-distribution.
|
||||
|
||||
## Variable Flow
|
||||
|
||||
```
|
||||
.munitor.yml extract_munitor_vars.sh templates
|
||||
-------------- ----------------------- ---------
|
||||
supplemental_images: [...] --> MUNITOR_SUPPLEMENTAL="true" --> ##IF_SUPPLEMENTAL##
|
||||
MUNITOR_SUPPLEMENTAL_IMAGES_JSON --> docker_build_push(supplemental_images=...)
|
||||
update_cd_repo(supplemental_images=...)
|
||||
```
|
||||
|
||||
## Script Details
|
||||
|
||||
### build_push_supplemental.sh
|
||||
|
||||
```
|
||||
For each entry in SUPPLEMENTAL_IMAGES_JSON:
|
||||
1. Derive image name: {IMAGE_NAME}-{entry.name}
|
||||
2. If entry.dockerfile exists: use it
|
||||
Else: auto-generate Dockerfile.{name} from entry.base + entry.copy
|
||||
3. docker build -f {dockerfile} -t {REGISTRY}/{derived_name}:{VERSION} .
|
||||
4. If DOCKER_ENV_TAG set: also tag with env tag
|
||||
5. trivy image --severity HIGH,CRITICAL --exit-code 1 {full_tag}
|
||||
6. docker push {full_tag}
|
||||
7. If env tag: docker push {full_tag_env}
|
||||
```
|
||||
|
||||
### update_cd_repo.sh changes
|
||||
|
||||
After updating main image tag, if SUPPLEMENTAL_IMAGES_JSON is non-empty:
|
||||
- Helm: for each entry with cd.image_key, run `yq -i ".{key} = {VERSION}"`
|
||||
- Kustomize: for each entry, derive image_name as `{CD_IMAGE_NAME}-{name}` (or use cd.image_name), run yq on kustomization.yaml
|
||||
@@ -0,0 +1,126 @@
|
||||
## Prompt: Adopting Munitor Supplemental Images for Pre-Rollout Containers
|
||||
|
||||
You are helping a development team configure their `.munitor.yml` file to use the **supplemental images** feature in the Munitor CircleCI orb. This feature builds, Trivy-scans, and pushes additional Docker images (sidecar/init containers) alongside the main application image during CI/CD.
|
||||
|
||||
### When to use supplemental images
|
||||
|
||||
Use this for any container that runs **before or alongside** the main application deployment:
|
||||
- **Liquibase migrations** — runs DB changelogs before the app starts
|
||||
- **Database backup** — snapshots the DB before a migration
|
||||
- **Data seeding** — loads reference data into a fresh environment
|
||||
- **Schema validation** — validates DB schema compatibility
|
||||
- Any other init container or Job that needs its own image
|
||||
|
||||
### How it works
|
||||
|
||||
1. Munitor builds the main app image as usual
|
||||
2. For each entry in `supplemental_images`, it either:
|
||||
- **Auto-generates a Dockerfile** from `base` + `copy` directives, OR
|
||||
- **Uses a provided Dockerfile** from the repo
|
||||
3. Each supplemental image is built, scanned with Trivy (HIGH/CRITICAL), and pushed to the same registry
|
||||
4. Image naming: `{image_name}-{supplemental_name}` (e.g., `me-health-portal-migrations`)
|
||||
5. All images share the same version tag
|
||||
6. The CD repo update commits all image tags (main + supplemental) atomically in a single commit
|
||||
|
||||
### Configuration reference
|
||||
|
||||
Add a `supplemental_images` array to your `.munitor.yml`:
|
||||
|
||||
```yaml
|
||||
supplemental_images:
|
||||
- name: <string> # REQUIRED. Suffix appended to image_name (e.g., "migrations")
|
||||
base: <string> # Option A: base Docker image (e.g., "liquibase/liquibase:4.31")
|
||||
copy: # Files to COPY into the auto-generated Dockerfile
|
||||
- src: <path> # Source path relative to repo root
|
||||
dest: <path> # Destination path in the container
|
||||
dockerfile: <string> # Option B: path to a Dockerfile in the repo (mutually exclusive with base)
|
||||
cd: # CD repo tag update config
|
||||
image_key: <string> # For Helm: dot-path in values.yaml (e.g., "migrations.image.tag")
|
||||
image_name: <string> # For Kustomize: image name in kustomization.yaml (defaults to {image_name}-{name})
|
||||
```
|
||||
|
||||
Each entry must have either `base` or `dockerfile`, not both.
|
||||
|
||||
### Example: Liquibase migrations
|
||||
|
||||
```yaml
|
||||
pipeline: java-webapp
|
||||
image_name: me-health-portal
|
||||
java_version: "21"
|
||||
|
||||
docker:
|
||||
registry: ghcr.io/dmdbrands
|
||||
|
||||
cd:
|
||||
repo: dmdbrands/me-health-portal-cd-pipeline
|
||||
|
||||
supplemental_images:
|
||||
- name: migrations
|
||||
base: liquibase/liquibase:4.31
|
||||
copy:
|
||||
- src: db/changelog/
|
||||
dest: /liquibase/changelog/
|
||||
cd:
|
||||
image_key: migrations.image.tag
|
||||
```
|
||||
|
||||
This produces:
|
||||
- Main image: `ghcr.io/dmdbrands/me-health-portal:1.2.3`
|
||||
- Supplemental: `ghcr.io/dmdbrands/me-health-portal-migrations:1.2.3`
|
||||
- CD repo `values.yaml` gets both `image.tag: "1.2.3"` and `migrations.image.tag: "1.2.3"` in one commit
|
||||
|
||||
### Example: Multiple supplemental images
|
||||
|
||||
```yaml
|
||||
supplemental_images:
|
||||
- name: migrations
|
||||
base: liquibase/liquibase:4.31
|
||||
copy:
|
||||
- src: db/changelog/
|
||||
dest: /liquibase/changelog/
|
||||
cd:
|
||||
image_key: migrations.image.tag
|
||||
|
||||
- name: db-backup
|
||||
dockerfile: docker/Dockerfile.db-backup
|
||||
cd:
|
||||
image_key: dbBackup.image.tag
|
||||
```
|
||||
|
||||
### Example: Kustomize CD format
|
||||
|
||||
```yaml
|
||||
supplemental_images:
|
||||
- name: migrations
|
||||
base: liquibase/liquibase:4.31
|
||||
copy:
|
||||
- src: db/changelog/
|
||||
dest: /liquibase/changelog/
|
||||
cd:
|
||||
image_name: me-health-portal-migrations # optional, defaults to {image_name}-{name}
|
||||
```
|
||||
|
||||
This updates `kustomization.yaml`:
|
||||
```yaml
|
||||
images:
|
||||
- name: me-health-portal
|
||||
newTag: "1.2.3"
|
||||
- name: me-health-portal-migrations
|
||||
newTag: "1.2.3"
|
||||
```
|
||||
|
||||
### Key constraints
|
||||
|
||||
- The `name` field becomes part of the Docker image name, so use lowercase alphanumeric + hyphens only
|
||||
- `base` + `copy` auto-generates a simple `FROM` + `COPY` Dockerfile — for anything more complex (RUN commands, ENV, etc.), use `dockerfile` instead
|
||||
- All supplemental images are Trivy-scanned with `--severity HIGH,CRITICAL --exit-code 1` — the build fails if vulnerabilities are found
|
||||
- The feature is available on all pipeline types: `java-webapp`, `node-api`, `node-webapp`
|
||||
- If `supplemental_images` is not present in `.munitor.yml`, no supplemental processing occurs (fully backward compatible)
|
||||
|
||||
### Your task
|
||||
|
||||
Given the team's application context, help them:
|
||||
1. Identify which pre-rollout tasks need their own container image
|
||||
2. Determine whether each needs `base` + `copy` (simple) or a custom `dockerfile` (complex)
|
||||
3. Configure the `supplemental_images` section in their `.munitor.yml`
|
||||
4. Ensure the CD repo's `values.yaml` or `kustomization.yaml` has matching entries for the supplemental image tags
|
||||
@@ -0,0 +1,22 @@
|
||||
# TODO: Supplemental Images
|
||||
|
||||
## Implementation Checklist
|
||||
|
||||
- [ ] **Step 1:** `extract_munitor_vars.sh` - Parse `supplemental_images` array, export `MUNITOR_SUPPLEMENTAL` + `MUNITOR_SUPPLEMENTAL_IMAGES_JSON`, add to exports and `get_envsubst_vars()`
|
||||
- [ ] **Step 2:** `generate_config.sh` - Add `SUPPLEMENTAL` to conditional flags list, add `supplemental_images` to KNOWN_KEYS
|
||||
- [ ] **Step 3:** `build_push_supplemental.sh` (NEW) - Loop: auto-generate Dockerfile, build, Trivy scan, push each supplemental image
|
||||
- [ ] **Step 4:** `build_push_supplemental.yml` (NEW) - Orb command wrapping the script
|
||||
- [ ] **Step 5:** `docker_build_push.yml` - Add `supplemental_images` param + `build_push_supplemental` step after `docker_push_ghcr`
|
||||
- [ ] **Step 6:** `update_cd_repo.sh` - Read `SUPPLEMENTAL_IMAGES_JSON`, update supplemental image tags in same commit (both Helm + Kustomize)
|
||||
- [ ] **Step 7:** `update_cd_repo.yml` - Add `supplemental_images` parameter + env var
|
||||
- [ ] **Step 8a:** `java-webapp.yml.tpl` - Add `##IF_SUPPLEMENTAL##` blocks on docker_build_push + update_cd_repo (release-candidate + production)
|
||||
- [ ] **Step 8b:** `node-api.yml.tpl` - Same
|
||||
- [ ] **Step 8c:** `node-webapp.yml.tpl` - Same
|
||||
- [ ] **Step 8d:** `java-webapp-deploy.yml.tpl` - Add `##IF_SUPPLEMENTAL##` blocks on docker_build_push + update_cd_repo
|
||||
- [ ] **Step 8e:** `node-api-deploy.yml.tpl` - Same
|
||||
- [ ] **Step 8f:** `node-webapp-deploy.yml.tpl` - Same
|
||||
- [ ] **Step 9a:** `java-webapp-supplemental.munitor.yml` (NEW) - Test fixture
|
||||
- [ ] **Step 9b:** `test_extract_munitor_vars.sh` - Test supplemental_images parsing (enabled + default disabled)
|
||||
- [ ] **Step 9c:** `test_generate_config.sh` - Test ##IF_SUPPLEMENTAL## conditional rendering
|
||||
- [ ] **Step 9d:** `test_scripts.sh` - Test build_push_supplemental.sh structure (helpers, error handling, jq usage)
|
||||
- [ ] **Step 10:** Run `make all` - Validate everything passes
|
||||
@@ -0,0 +1,157 @@
|
||||
# Design: obsidian-plugin Pipeline Type
|
||||
|
||||
New Munitor pipeline type for Obsidian plugins. Handles building, testing, quality gating, and releasing TypeScript/esbuild-based Obsidian plugins to GitHub Releases. No Docker, no CD deployment.
|
||||
|
||||
## Decisions
|
||||
|
||||
| Decision | Choice | Rationale |
|
||||
|----------|--------|-----------|
|
||||
| Pipeline naming | `obsidian-plugin` (specific) | Bakes in Obsidian conventions (hardcoded artifacts, no Docker) |
|
||||
| Release model | Branch-based (release-candidate + production) | Aligns with SDLC Section 6.3 and org branching strategy |
|
||||
| Quality gates | All node gates supported as conditionals | SAST, coverage, SBOM, security-scan enabled for obsidian-penny |
|
||||
| Artifact handling | Hardcoded `main.js manifest.json styles.css` | Convention over configuration for Obsidian-specific type |
|
||||
| Artifact upload mechanism | Extend existing `github_release` job | Adds `release_artifacts` parameter; minimal orb changes |
|
||||
| Build output persistence | Use `test.commands` override to chain build + test | Works today with no orb changes; dedicated `build_command` can come later |
|
||||
|
||||
## Template Structure
|
||||
|
||||
File: `src/scripts/templates/obsidian-plugin.yml.tpl`
|
||||
|
||||
Four workflows matching the SDLC branch model:
|
||||
|
||||
### pr-checks (feature/\*, hotfix/\*)
|
||||
|
||||
Full quality pipeline. Jobs:
|
||||
- `node_build_and_test` (npm install + build + test via `test.commands`)
|
||||
- `secrets_scan`
|
||||
- `sast_scan` (conditional: `##IF_SAST##`)
|
||||
- `node_code_quality` (requires: build-and-test)
|
||||
- `node_coverage` (requires: build-and-test)
|
||||
- `node_security_scan` (requires: build-and-test)
|
||||
- `node_e2e_test` (conditional: `##IF_E2E##`, requires: build-and-test)
|
||||
|
||||
### develop (develop branch)
|
||||
|
||||
Smoke check only. Jobs:
|
||||
- `node_build_and_test`
|
||||
|
||||
No deploy partials, no Docker, no CD. This differs from node-api/node-webapp which use `##INCLUDE_DEPLOY##` for develop.
|
||||
|
||||
### release-candidate (release/\*)
|
||||
|
||||
Full quality pipeline gated before release. Jobs:
|
||||
- All pr-checks jobs
|
||||
- `node_sonar_scan` (conditional: `##IF_SONAR##`)
|
||||
- `node_sbom` (conditional: `##IF_SBOM##`, gated on quality gates)
|
||||
- `github_release` with `release_artifacts: "main.js manifest.json styles.css"` (gated on quality gates, pre-release via RC version detection)
|
||||
|
||||
The `github_release` job requires all quality gate jobs. No Docker gate since there is no Docker job.
|
||||
|
||||
### production (main)
|
||||
|
||||
Fast-path promotion (quality gates already passed on release/\*). Jobs:
|
||||
- `node_build_and_test`
|
||||
- `github_release` with `release_artifacts: "main.js manifest.json styles.css"` (requires: build-and-test, full release)
|
||||
|
||||
## Changes to `github_release` Job/Script
|
||||
|
||||
### `src/jobs/github_release.yml`
|
||||
|
||||
Add optional parameter:
|
||||
|
||||
```yaml
|
||||
parameters:
|
||||
release_artifacts:
|
||||
type: string
|
||||
default: ""
|
||||
description: "Space-separated list of files to upload to the GitHub Release"
|
||||
```
|
||||
|
||||
Pass to script as `MUNITOR_RELEASE_ARTIFACTS` environment variable.
|
||||
|
||||
### `src/scripts/github_release.sh`
|
||||
|
||||
After the `gh release create` block, add artifact upload:
|
||||
|
||||
```bash
|
||||
if [[ -n "${MUNITOR_RELEASE_ARTIFACTS:-}" ]]; then
|
||||
echo "Uploading release artifacts: ${MUNITOR_RELEASE_ARTIFACTS}"
|
||||
# shellcheck disable=SC2086
|
||||
gh release upload "${TAG}" ${MUNITOR_RELEASE_ARTIFACTS}
|
||||
fi
|
||||
```
|
||||
|
||||
Uses `gh release upload` (separate from create) so it works whether the release was just created or already existed. Backward compatible -- existing pipelines pass no artifacts.
|
||||
|
||||
## `.munitor.yml` Schema
|
||||
|
||||
obsidian-penny configuration:
|
||||
|
||||
```yaml
|
||||
pipeline: obsidian-plugin
|
||||
orb_version: "0.3"
|
||||
node_version: "20"
|
||||
sast: true
|
||||
sbom: true
|
||||
test:
|
||||
commands: ["npm run build", "npm test"]
|
||||
coverage:
|
||||
tool: vitest
|
||||
command: npx vitest run --coverage
|
||||
contexts:
|
||||
github: github
|
||||
```
|
||||
|
||||
No new variables in `extract_munitor_vars.sh`. The template uses a subset of existing `MUNITOR_*` variables: `NODE_VERSION`, `PACKAGE_MANAGER`, `SAST`, `SAST_FAIL_ON_FINDINGS`, `SBOM`, `COVERAGE_MIN`, `COVERAGE_TOOL`, `COVERAGE_COMMAND`, `CONTEXT_GITHUB`, and the node feature flags.
|
||||
|
||||
### `generate_config.sh` validation
|
||||
|
||||
Add `obsidian-plugin` to the pipeline type case statement. Required: `contexts.github`. Not required: `image_name`, `docker.registry`, `cd.repo`.
|
||||
|
||||
### `packed_generate_config.sh`
|
||||
|
||||
Embed `obsidian-plugin.yml.tpl` in the packed script using the same heredoc pattern as other templates.
|
||||
|
||||
## Testing
|
||||
|
||||
### Test fixture
|
||||
|
||||
`tests/fixtures/obsidian-plugin.munitor.yml` -- mirrors the schema above.
|
||||
|
||||
### `tests/test_generate_config.sh`
|
||||
|
||||
Positive tests (patterns present):
|
||||
- Valid YAML output
|
||||
- All 4 workflows: `pr-checks`, `develop`, `release-candidate`, `production`
|
||||
- `build-and-test` in all workflows
|
||||
- `secrets-scan` and `sast-scan` in pr-checks and release-candidate
|
||||
- `github-release` in release-candidate and production
|
||||
- `release_artifacts: "main.js manifest.json styles.css"` on github-release jobs
|
||||
- `security-scan` present
|
||||
- `sbom` present
|
||||
- Correct branch filters
|
||||
|
||||
Negative tests (patterns absent):
|
||||
- No `docker-build-push`
|
||||
- No `update-cd-repo`
|
||||
- No `image_name` or `registry` references
|
||||
- No `INCLUDE_DEPLOY` partials
|
||||
|
||||
### `tests/test_scripts.sh`
|
||||
|
||||
- `github_release.sh` with `MUNITOR_RELEASE_ARTIFACTS` set -- verify upload behavior
|
||||
- `github_release.sh` with `MUNITOR_RELEASE_ARTIFACTS` empty -- verify no upload (backward compat)
|
||||
|
||||
## Consumer Repo Changes (obsidian-penny, post-release)
|
||||
|
||||
1. Create `.munitor.yml` (schema above)
|
||||
2. Bump `.circleci/config.yml` orb version to new release
|
||||
3. Remove `.github/workflows/release.yml` (redundant)
|
||||
4. Verify workspace persistence delivers `main.js` to `github_release` job
|
||||
|
||||
## Not Changed
|
||||
|
||||
- `extract_munitor_vars.sh` -- no new variables needed
|
||||
- `node_build_and_test` job -- works as-is with `test.commands` override
|
||||
- Other pipeline templates -- no modifications
|
||||
- `sdk-distribution.yml.tpl` -- remains tag-based, separate use case
|
||||
@@ -39,7 +39,7 @@ echo "Packing generate_config.sh..."
|
||||
echo ''
|
||||
|
||||
# Embed each template
|
||||
for tpl in java-webapp gradle-webapp node-api node-webapp terraform sdk-distribution validate-cd-repo argocd-apps; do
|
||||
for tpl in java-webapp gradle-webapp node-api node-webapp terraform sdk-distribution validate-cd-repo argocd-apps obsidian-plugin; do
|
||||
echo "cat > /tmp/munitor/templates/${tpl}.yml.tpl << 'MUNITOR_TPL_EOF'"
|
||||
cat "${SRC}/templates/${tpl}.yml.tpl"
|
||||
echo 'MUNITOR_TPL_EOF'
|
||||
|
||||
@@ -1,7 +1,15 @@
|
||||
description: >
|
||||
Create an annotated git tag and GitHub Release using the version
|
||||
calculated by GitVersion. Skips if tag or release already exists.
|
||||
Optionally uploads release artifacts to the created release.
|
||||
parameters:
|
||||
release_artifacts:
|
||||
type: string
|
||||
default: ""
|
||||
description: "Space-separated list of files to upload to the GitHub Release."
|
||||
steps:
|
||||
- run:
|
||||
name: Create GitHub Release
|
||||
environment:
|
||||
MUNITOR_RELEASE_ARTIFACTS: << parameters.release_artifacts >>
|
||||
command: << include(scripts/github_release.sh) >>
|
||||
@@ -5,9 +5,14 @@ parameters:
|
||||
type: string
|
||||
default: "20"
|
||||
description: Node.js major version to install (e.g., 20, 22).
|
||||
package_manager:
|
||||
type: string
|
||||
default: "npm"
|
||||
description: Package manager to use (npm, pnpm, yarn).
|
||||
steps:
|
||||
- run:
|
||||
name: Install Node.js << parameters.version >>
|
||||
environment:
|
||||
NODE_VERSION: << parameters.version >>
|
||||
MUNITOR_PACKAGE_MANAGER: << parameters.package_manager >>
|
||||
command: << include(scripts/install_node.sh) >>
|
||||
@@ -0,0 +1,6 @@
|
||||
description: >
|
||||
Run a security audit to check for known vulnerabilities in dependencies.
|
||||
steps:
|
||||
- run:
|
||||
name: Security audit
|
||||
command: << include(scripts/node_audit.sh) >>
|
||||
@@ -14,6 +14,12 @@ parameters:
|
||||
type: string
|
||||
default: ""
|
||||
description: Custom command to generate coverage report before threshold check.
|
||||
coverage_summary_path:
|
||||
type: string
|
||||
default: "coverage/coverage-summary.json"
|
||||
description: >
|
||||
Path to coverage-summary.json. Supports glob patterns for monorepos
|
||||
(e.g., packages/*/coverage/coverage-summary.json).
|
||||
steps:
|
||||
- run:
|
||||
name: Coverage threshold check
|
||||
@@ -21,4 +27,5 @@ steps:
|
||||
MIN_COVERAGE: << parameters.min_coverage >>
|
||||
MUNITOR_COVERAGE_TOOL: << parameters.coverage_tool >>
|
||||
MUNITOR_COVERAGE_COMMAND: << parameters.coverage_command >>
|
||||
command: << include(scripts/npm_coverage_check.sh) >>
|
||||
MUNITOR_COVERAGE_SUMMARY_PATH: << parameters.coverage_summary_path >>
|
||||
command: << include(scripts/node_coverage_check.sh) >>
|
||||
@@ -0,0 +1,13 @@
|
||||
description: >
|
||||
Install project dependencies using the configured package manager.
|
||||
parameters:
|
||||
package_manager:
|
||||
type: string
|
||||
default: "npm"
|
||||
description: Package manager to use (npm, pnpm, yarn).
|
||||
steps:
|
||||
- run:
|
||||
name: Install dependencies
|
||||
environment:
|
||||
MUNITOR_PACKAGE_MANAGER: << parameters.package_manager >>
|
||||
command: << include(scripts/node_install_deps.sh) >>
|
||||
@@ -3,4 +3,4 @@ description: >
|
||||
steps:
|
||||
- run:
|
||||
name: ESLint
|
||||
command: << include(scripts/npm_lint.sh) >>
|
||||
command: << include(scripts/node_lint.sh) >>
|
||||
@@ -0,0 +1,6 @@
|
||||
description: >
|
||||
Generate a CycloneDX SBOM from a Node.js project.
|
||||
steps:
|
||||
- run:
|
||||
name: Generate SBOM
|
||||
command: << include(scripts/node_sbom.sh) >>
|
||||
@@ -19,4 +19,4 @@ steps:
|
||||
SONAR_PROJECT_KEY: << parameters.sonar_project_key >>
|
||||
SONAR_ORG: << parameters.sonar_org >>
|
||||
SONAR_TOKEN_VAR: << parameters.sonar_token_env >>
|
||||
command: << include(scripts/npm_sonar.sh) >>
|
||||
command: << include(scripts/node_sonar.sh) >>
|
||||
@@ -1,17 +1,22 @@
|
||||
description: >
|
||||
Run tests with CI flags, coverage, and JUnit reporter. Supports custom
|
||||
test commands via JSON array or falls back to Jest defaults.
|
||||
test commands via JSON array or falls back to package manager defaults.
|
||||
parameters:
|
||||
test_commands:
|
||||
type: string
|
||||
default: ""
|
||||
description: JSON array of custom test commands to run instead of Jest.
|
||||
package_manager:
|
||||
type: string
|
||||
default: "npm"
|
||||
description: Package manager to use (npm, pnpm, yarn).
|
||||
steps:
|
||||
- run:
|
||||
name: npm test
|
||||
name: Run tests
|
||||
environment:
|
||||
MUNITOR_TEST_COMMANDS_JSON: << parameters.test_commands >>
|
||||
command: << include(scripts/npm_test.sh) >>
|
||||
MUNITOR_PACKAGE_MANAGER: << parameters.package_manager >>
|
||||
command: << include(scripts/node_test.sh) >>
|
||||
- store_test_results:
|
||||
path: reports/junit
|
||||
- store_artifacts:
|
||||
@@ -1,6 +0,0 @@
|
||||
description: >
|
||||
Run npm audit to check for known vulnerabilities in dependencies.
|
||||
steps:
|
||||
- run:
|
||||
name: npm audit
|
||||
command: << include(scripts/npm_audit.sh) >>
|
||||
@@ -1,6 +0,0 @@
|
||||
description: >
|
||||
Run npm ci for a clean, reproducible dependency install.
|
||||
steps:
|
||||
- run:
|
||||
name: npm ci
|
||||
command: << include(scripts/npm_install.sh) >>
|
||||
@@ -1,6 +0,0 @@
|
||||
description: >
|
||||
Generate a CycloneDX SBOM from an npm project.
|
||||
steps:
|
||||
- run:
|
||||
name: Generate SBOM (npm)
|
||||
command: << include(scripts/npm_sbom.sh) >>
|
||||
@@ -0,0 +1,24 @@
|
||||
description: >
|
||||
Restore the dependency cache based on lockfile checksum.
|
||||
parameters:
|
||||
package_manager:
|
||||
type: string
|
||||
default: "npm"
|
||||
description: Package manager (npm, pnpm, yarn).
|
||||
steps:
|
||||
- when:
|
||||
condition:
|
||||
equal: ["npm", << parameters.package_manager >>]
|
||||
steps:
|
||||
- restore_cache:
|
||||
keys:
|
||||
- npm-v1-{{ checksum "package-lock.json" }}
|
||||
- npm-v1-
|
||||
- when:
|
||||
condition:
|
||||
equal: ["pnpm", << parameters.package_manager >>]
|
||||
steps:
|
||||
- restore_cache:
|
||||
keys:
|
||||
- pnpm-v1-{{ checksum "pnpm-lock.yaml" }}
|
||||
- pnpm-v1-
|
||||
@@ -1,7 +0,0 @@
|
||||
description: >
|
||||
Restore the npm cache based on package-lock.json checksum.
|
||||
steps:
|
||||
- restore_cache:
|
||||
keys:
|
||||
- npm-v1-{{ checksum "package-lock.json" }}
|
||||
- npm-v1-
|
||||
@@ -0,0 +1,24 @@
|
||||
description: >
|
||||
Save the dependency cache for future builds.
|
||||
parameters:
|
||||
package_manager:
|
||||
type: string
|
||||
default: "npm"
|
||||
description: Package manager (npm, pnpm, yarn).
|
||||
steps:
|
||||
- when:
|
||||
condition:
|
||||
equal: ["npm", << parameters.package_manager >>]
|
||||
steps:
|
||||
- save_cache:
|
||||
key: npm-v1-{{ checksum "package-lock.json" }}
|
||||
paths:
|
||||
- ~/.npm
|
||||
- when:
|
||||
condition:
|
||||
equal: ["pnpm", << parameters.package_manager >>]
|
||||
steps:
|
||||
- save_cache:
|
||||
key: pnpm-v1-{{ checksum "pnpm-lock.yaml" }}
|
||||
paths:
|
||||
- ~/.local/share/pnpm/store
|
||||
@@ -1,7 +0,0 @@
|
||||
description: >
|
||||
Save the npm cache for future builds.
|
||||
steps:
|
||||
- save_cache:
|
||||
key: npm-v1-{{ checksum "package-lock.json" }}
|
||||
paths:
|
||||
- ~/.npm
|
||||
@@ -1,6 +1,12 @@
|
||||
description: >
|
||||
Create an annotated git tag and GitHub Release on main branch merges.
|
||||
Uses PROJECT_VERSION from GitVersion (persisted by the build job).
|
||||
Optionally uploads release artifacts (e.g., main.js, manifest.json).
|
||||
parameters:
|
||||
release_artifacts:
|
||||
type: string
|
||||
default: ""
|
||||
description: "Space-separated list of files to upload to the GitHub Release."
|
||||
executor: base
|
||||
steps:
|
||||
- checkout
|
||||
@@ -10,4 +16,5 @@ steps:
|
||||
name: Restore version metadata
|
||||
command: <<include(scripts/restore_version_metadata.sh)>>
|
||||
- install_gh
|
||||
- github_release
|
||||
- github_release:
|
||||
release_artifacts: << parameters.release_artifacts >>
|
||||
@@ -1,12 +1,16 @@
|
||||
description: >
|
||||
Full Node.js build and test job. Installs Node.js, restores cache, runs
|
||||
npm ci, calculates version, tests with coverage, saves cache, and persists
|
||||
dependency install, calculates version, tests with coverage, saves cache, and persists
|
||||
the workspace for downstream jobs.
|
||||
parameters:
|
||||
node_version:
|
||||
type: string
|
||||
default: "20"
|
||||
description: Node.js major version to install.
|
||||
package_manager:
|
||||
type: string
|
||||
default: "npm"
|
||||
description: Package manager to use (npm, pnpm, yarn).
|
||||
npm_auth:
|
||||
type: boolean
|
||||
default: false
|
||||
@@ -46,14 +50,17 @@ steps:
|
||||
- checkout
|
||||
- install_node:
|
||||
version: << parameters.node_version >>
|
||||
package_manager: << parameters.package_manager >>
|
||||
- when:
|
||||
condition: << parameters.npm_auth >>
|
||||
steps:
|
||||
- npm_auth:
|
||||
npm_scopes: << parameters.npm_scopes >>
|
||||
npm_default_scope: << parameters.npm_default_scope >>
|
||||
- restore_npm_cache
|
||||
- npm_install
|
||||
- restore_node_cache:
|
||||
package_manager: << parameters.package_manager >>
|
||||
- node_install_deps:
|
||||
package_manager: << parameters.package_manager >>
|
||||
- when:
|
||||
condition: << parameters.services >>
|
||||
steps:
|
||||
@@ -69,11 +76,13 @@ steps:
|
||||
- run:
|
||||
name: Persist version metadata
|
||||
command: <<include(scripts/persist_version_metadata.sh)>>
|
||||
- npm_test:
|
||||
- node_test:
|
||||
test_commands: << parameters.test_commands >>
|
||||
package_manager: << parameters.package_manager >>
|
||||
- store_test_results:
|
||||
path: reports/junit
|
||||
- save_npm_cache
|
||||
- save_node_cache:
|
||||
package_manager: << parameters.package_manager >>
|
||||
- persist_to_workspace:
|
||||
root: .
|
||||
paths:
|
||||
@@ -1,7 +1,15 @@
|
||||
description: >
|
||||
Run ESLint code quality checks.
|
||||
Requires workspace from npm_build_and_test.
|
||||
Requires workspace from node_build_and_test.
|
||||
parameters:
|
||||
node_version:
|
||||
type: string
|
||||
default: "20"
|
||||
description: Node.js major version to install.
|
||||
package_manager:
|
||||
type: string
|
||||
default: "npm"
|
||||
description: Package manager (npm, pnpm, yarn).
|
||||
resource_class:
|
||||
type: enum
|
||||
enum:
|
||||
@@ -15,7 +23,10 @@ executor:
|
||||
steps:
|
||||
- attach_workspace:
|
||||
at: .
|
||||
- npm_lint
|
||||
- install_node:
|
||||
version: << parameters.node_version >>
|
||||
package_manager: << parameters.package_manager >>
|
||||
- node_lint
|
||||
- store_artifacts:
|
||||
path: /tmp/eslint-report.json
|
||||
destination: eslint-report.json
|
||||
@@ -1,7 +1,15 @@
|
||||
description: >
|
||||
Enforce minimum coverage threshold from coverage output.
|
||||
Requires workspace from npm_build_and_test.
|
||||
Requires workspace from node_build_and_test.
|
||||
parameters:
|
||||
node_version:
|
||||
type: string
|
||||
default: "20"
|
||||
description: Node.js major version to install.
|
||||
package_manager:
|
||||
type: string
|
||||
default: "npm"
|
||||
description: Package manager (npm, pnpm, yarn).
|
||||
min_coverage:
|
||||
type: string
|
||||
default: "70"
|
||||
@@ -14,6 +22,11 @@ parameters:
|
||||
type: string
|
||||
default: ""
|
||||
description: Custom command to generate coverage report before threshold check.
|
||||
coverage_summary_path:
|
||||
type: string
|
||||
default: "coverage/coverage-summary.json"
|
||||
description: >
|
||||
Path to coverage-summary.json. Supports glob patterns for monorepos.
|
||||
resource_class:
|
||||
type: enum
|
||||
enum:
|
||||
@@ -27,10 +40,14 @@ executor:
|
||||
steps:
|
||||
- attach_workspace:
|
||||
at: .
|
||||
- npm_coverage_check:
|
||||
- install_node:
|
||||
version: << parameters.node_version >>
|
||||
package_manager: << parameters.package_manager >>
|
||||
- node_coverage_check:
|
||||
min_coverage: << parameters.min_coverage >>
|
||||
coverage_tool: << parameters.coverage_tool >>
|
||||
coverage_command: << parameters.coverage_command >>
|
||||
coverage_summary_path: << parameters.coverage_summary_path >>
|
||||
- store_artifacts:
|
||||
path: coverage
|
||||
destination: coverage-report
|
||||
@@ -1,6 +1,14 @@
|
||||
description: >
|
||||
Run Playwright E2E tests. Requires workspace from npm_build_and_test.
|
||||
Run Playwright E2E tests. Requires workspace from node_build_and_test.
|
||||
parameters:
|
||||
node_version:
|
||||
type: string
|
||||
default: "20"
|
||||
description: Node.js major version to install.
|
||||
package_manager:
|
||||
type: string
|
||||
default: "npm"
|
||||
description: Package manager (npm, pnpm, yarn).
|
||||
test_dir:
|
||||
type: string
|
||||
default: e2e
|
||||
@@ -18,6 +26,9 @@ executor:
|
||||
steps:
|
||||
- attach_workspace:
|
||||
at: .
|
||||
- install_node:
|
||||
version: << parameters.node_version >>
|
||||
package_manager: << parameters.package_manager >>
|
||||
- run_e2e_playwright:
|
||||
test_dir: << parameters.test_dir >>
|
||||
- store_artifacts:
|
||||
@@ -1,11 +1,15 @@
|
||||
description: >
|
||||
Generate SBOM and submit dependency graph for Node.js projects.
|
||||
Requires workspace from npm_build_and_test.
|
||||
Requires workspace from node_build_and_test.
|
||||
parameters:
|
||||
node_version:
|
||||
type: string
|
||||
default: "20"
|
||||
description: Node.js major version to install.
|
||||
package_manager:
|
||||
type: string
|
||||
default: "npm"
|
||||
description: Package manager (npm, pnpm, yarn).
|
||||
resource_class:
|
||||
type: enum
|
||||
enum:
|
||||
@@ -21,7 +25,8 @@ steps:
|
||||
at: .
|
||||
- install_node:
|
||||
version: << parameters.node_version >>
|
||||
- npm_sbom
|
||||
package_manager: << parameters.package_manager >>
|
||||
- node_sbom
|
||||
- submit_dependency_graph:
|
||||
sbom_path: bom.json
|
||||
detector_name: CycloneDX npm
|
||||
@@ -1,7 +1,15 @@
|
||||
description: >
|
||||
Run npm audit and Trivy filesystem scan.
|
||||
Requires workspace from npm_build_and_test.
|
||||
Requires workspace from node_build_and_test.
|
||||
parameters:
|
||||
node_version:
|
||||
type: string
|
||||
default: "20"
|
||||
description: Node.js major version to install.
|
||||
package_manager:
|
||||
type: string
|
||||
default: "npm"
|
||||
description: Package manager (npm, pnpm, yarn).
|
||||
resource_class:
|
||||
type: enum
|
||||
enum:
|
||||
@@ -15,7 +23,10 @@ executor:
|
||||
steps:
|
||||
- attach_workspace:
|
||||
at: .
|
||||
- npm_audit
|
||||
- install_node:
|
||||
version: << parameters.node_version >>
|
||||
package_manager: << parameters.package_manager >>
|
||||
- node_audit
|
||||
- restore_trivy_cache
|
||||
- run_trivy
|
||||
- save_trivy_cache
|
||||
@@ -1,11 +1,15 @@
|
||||
description: >
|
||||
Run SonarCloud analysis for Node.js projects. Attaches workspace from
|
||||
npm_build_and_test and uses the sonar-scanner CLI with bundled JRE.
|
||||
node_build_and_test and uses the sonar-scanner CLI with bundled JRE.
|
||||
parameters:
|
||||
node_version:
|
||||
type: string
|
||||
default: "20"
|
||||
description: Node.js major version to install.
|
||||
package_manager:
|
||||
type: string
|
||||
default: "npm"
|
||||
description: Package manager (npm, pnpm, yarn).
|
||||
sonar_project_key:
|
||||
type: string
|
||||
description: SonarCloud project key.
|
||||
@@ -29,6 +33,7 @@ steps:
|
||||
at: .
|
||||
- install_node:
|
||||
version: << parameters.node_version >>
|
||||
- npm_sonar:
|
||||
package_manager: << parameters.package_manager >>
|
||||
- node_sonar:
|
||||
sonar_project_key: << parameters.sonar_project_key >>
|
||||
sonar_org: << parameters.sonar_org >>
|
||||
@@ -96,6 +96,7 @@ extract_munitor_vars() {
|
||||
if [[ -n "${MUNITOR_TEST_COVERAGE_MIN}" ]]; then
|
||||
MUNITOR_COVERAGE_MIN="${MUNITOR_TEST_COVERAGE_MIN}"
|
||||
fi
|
||||
MUNITOR_COVERAGE_SUMMARY_PATH=$(yq '.test.coverage.summary_path // "coverage/coverage-summary.json"' "${config_file}")
|
||||
|
||||
# Terraform pipeline settings
|
||||
MUNITOR_TF_PATH=$(yq '.terraform.path // "terraform/"' "${config_file}")
|
||||
@@ -214,7 +215,7 @@ extract_munitor_vars() {
|
||||
export MUNITOR_SERVICES MUNITOR_SERVICES_JSON
|
||||
export MUNITOR_TEST_SETUP MUNITOR_TEST_SETUP_SCRIPT
|
||||
export MUNITOR_CUSTOM_TEST MUNITOR_TEST_COMMANDS_JSON
|
||||
export MUNITOR_COVERAGE_TOOL MUNITOR_COVERAGE_CMD MUNITOR_COVERAGE_COMMAND
|
||||
export MUNITOR_COVERAGE_TOOL MUNITOR_COVERAGE_CMD MUNITOR_COVERAGE_COMMAND MUNITOR_COVERAGE_SUMMARY_PATH
|
||||
export MUNITOR_TF_PATH MUNITOR_TF_LIVE_PATH MUNITOR_TF_ENVIRONMENTS MUNITOR_CHECKOV_SKIP MUNITOR_SAST MUNITOR_SAST_FAIL_ON_FINDINGS
|
||||
export MUNITOR_KUSTOMIZE_VERSION MUNITOR_KUSTOMIZE_BASE_PATH MUNITOR_KUSTOMIZE_LOAD_RESTRICTOR
|
||||
export MUNITOR_KUSTOMIZE_SCAN_OVERLAY MUNITOR_KUSTOMIZE_OVERLAYS MUNITOR_KUSTOMIZE_OVERLAY_DIR
|
||||
@@ -229,5 +230,5 @@ extract_munitor_vars() {
|
||||
# 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}'
|
||||
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}'
|
||||
}
|
||||
@@ -80,6 +80,9 @@ validate_required_fields() {
|
||||
validate-cd-repo|argocd-apps)
|
||||
# No additional required fields beyond orb_version
|
||||
;;
|
||||
obsidian-plugin)
|
||||
[[ -z "$(yq '.contexts.github // ""' "${config}")" ]] && missing+=("contexts.github")
|
||||
;;
|
||||
esac
|
||||
|
||||
if [[ ${#missing[@]} -gt 0 ]]; then
|
||||
|
||||
@@ -42,7 +42,42 @@ case "${MUNITOR_PIPELINE}" in
|
||||
nextjs)
|
||||
# Multi-stage Next.js standalone Dockerfile.
|
||||
# Assumes `output: 'standalone'` in next.config.js.
|
||||
cat > Dockerfile <<DOCKERFILE
|
||||
case "${MUNITOR_PACKAGE_MANAGER}" in
|
||||
pnpm)
|
||||
cat > Dockerfile <<DOCKERFILE
|
||||
FROM node:${MUNITOR_NODE_VERSION}-alpine AS deps
|
||||
WORKDIR /app
|
||||
RUN corepack enable
|
||||
COPY package.json pnpm-lock.yaml ./
|
||||
RUN pnpm install --frozen-lockfile
|
||||
|
||||
FROM node:${MUNITOR_NODE_VERSION}-alpine AS builder
|
||||
WORKDIR /app
|
||||
RUN corepack enable
|
||||
COPY --from=deps /app/node_modules ./node_modules
|
||||
COPY . .
|
||||
ENV STANDALONE=true
|
||||
ARG GIT_COMMIT_SHA
|
||||
ENV GIT_COMMIT_SHA=\${GIT_COMMIT_SHA}
|
||||
RUN pnpm run build
|
||||
|
||||
FROM node:${MUNITOR_NODE_VERSION}-alpine AS runner
|
||||
WORKDIR /app
|
||||
RUN apk update && apk upgrade --no-cache && rm -rf /var/cache/apk/*
|
||||
RUN npm cache clean --force && rm -rf /usr/local/lib/node_modules /usr/local/bin/npm /usr/local/bin/npx
|
||||
RUN addgroup --system --gid 1001 nodejs \\
|
||||
&& adduser --system --uid 1001 nextjs
|
||||
COPY --from=builder /app/public ./public
|
||||
COPY --from=builder --chown=nextjs:nodejs /app/.next/standalone ./
|
||||
COPY --from=builder --chown=nextjs:nodejs /app/.next/static ./.next/static
|
||||
USER nextjs
|
||||
EXPOSE 3000
|
||||
ENV PORT=3000
|
||||
CMD ["node", "server.js"]
|
||||
DOCKERFILE
|
||||
;;
|
||||
*)
|
||||
cat > Dockerfile <<DOCKERFILE
|
||||
FROM node:${MUNITOR_NODE_VERSION}-alpine AS deps
|
||||
WORKDIR /app
|
||||
COPY package*.json ./
|
||||
@@ -73,11 +108,38 @@ EXPOSE 3000
|
||||
ENV PORT=3000
|
||||
CMD ["node", "server.js"]
|
||||
DOCKERFILE
|
||||
;;
|
||||
esac
|
||||
;;
|
||||
|
||||
express)
|
||||
# Two-stage Express Dockerfile. Uses package.json "main" field via `node .`.
|
||||
cat > Dockerfile <<DOCKERFILE
|
||||
case "${MUNITOR_PACKAGE_MANAGER}" in
|
||||
pnpm)
|
||||
cat > Dockerfile <<DOCKERFILE
|
||||
FROM node:${MUNITOR_NODE_VERSION}-alpine AS deps
|
||||
WORKDIR /app
|
||||
RUN corepack enable
|
||||
COPY package.json pnpm-lock.yaml ./
|
||||
RUN pnpm install --frozen-lockfile --prod
|
||||
|
||||
FROM node:${MUNITOR_NODE_VERSION}-alpine AS runner
|
||||
WORKDIR /app
|
||||
RUN apk update && apk upgrade --no-cache && rm -rf /var/cache/apk/*
|
||||
RUN npm cache clean --force && rm -rf /usr/local/lib/node_modules /usr/local/bin/npm /usr/local/bin/npx
|
||||
RUN addgroup --system --gid 1001 nodejs \\
|
||||
&& adduser --system --uid 1001 appuser -G nodejs
|
||||
COPY --from=deps /app/node_modules ./node_modules
|
||||
COPY . .
|
||||
USER appuser
|
||||
EXPOSE ${MUNITOR_HEALTH_PORT}
|
||||
HEALTHCHECK --interval=30s --timeout=3s --start-period=10s --retries=3 \\
|
||||
CMD wget --no-verbose --tries=1 --spider http://localhost:${MUNITOR_HEALTH_PORT}${MUNITOR_HEALTH_PATH} || exit 1
|
||||
CMD ["node", "."]
|
||||
DOCKERFILE
|
||||
;;
|
||||
*)
|
||||
cat > Dockerfile <<DOCKERFILE
|
||||
FROM node:${MUNITOR_NODE_VERSION}-alpine AS deps
|
||||
WORKDIR /app
|
||||
COPY package*.json ./
|
||||
@@ -97,6 +159,8 @@ HEALTHCHECK --interval=30s --timeout=3s --start-period=10s --retries=3 \\
|
||||
CMD wget --no-verbose --tries=1 --spider http://localhost:${MUNITOR_HEALTH_PORT}${MUNITOR_HEALTH_PATH} || exit 1
|
||||
CMD ["node", "."]
|
||||
DOCKERFILE
|
||||
;;
|
||||
esac
|
||||
;;
|
||||
|
||||
*)
|
||||
@@ -198,7 +262,31 @@ DOCKERFILE
|
||||
|
||||
node-webapp)
|
||||
echo "Generating Dockerfile for node-webapp (node ${MUNITOR_NODE_VERSION})"
|
||||
cat > Dockerfile <<DOCKERFILE
|
||||
case "${MUNITOR_PACKAGE_MANAGER}" in
|
||||
pnpm)
|
||||
cat > Dockerfile <<DOCKERFILE
|
||||
FROM node:${MUNITOR_NODE_VERSION}-alpine AS builder
|
||||
WORKDIR /app
|
||||
RUN corepack enable
|
||||
COPY package.json pnpm-lock.yaml ./
|
||||
RUN pnpm install --frozen-lockfile
|
||||
COPY . .
|
||||
ARG GIT_COMMIT_SHA
|
||||
ENV GIT_COMMIT_SHA=\${GIT_COMMIT_SHA}
|
||||
RUN pnpm run build
|
||||
|
||||
FROM gcr.io/distroless/nodejs${MUNITOR_NODE_VERSION}-debian12 AS runner
|
||||
WORKDIR /app
|
||||
ENV NODE_ENV=production
|
||||
COPY --from=builder /app/.next/standalone ./
|
||||
COPY --from=builder /app/.next/static ./.next/static
|
||||
COPY --from=builder /app/public ./public
|
||||
EXPOSE ${MUNITOR_HEALTH_PORT}
|
||||
CMD ["server.js"]
|
||||
DOCKERFILE
|
||||
;;
|
||||
*)
|
||||
cat > Dockerfile <<DOCKERFILE
|
||||
FROM node:${MUNITOR_NODE_VERSION}-alpine AS builder
|
||||
WORKDIR /app
|
||||
COPY package*.json ./
|
||||
@@ -217,6 +305,8 @@ COPY --from=builder /app/public ./public
|
||||
EXPOSE ${MUNITOR_HEALTH_PORT}
|
||||
CMD ["server.js"]
|
||||
DOCKERFILE
|
||||
;;
|
||||
esac
|
||||
;;
|
||||
|
||||
*)
|
||||
|
||||
@@ -56,4 +56,20 @@ else
|
||||
echo "GitHub Release ${TAG} created."
|
||||
fi
|
||||
|
||||
# Upload release artifacts if specified
|
||||
if [[ -n "${MUNITOR_RELEASE_ARTIFACTS:-}" ]]; then
|
||||
echo "Uploading release artifacts: ${MUNITOR_RELEASE_ARTIFACTS}"
|
||||
for artifact in ${MUNITOR_RELEASE_ARTIFACTS}; do
|
||||
if [[ ! -f "${artifact}" ]]; then
|
||||
echo "ERROR: Release artifact '${artifact}' not found."
|
||||
echo " Working directory: $(pwd)"
|
||||
echo " Available files: $(ls -la)"
|
||||
exit 1
|
||||
fi
|
||||
done
|
||||
# shellcheck disable=SC2086
|
||||
gh release upload "${TAG}" ${MUNITOR_RELEASE_ARTIFACTS} --clobber
|
||||
echo "Artifacts uploaded to ${TAG}."
|
||||
fi
|
||||
|
||||
echo "github_release completed"
|
||||
@@ -64,3 +64,41 @@ NODE_BIN_DIR="$(dirname "$(command -v node)")"
|
||||
} >> "${BASH_ENV}"
|
||||
|
||||
echo " BASH_ENV: exported PATH with ${NODE_BIN_DIR}"
|
||||
|
||||
# Activate non-npm package managers via corepack
|
||||
PACKAGE_MANAGER="${MUNITOR_PACKAGE_MANAGER:-npm}"
|
||||
if [[ "${PACKAGE_MANAGER}" != "npm" ]]; then
|
||||
echo ""
|
||||
echo "=== Activating ${PACKAGE_MANAGER} via corepack ==="
|
||||
corepack enable
|
||||
|
||||
PM_VERSION=""
|
||||
if [[ -f "package.json" ]]; then
|
||||
# Priority 1: packageManager field (corepack-native, e.g. "pnpm@9.15.9")
|
||||
PM_FIELD=$(node -e "try{const p=require('./package.json').packageManager||'';console.log(p)}catch{console.log('')}" 2>/dev/null)
|
||||
if [[ "${PM_FIELD}" == "${PACKAGE_MANAGER}@"* ]]; then
|
||||
PM_VERSION="${PM_FIELD#*@}"
|
||||
fi
|
||||
|
||||
# Priority 2: engines field (e.g. "engines": {"pnpm": ">=9"})
|
||||
if [[ -z "${PM_VERSION}" ]]; then
|
||||
PM_VERSION=$(node -e "try{console.log(require('./package.json').engines?.['${PACKAGE_MANAGER}']||'')}catch{console.log('')}" 2>/dev/null)
|
||||
fi
|
||||
fi
|
||||
|
||||
if [[ -n "${PM_VERSION}" ]]; then
|
||||
echo " Detected version: ${PM_VERSION}"
|
||||
corepack prepare "${PACKAGE_MANAGER}@${PM_VERSION}" --activate
|
||||
else
|
||||
echo " No version constraint found, using corepack default"
|
||||
fi
|
||||
|
||||
echo " ${PACKAGE_MANAGER}: $(${PACKAGE_MANAGER} --version)"
|
||||
|
||||
# Export PM binary to BASH_ENV for downstream steps
|
||||
PM_BIN_DIR="$(dirname "$(command -v "${PACKAGE_MANAGER}")")"
|
||||
if [[ "${PM_BIN_DIR}" != "${NODE_BIN_DIR}" ]]; then
|
||||
echo "export PATH=\"${PM_BIN_DIR}:\${PATH}\"" >> "${BASH_ENV}"
|
||||
echo " BASH_ENV: exported PATH with ${PM_BIN_DIR}"
|
||||
fi
|
||||
fi
|
||||
@@ -11,7 +11,7 @@ elif ! type munitor_header &>/dev/null; then
|
||||
munitor_download_with_retry() { curl -fsSL --retry 3 "$1" -o "$2"; }
|
||||
fi
|
||||
|
||||
munitor_header "npm_audit"
|
||||
munitor_header "node_audit"
|
||||
|
||||
echo "Running npm audit..."
|
||||
|
||||
@@ -0,0 +1,88 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
# Source shared helpers
|
||||
MUNITOR_HELPERS="${MUNITOR_HELPERS:-$(cd "$(dirname "${BASH_SOURCE[0]:-$0}")" && pwd)/munitor_helpers.sh}"
|
||||
# shellcheck source=munitor_helpers.sh
|
||||
if [[ -f "${MUNITOR_HELPERS}" ]]; then source "${MUNITOR_HELPERS}"
|
||||
elif ! type munitor_header &>/dev/null; then
|
||||
munitor_header() { echo "=== Munitor: ${1:-unknown} ==="; }
|
||||
munitor_check_tool() { command -v "$1" &>/dev/null || { echo "ERROR: $1 not found"; exit 1; }; }
|
||||
munitor_download_with_retry() { curl -fsSL --retry 3 "$1" -o "$2"; }
|
||||
fi
|
||||
|
||||
MIN="${MIN_COVERAGE:-70}"
|
||||
COVERAGE_TOOL="${MUNITOR_COVERAGE_TOOL:-jest}"
|
||||
COVERAGE_COMMAND="${MUNITOR_COVERAGE_COMMAND:-}"
|
||||
SUMMARY_PATH="${MUNITOR_COVERAGE_SUMMARY_PATH:-coverage/coverage-summary.json}"
|
||||
|
||||
munitor_header "node_coverage_check (min: ${MIN}%)"
|
||||
munitor_check_tool node --version
|
||||
|
||||
# Validate MIN_COVERAGE is numeric
|
||||
if ! [[ "${MIN}" =~ ^[0-9]+$ ]]; then
|
||||
echo "ERROR: MIN_COVERAGE must be a whole number, got '${MIN}'."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "Checking coverage threshold (minimum: ${MIN}%, tool: ${COVERAGE_TOOL})..."
|
||||
|
||||
# Run custom coverage report command if specified
|
||||
if [[ -n "${COVERAGE_COMMAND}" ]]; then
|
||||
echo "Running coverage report command: ${COVERAGE_COMMAND}"
|
||||
bash -c "${COVERAGE_COMMAND}"
|
||||
fi
|
||||
|
||||
# Resolve summary file(s) - supports glob patterns for monorepos
|
||||
# shellcheck disable=SC2206
|
||||
SUMMARY_FILES=( ${SUMMARY_PATH} )
|
||||
|
||||
if [[ ${#SUMMARY_FILES[@]} -eq 0 ]] || [[ ! -f "${SUMMARY_FILES[0]}" ]]; then
|
||||
echo "ERROR: Coverage summary not found at ${SUMMARY_PATH}."
|
||||
echo ""
|
||||
echo " Ensure your test runner generates coverage-summary.json."
|
||||
echo " For monorepos, set test.coverage.summary_path in .munitor.yml:"
|
||||
echo " test:"
|
||||
echo " coverage:"
|
||||
echo " summary_path: \"packages/*/coverage/coverage-summary.json\""
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [[ ${#SUMMARY_FILES[@]} -eq 1 ]]; then
|
||||
# Single file - use directly
|
||||
SUMMARY_FILE="${SUMMARY_FILES[0]}"
|
||||
echo "Using coverage summary: ${SUMMARY_FILE}"
|
||||
|
||||
ACTUAL=$(node -e "
|
||||
const s = require('./${SUMMARY_FILE}');
|
||||
console.log(s.total.lines.pct);
|
||||
")
|
||||
else
|
||||
# Multiple files (monorepo) - compute weighted average
|
||||
echo "Found ${#SUMMARY_FILES[@]} coverage summaries (monorepo mode):"
|
||||
for f in "${SUMMARY_FILES[@]}"; do
|
||||
echo " - ${f}"
|
||||
done
|
||||
|
||||
ACTUAL=$(node -e "
|
||||
const files = process.argv.slice(1);
|
||||
let totalCovered = 0, totalTotal = 0;
|
||||
for (const f of files) {
|
||||
const s = require('./' + f);
|
||||
totalCovered += s.total.lines.covered;
|
||||
totalTotal += s.total.lines.total;
|
||||
}
|
||||
console.log(totalTotal > 0 ? ((totalCovered / totalTotal) * 100).toFixed(2) : '0');
|
||||
" "${SUMMARY_FILES[@]}")
|
||||
fi
|
||||
|
||||
echo "Line coverage: ${ACTUAL}%"
|
||||
|
||||
# Compare as integers (floor)
|
||||
ACTUAL_INT=${ACTUAL%.*}
|
||||
if [[ "${ACTUAL_INT}" -lt "${MIN}" ]]; then
|
||||
echo "FAIL: Coverage ${ACTUAL}% is below minimum ${MIN}%."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "Coverage check passed (${ACTUAL}% >= ${MIN}%)."
|
||||
@@ -0,0 +1,121 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
# Source shared helpers
|
||||
MUNITOR_HELPERS="${MUNITOR_HELPERS:-$(cd "$(dirname "${BASH_SOURCE[0]:-$0}")" && pwd)/munitor_helpers.sh}"
|
||||
# shellcheck source=munitor_helpers.sh
|
||||
if [[ -f "${MUNITOR_HELPERS}" ]]; then source "${MUNITOR_HELPERS}"
|
||||
elif ! type munitor_header &>/dev/null; then
|
||||
munitor_header() { echo "=== Munitor: ${1:-unknown} ==="; }
|
||||
munitor_check_tool() { command -v "$1" &>/dev/null || { echo "ERROR: $1 not found"; exit 1; }; }
|
||||
munitor_download_with_retry() { curl -fsSL --retry 3 "$1" -o "$2"; }
|
||||
fi
|
||||
|
||||
PACKAGE_MANAGER="${MUNITOR_PACKAGE_MANAGER:-npm}"
|
||||
|
||||
munitor_header "node_install_deps (${PACKAGE_MANAGER})"
|
||||
munitor_check_tool node --version
|
||||
|
||||
case "${PACKAGE_MANAGER}" in
|
||||
npm)
|
||||
munitor_check_tool npm --version
|
||||
|
||||
# Verify package-lock.json exists
|
||||
if [[ ! -f "package-lock.json" ]]; then
|
||||
echo "ERROR: package-lock.json not found in $(pwd)"
|
||||
echo " npm ci requires a lockfile. Run 'npm install' locally and commit the lockfile."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Check lockfile version compatibility
|
||||
LOCKFILE_VERSION=$(node -e "console.log(require('./package-lock.json').lockfileVersion || 'unknown')" 2>/dev/null || echo "unknown")
|
||||
NPM_MAJOR=$(npm --version 2>/dev/null | cut -d. -f1)
|
||||
echo " lockfileVersion: ${LOCKFILE_VERSION}"
|
||||
|
||||
if [[ "${LOCKFILE_VERSION}" == "3" && -n "${NPM_MAJOR}" && "${NPM_MAJOR}" -lt 11 ]]; then
|
||||
echo ""
|
||||
echo "WARNING: package-lock.json uses lockfileVersion 3 (npm 11+)"
|
||||
echo " but CI is running npm ${NPM_MAJOR} ($(npm --version))."
|
||||
echo " This will likely cause 'npm ci' to fail."
|
||||
echo ""
|
||||
echo " Fix: regenerate your lockfile with the same Node version CI uses."
|
||||
echo " Add an .nvmrc to your repo to keep local and CI versions in sync."
|
||||
echo ""
|
||||
fi
|
||||
|
||||
echo ""
|
||||
echo "Running npm ci..."
|
||||
npm ci
|
||||
|
||||
PKG_COUNT=$(find node_modules -maxdepth 1 -mindepth 1 -type d | wc -l | tr -d ' ')
|
||||
echo "npm ci complete. ${PKG_COUNT} packages installed."
|
||||
;;
|
||||
|
||||
pnpm)
|
||||
munitor_check_tool pnpm --version
|
||||
|
||||
# Verify pnpm-lock.yaml exists
|
||||
if [[ ! -f "pnpm-lock.yaml" ]]; then
|
||||
echo "ERROR: pnpm-lock.yaml not found in $(pwd)"
|
||||
echo " pnpm install --frozen-lockfile requires a lockfile. Run 'pnpm install' locally and commit the lockfile."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo ""
|
||||
echo "Running pnpm install --frozen-lockfile..."
|
||||
pnpm install --frozen-lockfile
|
||||
|
||||
PKG_COUNT=$(find node_modules -maxdepth 1 -mindepth 1 -type d | wc -l | tr -d ' ')
|
||||
echo "pnpm install complete. ${PKG_COUNT} packages installed."
|
||||
;;
|
||||
|
||||
*)
|
||||
echo "ERROR: Unsupported package manager '${PACKAGE_MANAGER}'"
|
||||
echo " Supported values: npm, pnpm"
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
|
||||
# Prisma auto-detection: generate client if schema files are present
|
||||
PRISMA_SCHEMAS=$(find . -path "*/prisma/schema.prisma" -not -path "*/node_modules/*" -not -path "*/dist/*" -not -path "*/build/*" 2>/dev/null || true)
|
||||
|
||||
if [[ -n "${PRISMA_SCHEMAS}" ]]; then
|
||||
echo ""
|
||||
echo "=== Prisma schema(s) detected ==="
|
||||
|
||||
PRISMA_GENERATED=0
|
||||
while IFS= read -r SCHEMA_PATH; do
|
||||
# Resolve the package directory (parent of prisma/)
|
||||
PKG_DIR=$(dirname "$(dirname "${SCHEMA_PATH}")")
|
||||
|
||||
# Check if prisma CLI is available from the package directory.
|
||||
# In monorepos, prisma may only be installed in a workspace package,
|
||||
# not at the root, so we must check from the package's own context.
|
||||
PRISMA_CMD=""
|
||||
case "${PACKAGE_MANAGER}" in
|
||||
npm)
|
||||
if (cd "${PKG_DIR}" && npx prisma --version) &>/dev/null; then
|
||||
PRISMA_CMD="npx prisma"
|
||||
fi
|
||||
;;
|
||||
pnpm)
|
||||
if (cd "${PKG_DIR}" && pnpm exec prisma --version) &>/dev/null; then
|
||||
PRISMA_CMD="pnpm exec prisma"
|
||||
fi
|
||||
;;
|
||||
esac
|
||||
|
||||
if [[ -n "${PRISMA_CMD}" ]]; then
|
||||
echo " Generating Prisma client for: ${SCHEMA_PATH}"
|
||||
(cd "${PKG_DIR}" && ${PRISMA_CMD} generate --schema=prisma/schema.prisma)
|
||||
PRISMA_GENERATED=$((PRISMA_GENERATED + 1))
|
||||
else
|
||||
echo " WARNING: Found ${SCHEMA_PATH} but prisma CLI not available in ${PKG_DIR}."
|
||||
echo " Add prisma as a dev dependency in that package."
|
||||
fi
|
||||
done <<< "${PRISMA_SCHEMAS}"
|
||||
|
||||
if [[ "${PRISMA_GENERATED}" -gt 0 ]]; then
|
||||
echo "Prisma generate complete (${PRISMA_GENERATED} schema(s))."
|
||||
fi
|
||||
fi
|
||||
@@ -11,7 +11,7 @@ elif ! type munitor_header &>/dev/null; then
|
||||
munitor_download_with_retry() { curl -fsSL --retry 3 "$1" -o "$2"; }
|
||||
fi
|
||||
|
||||
munitor_header "npm_lint"
|
||||
munitor_header "node_lint"
|
||||
|
||||
echo "Running ESLint..."
|
||||
|
||||
@@ -11,7 +11,7 @@ elif ! type munitor_header &>/dev/null; then
|
||||
munitor_download_with_retry() { curl -fsSL --retry 3 "$1" -o "$2"; }
|
||||
fi
|
||||
|
||||
munitor_header "npm_sbom"
|
||||
munitor_header "node_sbom"
|
||||
munitor_check_tool node --version
|
||||
munitor_check_tool npx --version
|
||||
|
||||
@@ -11,7 +11,7 @@ elif ! type munitor_header &>/dev/null; then
|
||||
munitor_download_with_retry() { curl -fsSL --retry 3 "$1" -o "$2"; }
|
||||
fi
|
||||
|
||||
munitor_header "npm_sonar"
|
||||
munitor_header "node_sonar"
|
||||
|
||||
PROJECT_KEY="${SONAR_PROJECT_KEY:?SONAR_PROJECT_KEY not set}"
|
||||
ORG="${SONAR_ORG:-KofTwentyTwo}"
|
||||
@@ -11,7 +11,7 @@ elif ! type munitor_header &>/dev/null; then
|
||||
munitor_download_with_retry() { curl -fsSL --retry 3 "$1" -o "$2"; }
|
||||
fi
|
||||
|
||||
munitor_header "npm_test"
|
||||
munitor_header "node_test"
|
||||
|
||||
# Prevent interactive prompts from apt/dpkg when test commands install system deps
|
||||
export DEBIAN_FRONTEND=noninteractive
|
||||
@@ -34,36 +34,44 @@ if [[ -n "${TEST_COMMANDS_JSON}" && "${TEST_COMMANDS_JSON}" != "[]" && "${TEST_C
|
||||
|
||||
echo "Custom test commands complete."
|
||||
else
|
||||
# Default: Jest with coverage and JUnit reporter
|
||||
if ! npx jest --version &>/dev/null; then
|
||||
echo ""
|
||||
echo "ERROR: Jest is not installed and no custom test commands are configured."
|
||||
echo ""
|
||||
echo " Munitor defaults to 'npx jest' but this project doesn't have Jest."
|
||||
echo " Add custom test commands to your .munitor.yml:"
|
||||
echo ""
|
||||
echo " test:"
|
||||
echo " commands:"
|
||||
echo " - \"npm test\""
|
||||
echo ""
|
||||
echo " Or install Jest: npm install --save-dev jest"
|
||||
echo ""
|
||||
exit 1
|
||||
PACKAGE_MANAGER="${MUNITOR_PACKAGE_MANAGER:-npm}"
|
||||
|
||||
if [[ "${PACKAGE_MANAGER}" == "pnpm" ]]; then
|
||||
echo "Running pnpm test..."
|
||||
pnpm test
|
||||
echo "pnpm test complete."
|
||||
else
|
||||
# Default: Jest with coverage and JUnit reporter
|
||||
if ! npx jest --version &>/dev/null; then
|
||||
echo ""
|
||||
echo "ERROR: Jest is not installed and no custom test commands are configured."
|
||||
echo ""
|
||||
echo " Munitor defaults to 'npx jest' but this project doesn't have Jest."
|
||||
echo " Add custom test commands to your .munitor.yml:"
|
||||
echo ""
|
||||
echo " test:"
|
||||
echo " commands:"
|
||||
echo " - \"npm test\""
|
||||
echo ""
|
||||
echo " Or install Jest: npm install --save-dev jest"
|
||||
echo ""
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "Running Jest tests..."
|
||||
|
||||
export JEST_JUNIT_OUTPUT_DIR="reports/junit"
|
||||
export JEST_JUNIT_OUTPUT_NAME="results.xml"
|
||||
|
||||
npx jest \
|
||||
--ci \
|
||||
--forceExit \
|
||||
--coverage \
|
||||
--coverageReporters=json-summary \
|
||||
--coverageReporters=lcov \
|
||||
--reporters=default \
|
||||
--reporters=jest-junit
|
||||
|
||||
echo "Jest tests complete."
|
||||
fi
|
||||
|
||||
echo "Running Jest tests..."
|
||||
|
||||
export JEST_JUNIT_OUTPUT_DIR="reports/junit"
|
||||
export JEST_JUNIT_OUTPUT_NAME="results.xml"
|
||||
|
||||
npx jest \
|
||||
--ci \
|
||||
--forceExit \
|
||||
--coverage \
|
||||
--coverageReporters=json-summary \
|
||||
--coverageReporters=lcov \
|
||||
--reporters=default \
|
||||
--reporters=jest-junit
|
||||
|
||||
echo "Jest tests complete."
|
||||
fi
|
||||
@@ -1,57 +0,0 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
# Source shared helpers
|
||||
MUNITOR_HELPERS="${MUNITOR_HELPERS:-$(cd "$(dirname "${BASH_SOURCE[0]:-$0}")" && pwd)/munitor_helpers.sh}"
|
||||
# shellcheck source=munitor_helpers.sh
|
||||
if [[ -f "${MUNITOR_HELPERS}" ]]; then source "${MUNITOR_HELPERS}"
|
||||
elif ! type munitor_header &>/dev/null; then
|
||||
munitor_header() { echo "=== Munitor: ${1:-unknown} ==="; }
|
||||
munitor_check_tool() { command -v "$1" &>/dev/null || { echo "ERROR: $1 not found"; exit 1; }; }
|
||||
munitor_download_with_retry() { curl -fsSL --retry 3 "$1" -o "$2"; }
|
||||
fi
|
||||
|
||||
MIN="${MIN_COVERAGE:-70}"
|
||||
COVERAGE_TOOL="${MUNITOR_COVERAGE_TOOL:-jest}"
|
||||
COVERAGE_COMMAND="${MUNITOR_COVERAGE_COMMAND:-}"
|
||||
SUMMARY_FILE="coverage/coverage-summary.json"
|
||||
|
||||
munitor_header "npm_coverage_check (min: ${MIN}%)"
|
||||
munitor_check_tool node --version
|
||||
|
||||
# Validate MIN_COVERAGE is numeric
|
||||
if ! [[ "${MIN}" =~ ^[0-9]+$ ]]; then
|
||||
echo "ERROR: MIN_COVERAGE must be a whole number, got '${MIN}'."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "Checking coverage threshold (minimum: ${MIN}%, tool: ${COVERAGE_TOOL})..."
|
||||
|
||||
# Run custom coverage report command if specified
|
||||
if [[ -n "${COVERAGE_COMMAND}" ]]; then
|
||||
echo "Running coverage report command: ${COVERAGE_COMMAND}"
|
||||
bash -c "${COVERAGE_COMMAND}"
|
||||
fi
|
||||
|
||||
if [[ ! -f "${SUMMARY_FILE}" ]]; then
|
||||
echo "ERROR: Coverage summary not found at ${SUMMARY_FILE}."
|
||||
echo "Ensure your test runner generates coverage/coverage-summary.json."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Extract total line coverage percentage from summary (same format for jest and nyc)
|
||||
ACTUAL=$(node -e "
|
||||
const s = require('./${SUMMARY_FILE}');
|
||||
console.log(s.total.lines.pct);
|
||||
")
|
||||
|
||||
echo "Line coverage: ${ACTUAL}%"
|
||||
|
||||
# Compare as integers (floor)
|
||||
ACTUAL_INT=${ACTUAL%.*}
|
||||
if [[ "${ACTUAL_INT}" -lt "${MIN}" ]]; then
|
||||
echo "FAIL: Coverage ${ACTUAL}% is below minimum ${MIN}%."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "Coverage check passed (${ACTUAL}% >= ${MIN}%)."
|
||||
@@ -1,46 +0,0 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
# Source shared helpers
|
||||
MUNITOR_HELPERS="${MUNITOR_HELPERS:-$(cd "$(dirname "${BASH_SOURCE[0]:-$0}")" && pwd)/munitor_helpers.sh}"
|
||||
# shellcheck source=munitor_helpers.sh
|
||||
if [[ -f "${MUNITOR_HELPERS}" ]]; then source "${MUNITOR_HELPERS}"
|
||||
elif ! type munitor_header &>/dev/null; then
|
||||
munitor_header() { echo "=== Munitor: ${1:-unknown} ==="; }
|
||||
munitor_check_tool() { command -v "$1" &>/dev/null || { echo "ERROR: $1 not found"; exit 1; }; }
|
||||
munitor_download_with_retry() { curl -fsSL --retry 3 "$1" -o "$2"; }
|
||||
fi
|
||||
|
||||
munitor_header "npm_install"
|
||||
munitor_check_tool node --version
|
||||
munitor_check_tool npm --version
|
||||
|
||||
# Verify package-lock.json exists
|
||||
if [[ ! -f "package-lock.json" ]]; then
|
||||
echo "ERROR: package-lock.json not found in $(pwd)"
|
||||
echo " npm ci requires a lockfile. Run 'npm install' locally and commit the lockfile."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Check lockfile version compatibility
|
||||
LOCKFILE_VERSION=$(node -e "console.log(require('./package-lock.json').lockfileVersion || 'unknown')" 2>/dev/null || echo "unknown")
|
||||
NPM_MAJOR=$(npm --version 2>/dev/null | cut -d. -f1)
|
||||
echo " lockfileVersion: ${LOCKFILE_VERSION}"
|
||||
|
||||
if [[ "${LOCKFILE_VERSION}" == "3" && -n "${NPM_MAJOR}" && "${NPM_MAJOR}" -lt 11 ]]; then
|
||||
echo ""
|
||||
echo "WARNING: package-lock.json uses lockfileVersion 3 (npm 11+)"
|
||||
echo " but CI is running npm ${NPM_MAJOR} ($(npm --version))."
|
||||
echo " This will likely cause 'npm ci' to fail."
|
||||
echo ""
|
||||
echo " Fix: regenerate your lockfile with the same Node version CI uses."
|
||||
echo " Add an .nvmrc to your repo to keep local and CI versions in sync."
|
||||
echo ""
|
||||
fi
|
||||
|
||||
echo ""
|
||||
echo "Running npm ci..."
|
||||
npm ci
|
||||
|
||||
PKG_COUNT=$(find node_modules -maxdepth 1 -mindepth 1 -type d | wc -l | tr -d ' ')
|
||||
echo "npm ci complete. ${PKG_COUNT} packages installed."
|
||||
@@ -193,6 +193,7 @@ extract_munitor_vars() {
|
||||
if [[ -n "${MUNITOR_TEST_COVERAGE_MIN}" ]]; then
|
||||
MUNITOR_COVERAGE_MIN="${MUNITOR_TEST_COVERAGE_MIN}"
|
||||
fi
|
||||
MUNITOR_COVERAGE_SUMMARY_PATH=$(yq '.test.coverage.summary_path // "coverage/coverage-summary.json"' "${config_file}")
|
||||
|
||||
# Terraform pipeline settings
|
||||
MUNITOR_TF_PATH=$(yq '.terraform.path // "terraform/"' "${config_file}")
|
||||
@@ -311,7 +312,7 @@ extract_munitor_vars() {
|
||||
export MUNITOR_SERVICES MUNITOR_SERVICES_JSON
|
||||
export MUNITOR_TEST_SETUP MUNITOR_TEST_SETUP_SCRIPT
|
||||
export MUNITOR_CUSTOM_TEST MUNITOR_TEST_COMMANDS_JSON
|
||||
export MUNITOR_COVERAGE_TOOL MUNITOR_COVERAGE_CMD MUNITOR_COVERAGE_COMMAND
|
||||
export MUNITOR_COVERAGE_TOOL MUNITOR_COVERAGE_CMD MUNITOR_COVERAGE_COMMAND MUNITOR_COVERAGE_SUMMARY_PATH
|
||||
export MUNITOR_TF_PATH MUNITOR_TF_LIVE_PATH MUNITOR_TF_ENVIRONMENTS MUNITOR_CHECKOV_SKIP MUNITOR_SAST MUNITOR_SAST_FAIL_ON_FINDINGS
|
||||
export MUNITOR_KUSTOMIZE_VERSION MUNITOR_KUSTOMIZE_BASE_PATH MUNITOR_KUSTOMIZE_LOAD_RESTRICTOR
|
||||
export MUNITOR_KUSTOMIZE_SCAN_OVERLAY MUNITOR_KUSTOMIZE_OVERLAYS MUNITOR_KUSTOMIZE_OVERLAY_DIR
|
||||
@@ -326,7 +327,7 @@ extract_munitor_vars() {
|
||||
# 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}'
|
||||
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}'
|
||||
}
|
||||
MUNITOR_EXTRACT_EOF
|
||||
|
||||
@@ -983,9 +984,10 @@ orbs:
|
||||
workflows:
|
||||
pr-checks:
|
||||
jobs:
|
||||
- munitor/npm_build_and_test:
|
||||
- munitor/node_build_and_test:
|
||||
name: build-and-test
|
||||
node_version: "${MUNITOR_NODE_VERSION}"
|
||||
package_manager: "${MUNITOR_PACKAGE_MANAGER}"
|
||||
##IF_NPM_AUTH##
|
||||
npm_auth: true
|
||||
npm_scopes: '${MUNITOR_NPM_SCOPES}'
|
||||
@@ -1022,8 +1024,10 @@ workflows:
|
||||
only:
|
||||
- /feature\/.*/
|
||||
- /hotfix\/.*/
|
||||
- munitor/npm_code_quality:
|
||||
- munitor/node_code_quality:
|
||||
name: code-quality
|
||||
node_version: "${MUNITOR_NODE_VERSION}"
|
||||
package_manager: "${MUNITOR_PACKAGE_MANAGER}"
|
||||
requires:
|
||||
- build-and-test
|
||||
filters:
|
||||
@@ -1031,10 +1035,13 @@ workflows:
|
||||
only:
|
||||
- /feature\/.*/
|
||||
- /hotfix\/.*/
|
||||
- munitor/npm_coverage:
|
||||
- munitor/node_coverage:
|
||||
name: coverage
|
||||
node_version: "${MUNITOR_NODE_VERSION}"
|
||||
package_manager: "${MUNITOR_PACKAGE_MANAGER}"
|
||||
min_coverage: "${MUNITOR_COVERAGE_MIN}"
|
||||
coverage_tool: ${MUNITOR_COVERAGE_TOOL}
|
||||
coverage_summary_path: "${MUNITOR_COVERAGE_SUMMARY_PATH}"
|
||||
##IF_COVERAGE_CMD##
|
||||
coverage_command: ${MUNITOR_COVERAGE_COMMAND}
|
||||
##ENDIF_COVERAGE_CMD##
|
||||
@@ -1045,8 +1052,10 @@ workflows:
|
||||
only:
|
||||
- /feature\/.*/
|
||||
- /hotfix\/.*/
|
||||
- munitor/npm_security_scan:
|
||||
- munitor/node_security_scan:
|
||||
name: security-scan
|
||||
node_version: "${MUNITOR_NODE_VERSION}"
|
||||
package_manager: "${MUNITOR_PACKAGE_MANAGER}"
|
||||
requires:
|
||||
- build-and-test
|
||||
filters:
|
||||
@@ -1055,8 +1064,10 @@ workflows:
|
||||
- /feature\/.*/
|
||||
- /hotfix\/.*/
|
||||
##IF_E2E##
|
||||
- munitor/npm_e2e_test:
|
||||
- munitor/node_e2e_test:
|
||||
name: e2e-tests
|
||||
node_version: "${MUNITOR_NODE_VERSION}"
|
||||
package_manager: "${MUNITOR_PACKAGE_MANAGER}"
|
||||
requires:
|
||||
- build-and-test
|
||||
filters:
|
||||
@@ -1071,9 +1082,10 @@ workflows:
|
||||
|
||||
release-candidate:
|
||||
jobs:
|
||||
- munitor/npm_build_and_test:
|
||||
- munitor/node_build_and_test:
|
||||
name: build-and-test
|
||||
node_version: "${MUNITOR_NODE_VERSION}"
|
||||
package_manager: "${MUNITOR_PACKAGE_MANAGER}"
|
||||
##IF_NPM_AUTH##
|
||||
npm_auth: true
|
||||
npm_scopes: '${MUNITOR_NPM_SCOPES}'
|
||||
@@ -1107,18 +1119,23 @@ workflows:
|
||||
branches:
|
||||
only:
|
||||
- /release\/.*/
|
||||
- munitor/npm_code_quality:
|
||||
- munitor/node_code_quality:
|
||||
name: code-quality
|
||||
node_version: "${MUNITOR_NODE_VERSION}"
|
||||
package_manager: "${MUNITOR_PACKAGE_MANAGER}"
|
||||
requires:
|
||||
- build-and-test
|
||||
filters:
|
||||
branches:
|
||||
only:
|
||||
- /release\/.*/
|
||||
- munitor/npm_coverage:
|
||||
- munitor/node_coverage:
|
||||
name: coverage
|
||||
node_version: "${MUNITOR_NODE_VERSION}"
|
||||
package_manager: "${MUNITOR_PACKAGE_MANAGER}"
|
||||
min_coverage: "${MUNITOR_COVERAGE_MIN}"
|
||||
coverage_tool: ${MUNITOR_COVERAGE_TOOL}
|
||||
coverage_summary_path: "${MUNITOR_COVERAGE_SUMMARY_PATH}"
|
||||
##IF_COVERAGE_CMD##
|
||||
coverage_command: ${MUNITOR_COVERAGE_COMMAND}
|
||||
##ENDIF_COVERAGE_CMD##
|
||||
@@ -1128,8 +1145,10 @@ workflows:
|
||||
branches:
|
||||
only:
|
||||
- /release\/.*/
|
||||
- munitor/npm_security_scan:
|
||||
- munitor/node_security_scan:
|
||||
name: security-scan
|
||||
node_version: "${MUNITOR_NODE_VERSION}"
|
||||
package_manager: "${MUNITOR_PACKAGE_MANAGER}"
|
||||
requires:
|
||||
- build-and-test
|
||||
filters:
|
||||
@@ -1137,8 +1156,10 @@ workflows:
|
||||
only:
|
||||
- /release\/.*/
|
||||
##IF_E2E##
|
||||
- munitor/npm_e2e_test:
|
||||
- munitor/node_e2e_test:
|
||||
name: e2e-tests
|
||||
node_version: "${MUNITOR_NODE_VERSION}"
|
||||
package_manager: "${MUNITOR_PACKAGE_MANAGER}"
|
||||
requires:
|
||||
- build-and-test
|
||||
filters:
|
||||
@@ -1147,9 +1168,10 @@ workflows:
|
||||
- /release\/.*/
|
||||
##ENDIF_E2E##
|
||||
##IF_SONAR##
|
||||
- munitor/npm_sonar_scan:
|
||||
- munitor/node_sonar_scan:
|
||||
name: sonar-scan
|
||||
node_version: "${MUNITOR_NODE_VERSION}"
|
||||
package_manager: "${MUNITOR_PACKAGE_MANAGER}"
|
||||
sonar_project_key: ${MUNITOR_SONAR_PROJECT_KEY}
|
||||
requires:
|
||||
- build-and-test
|
||||
@@ -1187,9 +1209,10 @@ workflows:
|
||||
only:
|
||||
- /release\/.*/
|
||||
##IF_SBOM##
|
||||
- munitor/npm_sbom:
|
||||
- munitor/node_sbom:
|
||||
name: sbom
|
||||
node_version: "${MUNITOR_NODE_VERSION}"
|
||||
package_manager: "${MUNITOR_PACKAGE_MANAGER}"
|
||||
context:
|
||||
- ${MUNITOR_CONTEXT_GITHUB}
|
||||
requires:
|
||||
@@ -1242,9 +1265,10 @@ workflows:
|
||||
|
||||
production:
|
||||
jobs:
|
||||
- munitor/npm_build_and_test:
|
||||
- munitor/node_build_and_test:
|
||||
name: build-and-test
|
||||
node_version: "${MUNITOR_NODE_VERSION}"
|
||||
package_manager: "${MUNITOR_PACKAGE_MANAGER}"
|
||||
##IF_NPM_AUTH##
|
||||
npm_auth: true
|
||||
npm_scopes: '${MUNITOR_NPM_SCOPES}'
|
||||
@@ -1323,9 +1347,10 @@ orbs:
|
||||
workflows:
|
||||
pr-checks:
|
||||
jobs:
|
||||
- munitor/npm_build_and_test:
|
||||
- munitor/node_build_and_test:
|
||||
name: build-and-test
|
||||
node_version: "${MUNITOR_NODE_VERSION}"
|
||||
package_manager: "${MUNITOR_PACKAGE_MANAGER}"
|
||||
##IF_NPM_AUTH##
|
||||
npm_auth: true
|
||||
npm_scopes: '${MUNITOR_NPM_SCOPES}'
|
||||
@@ -1362,8 +1387,10 @@ workflows:
|
||||
only:
|
||||
- /feature\/.*/
|
||||
- /hotfix\/.*/
|
||||
- munitor/npm_code_quality:
|
||||
- munitor/node_code_quality:
|
||||
name: code-quality
|
||||
node_version: "${MUNITOR_NODE_VERSION}"
|
||||
package_manager: "${MUNITOR_PACKAGE_MANAGER}"
|
||||
requires:
|
||||
- build-and-test
|
||||
filters:
|
||||
@@ -1371,10 +1398,13 @@ workflows:
|
||||
only:
|
||||
- /feature\/.*/
|
||||
- /hotfix\/.*/
|
||||
- munitor/npm_coverage:
|
||||
- munitor/node_coverage:
|
||||
name: coverage
|
||||
node_version: "${MUNITOR_NODE_VERSION}"
|
||||
package_manager: "${MUNITOR_PACKAGE_MANAGER}"
|
||||
min_coverage: "${MUNITOR_COVERAGE_MIN}"
|
||||
coverage_tool: ${MUNITOR_COVERAGE_TOOL}
|
||||
coverage_summary_path: "${MUNITOR_COVERAGE_SUMMARY_PATH}"
|
||||
##IF_COVERAGE_CMD##
|
||||
coverage_command: ${MUNITOR_COVERAGE_COMMAND}
|
||||
##ENDIF_COVERAGE_CMD##
|
||||
@@ -1385,8 +1415,10 @@ workflows:
|
||||
only:
|
||||
- /feature\/.*/
|
||||
- /hotfix\/.*/
|
||||
- munitor/npm_security_scan:
|
||||
- munitor/node_security_scan:
|
||||
name: security-scan
|
||||
node_version: "${MUNITOR_NODE_VERSION}"
|
||||
package_manager: "${MUNITOR_PACKAGE_MANAGER}"
|
||||
requires:
|
||||
- build-and-test
|
||||
filters:
|
||||
@@ -1395,8 +1427,10 @@ workflows:
|
||||
- /feature\/.*/
|
||||
- /hotfix\/.*/
|
||||
##IF_E2E##
|
||||
- munitor/npm_e2e_test:
|
||||
- munitor/node_e2e_test:
|
||||
name: e2e-tests
|
||||
node_version: "${MUNITOR_NODE_VERSION}"
|
||||
package_manager: "${MUNITOR_PACKAGE_MANAGER}"
|
||||
requires:
|
||||
- build-and-test
|
||||
filters:
|
||||
@@ -1411,9 +1445,10 @@ workflows:
|
||||
|
||||
release-candidate:
|
||||
jobs:
|
||||
- munitor/npm_build_and_test:
|
||||
- munitor/node_build_and_test:
|
||||
name: build-and-test
|
||||
node_version: "${MUNITOR_NODE_VERSION}"
|
||||
package_manager: "${MUNITOR_PACKAGE_MANAGER}"
|
||||
##IF_NPM_AUTH##
|
||||
npm_auth: true
|
||||
npm_scopes: '${MUNITOR_NPM_SCOPES}'
|
||||
@@ -1447,18 +1482,23 @@ workflows:
|
||||
branches:
|
||||
only:
|
||||
- /release\/.*/
|
||||
- munitor/npm_code_quality:
|
||||
- munitor/node_code_quality:
|
||||
name: code-quality
|
||||
node_version: "${MUNITOR_NODE_VERSION}"
|
||||
package_manager: "${MUNITOR_PACKAGE_MANAGER}"
|
||||
requires:
|
||||
- build-and-test
|
||||
filters:
|
||||
branches:
|
||||
only:
|
||||
- /release\/.*/
|
||||
- munitor/npm_coverage:
|
||||
- munitor/node_coverage:
|
||||
name: coverage
|
||||
node_version: "${MUNITOR_NODE_VERSION}"
|
||||
package_manager: "${MUNITOR_PACKAGE_MANAGER}"
|
||||
min_coverage: "${MUNITOR_COVERAGE_MIN}"
|
||||
coverage_tool: ${MUNITOR_COVERAGE_TOOL}
|
||||
coverage_summary_path: "${MUNITOR_COVERAGE_SUMMARY_PATH}"
|
||||
##IF_COVERAGE_CMD##
|
||||
coverage_command: ${MUNITOR_COVERAGE_COMMAND}
|
||||
##ENDIF_COVERAGE_CMD##
|
||||
@@ -1468,8 +1508,10 @@ workflows:
|
||||
branches:
|
||||
only:
|
||||
- /release\/.*/
|
||||
- munitor/npm_security_scan:
|
||||
- munitor/node_security_scan:
|
||||
name: security-scan
|
||||
node_version: "${MUNITOR_NODE_VERSION}"
|
||||
package_manager: "${MUNITOR_PACKAGE_MANAGER}"
|
||||
requires:
|
||||
- build-and-test
|
||||
filters:
|
||||
@@ -1477,8 +1519,10 @@ workflows:
|
||||
only:
|
||||
- /release\/.*/
|
||||
##IF_E2E##
|
||||
- munitor/npm_e2e_test:
|
||||
- munitor/node_e2e_test:
|
||||
name: e2e-tests
|
||||
node_version: "${MUNITOR_NODE_VERSION}"
|
||||
package_manager: "${MUNITOR_PACKAGE_MANAGER}"
|
||||
requires:
|
||||
- build-and-test
|
||||
filters:
|
||||
@@ -1487,9 +1531,10 @@ workflows:
|
||||
- /release\/.*/
|
||||
##ENDIF_E2E##
|
||||
##IF_SONAR##
|
||||
- munitor/npm_sonar_scan:
|
||||
- munitor/node_sonar_scan:
|
||||
name: sonar-scan
|
||||
node_version: "${MUNITOR_NODE_VERSION}"
|
||||
package_manager: "${MUNITOR_PACKAGE_MANAGER}"
|
||||
sonar_project_key: ${MUNITOR_SONAR_PROJECT_KEY}
|
||||
requires:
|
||||
- build-and-test
|
||||
@@ -1527,9 +1572,10 @@ workflows:
|
||||
only:
|
||||
- /release\/.*/
|
||||
##IF_SBOM##
|
||||
- munitor/npm_sbom:
|
||||
- munitor/node_sbom:
|
||||
name: sbom
|
||||
node_version: "${MUNITOR_NODE_VERSION}"
|
||||
package_manager: "${MUNITOR_PACKAGE_MANAGER}"
|
||||
context:
|
||||
- ${MUNITOR_CONTEXT_GITHUB}
|
||||
requires:
|
||||
@@ -1582,9 +1628,10 @@ workflows:
|
||||
|
||||
production:
|
||||
jobs:
|
||||
- munitor/npm_build_and_test:
|
||||
- munitor/node_build_and_test:
|
||||
name: build-and-test
|
||||
node_version: "${MUNITOR_NODE_VERSION}"
|
||||
package_manager: "${MUNITOR_PACKAGE_MANAGER}"
|
||||
##IF_NPM_AUTH##
|
||||
npm_auth: true
|
||||
npm_scopes: '${MUNITOR_NPM_SCOPES}'
|
||||
@@ -2108,6 +2155,322 @@ workflows:
|
||||
only: main
|
||||
MUNITOR_TPL_EOF
|
||||
|
||||
cat > /tmp/munitor/templates/obsidian-plugin.yml.tpl << 'MUNITOR_TPL_EOF'
|
||||
version: 2.1
|
||||
|
||||
orbs:
|
||||
munitor: ${MUNITOR_ORB_SLUG}@${MUNITOR_ORB_VERSION}
|
||||
|
||||
workflows:
|
||||
pr-checks:
|
||||
jobs:
|
||||
- munitor/node_build_and_test:
|
||||
name: build-and-test
|
||||
node_version: "${MUNITOR_NODE_VERSION}"
|
||||
package_manager: "${MUNITOR_PACKAGE_MANAGER}"
|
||||
##IF_NPM_AUTH##
|
||||
npm_auth: true
|
||||
npm_scopes: '${MUNITOR_NPM_SCOPES}'
|
||||
npm_default_scope: '${MUNITOR_NPM_DEFAULT_SCOPE}'
|
||||
##ENDIF_NPM_AUTH##
|
||||
##IF_SERVICES##
|
||||
services: '${MUNITOR_SERVICES_JSON}'
|
||||
##ENDIF_SERVICES##
|
||||
##IF_TEST_SETUP##
|
||||
test_setup: ${MUNITOR_TEST_SETUP_SCRIPT}
|
||||
##ENDIF_TEST_SETUP##
|
||||
##IF_CUSTOM_TEST##
|
||||
test_commands: '${MUNITOR_TEST_COMMANDS_JSON}'
|
||||
##ENDIF_CUSTOM_TEST##
|
||||
context:
|
||||
- ${MUNITOR_CONTEXT_GITHUB}
|
||||
filters:
|
||||
branches:
|
||||
only:
|
||||
- /feature\/.*/
|
||||
- /hotfix\/.*/
|
||||
- munitor/secrets_scan:
|
||||
name: secrets-scan
|
||||
filters:
|
||||
branches:
|
||||
only:
|
||||
- /feature\/.*/
|
||||
- /hotfix\/.*/
|
||||
##IF_SAST##
|
||||
- munitor/sast_scan:
|
||||
name: sast-scan
|
||||
fail_on_findings: "${MUNITOR_SAST_FAIL_ON_FINDINGS}"
|
||||
filters:
|
||||
branches:
|
||||
only:
|
||||
- /feature\/.*/
|
||||
- /hotfix\/.*/
|
||||
##ENDIF_SAST##
|
||||
- munitor/node_code_quality:
|
||||
name: code-quality
|
||||
node_version: "${MUNITOR_NODE_VERSION}"
|
||||
package_manager: "${MUNITOR_PACKAGE_MANAGER}"
|
||||
requires:
|
||||
- build-and-test
|
||||
filters:
|
||||
branches:
|
||||
only:
|
||||
- /feature\/.*/
|
||||
- /hotfix\/.*/
|
||||
- munitor/node_coverage:
|
||||
name: coverage
|
||||
node_version: "${MUNITOR_NODE_VERSION}"
|
||||
package_manager: "${MUNITOR_PACKAGE_MANAGER}"
|
||||
min_coverage: "${MUNITOR_COVERAGE_MIN}"
|
||||
coverage_tool: ${MUNITOR_COVERAGE_TOOL}
|
||||
coverage_summary_path: "${MUNITOR_COVERAGE_SUMMARY_PATH}"
|
||||
##IF_COVERAGE_CMD##
|
||||
coverage_command: ${MUNITOR_COVERAGE_COMMAND}
|
||||
##ENDIF_COVERAGE_CMD##
|
||||
requires:
|
||||
- build-and-test
|
||||
filters:
|
||||
branches:
|
||||
only:
|
||||
- /feature\/.*/
|
||||
- /hotfix\/.*/
|
||||
- munitor/node_security_scan:
|
||||
name: security-scan
|
||||
node_version: "${MUNITOR_NODE_VERSION}"
|
||||
package_manager: "${MUNITOR_PACKAGE_MANAGER}"
|
||||
requires:
|
||||
- build-and-test
|
||||
filters:
|
||||
branches:
|
||||
only:
|
||||
- /feature\/.*/
|
||||
- /hotfix\/.*/
|
||||
##IF_E2E##
|
||||
- munitor/node_e2e_test:
|
||||
name: e2e-tests
|
||||
node_version: "${MUNITOR_NODE_VERSION}"
|
||||
package_manager: "${MUNITOR_PACKAGE_MANAGER}"
|
||||
requires:
|
||||
- build-and-test
|
||||
filters:
|
||||
branches:
|
||||
only:
|
||||
- /feature\/.*/
|
||||
- /hotfix\/.*/
|
||||
##ENDIF_E2E##
|
||||
|
||||
develop:
|
||||
jobs:
|
||||
- munitor/node_build_and_test:
|
||||
name: build-and-test
|
||||
node_version: "${MUNITOR_NODE_VERSION}"
|
||||
package_manager: "${MUNITOR_PACKAGE_MANAGER}"
|
||||
##IF_NPM_AUTH##
|
||||
npm_auth: true
|
||||
npm_scopes: '${MUNITOR_NPM_SCOPES}'
|
||||
npm_default_scope: '${MUNITOR_NPM_DEFAULT_SCOPE}'
|
||||
##ENDIF_NPM_AUTH##
|
||||
##IF_SERVICES##
|
||||
services: '${MUNITOR_SERVICES_JSON}'
|
||||
##ENDIF_SERVICES##
|
||||
##IF_TEST_SETUP##
|
||||
test_setup: ${MUNITOR_TEST_SETUP_SCRIPT}
|
||||
##ENDIF_TEST_SETUP##
|
||||
##IF_CUSTOM_TEST##
|
||||
test_commands: '${MUNITOR_TEST_COMMANDS_JSON}'
|
||||
##ENDIF_CUSTOM_TEST##
|
||||
context:
|
||||
- ${MUNITOR_CONTEXT_GITHUB}
|
||||
filters:
|
||||
branches:
|
||||
only: develop
|
||||
|
||||
release-candidate:
|
||||
jobs:
|
||||
- munitor/node_build_and_test:
|
||||
name: build-and-test
|
||||
node_version: "${MUNITOR_NODE_VERSION}"
|
||||
package_manager: "${MUNITOR_PACKAGE_MANAGER}"
|
||||
##IF_NPM_AUTH##
|
||||
npm_auth: true
|
||||
npm_scopes: '${MUNITOR_NPM_SCOPES}'
|
||||
npm_default_scope: '${MUNITOR_NPM_DEFAULT_SCOPE}'
|
||||
##ENDIF_NPM_AUTH##
|
||||
##IF_SERVICES##
|
||||
services: '${MUNITOR_SERVICES_JSON}'
|
||||
##ENDIF_SERVICES##
|
||||
##IF_TEST_SETUP##
|
||||
test_setup: ${MUNITOR_TEST_SETUP_SCRIPT}
|
||||
##ENDIF_TEST_SETUP##
|
||||
##IF_CUSTOM_TEST##
|
||||
test_commands: '${MUNITOR_TEST_COMMANDS_JSON}'
|
||||
##ENDIF_CUSTOM_TEST##
|
||||
context:
|
||||
- ${MUNITOR_CONTEXT_GITHUB}
|
||||
filters:
|
||||
branches:
|
||||
only:
|
||||
- /release\/.*/
|
||||
- munitor/secrets_scan:
|
||||
name: secrets-scan
|
||||
filters:
|
||||
branches:
|
||||
only:
|
||||
- /release\/.*/
|
||||
##IF_SAST##
|
||||
- munitor/sast_scan:
|
||||
name: sast-scan
|
||||
fail_on_findings: "${MUNITOR_SAST_FAIL_ON_FINDINGS}"
|
||||
filters:
|
||||
branches:
|
||||
only:
|
||||
- /release\/.*/
|
||||
##ENDIF_SAST##
|
||||
- munitor/node_code_quality:
|
||||
name: code-quality
|
||||
node_version: "${MUNITOR_NODE_VERSION}"
|
||||
package_manager: "${MUNITOR_PACKAGE_MANAGER}"
|
||||
requires:
|
||||
- build-and-test
|
||||
filters:
|
||||
branches:
|
||||
only:
|
||||
- /release\/.*/
|
||||
- munitor/node_coverage:
|
||||
name: coverage
|
||||
node_version: "${MUNITOR_NODE_VERSION}"
|
||||
package_manager: "${MUNITOR_PACKAGE_MANAGER}"
|
||||
min_coverage: "${MUNITOR_COVERAGE_MIN}"
|
||||
coverage_tool: ${MUNITOR_COVERAGE_TOOL}
|
||||
coverage_summary_path: "${MUNITOR_COVERAGE_SUMMARY_PATH}"
|
||||
##IF_COVERAGE_CMD##
|
||||
coverage_command: ${MUNITOR_COVERAGE_COMMAND}
|
||||
##ENDIF_COVERAGE_CMD##
|
||||
requires:
|
||||
- build-and-test
|
||||
filters:
|
||||
branches:
|
||||
only:
|
||||
- /release\/.*/
|
||||
- munitor/node_security_scan:
|
||||
name: security-scan
|
||||
node_version: "${MUNITOR_NODE_VERSION}"
|
||||
package_manager: "${MUNITOR_PACKAGE_MANAGER}"
|
||||
requires:
|
||||
- build-and-test
|
||||
filters:
|
||||
branches:
|
||||
only:
|
||||
- /release\/.*/
|
||||
##IF_E2E##
|
||||
- munitor/node_e2e_test:
|
||||
name: e2e-tests
|
||||
node_version: "${MUNITOR_NODE_VERSION}"
|
||||
package_manager: "${MUNITOR_PACKAGE_MANAGER}"
|
||||
requires:
|
||||
- build-and-test
|
||||
filters:
|
||||
branches:
|
||||
only:
|
||||
- /release\/.*/
|
||||
##ENDIF_E2E##
|
||||
##IF_SONAR##
|
||||
- munitor/node_sonar_scan:
|
||||
name: sonar-scan
|
||||
node_version: "${MUNITOR_NODE_VERSION}"
|
||||
package_manager: "${MUNITOR_PACKAGE_MANAGER}"
|
||||
sonar_project_key: ${MUNITOR_SONAR_PROJECT_KEY}
|
||||
requires:
|
||||
- build-and-test
|
||||
- coverage
|
||||
context:
|
||||
- ${MUNITOR_CONTEXT_SONAR}
|
||||
filters:
|
||||
branches:
|
||||
only:
|
||||
- /release\/.*/
|
||||
##ENDIF_SONAR##
|
||||
##IF_SBOM##
|
||||
- munitor/node_sbom:
|
||||
name: sbom
|
||||
node_version: "${MUNITOR_NODE_VERSION}"
|
||||
package_manager: "${MUNITOR_PACKAGE_MANAGER}"
|
||||
context:
|
||||
- ${MUNITOR_CONTEXT_GITHUB}
|
||||
requires:
|
||||
- code-quality
|
||||
- coverage
|
||||
- secrets-scan
|
||||
##IF_SAST##
|
||||
- sast-scan
|
||||
##ENDIF_SAST##
|
||||
- security-scan
|
||||
##IF_E2E##
|
||||
- e2e-tests
|
||||
##ENDIF_E2E##
|
||||
filters:
|
||||
branches:
|
||||
only:
|
||||
- /release\/.*/
|
||||
##ENDIF_SBOM##
|
||||
- munitor/github_release:
|
||||
name: github-release
|
||||
release_artifacts: "main.js manifest.json styles.css"
|
||||
requires:
|
||||
- code-quality
|
||||
- coverage
|
||||
- secrets-scan
|
||||
##IF_SAST##
|
||||
- sast-scan
|
||||
##ENDIF_SAST##
|
||||
- security-scan
|
||||
##IF_E2E##
|
||||
- e2e-tests
|
||||
##ENDIF_E2E##
|
||||
context:
|
||||
- ${MUNITOR_CONTEXT_GITHUB}
|
||||
filters:
|
||||
branches:
|
||||
only:
|
||||
- /release\/.*/
|
||||
|
||||
production:
|
||||
jobs:
|
||||
- munitor/node_build_and_test:
|
||||
name: build-and-test
|
||||
node_version: "${MUNITOR_NODE_VERSION}"
|
||||
package_manager: "${MUNITOR_PACKAGE_MANAGER}"
|
||||
##IF_NPM_AUTH##
|
||||
npm_auth: true
|
||||
npm_scopes: '${MUNITOR_NPM_SCOPES}'
|
||||
npm_default_scope: '${MUNITOR_NPM_DEFAULT_SCOPE}'
|
||||
##ENDIF_NPM_AUTH##
|
||||
##IF_SERVICES##
|
||||
services: '${MUNITOR_SERVICES_JSON}'
|
||||
##ENDIF_SERVICES##
|
||||
##IF_TEST_SETUP##
|
||||
test_setup: ${MUNITOR_TEST_SETUP_SCRIPT}
|
||||
##ENDIF_TEST_SETUP##
|
||||
##IF_CUSTOM_TEST##
|
||||
test_commands: '${MUNITOR_TEST_COMMANDS_JSON}'
|
||||
##ENDIF_CUSTOM_TEST##
|
||||
context:
|
||||
- ${MUNITOR_CONTEXT_GITHUB}
|
||||
filters:
|
||||
branches:
|
||||
only: main
|
||||
- munitor/github_release:
|
||||
name: github-release
|
||||
release_artifacts: "main.js manifest.json styles.css"
|
||||
requires:
|
||||
- build-and-test
|
||||
context:
|
||||
- ${MUNITOR_CONTEXT_GITHUB}
|
||||
filters:
|
||||
branches:
|
||||
only: main
|
||||
MUNITOR_TPL_EOF
|
||||
|
||||
cat > /tmp/munitor/templates/partials/java-webapp-deploy.yml.tpl << 'MUNITOR_PARTIAL_EOF'
|
||||
__WORKFLOW_NAME__:
|
||||
jobs:
|
||||
@@ -2409,9 +2772,10 @@ MUNITOR_PARTIAL_EOF
|
||||
cat > /tmp/munitor/templates/partials/node-api-deploy.yml.tpl << 'MUNITOR_PARTIAL_EOF'
|
||||
__WORKFLOW_NAME__:
|
||||
jobs:
|
||||
- munitor/npm_build_and_test:
|
||||
- munitor/node_build_and_test:
|
||||
name: build-and-test
|
||||
node_version: "${MUNITOR_NODE_VERSION}"
|
||||
package_manager: "${MUNITOR_PACKAGE_MANAGER}"
|
||||
##IF_NPM_AUTH##
|
||||
npm_auth: true
|
||||
npm_scopes: '${MUNITOR_NPM_SCOPES}'
|
||||
@@ -2442,17 +2806,22 @@ cat > /tmp/munitor/templates/partials/node-api-deploy.yml.tpl << 'MUNITOR_PARTIA
|
||||
filters:
|
||||
branches:
|
||||
only: __BRANCH_FILTER__
|
||||
- munitor/npm_code_quality:
|
||||
- munitor/node_code_quality:
|
||||
name: code-quality
|
||||
node_version: "${MUNITOR_NODE_VERSION}"
|
||||
package_manager: "${MUNITOR_PACKAGE_MANAGER}"
|
||||
requires:
|
||||
- build-and-test
|
||||
filters:
|
||||
branches:
|
||||
only: __BRANCH_FILTER__
|
||||
- munitor/npm_coverage:
|
||||
- munitor/node_coverage:
|
||||
name: coverage
|
||||
node_version: "${MUNITOR_NODE_VERSION}"
|
||||
package_manager: "${MUNITOR_PACKAGE_MANAGER}"
|
||||
min_coverage: "${MUNITOR_COVERAGE_MIN}"
|
||||
coverage_tool: ${MUNITOR_COVERAGE_TOOL}
|
||||
coverage_summary_path: "${MUNITOR_COVERAGE_SUMMARY_PATH}"
|
||||
##IF_COVERAGE_CMD##
|
||||
coverage_command: ${MUNITOR_COVERAGE_COMMAND}
|
||||
##ENDIF_COVERAGE_CMD##
|
||||
@@ -2461,16 +2830,20 @@ cat > /tmp/munitor/templates/partials/node-api-deploy.yml.tpl << 'MUNITOR_PARTIA
|
||||
filters:
|
||||
branches:
|
||||
only: __BRANCH_FILTER__
|
||||
- munitor/npm_security_scan:
|
||||
- munitor/node_security_scan:
|
||||
name: security-scan
|
||||
node_version: "${MUNITOR_NODE_VERSION}"
|
||||
package_manager: "${MUNITOR_PACKAGE_MANAGER}"
|
||||
requires:
|
||||
- build-and-test
|
||||
filters:
|
||||
branches:
|
||||
only: __BRANCH_FILTER__
|
||||
##IF_E2E##
|
||||
- munitor/npm_e2e_test:
|
||||
- munitor/node_e2e_test:
|
||||
name: e2e-tests
|
||||
node_version: "${MUNITOR_NODE_VERSION}"
|
||||
package_manager: "${MUNITOR_PACKAGE_MANAGER}"
|
||||
requires:
|
||||
- build-and-test
|
||||
filters:
|
||||
@@ -2478,9 +2851,10 @@ cat > /tmp/munitor/templates/partials/node-api-deploy.yml.tpl << 'MUNITOR_PARTIA
|
||||
only: __BRANCH_FILTER__
|
||||
##ENDIF_E2E##
|
||||
##IF_SONAR##
|
||||
- munitor/npm_sonar_scan:
|
||||
- munitor/node_sonar_scan:
|
||||
name: sonar-scan
|
||||
node_version: "${MUNITOR_NODE_VERSION}"
|
||||
package_manager: "${MUNITOR_PACKAGE_MANAGER}"
|
||||
sonar_project_key: ${MUNITOR_SONAR_PROJECT_KEY}
|
||||
requires:
|
||||
- build-and-test
|
||||
@@ -2516,9 +2890,10 @@ cat > /tmp/munitor/templates/partials/node-api-deploy.yml.tpl << 'MUNITOR_PARTIA
|
||||
branches:
|
||||
only: __BRANCH_FILTER__
|
||||
##IF_SBOM##
|
||||
- munitor/npm_sbom:
|
||||
- munitor/node_sbom:
|
||||
name: sbom
|
||||
node_version: "${MUNITOR_NODE_VERSION}"
|
||||
package_manager: "${MUNITOR_PACKAGE_MANAGER}"
|
||||
context:
|
||||
- ${MUNITOR_CONTEXT_GITHUB}
|
||||
requires:
|
||||
@@ -2559,9 +2934,10 @@ MUNITOR_PARTIAL_EOF
|
||||
cat > /tmp/munitor/templates/partials/node-webapp-deploy.yml.tpl << 'MUNITOR_PARTIAL_EOF'
|
||||
__WORKFLOW_NAME__:
|
||||
jobs:
|
||||
- munitor/npm_build_and_test:
|
||||
- munitor/node_build_and_test:
|
||||
name: build-and-test
|
||||
node_version: "${MUNITOR_NODE_VERSION}"
|
||||
package_manager: "${MUNITOR_PACKAGE_MANAGER}"
|
||||
##IF_NPM_AUTH##
|
||||
npm_auth: true
|
||||
npm_scopes: '${MUNITOR_NPM_SCOPES}'
|
||||
@@ -2592,17 +2968,22 @@ cat > /tmp/munitor/templates/partials/node-webapp-deploy.yml.tpl << 'MUNITOR_PAR
|
||||
filters:
|
||||
branches:
|
||||
only: __BRANCH_FILTER__
|
||||
- munitor/npm_code_quality:
|
||||
- munitor/node_code_quality:
|
||||
name: code-quality
|
||||
node_version: "${MUNITOR_NODE_VERSION}"
|
||||
package_manager: "${MUNITOR_PACKAGE_MANAGER}"
|
||||
requires:
|
||||
- build-and-test
|
||||
filters:
|
||||
branches:
|
||||
only: __BRANCH_FILTER__
|
||||
- munitor/npm_coverage:
|
||||
- munitor/node_coverage:
|
||||
name: coverage
|
||||
node_version: "${MUNITOR_NODE_VERSION}"
|
||||
package_manager: "${MUNITOR_PACKAGE_MANAGER}"
|
||||
min_coverage: "${MUNITOR_COVERAGE_MIN}"
|
||||
coverage_tool: ${MUNITOR_COVERAGE_TOOL}
|
||||
coverage_summary_path: "${MUNITOR_COVERAGE_SUMMARY_PATH}"
|
||||
##IF_COVERAGE_CMD##
|
||||
coverage_command: ${MUNITOR_COVERAGE_COMMAND}
|
||||
##ENDIF_COVERAGE_CMD##
|
||||
@@ -2611,16 +2992,20 @@ cat > /tmp/munitor/templates/partials/node-webapp-deploy.yml.tpl << 'MUNITOR_PAR
|
||||
filters:
|
||||
branches:
|
||||
only: __BRANCH_FILTER__
|
||||
- munitor/npm_security_scan:
|
||||
- munitor/node_security_scan:
|
||||
name: security-scan
|
||||
node_version: "${MUNITOR_NODE_VERSION}"
|
||||
package_manager: "${MUNITOR_PACKAGE_MANAGER}"
|
||||
requires:
|
||||
- build-and-test
|
||||
filters:
|
||||
branches:
|
||||
only: __BRANCH_FILTER__
|
||||
##IF_E2E##
|
||||
- munitor/npm_e2e_test:
|
||||
- munitor/node_e2e_test:
|
||||
name: e2e-tests
|
||||
node_version: "${MUNITOR_NODE_VERSION}"
|
||||
package_manager: "${MUNITOR_PACKAGE_MANAGER}"
|
||||
requires:
|
||||
- build-and-test
|
||||
filters:
|
||||
@@ -2628,9 +3013,10 @@ cat > /tmp/munitor/templates/partials/node-webapp-deploy.yml.tpl << 'MUNITOR_PAR
|
||||
only: __BRANCH_FILTER__
|
||||
##ENDIF_E2E##
|
||||
##IF_SONAR##
|
||||
- munitor/npm_sonar_scan:
|
||||
- munitor/node_sonar_scan:
|
||||
name: sonar-scan
|
||||
node_version: "${MUNITOR_NODE_VERSION}"
|
||||
package_manager: "${MUNITOR_PACKAGE_MANAGER}"
|
||||
sonar_project_key: ${MUNITOR_SONAR_PROJECT_KEY}
|
||||
requires:
|
||||
- build-and-test
|
||||
@@ -2666,9 +3052,10 @@ cat > /tmp/munitor/templates/partials/node-webapp-deploy.yml.tpl << 'MUNITOR_PAR
|
||||
branches:
|
||||
only: __BRANCH_FILTER__
|
||||
##IF_SBOM##
|
||||
- munitor/npm_sbom:
|
||||
- munitor/node_sbom:
|
||||
name: sbom
|
||||
node_version: "${MUNITOR_NODE_VERSION}"
|
||||
package_manager: "${MUNITOR_PACKAGE_MANAGER}"
|
||||
context:
|
||||
- ${MUNITOR_CONTEXT_GITHUB}
|
||||
requires:
|
||||
@@ -2793,6 +3180,9 @@ validate_required_fields() {
|
||||
validate-cd-repo|argocd-apps)
|
||||
# No additional required fields beyond orb_version
|
||||
;;
|
||||
obsidian-plugin)
|
||||
[[ -z "$(yq '.contexts.github // ""' "${config}")" ]] && missing+=("contexts.github")
|
||||
;;
|
||||
esac
|
||||
|
||||
if [[ ${#missing[@]} -gt 0 ]]; then
|
||||
|
||||
@@ -193,6 +193,7 @@ extract_munitor_vars() {
|
||||
if [[ -n "${MUNITOR_TEST_COVERAGE_MIN}" ]]; then
|
||||
MUNITOR_COVERAGE_MIN="${MUNITOR_TEST_COVERAGE_MIN}"
|
||||
fi
|
||||
MUNITOR_COVERAGE_SUMMARY_PATH=$(yq '.test.coverage.summary_path // "coverage/coverage-summary.json"' "${config_file}")
|
||||
|
||||
# Terraform pipeline settings
|
||||
MUNITOR_TF_PATH=$(yq '.terraform.path // "terraform/"' "${config_file}")
|
||||
@@ -311,7 +312,7 @@ extract_munitor_vars() {
|
||||
export MUNITOR_SERVICES MUNITOR_SERVICES_JSON
|
||||
export MUNITOR_TEST_SETUP MUNITOR_TEST_SETUP_SCRIPT
|
||||
export MUNITOR_CUSTOM_TEST MUNITOR_TEST_COMMANDS_JSON
|
||||
export MUNITOR_COVERAGE_TOOL MUNITOR_COVERAGE_CMD MUNITOR_COVERAGE_COMMAND
|
||||
export MUNITOR_COVERAGE_TOOL MUNITOR_COVERAGE_CMD MUNITOR_COVERAGE_COMMAND MUNITOR_COVERAGE_SUMMARY_PATH
|
||||
export MUNITOR_TF_PATH MUNITOR_TF_LIVE_PATH MUNITOR_TF_ENVIRONMENTS MUNITOR_CHECKOV_SKIP MUNITOR_SAST MUNITOR_SAST_FAIL_ON_FINDINGS
|
||||
export MUNITOR_KUSTOMIZE_VERSION MUNITOR_KUSTOMIZE_BASE_PATH MUNITOR_KUSTOMIZE_LOAD_RESTRICTOR
|
||||
export MUNITOR_KUSTOMIZE_SCAN_OVERLAY MUNITOR_KUSTOMIZE_OVERLAYS MUNITOR_KUSTOMIZE_OVERLAY_DIR
|
||||
@@ -326,7 +327,7 @@ extract_munitor_vars() {
|
||||
# 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}'
|
||||
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}'
|
||||
}
|
||||
MUNITOR_EXTRACT_EOF
|
||||
|
||||
@@ -377,7 +378,42 @@ case "${MUNITOR_PIPELINE}" in
|
||||
nextjs)
|
||||
# Multi-stage Next.js standalone Dockerfile.
|
||||
# Assumes `output: 'standalone'` in next.config.js.
|
||||
cat > Dockerfile <<DOCKERFILE
|
||||
case "${MUNITOR_PACKAGE_MANAGER}" in
|
||||
pnpm)
|
||||
cat > Dockerfile <<DOCKERFILE
|
||||
FROM node:${MUNITOR_NODE_VERSION}-alpine AS deps
|
||||
WORKDIR /app
|
||||
RUN corepack enable
|
||||
COPY package.json pnpm-lock.yaml ./
|
||||
RUN pnpm install --frozen-lockfile
|
||||
|
||||
FROM node:${MUNITOR_NODE_VERSION}-alpine AS builder
|
||||
WORKDIR /app
|
||||
RUN corepack enable
|
||||
COPY --from=deps /app/node_modules ./node_modules
|
||||
COPY . .
|
||||
ENV STANDALONE=true
|
||||
ARG GIT_COMMIT_SHA
|
||||
ENV GIT_COMMIT_SHA=\${GIT_COMMIT_SHA}
|
||||
RUN pnpm run build
|
||||
|
||||
FROM node:${MUNITOR_NODE_VERSION}-alpine AS runner
|
||||
WORKDIR /app
|
||||
RUN apk update && apk upgrade --no-cache && rm -rf /var/cache/apk/*
|
||||
RUN npm cache clean --force && rm -rf /usr/local/lib/node_modules /usr/local/bin/npm /usr/local/bin/npx
|
||||
RUN addgroup --system --gid 1001 nodejs \\
|
||||
&& adduser --system --uid 1001 nextjs
|
||||
COPY --from=builder /app/public ./public
|
||||
COPY --from=builder --chown=nextjs:nodejs /app/.next/standalone ./
|
||||
COPY --from=builder --chown=nextjs:nodejs /app/.next/static ./.next/static
|
||||
USER nextjs
|
||||
EXPOSE 3000
|
||||
ENV PORT=3000
|
||||
CMD ["node", "server.js"]
|
||||
DOCKERFILE
|
||||
;;
|
||||
*)
|
||||
cat > Dockerfile <<DOCKERFILE
|
||||
FROM node:${MUNITOR_NODE_VERSION}-alpine AS deps
|
||||
WORKDIR /app
|
||||
COPY package*.json ./
|
||||
@@ -408,11 +444,38 @@ EXPOSE 3000
|
||||
ENV PORT=3000
|
||||
CMD ["node", "server.js"]
|
||||
DOCKERFILE
|
||||
;;
|
||||
esac
|
||||
;;
|
||||
|
||||
express)
|
||||
# Two-stage Express Dockerfile. Uses package.json "main" field via `node .`.
|
||||
cat > Dockerfile <<DOCKERFILE
|
||||
case "${MUNITOR_PACKAGE_MANAGER}" in
|
||||
pnpm)
|
||||
cat > Dockerfile <<DOCKERFILE
|
||||
FROM node:${MUNITOR_NODE_VERSION}-alpine AS deps
|
||||
WORKDIR /app
|
||||
RUN corepack enable
|
||||
COPY package.json pnpm-lock.yaml ./
|
||||
RUN pnpm install --frozen-lockfile --prod
|
||||
|
||||
FROM node:${MUNITOR_NODE_VERSION}-alpine AS runner
|
||||
WORKDIR /app
|
||||
RUN apk update && apk upgrade --no-cache && rm -rf /var/cache/apk/*
|
||||
RUN npm cache clean --force && rm -rf /usr/local/lib/node_modules /usr/local/bin/npm /usr/local/bin/npx
|
||||
RUN addgroup --system --gid 1001 nodejs \\
|
||||
&& adduser --system --uid 1001 appuser -G nodejs
|
||||
COPY --from=deps /app/node_modules ./node_modules
|
||||
COPY . .
|
||||
USER appuser
|
||||
EXPOSE ${MUNITOR_HEALTH_PORT}
|
||||
HEALTHCHECK --interval=30s --timeout=3s --start-period=10s --retries=3 \\
|
||||
CMD wget --no-verbose --tries=1 --spider http://localhost:${MUNITOR_HEALTH_PORT}${MUNITOR_HEALTH_PATH} || exit 1
|
||||
CMD ["node", "."]
|
||||
DOCKERFILE
|
||||
;;
|
||||
*)
|
||||
cat > Dockerfile <<DOCKERFILE
|
||||
FROM node:${MUNITOR_NODE_VERSION}-alpine AS deps
|
||||
WORKDIR /app
|
||||
COPY package*.json ./
|
||||
@@ -432,6 +495,8 @@ HEALTHCHECK --interval=30s --timeout=3s --start-period=10s --retries=3 \\
|
||||
CMD wget --no-verbose --tries=1 --spider http://localhost:${MUNITOR_HEALTH_PORT}${MUNITOR_HEALTH_PATH} || exit 1
|
||||
CMD ["node", "."]
|
||||
DOCKERFILE
|
||||
;;
|
||||
esac
|
||||
;;
|
||||
|
||||
*)
|
||||
@@ -533,7 +598,31 @@ DOCKERFILE
|
||||
|
||||
node-webapp)
|
||||
echo "Generating Dockerfile for node-webapp (node ${MUNITOR_NODE_VERSION})"
|
||||
cat > Dockerfile <<DOCKERFILE
|
||||
case "${MUNITOR_PACKAGE_MANAGER}" in
|
||||
pnpm)
|
||||
cat > Dockerfile <<DOCKERFILE
|
||||
FROM node:${MUNITOR_NODE_VERSION}-alpine AS builder
|
||||
WORKDIR /app
|
||||
RUN corepack enable
|
||||
COPY package.json pnpm-lock.yaml ./
|
||||
RUN pnpm install --frozen-lockfile
|
||||
COPY . .
|
||||
ARG GIT_COMMIT_SHA
|
||||
ENV GIT_COMMIT_SHA=\${GIT_COMMIT_SHA}
|
||||
RUN pnpm run build
|
||||
|
||||
FROM gcr.io/distroless/nodejs${MUNITOR_NODE_VERSION}-debian12 AS runner
|
||||
WORKDIR /app
|
||||
ENV NODE_ENV=production
|
||||
COPY --from=builder /app/.next/standalone ./
|
||||
COPY --from=builder /app/.next/static ./.next/static
|
||||
COPY --from=builder /app/public ./public
|
||||
EXPOSE ${MUNITOR_HEALTH_PORT}
|
||||
CMD ["server.js"]
|
||||
DOCKERFILE
|
||||
;;
|
||||
*)
|
||||
cat > Dockerfile <<DOCKERFILE
|
||||
FROM node:${MUNITOR_NODE_VERSION}-alpine AS builder
|
||||
WORKDIR /app
|
||||
COPY package*.json ./
|
||||
@@ -552,6 +641,8 @@ COPY --from=builder /app/public ./public
|
||||
EXPOSE ${MUNITOR_HEALTH_PORT}
|
||||
CMD ["server.js"]
|
||||
DOCKERFILE
|
||||
;;
|
||||
esac
|
||||
;;
|
||||
|
||||
*)
|
||||
|
||||
@@ -16,16 +16,17 @@ munitor_header "run_test_setup"
|
||||
SETUP_SCRIPT="${MUNITOR_TEST_SETUP_SCRIPT:-}"
|
||||
|
||||
if [[ -z "${SETUP_SCRIPT}" ]]; then
|
||||
echo "No test setup script configured."
|
||||
echo "No test setup configured."
|
||||
exit 0
|
||||
fi
|
||||
|
||||
if [[ ! -f "${SETUP_SCRIPT}" ]]; then
|
||||
echo "ERROR: Test setup script '${SETUP_SCRIPT}' not found."
|
||||
exit 1
|
||||
if [[ -f "${SETUP_SCRIPT}" ]]; then
|
||||
echo "Running test setup script: ${SETUP_SCRIPT}"
|
||||
chmod +x "${SETUP_SCRIPT}"
|
||||
"${SETUP_SCRIPT}"
|
||||
else
|
||||
echo "Running test setup command: ${SETUP_SCRIPT}"
|
||||
bash -c "${SETUP_SCRIPT}"
|
||||
fi
|
||||
|
||||
echo "Running test setup: ${SETUP_SCRIPT}"
|
||||
chmod +x "${SETUP_SCRIPT}"
|
||||
"${SETUP_SCRIPT}"
|
||||
echo "Test setup complete."
|
||||
@@ -6,9 +6,10 @@ orbs:
|
||||
workflows:
|
||||
pr-checks:
|
||||
jobs:
|
||||
- munitor/npm_build_and_test:
|
||||
- munitor/node_build_and_test:
|
||||
name: build-and-test
|
||||
node_version: "${MUNITOR_NODE_VERSION}"
|
||||
package_manager: "${MUNITOR_PACKAGE_MANAGER}"
|
||||
##IF_NPM_AUTH##
|
||||
npm_auth: true
|
||||
npm_scopes: '${MUNITOR_NPM_SCOPES}'
|
||||
@@ -45,8 +46,10 @@ workflows:
|
||||
only:
|
||||
- /feature\/.*/
|
||||
- /hotfix\/.*/
|
||||
- munitor/npm_code_quality:
|
||||
- munitor/node_code_quality:
|
||||
name: code-quality
|
||||
node_version: "${MUNITOR_NODE_VERSION}"
|
||||
package_manager: "${MUNITOR_PACKAGE_MANAGER}"
|
||||
requires:
|
||||
- build-and-test
|
||||
filters:
|
||||
@@ -54,10 +57,13 @@ workflows:
|
||||
only:
|
||||
- /feature\/.*/
|
||||
- /hotfix\/.*/
|
||||
- munitor/npm_coverage:
|
||||
- munitor/node_coverage:
|
||||
name: coverage
|
||||
node_version: "${MUNITOR_NODE_VERSION}"
|
||||
package_manager: "${MUNITOR_PACKAGE_MANAGER}"
|
||||
min_coverage: "${MUNITOR_COVERAGE_MIN}"
|
||||
coverage_tool: ${MUNITOR_COVERAGE_TOOL}
|
||||
coverage_summary_path: "${MUNITOR_COVERAGE_SUMMARY_PATH}"
|
||||
##IF_COVERAGE_CMD##
|
||||
coverage_command: ${MUNITOR_COVERAGE_COMMAND}
|
||||
##ENDIF_COVERAGE_CMD##
|
||||
@@ -68,8 +74,10 @@ workflows:
|
||||
only:
|
||||
- /feature\/.*/
|
||||
- /hotfix\/.*/
|
||||
- munitor/npm_security_scan:
|
||||
- munitor/node_security_scan:
|
||||
name: security-scan
|
||||
node_version: "${MUNITOR_NODE_VERSION}"
|
||||
package_manager: "${MUNITOR_PACKAGE_MANAGER}"
|
||||
requires:
|
||||
- build-and-test
|
||||
filters:
|
||||
@@ -78,8 +86,10 @@ workflows:
|
||||
- /feature\/.*/
|
||||
- /hotfix\/.*/
|
||||
##IF_E2E##
|
||||
- munitor/npm_e2e_test:
|
||||
- munitor/node_e2e_test:
|
||||
name: e2e-tests
|
||||
node_version: "${MUNITOR_NODE_VERSION}"
|
||||
package_manager: "${MUNITOR_PACKAGE_MANAGER}"
|
||||
requires:
|
||||
- build-and-test
|
||||
filters:
|
||||
@@ -94,9 +104,10 @@ workflows:
|
||||
|
||||
release-candidate:
|
||||
jobs:
|
||||
- munitor/npm_build_and_test:
|
||||
- munitor/node_build_and_test:
|
||||
name: build-and-test
|
||||
node_version: "${MUNITOR_NODE_VERSION}"
|
||||
package_manager: "${MUNITOR_PACKAGE_MANAGER}"
|
||||
##IF_NPM_AUTH##
|
||||
npm_auth: true
|
||||
npm_scopes: '${MUNITOR_NPM_SCOPES}'
|
||||
@@ -130,18 +141,23 @@ workflows:
|
||||
branches:
|
||||
only:
|
||||
- /release\/.*/
|
||||
- munitor/npm_code_quality:
|
||||
- munitor/node_code_quality:
|
||||
name: code-quality
|
||||
node_version: "${MUNITOR_NODE_VERSION}"
|
||||
package_manager: "${MUNITOR_PACKAGE_MANAGER}"
|
||||
requires:
|
||||
- build-and-test
|
||||
filters:
|
||||
branches:
|
||||
only:
|
||||
- /release\/.*/
|
||||
- munitor/npm_coverage:
|
||||
- munitor/node_coverage:
|
||||
name: coverage
|
||||
node_version: "${MUNITOR_NODE_VERSION}"
|
||||
package_manager: "${MUNITOR_PACKAGE_MANAGER}"
|
||||
min_coverage: "${MUNITOR_COVERAGE_MIN}"
|
||||
coverage_tool: ${MUNITOR_COVERAGE_TOOL}
|
||||
coverage_summary_path: "${MUNITOR_COVERAGE_SUMMARY_PATH}"
|
||||
##IF_COVERAGE_CMD##
|
||||
coverage_command: ${MUNITOR_COVERAGE_COMMAND}
|
||||
##ENDIF_COVERAGE_CMD##
|
||||
@@ -151,8 +167,10 @@ workflows:
|
||||
branches:
|
||||
only:
|
||||
- /release\/.*/
|
||||
- munitor/npm_security_scan:
|
||||
- munitor/node_security_scan:
|
||||
name: security-scan
|
||||
node_version: "${MUNITOR_NODE_VERSION}"
|
||||
package_manager: "${MUNITOR_PACKAGE_MANAGER}"
|
||||
requires:
|
||||
- build-and-test
|
||||
filters:
|
||||
@@ -160,8 +178,10 @@ workflows:
|
||||
only:
|
||||
- /release\/.*/
|
||||
##IF_E2E##
|
||||
- munitor/npm_e2e_test:
|
||||
- munitor/node_e2e_test:
|
||||
name: e2e-tests
|
||||
node_version: "${MUNITOR_NODE_VERSION}"
|
||||
package_manager: "${MUNITOR_PACKAGE_MANAGER}"
|
||||
requires:
|
||||
- build-and-test
|
||||
filters:
|
||||
@@ -170,9 +190,10 @@ workflows:
|
||||
- /release\/.*/
|
||||
##ENDIF_E2E##
|
||||
##IF_SONAR##
|
||||
- munitor/npm_sonar_scan:
|
||||
- munitor/node_sonar_scan:
|
||||
name: sonar-scan
|
||||
node_version: "${MUNITOR_NODE_VERSION}"
|
||||
package_manager: "${MUNITOR_PACKAGE_MANAGER}"
|
||||
sonar_project_key: ${MUNITOR_SONAR_PROJECT_KEY}
|
||||
requires:
|
||||
- build-and-test
|
||||
@@ -210,9 +231,10 @@ workflows:
|
||||
only:
|
||||
- /release\/.*/
|
||||
##IF_SBOM##
|
||||
- munitor/npm_sbom:
|
||||
- munitor/node_sbom:
|
||||
name: sbom
|
||||
node_version: "${MUNITOR_NODE_VERSION}"
|
||||
package_manager: "${MUNITOR_PACKAGE_MANAGER}"
|
||||
context:
|
||||
- ${MUNITOR_CONTEXT_GITHUB}
|
||||
requires:
|
||||
@@ -265,9 +287,10 @@ workflows:
|
||||
|
||||
production:
|
||||
jobs:
|
||||
- munitor/npm_build_and_test:
|
||||
- munitor/node_build_and_test:
|
||||
name: build-and-test
|
||||
node_version: "${MUNITOR_NODE_VERSION}"
|
||||
package_manager: "${MUNITOR_PACKAGE_MANAGER}"
|
||||
##IF_NPM_AUTH##
|
||||
npm_auth: true
|
||||
npm_scopes: '${MUNITOR_NPM_SCOPES}'
|
||||
|
||||
@@ -6,9 +6,10 @@ orbs:
|
||||
workflows:
|
||||
pr-checks:
|
||||
jobs:
|
||||
- munitor/npm_build_and_test:
|
||||
- munitor/node_build_and_test:
|
||||
name: build-and-test
|
||||
node_version: "${MUNITOR_NODE_VERSION}"
|
||||
package_manager: "${MUNITOR_PACKAGE_MANAGER}"
|
||||
##IF_NPM_AUTH##
|
||||
npm_auth: true
|
||||
npm_scopes: '${MUNITOR_NPM_SCOPES}'
|
||||
@@ -45,8 +46,10 @@ workflows:
|
||||
only:
|
||||
- /feature\/.*/
|
||||
- /hotfix\/.*/
|
||||
- munitor/npm_code_quality:
|
||||
- munitor/node_code_quality:
|
||||
name: code-quality
|
||||
node_version: "${MUNITOR_NODE_VERSION}"
|
||||
package_manager: "${MUNITOR_PACKAGE_MANAGER}"
|
||||
requires:
|
||||
- build-and-test
|
||||
filters:
|
||||
@@ -54,10 +57,13 @@ workflows:
|
||||
only:
|
||||
- /feature\/.*/
|
||||
- /hotfix\/.*/
|
||||
- munitor/npm_coverage:
|
||||
- munitor/node_coverage:
|
||||
name: coverage
|
||||
node_version: "${MUNITOR_NODE_VERSION}"
|
||||
package_manager: "${MUNITOR_PACKAGE_MANAGER}"
|
||||
min_coverage: "${MUNITOR_COVERAGE_MIN}"
|
||||
coverage_tool: ${MUNITOR_COVERAGE_TOOL}
|
||||
coverage_summary_path: "${MUNITOR_COVERAGE_SUMMARY_PATH}"
|
||||
##IF_COVERAGE_CMD##
|
||||
coverage_command: ${MUNITOR_COVERAGE_COMMAND}
|
||||
##ENDIF_COVERAGE_CMD##
|
||||
@@ -68,8 +74,10 @@ workflows:
|
||||
only:
|
||||
- /feature\/.*/
|
||||
- /hotfix\/.*/
|
||||
- munitor/npm_security_scan:
|
||||
- munitor/node_security_scan:
|
||||
name: security-scan
|
||||
node_version: "${MUNITOR_NODE_VERSION}"
|
||||
package_manager: "${MUNITOR_PACKAGE_MANAGER}"
|
||||
requires:
|
||||
- build-and-test
|
||||
filters:
|
||||
@@ -78,8 +86,10 @@ workflows:
|
||||
- /feature\/.*/
|
||||
- /hotfix\/.*/
|
||||
##IF_E2E##
|
||||
- munitor/npm_e2e_test:
|
||||
- munitor/node_e2e_test:
|
||||
name: e2e-tests
|
||||
node_version: "${MUNITOR_NODE_VERSION}"
|
||||
package_manager: "${MUNITOR_PACKAGE_MANAGER}"
|
||||
requires:
|
||||
- build-and-test
|
||||
filters:
|
||||
@@ -94,9 +104,10 @@ workflows:
|
||||
|
||||
release-candidate:
|
||||
jobs:
|
||||
- munitor/npm_build_and_test:
|
||||
- munitor/node_build_and_test:
|
||||
name: build-and-test
|
||||
node_version: "${MUNITOR_NODE_VERSION}"
|
||||
package_manager: "${MUNITOR_PACKAGE_MANAGER}"
|
||||
##IF_NPM_AUTH##
|
||||
npm_auth: true
|
||||
npm_scopes: '${MUNITOR_NPM_SCOPES}'
|
||||
@@ -130,18 +141,23 @@ workflows:
|
||||
branches:
|
||||
only:
|
||||
- /release\/.*/
|
||||
- munitor/npm_code_quality:
|
||||
- munitor/node_code_quality:
|
||||
name: code-quality
|
||||
node_version: "${MUNITOR_NODE_VERSION}"
|
||||
package_manager: "${MUNITOR_PACKAGE_MANAGER}"
|
||||
requires:
|
||||
- build-and-test
|
||||
filters:
|
||||
branches:
|
||||
only:
|
||||
- /release\/.*/
|
||||
- munitor/npm_coverage:
|
||||
- munitor/node_coverage:
|
||||
name: coverage
|
||||
node_version: "${MUNITOR_NODE_VERSION}"
|
||||
package_manager: "${MUNITOR_PACKAGE_MANAGER}"
|
||||
min_coverage: "${MUNITOR_COVERAGE_MIN}"
|
||||
coverage_tool: ${MUNITOR_COVERAGE_TOOL}
|
||||
coverage_summary_path: "${MUNITOR_COVERAGE_SUMMARY_PATH}"
|
||||
##IF_COVERAGE_CMD##
|
||||
coverage_command: ${MUNITOR_COVERAGE_COMMAND}
|
||||
##ENDIF_COVERAGE_CMD##
|
||||
@@ -151,8 +167,10 @@ workflows:
|
||||
branches:
|
||||
only:
|
||||
- /release\/.*/
|
||||
- munitor/npm_security_scan:
|
||||
- munitor/node_security_scan:
|
||||
name: security-scan
|
||||
node_version: "${MUNITOR_NODE_VERSION}"
|
||||
package_manager: "${MUNITOR_PACKAGE_MANAGER}"
|
||||
requires:
|
||||
- build-and-test
|
||||
filters:
|
||||
@@ -160,8 +178,10 @@ workflows:
|
||||
only:
|
||||
- /release\/.*/
|
||||
##IF_E2E##
|
||||
- munitor/npm_e2e_test:
|
||||
- munitor/node_e2e_test:
|
||||
name: e2e-tests
|
||||
node_version: "${MUNITOR_NODE_VERSION}"
|
||||
package_manager: "${MUNITOR_PACKAGE_MANAGER}"
|
||||
requires:
|
||||
- build-and-test
|
||||
filters:
|
||||
@@ -170,9 +190,10 @@ workflows:
|
||||
- /release\/.*/
|
||||
##ENDIF_E2E##
|
||||
##IF_SONAR##
|
||||
- munitor/npm_sonar_scan:
|
||||
- munitor/node_sonar_scan:
|
||||
name: sonar-scan
|
||||
node_version: "${MUNITOR_NODE_VERSION}"
|
||||
package_manager: "${MUNITOR_PACKAGE_MANAGER}"
|
||||
sonar_project_key: ${MUNITOR_SONAR_PROJECT_KEY}
|
||||
requires:
|
||||
- build-and-test
|
||||
@@ -210,9 +231,10 @@ workflows:
|
||||
only:
|
||||
- /release\/.*/
|
||||
##IF_SBOM##
|
||||
- munitor/npm_sbom:
|
||||
- munitor/node_sbom:
|
||||
name: sbom
|
||||
node_version: "${MUNITOR_NODE_VERSION}"
|
||||
package_manager: "${MUNITOR_PACKAGE_MANAGER}"
|
||||
context:
|
||||
- ${MUNITOR_CONTEXT_GITHUB}
|
||||
requires:
|
||||
@@ -265,9 +287,10 @@ workflows:
|
||||
|
||||
production:
|
||||
jobs:
|
||||
- munitor/npm_build_and_test:
|
||||
- munitor/node_build_and_test:
|
||||
name: build-and-test
|
||||
node_version: "${MUNITOR_NODE_VERSION}"
|
||||
package_manager: "${MUNITOR_PACKAGE_MANAGER}"
|
||||
##IF_NPM_AUTH##
|
||||
npm_auth: true
|
||||
npm_scopes: '${MUNITOR_NPM_SCOPES}'
|
||||
|
||||
@@ -0,0 +1,313 @@
|
||||
version: 2.1
|
||||
|
||||
orbs:
|
||||
munitor: ${MUNITOR_ORB_SLUG}@${MUNITOR_ORB_VERSION}
|
||||
|
||||
workflows:
|
||||
pr-checks:
|
||||
jobs:
|
||||
- munitor/node_build_and_test:
|
||||
name: build-and-test
|
||||
node_version: "${MUNITOR_NODE_VERSION}"
|
||||
package_manager: "${MUNITOR_PACKAGE_MANAGER}"
|
||||
##IF_NPM_AUTH##
|
||||
npm_auth: true
|
||||
npm_scopes: '${MUNITOR_NPM_SCOPES}'
|
||||
npm_default_scope: '${MUNITOR_NPM_DEFAULT_SCOPE}'
|
||||
##ENDIF_NPM_AUTH##
|
||||
##IF_SERVICES##
|
||||
services: '${MUNITOR_SERVICES_JSON}'
|
||||
##ENDIF_SERVICES##
|
||||
##IF_TEST_SETUP##
|
||||
test_setup: ${MUNITOR_TEST_SETUP_SCRIPT}
|
||||
##ENDIF_TEST_SETUP##
|
||||
##IF_CUSTOM_TEST##
|
||||
test_commands: '${MUNITOR_TEST_COMMANDS_JSON}'
|
||||
##ENDIF_CUSTOM_TEST##
|
||||
context:
|
||||
- ${MUNITOR_CONTEXT_GITHUB}
|
||||
filters:
|
||||
branches:
|
||||
only:
|
||||
- /feature\/.*/
|
||||
- /hotfix\/.*/
|
||||
- munitor/secrets_scan:
|
||||
name: secrets-scan
|
||||
filters:
|
||||
branches:
|
||||
only:
|
||||
- /feature\/.*/
|
||||
- /hotfix\/.*/
|
||||
##IF_SAST##
|
||||
- munitor/sast_scan:
|
||||
name: sast-scan
|
||||
fail_on_findings: "${MUNITOR_SAST_FAIL_ON_FINDINGS}"
|
||||
filters:
|
||||
branches:
|
||||
only:
|
||||
- /feature\/.*/
|
||||
- /hotfix\/.*/
|
||||
##ENDIF_SAST##
|
||||
- munitor/node_code_quality:
|
||||
name: code-quality
|
||||
node_version: "${MUNITOR_NODE_VERSION}"
|
||||
package_manager: "${MUNITOR_PACKAGE_MANAGER}"
|
||||
requires:
|
||||
- build-and-test
|
||||
filters:
|
||||
branches:
|
||||
only:
|
||||
- /feature\/.*/
|
||||
- /hotfix\/.*/
|
||||
- munitor/node_coverage:
|
||||
name: coverage
|
||||
node_version: "${MUNITOR_NODE_VERSION}"
|
||||
package_manager: "${MUNITOR_PACKAGE_MANAGER}"
|
||||
min_coverage: "${MUNITOR_COVERAGE_MIN}"
|
||||
coverage_tool: ${MUNITOR_COVERAGE_TOOL}
|
||||
coverage_summary_path: "${MUNITOR_COVERAGE_SUMMARY_PATH}"
|
||||
##IF_COVERAGE_CMD##
|
||||
coverage_command: ${MUNITOR_COVERAGE_COMMAND}
|
||||
##ENDIF_COVERAGE_CMD##
|
||||
requires:
|
||||
- build-and-test
|
||||
filters:
|
||||
branches:
|
||||
only:
|
||||
- /feature\/.*/
|
||||
- /hotfix\/.*/
|
||||
- munitor/node_security_scan:
|
||||
name: security-scan
|
||||
node_version: "${MUNITOR_NODE_VERSION}"
|
||||
package_manager: "${MUNITOR_PACKAGE_MANAGER}"
|
||||
requires:
|
||||
- build-and-test
|
||||
filters:
|
||||
branches:
|
||||
only:
|
||||
- /feature\/.*/
|
||||
- /hotfix\/.*/
|
||||
##IF_E2E##
|
||||
- munitor/node_e2e_test:
|
||||
name: e2e-tests
|
||||
node_version: "${MUNITOR_NODE_VERSION}"
|
||||
package_manager: "${MUNITOR_PACKAGE_MANAGER}"
|
||||
requires:
|
||||
- build-and-test
|
||||
filters:
|
||||
branches:
|
||||
only:
|
||||
- /feature\/.*/
|
||||
- /hotfix\/.*/
|
||||
##ENDIF_E2E##
|
||||
|
||||
develop:
|
||||
jobs:
|
||||
- munitor/node_build_and_test:
|
||||
name: build-and-test
|
||||
node_version: "${MUNITOR_NODE_VERSION}"
|
||||
package_manager: "${MUNITOR_PACKAGE_MANAGER}"
|
||||
##IF_NPM_AUTH##
|
||||
npm_auth: true
|
||||
npm_scopes: '${MUNITOR_NPM_SCOPES}'
|
||||
npm_default_scope: '${MUNITOR_NPM_DEFAULT_SCOPE}'
|
||||
##ENDIF_NPM_AUTH##
|
||||
##IF_SERVICES##
|
||||
services: '${MUNITOR_SERVICES_JSON}'
|
||||
##ENDIF_SERVICES##
|
||||
##IF_TEST_SETUP##
|
||||
test_setup: ${MUNITOR_TEST_SETUP_SCRIPT}
|
||||
##ENDIF_TEST_SETUP##
|
||||
##IF_CUSTOM_TEST##
|
||||
test_commands: '${MUNITOR_TEST_COMMANDS_JSON}'
|
||||
##ENDIF_CUSTOM_TEST##
|
||||
context:
|
||||
- ${MUNITOR_CONTEXT_GITHUB}
|
||||
filters:
|
||||
branches:
|
||||
only: develop
|
||||
|
||||
release-candidate:
|
||||
jobs:
|
||||
- munitor/node_build_and_test:
|
||||
name: build-and-test
|
||||
node_version: "${MUNITOR_NODE_VERSION}"
|
||||
package_manager: "${MUNITOR_PACKAGE_MANAGER}"
|
||||
##IF_NPM_AUTH##
|
||||
npm_auth: true
|
||||
npm_scopes: '${MUNITOR_NPM_SCOPES}'
|
||||
npm_default_scope: '${MUNITOR_NPM_DEFAULT_SCOPE}'
|
||||
##ENDIF_NPM_AUTH##
|
||||
##IF_SERVICES##
|
||||
services: '${MUNITOR_SERVICES_JSON}'
|
||||
##ENDIF_SERVICES##
|
||||
##IF_TEST_SETUP##
|
||||
test_setup: ${MUNITOR_TEST_SETUP_SCRIPT}
|
||||
##ENDIF_TEST_SETUP##
|
||||
##IF_CUSTOM_TEST##
|
||||
test_commands: '${MUNITOR_TEST_COMMANDS_JSON}'
|
||||
##ENDIF_CUSTOM_TEST##
|
||||
context:
|
||||
- ${MUNITOR_CONTEXT_GITHUB}
|
||||
filters:
|
||||
branches:
|
||||
only:
|
||||
- /release\/.*/
|
||||
- munitor/secrets_scan:
|
||||
name: secrets-scan
|
||||
filters:
|
||||
branches:
|
||||
only:
|
||||
- /release\/.*/
|
||||
##IF_SAST##
|
||||
- munitor/sast_scan:
|
||||
name: sast-scan
|
||||
fail_on_findings: "${MUNITOR_SAST_FAIL_ON_FINDINGS}"
|
||||
filters:
|
||||
branches:
|
||||
only:
|
||||
- /release\/.*/
|
||||
##ENDIF_SAST##
|
||||
- munitor/node_code_quality:
|
||||
name: code-quality
|
||||
node_version: "${MUNITOR_NODE_VERSION}"
|
||||
package_manager: "${MUNITOR_PACKAGE_MANAGER}"
|
||||
requires:
|
||||
- build-and-test
|
||||
filters:
|
||||
branches:
|
||||
only:
|
||||
- /release\/.*/
|
||||
- munitor/node_coverage:
|
||||
name: coverage
|
||||
node_version: "${MUNITOR_NODE_VERSION}"
|
||||
package_manager: "${MUNITOR_PACKAGE_MANAGER}"
|
||||
min_coverage: "${MUNITOR_COVERAGE_MIN}"
|
||||
coverage_tool: ${MUNITOR_COVERAGE_TOOL}
|
||||
coverage_summary_path: "${MUNITOR_COVERAGE_SUMMARY_PATH}"
|
||||
##IF_COVERAGE_CMD##
|
||||
coverage_command: ${MUNITOR_COVERAGE_COMMAND}
|
||||
##ENDIF_COVERAGE_CMD##
|
||||
requires:
|
||||
- build-and-test
|
||||
filters:
|
||||
branches:
|
||||
only:
|
||||
- /release\/.*/
|
||||
- munitor/node_security_scan:
|
||||
name: security-scan
|
||||
node_version: "${MUNITOR_NODE_VERSION}"
|
||||
package_manager: "${MUNITOR_PACKAGE_MANAGER}"
|
||||
requires:
|
||||
- build-and-test
|
||||
filters:
|
||||
branches:
|
||||
only:
|
||||
- /release\/.*/
|
||||
##IF_E2E##
|
||||
- munitor/node_e2e_test:
|
||||
name: e2e-tests
|
||||
node_version: "${MUNITOR_NODE_VERSION}"
|
||||
package_manager: "${MUNITOR_PACKAGE_MANAGER}"
|
||||
requires:
|
||||
- build-and-test
|
||||
filters:
|
||||
branches:
|
||||
only:
|
||||
- /release\/.*/
|
||||
##ENDIF_E2E##
|
||||
##IF_SONAR##
|
||||
- munitor/node_sonar_scan:
|
||||
name: sonar-scan
|
||||
node_version: "${MUNITOR_NODE_VERSION}"
|
||||
package_manager: "${MUNITOR_PACKAGE_MANAGER}"
|
||||
sonar_project_key: ${MUNITOR_SONAR_PROJECT_KEY}
|
||||
requires:
|
||||
- build-and-test
|
||||
- coverage
|
||||
context:
|
||||
- ${MUNITOR_CONTEXT_SONAR}
|
||||
filters:
|
||||
branches:
|
||||
only:
|
||||
- /release\/.*/
|
||||
##ENDIF_SONAR##
|
||||
##IF_SBOM##
|
||||
- munitor/node_sbom:
|
||||
name: sbom
|
||||
node_version: "${MUNITOR_NODE_VERSION}"
|
||||
package_manager: "${MUNITOR_PACKAGE_MANAGER}"
|
||||
context:
|
||||
- ${MUNITOR_CONTEXT_GITHUB}
|
||||
requires:
|
||||
- code-quality
|
||||
- coverage
|
||||
- secrets-scan
|
||||
##IF_SAST##
|
||||
- sast-scan
|
||||
##ENDIF_SAST##
|
||||
- security-scan
|
||||
##IF_E2E##
|
||||
- e2e-tests
|
||||
##ENDIF_E2E##
|
||||
filters:
|
||||
branches:
|
||||
only:
|
||||
- /release\/.*/
|
||||
##ENDIF_SBOM##
|
||||
- munitor/github_release:
|
||||
name: github-release
|
||||
release_artifacts: "main.js manifest.json styles.css"
|
||||
requires:
|
||||
- code-quality
|
||||
- coverage
|
||||
- secrets-scan
|
||||
##IF_SAST##
|
||||
- sast-scan
|
||||
##ENDIF_SAST##
|
||||
- security-scan
|
||||
##IF_E2E##
|
||||
- e2e-tests
|
||||
##ENDIF_E2E##
|
||||
context:
|
||||
- ${MUNITOR_CONTEXT_GITHUB}
|
||||
filters:
|
||||
branches:
|
||||
only:
|
||||
- /release\/.*/
|
||||
|
||||
production:
|
||||
jobs:
|
||||
- munitor/node_build_and_test:
|
||||
name: build-and-test
|
||||
node_version: "${MUNITOR_NODE_VERSION}"
|
||||
package_manager: "${MUNITOR_PACKAGE_MANAGER}"
|
||||
##IF_NPM_AUTH##
|
||||
npm_auth: true
|
||||
npm_scopes: '${MUNITOR_NPM_SCOPES}'
|
||||
npm_default_scope: '${MUNITOR_NPM_DEFAULT_SCOPE}'
|
||||
##ENDIF_NPM_AUTH##
|
||||
##IF_SERVICES##
|
||||
services: '${MUNITOR_SERVICES_JSON}'
|
||||
##ENDIF_SERVICES##
|
||||
##IF_TEST_SETUP##
|
||||
test_setup: ${MUNITOR_TEST_SETUP_SCRIPT}
|
||||
##ENDIF_TEST_SETUP##
|
||||
##IF_CUSTOM_TEST##
|
||||
test_commands: '${MUNITOR_TEST_COMMANDS_JSON}'
|
||||
##ENDIF_CUSTOM_TEST##
|
||||
context:
|
||||
- ${MUNITOR_CONTEXT_GITHUB}
|
||||
filters:
|
||||
branches:
|
||||
only: main
|
||||
- munitor/github_release:
|
||||
name: github-release
|
||||
release_artifacts: "main.js manifest.json styles.css"
|
||||
requires:
|
||||
- build-and-test
|
||||
context:
|
||||
- ${MUNITOR_CONTEXT_GITHUB}
|
||||
filters:
|
||||
branches:
|
||||
only: main
|
||||
@@ -1,8 +1,9 @@
|
||||
__WORKFLOW_NAME__:
|
||||
jobs:
|
||||
- munitor/npm_build_and_test:
|
||||
- munitor/node_build_and_test:
|
||||
name: build-and-test
|
||||
node_version: "${MUNITOR_NODE_VERSION}"
|
||||
package_manager: "${MUNITOR_PACKAGE_MANAGER}"
|
||||
##IF_NPM_AUTH##
|
||||
npm_auth: true
|
||||
npm_scopes: '${MUNITOR_NPM_SCOPES}'
|
||||
@@ -33,17 +34,22 @@
|
||||
filters:
|
||||
branches:
|
||||
only: __BRANCH_FILTER__
|
||||
- munitor/npm_code_quality:
|
||||
- munitor/node_code_quality:
|
||||
name: code-quality
|
||||
node_version: "${MUNITOR_NODE_VERSION}"
|
||||
package_manager: "${MUNITOR_PACKAGE_MANAGER}"
|
||||
requires:
|
||||
- build-and-test
|
||||
filters:
|
||||
branches:
|
||||
only: __BRANCH_FILTER__
|
||||
- munitor/npm_coverage:
|
||||
- munitor/node_coverage:
|
||||
name: coverage
|
||||
node_version: "${MUNITOR_NODE_VERSION}"
|
||||
package_manager: "${MUNITOR_PACKAGE_MANAGER}"
|
||||
min_coverage: "${MUNITOR_COVERAGE_MIN}"
|
||||
coverage_tool: ${MUNITOR_COVERAGE_TOOL}
|
||||
coverage_summary_path: "${MUNITOR_COVERAGE_SUMMARY_PATH}"
|
||||
##IF_COVERAGE_CMD##
|
||||
coverage_command: ${MUNITOR_COVERAGE_COMMAND}
|
||||
##ENDIF_COVERAGE_CMD##
|
||||
@@ -52,16 +58,20 @@
|
||||
filters:
|
||||
branches:
|
||||
only: __BRANCH_FILTER__
|
||||
- munitor/npm_security_scan:
|
||||
- munitor/node_security_scan:
|
||||
name: security-scan
|
||||
node_version: "${MUNITOR_NODE_VERSION}"
|
||||
package_manager: "${MUNITOR_PACKAGE_MANAGER}"
|
||||
requires:
|
||||
- build-and-test
|
||||
filters:
|
||||
branches:
|
||||
only: __BRANCH_FILTER__
|
||||
##IF_E2E##
|
||||
- munitor/npm_e2e_test:
|
||||
- munitor/node_e2e_test:
|
||||
name: e2e-tests
|
||||
node_version: "${MUNITOR_NODE_VERSION}"
|
||||
package_manager: "${MUNITOR_PACKAGE_MANAGER}"
|
||||
requires:
|
||||
- build-and-test
|
||||
filters:
|
||||
@@ -69,9 +79,10 @@
|
||||
only: __BRANCH_FILTER__
|
||||
##ENDIF_E2E##
|
||||
##IF_SONAR##
|
||||
- munitor/npm_sonar_scan:
|
||||
- munitor/node_sonar_scan:
|
||||
name: sonar-scan
|
||||
node_version: "${MUNITOR_NODE_VERSION}"
|
||||
package_manager: "${MUNITOR_PACKAGE_MANAGER}"
|
||||
sonar_project_key: ${MUNITOR_SONAR_PROJECT_KEY}
|
||||
requires:
|
||||
- build-and-test
|
||||
@@ -107,9 +118,10 @@
|
||||
branches:
|
||||
only: __BRANCH_FILTER__
|
||||
##IF_SBOM##
|
||||
- munitor/npm_sbom:
|
||||
- munitor/node_sbom:
|
||||
name: sbom
|
||||
node_version: "${MUNITOR_NODE_VERSION}"
|
||||
package_manager: "${MUNITOR_PACKAGE_MANAGER}"
|
||||
context:
|
||||
- ${MUNITOR_CONTEXT_GITHUB}
|
||||
requires:
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
__WORKFLOW_NAME__:
|
||||
jobs:
|
||||
- munitor/npm_build_and_test:
|
||||
- munitor/node_build_and_test:
|
||||
name: build-and-test
|
||||
node_version: "${MUNITOR_NODE_VERSION}"
|
||||
package_manager: "${MUNITOR_PACKAGE_MANAGER}"
|
||||
##IF_NPM_AUTH##
|
||||
npm_auth: true
|
||||
npm_scopes: '${MUNITOR_NPM_SCOPES}'
|
||||
@@ -33,17 +34,22 @@
|
||||
filters:
|
||||
branches:
|
||||
only: __BRANCH_FILTER__
|
||||
- munitor/npm_code_quality:
|
||||
- munitor/node_code_quality:
|
||||
name: code-quality
|
||||
node_version: "${MUNITOR_NODE_VERSION}"
|
||||
package_manager: "${MUNITOR_PACKAGE_MANAGER}"
|
||||
requires:
|
||||
- build-and-test
|
||||
filters:
|
||||
branches:
|
||||
only: __BRANCH_FILTER__
|
||||
- munitor/npm_coverage:
|
||||
- munitor/node_coverage:
|
||||
name: coverage
|
||||
node_version: "${MUNITOR_NODE_VERSION}"
|
||||
package_manager: "${MUNITOR_PACKAGE_MANAGER}"
|
||||
min_coverage: "${MUNITOR_COVERAGE_MIN}"
|
||||
coverage_tool: ${MUNITOR_COVERAGE_TOOL}
|
||||
coverage_summary_path: "${MUNITOR_COVERAGE_SUMMARY_PATH}"
|
||||
##IF_COVERAGE_CMD##
|
||||
coverage_command: ${MUNITOR_COVERAGE_COMMAND}
|
||||
##ENDIF_COVERAGE_CMD##
|
||||
@@ -52,16 +58,20 @@
|
||||
filters:
|
||||
branches:
|
||||
only: __BRANCH_FILTER__
|
||||
- munitor/npm_security_scan:
|
||||
- munitor/node_security_scan:
|
||||
name: security-scan
|
||||
node_version: "${MUNITOR_NODE_VERSION}"
|
||||
package_manager: "${MUNITOR_PACKAGE_MANAGER}"
|
||||
requires:
|
||||
- build-and-test
|
||||
filters:
|
||||
branches:
|
||||
only: __BRANCH_FILTER__
|
||||
##IF_E2E##
|
||||
- munitor/npm_e2e_test:
|
||||
- munitor/node_e2e_test:
|
||||
name: e2e-tests
|
||||
node_version: "${MUNITOR_NODE_VERSION}"
|
||||
package_manager: "${MUNITOR_PACKAGE_MANAGER}"
|
||||
requires:
|
||||
- build-and-test
|
||||
filters:
|
||||
@@ -69,9 +79,10 @@
|
||||
only: __BRANCH_FILTER__
|
||||
##ENDIF_E2E##
|
||||
##IF_SONAR##
|
||||
- munitor/npm_sonar_scan:
|
||||
- munitor/node_sonar_scan:
|
||||
name: sonar-scan
|
||||
node_version: "${MUNITOR_NODE_VERSION}"
|
||||
package_manager: "${MUNITOR_PACKAGE_MANAGER}"
|
||||
sonar_project_key: ${MUNITOR_SONAR_PROJECT_KEY}
|
||||
requires:
|
||||
- build-and-test
|
||||
@@ -107,9 +118,10 @@
|
||||
branches:
|
||||
only: __BRANCH_FILTER__
|
||||
##IF_SBOM##
|
||||
- munitor/npm_sbom:
|
||||
- munitor/node_sbom:
|
||||
name: sbom
|
||||
node_version: "${MUNITOR_NODE_VERSION}"
|
||||
package_manager: "${MUNITOR_PACKAGE_MANAGER}"
|
||||
context:
|
||||
- ${MUNITOR_CONTEXT_GITHUB}
|
||||
requires:
|
||||
|
||||
+12
@@ -0,0 +1,12 @@
|
||||
pipeline: obsidian-plugin
|
||||
orb_version: dev:snapshot
|
||||
node_version: "20"
|
||||
sast: true
|
||||
sbom: true
|
||||
test:
|
||||
commands: ["npm run build", "npm test"]
|
||||
coverage:
|
||||
tool: vitest
|
||||
command: npx vitest run --coverage
|
||||
contexts:
|
||||
github: github
|
||||
+10
@@ -0,0 +1,10 @@
|
||||
pipeline: node-webapp
|
||||
orb_version: dev:snapshot
|
||||
package_manager: pnpm
|
||||
node_version: "22"
|
||||
image_name: ghcr.io/koftwentytwo/pnpm-app
|
||||
docker:
|
||||
registry: ghcr.io/koftwentytwo
|
||||
health:
|
||||
path: /api/health
|
||||
port: "3000"
|
||||
@@ -263,6 +263,9 @@ assert_eq "health_port default 3000" "3000" "${MUNITOR_HEALTH_PORT}"
|
||||
assert_eq "coverage min default" "70" "${MUNITOR_COVERAGE_MIN}"
|
||||
assert_eq "package_manager default" "npm" "${MUNITOR_PACKAGE_MANAGER}"
|
||||
|
||||
extract_munitor_vars "${FIXTURES_DIR}/pnpm-webapp.munitor.yml"
|
||||
assert_eq "pnpm package_manager is extracted" "pnpm" "${MUNITOR_PACKAGE_MANAGER}"
|
||||
|
||||
# --------------------------------------------------------------------------
|
||||
# supplemental_images (enabled)
|
||||
# --------------------------------------------------------------------------
|
||||
|
||||
+196
-34
@@ -175,13 +175,13 @@ run_test "java-webapp: includes sbom when enabled" \
|
||||
"${FIXTURES_DIR}/java-webapp.munitor.yml" \
|
||||
"sbom"
|
||||
|
||||
run_test "java-webapp: uses mvn sbom (not npm_sbom)" \
|
||||
run_test "java-webapp: uses mvn sbom (not node_sbom)" \
|
||||
"${FIXTURES_DIR}/java-webapp.munitor.yml" \
|
||||
"munitor/sbom"
|
||||
|
||||
run_negative_test "java-webapp: does not use npm_sbom" \
|
||||
run_negative_test "java-webapp: does not use node_sbom" \
|
||||
"${FIXTURES_DIR}/java-webapp.munitor.yml" \
|
||||
"munitor/npm_sbom"
|
||||
"munitor/node_sbom"
|
||||
|
||||
# Java-webapp sonar should still gate docker-build-push (regression guard)
|
||||
run_context_test "java-webapp: sonar-scan blocks docker-build-push" \
|
||||
@@ -228,26 +228,26 @@ run_test "node-api: includes sonar when project_key set" \
|
||||
"${FIXTURES_DIR}/node-api.munitor.yml" \
|
||||
"sonar-scan"
|
||||
|
||||
run_test "node-api: uses npm_sonar_scan (not mvn sonar_scan)" \
|
||||
run_test "node-api: uses node_sonar_scan (not mvn sonar_scan)" \
|
||||
"${FIXTURES_DIR}/node-api.munitor.yml" \
|
||||
"munitor/npm_sonar_scan"
|
||||
"munitor/node_sonar_scan"
|
||||
|
||||
run_test "node-api: includes sbom when enabled" \
|
||||
"${FIXTURES_DIR}/node-api.munitor.yml" \
|
||||
"sbom"
|
||||
|
||||
run_test "node-api: uses npm_sbom (not mvn sbom)" \
|
||||
run_test "node-api: uses node_sbom (not mvn sbom)" \
|
||||
"${FIXTURES_DIR}/node-api.munitor.yml" \
|
||||
"munitor/npm_sbom"
|
||||
"munitor/node_sbom"
|
||||
|
||||
run_negative_test "node-api: does not use mvn sbom job" \
|
||||
"${FIXTURES_DIR}/node-api.munitor.yml" \
|
||||
"munitor/sbom:"
|
||||
|
||||
# Verify the npm_sbom block includes the node_version parameter
|
||||
run_context_test "node-api: npm_sbom passes node_version" \
|
||||
# Verify the node_sbom block includes the node_version parameter
|
||||
run_context_test "node-api: node_sbom passes node_version" \
|
||||
"${FIXTURES_DIR}/node-api.munitor.yml" \
|
||||
"munitor/npm_sbom" \
|
||||
"munitor/node_sbom" \
|
||||
"requires:" \
|
||||
"node_version:"
|
||||
|
||||
@@ -263,17 +263,17 @@ run_test "node-api: sonar-scan job still present in workflow" \
|
||||
"${FIXTURES_DIR}/node-api.munitor.yml" \
|
||||
"name: sonar-scan"
|
||||
|
||||
run_test "node-api: uses npm jobs" \
|
||||
run_test "node-api: uses node jobs" \
|
||||
"${FIXTURES_DIR}/node-api.munitor.yml" \
|
||||
"npm_build_and_test"
|
||||
"node_build_and_test"
|
||||
|
||||
run_test "node-api: includes npm code quality" \
|
||||
run_test "node-api: includes node code quality" \
|
||||
"${FIXTURES_DIR}/node-api.munitor.yml" \
|
||||
"npm_code_quality"
|
||||
"node_code_quality"
|
||||
|
||||
run_test "node-api: includes npm security scan" \
|
||||
run_test "node-api: includes node security scan" \
|
||||
"${FIXTURES_DIR}/node-api.munitor.yml" \
|
||||
"npm_security_scan"
|
||||
"node_security_scan"
|
||||
|
||||
# Test node-api-minimal: e2e/sbom/sonar/extended features should be excluded
|
||||
run_test "node-api-minimal: renders node 22" \
|
||||
@@ -349,9 +349,9 @@ run_test "node-api-services: coverage min from test.coverage.min_instruction" \
|
||||
"${FIXTURES_DIR}/node-api-services.munitor.yml" \
|
||||
'min_coverage: "70"'
|
||||
|
||||
run_test "node-api-services: uses npm_sbom for sbom" \
|
||||
run_test "node-api-services: uses node_sbom for sbom" \
|
||||
"${FIXTURES_DIR}/node-api-services.munitor.yml" \
|
||||
"munitor/npm_sbom"
|
||||
"munitor/node_sbom"
|
||||
|
||||
run_negative_test "node-api-services: does not use mvn sbom job" \
|
||||
"${FIXTURES_DIR}/node-api-services.munitor.yml" \
|
||||
@@ -403,33 +403,33 @@ run_test "node-webapp: includes sonar when project_key set" \
|
||||
"${FIXTURES_DIR}/node-webapp.munitor.yml" \
|
||||
"sonar-scan"
|
||||
|
||||
run_test "node-webapp: uses npm_sonar_scan (not mvn sonar_scan)" \
|
||||
run_test "node-webapp: uses node_sonar_scan (not mvn sonar_scan)" \
|
||||
"${FIXTURES_DIR}/node-webapp.munitor.yml" \
|
||||
"munitor/npm_sonar_scan"
|
||||
"munitor/node_sonar_scan"
|
||||
|
||||
run_test "node-webapp: includes sbom when enabled" \
|
||||
"${FIXTURES_DIR}/node-webapp.munitor.yml" \
|
||||
"sbom"
|
||||
|
||||
run_test "node-webapp: uses npm_sbom (not mvn sbom)" \
|
||||
run_test "node-webapp: uses node_sbom (not mvn sbom)" \
|
||||
"${FIXTURES_DIR}/node-webapp.munitor.yml" \
|
||||
"munitor/npm_sbom"
|
||||
"munitor/node_sbom"
|
||||
|
||||
run_test "node-webapp: uses npm_build_and_test" \
|
||||
run_test "node-webapp: uses node_build_and_test" \
|
||||
"${FIXTURES_DIR}/node-webapp.munitor.yml" \
|
||||
"npm_build_and_test"
|
||||
"node_build_and_test"
|
||||
|
||||
run_test "node-webapp: includes npm code quality" \
|
||||
run_test "node-webapp: includes node code quality" \
|
||||
"${FIXTURES_DIR}/node-webapp.munitor.yml" \
|
||||
"npm_code_quality"
|
||||
"node_code_quality"
|
||||
|
||||
run_test "node-webapp: includes npm coverage" \
|
||||
run_test "node-webapp: includes node coverage" \
|
||||
"${FIXTURES_DIR}/node-webapp.munitor.yml" \
|
||||
"npm_coverage"
|
||||
"node_coverage"
|
||||
|
||||
run_test "node-webapp: includes npm security scan" \
|
||||
run_test "node-webapp: includes node security scan" \
|
||||
"${FIXTURES_DIR}/node-webapp.munitor.yml" \
|
||||
"npm_security_scan"
|
||||
"node_security_scan"
|
||||
|
||||
# Sonar non-blocking: sonar-scan should NOT be in docker-build-push requires
|
||||
run_negative_context_test "node-webapp: sonar-scan not in docker-build-push requires" \
|
||||
@@ -689,13 +689,13 @@ run_negative_context_test "node-api: production has no coverage" \
|
||||
"${FIXTURES_DIR}/node-api.munitor.yml" \
|
||||
"production:" \
|
||||
"release-candidate:" \
|
||||
"npm_coverage"
|
||||
"node_coverage"
|
||||
|
||||
run_negative_context_test "node-api: production has no security-scan" \
|
||||
"${FIXTURES_DIR}/node-api.munitor.yml" \
|
||||
"production:" \
|
||||
"release-candidate:" \
|
||||
"npm_security_scan"
|
||||
"node_security_scan"
|
||||
|
||||
# node-api: release-candidate has quality gates
|
||||
run_context_test "node-api: release-candidate has code-quality" \
|
||||
@@ -728,13 +728,13 @@ run_negative_context_test "node-webapp: production has no coverage" \
|
||||
"${FIXTURES_DIR}/node-webapp.munitor.yml" \
|
||||
"production:" \
|
||||
"release-candidate:" \
|
||||
"npm_coverage"
|
||||
"node_coverage"
|
||||
|
||||
run_negative_context_test "node-webapp: production has no security-scan" \
|
||||
"${FIXTURES_DIR}/node-webapp.munitor.yml" \
|
||||
"production:" \
|
||||
"release-candidate:" \
|
||||
"npm_security_scan"
|
||||
"node_security_scan"
|
||||
|
||||
# node-webapp: release-candidate has quality gates
|
||||
run_context_test "node-webapp: release-candidate has code-quality" \
|
||||
@@ -753,6 +753,24 @@ run_test "node-webapp: includes update-cd-repo when cd.repo set" \
|
||||
"${FIXTURES_DIR}/node-webapp.munitor.yml" \
|
||||
"update-cd-repo"
|
||||
|
||||
# ============================================================
|
||||
# pnpm node-webapp
|
||||
# ============================================================
|
||||
echo ""
|
||||
echo "=== pnpm node-webapp tests ==="
|
||||
|
||||
run_test "pnpm-webapp: uses node_build_and_test" \
|
||||
"${FIXTURES_DIR}/pnpm-webapp.munitor.yml" \
|
||||
"node_build_and_test"
|
||||
|
||||
run_test "pnpm-webapp: passes package_manager param" \
|
||||
"${FIXTURES_DIR}/pnpm-webapp.munitor.yml" \
|
||||
'package_manager: "pnpm"'
|
||||
|
||||
run_negative_test "pnpm-webapp: does not reference npm_build_and_test" \
|
||||
"${FIXTURES_DIR}/pnpm-webapp.munitor.yml" \
|
||||
"npm_build_and_test"
|
||||
|
||||
# terraform: has release-candidate and production workflows
|
||||
run_test "terraform: has release-candidate workflow" \
|
||||
"${FIXTURES_DIR}/terraform.munitor.yml" \
|
||||
@@ -1213,6 +1231,150 @@ run_negative_test "gradle-webapp: no sonar block (sonar not configured)" \
|
||||
"${FIXTURES_DIR}/gradle-webapp.munitor.yml" \
|
||||
"sonar-scan"
|
||||
|
||||
# ============================================================
|
||||
# obsidian-plugin template rendering
|
||||
# ============================================================
|
||||
echo ""
|
||||
echo "=== obsidian-plugin Template Rendering Tests ==="
|
||||
|
||||
# Basic rendering
|
||||
run_test "obsidian-plugin: renders node_version" \
|
||||
"${FIXTURES_DIR}/obsidian-plugin.munitor.yml" \
|
||||
"node_version: \"20\""
|
||||
|
||||
run_test "obsidian-plugin: uses node_build_and_test" \
|
||||
"${FIXTURES_DIR}/obsidian-plugin.munitor.yml" \
|
||||
"node_build_and_test"
|
||||
|
||||
run_test "obsidian-plugin: includes node code quality" \
|
||||
"${FIXTURES_DIR}/obsidian-plugin.munitor.yml" \
|
||||
"node_code_quality"
|
||||
|
||||
run_test "obsidian-plugin: includes node coverage" \
|
||||
"${FIXTURES_DIR}/obsidian-plugin.munitor.yml" \
|
||||
"node_coverage"
|
||||
|
||||
run_test "obsidian-plugin: includes node security scan" \
|
||||
"${FIXTURES_DIR}/obsidian-plugin.munitor.yml" \
|
||||
"node_security_scan"
|
||||
|
||||
run_test "obsidian-plugin: includes sast-scan" \
|
||||
"${FIXTURES_DIR}/obsidian-plugin.munitor.yml" \
|
||||
"sast-scan"
|
||||
|
||||
run_test "obsidian-plugin: includes secrets-scan" \
|
||||
"${FIXTURES_DIR}/obsidian-plugin.munitor.yml" \
|
||||
"secrets-scan"
|
||||
|
||||
run_test "obsidian-plugin: includes sbom when enabled" \
|
||||
"${FIXTURES_DIR}/obsidian-plugin.munitor.yml" \
|
||||
"sbom"
|
||||
|
||||
run_test "obsidian-plugin: includes test_commands" \
|
||||
"${FIXTURES_DIR}/obsidian-plugin.munitor.yml" \
|
||||
"test_commands:"
|
||||
|
||||
run_test "obsidian-plugin: includes coverage_command" \
|
||||
"${FIXTURES_DIR}/obsidian-plugin.munitor.yml" \
|
||||
"coverage_command:"
|
||||
|
||||
run_test "obsidian-plugin: includes coverage_tool vitest" \
|
||||
"${FIXTURES_DIR}/obsidian-plugin.munitor.yml" \
|
||||
"coverage_tool: vitest"
|
||||
|
||||
# Workflow presence
|
||||
run_test "obsidian-plugin: has pr-checks workflow" \
|
||||
"${FIXTURES_DIR}/obsidian-plugin.munitor.yml" \
|
||||
"pr-checks:"
|
||||
|
||||
run_test "obsidian-plugin: has develop workflow" \
|
||||
"${FIXTURES_DIR}/obsidian-plugin.munitor.yml" \
|
||||
"develop:"
|
||||
|
||||
run_test "obsidian-plugin: has release-candidate workflow" \
|
||||
"${FIXTURES_DIR}/obsidian-plugin.munitor.yml" \
|
||||
"release-candidate:"
|
||||
|
||||
run_test "obsidian-plugin: has production workflow" \
|
||||
"${FIXTURES_DIR}/obsidian-plugin.munitor.yml" \
|
||||
"production:"
|
||||
|
||||
# GitHub Release with artifacts
|
||||
run_test "obsidian-plugin: has github-release job" \
|
||||
"${FIXTURES_DIR}/obsidian-plugin.munitor.yml" \
|
||||
"github-release"
|
||||
|
||||
run_test "obsidian-plugin: github-release has release_artifacts" \
|
||||
"${FIXTURES_DIR}/obsidian-plugin.munitor.yml" \
|
||||
"release_artifacts:"
|
||||
|
||||
run_test "obsidian-plugin: release_artifacts includes main.js" \
|
||||
"${FIXTURES_DIR}/obsidian-plugin.munitor.yml" \
|
||||
"main.js manifest.json styles.css"
|
||||
|
||||
# Release-candidate has quality gates
|
||||
run_context_test "obsidian-plugin: release-candidate has code-quality" \
|
||||
"${FIXTURES_DIR}/obsidian-plugin.munitor.yml" \
|
||||
"release-candidate:" \
|
||||
"production:" \
|
||||
"code-quality"
|
||||
|
||||
run_context_test "obsidian-plugin: release-candidate has coverage" \
|
||||
"${FIXTURES_DIR}/obsidian-plugin.munitor.yml" \
|
||||
"release-candidate:" \
|
||||
"production:" \
|
||||
"node_coverage"
|
||||
|
||||
run_context_test "obsidian-plugin: release-candidate has security-scan" \
|
||||
"${FIXTURES_DIR}/obsidian-plugin.munitor.yml" \
|
||||
"release-candidate:" \
|
||||
"production:" \
|
||||
"node_security_scan"
|
||||
|
||||
# Production has NO quality gates (fast-path)
|
||||
run_negative_context_test "obsidian-plugin: production has no code-quality" \
|
||||
"${FIXTURES_DIR}/obsidian-plugin.munitor.yml" \
|
||||
"production:" \
|
||||
"release-candidate:" \
|
||||
"code-quality"
|
||||
|
||||
run_negative_context_test "obsidian-plugin: production has no coverage" \
|
||||
"${FIXTURES_DIR}/obsidian-plugin.munitor.yml" \
|
||||
"production:" \
|
||||
"release-candidate:" \
|
||||
"node_coverage"
|
||||
|
||||
run_negative_context_test "obsidian-plugin: production has no security-scan" \
|
||||
"${FIXTURES_DIR}/obsidian-plugin.munitor.yml" \
|
||||
"production:" \
|
||||
"release-candidate:" \
|
||||
"node_security_scan"
|
||||
|
||||
# Negative tests: no Docker/CD artifacts
|
||||
run_negative_test "obsidian-plugin: no docker-build-push" \
|
||||
"${FIXTURES_DIR}/obsidian-plugin.munitor.yml" \
|
||||
"docker-build-push"
|
||||
|
||||
run_negative_test "obsidian-plugin: no update-cd-repo" \
|
||||
"${FIXTURES_DIR}/obsidian-plugin.munitor.yml" \
|
||||
"update-cd-repo"
|
||||
|
||||
run_negative_test "obsidian-plugin: no image_name" \
|
||||
"${FIXTURES_DIR}/obsidian-plugin.munitor.yml" \
|
||||
"image_name:"
|
||||
|
||||
run_negative_test "obsidian-plugin: no registry" \
|
||||
"${FIXTURES_DIR}/obsidian-plugin.munitor.yml" \
|
||||
"registry:"
|
||||
|
||||
run_negative_test "obsidian-plugin: no INCLUDE_DEPLOY" \
|
||||
"${FIXTURES_DIR}/obsidian-plugin.munitor.yml" \
|
||||
"INCLUDE_DEPLOY"
|
||||
|
||||
run_negative_test "obsidian-plugin: no staging workflow" \
|
||||
"${FIXTURES_DIR}/obsidian-plugin.munitor.yml" \
|
||||
"staging:"
|
||||
|
||||
echo ""
|
||||
echo "=== Results: ${PASS} passed, ${FAIL} failed ==="
|
||||
|
||||
|
||||
@@ -495,6 +495,168 @@ else
|
||||
fi
|
||||
teardown
|
||||
|
||||
# =============================================================================
|
||||
# Test: node-webapp with pnpm generates correct Dockerfile
|
||||
# =============================================================================
|
||||
echo ""
|
||||
echo "=== node-webapp pnpm Dockerfile Generation ==="
|
||||
|
||||
echo -n " TEST: pnpm node-webapp includes corepack enable... "
|
||||
setup
|
||||
cat > "${WORK_DIR}/.munitor.yml" <<'EOF'
|
||||
pipeline: node-webapp
|
||||
image_name: my-webapp
|
||||
node_version: "22"
|
||||
package_manager: pnpm
|
||||
EOF
|
||||
run_generate > /dev/null
|
||||
if grep -q 'corepack enable' "${WORK_DIR}/Dockerfile"; then
|
||||
pass
|
||||
else
|
||||
fail "expected corepack enable"
|
||||
fi
|
||||
teardown
|
||||
|
||||
echo -n " TEST: pnpm node-webapp uses pnpm install --frozen-lockfile... "
|
||||
setup
|
||||
cat > "${WORK_DIR}/.munitor.yml" <<'EOF'
|
||||
pipeline: node-webapp
|
||||
image_name: my-webapp
|
||||
node_version: "22"
|
||||
package_manager: pnpm
|
||||
EOF
|
||||
run_generate > /dev/null
|
||||
if grep -q 'pnpm install --frozen-lockfile' "${WORK_DIR}/Dockerfile"; then
|
||||
pass
|
||||
else
|
||||
fail "expected pnpm install --frozen-lockfile"
|
||||
fi
|
||||
teardown
|
||||
|
||||
echo -n " TEST: pnpm node-webapp does not contain npm ci... "
|
||||
setup
|
||||
cat > "${WORK_DIR}/.munitor.yml" <<'EOF'
|
||||
pipeline: node-webapp
|
||||
image_name: my-webapp
|
||||
node_version: "22"
|
||||
package_manager: pnpm
|
||||
EOF
|
||||
run_generate > /dev/null
|
||||
if ! grep -q 'npm ci' "${WORK_DIR}/Dockerfile"; then
|
||||
pass
|
||||
else
|
||||
fail "expected no npm ci"
|
||||
fi
|
||||
teardown
|
||||
|
||||
# =============================================================================
|
||||
# Test: node-api (nextjs) with pnpm generates correct Dockerfile
|
||||
# =============================================================================
|
||||
echo ""
|
||||
echo "=== node-api pnpm (nextjs) Dockerfile Generation ==="
|
||||
|
||||
echo -n " TEST: pnpm node-api nextjs includes corepack enable... "
|
||||
setup
|
||||
cat > "${WORK_DIR}/.munitor.yml" <<'EOF'
|
||||
pipeline: node-api
|
||||
image_name: my-app
|
||||
package_manager: pnpm
|
||||
EOF
|
||||
run_generate > /dev/null
|
||||
if grep -q 'corepack enable' "${WORK_DIR}/Dockerfile"; then
|
||||
pass
|
||||
else
|
||||
fail "expected corepack enable"
|
||||
fi
|
||||
teardown
|
||||
|
||||
echo -n " TEST: pnpm node-api nextjs uses pnpm install --frozen-lockfile... "
|
||||
setup
|
||||
cat > "${WORK_DIR}/.munitor.yml" <<'EOF'
|
||||
pipeline: node-api
|
||||
image_name: my-app
|
||||
package_manager: pnpm
|
||||
EOF
|
||||
run_generate > /dev/null
|
||||
if grep -q 'pnpm install --frozen-lockfile' "${WORK_DIR}/Dockerfile"; then
|
||||
pass
|
||||
else
|
||||
fail "expected pnpm install --frozen-lockfile"
|
||||
fi
|
||||
teardown
|
||||
|
||||
echo -n " TEST: pnpm node-api nextjs does not contain npm ci... "
|
||||
setup
|
||||
cat > "${WORK_DIR}/.munitor.yml" <<'EOF'
|
||||
pipeline: node-api
|
||||
image_name: my-app
|
||||
package_manager: pnpm
|
||||
EOF
|
||||
run_generate > /dev/null
|
||||
if ! grep -q 'npm ci' "${WORK_DIR}/Dockerfile"; then
|
||||
pass
|
||||
else
|
||||
fail "expected no npm ci"
|
||||
fi
|
||||
teardown
|
||||
|
||||
# =============================================================================
|
||||
# Test: node-api (express) with pnpm generates correct Dockerfile
|
||||
# =============================================================================
|
||||
echo ""
|
||||
echo "=== node-api pnpm (express) Dockerfile Generation ==="
|
||||
|
||||
echo -n " TEST: pnpm node-api express includes corepack enable... "
|
||||
setup
|
||||
cat > "${WORK_DIR}/.munitor.yml" <<'EOF'
|
||||
pipeline: node-api
|
||||
image_name: my-app
|
||||
package_manager: pnpm
|
||||
node:
|
||||
framework: express
|
||||
EOF
|
||||
run_generate > /dev/null
|
||||
if grep -q 'corepack enable' "${WORK_DIR}/Dockerfile"; then
|
||||
pass
|
||||
else
|
||||
fail "expected corepack enable"
|
||||
fi
|
||||
teardown
|
||||
|
||||
echo -n " TEST: pnpm node-api express uses pnpm install --frozen-lockfile... "
|
||||
setup
|
||||
cat > "${WORK_DIR}/.munitor.yml" <<'EOF'
|
||||
pipeline: node-api
|
||||
image_name: my-app
|
||||
package_manager: pnpm
|
||||
node:
|
||||
framework: express
|
||||
EOF
|
||||
run_generate > /dev/null
|
||||
if grep -q 'pnpm install --frozen-lockfile' "${WORK_DIR}/Dockerfile"; then
|
||||
pass
|
||||
else
|
||||
fail "expected pnpm install --frozen-lockfile"
|
||||
fi
|
||||
teardown
|
||||
|
||||
echo -n " TEST: pnpm node-api express does not contain npm ci... "
|
||||
setup
|
||||
cat > "${WORK_DIR}/.munitor.yml" <<'EOF'
|
||||
pipeline: node-api
|
||||
image_name: my-app
|
||||
package_manager: pnpm
|
||||
node:
|
||||
framework: express
|
||||
EOF
|
||||
run_generate > /dev/null
|
||||
if ! grep -q 'npm ci' "${WORK_DIR}/Dockerfile"; then
|
||||
pass
|
||||
else
|
||||
fail "expected no npm ci"
|
||||
fi
|
||||
teardown
|
||||
|
||||
# =============================================================================
|
||||
# Test: unsupported pipeline type
|
||||
# =============================================================================
|
||||
|
||||
+88
-9
@@ -20,27 +20,27 @@ fail() {
|
||||
}
|
||||
|
||||
# =============================================================================
|
||||
# Test: npm_test.sh - Custom test commands
|
||||
# Test: node_test.sh - Custom test commands
|
||||
# =============================================================================
|
||||
echo "=== npm_test.sh Tests ==="
|
||||
echo "=== node_test.sh Tests ==="
|
||||
|
||||
echo -n " TEST: runs custom test commands via bash -c (not eval)... "
|
||||
# Verify the script uses bash -c, not eval
|
||||
if grep -q 'bash -c "\${CMD}"' "${SRC_SCRIPTS}/npm_test.sh"; then
|
||||
if grep -q 'bash -c "\${CMD}"' "${SRC_SCRIPTS}/node_test.sh"; then
|
||||
pass
|
||||
else
|
||||
fail "script should use 'bash -c' not 'eval'"
|
||||
fi
|
||||
|
||||
echo -n " TEST: creates reports/junit directory... "
|
||||
if grep -q 'mkdir -p reports/junit' "${SRC_SCRIPTS}/npm_test.sh"; then
|
||||
if grep -q 'mkdir -p reports/junit' "${SRC_SCRIPTS}/node_test.sh"; then
|
||||
pass
|
||||
else
|
||||
fail "should create reports/junit"
|
||||
fi
|
||||
|
||||
echo -n " TEST: handles empty TEST_COMMANDS_JSON... "
|
||||
if grep -q '\[\]' "${SRC_SCRIPTS}/npm_test.sh" && grep -q 'null' "${SRC_SCRIPTS}/npm_test.sh"; then
|
||||
if grep -q '\[\]' "${SRC_SCRIPTS}/node_test.sh" && grep -q 'null' "${SRC_SCRIPTS}/node_test.sh"; then
|
||||
pass
|
||||
else
|
||||
fail "should handle empty/null JSON"
|
||||
@@ -288,13 +288,13 @@ else
|
||||
fi
|
||||
|
||||
# =============================================================================
|
||||
# Test: npm_coverage_check.sh - Security
|
||||
# Test: node_coverage_check.sh - Security
|
||||
# =============================================================================
|
||||
echo ""
|
||||
echo "=== npm_coverage_check.sh Tests ==="
|
||||
echo "=== node_coverage_check.sh Tests ==="
|
||||
|
||||
echo -n " TEST: uses bash -c for coverage command (not eval)... "
|
||||
if grep -q 'bash -c "\${COVERAGE_COMMAND}"' "${SRC_SCRIPTS}/npm_coverage_check.sh"; then
|
||||
if grep -q 'bash -c "\${COVERAGE_COMMAND}"' "${SRC_SCRIPTS}/node_coverage_check.sh"; then
|
||||
pass
|
||||
else
|
||||
fail "should use 'bash -c' not 'eval'"
|
||||
@@ -494,6 +494,44 @@ else
|
||||
fail "should use Alpine JRE with non-root user"
|
||||
fi
|
||||
|
||||
echo ""
|
||||
echo "=== node_install_deps.sh pnpm support ==="
|
||||
|
||||
echo -n " TEST: node_install_deps.sh handles pnpm case... "
|
||||
if grep -q 'pnpm install --frozen-lockfile' "${SRC_SCRIPTS}/node_install_deps.sh"; then
|
||||
pass
|
||||
else
|
||||
fail "missing pnpm install --frozen-lockfile"
|
||||
fi
|
||||
|
||||
echo -n " TEST: node_install_deps.sh has Prisma auto-detection... "
|
||||
if grep -q 'prisma/schema.prisma' "${SRC_SCRIPTS}/node_install_deps.sh"; then
|
||||
pass
|
||||
else
|
||||
fail "missing Prisma auto-detection"
|
||||
fi
|
||||
|
||||
echo -n " TEST: node_test.sh handles pnpm fallback... "
|
||||
if grep -q 'pnpm test' "${SRC_SCRIPTS}/node_test.sh"; then
|
||||
pass
|
||||
else
|
||||
fail "missing pnpm test fallback"
|
||||
fi
|
||||
|
||||
echo -n " TEST: run_test_setup.sh supports inline commands... "
|
||||
if grep -q 'bash -c' "${SRC_SCRIPTS}/run_test_setup.sh"; then
|
||||
pass
|
||||
else
|
||||
fail "missing bash -c inline command support"
|
||||
fi
|
||||
|
||||
echo -n " TEST: generate_dockerfile.sh has pnpm Dockerfile variant... "
|
||||
if grep -q 'pnpm install --frozen-lockfile' "${SRC_SCRIPTS}/generate_dockerfile.sh"; then
|
||||
pass
|
||||
else
|
||||
fail "missing pnpm Dockerfile variant"
|
||||
fi
|
||||
|
||||
# =============================================================================
|
||||
# Test: install_kustomize.sh - Pinned binary install
|
||||
# =============================================================================
|
||||
@@ -888,7 +926,7 @@ YQ_VER=$(extract_version YQ_VERSION "${SRC_SCRIPTS}/install_yq.sh")
|
||||
KUSTOMIZE_VER=$(extract_version KUSTOMIZE_VERSION "${SRC_SCRIPTS}/install_kustomize.sh")
|
||||
KUBESEC_VER=$(extract_version KUBESEC_VERSION "${SRC_SCRIPTS}/install_kubesec.sh")
|
||||
TFSEC_TRIVY_VER=$(extract_version TRIVY_VERSION "${SRC_SCRIPTS}/install_tfsec.sh")
|
||||
SONAR_VER=$(extract_version SONAR_SCANNER_VERSION "${SRC_SCRIPTS}/npm_sonar.sh")
|
||||
SONAR_VER=$(extract_version SONAR_SCANNER_VERSION "${SRC_SCRIPTS}/node_sonar.sh")
|
||||
|
||||
# All URLs target linux/amd64 -- matches the CI executor
|
||||
URLS=(
|
||||
@@ -1019,6 +1057,47 @@ else
|
||||
fail "should detect pmdMain task"
|
||||
fi
|
||||
|
||||
# =============================================================================
|
||||
# Test: github_release.sh - Release artifact upload support
|
||||
# =============================================================================
|
||||
echo ""
|
||||
echo "=== github_release.sh Artifact Upload Tests ==="
|
||||
|
||||
echo -n " TEST: supports MUNITOR_RELEASE_ARTIFACTS env var... "
|
||||
if grep -q 'MUNITOR_RELEASE_ARTIFACTS' "${SRC_SCRIPTS}/github_release.sh"; then
|
||||
pass
|
||||
else
|
||||
fail "should support MUNITOR_RELEASE_ARTIFACTS"
|
||||
fi
|
||||
|
||||
echo -n " TEST: uses gh release upload for artifacts... "
|
||||
if grep -q 'gh release upload' "${SRC_SCRIPTS}/github_release.sh"; then
|
||||
pass
|
||||
else
|
||||
fail "should use gh release upload"
|
||||
fi
|
||||
|
||||
echo -n " TEST: validates artifact files exist before upload... "
|
||||
if grep -q 'not found' "${SRC_SCRIPTS}/github_release.sh" && grep -q '! -f' "${SRC_SCRIPTS}/github_release.sh"; then
|
||||
pass
|
||||
else
|
||||
fail "should validate artifact files exist"
|
||||
fi
|
||||
|
||||
echo -n " TEST: uses --clobber for idempotent uploads... "
|
||||
if grep -q '\-\-clobber' "${SRC_SCRIPTS}/github_release.sh"; then
|
||||
pass
|
||||
else
|
||||
fail "should use --clobber flag"
|
||||
fi
|
||||
|
||||
echo -n " TEST: skips upload when MUNITOR_RELEASE_ARTIFACTS is empty... "
|
||||
if grep -q 'if \[\[ -n "\${MUNITOR_RELEASE_ARTIFACTS:-}"' "${SRC_SCRIPTS}/github_release.sh"; then
|
||||
pass
|
||||
else
|
||||
fail "should skip upload when artifacts is empty"
|
||||
fi
|
||||
|
||||
# =============================================================================
|
||||
# Summary
|
||||
# =============================================================================
|
||||
|
||||
Reference in new issue
Block a user