@freshworks/shiftleft-tools 1.1.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +351 -0
- package/bin/shiftleft.js +95 -0
- package/package.json +57 -0
- package/src/commands/doctor.js +208 -0
- package/src/commands/init-postman.js +298 -0
- package/src/commands/init-rules.js +78 -0
- package/src/commands/link.js +172 -0
- package/src/commands/protect.js +61 -0
- package/src/commands/run-tests.js +182 -0
- package/src/commands/setup-pipeline.js +209 -0
- package/src/commands/update.js +203 -0
- package/src/index.js +4 -0
- package/src/utils/copy-tree.js +98 -0
- package/src/utils/gitignore.js +26 -0
- package/src/utils/logger.js +9 -0
- package/src/utils/manifest.js +145 -0
- package/src/utils/stack.js +80 -0
- package/src/utils/template.js +135 -0
- package/templates/AGENTS.md +109 -0
- package/templates/CLAUDE.md +3 -0
- package/templates/jenkins/Jenkinsfile-java.groovy +432 -0
- package/templates/jenkins/Jenkinsfile-node.groovy +450 -0
- package/templates/postman/.husky/pre-commit +19 -0
- package/templates/postman/.prettierrc.json +5 -0
- package/templates/postman/README.md.ejs +147 -0
- package/templates/postman/collections/01-core.json.ejs +91 -0
- package/templates/postman/config/local.json.ejs +12 -0
- package/templates/postman/config/staging.json.ejs +26 -0
- package/templates/postman/environments/local.postman_environment.json.ejs +31 -0
- package/templates/postman/environments/staging.postman_environment.json.ejs +31 -0
- package/templates/postman/gitignore +16 -0
- package/templates/postman/npmrc +31 -0
- package/templates/postman/package.json.ejs +66 -0
- package/templates/postman/run-all-shim.sh +16 -0
- package/templates/postman/scripts/auth/generate-jwt.sh +113 -0
- package/templates/postman/scripts/auth/get-issuer-secret.sh +140 -0
- package/templates/postman/scripts/infra/start-mocks.sh +138 -0
- package/templates/postman/scripts/infra/stop-mocks.sh +43 -0
- package/templates/postman/scripts/lib/api_coverage.py +1122 -0
- package/templates/postman/scripts/lib/cleanup-reports.sh +101 -0
- package/templates/postman/scripts/lib/cleanup-stryker.sh +44 -0
- package/templates/postman/scripts/lib/report_combined.py +527 -0
- package/templates/postman/scripts/lib/report_consolidated.py +363 -0
- package/templates/postman/scripts/lib/report_generator.py +121 -0
- package/templates/postman/scripts/lib/report_migration.py +156 -0
- package/templates/postman/scripts/lib/report_mutation.py +110 -0
- package/templates/postman/scripts/lib/report_unit.py +353 -0
- package/templates/postman/scripts/lib/report_utils.py +973 -0
- package/templates/postman/scripts/report-generators/generate-consolidated-report.sh +445 -0
- package/templates/postman/scripts/report-generators/java-api-coverage-matrix.sh +257 -0
- package/templates/postman/scripts/report-generators/mutation-report.sh +672 -0
- package/templates/postman/scripts/report-generators/node-api-coverage-matrix.sh +167 -0
- package/templates/postman/scripts/report-generators/stage-report-artifacts.sh +27 -0
- package/templates/postman/scripts/run-all.sh +452 -0
- package/templates/postman/scripts/runners/run-mutation-tests.sh +113 -0
- package/templates/postman/scripts/runners/run-tests-local.sh +936 -0
- package/templates/postman/scripts/runners/run-tests-staging.sh +741 -0
- package/templates/postman-node/README.md.ejs +26 -0
- package/templates/postman-node/collections/crud/01-bootstrap.json.ejs +34 -0
- package/templates/postman-node/config/local.json.ejs +46 -0
- package/templates/postman-node/config/staging.json.ejs +31 -0
- package/templates/postman-node/local.test.env.ejs +3 -0
- package/templates/postman-node/mocks/external.js +14 -0
- package/templates/postman-node/package.json.ejs +39 -0
- package/templates/postman-node/requirements.txt +1 -0
- package/templates/postman-node/scripts/database/cleanup-mysql.sh +12 -0
- package/templates/postman-node/scripts/database/run-migrations.js +29 -0
- package/templates/postman-node/scripts/database/start-mysql.sh +34 -0
- package/templates/postman-node/scripts/database/wait-for-mysql.sh +36 -0
- package/templates/postman-node/scripts/lib/api_coverage_node.py +1137 -0
- package/templates/postman-node/scripts/lib/fetch-jwt.sh +86 -0
- package/templates/postman-node/scripts/lib/run-newman.sh +104 -0
- package/templates/postman-node/scripts/lib/setup-database.sh +55 -0
- package/templates/postman-node/scripts/lib/start-app.sh +48 -0
- package/templates/postman-node/scripts/lib/utils.sh +114 -0
- package/templates/postman-node/scripts/report-generators/stage-report-artifacts.sh +26 -0
- package/templates/postman-node/scripts/run-all.sh +303 -0
- package/templates/postman-node/scripts/runners/run-tests.sh +123 -0
- package/templates/postman-node/scripts/setup-mocks.js.ejs +29 -0
- package/templates/postman-node/stryker.config.js.ejs +51 -0
- package/templates/rules/local-test-setup.mdc +420 -0
- package/templates/rules/testing-node.mdc +66 -0
- package/templates/rules/testing.mdc +248 -0
- package/templates/skills/_shared/postman-standards.md +380 -0
- package/templates/skills/enhance-test-pipeline/SKILL-java.md +483 -0
- package/templates/skills/enhance-test-pipeline/SKILL-node.md +431 -0
- package/templates/skills/enhance-test-pipeline/SKILL.md +9 -0
- package/templates/skills/review-test-suite/SKILL-java.md +137 -0
- package/templates/skills/review-test-suite/SKILL-node.md +78 -0
- package/templates/skills/review-test-suite/SKILL.md +9 -0
- package/templates/skills/run-test-suite/SKILL-java.md +186 -0
- package/templates/skills/run-test-suite/SKILL-node.md +191 -0
- package/templates/skills/run-test-suite/SKILL.md +9 -0
- package/templates/skills/setup-api-tests/SKILL-java.md +1094 -0
- package/templates/skills/setup-api-tests/SKILL-node.md +141 -0
- package/templates/skills/setup-api-tests/SKILL.md +9 -0
- package/templates/skills/setup-mutation-tests/SKILL-java.md +303 -0
- package/templates/skills/setup-mutation-tests/SKILL-node.md +408 -0
- package/templates/skills/setup-mutation-tests/SKILL.md +9 -0
- package/templates/skills/setup-test-pipeline/SKILL-java.md +454 -0
- package/templates/skills/setup-test-pipeline/SKILL-node.md +318 -0
- package/templates/skills/setup-test-pipeline/SKILL.md +9 -0
- package/templates/skills/write-api-tests/SKILL-java.md +115 -0
- package/templates/skills/write-api-tests/SKILL-node.md +83 -0
- package/templates/skills/write-api-tests/SKILL.md +9 -0
- package/templates/stryker.config.js +50 -0
|
@@ -0,0 +1,167 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
|
|
3
|
+
###############################################################################
|
|
4
|
+
# API Coverage Matrix Generator - Node.js Services (thin wrapper)
|
|
5
|
+
#
|
|
6
|
+
# Usage:
|
|
7
|
+
# ./node-api-coverage-matrix.sh [ROUTES_DIR] [POSTMAN_DIR]
|
|
8
|
+
###############################################################################
|
|
9
|
+
|
|
10
|
+
set -e
|
|
11
|
+
|
|
12
|
+
if [ -t 1 ]; then
|
|
13
|
+
RED='\033[0;31m'
|
|
14
|
+
GREEN='\033[0;32m'
|
|
15
|
+
YELLOW='\033[1;33m'
|
|
16
|
+
BLUE='\033[0;34m'
|
|
17
|
+
NC='\033[0m'
|
|
18
|
+
else
|
|
19
|
+
RED='' GREEN='' YELLOW='' BLUE='' NC=''
|
|
20
|
+
fi
|
|
21
|
+
|
|
22
|
+
log_info() { echo -e "${BLUE}[INFO]${NC} $1"; }
|
|
23
|
+
log_success() { echo -e "${GREEN}[SUCCESS]${NC} $1"; }
|
|
24
|
+
log_warn() { echo -e "${YELLOW}[WARN]${NC} $1"; }
|
|
25
|
+
log_error() { echo -e "${RED}[ERROR]${NC} $1" >&2; }
|
|
26
|
+
|
|
27
|
+
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
28
|
+
PROJECT_ROOT="$(cd "$SCRIPT_DIR/../.." && pwd)"
|
|
29
|
+
REPO_ROOT="$PROJECT_ROOT"
|
|
30
|
+
|
|
31
|
+
source "$SCRIPT_DIR/../lib/cleanup-reports.sh"
|
|
32
|
+
|
|
33
|
+
check_python() {
|
|
34
|
+
if ! command -v python3 &> /dev/null; then
|
|
35
|
+
log_error "Python 3 is required but not installed."
|
|
36
|
+
exit 2
|
|
37
|
+
fi
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
find_routes_dir() {
|
|
41
|
+
local base_dir="$1"
|
|
42
|
+
local patterns=("src/controllers" "src/routes" "routes" "lib/routes" "app/routes" "api/routes" "server/routes" "controllers")
|
|
43
|
+
for pattern in "${patterns[@]}"; do
|
|
44
|
+
if [ -d "$base_dir/$pattern" ]; then
|
|
45
|
+
echo "$base_dir/$pattern"
|
|
46
|
+
return 0
|
|
47
|
+
fi
|
|
48
|
+
done
|
|
49
|
+
echo ""
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
find_postman_dir() {
|
|
53
|
+
local base_dir="$1"
|
|
54
|
+
if [ -d "$base_dir/postman" ]; then
|
|
55
|
+
echo "$base_dir/postman"
|
|
56
|
+
return 0
|
|
57
|
+
fi
|
|
58
|
+
echo ""
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
validate_inputs() {
|
|
62
|
+
local routes_dir="$1"
|
|
63
|
+
local postman_dir="$2"
|
|
64
|
+
if [ -z "$routes_dir" ] || [ ! -d "$routes_dir" ]; then
|
|
65
|
+
log_error "Routes directory not found: $routes_dir"
|
|
66
|
+
exit 1
|
|
67
|
+
fi
|
|
68
|
+
JS_COUNT=$(find "$routes_dir" \( -name "*.js" -o -name "*.ts" \) 2>/dev/null | wc -l | tr -d ' ')
|
|
69
|
+
if [ "$JS_COUNT" -eq 0 ]; then
|
|
70
|
+
log_error "No JavaScript/TypeScript files found in: $routes_dir"
|
|
71
|
+
exit 3
|
|
72
|
+
fi
|
|
73
|
+
log_info "Found $JS_COUNT route files"
|
|
74
|
+
if [ -z "$postman_dir" ] || [ ! -d "$postman_dir" ]; then
|
|
75
|
+
log_error "Postman directory not found: $postman_dir"
|
|
76
|
+
exit 1
|
|
77
|
+
fi
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
echo "========================================"
|
|
81
|
+
echo "Node.js API Coverage Matrix Generator"
|
|
82
|
+
echo "========================================"
|
|
83
|
+
echo ""
|
|
84
|
+
|
|
85
|
+
check_python
|
|
86
|
+
|
|
87
|
+
if [ -n "${1:-}" ]; then
|
|
88
|
+
if [ -d "$1" ]; then
|
|
89
|
+
ROUTES_DIR="$(cd "$1" && pwd)"
|
|
90
|
+
elif [ -d "$REPO_ROOT/$1" ]; then
|
|
91
|
+
ROUTES_DIR="$(cd "$REPO_ROOT/$1" && pwd)"
|
|
92
|
+
else
|
|
93
|
+
ROUTES_DIR=$(find_routes_dir "$REPO_ROOT")
|
|
94
|
+
log_warn "Routes path '$1' not found; using: ${ROUTES_DIR:-<none>}"
|
|
95
|
+
fi
|
|
96
|
+
else
|
|
97
|
+
ROUTES_DIR=$(find_routes_dir "$REPO_ROOT")
|
|
98
|
+
fi
|
|
99
|
+
|
|
100
|
+
if [ -n "${2:-}" ]; then
|
|
101
|
+
if [ -d "$2" ]; then
|
|
102
|
+
POSTMAN_DIR="$(cd "$2" && pwd)"
|
|
103
|
+
elif [ -d "$REPO_ROOT/$2" ]; then
|
|
104
|
+
POSTMAN_DIR="$(cd "$REPO_ROOT/$2" && pwd)"
|
|
105
|
+
else
|
|
106
|
+
POSTMAN_DIR=$(find_postman_dir "$REPO_ROOT")
|
|
107
|
+
log_warn "Postman path '$2' not found; using: ${POSTMAN_DIR:-<none>}"
|
|
108
|
+
fi
|
|
109
|
+
else
|
|
110
|
+
POSTMAN_DIR=$(find_postman_dir "$REPO_ROOT")
|
|
111
|
+
fi
|
|
112
|
+
|
|
113
|
+
echo "Configuration:"
|
|
114
|
+
echo " ROUTES_DIR: ${ROUTES_DIR:-<not found>}"
|
|
115
|
+
echo " POSTMAN_DIR: ${POSTMAN_DIR:-<not found>}"
|
|
116
|
+
echo ""
|
|
117
|
+
|
|
118
|
+
validate_inputs "$ROUTES_DIR" "$POSTMAN_DIR"
|
|
119
|
+
|
|
120
|
+
REPORTS_DIR="$POSTMAN_DIR/reports"
|
|
121
|
+
mkdir -p "$REPORTS_DIR"
|
|
122
|
+
cleanup_reports_by_pattern "$REPORTS_DIR" "api-coverage-matrix-*.html" 1
|
|
123
|
+
cleanup_reports_by_pattern "$REPORTS_DIR" "api-coverage-matrix-*.json" 1
|
|
124
|
+
|
|
125
|
+
TIMESTAMP=$(date +%Y%m%d-%H%M%S)
|
|
126
|
+
HTML_OUTPUT_FILE="$REPORTS_DIR/api-coverage-matrix-$TIMESTAMP.html"
|
|
127
|
+
|
|
128
|
+
log_info "Generating coverage matrix..."
|
|
129
|
+
cd "$SCRIPT_DIR/lib"
|
|
130
|
+
if [ -f api_coverage_node.py ]; then
|
|
131
|
+
COVERAGE_SCRIPT=api_coverage_node.py
|
|
132
|
+
else
|
|
133
|
+
log_error "api_coverage_node.py not found in lib/ — re-run shiftleft init-postman --stack node"
|
|
134
|
+
exit 1
|
|
135
|
+
fi
|
|
136
|
+
python3 "$COVERAGE_SCRIPT" \
|
|
137
|
+
--routes-dir "$ROUTES_DIR" \
|
|
138
|
+
--postman-dir "$POSTMAN_DIR" \
|
|
139
|
+
--html-output "$HTML_OUTPUT_FILE"
|
|
140
|
+
PYTHON_EXIT=$?
|
|
141
|
+
|
|
142
|
+
if [ $PYTHON_EXIT -ne 0 ]; then
|
|
143
|
+
log_error "Matrix generation failed (exit code: $PYTHON_EXIT)"
|
|
144
|
+
exit $PYTHON_EXIT
|
|
145
|
+
fi
|
|
146
|
+
|
|
147
|
+
LATEST_LINK="$REPORTS_DIR/api-coverage-matrix-latest.html"
|
|
148
|
+
cp -f "$HTML_OUTPUT_FILE" "$LATEST_LINK"
|
|
149
|
+
log_info "Latest report copy: $LATEST_LINK"
|
|
150
|
+
|
|
151
|
+
CANONICAL_REPORTS_DIR="$REPO_ROOT/postman/reports"
|
|
152
|
+
mkdir -p "$CANONICAL_REPORTS_DIR"
|
|
153
|
+
REAL_REPORTS="$(cd "$REPORTS_DIR" && pwd)"
|
|
154
|
+
REAL_CANON="$(cd "$CANONICAL_REPORTS_DIR" && pwd)"
|
|
155
|
+
if [ "$REAL_REPORTS" != "$REAL_CANON" ]; then
|
|
156
|
+
cp -f "$HTML_OUTPUT_FILE" "$CANONICAL_REPORTS_DIR/"
|
|
157
|
+
cp -f "$LATEST_LINK" "$CANONICAL_REPORTS_DIR/api-coverage-matrix-latest.html"
|
|
158
|
+
JSON_SIDE="${HTML_OUTPUT_FILE%.html}.json"
|
|
159
|
+
[ -f "$JSON_SIDE" ] && cp -f "$JSON_SIDE" "$CANONICAL_REPORTS_DIR/"
|
|
160
|
+
log_info "Mirrored reports to $CANONICAL_REPORTS_DIR for Jenkins publishHTML."
|
|
161
|
+
fi
|
|
162
|
+
|
|
163
|
+
echo ""
|
|
164
|
+
echo "========================================"
|
|
165
|
+
log_success "Matrix Generation Complete"
|
|
166
|
+
echo "HTML: $HTML_OUTPUT_FILE"
|
|
167
|
+
echo "========================================"
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
#
|
|
3
|
+
# Copy JaCoCo and PIT HTML reports into postman/reports/artifacts/
|
|
4
|
+
# so the combined quality report can link to them with relative URLs (Jenkins-safe).
|
|
5
|
+
#
|
|
6
|
+
# Usage: stage-report-artifacts.sh <project_root> <reports_dir>
|
|
7
|
+
|
|
8
|
+
set -euo pipefail
|
|
9
|
+
|
|
10
|
+
PROJECT_ROOT="${1:?project root required}"
|
|
11
|
+
REPORTS_DIR="${2:?reports dir required}"
|
|
12
|
+
ARTIFACTS_DIR="$REPORTS_DIR/artifacts"
|
|
13
|
+
|
|
14
|
+
rm -rf "$ARTIFACTS_DIR"
|
|
15
|
+
mkdir -p "$ARTIFACTS_DIR/jacoco" "$ARTIFACTS_DIR/pit"
|
|
16
|
+
|
|
17
|
+
JACOCO_SRC="$PROJECT_ROOT/target/site/jacoco"
|
|
18
|
+
if [ -d "$JACOCO_SRC" ] && [ -f "$JACOCO_SRC/index.html" ]; then
|
|
19
|
+
cp -R "$JACOCO_SRC/." "$ARTIFACTS_DIR/jacoco/"
|
|
20
|
+
echo "Staged JaCoCo report -> artifacts/jacoco/"
|
|
21
|
+
fi
|
|
22
|
+
|
|
23
|
+
PIT_DIR="$PROJECT_ROOT/target/pit-reports"
|
|
24
|
+
if [ -f "$PIT_DIR/index.html" ]; then
|
|
25
|
+
cp -R "$PIT_DIR/." "$ARTIFACTS_DIR/pit/"
|
|
26
|
+
echo "Staged PIT report -> artifacts/pit/"
|
|
27
|
+
fi
|
|
@@ -0,0 +1,452 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
#
|
|
3
|
+
# Unified Test & Quality Report Runner
|
|
4
|
+
# =====================================
|
|
5
|
+
# Single script that runs everything and produces one combined report:
|
|
6
|
+
# 1. Unit Tests + JaCoCo Coverage
|
|
7
|
+
# 2. PIT Mutation Testing
|
|
8
|
+
# 3. Postman API Integration Tests (local or staging)
|
|
9
|
+
# 4. API Coverage Matrix
|
|
10
|
+
# 5. Combined Quality Report (all in one)
|
|
11
|
+
#
|
|
12
|
+
# Usage:
|
|
13
|
+
# ./run-all.sh [OPTIONS]
|
|
14
|
+
#
|
|
15
|
+
# Options:
|
|
16
|
+
# --env {local|staging} Target environment for Postman tests (default: local)
|
|
17
|
+
# --skip-unit Skip unit tests (use existing results)
|
|
18
|
+
# --skip-mutation Skip mutation tests (use existing results)
|
|
19
|
+
# --skip-postman Skip Postman API tests (use existing results)
|
|
20
|
+
# --skip-coverage Skip API coverage matrix (use existing results)
|
|
21
|
+
# --skip-report Skip quality report generation
|
|
22
|
+
# --no-delay Skip delays between phases
|
|
23
|
+
# -h, --help Show this help message
|
|
24
|
+
#
|
|
25
|
+
# Examples:
|
|
26
|
+
# ./run-all.sh # Run everything (local tests)
|
|
27
|
+
# ./run-all.sh --env staging # Run everything against staging
|
|
28
|
+
# ./run-all.sh --skip-mutation # Skip slow mutation tests
|
|
29
|
+
# ./run-all.sh --env staging --skip-unit # Staging tests only, no unit tests
|
|
30
|
+
#
|
|
31
|
+
|
|
32
|
+
set -euo pipefail
|
|
33
|
+
|
|
34
|
+
# Colors
|
|
35
|
+
GREEN='\033[0;32m'
|
|
36
|
+
RED='\033[0;31m'
|
|
37
|
+
YELLOW='\033[1;33m'
|
|
38
|
+
BLUE='\033[0;34m'
|
|
39
|
+
CYAN='\033[0;36m'
|
|
40
|
+
BOLD='\033[1m'
|
|
41
|
+
NC='\033[0m'
|
|
42
|
+
|
|
43
|
+
# Configuration
|
|
44
|
+
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
45
|
+
PROJECT_ROOT="$(cd "$SCRIPT_DIR/../.." && pwd)"
|
|
46
|
+
# Display name shown on the reports — the repo/service name, overridable.
|
|
47
|
+
REPORT_LOGO="${SHIFTLEFT_REPORT_LOGO:-$(basename "$PROJECT_ROOT")}"
|
|
48
|
+
export REPORT_LOGO
|
|
49
|
+
POSTMAN_DIR="$(dirname "$SCRIPT_DIR")"
|
|
50
|
+
REPORTS_DIR="$POSTMAN_DIR/reports"
|
|
51
|
+
APP_PORT="${APP_PORT:-9090}"
|
|
52
|
+
TIMESTAMP=$(date +"%Y%m%d-%H%M%S")
|
|
53
|
+
|
|
54
|
+
# Environment selection (local or staging)
|
|
55
|
+
POSTMAN_ENV="${POSTMAN_ENV:-local}"
|
|
56
|
+
|
|
57
|
+
# Flags
|
|
58
|
+
SKIP_UNIT=false
|
|
59
|
+
SKIP_MUTATION=false
|
|
60
|
+
SKIP_POSTMAN=false
|
|
61
|
+
SKIP_COVERAGE=false
|
|
62
|
+
SKIP_REPORT=false
|
|
63
|
+
SKIP_DELAY=false
|
|
64
|
+
|
|
65
|
+
# Track results
|
|
66
|
+
UNIT_OK=false
|
|
67
|
+
MUTATION_OK=false
|
|
68
|
+
POSTMAN_OK=false
|
|
69
|
+
COVERAGE_OK=false
|
|
70
|
+
POSTMAN_RESULT=0
|
|
71
|
+
|
|
72
|
+
# Parse arguments
|
|
73
|
+
while [[ $# -gt 0 ]]; do
|
|
74
|
+
case $1 in
|
|
75
|
+
-h|--help) head -31 "$0" | tail -29; exit 0 ;;
|
|
76
|
+
--env) POSTMAN_ENV="$2"; shift 2 ;;
|
|
77
|
+
--skip-unit) SKIP_UNIT=true; shift ;;
|
|
78
|
+
--skip-mutation) SKIP_MUTATION=true; shift ;;
|
|
79
|
+
--skip-postman) SKIP_POSTMAN=true; shift ;;
|
|
80
|
+
--skip-coverage) SKIP_COVERAGE=true; shift ;;
|
|
81
|
+
--skip-report) SKIP_REPORT=true; shift ;;
|
|
82
|
+
--no-delay) SKIP_DELAY=true; shift ;;
|
|
83
|
+
*) echo -e "${RED}Unknown option: $1${NC}"; exit 1 ;;
|
|
84
|
+
esac
|
|
85
|
+
done
|
|
86
|
+
|
|
87
|
+
# Validate environment
|
|
88
|
+
if [[ ! "$POSTMAN_ENV" =~ ^(local|staging)$ ]]; then
|
|
89
|
+
echo -e "${RED}✗ Error: Invalid environment '$POSTMAN_ENV'${NC}"
|
|
90
|
+
echo -e "${YELLOW}Supported environments: local, staging${NC}"
|
|
91
|
+
exit 1
|
|
92
|
+
fi
|
|
93
|
+
|
|
94
|
+
# Cleanup function
|
|
95
|
+
cleanup() {
|
|
96
|
+
# Stop Spring Boot if running
|
|
97
|
+
if [ -f "$SCRIPT_DIR/spring-boot-app.pid" ]; then
|
|
98
|
+
APP_PID=$(cat "$SCRIPT_DIR/spring-boot-app.pid" 2>/dev/null || echo "")
|
|
99
|
+
if [ -n "$APP_PID" ] && ps -p "$APP_PID" > /dev/null 2>&1; then
|
|
100
|
+
echo -e "${YELLOW}Stopping Spring Boot application...${NC}"
|
|
101
|
+
kill "$APP_PID" 2>/dev/null || true
|
|
102
|
+
sleep 2
|
|
103
|
+
if ps -p "$APP_PID" > /dev/null 2>&1; then
|
|
104
|
+
kill -9 "$APP_PID" 2>/dev/null || true
|
|
105
|
+
fi
|
|
106
|
+
fi
|
|
107
|
+
rm -f "$SCRIPT_DIR/spring-boot-app.pid"
|
|
108
|
+
fi
|
|
109
|
+
# Stop WireMock only if local Postman tests were actually run (mocks were started)
|
|
110
|
+
if [ "$SKIP_POSTMAN" = false ] && [ "$POSTMAN_ENV" = "local" ]; then
|
|
111
|
+
"$SCRIPT_DIR/infra/stop-mocks.sh" 2>/dev/null || true
|
|
112
|
+
fi
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
trap cleanup EXIT
|
|
116
|
+
|
|
117
|
+
mkdir -p "$REPORTS_DIR"
|
|
118
|
+
|
|
119
|
+
# Clean up old reports — keep only the latest 3 of each type
|
|
120
|
+
echo -e "${YELLOW}Cleaning up old reports...${NC}"
|
|
121
|
+
_keep_latest() {
|
|
122
|
+
local pattern="$1" keep="${2:-3}"
|
|
123
|
+
# shellcheck disable=SC2012
|
|
124
|
+
ls -t $pattern 2>/dev/null | tail -n +$((keep + 1)) | xargs rm -f 2>/dev/null || true
|
|
125
|
+
}
|
|
126
|
+
_keep_latest "$REPORTS_DIR/quality-report-*.html" 3
|
|
127
|
+
if [ "$SKIP_POSTMAN" = false ]; then
|
|
128
|
+
# Remove only THIS environment's stale per-collection Newman HTML reports
|
|
129
|
+
# (they are about to be regenerated). Scoping the delete to the current env
|
|
130
|
+
# leaves the other env's reports — and the "View Details" links of its kept
|
|
131
|
+
# consolidated report — intact.
|
|
132
|
+
find "$REPORTS_DIR" -maxdepth 1 -name "test-${POSTMAN_ENV}-*.html" \
|
|
133
|
+
-delete 2>/dev/null || true
|
|
134
|
+
fi
|
|
135
|
+
if [ "$SKIP_POSTMAN" = false ]; then
|
|
136
|
+
_keep_latest "$REPORTS_DIR/consolidated-*.html" 3
|
|
137
|
+
_keep_latest "$REPORTS_DIR/consolidated-*.json" 3
|
|
138
|
+
rm -rf "$REPORTS_DIR"/json 2>/dev/null || true
|
|
139
|
+
fi
|
|
140
|
+
if [ "$SKIP_COVERAGE" = false ]; then
|
|
141
|
+
_keep_latest "$REPORTS_DIR/api-coverage-matrix-*.html" 3
|
|
142
|
+
_keep_latest "$REPORTS_DIR/api-coverage-matrix-*.json" 3
|
|
143
|
+
fi
|
|
144
|
+
echo -e "${GREEN}✓ Old reports cleaned${NC}"
|
|
145
|
+
echo ""
|
|
146
|
+
|
|
147
|
+
# Print header
|
|
148
|
+
[ -t 1 ] && clear || true
|
|
149
|
+
echo -e "${BOLD}${BLUE}╔════════════════════════════════════════════════════════════╗${NC}"
|
|
150
|
+
echo -e "${BOLD}${BLUE}║ UNIFIED TEST & QUALITY REPORT RUNNER ║${NC}"
|
|
151
|
+
echo -e "${BOLD}${BLUE}║ (One Command, One Report!) ║${NC}"
|
|
152
|
+
echo -e "${BOLD}${BLUE}╚════════════════════════════════════════════════════════════╝${NC}"
|
|
153
|
+
echo ""
|
|
154
|
+
echo -e "${CYAN}This will run:${NC}"
|
|
155
|
+
[ "$SKIP_UNIT" = false ] && echo -e " ${BOLD}1.${NC} Unit Tests + JaCoCo Coverage" || echo -e " ${BOLD}1.${NC} Unit Tests + JaCoCo Coverage ${YELLOW}(skipped)${NC}"
|
|
156
|
+
[ "$SKIP_MUTATION" = false ] && echo -e " ${BOLD}2.${NC} PIT Mutation Testing" || echo -e " ${BOLD}2.${NC} PIT Mutation Testing ${YELLOW}(skipped)${NC}"
|
|
157
|
+
[ "$SKIP_POSTMAN" = false ] && echo -e " ${BOLD}3.${NC} Postman API Integration Tests" || echo -e " ${BOLD}3.${NC} Postman API Integration Tests ${YELLOW}(skipped)${NC}"
|
|
158
|
+
[ "$SKIP_COVERAGE" = false ] && echo -e " ${BOLD}4.${NC} API Coverage Matrix" || echo -e " ${BOLD}4.${NC} API Coverage Matrix ${YELLOW}(skipped)${NC}"
|
|
159
|
+
echo -e " ${BOLD}5.${NC} Combined Quality Report"
|
|
160
|
+
echo ""
|
|
161
|
+
if [ "$SKIP_DELAY" = "false" ]; then
|
|
162
|
+
echo -e "${YELLOW}Starting in 2 seconds... (Ctrl+C to cancel)${NC}"
|
|
163
|
+
sleep 2
|
|
164
|
+
fi
|
|
165
|
+
|
|
166
|
+
# ============================================================================
|
|
167
|
+
# PHASE 1: Unit Tests + JaCoCo Coverage
|
|
168
|
+
# ============================================================================
|
|
169
|
+
echo ""
|
|
170
|
+
echo -e "${CYAN}╔════════════════════════════════════════════════════════════╗${NC}"
|
|
171
|
+
echo -e "${CYAN}║ Phase 1: Unit Tests + JaCoCo Coverage ║${NC}"
|
|
172
|
+
echo -e "${CYAN}╚════════════════════════════════════════════════════════════╝${NC}"
|
|
173
|
+
echo ""
|
|
174
|
+
|
|
175
|
+
SUREFIRE_DIR="$PROJECT_ROOT/target/surefire-reports"
|
|
176
|
+
JACOCO_XML="$PROJECT_ROOT/target/site/jacoco/jacoco.xml"
|
|
177
|
+
UNIT_JACOCO_XML="$PROJECT_ROOT/target/site/jacoco/jacoco-unit.xml"
|
|
178
|
+
|
|
179
|
+
if [ "$SKIP_UNIT" = false ]; then
|
|
180
|
+
echo -e "${YELLOW}Running unit tests with coverage...${NC}"
|
|
181
|
+
cd "$PROJECT_ROOT"
|
|
182
|
+
if mvn clean test jacoco:report -q; then
|
|
183
|
+
echo -e "${GREEN}✓ Unit tests passed${NC}"
|
|
184
|
+
UNIT_OK=true
|
|
185
|
+
else
|
|
186
|
+
echo -e "${RED}✗ Unit tests had failures${NC}"
|
|
187
|
+
UNIT_OK=true # Still continue - report will show failures
|
|
188
|
+
fi
|
|
189
|
+
# Preserve unit test JaCoCo before Postman phase overwrites it
|
|
190
|
+
if [ -f "$JACOCO_XML" ]; then
|
|
191
|
+
cp "$JACOCO_XML" "$UNIT_JACOCO_XML"
|
|
192
|
+
echo -e "${GREEN}✓ Unit test coverage preserved${NC}"
|
|
193
|
+
fi
|
|
194
|
+
else
|
|
195
|
+
echo -e "${YELLOW}Skipping unit tests (using existing results)${NC}"
|
|
196
|
+
if [ -d "$SUREFIRE_DIR" ]; then
|
|
197
|
+
UNIT_OK=true
|
|
198
|
+
echo -e "${GREEN}✓ Found existing Surefire reports${NC}"
|
|
199
|
+
else
|
|
200
|
+
echo -e "${RED}✗ No existing Surefire reports found${NC}"
|
|
201
|
+
fi
|
|
202
|
+
# Check for preserved unit JaCoCo
|
|
203
|
+
if [ -f "$UNIT_JACOCO_XML" ]; then
|
|
204
|
+
echo -e "${GREEN}✓ Found preserved unit test coverage${NC}"
|
|
205
|
+
elif [ -f "$JACOCO_XML" ]; then
|
|
206
|
+
cp "$JACOCO_XML" "$UNIT_JACOCO_XML"
|
|
207
|
+
echo -e "${GREEN}✓ Current JaCoCo report preserved${NC}"
|
|
208
|
+
fi
|
|
209
|
+
fi
|
|
210
|
+
|
|
211
|
+
# ============================================================================
|
|
212
|
+
# PHASE 2: PIT Mutation Testing
|
|
213
|
+
# ============================================================================
|
|
214
|
+
echo ""
|
|
215
|
+
echo -e "${CYAN}╔════════════════════════════════════════════════════════════╗${NC}"
|
|
216
|
+
echo -e "${CYAN}║ Phase 2: PIT Mutation Testing ║${NC}"
|
|
217
|
+
echo -e "${CYAN}╚════════════════════════════════════════════════════════════╝${NC}"
|
|
218
|
+
echo ""
|
|
219
|
+
|
|
220
|
+
MUTATIONS_XML="$PROJECT_ROOT/target/pit-reports/mutations.xml"
|
|
221
|
+
|
|
222
|
+
if [ "$SKIP_MUTATION" = false ]; then
|
|
223
|
+
echo -e "${YELLOW}Running mutation tests (this may take 2-3 minutes)...${NC}"
|
|
224
|
+
cd "$PROJECT_ROOT"
|
|
225
|
+
# PIT is profile-gated (-Pmutation-tests) per the setup-mutation-tests skill, so the
|
|
226
|
+
# profile's pinned pitest-maven version + pitest-junit5-plugin dependency are used.
|
|
227
|
+
# Without it, Maven resolves PIT's latest with no JUnit 5 plugin -> "could not run any tests".
|
|
228
|
+
# test-compile ensures test classes exist when unit tests were skipped/reused.
|
|
229
|
+
if mvn test-compile org.pitest:pitest-maven:mutationCoverage -Pmutation-tests -q 2>&1; then
|
|
230
|
+
echo -e "${GREEN}✓ Mutation tests completed${NC}"
|
|
231
|
+
MUTATION_OK=true
|
|
232
|
+
else
|
|
233
|
+
echo -e "${RED}✗ Mutation tests failed${NC}"
|
|
234
|
+
fi
|
|
235
|
+
else
|
|
236
|
+
echo -e "${YELLOW}Skipping mutation tests (using existing results)${NC}"
|
|
237
|
+
if [ -f "$MUTATIONS_XML" ]; then
|
|
238
|
+
MUTATION_OK=true
|
|
239
|
+
echo -e "${GREEN}✓ Found existing mutation data${NC}"
|
|
240
|
+
else
|
|
241
|
+
echo -e "${RED}✗ No existing mutation data found${NC}"
|
|
242
|
+
fi
|
|
243
|
+
fi
|
|
244
|
+
|
|
245
|
+
# ============================================================================
|
|
246
|
+
# PHASE 3: Postman API Integration Tests
|
|
247
|
+
# ============================================================================
|
|
248
|
+
echo ""
|
|
249
|
+
echo -e "${CYAN}╔════════════════════════════════════════════════════════════╗${NC}"
|
|
250
|
+
echo -e "${CYAN}║ Phase 3: Postman API Integration Tests ($(echo "$POSTMAN_ENV" | tr '[:lower:]' '[:upper:]')) ║${NC}"
|
|
251
|
+
echo -e "${CYAN}╚════════════════════════════════════════════════════════════╝${NC}"
|
|
252
|
+
echo ""
|
|
253
|
+
|
|
254
|
+
POSTMAN_PASSED=0
|
|
255
|
+
POSTMAN_FAILED=0
|
|
256
|
+
POSTMAN_JSON_DIR="$REPORTS_DIR/json"
|
|
257
|
+
|
|
258
|
+
if [ "$SKIP_POSTMAN" = false ]; then
|
|
259
|
+
# Clear old JSON reports so totals only reflect this run
|
|
260
|
+
rm -rf "$POSTMAN_JSON_DIR"
|
|
261
|
+
|
|
262
|
+
# Delegate to appropriate test runner (local or staging)
|
|
263
|
+
set +e
|
|
264
|
+
if [ "$POSTMAN_ENV" = "staging" ]; then
|
|
265
|
+
"$SCRIPT_DIR/runners/run-tests-staging.sh"
|
|
266
|
+
else
|
|
267
|
+
"$SCRIPT_DIR/runners/run-tests-local.sh"
|
|
268
|
+
fi
|
|
269
|
+
POSTMAN_RESULT=$?
|
|
270
|
+
set -e
|
|
271
|
+
|
|
272
|
+
# Derive collection pass/fail counts from the consolidated JSON
|
|
273
|
+
# (individual JSON reports are cleaned up by run-*sh scripts after consolidation)
|
|
274
|
+
CONSOLIDATED_JSON=$(ls -t "$REPORTS_DIR"/consolidated-*.json 2>/dev/null | head -1)
|
|
275
|
+
if [ -n "$CONSOLIDATED_JSON" ] && [ -f "$CONSOLIDATED_JSON" ]; then
|
|
276
|
+
POSTMAN_PASSED=$(jq '.summary.collections.passed // 0' "$CONSOLIDATED_JSON" 2>/dev/null || echo "0")
|
|
277
|
+
POSTMAN_FAILED=$(jq '.summary.collections.failed // 0' "$CONSOLIDATED_JSON" 2>/dev/null || echo "0")
|
|
278
|
+
POSTMAN_OK=true
|
|
279
|
+
fi
|
|
280
|
+
else
|
|
281
|
+
echo -e "${YELLOW}Skipping Postman tests (using existing results)${NC}"
|
|
282
|
+
if ls "$POSTMAN_JSON_DIR"/*.json 1>/dev/null 2>&1; then
|
|
283
|
+
POSTMAN_OK=true
|
|
284
|
+
echo -e "${GREEN}✓ Found existing Postman results${NC}"
|
|
285
|
+
else
|
|
286
|
+
echo -e "${RED}✗ No existing Postman results found${NC}"
|
|
287
|
+
fi
|
|
288
|
+
fi
|
|
289
|
+
|
|
290
|
+
# ============================================================================
|
|
291
|
+
# PHASE 4: API Coverage Matrix
|
|
292
|
+
# ============================================================================
|
|
293
|
+
echo ""
|
|
294
|
+
echo -e "${CYAN}╔════════════════════════════════════════════════════════════╗${NC}"
|
|
295
|
+
echo -e "${CYAN}║ Phase 4: API Coverage Matrix ║${NC}"
|
|
296
|
+
echo -e "${CYAN}╚════════════════════════════════════════════════════════════╝${NC}"
|
|
297
|
+
echo ""
|
|
298
|
+
|
|
299
|
+
API_COVERAGE_JSON=""
|
|
300
|
+
|
|
301
|
+
if [ "$SKIP_COVERAGE" = false ]; then
|
|
302
|
+
echo -e "${YELLOW}Generating API coverage matrix...${NC}"
|
|
303
|
+
if "$SCRIPT_DIR/report-generators/java-api-coverage-matrix.sh" 2>&1; then
|
|
304
|
+
COVERAGE_OK=true
|
|
305
|
+
echo -e "${GREEN}✓ API coverage matrix generated${NC}"
|
|
306
|
+
else
|
|
307
|
+
echo -e "${RED}✗ API coverage matrix failed${NC}"
|
|
308
|
+
fi
|
|
309
|
+
else
|
|
310
|
+
echo -e "${YELLOW}Skipping API coverage matrix (using existing results)${NC}"
|
|
311
|
+
if ls "$REPORTS_DIR"/api-coverage-matrix-*.json 1>/dev/null 2>&1; then
|
|
312
|
+
COVERAGE_OK=true
|
|
313
|
+
echo -e "${GREEN}✓ Found existing API coverage data${NC}"
|
|
314
|
+
fi
|
|
315
|
+
fi
|
|
316
|
+
|
|
317
|
+
# Load API coverage JSON if available
|
|
318
|
+
COVERAGE_JSON_FILE=$(ls -t "$REPORTS_DIR"/api-coverage-matrix-*.json 2>/dev/null | head -1 || true)
|
|
319
|
+
if [ -n "$COVERAGE_JSON_FILE" ] && [ -f "$COVERAGE_JSON_FILE" ]; then
|
|
320
|
+
API_COVERAGE_JSON=$(cat "$COVERAGE_JSON_FILE")
|
|
321
|
+
fi
|
|
322
|
+
|
|
323
|
+
# ============================================================================
|
|
324
|
+
# PHASE 5: Generate Combined Quality Report
|
|
325
|
+
# ============================================================================
|
|
326
|
+
echo ""
|
|
327
|
+
echo -e "${CYAN}╔════════════════════════════════════════════════════════════╗${NC}"
|
|
328
|
+
echo -e "${CYAN}║ Phase 5: Generate Combined Quality Report ║${NC}"
|
|
329
|
+
echo -e "${CYAN}╚════════════════════════════════════════════════════════════╝${NC}"
|
|
330
|
+
echo ""
|
|
331
|
+
|
|
332
|
+
if [ "$SKIP_REPORT" = false ]; then
|
|
333
|
+
# Calculate Postman stats from the consolidated JSON
|
|
334
|
+
# (individual JSON reports are cleaned up by run-tests-local.sh after consolidation)
|
|
335
|
+
POSTMAN_TOTAL_ASSERTIONS=0
|
|
336
|
+
POSTMAN_PASSED_ASSERTIONS=0
|
|
337
|
+
POSTMAN_FAILED_ASSERTIONS=0
|
|
338
|
+
POSTMAN_TOTAL_REQUESTS=0
|
|
339
|
+
POSTMAN_DURATION="0"
|
|
340
|
+
|
|
341
|
+
CONSOLIDATED_JSON="${CONSOLIDATED_JSON:-$(ls -t "$REPORTS_DIR"/consolidated-*.json 2>/dev/null | head -1)}"
|
|
342
|
+
if [ -n "$CONSOLIDATED_JSON" ] && [ -f "$CONSOLIDATED_JSON" ]; then
|
|
343
|
+
POSTMAN_TOTAL_ASSERTIONS=$(jq '.summary.assertions.total // 0' "$CONSOLIDATED_JSON" 2>/dev/null || echo "0")
|
|
344
|
+
POSTMAN_FAILED_ASSERTIONS=$(jq '.summary.assertions.failed // 0' "$CONSOLIDATED_JSON" 2>/dev/null || echo "0")
|
|
345
|
+
POSTMAN_TOTAL_REQUESTS=$(jq '.summary.requests.total // 0' "$CONSOLIDATED_JSON" 2>/dev/null || echo "0")
|
|
346
|
+
POSTMAN_TOTAL_DURATION=$(jq '.summary.duration_ms // 0' "$CONSOLIDATED_JSON" 2>/dev/null || echo "0")
|
|
347
|
+
POSTMAN_PASSED_ASSERTIONS=$((POSTMAN_TOTAL_ASSERTIONS - POSTMAN_FAILED_ASSERTIONS))
|
|
348
|
+
POSTMAN_DURATION=$(echo "scale=2; $POSTMAN_TOTAL_DURATION / 1000" | bc 2>/dev/null || echo "0")
|
|
349
|
+
fi
|
|
350
|
+
|
|
351
|
+
COMBINED_OUTPUT="$REPORTS_DIR/quality-report-$TIMESTAMP.html"
|
|
352
|
+
|
|
353
|
+
echo -e "${YELLOW}Staging report artifacts for Jenkins-safe links...${NC}"
|
|
354
|
+
"$SCRIPT_DIR/report-generators/stage-report-artifacts.sh" "$PROJECT_ROOT" "$REPORTS_DIR"
|
|
355
|
+
|
|
356
|
+
echo -e "${YELLOW}Generating combined report...${NC}"
|
|
357
|
+
|
|
358
|
+
# Build report arguments as an array to handle spaces properly
|
|
359
|
+
REPORT_ARGS=(combined "$COMBINED_OUTPUT" --logo "$REPORT_LOGO" --env "$POSTMAN_ENV" --timestamp "$TIMESTAMP")
|
|
360
|
+
|
|
361
|
+
# Unit test data (use preserved unit test JaCoCo, not the postman one)
|
|
362
|
+
[ -d "$SUREFIRE_DIR" ] && REPORT_ARGS+=(--surefire-dir "$SUREFIRE_DIR")
|
|
363
|
+
if [ -f "$UNIT_JACOCO_XML" ]; then
|
|
364
|
+
REPORT_ARGS+=(--jacoco-xml "$UNIT_JACOCO_XML")
|
|
365
|
+
elif [ -f "$JACOCO_XML" ]; then
|
|
366
|
+
REPORT_ARGS+=(--jacoco-xml "$JACOCO_XML")
|
|
367
|
+
fi
|
|
368
|
+
[ -f "$MUTATIONS_XML" ] && REPORT_ARGS+=(--mutations-xml "$MUTATIONS_XML")
|
|
369
|
+
|
|
370
|
+
# Postman data
|
|
371
|
+
REPORT_ARGS+=(--postman-assertions-total "$POSTMAN_TOTAL_ASSERTIONS")
|
|
372
|
+
REPORT_ARGS+=(--postman-assertions-passed "$POSTMAN_PASSED_ASSERTIONS")
|
|
373
|
+
REPORT_ARGS+=(--postman-assertions-failed "$POSTMAN_FAILED_ASSERTIONS")
|
|
374
|
+
REPORT_ARGS+=(--postman-requests "$POSTMAN_TOTAL_REQUESTS")
|
|
375
|
+
REPORT_ARGS+=(--postman-duration "$POSTMAN_DURATION")
|
|
376
|
+
REPORT_ARGS+=(--postman-collections-passed "$POSTMAN_PASSED")
|
|
377
|
+
REPORT_ARGS+=(--postman-collections-failed "$POSTMAN_FAILED")
|
|
378
|
+
|
|
379
|
+
# API coverage data
|
|
380
|
+
TEMP_COVERAGE=""
|
|
381
|
+
if [ -n "$API_COVERAGE_JSON" ]; then
|
|
382
|
+
TEMP_COVERAGE="/tmp/api-coverage-data-$$.json"
|
|
383
|
+
echo "$API_COVERAGE_JSON" > "$TEMP_COVERAGE"
|
|
384
|
+
REPORT_ARGS+=(--api-coverage-file "$TEMP_COVERAGE")
|
|
385
|
+
fi
|
|
386
|
+
|
|
387
|
+
# API coverage HTML (for linking)
|
|
388
|
+
API_COVERAGE_HTML=$(ls -t "$REPORTS_DIR"/api-coverage-matrix-*.html 2>/dev/null | head -1 || true)
|
|
389
|
+
if [ -n "$API_COVERAGE_HTML" ]; then
|
|
390
|
+
REPORT_ARGS+=(--api-coverage-html "$API_COVERAGE_HTML")
|
|
391
|
+
fi
|
|
392
|
+
|
|
393
|
+
# Newman JSON results directory (for per-collection details)
|
|
394
|
+
if [ -d "$POSTMAN_JSON_DIR" ]; then
|
|
395
|
+
REPORT_ARGS+=(--postman-json-dir "$POSTMAN_JSON_DIR")
|
|
396
|
+
fi
|
|
397
|
+
|
|
398
|
+
# Consolidated Postman HTML report (for linking).
|
|
399
|
+
# Always (re)generate it for THIS run's timestamp so the combined report never
|
|
400
|
+
# links to a stale consolidated report whose per-collection detail files have
|
|
401
|
+
# already been cleaned up. Only fall back to the newest existing one if this
|
|
402
|
+
# run produced no consolidated JSON to render.
|
|
403
|
+
POSTMAN_CONSOLIDATED_HTML="$REPORTS_DIR/consolidated-${POSTMAN_ENV}-${TIMESTAMP}.html"
|
|
404
|
+
CONSOLIDATED_JSON_THIS_RUN="$REPORTS_DIR/consolidated-${POSTMAN_ENV}-${TIMESTAMP}.json"
|
|
405
|
+
if [ ! -f "$POSTMAN_CONSOLIDATED_HTML" ] && [ -f "$CONSOLIDATED_JSON_THIS_RUN" ]; then
|
|
406
|
+
echo -e "${YELLOW}Generating consolidated HTML report...${NC}"
|
|
407
|
+
"$SCRIPT_DIR/report-generators/generate-consolidated-report.sh" "$POSTMAN_ENV" "$TIMESTAMP" "$REPORTS_DIR" "$POSTMAN_PASSED" "$POSTMAN_FAILED" 0 >/dev/null 2>&1 || true
|
|
408
|
+
fi
|
|
409
|
+
if [ ! -f "$POSTMAN_CONSOLIDATED_HTML" ]; then
|
|
410
|
+
POSTMAN_CONSOLIDATED_HTML=$(ls -t "$REPORTS_DIR"/consolidated-*.html 2>/dev/null | head -1 || true)
|
|
411
|
+
fi
|
|
412
|
+
if [ -n "$POSTMAN_CONSOLIDATED_HTML" ] && [ -f "$POSTMAN_CONSOLIDATED_HTML" ]; then
|
|
413
|
+
REPORT_ARGS+=(--postman-consolidated-html "$POSTMAN_CONSOLIDATED_HTML")
|
|
414
|
+
fi
|
|
415
|
+
|
|
416
|
+
python3 "$SCRIPT_DIR/lib/report_generator.py" "${REPORT_ARGS[@]}"
|
|
417
|
+
|
|
418
|
+
# Cleanup temp file
|
|
419
|
+
[ -n "$TEMP_COVERAGE" ] && rm -f "$TEMP_COVERAGE"
|
|
420
|
+
|
|
421
|
+
if [ -f "$COMBINED_OUTPUT" ]; then
|
|
422
|
+
echo -e "${GREEN}✓ Combined report generated${NC}"
|
|
423
|
+
|
|
424
|
+
echo ""
|
|
425
|
+
echo -e "${CYAN}═══════════════════════════════════════════════════════════════${NC}"
|
|
426
|
+
echo -e "${BOLD} FINAL SUMMARY${NC}"
|
|
427
|
+
echo -e "${CYAN}═══════════════════════════════════════════════════════════════${NC}"
|
|
428
|
+
echo ""
|
|
429
|
+
echo -e " ${BLUE}Environment:${NC} ${POSTMAN_ENV^^}"
|
|
430
|
+
echo ""
|
|
431
|
+
[ "$UNIT_OK" = true ] && echo -e " ${GREEN}✓${NC} Unit Tests" || echo -e " ${RED}✗${NC} Unit Tests"
|
|
432
|
+
[ "$MUTATION_OK" = true ] && echo -e " ${GREEN}✓${NC} Mutation Testing" || echo -e " ${RED}✗${NC} Mutation Testing"
|
|
433
|
+
[ "$POSTMAN_OK" = true ] && echo -e " ${GREEN}✓${NC} Postman API Tests (${POSTMAN_PASSED} passed, ${POSTMAN_FAILED} failed)" || echo -e " ${RED}✗${NC} Postman API Tests"
|
|
434
|
+
[ "$COVERAGE_OK" = true ] && echo -e " ${GREEN}✓${NC} API Coverage Matrix" || echo -e " ${RED}✗${NC} API Coverage Matrix"
|
|
435
|
+
echo ""
|
|
436
|
+
echo -e " ${GREEN}Report:${NC} $COMBINED_OUTPUT"
|
|
437
|
+
echo ""
|
|
438
|
+
echo -e "${CYAN}═══════════════════════════════════════════════════════════════${NC}"
|
|
439
|
+
|
|
440
|
+
# Open report on macOS
|
|
441
|
+
if [[ "$OSTYPE" == "darwin"* ]]; then
|
|
442
|
+
open "$COMBINED_OUTPUT" 2>/dev/null || true
|
|
443
|
+
fi
|
|
444
|
+
else
|
|
445
|
+
echo -e "${RED}✗ Failed to generate combined report${NC}"
|
|
446
|
+
exit 1
|
|
447
|
+
fi
|
|
448
|
+
else
|
|
449
|
+
echo -e "${YELLOW}Skipping quality report generation (--skip-report flag set)${NC}"
|
|
450
|
+
fi
|
|
451
|
+
|
|
452
|
+
exit $POSTMAN_RESULT
|