@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.
Files changed (106) hide show
  1. package/README.md +351 -0
  2. package/bin/shiftleft.js +95 -0
  3. package/package.json +57 -0
  4. package/src/commands/doctor.js +208 -0
  5. package/src/commands/init-postman.js +298 -0
  6. package/src/commands/init-rules.js +78 -0
  7. package/src/commands/link.js +172 -0
  8. package/src/commands/protect.js +61 -0
  9. package/src/commands/run-tests.js +182 -0
  10. package/src/commands/setup-pipeline.js +209 -0
  11. package/src/commands/update.js +203 -0
  12. package/src/index.js +4 -0
  13. package/src/utils/copy-tree.js +98 -0
  14. package/src/utils/gitignore.js +26 -0
  15. package/src/utils/logger.js +9 -0
  16. package/src/utils/manifest.js +145 -0
  17. package/src/utils/stack.js +80 -0
  18. package/src/utils/template.js +135 -0
  19. package/templates/AGENTS.md +109 -0
  20. package/templates/CLAUDE.md +3 -0
  21. package/templates/jenkins/Jenkinsfile-java.groovy +432 -0
  22. package/templates/jenkins/Jenkinsfile-node.groovy +450 -0
  23. package/templates/postman/.husky/pre-commit +19 -0
  24. package/templates/postman/.prettierrc.json +5 -0
  25. package/templates/postman/README.md.ejs +147 -0
  26. package/templates/postman/collections/01-core.json.ejs +91 -0
  27. package/templates/postman/config/local.json.ejs +12 -0
  28. package/templates/postman/config/staging.json.ejs +26 -0
  29. package/templates/postman/environments/local.postman_environment.json.ejs +31 -0
  30. package/templates/postman/environments/staging.postman_environment.json.ejs +31 -0
  31. package/templates/postman/gitignore +16 -0
  32. package/templates/postman/npmrc +31 -0
  33. package/templates/postman/package.json.ejs +66 -0
  34. package/templates/postman/run-all-shim.sh +16 -0
  35. package/templates/postman/scripts/auth/generate-jwt.sh +113 -0
  36. package/templates/postman/scripts/auth/get-issuer-secret.sh +140 -0
  37. package/templates/postman/scripts/infra/start-mocks.sh +138 -0
  38. package/templates/postman/scripts/infra/stop-mocks.sh +43 -0
  39. package/templates/postman/scripts/lib/api_coverage.py +1122 -0
  40. package/templates/postman/scripts/lib/cleanup-reports.sh +101 -0
  41. package/templates/postman/scripts/lib/cleanup-stryker.sh +44 -0
  42. package/templates/postman/scripts/lib/report_combined.py +527 -0
  43. package/templates/postman/scripts/lib/report_consolidated.py +363 -0
  44. package/templates/postman/scripts/lib/report_generator.py +121 -0
  45. package/templates/postman/scripts/lib/report_migration.py +156 -0
  46. package/templates/postman/scripts/lib/report_mutation.py +110 -0
  47. package/templates/postman/scripts/lib/report_unit.py +353 -0
  48. package/templates/postman/scripts/lib/report_utils.py +973 -0
  49. package/templates/postman/scripts/report-generators/generate-consolidated-report.sh +445 -0
  50. package/templates/postman/scripts/report-generators/java-api-coverage-matrix.sh +257 -0
  51. package/templates/postman/scripts/report-generators/mutation-report.sh +672 -0
  52. package/templates/postman/scripts/report-generators/node-api-coverage-matrix.sh +167 -0
  53. package/templates/postman/scripts/report-generators/stage-report-artifacts.sh +27 -0
  54. package/templates/postman/scripts/run-all.sh +452 -0
  55. package/templates/postman/scripts/runners/run-mutation-tests.sh +113 -0
  56. package/templates/postman/scripts/runners/run-tests-local.sh +936 -0
  57. package/templates/postman/scripts/runners/run-tests-staging.sh +741 -0
  58. package/templates/postman-node/README.md.ejs +26 -0
  59. package/templates/postman-node/collections/crud/01-bootstrap.json.ejs +34 -0
  60. package/templates/postman-node/config/local.json.ejs +46 -0
  61. package/templates/postman-node/config/staging.json.ejs +31 -0
  62. package/templates/postman-node/local.test.env.ejs +3 -0
  63. package/templates/postman-node/mocks/external.js +14 -0
  64. package/templates/postman-node/package.json.ejs +39 -0
  65. package/templates/postman-node/requirements.txt +1 -0
  66. package/templates/postman-node/scripts/database/cleanup-mysql.sh +12 -0
  67. package/templates/postman-node/scripts/database/run-migrations.js +29 -0
  68. package/templates/postman-node/scripts/database/start-mysql.sh +34 -0
  69. package/templates/postman-node/scripts/database/wait-for-mysql.sh +36 -0
  70. package/templates/postman-node/scripts/lib/api_coverage_node.py +1137 -0
  71. package/templates/postman-node/scripts/lib/fetch-jwt.sh +86 -0
  72. package/templates/postman-node/scripts/lib/run-newman.sh +104 -0
  73. package/templates/postman-node/scripts/lib/setup-database.sh +55 -0
  74. package/templates/postman-node/scripts/lib/start-app.sh +48 -0
  75. package/templates/postman-node/scripts/lib/utils.sh +114 -0
  76. package/templates/postman-node/scripts/report-generators/stage-report-artifacts.sh +26 -0
  77. package/templates/postman-node/scripts/run-all.sh +303 -0
  78. package/templates/postman-node/scripts/runners/run-tests.sh +123 -0
  79. package/templates/postman-node/scripts/setup-mocks.js.ejs +29 -0
  80. package/templates/postman-node/stryker.config.js.ejs +51 -0
  81. package/templates/rules/local-test-setup.mdc +420 -0
  82. package/templates/rules/testing-node.mdc +66 -0
  83. package/templates/rules/testing.mdc +248 -0
  84. package/templates/skills/_shared/postman-standards.md +380 -0
  85. package/templates/skills/enhance-test-pipeline/SKILL-java.md +483 -0
  86. package/templates/skills/enhance-test-pipeline/SKILL-node.md +431 -0
  87. package/templates/skills/enhance-test-pipeline/SKILL.md +9 -0
  88. package/templates/skills/review-test-suite/SKILL-java.md +137 -0
  89. package/templates/skills/review-test-suite/SKILL-node.md +78 -0
  90. package/templates/skills/review-test-suite/SKILL.md +9 -0
  91. package/templates/skills/run-test-suite/SKILL-java.md +186 -0
  92. package/templates/skills/run-test-suite/SKILL-node.md +191 -0
  93. package/templates/skills/run-test-suite/SKILL.md +9 -0
  94. package/templates/skills/setup-api-tests/SKILL-java.md +1094 -0
  95. package/templates/skills/setup-api-tests/SKILL-node.md +141 -0
  96. package/templates/skills/setup-api-tests/SKILL.md +9 -0
  97. package/templates/skills/setup-mutation-tests/SKILL-java.md +303 -0
  98. package/templates/skills/setup-mutation-tests/SKILL-node.md +408 -0
  99. package/templates/skills/setup-mutation-tests/SKILL.md +9 -0
  100. package/templates/skills/setup-test-pipeline/SKILL-java.md +454 -0
  101. package/templates/skills/setup-test-pipeline/SKILL-node.md +318 -0
  102. package/templates/skills/setup-test-pipeline/SKILL.md +9 -0
  103. package/templates/skills/write-api-tests/SKILL-java.md +115 -0
  104. package/templates/skills/write-api-tests/SKILL-node.md +83 -0
  105. package/templates/skills/write-api-tests/SKILL.md +9 -0
  106. package/templates/stryker.config.js +50 -0
@@ -0,0 +1,86 @@
1
+ #!/bin/bash
2
+ # JWT fetching - environment-aware
3
+
4
+ fetch_jwt() {
5
+ local config_file="$1"
6
+ local auth_type=$(jq -r '.auth.type' "$config_file")
7
+ local env_name=$(jq -r '.environment' "$config_file")
8
+
9
+ case "$auth_type" in
10
+ "local")
11
+ log_info "Generating JWT (local mode)"
12
+ cd "$PROJECT_ROOT"
13
+ "$SCRIPT_DIR/auth/generate-jwt.sh" local local > /dev/null 2>&1
14
+
15
+ # Read token from updated environment file
16
+ local env_file="$POSTMAN_DIR/environments/local.postman_environment.json"
17
+ local token=$(jq -r '.values[] | select(.key=="auth_token") | .value' "$env_file")
18
+ echo "$token"
19
+ ;;
20
+
21
+ "aws")
22
+ log_info "Fetching secret from AWS Secrets Manager"
23
+
24
+ local secret_name=$(jq -r '.auth.aws.secretName' "$config_file")
25
+ local client=$(jq -r '.auth.aws.client' "$config_file")
26
+ local region=$(jq -r '.auth.aws.region' "$config_file")
27
+ local aws_profile=$(jq -r '.auth.aws.profile // empty' "$config_file")
28
+
29
+ # Set AWS profile if specified in config (unless already set by user)
30
+ if [ -n "$aws_profile" ] && [ -z "${AWS_PROFILE:-}" ]; then
31
+ export AWS_PROFILE="$aws_profile"
32
+ log_info "Using AWS profile: $aws_profile"
33
+ elif [ -n "${AWS_PROFILE:-}" ]; then
34
+ log_info "Using AWS profile from environment: $AWS_PROFILE"
35
+ else
36
+ log_info "Using default AWS credentials (IAM role)"
37
+ fi
38
+
39
+ # Fetch secrets
40
+ set +e
41
+ SCRIPT_OUTPUT=$("$SCRIPT_DIR/auth/get-issuer-secret.sh" "$secret_name" "$client" "$region" 2>&1)
42
+ EXIT_CODE=$?
43
+ set -e
44
+
45
+ if [ $EXIT_CODE -ne 0 ]; then
46
+ error "Failed to fetch AWS secret"
47
+ echo "$SCRIPT_OUTPUT" >&2
48
+ exit 1
49
+ fi
50
+
51
+ # Extract both secrets from output (format: KEY=value)
52
+ ISSUER_SECRET=$(echo "$SCRIPT_OUTPUT" | grep "^PRIMARY_SECRET=" | cut -d'=' -f2-)
53
+ ISSUER_SECRET_SECONDARY=$(echo "$SCRIPT_OUTPUT" | grep "^SECONDARY_SECRET=" | cut -d'=' -f2-)
54
+
55
+ if [ -z "$ISSUER_SECRET" ]; then
56
+ error "Failed to parse primary secret from AWS"
57
+ echo "$SCRIPT_OUTPUT" >&2
58
+ exit 1
59
+ fi
60
+
61
+ log_info "Generating JWT with AWS secrets"
62
+
63
+ # Export both secrets - generate-jwt.sh reads all other config from the config file
64
+ export ISSUER_SECRET
65
+ export ISSUER_SECRET_SECONDARY
66
+
67
+ # Generate JWT using shell script and update environment file
68
+ # The script reads user-specific config from config/{env_name}.json (same as local mode)
69
+ "$SCRIPT_DIR/auth/generate-jwt.sh" aws "$env_name" > /dev/null 2>&1
70
+
71
+ # Clear secrets from memory
72
+ unset ISSUER_SECRET
73
+ unset ISSUER_SECRET_SECONDARY
74
+
75
+ # Read token from updated environment file
76
+ local env_file="$POSTMAN_DIR/environments/${env_name}.postman_environment.json"
77
+ local token=$(jq -r '.values[] | select(.key=="auth_token") | .value' "$env_file")
78
+ echo "$token"
79
+ ;;
80
+
81
+ *)
82
+ error "Unknown auth type: $auth_type"
83
+ exit 1
84
+ ;;
85
+ esac
86
+ }
@@ -0,0 +1,104 @@
1
+ #!/bin/bash
2
+ # Newman test execution
3
+
4
+ run_newman_tests() {
5
+ local environment="$1"
6
+
7
+ cd "$POSTMAN_DIR"
8
+
9
+ # Install dependencies if needed
10
+ if [ ! -d "node_modules" ]; then
11
+ log_info "Installing Newman dependencies..."
12
+ npm install --ignore-scripts
13
+ fi
14
+
15
+ # Create reports directories
16
+ mkdir -p "$POSTMAN_DIR/reports"
17
+ mkdir -p "$POSTMAN_DIR/reports/json"
18
+
19
+ local timestamp=$(date +%Y-%m-%d_%H-%M-%S)
20
+ local overall_exit_code=0
21
+ local passed_count=0
22
+ local failed_count=0
23
+ declare -a failed_collections=()
24
+ local env_file="$POSTMAN_DIR/environments/${environment}.postman_environment.json"
25
+
26
+ # Run all collections in crud folder (sorted by filename)
27
+ for collection_file in "$POSTMAN_DIR/collections/crud"/*.json; do
28
+ if [ -f "$collection_file" ]; then
29
+ local collection_name=$(basename "$collection_file" .json)
30
+ local html_report_path="$POSTMAN_DIR/reports/${collection_name}-${environment}-${timestamp}.html"
31
+ local json_report_path="$POSTMAN_DIR/reports/json/${collection_name}-${timestamp}.json"
32
+
33
+ echo ""
34
+ log_info "Running collection: $collection_name"
35
+
36
+ local exit_code=0
37
+ npx newman run "$collection_file" \
38
+ -e "$env_file" \
39
+ --export-environment "$env_file" \
40
+ -r cli,htmlextra,json \
41
+ --reporter-htmlextra-export "$html_report_path" \
42
+ --reporter-htmlextra-title "${collection_name} - ${environment}" \
43
+ --reporter-json-export "$json_report_path" \
44
+ --delay-request 500 \
45
+ --color on || exit_code=$?
46
+
47
+ if [ $exit_code -ne 0 ]; then
48
+ overall_exit_code=$exit_code
49
+ failed_count=$((failed_count + 1))
50
+ failed_collections+=("$collection_name")
51
+ log_error "Collection $collection_name failed"
52
+ else
53
+ passed_count=$((passed_count + 1))
54
+ log_success "Collection $collection_name passed"
55
+ fi
56
+
57
+ echo " HTML Report: $html_report_path"
58
+ echo " JSON Report: $json_report_path"
59
+ fi
60
+ done
61
+
62
+ echo ""
63
+ echo "========================================="
64
+ log_info "Test Results Summary"
65
+ echo "========================================="
66
+ echo " Passed: $passed_count"
67
+ echo " Failed: $failed_count"
68
+
69
+ if [ ${#failed_collections[@]} -gt 0 ]; then
70
+ echo ""
71
+ echo " Failed collections:"
72
+ for col in "${failed_collections[@]}"; do
73
+ echo " - $col"
74
+ done
75
+ fi
76
+
77
+ echo ""
78
+ log_info "Reports saved in: $POSTMAN_DIR/reports/"
79
+
80
+ # Generate consolidated report (links must match per-collection HTML from this run's timestamp)
81
+ echo ""
82
+ log_info "Generating consolidated report..."
83
+ CONSOLIDATED_GENERATOR="$POSTMAN_DIR/scripts/report-generators/generate-consolidated-report.sh"
84
+ if [ -f "$CONSOLIDATED_GENERATOR" ]; then
85
+ "$CONSOLIDATED_GENERATOR" "$environment" "$timestamp" "$POSTMAN_DIR/reports" "$passed_count" "$failed_count" "$overall_exit_code" || log_error "Failed to generate consolidated report"
86
+ consolidated_report="$POSTMAN_DIR/reports/consolidated-${environment}-${timestamp}.html"
87
+ consolidated_json="$POSTMAN_DIR/reports/consolidated-${environment}-${timestamp}.json"
88
+ if [ -f "$consolidated_report" ]; then
89
+ echo ""
90
+ log_success "📊 Consolidated HTML: $consolidated_report"
91
+ fi
92
+ if [ -f "$consolidated_json" ]; then
93
+ log_success "📄 Consolidated JSON: $consolidated_json"
94
+ fi
95
+ fi
96
+
97
+ if [ $overall_exit_code -eq 0 ]; then
98
+ log_success "All tests passed!"
99
+ return 0
100
+ else
101
+ log_error "Some tests failed (exit code: $overall_exit_code)"
102
+ exit $overall_exit_code
103
+ fi
104
+ }
@@ -0,0 +1,55 @@
1
+ #!/bin/bash
2
+ # Database setup functions
3
+
4
+ setup_database() {
5
+ local config_file="$1"
6
+
7
+ # Check Podman
8
+ if ! command -v podman &> /dev/null; then
9
+ error "Podman is not installed"
10
+ exit 1
11
+ fi
12
+
13
+ if ! podman info &> /dev/null; then
14
+ error "Podman machine is not running. Run 'podman machine start'"
15
+ exit 1
16
+ fi
17
+
18
+ log_info "Podman is available"
19
+
20
+ # Start MySQL container
21
+ local container_name=$(jq -r '.setup.database.container_name' "$config_file")
22
+ local mysql_port=$(jq -r '.setup.database.port' "$config_file")
23
+
24
+ log_info "Starting MySQL container: $container_name"
25
+ bash "$SCRIPT_DIR/database/start-mysql.sh"
26
+
27
+ # Wait for MySQL
28
+ log_info "Waiting for MySQL to be ready..."
29
+ bash "$SCRIPT_DIR/database/wait-for-mysql.sh"
30
+
31
+ log_success "Database ready"
32
+ }
33
+
34
+ run_migrations() {
35
+ local config_file="$1"
36
+
37
+ # Source the test environment to get stack_settings (required by run-migrations.js)
38
+ local env_file=$(jq -r '.setup.app.env_file // "postman/local.test.env"' "$config_file")
39
+ if [ -f "$PROJECT_ROOT/$env_file" ]; then
40
+ log_info "Loading environment from $env_file"
41
+ source "$PROJECT_ROOT/$env_file"
42
+ else
43
+ log_warning "Environment file not found: $env_file"
44
+ fi
45
+
46
+ log_info "Running migrations and seeding data..."
47
+ cd "$PROJECT_ROOT"
48
+ node "$SCRIPT_DIR/database/run-migrations.js" || {
49
+ local exit_code=$?
50
+ error "Migrations failed with exit code $exit_code"
51
+ exit $exit_code
52
+ }
53
+
54
+ log_success "Migrations complete"
55
+ }
@@ -0,0 +1,48 @@
1
+ #!/bin/bash
2
+ # Application startup functions
3
+
4
+ start_application() {
5
+ local config_file="$1"
6
+
7
+ cd "$PROJECT_ROOT"
8
+
9
+ # Load environment variables
10
+ local env_file=$(jq -r '.setup.app.env_file // "local.env"' "$config_file")
11
+ if [ -f "$env_file" ]; then
12
+ source "$env_file"
13
+ else
14
+ source "$PROJECT_ROOT/local.env"
15
+ fi
16
+
17
+ # Set environment variables
18
+ export NODE_ENV=$(jq -r '.setup.app.node_env' "$config_file")
19
+ export DB_HOST=$(jq -r '.setup.database.host' "$config_file")
20
+ export DB_PORT=$(jq -r '.setup.database.port' "$config_file")
21
+ export DB_USER=$(jq -r '.setup.database.user' "$config_file")
22
+ export DB_PASSWORD=$(jq -r '.setup.database.password' "$config_file")
23
+ # NOTE: Do NOT set DB_NAME - global and regional databases have different names
24
+ # They will use the values from local.env config instead
25
+
26
+ local app_port=$(jq -r '.setup.app.port' "$config_file")
27
+
28
+ log_info "Starting Node.js app on port $app_port"
29
+ node src/index.js $app_port &
30
+ APP_PID=$!
31
+
32
+ log_info "App started with PID: $APP_PID"
33
+
34
+ # Wait for app to be ready
35
+ log_info "Waiting for app health check..."
36
+ local max_wait=30
37
+ local elapsed=0
38
+ while [ $elapsed -lt $max_wait ]; do
39
+ if curl -s "http://localhost:$app_port/ping" > /dev/null 2>&1; then
40
+ log_success "App is ready!"
41
+ return 0
42
+ fi
43
+ sleep 1
44
+ elapsed=$((elapsed + 1))
45
+ done
46
+
47
+ log_warning "App health check timed out, proceeding anyway..."
48
+ }
@@ -0,0 +1,114 @@
1
+ #!/bin/bash
2
+ # Common utility functions
3
+
4
+ # Colors
5
+ RED='\033[0;31m'
6
+ GREEN='\033[0;32m'
7
+ YELLOW='\033[1;33m'
8
+ BLUE='\033[0;34m'
9
+ CYAN='\033[0;36m'
10
+ NC='\033[0m'
11
+
12
+ # Logging functions (all output to stderr to avoid capturing in command substitution)
13
+ log_header() {
14
+ echo -e "${BLUE}═══════════════════════════════════════════════════════════════${NC}" >&2
15
+ echo -e "${BLUE} $1${NC}" >&2
16
+ echo -e "${BLUE}═══════════════════════════════════════════════════════════════${NC}" >&2
17
+ }
18
+
19
+ log_step() {
20
+ local step_num="$1"
21
+ local message="$2"
22
+ echo -e "${CYAN}[Step $step_num] $message${NC}" >&2
23
+ }
24
+
25
+ log_info() {
26
+ echo -e "${GREEN}✓${NC} $1" >&2
27
+ }
28
+
29
+ log_warning() {
30
+ echo -e "${YELLOW}⚠${NC} $1" >&2
31
+ }
32
+
33
+ log_error() {
34
+ echo -e "${RED}✗${NC} $1" >&2
35
+ }
36
+
37
+ log_success() {
38
+ echo -e "${GREEN}✓ $1${NC}" >&2
39
+ }
40
+
41
+ error() {
42
+ log_error "$1"
43
+ }
44
+
45
+ # Cleanup function
46
+ cleanup() {
47
+ if [ "$CLEANUP_ENABLED" != "true" ]; then
48
+ log_warning "Cleanup skipped"
49
+ return
50
+ fi
51
+
52
+ echo "" >&2
53
+ log_warning "Cleaning up..."
54
+
55
+ # Stop app
56
+ if [ ! -z "${APP_PID:-}" ]; then
57
+ log_info "Stopping Node.js app (PID: $APP_PID)"
58
+ kill $APP_PID 2>/dev/null || true
59
+ wait $APP_PID 2>/dev/null || true
60
+ fi
61
+
62
+ # Kill any process on app port
63
+ local app_port=$(jq -r '.setup.app.port // 4013' "$CONFIG_FILE" 2>/dev/null || echo "4013")
64
+ lsof -ti:$app_port | xargs kill -9 2>/dev/null || true
65
+
66
+ # Cleanup Docker containers
67
+ if [ "$SETUP_DB" = "true" ]; then
68
+ bash "$SCRIPT_DIR/database/cleanup-mysql.sh" 2>/dev/null || true
69
+ fi
70
+
71
+ log_success "Cleanup complete"
72
+ }
73
+
74
+ # Update Postman environment file
75
+ update_postman_environment() {
76
+ local env="$1"
77
+ local api_url="$3"
78
+ local config_file="${4:-}"
79
+
80
+ local env_file="$POSTMAN_DIR/environments/${env}.postman_environment.json"
81
+
82
+ if [ ! -f "$env_file" ]; then
83
+ log_error "Environment file not found: $env_file"
84
+ return 1
85
+ fi
86
+
87
+ # Read account_id from config if available
88
+ local product_account_id=""
89
+ if [ -n "$config_file" ] && [ -f "$config_file" ]; then
90
+ product_account_id=$(jq -r '.auth.jwt.account_id // ""' "$config_file")
91
+ fi
92
+
93
+ # Update existing values (auth_token and agent_token are already set by generate-jwt.sh)
94
+ # Only update api_url and product_account_id here
95
+ jq --arg api_url "$api_url" \
96
+ --arg product_account_id "$product_account_id" \
97
+ '
98
+ # Update existing values
99
+ .values |= map(
100
+ if .key == "api_url" then .value = $api_url
101
+ elif .key == "product_account_id" and $product_account_id != "" then .value = $product_account_id
102
+ else . end
103
+ )
104
+ # Add product_account_id if it does not exist and we have a value
105
+ | if ($product_account_id != "") and ([.values[] | select(.key == "product_account_id")] | length == 0)
106
+ then .values += [{"key": "product_account_id", "value": $product_account_id, "type": "default", "enabled": true}]
107
+ else . end
108
+ ' \
109
+ "$env_file" > "$env_file.tmp"
110
+
111
+ mv "$env_file.tmp" "$env_file"
112
+
113
+ log_info "Environment file updated (product_account_id: ${product_account_id:-not set})"
114
+ }
@@ -0,0 +1,26 @@
1
+ #!/bin/bash
2
+ #
3
+ # Copy nyc and Stryker HTML reports into postman/reports/artifacts/ for Jenkins-safe links.
4
+ #
5
+ # Usage: stage-report-artifacts.sh <project_root> <reports_dir>
6
+
7
+ set -euo pipefail
8
+
9
+ PROJECT_ROOT="${1:?project root required}"
10
+ REPORTS_DIR="${2:?reports dir required}"
11
+ ARTIFACTS_DIR="$REPORTS_DIR/artifacts"
12
+
13
+ rm -rf "$ARTIFACTS_DIR"
14
+ mkdir -p "$ARTIFACTS_DIR/nyc" "$ARTIFACTS_DIR/stryker"
15
+
16
+ NYC_SRC="$PROJECT_ROOT/coverage/unit-tests"
17
+ if [ -f "$NYC_SRC/index.html" ]; then
18
+ cp -R "$NYC_SRC/." "$ARTIFACTS_DIR/nyc/"
19
+ echo "Staged nyc report -> artifacts/nyc/"
20
+ fi
21
+
22
+ STRYKER_SRC="$PROJECT_ROOT/coverage/mutation"
23
+ if [ -f "$STRYKER_SRC/index.html" ]; then
24
+ cp -R "$STRYKER_SRC/." "$ARTIFACTS_DIR/stryker/"
25
+ echo "Staged Stryker report -> artifacts/stryker/"
26
+ fi