Elixir: mix run does not resolve path correctly when called via mix test from umbrella root

Created on 2 Nov 2018  路  3Comments  路  Source: elixir-lang/elixir

When an app in umbrella app has alias on test with run somefile.exs, which refers relative path to the app (not to the umbrella root), it works only when running mix test at the app root - not at the umbrella root.

Under apps/inside_app/mix.exs:

  def aliases()
    test: ["cmd ./shell.sh", "run script.exs", "test"]
  end

Here is a script to reproduce it

#!/bin/bash -eux
rm -rf umbrella

mix new --umbrella umbrella

pushd umbrella/apps
  mix new inside
popd

pushd umbrella/apps/inside
  echo "echo 'hello from cmd'" > hello.sh
  chmod +x hello.sh

  echo 'IO.puts("hello from run")' > hello.exs
  gsed -i -E 's/^      deps: deps\(\)$/      deps: deps(),\n      aliases: aliases()/' mix.exs
  gsed -i -E 's/^end/  defp aliases, do: [test: ["cmd .\/hello.sh", "run hello.exs", "test"]]\nend/' mix.exs

  mix test
popd

pushd umbrella
  mix test
popd

Note that this happens from a umbrella phoenix project since the main app (with ecto) has following aliases:

  defp aliases do
    [
      "ecto.setup": ["ecto.create", "ecto.migrate", "run priv/repo/seeds.exs"],
      "ecto.reset": ["ecto.drop", "ecto.setup"],
      test: ["ecto.create --quiet", "ecto.migrate", "test"]
    ]
  end

Environment

  • Erlang/OTP 21 [erts-10.1.1] [source] [64-bit] [smp:8:8] [ds:8:8:10] [async-threads:1] [hipe]
  • Elixir 1.7.4 (compiled with Erlang/OTP 21)
  • Operating system: Mac

Current behavior

  • Running mix test at umbrella root: cmd works but run fails with ** (Mix) No such file: script.exs
  • Running mix test at the app: both cmd and run works

Please note that "cmd ./shell.sh" is correctly expanded.

Expected behavior

  • Running mix test should work with expanding alias, as it runs at the app root.
Mix Bug Unresolved

Most helpful comment

Hi @chulkilee!

I have actually investigated this about a week ago but I forgot to report back.

This is behaving as expected because the run task always runs at the project that invoked mix. So if you are inside the umbrella, it is the umbrella, if you are a child app, it is the child app. A possible fix for this is to pass the full path:

"mix run #{Path.join(__DIR__, "priv/foo/bar.exs")}"

I have explored some solutions but I don't think we will be able to fix this in any other way without intervention, sorry.

All 3 comments

Thanks @chulkilee! It would be awesome if you could provide a small application that reproduces this, as it would make our life easier.

I added a script in the body @josevalim

Hi @chulkilee!

I have actually investigated this about a week ago but I forgot to report back.

This is behaving as expected because the run task always runs at the project that invoked mix. So if you are inside the umbrella, it is the umbrella, if you are a child app, it is the child app. A possible fix for this is to pass the full path:

"mix run #{Path.join(__DIR__, "priv/foo/bar.exs")}"

I have explored some solutions but I don't think we will be able to fix this in any other way without intervention, sorry.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

alexrp picture alexrp  路  4Comments

ericmj picture ericmj  路  3Comments

eproxus picture eproxus  路  3Comments

GianFF picture GianFF  路  3Comments

josevalim picture josevalim  路  3Comments