chore(release): harden nick contract for v0.1.2
This commit is contained in:
@@ -65,11 +65,11 @@ def test_checkout_identity_is_exact():
|
||||
|
||||
def test_project_version_must_match_release_tag(tmp_path):
|
||||
project = tmp_path / "pyproject.toml"
|
||||
project.write_text('[project]\nversion = "0.1.1"\n')
|
||||
assert image_release.project_release_version(project) == "v0.1.1"
|
||||
assert image_release.validate_release_event("push", "refs/tags/v0.1.1", COMMIT, "v0.1.1") == "v0.1.1"
|
||||
project.write_text('[project]\nversion = "0.1.2"\n')
|
||||
assert image_release.project_release_version(project) == "v0.1.2"
|
||||
assert image_release.validate_release_event("push", "refs/tags/v0.1.2", COMMIT, "v0.1.2") == "v0.1.2"
|
||||
with pytest.raises(ValueError, match="project version"):
|
||||
image_release.validate_release_event("push", "refs/tags/v0.1.2", COMMIT, "v0.1.1")
|
||||
image_release.validate_release_event("push", "refs/tags/v0.1.3", COMMIT, "v0.1.2")
|
||||
|
||||
def test_installed_smoke_has_import_cli_exact_inventory_and_cleanup():
|
||||
inventory = tuple(
|
||||
|
||||
@@ -47,10 +47,10 @@ def test_workflow_actions_are_commit_pinned_and_verify_version_is_project_derive
|
||||
assert len(revision) == 40 and all(char in "0123456789abcdef" for char in revision)
|
||||
verify = VERIFY.read_text()
|
||||
assert "tomllib" in verify and 'RELEASE_VERSION=${RELEASE_VERSION}' in verify
|
||||
assert 'RELEASE_VERSION=v0.1.1' not in verify
|
||||
assert 'RELEASE_VERSION=v0.1.2' not in verify
|
||||
|
||||
|
||||
def test_release_version_and_migration_contract_are_v011_head_0029():
|
||||
def test_release_version_and_migration_contract_are_v012_head_0029():
|
||||
project = (REPO / "pyproject.toml").read_text()
|
||||
config = (REPO / "app/core/config.py").read_text()
|
||||
migrations = sorted(
|
||||
@@ -58,8 +58,8 @@ def test_release_version_and_migration_contract_are_v011_head_0029():
|
||||
for path in (REPO / "app/db/alembic/versions").glob("*.py")
|
||||
if path.name != "__init__.py"
|
||||
)
|
||||
assert 'version = "0.1.1"' in project
|
||||
assert 'app_version: str = "0.1.1"' in config
|
||||
assert 'version = "0.1.2"' in project
|
||||
assert 'app_version: str = "0.1.2"' in config
|
||||
assert len(migrations) == 29
|
||||
assert migrations[-1].startswith("20260814_0029")
|
||||
|
||||
@@ -85,6 +85,9 @@ def test_operations_separate_publication_deployment_migration_and_db_rollback():
|
||||
"Image rollback is **not** database rollback",
|
||||
"read-only root filesystem",
|
||||
"10001:10001",
|
||||
"PortfolioHub v0.1.2 container contract",
|
||||
"v0.1.2 introduces no schema migration",
|
||||
"trex-web v0.2.2 requires this backend contract",
|
||||
):
|
||||
assert value in text
|
||||
for forbidden in (
|
||||
|
||||
@@ -194,6 +194,36 @@ def test_admin_create_custom_nick_and_patch_nick_only_preserve_id_and_increment_
|
||||
assert repo.strategies[strategy_id].nick == "mom-primary"
|
||||
|
||||
|
||||
def test_admin_create_trims_nick() -> None:
|
||||
repo = FakeStrategyRepo()
|
||||
with _repos(repo):
|
||||
created = _client().post(
|
||||
"/v1/admin/strategies",
|
||||
json={"name": "momentum", "nick": " mom-20 ", "config": {"window": 20}},
|
||||
headers=_auth("admin-token"),
|
||||
)
|
||||
assert created.status_code == 201
|
||||
assert created.json()["nick"] == "mom-20"
|
||||
|
||||
|
||||
def test_admin_create_and_patch_reject_whitespace_only_nick() -> None:
|
||||
repo = FakeStrategyRepo()
|
||||
with _repos(repo):
|
||||
created = _client().post(
|
||||
"/v1/admin/strategies",
|
||||
json={"name": "momentum", "nick": " \t ", "config": {"window": 20}},
|
||||
headers=_auth("admin-token"),
|
||||
)
|
||||
changed = _client().patch(
|
||||
"/v1/admin/strategies/active-1",
|
||||
json={"nick": " \n "},
|
||||
headers=_auth("admin-token"),
|
||||
)
|
||||
assert created.status_code == 422
|
||||
assert changed.status_code == 422
|
||||
assert repo.strategies["active-1"].nick == "target_value:base"
|
||||
|
||||
|
||||
def test_admin_patch_omitting_nick_preserves_custom_nick_when_name_and_config_change() -> None:
|
||||
repo = FakeStrategyRepo()
|
||||
with _repos(repo):
|
||||
@@ -227,6 +257,24 @@ def test_admin_create_omitting_nick_retains_legacy_generated_value() -> None:
|
||||
assert created.json()["nick"] == expected
|
||||
|
||||
|
||||
def test_admin_create_and_patch_accept_explicit_null_nick() -> None:
|
||||
repo = FakeStrategyRepo()
|
||||
with _repos(repo):
|
||||
created = _client().post(
|
||||
"/v1/admin/strategies",
|
||||
json={"name": "legacy-null", "nick": None, "config": {}},
|
||||
headers=_auth("admin-token"),
|
||||
)
|
||||
changed = _client().patch(
|
||||
"/v1/admin/strategies/active-1",
|
||||
json={"nick": None},
|
||||
headers=_auth("admin-token"),
|
||||
)
|
||||
assert created.status_code == 201
|
||||
assert changed.status_code == 200
|
||||
assert repo.strategies["active-1"].nick == "target_value:base"
|
||||
|
||||
|
||||
def test_admin_duplicate_nick_returns_conflict() -> None:
|
||||
repo = FakeStrategyRepo()
|
||||
with _repos(repo):
|
||||
|
||||
Reference in New Issue
Block a user