     |> do_call_action(fun, args)
   end
 
-  @spec do_call_action([t()], atom(), [term()]) :: Result.t()
-  defp do_call_action(plugins, fun, args)
+  @spec do_call_action([{integer(), t()}], atom(), [term()]) :: Result.t()
+  defp do_call_action(arity_and_plugins, fun, args)
   defp do_call_action([], _fun, _args), do: :ok
 
-  defp do_call_action([plugin | plugins], fun, args) do
-    case apply(plugin.module, fun, args) do
+  defp do_call_action([{arity, plugin} | arity_and_plugins], fun, args) do
+    new_args = update_callback_args(args, plugin, fun, arity)
+
+    case apply(plugin.module, fun, new_args) do
       :ok ->
-        do_call_action(plugins, fun, args)
+        do_call_action(arity_and_plugins, fun, args)
 
       {:error, _} = error ->
         error

    end
  rescue
    exception -> handle_exception(exception, plugin.module, fun)
  end

  @spec handle_exception(Exception.t(), atom(), atom()) :: Result.t()

  @type spec :: atom() | {atom(), plugin_options()}
  @type plugin_options :: [only: atom() | [atom()], args: term()]

  @old_callback_arities [
    build_started: 2,
    reading_pages: 1,
    reading_posts: 1,
    reading_templates: 1,
    processing_page: 1,
    processing_post: 1,
    processing_template: 1,
    processed_page: 1,
    processed_post: 1,
    processed_template: 1,
    processed_list: 1,
    processed_pages: 1,
    processed_posts: 1,
    rendering_fragment: 2,
    rendered_fragment: 1,
    rendered_page: 1,
    wrote_file: 1,
    build_succeeded: 2,
    build_failed: 3,
    finalizing: 2
  ]

  @optional_callbacks @old_callback_arities
                      |> Enum.map(fn {name, arity} ->
                        [{name, arity}, {name, arity + 1}]
                      end)
