From fab437fc8053d8b8f2da8a54abe4c03bd7ed59fb Mon Sep 17 00:00:00 2001 From: Stefan VanBuren Date: Tue, 11 Aug 2026 19:59:21 -0400 Subject: [PATCH] feat: add periodic auto-refresh for per-user custom apps repos System apps get a scheduled 12h background refresh (SYSTEM_APPS_AUTO_REFRESH), but per-user custom apps repos were only pulled when first saved or via the manual "Refresh" button on Settings -> Content. Add the same ticker pattern, gated behind a new CUSTOM_APPS_AUTO_REFRESH env var (default false), that iterates over every user with a configured repo and re-pulls it. Fixes #876 --- README.md | 1 + internal/config/config.go | 1 + internal/server/handlers_user.go | 41 ++++++++++++++++++++++++++++++++ internal/server/server.go | 1 + 4 files changed, 44 insertions(+) diff --git a/README.md b/README.md index 3fc1f7a4..09ac546c 100644 --- a/README.md +++ b/README.md @@ -106,6 +106,7 @@ The server can be configured via environment variables or `.env` file: * `SINGLE_USER_AUTO_LOGIN`: Skip login when only one user exists (default: `false`). * `SYSTEM_APPS_REPO`: Git repository URL for system apps (default: `https://github.com/tronbyt/apps.git`). * `SYSTEM_APPS_AUTO_REFRESH`: Automatically refresh the system apps repository (default: `false`). +* `CUSTOM_APPS_AUTO_REFRESH`: Automatically refresh every user's custom apps repository, every 12h (default: `false`). * `GITHUB_TOKEN`: GitHub token for private app repositories (optional). * `REDIS_URL`: Redis connection string for caching (optional). * `LOG_LEVEL`: Logging verbosity: `DEBUG`, `INFO`, `WARN`, `ERROR` (default: `INFO`). diff --git a/internal/config/config.go b/internal/config/config.go index f9213fa0..0313984a 100644 --- a/internal/config/config.go +++ b/internal/config/config.go @@ -19,6 +19,7 @@ type Settings struct { SingleUserAutoLogin bool `env:"SINGLE_USER_AUTO_LOGIN"` SystemAppsAutoRefresh bool `env:"SYSTEM_APPS_AUTO_REFRESH"` SystemAppsRepo string `env:"SYSTEM_APPS_REPO" envDefault:"https://github.com/tronbyt/apps.git"` + CustomAppsAutoRefresh bool `env:"CUSTOM_APPS_AUTO_REFRESH"` GitHubToken string `env:"GITHUB_TOKEN"` RedisURL string `env:"REDIS_URL"` Host string `env:"TRONBYT_HOST" envDefault:""` diff --git a/internal/server/handlers_user.go b/internal/server/handlers_user.go index 061bd448..5b264570 100644 --- a/internal/server/handlers_user.go +++ b/internal/server/handlers_user.go @@ -1,6 +1,7 @@ package server import ( + "context" "encoding/json" "fmt" "io" @@ -9,6 +10,7 @@ import ( "os" "path/filepath" "strings" + "time" "tronbyt-server/internal/data" "tronbyt-server/internal/gitutils" @@ -275,6 +277,45 @@ func (s *Server) handleRefreshUserRepo(w http.ResponseWriter, r *http.Request) { s.flashAndRedirect(w, r, "User repository refreshed successfully.", "/settings/content", http.StatusSeeOther) } +// autoRefreshCustomAppsRepos periodically re-pulls every user's custom apps +// repo, mirroring autoRefreshSystemRepo for the per-user equivalent. +func (s *Server) autoRefreshCustomAppsRepos() { + if !s.Config.CustomAppsAutoRefresh { + return + } + + slog.Info("Scheduled custom apps auto-refresh enabled (every 12h)") + + ticker := time.NewTicker(12 * time.Hour) + defer ticker.Stop() + for range ticker.C { + if !s.Config.CustomAppsAutoRefresh { + slog.Info("Custom apps auto-refresh disabled, stopping ticker") + return + } + slog.Info("Performing scheduled custom apps refresh") + s.refreshAllCustomAppsRepos() + } +} + +// refreshAllCustomAppsRepos re-pulls the custom apps repo for every user that +// has one configured. A failure for one user is logged and does not stop the +// others from refreshing. +func (s *Server) refreshAllCustomAppsRepos() { + users, err := gorm.G[data.User](s.DB).Where("app_repo_url <> ?", "").Find(context.Background()) + if err != nil { + slog.Error("Failed to list users with custom apps repos", "error", err) + return + } + + for _, user := range users { + appsPath := filepath.Join(s.DataDir, "users", user.Username, "repo") + if err := gitutils.EnsureRepo(appsPath, user.AppRepoURL, s.Config.GitHubToken, true); err != nil { + slog.Error("Scheduled refresh of custom apps repo failed", "user", user.Username, "error", err) + } + } +} + func (s *Server) handleExportUserConfig(w http.ResponseWriter, r *http.Request) { userContext := GetUser(r) diff --git a/internal/server/server.go b/internal/server/server.go index f432b235..6d8b0e1f 100644 --- a/internal/server/server.go +++ b/internal/server/server.go @@ -238,6 +238,7 @@ func NewServer(db *gorm.DB, cfg *config.Settings) *Server { go s.checkForUpdates(context.Background()) go s.autoRefreshSystemRepo() + go s.autoRefreshCustomAppsRepos() s.routes() return s