fix(task-020): support s3 assets in publishing dry-run and commit

This commit is contained in:
2026-05-22 02:10:33 +03:00
parent 7667819c46
commit 5ea0d5978a
4 changed files with 161 additions and 6 deletions
@@ -0,0 +1,55 @@
# Task 020: Demo Publishing S3 Assets Compatibility
Development description: Fix publish dry-run/commit flow so approved assets stored in object storage (`s3://...`) are correctly bundled for Git publishing in demo Compose mode.
## Implementation Details
- Root cause:
- Publishing bundle loader accepted only `file://` asset URLs.
- In Compose demo mode, approved assets are stored in MinIO and exposed as `s3://bucket/key`.
- Required backend changes:
- Extend object storage client with read capability (`get_bytes`).
- Update publishing asset collector to support both `file://` and `s3://` sources.
- Use `asset.object_key` (or URL-derived key fallback) for object-storage fetch.
- Preserve existing manifest structure and publish workflow statuses.
- Validation:
- Add regression test proving dry-run works when approved assets use `s3://` URLs with valid object keys.
## Public Interface
- No API contract changes.
- Existing endpoints must behave identically, except they no longer fail on `s3://` approved assets:
- `POST /api/articles/{article_id}/publishing/dry-run`
- `POST /api/articles/{article_id}/publishing/create-commit`
## Acceptance Criteria
- [x] Dry-run no longer fails with `Approved asset file is unavailable: s3://...` when asset object exists.
- [x] Publish bundle copies approved assets from object storage into target repo workspace.
- [x] Existing file-based publishing tests continue to pass.
- [x] New regression test covers `s3://` asset URL compatibility.
## Verification
- Run publishing integration suite:
- `PYTHONPATH=/private/tmp/pupline-backend-deps python3 -m unittest apps/backend/tests/integration/test_publishing_git_flow_public_api.py`
- Run task 019 demo smoke:
- `PYTHONPATH=/private/tmp/pupline-backend-deps python3 -m unittest apps/backend/tests/integration/test_end_to_end_demo_stack_smoke_public_api.py`
- Run clean compose checklist manually (`down -v` -> `up --build`) and verify publish dry-run/commit steps.
## Result
- Status: Implemented.
- Files changed:
- `apps/backend/src/infrastructure/object_storage.py`
- `apps/backend/src/application/publishing.py`
- `apps/backend/tests/integration/test_publishing_git_flow_public_api.py`
- Green evidence:
- `PYTHONPATH=/private/tmp/pupline-backend-deps python3 -m unittest apps/backend/tests/integration/test_publishing_git_flow_public_api.py` -> `Ran 7 tests ... OK`
- `PYTHONPATH=/private/tmp/pupline-backend-deps python3 -m unittest apps/backend/tests/integration/test_end_to_end_demo_stack_smoke_public_api.py` -> `Ran 1 test ... OK`
- Clean compose check (`docker compose down -v` -> `docker compose up --build -d`) + manual public API flow:
- final approval: `200 PUBLISH_DRY_RUN_REQUIRED`
- publishing dry-run: `201 PUBLISH_COMMIT_READY`
- create-commit: `201 PUBLISH_COMMIT_CREATED`
- Refactor notes:
- Added storage read path to reuse existing object storage abstractions instead of introducing publish-specific S3 calls.