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

A dep installed with a higher minimum_otp_version than used currently can never be upgraded #2938

Open
baronbosse opened this issue Feb 18, 2025 · 3 comments

Comments

@baronbosse
Copy link

baronbosse commented Feb 18, 2025

How to reproduce.

  • Create a project with otp 25.
  • Add a dep with {minimum_otp_vsn, "27"}.
  • rebar3 upgrade mydep
  • get an error ===> OTP release 27 or later is required by mydep. Version in use: 25.3.2.8
  • change the dep to only requiring otp 25. {minimum_otp_vsn, "25"}.
    -rebar3 upgrade mydep

Expected behavior
mydep is updated and can now compile with otp 25

Actual behavior
mydep can't be upgraded.
===> OTP release 27 or later is required by mydep. Version in use: 25.3.2.8

@ferd
Copy link
Collaborator

ferd commented Feb 18, 2025

I don't like that feature. Your best workaround in the short term is to rely on overrides:

{overrides, [{del, [{minimum_otp_vsn, "27"}]}]}.

and then see if it works.

I don't think we can easily fix the dep check, because it gets checked at file scan time when the code runs, before any upgrade processing actually happens. A workaround based on that is something like delete the dep (unfetch it) and then do the upgrade.

@baronbosse
Copy link
Author

baronbosse commented Feb 21, 2025

So, wouldn't it be possible to automatically add an override that dels this minimum_otp_vsn on upgrade?

I can understand the min-requirement for targets like compile, ct, xref etc, but not for targets like upgrade, clean and so forth.

@ferd
Copy link
Collaborator

ferd commented Feb 21, 2025

Unfortunately, not the way things are currently structured.

Basically, the version check happens in three places:

  1. when booting rebar3 based on the current app's specification
  2. whenever an app is scanned in a discovery phase
  3. whenever an app is fetched and installed

Rebar3 tasks are all "independent", but can specify their dependencies. For example, the upgrade command specifies a dependency on lock, because there needs to be a lock file for it to be able to run an upgrade.

The lock provider itself depends on install_deps, which in turn depends on app_discovery.

So when Rebar3 is asked to run upgrade, it builds the dependency chain: app_discovery -> install_deps -> lock -> upgrade. All these tasks run independently, and it is app_discovery that does the version check, indirectly, by building a list of all applications on disk that have been fetched.

The clean task does not have dependencies. Removing the check on upgrade would probably require either making app_discovery know of subsequent calls in the dependency chain (which we do not have a way to do today), or for upgrade to reimplement the lock step in a way that scans and installs missing files without doing validation.

So basically, the reason this is messy is that the entire structure of how Rebar3 dispatches tasks makes it really difficult to special-case scenarios like this. app_discovery is relied on by almost all tasks directly or indirectly, and changing its behavior to not validate these situations implies that validation needs to be shifted to all the other tasks that currently depend on it.

The only way I can think of doing that would be to uplift the task-definition framework we use to allow passing in an option for "forced configs" at creation time, do some kind of tricky lookahead in tasks being run before they happen to force the application early and hope that it applies properly, but it could still be overridden by other intermediary tasks.

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

No branches or pull requests

2 participants