convex-pbt-cli
Safe HaskellSafe-Inferred
LanguageHaskell2010

PbtCli.Run

Description

Implementations of the pbt-cli commands.

Every command returns an ExitCode rather than calling exitWith itself, so the exit-code contract lives in one place and is testable:

  • 0 — success
  • 1 — tests failed, or nothing matched (no suites, empty tree)
  • 2 — usage error: unknown suite, or a suite that cannot do what was asked
  • 3 — discovery failed (the root is not a readable directory)
  • 4 — cabal could not be found or could not be started
  • 5 — some other I/O failure

5 exists so that 1 keeps meaning what it says. An unrelated I/O error — a write failure part-way through suites --json, an EMFILE while forking cabal — must not reach a CI consumer looking like a failing test run.

Synopsis

Documentation

execute :: Command -> IO ExitCode Source #

Dispatch a parsed command.

A missing cabal is caught here rather than per command: it is the one failure every non-static command shares, and it deserves the same message and exit code wherever it surfaces.

Selection (exposed for testing)

groupByProject :: [SuiteRef] -> [(Maybe FilePath, [SuiteRef])] Source #

Group suites by the project file that owns them, preserving first- appearance order.

Grouping is what lets one cabal test call cover a whole project's suites. Suites are named explicitly rather than using cabal's all target because cabal.project.schema-gen imports cabal.project, so all under a variant project file would re-run every suite in the repository.

selectSuites :: [SuiteRef] -> [Text] -> Either String [SuiteRef] Source #

Resolve the requested suite names against what was discovered.

An empty request means "everything", which is what makes pbt-cli run with no arguments the run-all-tests command.

Exit codes

classifyIoError :: IOException -> ExitCode Source #

Which exit code an IOException deserves.

Shared with main, which classifies a failure of its own final hFlush stdout the same way -- otherwise a write error would be reported with one code inside execute and another at shutdown.

  • A vanished resource means stdout closed under us: the consumer of a pipe stopped reading, which is what pbt-cli suites | head does. It got what it asked for, so exit quietly.
  • A missing or unreadable file is the one class that can mean cabal itself could not be started, so it keeps cabal's code.
  • Everything else gets its own code. Blaming cabal was actively misleading -- an encoding error while rendering a table used to be reported as "could not run cabal" -- but so is exit 1, which the contract reserves for a failing test run.