- ControlPlane 라우터에 워커/에이전트 구독 채널을 추가한다 - ProtoSocket 기반 실시간 양방향 채널( dispatcher, envelope, server)을 구현한다 - Forgejo push 이벤트를 provider 어댑터로 처리하도록 연동한다 - PostgreSQL 스토리지 백엔드를 분리하여 postgres.go로 신설한다 - Git engine command에 diff/checkout/merge 연쇄 연산을 추가한다 - 런타임 모델에 agentSession, runtimeChannel 스키마를 추가한다 - 데이터베이스 마이그레이션에 agent_session, runtime_channel, lease 테이블을 추가한다 - agent-contract에 Forgejo branch events 계약 문서를 작성한다 - 로드맵 마일스톤과 아카이브 작업을 갱신한다
81 lines
2 KiB
Go
81 lines
2 KiB
Go
package main
|
|
|
|
import (
|
|
"context"
|
|
"log/slog"
|
|
"net/http"
|
|
"os"
|
|
"path/filepath"
|
|
|
|
"git.toki-labs.com/toki/gito/services/core/internal/config"
|
|
"git.toki-labs.com/toki/gito/services/core/internal/controlplane"
|
|
"git.toki-labs.com/toki/gito/services/core/internal/storage"
|
|
)
|
|
|
|
// migrationSQL loads the initial migration SQL from well-known paths relative
|
|
// to the executable or common working directories, so the server works
|
|
// regardless of the cwd it is launched from.
|
|
func migrationSQL() string {
|
|
exe, err := os.Executable()
|
|
if err != nil {
|
|
exe = ""
|
|
}
|
|
candidates := []string{
|
|
// set explicitly via env
|
|
os.Getenv("GITO_MIGRATION_PATH"),
|
|
// next to the binary (bin/gito-server → bin/../migrations/...)
|
|
filepath.Join(filepath.Dir(exe), "migrations", "00001_initial.sql"),
|
|
// launched from repo root
|
|
filepath.Join("services", "core", "migrations", "00001_initial.sql"),
|
|
// launched from services/core
|
|
filepath.Join("migrations", "00001_initial.sql"),
|
|
}
|
|
for _, p := range candidates {
|
|
if p == "" {
|
|
continue
|
|
}
|
|
data, err := os.ReadFile(p)
|
|
if err == nil {
|
|
return string(data)
|
|
}
|
|
}
|
|
return ""
|
|
}
|
|
|
|
func main() {
|
|
cfg := config.Load()
|
|
logger := slog.New(slog.NewJSONHandler(os.Stdout, nil))
|
|
|
|
var pgStore *storage.PgStore
|
|
if dsn := os.Getenv("DATABASE_URL"); dsn != "" {
|
|
var err error
|
|
pgStore, err = storage.NewPgStore(context.Background(), dsn, migrationSQL())
|
|
if err != nil {
|
|
logger.Error("failed to open postgres store", "error", err)
|
|
os.Exit(1)
|
|
}
|
|
logger.Info("postgres store connected")
|
|
}
|
|
|
|
var handler http.Handler
|
|
if pgStore != nil {
|
|
handler = controlplane.NewRouterWithStore(cfg, logger, pgStore)
|
|
} else {
|
|
handler = controlplane.NewRouter(cfg, logger)
|
|
}
|
|
|
|
if pgStore != nil {
|
|
defer pgStore.Close()
|
|
}
|
|
|
|
server := &http.Server{
|
|
Addr: cfg.HTTPAddr,
|
|
Handler: handler,
|
|
}
|
|
|
|
logger.Info("gito control plane listening", "addr", cfg.HTTPAddr)
|
|
if err := server.ListenAndServe(); err != nil && err != http.ErrServerClosed {
|
|
logger.Error("server stopped", "error", err)
|
|
os.Exit(1)
|
|
}
|
|
}
|