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

Prefer checksummed versioned or no_checksum latest casks? #1021

Closed
phinze opened this issue Sep 15, 2013 · 22 comments
Closed

Prefer checksummed versioned or no_checksum latest casks? #1021

phinze opened this issue Sep 15, 2013 · 22 comments

Comments

@phinze
Copy link
Contributor

phinze commented Sep 15, 2013

This issue comes from a long discussion in #1011 between @gregstallings @vitorgalvao @nanoxd and @passcod.

If anybody believes the core issue to be different than the one I've titled; please let me know and I'm happy to edit.


Here's the way I put it over there:

For a given cask, if we have available both latest / no_checksum and versioned / checksummed URLs, which should we prefer?

So to lay out some differences...

Preferring latest

  • 👍 Maintainers don't have to deal with PRs for every cask update.
  • 👍 / 👎 For apps with autoupdate, users don't interact with homebrew-cask for upgrades. (Some users may prefer this usage model; other may prefer homebrew-cask to be a one-stop-shop package manager.)
  • 👎 There's no checksum protecting the download from MITM.

Preferring checksummed

  • 👍 Checksums protect the downloads from tomfoolery and skullduggery 💀.
  • 👍 / 👎 For upgrades, homebrew-cask manages different versions.
  • 👎 Maintainers + contributors need to process update PRs more often.

There are a few things I'd like to highlight as we continue this conversation:

Users and Maintainers are Different

There is an important distinction between user benefit and maintainer benefit. I believe we should strive for both, but in situations where they are at odds where should always prefer users over maintainers (within reason). Obviously hours of maintainer work for a minor user benefit is a bad idea. But something somewhat inconvenient for maintainers that provides a major benefit to users deserves to be considered.

Mostly I want to make sure we distinguish the two in our conversations about features and stuff, so we can properly talk about the needs of the two groups.

There was one more thing but now I've forgotten it.

Maybe it will come back to me. 😊

@sheerun
Copy link
Contributor

sheerun commented Sep 22, 2013

Maybe just some warning when checksum changes

@vitorgalvao
Copy link
Member

Maybe just some warning when checksum changes

Could you please elaborate? How would this help? If the checksum changes, there is no need for a warning (since it’ll be checked anyway, and if it does not match, you’ll get a warning anyway), and that still entails always using it.

@passcod
Copy link
Contributor

passcod commented Sep 24, 2013

I think @sheerun means something of the kind "Warning, checksum doesn't match, continuing anyway..."

@sheerun
Copy link
Contributor

sheerun commented Sep 24, 2013

Yes, exactly.

@vitorgalvao
Copy link
Member

I see how it would work, just not how it would help — if the checksum doesn’t match, you likely wouldn’t want the installation to continue, you’d prefer to know what is wrong, and try again after solving the issue. Having the trouble of checksumming everything and just showing a warning instead of preventing the installation, seems a bit pointless to me. In short, I don’t see that solution as an argument for or against any of the proposals.

@hanxue
Copy link
Contributor

hanxue commented Oct 31, 2013

I fully support @phinze 's view that user's benefit should be above maintainers' benefit, within reason.

Have we come to a decision and a guideline?

My reasons from #1410

  • without version and checksum, there is little added value for a homebrew cask user
  • not leveraging the (expected) functions inherited from homebrew
  • user cannot determine version of an app using brew cask info <app>

Where applicable, a Cask should include the version and checksum.

[Remove gripe]

Please consider giving contributor a chance to amend their Pull Request before closing. Linking issues rather than closing.

@vitorgalvao
Copy link
Member

Please consider giving contributor a chance to amend their Pull Request before closing. Linking issues rather than closing.

When have you seen that happen? If a new cask is added, the url points to a link without a version in the name but it has a version number and checksum, we ask the contributor to change it; if the contributor changes an already present cask to have a version and checksum, the issue is closed and directed to the relevant discussion. How could the issue, in the latter case, be further amended? It changed something that is not yet agreed upon, so naturally it will be rejected/put on hold until we reach a consensus; if we do, and we change it, then we start changing it for every cask.

My vote is still to continue using latest. Let’s not forget that having an application link to a url without a specific version, but with a checksum, will break the cask all the time — it happened before — latest has a reason for existing, and it’s a good one, it doesn’t just facilitate the work for contributors, it’s also less annoying for users.

@hanxue
Copy link
Contributor

hanxue commented Nov 1, 2013

When have you seen that happen? If a new cask is added, the url points
to a link without a version in the name but it has a version number and
checksum, we ask the contributor to change it; if the contributor changes
an already present cask to have a version and checksum, the issue is
closed and directed to the relevant discussion. How could the issue, in the
latter case, be further amended? It changed something that is not yet
agreed upon, so naturally it will be rejected/put on hold until we reach a
consensus; if we do, and we change it, then we start changing it for every
cask.

My interpretation is the issue is undecided. So whether a Cask author
includes version/checksum or latest, they should be accepted or put on
hold, but not closed. These are closed without giving me a chance to amend
the PR: #1359 #1360 #1364 #1363 #1354

My vote is still to continue using latest. Let’s not forget that having
an application link to a url without a specific version, but with a
checksum, will break the cask all the time — it happened before — *
latest* has a reason for existing, and it’s a good one, it’s doesn’t just
facilitate the work for contributors, it’s also less annoying for users.

Can we agree to disagree here? :) My reasons are in #1410

@nanoxd
Copy link
Contributor

nanoxd commented Nov 1, 2013

#1359 #1363 #1354 are still open and waiting for your changes.
#1360 #1364 were changed, merged, and closed via commit by me here: 0186293 db59328

@vitorgalvao
Copy link
Member

Can we agree to disagree here?

Not really. We’ll eventually have to stick with one, so the community has to reach some kind of agreement — specially since the options are mutually exclusive.

My interpretation is the issue is undecided.

You are correct.

So whether a Cask author includes version/checksum or latest, they should be accepted or put on hold, but not closed.

No, they should not. This issue is not a case of “should we do it this way or that way”, it’s a case of “we’ve been doing it a certain way, should we change it”. This means that until a decision is made, the old way (read, current way) should be in place. Consistency is the word; let’s not have a bunch of casks that all follow different rules, that’s why there are people that triage, discuss, and manage what changes are best for the project as a whole (with the help and opinions of the rest of the community, naturally).

I’ve seen pull requests pile up on this project waiting on something (the uninstall feature); it’s not good — things get outdated, a bunch of duplicates get suggested, and it becomes a mess to manage the unrelated ones from the ones on hold. I’ve also seen changes that required almost every single cask to be changed — some were solved with a few lines of code and some sed magic (changing the syntax for link), and some others required that every cask was updated by hand (when link became mandatory). Again, until a decision is made, new casks should follow the current implementation, and edits that change an already existing cask to a syntax that’s not even agreed if it will be implemented should be closed, lest we start an editing war, and wasting a lot of time from a lot of people.

These are closed without giving me a chance to amend the PR: #1359 #1360 #1364 #1363 #1354

Since @nanoxd already answered that, my question remains

When have you seen that happen?

@laurentperrinet
Copy link
Contributor

IMHO, user benefit should prime, and security is part of it: we should use checksums when possible. Having one vulnerability in any of the casks could compromise the reputation of the whole project. Having packages updated regularly is another great way to fix potential bugs, thus (in general) improving security.

Maintainers are often users who love to crowdsource their work and thanks to the workflow design, this is quite easy to achieve.

@doits
Copy link
Contributor

doits commented Feb 16, 2014

I'm maybe having a little bit different perspective as an osx server manager with a few workstation clients. I am installing apps on the server in a shared directory which clients have access to. So no need to install each app on each client. The shared directory is ro of course, because otherwise the apps could be modified by a malicious user. But this means, apps cannot autoupdate itself, either.

From this perspective it is essential that casks are updated by a brew upgrade or brew cask upgrade command and that the versioning scheme is the checksummed approach. This way, with a simple command I can update all apps on the server and do not have to go through each program to see if there's an update.

I am using homebrew cask on my local laptop, too, and even there this would be how I'd like it to be (run one command, have latest version for all apps).

It might even be an idea to have the cask directory ro for the current/local user for versioned apps. That would mean an upgrade of the app is only possible from the command line (but that is what we want - or why did we use homebrew to install the app?). This does not work well for all apps of course (latest scheme or alpha/beta apps with update every other day), but for an app like e.g. firefox, releasing an update about every 6 weeks, storing the version and checksum in the cask would be my favorite approach. If enough people use homebrew cask, there will be always someone who updates the casks when a new version arrives for popular apps.

So my vote (as a server admin and local cask user for just some few days) is:

  • versioned apps preferred over apps with latest scheme
  • checksum and download url to the version in the cask (no "latest" download url)
  • maybe even cask directory readonly, so updates must happen from cask

Btw the checksummed approach is what homebrew uses, and other similar projects (like arch aur) do and it works well for them.

@vitorgalvao
Copy link
Member

[Emphasis mine on the following quote]

It might even be an idea to have the cask directory ro for the current/local user for versioned apps. That would mean an upgrade of the app is only possible from the command line (but that is what we want - or why did we use homebrew to install the app?)

Because it’s faster, easier, and I can uninstall it just as easily later, if I so wish. Making it read-only sounds like an awful idea, to me — the amount of open issues we’d have due to repercussions on that would be staggering; not to mention the bug reports on those other apps, from users that see a prompt asking them to update, and when they try to it does not work (and have, naturally, no idea why). If apps can auto-update, why would we block that functionality without a really strong reason? We want to facilitate a process, not enforce a way of doing things.

Regarding

checksum and download url to the version in the cask (no "latest" download url)

and

Btw the checksummed approach is what homebrew uses, and other similar projects (like arch aur) do and it works well for them.

Keep in mind that will not always be possible, in our case. Different projects warrant different approaches, and it is quite common for sites of OS X apps to provide only the “latest” download option (see github’s app itself, for an example). These cases are problematic. Going back to a previous comment

having an application link to a url without a specific version, but with a checksum, will break the cask all the time — it happened before — latest has a reason for existing, and it’s a good one, it doesn’t just facilitate the work for contributors, it’s also less annoying for users.

Saying

with a simple command I can update all apps on the server and do not have to go through each program to see if there's an update

sound good in theory, but will likely not happen as you’re envisioning. As mentioned, apps that only provide the latest version will be constantly breaking and needing to be fixed.

@doits
Copy link
Contributor

doits commented Feb 16, 2014

@vitorgalvao the thing with read only was an unfinished thought as an osx server admin. I did not think much about it's possible consequences for osx, but having a strong linux background, too, where nearly all software is read only for the user (even it is the only user on the machine) and managed by a package manager, I know this can work (but is a different philosophy, of course). And that's also the way it currently works with my osx server/workstation combination, but that is only a side show for homebrew cask. So let's not focus on the ro thing for now.

But then this brings me to the question what homebrew cask wants to be: "To install, drag this icon..." no more!- it does this really well. If that's all it wants to be we don't have to change anything. But if it wants to be more like a package manager - not only help you to install things and then let you and the app alone - then a reliable update process must be found. And that is where I see the potential of homebrew casks.

That osx apps don't provide old versions to download on their homepage does not make this easy, of course. But then I'd still have a version number in the cask file with no checksum and pointing to the latest download url. When the app is updated the version number in the cask is amended to match again - and this triggers a redownload for all users that have installed it.

To summarize my proposal:

  • apps that have direct urls to each version and provide old version: checksum, link to version directly
  • apps with only the latest download url: no checksum, link to latest url
  • always a specific version in the file (no "latest" version), updated when new version of program is released

This would have the great benefit of having apps upgradable by homebrew cask with two negative points:

  • it might happen the user installs a greater version with a latest download url than written in the cask file - but there would be no error and no failed install which I understand we want to avoid as much as we can. To handle this three approaches come into my mind:
      1. Display the version number as something like >=26, which means version 26 or greater will be installed of the program (might confuse some users)
      1. Display latest to the user and only track version number internally in the cask
      1. Track the release date of a latest version in the cask file. When a new version is released on date A and the maintainer of the cask updates the cask file a week later on date B, he inserts date A into the cask file. If a user's install date of the cask is after A, there is no need to update it for the user, because he has the latest version already.
  • app might be reinstalled even if it already updated itself to the newest version (which should not harm the user other than using bandwidth). But there is nothing we can do about this if apps update themselves.

So my final proposal to handle updating of casks and whether to checksum or not is:

  • apps with direct download url to version and old versions available, use it and:
    • store direct download url to version
    • checksum
    • store version
    • display version to the user
    • update app when version number updates
    • so cask update process would be to change the url, checksum and version number
  • apps with only latest download url:
    • store latest download url
    • no checksum (or store it and a different checksum would be a hint a new version is released for the maintainer, but that should not bother the end user, of course)
    • store release date of the app version internally
    • display latest to the user
    • update app only if user's install date is before the release date
    • so cask update process would be to only change the release date

@alebcay
Copy link
Member

alebcay commented Feb 16, 2014

@doits perhaps regarding the issue of the user updating an app manually, and then the caskfile downgrading it: perhaps we can work in some way to read the Info.plist file inside the application bundles (which any well-tempered app developer should use) and determine whether or not to update the package. As an added bonus, maybe have brew-cask call home (with user permission, of course) to notify us project maintainers to update the caskfile as well. That way, packages aren't accidentally downgraded for one thing and maintaining/updating the versions in caskfiles is simplified.

@doits
Copy link
Contributor

doits commented Feb 17, 2014

@alebcay this is a good idea but cannot be handled generally for every cask, so it requires extra work per app. Thinking this one step further and to make it work for generally, one could even define a shell command in a cask file to get the latest version of an installed app. For a plist this would be something like grep ${app}/Contents/whatever.plist VersionString | awk ... or without a plist it might be ${app}/Contents/MacOS/binary --version | awk ....

This would be, of course, the best possible case: In the cask file is the latest version written (whether for latest apps or for versioned apps). On an updated cask file, homebrew cask check whether the installed app version is lower than the one in the cask file with the shell command/plist of that app and updates it if necessary.

With this, casks update process would only be distinguished by whether it is possible to detect the installed version (best case) or not. If not, one could elaborate further whether to simply always update them when a new version comes out (possibly overwriting an auto updated one) or whether to handle them like written in my last comment. But if let's say for 90 % of casks we can get the installed version, I'd leave the other 10 % simple and just overwrite it on an update to not make things overly complicated.

@doits
Copy link
Contributor

doits commented Feb 22, 2014

Just in case someone missed it: I've worked towards an automatic update mechanism in #3084 - definitely not finished (e.g. tests missing) but open for discussion. brew cask upgrade and brew cask outdated seem to work.

@indeyets
Copy link
Contributor

indeyets commented Mar 9, 2014

I tried to add versions in #3470, #3471 without reading this issue first. I came from the main homebrew, and my expectation was, that it is supposed to be that way.

After reading this issue I think that using "latest" versions is a must until upgrade mechanics is implemented, but not a tad later. A lot of "package managers" value is ability to do centralised updates.

My personal usecases are:

  1. there is a bunch of software I do not use often, but need to keep up-to-date. Automatic updates kick in only when app is already running and needing to wait for an update is undesirable.
  2. some of the applications just do not have a reliable automatic update functionality (both Calibre and DropBox fall in this category) so package manager can greatly improve status-quo

@vitorgalvao
Copy link
Member

Playing with the concept of getting an app’s version via a script, here’s an idea that could get us the best of both worlds.

The best thing here is that between the project and script mentioned on the linked comment, we already have most of the work done, it’s just a matter of tweaking things a bit and we could get up and running pretty soon.

@rolandwalker
Copy link
Contributor

Just a note to tie other conversations onto this issue.

As described in #4688 and #4678, I think we should (eventually) get to the point of minimizing 'latest' Casks for two reasons:

  1. having an upgrade verb means tracking versions
  2. it has also always been the plan to be able to install multiple versions of an app

However, there are many qualifiers on that general opinion:

  1. I am in no hurry to transition
  2. We should only transition toward versions when we have appcasts working, and other things to make the versioned Casks have an actual, tangible advantage to users over the 'latest' Casks.
  3. We will be attacking this in multiple ways. One upcoming change is adding an app stanza, and subsequently learning to read the canonical App version number from the Info.plist at any time — not just install time. If that ends up working very well, perhaps we can just finesse the issue by having runtime knowledge of the App version.
  4. There will always be some cases where 'latest' is the only sensible approach, or the only possible approach. So we will never lose it entirely. If those remaining 'latest' Casks are more difficult to upgrade, that's just a compromise we will have to accept. The perfect is the enemy of the good.

@phinze
Copy link
Contributor Author

phinze commented Feb 8, 2015

Closing this as I think the core maintainers are all on the same page. @rolandwalker's last update accurately represents the state of the union. Anybody who disagrees is welcome to chime in and we can talk about reopening. 👌

@Yann-R
Copy link

Yann-R commented Apr 5, 2015

@rolandwalker

There will always be some cases where 'latest' is the only sensible approach, or the only possible approach. So we will never lose it entirely. If those remaining 'latest' Casks are more difficult to upgrade, that's just a compromise we will have to accept. The perfect is the enemy of the good.

Do you mean that when the download URL of the binary contains no version (e.g. http://company.com/download/latest_version.dmg) we must go to unversioned formula?

I am fully aware that a set of expert contributors to homebrew-cask are already thinking of a design of automatic-update mechanism, and I thank them for their efforts that should lead to a future solution.

But meantime, brew cask install installed_formula is a very acceptable workaround for many users like me, that gives a way to get an update of all their installed software in a not so bad way (like brew cask install```brew cask list``). Nevertheless this can not work with the general use of :latest` in formulae (used by around 950 casks out of 2400).
During this meantime, from a user point of view, the proposal @doits sounded interesting:

  • apps that have direct urls to each version and provide old version: checksum, link to version directly
  • apps with only the latest download url: no checksum, link to latest url
  • always a specific version in the file (no "latest" version), updated when new version of program is released

With this proposal, current formulae with :latest as version and :no_check for the hash would switch to numbered version and :no_check.
This wouldn't break the formula that remains possible to install for any user. But it keeps also the possibility for the maintainer to trigger an update for every user who installed this software by increasing the version number in the formula.

The drawback being that the cask could be stored in a subfolder named x.y.z whereas the installed version is a newer one. If this is really a problem, a possible solution for this could be inspired from above proposals. Why not write '>= x.y.z' as version in the formula, instead of only 'x.y.z'.
This would make it possible for homebrew-cask to:

  • understand it should keep 'latest' as destination folder, but keeping the version number 'x.y.z' stored in an auxiliary file in the caskroom
  • and to take this version from the formula into account, to download the new version if it changed.

Isn't it sensible meantime, before a real update mechanism?

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests