Commit 424d6d4
authored
feat(seeder): expand db-seed with demo files + multi-type comments (sbpp#1484)
`./sbpp.sh db-seed` previously stopped at empty `:prefix_demos` rows and
ban-only comments. Two visible-but-empty surfaces on a freshly-seeded
dev DB:
1. **"Review Demo" link on the banlist** rendered as a dead anchor —
`:prefix_demos` was untouched by the seeder, so the page handler
never emitted the affordance and the surface was unreachable for
manual exploration / acceptance audits / screenshot work without
hand-uploading a demo first.
2. **Moderation queues** (admin submissions + protests) and the
public banlist's per-row comment disclosure rendered with empty
comment threads — `:prefix_comments` only ever got type `'B'`
(ban-attached) rows, so the C / S / P columns of the table were
structurally untestable.
This PR closes both gaps with one expansion of `Sbpp\Tests\Synthesizer`:
**Demo seeding.** `insertDemos()` writes ~80 rows at medium scale
(64 ban-attached, 16 submission-attached — 80/20 split that mirrors
the panel's own bias toward bans-with-evidence) and lands a paired
~1 KiB opaque text payload on disk under `SB_DEMOS` (`web/demos/` on
the dev bind-mount). Filenames are `md5(seed|demtype|demid)` so
re-seeds round-trip identically and the truncate-time wipe can find
them by re-reading the table. Picks use `array_rand` for exact
unique counts — rejection-sampling-with-collisions undershoots the
budget by ~6% which made the screenshot-flow rendering jittery
across runs. The synth payload is text (not a Source-engine binary),
so the "Review Demo" link round-trips end-to-end through
`getdemo.php` with `Content-Type: application/octet-stream` and a
download lands in the browser, but the SDK demoviewer won't replay
them — that would need a real demo binary and is out of scope for a
panel-chrome seeder.
**Multi-type comments.** `insertComments()` now fans the comment
budget across all four `:prefix_comments.type` values:
- `B` (ban) — 60% — `comments.bid` → `bans.bid`
- `C` (comm block) — 20% — `comments.bid` → `comms.bid`
- `S` (submission) — 10% — `comments.bid` → `submissions.subid`
- `P` (protest) — 10% — `comments.bid` → `protests.pid`
Medium scale → 200 comments → 120/40/20/20. The split matches the
overload contract in `api_bans_add_comment`'s `match($ctype)` arms
documented in AGENTS.md → "Add a comment-delete trash icon". The
parent-ID tracking arrays (`commsCids`, `submissionSubids`,
`protestPids`) populate during their respective `insert*()` passes
via `lastInsertId()` so the comment-insert pass has the FK pool ready.
**Idempotency contract.** The pre-existing truncate-then-reseed flow
got two refinements:
- **Snapshot filenames BEFORE truncate, unlink AFTER.** Previous
pre-fix shape was wipe-files-then-truncate, which left a transient
window where files were gone but DB rows still pointed at them
(any panel page query during that window 404'd the "Review Demo"
link). New order: snapshot → truncate → unlink, so rows + files
drop visibly together from the panel's POV.
- **Wipe scope is the snapshotted set, not the directory.** Manual
panel uploads (anyone who uploaded a demo against the dev stack)
and `.gitkeep` survive untouched. The `db-reset` companion (see
below) is the only thing that strips by-name across the whole
directory, scoped to the MD5-basename shape.
**Paired surface changes:**
- `.gitignore` — `web/demos/*` + `!.gitkeep` exception. Pre-fix a
fresh `db-seed` polluted `git status` with 80 untracked MD5-named
files; the demo store is also where the panel's `UploadHandler`
writes real ban evidence on production installs, so checking those
in would leak operator evidence into the source tree.
- `sbpp.sh db-reset` — strips MD5-basename files from `web/demos/`
after the DB volume drop. The `_demos` rows that pointed at them
vanish with the volume, so the next `db-seed`'s referenced-only
wipe reads zero rows from the fresh DB and skips them; without the
reset-time strip those files would accumulate as permanent orphans
across worktree lifetimes. `find … -regex '.*/[0-9a-f]{32}$'`
matches both shapes the write path produces (synth + the panel's
own `UploadHandler::handle()` with `renameToHash: true`).
- `AGENTS.md` + `docker/README.md` — exact per-scale counts, demo
payload caveat (not playable in the demoviewer), the new wipe
ordering contract, gitignore + `db-reset` cleanup behavior.
**Verification.** Default-seed run produces exactly 80 demos +
exactly 200 comments split B=120/C=40/S=20/P=20; FK joins return
zero orphans across all six pairs (`demos.B` → bans, `demos.S` →
submissions, `comments.B/C/S/P` → bans/comms/submissions/protests);
two consecutive seeds with the default seed produce identical
filename sets (`md5sum` of `ls` output matches byte-for-byte); a
manually-touched decoy file in `web/demos/` survives every seed.
PHPStan clean; the one PHPUnit test that touches `:prefix_demos` /
`:prefix_comments` (`ExportBundleWriterTest`, 426 assertions) passes
unchanged.
Follow-up: sbpp#1483 tracks the pre-existing tech debt where the seeder
writes bare letter codes (`'U'` / `'D'` / `'m'` / `'w'` / `'e'`) into
the column-typed string fields covered by `BanRemoval` / `LogType`
instead of routing through the enum's `->value` per AGENTS.md
"Backed enums for column-typed fields". Out of scope for this PR.1 parent 6126cc8 commit 424d6d4
5 files changed
Lines changed: 471 additions & 42 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
53 | 53 | | |
54 | 54 | | |
55 | 55 | | |
| 56 | + | |
| 57 | + | |
| 58 | + | |
| 59 | + | |
| 60 | + | |
| 61 | + | |
| 62 | + | |
| 63 | + | |
| 64 | + | |
| 65 | + | |
56 | 66 | | |
57 | 67 | | |
58 | 68 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
618 | 618 | | |
619 | 619 | | |
620 | 620 | | |
621 | | - | |
622 | | - | |
623 | | - | |
624 | | - | |
| 621 | + | |
| 622 | + | |
| 623 | + | |
| 624 | + | |
| 625 | + | |
| 626 | + | |
625 | 627 | | |
626 | 628 | | |
627 | 629 | | |
628 | 630 | | |
629 | 631 | | |
630 | 632 | | |
631 | | - | |
632 | | - | |
633 | | - | |
| 633 | + | |
| 634 | + | |
| 635 | + | |
| 636 | + | |
| 637 | + | |
| 638 | + | |
| 639 | + | |
| 640 | + | |
| 641 | + | |
| 642 | + | |
| 643 | + | |
| 644 | + | |
| 645 | + | |
| 646 | + | |
634 | 647 | | |
635 | | - | |
636 | | - | |
637 | | - | |
638 | | - | |
| 648 | + | |
| 649 | + | |
| 650 | + | |
| 651 | + | |
| 652 | + | |
| 653 | + | |
| 654 | + | |
| 655 | + | |
| 656 | + | |
| 657 | + | |
| 658 | + | |
| 659 | + | |
| 660 | + | |
| 661 | + | |
| 662 | + | |
| 663 | + | |
| 664 | + | |
| 665 | + | |
| 666 | + | |
| 667 | + | |
| 668 | + | |
| 669 | + | |
| 670 | + | |
| 671 | + | |
| 672 | + | |
| 673 | + | |
| 674 | + | |
| 675 | + | |
639 | 676 | | |
640 | 677 | | |
641 | 678 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
86 | 86 | | |
87 | 87 | | |
88 | 88 | | |
89 | | - | |
90 | | - | |
| 89 | + | |
| 90 | + | |
91 | 91 | | |
92 | 92 | | |
93 | 93 | | |
94 | 94 | | |
95 | 95 | | |
96 | | - | |
97 | | - | |
98 | | - | |
99 | | - | |
100 | | - | |
101 | | - | |
| 96 | + | |
| 97 | + | |
| 98 | + | |
| 99 | + | |
| 100 | + | |
| 101 | + | |
| 102 | + | |
| 103 | + | |
| 104 | + | |
102 | 105 | | |
103 | 106 | | |
104 | | - | |
105 | | - | |
106 | | - | |
| 107 | + | |
| 108 | + | |
| 109 | + | |
107 | 110 | | |
108 | 111 | | |
109 | 112 | | |
| 113 | + | |
| 114 | + | |
| 115 | + | |
| 116 | + | |
| 117 | + | |
| 118 | + | |
| 119 | + | |
| 120 | + | |
| 121 | + | |
| 122 | + | |
| 123 | + | |
| 124 | + | |
| 125 | + | |
| 126 | + | |
| 127 | + | |
| 128 | + | |
| 129 | + | |
| 130 | + | |
110 | 131 | | |
111 | 132 | | |
112 | 133 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
33 | 33 | | |
34 | 34 | | |
35 | 35 | | |
36 | | - | |
| 36 | + | |
| 37 | + | |
37 | 38 | | |
38 | 39 | | |
39 | 40 | | |
| |||
228 | 229 | | |
229 | 230 | | |
230 | 231 | | |
| 232 | + | |
| 233 | + | |
| 234 | + | |
| 235 | + | |
| 236 | + | |
| 237 | + | |
| 238 | + | |
| 239 | + | |
| 240 | + | |
| 241 | + | |
| 242 | + | |
| 243 | + | |
| 244 | + | |
| 245 | + | |
| 246 | + | |
| 247 | + | |
231 | 248 | | |
232 | 249 | | |
233 | 250 | | |
| |||
0 commit comments