Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 6 additions & 1 deletion packages/db/drizzle.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,14 @@ export default {
dbCredentials: {
url: process.env.DATABASE_URL!,
},
/** Runner-owned journals and resumable cleanup cursors must survive a development schema push. */
/**
* Runner-owned journals, resumable cleanup cursors, and a Project bootstrap's connector and
* rollout marker (until its migration retires them) must survive a development schema push.
*/
tablesFilter: [
'!script_migrations',
'!project_workspace',
'!project_membership_rollout',
'!project_backfill_archive_repairs',
'!search_embedding_cleanup_progress',
'!search_embedding_cleanup_targets',
Expand Down
18 changes: 15 additions & 3 deletions packages/db/schema.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2171,6 +2171,20 @@ export const workspaceModeEnum = pgEnum('workspace_mode', [

export type WorkspaceMode = (typeof workspaceModeEnum.enumValues)[number]

/**
* A development push that bootstraps Projects first pushes this column nullable, so the columns
* `0032_project_membership` reads exist before it fills the column and enforces NOT NULL; the
* push that follows uses the required column. Every other push and generation reads it required.
*/
function workspaceProjectIdColumn() {
const column = text('project_id').references((): AnyPgColumn => project.id, {
onDelete: 'restrict',
})
return process.env.SIM_DB_PUSH_PROJECT_BOOTSTRAP === '1'
? (column as ReturnType<typeof column.notNull>)
: column.notNull()
}

export const workspace = pgTable(
'workspace',
{
Expand Down Expand Up @@ -2198,9 +2212,7 @@ export const workspace = pgTable(
organizationScopeKey: text('organization_scope_key').generatedAlwaysAs(
sql`CASE WHEN organization_id IS NULL THEN 'personal' ELSE 'organization:' || organization_id END`
),
projectId: text('project_id')
.notNull()
.references((): AnyPgColumn => project.id, { onDelete: 'restrict' }),
projectId: workspaceProjectIdColumn(),
workspaceMode: workspaceModeEnum('workspace_mode').notNull().default('grandfathered_shared'),
billedAccountUserId: text('billed_account_user_id')
.notNull()
Expand Down
Loading
Loading