feat: show new updates in dashboard (#690)

* feat: show new update banner

* feat(http): add request logger

* refactor: updates checker

* feat: make update check optional

* fix: empty releases

* add toggle switch for update checks

* feat: toggle updates check from settings

* feat: toggle updates check from settings

* feat: check on toggle enabled

---------

Co-authored-by: soup <soup@r4tio.dev>
This commit is contained in:
ze0s 2023-02-05 18:44:11 +01:00 committed by GitHub
parent 3fdd7cf5e4
commit 2917a7d42d
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
24 changed files with 687 additions and 121 deletions

View file

@ -2,6 +2,7 @@ package config
import (
"bytes"
"fmt"
"log"
"os"
"path"
@ -72,6 +73,10 @@ logLevel = "DEBUG"
#
#logMaxBackups = 3
# Check for updates
#
checkForUpdates = true
# Session secret
#
sessionSecret = "{{ .sessionSecret }}"
@ -148,6 +153,7 @@ func writeConfig(configPath string, configFile string) error {
}
type Config interface {
UpdateConfig() error
DynamicReload(log logger.Logger)
}
@ -179,6 +185,7 @@ func (c *AppConfig) defaults() {
BaseURL: "/",
SessionSecret: "secret-session-key",
CustomDefinitions: "",
CheckForUpdates: true,
DatabaseType: "sqlite",
PostgresHost: "",
PostgresPort: 0,
@ -240,6 +247,9 @@ func (c *AppConfig) DynamicReload(log logger.Logger) {
logPath := viper.GetString("logPath")
c.Config.LogPath = logPath
checkUpdates := viper.GetBool("checkForUpdates")
c.Config.CheckForUpdates = checkUpdates
log.Debug().Msg("config file reloaded!")
c.m.Unlock()
@ -248,3 +258,46 @@ func (c *AppConfig) DynamicReload(log logger.Logger) {
return
}
func (c *AppConfig) UpdateConfig() error {
file := path.Join(c.Config.ConfigPath, "config.toml")
f, err := os.ReadFile(file)
if err != nil {
return errors.Wrap(err, "could not read config file: %s", file)
}
lines := strings.Split(string(f), "\n")
lines = c.processLines(lines)
output := strings.Join(lines, "\n")
if err := os.WriteFile(file, []byte(output), 0644); err != nil {
return errors.Wrap(err, "could not write config file: %s", file)
}
return nil
}
func (c *AppConfig) processLines(lines []string) []string {
// keep track of not found values to append at bottom
var (
foundLineUpdate = false
)
for i, line := range lines {
// set checkForUpdates
if !foundLineUpdate && strings.Contains(line, "checkForUpdates =") {
lines[i] = fmt.Sprintf("checkForUpdates = %t", c.Config.CheckForUpdates)
foundLineUpdate = true
}
}
// append missing vars to bottom
if !foundLineUpdate {
lines = append(lines, "# Check for updates")
lines = append(lines, "#")
lines = append(lines, fmt.Sprintf("checkForUpdates = %t", c.Config.CheckForUpdates))
}
return lines
}

View file

@ -0,0 +1,55 @@
package config
import (
"reflect"
"sync"
"testing"
"github.com/autobrr/autobrr/internal/domain"
)
func TestAppConfig_processLines(t *testing.T) {
type fields struct {
Config *domain.Config
m sync.Mutex
}
type args struct {
lines []string
}
tests := []struct {
name string
fields fields
args args
want []string
}{
{
name: "append missing",
fields: fields{
Config: &domain.Config{CheckForUpdates: true},
m: sync.Mutex{},
},
args: args{[]string{}},
want: []string{"# Check for updates", "#", "checkForUpdates = true"},
},
{
name: "update existing",
fields: fields{
Config: &domain.Config{CheckForUpdates: true},
m: sync.Mutex{},
},
args: args{[]string{"# Check for updates", "#", "#checkForUpdates = false"}},
want: []string{"# Check for updates", "#", "checkForUpdates = true"},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
c := &AppConfig{
Config: tt.fields.Config,
m: tt.fields.m,
}
if got := c.processLines(tt.args.lines); !reflect.DeepEqual(got, tt.want) {
t.Errorf("processLines() = %v, want %v", got, tt.want)
}
})
}
}