feat: Versionsstelle als Kompatibilitaetsfrage, Breaking-Change-Vermerk erzwungen (2.5.0)
Files changed: - CHANGES.md - INSTALL.md - VERSION - instructions/dev/stack-dev/SKILL.md - instructions/dev/version-parts.md - tools/CONTRACT.md - tools/chemenu/commands/docs_verify.py - tools/chemenu/commands/version_cmd.py - tools/chemenu/tests/test_docs_verify.py - tools/chemenu/tests/test_version_cmd.py - tools/chemenu/version.py
This commit is contained in:
1 parent
7fbb9a99df
commit
31662dc3ff
11 files changed
+431
-32
No files matched your search
@@ -10,11 +10,23 @@ ingest into a release.
|
||||
|
||||
**Compatibility is read off the leftmost non-zero component**, the rule Cargo's
|
||||
caret ranges use: `0.1.3 -> 0.1.4` is safe, `0.1.3 -> 0.2.0` is not, and from
|
||||
`1.0.0` on the same rule reads as the familiar "MAJOR means migration". Stating
|
||||
it that way is what lets the 0.x era carry the migration signal at all - under
|
||||
plain "MAJOR breaks" semantics every 0.x release would be indistinguishable
|
||||
from every other, which is exactly the signal update detection needs. Nothing
|
||||
about the mechanism changes at 1.0.0.
|
||||
`1.0.0` on the same rule reads as the familiar "MAJOR breaks". Stating it that
|
||||
way is what lets the 0.x era carry the signal at all - under a rule keyed to
|
||||
the MAJOR component alone, every 0.x release would be indistinguishable from
|
||||
every other, which is exactly the signal update detection needs. Nothing about
|
||||
the mechanism changes at 1.0.0.
|
||||
|
||||
What that component answers is **whether the new version is a drop-in
|
||||
replacement**: whether an instance can copy the new machinery over itself with
|
||||
no hand-work and still put the old version back afterwards. Whether *content*
|
||||
must be migrated is a **second, independent question**. It is one way to fail
|
||||
the first - but a renamed release feed, artefact, import name, flag or envvar
|
||||
fails it too, with `kb/` untouched, which is why `--no-migration` exists at all:
|
||||
boundary-crossing bumps that migrate nothing are a real case, not an escape
|
||||
hatch. Hence two markers below rather than one - `BREAKING_CHANGE_MARKER`
|
||||
records the break, `MIGRATION_NONE_MARKER` records the absence of the
|
||||
migration. Which part a change earns stays a judgment call made before the
|
||||
bump; this module only enforces that a crossing says what it costs.
|
||||
|
||||
Paths are resolved through `config.ROOT` at call time rather than at import,
|
||||
because the tests (and `dist export`'s own fixtures) relocate the root.
|
||||
@@ -64,6 +76,11 @@ _SEMVER_RE = re.compile(r"^\s*v?(\d+)\.(\d+)\.(\d+)\s*$")
|
||||
# boundary that needs no content migration. `docs verify` accepts it in place
|
||||
# of a migration document, so the exact string is a contract between the two.
|
||||
MIGRATION_NONE_MARKER = "**Migration:** none required"
|
||||
# Written into every CHANGES.md entry whose version crosses a compatibility
|
||||
# boundary, migration or not: the swap is not drop-in, and the operator of an
|
||||
# existing instance has to be told what stops working. `docs verify` checks the
|
||||
# newest crossing carries it, so this string too is a contract between the two.
|
||||
BREAKING_CHANGE_MARKER = "**Breaking Change:**"
|
||||
# A changelog entry that names a version. Entries predating versioning start
|
||||
# with a date instead and are deliberately not matched - they are history, not
|
||||
# a claim about which version the tree is.
|
||||
@@ -332,15 +349,22 @@ def insert_changes_entry(
|
||||
title: str,
|
||||
author: str,
|
||||
no_migration_reason: Optional[str] = None,
|
||||
breaking_reason: Optional[str] = None,
|
||||
) -> str:
|
||||
"""Add a heading for `version` above the newest existing entry.
|
||||
|
||||
Only the skeleton: heading, date, author, and - when a compatibility
|
||||
boundary is crossed without a migration - the line that says so. The
|
||||
entry's actual content is written afterwards by whoever made the change,
|
||||
which is also why `bump` refuses to invent a title.
|
||||
boundary is crossed - the line saying what breaks, plus the line saying no
|
||||
content has to change where that applies. The entry's actual content is
|
||||
written afterwards by whoever made the change, which is also why `bump`
|
||||
refuses to invent a title.
|
||||
|
||||
The break comes first: it is what an operator reading the release notes has
|
||||
to act on, and the migration line only qualifies it.
|
||||
"""
|
||||
lines = [f"## {version} - {date} - {title}", "", f"**Author:** {author}", ""]
|
||||
if breaking_reason:
|
||||
lines += [f"{BREAKING_CHANGE_MARKER} {breaking_reason}", ""]
|
||||
if no_migration_reason:
|
||||
lines += [f"{MIGRATION_NONE_MARKER} - {no_migration_reason}", ""]
|
||||
entry = "\n".join(lines) + "\n---\n\n"
|
||||
|
||||
Reference in new issue
Block a user