Skip to content

feat(extensions): fake implementations with error injection#197

Open
behinddwalls wants to merge 1 commit into
scorerfrom
preetam/mock-ext-fakes
Open

feat(extensions): fake implementations with error injection#197
behinddwalls wants to merge 1 commit into
scorerfrom
preetam/mock-ext-fakes

Conversation

@behinddwalls
Copy link
Copy Markdown
Collaborator

@behinddwalls behinddwalls commented Jun 4, 2026

Summary

Why?

Extensions over external systems (changeprovider, buildrunner, pusher,
mergechecker) had no runnable stub to exercise their success — and
especially failure — paths without standing up the real backend
(GitHub/CI/git). scorer and conflict had deterministic stubs (heuristic,
composite, all, none) but no way to inject errors. These fakes let tests
drive both happy and error paths end-to-end from a land request.

What?

  • buildrunner/fake, changeprovider/fake, pusher/fake, mergechecker/fake:
    best-case by default; inject failures via an sq-fake=<token> marker in
    a change URI (e.g. build-fail, conflict, unmergeable, provider-error).
  • scorer/fake, conflict/fake: decorators that wrap an existing impl (the
    "pick") and overlay error injection — scorer via the URI marker
    (score-error) over entity.BatchChanges, analyzer via a predicate, since
    Analyze sees batches, not change URIs.
  • Each fake exposes only New(...) (decorator constructors for scorer/
    conflict). No factory implementations live in extension/* — those belong
    in the wiring layer.
  • pusher/README.md documents the fake.

These packages are test/example stubs, never production. They are wired
into the example orchestrator in a follow-up PR.

Test Plan

  • make test — fake package tests
  • bazel build //...

Stack

  1. refactor(storage): fold ChangeStore into storage, drop dead store #191
  2. refactor(change): persist typed change details from the change provider #195
  3. refactor(scorer): score batches over typed change details #196
  4. @ feat(extensions): fake implementations with error injection #197
  5. feat(example): per-queue extension wiring; retire buildrunner/noop #193

## Summary

### Why?

Extensions over external systems (changeprovider, buildrunner, pusher,
mergechecker) had no runnable stub to exercise their success — and
especially failure — paths without standing up the real backend
(GitHub/CI/git). scorer and conflict had deterministic stubs (heuristic,
composite, all, none) but no way to inject errors. These fakes let tests
drive both happy and error paths end-to-end from a land request.

### What?

- buildrunner/fake, changeprovider/fake, pusher/fake, mergechecker/fake:
  best-case by default; inject failures via an `sq-fake=<token>` marker in
  a change URI (e.g. build-fail, conflict, unmergeable, provider-error).
- scorer/fake, conflict/fake: decorators that wrap an existing impl (the
  "pick") and overlay error injection — scorer via the URI marker
  (score-error) over entity.BatchChanges, analyzer via a predicate, since
  Analyze sees batches, not change URIs.
- Each fake exposes only New(...) (decorator constructors for scorer/
  conflict). No factory implementations live in extension/* — those belong
  in the wiring layer.
- pusher/README.md documents the fake.

These packages are test/example stubs, never production. They are wired
into the example orchestrator in a follow-up PR.

## Test Plan

- ✅ `make test` — fake package tests
- ✅ `bazel build //...`
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant