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

Implement a compatibility_version/api_version/abi_version DSL #19202

Open
1 task done
carlocab opened this issue Feb 3, 2025 · 4 comments
Open
1 task done

Implement a compatibility_version/api_version/abi_version DSL #19202

carlocab opened this issue Feb 3, 2025 · 4 comments
Labels
features New features help wanted We want help addressing this

Comments

@carlocab
Copy link
Member

carlocab commented Feb 3, 2025

Verification

Provide a detailed description of the proposed feature

Formulae should have an (optional?) compatibility_version field. Alternative suggested names for this field are api_version or abi_version.

The compatibility_version field should capture suitability for use as a dependency. In particular, if a formula has a compatibility_version of 1, then it need not be upgraded when installing or upgrading dependencies as long as dependencies are known to work with versions of the formula that have compatibility_version 1.

A crucial part of this feature involves including CI testing so that:

  1. compatibility_version is bumped whenever needed
  2. compatibility_version is not bumped when a bump is not needed

To do the above, we would likely need to run the following dependent tests (or something similar to them):

If compatibility_version is bumped, we need to check that each dependent is broken when using the previous compatibility_version, but is not broken under the newer compatibility_version.

If compatibility_version is not bumped, then we need to check that each dependent still works when using the oldest bottles that have the same compatibility_version.

What is the motivation for the feature?

This should help minimise the number of formulae that brew {install,upgrade} foo needs to upgrade to ensure that user installs are not broken.

How will the feature be relevant to at least 90% of Homebrew users?

This should help address a pain point that many users have expressed many times over the years.

What alternatives to the feature have been considered?

Doing nothing.

@carlocab carlocab added the features New features label Feb 3, 2025
@MikeMcQuaid MikeMcQuaid added the help wanted We want help addressing this label Feb 3, 2025
@MikeMcQuaid
Copy link
Member

Thanks for write-up @carlocab, this is great! Thoughts:

Formulae should have an (optional?) compatibility_version field.

Suggest "optional while we're rolling it out" and then "mandatory for anything that has a dependency on anything else" (i.e. if something has no dependancies: not required, if a dependency is added later: CI fails on the dependent add until it's added to the dependency).

For an initial value for this field: we could set it to the .dylib/.so "major" version for libraries and/or the major version for things that seem at least vaguely semver.

If compatibility_version is not bumped, then we need to check that each dependent still works when using the oldest bottles that have the same compatibility_version.

I think this logic is essentially the same way we detect "revision bumps" today: we download the bottle, we attempt brew linkage and brew test on that bottle and, if they both pass, no bump is needed.

The tricky bit is deciding if some dependencies need a bump and others don't (and also the cases where the linkage or test has bitrot into failing). Perhaps it should be something like >=50% of total dependencies needed bumped?

If compatibility_version is bumped, we need to check that each dependent is broken when using the previous compatibility_version, but is not broken under the newer compatibility_version.

This will be trickier. Might be a bit of a manual/human process here or brew test-bot outputs something at an earlier stage that ensures that e.g. a label is set in the PR and a bump is allowed?

Will want to make sure we socialise (very) hard that compatibility_version should NEVER be bumped except when brew test-bot says that it's needed.

The compatibility_version field should capture suitability for use as a dependency. In particular, if a formula has a compatibility_version of 1, then it need not be upgraded when installing or upgrading dependencies as long as dependencies are known to work with versions of the formula that have compatibility_version 1.

Note: this should be stored in the INSTALL_RECEIPT.json.

@carlocab
Copy link
Member Author

carlocab commented Feb 3, 2025

I think this logic is essentially the same way we detect "revision bumps" today: we download the bottle, we attempt brew linkage and brew test on that bottle and, if they both pass, no bump is needed.

Somewhat. The tricky part is the following. Suppose formula foo has versions 1.0, 1.1, and 1.2, and all those versions have compatibility_version 1. In our current CI setup, when we bump foo to version 1.3 but keep compatibility_version 1, we test the dependents of foo against version 1.3. However, I think we need to test dependents at least against version 1.0 as well.

The reason is that dependents may also themselves have had version bumps since we updated foo to version 1.2, so current dependents will not have otherwise been tested against foo version 1.0 unless we explicitly do so in CI.

@gromgit
Copy link
Contributor

gromgit commented Feb 3, 2025

Apologies if any of this has already been discussed in person...

Clarification:

In particular, if a formula has a compatibility_version of 1, then it need not be upgraded when installing or upgrading dependencies as long as dependencies are known to work with versions of the formula that have compatibility_version 1.

Did you mean dependents when you wrote "dependencies"?

If I understand this proposal correctly, it's a coarser-grained dependency-POV versioning alternative to the typical dependent-POV versioning common with other package management systems (e.g. depends_on "glibc" >= 2.31). In that case, I think:

If compatibility_version is bumped, we need to check that each dependent is broken when using the previous compatibility_version, but is not broken under the newer compatibility_version.

should read:

If compatibility_version is bumped, we need to check that all dependents are not broken when using the newer compatibility_version, but at least one dependent is broken under the previous compatibility_version.

since compatibility_version applies to all installations of this formula, regardless of which (different) subset of dependents each user also happens to have installed. In other words, "sorry everyone, formula X in Homebrew that uses me simply can't work with my previous version, so all of you will have to upgrade me even if you're not using X".

Also, how do security fixes factor into this scheme? These almost never change the ABI, nor do they result in major upstream revs, but if compatibility_version isn't (manually) bumped, these fixes would never be deployed for everyone until the next major rev, potentially leaving holes open for extended periods. Ascertaining the need (or not) for a bump would require knowing the why for each new rev, methinks...or a user to go "hey guys, Y version 2.35 contains critical security patches, and you've already built the bottles for it, so why does brew upgrade still leave me with 2.26?!?!"

(In that last case, and/or for users who expect and appreciate the current "always upgrade to latest" behaviour, perhaps a new brew upgrade --latest could take over this behaviour, while simple brew upgrade only upgrades the minimum required.)

@MikeMcQuaid
Copy link
Member

brew upgrade still leave me with 2.26?!?!"

brew upgrade would never leave you with the old version: it will continue to globally upgrade everything. brew install <foo> or brew upgrade <foo> might leave you with an old version of bar when foo is a dependent or dependency of bar when this is not the case. "Why did brew upgrade everything when I just wanted to install something?" is the problem this intends to fix.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
features New features help wanted We want help addressing this
Projects
None yet
Development

No branches or pull requests

3 participants