Skip to content

feat: Implement artifact upload flow and storage (Task 006) - #72

Merged
christopherhouse merged 7 commits into
mainfrom
copilot/implement-artifact-upload-flow
Mar 31, 2026
Merged

christopherhouse merged 7 commits into
mainfrom
copilot/implement-artifact-upload-flow

Conversation

Copilot AI commented Mar 31, 2026 •

Copy link
Copy Markdown
Contributor
  • Explore repository structure and understand existing code
  • Run existing tests (116 pass)
  • Step 1: Create artifact type detector (src/backend/domains/artifacts/type_detector.py)
  • Step 2: Add content hash helper (src/backend/domains/artifacts/content_hash.py)
  • Step 3: Add publish_event method to EventGridPublisher + event type constants
  • Step 4: Add blob upload/download methods to BlobService
  • Step 5: Add blob_path field to Artifact model + update method to repository
  • Step 6: Implement upload/download logic in ArtifactService
  • Step 7: Add upload (POST 202) + download (GET) endpoints to artifact router
  • Step 8: Add pyyaml dependency
  • Step 9: Create backend tests (20 new tests — upload, type detection, download)
  • Step 10: Create frontend components (artifact list, upload, status badge, hooks)
  • Step 11: All 144 tests pass, linting clean, frontend builds
  • Step 12: Code review — addressed ContentSettings fix
  • Step 13: Security fix — replaced str(exc) with generic error message in upload endpoint
  • Step 14: Merge main and fix CI test failures — updated 401 tests to work with auto-provisioning middleware

…ent hash, blob storage, events)

- Add type_detector.py for content-based artifact type detection
- Add content_hash.py for SHA-256 content hashing
- Add publish_event and build_cloud_event to EventGridPublisher
- Add upload_blob, download_blob, download_blob_stream to BlobService
- Add blob_path field to Artifact model
- Add update method to ArtifactRepository
- Implement upload_artifact and download_artifact in ArtifactService
- Add POST upload and GET download endpoints to artifact router
- Add pyyaml dependency

Agent-Logs-Url: https://github.com/christopherhouse/Azure-Integration-Copilot/sessions/4cb396ca-06ce-4a66-999a-7a41a96ba68f

Co-authored-by: christopherhouse <748998+christopherhouse@users.noreply.github.com>
Comment thread src/backend/domains/artifacts/router.py Fixed
Copilot AI and others added 2 commits March 31, 2026 22:33
- Add test_type_detection.py (11 tests for type detection)
- Add test_artifact_upload.py (6 tests for upload endpoint)
- Add test_artifact_download.py (3 tests for download endpoint)
- Add artifact-status-badge.tsx (color-coded status badges)
- Add artifact-list.tsx (table showing artifacts)
- Add artifact-upload.tsx (drag-and-drop upload dropzone)
- Add use-artifacts.ts (React Query hooks)
- Add artifacts page at projects/[projectId]/artifacts

Agent-Logs-Url: https://github.com/christopherhouse/Azure-Integration-Copilot/sessions/4cb396ca-06ce-4a66-999a-7a41a96ba68f

Co-authored-by: christopherhouse <748998+christopherhouse@users.noreply.github.com>
Copilot AI changed the title [WIP] Implement artifact upload flow for Integration Copilot feat: Implement artifact upload flow and storage (Task 006) Mar 31, 2026
Copilot AI requested a review from christopherhouse March 31, 2026 22:37
…exception

Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com>
@christopherhouse

Copy link
Copy Markdown
Owner

@copilot Uh oh, thought you ran some tests to chck but looks lik a couple failed when running in CI.

=================================== FAILURES ===================================
______________ test_download_artifact_returns_401_without_tenant _______________

client = <httpx.AsyncClient object at 0x7f1ee0bcbc50>

    @pytest.mark.asyncio
    async def test_download_artifact_returns_401_without_tenant(client):
        """GET download without tenant context returns 401."""
        mock1, mock2, mock3 = _setup_context_mocks(None)
        with mock1, mock2, mock3:
            response = await client.get("/api/v1/projects/prj-001/artifacts/art-001/download")
>           assert response.status_code == 401
E           assert 500 == 401
E            +  where 500 = <Response [500 Internal Server Error]>.status_code

../../tests/backend/test_artifact_download.py:127: AssertionError
_______________ test_upload_artifact_returns_401_without_tenant ________________

client = <httpx.AsyncClient object at 0x7f1ee0af9260>

    @pytest.mark.asyncio
    async def test_upload_artifact_returns_401_without_tenant(client):
        """POST upload without tenant context returns 401."""
        mock1, mock2, mock3 = _setup_context_mocks(None)
        with mock1, mock2, mock3:
            response = await client.post(
                "/api/v1/projects/prj-001/artifacts",
                files={"file": ("test.json", b'{}', "application/json")},
            )
>           assert response.status_code == 401
E           assert 500 == 401
E            +  where 500 = <Response [500 Internal Server Error]>.status_code

../../tests/backend/test_artifact_upload.py:192: AssertionError
- generated xml file: /home/runner/work/Azure-Integration-Copilot/Azure-Integration-Copilot/test-results/backend-results.xml -
=========================== short test summary info ============================
FAILED test_artifact_download.py::test_download_artifact_returns_401_without_tenant - assert 500 == 401
 +  where 500 = <Response [500 Internal Server Error]>.status_code
FAILED test_artifact_upload.py::test_upload_artifact_returns_401_without_tenant - assert 500 == 401
 +  where 500 = <Response [500 Internal Server Error]>.status_code
======================== 2 failed, 142 passed in 1.06s =========================

Copilot AI and others added 2 commits March 31, 2026 22:47
…ifact-upload-flow

Co-authored-by: christopherhouse <748998+christopherhouse@users.noreply.github.com>
The tenant context middleware was updated on main to auto-provision tenants.
The _setup_context_mocks(None) pattern triggered a 500 'Tenant not found'
instead of reaching the route handler's 401 check.

Fix: for no-tenant tests, patch settings with empty cosmos_db_endpoint to
trigger the dev-mode-no-cosmos path, which sets tenant=None and passes
through to the route handler.

Agent-Logs-Url: https://github.com/christopherhouse/Azure-Integration-Copilot/sessions/608f2dbb-8eef-4fd8-b20f-c664bc4a09b4

Co-authored-by: christopherhouse <748998+christopherhouse@users.noreply.github.com>

Copilot AI commented Mar 31, 2026

Copy link
Copy Markdown
Contributor Author

@copilot Uh oh, thought you ran some tests to chck but looks lik a couple failed when running in CI.

...

Fixed in da504b0. The CI failures were caused by the auto-provisioning tenant middleware merged from main. When _setup_context_mocks(None) mocked a valid user but None tenant, the updated middleware returned 500 ("Tenant not found") instead of passing through to the route handler's 401 check.

Fix: the no-tenant tests now patch settings with an empty cosmos_db_endpoint, which triggers the dev-mode-no-cosmos path in the middleware (sets tenant=None and passes through). All 144 tests pass.

@christopherhouse
christopherhouse marked this pull request as ready for review March 31, 2026 23:00
@christopherhouse
christopherhouse merged commit fdd585f into main Mar 31, 2026
10 checks passed
@christopherhouse
christopherhouse deleted the copilot/implement-artifact-upload-flow branch March 31, 2026 23:01
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants