@kanopi/wp-ai-indexer 1.0.0

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.
@@ -0,0 +1,41 @@
1
+ # wp-ai-indexer CircleCI Scripts
2
+
3
+ CI/CD scripts for the wp-ai-indexer Node.js package.
4
+
5
+ ## Scripts
6
+
7
+ ### test-package.sh
8
+ Runs npm tests with caching and parallelism support.
9
+
10
+ Usage:
11
+ ```bash
12
+ ./test-package.sh [--cache-key KEY] [--max-workers NUM] [--test-command CMD]
13
+ ```
14
+
15
+ ### security-audit-npm.sh
16
+ Runs npm security audits with configurable severity levels.
17
+
18
+ Usage:
19
+ ```bash
20
+ ./security-audit-npm.sh PACKAGE_PATH [--audit-level LEVEL] [--fail-on-vulnerabilities]
21
+ ```
22
+
23
+ ### setup-node.sh
24
+ Installs Node.js if not already present.
25
+
26
+ Usage:
27
+ ```bash
28
+ ./setup-node.sh [--version VERSION] [--skip-if-installed]
29
+ ```
30
+
31
+ ### install-dependencies.sh
32
+ Unified dependency installer for npm or Composer projects.
33
+
34
+ Usage:
35
+ ```bash
36
+ ./install-dependencies.sh PROJECT_PATH [--type npm|composer]
37
+ ```
38
+
39
+ ## Integration
40
+
41
+ These scripts are designed to work both in CircleCI and locally. See the main project's `.circleci/INTEGRATION.md` for complete integration examples.
@@ -0,0 +1,43 @@
1
+ version: 2.1
2
+
3
+ jobs:
4
+ test-package:
5
+ docker:
6
+ - image: cimg/node:22.9
7
+ steps:
8
+ - checkout
9
+ - restore_cache:
10
+ keys:
11
+ - package-deps-{{ checksum "package-lock.json" }}
12
+ - package-deps-{{ .Branch }}-
13
+ - package-deps-main-
14
+ - package-deps-
15
+ - run:
16
+ name: Run Package Tests
17
+ command: .circleci/test-package.sh .
18
+ - save_cache:
19
+ key: package-deps-{{ checksum "package-lock.json" }}
20
+ paths:
21
+ - node_modules
22
+ - ~/.npm
23
+ - ~/.cache
24
+ - store_test_results:
25
+ path: coverage
26
+ - store_artifacts:
27
+ path: coverage
28
+
29
+ security-audit:
30
+ docker:
31
+ - image: cimg/node:22.9
32
+ steps:
33
+ - checkout
34
+ - run:
35
+ name: Security Audit
36
+ command: .circleci/security-audit-npm.sh .
37
+
38
+ workflows:
39
+ version: 2
40
+ test:
41
+ jobs:
42
+ - test-package
43
+ - security-audit
@@ -0,0 +1,319 @@
1
+ #!/bin/bash
2
+ #
3
+ # Unified Dependency Installation Script
4
+ #
5
+ # Description:
6
+ # Installs dependencies for Node.js (npm) or PHP (Composer) projects with caching support.
7
+ #
8
+ # Usage:
9
+ # install-dependencies.sh [OPTIONS] PROJECT_PATH
10
+ #
11
+ # Arguments:
12
+ # PROJECT_PATH Path to the project directory
13
+ #
14
+ # Options:
15
+ # --type TYPE Dependency type: npm|composer (default: auto-detect)
16
+ # --cache-key KEY Cache key prefix (default: v1-deps)
17
+ # --skip-cache Skip cache restoration and saving
18
+ # --npm-command CMD npm install command: ci|install (default: ci)
19
+ # --composer-options OPTS Additional Composer install options (default: --prefer-dist --no-interaction)
20
+ # --acf-auth Enable ACF authentication for Composer (requires ACF_USERNAME, ACF_PROD_URL)
21
+ # --yoast-auth Enable Yoast authentication for Composer (requires YOAST_TOKEN)
22
+ # --dry-run Show what would be done without executing
23
+ # --help Show this help message
24
+ #
25
+ # Environment Variables:
26
+ # ACF_USERNAME Advanced Custom Fields username (for Composer with --acf-auth)
27
+ # ACF_PROD_URL Advanced Custom Fields production URL (for Composer with --acf-auth)
28
+ # YOAST_TOKEN Yoast token (for Composer with --yoast-auth)
29
+ # CIRCLECI Set automatically in CircleCI environment
30
+ #
31
+ # Exit Codes:
32
+ # 0 - Dependencies installed successfully
33
+ # 1 - Installation failed
34
+ # 2 - Invalid arguments or missing files
35
+ #
36
+
37
+ set -eo pipefail
38
+
39
+ # Colors for output
40
+ RED='\033[0;31m'
41
+ GREEN='\033[0;32m'
42
+ YELLOW='\033[1;33m'
43
+ BLUE='\033[0;34m'
44
+ NC='\033[0m' # No Color
45
+
46
+ # Default values
47
+ PROJECT_PATH=""
48
+ TYPE="auto"
49
+ CACHE_KEY="v1-deps"
50
+ SKIP_CACHE="false"
51
+ NPM_COMMAND="ci"
52
+ COMPOSER_OPTIONS="--prefer-dist --no-interaction"
53
+ ACF_AUTH="false"
54
+ YOAST_AUTH="false"
55
+ DRY_RUN="false"
56
+
57
+ # Parse arguments
58
+ while [[ $# -gt 0 ]]; do
59
+ case $1 in
60
+ --type)
61
+ TYPE="$2"
62
+ shift 2
63
+ ;;
64
+ --cache-key)
65
+ CACHE_KEY="$2"
66
+ shift 2
67
+ ;;
68
+ --skip-cache)
69
+ SKIP_CACHE="true"
70
+ shift
71
+ ;;
72
+ --npm-command)
73
+ NPM_COMMAND="$2"
74
+ shift 2
75
+ ;;
76
+ --composer-options)
77
+ COMPOSER_OPTIONS="$2"
78
+ shift 2
79
+ ;;
80
+ --acf-auth)
81
+ ACF_AUTH="true"
82
+ shift
83
+ ;;
84
+ --yoast-auth)
85
+ YOAST_AUTH="true"
86
+ shift
87
+ ;;
88
+ --dry-run)
89
+ DRY_RUN="true"
90
+ shift
91
+ ;;
92
+ --help)
93
+ grep '^#' "$0" | grep -v '#!/bin/bash' | sed 's/^# //;s/^#//'
94
+ exit 0
95
+ ;;
96
+ -*)
97
+ echo -e "${RED}Error: Unknown option $1${NC}"
98
+ echo "Use --help for usage information"
99
+ exit 2
100
+ ;;
101
+ *)
102
+ PROJECT_PATH="$1"
103
+ shift
104
+ ;;
105
+ esac
106
+ done
107
+
108
+ # Helper functions
109
+ log_header() {
110
+ echo -e "\n${BLUE}========================================${NC}"
111
+ echo -e "${BLUE}$1${NC}"
112
+ echo -e "${BLUE}========================================${NC}"
113
+ }
114
+
115
+ log_success() {
116
+ echo -e "${GREEN}✓${NC} $1"
117
+ }
118
+
119
+ log_error() {
120
+ echo -e "${RED}✗${NC} $1"
121
+ }
122
+
123
+ log_warning() {
124
+ echo -e "${YELLOW}⚠${NC} $1"
125
+ }
126
+
127
+ log_info() {
128
+ echo -e "${BLUE}ℹ${NC} $1"
129
+ }
130
+
131
+ # Validate required parameters
132
+ if [[ -z "$PROJECT_PATH" ]]; then
133
+ log_error "Project path is required"
134
+ echo "Usage: $0 [OPTIONS] PROJECT_PATH"
135
+ exit 2
136
+ fi
137
+
138
+ if [[ ! -d "$PROJECT_PATH" ]]; then
139
+ log_error "Project path does not exist: $PROJECT_PATH"
140
+ exit 2
141
+ fi
142
+
143
+ # Auto-detect dependency type if not specified
144
+ if [[ "$TYPE" == "auto" ]]; then
145
+ if [[ -f "$PROJECT_PATH/package.json" ]]; then
146
+ TYPE="npm"
147
+ log_info "Auto-detected: npm (found package.json)"
148
+ elif [[ -f "$PROJECT_PATH/composer.json" ]]; then
149
+ TYPE="composer"
150
+ log_info "Auto-detected: Composer (found composer.json)"
151
+ else
152
+ log_error "Could not auto-detect dependency type (no package.json or composer.json found)"
153
+ exit 2
154
+ fi
155
+ fi
156
+
157
+ # Validate type
158
+ if [[ ! "$TYPE" =~ ^(npm|composer)$ ]]; then
159
+ log_error "Invalid dependency type: $TYPE"
160
+ echo "Valid types: npm, composer"
161
+ exit 2
162
+ fi
163
+
164
+ log_header "Dependency Installation"
165
+ log_info "Project: $PROJECT_PATH"
166
+ log_info "Type: $TYPE"
167
+ log_info "Dry run: $DRY_RUN"
168
+
169
+ # Function to install npm dependencies
170
+ install_npm_dependencies() {
171
+ log_header "Installing npm Dependencies"
172
+
173
+ # Validate npm is available
174
+ if ! command -v npm &> /dev/null; then
175
+ log_error "npm is not installed"
176
+ exit 1
177
+ fi
178
+
179
+ # Determine lock file for cache key
180
+ LOCK_FILE=""
181
+ if [[ -f "$PROJECT_PATH/package-lock.json" ]]; then
182
+ LOCK_FILE="package-lock.json"
183
+ elif [[ -f "$PROJECT_PATH/npm-shrinkwrap.json" ]]; then
184
+ LOCK_FILE="npm-shrinkwrap.json"
185
+ fi
186
+
187
+ # Restore cache (if in CircleCI)
188
+ if [[ "$SKIP_CACHE" == "false" ]] && [[ -n "${CIRCLECI:-}" ]]; then
189
+ log_info "Cache restoration handled by CircleCI"
190
+ if [[ -n "$LOCK_FILE" ]]; then
191
+ log_info "Cache key: ${CACHE_KEY}-{{ checksum \"$PROJECT_PATH/$LOCK_FILE\" }}"
192
+ fi
193
+ fi
194
+
195
+ if [[ "$DRY_RUN" == "false" ]]; then
196
+ cd "$PROJECT_PATH"
197
+
198
+ # Choose install command
199
+ if [[ "$NPM_COMMAND" == "ci" ]]; then
200
+ if [[ -f "package-lock.json" ]] || [[ -f "npm-shrinkwrap.json" ]]; then
201
+ log_info "Running npm ci..."
202
+ npm ci
203
+ else
204
+ log_warning "No lock file found, falling back to npm install..."
205
+ npm install
206
+ fi
207
+ else
208
+ log_info "Running npm install..."
209
+ npm install
210
+ fi
211
+
212
+ log_success "npm dependencies installed"
213
+ cd - > /dev/null
214
+ else
215
+ log_info "[DRY RUN] Would run: npm $NPM_COMMAND"
216
+ fi
217
+
218
+ # Save cache (if in CircleCI)
219
+ if [[ "$SKIP_CACHE" == "false" ]] && [[ -n "${CIRCLECI:-}" ]]; then
220
+ log_info "Cache saving handled by CircleCI"
221
+ log_info "Cache paths:"
222
+ log_info " - $PROJECT_PATH/node_modules"
223
+ log_info " - ~/.npm"
224
+ log_info " - ~/.cache"
225
+ fi
226
+ }
227
+
228
+ # Function to install Composer dependencies
229
+ install_composer_dependencies() {
230
+ log_header "Installing Composer Dependencies"
231
+
232
+ # Validate composer is available
233
+ if ! command -v composer &> /dev/null; then
234
+ log_error "Composer is not installed"
235
+ exit 1
236
+ fi
237
+
238
+ # Restore cache (if in CircleCI)
239
+ if [[ "$SKIP_CACHE" == "false" ]] && [[ -n "${CIRCLECI:-}" ]]; then
240
+ log_info "Cache restoration handled by CircleCI"
241
+ if [[ -f "$PROJECT_PATH/composer.lock" ]]; then
242
+ log_info "Cache key: ${CACHE_KEY}-{{ checksum \"$PROJECT_PATH/composer.lock\" }}"
243
+ fi
244
+ fi
245
+
246
+ # Configure authentication
247
+ if [[ "$ACF_AUTH" == "true" ]] || [[ "$YOAST_AUTH" == "true" ]]; then
248
+ log_header "Configuring Composer Authentication"
249
+
250
+ if [[ "$ACF_AUTH" == "true" ]]; then
251
+ if [[ -z "${ACF_USERNAME:-}" ]] || [[ -z "${ACF_PROD_URL:-}" ]]; then
252
+ log_error "ACF authentication requested but ACF_USERNAME or ACF_PROD_URL not set"
253
+ exit 2
254
+ fi
255
+
256
+ if [[ "$DRY_RUN" == "false" ]]; then
257
+ log_info "Configuring ACF authentication..."
258
+ composer config -g http-basic.connect.advancedcustomfields.com "$ACF_USERNAME" "$ACF_PROD_URL"
259
+ log_success "ACF authentication configured"
260
+ else
261
+ log_info "[DRY RUN] Would configure ACF authentication"
262
+ fi
263
+ fi
264
+
265
+ if [[ "$YOAST_AUTH" == "true" ]]; then
266
+ if [[ -z "${YOAST_TOKEN:-}" ]]; then
267
+ log_error "Yoast authentication requested but YOAST_TOKEN not set"
268
+ exit 2
269
+ fi
270
+
271
+ if [[ "$DRY_RUN" == "false" ]]; then
272
+ log_info "Configuring Yoast authentication..."
273
+ composer config -g http-basic.my.yoast.com token "$YOAST_TOKEN"
274
+ log_success "Yoast authentication configured"
275
+ else
276
+ log_info "[DRY RUN] Would configure Yoast authentication"
277
+ fi
278
+ fi
279
+ fi
280
+
281
+ if [[ "$DRY_RUN" == "false" ]]; then
282
+ cd "$PROJECT_PATH"
283
+
284
+ log_info "Running composer install $COMPOSER_OPTIONS..."
285
+ if composer install $COMPOSER_OPTIONS; then
286
+ log_success "Composer dependencies installed"
287
+ else
288
+ log_error "Composer install failed"
289
+ exit 1
290
+ fi
291
+
292
+ cd - > /dev/null
293
+ else
294
+ log_info "[DRY RUN] Would run: composer install $COMPOSER_OPTIONS"
295
+ fi
296
+
297
+ # Save cache (if in CircleCI)
298
+ if [[ "$SKIP_CACHE" == "false" ]] && [[ -n "${CIRCLECI:-}" ]]; then
299
+ log_info "Cache saving handled by CircleCI"
300
+ log_info "Cache paths:"
301
+ log_info " - $PROJECT_PATH/vendor"
302
+ log_info " - ~/.composer/cache"
303
+ log_info " - ~/.cache/composer"
304
+ fi
305
+ }
306
+
307
+ # Install dependencies based on type
308
+ case "$TYPE" in
309
+ npm)
310
+ install_npm_dependencies
311
+ ;;
312
+ composer)
313
+ install_composer_dependencies
314
+ ;;
315
+ esac
316
+
317
+ log_header "Installation Complete"
318
+ log_success "Dependencies installed successfully"
319
+ exit 0
@@ -0,0 +1,264 @@
1
+ #!/bin/bash
2
+ #
3
+ # npm Security Audit Script
4
+ #
5
+ # Description:
6
+ # Runs npm audit on Node.js packages to detect security vulnerabilities.
7
+ #
8
+ # Usage:
9
+ # security-audit-npm.sh [OPTIONS] PACKAGE_PATH
10
+ #
11
+ # Arguments:
12
+ # PACKAGE_PATH Path to the package (e.g., packages/wp-ai-indexer)
13
+ #
14
+ # Options:
15
+ # --audit-level LEVEL Audit level: info|low|moderate|high|critical (default: high)
16
+ # --cache-key KEY Custom cache key prefix (default: v1-indexer-deps)
17
+ # --skip-cache Skip cache restoration
18
+ # --fail-on-vulnerabilities Fail (exit 1) if vulnerabilities are found (default: false)
19
+ # --output-file FILE Custom output file path (default: {package}/npm-audit-report.json)
20
+ # --store-artifacts Store audit report as artifact (default: true in CI)
21
+ # --dry-run Show what would be done without executing
22
+ # --help Show this help message
23
+ #
24
+ # Exit Codes:
25
+ # 0 - No vulnerabilities found or vulnerabilities ignored
26
+ # 1 - Vulnerabilities found (when --fail-on-vulnerabilities is set)
27
+ # 2 - Invalid arguments or execution error
28
+ #
29
+
30
+ set -eo pipefail
31
+
32
+ # Colors for output
33
+ RED='\033[0;31m'
34
+ GREEN='\033[0;32m'
35
+ YELLOW='\033[1;33m'
36
+ BLUE='\033[0;34m'
37
+ NC='\033[0m' # No Color
38
+
39
+ # Default values
40
+ PACKAGE_PATH=""
41
+ AUDIT_LEVEL="high"
42
+ CACHE_KEY="v1-indexer-deps"
43
+ SKIP_CACHE="false"
44
+ FAIL_ON_VULNERABILITIES="false"
45
+ OUTPUT_FILE=""
46
+ STORE_ARTIFACTS="${CIRCLECI:-false}"
47
+ DRY_RUN="false"
48
+
49
+ # Parse arguments
50
+ while [[ $# -gt 0 ]]; do
51
+ case $1 in
52
+ --audit-level)
53
+ AUDIT_LEVEL="$2"
54
+ shift 2
55
+ ;;
56
+ --cache-key)
57
+ CACHE_KEY="$2"
58
+ shift 2
59
+ ;;
60
+ --skip-cache)
61
+ SKIP_CACHE="true"
62
+ shift
63
+ ;;
64
+ --fail-on-vulnerabilities)
65
+ FAIL_ON_VULNERABILITIES="true"
66
+ shift
67
+ ;;
68
+ --output-file)
69
+ OUTPUT_FILE="$2"
70
+ shift 2
71
+ ;;
72
+ --store-artifacts)
73
+ STORE_ARTIFACTS="true"
74
+ shift
75
+ ;;
76
+ --dry-run)
77
+ DRY_RUN="true"
78
+ shift
79
+ ;;
80
+ --help)
81
+ grep '^#' "$0" | grep -v '#!/bin/bash' | sed 's/^# //;s/^#//'
82
+ exit 0
83
+ ;;
84
+ -*)
85
+ echo -e "${RED}Error: Unknown option $1${NC}"
86
+ echo "Use --help for usage information"
87
+ exit 2
88
+ ;;
89
+ *)
90
+ PACKAGE_PATH="$1"
91
+ shift
92
+ ;;
93
+ esac
94
+ done
95
+
96
+ # Helper functions
97
+ log_header() {
98
+ echo -e "\n${BLUE}========================================${NC}"
99
+ echo -e "${BLUE}$1${NC}"
100
+ echo -e "${BLUE}========================================${NC}"
101
+ }
102
+
103
+ log_success() {
104
+ echo -e "${GREEN}✓${NC} $1"
105
+ }
106
+
107
+ log_error() {
108
+ echo -e "${RED}✗${NC} $1"
109
+ }
110
+
111
+ log_warning() {
112
+ echo -e "${YELLOW}⚠${NC} $1"
113
+ }
114
+
115
+ log_info() {
116
+ echo -e "${BLUE}ℹ${NC} $1"
117
+ }
118
+
119
+ # Validate required parameters
120
+ if [[ -z "$PACKAGE_PATH" ]]; then
121
+ log_error "Package path is required"
122
+ echo "Usage: $0 [OPTIONS] PACKAGE_PATH"
123
+ exit 2
124
+ fi
125
+
126
+ if [[ ! -d "$PACKAGE_PATH" ]]; then
127
+ log_error "Package path does not exist: $PACKAGE_PATH"
128
+ exit 2
129
+ fi
130
+
131
+ if [[ ! -f "$PACKAGE_PATH/package.json" ]]; then
132
+ log_error "No package.json found in $PACKAGE_PATH"
133
+ exit 2
134
+ fi
135
+
136
+ # Validate audit level
137
+ if [[ ! "$AUDIT_LEVEL" =~ ^(info|low|moderate|high|critical)$ ]]; then
138
+ log_error "Invalid audit level: $AUDIT_LEVEL"
139
+ echo "Valid levels: info, low, moderate, high, critical"
140
+ exit 2
141
+ fi
142
+
143
+ # Set default output file if not specified
144
+ if [[ -z "$OUTPUT_FILE" ]]; then
145
+ OUTPUT_FILE="$PACKAGE_PATH/npm-audit-report.json"
146
+ fi
147
+
148
+ log_header "npm Security Audit"
149
+ log_info "Package: $PACKAGE_PATH"
150
+ log_info "Audit level: $AUDIT_LEVEL"
151
+ log_info "Output file: $OUTPUT_FILE"
152
+ log_info "Dry run: $DRY_RUN"
153
+
154
+ # Restore cache (if in CircleCI and cache enabled)
155
+ if [[ "$SKIP_CACHE" == "false" ]] && [[ -n "${CIRCLECI:-}" ]]; then
156
+ log_header "Restoring Cache"
157
+ if [[ "$DRY_RUN" == "false" ]]; then
158
+ log_info "Cache restoration handled by CircleCI"
159
+ log_info "Cache key: ${CACHE_KEY}-{{ checksum \"$PACKAGE_PATH/package-lock.json\" }}"
160
+ else
161
+ log_info "[DRY RUN] Would restore cache with key: $CACHE_KEY"
162
+ fi
163
+ fi
164
+
165
+ # Install dependencies
166
+ log_header "Installing Dependencies"
167
+ if [[ "$DRY_RUN" == "false" ]]; then
168
+ cd "$PACKAGE_PATH"
169
+
170
+ if [[ -f "package-lock.json" ]]; then
171
+ log_info "Running npm ci..."
172
+ npm ci
173
+ log_success "Dependencies installed"
174
+ else
175
+ log_info "No package-lock.json found, running npm install..."
176
+ npm install
177
+ log_success "Dependencies installed"
178
+ fi
179
+
180
+ cd - > /dev/null
181
+ else
182
+ log_info "[DRY RUN] Would run: cd $PACKAGE_PATH && npm ci"
183
+ fi
184
+
185
+ # Run npm audit
186
+ log_header "Running npm audit"
187
+ AUDIT_RESULT=0
188
+
189
+ if [[ "$DRY_RUN" == "false" ]]; then
190
+ cd "$PACKAGE_PATH"
191
+
192
+ # Run audit with JSON output (continue on failure)
193
+ log_info "Generating JSON audit report..."
194
+ if npm audit --audit-level="$AUDIT_LEVEL" --json > "$(basename "$OUTPUT_FILE")" 2>&1; then
195
+ log_success "No vulnerabilities found at $AUDIT_LEVEL level or above"
196
+ AUDIT_RESULT=0
197
+ else
198
+ VULNERABILITIES_EXIT_CODE=$?
199
+ log_warning "Vulnerabilities detected"
200
+ AUDIT_RESULT=1
201
+ fi
202
+
203
+ # Run audit again for human-readable output
204
+ echo ""
205
+ log_info "Running audit for display output..."
206
+ if npm audit --audit-level="$AUDIT_LEVEL"; then
207
+ log_success "Audit passed"
208
+ else
209
+ # Parse JSON report to show summary
210
+ if [[ -f "$(basename "$OUTPUT_FILE")" ]]; then
211
+ if command -v jq &> /dev/null; then
212
+ echo ""
213
+ log_info "Vulnerability summary:"
214
+ jq -r '.metadata | "Total: \(.vulnerabilities.total)\nInfo: \(.vulnerabilities.info)\nLow: \(.vulnerabilities.low)\nModerate: \(.vulnerabilities.moderate)\nHigh: \(.vulnerabilities.high)\nCritical: \(.vulnerabilities.critical)"' "$(basename "$OUTPUT_FILE")"
215
+ fi
216
+ fi
217
+ fi
218
+
219
+ # Move output file to final location if different
220
+ if [[ "$(basename "$OUTPUT_FILE")" != "$OUTPUT_FILE" ]]; then
221
+ mkdir -p "$(dirname "$OUTPUT_FILE")"
222
+ mv "$(basename "$OUTPUT_FILE")" "$OUTPUT_FILE"
223
+ fi
224
+
225
+ cd - > /dev/null
226
+
227
+ if [[ -f "$OUTPUT_FILE" ]]; then
228
+ log_success "Audit report saved to: $OUTPUT_FILE"
229
+ fi
230
+ else
231
+ log_info "[DRY RUN] Would run: npm audit --audit-level=$AUDIT_LEVEL"
232
+ AUDIT_RESULT=0
233
+ fi
234
+
235
+ # Store artifacts (if in CircleCI)
236
+ if [[ "$STORE_ARTIFACTS" == "true" ]] && [[ -n "${CIRCLECI:-}" ]]; then
237
+ log_header "Storing Artifacts"
238
+ if [[ "$DRY_RUN" == "false" ]]; then
239
+ if [[ -f "$OUTPUT_FILE" ]]; then
240
+ log_info "Artifact storage handled by CircleCI"
241
+ log_info " - store_artifacts: $OUTPUT_FILE"
242
+ else
243
+ log_warning "Output file not found: $OUTPUT_FILE"
244
+ fi
245
+ else
246
+ log_info "[DRY RUN] Would store artifact: $OUTPUT_FILE"
247
+ fi
248
+ fi
249
+
250
+ log_header "Security Audit Complete"
251
+
252
+ if [[ $AUDIT_RESULT -eq 0 ]]; then
253
+ log_success "No vulnerabilities found at $AUDIT_LEVEL level or above"
254
+ exit 0
255
+ else
256
+ if [[ "$FAIL_ON_VULNERABILITIES" == "true" ]]; then
257
+ log_error "Vulnerabilities found - failing build"
258
+ exit 1
259
+ else
260
+ log_warning "Vulnerabilities found but not failing build"
261
+ log_info "Use --fail-on-vulnerabilities to fail on vulnerabilities"
262
+ exit 0
263
+ fi
264
+ fi