HashNuke / heroku-buildpack-elixir

Heroku Buildpack for Elixir with nitro boost
MIT License
810 stars 304 forks source link

use MIX_HOME,HEX_HOME when installing mix/hex dependencies #203

Closed fivetanley closed 3 years ago

fivetanley commented 3 years ago

tl;dr:

By using MIX_HOME and HEX_HOME, we can consolidate some logic for transferring mix/hex files in and out of the cache and app build directory.

This should allow the buildpack to work in the new build system and the old build system since this buildpack no longer relies on what the value of HOME is at either build time or runtime.

fixes #194

https://github.com/HashNuke/heroku-buildpack-elixir/issues/194

The Longer Explanation

This strategy was taken from the heroku-buildpack-ruby buildpack, which sets GEM_HOME and GEM_PATH environment variables as well as the BUNDLE_PATH environment variable to a path in the BUILD_DIR argument when running the bundle install command.

Although the Elixir programming langauge and buildpack doesn't use Bundler/Rubygems, it has similar patterns for setting the installation directory and archive paths for Mix and Hex.

MIX_HOME has been supported since v0.7.0 of Elixir (support for MIX_HOME added ~9 years ago).

Note: There is a MIX_ARCHIVES env variable that Mix can use, but MIX_ARCHIVES support was added in version 0.14.7. I'm not sure if anyone is still using this Elixir version (they should upgrade as the OTP that 0.14.7 supports is very outdated and doesn't receive security updates). If MIX_ARCHIVES is not present, then Mix will put archives in $MIX_HOME/archives. In order to keep compatibility as close as possible, this commit continues using the old strategy of backing up everything in MIX_HOME, rather than what's in MIX_ARCHIVES alone.

HEX_HOME support was added in Hex v0.3.3. This was the commit that made Hex put stuff in $HEX_HOME directory, meaning that support for HEX_HOME has existed for a long time and we should be able to rely on Hex using the HEX_HOME directory. The old strategy used by the Elixir buildpack always backed up the default HEX_HOME value ($HOME/.hex).

fivetanley commented 3 years ago

@edmorley I've tested this on Heroku CI, Heroku-20 (old build system), and Heroku-20 (new build system). Can you take a peak and let me know what you think? I think i addressed your feedback from the reverted PR, but let me know if I missed something or misunderstood.

fivetanley commented 3 years ago

@HashNuke @jesseshieh any thoughts on this approach?

jesseshieh commented 3 years ago

At first glance, it looks great to me. Sorry, I was waiting for @edmorley to comment first. As long as it's tested to work on both the old system and the new system, and @edmorley is happy with it, then I'm happy with it.

jesseshieh commented 3 years ago

I just tried testing this and although this buildpack still works on it's own, when paired with the phoenix buildpack, I get this error.

       Could not find Hex, which is needed to build dependency :phoenix
       Shall I install Hex? (if running non-interactively, use "mix local.hex --force") [Yn] ** (Mix) Could not find an SCM for dependency :phoenix from Foo.MixProject

I'm guessing the phoenix buildpack is looking for hex in the wrong place. Is there a way to keep this buildpack backward compatible so the phoenix buildpack still works as-is?

edmorley commented 3 years ago

Yeah that's likely due to: https://github.com/HashNuke/heroku-buildpack-elixir/pull/203#discussion_r662209951

fivetanley commented 3 years ago

@jesseshieh I've updated this PR to copy the Hex/Mix/Elixir directories as well as the erlang directory to the runtime path if the runtime path and buildtime path don't match. I tried this with an application with the phoenix buildpack (thanks for that detail! our app doesn't happen to use the phoenix buildpack since we don't use static assets) and it seems to work. Can you please give this PR another try when you have a moment? Thanks!

jesseshieh commented 3 years ago

Looks great and thank you so much for doing this!