feat(db): Add schema migration v6 for merge request support
Introduces comprehensive database schema for merge request ingestion (CP2), designed with forward compatibility for future features. New tables: - merge_requests: Core MR metadata with draft status, branch info, detailed_merge_status (modern API field), and sync health telemetry columns for debuggability - mr_labels: Junction table linking MRs to shared labels table - mr_assignees: MR assignee usernames (same pattern as issues) - mr_reviewers: MR-specific reviewer tracking (not applicable to issues) Additional indexes: - discussions: Add merge_request_id and resolved status indexes - notes: Add composite indexes for DiffNote file/line queries DiffNote position enhancements: - position_type: 'text' | 'image' | 'file' for diff comment semantics - position_line_range_start/end: Multi-line comment range support - position_base_sha/start_sha/head_sha: Commit context for diff notes The schema captures CP3-ready fields (head_sha, references_short/full, SHA triplet) at zero additional API cost, preparing for file-context and cross-project reference features. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
97
migrations/006_merge_requests.sql
Normal file
97
migrations/006_merge_requests.sql
Normal file
@@ -0,0 +1,97 @@
|
|||||||
|
-- Migration 006: Merge Requests, MR Labels, Assignees, Reviewers
|
||||||
|
-- Schema version: 6
|
||||||
|
-- Adds CP2 MR ingestion support
|
||||||
|
|
||||||
|
-- Merge requests table
|
||||||
|
CREATE TABLE merge_requests (
|
||||||
|
id INTEGER PRIMARY KEY,
|
||||||
|
gitlab_id INTEGER UNIQUE NOT NULL,
|
||||||
|
project_id INTEGER NOT NULL REFERENCES projects(id),
|
||||||
|
iid INTEGER NOT NULL,
|
||||||
|
title TEXT,
|
||||||
|
description TEXT,
|
||||||
|
state TEXT, -- 'opened' | 'merged' | 'closed' | 'locked'
|
||||||
|
draft INTEGER NOT NULL DEFAULT 0, -- 0/1 (SQLite boolean) - work-in-progress status
|
||||||
|
author_username TEXT,
|
||||||
|
source_branch TEXT,
|
||||||
|
target_branch TEXT,
|
||||||
|
head_sha TEXT, -- Current commit SHA at head of source branch (CP3-ready)
|
||||||
|
references_short TEXT, -- Short reference e.g. "!123" (CP3-ready for display)
|
||||||
|
references_full TEXT, -- Full reference e.g. "group/project!123" (CP3-ready for cross-project)
|
||||||
|
detailed_merge_status TEXT, -- preferred, non-deprecated (replaces merge_status)
|
||||||
|
merge_user_username TEXT, -- preferred over deprecated merged_by
|
||||||
|
created_at INTEGER, -- ms epoch UTC
|
||||||
|
updated_at INTEGER, -- ms epoch UTC
|
||||||
|
merged_at INTEGER, -- ms epoch UTC (NULL if not merged)
|
||||||
|
closed_at INTEGER, -- ms epoch UTC (NULL if not closed)
|
||||||
|
last_seen_at INTEGER NOT NULL, -- ms epoch UTC, updated on every upsert
|
||||||
|
-- Prevents re-fetching discussions on cursor rewind / reruns unless MR changed.
|
||||||
|
discussions_synced_for_updated_at INTEGER,
|
||||||
|
-- Sync health telemetry for debuggability
|
||||||
|
discussions_sync_last_attempt_at INTEGER, -- ms epoch UTC of last sync attempt
|
||||||
|
discussions_sync_attempts INTEGER DEFAULT 0, -- count of sync attempts for this MR version
|
||||||
|
discussions_sync_last_error TEXT, -- last error message if sync failed
|
||||||
|
web_url TEXT,
|
||||||
|
raw_payload_id INTEGER REFERENCES raw_payloads(id)
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE INDEX idx_mrs_project_updated ON merge_requests(project_id, updated_at);
|
||||||
|
CREATE INDEX idx_mrs_author ON merge_requests(author_username);
|
||||||
|
CREATE INDEX idx_mrs_target_branch ON merge_requests(project_id, target_branch);
|
||||||
|
CREATE INDEX idx_mrs_source_branch ON merge_requests(project_id, source_branch);
|
||||||
|
CREATE INDEX idx_mrs_state ON merge_requests(project_id, state);
|
||||||
|
CREATE INDEX idx_mrs_detailed_merge_status ON merge_requests(project_id, detailed_merge_status);
|
||||||
|
CREATE INDEX idx_mrs_draft ON merge_requests(project_id, draft);
|
||||||
|
CREATE INDEX idx_mrs_discussions_sync ON merge_requests(project_id, discussions_synced_for_updated_at);
|
||||||
|
CREATE UNIQUE INDEX uq_mrs_project_iid ON merge_requests(project_id, iid);
|
||||||
|
|
||||||
|
-- MR-Label junction (reuses labels table from CP1)
|
||||||
|
CREATE TABLE mr_labels (
|
||||||
|
merge_request_id INTEGER REFERENCES merge_requests(id) ON DELETE CASCADE,
|
||||||
|
label_id INTEGER REFERENCES labels(id) ON DELETE CASCADE,
|
||||||
|
PRIMARY KEY(merge_request_id, label_id)
|
||||||
|
);
|
||||||
|
CREATE INDEX idx_mr_labels_label ON mr_labels(label_id);
|
||||||
|
|
||||||
|
-- MR assignees (same pattern as issue_assignees)
|
||||||
|
CREATE TABLE mr_assignees (
|
||||||
|
merge_request_id INTEGER REFERENCES merge_requests(id) ON DELETE CASCADE,
|
||||||
|
username TEXT NOT NULL,
|
||||||
|
PRIMARY KEY(merge_request_id, username)
|
||||||
|
);
|
||||||
|
CREATE INDEX idx_mr_assignees_username ON mr_assignees(username);
|
||||||
|
|
||||||
|
-- MR reviewers (MR-specific, not applicable to issues)
|
||||||
|
CREATE TABLE mr_reviewers (
|
||||||
|
merge_request_id INTEGER REFERENCES merge_requests(id) ON DELETE CASCADE,
|
||||||
|
username TEXT NOT NULL,
|
||||||
|
PRIMARY KEY(merge_request_id, username)
|
||||||
|
);
|
||||||
|
CREATE INDEX idx_mr_reviewers_username ON mr_reviewers(username);
|
||||||
|
|
||||||
|
-- Add FK constraint to discussions table for merge_request_id
|
||||||
|
-- Note: SQLite doesn't support ADD CONSTRAINT, the FK was defined in CP1 but nullable
|
||||||
|
-- We just need to add an index if not already present
|
||||||
|
CREATE INDEX IF NOT EXISTS idx_discussions_mr_id ON discussions(merge_request_id);
|
||||||
|
CREATE INDEX IF NOT EXISTS idx_discussions_mr_resolved ON discussions(merge_request_id, resolved, resolvable);
|
||||||
|
|
||||||
|
-- Additional indexes for DiffNote queries (notes table from CP1)
|
||||||
|
-- These composite indexes enable efficient file-context queries for CP3
|
||||||
|
CREATE INDEX IF NOT EXISTS idx_notes_type ON notes(note_type);
|
||||||
|
CREATE INDEX IF NOT EXISTS idx_notes_new_path ON notes(position_new_path);
|
||||||
|
CREATE INDEX IF NOT EXISTS idx_notes_new_path_line ON notes(position_new_path, position_new_line);
|
||||||
|
CREATE INDEX IF NOT EXISTS idx_notes_old_path_line ON notes(position_old_path, position_old_line);
|
||||||
|
|
||||||
|
-- CP2: capture richer diff note position shapes (minimal, still MVP)
|
||||||
|
-- These fields support modern GitLab diff note semantics without full diff reconstruction
|
||||||
|
ALTER TABLE notes ADD COLUMN position_type TEXT; -- 'text' | 'image' | 'file'
|
||||||
|
ALTER TABLE notes ADD COLUMN position_line_range_start INTEGER; -- multi-line comment start
|
||||||
|
ALTER TABLE notes ADD COLUMN position_line_range_end INTEGER; -- multi-line comment end
|
||||||
|
-- DiffNote SHA triplet for commit context (CP3-ready, zero extra API cost)
|
||||||
|
ALTER TABLE notes ADD COLUMN position_base_sha TEXT; -- Base commit SHA for diff
|
||||||
|
ALTER TABLE notes ADD COLUMN position_start_sha TEXT; -- Start commit SHA for diff
|
||||||
|
ALTER TABLE notes ADD COLUMN position_head_sha TEXT; -- Head commit SHA for diff
|
||||||
|
|
||||||
|
-- Update schema version
|
||||||
|
INSERT INTO schema_version (version, applied_at, description)
|
||||||
|
VALUES (6, strftime('%s', 'now') * 1000, 'Merge requests, MR labels, assignees, reviewers');
|
||||||
Reference in New Issue
Block a user