Skip to content

fix(Import/Export): Destructive environment-level import resets feature states in other environments#7349

Merged
khvn26 merged 9 commits intomainfrom
fix/destructive-import-resets-other-envs
Apr 28, 2026
Merged

fix(Import/Export): Destructive environment-level import resets feature states in other environments#7349
khvn26 merged 9 commits intomainfrom
fix/destructive-import-resets-other-envs

Conversation

@khvn26
Copy link
Copy Markdown
Member

@khvn26 khvn26 commented Apr 27, 2026

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

  • I have read the Contributing Guide.
  • I have added information to docs/ if required so people know about the feature.
  • I have filled in the "Changes" section below.
  • I have filled in the "How did you test this code" section below.

Changes

Closes #7166

The OVERWRITE_DESTRUCTIVE strategy in _import_features_for_environment deleted the entire Feature and recreated it. The cascade soft-deleted every FeatureState across every environment, and Feature.objects.create(...) then re-seeded env-default FeatureStates for all environments using the exporter's initial_value / default_enabled. Only the target environment had the imported value/enabled written back, so every other environment was reset to the exporter's defaults.

Replaced the delete + recreate with a new overwrite_feature_for_environment service that:

  • Updates Feature-level fields (initial_value, is_server_key_only, default_enabled) in place. These only seed new environments and don't retroactively change existing FeatureStates.
  • Deletes only the target environment's FeatureSegments and identity-override FeatureStates, preserving the destructive semantic within the target env. Other environments' overrides are untouched.
  • Reconciles MultivariateFeatureOptions on the feature by (type, value): reuses matches, creates missing, leaves extras alone (they may belong to other envs' allocations).
  • Upserts the target env's MultivariateFeatureStateValue percentage allocations and zeroes out any options the import dropped, scoped to the target env's MV state values only.
  • Looks up the target env-default FeatureState via FeatureState.objects.get_live_feature_states(...) so the live version's FS is targeted on v2-versioned environments. Previously a .filter(...).first() returned the lowest-id (initial-version) FS once subsequent versions had been published, silently no-opping the import.

Also moved the existing create-strategy logic to services.py for symmetry, and added a FeatureExportData TypedDict in types.py to drop the previous untyped dict[str, Optional[Union[bool, str, int]]] signatures and a string of # type: ignore comments.

The v1 and v2 paths are identical: the destructive strategy mutates the live FeatureState in place rather than publishing a new EnvironmentFeatureVersion. Opting into OVERWRITE_DESTRUCTIVE is opting out of audit trail; spending code to gently publish a new version subverts the strategy's stated intent.

How did you test this code?

Two end-to-end tests covering the full export → import pipeline:

  • The existing destructive-strategy E2E test now also exercises bystander-env preservation and target-env segment + identity override destruction.
  • A new v2-versioning E2E test sets up a v2-versioned target env with multiple published versions and verifies that a destructive import mutates the live version's FS in place (no extra version is created), the prior version's FS is untouched, and live state reflects the imported value / enabled.

@khvn26 khvn26 requested a review from a team as a code owner April 27, 2026 15:20
@khvn26 khvn26 requested review from gagantrivedi and removed request for a team April 27, 2026 15:20
Copy link
Copy Markdown

@claude claude 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 skipped — your organization's overage spend limit has been reached.

Code review is billed via overage credits. To resume reviews, an organization admin can raise the monthly limit at claude.ai/admin-settings/claude-code.

Once credits are available, reopen this pull request to trigger a review.

@vercel
Copy link
Copy Markdown

vercel Bot commented Apr 27, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
docs Ready Ready Preview, Comment Apr 28, 2026 3:18pm
flagsmith-frontend-preview Ready Ready Preview, Comment Apr 28, 2026 3:18pm
flagsmith-frontend-staging Ready Ready Preview, Comment Apr 28, 2026 3:18pm

Request Review

@github-actions github-actions Bot added the api Issue related to the REST API label Apr 27, 2026
@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented Apr 27, 2026

Docker builds report

Image Build Status Security report
ghcr.io/flagsmith/flagsmith-api-test:pr-7349 Finished ✅ Skipped
ghcr.io/flagsmith/flagsmith-api:pr-7349 Finished ✅ Results
ghcr.io/flagsmith/flagsmith:pr-7349 Finished ✅ Results
ghcr.io/flagsmith/flagsmith-private-cloud:pr-7349 Finished ✅ Results
ghcr.io/flagsmith/flagsmith-frontend:pr-7349 Finished ✅ Results

@github-actions github-actions Bot added the fix label Apr 27, 2026
@codecov
Copy link
Copy Markdown

codecov Bot commented Apr 27, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 98.44%. Comparing base (e44ea99) to head (df5a068).
⚠️ Report is 4 commits behind head on main.

Additional details and impacted files
@@           Coverage Diff            @@
##             main    #7349    +/-   ##
========================================
  Coverage   98.43%   98.44%            
========================================
  Files        1395     1398     +3     
  Lines       52514    52629   +115     
========================================
+ Hits        51691    51809   +118     
+ Misses        823      820     -3     

☔ View full report in Codecov by Sentry.
📢 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.

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented Apr 27, 2026

Playwright Test Results (oss - depot-ubuntu-latest-arm-16)

passed  11 passed

Details

stats  11 tests across 8 suites
duration  28.4 seconds
commit  ae06819
info  🔄 Run: #16341 (attempt 1)

Playwright Test Results (oss - depot-ubuntu-latest-16)

passed  11 passed

Details

stats  11 tests across 8 suites
duration  52.3 seconds
commit  ae06819
info  🔄 Run: #16341 (attempt 1)

Playwright Test Results (private-cloud - depot-ubuntu-latest-16)

passed  2 passed

Details

stats  2 tests across 2 suites
duration  47.4 seconds
commit  ae06819
info  🔄 Run: #16341 (attempt 1)

Playwright Test Results (private-cloud - depot-ubuntu-latest-arm-16)

passed  1 passed

Details

stats  1 test across 1 suite
duration  1 minute, 3 seconds
commit  ae06819
info  🔄 Run: #16341 (attempt 1)

Playwright Test Results (oss - depot-ubuntu-latest-16)

passed  11 passed

Details

stats  11 tests across 8 suites
duration  24.4 seconds
commit  3ed0ca7
info  🔄 Run: #16342 (attempt 1)

Playwright Test Results (oss - depot-ubuntu-latest-arm-16)

passed  11 passed

Details

stats  11 tests across 8 suites
duration  27.2 seconds
commit  3ed0ca7
info  🔄 Run: #16342 (attempt 1)

Playwright Test Results (private-cloud - depot-ubuntu-latest-16)

passed  17 passed

Details

stats  17 tests across 14 suites
duration  52.5 seconds
commit  3ed0ca7
info  🔄 Run: #16342 (attempt 1)

Playwright Test Results (private-cloud - depot-ubuntu-latest-arm-16)

passed  17 passed

Details

stats  17 tests across 14 suites
duration  1 minute, 12 seconds
commit  3ed0ca7
info  🔄 Run: #16342 (attempt 1)

Playwright Test Results (oss - depot-ubuntu-latest-16)

passed  11 passed

Details

stats  11 tests across 8 suites
duration  43.9 seconds
commit  9bf3353
info  🔄 Run: #16343 (attempt 1)

Playwright Test Results (oss - depot-ubuntu-latest-arm-16)

passed  11 passed

Details

stats  11 tests across 8 suites
duration  11.2 seconds
commit  9bf3353
info  🔄 Run: #16343 (attempt 1)

Playwright Test Results (private-cloud - depot-ubuntu-latest-16)

passed  17 passed

Details

stats  17 tests across 14 suites
duration  50 seconds
commit  9bf3353
info  🔄 Run: #16343 (attempt 1)

Playwright Test Results (private-cloud - depot-ubuntu-latest-arm-16)

passed  1 passed

Details

stats  1 test across 1 suite
duration  1 minute, 3 seconds
commit  9bf3353
info  🔄 Run: #16343 (attempt 1)

Playwright Test Results (oss - depot-ubuntu-latest-16)

passed  11 passed

Details

stats  11 tests across 8 suites
duration  9.4 seconds
commit  e846b5f
info  🔄 Run: #16345 (attempt 1)

Playwright Test Results (oss - depot-ubuntu-latest-arm-16)

passed  11 passed

Details

stats  11 tests across 8 suites
duration  49.7 seconds
commit  e846b5f
info  🔄 Run: #16345 (attempt 1)

Playwright Test Results (private-cloud - depot-ubuntu-latest-16)

passed  2 passed

Details

stats  2 tests across 2 suites
duration  55.4 seconds
commit  e846b5f
info  🔄 Run: #16345 (attempt 1)

Playwright Test Results (private-cloud - depot-ubuntu-latest-arm-16)

passed  1 passed

Details

stats  1 test across 1 suite
duration  1 minute, 2 seconds
commit  e846b5f
info  🔄 Run: #16345 (attempt 1)

Playwright Test Results (oss - depot-ubuntu-latest-16)

passed  11 passed

Details

stats  11 tests across 8 suites
duration  44.4 seconds
commit  e27a0ac
info  🔄 Run: #16346 (attempt 1)

Playwright Test Results (oss - depot-ubuntu-latest-arm-16)

passed  11 passed

Details

stats  11 tests across 8 suites
duration  11.6 seconds
commit  e27a0ac
info  🔄 Run: #16346 (attempt 1)

Playwright Test Results (private-cloud - depot-ubuntu-latest-arm-16)

passed  2 passed

Details

stats  2 tests across 2 suites
duration  1 minute, 2 seconds
commit  e27a0ac
info  🔄 Run: #16346 (attempt 1)

Playwright Test Results (private-cloud - depot-ubuntu-latest-16)

passed  2 passed

Details

stats  2 tests across 2 suites
duration  45.7 seconds
commit  e27a0ac
info  🔄 Run: #16346 (attempt 1)

Playwright Test Results (private-cloud - depot-ubuntu-latest-arm-16)

passed  1 passed

Details

stats  1 test across 1 suite
duration  1 minute, 6 seconds
commit  f85ac67
info  🔄 Run: #16381 (attempt 1)

Playwright Test Results (private-cloud - depot-ubuntu-latest-16)

passed  1 passed

Details

stats  1 test across 1 suite
duration  52.7 seconds
commit  f85ac67
info  🔄 Run: #16381 (attempt 1)

Playwright Test Results (oss - depot-ubuntu-latest-16)

passed  11 passed

Details

stats  11 tests across 8 suites
duration  25.2 seconds
commit  df5a068
info  🔄 Run: #16383 (attempt 1)

Playwright Test Results (oss - depot-ubuntu-latest-arm-16)

passed  11 passed

Details

stats  11 tests across 8 suites
duration  51.3 seconds
commit  df5a068
info  🔄 Run: #16383 (attempt 1)

Playwright Test Results (private-cloud - depot-ubuntu-latest-arm-16)

passed  1 passed

Details

stats  1 test across 1 suite
duration  1 minute, 1 second
commit  df5a068
info  🔄 Run: #16383 (attempt 1)

Playwright Test Results (private-cloud - depot-ubuntu-latest-16)

passed  1 passed

Details

stats  1 test across 1 suite
duration  52 seconds
commit  df5a068
info  🔄 Run: #16383 (attempt 1)

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented Apr 27, 2026

Visual Regression

16 screenshots compared. See report for details.
View full report

@github-actions github-actions Bot added fix and removed fix labels Apr 27, 2026
@github-actions github-actions Bot added fix and removed fix labels Apr 27, 2026
@github-actions github-actions Bot added fix and removed fix labels Apr 28, 2026
Copy link
Copy Markdown
Contributor

@emyller emyller left a comment

Choose a reason for hiding this comment

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

LGTM! Couple optional comments.

Comment thread api/features/import_export/services.py Outdated
Comment thread api/features/import_export/services.py
Copy link
Copy Markdown
Contributor

@emyller emyller left a comment

Choose a reason for hiding this comment

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

Sorry, need to update this UI note and this doc note. Makes me wonder whether this PR warrants ditching the "destructive" term entirely.

@github-actions github-actions Bot added fix and removed fix labels Apr 28, 2026
@khvn26 khvn26 requested review from a team as code owners April 28, 2026 15:17
@khvn26 khvn26 requested review from talissoncosta and removed request for a team April 28, 2026 15:17
@github-actions github-actions Bot added front-end Issue related to the React Front End Dashboard docs Documentation updates labels Apr 28, 2026
@github-actions github-actions Bot added fix and removed fix docs Documentation updates labels Apr 28, 2026
@khvn26
Copy link
Copy Markdown
Member Author

khvn26 commented Apr 28, 2026

@emyller see df5a068. IMO we're still destructive at the environment level, even though the gravity of the naming has diminished.

Copy link
Copy Markdown
Contributor

@emyller emyller left a comment

Choose a reason for hiding this comment

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

Thanks for addressing my review neatly.

@khvn26 khvn26 merged commit 567637e into main Apr 28, 2026
40 checks passed
@khvn26 khvn26 deleted the fix/destructive-import-resets-other-envs branch April 28, 2026 15:30
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 fix front-end Issue related to the React Front End Dashboard

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Destructive environment-level import resets feature states in other environments

3 participants