Hacker News new | ask | show | jobs
by darkandbrooding 1905 days ago
There is one single feature of homebrew that regularly bites my coworkers. You can refer to software by name@version ("brew install postgresql@11" or "brew install postgresql@12") and there is no confusion about what you are installing; or you can refer to software by name only ("brew install postgresql") and the version number is calculated to be "most recently released." (v13 at the time this was written.)

Hypothetically I have two machines that I want to build out and give to developers. One machine arrives on Monday. My script runs "brew install postgresql" (no version), because of when I ran that script postgresql@10 gets installed. Tests pass, I hand that machine off to a new developer. The second machine arrives on Wednesday. I run the same script, but because v11 of postgres was added to homebrew on Tuesday, the second machine receives postgresql@11 even though the first machine received @10. Same script, two days apart, different major version of postgresql.

Yes, I can write my scripts carefully to avoid this. But consider this scenario: a new developer encounters a problem, tries to solve it themselves, finds a seemingly helpful blog, and ends up with postgresql@13 and node@15 when everyone else in their team is using postgresql@11 and node@12. Now tests are failing, but only for this one developer and only locally...

8 comments

Doesn’t apt (for instance) work the same way? Or docker images without a tag? I’d you don’t specify a version in each case then you get the latest available. I’d you want a specific version pinned then you should specify it. I think I don’t see your point, works as intended. If you enforced mandatory version specification every time, you’d have to know exactly which version is which package for anything you install: apt install Firefox > nope won’t work, instead you have to know what is today’s latest Firefox version (changes every couple of days/weeks)
It's not really how apt works but rather how Debian works: you use apt with a specific release repository of Debian (stretch, buster or whatever ISO you installed).

Debian is really strict about its releases and won't push a breaking change in a specific version of the OS.

For instance, `apt install htop` will only ever install the 2.X version of htop in Buster. Including security patches and all, but you won't get a 3.0.0 version without going sideways and add a specific repository for that. Debian will ship with htop version 3 in the next release, but you'll have to upgrade the entire distro for that.

Brew is different in that it allows anybody to merge a new breaking version of the software you use, so `brew install htop` on Monday could give you the 2.x version, and on Tuesday will install the 3.0.0 version.

You could maybe compare it to the rolling releases of Arch. But Arch has a better way of handling it than Brew: they test, they prepare, they communicate for bug changes..

Brew would benefit from segmenting their offering, but you'd lose the bleeding-edginess of it. Really, if you want reproducible packaging on Mac, I'd use nix or docker. If you want convenience and edge, use brew and deal with it.

> For instance, `apt install htop` will only ever install the 2.X version of htop in Buster. Including security patches and all, but you won't get a 3.0.0 version without going sideways and add a specific repository for that. Debian will ship with htop version 3 in the next release, but you'll have to upgrade the entire distro for that.

Debian has an official backports repository if you want that behavior. It just gives you the freedom to choose.

On most debian-based distros, most packages aren't upgraded to a new major version in the repos for a particular version of the OS. If a new version of postgres is released, it won't be added to the apt repos for the current stable debian, ubuntu, etc. distributions. Instead it will be included in the repo for the next major release of the distro.

There are exceptions to that, for example browsers like Firefox and Chromium, but upgrading the major version of Firefox is much less risky than upgrading the major version of postgresql.

Rolling release distros like Debian Sid (and archlinux, though that doesn't use apt) don't work this way, which is why rolling release distros have a reputation for being less stable.

That’s really interesting, does anyone have a book or blog post taking about this versioning and releasing strategy?

I feel like as a new dev there’s so much in engineering I could learn from that’s already been solved and re-solved again and again or at least addressed by existing distribution systems.

However the reading materials to learn about some of this stuff seems far and few or very niche, sitting on some cached blog post from the 90s..

apt generally doesn't switch you to a new incompatible version of a package unless you upgrade your whole install. Browsers are not libraries and have special status due to their importance and having security and feature updates not separated.
Why not run a docker container locally with Postgres and code against that? Then everyone is using the same Postgres version.
If the solution to homebrews handling of major versions is to not use homebrew, I think it indicates there are issues.

I think it should work like almost Linux distros where the major version is fixed for a release lifecycle, and any other installations require modification. So say brew install postgresql should always install 12, and if you want something else you have to add the version modifier.

This is a side point but the docker suggestion is far cleaner if you work on multiple apps as you can easily configure and run multiple versions with Dockerfiles and compose files to be exactly right for each app, with only the plugins the specific app needs, data stored in a custom location for each app, and the ability to turn off postgres for an app. System postgres installs and upgrades are a needles pain for development.

But I agree that's nothing to do with brew conversation.

Not just different apps but having multiple working environments for the same app - very useful when you wreck the db on a feature branch and need to jump to another to fix a bug etc.
We do this where I work and while it’s great that it solves this problem, but Docker on macOS leaves much to be desired. The situation with filesystem performance is abysmal, and if you’re unlucky, CPU usage can go through the roof even when running a few lightweight containers.
True that. I see them actively working on the issue, trying to improve the overall experience, which implies improvements, but also regressions.
That is my preferred solution and I think it works great. I have persuaded a couple of coworkers to switch, but only a couple so far.

Containerized Postgres is a real win, but running OpenLDAP (+ custom schema) as a containerized application has measurably improved my quality of life. Kudos and great gratitude to the people behind https://github.com/osixia/docker-openldap

What you want to do is maintain a tap for your organization and pin formula versions there.
I think you could also utilize 'Brewfile' with pinned versions, where needed, and the latest available for the rest. I manage my environment this way when migrating from one work laptop to another. Works fine so far.

Alternatively, you can create your own 'tap' to gain more control over some packages.

For databases, I'd stick to running them as containers, too.

Homebrew is not ideal, of course, but there are ways to achieve desired goals until we have something better.

Brew always had and always will have a rolling-release model. Pin your dependencies or don't, but you can't blame Brew for this situation.
It's actually worse than you think since the @version notation needs to be explicitly marked by the maintainer of the package.

If they don't do this then there is no easy way to install an older version of a package, you will have to get the old .rb file from the brew git history and execute it yourself.

Does apt solve that problem? If so, how?
Apt sidesteps this problem because Debian-based releases are not rolling releases. Unless you install a custom PPA, if you are running Ubuntu 18.04 and you "apt-get install postgres" you will always get version 10.x. The major version number will not get bumped for Ubuntu 18.04.

If want to use a version of postgres other than 10.x, you can either use a different version of Ubuntu or install a custom PPA.

Apt's target audience is systems administrators. Homebrew's target audience is independent developers who might need to have four different versions of Postgresql installed simultaneously on their laptop, because they maintain Rails/Django/Node apps for four different clients who are each unwilling to upgrade for whatever reason.

IMO homebrew is "messy" because it is trying to solve a harder problem. If there is such a thing as an average enterprise software developer, I would argue that homebrew is trying to solve problems that the enterprise developer does not have.

Homebrew is like running Debian unstable, the world underneath you is currently changing.

Mac OS itself doesn’t really have this problem since applications can bundle the exact version of their required frameworks, a bit like Ubuntu Snaps.

This doesn't really answer the question does it?

It's been a while since I used apt, but if I remember correctly you'd have the same problem the parent described, right?

-------------------

And regarding the 'name@version' criticism: If you want to stick to a version, how can you do it without specifying it?

For example Ubuntu X.Y LTS always use a pinner version of Apache 2.xxx and it will remain that version throughout that LTS release, such as 18.04. what they do for you is apply security patches and bump Apache 2.xxx.Y where Y is the security release applied patch. Apache stays at 2.xxx for the duration of that LTS and is considered the Stable version. Want something newer like Apache 3.x install from a PPA or an all-in-one bundled Snap package...
> It's been a while since I used apt, but if I remember correctly you'd have the same problem the parent described, right?

Only if you are running Debian Sid or equivalent.

Except dpgk/apt is pretty good about keeping track of what libraries are being used. I've had homebrew upgrade readline to the next major version, uninstalling the version that all my other utilities were linked against. Admittedly, this was years ago and I don't know if that still happens; the experienced has soured me on homebrew and I actively avoid having to run the brew command and risking the same again.
"brew upgrade" caused no end of troubles. Let's just upgrade everything to the next major version(MySQL 5.6 -> 5.7).

Tests failing.

I found it much worse that installing anything STILL by defaults upgrades literally everything. You have to actually set an ENV variable to stop this behaviour. My stuff constantly broke because I'd forget about this and install something else and a couple days later I'd go "what happened??"
I don't think brew does this? What it does do is update its package definitions automatically.
It was doing this until recently when I set the env variable. It updates itself every time and then updates everything else too. Maybe I did something wrong to trigger this behaviour but it was definitely updating the packages
I've seen the exact same behavior. I didn't realize it was behind an environment variable. I passed a package to the command and for the next week I was dealing with issues from everything being upgraded.
Why would you run brew upgrade if you don't want to upgrade packages? I don't understand.
You'd expect MySQL 5.6.8 to upgrade to 5.6.12, not to 5.7...