debian12 ships libssl3 3.0.18 with open HIGH/CRITICAL CVEs that fail the Trivy gate; debian13 scans clean. Closes #14
793 lines
19 KiB
Bash
Executable File
793 lines
19 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
set -euo pipefail
|
|
|
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
PROJECT_DIR="$(cd "${SCRIPT_DIR}/.." && pwd)"
|
|
SCRIPT="${PROJECT_DIR}/src/scripts/generate_dockerfile.sh"
|
|
PASS=0
|
|
FAIL=0
|
|
|
|
# Test helper functions
|
|
pass() {
|
|
echo "PASS"
|
|
PASS=$((PASS + 1))
|
|
}
|
|
|
|
fail() {
|
|
local msg="${1:-}"
|
|
echo "FAIL${msg:+ ($msg)}"
|
|
FAIL=$((FAIL + 1))
|
|
}
|
|
|
|
# Create a temp working directory for each test
|
|
setup() {
|
|
WORK_DIR=$(mktemp -d)
|
|
}
|
|
|
|
teardown() {
|
|
rm -rf "${WORK_DIR}"
|
|
}
|
|
|
|
run_generate() {
|
|
(cd "${WORK_DIR}" && MUNITOR_CONFIG=".munitor.yml" bash "${SCRIPT}" 2>&1)
|
|
}
|
|
|
|
run_generate_rc() {
|
|
(cd "${WORK_DIR}" && MUNITOR_CONFIG=".munitor.yml" bash "${SCRIPT}" 2>&1) || true
|
|
(cd "${WORK_DIR}" && MUNITOR_CONFIG=".munitor.yml" bash "${SCRIPT}" >/dev/null 2>&1)
|
|
echo $?
|
|
}
|
|
|
|
# =============================================================================
|
|
# Test: node-api generates correct Dockerfile
|
|
# =============================================================================
|
|
echo "=== node-api Dockerfile Generation ==="
|
|
|
|
echo -n " TEST: generates Dockerfile with node:20-alpine (default)... "
|
|
setup
|
|
cat > "${WORK_DIR}/.munitor.yml" <<'EOF'
|
|
pipeline: node-api
|
|
image_name: my-app
|
|
EOF
|
|
run_generate > /dev/null
|
|
if grep -q 'FROM node:20-alpine AS deps' "${WORK_DIR}/Dockerfile"; then
|
|
pass
|
|
else
|
|
fail "expected node:20-alpine"
|
|
fi
|
|
teardown
|
|
|
|
echo -n " TEST: generates Dockerfile with node:22-alpine (custom)... "
|
|
setup
|
|
cat > "${WORK_DIR}/.munitor.yml" <<'EOF'
|
|
pipeline: node-api
|
|
image_name: my-app
|
|
node_version: "22"
|
|
EOF
|
|
run_generate > /dev/null
|
|
if grep -q 'FROM node:22-alpine AS deps' "${WORK_DIR}/Dockerfile"; then
|
|
pass
|
|
else
|
|
fail "expected node:22-alpine"
|
|
fi
|
|
teardown
|
|
|
|
echo -n " TEST: includes STANDALONE=true env... "
|
|
setup
|
|
cat > "${WORK_DIR}/.munitor.yml" <<'EOF'
|
|
pipeline: node-api
|
|
image_name: my-app
|
|
EOF
|
|
run_generate > /dev/null
|
|
if grep -q 'ENV STANDALONE=true' "${WORK_DIR}/Dockerfile"; then
|
|
pass
|
|
else
|
|
fail "expected STANDALONE=true"
|
|
fi
|
|
teardown
|
|
|
|
echo -n " TEST: includes npm ci in deps stage... "
|
|
setup
|
|
cat > "${WORK_DIR}/.munitor.yml" <<'EOF'
|
|
pipeline: node-api
|
|
image_name: my-app
|
|
EOF
|
|
run_generate > /dev/null
|
|
if grep -q 'RUN npm ci' "${WORK_DIR}/Dockerfile"; then
|
|
pass
|
|
else
|
|
fail "expected npm ci"
|
|
fi
|
|
teardown
|
|
|
|
echo -n " TEST: runs as nextjs user... "
|
|
setup
|
|
cat > "${WORK_DIR}/.munitor.yml" <<'EOF'
|
|
pipeline: node-api
|
|
image_name: my-app
|
|
EOF
|
|
run_generate > /dev/null
|
|
if grep -q 'USER nextjs' "${WORK_DIR}/Dockerfile"; then
|
|
pass
|
|
else
|
|
fail "expected USER nextjs"
|
|
fi
|
|
teardown
|
|
|
|
# =============================================================================
|
|
# Test: node-api Express framework generates correct Dockerfile
|
|
# =============================================================================
|
|
echo ""
|
|
echo "=== node-api Express Dockerfile Generation ==="
|
|
|
|
echo -n " TEST: express generates Dockerfile without STANDALONE env... "
|
|
setup
|
|
cat > "${WORK_DIR}/.munitor.yml" <<'EOF'
|
|
pipeline: node-api
|
|
image_name: my-express-app
|
|
node:
|
|
framework: express
|
|
EOF
|
|
run_generate > /dev/null
|
|
if ! grep -q 'ENV STANDALONE=true' "${WORK_DIR}/Dockerfile"; then
|
|
pass
|
|
else
|
|
fail "expected no STANDALONE env for express"
|
|
fi
|
|
teardown
|
|
|
|
echo -n " TEST: express does not copy .next/standalone... "
|
|
setup
|
|
cat > "${WORK_DIR}/.munitor.yml" <<'EOF'
|
|
pipeline: node-api
|
|
image_name: my-express-app
|
|
node:
|
|
framework: express
|
|
EOF
|
|
run_generate > /dev/null
|
|
if ! grep -q '.next/standalone' "${WORK_DIR}/Dockerfile"; then
|
|
pass
|
|
else
|
|
fail "expected no .next/standalone for express"
|
|
fi
|
|
teardown
|
|
|
|
echo -n " TEST: express uses appuser not nextjs... "
|
|
setup
|
|
cat > "${WORK_DIR}/.munitor.yml" <<'EOF'
|
|
pipeline: node-api
|
|
image_name: my-express-app
|
|
node:
|
|
framework: express
|
|
EOF
|
|
run_generate > /dev/null
|
|
if grep -q 'USER appuser' "${WORK_DIR}/Dockerfile" && ! grep -q 'USER nextjs' "${WORK_DIR}/Dockerfile"; then
|
|
pass
|
|
else
|
|
fail "expected USER appuser, not nextjs"
|
|
fi
|
|
teardown
|
|
|
|
echo -n " TEST: express CMD uses node . ... "
|
|
setup
|
|
cat > "${WORK_DIR}/.munitor.yml" <<'EOF'
|
|
pipeline: node-api
|
|
image_name: my-express-app
|
|
node:
|
|
framework: express
|
|
EOF
|
|
run_generate > /dev/null
|
|
if grep -q 'CMD \["node", "."\]' "${WORK_DIR}/Dockerfile"; then
|
|
pass
|
|
else
|
|
fail "expected CMD [\"node\", \".\"]"
|
|
fi
|
|
teardown
|
|
|
|
echo -n " TEST: express includes HEALTHCHECK... "
|
|
setup
|
|
cat > "${WORK_DIR}/.munitor.yml" <<'EOF'
|
|
pipeline: node-api
|
|
image_name: my-express-app
|
|
node:
|
|
framework: express
|
|
EOF
|
|
run_generate > /dev/null
|
|
if grep -q 'HEALTHCHECK' "${WORK_DIR}/Dockerfile"; then
|
|
pass
|
|
else
|
|
fail "expected HEALTHCHECK directive"
|
|
fi
|
|
teardown
|
|
|
|
echo -n " TEST: express EXPOSE uses health port (default 3000)... "
|
|
setup
|
|
cat > "${WORK_DIR}/.munitor.yml" <<'EOF'
|
|
pipeline: node-api
|
|
image_name: my-express-app
|
|
node:
|
|
framework: express
|
|
EOF
|
|
run_generate > /dev/null
|
|
if grep -q 'EXPOSE 3000' "${WORK_DIR}/Dockerfile"; then
|
|
pass
|
|
else
|
|
fail "expected EXPOSE 3000"
|
|
fi
|
|
teardown
|
|
|
|
echo -n " TEST: express EXPOSE uses custom health port... "
|
|
setup
|
|
cat > "${WORK_DIR}/.munitor.yml" <<'EOF'
|
|
pipeline: node-api
|
|
image_name: my-express-app
|
|
node:
|
|
framework: express
|
|
health:
|
|
port: 4000
|
|
EOF
|
|
run_generate > /dev/null
|
|
if grep -q 'EXPOSE 4000' "${WORK_DIR}/Dockerfile"; then
|
|
pass
|
|
else
|
|
fail "expected EXPOSE 4000"
|
|
fi
|
|
teardown
|
|
|
|
echo -n " TEST: express npm ci uses --omit=dev... "
|
|
setup
|
|
cat > "${WORK_DIR}/.munitor.yml" <<'EOF'
|
|
pipeline: node-api
|
|
image_name: my-express-app
|
|
node:
|
|
framework: express
|
|
EOF
|
|
run_generate > /dev/null
|
|
if grep -q 'npm ci --omit=dev' "${WORK_DIR}/Dockerfile"; then
|
|
pass
|
|
else
|
|
fail "expected npm ci --omit=dev"
|
|
fi
|
|
teardown
|
|
|
|
echo -n " TEST: unsupported node framework fails... "
|
|
setup
|
|
cat > "${WORK_DIR}/.munitor.yml" <<'EOF'
|
|
pipeline: node-api
|
|
image_name: my-app
|
|
node:
|
|
framework: koa
|
|
EOF
|
|
OUTPUT=$(cd "${WORK_DIR}" && MUNITOR_CONFIG=".munitor.yml" bash "${SCRIPT}" 2>&1 || true)
|
|
RC=$(cd "${WORK_DIR}" && MUNITOR_CONFIG=".munitor.yml" bash "${SCRIPT}" >/dev/null 2>&1; echo $?) || true
|
|
if [[ "${RC}" -ne 0 ]] && echo "${OUTPUT}" | grep -q "Unsupported node framework"; then
|
|
pass
|
|
else
|
|
fail "expected non-zero exit for unsupported framework"
|
|
fi
|
|
teardown
|
|
|
|
# =============================================================================
|
|
# Test: java-webapp generates correct Dockerfile
|
|
# =============================================================================
|
|
echo ""
|
|
echo "=== java-webapp Dockerfile Generation ==="
|
|
|
|
# Helper to set up java-webapp test with a mock JAR
|
|
setup_java() {
|
|
setup
|
|
mkdir -p "${WORK_DIR}/target"
|
|
touch "${WORK_DIR}/target/my-app-1.0.0.jar"
|
|
}
|
|
|
|
echo -n " TEST: generates Dockerfile with Alpine JRE base... "
|
|
setup_java
|
|
cat > "${WORK_DIR}/.munitor.yml" <<'EOF'
|
|
pipeline: java-webapp
|
|
image_name: my-app
|
|
EOF
|
|
run_generate > /dev/null
|
|
if grep -q 'FROM eclipse-temurin:21-jre-alpine' "${WORK_DIR}/Dockerfile"; then
|
|
pass
|
|
else
|
|
fail "expected eclipse-temurin:21-jre-alpine"
|
|
fi
|
|
teardown
|
|
|
|
echo -n " TEST: generates Dockerfile with temurin-17-jre-alpine (custom)... "
|
|
setup_java
|
|
cat > "${WORK_DIR}/.munitor.yml" <<'EOF'
|
|
pipeline: java-webapp
|
|
image_name: my-app
|
|
java_version: "17"
|
|
EOF
|
|
run_generate > /dev/null
|
|
if grep -q 'FROM eclipse-temurin:17-jre-alpine' "${WORK_DIR}/Dockerfile"; then
|
|
pass
|
|
else
|
|
fail "expected eclipse-temurin:17-jre-alpine"
|
|
fi
|
|
teardown
|
|
|
|
echo -n " TEST: uses non-root user (appuser)... "
|
|
setup_java
|
|
cat > "${WORK_DIR}/.munitor.yml" <<'EOF'
|
|
pipeline: java-webapp
|
|
image_name: my-app
|
|
EOF
|
|
run_generate > /dev/null
|
|
if grep -q 'USER appuser' "${WORK_DIR}/Dockerfile"; then
|
|
pass
|
|
else
|
|
fail "expected USER appuser"
|
|
fi
|
|
teardown
|
|
|
|
echo -n " TEST: EXPOSE uses health port (default 8080)... "
|
|
setup_java
|
|
cat > "${WORK_DIR}/.munitor.yml" <<'EOF'
|
|
pipeline: java-webapp
|
|
image_name: my-app
|
|
EOF
|
|
run_generate > /dev/null
|
|
if grep -q 'EXPOSE 8080' "${WORK_DIR}/Dockerfile"; then
|
|
pass
|
|
else
|
|
fail "expected EXPOSE 8080"
|
|
fi
|
|
teardown
|
|
|
|
echo -n " TEST: EXPOSE uses custom health port... "
|
|
setup_java
|
|
cat > "${WORK_DIR}/.munitor.yml" <<'EOF'
|
|
pipeline: java-webapp
|
|
image_name: my-app
|
|
health:
|
|
port: 8000
|
|
EOF
|
|
run_generate > /dev/null
|
|
if grep -q 'EXPOSE 8000' "${WORK_DIR}/Dockerfile"; then
|
|
pass
|
|
else
|
|
fail "expected EXPOSE 8000"
|
|
fi
|
|
teardown
|
|
|
|
echo -n " TEST: HEALTHCHECK uses health path and port... "
|
|
setup_java
|
|
cat > "${WORK_DIR}/.munitor.yml" <<'EOF'
|
|
pipeline: java-webapp
|
|
image_name: my-app
|
|
health:
|
|
path: /qqq-api/health
|
|
port: 8000
|
|
EOF
|
|
run_generate > /dev/null
|
|
if grep -q 'http://localhost:8000/qqq-api/health' "${WORK_DIR}/Dockerfile"; then
|
|
pass
|
|
else
|
|
fail "expected HEALTHCHECK with custom path/port"
|
|
fi
|
|
teardown
|
|
|
|
echo -n " TEST: includes JVM container tuning flags... "
|
|
setup_java
|
|
cat > "${WORK_DIR}/.munitor.yml" <<'EOF'
|
|
pipeline: java-webapp
|
|
image_name: my-app
|
|
EOF
|
|
run_generate > /dev/null
|
|
if grep -q 'UseContainerSupport' "${WORK_DIR}/Dockerfile" \
|
|
&& grep -q 'MaxRAMPercentage' "${WORK_DIR}/Dockerfile"; then
|
|
pass
|
|
else
|
|
fail "expected JVM container flags"
|
|
fi
|
|
teardown
|
|
|
|
echo -n " TEST: copies detected JAR as app.jar... "
|
|
setup_java
|
|
cat > "${WORK_DIR}/.munitor.yml" <<'EOF'
|
|
pipeline: java-webapp
|
|
image_name: my-app
|
|
EOF
|
|
run_generate > /dev/null
|
|
if grep -q 'COPY target/my-app-1.0.0.jar app.jar' "${WORK_DIR}/Dockerfile"; then
|
|
pass
|
|
else
|
|
fail "expected COPY with detected JAR path"
|
|
fi
|
|
teardown
|
|
|
|
echo -n " TEST: excludes original-* JARs from detection... "
|
|
setup_java
|
|
touch "${WORK_DIR}/target/original-my-app-1.0.0.jar"
|
|
cat > "${WORK_DIR}/.munitor.yml" <<'EOF'
|
|
pipeline: java-webapp
|
|
image_name: my-app
|
|
EOF
|
|
run_generate > /dev/null
|
|
if grep -q 'COPY target/my-app-1.0.0.jar app.jar' "${WORK_DIR}/Dockerfile"; then
|
|
pass
|
|
else
|
|
fail "expected original-* to be excluded"
|
|
fi
|
|
teardown
|
|
|
|
echo -n " TEST: fails when no JAR found in target/... "
|
|
setup
|
|
cat > "${WORK_DIR}/.munitor.yml" <<'EOF'
|
|
pipeline: java-webapp
|
|
image_name: my-app
|
|
EOF
|
|
OUTPUT=$(cd "${WORK_DIR}" && MUNITOR_CONFIG=".munitor.yml" bash "${SCRIPT}" 2>&1 || true)
|
|
RC=$(cd "${WORK_DIR}" && MUNITOR_CONFIG=".munitor.yml" bash "${SCRIPT}" >/dev/null 2>&1; echo $?) || true
|
|
if [[ "${RC}" -ne 0 ]] && echo "${OUTPUT}" | grep -q "No application JAR found"; then
|
|
pass
|
|
else
|
|
fail "expected failure when no JAR in target/"
|
|
fi
|
|
teardown
|
|
|
|
echo -n " TEST: no builder stage (no maven FROM)... "
|
|
setup_java
|
|
cat > "${WORK_DIR}/.munitor.yml" <<'EOF'
|
|
pipeline: java-webapp
|
|
image_name: my-app
|
|
EOF
|
|
run_generate > /dev/null
|
|
if ! grep -q 'FROM maven' "${WORK_DIR}/Dockerfile"; then
|
|
pass
|
|
else
|
|
fail "expected no maven builder stage"
|
|
fi
|
|
teardown
|
|
|
|
# =============================================================================
|
|
# Test: node-webapp auto-generates Dockerfile
|
|
# =============================================================================
|
|
echo ""
|
|
echo "=== node-webapp Dockerfile Generation ==="
|
|
|
|
echo -n " TEST: generates Dockerfile for node-webapp... "
|
|
setup
|
|
cat > "${WORK_DIR}/.munitor.yml" <<'EOF'
|
|
pipeline: node-webapp
|
|
image_name: my-webapp
|
|
node_version: "22"
|
|
EOF
|
|
OUTPUT=$(run_generate)
|
|
if echo "${OUTPUT}" | grep -q "Generating Dockerfile for node-webapp"; then
|
|
pass
|
|
else
|
|
fail "expected 'Generating Dockerfile for node-webapp' message"
|
|
fi
|
|
teardown
|
|
|
|
echo -n " TEST: uses distroless runner image... "
|
|
setup
|
|
cat > "${WORK_DIR}/.munitor.yml" <<'EOF'
|
|
pipeline: node-webapp
|
|
image_name: my-webapp
|
|
node_version: "22"
|
|
EOF
|
|
run_generate > /dev/null
|
|
if grep -q "FROM gcr.io/distroless/nodejs22-debian13 AS runner" "${WORK_DIR}/Dockerfile"; then
|
|
pass
|
|
else
|
|
fail "expected distroless debian13 runner image in Dockerfile"
|
|
fi
|
|
teardown
|
|
|
|
echo -n " TEST: does not use the debian12 runner (open OpenSSL CVEs)... "
|
|
setup
|
|
cat > "${WORK_DIR}/.munitor.yml" <<'EOF'
|
|
pipeline: node-webapp
|
|
image_name: my-webapp
|
|
node_version: "22"
|
|
EOF
|
|
run_generate > /dev/null
|
|
if ! grep -q "debian12" "${WORK_DIR}/Dockerfile"; then
|
|
pass
|
|
else
|
|
fail "expected no debian12 base image"
|
|
fi
|
|
teardown
|
|
|
|
echo -n " TEST: overwrites existing Dockerfile... "
|
|
setup
|
|
cat > "${WORK_DIR}/.munitor.yml" <<'EOF'
|
|
pipeline: node-webapp
|
|
image_name: my-webapp
|
|
node_version: "22"
|
|
EOF
|
|
echo "OLD CONTENT" > "${WORK_DIR}/Dockerfile"
|
|
run_generate > /dev/null
|
|
if ! grep -q "OLD CONTENT" "${WORK_DIR}/Dockerfile" && grep -q "distroless" "${WORK_DIR}/Dockerfile"; then
|
|
pass
|
|
else
|
|
fail "Dockerfile was not overwritten with generated content"
|
|
fi
|
|
teardown
|
|
|
|
# =============================================================================
|
|
# Test: node-webapp can preserve a repository Dockerfile
|
|
# =============================================================================
|
|
echo ""
|
|
echo "=== node-webapp Repository Dockerfile ==="
|
|
|
|
echo -n " TEST: preserves an opted-in repository Dockerfile... "
|
|
setup
|
|
cat > "${WORK_DIR}/.munitor.yml" <<'EOF'
|
|
pipeline: node-webapp
|
|
image_name: my-webapp
|
|
docker:
|
|
use_repo_dockerfile: true
|
|
EOF
|
|
echo "CUSTOM RUNTIME" > "${WORK_DIR}/Dockerfile"
|
|
OUTPUT=$(run_generate)
|
|
if grep -q "CUSTOM RUNTIME" "${WORK_DIR}/Dockerfile" && echo "${OUTPUT}" | grep -q "Using repository Dockerfile"; then
|
|
pass
|
|
else
|
|
fail "repository Dockerfile was not preserved"
|
|
fi
|
|
teardown
|
|
|
|
echo -n " TEST: rejects opt-in when Dockerfile is missing... "
|
|
setup
|
|
cat > "${WORK_DIR}/.munitor.yml" <<'EOF'
|
|
pipeline: node-webapp
|
|
image_name: my-webapp
|
|
docker:
|
|
use_repo_dockerfile: true
|
|
EOF
|
|
if OUTPUT=$(run_generate); then
|
|
fail "expected missing Dockerfile to fail"
|
|
elif echo "${OUTPUT}" | grep -q "requires a Dockerfile"; then
|
|
pass
|
|
else
|
|
fail "expected a clear missing Dockerfile error"
|
|
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
|
|
|
|
echo -n " TEST: pnpm node-webapp uses distroless debian13 runner... "
|
|
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 "FROM gcr.io/distroless/nodejs22-debian13 AS runner" "${WORK_DIR}/Dockerfile"; then
|
|
pass
|
|
else
|
|
fail "expected distroless debian13 runner image in pnpm Dockerfile"
|
|
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
|
|
# =============================================================================
|
|
echo ""
|
|
echo "=== Error Handling ==="
|
|
|
|
echo -n " TEST: fails for unsupported pipeline type... "
|
|
setup
|
|
cat > "${WORK_DIR}/.munitor.yml" <<'EOF'
|
|
pipeline: python-api
|
|
image_name: my-app
|
|
EOF
|
|
OUTPUT=$(cd "${WORK_DIR}" && MUNITOR_CONFIG=".munitor.yml" bash "${SCRIPT}" 2>&1 || true)
|
|
RC=$(cd "${WORK_DIR}" && MUNITOR_CONFIG=".munitor.yml" bash "${SCRIPT}" >/dev/null 2>&1; echo $?) || true
|
|
if [[ "${RC}" -ne 0 ]] && echo "${OUTPUT}" | grep -q "Unsupported pipeline type"; then
|
|
pass
|
|
else
|
|
fail "expected non-zero exit and error message (rc=${RC})"
|
|
fi
|
|
teardown
|
|
|
|
echo -n " TEST: fails when .munitor.yml is missing... "
|
|
setup
|
|
OUTPUT=$(cd "${WORK_DIR}" && MUNITOR_CONFIG=".munitor.yml" bash "${SCRIPT}" 2>&1 || true)
|
|
RC=$(cd "${WORK_DIR}" && MUNITOR_CONFIG=".munitor.yml" bash "${SCRIPT}" >/dev/null 2>&1; echo $?) || true
|
|
if [[ "${RC}" -ne 0 ]] && echo "${OUTPUT}" | grep -q "not found"; then
|
|
pass
|
|
else
|
|
fail "expected non-zero exit for missing config"
|
|
fi
|
|
teardown
|
|
|
|
# =============================================================================
|
|
# Test: generated file is non-empty
|
|
# =============================================================================
|
|
echo ""
|
|
echo "=== File Validation ==="
|
|
|
|
echo -n " TEST: generated Dockerfile exists and is non-empty... "
|
|
setup
|
|
cat > "${WORK_DIR}/.munitor.yml" <<'EOF'
|
|
pipeline: node-api
|
|
image_name: my-app
|
|
node_version: "22"
|
|
EOF
|
|
run_generate > /dev/null
|
|
if [[ -s "${WORK_DIR}/Dockerfile" ]]; then
|
|
pass
|
|
else
|
|
fail "Dockerfile missing or empty"
|
|
fi
|
|
teardown
|
|
|
|
# =============================================================================
|
|
# Summary
|
|
# =============================================================================
|
|
echo ""
|
|
echo "=== Results: ${PASS} passed, ${FAIL} failed ==="
|
|
|
|
if [[ ${FAIL} -gt 0 ]]; then
|
|
exit 1
|
|
fi
|