fix(e2e): bunyip-e2e-bootstrap ON CONFLICT match partial unique index (BUNYIP-161) #182

Merged
nrupard merged 1 commit from fix/BUNYIP-161-bootstrap-partial-index-conflict into main 2026-06-22 18:22:18 +02:00
Owner

What

Fixes bunyip-e2e-bootstrap failing to seed the E2E accounts:

Error: failed to upsert e2e-user@a8n.run
  there is no unique or exclusion constraint matching the ON CONFLICT specification

users.email uniqueness is a PARTIAL unique index since migration 20260324000029_soft_delete_email_unique.sql (users_email_unique_active: UNIQUE (email) WHERE deleted_at IS NULL), so the bootstrap's bare ON CONFLICT (email) has no matching arbiter. Adds the predicate:

ON CONFLICT (email) WHERE deleted_at IS NULL DO UPDATE SET ...

The bootstrap (BUNYIP-52) predates that migration and had never run against the post-migration schema.

Test

Not compiled locally (musl/dunite workspace build); CI validates. SQL string literal, runtime sqlx::query (no query! macro, no .sqlx regen), no Rust type impact. The INSERT supplies all NOT NULL-without-default columns, so no second error.

Deploy note

c-01 must rebuild the bunyip-api image (CI on merge) and redeploy before re-running just e2e-bootstrap; the fix is in the binary.

#BUNYIP-161

## What Fixes `bunyip-e2e-bootstrap` failing to seed the E2E accounts: ``` Error: failed to upsert e2e-user@a8n.run there is no unique or exclusion constraint matching the ON CONFLICT specification ``` `users.email` uniqueness is a PARTIAL unique index since migration `20260324000029_soft_delete_email_unique.sql` (`users_email_unique_active: UNIQUE (email) WHERE deleted_at IS NULL`), so the bootstrap's bare `ON CONFLICT (email)` has no matching arbiter. Adds the predicate: ```sql ON CONFLICT (email) WHERE deleted_at IS NULL DO UPDATE SET ... ``` The bootstrap (BUNYIP-52) predates that migration and had never run against the post-migration schema. ## Test Not compiled locally (musl/dunite workspace build); CI validates. SQL string literal, runtime `sqlx::query` (no `query!` macro, no `.sqlx` regen), no Rust type impact. The INSERT supplies all NOT NULL-without-default columns, so no second error. ## Deploy note c-01 must rebuild the bunyip-api image (CI on merge) and redeploy before re-running `just e2e-bootstrap`; the fix is in the binary. #BUNYIP-161
fix(e2e): match the partial unique index in bunyip-e2e-bootstrap upsert
Some checks failed
E2E / Playwright against deployment (pull_request) Failing after 37s
Check / fmt + clippy + build + tests (pull_request) Successful in 6m5s
Create release / Create release from merged PR (pull_request) Has been skipped
bf5dd1850d
Running bunyip-e2e-bootstrap against the current schema failed with "there is no unique or exclusion constraint matching the ON CONFLICT specification". Migration 20260324000029 dropped the plain users_email_key constraint and replaced it with a partial unique index (users_email_unique_active: UNIQUE (email) WHERE deleted_at IS NULL), so the bootstrap's bare `ON CONFLICT (email)` no longer has a matching arbiter. The bootstrap (BUNYIP-52) predates that migration and had not been run against the post-migration schema.

Add the index predicate to the conflict target: `ON CONFLICT (email) WHERE deleted_at IS NULL DO UPDATE SET ...`. The INSERT already supplies every NOT NULL column without a default (email, password_hash, role, email_verified); the rest default, so this is the only change. Runtime sqlx::query (not the query! macro), so no .sqlx cache regen.

Not compiled locally (musl/dunite workspace build); CI check.yml + build-api.yml validate. The change is a SQL string literal with no Rust type impact. c-01 needs a rebuilt bunyip-api image + redeploy to pick up the fixed binary before re-running `just e2e-bootstrap`.

#BUNYIP-161

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
nrupard scheduled this pull request to auto merge when all checks succeed 2026-06-22 18:17:26 +02:00
nrupard deleted branch fix/BUNYIP-161-bootstrap-partial-index-conflict 2026-06-22 18:22:18 +02:00
Sign in to join this conversation.
No reviewers
No labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
psa-systems/bunyip!182
No description provided.