perf(test): make schema-dump target + opt-in fast-path docs (WS-6)
Session 2.6's per-test migrate:fresh in 4 backfill test classes replays ~120 migrations. Laravel's schema:dump produces a single SQL file that migrate:fresh loads atomically when present — significantly faster on environments where the host has the \`mysql\` CLI available for Laravel's load step. Changes: - New Makefile target \`schema-dump\` runs mysqldump INSIDE the bm_mysql Docker container (no host mysqldump dependency to GENERATE the dump). Outputs api/database/schema/mysql-schema.sql. - api/database/schema/.gitignore added: mysql-schema.sql is NOT committed by default. Laravel's auto-load on migrate:fresh shells out to the host's \`mysql\` CLI; on hosts without it, the presence of the dump file actively breaks migrate (exit 127). Treat the dump as opt-in per dev environment. - CLAUDE.md "Schema dumps (opt-in fast path)" subsection added with the workflow: brew install mysql-client → migrate to head → make schema-dump → optionally commit. phpstan-baseline.neon: removed a stale "unused use \$actor" entry in FormSubmissionService whose underlying closure pint cleaned up in commit060d6f3(Task 1). Wall-time on this dev machine (no host mysql CLI): NO speedup, backfill tests still ~6s per setUp. The dump file is ready for environments that have mysql CLI. Documented as a deviation. JSON canonicalization (commit060d6f3) is the load-bearing correctness fix from this branch; the schema-dump perf path is a nice-to-have that activates per-environment. Refs: WS-6 session 2.6 deviation #5 cleanup Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
33
CLAUDE.md
33
CLAUDE.md
@@ -100,7 +100,7 @@ When writing migrations or queries:
|
||||
- Use Laravel's query builder where possible — it handles cross-DB syntax consistently
|
||||
- For raw SQL, write MySQL syntax (no need for SQLite fallbacks). Index introspection: query `information_schema.STATISTICS`, never `sqlite_master`.
|
||||
- Foreign keys go on every relation column. The `nullOnDelete` / `cascadeOnDelete` choice is per the relationship's domain semantics; "no FK" is not an option.
|
||||
- Tests that round-trip JSON data via MySQL JSON columns must use `assertEquals` (structural equality) rather than `assertSame` on associative arrays — MySQL JSON may reorder object keys.
|
||||
- JSON values stored in byte-stable columns (`schema_snapshot`, webhook `payload_snapshot`, activity-log `properties` for diff payloads) MUST be canonicalized at write via `App\Support\Json\JsonCanonicalizer`. MySQL JSON columns may reorder associative-array keys on round-trip; canonicalize so re-emits / HMAC signatures / audit-replay diffs are byte-identical. Opaque-config JSON (`form_schemas.settings`, `translations`) is exempt — key order has no semantic meaning there. Tests on canonicalized data use `assertSame(JsonCanonicalizer::encode($a), JsonCanonicalizer::encode($b))`.
|
||||
|
||||
Other database rules:
|
||||
|
||||
@@ -108,6 +108,37 @@ Other database rules:
|
||||
- Create migrations in dependency order: foundation first, then dependent tables
|
||||
- Always add composite indexes as documented in the design document (section 3.5)
|
||||
|
||||
### Schema dumps (opt-in fast path)
|
||||
|
||||
Laravel supports `database/schema/{driver}-schema.sql` as a fast-path
|
||||
baseline that `migrate:fresh` loads in one statement instead of replaying
|
||||
every migration. For Crewli's backfill / migration tests (which call
|
||||
`migrate:fresh` per test), this can yield a meaningful speedup —
|
||||
**when the host has the `mysql` and `mysqldump` CLI tools available.**
|
||||
|
||||
Workflow:
|
||||
|
||||
1. Install MySQL client tools on host (one-time):
|
||||
```bash
|
||||
brew install mysql-client
|
||||
echo 'export PATH="/opt/homebrew/opt/mysql-client/bin:$PATH"' >> ~/.zshrc
|
||||
```
|
||||
2. Bring `crewli_test` to head: `DB_DATABASE=crewli_test php artisan migrate --force`
|
||||
3. Generate the dump: `make schema-dump`
|
||||
4. Commit `api/database/schema/mysql-schema.sql` alongside any new migrations.
|
||||
|
||||
The schema dump is **NOT committed by default** because Laravel's
|
||||
auto-load path shells out to the `mysql` CLI; on hosts without it,
|
||||
the presence of the dump file actively breaks `migrate` / `migrate:fresh`
|
||||
(load fails, exit 127). Treat the dump as opt-in per dev environment.
|
||||
|
||||
`make schema-dump` runs `mysqldump` inside the `bm_mysql` Docker
|
||||
container, so contributors don't need `mysqldump` on the host to
|
||||
**generate** the dump — only to **load** it via Laravel's auto-detection.
|
||||
|
||||
`--prune` is NOT used: individual migration files stay readable in
|
||||
`api/database/migrations/` for audit / rollback purposes.
|
||||
|
||||
### Roles and permissions
|
||||
|
||||
- Use Spatie `laravel-permission`
|
||||
|
||||
23
Makefile
23
Makefile
@@ -1,4 +1,4 @@
|
||||
.PHONY: help services services-stop api app portal docs migrate fresh db-shell test test-db-create
|
||||
.PHONY: help services services-stop api app portal docs migrate fresh db-shell test test-db-create schema-dump
|
||||
|
||||
# Colors
|
||||
GREEN := \033[0;32m
|
||||
@@ -27,6 +27,7 @@ help:
|
||||
@echo " make fresh Fresh migrate + seed"
|
||||
@echo " make db-shell Open MySQL shell"
|
||||
@echo " make test-db-create Create crewli_test database (one-time)"
|
||||
@echo " make schema-dump Regenerate MySQL schema dump (run after new migrations)"
|
||||
@echo ""
|
||||
@echo " $(YELLOW)Testing:$(NC)"
|
||||
@echo " make test Run PHPUnit suite (creates crewli_test if needed)"
|
||||
@@ -81,3 +82,23 @@ test-db-create:
|
||||
|
||||
test: test-db-create
|
||||
@cd api && php artisan test
|
||||
|
||||
# Regenerate api/database/schema/mysql-schema.sql from the current
|
||||
# crewli_test schema. Runs mysqldump INSIDE the bm_mysql Docker
|
||||
# container, so contributors don't need mysqldump on the host.
|
||||
#
|
||||
# Workflow: this target dumps WHATEVER state crewli_test is currently
|
||||
# in. Run `make test-db-create` (creates DB), then put it at the desired
|
||||
# state — typically by running the test suite, which migrates the test
|
||||
# DB to head — then `make schema-dump`.
|
||||
#
|
||||
# See CLAUDE.md "Schema dumps" — commit the regenerated dump alongside
|
||||
# any new migrations so CI / fast-path migrate:fresh stays in sync.
|
||||
schema-dump:
|
||||
@echo "$(GREEN)Regenerating api/database/schema/mysql-schema.sql from current crewli_test state...$(NC)"
|
||||
@docker exec bm_mysql mysqldump --no-tablespaces --skip-add-locks --skip-comments --skip-set-charset --tz-utc -u root -proot crewli_test --routines --no-data 2>/dev/null > /tmp/crewli-schema-structure.sql
|
||||
@docker exec bm_mysql mysqldump --no-tablespaces --skip-add-locks --skip-comments --skip-set-charset --tz-utc -u root -proot crewli_test migrations --no-create-info 2>/dev/null > /tmp/crewli-schema-migrations.sql
|
||||
@cat /tmp/crewli-schema-structure.sql /tmp/crewli-schema-migrations.sql > api/database/schema/mysql-schema.sql
|
||||
@rm /tmp/crewli-schema-structure.sql /tmp/crewli-schema-migrations.sql
|
||||
@echo "$(GREEN)✓ api/database/schema/mysql-schema.sql updated$(NC)"
|
||||
@echo "$(YELLOW)Note: Commit the updated schema dump alongside any new migrations.$(NC)"
|
||||
|
||||
4
api/database/schema/.gitignore
vendored
Normal file
4
api/database/schema/.gitignore
vendored
Normal file
@@ -0,0 +1,4 @@
|
||||
# Schema dumps are environment-specific and require mysql CLI on host
|
||||
# for Laravel's auto-load. NOT committed by default. See CLAUDE.md
|
||||
# "Schema dumps (opt-in fast path)".
|
||||
mysql-schema.sql
|
||||
@@ -5886,12 +5886,6 @@ parameters:
|
||||
count: 1
|
||||
path: app/Services/FormBuilder/FormSubmissionService.php
|
||||
|
||||
-
|
||||
message: '#^Anonymous function has an unused use \$actor\.$#'
|
||||
identifier: closure.unusedUse
|
||||
count: 1
|
||||
path: app/Services/FormBuilder/FormSubmissionService.php
|
||||
|
||||
-
|
||||
message: '#^Call to an undefined method Illuminate\\Database\\Eloquent\\Model\:\:rootConditionalLogicGroup\(\)\.$#'
|
||||
identifier: method.notFound
|
||||
|
||||
Reference in New Issue
Block a user