Files
ForgeBucket/cmd/forgebucket/main.go
T
2026-05-12 20:32:30 +02:00

111 lines
2.7 KiB
Go

package main
import (
"context"
"fmt"
"log"
"net/http"
"os"
"os/signal"
"syscall"
"time"
"github.com/gorilla/sessions"
"github.com/joho/godotenv"
_ "github.com/lib/pq"
"github.com/forgeo/forgebucket/internal/api"
"github.com/forgeo/forgebucket/internal/config"
"github.com/forgeo/forgebucket/internal/db"
"github.com/forgeo/forgebucket/internal/domain/ci"
gitdomain "github.com/forgeo/forgebucket/internal/domain/git"
"github.com/forgeo/forgebucket/internal/domain/gitops"
"github.com/forgeo/forgebucket/internal/events"
"github.com/forgeo/forgebucket/internal/observability"
"github.com/forgeo/forgebucket/internal/models/migrations"
"github.com/forgeo/forgebucket/web"
)
func main() {
_ = godotenv.Load()
cfg, err := config.Load()
if err != nil {
log.Fatalf("config: %v", err)
}
engine, err := db.Open(cfg.DatabaseURL, cfg.Debug)
if err != nil {
log.Fatalf("database: %v", err)
}
defer engine.Close()
if err := migrations.Run(engine); err != nil {
log.Fatalf("migrations: %v", err)
}
gitdomain.SetRepoRoot(cfg.RepoRoot)
if err := os.MkdirAll(cfg.ArtifactRoot, 0755); err != nil {
log.Fatalf("artifact root: %v", err)
}
bus, err := events.New(cfg.NATSUrl)
if err != nil {
log.Fatalf("events: %v", err)
}
defer bus.Close()
store := sessions.NewCookieStore([]byte(cfg.SessionSecret))
store.Options = &sessions.Options{
Path: "/",
MaxAge: 86400 * 7,
HttpOnly: true,
Secure: !cfg.Debug,
SameSite: http.SameSiteLaxMode,
}
// Start CI orchestrator and runner manager in background goroutines.
ciCtx, ciCancel := context.WithCancel(context.Background())
defer ciCancel()
orchestrator := ci.NewOrchestrator(engine, bus)
go orchestrator.Start(ciCtx)
runnerMgr := ci.NewRunnerManager(engine, bus, cfg, 4)
go runnerMgr.Start(ciCtx)
gitopsCtrl := gitops.NewController(engine, bus, cfg)
go gitopsCtrl.Start(ciCtx)
go observability.StartNATSWatcher(ciCtx, bus)
handler := api.New(cfg, engine, store, bus, cfg.ArtifactRoot, web.FS())
srv := &http.Server{
Addr: fmt.Sprintf(":%s", cfg.Port),
Handler: handler,
ReadTimeout: 15 * time.Second,
WriteTimeout: 60 * time.Second,
IdleTimeout: 120 * time.Second,
}
go func() {
log.Printf("ForgeBucket listening on http://localhost:%s", cfg.Port)
if err := srv.ListenAndServe(); err != nil && err != http.ErrServerClosed {
log.Fatalf("server: %v", err)
}
}()
quit := make(chan os.Signal, 1)
signal.Notify(quit, syscall.SIGINT, syscall.SIGTERM)
<-quit
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
defer cancel()
if err := srv.Shutdown(ctx); err != nil {
log.Printf("shutdown: %v", err)
}
log.Println("ForgeBucket stopped")
}