Single compose file for Coolify: MariaDB, Redis, idempotent site creation, migrations on redeploy, SERVICE_URL_FRONTEND_8080 routing, and Forgejo Actions readiness validation vendored from production-ci-readiness skill.
127 lines
4 KiB
Bash
Executable file
127 lines
4 KiB
Bash
Executable file
#!/usr/bin/env bash
|
|
# Production readiness scanner — run from repo root or pass path as $1
|
|
# SPDX-License-Identifier: Apache-2.0
|
|
set -euo pipefail
|
|
|
|
REPO="${1:-.}"
|
|
REPO="$(cd "$REPO" && pwd)"
|
|
STRICT="${STRICT:-0}"
|
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
|
|
ERR=0
|
|
WARN=0
|
|
INFO=0
|
|
|
|
err() { echo "ERROR $*"; ERR=$((ERR + 1)); }
|
|
warn() { echo "WARN $*"; WARN=$((WARN + 1)); }
|
|
info() { echo "INFO $*"; }
|
|
pass() { echo "OK $*"; }
|
|
|
|
echo "=== Production readiness: $REPO ==="
|
|
echo "strict=$STRICT"
|
|
echo
|
|
|
|
# --- Secrets in tracked files ---
|
|
if command -v git >/dev/null 2>&1 && git -C "$REPO" rev-parse --is-inside-work-tree >/dev/null 2>&1; then
|
|
if git -C "$REPO" ls-files | grep -qE '^\.env$|credentials\.json|\.pem$'; then
|
|
err "[SEC-01] Tracked sensitive files (.env, credentials, pem)"
|
|
else
|
|
pass "[SEC-01] No obvious secret filenames tracked"
|
|
fi
|
|
while IFS= read -r f; do
|
|
[ -f "$REPO/$f" ] || continue
|
|
if grep -qE 'BEGIN (RSA |EC )?PRIVATE KEY|api[_-]?key\s*=\s*["\x27][a-zA-Z0-9]{20,}' "$REPO/$f" 2>/dev/null; then
|
|
err "[SEC-01] Possible secret in tracked file: $f"
|
|
fi
|
|
done < <(git -C "$REPO" ls-files '*.yml' '*.yaml' '*.json' '*.md' '*.sh' '*.js' '*.go' '*.env*' 2>/dev/null | head -500)
|
|
else
|
|
warn "[SEC-01] Not a git repo — skip secret scan"
|
|
fi
|
|
|
|
# --- node_modules in git ---
|
|
if command -v git >/dev/null 2>&1 && git -C "$REPO" rev-parse --is-inside-work-tree >/dev/null 2>&1; then
|
|
NM_COUNT=$(git -C "$REPO" ls-files '**/node_modules/**' 2>/dev/null | wc -l | tr -d ' ')
|
|
if [ "${NM_COUNT:-0}" -gt 0 ]; then
|
|
err "[DC-06] node_modules tracked ($NM_COUNT files) — git rm -r --cached and .gitignore"
|
|
else
|
|
pass "[DC-06] node_modules not tracked"
|
|
fi
|
|
fi
|
|
|
|
# --- Node Dockerfiles: lockfile + npm ci ---
|
|
while IFS= read -r df; do
|
|
[ -f "$df" ] || continue
|
|
dir="$(dirname "$df")"
|
|
if grep -qE 'npm install' "$df" && ! grep -qE 'npm ci' "$df"; then
|
|
warn "[DC-07] $df uses npm install without npm ci"
|
|
fi
|
|
if grep -qE 'npm ci|npm install' "$df"; then
|
|
if [ ! -f "$dir/package-lock.json" ] && [ ! -f "$dir/yarn.lock" ] && [ ! -f "$dir/pnpm-lock.yaml" ]; then
|
|
warn "[DC-07] $df has no lockfile in $dir"
|
|
else
|
|
pass "[DC-07] $df has lockfile"
|
|
fi
|
|
fi
|
|
done < <(find "$REPO" -name Dockerfile \
|
|
-not -path '*/node_modules/*' \
|
|
-not -path '*/fabric-samples-upstream/*' \
|
|
-not -path '*/.git/*' \
|
|
2>/dev/null)
|
|
|
|
# --- Gateway patterns (if present) ---
|
|
GW="$REPO/gateway/server.js"
|
|
if [ -f "$GW" ]; then
|
|
if grep -q 'withChainLock' "$GW" && grep -q 'evaluateChaincodeRaw' "$GW"; then
|
|
if grep -A2 'evaluateChaincodeRaw' "$GW" | grep -q 'withChainLock'; then
|
|
warn "[GW-02] gateway evaluates may be serialized behind withChainLock"
|
|
else
|
|
pass "[GW-02] evaluates not behind global chain lock"
|
|
fi
|
|
fi
|
|
if grep -qE "app\.get\(['\"]/health" "$GW"; then
|
|
pass "[GW-01] /health route present"
|
|
else
|
|
warn "[GW-01] no /health in gateway/server.js"
|
|
fi
|
|
fi
|
|
|
|
# --- Deploy docs ---
|
|
for doc in README.md docs/COOLIFY_DEPLOY.md docs/GATEWAY.md AGENTS.md; do
|
|
if [ -f "$REPO/$doc" ]; then
|
|
pass "[HY-01] found $doc"
|
|
break
|
|
fi
|
|
done
|
|
|
|
# --- Compose (delegate) ---
|
|
if [ -f "$REPO/docker-compose.yml" ] || [ -f "$REPO/docker-compose.yaml" ]; then
|
|
echo
|
|
echo "--- docker-compose validation ---"
|
|
COMPOSE_ERR=0
|
|
bash "$SCRIPT_DIR/validate-docker-compose.sh" "$REPO" || COMPOSE_ERR=$?
|
|
if [ "$COMPOSE_ERR" -ne 0 ]; then
|
|
ERR=$((ERR + COMPOSE_ERR))
|
|
fi
|
|
fi
|
|
|
|
# --- Go tests hint ---
|
|
if [ -f "$REPO/Makefile" ] && grep -q 'test' "$REPO/Makefile"; then
|
|
info "[HY-03] Makefile has test target — run in CI"
|
|
fi
|
|
if [ -d "$REPO/chaincode" ] || find "$REPO" -name go.mod -print -quit 2>/dev/null | grep -q .; then
|
|
info "Consider: cd chaincode && go test ./..."
|
|
fi
|
|
|
|
echo
|
|
echo "=== Summary ==="
|
|
echo "errors=$ERR warnings=$WARN"
|
|
if [ "$ERR" -gt 0 ]; then
|
|
echo "VERDICT: FAIL"
|
|
exit 1
|
|
fi
|
|
if [ "$STRICT" = "1" ] && [ "$WARN" -gt 0 ]; then
|
|
echo "VERDICT: FAIL (strict mode, warnings treated as errors)"
|
|
exit 1
|
|
fi
|
|
echo "VERDICT: PASS"
|
|
exit 0
|