Skip to content
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

Open
leaanthony opened this issue Feb 23, 2022 · 27 comments
Open

Support Self-Updating #1178

leaanthony opened this issue Feb 23, 2022 · 27 comments
Labels
Enhancement New feature or request TODO The issue is ready to be developed v3

Comments

@leaanthony
Copy link
Member

Investigate https://github.com/minio/selfupdate

@leaanthony leaanthony added the Enhancement New feature or request label Feb 23, 2022
@leaanthony leaanthony added this to the v2.1.0 milestone Mar 7, 2022
@misitebao
Copy link
Contributor

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.

@stale
Copy link

stale bot commented Apr 28, 2022

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.

@stale stale bot added the wont fix This will not be worked on label Apr 28, 2022
@leaanthony leaanthony removed the wont fix This will not be worked on label Apr 28, 2022
@leaanthony
Copy link
Member Author

@leaanthony
Copy link
Member Author

@leaanthony leaanthony added the TODO The issue is ready to be developed label Jul 3, 2022
@olup
Copy link

olup commented Jul 20, 2022

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 ?

@annikovk
Copy link

I'm using it with wails for some time. Work smoothly. Implemented like that:

func CheckForUpdate(currentVersion string) (bool, string, string) {
	latest, found, err := selfupdate.DetectLatest("annikovk/IntelliJ-Log-Analyzer")
	if err != nil {
		log.Println("Error occurred while detecting version:", err)
		return false, "", ""
	}
	v := semver.MustParse(currentVersion)
	if !found || latest.Version.LTE(v) {
		log.Println("Current version is the latest")
		return false, "", ""
	}
	return true, latest.Version.String(), latest.ReleaseNotes
}

@leaanthony
Copy link
Member Author

Love the work you're doing on the log analyser 🔥

@leaanthony
Copy link
Member Author

Would love a guide on how to do this in the docs ;-)

@olup
Copy link

olup commented Jul 24, 2022

@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 .app file, with moving parts ? The download and extracting and replacing is something we have to build or it's provided by the lib ? What's your experience with it ?

@brys0
Copy link

brys0 commented Aug 5, 2022

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.

@olup
Copy link

olup commented Sep 28, 2022

Maybe building something internal for this ? Tauri's implementation is interesting to look at

@leaanthony leaanthony modified the milestones: v2.1.0, v2.2.0 Oct 1, 2022
@leaanthony leaanthony modified the milestones: v2.2.0, v2.3.0 Oct 16, 2022
@Bluebugs
Copy link

Bluebugs commented Oct 21, 2022

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.

@beatscode
Copy link

beatscode commented Dec 7, 2022

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

	err = selfupdate.Apply(resp.Body, selfupdate.Options{
		TargetPath: exPath,
	})

I use the myapp.app/Contents/MacOS/binary.app to self update with. I couldn't get the .app to work
Am I missing something?

@kylege
Copy link

kylege commented Dec 8, 2022

Only update the binary itself is not enough. In macOS app/dmg file, the binary can't run if other files don't match, such as codesigning and notarizing

@leaanthony leaanthony removed this from the v2.4.0 milestone Dec 29, 2022
@Riz-waan
Copy link

@leaanthony So I noticed this is no longer on the milestone, is this still on the roadmap though?

@stffabi
Copy link
Collaborator

stffabi commented Dec 31, 2022

It is on the roadmap but has been rescheduled for v3: #1484

@leaanthony
Copy link
Member Author

Yeah, there are currently ways to do this already (see riftshare) so it's not a priority to bake into the project. There's also been very mixed feedback about how it should work (GitHub vs S3 vs etc etc)

@FrenchGithubUser
Copy link

FrenchGithubUser commented Apr 2, 2023

@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 /usr/bin/ or in windows' programs folder. I was wondering if you also encountered this issue, and if so, how did you fix it ? (ask the user for admin rights ? if so, how ? something else ?

@SgtPooki
Copy link

SgtPooki commented Jul 1, 2023

Yeah, there are currently ways to do this already (see riftshare) so it's not a priority to bake into the project. There's also been very mixed feedback about how it should work (GitHub vs S3 vs etc etc)

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.

@leaanthony
Copy link
Member Author

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.

@pavelbinar
Copy link
Contributor

Is it safe/good idea to use rhysd/go-github-selfupdate?
The latest activity is from Jan 13, 2021 🤔

@mJehanno
Copy link
Contributor

mJehanno commented Mar 4, 2024

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.
It let the user of the library choose if it will just check if there is a new version or if it will check and update.
You can find it here.

don't hesitate to use it, fork it, improve it, takes some part of it if that can help.

@wudimenghuan
Copy link

@RichardLindhout
Copy link

It looks like in production it has not the permission to run 'ditto' at least I got some errors there

@RichardLindhout
Copy link

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

@wudimenghuan
Copy link

@annikovk谢谢你的例子,那我就用这个方法吧。我还是不太清楚实际更新应该如何进行——我可以想象在 Linux 或 Windows 上更新时,我会得到一个可执行文件,但对于 MacOS 来说,它是一个.app文件,有移动部件?下载、提取和替换是我们必须构建的,还是由库提供的?你对此有什么经验?

Me too, .app not work

@MickeyUK
Copy link

MickeyUK commented Oct 9, 2024

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

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Enhancement New feature or request TODO The issue is ready to be developed v3
Projects
None yet
Development

No branches or pull requests