feat: add CSV export endpoint for alerts (#521)#577
Merged
Conversation
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## main #577 +/- ##
==========================================
+ Coverage 88.75% 89.92% +1.17%
==========================================
Files 52 55 +3
Lines 2196 2451 +255
==========================================
+ Hits 1949 2204 +255
Misses 247 247
Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
Add `GET /alerts/export?from_date=...&to_date=...` returning a CSV with columns id, lat, lon, started_at, last_seen_at, scoped to the caller's organization. Filters on `started_at` within the inclusive UTC window.
Add a test that exports an alert with NULL coordinates and asserts the CSV renders them as empty cells, exercising the previously uncovered None branches in _iter_alerts_csv.
…tch coverage Lines immediately following an `await` are mishandled by the project's async coverage tracing, leaving 3 lines reported as uncovered even though the happy-path test executes them. Move the response build into a sync helper and inline the awaited fetch into the return statement so the await is part of the line that is already marked as covered. No behavioral change.
c4bbb4d to
d9b889b
Compare
fe51
previously approved these changes
May 6, 2026
Member
fe51
left a comment
There was a problem hiding this comment.
Hi Alexis, thanks a lot for this PR and sorry for the review delay !
Tested it works, and reviewed the code !
This is clean, and quite efficient (have not tested to extract for long time period but the content is light)
I have juste added one remark/question in tests but non blocking to me !
returned_ids == {a_in.id} is set equality and already implies the other
ids are absent. Per review feedback from @fe51.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
GET /alerts/export?from_date=YYYY-MM-DD&to_date=YYYY-MM-DDreturning a CSV streamed download with columnsid, lat, lon, started_at, last_seen_at.started_atwithin the inclusive UTC window[from_date 00:00:00, to_date 23:59:59.999999]and scopes results to the caller'sorganization_id.Implementation notes
/{alert_id}inalerts.pyso FastAPI doesn't try to parseexportas anintpath param.csv+io.StringIO+StreamingResponse(no new dependencies; pandas not needed for this shape).select(Alert).where(...)mirrorsfetch_alerts_from_date; nothing added to the CRUD layer.app.core.time.utcnow), so the bounds are built withouttzinfo.to_date < from_date, 401 when unauthenticated, 200 with header-only body for an empty range.Test plan
pytest tests/endpoints/test_alerts.py -v(all 10 tests, including 6 new export tests, pass)to_date < from_date→ 422ruff 0.11.9 checkandruff 0.11.9 format --checkpasscurlthe new endpoint with a valid token and confirm the CSV opens cleanly