Release v0.1.2

This commit is contained in:
2026-06-25 19:58:20 +02:00
parent 39ad3500e2
commit 23318c709a
98 changed files with 3432 additions and 2339 deletions

View File

@@ -31,13 +31,7 @@ from govoplan_campaign.backend.messages.builder import build_campaign_messages
from govoplan_campaign.backend.messages.models import MessageDraft
from govoplan_campaign.backend.sending.execution import create_execution_snapshot
from govoplan_campaign.backend.campaign.models import CampaignConfig
from govoplan_mail.backend.mail_profiles import materialize_campaign_mail_profile_config
from govoplan_files.backend.storage.campaign_usage import record_campaign_attachment_uses_for_jobs
from govoplan_files.backend.storage.campaign_attachments import (
annotate_built_messages_with_managed_files,
prepared_campaign_snapshot,
public_attachment_summary_payload,
)
from govoplan_campaign.backend.integrations import files_integration, mail_integration
RUNTIME_DIR = Path(__file__).resolve().parents[3] / "runtime"
CAMPAIGN_SNAPSHOT_DIR = RUNTIME_DIR / "campaign_snapshots"
@@ -64,7 +58,7 @@ def load_campaign_config_from_json(
owner_user_id: str | None = None,
owner_group_id: str | None = None,
) -> CampaignConfig:
materialized = materialize_campaign_mail_profile_config(
materialized = mail_integration().materialize_campaign_mail_profile_config(
session,
tenant_id=tenant_id,
raw_json=raw_json,
@@ -274,7 +268,8 @@ def validate_campaign_version(
raise CampaignPersistenceError(f"{lock_label.capitalize()} campaign versions cannot be validated. Unlock or create an editable copy instead.")
if check_files:
with prepared_campaign_snapshot(
files = files_integration()
with files.prepared_campaign_snapshot(
session,
tenant_id=tenant_id,
campaign_id=campaign.id,
@@ -379,7 +374,7 @@ def _job_from_message(
"bounce_to": [item.model_dump(mode="json") for item in message.bounce_to],
"disposition_notification_to": [item.model_dump(mode="json") for item in message.disposition_notification_to],
},
resolved_attachments=[public_attachment_summary_payload(item) for item in message.attachments],
resolved_attachments=[files_integration().public_attachment_summary_payload(item) for item in message.attachments],
issues_snapshot=[item.model_dump(mode="json") for item in message.issues],
last_error="; ".join(issue.message for issue in message.issues if issue.severity == "error") or None,
)
@@ -405,7 +400,8 @@ def build_campaign_version(
_ensure_version_validated_and_locked(version)
output_dir = BUILD_OUTPUT_DIR / campaign.id / version.id
with prepared_campaign_snapshot(
files = files_integration()
with files.prepared_campaign_snapshot(
session,
tenant_id=tenant_id,
campaign_id=campaign.id,
@@ -416,11 +412,11 @@ def build_campaign_version(
managed_raw = load_campaign_json(prepared.path)
managed_config = load_campaign_config_from_json(session, tenant_id=tenant_id, raw_json=managed_raw, campaign_id=campaign.id)
result = build_campaign_messages(managed_config, campaign_file=prepared.path, output_dir=output_dir, write_eml=write_eml)
annotate_built_messages_with_managed_files(result.built_messages, prepared.managed_files_by_local_path)
files.annotate_built_messages_with_managed_files(result.built_messages, prepared.managed_files_by_local_path)
report_json = result.report.model_dump(mode="json", by_alias=True)
for message_payload, message in zip(report_json.get("messages", []), result.report.messages, strict=False):
if isinstance(message_payload, dict):
message_payload["attachments"] = [public_attachment_summary_payload(item) for item in message.attachments]
message_payload["attachments"] = [files.public_attachment_summary_payload(item) for item in message.attachments]
report_json["built_at"] = datetime.now(UTC).isoformat()
report_json["build_token"] = uuid4().hex
report_json.update({
@@ -459,17 +455,18 @@ def build_campaign_version(
# records in bulk. This avoids one flush plus several metadata queries per
# recipient for large campaigns.
session.flush()
record_campaign_attachment_uses_for_jobs(
files.record_campaign_attachment_uses_for_jobs(
session,
[job for job, _message in job_build_pairs],
stage="built",
)
if not managed_config.server.smtp:
runtime_smtp = managed_config.server.runtime_smtp_config()
if not runtime_smtp:
raise CampaignPersistenceError("Campaign has no SMTP configuration; an execution snapshot cannot be created")
execution_snapshot, execution_snapshot_hash = create_execution_snapshot(
version,
smtp=managed_config.server.smtp,
imap=managed_config.server.imap,
smtp=runtime_smtp,
imap=managed_config.server.runtime_imap_config(),
delivery=managed_config.delivery,
jobs=[job for job, _message in job_build_pairs],
build_summary=report_json,