Skip to content

Commit 10e4f50

Browse files
authored
fix(db): make seed-db script idempotent by cleaning up FK dependencies (#2383)
The seed script failed on repeated runs with a foreign key violation: "envs_teams_envs" on table "envs" (SQLSTATE 23503) This happened because DELETE FROM teams was attempted while rows in envs, snapshots, and volumes still referenced the team via ON DELETE NO ACTION constraints. Similarly, deleting auth.users could be blocked by addons.added_by (also ON DELETE NO ACTION). Fix the deletion order to explicitly remove blocking child rows before deleting the parent team and user: 1. DELETE envs for the team 2. DELETE snapshots for the team 3. DELETE volumes for the team 4. DELETE addons for the user 5. DELETE teams (team_api_keys, users_teams cascade automatically) 6. DELETE auth.users (access_tokens cascade automatically) 7. Re-create user, team, and associated credentials Tables with ON DELETE CASCADE/SET NULL (team_api_keys, users_teams, access_tokens, env_aliases, env_builds, etc.) are cleaned up automatically and do not need explicit deletes. Additionally, inserting into auth.users fires a trigger chain (sync_inserts_to_public_users -> post_user_signup) that auto-creates a default team. Delete that trigger-created team before inserting the seed team to avoid leaving duplicate teams for the same user.
1 parent 93261e6 commit 10e4f50

1 file changed

Lines changed: 46 additions & 3 deletions

File tree

packages/db/scripts/seed/postgres/seed-db.go

Lines changed: 46 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -77,8 +77,46 @@ func main() {
7777
}
7878
defer authDb.Close()
7979

80-
// Open .e2b/config.json
81-
// Delete existing user and recreate (simpler for seeding)
80+
// Clean up existing data for idempotent re-seeding.
81+
// Delete child rows that have ON DELETE NO ACTION constraints
82+
// before deleting the team and user.
83+
err = authDb.TestsRawSQL(ctx, `
84+
DELETE FROM envs WHERE team_id IN (SELECT id FROM teams WHERE email = $1)
85+
`, email)
86+
if err != nil {
87+
panic(err)
88+
}
89+
90+
err = authDb.TestsRawSQL(ctx, `
91+
DELETE FROM snapshots WHERE team_id IN (SELECT id FROM teams WHERE email = $1)
92+
`, email)
93+
if err != nil {
94+
panic(err)
95+
}
96+
97+
err = authDb.TestsRawSQL(ctx, `
98+
DELETE FROM volumes WHERE team_id IN (SELECT id FROM teams WHERE email = $1)
99+
`, email)
100+
if err != nil {
101+
panic(err)
102+
}
103+
104+
err = authDb.TestsRawSQL(ctx, `
105+
DELETE FROM addons WHERE added_by IN (SELECT id FROM auth.users WHERE email = $1)
106+
`, email)
107+
if err != nil {
108+
panic(err)
109+
}
110+
111+
// Now safe to delete team (team_api_keys, users_teams cascade automatically)
112+
err = authDb.TestsRawSQL(ctx, `
113+
DELETE FROM teams WHERE email = $1
114+
`, email)
115+
if err != nil {
116+
panic(err)
117+
}
118+
119+
// Now safe to delete user (access_tokens cascade automatically)
82120
err = authDb.TestsRawSQL(ctx, `
83121
DELETE FROM auth.users WHERE email = $1
84122
`, email)
@@ -87,6 +125,10 @@ DELETE FROM auth.users WHERE email = $1
87125
}
88126

89127
// Create the user
128+
// NOTE: Inserting into auth.users fires the sync_inserts_to_public_users trigger,
129+
// which inserts into public.users, which fires the post_user_signup trigger,
130+
// which auto-creates a default team + users_teams row. We delete that
131+
// trigger-created team below so we can create our own with a known ID/name.
90132
userID := uuid.New()
91133
err = authDb.TestsRawSQL(ctx, `
92134
INSERT INTO auth.users (id, email)
@@ -96,7 +138,8 @@ VALUES ($1, $2)
96138
panic(err)
97139
}
98140

99-
// Delete team
141+
// Remove the team auto-created by the post_user_signup trigger so we can
142+
// create our own seed team with a deterministic ID and custom name/slug.
100143
err = authDb.TestsRawSQL(ctx, `
101144
DELETE FROM teams WHERE email = $1
102145
`, email)

0 commit comments

Comments
 (0)