fix: support postgres initial agent setup (#1410)

This commit is contained in:
Carlos Florêncio
2026-06-17 09:54:44 +01:00
committed by GitHub
parent 9ea30d5e3e
commit bebb46a189
5 changed files with 102 additions and 2 deletions
@@ -1,6 +1,7 @@
package main
import (
"context"
"fmt"
"net/url"
"os"
@@ -12,7 +13,9 @@ import (
_ "github.com/jackc/pgx/v5/stdlib"
"github.com/jmoiron/sqlx"
"github.com/kandev/kandev/internal/agent/registry"
"github.com/kandev/kandev/internal/common/config"
"github.com/kandev/kandev/internal/events/bus"
"github.com/kandev/kandev/internal/testutil"
)
@@ -62,6 +65,31 @@ func TestPostgresBootInitializesRepositories(t *testing.T) {
}
}
})
agentRegistry, registryCleanup, err := registry.Provide(log)
if err != nil {
t.Fatalf("provide agent registry: %v", err)
}
t.Cleanup(func() {
if registryCleanup != nil {
_ = registryCleanup()
}
})
services, agentSettingsController, err := provideServices(
cfg,
log,
repos,
pool,
bus.NewMemoryEventBus(log),
agentRegistry,
"test-postgres-boot",
)
if err != nil {
t.Fatalf("provide services with postgres: %v", err)
}
if err := runInitialAgentSetup(context.Background(), services.User, agentSettingsController, log); err != nil {
t.Fatalf("run initial agent setup with postgres: %v", err)
}
}
type postgresConnInfo struct {
@@ -1,6 +1,7 @@
package store
import (
"context"
"testing"
"github.com/kandev/kandev/internal/testutil"
@@ -13,3 +14,45 @@ func TestPostgresFreshSchemaInitializes(t *testing.T) {
t.Fatalf("init fresh postgres schema: %v", err)
}
}
func TestPostgresHasDeletedAgentProfilesHandlesMissingAgent(t *testing.T) {
db := testutil.OpenIsolatedPostgres(t, testutil.PostgresDSNFromEnv(t))
repo, err := newSQLiteRepositoryWithDB(db, db, nil)
if err != nil {
t.Fatalf("init fresh postgres schema: %v", err)
}
hasDeleted, err := repo.HasDeletedAgentProfiles(context.Background(), "missing-agent")
if err != nil {
t.Fatalf("HasDeletedAgentProfiles: %v", err)
}
if hasDeleted {
t.Fatal("HasDeletedAgentProfiles = true, want false")
}
}
func TestPostgresHasDeletedAgentProfilesReturnsTrueForDeletedProfile(t *testing.T) {
db := testutil.OpenIsolatedPostgres(t, testutil.PostgresDSNFromEnv(t))
repo, err := newSQLiteRepositoryWithDB(db, db, nil)
if err != nil {
t.Fatalf("init fresh postgres schema: %v", err)
}
ctx := context.Background()
profileID := seedAgentProfile(t, repo, "postgres-deleted", "postgres-agent")
profile, err := repo.GetAgentProfileIncludingDeleted(ctx, profileID)
if err != nil {
t.Fatalf("lookup profile: %v", err)
}
if err := repo.DeleteAgentProfile(ctx, profileID); err != nil {
t.Fatalf("delete profile: %v", err)
}
hasDeleted, err := repo.HasDeletedAgentProfiles(ctx, profile.AgentID)
if err != nil {
t.Fatalf("HasDeletedAgentProfiles: %v", err)
}
if !hasDeleted {
t.Fatal("HasDeletedAgentProfiles = false, want true")
}
}
@@ -860,12 +860,15 @@ func (r *sqliteRepository) ListAgentProfiles(ctx context.Context, agentID string
func (r *sqliteRepository) HasDeletedAgentProfiles(ctx context.Context, agentID string) (bool, error) {
var exists int
err := r.ro.QueryRowContext(ctx,
r.ro.Rebind(`SELECT EXISTS(SELECT 1 FROM agent_profiles WHERE agent_id = ? AND deleted_at IS NOT NULL)`),
r.ro.Rebind(`SELECT 1 FROM agent_profiles WHERE agent_id = ? AND deleted_at IS NOT NULL LIMIT 1`),
agentID).Scan(&exists)
if errors.Is(err, sql.ErrNoRows) {
return false, nil
}
if err != nil {
return false, err
}
return exists == 1, nil
return true, nil
}
// applyLegacyBackfill returns the profile with CLIFlags populated from the
@@ -8,6 +8,7 @@ import (
"github.com/jmoiron/sqlx"
"github.com/kandev/kandev/internal/db"
"github.com/kandev/kandev/internal/db/dialect"
)
// Store persists install-wide Kandev settings that are not scoped to a user,
@@ -39,6 +40,10 @@ func (s *Store) initSchema() error {
}
func (s *Store) migrateLegacySystemSettings() error {
if dialect.IsPostgres(s.db.DriverName()) {
return nil
}
var exists int
if err := s.db.QueryRow(`
SELECT COUNT(*) FROM sqlite_master WHERE type = 'table' AND name = 'system_settings'
@@ -8,6 +8,7 @@ import (
_ "github.com/mattn/go-sqlite3"
"github.com/kandev/kandev/internal/db"
"github.com/kandev/kandev/internal/testutil"
)
func TestStoreSaveAndGet(t *testing.T) {
@@ -62,6 +63,26 @@ func TestStoreMigratesLegacySystemSettings(t *testing.T) {
}
}
func TestStoreInitializesOnPostgres(t *testing.T) {
conn := testutil.OpenIsolatedPostgres(t, testutil.PostgresDSNFromEnv(t))
store, err := NewStore(db.NewPool(conn, conn))
if err != nil {
t.Fatalf("new postgres store: %v", err)
}
ctx := context.Background()
if err := store.Save(ctx, "system_metrics", []byte(`{"interval_seconds":5}`)); err != nil {
t.Fatalf("save postgres setting: %v", err)
}
value, found, err := store.Get(ctx, "system_metrics")
if err != nil {
t.Fatalf("get postgres setting: %v", err)
}
if !found || string(value) != `{"interval_seconds":5}` {
t.Fatalf("postgres value = (%q, %v)", value, found)
}
}
func newTestStore(t *testing.T) *Store {
t.Helper()
conn := newSQLite(t)