Default versions and pkg (slight rant)

From: Dan Mahoney <freebsd_at_gushi.org>
Date: Sun, 09 Oct 2022 19:18:22 UTC
Hey there all,

I recently asked about default versions in pkg, and if it was possible to tell a pkg (without building it yourself) "no, don't conflict with that", for example to point bind-tools916 at python3.9, because it's just a shebang line.  That thread went a lot of places, but only served to expose an underlying problem.

In asking those questions, I was trying to learm more about the DEFAULTS changes, and how we can mitigate them, because every time one changes, there's pain.

This stems from a healthy culture of having pkg bite me during what should be a routine thing.

Here's a few examples where we've been burned:

* As recently mentioned, we had two versions of python installed on a system, and removing python3.8 attempted to remove bind-tools, which in turn would have wanted to deinstall bind9.  A more recent bind-tools didn't require python at all -- but that upgrade path wasn't suggested as part of it.  Pkg remove only attempts to remove things, not fix a running system.  Pkg doesn't have any option to keep leaf packages installed at all cost.  Nor does it fire the solver when doing a pkg remove.

* We run RT, against PostgreSQL.  We installed p5-DBD-Pg (which is not a direct dependency), During a routine pkg upgrade, because of a default version change, p5-DBD-Pg forced an upgrade from postgresql12-client to postgresql13-client.  It did not, however, cause an upgrade to postgresql13-server, it only caused postgresql12-server to be removed because it conflicted with postgresql13-client.  The ultimate fix here was a full dump and restore to get from pg12 to pg13, which took hours.

* On a recent upgrade where ruby30 became the default, we were left with a puppet6 install that had no ruby interpreter it could run with.  The puppet6 port is marked as broken (because it doesn't work with ruby30), but pkg didn't deinstall it, threw no warnings about it, because its listed as having ruby30 as a dependency, as opposed to a lower ruby.  The solution was "Well, I guess we're upgrading to puppetserver 7 tonight, hope there's no fallout from that".  Luckily, our manifests are really solid, but in the older days of puppet, there were a lot of breaking changes.

In all three of the cases, the old no-longer-default dependencies were still in the tree to be pkg installed.  In all three cases, pulling down a ports tree and editing make.conf to point at the old version might have been a reasonable solution, that wouldn't have carried forward with someone who just wants to be able to pkg upgrade their stuff, and it would have required building some major packages from scratch (in all three of the above, it would have resulted in building a language -- python, perl, and ruby, respectively).

Here's what I'm asking:

* Most of this could be solved by reading /usr/ports/UPDATING.  However, as someone who wants to trust the maintainers, and just use the packages, is there a way to see "Updating" without pulling down a ports tree?  You've baked a "pkg" command in to read it, but that's half the work.  (Perhaps, maybe, just make /usr/local/share/doc/pkg/UPDATING, itself a pkg that can be updated)?  Maybe, on-upgrade, print those things out as part of the process -- i.e. if the date on the UPDATING entry is sometime between now and when my pkg was installed...just print a "Hey, some warnings exist, you might want to read this, display [Y/n]".

* In the special case of puppetserver6, if the thing is broken because it doesn't work with ruby, why not list the old ruby as a dependency?  I'm fairly certain in that case that multiple rubies could have coexisted.  (FWIW, it looks like puppet6 will probably never work with 3.0 per https://tickets.puppetlabs.com/browse/PUP-10957 <https://tickets.puppetlabs.com/browse/PUP-10957>).  Nobody made it a flavored port that could also work against ruby2.7.  The "upgrade" list didn't show that it would be upgraded/touched/deleted, so one was left to assume that it would "just work".  There should have been some way for the repo to have listed the broken version and warned me about it.  "Hi, this configuration WILL NOT WORK".

* Finally, some option to, when removing a dependency package, make the solver smarter in some way?  I know that's vague, but all the info to say "your currently installed version will be deleted if you remove this, but the following version would cause that to not happen" is present in the repo, it's just not clearly presented to the user.

-Dan