3 ms·
> If you're relying on random globals (like the path /usr/bin/egrep) to (a) exist and (b) behave in a certain way, then don't mutate them. It's a bit old now,
by thomascgalvin 4y ago
> If you're relying on random globals (like the path /usr/bin/egrep) to (a) exist and (b) behave in a certain way, then don't mutate them.
It's a bit old now, but one of the principles of Twelve Factor Applications is to vendor-in all of your dependencies.[1]
> A twelve-factor app never relies on implicit existence of system-wide packages. It declares all dependencies, completely and exactly, via a dependency declaration manifest. Furthermore, it uses a dependency isolation tool during execution to ensure that no implicit dependencies “leak in” from the surrounding system. The full and explicit dependency specification is applied uniformly to both production and development.
This scenario, with `fgrep` and `egrep` releasing a potentially breaking change, is exactly why this principle exists. If your software depends on "whatever fgrep happens to be lying around at the moment", your application might break the next time you build and deploy a new image. If you're pinned to a specific version, however, you're protected.
[1] https://12factor.net/dependencies https://12factor.net/dependencies
- mcv 4y agoYou're protected, but it also means you can never upgrade anything. An application can never know what future versions of a dependency it can work with (because a new version might contain a breaking change), so it will always require versions that existed at the time of its own creation. But those versions might contain vulnerabilities, and the new version might fix those while being fully compatible in every other way, in which case you really do want the upgrade. Those dependencies should really declare when they change existing behaviour of the previous versions, and only then should your application refuse the upgrade. No idea if there is a system that works that way; I can imagine it could get hideously complex.
- joshuacc 4y agoIsn’t that essentially semantic versioning plus version ranges ala npm?
- thomascgalvin 4y ago> You're protected, but it also means you can never upgrade anything. You're protected, and it means you have to test your system _before_ upgrading. Also, I think I'm working with a much broader definition of what "a dependency" is than you are. I consider `Alpine Linux 3.16.2` to be an atomic thing; I don't try to track the state of every single binary that comes along for the ride. But if I depend on something to be executable from my application, like `ffmpeg 5.1.2` or whatever, I _would_ version lock that, and install it myself as part of the build script. Then, when `Alpine 3.17` or `ffmpeg 5.2` comes out, I can bump to those versions, run our integration tests, and verify nothing broke.
- chriswarbo 4y ago> You're protected, but it also means you can never upgrade anything. No, it just means that: - Upgrading a dependency is a change, which should be treated like a code change (review, testing, etc.). I stated as much above. - If, for some reason, you're stuck using an old version, that only affects the relevant part of the system. For example, scripts which rely on some old behaviour can remain pinned to that version; whilst other parts of the system can use an upgraded dependency. Also, just as importantly, parts of the system which don't need something (like grep) have no access to any version of it.