-
-
Notifications
You must be signed in to change notification settings - Fork 1.3k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Support Self-Updating #1178
Comments
I think this feature can exist as an official library under the wailsapp organization, and developers can choose to use it or not, and should not be built into the wails project. This way developers can customize their auto-update strategy and we can provide guidance and examples. |
This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions. |
Vital feedback on this feature: https://gophers.slack.com/archives/CJ4P9F7MZ/p1656654913191629?thread_ts=1656616142.685839&cid=CJ4P9F7MZ |
I am very interested by this but does not have access to the slack post in question. Has anyone tested rhysd/go-github-selfupdate with wails ? |
I'm using it with wails for some time. Work smoothly. Implemented like that:
|
Love the work you're doing on the log analyser 🔥 |
Would love a guide on how to do this in the docs ;-) |
@annikovk thanks for the example, I am going to use this route then. It's still a bit fuzzy for me how the actual update should happend - I can picture it for linux or windows where I get a single executable, but what about macos where it's a |
I would probably use the go selfupdate if it had the features I wanted. For now I enabled the ability to download an exe from a url (not sure on the api setup yet) and it gives download progress (which go-selfupdate does not). I'd be happy to have a sorta package or something around it for people who want it. This does mean writing some sort of syntax for the download URL in such and so it might take some time. Let me know if you people are interested in this. |
Maybe building something internal for this ? Tauri's implementation is interesting to look at |
Just wanted to point out to another selfupdate solution : https://github.com/fynelabs/selfupdate , used mostly by Fyne related project, but it is not depending on it and can be use by any other go project. It gives progress, work on MacOS, Linux and Windows. |
I'm working with the minio/selfupdate package to self update. It works, sort of. After the update the app opens however, any tags used (Build version for example) are not kept through the update. The code is pretty straight forward
I use the |
@annikovk I implemented a self-update mechanism as well with rhysd/go-github-selfupdate. It works well but only if the binary is in a folder that doesn't require admin/root rights to write in. So this is problematic if the binary is in |
I'm not a gopher so this may be a dumb question, but since this is a golang project, and golang goes hard on github, why isn't github the obvious first choice? Btw, the riftshare code for selfupdate is at https://github.com/achhabra2/riftshare/blob/main/internal/update/selfupdate.go for those curious. |
Indeed. Also, different people want different things. There's a plugin system for wails3 that's working pretty well in the pre-alpha. I think that's an ideal candidate for this. |
Is it safe/good idea to use rhysd/go-github-selfupdate? |
I wanted to add this feature to my wails app recently. I choosed to create my own library to handle this. Why ? because other libraries are either relying on storage object (s3) or are behaving like the binary is located in $GOBIN (which is not always the case with a builded wails app). My lib relies on github releases. It's a bit experimental, it seems to work on linux, didn't really try on windows. don't hesitate to use it, fork it, improve it, takes some part of it if that can help. |
It looks like in production it has not the permission to run 'ditto' at least I got some errors there |
Looks like it needs another process to replace itself. So really self-update is not possible a.t.m. I think i will just add a button if update is available to download (then permission will be required on mac to download) and then after dowloading redirecting the user to the install .pkg |
Me too, .app not work |
I am new to golang, so I'm not sure if this is the best way, but this is how I've implemented self updating on Windows for my wails app, using GitHub. I learnt how to check for updates using the example mentioned above (https://github.com/achhabra2/riftshare/blob/main/internal/update/selfupdate.go) ...however, I couldn't get the actual updating to work with that example. So what I did was I used this to download the update to the working directory (https://github.com/cavaliergopher/grab), then I created a batch file that will rename the file and update. This is a rough example: func startUpdate(version string) {
file := "https://github.com/USER/REPOSITORY/releases/download/" + version + "/YourApp_windows_amd64.exe"
// create client
client := grab.NewClient()
req, _ := grab.NewRequest(".", file)
// start download
fmt.Printf("Downloading %v...\n", req.URL())
resp := client.Do(req)
fmt.Printf(" %v\n", resp.HTTPResponse.Status)
// start UI loop
t := time.NewTicker(500 * time.Millisecond)
defer t.Stop()
Loop:
for {
select {
case <-t.C:
// Can get progress with: int(resp.Progress() * 100)
case <-resp.Done:
break Loop
}
}
// check for errors
if err := resp.Err(); err != nil {
fmt.Fprintf(os.Stderr, "Download failed: %v\n", err)
os.Exit(1)
}
fmt.Printf("Download saved to ./%v \n", resp.Filename)
// New and old file names
oldFile := "YourApp.exe"
newFile := "YourApp_windows_amd64.exe"
// Create the batch script content
script := fmt.Sprintf(`@echo off
echo The application is updating. Please wait...
timeout /t 5
del %s
rename %s %s
start %s
del %s
exit`, oldFile, newFile, oldFile, oldFile, "update.bat")
// Write the script to a file
updateFile, err := os.Create("update.bat")
if err != nil {
panic(err)
}
defer updateFile.Close()
_, err = updateFile.WriteString(script)
if err != nil {
panic(err)
}
// Run the script
cmd := exec.Command("cmd", "/C", "start update.bat")
cmd.Start()
// Close the application
os.Exit(0)
} Hope this helps someone |
I would like to see this auto-update feature too. |
This is also probably better off becoming a plugin for wails v3. |
Just for your Info: i am currently using the Self updating service API by keygen.sh. If someone needs to use something like this now |
A little guide on how to do this would be incredible! Looks like a great option. |
This is a little late but what I did previously for my apps is have a centralized location to check if there's a new version available. If there is I rename the current process, download the new application with the rename to the previous, then on next restart it should be running the new instance of the app. This is probably if not the simplest way to have "automatic" in-app updates. |
On KeyGen.Sh you have to create a free account (or self host it if preferred). After this you can create releases via WebUI or API. Every release needs to have some artifacts for the specific OS/Architecture ,e.g. [Your_APP.exe]_windows_amd64.exe. Upload the artifact and "release" the release. On the Go-Side: func (a *App) CheckForUpdates(mode int) {
env, err := assetenv.ReadFile(".env")
if err != nil {
log.Fatal("Error loading .env file")
}
viper.SetConfigName("env") // name of config file (without extension)
viper.SetConfigType("env")
err = viper.ReadConfig(bytes.NewBuffer(env))
if err != nil {
log.Fatal("Error reading .env file")
}
keygen.Account = viper.Get("keygen.Account").(string)
keygen.Product = viper.Get("keygen.Product").(string)
opts := keygen.UpgradeOptions{CurrentVersion: Version, Channel: Channel, PublicKey: PublicKey}
// Check for an upgrade
release, err := keygen.Upgrade(opts)
switch {
case err == keygen.ErrUpgradeNotAvailable:
fmt.Println("No upgrade available, already at the latest version!")
functions.EmitError(
a.ctx,
errors.New("Kein Update verfügbar. Bereits auf dem neuesten Stand!"),
)
return
case err != nil:
fmt.Println("Upgrade check failed!")
return
}
// Upgrade is available!
if mode == BrowserMode {
functions.EmitError(a.ctx, errors.New("Update verfügbar! Bitte Update durchführen!"))
} else if mode == GoMode {
fmt.Println("Upgrade available:", release.Version)
}
a.update = release
fmt.Println("Release hinterlegt")
}
func (a *App) UpgradeInfos() VersionType {
fmt.Println("UpgradeInfos")
if a.update == nil {
return VersionType{}
}
fmt.Println("Upgrade available from SysInfo:", a.update.Version)
var rtnValue VersionType
rtnValue.Version = a.update.Version
rtnValue.Channel = a.update.Channel
rtnValue.Created = a.update.Created.String()
return rtnValue
}
func (a *App) UpgradeApp() {
// Install the upgrade
functions.EmitProgress(a.ctx, FtpClient.Progresstype{Message: "Starte Upgrade"})
if err := a.update.Install(); err != nil {
fmt.Println(err)
functions.EmitError(a.ctx, errors.New("Upgrade Installation fehlgeschlagen!"))
} else {
functions.EmitError(a.ctx, errors.New("Upgrade vollständig! Bitte Anwendung neu starten"))
}
functions.EmitProgress(a.ctx, FtpClient.Progresstype{})
} Not the cleanest, but it works very well. package main
var (
Version = "0.x.y"
Date = "2024-12-13 13:50:00 +0200 CEST"
Channel = "stable"
PublicKey = `[your key from keygen]`
) On Init, the API compares the local Version with the versions online. If a newer Release is available, you get a response which is, in this case, stored locally for immediate use. |
Thank you so much @StephanMa 🙏 |
A walkthrough on using go-sparkle to self-update wails for the next wayward soul who stumbles through to this thread |
This would make a great v3 Service. |
i agree on this, and im enthusiastly waiting until v3 |
Hey, developer of go-sparkle and go-winsparkle here (the packages @kruegernet is using in the example above). I'm happy to help with the integration. I'm thinking a higher level package which selects either go-sparkle or go-winsparkle, based on which OS is running which has a unified API would probably simplify things. |
I've also created an app which automatically creates and deploys the appcast feeds needed for sparkle and winsparkle: https://github.com/kubri/kubri This can also be used as a library so we could have a single command in wails which builds the app, then generates the appcast feed and publishes it. FYI kubri also creates YUM and APT repos so we could integrate it so that auto-updating is completely cross platform including creating and updating Linux repos. The Linux repos and the appcast feed can all be deployed to a GitHub repo so users do not need a server to host their updates. |
Hey @abemedia 👋 Great to see you here! That sounds amazing 😍 Are you on discord at all? I've been working on this in the background and tying it in with native app signing. It would be good to co-ordinate efforts. |
@leaanthony I do. Just added you as a friend. |
Investigate https://github.com/minio/selfupdate
The text was updated successfully, but these errors were encountered: