Files
kandev/apps/backend/internal/task/repository/sqlite/environment.go
T
2026-02-19 22:18:01 +00:00

138 lines
4.9 KiB
Go

package sqlite
import (
"context"
"database/sql"
"encoding/json"
"fmt"
"time"
"github.com/google/uuid"
"github.com/kandev/kandev/internal/db/dialect"
"github.com/kandev/kandev/internal/task/models"
)
// CreateEnvironment creates a new environment
func (r *Repository) CreateEnvironment(ctx context.Context, environment *models.Environment) error {
if environment.ID == "" {
environment.ID = uuid.New().String()
}
now := time.Now().UTC()
environment.CreatedAt = now
environment.UpdatedAt = now
buildConfigJSON, err := json.Marshal(environment.BuildConfig)
if err != nil {
return fmt.Errorf("failed to serialize environment build config: %w", err)
}
_, err = r.db.ExecContext(ctx, r.db.Rebind(`
INSERT INTO environments (id, name, kind, is_system, worktree_root, image_tag, dockerfile, build_config, created_at, updated_at, deleted_at)
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
`), environment.ID, environment.Name, environment.Kind, dialect.BoolToInt(environment.IsSystem), environment.WorktreeRoot, environment.ImageTag, environment.Dockerfile, string(buildConfigJSON), environment.CreatedAt, environment.UpdatedAt, environment.DeletedAt)
return err
}
// GetEnvironment retrieves an environment by ID
func (r *Repository) GetEnvironment(ctx context.Context, id string) (*models.Environment, error) {
environment := &models.Environment{}
var buildConfigJSON string
var isSystem int
err := r.ro.QueryRowContext(ctx, r.ro.Rebind(`
SELECT id, name, kind, is_system, worktree_root, image_tag, dockerfile, build_config, created_at, updated_at, deleted_at
FROM environments WHERE id = ? AND deleted_at IS NULL
`), id).Scan(
&environment.ID, &environment.Name, &environment.Kind, &isSystem, &environment.WorktreeRoot,
&environment.ImageTag, &environment.Dockerfile, &buildConfigJSON,
&environment.CreatedAt, &environment.UpdatedAt, &environment.DeletedAt,
)
if err == sql.ErrNoRows {
return nil, fmt.Errorf("environment not found: %s", id)
}
if err != nil {
return nil, err
}
environment.IsSystem = isSystem == 1
if buildConfigJSON != "" && buildConfigJSON != "{}" {
if err := json.Unmarshal([]byte(buildConfigJSON), &environment.BuildConfig); err != nil {
return nil, fmt.Errorf("failed to deserialize environment build config: %w", err)
}
}
return environment, nil
}
// UpdateEnvironment updates an existing environment
func (r *Repository) UpdateEnvironment(ctx context.Context, environment *models.Environment) error {
environment.UpdatedAt = time.Now().UTC()
buildConfigJSON, err := json.Marshal(environment.BuildConfig)
if err != nil {
return fmt.Errorf("failed to serialize environment build config: %w", err)
}
result, err := r.db.ExecContext(ctx, r.db.Rebind(`
UPDATE environments SET name = ?, kind = ?, is_system = ?, worktree_root = ?, image_tag = ?, dockerfile = ?, build_config = ?, updated_at = ?
WHERE id = ? AND deleted_at IS NULL
`), environment.Name, environment.Kind, dialect.BoolToInt(environment.IsSystem), environment.WorktreeRoot, environment.ImageTag, environment.Dockerfile, string(buildConfigJSON), environment.UpdatedAt, environment.ID)
if err != nil {
return err
}
rows, _ := result.RowsAffected()
if rows == 0 {
return fmt.Errorf("environment not found: %s", environment.ID)
}
return nil
}
// DeleteEnvironment soft-deletes an environment by ID
func (r *Repository) DeleteEnvironment(ctx context.Context, id string) error {
now := time.Now().UTC()
result, err := r.db.ExecContext(ctx, r.db.Rebind(`
UPDATE environments SET deleted_at = ?, updated_at = ? WHERE id = ? AND deleted_at IS NULL
`), now, now, id)
if err != nil {
return err
}
rows, _ := result.RowsAffected()
if rows == 0 {
return fmt.Errorf("environment not found: %s", id)
}
return nil
}
// ListEnvironments returns all non-deleted environments
func (r *Repository) ListEnvironments(ctx context.Context) ([]*models.Environment, error) {
rows, err := r.ro.QueryContext(ctx, `
SELECT id, name, kind, is_system, worktree_root, image_tag, dockerfile, build_config, created_at, updated_at, deleted_at
FROM environments WHERE deleted_at IS NULL ORDER BY created_at ASC
`)
if err != nil {
return nil, err
}
defer func() { _ = rows.Close() }()
var result []*models.Environment
for rows.Next() {
environment := &models.Environment{}
var buildConfigJSON string
var isSystem int
if err := rows.Scan(
&environment.ID, &environment.Name, &environment.Kind, &isSystem, &environment.WorktreeRoot,
&environment.ImageTag, &environment.Dockerfile, &buildConfigJSON,
&environment.CreatedAt, &environment.UpdatedAt, &environment.DeletedAt,
); err != nil {
return nil, err
}
environment.IsSystem = isSystem == 1
if buildConfigJSON != "" && buildConfigJSON != "{}" {
if err := json.Unmarshal([]byte(buildConfigJSON), &environment.BuildConfig); err != nil {
return nil, fmt.Errorf("failed to deserialize environment build config: %w", err)
}
}
result = append(result, environment)
}
return result, rows.Err()
}