Skip to content

feat: add Heap region support#7732

Open
SahilJat wants to merge 2 commits into
Flagsmith:mainfrom
SahilJat:feat/heap-region-support
Open

feat: add Heap region support#7732
SahilJat wants to merge 2 commits into
Flagsmith:mainfrom
SahilJat:feat/heap-region-support

Conversation

@SahilJat
Copy link
Copy Markdown
Contributor

@SahilJat SahilJat commented Jun 8, 2026

Thanks for submitting a PR! Please check the boxes below:

[x] I have read the Contributing Guide /Flagsmith/flagsmith/blob/main/CONTRIBUTING.md.
[ ] I have added information to docs/ if required so people know about the feature.
[x] I have filled in the "Changes" section below.
[x] I have filled in the "How did you test this code" section below.

Changes

Closes #7730

The Heap integration was hardcoded to target https://heapanalytics.com , preventing users with European Heap instances ( https://eu.heapanalytics.com ) from using the integration.

This PR adds base_url support to the Heap integration, following the same pattern as the existing Amplitude integration:

• api/integrations/heap/constants.py — New file with DEFAULT_HEAP_API_URL constant.
• api/integrations/heap/models.py — Override the inherited base_url field with a default value of https://heapanalytics.com .
• api/integrations/heap/heap.py — Use config.base_url instead of the hardcoded HEAP_API_URL constant.
• api/integrations/heap/serializers.py — Expose base_url in the API serializer fields.
• api/integrations/heap/migrations/0004_add_default_base_url.py — Data migration to backfill existing rows with the default URL + alter the field to set a default.
• frontend/common/stores/default-flags.ts — Add base_url field to the Heap integration UI configuration.

This change is fully backwards compatible — existing configurations receive the default US URL via the data migration, and new configurations without an explicit base_url also default to US.

How did you test this code?

Unit tests

Added and updated tests in:

• api/tests/unit/integrations/heap/test_unit_heap.py :
• Existing test now asserts default URL resolves to https://heapanalytics.com/api/track .
• New test test_heap_wrapper__eu_base_url__uses_eu_url verifies EU URL is used correctly.
• api/tests/unit/integrations/heap/test_unit_heap_views.py :
• Updated list test to assert base_url is present in API response with default value.
• Updated create test to verify default base_url is set when omitted.
• New test test_create_heap_config__with_eu_base_url__returns_created verifies creating a config with a custom EU base URL.

Manual verification

  1. Start the API: cd api && make serve

  2. Create a Heap config without base_url — confirm it defaults to https://heapanalytics.com :
    curl -X POST http://localhost:8000/api/v1/environments/<ENV_KEY>/integrations/heap/
    -H "Authorization: Token "
    -H "Content-Type: application/json"
    -d '{"api_key": "test-key"}'

  3. Create a Heap config with EU base_url — confirm it is stored and returned:
    curl -X POST http://localhost:8000/api/v1/environments/<ENV_KEY>/integrations/heap/
    -H "Authorization: Token "
    -H "Content-Type: application/json"
    -d '{"api_key": "test-key", "base_url": "https://eu.heapanalytics.com"}'

  4. Start the frontend ( cd frontend && ENV=local npm run dev ) and navigate to Integrations → Heap Analytics — confirm the "Base URL" field is visible alongside the API Key field.

@SahilJat SahilJat requested review from a team as code owners June 8, 2026 15:28
@SahilJat SahilJat requested review from emyller and kyle-ssg and removed request for a team June 8, 2026 15:28
@vercel
Copy link
Copy Markdown

vercel Bot commented Jun 8, 2026

@SahilJat is attempting to deploy a commit to the Flagsmith Team on Vercel.

A member of the Team first needs to authorize it.

@github-actions github-actions Bot added front-end Issue related to the React Front End Dashboard api Issue related to the REST API labels Jun 8, 2026
@codecov
Copy link
Copy Markdown

codecov Bot commented Jun 8, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 98.39%. Comparing base (19ffc62) to head (bca1eb5).
⚠️ Report is 2 commits behind head on main.

Additional details and impacted files
@@            Coverage Diff             @@
##             main    #7732      +/-   ##
==========================================
- Coverage   98.54%   98.39%   -0.15%     
==========================================
  Files        1452     1453       +1     
  Lines       55793    55818      +25     
==========================================
- Hits        54983    54924      -59     
- Misses        810      894      +84     

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@Zaimwa9
Copy link
Copy Markdown
Contributor

Zaimwa9 commented Jun 8, 2026

@gemini-code-assist review

Copy link
Copy Markdown
Contributor

@gemini-code-assist gemini-code-assist Bot left a comment

Choose a reason for hiding this comment

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

Code Review

This pull request introduces a configurable base_url for the Heap integration, allowing users to specify custom endpoints (such as for EU-based Heap instances) instead of relying on a hardcoded default. The changes include backend model updates, serializers, database migrations, unit tests, and frontend configuration. The reviewer's feedback focuses on ensuring data integrity by explicitly enforcing null=False and blank=False on the new base_url field in both the model and migration, as well as safely backfilling soft-deleted records during the migration using the all_objects manager.

Comment thread api/integrations/heap/models.py Outdated


class HeapConfiguration(EnvironmentIntegrationModel):
base_url = models.URLField(default=DEFAULT_HEAP_API_URL)
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

high

Since IntegrationsModel defines base_url with null=True, overriding it here without explicitly setting null=False allows base_url to be set to None. This can lead to runtime errors when constructing the track URL (e.g., 'None/api/track'). Enforce null=False and blank=False to guarantee data integrity.

Suggested change
base_url = models.URLField(default=DEFAULT_HEAP_API_URL)
base_url = models.URLField(default=DEFAULT_HEAP_API_URL, null=False, blank=False)

Comment on lines +8 to +10
heap_configuration_model.objects.filter(
Q(base_url__isnull=True) | Q(base_url="")
).update(base_url="https://heapanalytics.com")
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

high

To prevent database migration failures when altering the base_url field to null=False, we must ensure that all existing records—including soft-deleted ones—are backfilled. Since HeapConfiguration inherits from SoftDeleteExportableModel, the default objects manager might filter out soft-deleted records depending on how the manager is configured or serialized in migrations. Using all_objects (or falling back to objects) ensures all records are safely updated.

Suggested change
heap_configuration_model.objects.filter(
Q(base_url__isnull=True) | Q(base_url="")
).update(base_url="https://heapanalytics.com")
manager = getattr(heap_configuration_model, "all_objects", heap_configuration_model.objects)
manager.filter(
Q(base_url__isnull=True) | Q(base_url="")
).update(base_url="https://heapanalytics.com")

Comment on lines +22 to +26
migrations.AlterField(
model_name="heapconfiguration",
name="base_url",
field=models.URLField(default="https://heapanalytics.com"),
),
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

high

Update the AlterField operation to enforce null=False and blank=False in the database schema, matching the model definition and preventing future null values.

Suggested change
migrations.AlterField(
model_name="heapconfiguration",
name="base_url",
field=models.URLField(default="https://heapanalytics.com"),
),
migrations.AlterField(
model_name="heapconfiguration",
name="base_url",
field=models.URLField(default="https://heapanalytics.com", null=False, blank=False),
),

Copy link
Copy Markdown
Contributor

@Zaimwa9 Zaimwa9 left a comment

Choose a reason for hiding this comment

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

Overall we are able to drop the database migration. I guess this was inspired by the amplitude but with heap the url field is null for all the integrations and previous records will still be using the same url.
So self.url = "{config.base_url or DEFAULT_HEAP_API_URL}/api/track" should do the job.

We are still discussing internally how to address the frontend so a first step would be to focus on the backend. We will discuss and come back to you

Comment thread api/integrations/heap/migrations/0004_add_default_base_url.py Outdated
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

api Issue related to the REST API front-end Issue related to the React Front End Dashboard

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Support Heap integration for EU tenant

4 participants