From f5a141f97bb4d74b6fb476cce086e00cdc7af05a Mon Sep 17 00:00:00 2001 From: Claude Code Date: Fri, 17 Oct 2025 09:26:02 +1100 Subject: [PATCH] Bump WHOOSH release to 0.1.7 --- Dockerfile | 14 +++--- cmd/whoosh/main.go | 20 ++++---- internal/config/config.go | 97 +++++++++++++++++++++------------------ scripts/deploy-swarm.sh | 4 +- 4 files changed, 73 insertions(+), 62 deletions(-) diff --git a/Dockerfile b/Dockerfile index dfbb5d9..2971b6b 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,4 +1,6 @@ -FROM golang:1.22-alpine AS builder +# syntax=docker/dockerfile:1.4 + +FROM golang:1.24-alpine AS builder # Install build dependencies RUN apk add --no-cache git ca-certificates tzdata @@ -6,15 +8,15 @@ RUN apk add --no-cache git ca-certificates tzdata # Set working directory WORKDIR /app +# Provide CHORUS module for local replace directive +COPY --from=chorus / /CHORUS/ + # Copy BACKBEAT dependency first COPY BACKBEAT-prototype ./BACKBEAT-prototype/ # Copy go mod files first for better caching COPY go.mod go.sum ./ -# Download and verify dependencies -RUN go mod download && go mod verify - # Copy source code COPY . . @@ -24,7 +26,7 @@ RUN cp /etc/group /tmp/group && \ echo "docker:x:998:65534" >> /tmp/group # Build with optimizations and version info -ARG VERSION=v0.1.0-mvp +ARG VERSION=v0.1.7 ARG COMMIT_HASH ARG BUILD_DATE RUN CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build \ @@ -76,4 +78,4 @@ LABEL maintainer="CHORUS Ecosystem" \ # Run the application ENTRYPOINT ["/app/whoosh"] -CMD [] \ No newline at end of file +CMD [] diff --git a/cmd/whoosh/main.go b/cmd/whoosh/main.go index 5b14238..c38a7bb 100644 --- a/cmd/whoosh/main.go +++ b/cmd/whoosh/main.go @@ -26,7 +26,7 @@ const ( var ( // Build-time variables (set via ldflags) - version = "0.1.5" + version = "0.1.7" commitHash = "unknown" buildDate = "unknown" ) @@ -67,7 +67,7 @@ func main() { // Load configuration var cfg config.Config - + // Debug: Print all environment variables starting with WHOOSH log.Debug().Msg("Environment variables:") for _, env := range os.Environ() { @@ -83,7 +83,7 @@ func main() { } } } - + if err := envconfig.Process("whoosh", &cfg); err != nil { log.Fatal().Err(err).Msg("Failed to load configuration") } @@ -122,7 +122,7 @@ func main() { log.Fatal().Err(err).Msg("Failed to initialize tracing") } defer tracingCleanup() - + if cfg.OpenTelemetry.Enabled { log.Info(). Str("jaeger_endpoint", cfg.OpenTelemetry.JaegerEndpoint). @@ -133,7 +133,7 @@ func main() { // Set version for server server.SetVersion(version) - + // Initialize server srv, err := server.NewServer(&cfg, db) if err != nil { @@ -148,7 +148,7 @@ func main() { log.Info(). Str("addr", cfg.Server.ListenAddr). Msg("🌐 Starting HTTP server") - + if err := srv.Start(ctx); err != nil { log.Error().Err(err).Msg("Server startup failed") cancel() @@ -168,7 +168,7 @@ func main() { // Graceful shutdown log.Info().Msg("🔄 Starting graceful shutdown...") - + shutdownCtx, shutdownCancel := context.WithTimeout(context.Background(), 30*time.Second) defer shutdownCancel() @@ -182,10 +182,10 @@ func main() { func runHealthCheck() error { // Simple health check - try to connect to health endpoint client := &http.Client{Timeout: 5 * time.Second} - + // Use localhost for health check healthURL := "http://localhost:8080/health" - + resp, err := client.Get(healthURL) if err != nil { return fmt.Errorf("health check request failed: %w", err) @@ -202,7 +202,7 @@ func runHealthCheck() error { func setupLogging() { // Configure zerolog for structured logging zerolog.TimeFieldFormat = zerolog.TimeFormatUnix - + // Set log level from environment level := os.Getenv("LOG_LEVEL") switch level { diff --git a/internal/config/config.go b/internal/config/config.go index 6e9b50a..bb31881 100644 --- a/internal/config/config.go +++ b/internal/config/config.go @@ -9,16 +9,17 @@ import ( ) type Config struct { - Server ServerConfig `envconfig:"server"` - Database DatabaseConfig `envconfig:"database"` - GITEA GITEAConfig `envconfig:"gitea"` - Auth AuthConfig `envconfig:"auth"` - Logging LoggingConfig `envconfig:"logging"` - BACKBEAT BackbeatConfig `envconfig:"backbeat"` - Docker DockerConfig `envconfig:"docker"` - N8N N8NConfig `envconfig:"n8n"` + Server ServerConfig `envconfig:"server"` + Database DatabaseConfig `envconfig:"database"` + GITEA GITEAConfig `envconfig:"gitea"` + Auth AuthConfig `envconfig:"auth"` + Logging LoggingConfig `envconfig:"logging"` + BACKBEAT BackbeatConfig `envconfig:"backbeat"` + Docker DockerConfig `envconfig:"docker"` + N8N N8NConfig `envconfig:"n8n"` OpenTelemetry OpenTelemetryConfig `envconfig:"opentelemetry"` - Composer ComposerConfig `envconfig:"composer"` + Composer ComposerConfig `envconfig:"composer"` + TaskAnnouncer TaskAnnouncerConfig `envconfig:"task_announcer"` } type ServerConfig struct { @@ -44,7 +45,6 @@ type DatabaseConfig struct { MaxIdleConns int `envconfig:"DB_MAX_IDLE_CONNS" default:"5"` } - type GITEAConfig struct { BaseURL string `envconfig:"BASE_URL" required:"true"` Token string `envconfig:"TOKEN"` @@ -52,13 +52,13 @@ type GITEAConfig struct { WebhookPath string `envconfig:"WEBHOOK_PATH" default:"/webhooks/gitea"` WebhookToken string `envconfig:"WEBHOOK_TOKEN"` WebhookTokenFile string `envconfig:"WEBHOOK_TOKEN_FILE"` - + // Fetch hardening options - EagerFilter bool `envconfig:"EAGER_FILTER" default:"true"` // Pre-filter by labels at API level - FullRescan bool `envconfig:"FULL_RESCAN" default:"false"` // Ignore since parameter for full rescan - DebugURLs bool `envconfig:"DEBUG_URLS" default:"false"` // Log exact URLs being used - MaxRetries int `envconfig:"MAX_RETRIES" default:"3"` // Maximum retry attempts - RetryDelay time.Duration `envconfig:"RETRY_DELAY" default:"2s"` // Delay between retries + EagerFilter bool `envconfig:"EAGER_FILTER" default:"true"` // Pre-filter by labels at API level + FullRescan bool `envconfig:"FULL_RESCAN" default:"false"` // Ignore since parameter for full rescan + DebugURLs bool `envconfig:"DEBUG_URLS" default:"false"` // Log exact URLs being used + MaxRetries int `envconfig:"MAX_RETRIES" default:"3"` // Maximum retry attempts + RetryDelay time.Duration `envconfig:"RETRY_DELAY" default:"2s"` // Delay between retries } type AuthConfig struct { @@ -75,10 +75,10 @@ type LoggingConfig struct { } type BackbeatConfig struct { - Enabled bool `envconfig:"ENABLED" default:"true"` - ClusterID string `envconfig:"CLUSTER_ID" default:"chorus-production"` - AgentID string `envconfig:"AGENT_ID" default:"whoosh"` - NATSUrl string `envconfig:"NATS_URL" default:"nats://backbeat-nats:4222"` + Enabled bool `envconfig:"ENABLED" default:"true"` + ClusterID string `envconfig:"CLUSTER_ID" default:"chorus-production"` + AgentID string `envconfig:"AGENT_ID" default:"whoosh"` + NATSUrl string `envconfig:"NATS_URL" default:"nats://backbeat-nats:4222"` } type DockerConfig struct { @@ -91,50 +91,60 @@ type N8NConfig struct { } type OpenTelemetryConfig struct { - Enabled bool `envconfig:"ENABLED" default:"true"` - ServiceName string `envconfig:"SERVICE_NAME" default:"whoosh"` - ServiceVersion string `envconfig:"SERVICE_VERSION" default:"1.0.0"` - Environment string `envconfig:"ENVIRONMENT" default:"production"` - JaegerEndpoint string `envconfig:"JAEGER_ENDPOINT" default:"http://localhost:14268/api/traces"` - SampleRate float64 `envconfig:"SAMPLE_RATE" default:"1.0"` + Enabled bool `envconfig:"ENABLED" default:"true"` + ServiceName string `envconfig:"SERVICE_NAME" default:"whoosh"` + ServiceVersion string `envconfig:"SERVICE_VERSION" default:"0.1.7"` + Environment string `envconfig:"ENVIRONMENT" default:"production"` + JaegerEndpoint string `envconfig:"JAEGER_ENDPOINT" default:"http://localhost:14268/api/traces"` + SampleRate float64 `envconfig:"SAMPLE_RATE" default:"1.0"` } type ComposerConfig struct { // Feature flags for experimental features - EnableLLMClassification bool `envconfig:"ENABLE_LLM_CLASSIFICATION" default:"false"` - EnableLLMSkillAnalysis bool `envconfig:"ENABLE_LLM_SKILL_ANALYSIS" default:"false"` - EnableLLMTeamMatching bool `envconfig:"ENABLE_LLM_TEAM_MATCHING" default:"false"` - + EnableLLMClassification bool `envconfig:"ENABLE_LLM_CLASSIFICATION" default:"false"` + EnableLLMSkillAnalysis bool `envconfig:"ENABLE_LLM_SKILL_ANALYSIS" default:"false"` + EnableLLMTeamMatching bool `envconfig:"ENABLE_LLM_TEAM_MATCHING" default:"false"` + // Analysis features - EnableComplexityAnalysis bool `envconfig:"ENABLE_COMPLEXITY_ANALYSIS" default:"true"` - EnableRiskAssessment bool `envconfig:"ENABLE_RISK_ASSESSMENT" default:"true"` - EnableAlternativeOptions bool `envconfig:"ENABLE_ALTERNATIVE_OPTIONS" default:"false"` - + EnableComplexityAnalysis bool `envconfig:"ENABLE_COMPLEXITY_ANALYSIS" default:"true"` + EnableRiskAssessment bool `envconfig:"ENABLE_RISK_ASSESSMENT" default:"true"` + EnableAlternativeOptions bool `envconfig:"ENABLE_ALTERNATIVE_OPTIONS" default:"false"` + // Debug and monitoring - EnableAnalysisLogging bool `envconfig:"ENABLE_ANALYSIS_LOGGING" default:"true"` - EnablePerformanceMetrics bool `envconfig:"ENABLE_PERFORMANCE_METRICS" default:"true"` - EnableFailsafeFallback bool `envconfig:"ENABLE_FAILSAFE_FALLBACK" default:"true"` - + EnableAnalysisLogging bool `envconfig:"ENABLE_ANALYSIS_LOGGING" default:"true"` + EnablePerformanceMetrics bool `envconfig:"ENABLE_PERFORMANCE_METRICS" default:"true"` + EnableFailsafeFallback bool `envconfig:"ENABLE_FAILSAFE_FALLBACK" default:"true"` + // LLM model configuration ClassificationModel string `envconfig:"CLASSIFICATION_MODEL" default:"llama3.1:8b"` SkillAnalysisModel string `envconfig:"SKILL_ANALYSIS_MODEL" default:"llama3.1:8b"` MatchingModel string `envconfig:"MATCHING_MODEL" default:"llama3.1:8b"` - + // Performance settings - AnalysisTimeoutSecs int `envconfig:"ANALYSIS_TIMEOUT_SECS" default:"60"` + AnalysisTimeoutSecs int `envconfig:"ANALYSIS_TIMEOUT_SECS" default:"60"` SkillMatchThreshold float64 `envconfig:"SKILL_MATCH_THRESHOLD" default:"0.6"` } +type TaskAnnouncerConfig struct { + Enabled bool `envconfig:"ENABLED" default:"false"` + Interval time.Duration `envconfig:"INTERVAL" default:"2m"` + ListenAddresses []string `envconfig:"LISTEN_ADDRESSES" default:"/ip4/0.0.0.0/tcp/0"` + BootstrapPeers []string `envconfig:"BOOTSTRAP_PEERS"` + MonitorLabels []string `envconfig:"MONITOR_LABELS" default:"bzzz-task"` + ReannounceAfter time.Duration `envconfig:"REANNOUNCE_AFTER" default:"12h"` + NodeID string `envconfig:"NODE_ID" default:"whoosh-task-announcer"` +} + func readSecretFile(filePath string) (string, error) { if filePath == "" { return "", nil } - + content, err := os.ReadFile(filePath) if err != nil { return "", fmt.Errorf("failed to read secret file %s: %w", filePath, err) } - + return strings.TrimSpace(string(content)), nil } @@ -148,7 +158,6 @@ func (c *Config) loadSecrets() error { c.Database.Password = password } - // Load GITEA token from file if specified if c.GITEA.TokenFile != "" { token, err := readSecretFile(c.GITEA.TokenFile) @@ -249,4 +258,4 @@ func (c *Config) Validate() error { } return nil -} \ No newline at end of file +} diff --git a/scripts/deploy-swarm.sh b/scripts/deploy-swarm.sh index ae38832..fa5ea1e 100755 --- a/scripts/deploy-swarm.sh +++ b/scripts/deploy-swarm.sh @@ -4,7 +4,7 @@ set -e # WHOOSH Docker Swarm Deployment Script # Following CHORUS deployment patterns with SHHH secret management -VERSION=${1:-v0.1.0-mvp} +VERSION=${1:-v0.1.7} REGISTRY_HOST=registry.home.deepblack.cloud echo "🎭 WHOOSH Swarm Deployment - Version: $VERSION" @@ -76,4 +76,4 @@ echo " - Health: https://whoosh.chorus.services/health" echo " - Ready: https://whoosh.chorus.services/health/ready" echo "📝 Monitor logs with:" -echo " docker service logs -f whoosh_whoosh" \ No newline at end of file +echo " docker service logs -f whoosh_whoosh"