Summary
Every PR hand-edits the same VERSION line in application/single_app/config.py and adds a matching ### **(vX.XXX.XXX)** heading to docs/explanation/release_notes.md. With one PR in flight that is fine. With six, it serialises the whole queue through two lines, and a large share of the resulting merge conflicts have nothing to do with the code being reviewed.
Raised by the PR merge orchestration session after coordinating six concurrent admin-settings-V2 PRs. Their assessment, which matches what I saw resolving #1425:
six PRs serialising through one integer in one file is the underlying problem — the assignment scheme managed the symptom
What actually happened
The scheme worked — nothing shipped with a duplicate or regressed version. It just cost a lot of coordination for something no human was reading during review.
Why the conflict is structural
Both contended edits are append-at-the-top operations on a shared line:
| File |
What every PR does |
application/single_app/config.py |
Replaces the single VERSION = "..." line |
docs/explanation/release_notes.md |
Inserts a new ### **(vX.XXX.XXX)** section at the top |
Git cannot auto-merge either, because both sides changed the same line or inserted at the same anchor. The result is a guaranteed conflict between any two concurrent PRs, independent of whether they touch any of the same code.
Suggested direction
Not proposing a specific mechanism, but the shape worth considering is deriving the patch bump at release time rather than hand-editing it per PR:
- Let PRs declare that they change the application, not which number they land as — for example a changelog fragment file per PR (
docs/release_notes.d/<branch>.md), which is conflict-free because each PR adds its own file. The release step concatenates fragments and assigns the number.
- Compute
VERSION at build or release time from commit count or tag, so config.py is not edited per PR at all.
- Keep the current convention for the major/minor segments, which are deliberate decisions, and only automate the third.
Any of these removes the two lines that currently serialise everything.
What already works and should be kept
functional_tests/test_support/versioning.py already provides assert_app_version_at_least, and the repository instructions require tests to use it rather than asserting exact equality. That is the right call and it means test assertions are already immune to renumbering — a pre-assignment change does not invalidate them. The remaining cost is purely the hand-edited literals in headers and docs.
For scale: 236 files currently contain a 0.261.x literal (105 under docs/, 124 under functional_tests/, 7 under application/). Most are historical records that correctly should not move. The problem is narrowly the two lines that every new PR must edit.
Caveats
- This touches a documented repository convention (
.github/instructions, version management), so it needs a deliberate decision rather than a drive-by change.
- Deriving the version from commit count or tags changes what the number means, which may matter for support and for the deployer, which tracks its own version separately in
deployers/version.txt.
- Low urgency. It only bites when several PRs are in flight at once, which is exactly when it bit.
Context
Observed across PRs #1415, #1418, #1419, #1421, #1422, #1424, #1425 and #1426 during the admin-settings-V2 work.
Summary
Every PR hand-edits the same
VERSIONline inapplication/single_app/config.pyand adds a matching### **(vX.XXX.XXX)**heading todocs/explanation/release_notes.md. With one PR in flight that is fine. With six, it serialises the whole queue through two lines, and a large share of the resulting merge conflicts have nothing to do with the code being reviewed.Raised by the PR merge orchestration session after coordinating six concurrent admin-settings-V2 PRs. Their assessment, which matches what I saw resolving #1425:
What actually happened
VERSIONline twice inside ten minutes.0.261.061,063,065,070,071,072…) to stop the collisions.072→080→082) as the queue reordered. Each reissue meant re-editingconfig.py, the release-notes heading, and the version literal in every functional test header touched by that PR.The scheme worked — nothing shipped with a duplicate or regressed version. It just cost a lot of coordination for something no human was reading during review.
Why the conflict is structural
Both contended edits are append-at-the-top operations on a shared line:
application/single_app/config.pyVERSION = "..."linedocs/explanation/release_notes.md### **(vX.XXX.XXX)**section at the topGit cannot auto-merge either, because both sides changed the same line or inserted at the same anchor. The result is a guaranteed conflict between any two concurrent PRs, independent of whether they touch any of the same code.
Suggested direction
Not proposing a specific mechanism, but the shape worth considering is deriving the patch bump at release time rather than hand-editing it per PR:
docs/release_notes.d/<branch>.md), which is conflict-free because each PR adds its own file. The release step concatenates fragments and assigns the number.VERSIONat build or release time from commit count or tag, soconfig.pyis not edited per PR at all.Any of these removes the two lines that currently serialise everything.
What already works and should be kept
functional_tests/test_support/versioning.pyalready providesassert_app_version_at_least, and the repository instructions require tests to use it rather than asserting exact equality. That is the right call and it means test assertions are already immune to renumbering — a pre-assignment change does not invalidate them. The remaining cost is purely the hand-edited literals in headers and docs.For scale: 236 files currently contain a
0.261.xliteral (105 underdocs/, 124 underfunctional_tests/, 7 underapplication/). Most are historical records that correctly should not move. The problem is narrowly the two lines that every new PR must edit.Caveats
.github/instructions, version management), so it needs a deliberate decision rather than a drive-by change.deployers/version.txt.Context
Observed across PRs #1415, #1418, #1419, #1421, #1422, #1424, #1425 and #1426 during the admin-settings-V2 work.