Skip to content

fix(source-hubspot): use v3 properties API for CRM search streams and fix test cache leaks#74097

Draft
suisuixia42 wants to merge 6 commits intomasterfrom
devin/1772237000-conftest-v3-cache-fix
Draft

fix(source-hubspot): use v3 properties API for CRM search streams and fix test cache leaks#74097
suisuixia42 wants to merge 6 commits intomasterfrom
devin/1772237000-conftest-v3-cache-fix

Conversation

@suisuixia42
Copy link
Contributor

@suisuixia42 suisuixia42 commented Feb 28, 2026

This PR targets the following PR:


What

CRM search streams (companies, contacts, deals, tickets, leads, deal_splits, engagements_*) use PropertiesFromEndpoint to discover HubSpot properties for search requests. The v2 API (/properties/v2/{entity}/properties) returns all properties including those with dataSensitivity: "high", which causes 403 MISSING_SCOPES errors on Enterprise accounts with sensitive custom properties.

This PR (based on #74032 by hlepouse-vasco) switches to the v3 API which excludes sensitive properties by default, and adds test infrastructure to prevent HTTP cache leaks between tests.

How

Core fix (from #74032):

  • manifest.yaml: Switch PropertiesFromEndpoint path from /properties/v2/{entity}/properties to /crm/v3/properties/{entity}, update field_path from [] to ["results"] (v3 wraps response array)

Test infrastructure (from #74032):

  • All property mock helpers (mock_dynamic_schema_requests, mock_dynamic_schema_requests_with_skip, mock_properties, mock_all_properties) now register both v2 and v3 mocks
  • New CrmSearchPropertiesRequestBuilder for v3 property URL
  • Individual tests in test_source.py and test_streams.py updated to register v3 mocks

Additional changes on top of #74032:

  • conftest.py: Added import requests_cache and clear_http_cache autouse fixture that clears the CDK's shared in-memory SQLite HTTP cache before each test (prevents requests_cache from bypassing requests_mock)
  • conftest.py: Changed mock_v3_properties helper URL from relative (/crm/v3/properties/{entity}) to absolute (https://api.hubapi.com/crm/v3/properties/{entity})
  • test_streams.py: Changed deal_split test mocks from relative to absolute URLs for endpoint_path (/crm/v3/objects/deal_split/searchhttps://api.hubapi.com/...) and properties_path (/properties/v2/deal_split/propertieshttps://api.hubapi.com/...). Without full URLs, the clear_http_cache fixture exposes a NoMockAddress error that was previously hidden by cached responses from earlier tests.

Review guide

⚠️ Key items for reviewer attention:

  1. conftest.py clear_http_cache fixtureautouse=True (runs for every test). Verify this doesn't introduce unexpected side effects or slowdowns for tests that don't use HTTP caching.

  2. conftest.py mock_v3_properties — Uses full URL (https://api.hubapi.com/...) with register_uri. Tests that call both mock_v3_properties and mock_dynamic_schema_requests will register the v3 mock twice. Verify double-registration doesn't cause issues with requests_mock.

  3. test_streams.py deal_split tests — Now use full URLs while some other test mocks still use relative URLs. This is intentional (the clear_http_cache fixture surfaces the mismatch for deal_split tests specifically), but verify no other tests have the same latent relative-URL issue that could surface under different test ordering.

  4. integrations/__init__.py mock_properties v3 response construction — The v3 response is built by starting with v3_records = copy.deepcopy(templates) and then appending built records. This means v3_records contains both the original template records AND the newly built records. Verify this produces the correct JSON structure for the v3 API response format {"results": [...]}. The v2 path uses RootHttpResponseBuilder which may handle templates differently.

  5. manifest.yaml PropertiesFromEndpoint — Core fix: v2 → v3 API path change. Verify this correctly excludes sensitive properties and that the v3 response format {"results": [...]} matches actual API behavior.

  6. integrations/__init__.py mock_all_properties — Now checks existing_v2 and existing_v3 separately to avoid double-registration. Verify the logic correctly identifies already-mocked entities for both v2 and v3 URLs.

User Impact

Users with HubSpot Enterprise accounts who have marked custom properties as sensitive will no longer experience 403 errors on CRM search streams. Backward-compatible — accounts without sensitive properties are unaffected.

Can this PR be safely reverted and rolled back?

  • YES 💚
  • NO ❌

No state/config format changes. Safe to revert.


Requested by: suisuixia42
Link to Devin run

hlepouse-vasco and others added 5 commits February 25, 2026 11:25
The v2 properties API (/properties/v2/{entity}/properties) returns all
properties including those with high data sensitivity. When these
sensitive properties are passed in the CRM search request body, HubSpot
returns 403 MISSING_SCOPES requiring granular scopes like
`tickets.highly_sensitive.v2` or `crm.objects.deals.sensitive.read.v2`.
These scopes are not available on legacy OAuth apps and require HubSpot
review for new-style apps.

Switch CRM search streams to discover properties via the v3 API
(/crm/v3/properties/{entity}) which excludes sensitive properties by
default, preventing the 403 errors.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Run ruff format to satisfy pre-commit format check.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…che, and fix mock_v3_properties URL

Co-Authored-By: suisui.xia <suisui.xia@airbyte.io>
@devin-ai-integration
Copy link
Contributor

🤖 Devin AI Engineer

I'll be helping with this pull request! Here's what you should know:

✅ I will automatically:

  • Address comments on this PR. Add '(aside)' to your comment to have me ignore it.
  • Look at CI failures and help fix them

Note: I can only respond to comments from users who have write access to this repository.

⚙️ Control Options:

  • Disable automatic comment and CI monitoring

@CLAassistant
Copy link

CLA assistant check
Thank you for your submission! We really appreciate it. Like many open source projects, we ask that you all sign our Contributor License Agreement before we can accept your contribution.
1 out of 2 committers have signed the CLA.

✅ hlepouse-vasco
❌ suisuixia42
You have signed the CLA already but the status is still pending? Let us recheck it.

@github-actions
Copy link
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.
  • ❇️ 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.
  • 🚀 Connector Releases:
    • /publish-connectors-prerelease - Publishes pre-release connector builds (tagged as {version}-preview.{git-sha}) for all modified connectors in the PR.
    • /bump-progressive-rollout-version - Bumps connector version with an RC suffix (2.16.10-rc.1) for progressive rollouts (enableProgressiveRollout: true).
      • Example: /bump-progressive-rollout-version changelog="Add new feature for progressive rollout"
  • ☕️ 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
    • /bump-bulk-cdk-version bump=patch changelog='foo' - Bump the Bulk CDK's version. bump can be major/minor/patch.
  • 🐍 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
Copy link
Contributor

github-actions bot commented Feb 28, 2026

Deploy preview for airbyte-docs ready!

✅ Preview
https://airbyte-docs-f71zzxhr5-airbyte-growth.vercel.app

Built with commit 5e91cd6.
This pull request is being automatically deployed with vercel-action

@github-actions
Copy link
Contributor

github-actions bot commented Feb 28, 2026

source-hubspot Connector Test Results

146 tests   145 ✅  12m 36s ⏱️
  1 suites    0 💤
  1 files      1 ❌

For more details on these failures, see this check.

Results for commit 5e91cd6.

♻️ This comment has been updated with latest results.

…est_streams.py

Co-Authored-By: suisui.xia <suisui.xia@airbyte.io>
@devin-ai-integration devin-ai-integration bot changed the title fix(source-hubspot): add clear_http_cache fixture and fix mock_v3_properties URL in conftest.py fix(source-hubspot): use v3 properties API for CRM search streams and fix test cache leaks Feb 28, 2026
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.

4 participants