EDCD / EDMarketConnector

Downloads commodity market and other station data from the game Elite: Dangerous for use with all popular online and offline trading tools.
GNU General Public License v2.0
988 stars 155 forks source link

New feature: Plugin management & update API #513

Open kam1sh opened 4 years ago

kam1sh commented 4 years ago

That would be awesome if plugins management and updating would be automated.

Here's my view on that:

There is already File menu -> Settings window -> Plugins tab, where right now there is just plugins folder setting. What about if there would be also some kind of Add plugin -> GitHub full project name (group/name) field, and EDMC would fetch from GitHub API latest release, download zip archive, extract it in plugins directory, and restart EDMC.

Updating scenario: fetch from GH latest release, compare versions (via packaging?), download new release if needed, clean old plugin directory and extract new version.

Also, there could be Update API specification for projects that aren't hosted on GihHub. In this case, in plugins tab there would be Add plugin -> Custom URL, that should return next JSON:

{
    "latest_version": "1.4.0",
    "zip_url": "..."
}

I can try to implement that by myself when I'll have some spare time.

Athanasius commented 4 years ago

I would definitely go through known plugins to find one that already implements its own updating, check how well it works, then use it as a starting point for the actual updating. I'm thinking here how you're really going to want to fully unload the plugin's python module before you start messing with files, which of course then means having zero access to the plugin's code during the update, so it couldn't provide any helpers for handling things like settings files or other data.

And I don't think there's necessarily any need to tie this into GitHub, although that depends on how much special handling is needed between "this is a URL pointing to the latest release" and "that means the URL for the .zip of latest release is" .... Obviously GitHub has one way to do that and other hosting will likely differ.

kam1sh commented 4 years ago

to find one that already implements its own updating

Here's how we in EDMC-Triumvirate manage updates:

class Release(Frame, Module):

    def check_updates(self):
        if self.installed:
            return
        url = settings.release_gh_latest # https://api.github.com/repos/VAKazakov/EDMC-Triumvirate/releases/latest
        client = WebClient()
        data = client.get(url).json()
        latest_tag = data["tag_name"]
        latest_version = Version(latest_tag)
        self.hyperlink["url"] = data["html_url"]
        self.hyperlink["text"] = f"EDMC-Triumvirate: {latest_tag}"
        if latest_version == self.version:
            self.grid_remove()
            return
        elif latest_version < self.version:
            self.hyperlink["text"] = f"Тестовая версия {self.version.raw_value}"
            return
        if self.auto.get() != 1:
            debug("Automatic update disabled.")
            return
        self.download(latest_tag)

    def download(self, tag):
        debug("Downloading version {}", tag)
        url = settings.release_zip_template.format(tag) # https://github.com/VAKazakov/EDMC-Triumvirate/archive/{}.zip
        new_plugin_dir = f"EDMC-Triumvirate-{tag}"
        client = WebClient()
        response = client.get(url, stream=True)
        try:
            zf = zipfile.ZipFile(response.raw)
            zf.extractall(os.path.dirname(self.plugin_dir))
        finally:
            response.close()
        renamed = f"{self.plugin_dir}.disabled"
        os.rename(self.plugin_dir, renamed)
        debug("Upgrade completed.")
        self.plugin_dir = new_plugin_dir
        self.installed = True
        if sys.platform == "win32":
            import winsound

            winsound.MessageBeep(type=winsound.MB_OK)
lekeno commented 4 years ago

In case that's useful, this is how I do it in EDR: