Initial import with modified Dockerfile for env-based config generation
This commit is contained in:
@@ -0,0 +1,138 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"flag"
|
||||
"net/http"
|
||||
"os"
|
||||
"os/signal"
|
||||
"syscall"
|
||||
"time"
|
||||
|
||||
"github.com/rs/zerolog"
|
||||
|
||||
"github.com/vincentc-afk/gitea-notification-hub/internal/config"
|
||||
"github.com/vincentc-afk/gitea-notification-hub/internal/event"
|
||||
"github.com/vincentc-afk/gitea-notification-hub/internal/identity"
|
||||
"github.com/vincentc-afk/gitea-notification-hub/internal/identity/cache"
|
||||
"github.com/vincentc-afk/gitea-notification-hub/internal/identity/gitea"
|
||||
slacknotifier "github.com/vincentc-afk/gitea-notification-hub/internal/notifier/slack"
|
||||
"github.com/vincentc-afk/gitea-notification-hub/internal/server"
|
||||
"github.com/vincentc-afk/gitea-notification-hub/internal/storage/sqlite"
|
||||
"github.com/vincentc-afk/gitea-notification-hub/internal/webhook"
|
||||
)
|
||||
|
||||
func main() {
|
||||
// Parse flags
|
||||
configPath := flag.String("config", "config/config.yaml", "path to config file")
|
||||
debug := flag.Bool("debug", false, "enable debug logging")
|
||||
flag.Parse()
|
||||
|
||||
// Setup logger
|
||||
logger := setupLogger(*debug)
|
||||
|
||||
// Load configuration
|
||||
cfg, err := config.Load(*configPath)
|
||||
if err != nil {
|
||||
logger.Fatal().Err(err).Msg("failed to load configuration")
|
||||
}
|
||||
logger.Info().Str("path", *configPath).Msg("configuration loaded")
|
||||
|
||||
ctx := context.Background()
|
||||
|
||||
// Initialize storage
|
||||
repo, err := sqlite.New(cfg.Database.DSN)
|
||||
if err != nil {
|
||||
logger.Fatal().Err(err).Msg("failed to initialize database")
|
||||
}
|
||||
defer repo.Close()
|
||||
|
||||
// Run migrations
|
||||
if err := repo.Migrate(ctx); err != nil {
|
||||
logger.Fatal().Err(err).Msg("failed to run migrations")
|
||||
}
|
||||
logger.Info().Msg("database initialized")
|
||||
|
||||
// Initialize Gitea API provider for email lookup
|
||||
var emailLookup identity.EmailLookup
|
||||
if cfg.Identity.Gitea.URL != "" {
|
||||
giteaProvider := gitea.New(&cfg.Identity.Gitea, logger)
|
||||
emailLookup = giteaProvider
|
||||
logger.Info().Str("url", cfg.Identity.Gitea.URL).Msg("Gitea identity provider initialized")
|
||||
} else {
|
||||
logger.Warn().Msg("Gitea URL not configured, email lookup disabled")
|
||||
}
|
||||
|
||||
// Initialize Slack notifier
|
||||
slackClient := slacknotifier.New(&cfg.Notification.Slack, logger)
|
||||
logger.Info().Msg("Slack notifier initialized")
|
||||
|
||||
// Initialize cached identity resolver
|
||||
resolver := cache.NewCachedResolver(repo, emailLookup, slackClient, logger)
|
||||
logger.Info().Msg("identity resolver initialized")
|
||||
|
||||
// Create processor adapter that implements webhook.EventHandler
|
||||
processor := event.NewProcessor(cfg, &resolverAdapter{resolver}, slackClient, logger)
|
||||
logger.Info().Msg("event processor initialized")
|
||||
|
||||
// Create HTTP server
|
||||
srv := server.New(cfg, logger)
|
||||
|
||||
// Register webhook handler
|
||||
webhookHandler := webhook.NewHandler(cfg.Server.WebhookSecret, processor, logger)
|
||||
srv.Router().Post("/webhook", webhookHandler.ServeHTTP)
|
||||
logger.Info().Msg("webhook handler registered at POST /webhook")
|
||||
|
||||
// Graceful shutdown
|
||||
go func() {
|
||||
sigCh := make(chan os.Signal, 1)
|
||||
signal.Notify(sigCh, syscall.SIGINT, syscall.SIGTERM)
|
||||
<-sigCh
|
||||
|
||||
logger.Info().Msg("received shutdown signal")
|
||||
|
||||
shutdownCtx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
|
||||
defer cancel()
|
||||
|
||||
if err := srv.Shutdown(shutdownCtx); err != nil {
|
||||
logger.Error().Err(err).Msg("shutdown error")
|
||||
}
|
||||
}()
|
||||
|
||||
// Start server
|
||||
logger.Info().Int("port", cfg.Server.Port).Msg("starting server")
|
||||
if err := srv.Start(); err != nil && err != http.ErrServerClosed {
|
||||
logger.Fatal().Err(err).Msg("server error")
|
||||
}
|
||||
}
|
||||
|
||||
func setupLogger(debug bool) zerolog.Logger {
|
||||
zerolog.TimeFieldFormat = time.RFC3339
|
||||
|
||||
level := zerolog.InfoLevel
|
||||
if debug {
|
||||
level = zerolog.DebugLevel
|
||||
}
|
||||
|
||||
return zerolog.New(zerolog.ConsoleWriter{
|
||||
Out: os.Stdout,
|
||||
TimeFormat: "15:04:05",
|
||||
}).Level(level).With().Timestamp().Caller().Logger()
|
||||
}
|
||||
|
||||
// resolverAdapter adapts cache.CachedResolver to event.IdentityResolver
|
||||
type resolverAdapter struct {
|
||||
resolver *cache.CachedResolver
|
||||
}
|
||||
|
||||
func (a *resolverAdapter) Resolve(ctx context.Context, user event.User) (*event.ResolvedIdentity, error) {
|
||||
identity, err := a.resolver.Resolve(ctx, user)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &event.ResolvedIdentity{
|
||||
Email: identity.Email,
|
||||
SlackID: identity.SlackID,
|
||||
SlackName: identity.SlackName,
|
||||
}, nil
|
||||
}
|
||||
Reference in New Issue
Block a user