ExQuality.Umbrella (ExQuality v0.13.0)

View Source

Umbrella awareness: which child apps exist, where they live, and what they declare.

An umbrella root's mix.exs usually declares no dependencies of its own, so anything that reads only the root project sees an empty list and concludes that no quality tools are installed. Every function here folds the child apps in, and answers false, %{} or nil for a single-app project, so callers never branch on the project shape themselves.

Example

ExQuality.Umbrella.apps_paths()
#=> %{web: "apps/web", core: "apps/core"}

ExQuality.Umbrella.app_for_path("apps/web/lib/user.ex")
#=> :web

Summary

Functions

Returns the dependency specs declared by each child app, keyed by app.

Returns the umbrella app a path belongs to, or nil when it belongs to none.

Returns the child apps as a map of app name to path, relative to the umbrella root.

Returns the dependency specs declared by every child app, in mix.exs form.

Drops the cached child dependencies. Intended for tests.

Returns true when the current project is an umbrella.

Functions

app_deps()

@spec app_deps() :: %{required(atom()) => [tuple()]}

Returns the dependency specs declared by each child app, keyed by app.

Use this over child_deps/0 when which app declares a dependency matters, as it does for a stage that only has something to say about the apps using a given library.

Returns an empty map for a single-app project. Shares child_deps/0's cache.

app_for_path(path, apps \\ apps_paths())

@spec app_for_path(String.t() | nil, %{required(atom()) => String.t()}) ::
  atom() | nil

Returns the umbrella app a path belongs to, or nil when it belongs to none.

Pass apps to avoid re-reading the project once per path, which is what callers tagging a list of findings should do.

iex> apps = %{web: "apps/web"}
iex> ExQuality.Umbrella.app_for_path("apps/web/lib/user.ex", apps)
:web

iex> ExQuality.Umbrella.app_for_path("lib/user.ex", %{web: "apps/web"})
nil

apps_paths()

@spec apps_paths() :: %{required(atom()) => String.t()}

Returns the child apps as a map of app name to path, relative to the umbrella root.

Returns an empty map for a single-app project.

child_deps()

@spec child_deps() :: [tuple()]

Returns the dependency specs declared by every child app, in mix.exs form.

The result is cached for the lifetime of the VM, because reading it evaluates each child's mix.exs. A child whose mix.exs cannot be evaluated contributes nothing rather than failing the run: the compile stage reports that problem with a far better message than tool detection could.

reset_cache()

@spec reset_cache() :: :ok

Drops the cached child dependencies. Intended for tests.

umbrella?()

@spec umbrella?() :: boolean()

Returns true when the current project is an umbrella.

Returns false when there is no project at all, so this is safe to call outside a Mix project.