Skip to content

fix(clickhouse): Unblock flagsmith migrate when ClickHouse is configured - #8445

Closed
matthewelwell wants to merge 1 commit into
mainfrom
fix/clickhouse-migration-recorder-patch-ordering
Closed

fix(clickhouse): Unblock flagsmith migrate when ClickHouse is configured#8445
matthewelwell wants to merge 1 commit into
mainfrom
fix/clickhouse-migration-recorder-patch-ordering

Conversation

@matthewelwell

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

On any install with CLICKHOUSE_URL or CLICKHOUSE_HOST set, flagsmith migrate exits 1 partway through with FieldError: Cannot resolve keyword 'deleted' into field. Choices are: app, applied, id, name, so migrations never complete.

_migrate() walks FLAGSMITH_MIGRATE_DATABASES in one process with clickhouse appended last, so default is migrated first. That resolves a Postgres MigrationRecorder, and Django's classproperty caches the Postgres-shaped model on the class. clickhouse-backend applies its monkeypatches as an import side effect of clickhouse_backend.backend, which Django only imports when it opens the ClickHouse connection — too late. Its replacement Migration property reads the stale class attribute, so the ClickHouse recorder gets a model with no deleted column and migration_qs, which filters on deleted for ClickHouse connections, raises.

This imports the backend from the app's ready() so the patches land before any recorder is resolved, behind a check on the clickhouse alias so Postgres-only installs stay unpatched as they are today.

The same stale cache breaks local make test, where each xdist worker sets up databases lazily — several hundred errors per run, varying with test order. CI never saw either symptom: no workflow runs migrations, and --ci builds every connection up front, importing the backend before any recorder exists.

How did you test this code?

Two new unit tests cover both branches of the alias guard.

Manually, against throwaway Postgres and ClickHouse databases:

  1. CLICKHOUSE_HOST=localhost ... flagsmith migrate on mainexit 1, dies on the first migration recorded against the clickhouse alias.
  2. Same command with this change → exit 0, full run completes.
  3. Reproduced the underlying ordering directly: resolving a Postgres recorder before the ClickHouse one yielded a Migration model with fields ['app', 'applied', 'id', 'name'] and a FieldError; with this change it yields ['app', 'applied', 'deleted', 'id', 'name'].
  4. Confirmed a Postgres-only install (no CLICKHOUSE_*) leaves clickhouse_backend.backend unimported.

Full suite locally with -n auto: 5022 passed, 24 skipped, 0 failed, 0 errors — previously 1123 errors from this cause on the same machine.

…gured

On any install with `CLICKHOUSE_URL` or `CLICKHOUSE_HOST` set, `flagsmith
migrate` exits 1 partway through without finishing:

    django.core.exceptions.FieldError: Cannot resolve keyword 'deleted'
    into field. Choices are: app, applied, id, name

`_migrate()` walks `FLAGSMITH_MIGRATE_DATABASES` in a single process and
`clickhouse` is appended last, so `default` is always migrated first. That
resolves a Postgres `MigrationRecorder`, and Django's `classproperty` caches
the Postgres-shaped model on the *class*. `clickhouse-backend` applies its
monkeypatches as an import side effect of `clickhouse_backend.backend`,
which Django only imports when it opens the ClickHouse connection -- by
which point that cache is already populated. The patched `Migration`
property reads the stale class attribute, so the ClickHouse recorder is
handed a model with no `deleted` column, and `migration_qs`, which filters
on `deleted` for ClickHouse connections, raises.

Import the backend from the app's `ready()` so the patches are in place
before any recorder is resolved. Kept behind a check on the `clickhouse`
alias so Postgres-only installs stay unpatched, as they are today.

The same stale cache also breaks local test runs, where each xdist worker
sets up its databases lazily. It accounted for several hundred errors per
`make test`, varying with test order. CI escaped both symptoms: no workflow
runs migrations, and `--ci` builds every connection up front, which imports
the backend before any recorder exists.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@matthewelwell
matthewelwell requested a review from a team as a code owner September 2, 2026 17:54
@matthewelwell
matthewelwell requested review from emyller and removed request for a team September 2, 2026 17:54
@vercel

vercel Bot commented Sep 2, 2026

Copy link
Copy Markdown

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

3 Skipped Deployments
Project Deployment Actions Updated
docs Ignored Ignored Sep 2, 2026 5:54pm UTC
flagsmith-frontend-preview Ignored Ignored Sep 2, 2026 5:54pm UTC
flagsmith-frontend-staging Ignored Ignored Sep 2, 2026 5:54pm UTC

Request Review

@github-actions github-actions Bot added api Issue related to the REST API fix labels Sep 2, 2026
@github-actions

github-actions Bot commented Sep 2, 2026

Copy link
Copy Markdown
Contributor

Docker builds report

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

@coderabbitai

coderabbitai Bot commented Sep 2, 2026

Copy link
Copy Markdown

Review Change Stack

Caution

Review failed

The pull request is closed.

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Team

Run ID: b3382b17-f5f9-4a25-a1ff-39d9f478fcb4

📥 Commits

Reviewing files that changed from the base of the PR and between 2d18e02 and 4842d89.

📒 Files selected for processing (3)
  • api/clickhouse/apps.py
  • api/tests/unit/clickhouse/__init__.py
  • api/tests/unit/clickhouse/test_unit_clickhouse_apps.py

📝 Walkthrough

Walkthrough

ClickHouseConfig.ready() now eagerly imports the ClickHouse backend when clickhouse exists in settings.DATABASES. It returns without importing the backend when ClickHouse is not configured. Unit tests cover both configuration paths.

Estimated code review effort: 2 (Simple) | ~10 minutes


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.

@matthewelwell

Copy link
Copy Markdown
Contributor Author

I don't understand the need for this PR enough to stand behind it - it's pure slop. Closing and will discuss internally as needed.

@emyller
emyller deleted the fix/clickhouse-migration-recorder-patch-ordering branch September 2, 2026 17:56
@github-actions

github-actions Bot commented Sep 2, 2026

Copy link
Copy Markdown
Contributor
✅ private-cloud · depot-ubuntu-latest-arm-16 — run #20076 (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, 17 seconds
commit  4842d89
info  🔄 Run: #20076 (attempt 1)

🗂️ Previous results
✅ private-cloud · depot-ubuntu-latest-16 — run #20076 (attempt 1)

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

passed  1 passed

Details

stats  1 test across 1 suite
duration  37.7 seconds
commit  4842d89
info  🔄 Run: #20076 (attempt 1)

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

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

passed  1 passed

Details

stats  1 test across 1 suite
duration  49.1 seconds
commit  4842d89
info  🔄 Run: #20076 (attempt 1)

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

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

passed  1 passed

Details

stats  1 test across 1 suite
duration  33.5 seconds
commit  4842d89
info  🔄 Run: #20076 (attempt 1)

@codecov

codecov Bot commented Sep 2, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 98.81%. Comparing base (2d18e02) to head (4842d89).

Additional details and impacted files
@@           Coverage Diff           @@
##             main    #8445   +/-   ##
=======================================
  Coverage   98.81%   98.81%           
=======================================
  Files        1621     1622    +1     
  Lines       66128    66155   +27     
=======================================
+ Hits        65344    65371   +27     
  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.

@github-actions

github-actions Bot commented Sep 2, 2026

Copy link
Copy Markdown
Contributor

Visual Regression

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

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

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant