ReleaseReady Docs

Practical implementation guidance for Playwright JavaScript/TypeScript teams.

Architecture

Runners and agents architecture

Current extensibility analysis for adding more runner or execution agent types.

Runners and agents architecture

Current architecture summary

ReleaseReady currently separates a few concerns well:

  • webhook intake happens in the GitHub webhook route,
  • manual execution entry points flow through the project run route,
  • result normalization and ingestion happen in the runner results route,
  • and shared runner payload schemas live in src/lib/runner.ts and src/lib/runner-results.ts.

The most important execution decision happens inside the project run route:

  • if RUNNER_URL exists, execution is delegated to the external runner,
  • otherwise the app runtime performs direct checkout and command execution.

Where coupling still exists

Runner selection and runner request shaping are still mostly controlled inside app/api/projects/[projectId]/run-tests/route.ts.

That means the product is **possible to extend with moderate refactor**, but not yet a clean multi-provider execution platform.

Extensibility assessment

Is runner or agent logic tightly coupled?

Partially.

The product already has a useful separation between:

  • trigger intake,
  • execution request creation,
  • and result ingestion.

But provider selection, payload shaping, and delegated-response parsing are still concentrated in a single route.

Can additional runner types be added without major rewrites?

Yes, but most likely with a moderate refactor rather than a zero-change add-on.

Are abstraction boundaries clear?

They are becoming clear:

  • trigger orchestration lives in webhook routes,
  • execution orchestration lives in the run route,
  • result normalization lives in runner result helpers.

The missing boundary is a dedicated execution-provider adapter layer.

Is there a place where a provider or adapter strategy pattern makes sense?

Yes. The best fit is between the project run route and the delegated runner HTTP call. That layer can decide:

  • which execution provider to use,
  • how to build the provider request,
  • how to parse the provider response,
  • and how to store provider-specific metadata while preserving the checklist run contract.

Low-risk improvement included now

This change set introduces a dedicated helper for building delegated runner requests and parsing delegated runner responses.

That does **not** change current webhook, manual run, or runner results contracts. It only isolates provider-specific logic so the next provider can be introduced with less route churn.

Recommendation

Use an execution-provider adapter model with a small interface, for example:

tsCopy/paste friendly
interface ExecutionProvider {
  name: string;
  canHandle(input: ExecutionRequestContext): boolean;
  startRun(input: ExecutionRequestContext): Promise<ExecutionProviderResult>;
}

Then keep the checklist run record as the stable system boundary and let provider adapters map their own payloads into that common shape.

Final assessment

Adding more runners or agents is:

**possible with moderate refactor**

The current design already has enough separation to evolve safely, but it should continue extracting runner-specific behavior out of the main project run route before multiple providers are introduced.