fix(events): Handle nullable label and milestone in resource events
GitLab returns null for the label/milestone fields on resource_label_events and resource_milestone_events when the referenced label or milestone has been deleted. This caused deserialization failures during sync. - Add migration 012 to recreate both event tables with nullable label_name, milestone_title, and milestone_id columns (SQLite requires table recreation to alter NOT NULL constraints) - Change GitLabLabelEvent.label and GitLabMilestoneEvent.milestone to Option<> in the Rust types - Update upsert functions to pass through None values correctly - Add tests for null label and null milestone deserialization Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
65
migrations/012_nullable_label_milestone.sql
Normal file
65
migrations/012_nullable_label_milestone.sql
Normal file
@@ -0,0 +1,65 @@
|
||||
-- Migration 012: Make label_name and milestone_title nullable
|
||||
-- GitLab returns null for these when the referenced label/milestone has been deleted.
|
||||
|
||||
-- Recreate resource_label_events with nullable label_name
|
||||
CREATE TABLE resource_label_events_new (
|
||||
id INTEGER PRIMARY KEY,
|
||||
gitlab_id INTEGER NOT NULL,
|
||||
project_id INTEGER NOT NULL REFERENCES projects(id) ON DELETE CASCADE,
|
||||
issue_id INTEGER REFERENCES issues(id) ON DELETE CASCADE,
|
||||
merge_request_id INTEGER REFERENCES merge_requests(id) ON DELETE CASCADE,
|
||||
action TEXT NOT NULL CHECK (action IN ('add', 'remove')),
|
||||
label_name TEXT,
|
||||
actor_gitlab_id INTEGER,
|
||||
actor_username TEXT,
|
||||
created_at INTEGER NOT NULL,
|
||||
CHECK (
|
||||
(issue_id IS NOT NULL AND merge_request_id IS NULL) OR
|
||||
(issue_id IS NULL AND merge_request_id IS NOT NULL)
|
||||
)
|
||||
);
|
||||
|
||||
INSERT INTO resource_label_events_new
|
||||
SELECT * FROM resource_label_events;
|
||||
|
||||
DROP TABLE resource_label_events;
|
||||
ALTER TABLE resource_label_events_new RENAME TO resource_label_events;
|
||||
|
||||
CREATE UNIQUE INDEX uq_label_events_gitlab ON resource_label_events(gitlab_id, project_id);
|
||||
CREATE INDEX idx_label_events_issue ON resource_label_events(issue_id) WHERE issue_id IS NOT NULL;
|
||||
CREATE INDEX idx_label_events_mr ON resource_label_events(merge_request_id) WHERE merge_request_id IS NOT NULL;
|
||||
CREATE INDEX idx_label_events_created ON resource_label_events(created_at);
|
||||
|
||||
-- Recreate resource_milestone_events with nullable milestone_title
|
||||
CREATE TABLE resource_milestone_events_new (
|
||||
id INTEGER PRIMARY KEY,
|
||||
gitlab_id INTEGER NOT NULL,
|
||||
project_id INTEGER NOT NULL REFERENCES projects(id) ON DELETE CASCADE,
|
||||
issue_id INTEGER REFERENCES issues(id) ON DELETE CASCADE,
|
||||
merge_request_id INTEGER REFERENCES merge_requests(id) ON DELETE CASCADE,
|
||||
action TEXT NOT NULL CHECK (action IN ('add', 'remove')),
|
||||
milestone_title TEXT,
|
||||
milestone_id INTEGER,
|
||||
actor_gitlab_id INTEGER,
|
||||
actor_username TEXT,
|
||||
created_at INTEGER NOT NULL,
|
||||
CHECK (
|
||||
(issue_id IS NOT NULL AND merge_request_id IS NULL) OR
|
||||
(issue_id IS NULL AND merge_request_id IS NOT NULL)
|
||||
)
|
||||
);
|
||||
|
||||
INSERT INTO resource_milestone_events_new
|
||||
SELECT * FROM resource_milestone_events;
|
||||
|
||||
DROP TABLE resource_milestone_events;
|
||||
ALTER TABLE resource_milestone_events_new RENAME TO resource_milestone_events;
|
||||
|
||||
CREATE UNIQUE INDEX uq_milestone_events_gitlab ON resource_milestone_events(gitlab_id, project_id);
|
||||
CREATE INDEX idx_milestone_events_issue ON resource_milestone_events(issue_id) WHERE issue_id IS NOT NULL;
|
||||
CREATE INDEX idx_milestone_events_mr ON resource_milestone_events(merge_request_id) WHERE merge_request_id IS NOT NULL;
|
||||
CREATE INDEX idx_milestone_events_created ON resource_milestone_events(created_at);
|
||||
|
||||
-- Update schema version
|
||||
INSERT INTO schema_version (version, applied_at, description)
|
||||
VALUES (12, strftime('%s', 'now') * 1000, 'Make label_name and milestone_title nullable for deleted labels/milestones');
|
||||
Reference in New Issue
Block a user