mouuff / go-rocket-update

Easy to use and modular library to make self updating golang programs
Other
103 stars 11 forks source link

Suggestion: allow basic templating in `ArchiveName` & `ExecutableName` #14

Open axllent opened 3 years ago

axllent commented 3 years ago

Certain projects use the release tag in the archive name, eg awesome-package_0.1.2_linux_amd64.tar.gz, and I seem to recall some that even use it in the binary name too (not that I think the latter is a good idea).

My suggestion is to allow some basic go templating on both the Provider ArchiveName and Updater .ExecutableName of at least some common variables, such as {{.Tag}} {{.GOOS}}&{{.GOARCH}}. Whilst certain variables can be generated before the request (runtime.GOOS&runtime.GOARCH`), others are dependent on the remote info.

u := &updater.Updater{
    Provider: &provider.Github{
        RepositoryURL: "github.com/user/awesome-package",
        ArchiveName:   `awesome-package_{{.Tag}}_{{.GOOS}}_{{.GOARCH}}`,
    },
    ExecutableName: "awesome-package_{{.Tag}}",
    Version:        "0.1.1",
}

This would of course still remain completely backwards compatible with the current system, and one could even mix the two: ArchiveName: fmt.Sprintf("awesome-package_{{.Tag}}_%s_%s.tar.gz", runtime.GOOS, runtime.GOARCH).

The backstory is I've been meaning to rewrite a simple GitHub binary updater I wrote some time ago (far more primitive than yours), although I have been putting it off while I collect ideas etc. I just came across go-rocket-update which I think has a lot of potential, so rather than me spend time rewriting mine from scratch, I'd first check to see if you were open to suggestions to yours instead? I also have some other suggestions too if you're open to it.

mouuff commented 3 years ago

Thank you for the suggestion! Yes I think it could be a good idea! Today what you can do is call the provider by yourself to get the version (and then the updater) but I agree that variables would make things a lot easier :)

Implementation:

I think we should add the whole templating logic outside the updater. The updater would just use an interface to get the variables. We would have a default implementation for the basic {{.Tag}} {{.GOOS}} {{.GOARCH}} variables, and if a dev wants to add his own variables then he could make his own implementation of that interface.

axllent commented 3 years ago

I hadn't considered running it twice as an interim workaround, although I haven't implemented go-rocket-update yet in anything as I'm still in the testing phase, and seeing where this project is headed. I think that your implementation proposal makes good sense though, and hopefully doesn't add too much bulk or complication.

mouuff commented 3 years ago

Not exactly running it twice, just running the provider to get the latest version, then setup the updater with this information. But indeed GetLatestVersion will be called a second time by the updater. I m not afraid of the bulk/complications. It's just another interface. But fell free to make a PR with your own implementation :)

mouuff commented 3 years ago

Here is a workaround for now. Example with ticker:

func selfUpdate() (updater.UpdateStatus, error) {
    provider := &provider.Github{
        RepositoryURL: "github.com/achannarasappa/ticker",
    }
    latestVersion, err := provider.GetLatestVersion()
    if err != nil {
        return updater.Unknown, err
    }
    if len(latestVersion) > 0 {
        latestVersion = latestVersion[1:] // removes the 'v' prefix to match github archive
    }
    provider.ArchiveName = fmt.Sprintf("ticker-%s-%s-%s.tar.gz", latestVersion, runtime.GOOS, runtime.GOARCH)
    u := &updater.Updater{
        Provider:       provider,
        ExecutableName: "ticker",
        Version:        c.Version,
    }
    return u.Update()
}
mouuff commented 3 years ago

I think I will try to find some time this or next month to implement that. except if you fell like making a PR :) I think it could be a great addition!

axllent commented 3 years ago

It's unlikely I'll be able to spend much time on this in the next two months as well, as I just returned to work last week after a shoulder operation two months ago (long recovery, and now a huge backlog of work to catch up on). This was actually the main reason I was looking for existing self updater modules last week, as I just don't have the time to reinvent the wheel right now again :-) I'm also not in any rush either. If I do manage to spend some time on it I'll let you know though!