1
votes

I've got a custom mix task. its working perfectly, however, it is not triggering a compile when it is called like other mix tasks do. I can run the compile manually but this is very frustrating as I almost always forget to do it and have to run the task once or twice before I realize why I'm not seeing my changes.

Here is "my" task, what am i missing?

defmodule Mix.Tasks.Return do
  @moduledoc """
  Task for processing returns
  """
  use Mix.Task
  require Logger
  alias Returns

  @shortdoc "Check for returns and process"

  def run(args) do
    args
    |> get_return_file_name()
    |> Returns.process()
    |> Kernel.inspect()
    |> Logger.info()
  end

  defp get_file_name(nil), do: get_file_name([])
  defp get_file_name([]), do: get_default_file_name()
  defp get_file_name([filename]), do: filename

  defp get_default_file_name() do
    DateTime.utc_now() 
    |> DateTime.to_string()   
    |> String.split(" ")  
    |> List.first()
    |> (fn date -> "default-#{date}.txt" end).()
  end
end
2

2 Answers

3
votes

You need to explicitly say in your task that you want to compile.

@impl true
def run(args) do
  ...
  Mix.Task.run("compile")
  ...

A couple examples are app.tree, app.start and phx.routes.

This is because not all mix tasks require the compilation step. For example, mix deps.get does not compile the project before fetching dependencies, else you may have lots of errors/warnings about missing modules. All the dependencies should be called manually, there is no implicit mechanism to call chains of tasks according to some “internal rules” built into mix.

0
votes

The Mix.Task.run("compile") fix may not actually work. José Valim has this suggestion:

That's because if they are recompiled, you won't execute the new module version in memory. A work-around is for you to do this:

def run(args) do
  Mix.Task.run("compile")
  __MODULE__.compiled_run(args)
end

def compiled_run(args) do
  ...
end

That will force it to pick the latest version of the module. Although this is probably something we should tackle in Elixir itself.