feat(task-017): implement git publishing dry-run and commit flow
This commit is contained in:
@@ -32,6 +32,7 @@ from src.domain.contracts import (
|
||||
PlanReviewStatus,
|
||||
PlanSectionSummary,
|
||||
PlanSummary,
|
||||
PublishCommitSummary,
|
||||
PublishingRules,
|
||||
PublishingStatus,
|
||||
ResearchArtifactManifestSummary,
|
||||
@@ -67,6 +68,7 @@ class BackendRepository:
|
||||
self.content_reviews = ContentReviewsRepository(self)
|
||||
self.assets = AssetsRepository(self)
|
||||
self.research_manifests = ResearchManifestsRepository(self)
|
||||
self.publish_commits = PublishCommitsRepository(self)
|
||||
self.evidence_items = EvidenceItemsRepository(self)
|
||||
self.claims = ClaimsRepository(self)
|
||||
self.agent_jobs = AgentJobsRepository(self)
|
||||
@@ -568,6 +570,26 @@ class ArticlesRepository:
|
||||
|
||||
return self.get(article_id)
|
||||
|
||||
def update_publishing_status(
|
||||
self,
|
||||
*,
|
||||
article_id: UUID,
|
||||
publishing_status: PublishingStatus,
|
||||
updated_at: datetime,
|
||||
) -> ArticleSummary:
|
||||
placeholder = self._repository.placeholder()
|
||||
with self._repository.connection() as connection:
|
||||
connection.execute(
|
||||
f"""
|
||||
UPDATE articles
|
||||
SET publishing_status = {placeholder}, updated_at = {placeholder}
|
||||
WHERE id = {placeholder}
|
||||
""",
|
||||
(publishing_status.value, _datetime_value(updated_at), str(article_id)),
|
||||
)
|
||||
|
||||
return self.get(article_id)
|
||||
|
||||
def create_workflow_event(
|
||||
self,
|
||||
*,
|
||||
@@ -2049,6 +2071,150 @@ class ResearchManifestsRepository:
|
||||
return _research_manifest_from_row(row)
|
||||
|
||||
|
||||
class PublishCommitsRepository:
|
||||
def __init__(self, repository: BackendRepository) -> None:
|
||||
self._repository = repository
|
||||
|
||||
def create(
|
||||
self,
|
||||
*,
|
||||
article_id: UUID,
|
||||
target_site_id: UUID,
|
||||
repository_url: str,
|
||||
branch: str,
|
||||
commit_sha: str | None,
|
||||
content_bundle_manifest: JsonObject,
|
||||
status: PublishingStatus,
|
||||
deployment_status: str | None,
|
||||
created_at: datetime,
|
||||
) -> PublishCommitSummary:
|
||||
publish_commit_id = uuid4()
|
||||
placeholder = self._repository.placeholder()
|
||||
json_cast = self._repository.json_cast()
|
||||
with self._repository.connection() as connection:
|
||||
connection.execute(
|
||||
f"""
|
||||
INSERT INTO publish_commits (
|
||||
id,
|
||||
article_id,
|
||||
target_site_id,
|
||||
repository_url,
|
||||
branch,
|
||||
commit_sha,
|
||||
content_bundle_manifest,
|
||||
status,
|
||||
deployment_status,
|
||||
created_at
|
||||
)
|
||||
VALUES (
|
||||
{placeholder},
|
||||
{placeholder},
|
||||
{placeholder},
|
||||
{placeholder},
|
||||
{placeholder},
|
||||
{placeholder},
|
||||
{placeholder}{json_cast},
|
||||
{placeholder},
|
||||
{placeholder},
|
||||
{placeholder}
|
||||
)
|
||||
""",
|
||||
(
|
||||
str(publish_commit_id),
|
||||
str(article_id),
|
||||
str(target_site_id),
|
||||
repository_url,
|
||||
branch,
|
||||
commit_sha,
|
||||
_json_value(content_bundle_manifest),
|
||||
status.value,
|
||||
deployment_status,
|
||||
_datetime_value(created_at),
|
||||
),
|
||||
)
|
||||
|
||||
return self.get(publish_commit_id)
|
||||
|
||||
def get(self, publish_commit_id: UUID) -> PublishCommitSummary:
|
||||
placeholder = self._repository.placeholder()
|
||||
with self._repository.connection() as connection:
|
||||
row = connection.execute(
|
||||
f"""
|
||||
SELECT {self._select_columns()}
|
||||
FROM publish_commits
|
||||
WHERE id = {placeholder}
|
||||
""",
|
||||
(str(publish_commit_id),),
|
||||
).fetchone()
|
||||
|
||||
if row is None:
|
||||
raise LookupError(f"Publish commit not found: {publish_commit_id}")
|
||||
return _publish_commit_from_row(row)
|
||||
|
||||
def list_for_article(self, article_id: UUID) -> list[PublishCommitSummary]:
|
||||
placeholder = self._repository.placeholder()
|
||||
with self._repository.connection() as connection:
|
||||
rows = connection.execute(
|
||||
f"""
|
||||
SELECT {self._select_columns()}
|
||||
FROM publish_commits
|
||||
WHERE article_id = {placeholder}
|
||||
ORDER BY created_at DESC, id DESC
|
||||
""",
|
||||
(str(article_id),),
|
||||
).fetchall()
|
||||
|
||||
return [_publish_commit_from_row(row) for row in rows]
|
||||
|
||||
def latest_for_article(self, article_id: UUID) -> PublishCommitSummary | None:
|
||||
commits = self.list_for_article(article_id)
|
||||
if not commits:
|
||||
return None
|
||||
return commits[0]
|
||||
|
||||
def latest_for_article_with_statuses(
|
||||
self,
|
||||
article_id: UUID,
|
||||
*,
|
||||
statuses: set[PublishingStatus],
|
||||
) -> PublishCommitSummary | None:
|
||||
status_values = [status.value for status in statuses]
|
||||
if not status_values:
|
||||
return None
|
||||
placeholder = self._repository.placeholder()
|
||||
status_placeholders = ", ".join([placeholder] * len(status_values))
|
||||
with self._repository.connection() as connection:
|
||||
row = connection.execute(
|
||||
f"""
|
||||
SELECT {self._select_columns()}
|
||||
FROM publish_commits
|
||||
WHERE article_id = {placeholder}
|
||||
AND status IN ({status_placeholders})
|
||||
ORDER BY created_at DESC, id DESC
|
||||
LIMIT 1
|
||||
""",
|
||||
(str(article_id), *status_values),
|
||||
).fetchone()
|
||||
|
||||
if row is None:
|
||||
return None
|
||||
return _publish_commit_from_row(row)
|
||||
|
||||
def _select_columns(self) -> str:
|
||||
return """
|
||||
id,
|
||||
article_id,
|
||||
target_site_id,
|
||||
repository_url,
|
||||
branch,
|
||||
commit_sha,
|
||||
content_bundle_manifest,
|
||||
status,
|
||||
deployment_status,
|
||||
created_at
|
||||
"""
|
||||
|
||||
|
||||
class EvidenceItemsRepository:
|
||||
def __init__(self, repository: BackendRepository) -> None:
|
||||
self._repository = repository
|
||||
@@ -3066,6 +3232,21 @@ def _research_manifest_from_row(row: Any) -> ResearchArtifactManifestSummary:
|
||||
)
|
||||
|
||||
|
||||
def _publish_commit_from_row(row: Any) -> PublishCommitSummary:
|
||||
return PublishCommitSummary(
|
||||
id=_row_value(row, "id"),
|
||||
article_id=_row_value(row, "article_id"),
|
||||
target_site_id=_row_value(row, "target_site_id"),
|
||||
repository_url=_row_value(row, "repository_url"),
|
||||
branch=_row_value(row, "branch"),
|
||||
commit_sha=_row_value(row, "commit_sha"),
|
||||
content_bundle_manifest=_json_from_row(row, "content_bundle_manifest"),
|
||||
status=_row_value(row, "status"),
|
||||
deployment_status=_row_value(row, "deployment_status"),
|
||||
created_at=_row_value(row, "created_at"),
|
||||
)
|
||||
|
||||
|
||||
def _evidence_from_row(row: Any) -> EvidenceSummary:
|
||||
return EvidenceSummary(
|
||||
id=_row_value(row, "id"),
|
||||
|
||||
Reference in New Issue
Block a user