Skip to content

fix: convert deploy timestamps to UTC before sending#219

Merged
jeff-schnitter merged 1 commit into
mainfrom
fix/deploy-timestamp-utc-conversion
Jul 14, 2026
Merged

fix: convert deploy timestamps to UTC before sending#219
jeff-schnitter merged 1 commit into
mainfrom
fix/deploy-timestamp-utc-conversion

Conversation

@hannavigil

Copy link
Copy Markdown
Contributor

Problem

cortex deploys add (with no --timestamp) returns a timestamp that displays with the wrong time in the Cortex UI. Example — run at 11:26 PDT:

{ "timestamp": "2026-07-13T11:26:52Z", ... }

11:26 was the local wall-clock time, but it's labeled Z (UTC). The true UTC was 18:26. So every deploy is off by the client's UTC offset.

Root cause

In cortexapps_cli/commands/deploys.py:

  • The default is naive local time: timestamp: datetime = typer.Option(datetime.now(), ...)
  • It's then formatted with a hardcoded Z: data["timestamp"].strftime('%Y-%m-%dT%H:%M:%SZ')

So local time goes on the wire mislabeled as UTC. The backend (brain-backend) trusts the offset and round-trips the instant faithfully — the bug is entirely client-side.

Fix

Interpret the naive timestamp as local time and convert to UTC before formatting, so the Z is truthful. .astimezone(timezone.utc) treats a naive datetime as the machine's local time. Applied to both add and update-by-uuid; covers the datetime.now() default and an explicit --timestamp.

data["timestamp"] = data["timestamp"].astimezone(timezone.utc).strftime('%Y-%m-%dT%H:%M:%SZ')

Behavior note: an explicit --timestamp 2026-07-13T10:00:00 (which carries no offset) is now interpreted as local and converted to UTC, rather than being sent as-is-with-Z. This is consistent with the datetime.now() default and matches what a human means when typing a wall-clock time.

Tests

Added tests/test_deploys_timestamp.py — mocks the POST (via responses), pins a fixed offset zone, and asserts the outgoing payload's timestamp is converted to UTC (10:30 local UTC-5 → 15:30:00Z). Pre-fix code emitted 10:30:00Z, so this is a regression guard.

Out of scope (flagging for follow-up)

update-by-uuid's flag-based path has a separate, pre-existing bug: its guard if not title or tag or deploy_type: is always truthy (since tag is required), so it raises before sending whenever -f isn't used. The timestamp fix on that line is correct but currently only reachable once that guard is fixed. Not addressed here to keep this PR focused.

🤖 Generated with Claude Code

`deploys add` and `update-by-uuid` captured the local wall-clock time via
datetime.now() and formatted it with a hardcoded "Z" suffix, putting local
time on the wire mislabeled as UTC. The backend trusts the offset, so the
deploy shows up shifted by the client's UTC offset in the UI.

Interpret the naive timestamp as local time and convert to UTC before
formatting, so the "Z" is accurate. Covers both the default "now" and an
explicit --timestamp.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@hannavigil
hannavigil marked this pull request as ready for review July 13, 2026 20:41

@Cantaley Cantaley left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Approved. Minor note: it looks like this is a behavior change for existing users, so I am assuming we'll call it out in the release notes? Users who were compensating for the old behavior (if any) may be affected.

@jeff-schnitter jeff-schnitter left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks, Hanna!

@jeff-schnitter
jeff-schnitter merged commit 9dcf17b into main Jul 14, 2026
4 checks passed
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