defmodule GitHooks.Tasks.Mix do
@moduledoc """
Represents a Mix task that will be executed as a git hook task.
A mix task should be configured as `{:mix_task, task_name, task_args}`,
being `task_args` an optional configuration. See `#{__MODULE__}.new/1` for
more information.
For example:
```elixir
config :git_hooks,
hooks: [
pre_commit: [
{:mix_task, :test},
{:mix_task, :format, ["--dry-run"]}
]
]
```
See `https://hexdocs.pm/mix/Mix.Task.html#run/2` for reference.
"""
defstruct [:task, args: [], result: nil]
@typedoc """
Represents a Mix task.
"""
@type t :: %__MODULE__{
task: Mix.Task.task_name(),
args: [any]
}
@doc """
Creates a new Mix task struct.
This function expects a tuple or triple with `:mix_task`, the task name and
the task args.
### Examples
iex> #{__MODULE__}.new({:mix_task, :test, ["--failed"]})
%#{__MODULE__}{task: :test, args: ["--failed"]}
"""
@spec new({:mix_task, Mix.Task.task_name(), [any]} | Mix.Task.task_name()) :: __MODULE__.t()
def new({:mix_task, task, args}) do
%__MODULE__{
task: task,
args: args
}
end
end
defimpl GitHooks.Task, for: GitHooks.Tasks.Mix do
alias GitHooks.Tasks.Mix, as: MixTask
alias GitHooks.Printer
def run(%MixTask{task: :test, args: args} = mix_task, _opts) do
args = ["test" | args] ++ ["--color"]
{_, result} =
System.cmd(
"mix",
args,
into: IO.stream(:stdio, :line)
)
Map.put(mix_task, :result, result)
end
def run(%MixTask{task: task, args: args} = mix_task, _opts) do
result = Mix.Task.run(task, args)
Map.put(mix_task, :result, result)
end
# Mix tasks always raise an error if they are not success, at the moment does
# not seems that handling the result is needed. Also, handling the result to
# check the success of a task is almost impossible, as it will depend on each
# implementation.
#
# XXX Since tests runs on the command, if they fail then this task is
# considered failed.
def success?(%MixTask{result: 1}), do: false
def success?(%MixTask{result: _}), do: true
def print_result(%MixTask{task: task, result: 1} = mix_task) do
Printer.error("`#{task}` failed")
mix_task
end
def print_result(%MixTask{task: task, result: _} = mix_task) do
Printer.success("`#{task}` was successful")
mix_task
end
end