fix(backend): @field_serializer für BatchRead.created_at ergänzt (UTC/Z-Suffix)#97
Conversation
…/Z-Suffix)
BatchRead lieferte created_at als naiven ISO-String ohne TZ-Suffix
(`2026-06-02T09:46:18.701971`). Der Go-RFC3339-Parser im Hangar-Client
lehnte das ab: `cannot parse "" as "Z07:00"`. Folge: Hangar zeigte
"Hub aktuell nicht erreichbar" obwohl der Hub erreichbar war.
Fix: @field_serializer("created_at") mit serialize_datetime_utc analog
zu TemplateRead und JobRead. Tests in
tests/unit/schemas/test_batch_read.py (RED→GREEN, TDD).
Summary of ChangesHello, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed! Dieser Pull Request behebt einen Serialisierungsfehler in der 'BatchRead'-Schema-Definition. Bisher wurden Zeitstempel als naive ISO-Strings ohne Zeitzonen-Suffix ausgegeben, was zu Fehlern beim Parsen durch den Go-basierten Hangar-Client führte. Durch die Verwendung eines bestehenden Serialisierungs-Helpers wird nun sichergestellt, dass alle Zeitstempel ein korrektes 'Z'-Suffix erhalten, was die Interoperabilität zwischen Backend und Client sicherstellt. Highlights
Using Gemini Code AssistThe full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips. Invoking Gemini You can request assistance from Gemini at any point by creating a comment using either
Customization To customize the Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a Limitations & Feedback Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counterproductive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for GitHub and other Google products, sign up here. Footnotes
|
There was a problem hiding this comment.
Code Review
This pull request introduces a custom field serializer for the created_at field in BatchRead to ensure datetime values are serialized with a UTC timezone offset, preventing decoding issues with Go's strict RFC3339 parser. It also adds unit tests to verify this serialization behavior and test BatchSummary terminal logic. The review feedback suggests improving the test assertions by using datetime.datetime.fromisoformat() to validate the presence of timezone information instead of performing manual string slicing.
Important
The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.
| created_at_str: str = dumped["created_at"] | ||
| # Muss entweder mit Z oder +HH:MM enden — nie mit einer reinen Zeitangabe | ||
| has_tz = created_at_str.endswith("Z") or ( | ||
| len(created_at_str) >= 6 and created_at_str[-6] in ("+", "-") | ||
| ) | ||
| assert has_tz, f"Kein TZ-Suffix in created_at: {created_at_str!r}" |
There was a problem hiding this comment.
Anstatt den String manuell zu parsen und auf Suffixe wie Z oder +/- an bestimmten Positionen zu prüfen, kann die Zeitzonen-Validierung robuster und eleganter über datetime.datetime.fromisoformat() gelöst werden. Wenn das Ergebnis ein tzinfo besitzt, ist eine Zeitzone vorhanden.
created_at_str: str = dumped["created_at"]
parsed_dt = datetime.datetime.fromisoformat(created_at_str)
assert parsed_dt.tzinfo is not None, f"Kein TZ-Suffix in created_at: {created_at_str!r}"| val: str = data[field] | ||
| assert "Z" in val or "+" in val or (len(val) >= 6 and val[-6] == "-"), ( | ||
| f"Feld {field!r} hat keinen TZ-Suffix: {val!r}" | ||
| ) |
There was a problem hiding this comment.
Auch hier lässt sich die Zeitzonen-Validierung robuster über datetime.datetime.fromisoformat() abbilden, um manuelle String-Slicing-Prüfungen zu vermeiden.
val: str = data[field]
parsed_dt = datetime.datetime.fromisoformat(val)
assert parsed_dt.tzinfo is not None, f"Feld {field!r} hat keinen TZ-Suffix: {val!r}"
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## main #97 +/- ##
==========================================
+ Coverage 89.84% 89.90% +0.05%
==========================================
Files 89 89
Lines 4019 4023 +4
Branches 345 345
==========================================
+ Hits 3611 3617 +6
+ Misses 318 317 -1
+ Partials 90 89 -1
... and 2 files with indirect coverage changes
Flags with carried forward coverage won't be shown. Click here to find out more. Continue to review full report in Codecov by Sentry.
🚀 New features to boost your workflow:
|
There was a problem hiding this comment.
Pull request overview
Fixes RFC3339-Strict Kompatibilität für den Hangar-Go-Client, indem BatchRead.created_at jetzt konsistent als UTC-Zeitstempel mit Z-Suffix serialisiert wird (statt naivem ISO-String ohne TZ).
Changes:
- Ergänzt
@field_serializer("created_at")inBatchRead, der den bestehendenserialize_datetime_utc-Helper nutzt. - Fügt Unit-Tests hinzu, die das
Z-Suffix für naive und UTC-awarecreated_atvalidieren sowieBatchSummary.all_terminalabdecken.
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated 1 comment.
| File | Description |
|---|---|
| backend/app/schemas/batch_read.py | Ergänzt Serializer für created_at über serialize_datetime_utc, um RFC3339 (...Z) sicherzustellen. |
| backend/tests/unit/schemas/test_batch_read.py | Neue Unit-Tests für BatchRead.created_at-Serialisierung und BatchSummary.all_terminal. |
| # Alle datetime-Felder auf oberster Ebene prüfen | ||
| for field in ("created_at",): | ||
| val: str = data[field] | ||
| assert "Z" in val or "+" in val or (len(val) >= 6 and val[-6] == "-"), ( | ||
| f"Feld {field!r} hat keinen TZ-Suffix: {val!r}" | ||
| ) |
Summary
BatchRead.created_atwurde bisher als naiver ISO-String ohne Zeitzonen-Suffixserialisiert (
2026-06-02T09:46:18.701971). Der Go-RFC3339-Parser im Hangar-Client(Phase 1d) erwartet einen TZ-Offset und lehnte das Format ab:
Folge: Hangar zeigte „Hub aktuell nicht erreichbar — Status nicht verfügbar."
obwohl der Hub erreichbar war und valide Daten lieferte.
Fix:
@field_serializer("created_at")mit dem bestehendenserialize_datetime_utcHelper ergänzt — analog zu
TemplateReadundJobRead, die bereits korrektserialisieren.
JobReadwar nicht betroffen (hatte bereits alle Serializer).Contributor License Agreement (CLA)
By opening this pull request you affirm that you have read and agree to the
project's Contributor License Agreement for the contribution(s)
included here.
Linked issue
Type of change
Hardware tested on
Test coverage
Neue Datei:
backend/tests/unit/schemas/test_batch_read.py(7 Tests, TDD RED→GREEN)test_created_at_naive_serialised_with_z_suffix— Hauptregressiontest_created_at_utc_aware_serialised_with_z_suffix— UTC-aware Pfadtest_created_at_no_naive_iso_without_tz— kein naiver String ohne Suffixtest_batch_read_full_json_contains_z_timestamps— Vollständiger JSON-RoundtripBatchSummary.all_terminalLogikChecklist
feat(...): ...etc.)Migration / breaking change notes
Keine. Die Serialisierung von
created_atwar bisher fehlerhaft (naive ISOohne TZ). Das neue Format (
...Z) ist das korrekte RFC3339-Format und repariertbestehende Clients, die RFC3339 strict parsen.
Screenshots / output
Vorher (Regression):
Nachher (Fix):