Skip to content

Commit

Permalink
Mac/win: Update from unstable website. (#741)
Browse files Browse the repository at this point in the history
  • Loading branch information
davidnewhall authored May 29, 2024
2 parents 4a02cdf + 4544705 commit 876b38f
Show file tree
Hide file tree
Showing 10 changed files with 232 additions and 55 deletions.
9 changes: 6 additions & 3 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ jobs:
if: startsWith(github.ref, 'refs/tags/v') || github.ref == 'refs/heads/unstable' || github.ref == 'refs/heads/main'
outputs:
version: ${{ steps.release.outputs.version }}
revision: ${{ steps.release.outputs.revision }}
name: Make Release Assets
runs-on: ubuntu-latest
env:
Expand All @@ -69,7 +70,9 @@ jobs:
sudo gem install --no-document fpm
echo "${GPG_SIGNING_KEY}" | gpg --import -
make release
source settings.sh ; echo "version=${VERSION}-${ITERATION}" >> $GITHUB_OUTPUT
source settings.sh
echo "version=${VERSION}" >> $GITHUB_OUTPUT
echo "revision=${ITERATION}" >> $GITHUB_OUTPUT
- name: upload artifacts
uses: actions/upload-artifact@v4
with:
Expand Down Expand Up @@ -98,8 +101,8 @@ jobs:
[ -f "$file" ] || continue;
echo "Uploading: ${file}";
curl -sSH "X-API-KEY: ${{ secrets.UNSTABLE_UPLOAD_KEY }}" "https://unstable.golift.io/upload.php?folder=notifiarr" -F "file=@${file}";
versionfile="${{needs.release-test.outputs.version}};filename=${file}.txt;type=text/plain";
curl -sSH "X-API-KEY: ${{ secrets.UNSTABLE_UPLOAD_KEY }}" "https://unstable.golift.io/upload.php?folder=notifiarr" -F "file=${versionfile}";
echo '{"version":"${{needs.release-test.outputs.version}}","revision":${{needs.release-test.outputs.revision}},"size":'$(stat --printf="%s" ${file})'}' >> ${file}.txt
curl -sSH "X-API-KEY: ${{ secrets.UNSTABLE_UPLOAD_KEY }}" "https://unstable.golift.io/upload.php?folder=notifiarr" -F "file=@${file}.txt";
done
deploy-unstable-packagecloud:
Expand Down
34 changes: 34 additions & 0 deletions pkg/bindata/templates/config.html
Original file line number Diff line number Diff line change
Expand Up @@ -158,6 +158,40 @@ <h2 class="mb-3">General</h2>
</div>
</td>
</tr>
{{- if .ClientInfo.User.DevAllowed }}
<tr>
<td>
<div style="display:none;" class="dialogText">
Enabling the unstable updates channel will make the application check the unstable website for auto-updates instead of GitHub.
<b>Current Value</b>: <i>{{if .Config.UnstableCh}}Enabled{{else}}Disabled{{end}}</i>
</div>
<a onClick="dialog($(this), 'left')" class="help-icon far fa-question-circle"></a>
<span class="dialogTitle">Unstable Channel</span>
</td>
<td class="mobile-hide">
{{if .Config.UnstableCh}}Enabled{{else}}Disabled{{end}}
</td>
<td>
<div class="form-group" style="width:100%">
<div class="input-group" style="width:100%">
{{- if locked (printf "%s_UNSTABLE_CH" .Flags.EnvPrefix)}}
<div style="width:30px; max-width:30px;" class="input-group-addon input-sm">
<div style="display:none;" class="dialogText">
An environment variable exists for this value. Your new value will write to the config file, but the application will not use it.
</div>
<i onClick="dialog($(this), 'right')" class="text-danger help-icon fas fa-outdent"></i>
<span class="dialogTitle" style="display:none;">Env Variable: {{printf "%s_UNSTABLE_CH" .Flags.EnvPrefix}}</span>
</div>
{{- end}}
<select class="client-parameter form-control input-sm" data-group="config" data-label="UnstableCh" id="UnstableCh" name="UnstableCh" data-original="{{.Config.UnstableCh}}">
<option {{if .Config.UnstableCh}}selected {{end}}value="true">Enabled</option>
<option {{if not .Config.UnstableCh}}selected {{end}}value="false">Disabled</option>
</select>
</div>
</div>
</td>
</tr>
{{- end }}
{{- end }}
<tr>
<td>
Expand Down
51 changes: 35 additions & 16 deletions pkg/client/client_windows.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ import (
// This is the pop-up a user sees when they click update in the menu.
func (c *Client) upgradeWindows(ctx context.Context, update *update.Update) {
yes, _ := ui.Question(mnd.Title, "An Update is available! Upgrade Now?\n\n"+
"Your Version: "+update.Version+"\n"+
"Your Version: "+version.Version+"-"+version.Revision+"\n"+
"New Version: "+update.Current+"\n"+
"Date: "+update.RelDate.Format("Jan 2, 2006")+mnd.DurationAgo(update.RelDate), false)
if yes {
Expand Down Expand Up @@ -66,35 +66,54 @@ func (c *Client) AutoWatchUpdate(ctx context.Context) {
}
}

c.Print("Auto-updater enabled. Check interval:", durafmt.Parse(dur).String())
c.startAutoUpdater(ctx, dur)
}

go func() {
defer c.CapturePanic()
func (c *Client) startAutoUpdater(ctx context.Context, dur time.Duration) {
pfx := ""
if c.Config.UnstableCh {
pfx = "Unstable Channel "
}

time.Sleep(update.SleepTime)
// Check for update on startup.
if err := c.checkAndUpdate(ctx, "startup check"); err != nil {
c.Errorf("Startup-Update Failed: %v", err)
}
}()
c.Print(pfx+"Auto-updater started. Check interval:", durafmt.Parse(dur).String())

time.Sleep(update.SleepTime)
// Check for update on startup.
if err := c.checkAndUpdate(ctx, "startup check"); err != nil {
c.Errorf("Startup-Update Failed: %v", err)
}

ticker := time.NewTicker(dur)
for range ticker.C {
for range ticker.C { // the ticker never exits.
if err := c.checkAndUpdate(ctx, "automatic"); err != nil {
c.Errorf("Auto-Update Failed: %v", err)
}
}
}

func (c *Client) checkAndUpdate(ctx context.Context, how string) error {
c.Debugf("Checking GitHub for Update.")
var (
data *update.Update
err error
where = "GitHub"
)

if c.Config.UnstableCh {
c.Debugf("[cron requested] Checking Unstable website for Update.")

data, err = update.CheckUnstable(ctx, mnd.Title, version.Version)
where = "Unstable website"
} else {
c.Debugf("[cron requested] Checking GitHub for Update.")

data, err = update.CheckGitHub(ctx, mnd.UserRepo, version.Version)
}

u, err := update.Check(ctx, mnd.UserRepo, version.Version)
if err != nil {
return fmt.Errorf("checking GitHub for update: %w", err)
} else if !u.Outdate {
return fmt.Errorf("checking %s for update: %w", where, err)
} else if !data.Outdate {
return nil
} else if err = c.updateNow(ctx, u, how); err != nil {
} else if err = c.updateNow(ctx, data, how); err != nil {
return err
}

Expand Down
14 changes: 10 additions & 4 deletions pkg/client/tray.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,8 +41,8 @@ func (c *Client) startTray(ctx context.Context, cancel context.CancelFunc, clien
// systray.SetOnClick(c.showMenu) // buggy
systray.SetOnRClick(c.showMenu)
systray.SetOnDClick(func(_ systray.IMenu) { c.openGUI() })
c.makeMenus(ctx) // make the menu before starting the web server.
c.setupMenus(clientInfo) // code that runs on reload, too.
c.makeMenus(ctx, clientInfo) // make the menu before starting the web server.
c.setupMenus(clientInfo) // code that runs on reload, too.

// This starts the web server, and waits for reload/exit signals.
if err := c.Exit(ctx, cancel); err != nil {
Expand Down Expand Up @@ -116,7 +116,7 @@ func (c *Client) setupMenus(clientInfo *clientinfo.ClientInfo) {
}
}

func (c *Client) makeMenus(ctx context.Context) {
func (c *Client) makeMenus(ctx context.Context, clientInfo *clientinfo.ClientInfo) {
menu["stat"] = systray.AddMenuItem("Running", "web server state unknown")
menu["stat"].Click(func() { c.toggleServer(ctx) })

Expand All @@ -127,7 +127,13 @@ func (c *Client) makeMenus(ctx context.Context) {
c.debugMenu()

menu["update"] = systray.AddMenuItem("Update", "check GitHub for updated version")
menu["update"].Click(func() { go c.checkForUpdate(ctx) })
menu["update"].Click(func() { go c.checkForUpdate(ctx, false) })

if mnd.IsUnstable || (clientInfo != nil && clientInfo.User.DevAllowed) {
menu["unstable"] = systray.AddMenuItem("Unstable", "check Unstable website for updated version")
menu["unstable"].Click(func() { go c.checkForUpdate(ctx, true) })
}

menu["gui"] = systray.AddMenuItem("Open WebUI", "open the web page for this Notifiarr client")
menu["gui"].Click(c.openGUI)
menu["sub"] = systray.AddMenuItem("Subscribe", "subscribe for premium features")
Expand Down
49 changes: 35 additions & 14 deletions pkg/client/tray_commands.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,32 +43,53 @@ func (c *Client) rotateLogs() {

for _, err := range c.Logger.Rotate() {
if err != nil {
ui.Notify("Error rotateing log files: %v", err) //nolint:errcheck
ui.Notify("Error rotating log files: %v", err) //nolint:errcheck
c.Errorf("Rotating Log Files: %v", err)
}
}
}

func (c *Client) checkForUpdate(ctx context.Context) {
c.Print("[user requested] GitHub Update Check")
func (c *Client) checkForUpdate(ctx context.Context, unstable bool) {
var (
data *update.Update
err error
where = "GitHub"
)

switch update, err := update.Check(ctx, mnd.UserRepo, version.Version); {
if unstable {
c.Print("[user requested] Unstable Update Check")

data, err = update.CheckUnstable(ctx, mnd.Title, version.Revision)
where = "Unstable website"
} else {
c.Print("[user requested] GitHub Update Check")

data, err = update.CheckGitHub(ctx, mnd.UserRepo, version.Version)
}

switch {
case err != nil:
c.Errorf("Update Check: %v", err)
_, _ = ui.Error(TitleError, "Checking version on GitHub: "+err.Error())
case update.Outdate && runtime.GOOS == mnd.Windows:
c.upgradeWindows(ctx, update)
case update.Outdate:
c.downloadOther(update)
_, _ = ui.Error(TitleError, "Checking version on "+where+": "+err.Error())
case data.Outdate && runtime.GOOS == mnd.Windows:
c.upgradeWindows(ctx, data)
case data.Outdate:
c.downloadOther(data, unstable)
default:
_, _ = ui.Info(mnd.Title, "You're up to date! Version: "+update.Version+"\n"+
"Updated: "+update.RelDate.Format("Jan 2, 2006")+mnd.DurationAgo(update.RelDate))
_, _ = ui.Info(mnd.Title, "You're up to date! Version: "+data.Current+"\n"+
"Updated: "+data.RelDate.Format("Jan 2, 2006")+mnd.DurationAgo(data.RelDate))
}
}

func (c *Client) downloadOther(update *update.Update) {
yes, _ := ui.Question(mnd.Title, "An Update is available! Download?\n\n"+
"Your Version: "+update.Version+"\n"+
func (c *Client) downloadOther(update *update.Update, unstable bool) {
msg := "An Update is available! Download?\n\n"

if unstable {
msg = "An Unstable Update is available! Download?\n\n"
}

yes, _ := ui.Question(mnd.Title, msg+
"Your Version: "+version.Version+"-"+version.Revision+"\n"+
"New Version: "+update.Current+"\n"+
"Date: "+update.RelDate.Format("Jan 2, 2006")+mnd.DurationAgo(update.RelDate), false)
if yes {
Expand Down
1 change: 1 addition & 0 deletions pkg/configfile/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ type Config struct {
SSLKeyFile string `json:"sslKeyFile" toml:"ssl_key_file" xml:"ssl_key_file" yaml:"sslKeyFile"`
Upstreams []string `json:"upstreams" toml:"upstreams" xml:"upstreams" yaml:"upstreams"`
AutoUpdate string `json:"autoUpdate" toml:"auto_update" xml:"auto_update" yaml:"autoUpdate"`
UnstableCh bool `json:"unstableCh" toml:"unstable_ch" xml:"unstable_ch" yaml:"unstableCh"`
Timeout cnfg.Duration `json:"timeout" toml:"timeout" xml:"timeout" yaml:"timeout"`
Retries int `json:"retries" toml:"retries" xml:"retries" yaml:"retries"`
Snapshot *snapshot.Config `json:"snapshot" toml:"snapshot" xml:"snapshot" yaml:"snapshot"`
Expand Down
17 changes: 11 additions & 6 deletions pkg/configfile/template.go
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,11 @@ bind_addr = '''{{.BindAddr}}'''
## You may also set it to a Go duration like "12h" or "72h".
## THIS ONLY WORKS ON WINDOWS
{{if .AutoUpdate}}auto_update = "{{.AutoUpdate}}"{{else}}auto_update = "off"{{end}}
{{- if .UnstableCh}}
## Setting this to true uses the unstable website instead of GitHub for auto updates.
unstable_ch = true
{{- end}}
{{- end}}
## Quiet makes the app not log anything to output.
Expand Down Expand Up @@ -444,10 +449,10 @@ retries = {{.Retries}}
[[snapshot.mysql]]
name = "{{.Name}}"
host = "{{.Host}}"
user = "{{.User}}"
pass = '''{{.Pass}}'''
user = "{{.User}}"
pass = '''{{.Pass}}'''
interval = "{{.Interval}}" # Service check duration (if name is not empty).
timeout = "{{.Timeout}}"
timeout = "{{.Timeout}}"
{{end}}
{{else}}
#[[snapshot.mysql]]
Expand All @@ -466,9 +471,9 @@ retries = {{.Retries}}
# SMI Path is found automatically if left blank. Set it to path to nvidia-smi (nvidia-smi.exe on Windows).
[snapshot.nvidia]
disabled = {{.Snapshot.Nvidia.Disabled}}
smi_path = '''{{.Snapshot.Nvidia.SMIPath}}'''
bus_ids = [{{range $s := .Snapshot.Nvidia.BusIDs}}"{{$s}}",{{end}}]
disabled = {{.Snapshot.Nvidia.Disabled}}
smi_path = '''{{.Snapshot.Nvidia.SMIPath}}'''
bus_ids = [{{range $s := .Snapshot.Nvidia.BusIDs}}"{{$s}}",{{end}}]
##################
# Service Checks #
Expand Down
6 changes: 5 additions & 1 deletion pkg/mnd/variables.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,18 @@ package mnd
import (
"fmt"
"os"
"strings"

"golift.io/version"
)

//nolint:gochecknoglobals
var (
// IsSynology tells us if this we're running on a Synology.
IsSynology bool
// IsDocker tells us if this is our Docker container.
IsDocker = os.Getpid() == 1
IsDocker = os.Getpid() == 1
IsUnstable = strings.HasPrefix(version.Branch, "unstable")
)

// ErrDisabledInstance is returned when a request for a disabled instance is performed.
Expand Down
24 changes: 13 additions & 11 deletions pkg/update/check.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,25 +27,26 @@ var (
ErrNoFile = fmt.Errorf("no downloadable file found in release")
)

// Latest is where we find the latest release.
const Latest = "https://api.github.com/repos/%s/releases/latest"
// LatestGH is where we find the latest release.
const LatestGH = "https://api.github.com/repos/%s/releases/latest"

// GitHub API and JSON unmarshal timeout.
const timeout = 10 * time.Second

// Update contains running Version, Current version and Download URL for Current version.
// Outdate is true if the running version is older than the current version.
type Update struct {
Outdate bool
RelDate time.Time
Version string
Current string
CurrURL string
Outdate bool // True if we're outdated, update available.
Version string // Version passed in externally.
Current string // Current release available on GH or US.
CurrURL string // URL of current release on GH or US.
RelDate time.Time // Current version release date.
RelSize int64 // Current release file size.
}

// Check checks if the app this library lives in has an updated version on GitHub.
func Check(ctx context.Context, userRepo string, version string) (*Update, error) {
release, err := GetRelease(ctx, fmt.Sprintf(Latest, userRepo))
// CheckGitHub checks if the app this library lives in has an updated version on GitHub.
func CheckGitHub(ctx context.Context, userRepo string, version string) (*Update, error) {
release, err := GetRelease(ctx, fmt.Sprintf(LatestGH, userRepo))
if err != nil {
return nil, err
}
Expand Down Expand Up @@ -104,6 +105,7 @@ func FillUpdate(release *GitHubReleasesLatest, version string) (*Update, error)
if strings.HasSuffix(file.BrowserDownloadURL, suffix) {
update.CurrURL = file.BrowserDownloadURL
update.RelDate = file.UpdatedAt
update.RelSize = file.Size

break
}
Expand Down Expand Up @@ -148,7 +150,7 @@ type GHasset struct {
Uploader GHuser `json:"uploader"`
ContentType string `json:"content_type"`
State string `json:"state"`
Size int `json:"size"`
Size int64 `json:"size"`
DownloadCount int `json:"download_count"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
Expand Down
Loading

0 comments on commit 876b38f

Please sign in to comment.