All checks were successful
Release / Scraper / Test (push) Successful in 10s
Release / UI / Build (push) Successful in 26s
Release / v2 / Build ui-v2 (push) Successful in 17s
Release / Scraper / Docker (push) Successful in 47s
Release / UI / Docker (push) Successful in 56s
CI / Scraper / Lint (pull_request) Successful in 7s
CI / Scraper / Test (pull_request) Successful in 8s
CI / UI / Build (pull_request) Successful in 16s
CI / Scraper / Docker Push (pull_request) Has been skipped
CI / UI / Docker Push (pull_request) Has been skipped
Release / v2 / Docker / ui-v2 (push) Successful in 56s
Release / v2 / Test backend (push) Successful in 4m35s
iOS CI / Build (pull_request) Successful in 4m28s
Release / v2 / Docker / backend (push) Successful in 1m29s
Release / v2 / Docker / runner (push) Successful in 1m39s
iOS CI / Test (pull_request) Successful in 9m51s
- backend/: Go API server and runner binaries with PocketBase + MinIO storage - ui-v2/: SvelteKit frontend rewrite - docker-compose-new.yml: compose file for the v2 stack - .gitea/workflows/release-v2.yaml: CI/CD for backend, runner, and ui-v2 Docker Hub images - scripts/pb-init.sh: migrate from wget to curl, add superuser bootstrap for fresh installs - .env.example: document DOCKER_BUILDKIT=1 for Colima users
128 lines
4.1 KiB
Go
128 lines
4.1 KiB
Go
package config_test
|
|
|
|
import (
|
|
"os"
|
|
"testing"
|
|
"time"
|
|
|
|
"github.com/libnovel/backend/internal/config"
|
|
)
|
|
|
|
func TestLoad_Defaults(t *testing.T) {
|
|
// Unset all relevant vars so we test pure defaults.
|
|
unset := []string{
|
|
"LOG_LEVEL",
|
|
"POCKETBASE_URL", "POCKETBASE_ADMIN_EMAIL", "POCKETBASE_ADMIN_PASSWORD",
|
|
"MINIO_ENDPOINT", "MINIO_PUBLIC_ENDPOINT", "MINIO_ACCESS_KEY", "MINIO_SECRET_KEY",
|
|
"MINIO_USE_SSL", "MINIO_PUBLIC_USE_SSL",
|
|
"MINIO_BUCKET_CHAPTERS", "MINIO_BUCKET_AUDIO", "MINIO_BUCKET_AVATARS",
|
|
"KOKORO_URL", "KOKORO_VOICE",
|
|
"BACKEND_HTTP_ADDR",
|
|
"RUNNER_POLL_INTERVAL", "RUNNER_MAX_CONCURRENT_SCRAPE", "RUNNER_MAX_CONCURRENT_AUDIO",
|
|
"RUNNER_WORKER_ID", "RUNNER_WORKERS", "RUNNER_TIMEOUT", "SCRAPER_PROXY",
|
|
}
|
|
for _, k := range unset {
|
|
t.Setenv(k, "")
|
|
}
|
|
|
|
cfg := config.Load()
|
|
|
|
if cfg.LogLevel != "info" {
|
|
t.Errorf("LogLevel: want info, got %q", cfg.LogLevel)
|
|
}
|
|
if cfg.PocketBase.URL != "http://localhost:8090" {
|
|
t.Errorf("PocketBase.URL: want http://localhost:8090, got %q", cfg.PocketBase.URL)
|
|
}
|
|
if cfg.MinIO.BucketChapters != "libnovel-chapters" {
|
|
t.Errorf("MinIO.BucketChapters: want libnovel-chapters, got %q", cfg.MinIO.BucketChapters)
|
|
}
|
|
if cfg.MinIO.UseSSL != false {
|
|
t.Errorf("MinIO.UseSSL: want false, got %v", cfg.MinIO.UseSSL)
|
|
}
|
|
if cfg.MinIO.PublicUseSSL != true {
|
|
t.Errorf("MinIO.PublicUseSSL: want true, got %v", cfg.MinIO.PublicUseSSL)
|
|
}
|
|
if cfg.Kokoro.DefaultVoice != "af_bella" {
|
|
t.Errorf("Kokoro.DefaultVoice: want af_bella, got %q", cfg.Kokoro.DefaultVoice)
|
|
}
|
|
if cfg.HTTP.Addr != ":8080" {
|
|
t.Errorf("HTTP.Addr: want :8080, got %q", cfg.HTTP.Addr)
|
|
}
|
|
if cfg.Runner.PollInterval != 30*time.Second {
|
|
t.Errorf("Runner.PollInterval: want 30s, got %v", cfg.Runner.PollInterval)
|
|
}
|
|
if cfg.Runner.MaxConcurrentScrape != 1 {
|
|
t.Errorf("Runner.MaxConcurrentScrape: want 1, got %d", cfg.Runner.MaxConcurrentScrape)
|
|
}
|
|
if cfg.Runner.MaxConcurrentAudio != 1 {
|
|
t.Errorf("Runner.MaxConcurrentAudio: want 1, got %d", cfg.Runner.MaxConcurrentAudio)
|
|
}
|
|
}
|
|
|
|
func TestLoad_EnvOverride(t *testing.T) {
|
|
t.Setenv("LOG_LEVEL", "debug")
|
|
t.Setenv("POCKETBASE_URL", "https://pb.libnovel.cc")
|
|
t.Setenv("MINIO_USE_SSL", "true")
|
|
t.Setenv("MINIO_PUBLIC_USE_SSL", "false")
|
|
t.Setenv("RUNNER_POLL_INTERVAL", "1m")
|
|
t.Setenv("RUNNER_MAX_CONCURRENT_SCRAPE", "5")
|
|
t.Setenv("RUNNER_WORKER_ID", "homelab-01")
|
|
t.Setenv("BACKEND_HTTP_ADDR", ":9090")
|
|
t.Setenv("KOKORO_URL", "https://kokoro.libnovel.cc")
|
|
|
|
cfg := config.Load()
|
|
|
|
if cfg.LogLevel != "debug" {
|
|
t.Errorf("LogLevel: want debug, got %q", cfg.LogLevel)
|
|
}
|
|
if cfg.PocketBase.URL != "https://pb.libnovel.cc" {
|
|
t.Errorf("PocketBase.URL: want https://pb.libnovel.cc, got %q", cfg.PocketBase.URL)
|
|
}
|
|
if !cfg.MinIO.UseSSL {
|
|
t.Error("MinIO.UseSSL: want true")
|
|
}
|
|
if cfg.MinIO.PublicUseSSL {
|
|
t.Error("MinIO.PublicUseSSL: want false")
|
|
}
|
|
if cfg.Runner.PollInterval != time.Minute {
|
|
t.Errorf("Runner.PollInterval: want 1m, got %v", cfg.Runner.PollInterval)
|
|
}
|
|
if cfg.Runner.MaxConcurrentScrape != 5 {
|
|
t.Errorf("Runner.MaxConcurrentScrape: want 5, got %d", cfg.Runner.MaxConcurrentScrape)
|
|
}
|
|
if cfg.Runner.WorkerID != "homelab-01" {
|
|
t.Errorf("Runner.WorkerID: want homelab-01, got %q", cfg.Runner.WorkerID)
|
|
}
|
|
if cfg.HTTP.Addr != ":9090" {
|
|
t.Errorf("HTTP.Addr: want :9090, got %q", cfg.HTTP.Addr)
|
|
}
|
|
if cfg.Kokoro.URL != "https://kokoro.libnovel.cc" {
|
|
t.Errorf("Kokoro.URL: want https://kokoro.libnovel.cc, got %q", cfg.Kokoro.URL)
|
|
}
|
|
}
|
|
|
|
func TestLoad_InvalidInt_FallsToDefault(t *testing.T) {
|
|
t.Setenv("RUNNER_MAX_CONCURRENT_SCRAPE", "notanumber")
|
|
cfg := config.Load()
|
|
if cfg.Runner.MaxConcurrentScrape != 1 {
|
|
t.Errorf("want default 1, got %d", cfg.Runner.MaxConcurrentScrape)
|
|
}
|
|
}
|
|
|
|
func TestLoad_InvalidDuration_FallsToDefault(t *testing.T) {
|
|
t.Setenv("RUNNER_POLL_INTERVAL", "notaduration")
|
|
cfg := config.Load()
|
|
if cfg.Runner.PollInterval != 30*time.Second {
|
|
t.Errorf("want default 30s, got %v", cfg.Runner.PollInterval)
|
|
}
|
|
}
|
|
|
|
func TestLoad_WorkerID_FallsToHostname(t *testing.T) {
|
|
t.Setenv("RUNNER_WORKER_ID", "")
|
|
cfg := config.Load()
|
|
host, _ := os.Hostname()
|
|
if host != "" && cfg.Runner.WorkerID != host {
|
|
t.Errorf("want hostname %q, got %q", host, cfg.Runner.WorkerID)
|
|
}
|
|
}
|