Class RegressionGateRunner

java.lang.Object
dev.dokimos.core.gate.RegressionGateRunner

public final class RegressionGateRunner extends Object
The run lifecycle around RegressionGate: resolves whether to update, bootstrap, or compare a baseline, performs the file I/O, and turns a FAIL verdict into an AssertionError.

RegressionGate.evaluate(dev.dokimos.core.ExperimentResult, dev.dokimos.core.gate.BaselineFile, dev.dokimos.core.gate.GateConfig) produces the verdict; this layer adds the side effects that Assertions.assertNoRegression(dev.dokimos.core.ExperimentResult) delegates to. Everything that reads the outside world — CI detection, the update-requested flag, the verdict-output directory, the log sink — is injected through RegressionGateRunner.Environment, so callers and tests can supply their own without touching real environment variables or the source tree.

The throw decision is identical in CI and locally: a FAIL verdict throws on every runner, so a failing mvn test (or Gradle, GitLab, Jenkins) is the gate without any CI-specific wiring. RegressionGateRunner.Environment.ci() is consulted in exactly one place — suppressing the bootstrap write when no baseline exists, because a CI checkout is ephemeral and the write would be lost.

  • Method Details

    • run

      public static GateVerdict run(ExperimentResult candidate, Path baseline, GateConfig config, RegressionGateRunner.Environment env)
      Runs the gate lifecycle for one candidate against one baseline path.

      Branch order (first match wins):

      1. Updateconfig.updateBaseline() or env.updateRequested(): overwrite the baseline from the candidate and pass. No comparison ran, so no verdict JSON is written.
      2. No baseline, CI: do not write a baseline (the checkout is ephemeral); emit a NO_BASELINE verdict and the loud banner, write the verdict JSON, and pass.
      3. No baseline, local: write the baseline from the candidate. Pass when config.bootstrapPasses() (the default, so the new file lands in the PR diff for review); otherwise throw once so the new file is reviewed and committed before it counts.
      4. Compare: read the baseline, evaluate, always write the verdict JSON, then throw on a FAIL verdict.
      Parameters:
      candidate - the candidate experiment result
      baseline - the baseline file path (already resolved; this layer applies no path convention)
      config - the gate configuration
      env - the injected environment
      Returns:
      the verdict; the update and bootstrap paths return a NO_BASELINE verdict (no comparison ran), which the void assertion API discards
      Throws:
      AssertionError - on a FAIL verdict, and on a local missing baseline unless config.bootstrapPasses()
      UncheckedIOException - if the baseline itself cannot be written or read (a real gate error, unlike the best-effort verdict-JSON write)
    • systemEnvironment

      public static RegressionGateRunner.Environment systemEnvironment()
      Returns the production environment: CI from CI/GITHUB_ACTIONS, the update flag from GateConfig.updateBaselineRequested(), the verdict directory at target/dokimos, and the log sink routed to this class's logger.
      Returns:
      the system-backed environment