CodeIssuesDiscussionsWikiPull RequestsProjectsCommitsActionsReleasesContributorsPulse● GatesSecuritySettingsDeploymentsPipelineInsightsAgents✨ Explain✨ Ask AI✨ Workspace✨ Spec✨ Tests▓ Debt Map✨ NL Search🏛 Archaeology
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 | -- Gluecron database schema
-- Run this against your Neon PostgreSQL database to initialize all tables.
-- psql $DATABASE_URL -f drizzle/0000_init.sql
CREATE EXTENSION IF NOT EXISTS "pgcrypto";
-- Users
CREATE TABLE IF NOT EXISTS users (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
username TEXT NOT NULL UNIQUE,
email TEXT NOT NULL UNIQUE,
display_name TEXT,
password_hash TEXT NOT NULL,
avatar_url TEXT,
bio TEXT,
created_at TIMESTAMP DEFAULT NOW() NOT NULL,
updated_at TIMESTAMP DEFAULT NOW() NOT NULL
);
-- Sessions
CREATE TABLE IF NOT EXISTS sessions (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
user_id UUID NOT NULL REFERENCES users(id) ON DELETE CASCADE,
token TEXT NOT NULL UNIQUE,
expires_at TIMESTAMP NOT NULL,
created_at TIMESTAMP DEFAULT NOW() NOT NULL
);
-- Repositories
CREATE TABLE IF NOT EXISTS repositories (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
name TEXT NOT NULL,
owner_id UUID NOT NULL REFERENCES users(id),
description TEXT,
is_private BOOLEAN DEFAULT FALSE NOT NULL,
default_branch TEXT DEFAULT 'main' NOT NULL,
disk_path TEXT NOT NULL,
forked_from_id UUID REFERENCES repositories(id) ON DELETE SET NULL,
created_at TIMESTAMP DEFAULT NOW() NOT NULL,
updated_at TIMESTAMP DEFAULT NOW() NOT NULL,
pushed_at TIMESTAMP,
star_count INTEGER DEFAULT 0 NOT NULL,
fork_count INTEGER DEFAULT 0 NOT NULL,
issue_count INTEGER DEFAULT 0 NOT NULL
);
CREATE UNIQUE INDEX IF NOT EXISTS repos_owner_name ON repositories(owner_id, name);
-- Stars
CREATE TABLE IF NOT EXISTS stars (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
user_id UUID NOT NULL REFERENCES users(id) ON DELETE CASCADE,
repository_id UUID NOT NULL REFERENCES repositories(id) ON DELETE CASCADE,
created_at TIMESTAMP DEFAULT NOW() NOT NULL
);
CREATE UNIQUE INDEX IF NOT EXISTS stars_user_repo ON stars(user_id, repository_id);
-- Issues
CREATE TABLE IF NOT EXISTS issues (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
number SERIAL,
repository_id UUID NOT NULL REFERENCES repositories(id) ON DELETE CASCADE,
author_id UUID NOT NULL REFERENCES users(id),
title TEXT NOT NULL,
body TEXT,
state TEXT NOT NULL DEFAULT 'open',
created_at TIMESTAMP DEFAULT NOW() NOT NULL,
updated_at TIMESTAMP DEFAULT NOW() NOT NULL,
closed_at TIMESTAMP
);
CREATE INDEX IF NOT EXISTS issues_repo_state ON issues(repository_id, state);
CREATE INDEX IF NOT EXISTS issues_repo_number ON issues(repository_id, number);
-- Issue Comments
CREATE TABLE IF NOT EXISTS issue_comments (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
issue_id UUID NOT NULL REFERENCES issues(id) ON DELETE CASCADE,
author_id UUID NOT NULL REFERENCES users(id),
body TEXT NOT NULL,
created_at TIMESTAMP DEFAULT NOW() NOT NULL,
updated_at TIMESTAMP DEFAULT NOW() NOT NULL
);
CREATE INDEX IF NOT EXISTS comments_issue ON issue_comments(issue_id);
-- Labels
CREATE TABLE IF NOT EXISTS labels (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
repository_id UUID NOT NULL REFERENCES repositories(id) ON DELETE CASCADE,
name TEXT NOT NULL,
color TEXT NOT NULL DEFAULT '#8b949e',
description TEXT
);
CREATE UNIQUE INDEX IF NOT EXISTS labels_repo_name ON labels(repository_id, name);
-- Issue Labels
CREATE TABLE IF NOT EXISTS issue_labels (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
issue_id UUID NOT NULL REFERENCES issues(id) ON DELETE CASCADE,
label_id UUID NOT NULL REFERENCES labels(id) ON DELETE CASCADE
);
CREATE UNIQUE INDEX IF NOT EXISTS issue_labels_unique ON issue_labels(issue_id, label_id);
-- Pull Requests
CREATE TABLE IF NOT EXISTS pull_requests (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
number SERIAL,
repository_id UUID NOT NULL REFERENCES repositories(id) ON DELETE CASCADE,
author_id UUID NOT NULL REFERENCES users(id),
title TEXT NOT NULL,
body TEXT,
state TEXT NOT NULL DEFAULT 'open',
base_branch TEXT NOT NULL,
head_branch TEXT NOT NULL,
merged_at TIMESTAMP,
merged_by UUID REFERENCES users(id),
created_at TIMESTAMP DEFAULT NOW() NOT NULL,
updated_at TIMESTAMP DEFAULT NOW() NOT NULL,
closed_at TIMESTAMP
);
CREATE INDEX IF NOT EXISTS prs_repo_state ON pull_requests(repository_id, state);
CREATE INDEX IF NOT EXISTS prs_repo_number ON pull_requests(repository_id, number);
-- PR Comments
CREATE TABLE IF NOT EXISTS pr_comments (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
pull_request_id UUID NOT NULL REFERENCES pull_requests(id) ON DELETE CASCADE,
author_id UUID NOT NULL REFERENCES users(id),
body TEXT NOT NULL,
is_ai_review BOOLEAN DEFAULT FALSE NOT NULL,
file_path TEXT,
line_number INTEGER,
created_at TIMESTAMP DEFAULT NOW() NOT NULL,
updated_at TIMESTAMP DEFAULT NOW() NOT NULL
);
CREATE INDEX IF NOT EXISTS pr_comments_pr ON pr_comments(pull_request_id);
-- Activity Feed
CREATE TABLE IF NOT EXISTS activity_feed (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
repository_id UUID NOT NULL REFERENCES repositories(id) ON DELETE CASCADE,
user_id UUID REFERENCES users(id),
action TEXT NOT NULL,
target_type TEXT,
target_id TEXT,
metadata TEXT,
created_at TIMESTAMP DEFAULT NOW() NOT NULL
);
CREATE INDEX IF NOT EXISTS activity_repo ON activity_feed(repository_id);
CREATE INDEX IF NOT EXISTS activity_user ON activity_feed(user_id);
-- Webhooks
CREATE TABLE IF NOT EXISTS webhooks (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
repository_id UUID NOT NULL REFERENCES repositories(id) ON DELETE CASCADE,
url TEXT NOT NULL,
secret TEXT,
events TEXT NOT NULL DEFAULT 'push',
is_active BOOLEAN DEFAULT TRUE NOT NULL,
last_delivered_at TIMESTAMP,
last_status INTEGER,
created_at TIMESTAMP DEFAULT NOW() NOT NULL
);
CREATE INDEX IF NOT EXISTS webhooks_repo ON webhooks(repository_id);
-- API Tokens
CREATE TABLE IF NOT EXISTS api_tokens (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
user_id UUID NOT NULL REFERENCES users(id) ON DELETE CASCADE,
name TEXT NOT NULL,
token_hash TEXT NOT NULL,
token_prefix TEXT NOT NULL,
scopes TEXT NOT NULL DEFAULT 'repo',
last_used_at TIMESTAMP,
expires_at TIMESTAMP,
created_at TIMESTAMP DEFAULT NOW() NOT NULL
);
-- Repository Topics
CREATE TABLE IF NOT EXISTS repo_topics (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
repository_id UUID NOT NULL REFERENCES repositories(id) ON DELETE CASCADE,
topic TEXT NOT NULL
);
CREATE UNIQUE INDEX IF NOT EXISTS repo_topics_unique ON repo_topics(repository_id, topic);
CREATE INDEX IF NOT EXISTS topics_name ON repo_topics(topic);
-- SSH Keys
CREATE TABLE IF NOT EXISTS ssh_keys (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
user_id UUID NOT NULL REFERENCES users(id) ON DELETE CASCADE,
title TEXT NOT NULL,
fingerprint TEXT NOT NULL,
public_key TEXT NOT NULL,
last_used_at TIMESTAMP,
created_at TIMESTAMP DEFAULT NOW() NOT NULL
);
|