Plugins: Add preinstall_sync config - allow plugins to be preinstalled synchronously (#105292)

* feat: preinstall_sync config - process and installation logic

* ref: add preinstall_sync list to preinstalled plugins of frontendsettings

* fix: conf blank line for sections

* ref: remove plugins async flag, and rename PreinstallPlugins

* docs: default installed plugin list
This commit is contained in:
Syerikjan Kh
2025-05-16 10:45:50 -04:00
committed by GitHub
parent 7e038b67a5
commit b38662e985
12 changed files with 200 additions and 84 deletions
@@ -42,7 +42,6 @@ type Service struct {
pluginStore pluginstore.Store
pluginRepo repo.Service
features featuremgmt.FeatureToggles
failOnErr bool
updateChecker pluginchecker.PluginUpdateChecker
}
@@ -65,14 +64,13 @@ func ProvideService(
cfg: cfg,
pluginInstaller: pluginInstaller,
pluginStore: pluginStore,
failOnErr: !cfg.PreinstallPluginsAsync, // Fail on error if preinstall is synchronous
pluginRepo: pluginRepo,
features: features,
updateChecker: updateChecker,
}
if !cfg.PreinstallPluginsAsync {
if len(cfg.PreinstallPluginsSync) > 0 {
// Block initialization process until plugins are installed
err := s.installPluginsWithTimeout()
err := s.installPluginsWithTimeout(cfg.PreinstallPluginsSync)
if err != nil {
return nil, err
}
@@ -82,11 +80,10 @@ func ProvideService(
// IsDisabled disables background installation of plugins.
func (s *Service) IsDisabled() bool {
return len(s.cfg.PreinstallPlugins) == 0 ||
!s.cfg.PreinstallPluginsAsync
return len(s.cfg.PreinstallPluginsAsync) == 0
}
func (s *Service) installPluginsWithTimeout() error {
func (s *Service) installPluginsWithTimeout(pluginsToInstall []setting.InstallPlugin) error {
// Installation process does not timeout by default nor reuses the context
// passed to the request so we need to handle the timeout here.
// We could make this timeout configurable in the future.
@@ -94,7 +91,7 @@ func (s *Service) installPluginsWithTimeout() error {
defer cancel()
done := make(chan struct{ err error })
go func() {
done <- struct{ err error }{err: s.installPlugins(ctx)}
done <- struct{ err error }{err: s.installPlugins(ctx, pluginsToInstall, true)}
}()
select {
case <-ctx.Done():
@@ -114,8 +111,8 @@ func (s *Service) shouldUpdate(ctx context.Context, pluginID, currentVersion str
return s.updateChecker.CanUpdate(pluginID, currentVersion, info.Version, true)
}
func (s *Service) installPlugins(ctx context.Context) error {
for _, installPlugin := range s.cfg.PreinstallPlugins {
func (s *Service) installPlugins(ctx context.Context, pluginsToInstall []setting.InstallPlugin, failOnErr bool) error {
for _, installPlugin := range pluginsToInstall {
// Check if the plugin is already installed
p, exists := s.pluginStore.Plugin(ctx, installPlugin.ID)
if exists {
@@ -148,7 +145,7 @@ func (s *Service) installPlugins(ctx context.Context) error {
s.log.Debug("Plugin already installed", "pluginId", installPlugin.ID, "version", installPlugin.Version)
continue
}
if s.failOnErr {
if failOnErr {
// Halt execution in the synchronous scenario
return fmt.Errorf("failed to install plugin %s@%s: %w", installPlugin.ID, installPlugin.Version, err)
}
@@ -165,7 +162,7 @@ func (s *Service) installPlugins(ctx context.Context) error {
}
func (s *Service) Run(ctx context.Context) error {
err := s.installPlugins(ctx)
err := s.installPlugins(ctx, s.cfg.PreinstallPluginsAsync, false)
if err != nil {
// Unexpected error, asynchronous installation should not return errors
s.log.Error("Failed to install plugins", "error", err)