defmodule Edeliver.Relup.Modification do
@moduledoc """
This behaviour can be used to provide custom modifications of
relup instructions
when a release upgrade is built by edeliver.
By default the implementation from `Edeliver.Relup.PhoenixModification` is used
for phoenix applications and for all others the implementation from
`Edeliver.Relup.DefaultModification`.
Implementations can modify the relup instructions step by step by using
modules implementing the `Edeliver.Relup.Instruction` behaviour.
The implementation returning the highest `priority/0` or which is passed by the
`--relup-mod=` command line option will be used unless the `--skip-relup-mod`
option is set.
Example:
defmodule Acme.Relup.Modification do
use Edeliver.Relup.Modification
def modify_relup(instructions = %Instructions{}, config = %{}) do
instructions |> Edeliver.Relup.DefaultModification.modify_relup(config) # use default modifications
|> log_upgrade # add custom modification which logs the upgrade
end
defp log_upgrade(instructions = %Instructions{up_instructions: up_instructions}) do
log_instruction = {apply, {:Elixir.Logger, info, [<<"Upgraded successfully">>]}}
%{instructions| up_instructions: [log_instruction|up_instructions]}
end
end
"""
@doc """
Modifies the relup instructions and returns the modified instruction
"""
@callback modify_relup(Edeliver.Relup.Instructions.t, Edeliver.Relup.Config.t) :: Edeliver.Relup.Instructions.t
@doc """
Default priority for builtin relup modifications
"""
@spec priority_default :: 1
def priority_default, do: 1
@doc """
Default priority for user defined relup modificaitons
"""
@spec priority_user :: 1000
def priority_user, do: 1_000
@doc """
Priority lower as the default priority which can be used temporarily to
disable user defined relup modifications and use the defaults
"""
@spec priority_none :: 0
def priority_none, do: 0
@doc false
defmacro __using__(_opts) do
quote do
@behaviour Edeliver.Relup.Modification
alias Edeliver.Relup.Instructions
import Edeliver.Relup.Modification, only: [priority_default: 0, priority_user: 0, priority_none: 0]
Module.register_attribute __MODULE__, :name, accumulate: false, persist: true
Module.register_attribute __MODULE__, :moduledoc, accumulate: false, persist: true
Module.register_attribute __MODULE__, :shortdoc, accumulate: false, persist: true
@doc """
Returns the priority of this modification. Unless the module is set by the
`RELUP_MODIFICATION_MODULE` env or the `--relup-mod=` command line option
the module with the highest priority is used (which is also usable).
"""
@spec priority() :: non_neg_integer
def priority, do: priority_user()
@doc """
Returns true if this relup modification is usable for the project or not.
E.g. the `Edeliver.Relup.PhoenixModifcation` returns true only if the
project is a phoenix project. This function returns `true` by default
can be overridden in a custom `Edeliver.Relup.Modification` behaviour
implementation.
"""
@spec usable?(Edeliver.Relup.Config.t) :: boolean
def usable?(_config = %{}), do: true
defoverridable [priority: 0, usable?: 1]
end
end
end