Skip to content

feat: cohort CSV sync endpoint and cohort summary on segments - #8352

Merged
Zaimwa9 merged 6 commits into
mainfrom
feat/cohort-csv-sync
Aug 25, 2026
Merged

feat: cohort CSV sync endpoint and cohort summary on segments#8352
Zaimwa9 merged 6 commits into
mainfrom
feat/cohort-csv-sync

Conversation

@Zaimwa9

@Zaimwa9 Zaimwa9 commented Aug 25, 2026

Copy link
Copy Markdown
Contributor

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

Adds the API surface the dashboard needs to create segments from a CSV of identifiers, on top of the cohort CRUD from #8248.

CSV sync endpoint

  • POST /api/v1/environments/{api_key}/cohorts/{id}/sync-csv/: multipart upload with file, identifier_column (0-based, defaults to the first column) and has_header (defaults to true).
  • Declarative replace: the uploaded identifiers become the cohort's desired membership. Responds 202 with {version, added, removed, unchanged, ignored: {empty, duplicates, too_long}} and queues the membership delta application inside the transaction, with a row lock on the cohort and a version bump.
  • The file is parsed and discarded, never stored. Files over 10MB are rejected with 413.

Cohort creation

  • POST .../cohorts/ now accepts segment metadata (custom fields), applied to the managed segment.

Segments API

  • Segment payloads carry a read-only cohort summary (id, environment, source_type, version, deletion_requested_at), prefetched on the list view. This lets the dashboard tag CSV segments, route their deletion through the cohorts endpoint, and grey out segments awaiting drain.

Observability

  • New metrics flagsmith_cohorts_csv_syncs_total and flagsmith_cohorts_csv_sync_identifiers, new cohorts.csv.synced event, both documented in the observability catalogues.

How did you test this code?

  • Unit tests for the CSV extraction and sync services (delta semantics, duplicates, empty rows, too-long identifiers, version bumps), the sync-csv view (validation, size cap, permissions), metadata on create, and the segment list cohort summary.
  • Manually through the dashboard drawer (stacked frontend branch): created cohorts from CSV files, verified membership rows and delta counts in the database, re-synced and deleted cohorts.

Recreates #8294, which GitHub auto-closed as merged during a stack reorder (its former base branch came to contain its head). Same content, reviewed there by @gagantrivedi.

@Zaimwa9
Zaimwa9 requested review from a team as code owners August 25, 2026 09:54
@Zaimwa9
Zaimwa9 requested review from matthewelwell and removed request for a team August 25, 2026 09:54
@vercel

vercel Bot commented Aug 25, 2026

Copy link
Copy Markdown

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

3 Skipped Deployments
Project Deployment Actions Updated (UTC)
docs Ignored Ignored Preview Aug 25, 2026 10:57am
flagsmith-frontend-preview Ignored Ignored Preview Aug 25, 2026 10:57am
flagsmith-frontend-staging Ignored Ignored Preview Aug 25, 2026 10:57am

Request Review

@github-actions github-actions Bot added api Issue related to the REST API docs Documentation updates labels Aug 25, 2026
@coderabbitai

coderabbitai Bot commented Aug 25, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

Adds CSV upload support for cohort membership synchronisation. The change parses and validates identifiers, reconciles membership states in batches, updates cohort versions, queues membership application, records metrics, and returns synchronisation counts. Cohort creation now accepts segment metadata. Segment responses now include related cohort details. The API specifications, observability catalogues, and unit tests cover these changes.

Estimated code review effort: 4 (Complex) | ~60 minutes

Merge Risk: 🟠 High · up to 191e0

The CSV sync endpoint can return successfully while leaving the requested cohort membership unapplied, and concurrent uploads may produce an unintended combined membership set. The PR should not merge until transaction ordering and concurrency handling are fixed or explicitly accepted.


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@Zaimwa9
Zaimwa9 removed the request for review from matthewelwell August 25, 2026 09:57

@coderabbitai coderabbitai Bot 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.

Actionable comments posted: 1


ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 18a749ae-5fa0-4688-817f-40381dc7f2de

📥 Commits

Reviewing files that changed from the base of the PR and between cc20443 and 27adf8f.

📒 Files selected for processing (17)
  • api/cohorts/constants.py
  • api/cohorts/dataclasses.py
  • api/cohorts/exceptions.py
  • api/cohorts/metrics.py
  • api/cohorts/serializers.py
  • api/cohorts/services.py
  • api/cohorts/views.py
  • api/segments/serializers.py
  • api/segments/views.py
  • api/tests/unit/cohorts/conftest.py
  • api/tests/unit/cohorts/test_services.py
  • api/tests/unit/cohorts/test_views.py
  • api/tests/unit/segments/test_unit_segments_views.py
  • docs/docs/deployment-self-hosting/observability/_events-catalogue.md
  • docs/docs/deployment-self-hosting/observability/_metrics-catalogue.md
  • mcp/src/flagsmith_mcp/openapi.json
  • openapi.yaml

Included review availability: Your plan provides up to 8 included reviews per hour; 4 remain after this review.

Comment thread api/cohorts/services.py
# Conflicts:
#	api/cohorts/serializers.py
#	api/cohorts/services.py
#	api/cohorts/views.py
#	api/tests/unit/cohorts/conftest.py
#	api/tests/unit/cohorts/test_services.py
#	api/tests/unit/cohorts/test_views.py
#	docs/docs/deployment-self-hosting/observability/_events-catalogue.md
#	openapi.yaml
@github-actions github-actions Bot added feature New feature or request and removed docs Documentation updates labels Aug 25, 2026
@github-actions

github-actions Bot commented Aug 25, 2026

Copy link
Copy Markdown
Contributor

Docker builds report

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

@coderabbitai coderabbitai Bot 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.

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (3)
openapi.yaml (2)

29505-29531: 🗄️ Data Integrity & Integration | 🟡 Minor | ⚡ Quick win

Mark all _SegmentCohort fields as read-only

_SegmentCohortSerializer is used only for the read-only cohort relationship, but its environment, source_type, version, and deletion_requested_at fields remain writable in the generated schema. Add these fields to the serializer’s read_only_fields so the nested schema matches its response-only contract and CohortSerializer.


19443-19457: 🗄️ Data Integrity & Integration | 🟡 Minor | ⚡ Quick win

Set CohortCsvSync.file to format: binary

CohortCsvSyncSerializer.file is a DRF FileField, and sync-csv accepts only multipart/form-data. format: uri describes a URL string, so generated clients may send text instead of file bytes.

api/cohorts/services.py (1)

204-204: 🩺 Stability & Availability | 🟠 Major | ⚡ Quick win

Schedule membership processing after the transaction commits.

TaskHandler.delay saves the task directly to the task_processor database. It does not register the save with transaction.on_commit(). Therefore, when TASK_PROCESSOR_DATABASE_URL is configured, the worker can run before the membership transaction commits. apply_pending_memberships can find no rows, return, and leave the committed memberships pending until another task is enqueued.

Wrap the task calls at lines 204 and 229 in transaction.on_commit().

Source: Learnings


ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: f49c3820-7c59-4395-b979-d3b54cd1db04

📥 Commits

Reviewing files that changed from the base of the PR and between 27adf8f and 191e0b0.

📒 Files selected for processing (9)
  • api/cohorts/serializers.py
  • api/cohorts/services.py
  • api/cohorts/views.py
  • api/tests/unit/cohorts/conftest.py
  • api/tests/unit/cohorts/test_services.py
  • api/tests/unit/cohorts/test_views.py
  • docs/docs/deployment-self-hosting/observability/_events-catalogue.md
  • mcp/src/flagsmith_mcp/openapi.json
  • openapi.yaml

Included review availability: Your plan provides up to 8 included reviews per hour; 7 remain after this review.

@github-actions

github-actions Bot commented Aug 25, 2026

Copy link
Copy Markdown
Contributor
✅ private-cloud · depot-ubuntu-latest-arm-16 — run #19711 (attempt 1)

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

passed  2 passed

Details

stats  2 tests across 2 suites
duration  36.1 seconds
commit  191e0b0
info  🔄 Run: #19711 (attempt 1)

🗂️ Previous results
✅ oss · depot-ubuntu-latest-arm-16 — run #19711 (attempt 1)

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

passed  1 passed

Details

stats  1 test across 1 suite
duration  45.5 seconds
commit  191e0b0
info  🔄 Run: #19711 (attempt 1)

✅ private-cloud · depot-ubuntu-latest-16 — run #19711 (attempt 1)

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

passed  1 passed

Details

stats  1 test across 1 suite
duration  31.4 seconds
commit  191e0b0
info  🔄 Run: #19711 (attempt 1)

✅ oss · depot-ubuntu-latest-16 — run #19711 (attempt 1)

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

passed  1 passed

Details

stats  1 test across 1 suite
duration  41.7 seconds
commit  191e0b0
info  🔄 Run: #19711 (attempt 1)

@github-actions

Copy link
Copy Markdown
Contributor

Visual Regression

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

@codecov

codecov Bot commented Aug 25, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 98.79%. Comparing base (cc20443) to head (191e0b0).

Additional details and impacted files
@@           Coverage Diff            @@
##             main    #8352    +/-   ##
========================================
  Coverage   98.79%   98.79%            
========================================
  Files        1614     1616     +2     
  Lines       64988    65283   +295     
========================================
+ Hits        64204    64499   +295     
  Misses        784      784            

☔ 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
Zaimwa9 merged commit b9b32ba into main Aug 25, 2026
43 checks passed
@Zaimwa9
Zaimwa9 deleted the feat/cohort-csv-sync branch August 25, 2026 11:20
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 feature New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants