bitwalker / distillery

Simplify deployments in Elixir with OTP releases!
MIT License
2.97k stars 398 forks source link

Release failed: no match of right hand side value: {:error, :eacces} #749

Open KoeusIss opened 1 year ago

KoeusIss commented 1 year ago

Steps to reproduce

$ mix phx.new --no-ecto phoenix_distillery
$ cd phoenix_distillery

# mix.exs
defp deps do
    [ ...,
     {:distillery, "~> 2.0"},
      ...,
    ]
  end

$ mix deps.get --only prod
$ MIX_ENV=prod mix compile
$ npm run deploy --prefix assets
$ mix phx.digest

$ mix distillery.init

$ MIX_ENV=prod mix distillery.release

Just a brief list of the steps required to produce the issue.

Verbose Logs

Paste the output of the release command you ran with the --verbose flag below in the summary tags (this helps keep the issue easy to navigate):

``` Generated phoenix_distillery app ==> Assembling release.. ==> Building release phoenix_distillery:0.1.0 using environment prod ==> Including ERTS 13.1.4 from /opt/homebrew/Cellar/erlang/25.2.2/lib/erlang/erts-13.1.4 ==> Release failed: no match of right hand side value: {:error, :eacces} ```
gazzer82 commented 1 year ago

Same problem here, did you manage to resolve it? I turned on Verbose logging and no more useful hints I can see. Release on it's own seems to work fine.

miklblitz commented 1 year ago

somewhere in the Internet i found decision:

fix error: Release failed: no match of right hand side value: {:error, :eacces}

--- a/lib/distillery/releases/assembler.ex
+++ b/lib/distillery/releases/assembler.ex
@@ -860,7 +860,7 @@ defmodule Distillery.Releases.Assembler do
# no work around for this
old_cwd = File.cwd!()
File.cd!(output_dir)
-    :ok = :release_handler.create_RELEASES('./', 'releases', '#{relfile}', [])
+    :ok = :release_handler.create_RELEASES(File.cwd!(), Path.join([File.cwd!(), 'releases']), '#{relfile}', [])
     File.cd!(old_cwd)
     :ok
     end

and it works for me (dont forget remove _build folder after fixes)

wschroeder commented 1 month ago

Explanation of the above patch, as I just went through this process and made my own version of it before I found this issue:

--- a/lib/distillery/releases/assembler.ex
+++ b/lib/distillery/releases/assembler.ex
@@ -860,7 +860,11 @@ defmodule Distillery.Releases.Assembler do
     # no work around for this
     old_cwd = File.cwd!()
     File.cd!(output_dir)
-    :ok = :release_handler.create_RELEASES('./', 'releases', '#{relfile}', [])
+    :ok = :release_handler.create_RELEASES(
+      './' |> Path.absname() |> String.to_charlist(),
+      'releases' |> Path.absname() |> String.to_charlist(),
+      '#{relfile}',
+      [])
     File.cd!(old_cwd)
     :ok
   end

It turns out that the root cause is that

:release_handler.create_RELEASES('./', 'releases', '#{relfile}', [])

ultimately resulted in a call to :release_handler's

root_dir_relative_path(Pathname) ->
    case filename:pathtype(Pathname) of
        relative ->
            filename:join(code:root_dir(), Pathname);
        _ ->
            Pathname
    end.

That code:root_dir() reaches out to the Erlang release's root directory, which makes no sense for our purposes. In one of my environments, this was a readonly /nix path. The file writing in :release_handler fails to open the missing joined path:

do_write_file(File1, Str, FileOpts) ->
    File = root_dir_relative_path(File1),
    case file:open(File, [write | FileOpts]) of
    {ok, Fd} ->
        io:put_chars(Fd, Str),
        ok = file:close(Fd);
    {error, Reason} ->
        {error, {Reason, File}}
    end.

We have to use an absolute path instead of a relative path to avoid the relative fork and reach the expected RELEASE file directory.