Implement task 006 site config versioning and audit events
This commit is contained in:
@@ -0,0 +1,134 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import os
|
||||
import tempfile
|
||||
import sys
|
||||
from collections.abc import Iterator
|
||||
from contextlib import contextmanager
|
||||
from pathlib import Path
|
||||
import unittest
|
||||
from uuid import UUID
|
||||
|
||||
BACKEND_ROOT = Path(__file__).resolve().parents[2]
|
||||
sys.path.insert(0, str(BACKEND_ROOT))
|
||||
|
||||
|
||||
@contextmanager
|
||||
def repository_dsn() -> Iterator[str]:
|
||||
configured = os.environ.get("PIPELINE_TEST_DATABASE_DSN")
|
||||
if configured:
|
||||
yield configured
|
||||
return
|
||||
|
||||
with tempfile.TemporaryDirectory() as directory:
|
||||
yield f"sqlite:///{Path(directory) / 'pipeline-audit.db'}"
|
||||
|
||||
|
||||
class ScriptConfigAuditTest(unittest.TestCase):
|
||||
def test_rollback_writes_audit_event(self) -> None:
|
||||
with repository_dsn() as dsn:
|
||||
from src.application.auth import get_current_user_by_email
|
||||
from src.application.seed_data import seed_reference_data
|
||||
from src.application.site_config import (
|
||||
create_script_config_version,
|
||||
create_target_site,
|
||||
rollback_script_config_version,
|
||||
)
|
||||
from src.domain.contracts import (
|
||||
PublishingRules,
|
||||
ScriptConfigVersionCreateRequest,
|
||||
TargetSiteConfigCreateRequest,
|
||||
)
|
||||
from src.infrastructure.repositories import open_backend_repository
|
||||
|
||||
repository = open_backend_repository(dsn)
|
||||
repository.setup()
|
||||
seed_reference_data(repository)
|
||||
admin = get_current_user_by_email(repository, "admin@example.com")
|
||||
site = create_target_site(
|
||||
repository,
|
||||
TargetSiteConfigCreateRequest(
|
||||
name="Audit Test Site",
|
||||
slug="audit-site",
|
||||
publishing_type="git_next",
|
||||
default_language="en",
|
||||
brand_voice="Audit-focused publishing profile.",
|
||||
audience="QA operations team.",
|
||||
seo_rules={"primary_keyword_required": True},
|
||||
visual_rules={"hero_style": "technical"},
|
||||
source_rules={"minimum_sources": 1},
|
||||
publishing_rules=PublishingRules(
|
||||
repository_url="git@github.com:example/audit-site.git",
|
||||
production_branch="main",
|
||||
content_format="mdx",
|
||||
content_path_template="content/articles/{slug}.mdx",
|
||||
asset_path_template="public/articles/{slug}/{filename}",
|
||||
frontmatter_mapping={"title": "title"},
|
||||
dry_run_renderer="next-mdx",
|
||||
),
|
||||
active_script_config_version_id=None,
|
||||
),
|
||||
).site
|
||||
|
||||
initial = create_script_config_version(
|
||||
repository,
|
||||
site_id=site.id,
|
||||
current_user=admin,
|
||||
request=self._script_version_payload(summary="initial", activate=True),
|
||||
).version
|
||||
candidate = create_script_config_version(
|
||||
repository,
|
||||
site_id=site.id,
|
||||
current_user=admin,
|
||||
request=self._script_version_payload(
|
||||
summary="candidate",
|
||||
activate=True,
|
||||
rollback_target_version_id=initial.id,
|
||||
),
|
||||
).version
|
||||
|
||||
rolled_back = rollback_script_config_version(
|
||||
repository,
|
||||
site_id=site.id,
|
||||
version_id=initial.id,
|
||||
current_user=admin,
|
||||
)
|
||||
self.assertEqual(str(initial.id), str(rolled_back.version.id))
|
||||
|
||||
rollback_events = [
|
||||
event
|
||||
for event in repository.script_config_version_events.list_for_site(site.id)
|
||||
if event["event_type"] == "SCRIPT_CONFIG_VERSION_ROLLBACK"
|
||||
]
|
||||
self.assertEqual(1, len(rollback_events))
|
||||
rollback_event = rollback_events[0]
|
||||
self.assertEqual(str(site.id), str(rollback_event["target_site_id"]))
|
||||
self.assertEqual(str(initial.id), str(rollback_event["version_id"]))
|
||||
self.assertEqual(str(admin.id), str(rollback_event["actor_user_id"]))
|
||||
self.assertEqual(
|
||||
str(candidate.id),
|
||||
rollback_event["payload"]["rollback_target_version_id"],
|
||||
)
|
||||
|
||||
active_site = repository.target_sites.get_by_id(site.id)
|
||||
self.assertEqual(initial.id, active_site.active_script_config_version_id)
|
||||
|
||||
def _script_version_payload(
|
||||
self,
|
||||
summary: str,
|
||||
activate: bool = False,
|
||||
rollback_target_version_id: UUID | None = None,
|
||||
) -> ScriptConfigVersionCreateRequest:
|
||||
payload = ScriptConfigVersionCreateRequest(
|
||||
publishing_yaml="target:\n repo: audit\n",
|
||||
transform_script="export function transformArticle(article) { return article; }",
|
||||
diff={"summary": summary},
|
||||
activate=activate,
|
||||
)
|
||||
if rollback_target_version_id is not None:
|
||||
payload.rollback_target_version_id = rollback_target_version_id
|
||||
return payload
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
Reference in New Issue
Block a user