| 1 | import { createId } from "@paralleldrive/cuid2"; |
| 2 | import { sql } |
| 3 | import { |
| 4 | index, |
| 5 | pgEnum, |
| 6 | pgTable, |
| 7 | text, |
| 8 | timestamp, |
| 9 | uniqueIndex, |
| 10 | } from "drizzle-orm/pg-core"; |
| 11 | import { issue } |
| 12 | import { repository } |
| 13 | |
| 14 | export const pullRequestState = |
| 15 | "open", |
| 16 | "closed", |
| 17 | "merged", |
| 18 | ]); |
| 19 | |
| 20 | /** |
| 21 | * Base and head are stored as separate repository ids because they are only the same row for a branch-to-branch request; a fork request spans two write-ahead logs that never learn about each other. |
| 22 | * |
| 23 | * `headSha` is the tip as of the last time the request was refreshed, so the diff a reviewer read stays addressable after the branch moves on. |
| 24 | * |
| 25 | * Number, title, body, author and comments live on the `issue` row; this row holds only what a git comparison needs. `state` keeps `merged`, which an issue has no word for, and is kept in step with `issue.state`. |
| 26 | */ |
| 27 | export const pullRequest = |
| 28 | "pull_request", |
| 29 | { |
| 30 | id: text() |
| 31 | .primaryKey() |
| 32 | .unique() |
| 33 | .notNull() |
| 34 | .$defaultFn(() => |
| 35 | issueId: text() |
| 36 | .references(() => |
| 37 | .notNull() |
| 38 | .unique(), |
| 39 | state: pullRequestState().notNull |
| 40 | |
| 41 | baseRepositoryId: text() |
| 42 | .references(() => |
| 43 | .notNull(), |
| 44 | baseRef: text().notNull |
| 45 | // Null once the head repository is deleted. It cannot be deleted while it heads an open request, so only closed and merged requests lose it. |
| 46 | headRepositoryId: text().references |
| 47 | onDelete: "set null", |
| 48 | }), |
| 49 | headRef: text().notNull |
| 50 | headSha: text().notNull |
| 51 | |
| 52 | mergeCommitSha: text(), |
| 53 | |
| 54 | mergedAt: timestamp({ |
| 55 | }, |
| 56 | (t) => |
| 57 | // One open request per branch pair. Closed and merged rows are history, so the constraint has to be partial or reopening the same branch is blocked. |
| 58 | uniqueIndex("pull_request_open_branch_idx") |
| 59 | .on(t.baseRepositoryId |
| 60 | .where(sql`${ |
| 61 | |
| 62 | index("pull_request_head_idx"). |
| 63 | index("pull_request_base_state_idx"). |
| 64 | ], |
| 65 | ); |