Commit 4186d7d
docs(flyway): record the Option 2 decision and correct the seed convention
Per the discussion on #280, Option 2 is selected: seed data moves to repeatable
migrations, and only DDL keeps a version. This records the decision and brings
the operational README in line with it.
docs/decisions/flyway-test-fixture-strategy.md
----------------------------------------------
Status moves Proposed -> ACCEPTED. Rewritten to select Option 2 and to keep
Option 3 as a stretch goal rather than the target.
Sharpened the root cause. The original framing was "a flat, shared, sequential
namespace"; the operative property is that THE COLLISION IS INVISIBLE TO GIT.
Two branches claiming the same version produce two differently NAMED files, so
git merges them cleanly and the failure surfaces only when Flyway loads. That is
what selects the fix: an identifier derived from content rather than sequence
puts the clash back on one file path, where git reports it normally.
Also separates the two problems that were conflated, because they have different
answers: P1 (version collision, kills the suite at boot) and P2 (one shared
mutable dataset — PK collisions, cross-class leakage, order-dependence).
Option 1 is now recorded as REJECTED rather than a viable interim: day-granularity
timestamps were already adopted for this exact reason and collided on 2026-08-13
and again on 2026-08-19, because everyone hand-picks today's date, making a date
exactly as scarce as an integer. The fifth collision (V20260819) is added to the
record.
The Option 2 behaviour is documented as verified rather than assumed — probed on
Flyway 12.4.0 against the real Oracle container: all 46 versioned migrations at
ranks 1-46, all repeatables at 47-51, and repeatables ordered lexicographically
by description (05 -> 50 -> 90 -> bbb). So R__-after-V__ is a tool guarantee, and
a numeric prefix is what makes FK ordering deterministic.
Why Option 3 is deferred is recorded with its measurements: 74% of fixture data
(912 of 1,232 INSERTs) is shared backbone, so it would relocate ~26% and leave
the shared dataset in place; 115 IT classes with only 2 @transactional, so
rollback is unavailable and isolation must be hand-built; Flyway is 8.57s once
per JVM against a ~65s container start; and — the decisive risk — per-class
fixtures can make the cross-tenant IDOR tests pass VACUOUSLY, since they assert
"someone else's row -> 404" and would still pass if the foreign row were never
provisioned at all.
backend/src/test/resources/db/README.md
---------------------------------------
Convention 1 now says seed data goes in R__ with a content-derived name and an
ordering prefix (data 10-80, constraints/FKs 90+). Convention 1a keeps versions
for DDL only and says explicitly to keep INSERTs out of them, since a seed in a
new V__ reopens the collision. The timestamp history is kept as a note, because
it is the evidence for the rule.
Corrected the stale claim that ruled this out. The README asserted a
fixture-inserting migration "still takes a version, because re-running it on a
reused container would duplicate rows." Wrong on both halves: Flyway re-runs a
repeatable only when its CHECKSUM changes, and AbstractOracleIT creates the
container fresh per JVM (no withReuse), so each repeatable applies exactly once
per run. R__cost_detail_bridge_culvert_fks.sql already stated this two lines from
where the README contradicted it.
Also repointed three now-stale "per convention 1" cross-references in the
historical per-track notes, which would otherwise send a reader to a rule about
R__ seeds when they are reading about a past V__ choice.
Scope
-----
Docs only. No migration is renamed, no test changes, no existing fixture
converted — the current chain freezes as the baseline and the convention governs
new work. The one follow-up the ADR names is prefixing
R__cost_detail_bridge_culvert_fks.sql with 90_, which changes no behaviour until
a prefixed R__ constraint exists to sort against.
Separately noted in the ADR as not done here: extending
FlywayMigrationVersionUniquenessTest to reject a new V__ containing INSERTs. That
is what would make the convention self-enforcing — the README alone did not
prevent any of the five collisions, while the guard test caught the fifth.
Verified: FlywayMigrationVersionUniquenessTest green; branch merged up to
origin/main first.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>1 parent b33859d commit 4186d7d
2 files changed
Lines changed: 110 additions & 56 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
22 | 22 | | |
23 | 23 | | |
24 | 24 | | |
25 | | - | |
26 | | - | |
27 | | - | |
28 | | - | |
29 | | - | |
30 | | - | |
31 | | - | |
32 | | - | |
33 | | - | |
34 | | - | |
35 | | - | |
36 | | - | |
37 | | - | |
38 | | - | |
39 | | - | |
40 | | - | |
41 | | - | |
| 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 | + | |
42 | 63 | | |
43 | 64 | | |
44 | 65 | | |
| |||
54 | 75 | | |
55 | 76 | | |
56 | 77 | | |
57 | | - | |
58 | | - | |
| 78 | + | |
| 79 | + | |
59 | 80 | | |
60 | 81 | | |
61 | 82 | | |
62 | 83 | | |
63 | 84 | | |
64 | | - | |
| 85 | + | |
65 | 86 | | |
66 | 87 | | |
67 | 88 | | |
| |||
212 | 233 | | |
213 | 234 | | |
214 | 235 | | |
215 | | - | |
216 | | - | |
| 236 | + | |
| 237 | + | |
| 238 | + | |
0 commit comments