AuroraMeter.Install.Support (Aurora Meter v1.0.0)

View Source

What this host resolves, against what Aurora Meter says it supports.

mix aurora_meter.install --check-support prints this and exits non-zero when something present is below its floor. It is deliberately a plain module with no Igniter and no database in it, so the same answer is available from a release command, from iex, and from the installer's Igniter-less fallback.

It never connects to anything

Every row is read from the running system or from the host's own configuration. Nothing here opens a database connection, and that is why the Postgres row says what it says: a server version can only be learned by asking the server, and an installer that connects to a host's database to tell it about compatibility has done something the host did not ask for. The floor is printed; the check is the host's to run.

Summary

Types

How a row learns what is installed: {resolved version or nil, guarded module compiled?} for one dependency. Replaced in tests so both branches of the stale-build check run through the real row code.

One row of the report.

Functions

The dependency floors this package declares, as {app, floor, requirement}.

The declared floor for one dependency, or nil when this package does not declare it.

Whether mix aurora_meter.install --oban can be honoured on this host, and what to tell the host when it cannot.

One line naming every row that is a problem, for the message an aborting --check-support raises with.

The report as text, one line per row, with a verdict column.

Every row of the support report, in print order.

Whether anything present is below its floor or half installed.

Types

probe()

@type probe() :: (atom(), module() | nil -> {String.t() | nil, boolean()})

How a row learns what is installed: {resolved version or nil, guarded module compiled?} for one dependency. Replaced in tests so both branches of the stale-build check run through the real row code.

row()

@type row() :: %{
  name: String.t(),
  resolved: String.t() | nil,
  floor: String.t(),
  verdict: :ok | :below_floor | :absent | :unknown | :stale_build,
  note: String.t() | nil
}

One row of the report.

Functions

declared_deps()

@spec declared_deps() :: [{atom(), String.t(), :required | :optional}]

The dependency floors this package declares, as {app, floor, requirement}.

Public so that a test can compare them against mix.exs rather than against a comment.

floor_for(app)

@spec floor_for(atom()) :: String.t() | nil

The declared floor for one dependency, or nil when this package does not declare it.

For a message that has to name a version. A refusal that tells a host to add a dependency and invents the version it asks for is a refusal that will be wrong one release from now, so the number comes from the same table --check-support prints (repair unit R5).

oban_switch(arg1, arg2)

@spec oban_switch(boolean(), boolean()) :: :ok | {:error, String.t()}

Whether mix aurora_meter.install --oban can be honoured on this host, and what to tell the host when it cannot.

Takes the two answers rather than asking for them. oban is in this package's own lockfile, so Code.ensure_loaded?(Oban) is true in every test this suite will ever run, and a check that asked for itself could not be exercised from here at all. That is the whole reason the switch raised UndefinedFunctionError in a host without Oban through a unit whose subject was the installer (open-findings.md X375, repair unit R5).

The second argument distinguishes the two states that look the same from a host's side and need opposite answers: no Oban at all, and Oban added after aurora_meter was compiled. The second is the :stale_build verdict rows/1 already reports, and the same one line fixes it.

problem_summary(rows \\ rows())

@spec problem_summary([row()]) :: String.t()

One line naming every row that is a problem, for the message an aborting --check-support raises with.

Separate from report/1 because the report is what a supported host reads and this is what an unsupported one has to act on.

report(rows \\ rows())

@spec report([row()]) :: String.t()

The report as text, one line per row, with a verdict column.

rows(opts \\ [])

@spec rows(keyword()) :: [row()]

Every row of the support report, in print order.

:probe replaces how a dependency row learns what is installed. It exists so that the stale-build branch below can be induced and run rather than reasoned about; hosts never pass it.

supported?(rows \\ rows())

@spec supported?([row()]) :: boolean()

Whether anything present is below its floor or half installed.

An absent optional dependency is not a failure: that is the whole point of it being optional (invariant I20). A present one whose integration was not compiled is a failure, because the host has asked for something it is not getting and nothing else will tell it so.