Rewrites Mix.install dependency declarations for local testing.
This is the core feature of LivebookTest and the third stage in the pipeline:
Discovery → Exporter → **DependencyPatcher** → Runner → ReportWhy dependency patching matters
Livebook notebooks are standalone documents. They declare their
dependencies using Mix.install/2 with Hex version specifiers:
Mix.install([
{:my_lib, "~> 0.5"}
])When testing notebooks as part of a project's CI pipeline, you want
those notebooks to use the current checkout of my_lib, not the
published Hex version. This module rewrites the dependency declarations
to use local paths instead.
Modes
- Remote (
:remote) - leave the script untouched - Local (
:local) - rewrite Hex deps and existingpath:deps to stable absolute paths fromlocal_deps
How patching works
The patcher operates on the exported Elixir script (not the .livemd),
using regex-based replacement to rewrite Mix.install calls:
# Hex dep - before (remote)
Mix.install([{:my_lib, "~> 0.5"}])
# Hex dep - after (local)
Mix.install([{:my_lib, path: "/abs/path/to/project"}])
# Path dep - before
Mix.install([{:my_lib, path: Path.join(__DIR__, "..")}])
# Path dep - after (local, when my_lib is in local_deps)
Mix.install([{:my_lib, path: "/abs/path/to/project"}])
Summary
Functions
Patches an Elixir script according to the given dependency mode.
Types
@type local_deps() :: LivebookTest.Config.local_deps()
Local dependency mapping
@type patch_mode() :: :remote | :local
Patch mode matching LivebookTest.Config.dependency_mode()
Functions
@spec patch(String.t(), patch_mode(), local_deps()) :: String.t()
Patches an Elixir script according to the given dependency mode.
In :remote mode, the script is returned unchanged.
In :local mode, dependency declarations within Mix.install
are rewritten to use local paths.
Examples
iex> script = ~S|Mix.install([{:ex_arrow, "~> 0.5"}])|
iex> LivebookTest.DependencyPatcher.patch(script, :remote, [])
~S|Mix.install([{:ex_arrow, "~> 0.5"}])|
iex> script = ~S|Mix.install([{:ex_arrow, "~> 0.5"}])|
iex> patched = LivebookTest.DependencyPatcher.patch(script, :local, ex_arrow: ".")
iex> String.contains?(patched, "path:")
true