feat: refuse placeholder versions in the schema

core_version is a string the code states, null or keyed by build mode,
and the schema refuses Git, SVN, unknown, master, main, latest, dev and
HEAD, alone or annotated. version_basis is defined per kind with the
fields each one needs, and kind none requires a null version.

tests/test_version_basis.py reads a recorded fixture of forge answers
offline and fails on drift, holds every profile to a basis (tag versions
in describe form, aliases equal to their profile, none as null), checks
that a pin advance reads the version again or is refused, and that the
schema refuses placeholders.
This commit is contained in:
Abdessamad Derraz committed 2026-10-27 19:23:17 +01:00
1 parent 3199bc2a55
commit 91b7bd94d0
7 files changed
+708 -8

No files matched your search

+1
View File
@@ -7799,6 +7799,7 @@ _UNVERIFIED = {
"host_unsupported": "its host cannot be read",
"host_gone": "its source is gone",
"host_unreachable": "its host did not answer",
"pin_off_branch": "its recorded revision is not the build described",
"no_artifact": "no build recorded as read",
"no_source": "no source declared",
}
+2 -1
View File
@@ -2736,7 +2736,8 @@ def set_version_fields(text: str, version: object, basis: dict | None) -> str:
if span is None:
anchor = _top_block(lines, "upstream_commit") or _top_block(lines, "source_commit") \
or _top_block(lines, "profiled_date") or _top_block(lines, "upstream") \
or _top_block(lines, "source")
or _top_block(lines, "source") or _top_block(lines, "alias_of") \
or _top_block(lines, "type")
if anchor is None:
raise YamlWriteError("core_version: no line to write it after")
lines[anchor[1]:anchor[1]] = rendered
+5 -1
View File
@@ -93,7 +93,11 @@ def _by_mode(profile: dict, field: str, mode: str) -> str | None:
def is_placeholder(value: object) -> bool:
return isinstance(value, str) and value.strip().casefold() in PLACEHOLDERS
"""A VCS or branch word standing for a version, alone or annotated
("SVN (2015 snapshot)"). The schema refuses the same strings."""
if not isinstance(value, str):
return False
return re.split(r"[\s(]", value.strip(), maxsplit=1)[0].casefold() in PLACEHOLDERS
def format_version(match: re.Match, template: str | None) -> str: