-
Notifications
You must be signed in to change notification settings - Fork 521
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
support for optional_applications #2473
Comments
Optional dependencies is a run-time constraint, not a compile time one, so the thing here is that we should still fetch and build them, but we might just not yell if they're not found when it comes to assembling releases or starting a project, as far as I can tell. |
The app file additional is a runtime constraint, doesn't mean we can't provide compile time features around it. It probably isn't worth it so I'm fine leaving it as is. Though probably worth it add support for non-hex deps to not fetch optional deps, but leaving it so when working on the application itself all deps are fetched. |
Added in latest release. |
In my opinion there is some release handling needed for https://erlangforums.com/t/erlang-otp-27-0-rc1-released/3300 |
I think it could be useful to be able to specify three different types of 'release' specification:
The way the code is structured, rebar_relx.erl seems like the best place to do this. |
Isn't that handled with P.S. The problem is that it's not really clear what optional dependencies actually are. They can be not so optional from time to time - when a missing application causes root application to error/exit is it optional or not? |
So far they've been considered optional in that we're always attempting to include them, but it's not an error if they can't be found or if the release specifies they should not be brought in. One could easily not make it an error by simply excluding them from the relx config, as @MarkoMin points out. You could, for example, have a default release like:
and then make an extra profile like:
and every build by default ( |
Well, compare to embedded code loading: What one typically wants, apart from (in that case) avoiding incurring the cost of on-demand code loading, is the assurance that the system doesn't work accidentally due to specifics of the environment, only to later fail on another, where some local modules aren't picked up due to local paths and on-demand code loading. In this particular case, that's exactly what happened when testing the Aeternity code base on OTP 27. It failed because on the machine being tested, Obviously, there also wasn't any In such cases, it would be much better to have the build fail early. But I could have also clarified that the default behavior could remain as today, just as on-demand code loading is the default when starting Erlang. |
Yeah I could imagine (It wouldn't cover the case of third party libs suddenly incorporating more entries, which still get to be part of supply-chain checks for corporate entities, but would help for truly optional things). The gotcha here though is that this would be a setting easiest to add for releases; doing it for tests, dialyzer, xref, and dependency fetching would be significantly more complex, and I'm not quite sure at which level "not fetching in optional deps" would be most "correct". I can easily imagine it being the case for tests (when calling to boot dependent apps) also being a pain, but being much trickier to support well (based on messing around with the lock file when switching from desired to undesired for example, or also calls within OTP like |
A way to selectively include some optional applications under that setting would then be to specifically include them in the ´release´ apps list. |
I definitely agree, but it seems that your system was accidentally working before OTP27.
Under what code path? Rebar sets the code path to
It would fit nicely with
If you want to test your app without some apps, can't you do it in a profile that redefines
exactly |
Not if a transitive dep of a critical one includes the optional one in its own deps list or lock file, because then the app is already not in your config. You'd need something weirder like use |
For |
They could be separate applications I guess, but that's a separate problem. Try to reach OTP team, but I don't know if they'll fit it in OTP27 |
I just peeked over source and indeed, that would be a lot of work to support Example of how this might work: %%rebar.config
{profile,
[{minimal, [{app_discovery, [{include_optional_applications, false}, {include_apps, [wx]}]
]
]}. and then you could run |
Yeah, although part of the challenge there is that knowing what is optional or not requires evaluating the .app file, and this file can be changed up to final compilation steps under the current model, so even unwinding that can be quite tricky (see #2864 for example, opened this week, about hooks running after compilation modifying the app files and wanting to support that when building releases) I don't know for sure that we could support this without making it a breaking change that reevaluates how we interleave build steps far more aggressively. We're sort of caught by having picked a model that didn't care for this feature at first (because it didn't exist). |
A less brutal change could be to be to hook ourselves into I'm not exactly sure how it could be invoked, but it could look and test things properly for code analysis that depends on the path. Unfortunately, this doesn't involve relx, which builds releases without needing to load the apps and has its own resolution mechanism. Also on another note: the |
The same reasoning can then be used for |
What I think is or isn't valid cases turns out to not be really relevant to how people use this tool :/ Three quarters of the work is figuring out how to make shit work for use cases you never thought would make much sense but that someone has a really good edge case for sometimes. |
My understanding is that an optional application must not be started (and I would say not even included in the release) unless someone else depends on it as a non-optional application. Here is what the docs say:
if you automatically bring optional applications into a release, and therefore start them, one could argue they won’t match the behavior above? Optional applications are to enforce order, but not a requirement. |
Including them in a release != starting them (although if I remember correctly there was a bug case where optional apps got started even though they weren't listed in any |
Thank you. Not starting them definitely helps. So one last questions: what about Hex packages? If I have a dependency as optional on Hex, do you download it? Even if somebody does not depend on it? If the answer is no, it means optional hex packages are not even included in releases. Why would optional deps from OTP be included? If the answer is yes, should you download packages that are optional? Then what is the difference then between optional and included? |
If you have that dependency in your Naming is really unfortunate here and I dont like that mechanism, but it currently works. I remember being confused by it when I started doing Erlang and I still am. What we're lacking is "include an application, but don't start it" mechanism (we're currently using
Yes, because they are not exactly optional (cuz of the abuse). |
We could require optional applications be listed in the list of release applications in order to be included in the release. So, from the first example in this thread, instead of using
Yes wx:
|
In theory yes, in practice it's a tradeoff (again, because of the abuse above) - do you want sane releases ( |
@MarkoMin curiosity: why would @tsloughter's suggestion fail the sanity check? |
Example:
Why 5.? Because |
I'd say that's par for the course for optional dependencies. If I have an optional dependency, certain functionality won't be available, and it will raise at runtime unless the dependency is available. I believe Rust also behaves similarly with its optional dependencies via features, where whole modules or functions become undefined. I guess the big question is if you expect it to fail or not? You are arguing that someone could be surprised that |
Yes, but when runtime error occurs it can be significantly hard to tell what part of the system is missing! Ideally, you'll get Removing optional apps from the release is more or less just an optimization - it's up to the user to conclude whether it is safe to do it. |
Support for
optional_applications
will be merged into OTP soon: erlang/otp#2675I have opened an issue for supporting this in the hex plugin, erlef/rebar3_hex#195
I'm not actually sure if we need to do anything in rebar3 to support this because of how we resolve dependencies -- unlike mix where the optional deps version constraint is taken into account when deciding what version to pull of a dep.
I suppose one issue is if the user doesn't want to list all the optional deps in the project's default profile. If that were the case we'd be basing the optional deps published to hex solely on the
optional_applications
list which wouldn't have a version constraint (not that it matters I guess) or place to put the hex package name if it differs from the application name...Another case is if the project is pulled in as a git dependency. Does it then simply fetch all the deps, even those that are technically optional at runtime?
The text was updated successfully, but these errors were encountered: