fix: commit semantic repair changes
This commit is contained in:
@@ -1,16 +1,26 @@
|
||||
# [DEF:backend.src.api.routes.clean_release_v2:Module]
|
||||
# @COMPLEXITY: 3
|
||||
# [DEF:CleanReleaseV2Api:Module]
|
||||
# @COMPLEXITY: 4
|
||||
# @PURPOSE: Redesigned clean release API for headless candidate lifecycle.
|
||||
|
||||
from fastapi import APIRouter, Depends, HTTPException, status
|
||||
from typing import List, Dict, Any
|
||||
from datetime import datetime, timezone
|
||||
from ...services.clean_release.approval_service import approve_candidate, reject_candidate
|
||||
from ...services.clean_release.publication_service import publish_candidate, revoke_publication
|
||||
from ...services.clean_release.approval_service import (
|
||||
approve_candidate,
|
||||
reject_candidate,
|
||||
)
|
||||
from ...services.clean_release.publication_service import (
|
||||
publish_candidate,
|
||||
revoke_publication,
|
||||
)
|
||||
from ...services.clean_release.repository import CleanReleaseRepository
|
||||
from ...dependencies import get_clean_release_repository
|
||||
from ...services.clean_release.enums import CandidateStatus
|
||||
from ...models.clean_release import ReleaseCandidate, CandidateArtifact, DistributionManifest
|
||||
from ...models.clean_release import (
|
||||
ReleaseCandidate,
|
||||
CandidateArtifact,
|
||||
DistributionManifest,
|
||||
)
|
||||
from ...services.clean_release.dto import CandidateDTO, ManifestDTO
|
||||
|
||||
router = APIRouter(prefix="/api/v2/clean-release", tags=["Clean Release V2"])
|
||||
@@ -22,6 +32,8 @@ router = APIRouter(prefix="/api/v2/clean-release", tags=["Clean Release V2"])
|
||||
# @RELATION: USES -> [CandidateDTO]
|
||||
class ApprovalRequest(dict):
|
||||
pass
|
||||
|
||||
|
||||
# [/DEF:ApprovalRequest:Class]
|
||||
|
||||
|
||||
@@ -31,6 +43,8 @@ class ApprovalRequest(dict):
|
||||
# @RELATION: USES -> [CandidateDTO]
|
||||
class PublishRequest(dict):
|
||||
pass
|
||||
|
||||
|
||||
# [/DEF:PublishRequest:Class]
|
||||
|
||||
|
||||
@@ -40,8 +54,11 @@ class PublishRequest(dict):
|
||||
# @RELATION: USES -> [CandidateDTO]
|
||||
class RevokeRequest(dict):
|
||||
pass
|
||||
|
||||
|
||||
# [/DEF:RevokeRequest:Class]
|
||||
|
||||
|
||||
# [DEF:register_candidate:Function]
|
||||
# @COMPLEXITY: 3
|
||||
# @PURPOSE: Register a new release candidate.
|
||||
@@ -50,10 +67,12 @@ class RevokeRequest(dict):
|
||||
# @RETURN: CandidateDTO
|
||||
# @RELATION: CALLS -> [CleanReleaseRepository.save_candidate]
|
||||
# @RELATION: USES -> [CandidateDTO]
|
||||
@router.post("/candidates", response_model=CandidateDTO, status_code=status.HTTP_201_CREATED)
|
||||
@router.post(
|
||||
"/candidates", response_model=CandidateDTO, status_code=status.HTTP_201_CREATED
|
||||
)
|
||||
async def register_candidate(
|
||||
payload: Dict[str, Any],
|
||||
repository: CleanReleaseRepository = Depends(get_clean_release_repository)
|
||||
repository: CleanReleaseRepository = Depends(get_clean_release_repository),
|
||||
):
|
||||
candidate = ReleaseCandidate(
|
||||
id=payload["id"],
|
||||
@@ -61,7 +80,7 @@ async def register_candidate(
|
||||
source_snapshot_ref=payload["source_snapshot_ref"],
|
||||
created_by=payload["created_by"],
|
||||
created_at=datetime.now(timezone.utc),
|
||||
status=CandidateStatus.DRAFT.value
|
||||
status=CandidateStatus.DRAFT.value,
|
||||
)
|
||||
repository.save_candidate(candidate)
|
||||
return CandidateDTO(
|
||||
@@ -70,10 +89,13 @@ async def register_candidate(
|
||||
source_snapshot_ref=candidate.source_snapshot_ref,
|
||||
created_at=candidate.created_at,
|
||||
created_by=candidate.created_by,
|
||||
status=CandidateStatus(candidate.status)
|
||||
status=CandidateStatus(candidate.status),
|
||||
)
|
||||
|
||||
|
||||
# [/DEF:register_candidate:Function]
|
||||
|
||||
|
||||
# [DEF:import_artifacts:Function]
|
||||
# @COMPLEXITY: 3
|
||||
# @PURPOSE: Associate artifacts with a release candidate.
|
||||
@@ -84,27 +106,30 @@ async def register_candidate(
|
||||
async def import_artifacts(
|
||||
candidate_id: str,
|
||||
payload: Dict[str, Any],
|
||||
repository: CleanReleaseRepository = Depends(get_clean_release_repository)
|
||||
repository: CleanReleaseRepository = Depends(get_clean_release_repository),
|
||||
):
|
||||
candidate = repository.get_candidate(candidate_id)
|
||||
if not candidate:
|
||||
raise HTTPException(status_code=404, detail="Candidate not found")
|
||||
|
||||
|
||||
for art_data in payload.get("artifacts", []):
|
||||
artifact = CandidateArtifact(
|
||||
id=art_data["id"],
|
||||
candidate_id=candidate_id,
|
||||
path=art_data["path"],
|
||||
sha256=art_data["sha256"],
|
||||
size=art_data["size"]
|
||||
size=art_data["size"],
|
||||
)
|
||||
# In a real repo we'd have save_artifact
|
||||
# repository.save_artifact(artifact)
|
||||
pass
|
||||
|
||||
|
||||
return {"status": "success"}
|
||||
|
||||
|
||||
# [/DEF:import_artifacts:Function]
|
||||
|
||||
|
||||
# [DEF:build_manifest:Function]
|
||||
# @COMPLEXITY: 3
|
||||
# @PURPOSE: Generate distribution manifest for a candidate.
|
||||
@@ -113,15 +138,19 @@ async def import_artifacts(
|
||||
# @RETURN: ManifestDTO
|
||||
# @RELATION: CALLS -> [CleanReleaseRepository.save_manifest]
|
||||
# @RELATION: CALLS -> [CleanReleaseRepository.get_candidate]
|
||||
@router.post("/candidates/{candidate_id}/manifests", response_model=ManifestDTO, status_code=status.HTTP_201_CREATED)
|
||||
@router.post(
|
||||
"/candidates/{candidate_id}/manifests",
|
||||
response_model=ManifestDTO,
|
||||
status_code=status.HTTP_201_CREATED,
|
||||
)
|
||||
async def build_manifest(
|
||||
candidate_id: str,
|
||||
repository: CleanReleaseRepository = Depends(get_clean_release_repository)
|
||||
repository: CleanReleaseRepository = Depends(get_clean_release_repository),
|
||||
):
|
||||
candidate = repository.get_candidate(candidate_id)
|
||||
if not candidate:
|
||||
raise HTTPException(status_code=404, detail="Candidate not found")
|
||||
|
||||
|
||||
manifest = DistributionManifest(
|
||||
id=f"manifest-{candidate_id}",
|
||||
candidate_id=candidate_id,
|
||||
@@ -131,10 +160,10 @@ async def build_manifest(
|
||||
created_by="system",
|
||||
created_at=datetime.now(timezone.utc),
|
||||
source_snapshot_ref=candidate.source_snapshot_ref,
|
||||
content_json={"items": [], "summary": {}}
|
||||
content_json={"items": [], "summary": {}},
|
||||
)
|
||||
repository.save_manifest(manifest)
|
||||
|
||||
|
||||
return ManifestDTO(
|
||||
id=manifest.id,
|
||||
candidate_id=manifest.candidate_id,
|
||||
@@ -144,10 +173,13 @@ async def build_manifest(
|
||||
created_at=manifest.created_at,
|
||||
created_by=manifest.created_by,
|
||||
source_snapshot_ref=manifest.source_snapshot_ref,
|
||||
content_json=manifest.content_json
|
||||
content_json=manifest.content_json,
|
||||
)
|
||||
|
||||
|
||||
# [/DEF:build_manifest:Function]
|
||||
|
||||
|
||||
# [DEF:approve_candidate_endpoint:Function]
|
||||
# @COMPLEXITY: 3
|
||||
# @PURPOSE: Endpoint to record candidate approval.
|
||||
@@ -167,9 +199,13 @@ async def approve_candidate_endpoint(
|
||||
comment=payload.get("comment"),
|
||||
)
|
||||
except Exception as exc: # noqa: BLE001
|
||||
raise HTTPException(status_code=409, detail={"message": str(exc), "code": "APPROVAL_GATE_ERROR"})
|
||||
raise HTTPException(
|
||||
status_code=409, detail={"message": str(exc), "code": "APPROVAL_GATE_ERROR"}
|
||||
)
|
||||
|
||||
return {"status": "ok", "decision": decision.decision, "decision_id": decision.id}
|
||||
|
||||
|
||||
# [/DEF:approve_candidate_endpoint:Function]
|
||||
|
||||
|
||||
@@ -192,9 +228,13 @@ async def reject_candidate_endpoint(
|
||||
comment=payload.get("comment"),
|
||||
)
|
||||
except Exception as exc: # noqa: BLE001
|
||||
raise HTTPException(status_code=409, detail={"message": str(exc), "code": "APPROVAL_GATE_ERROR"})
|
||||
raise HTTPException(
|
||||
status_code=409, detail={"message": str(exc), "code": "APPROVAL_GATE_ERROR"}
|
||||
)
|
||||
|
||||
return {"status": "ok", "decision": decision.decision, "decision_id": decision.id}
|
||||
|
||||
|
||||
# [/DEF:reject_candidate_endpoint:Function]
|
||||
|
||||
|
||||
@@ -218,7 +258,10 @@ async def publish_candidate_endpoint(
|
||||
publication_ref=payload.get("publication_ref"),
|
||||
)
|
||||
except Exception as exc: # noqa: BLE001
|
||||
raise HTTPException(status_code=409, detail={"message": str(exc), "code": "PUBLICATION_GATE_ERROR"})
|
||||
raise HTTPException(
|
||||
status_code=409,
|
||||
detail={"message": str(exc), "code": "PUBLICATION_GATE_ERROR"},
|
||||
)
|
||||
|
||||
return {
|
||||
"status": "ok",
|
||||
@@ -227,12 +270,16 @@ async def publish_candidate_endpoint(
|
||||
"candidate_id": publication.candidate_id,
|
||||
"report_id": publication.report_id,
|
||||
"published_by": publication.published_by,
|
||||
"published_at": publication.published_at.isoformat() if publication.published_at else None,
|
||||
"published_at": publication.published_at.isoformat()
|
||||
if publication.published_at
|
||||
else None,
|
||||
"target_channel": publication.target_channel,
|
||||
"publication_ref": publication.publication_ref,
|
||||
"status": publication.status,
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
# [/DEF:publish_candidate_endpoint:Function]
|
||||
|
||||
|
||||
@@ -254,7 +301,10 @@ async def revoke_publication_endpoint(
|
||||
comment=payload.get("comment"),
|
||||
)
|
||||
except Exception as exc: # noqa: BLE001
|
||||
raise HTTPException(status_code=409, detail={"message": str(exc), "code": "PUBLICATION_GATE_ERROR"})
|
||||
raise HTTPException(
|
||||
status_code=409,
|
||||
detail={"message": str(exc), "code": "PUBLICATION_GATE_ERROR"},
|
||||
)
|
||||
|
||||
return {
|
||||
"status": "ok",
|
||||
@@ -263,12 +313,16 @@ async def revoke_publication_endpoint(
|
||||
"candidate_id": publication.candidate_id,
|
||||
"report_id": publication.report_id,
|
||||
"published_by": publication.published_by,
|
||||
"published_at": publication.published_at.isoformat() if publication.published_at else None,
|
||||
"published_at": publication.published_at.isoformat()
|
||||
if publication.published_at
|
||||
else None,
|
||||
"target_channel": publication.target_channel,
|
||||
"publication_ref": publication.publication_ref,
|
||||
"status": publication.status,
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
# [/DEF:revoke_publication_endpoint:Function]
|
||||
|
||||
# [/DEF:backend.src.api.routes.clean_release_v2:Module]
|
||||
# [/DEF:CleanReleaseV2Api:Module]
|
||||
|
||||
Reference in New Issue
Block a user