Pressure-testing Ota on Strapi: structured Yarn hydration and truthful contributor verification
How Strapi proved a strong current Ota contributor-readiness shape: structured Yarn hydration, aggregate verification, command-owned task bodies, and contract-driven CI install truth.
Overview
Strapi is a strong pressure repo for contributor-readiness narrowing in a large JavaScript monorepo.
The useful claim here is not full monorepo completeness.
It is a clean, current readiness slice with:
- structured workspace hydration
- structured e2e env and Playwright bootstrap
- real root lint and unit-test verification surfaces
- a real local CE Playwright smoke lane
- an aggregate verify path
- contract-driven CI install truth
What changed in the contract
The biggest upgrade is setup ownership.
The repo already declares packageManager: yarn@4.12.0, so Ota can own this directly as structured Yarn dependency hydration:
tasks: setup: prepare: kind: dependency_hydration medium: package_dependencies source: kind: node_package_manager cwd: . manager: yarn mode: install frozen_lockfile: trueThat moves the contract onto the current package-manager surface instead of replaying package manager state in shell.
The same pressure pass also exposed a second useful truth: replacing shell setup is not the end of the job.
Strapi's browser lane needed a structured local e2e setup path too:
tasks: setup:e2e: prepare: kind: sequence steps: - kind: copy_if_missing from: tests/e2e/.env.example to: tests/e2e/.env - kind: tool_bootstrap tool: playwright_browsers browsers: - chromium source: kind: node_package_manager cwd: . manager: yarnThat replaces two documented shell/setup steps with one contract-owned setup lane.
The task bodies also moved from raw run wrappers onto command where Ota already owns the lane:
tasks: lint: command: exe: corepack args: - yarn - lintThe default verification path uses the real root contributor surfaces:
tasks: verify: aggregate: tasks: - lint - testThat is the right maturity move.
If the branch claims verification, it should point to the real lint and unit-test lanes for the modeled slice, not a package-manager version check.
For the local browser slice, the truthful narrow proof lane is now explicit too:
tasks: test:e2e:ce:smoke: command: exe: corepack args: - yarn - test:e2e:ce - --domains=admin - -- - login.spec.ts - --project=chromium - --reporter=line depends_on: - build - setup:e2eThe important lesson is the dependency on build.
Real execution showed that hydration plus browser install were not enough. The generated e2e app also needed built workspace artifacts, so the correct fix was not another repo-local workaround or another guessed helper task. It was to bind the browser lane to the repo's existing truthful build surface.
What stayed intentionally narrow
The contract is still scoped honestly.
It claims:
- workspace hydration
- root lint
- root unit Vitest
- a canonical aggregate verify workflow
The final cleared pass did not expose a new blocking Ota gap for that claimed slice.
It still does not pretend to prove every meaningful Strapi monorepo path.
build remains on the branch as a widened pressure lane, not the default claim.
That is still the correct repo posture.
But build is now also a concrete example of why pressure testing has to force real execution after a shell replacement. The first widened e2e setup looked correct on paper and only real task execution exposed the deeper hidden prerequisite.
Workflow truth also changed
The matrix uses contract-driven setup:
- name: Set up ota uses: ota-run/setup@v1.0.8 with: source: contract contract-path: ota.yamlThat matters because the matrix should test the same bootstrap truth the contract declares, not a second handwritten install lane.
Why this repo still matters
Strapi is still a strong example of an important Ota rule:
truthful narrowing beats fake completeness.
And there is a second rule here too:
first-class setup ownership is necessary, but not sufficient.
You still have to run the widened lane for real and keep tracing until the next blocker is classified as either:
- an Ota gap
- or a hidden repo truth that the contract had not encoded yet
The mature contract is not the one that sounds largest.
It is the one that:
- models the real repo-owned setup path
- uses the strongest first-class bodies Ota already supports
- keeps default verification on the real claimed slice
- avoids pretending the branch proves more than it actually does
That is exactly why this repo is useful.
Links
- Contract: strapi
ota.yaml - Matrix workflow: test-ota-contract-matrix.yml
- Green matrix run: #28287928713
Take action