ExQuality.Stage (ExQuality v0.13.0)
View SourceType definitions for quality check stage results.
Each stage returns a result map with standardized fields for status, output, stats, and timing information.
Findings
A stage may also return findings, a list of ExQuality.Finding structs
parsed from its tool's output. Findings are optional: a stage that has no
parser, or whose output did not parse this run, simply omits the key.
Renderers follow one rule:
- If
findingsis non-empty, render the findings. - Otherwise, print
outputverbatim. Unparseable output is never hidden.
Metadata
A stage may also return meta, a map of extra report fields describing what
the stage did rather than what it found. The test stage uses it to say how
much of the suite it ran, because "status": "ok" over three test files and
"status": "ok" over the whole suite are different claims and a consumer has
to be able to tell them apart. Keys are merged into the stage's object in the
JSON report.
Skipped stages
A stage that was considered and not run returns a :skipped result carrying
the reason in summary, built with skipped/2. A run that says nothing about
a stage is indistinguishable from a run where the stage had nothing to say,
so silence is never an option.
Summary
Functions
Returns a result's findings, or an empty list when the stage reported none.
Returns whether a stage module reads the build or writes to it.
Builds a :skipped result for a stage that was considered and not run.
Types
@type kind() :: :reader | :writer
Whether a stage reads the build or writes to it.
The analysis phase runs its stages concurrently, which is only safe while
every one of them is a reader. A stage that recompiles the project or
rewrites files under _build invalidates the beams the others are part-way
through reading, and the reader that notices reports a failure that has
nothing to do with the code. Writers are run on their own, before the
readers, for the same reason compilation is a serialized gate.
A stage that does not say is a :reader.
@type result() :: %{ :name => String.t(), :status => :ok | :error | :skipped, :output => String.t(), :stats => stats(), :summary => String.t(), :duration_ms => non_neg_integer(), optional(:findings) => [ExQuality.Finding.t()], optional(:meta) => %{required(atom()) => term()} }
@type stats() :: %{ optional(:test_count) => non_neg_integer(), optional(:passed_count) => non_neg_integer(), optional(:failed_count) => non_neg_integer(), optional(:failures_by_app) => [{String.t(), non_neg_integer()}], optional(:coverage) => float(), optional(:coverage_by_app) => [{String.t(), float()}], optional(:coverage_required) => number(), optional(:warning_count) => non_neg_integer(), optional(:plt_built) => boolean(), optional(:issue_count) => non_neg_integer(), optional(:unused_deps) => non_neg_integer(), optional(:vulnerabilities) => non_neg_integer(), optional(:vulnerabilities_by_severity) => [{String.t(), non_neg_integer()}], optional(:files_formatted) => non_neg_integer(), optional(:missing_translations) => non_neg_integer(), optional(:fuzzy_translations) => non_neg_integer(), optional(:file_count) => non_neg_integer(), optional(:finding_count) => non_neg_integer(), optional(:blocking_count) => non_neg_integer(), optional(:informational_count) => non_neg_integer(), optional(:blocking_by_confidence) => [{String.t(), non_neg_integer()}], optional(String.t()) => term() }
Functions
@spec findings(map()) :: [ExQuality.Finding.t()]
Returns a result's findings, or an empty list when the stage reported none.
iex> ExQuality.Stage.findings(%{name: "Credo"})
[]
Returns whether a stage module reads the build or writes to it.
A module says so by exporting stage_kind/1, which is given the run's
config because a stage can be a writer only in some configurations. A module
that does not export it is a :reader, so classifying a stage is one
function on the stage that has something to declare rather than a line on
every stage that does not.
iex> ExQuality.Stage.kind(ExQuality.Stages.Credo, [])
:reader
iex> ExQuality.Stage.kind(ExQuality.Stages.Gettext, gettext: [extract: true])
:writer
Builds a :skipped result for a stage that was considered and not run.
The reason is carried in summary so renderers can say why the stage did
not run rather than leaving a gap in the output.
iex> ExQuality.Stage.skipped("Dialyzer", "--quick")
%{
name: "Dialyzer",
status: :skipped,
output: "",
stats: %{},
summary: "--quick",
duration_ms: 0
}