summaryrefslogtreecommitdiff
path: root/internal/storage/db.go
diff options
context:
space:
mode:
authorPeter Stone <thepeterstone@gmail.com>2026-03-21 21:23:42 +0000
committerPeter Stone <thepeterstone@gmail.com>2026-03-21 21:23:42 +0000
commit888f3014b42ff48f597d0a81e9f52104d19be6db (patch)
tree133d1c2e45affe293624991c3b8239b2429c21e9 /internal/storage/db.go
parenta10e7478a130d6453abbd8fb0694948785dd2155 (diff)
feat: Phase 2 — project registry, legacy field cleanup, credential path fix
- task.Project type + storage CRUD + UpsertProject + SeedProjects - Remove AgentConfig.ProjectDir, RepositoryURL, SkipPlanning - Remove ContainerRunner fallback git init logic - Project API endpoints: GET/POST /api/projects, GET/PUT /api/projects/{id} - processResult no longer extracts changestats (pool-side only) - claude_config_dir config field; default to credentials/claude/ - New scripts: sync-credentials, fix-permissions, check-token Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Diffstat (limited to 'internal/storage/db.go')
-rw-r--r--internal/storage/db.go71
1 files changed, 71 insertions, 0 deletions
diff --git a/internal/storage/db.go b/internal/storage/db.go
index 1a0e74f..8f834b2 100644
--- a/internal/storage/db.go
+++ b/internal/storage/db.go
@@ -109,6 +109,16 @@ func (s *DB) migrate() error {
)`,
`CREATE INDEX IF NOT EXISTS idx_agent_events_agent ON agent_events(agent)`,
`CREATE INDEX IF NOT EXISTS idx_agent_events_timestamp ON agent_events(timestamp)`,
+ `CREATE TABLE IF NOT EXISTS projects (
+ id TEXT PRIMARY KEY,
+ name TEXT NOT NULL,
+ remote_url TEXT NOT NULL DEFAULT '',
+ local_path TEXT NOT NULL DEFAULT '',
+ type TEXT NOT NULL DEFAULT 'web',
+ deploy_script TEXT NOT NULL DEFAULT '',
+ created_at DATETIME NOT NULL,
+ updated_at DATETIME NOT NULL
+ )`,
}
for _, m := range migrations {
if _, err := s.db.Exec(m); err != nil {
@@ -1056,3 +1066,64 @@ func timeOrNull(t *time.Time) interface{} {
}
return t.UTC()
}
+
+// CreateProject inserts a new project.
+func (s *DB) CreateProject(p *task.Project) error {
+ now := time.Now().UTC()
+ _, err := s.db.Exec(
+ `INSERT INTO projects (id, name, remote_url, local_path, type, deploy_script, created_at, updated_at) VALUES (?, ?, ?, ?, ?, ?, ?, ?)`,
+ p.ID, p.Name, p.RemoteURL, p.LocalPath, p.Type, p.DeployScript, now, now,
+ )
+ return err
+}
+
+// GetProject retrieves a project by ID.
+func (s *DB) GetProject(id string) (*task.Project, error) {
+ row := s.db.QueryRow(`SELECT id, name, remote_url, local_path, type, deploy_script FROM projects WHERE id = ?`, id)
+ p := &task.Project{}
+ if err := row.Scan(&p.ID, &p.Name, &p.RemoteURL, &p.LocalPath, &p.Type, &p.DeployScript); err != nil {
+ return nil, err
+ }
+ return p, nil
+}
+
+// ListProjects returns all projects.
+func (s *DB) ListProjects() ([]*task.Project, error) {
+ rows, err := s.db.Query(`SELECT id, name, remote_url, local_path, type, deploy_script FROM projects ORDER BY name`)
+ if err != nil {
+ return nil, err
+ }
+ defer rows.Close()
+ var projects []*task.Project
+ for rows.Next() {
+ p := &task.Project{}
+ if err := rows.Scan(&p.ID, &p.Name, &p.RemoteURL, &p.LocalPath, &p.Type, &p.DeployScript); err != nil {
+ return nil, err
+ }
+ projects = append(projects, p)
+ }
+ return projects, rows.Err()
+}
+
+// UpdateProject updates an existing project.
+func (s *DB) UpdateProject(p *task.Project) error {
+ now := time.Now().UTC()
+ _, err := s.db.Exec(
+ `UPDATE projects SET name = ?, remote_url = ?, local_path = ?, type = ?, deploy_script = ?, updated_at = ? WHERE id = ?`,
+ p.Name, p.RemoteURL, p.LocalPath, p.Type, p.DeployScript, now, p.ID,
+ )
+ return err
+}
+
+// UpsertProject inserts or updates a project by ID (used for seeding).
+func (s *DB) UpsertProject(p *task.Project) error {
+ now := time.Now().UTC()
+ _, err := s.db.Exec(
+ `INSERT INTO projects (id, name, remote_url, local_path, type, deploy_script, created_at, updated_at)
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?)
+ ON CONFLICT(id) DO UPDATE SET name=excluded.name, remote_url=excluded.remote_url,
+ local_path=excluded.local_path, type=excluded.type, deploy_script=excluded.deploy_script, updated_at=excluded.updated_at`,
+ p.ID, p.Name, p.RemoteURL, p.LocalPath, p.Type, p.DeployScript, now, now,
+ )
+ return err
+}