EventGhost
EventGhost copied to clipboard
Create an online plugin repository
Lack of discoverability for new functionality is currently one of EventGhost's biggest problems. Googling and browsing the forum is a fool's game. Someday, there's going to be a better way.
One of our long-term goals is to remove almost all non-essential plugins from the distribution and instead provide access from within EventGhost to an online plugin repository of both official plugins from the EventGhost team and trusted plugins from the community. This issue is where the discussion of this quantum leap forward will take place.
I envision the plugin repository to function just as the Add Plugin dialog currently does -- EventGhost will periodically update its package list in the background, and when you open the Add Plugin dialog, you'll see exactly what you see now, perhaps with plugins you currently have installed denoted in some way (bold font? "[Installed]" beside each one? "Installed Plugins" folder at the top?), and perhaps with a search box to filter the soon-to-be-much-larger list.
Plugins installed from the repository will auto-update by default, solving two important issues:
- Users won't need to keep up with an ever-growing list of forum threads to ensure their plugins are up-to-date.
- We won't need to release entirely new versions of EventGhost just to push out a few plugin updates, as is currently the case.
We can look to Sublime Text's Package Control for the gold standard of community package management. There are surely plenty of lessons we can learn from Will Bond and team's work, both in terms of code and policy.
Here's some previous discussion of this topic on the forum: www.eventghost.net/forum/viewtopic.php?t=7434 I agree this would be a very useful feature.
Just to be clear, this requires a ton of work to do well.
- Server side repository (this includes it's own codebase, deployment strategy, maintain cost for time and money)
- Website
- APIs
- Client side tool (could be built into EG)
- for devs to use to publish their packages and package updates
- for users to pull updates
- Package dependencies (
webserverplugin requirestornadolibrary etc.)
This is why many projects instead of creating their own ecosystem just hook into another package manager, in this case: pip / PyPI. It has the classifiers feature to tag packages. We could have the convention of an EventGhost classifier that all plugins use. I deeply believe each plugin should be its own repo and thus could use pip to publish and all the other actions. EG core could connect to pip to do updates and handle dependency resolution. This also removes the need to have our own server and maintain it.
To be clear, let's not reinvent the wheel. Instead, let's just integrate core with pip and rewrite plugins to be python packages.
If pip can be sufficiently bent to our will, I'm in favor of going that route. Doing so would allow us to remove a litany of dependencies from the distribution as well that most users just don't need.
I haven't found out how to use/integrate pip/PyPi with EG, but on the other hand haven't much research done as i don't like it. I would prefer to have a plugin manager integrated to EG and additionaly a download section in the forum. There the users can upload their plugins. And If we want, we can make the uploaded plugins requiere a approval by a moderator.
Have you gone through and implemented this in full already, or is it just a really elaborate mock-up? Because it really, really pains me to criticize if it's all already done.
The problems I see with this approach:
- First and foremost, no one with the experience to pull this sort of thing off (much less maintain it) has access to the server, and the admin refuses to cede control to someone who does. Pako does have access (though I'm not sure if it's full access), but -- and correct me if I'm wrong, Pako -- this is far outside his wheelhouse.
- We absolutely do not under any circumstances want to tie this to a dead package like phpBB (apparently it was updated as recently as April 17th of this year, but it hasn't changed in any meaningful way in the past 10+ years), nor would I personally ever install a third-party add-on for forum software on a production server, as they're notoriously riddled with security flaws.
- Because we're serving arbitrary Python code, anyone who breaks into such a download portal can now execute any code they want on every machine in the world running EventGhost by simply replacing a core plugin. There needs to be some sort of signing system in place either way, but this would only exacerbate the need.
- I'm betting the phpBB add-on doesn't have an API, and scraping is a losing battle. We upgrade the add-on to fix a security flaw, the output format changes, and suddenly, nobody can update their plugins until we release a new version of EventGhost.
- From a design perspective, this is infinitely more complex than it needs to be. As always, I prefer to hide as much from the user as is reasonably possible. For example, there should be no practical difference between an installed plugin and an uninstalled plugin, and in terms of updating, both the index and the plugins themselves should be updated automatically in the background, with, at most, an option to disable that. A well-designed system wouldn't require a package management dialog at all.
I'm not saying pip is necessarily the perfect solution, nor am I saying there aren't any issues we'd need to address with a pip system -- there just happen to be inexorable issues that make this particular path forward ill-advised.
Just a few ideas from my intermittent pondering throughout the day:
- We should require that plugins define a particular set of metadata (GUID, version in semver format, repo link, forum link...) to be accepted in the index. This isn't a radical idea or anything, but is something we need to nail down specifics for.
- When updated, the previous version of a plugin (I don't see a need to save more than one) should be moved to
%PROGRAMDATA%\EventGhost\plugins-backup. If an updated plugin fails to load, it should automatically be replaced with the last working copy fromplugins-backup, and the current version should be blacklisted (locally) so the program doesn't try to update to that version again. - We should extend the base class to add an extra tab to plugin configuration dialogs. This tab could include the ability to select the update channel (stable releases, pre-releases, or the latest code from
master), the ability to disable automatic updates for only that plugin, and the ability to rollback to the previous version. Only plugins with the necessary metadata should display this tab, as it isn't relevant to plugins not indexed (such as abandoned or in-development ones). - We should aim to update plugins without requiring a restart, which should be possible via disable,
imp.reload(), re-enable.
And a few concerns:
- It sounds like you're suggesting we submit EventGhost plugins to PyPI itself, @CarsonF, but @topic2k makes the important point that we should have some kind of moderation system. Does PyPI support that use case?
- If, as many other programs do, we offer developers the ability to run their own indexes (though frankly, I don't see the point), the official index should always take precedence to prevent unscrupulous individuals from, for example, surreptitiously offering their own
Systemplugin with a higher version that users of their index would then automatically update to. Troublingly, I'm not finding any evidence that this is somethingpipsupports. - I'm not finding any evidence that
pipsupports update channels either.
Should we need to roll our own solution to address the above concerns (and those are just off the top of my head), the simplest alternative would be to toss an index up on eventghost.github.io, have developers send along a pull request to update it with their latest plugins, and leverage agithub to pull version information and download links from the associated repo.
In any case, before any further work on this is done, we should complete the design in full. If we're going to attack this, we need to get it right.
Have you gone through and implemented this in full already, or is it just a really elaborate mock-up? Because it really, really pains me to criticize if it's all already done.
I had it already implemented and working two months ago, but then didn't go further. No problem if you don't like it and don't want to use it. I liked the challenge to implement it and on the way learn a bit PHP and SQL. :)
- First and foremost, no one with the experience to pull this sort of thing off (much less maintain it) has access to the server, and the admin refuses to cede control to someone who does. Pako does have access (though I'm not sure if it's full access), but -- and correct me if I'm wrong, Pako -- this is far outside his wheelhouse.
Maybe we should ask in the forum if there is someone with good knowledge of PHP and SQL. But that's of course only needed if plugin repository is an own.
- Because we're serving arbitrary Python code, anyone who breaks into such a download portal can now execute any code they want on every machine in the world running EventGhost by simply replacing a core plugin. There needs to be some sort of signing system in place either way, but this would only exacerbate the need.
Well, if someone forks the github source, compile a "special" version and spread it, there is although a risk to break the signing system. Software will never be safe to use. (Just my opinion.)
- I'm betting the phpBB add-on doesn't have an API, and scraping is a losing battle. We upgrade the add-on to fix a security flaw, the output format changes, and suddenly, nobody can update their plugins until we release a new version of EventGhost.
An API for integrating it in the Forum or an API to get file information? The latter is stored in a SQL-Database and good readable. Of course, the format could be changed, but i wouldn't worry to much about it. And if someone can't automatically update a plugin.. well.. i don't think that will be the end of the world. There should always be the possibility to manually update it. For they way, i have implemented it, there is only a simple php-script and a sql-database needed. The forum extension was just an idea and which was easy to adopt.
- From a design perspective, this is infinitely more complex than it needs to be. As always, I prefer to hide as much from the user as is reasonably possible. For example, there should be no practical difference between an installed plugin and an uninstalled plugin, and in terms of updating, both the index and the plugins themselves should be updated automatically in the background, with, at most, an option to disable that. A well-designed system wouldn't require a package management dialog at all.
The plugin manager dialog i showed is just a part of what i have in mind. Nearly what you've said: automatically update plugins/EG which the selected (by default activated). If there are new, never before released plugins, a popup or some other way to notify the user about it, should appear (with an option to diasable it). I think the manager dialog is still needed: if a user need a plugin for something, than he can open the manager and search for it and if found, directly install it. Of course he could search in the forum, download and install it manually.
- We should require that plugins define a particular set of metadata (GUID, version in semver format, repo link, forum link...) to be accepted in the index. This isn't a radical idea or anything, but is something we need to nail down specifics for.
- When updated, the previous version of a plugin (I don't see a need to save more than one) should be moved to %PROGRAMDATA%\EventGhost\plugins-backup. If an updated plugin fails to load, it should automatically be replaced with the last working copy from plugins-backup, and the current version should be blacklisted (locally) so the program doesn't try to update to that version again.
- We should extend the base class to add an extra tab to plugin configuration dialogs. This tab could include the ability to select the update channel (stable releases, pre-releases, or the latest code from master), the ability to disable automatic updates for only that plugin, and the ability to rollback to the previous version. Only plugins with the necessary metadata should display this tab, as it isn't relevant to plugins not indexed (such as abandoned or in-development ones).
+1 for the above three points. :)
- We should aim to update plugins without requiring a restart, which should be possible via disable, imp.reload(), re-enable.
It's not done with imp.reload(), but it's possible (have it working in my plugin manager).
- If, as many other programs do, we offer developers the ability to run their own indexes (though frankly, I don't see the point), the official index should always take precedence to prevent
I don't think that there is a need for other indexes. If EG would be more known/spread and have thousands of plugins, then mabye, but not know.
Should we need to roll our own solution to address the above concerns (and those are just off the top of my head), the simplest alternative would be to toss an index up on eventghost.github.io, have developers send along a pull request to update it with their latest plugins, and leverage agithub to pull version information and download links from the associated repo.
But if you pull from github (or other repos) then again you have no control and the repo could serve malicious code.
Maybe we should ask in the forum if there is someone with good knowledge of PHP and SQL. But that's of course only needed if plugin repository is an own.
There's at least one person right here typing this reply, and it sounds like you're on the right track yourself, but without access, it matters not.
Well, if someone forks the github source, compile a "special" version and spread it, there is although a risk to break the signing system. Software will never be safe to use. (Just my opinion.)
If a user is dumb enough to install a "special" version, they get what they deserve, I say. Just as A/V software won't always protect people who open .exe email attachments, we, too, can't protect people who don't care about being protected. Users doing the correct thing and using the official version, though, will have the (perfectly reasonable) expectation of this not blowing up in their faces, and it's those users we serve by making the correct design decisions.
You make the point that developers could serve malicious code from their repos, and that's fair, but they can also do that right now from the forum, and how many people aside from me are reviewing code before updating? Few, I suspect, if any at all. To be sure, automatic updates complicate things; fortunately, the people writing the lion's share of plugins are people we trust -- people like me, people like you, people like Pako, Walter, and Joni. And it's true that, even with people we trust, someone could break into their forum account, their GitHub account, their TeamViewer, or any number of other things, but that's significantly more difficult than typing "phpbb download addon exploit" into Google and following the directions.
You're right -- software will never be totally safe to use -- but we have an obligation to make this as safe as we possibly can, and there are concrete steps we can take to that end. Let's take them.
An API for integrating it in the Forum or an API to get file information?
An API the program can use to pull the information it needs from the server. Sure, the SQL database can be read, but not directly by the program -- there needs to be an API in place to do that.
For they way, i have implemented it, there is only a simple php-script and a sql-database needed. The forum extension was just an idea and which was easy to adopt.
Either way, there needs to be a way to publish these plugins in the first place. If not via the forum add-on, how?
If there are new, never before released plugins, a popup or some other way to notify the user about it, should appear (with an option to diasable it).
+1, though I'd like to see this disabled by default.
I think the manager dialog is still needed: if a user need a plugin for something, than he can open the manager and search for it and if found, directly install it.
My point was that the manager dialog can simply be the current Add Plugin dialog. As I say in the OP: "when you open the Add Plugin dialog, you'll see exactly what you see now, [...] perhaps with a search box to filter the soon-to-be-much-larger list." In addition to the plugins in Program Files and %PROGRAMDATA%, the dialog would also show all the plugins in the index. If the plugin you add isn't available on your system, it's downloaded before being added to your tree, and when you remove it from your tree, it's removed from your system as well (but only if it was downloaded from the index). The remaining features of the plugin manager dialog would be rolled into the base class tab, obviating the need for the dialog entirely.
I have a few remarks / concerns I like to share with you in terms of automatic plugin update in the Background:
- To update plugins in
Program Fileswe would need some sort of windows service, as the user may not have EventGhost run as admin and therefor has no permission to write to this folder. - I don't see a big benefit in updating plugins completely automated in the background; usually plugin updates add new features, but when the user doesn’t know there was an update or there are new features, he won’t use them. But notifying the user (on startup) if there is something new would be very cool. There should also be a change log displayed, so the user knows what's new (of course it would be the task of the Plugin Developer to maintain it).
- EventGhost is an automation tool that runs without a visible UI most of the time, I use it for home automation, for me it’s important that it runs absolutely stable. However, plugin developers don’t always test their plugins very carefully before releasing them, sometimes they aren’t even 100% backwards compatible. So it might be that your configuration stops working out of the blue after an automatic plugin update even if the “new” plugin loads perfectly without an error, but some events changed and your macros doesn’t fire anymore. Worst case, there is a new bug with a plugin update that will cause EG to crash if a specific action is executed. Because the update happened automated in the background and the user doesn’t know there was one, the user could blame EG in general to be a bad/unstable software.
- I also have concerns if a plugin get’s updated without restarting EventGhost. Some plugins have actions e.g. to initialize the connection to a remote host, that’s usually an action that needs to be executed once. Now, if the user puts this action under Autostart (where all the loaded plugins are initialized) the action would not fire without restarting EventGhost. So your macros will stop working until you restart EG after the update, as the connection to the remote host doesn’t exist anymore.
I'm sorry for criticizing that much. In general I like the idea of having a repository and I really appreciate you’re working on this.
I don't have that much experience with pip/pypi, though my experience with composer (PHP's package manager) it is a whipping to roll that code ourselves.
Something that hasn't been brought up yet is plugin dependencies. For example, I want to write a wrapper plugin for Foo device and there is a Foo SDK in PyPi. I should be able to just specify that dependencies instead of having to roll that into my plugin releases and maintain it.
That's why I said let's use pip if we can, since it will resolve those dependencies recursively (without duplicating them).
I'm not finding any evidence that pip supports update channels either.
That's an interesting point, I'm not sure either. With composer you can say ^3.0@beta. Maybe pip doesn't support different stabilities though.
To update plugins in Program Files we would need some sort of windows service, as the user may not have EventGhost run as admin and therefor has no permission to write to this folder.
We already have code in the builder to place all plugins in %PROGRAMDATA% instead of Program Files, just waiting to be activated.
But notifying the user (on startup) if there is something new would be very cool. There should also be a change log displayed, so the user knows what's new (of course it would be the task of the Plugin Developer to maintain it).
This is where #47 would come in handy, particularly after the Anniversary Update when we'll be able to add buttons.
However, plugin developers don’t always test their plugins very carefully before releasing them, sometimes they aren’t even 100% backwards compatible.
A valid point. Good developers should be using semver and incrementing the major version when there are backwards-incompatible changes, and we should be able to rely on that to decide when to automatically update and when to ask, but hobbyists don't always qualify as good developers. We may have to ask by default.
I also have concerns if a plugin get’s updated without restarting EventGhost. Some plugins have actions e.g. to initialize the connection to a remote host, that’s usually an action that needs to be executed once.
Can you provide an example of a plugin that initializes via action and not via its __start__() function? I can't think of any reason off the top of my head why one would do that. Sounds like bad design to me.
I'm sorry for criticizing that much.
No need to apologize whatsoever -- this is exactly what we want at this stage. To borrow a line from Jim Halpert (The Office): "This is a very good idea. This is good. Let's get all the bad ideas out now. Flush 'em out."
Can you provide an example of a plugin that initializes via action and not via its start() function? I can't think of any reason off the top of my head why one would do that. Sounds like bad design to me.
Sure, one good example would be the ping plugin in which you have an action called "Add Host". If the action is triggered EG starts a new thread which monitors the IP entered in the "Add Host" action. You can use the action "Remove Host" to stop pinging an address. There are lot's of plugins that behave similar and I wouldn't say that this is a bad design. The only alternative to provide a similar functionality I can think off is, to allow the plugin to be loaded multiple times and ping only one host you define in the plugin configuration, but I don't prefer that, as it's much more unflexible. Just two exempels:
- You may not want your host to be pinged all the time, but only start if a specific event occurs.
- I have a configuration were I ping multible hosts that are defined in some script in an array. Very simple to do right now, two lines of code or something, if I'd have to add another instance of the plugin to my configuration for each of the 30 hosts I'm pingin, it would be quite a task to setup everything...
How about a hybrid solution? Add all of the packages to PyPI (perhaps with an eg-prefix for easy searching?) but create a separate Github repository where plugins can be added through pull requests which would allow for automated travis or appveyor testing as well. That way we can still manually allow (and disallow) plugins from the repository while maintaining the automatic dependency installation that pip together with pypi offers.
Setting up your own plugin hosting service seems like a bad idea since it's yet another moving part which needs to be maintained. Github and PyPI are there for everyone to use and they offer enough to make this possible and convenient :)
As for the metadata, I would suggest using the setuptools entry points for that. That makes it trivial to register event listeners, actions, etc... Here's an example of how you can hook into setup.py: https://github.com/WoLpH/sphinx-pypi-upload but you can hook whichever way you like :)