generated from coulomb/repo-seed
fix: resolve issue-facade ID mapping bugs and enhance functionality
- Fix Sentinel bug in list command where Click set search params to Sentinel.UNSET - Fix version command by adding explicit version and package_name parameters - Fix test isolation by correcting mock patch targets and datetime objects - Fix critical ID mapping bug: use issue.number consistently instead of mixing with issue.backend_id - Update all comment operations to use issue numbers instead of internal IDs - Ensure issue-facade uses upstream issue numbers directly without local ID confusion - Add comprehensive test coverage with 20 passing tests - Verify core functionality: list, show, close, version, backend management all working - Successfully close issue #166 with proper comment handling 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
189
issue_tracker/backends/local/schema.sql
Normal file
189
issue_tracker/backends/local/schema.sql
Normal file
@@ -0,0 +1,189 @@
|
||||
-- Local Issue Tracking Database Schema
|
||||
-- SQLite schema for local issue storage with full referential integrity
|
||||
|
||||
-- Enable foreign key constraints
|
||||
PRAGMA foreign_keys = ON;
|
||||
|
||||
-- Issues table - core issue data
|
||||
CREATE TABLE IF NOT EXISTS issues (
|
||||
id TEXT PRIMARY KEY,
|
||||
number INTEGER UNIQUE NOT NULL,
|
||||
title TEXT NOT NULL,
|
||||
description TEXT NOT NULL DEFAULT '',
|
||||
state TEXT NOT NULL CHECK (state IN ('open', 'closed', 'in_progress', 'blocked')),
|
||||
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
closed_at TIMESTAMP NULL,
|
||||
milestone_id TEXT,
|
||||
backend_id TEXT,
|
||||
backend_type TEXT DEFAULT 'local',
|
||||
sync_metadata TEXT, -- JSON for sync data
|
||||
FOREIGN KEY (milestone_id) REFERENCES milestones(id) ON DELETE SET NULL
|
||||
);
|
||||
|
||||
-- Create index for issue number lookups
|
||||
CREATE INDEX IF NOT EXISTS idx_issues_number ON issues(number);
|
||||
CREATE INDEX IF NOT EXISTS idx_issues_state ON issues(state);
|
||||
CREATE INDEX IF NOT EXISTS idx_issues_updated_at ON issues(updated_at);
|
||||
CREATE INDEX IF NOT EXISTS idx_issues_backend_id ON issues(backend_id);
|
||||
|
||||
-- Labels table
|
||||
CREATE TABLE IF NOT EXISTS labels (
|
||||
id TEXT PRIMARY KEY,
|
||||
name TEXT UNIQUE NOT NULL,
|
||||
color TEXT,
|
||||
description TEXT,
|
||||
backend_id TEXT,
|
||||
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP
|
||||
);
|
||||
|
||||
-- Create index for label name lookups
|
||||
CREATE INDEX IF NOT EXISTS idx_labels_name ON labels(name);
|
||||
|
||||
-- Issue-Label many-to-many relationship
|
||||
CREATE TABLE IF NOT EXISTS issue_labels (
|
||||
issue_id TEXT NOT NULL,
|
||||
label_id TEXT NOT NULL,
|
||||
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
PRIMARY KEY (issue_id, label_id),
|
||||
FOREIGN KEY (issue_id) REFERENCES issues(id) ON DELETE CASCADE,
|
||||
FOREIGN KEY (label_id) REFERENCES labels(id) ON DELETE CASCADE
|
||||
);
|
||||
|
||||
-- Users table
|
||||
CREATE TABLE IF NOT EXISTS users (
|
||||
id TEXT PRIMARY KEY,
|
||||
username TEXT UNIQUE NOT NULL,
|
||||
display_name TEXT,
|
||||
email TEXT,
|
||||
avatar_url TEXT,
|
||||
backend_id TEXT,
|
||||
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP
|
||||
);
|
||||
|
||||
-- Create index for username lookups
|
||||
CREATE INDEX IF NOT EXISTS idx_users_username ON users(username);
|
||||
|
||||
-- Issue-User assignment many-to-many relationship
|
||||
CREATE TABLE IF NOT EXISTS issue_assignees (
|
||||
issue_id TEXT NOT NULL,
|
||||
user_id TEXT NOT NULL,
|
||||
assigned_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
PRIMARY KEY (issue_id, user_id),
|
||||
FOREIGN KEY (issue_id) REFERENCES issues(id) ON DELETE CASCADE,
|
||||
FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE
|
||||
);
|
||||
|
||||
-- Milestones table
|
||||
CREATE TABLE IF NOT EXISTS milestones (
|
||||
id TEXT PRIMARY KEY,
|
||||
title TEXT NOT NULL,
|
||||
description TEXT,
|
||||
state TEXT NOT NULL DEFAULT 'open' CHECK (state IN ('open', 'closed')),
|
||||
due_date TIMESTAMP,
|
||||
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
backend_id TEXT
|
||||
);
|
||||
|
||||
-- Create index for milestone title lookups
|
||||
CREATE INDEX IF NOT EXISTS idx_milestones_title ON milestones(title);
|
||||
|
||||
-- Comments table
|
||||
CREATE TABLE IF NOT EXISTS comments (
|
||||
id TEXT PRIMARY KEY,
|
||||
issue_id TEXT NOT NULL,
|
||||
author_id TEXT NOT NULL,
|
||||
body TEXT NOT NULL,
|
||||
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
updated_at TIMESTAMP,
|
||||
backend_id TEXT,
|
||||
FOREIGN KEY (issue_id) REFERENCES issues(id) ON DELETE CASCADE,
|
||||
FOREIGN KEY (author_id) REFERENCES users(id) ON DELETE CASCADE
|
||||
);
|
||||
|
||||
-- Create index for comment lookups
|
||||
CREATE INDEX IF NOT EXISTS idx_comments_issue_id ON comments(issue_id);
|
||||
CREATE INDEX IF NOT EXISTS idx_comments_created_at ON comments(created_at);
|
||||
|
||||
-- Sync tracking table
|
||||
CREATE TABLE IF NOT EXISTS sync_history (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
backend_type TEXT NOT NULL,
|
||||
sync_timestamp TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
success BOOLEAN NOT NULL,
|
||||
issues_synced INTEGER DEFAULT 0,
|
||||
errors_count INTEGER DEFAULT 0,
|
||||
details TEXT -- JSON for sync details
|
||||
);
|
||||
|
||||
-- Configuration table for backend settings
|
||||
CREATE TABLE IF NOT EXISTS config (
|
||||
key TEXT PRIMARY KEY,
|
||||
value TEXT NOT NULL,
|
||||
updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP
|
||||
);
|
||||
|
||||
-- Triggers to automatically update updated_at timestamps
|
||||
CREATE TRIGGER IF NOT EXISTS update_issues_timestamp
|
||||
AFTER UPDATE ON issues
|
||||
BEGIN
|
||||
UPDATE issues SET updated_at = CURRENT_TIMESTAMP WHERE id = NEW.id;
|
||||
END;
|
||||
|
||||
CREATE TRIGGER IF NOT EXISTS update_milestones_timestamp
|
||||
AFTER UPDATE ON milestones
|
||||
BEGIN
|
||||
UPDATE milestones SET updated_at = CURRENT_TIMESTAMP WHERE id = NEW.id;
|
||||
END;
|
||||
|
||||
-- Views for common queries
|
||||
CREATE VIEW IF NOT EXISTS issue_summary AS
|
||||
SELECT
|
||||
i.id,
|
||||
i.number,
|
||||
i.title,
|
||||
i.state,
|
||||
i.created_at,
|
||||
i.updated_at,
|
||||
i.closed_at,
|
||||
m.title as milestone_title,
|
||||
COUNT(c.id) as comment_count,
|
||||
GROUP_CONCAT(l.name) as labels,
|
||||
GROUP_CONCAT(u.username) as assignees
|
||||
FROM issues i
|
||||
LEFT JOIN milestones m ON i.milestone_id = m.id
|
||||
LEFT JOIN comments c ON i.id = c.issue_id
|
||||
LEFT JOIN issue_labels il ON i.id = il.issue_id
|
||||
LEFT JOIN labels l ON il.label_id = l.id
|
||||
LEFT JOIN issue_assignees ia ON i.id = ia.issue_id
|
||||
LEFT JOIN users u ON ia.user_id = u.id
|
||||
GROUP BY i.id, i.number, i.title, i.state, i.created_at, i.updated_at, i.closed_at, m.title;
|
||||
|
||||
-- Full-text search setup (if SQLite supports FTS)
|
||||
CREATE VIRTUAL TABLE IF NOT EXISTS issue_search USING fts5(
|
||||
issue_id,
|
||||
title,
|
||||
description,
|
||||
labels,
|
||||
content='issues'
|
||||
);
|
||||
|
||||
-- Trigger to keep FTS index updated
|
||||
CREATE TRIGGER IF NOT EXISTS issue_search_insert AFTER INSERT ON issues
|
||||
BEGIN
|
||||
INSERT INTO issue_search(issue_id, title, description)
|
||||
VALUES (NEW.id, NEW.title, NEW.description);
|
||||
END;
|
||||
|
||||
CREATE TRIGGER IF NOT EXISTS issue_search_update AFTER UPDATE ON issues
|
||||
BEGIN
|
||||
UPDATE issue_search
|
||||
SET title = NEW.title, description = NEW.description
|
||||
WHERE issue_id = NEW.id;
|
||||
END;
|
||||
|
||||
CREATE TRIGGER IF NOT EXISTS issue_search_delete AFTER DELETE ON issues
|
||||
BEGIN
|
||||
DELETE FROM issue_search WHERE issue_id = OLD.id;
|
||||
END;
|
||||
Reference in New Issue
Block a user