-
Notifications
You must be signed in to change notification settings - Fork 2
Expand file tree
/
Copy pathMakefile
More file actions
609 lines (538 loc) · 23.1 KB
/
Makefile
File metadata and controls
609 lines (538 loc) · 23.1 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
# Build variables
BINARY_NAME=oastools
BUILD_DIR=bin
MAIN_PATH=./cmd/oastools
BENCH_DIR=benchmarks
BENCH_TIME=5s
# Allow go commands to automatically download the toolchain version declared in
# go.mod when the local Go binary is older. This is the portable alternative to
# pinning GOROOT/PATH to a specific SDK path.
QUALITY_TARGETS := tidy fmt test test-quick test-race test-full test-coverage test-corpus test-corpus-short integration-test integration-test-debug count-tests count-benchmarks lint vet check
$(QUALITY_TARGETS): export GOTOOLCHAIN = auto
# Default target
all: build
# =============================================================================
# Build Targets
# =============================================================================
## build: Build the binary
.PHONY: build
build:
@echo "Building $(BINARY_NAME)..."
@mkdir -p $(BUILD_DIR)
go build -o $(BUILD_DIR)/$(BINARY_NAME) $(MAIN_PATH)
## install: Install the binary
.PHONY: install
install:
@echo "Installing $(BINARY_NAME)..."
go install $(MAIN_PATH)
## run: Run the CLI with arguments (usage: make run ARGS="generate -server ...")
.PHONY: run
run:
@go run $(MAIN_PATH) $(ARGS)
## clean: Clean build artifacts and benchmark outputs
.PHONY: clean
clean:
@echo "Cleaning..."
@rm -rf $(BUILD_DIR)
@rm -rf dist/
@rm -f coverage.txt coverage.html
@rm -f benchmark-*.txt
@rm -rf site/
@rm -rf .tmp/
# =============================================================================
# Test Targets
# =============================================================================
## test: Run tests with coverage (parallel execution for speed)
## Note: Fuzz tests are skipped in regular test runs. Use 'make test-fuzz-parse' to run them separately.
.PHONY: test
test:
@echo "Running tests..."
ifeq ("$(shell command -v gotestsum)", "")
go test -coverprofile=coverage.txt -covermode=atomic -timeout=5m -skip='^Fuzz' ./...
else
gotestsum --format testname -- -coverprofile=coverage.txt -covermode=atomic -timeout=5m -failfast -skip='^Fuzz' ./...
endif
## test-quick: Run tests quickly for rapid iteration (no coverage, short mode)
.PHONY: test-quick
test-quick:
@echo "Running quick tests..."
go test -short -skip='^Fuzz' ./...
## test-race: Run tests with race detector (slower, thorough race detection)
.PHONY: test-race
test-race:
@echo "Running tests with race detector (this may take several minutes)..."
ifeq ("$(shell command -v gotestsum)", "")
GORACE="halt_on_error=1" GOMAXPROCS=1 go test -v -race -short -timeout=10m -p=1 -parallel=1 -skip='^Fuzz' ./...
else
GORACE="halt_on_error=1" GOMAXPROCS=1 gotestsum --format testname -- -v -race -short -timeout=10m -failfast -p=1 -parallel=1 -skip='^Fuzz' ./...
endif
## test-full: Run comprehensive tests including race detection and all test modes
.PHONY: test-full
test-full:
@echo "Running comprehensive tests (this may take several minutes)..."
@echo ""
@echo "Phase 1: Unit tests with race detection..."
GORACE="halt_on_error=1" go test -race -short -timeout=10m -skip='^Fuzz' ./...
@echo ""
@echo "Phase 2: Full test suite with coverage..."
go test -v -coverprofile=coverage.txt -covermode=atomic -timeout=10m -skip='^Fuzz' ./...
@echo ""
@echo "Comprehensive tests complete."
## test-coverage: Run tests with coverage report
.PHONY: test-coverage
test-coverage: test
@echo "Generating coverage report..."
go tool cover -html=coverage.txt -o coverage.html
@echo "Coverage report generated at coverage.html"
## integration-test: Run integration tests (scenario-driven, uses build tags)
.PHONY: integration-test
integration-test:
@echo "Running integration tests..."
go test -tags=integration ./integration/... -v -count=1 -timeout=10m
## integration-test-debug: Run integration tests with debug output
.PHONY: integration-test-debug
integration-test-debug:
INTEGRATION_DEBUG=1 go test -tags=integration ./integration/... -v -count=1 -timeout=10m
## test-fuzz-parse: Run fuzz tests for parser (default: 1m30s, override with FUZZ_TIME, optionally set FUZZ_LOG=1 to save output)
.PHONY: test-fuzz-parse
test-fuzz-parse:
@echo "Running fuzz tests for ParseBytes..."
@FUZZ_TIME=$${FUZZ_TIME:-1m30s}; \
FUZZ_LOG=$${FUZZ_LOG:-0}; \
echo "Fuzz time: $${FUZZ_TIME}"; \
if [ "$$FUZZ_LOG" = "1" ]; then \
TIMESTAMP=$$(date +%Y%m%d-%H%M%S); \
LOG_FILE="fuzz-parse-$${TIMESTAMP}.log"; \
echo "Saving output to: $${LOG_FILE}"; \
go test -v ./parser -run=^$$ -fuzz=FuzzParseBytes -fuzztime=$${FUZZ_TIME} -fuzzminimizetime=30s -parallel=4 2>&1 | tee "$${LOG_FILE}"; \
echo ""; \
echo "Fuzz log saved to: $${LOG_FILE}"; \
else \
go test -v ./parser -run=^$$ -fuzz=FuzzParseBytes -fuzztime=$${FUZZ_TIME} -fuzzminimizetime=30s -parallel=4; \
fi
@echo ""
@echo "Fuzz corpus stored in: parser/testdata/fuzz/FuzzParseBytes"
@echo ""
@echo "To re-run a specific failing input: go test ./parser -run=FuzzParseBytes/<hash>"
@echo "To save fuzz output to a log file: FUZZ_LOG=1 make test-fuzz-parse"
## count-tests: Count all test runs including subtests
.PHONY: count-tests
count-tests:
@echo "Counting test runs (includes table-driven subtests)..."
@go test -v ./... 2>&1 | grep -c "=== RUN" || echo "0"
## count-benchmarks: Count all benchmark runs including sub-benchmarks
.PHONY: count-benchmarks
count-benchmarks:
@echo "Counting benchmark runs (includes parameterized cases)..."
@go test -bench=. -benchtime=1x ./... 2>&1 | grep -c "^Benchmark" || echo "0"
# =============================================================================
# Code Quality Targets
# =============================================================================
## lint: Run linter
.PHONY: lint
lint:
@echo "Running linter..."
@if command -v golangci-lint >/dev/null 2>&1; then \
golangci-lint run ./...; \
else \
echo "golangci-lint not installed. Install it from https://golangci-lint.run/usage/install/"; \
exit 1; \
fi
## fmt: Format code
.PHONY: fmt
fmt:
@echo "Formatting code..."
go fmt ./...
## vet: Run go vet
.PHONY: vet
vet:
@echo "Running go vet..."
go vet ./...
## lint-md: Lint markdown files
.PHONY: lint-md
lint-md:
@echo "Linting markdown..."
@if command -v npx >/dev/null 2>&1; then \
npx markdownlint-cli2; \
else \
echo "npx not found (Node.js required). Skipping markdown lint."; \
fi
## check: Run tidy, fmt, lint, lint-md, test, and git status
.PHONY: check
check: tidy fmt lint lint-md test
@echo "Running git status..."
@git status
# =============================================================================
# Dependency Targets
# =============================================================================
## deps: Download dependencies
.PHONY: deps
deps:
@echo "Downloading dependencies..."
go mod download
go mod tidy
## tidy: Tidy go modules
.PHONY: tidy
tidy:
@echo "Tidying go modules..."
go mod tidy
# =============================================================================
# Benchmark Targets
# =============================================================================
## bench: Run all benchmarks
.PHONY: bench
bench:
@echo "Running all benchmarks ($(BENCH_TIME) per benchmark)..."
@go test -bench=. -benchmem -benchtime=$(BENCH_TIME) -timeout=15m ./parser ./validator ./fixer ./httpvalidator ./converter ./joiner ./differ ./generator ./builder
## bench-parser: Run parser benchmarks only
.PHONY: bench-parser
bench-parser:
@echo "Running parser benchmarks..."
@go test -bench=. -benchmem -benchtime=$(BENCH_TIME) -timeout=15m ./parser
## bench-validator: Run validator benchmarks only
.PHONY: bench-validator
bench-validator:
@echo "Running validator benchmarks..."
@go test -bench=. -benchmem -benchtime=$(BENCH_TIME) -timeout=15m ./validator
## bench-fixer: Run fixer benchmarks only
.PHONY: bench-fixer
bench-fixer:
@echo "Running fixer benchmarks..."
@go test -bench=. -benchmem -benchtime=$(BENCH_TIME) -timeout=15m ./fixer
## bench-httpvalidator: Run httpvalidator benchmarks only
.PHONY: bench-httpvalidator
bench-httpvalidator:
@echo "Running httpvalidator benchmarks..."
@go test -bench=. -benchmem -benchtime=$(BENCH_TIME) -timeout=15m ./httpvalidator
## bench-converter: Run converter benchmarks only
.PHONY: bench-converter
bench-converter:
@echo "Running converter benchmarks..."
@go test -bench=. -benchmem -benchtime=$(BENCH_TIME) -timeout=15m ./converter
## bench-joiner: Run joiner benchmarks only
.PHONY: bench-joiner
bench-joiner:
@echo "Running joiner benchmarks..."
@go test -bench=. -benchmem -benchtime=$(BENCH_TIME) -timeout=15m ./joiner
## bench-differ: Run differ benchmarks only
.PHONY: bench-differ
bench-differ:
@echo "Running differ benchmarks..."
@go test -bench=. -benchmem -benchtime=$(BENCH_TIME) -timeout=15m ./differ
## bench-generator: Run generator benchmarks only
.PHONY: bench-generator
bench-generator:
@echo "Running generator benchmarks..."
@go test -bench=. -benchmem -benchtime=$(BENCH_TIME) -timeout=15m ./generator
## bench-builder: Run builder benchmarks only
.PHONY: bench-builder
bench-builder:
@echo "Running builder benchmarks..."
@go test -bench=. -benchmem -benchtime=$(BENCH_TIME) -timeout=15m ./builder
## bench-overlay: Run overlay and jsonpath benchmarks only
.PHONY: bench-overlay
bench-overlay:
@echo "Running overlay benchmarks..."
@go test -bench=. -benchmem -benchtime=$(BENCH_TIME) -timeout=15m ./overlay ./internal/jsonpath
## bench-save: Run all benchmarks and save to timestamped file
.PHONY: bench-save
bench-save:
@echo "Running benchmarks and saving results..."
@TIMESTAMP=$$(date +%Y%m%d-%H%M%S); \
OUTPUT_FILE="benchmark-$${TIMESTAMP}.txt"; \
go test -bench=. -benchmem -benchtime=$(BENCH_TIME) -timeout=15m ./parser ./validator ./fixer ./httpvalidator ./converter ./joiner ./differ ./generator ./builder ./overlay ./internal/jsonpath 2>&1 | tee "$${OUTPUT_FILE}"; \
echo ""; \
echo "Benchmark results saved to: $${OUTPUT_FILE}"
## bench-baseline: Run benchmarks and update baseline file
.PHONY: bench-baseline
bench-baseline:
@echo "Running benchmarks and updating baseline..."
@go test -bench=. -benchmem -benchtime=$(BENCH_TIME) -timeout=15m ./parser ./validator ./fixer ./httpvalidator ./converter ./joiner ./differ ./generator ./builder ./overlay ./internal/jsonpath 2>&1 | tee benchmark-baseline.txt
@echo ""
@echo "Baseline updated: benchmark-baseline.txt"
## bench-release: Run benchmarks for upcoming release (usage: make bench-release VERSION=v1.19.1)
## Note: Corpus benchmarks require -tags=corpus and are excluded by default.
## Use 'make bench-corpus' to run corpus benchmarks separately.
.PHONY: bench-release
bench-release:
@if [ -z "$(VERSION)" ]; then \
echo "Error: VERSION required"; \
echo "Usage: make bench-release VERSION=v1.19.1"; \
exit 1; \
fi
@echo "Running benchmarks for $(VERSION)..."
@go test -bench=. -benchmem -benchtime=$(BENCH_TIME) -timeout=15m ./parser ./validator ./fixer ./converter ./joiner ./differ ./generator ./builder ./overlay ./httpvalidator 2>&1 | tee "$(BENCH_DIR)/benchmark-$(VERSION).txt"
@echo ""
@echo "Benchmark saved to: $(BENCH_DIR)/benchmark-$(VERSION).txt"
@echo ""
@./scripts/compare-with-previous.sh "$(VERSION)" || true
## bench-quick: Run I/O-isolated benchmarks only (~2 min)
## Use for quick regression checks during development. Matches *Core, *Parsed, *Bytes benchmarks.
.PHONY: bench-quick
bench-quick:
@echo "Running quick benchmarks (I/O-isolated only, 2s per benchmark)..."
@go test -bench='Core|Parsed|Bytes' -benchmem -benchtime=2s -timeout=10m ./parser ./validator ./fixer ./converter ./joiner ./differ ./generator ./builder
## bench-fast: Run full benchmarks with reduced iteration time (~5-7 min)
## Faster than default but covers all benchmarks.
.PHONY: bench-fast
bench-fast:
@echo "Running fast benchmarks (1s per benchmark)..."
@$(MAKE) bench BENCH_TIME=1s
## bench-parallel: Run benchmarks in parallel across packages (local only)
## Faster wall-clock time but may have CPU contention. Results are interleaved.
.PHONY: bench-parallel
bench-parallel:
@echo "Running benchmarks in parallel ($(BENCH_TIME) per benchmark)..."
@for pkg in parser validator fixer httpvalidator converter joiner differ generator builder; do \
go test -bench=. -benchmem -benchtime=$(BENCH_TIME) -timeout=15m ./$$pkg & \
done; wait
@echo ""
@echo "Parallel benchmark run complete."
## bench-compare: Compare two benchmark files (usage: make bench-compare OLD=file1.txt NEW=file2.txt)
.PHONY: bench-compare
bench-compare:
@if [ -z "$(OLD)" ] || [ -z "$(NEW)" ]; then \
echo "Error: Please specify OLD and NEW benchmark files"; \
echo "Usage: make bench-compare OLD=benchmark-baseline.txt NEW=benchmark-20251117.txt"; \
exit 1; \
fi
@if command -v benchstat >/dev/null 2>&1; then \
echo "Comparing $(OLD) vs $(NEW)..."; \
benchstat "$(OLD)" "$(NEW)"; \
else \
echo "benchstat not installed. Install it with:"; \
echo " go install golang.org/x/perf/cmd/benchstat@latest"; \
echo ""; \
echo "Showing simple diff instead:"; \
echo ""; \
diff -u "$(OLD)" "$(NEW)" || true; \
fi
## bench-clean: Remove timestamped benchmark and fuzz output files (preserves baseline and corpus)
.PHONY: bench-clean
bench-clean:
@echo "Cleaning benchmark and fuzz outputs..."
@rm -f benchmark-[0-9]*.txt
@rm -f cpu-profile-*.prof
@rm -f mem-profile-*.prof
@rm -f fuzz-parse-*.log
@echo "Benchmark and fuzz outputs cleaned (baseline and corpus preserved)"
# =============================================================================
# Profiling Targets
# =============================================================================
## bench-cpu: Run benchmarks with CPU profiling
.PHONY: bench-cpu
bench-cpu:
@echo "Running benchmarks with CPU profiling..."
@TIMESTAMP=$$(date +%Y%m%d-%H%M%S); \
PROFILE_FILE="cpu-profile-$${TIMESTAMP}.prof"; \
go test -bench=. -benchmem -benchtime=$(BENCH_TIME) -cpuprofile="$${PROFILE_FILE}" ./parser ./validator ./converter ./joiner ./differ ./builder; \
echo ""; \
echo "CPU profile saved to: $${PROFILE_FILE}"; \
echo "Analyze with: go tool pprof $${PROFILE_FILE}"
## bench-mem: Run benchmarks with memory profiling
.PHONY: bench-mem
bench-mem:
@echo "Running benchmarks with memory profiling..."
@TIMESTAMP=$$(date +%Y%m%d-%H%M%S); \
PROFILE_FILE="mem-profile-$${TIMESTAMP}.prof"; \
go test -bench=. -benchmem -benchtime=$(BENCH_TIME) -memprofile="$${PROFILE_FILE}" ./parser ./validator ./converter ./joiner ./differ ./builder; \
echo ""; \
echo "Memory profile saved to: $${PROFILE_FILE}"; \
echo "Analyze with: go tool pprof $${PROFILE_FILE}"
## bench-profile: Run benchmarks with both CPU and memory profiling
.PHONY: bench-profile
bench-profile:
@echo "Running benchmarks with CPU and memory profiling..."
@TIMESTAMP=$$(date +%Y%m%d-%H%M%S); \
CPU_PROFILE="cpu-profile-$${TIMESTAMP}.prof"; \
MEM_PROFILE="mem-profile-$${TIMESTAMP}.prof"; \
go test -bench=. -benchmem -benchtime=$(BENCH_TIME) -cpuprofile="$${CPU_PROFILE}" -memprofile="$${MEM_PROFILE}" ./parser ./validator ./converter ./joiner ./differ ./builder; \
echo ""; \
echo "CPU profile saved to: $${CPU_PROFILE}"; \
echo "Memory profile saved to: $${MEM_PROFILE}"; \
echo "Analyze with: go tool pprof <profile-file>"
# =============================================================================
# Release Targets
# =============================================================================
## release-test: Test GoReleaser configuration locally (creates dist/ without publishing)
.PHONY: release-test
release-test:
@echo "Testing GoReleaser configuration (snapshot mode)..."
@if ! command -v goreleaser >/dev/null 2>&1; then \
echo "Error: goreleaser not installed. Install it with:"; \
echo " brew install goreleaser"; \
exit 1; \
fi
@goreleaser release --snapshot --clean
@echo ""
@echo "Test successful! Check dist/ directory for generated artifacts."
@echo "To clean up: make release-clean"
@echo ""
@echo "To create a real release, use:"
@echo " gh release create vX.Y.Z --title \"vX.Y.Z - Description\" --notes \"...\""
## release-clean: Clean GoReleaser artifacts from local testing
.PHONY: release-clean
release-clean:
@echo "Cleaning release artifacts..."
@rm -rf dist/
@echo "Release artifacts cleaned"
# =============================================================================
# Corpus Testing Targets
# =============================================================================
## corpus-download: Download public OpenAPI specifications for integration testing
.PHONY: corpus-download
corpus-download:
@echo "Downloading corpus specifications..."
@mkdir -p testdata/corpus
@echo " Downloading Petstore (OAS 2.0)..."
@curl -sL -o testdata/corpus/petstore-swagger.json "https://petstore.swagger.io/v2/swagger.json"
@echo " Downloading DigitalOcean (OAS 3.0.0, bundled)..."
@curl -sL -o testdata/corpus/digitalocean-public.v2.yaml "https://api-engineering.nyc3.digitaloceanspaces.com/spec-ci/DigitalOcean-public.v2.yaml"
@echo " Downloading Asana (OAS 3.0.0)..."
@curl -sL -o testdata/corpus/asana-oas.yaml "https://raw.githubusercontent.com/Asana/openapi/master/defs/asana_oas.yaml"
@echo " Downloading Google Maps (OAS 3.0.3)..."
@curl -sL -o testdata/corpus/google-maps-platform.json "https://raw.githubusercontent.com/googlemaps/openapi-specification/main/dist/google-maps-platform-openapi3.json"
@echo " Downloading US NWS (OAS 3.0.3)..."
@curl -sL -o testdata/corpus/nws-openapi.json "https://api.weather.gov/openapi.json"
@echo " Downloading Plaid (OAS 3.0.0)..."
@curl -sL -o testdata/corpus/plaid-2020-09-14.yml "https://raw.githubusercontent.com/plaid/plaid-openapi/master/2020-09-14.yml"
@echo " Downloading Discord (OAS 3.1.0)..."
@curl -sL -o testdata/corpus/discord-openapi.json "https://raw.githubusercontent.com/discord/discord-api-spec/main/specs/openapi.json"
@echo " Downloading GitHub (OAS 3.0.3)..."
@curl -sL -o testdata/corpus/github-api.json "https://raw.githubusercontent.com/github/rest-api-description/main/descriptions/api.github.com/api.github.com.json"
@echo " Downloading Stripe (OAS 3.0.0, large)..."
@curl -sL -o testdata/corpus/stripe-spec3.json "https://raw.githubusercontent.com/stripe/openapi/master/openapi/spec3.json"
@echo " Downloading Microsoft Graph (OAS 3.0.4, large)..."
@curl -sL -o testdata/corpus/msgraph-openapi.yaml "https://raw.githubusercontent.com/microsoftgraph/msgraph-metadata/master/openapi/v1.0/openapi.yaml"
@echo "Corpus download complete!"
@echo ""
@ls -lh testdata/corpus/
## corpus-clean: Remove downloaded corpus files
.PHONY: corpus-clean
corpus-clean:
@echo "Cleaning corpus files..."
@rm -f testdata/corpus/*.json testdata/corpus/*.yaml testdata/corpus/*.yml
@echo "Corpus files removed (README.md preserved)"
## test-corpus: Run corpus integration tests (requires corpus-download)
.PHONY: test-corpus
test-corpus:
@echo "Running corpus integration tests..."
@go test -v -count=1 ./... -run 'TestCorpus_'
## test-corpus-short: Run corpus integration tests excluding large specs
.PHONY: test-corpus-short
test-corpus-short:
@echo "Running corpus integration tests (short mode, excludes large specs)..."
@go test -v -short -count=1 ./... -run 'TestCorpus_'
## bench-corpus: Run corpus benchmarks (requires -tags=corpus)
## Note: Corpus benchmarks require large specs and more memory.
## These are excluded from regular benchmark runs to prevent memory exhaustion.
.PHONY: bench-corpus
bench-corpus:
@echo "Running corpus benchmarks (requires -tags=corpus)..."
@go test -tags=corpus -bench='BenchmarkCorpus' -benchmem -benchtime=$(BENCH_TIME) ./parser ./validator ./fixer ./differ
# =============================================================================
# Documentation Targets
# =============================================================================
## docs-prepare: Prepare documentation files
.PHONY: docs-prepare
docs-prepare:
@chmod +x scripts/prepare-docs.sh
@./scripts/prepare-docs.sh
## docs-build: Build static documentation site
.PHONY: docs-build
docs-build: docs-prepare
@echo "Building documentation..."
@if command -v mkdocs >/dev/null 2>&1; then \
mkdocs build; \
elif [ -f "$(HOME)/Library/Python/3.9/bin/mkdocs" ]; then \
"$(HOME)/Library/Python/3.9/bin/mkdocs" build; \
else \
echo "Error: mkdocs not found. Please install it or add it to your PATH."; \
exit 1; \
fi
## docs-serve: Serve documentation locally (blocking)
.PHONY: docs-serve
docs-serve: docs-prepare
@echo "Serving documentation at http://127.0.0.1:8000/oastools/ ..."
@if command -v mkdocs >/dev/null 2>&1; then \
mkdocs serve --dev-addr 127.0.0.1:8000; \
elif [ -f "$(HOME)/Library/Python/3.9/bin/mkdocs" ]; then \
"$(HOME)/Library/Python/3.9/bin/mkdocs" serve --dev-addr 127.0.0.1:8000; \
else \
echo "Error: mkdocs not found."; \
exit 1; \
fi
## docs-start: Start documentation server in background
.PHONY: docs-start
docs-start: docs-prepare
@echo "Starting documentation server in background..."
@mkdir -p .tmp
@if command -v mkdocs >/dev/null 2>&1; then \
nohup mkdocs serve --dev-addr 127.0.0.1:8000 > .tmp/mkdocs.log 2>&1 & echo $$! > .tmp/mkdocs.pid; \
elif [ -f "$(HOME)/Library/Python/3.9/bin/mkdocs" ]; then \
nohup "$(HOME)/Library/Python/3.9/bin/mkdocs" serve --dev-addr 127.0.0.1:8000 > .tmp/mkdocs.log 2>&1 & echo $$! > .tmp/mkdocs.pid; \
else \
echo "Error: mkdocs not found."; \
exit 1; \
fi
@echo "Server started. Logs: .tmp/mkdocs.log"
@echo "Stop with: make docs-stop"
## docs-stop: Stop background documentation server
.PHONY: docs-stop
docs-stop:
@if [ -f .tmp/mkdocs.pid ]; then \
kill $$(cat .tmp/mkdocs.pid) 2>/dev/null || true; \
rm .tmp/mkdocs.pid; \
echo "Server stopped."; \
else \
echo "No PID file found. Trying pkill mkdocs..."; \
pkill -f "mkdocs serve" || echo "No mkdocs server found."; \
fi
## docs-clean: Clean documentation artifacts
.PHONY: docs-clean
docs-clean:
@echo "Cleaning documentation..."
@rm -rf site/
@rm -rf .tmp/
@rm -f mkdocs.log mkdocs_error.log
@rm -f docs/index.md.tmp
@rm -f docs/CONTRIBUTORS.md docs/LICENSE.md docs/benchmarks.md
@rm -rf docs/packages docs/examples
## lint-links: Check for broken links in assembled docs
.PHONY: lint-links
lint-links: docs-prepare
@echo "Checking links in docs/..."
@if command -v lychee >/dev/null 2>&1; then \
lychee --no-progress docs/; \
else \
echo "WARNING: lychee not found — link checking SKIPPED." >&2; \
echo "Install: brew install lychee (or cargo install lychee)" >&2; \
fi
## docs-check: Full documentation validation (prepare + link check)
.PHONY: docs-check
docs-check: lint-links
# =============================================================================
# Help Target
# =============================================================================
## help: Show this help message
.PHONY: help
help:
@echo "Usage: make [target]"
@echo ""
@echo "Targets:"
@sed -n 's/^##//p' $(MAKEFILE_LIST) | column -t -s ':' | sed -e 's/^/ /'
@echo ""
@echo "Benchmark Configuration:"
@echo " BENCH_TIME=<duration> Benchmark run time per test (default: 5s)"
@echo " Example: make bench BENCH_TIME=10s"
@echo ""
@echo "Corpus Testing:"
@echo " 1. make corpus-download # Download all specs (one-time)"
@echo " 2. make test-corpus-short # Run tests (excludes large specs)"
@echo " 3. make test-corpus # Run all corpus tests"
@echo ""
@echo "Documentation:"
@echo " make docs-serve # Serve docs locally (blocking)"
@echo " make docs-start # Start docs server in background"
@echo " make docs-stop # Stop docs server"
@echo " make docs-build # Build static site"