Skip to content

fix(source-zendesk-support): render epoch cursor boundaries in UTC, not the host timezone - #84354

Draft
Anatolii Yatsuk (tolik0) wants to merge 2 commits into
masterfrom
tolik0/source-zendesk-support/fix-tz-dependent-epoch-interpolation
Draft

fix(source-zendesk-support): render epoch cursor boundaries in UTC, not the host timezone#84354
Anatolii Yatsuk (tolik0) wants to merge 2 commits into
masterfrom
tolik0/source-zendesk-support/fix-tz-dependent-epoch-interpolation

Conversation

@tolik0

@tolik0 Anatolii Yatsuk (tolik0) commented Aug 13, 2026

Copy link
Copy Markdown
Contributor

What

Two tickets_search unit tests pass in CI and fail on any developer machine outside UTC:

mock_server/test_tickets.py::TestTicketsSearchStream::test_given_lookback_window_when_read_tickets_search_then_rescan_from_before_the_cursor
mock_server/test_tickets.py::TestTicketsSearchStreamQueryParameters::test_when_read_tickets_search_then_partitions_produce_correct_query_params
requests_mock.exceptions.NoMockAddress: No mock address: GET .../search/export?query=updated_at%3E%3D...

The tests are correct. The manifest is not.

cursor_incremental_sync.start_datetime and the tickets_search cursor both render unix-epoch boundaries with strftime('%s'):

datetime: "{{ now_utc().strftime('%s') }}"
datetime: "{{ ... else day_delta(-730, '%s') }}"

Python does not implement %sstrftime delegates it to the C library, which ignores the datetime's tzinfo and applies the host's timezone. So the rendered epoch is shifted by the host's UTC offset, and the request window is wrong. Measured on the same frozen instant:

TZ=Europe/Kyiv          {{ now_utc().strftime('%s') }} -> 1786625138
TZ=UTC                  {{ now_utc().strftime('%s') }} -> 1786635941   # 3h apart

Airbyte's job containers run UTC, where both forms agree — which is why this has gone unnoticed. The CDK's own DatetimeParser special-cases %s on both parse and format paths for precisely this reason, with the comment "strftime('%s') is unreliable because it ignores the time zone information and assumes the time zone of the system it's running on". The manifest was doing the thing the CDK carefully avoids.

How

Render epochs with .timestamp() | int, which respects tzinfo:

datetime: "{{ now_utc().timestamp() | int }}"
datetime: "{{ ... else (now_utc() - duration('P730D')).timestamp() | int }}"

day_delta(num_days, format) applies strftime internally, so it carries the same defect whenever format is '%s'; now_utc() - duration('P730D') replaces it. The two remaining day_delta calls in the manifest request '%Y-%m-%dT%H:%M:%SZ' and are unaffected — that directive is implemented by Python and is timezone-correct. timestamp(...) was already safe and is unchanged.

Verified identical output across UTC, Europe/Kyiv, America/Los_Angeles and Asia/Kolkata (deliberately included for its half-hour offset).

Declarative-First Evaluation

Declarative only — three interpolation expressions. No Python component involved; the correct primitives already existed in the CDK's macro set.

Breaking Change Evaluation

Not breaking, and no production behavior change: Airbyte job containers run UTC, where the old and new expressions render the same epoch. What changes is correctness off UTC — a self-managed deployment on a non-UTC host was requesting windows shifted by its offset. Version 5.5.2.

Test Coverage

No new tests. The two existing tests above already assert the exact query window; they were failing for the right reason and now pass. Full connector suite, run twice:

TZ=Europe/Kyiv          215 passed
TZ=UTC                  215 passed

mock_server/test_tickets.py specifically, across four zones:

TZ=Europe/Kyiv          9 passed
TZ=UTC                  9 passed
TZ=America/Los_Angeles  9 passed
TZ=Asia/Kolkata         9 passed

Before this change, both non-UTC full-suite runs reported 2 failed.

Review guide

  1. manifest.yaml — three expressions, plus a comment at cursor_incremental_sync.start_datetime explaining why %s is banned here.
  2. AGENTS.md §5 — the rule and the symptom, so the next person writing an epoch cursor does not reintroduce it.

Note on version collision

#84353 (a side_conversations error-handling fix) also targets 5.5.2. Whichever merges second needs a bump to 5.5.3 and a changelog line move. The two PRs otherwise touch disjoint parts of the manifest.

Can this PR be safely reverted and rolled back?

  • YES 💚
  • NO ❌

Important

Active progressive rollout warning for source-zendesk-support.

  • (Click to Approve:) Bypass the active progressive rollout warning for source-zendesk-support in the PR comment here.

…ot the host timezone

`cursor_incremental_sync.start_datetime` and the `tickets_search` cursor rendered
their unix-epoch boundaries with `strftime('%s')`. Python does not implement `%s`;
`strftime` hands it to the C library, which ignores the datetime's tzinfo and
applies the host's timezone. The rendered epoch is therefore shifted by the host's
UTC offset, so the request window is wrong on any non-UTC host.

Use `.timestamp() | int` instead, and replace `day_delta(-730, '%s')` with
`(now_utc() - duration('P730D')).timestamp() | int` — `day_delta` applies
`strftime` internally and carries the same defect when asked for `%s`.

Airbyte's job containers run UTC, where both forms agree, which is why this went
unnoticed. It surfaced as two `tickets_search` unit tests that pass in CI and fail
on any developer machine outside UTC with `NoMockAddress`, the rendered query
window not matching the mock. Verified across UTC, Europe/Kyiv,
America/Los_Angeles and Asia/Kolkata (half-hour offset).

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@octavia-bot
octavia-bot Bot marked this pull request as draft August 13, 2026 15:55
@octavia-bot

octavia-bot Bot commented Aug 13, 2026

Copy link
Copy Markdown
Contributor

Note

📝 PR Converted to Draft

More info...

Thank you for creating this PR. As a policy to protect our engineers' time, Airbyte requires all PRs to be created first in draft status. Your PR has been automatically converted to draft status in respect for this policy.

As soon as your PR is ready for formal review, you can proceed to convert the PR to "ready for review" status by clicking the "Ready for review" button at the bottom of the PR page.

To skip draft status in future PRs, please include [ready] in your PR title or add the skip-draft-status label when creating your PR.

@github-actions

Copy link
Copy Markdown
Contributor

👋 Greetings, Airbyte Team Member!

Here are some helpful tips and reminders for your convenience.

💡 Show Tips and Tricks

PR Slash Commands

Airbyte Maintainers (that's you!) can execute the following slash commands on your PR:

  • 🛠️ Quick Fixes
    • /format-fix - Fixes most formatting issues.
    • /bump-version - Bumps connector versions, scraping changelog description from the PR title.
      • Bump types: patch (default), minor, major, major_rc, rc, promote.
      • The rc type is a smart default: applies minor_rc if stable, or bumps the RC number if already RC.
      • The promote type strips the RC suffix to finalize a release.
      • Example: /bump-version type=rc or /bump-version type=minor
    • /bump-progressive-rollout-version - Alias for /bump-version type=rc. Bumps with an RC suffix and enables progressive rollout.
  • ❇️ AI Testing and Review (internal link: AI-SDLC Docs):
    • /ai-prove-fix - Runs prerelease readiness checks, including testing against customer connections.
    • /ai-canary-prerelease - Rolls out prerelease to 5-10 connections for canary testing.
    • /ai-review - AI-powered PR review for connector safety and quality gates.
  • 📝 AI Documentation:
    • /ai-docs-review - AI-powered documentation review for PRs with connector changes.
    • /ai-create-docs-pr - Creates a documentation PR for connector changes, stacked on the current PR.
  • 🚀 Connector Releases:
    • /publish-connectors-prerelease - Publishes pre-release connector builds (tagged as {version}-preview.{git-sha}) for all modified connectors in the PR.
    • /enable-autopilot-rollouts - Enables autopilot progressive rollouts for the modified connector(s) in the PR, remediating "autopilot rollouts not enabled for {connector-name}" auto-merge blockers. Sets defaultRolloutMode: autopilot and enableProgressiveRollout: true, preserving any existing autopilotConfig.
      • Optional args: connector=<CONNECTOR_NAME> (defaults to the modified connectors in the PR), strategy=fast|slow|default (defaults to fast).
      • Example: /enable-autopilot-rollouts or /enable-autopilot-rollouts connector=source-faker strategy=slow
  • ☕️ JVM connectors:
    • /update-connector-cdk-version connector=<CONNECTOR_NAME> - Updates the specified connector to the latest CDK version.
      Example: /update-connector-cdk-version connector=destination-bigquery
  • 🐍 Python connectors:
    • /poe connector source-example lock - Run the Poe lock task on the source-example connector, committing the results back to the branch.
    • /poe source example lock - Alias for /poe connector source-example lock.
    • /poe source example use-cdk-branch my/branch - Pin the source-example CDK reference to the branch name specified.
    • /poe source example use-cdk-latest - Update the source-example CDK dependency to the latest available version.
  • ⚙️ Admin commands:
    • /force-merge reason="<REASON>" - Force merges the PR using admin privileges, bypassing CI checks. Requires a reason.
      Example: /force-merge reason="CI is flaky, tests pass locally"
📚 Show Repo Guidance

Helpful Resources

📝 Edit this welcome message.

@github-actions

github-actions Bot commented Aug 13, 2026

Copy link
Copy Markdown
Contributor

Detected source-zendesk-support Active Rollout: true

Important

Active progressive rollout warning for source-zendesk-support.

To bypass this warning, click on the matching checkbox in the PR description. Look for the checkbox text:

(Click to Approve:) Bypass the active progressive rollout warning for source-zendesk-support in the PR comment

  • Rollout version: 5.5.1
  • Rollout state: workflow_started
  • Rollout last updated by: Airbyte Support Bot <airbyte-support-bot@airbyte.io>
  • Open Connector Rollout Manager in Retool to clean up or close out this rollout if appropriate.

Version on master Branch: 5.5.1

  • RC marker on master branch: false

PR Description Checkbox Status

  • Bypass checkbox checked: false

ℹ️ More Information

Show/hide details...

🤔 What happens if this PR is merged

Checking the checkbox will allow the PR to merge, but it does not necessarily stop the active rollout by itself. The result of the PR merging depends on what connector version is published.

Expected outcomes by type of version number change:

If connector version is not modified in this PR...

No new connector version should be released, and the active rollout should continue unchanged.

If the connector version increments to a higher `-rc` version...

After this PR is merged, the new RC will be published and registered, replacing the active RC marker. When the new RC is registered, the platform cancels any existing non-terminal rollout for this connector without unpinning actors.

After merging, you still need to start the new rollout. During start, pinned actors from the previous rollout can be moved to the new RC.

If the connector version changes from RC to non-RC (GA) version...

You should not merge the PR unless/until the RC has been finalized as canceled. See above Rollout state for detected status.

[!Warning]
This PR should not be merged if the RC rollout is still active. First finalize the active rollout as successful or cancel it in Connector Rollout Manager.

When you finalize an RC rollout as successful, the platform triggers a promotion workflow that strips the -rc suffix, removes stable-version registryOverrides, disables progressive rollout, force-merges that promotion, and unpins actors.

🔁 How to rerun this check

To rerun the check, simply check and uncheck the box, or else modify the PR description and/or title in any way.

Alternatively, you can find the Active Progressive Rollout CI workflow and manually rerun it (although this is generally slower than the above methods).


This comment will be updated as PR and/or rollout status changes.

Workflow run

@github-actions

github-actions Bot commented Aug 13, 2026

Copy link
Copy Markdown
Contributor

Deploy preview for airbyte-docs ready!

Project:airbyte-docs
Status: ✅  Deploy successful!
Preview URL:https://airbyte-docs-9tq73c3km-airbyte-growth.vercel.app
Latest Commit:e903807

Deployed with vercel-action

@github-actions

Copy link
Copy Markdown
Contributor

source-zendesk-support Connector Test Results

235 tests   229 ✅  8m 25s ⏱️
  2 suites    4 💤
  2 files      2 ❌

For more details on these failures, see this check.

Results for commit e903807.

@github-actions

Copy link
Copy Markdown
Contributor

source-zendesk-support Connector Test Results

235 tests   229 ✅  8m 27s ⏱️
  2 suites    4 💤
  2 files      2 ❌

For more details on these failures, see this check.

Results for commit e903807.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants