- Introduced a new `.env.test.example` file for integration test configuration. - Added a `Makefile` to streamline test commands for unit and integration tests. - Implemented an integration testing harness with support for PostgreSQL, MinIO, and Redis using testcontainers. - Created a suite of integration tests covering health checks and user management functionalities. - Enhanced CI workflow to include integration tests with necessary environment variables.
86 lines
1.8 KiB
Go
86 lines
1.8 KiB
Go
package main
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
"log/slog"
|
|
"net/http"
|
|
"os"
|
|
"os/signal"
|
|
"syscall"
|
|
"time"
|
|
|
|
"github.com/ultisuite/ulti-backend/internal/config"
|
|
"github.com/ultisuite/ulti-backend/internal/dbmigrate"
|
|
"github.com/ultisuite/ulti-backend/internal/envexpand"
|
|
"github.com/ultisuite/ulti-backend/internal/server"
|
|
)
|
|
|
|
func main() {
|
|
ctx, cancel := context.WithCancel(context.Background())
|
|
defer cancel()
|
|
|
|
loadDotEnv()
|
|
|
|
cfg, err := config.Load()
|
|
if err != nil {
|
|
slog.Error("failed to load config", "error", err)
|
|
os.Exit(1)
|
|
}
|
|
|
|
if err := dbmigrate.Up(cfg.DatabaseURL); err != nil {
|
|
slog.Error("database migration failed", "error", err)
|
|
os.Exit(1)
|
|
}
|
|
|
|
app, err := server.New(ctx, cfg, server.Options{})
|
|
if err != nil {
|
|
slog.Error("failed to bootstrap server", "error", err)
|
|
os.Exit(1)
|
|
}
|
|
defer app.Close()
|
|
|
|
srv := &http.Server{
|
|
Addr: fmt.Sprintf(":%d", cfg.Port),
|
|
Handler: app.Router,
|
|
}
|
|
|
|
errCh := make(chan error, 1)
|
|
go func() {
|
|
slog.Info("server starting", "port", cfg.Port)
|
|
if err := srv.ListenAndServe(); err != nil && err != http.ErrServerClosed {
|
|
errCh <- err
|
|
}
|
|
}()
|
|
|
|
quit := make(chan os.Signal, 1)
|
|
signal.Notify(quit, syscall.SIGINT, syscall.SIGTERM)
|
|
|
|
select {
|
|
case <-quit:
|
|
case err := <-errCh:
|
|
slog.Error("server error", "error", err)
|
|
}
|
|
|
|
slog.Info("shutting down server")
|
|
cancel()
|
|
|
|
shutdownCtx, shutdownCancel := context.WithTimeout(context.Background(), 10*time.Second)
|
|
defer shutdownCancel()
|
|
|
|
if err := srv.Shutdown(shutdownCtx); err != nil {
|
|
slog.Error("server forced shutdown", "error", err)
|
|
os.Exit(1)
|
|
}
|
|
slog.Info("server stopped")
|
|
}
|
|
|
|
func loadDotEnv() {
|
|
for _, path := range []string{".env", "../.env"} {
|
|
if err := envexpand.ApplyFile(path); err == nil {
|
|
slog.Debug("loaded env file", "path", path)
|
|
return
|
|
}
|
|
}
|
|
}
|