feat: added repositories support

This commit is contained in:
Carlos Florêncio
2026-01-11 19:59:28 +00:00
parent 00c65268bc
commit 473b336b13
24 changed files with 2823 additions and 276 deletions
@@ -135,6 +135,35 @@ func (r *SQLiteRepository) initSchema() error {
FOREIGN KEY (column_id) REFERENCES columns(id) ON DELETE CASCADE
);
CREATE TABLE IF NOT EXISTS repositories (
id TEXT PRIMARY KEY,
workspace_id TEXT NOT NULL,
name TEXT NOT NULL,
source_type TEXT NOT NULL DEFAULT 'local',
local_path TEXT DEFAULT '',
provider TEXT DEFAULT '',
provider_repo_id TEXT DEFAULT '',
provider_owner TEXT DEFAULT '',
provider_name TEXT DEFAULT '',
default_branch TEXT DEFAULT '',
setup_script TEXT DEFAULT '',
cleanup_script TEXT DEFAULT '',
created_at DATETIME NOT NULL,
updated_at DATETIME NOT NULL,
FOREIGN KEY (workspace_id) REFERENCES workspaces(id) ON DELETE CASCADE
);
CREATE TABLE IF NOT EXISTS repository_scripts (
id TEXT PRIMARY KEY,
repository_id TEXT NOT NULL,
name TEXT NOT NULL,
command TEXT NOT NULL,
position INTEGER DEFAULT 0,
created_at DATETIME NOT NULL,
updated_at DATETIME NOT NULL,
FOREIGN KEY (repository_id) REFERENCES repositories(id) ON DELETE CASCADE
);
CREATE TABLE IF NOT EXISTS task_boards (
task_id TEXT NOT NULL,
board_id TEXT NOT NULL,
@@ -160,6 +189,8 @@ func (r *SQLiteRepository) initSchema() error {
CREATE INDEX IF NOT EXISTS idx_task_boards_board_id ON task_boards(board_id);
CREATE INDEX IF NOT EXISTS idx_task_columns_board_id ON task_columns(board_id);
CREATE INDEX IF NOT EXISTS idx_task_columns_column_id ON task_columns(column_id);
CREATE INDEX IF NOT EXISTS idx_repositories_workspace_id ON repositories(workspace_id);
CREATE INDEX IF NOT EXISTS idx_repository_scripts_repo_id ON repository_scripts(repository_id);
CREATE TABLE IF NOT EXISTS task_agent_execution_logs (
id TEXT PRIMARY KEY,
@@ -980,3 +1011,194 @@ func (r *SQLiteRepository) DeleteComment(ctx context.Context, id string) error {
}
return nil
}
// Repository operations
// CreateRepository creates a new repository
func (r *SQLiteRepository) CreateRepository(ctx context.Context, repository *models.Repository) error {
if repository.ID == "" {
repository.ID = uuid.New().String()
}
now := time.Now().UTC()
repository.CreatedAt = now
repository.UpdatedAt = now
_, err := r.db.ExecContext(ctx, `
INSERT INTO repositories (
id, workspace_id, name, source_type, local_path, provider, provider_repo_id, provider_owner,
provider_name, default_branch, setup_script, cleanup_script, created_at, updated_at
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
`, repository.ID, repository.WorkspaceID, repository.Name, repository.SourceType, repository.LocalPath, repository.Provider,
repository.ProviderRepoID, repository.ProviderOwner, repository.ProviderName, repository.DefaultBranch,
repository.SetupScript, repository.CleanupScript, repository.CreatedAt, repository.UpdatedAt)
return err
}
// GetRepository retrieves a repository by ID
func (r *SQLiteRepository) GetRepository(ctx context.Context, id string) (*models.Repository, error) {
repository := &models.Repository{}
err := r.db.QueryRowContext(ctx, `
SELECT id, workspace_id, name, source_type, local_path, provider, provider_repo_id, provider_owner,
provider_name, default_branch, setup_script, cleanup_script, created_at, updated_at
FROM repositories WHERE id = ?
`, id).Scan(
&repository.ID, &repository.WorkspaceID, &repository.Name, &repository.SourceType, &repository.LocalPath,
&repository.Provider, &repository.ProviderRepoID, &repository.ProviderOwner, &repository.ProviderName,
&repository.DefaultBranch, &repository.SetupScript, &repository.CleanupScript, &repository.CreatedAt, &repository.UpdatedAt,
)
if err == sql.ErrNoRows {
return nil, fmt.Errorf("repository not found: %s", id)
}
return repository, err
}
// UpdateRepository updates an existing repository
func (r *SQLiteRepository) UpdateRepository(ctx context.Context, repository *models.Repository) error {
repository.UpdatedAt = time.Now().UTC()
result, err := r.db.ExecContext(ctx, `
UPDATE repositories SET
name = ?, source_type = ?, local_path = ?, provider = ?, provider_repo_id = ?, provider_owner = ?,
provider_name = ?, default_branch = ?, setup_script = ?, cleanup_script = ?, updated_at = ?
WHERE id = ?
`, repository.Name, repository.SourceType, repository.LocalPath, repository.Provider, repository.ProviderRepoID,
repository.ProviderOwner, repository.ProviderName, repository.DefaultBranch, repository.SetupScript, repository.CleanupScript,
repository.UpdatedAt, repository.ID)
if err != nil {
return err
}
rows, _ := result.RowsAffected()
if rows == 0 {
return fmt.Errorf("repository not found: %s", repository.ID)
}
return nil
}
// DeleteRepository deletes a repository by ID
func (r *SQLiteRepository) DeleteRepository(ctx context.Context, id string) error {
result, err := r.db.ExecContext(ctx, `DELETE FROM repositories WHERE id = ?`, id)
if err != nil {
return err
}
rows, _ := result.RowsAffected()
if rows == 0 {
return fmt.Errorf("repository not found: %s", id)
}
return nil
}
// ListRepositories returns all repositories for a workspace
func (r *SQLiteRepository) ListRepositories(ctx context.Context, workspaceID string) ([]*models.Repository, error) {
rows, err := r.db.QueryContext(ctx, `
SELECT id, workspace_id, name, source_type, local_path, provider, provider_repo_id, provider_owner,
provider_name, default_branch, setup_script, cleanup_script, created_at, updated_at
FROM repositories WHERE workspace_id = ? ORDER BY created_at DESC
`, workspaceID)
if err != nil {
return nil, err
}
defer rows.Close()
var result []*models.Repository
for rows.Next() {
repository := &models.Repository{}
err := rows.Scan(
&repository.ID, &repository.WorkspaceID, &repository.Name, &repository.SourceType, &repository.LocalPath,
&repository.Provider, &repository.ProviderRepoID, &repository.ProviderOwner, &repository.ProviderName,
&repository.DefaultBranch, &repository.SetupScript, &repository.CleanupScript, &repository.CreatedAt, &repository.UpdatedAt,
)
if err != nil {
return nil, err
}
result = append(result, repository)
}
return result, rows.Err()
}
// Repository script operations
// CreateRepositoryScript creates a new repository script
func (r *SQLiteRepository) CreateRepositoryScript(ctx context.Context, script *models.RepositoryScript) error {
if script.ID == "" {
script.ID = uuid.New().String()
}
now := time.Now().UTC()
script.CreatedAt = now
script.UpdatedAt = now
_, err := r.db.ExecContext(ctx, `
INSERT INTO repository_scripts (id, repository_id, name, command, position, created_at, updated_at)
VALUES (?, ?, ?, ?, ?, ?, ?)
`, script.ID, script.RepositoryID, script.Name, script.Command, script.Position, script.CreatedAt, script.UpdatedAt)
return err
}
// GetRepositoryScript retrieves a repository script by ID
func (r *SQLiteRepository) GetRepositoryScript(ctx context.Context, id string) (*models.RepositoryScript, error) {
script := &models.RepositoryScript{}
err := r.db.QueryRowContext(ctx, `
SELECT id, repository_id, name, command, position, created_at, updated_at
FROM repository_scripts WHERE id = ?
`, id).Scan(&script.ID, &script.RepositoryID, &script.Name, &script.Command, &script.Position, &script.CreatedAt, &script.UpdatedAt)
if err == sql.ErrNoRows {
return nil, fmt.Errorf("repository script not found: %s", id)
}
return script, err
}
// UpdateRepositoryScript updates an existing repository script
func (r *SQLiteRepository) UpdateRepositoryScript(ctx context.Context, script *models.RepositoryScript) error {
script.UpdatedAt = time.Now().UTC()
result, err := r.db.ExecContext(ctx, `
UPDATE repository_scripts SET name = ?, command = ?, position = ?, updated_at = ? WHERE id = ?
`, script.Name, script.Command, script.Position, script.UpdatedAt, script.ID)
if err != nil {
return err
}
rows, _ := result.RowsAffected()
if rows == 0 {
return fmt.Errorf("repository script not found: %s", script.ID)
}
return nil
}
// DeleteRepositoryScript deletes a repository script by ID
func (r *SQLiteRepository) DeleteRepositoryScript(ctx context.Context, id string) error {
result, err := r.db.ExecContext(ctx, `DELETE FROM repository_scripts WHERE id = ?`, id)
if err != nil {
return err
}
rows, _ := result.RowsAffected()
if rows == 0 {
return fmt.Errorf("repository script not found: %s", id)
}
return nil
}
// ListRepositoryScripts returns all scripts for a repository
func (r *SQLiteRepository) ListRepositoryScripts(ctx context.Context, repositoryID string) ([]*models.RepositoryScript, error) {
rows, err := r.db.QueryContext(ctx, `
SELECT id, repository_id, name, command, position, created_at, updated_at
FROM repository_scripts WHERE repository_id = ? ORDER BY position
`, repositoryID)
if err != nil {
return nil, err
}
defer rows.Close()
var result []*models.RepositoryScript
for rows.Next() {
script := &models.RepositoryScript{}
err := rows.Scan(&script.ID, &script.RepositoryID, &script.Name, &script.Command, &script.Position, &script.CreatedAt, &script.UpdatedAt)
if err != nil {
return nil, err
}
result = append(result, script)
}
return result, rows.Err()
}