Overview
OrchardCore mattered because it is a real .NET repo, not a toy starter.
Even a narrow slice of the repo carries several different truths at once:
-
dotnetas the real toolchain owner - restore as a real dependency-hydration lane
- build and test as finite CLI surfaces, not shell glue
- native and container execution both advertised by the contract
- a much larger repo outside the selected slice that the contract should not pretend to own
That made OrchardCore a useful pressure repo for a simple question:
can Ota represent a serious .NET contributor path cleanly without collapsing back into raw shell
or overclaiming the whole repository?
Why this repo mattered
OrchardCore is a broad ASP.NET Core codebase with:
- many projects
- broader CI workflows
- functional and browser-heavy test surfaces
- asset and documentation paths outside the selected unit-project slice
That is exactly why the repo is useful.
A weak readiness contract would try to flatten all of that into one vague “build and test”
surface. A stronger contract narrows intentionally and says what it really owns.
The selected OrchardCore slice is honest:
- restore one unit-test project
- build that same project
- test that same project
- prove the slice on host and container paths where the contract advertises them
That is the right pressure bar for this repo.
What OrchardCore proved
1. Ota's .NET story is stronger when restore is first-class
The mature setup lane is not:
setup:
run: dotnet restore test/OrchardCore.Abstractions.Tests/OrchardCore.Abstractions.Tests.csproj
The stronger contract shape is:
setup:
prepare:
kind: dependency_hydration
medium: package_dependencies
source:
kind: dotnet_restore
cwd: test/OrchardCore.Abstractions.Tests
That matters because the contract now owns:
- the hydration lane itself
- the fact that it is package dependency preparation
- the requirement on the
dotnettoolchain - the network semantics of the lane
Instead of leaving all of that implicit inside one shell string.
2. Finite .NET task bodies should stay structured
OrchardCore also proved that plain dotnet build and dotnet test lanes do not need to stay as
raw run bodies.
The stronger shape is:
build:
command:
exe: dotnet
args:
- build
- --no-restore
cwd: test/OrchardCore.Abstractions.Tests
and:
test:
command:
exe: dotnet
args:
- test
- --no-restore
- --verbosity
- minimal
cwd: test/OrchardCore.Abstractions.Tests
That gives Ota a better execution boundary:
- executable identity is explicit
- arguments are explicit
- working directory is explicit
- mode branches only need to vary context, not duplicate command text
That is more mature governance than copying the same shell body across native and container modes.
3. Honest narrowing is more valuable than fake full-repo coverage
OrchardCore did not force a dramatic new Ota core bug.
What it proved instead is equally useful:
Ota can already carry a real .NET repo slice cleanly when the contract is disciplined about what
it is and is not claiming.
This contract does not pretend to own:
- the entire OrchardCore solution
- every functional test lane
- every database-backed or browser-backed path
- every asset or documentation workflow
It owns one clear contributor-readiness slice and proves that slice well.
That is better than a broader but less trustworthy contract.
What changed in the contract
The important changes were not dramatic. They were governance upgrades.
Toolchain ownership is explicit:
toolchains:
dotnet:
version: "10.0"
fulfillment:
source: dotnet
mode: run
The workflow now owns the setup boundary directly:
workflows:
verify:
prepare:
task: setup
run:
task: verify
And verification stays aggregate-owned instead of shell-chained:
verify:
aggregate:
tasks:
- build
- test
That final shape is small, but it is honest and machine-readable.
What the matrix proves
The current green OrchardCore matrix run for this narrowed slice is #28971743168.
That run is enough to support the note because it proved the slice the contract actually claims:
ota validateota doctorota tasks --useota tasks --safe --use- dry-run task coverage
- dry-run workflow coverage
- native execution on the selected unit-project slice
- container planning and execution for the same declared task surfaces
- matrix coverage across Ubuntu, macOS, and Windows for the contract branch at that time
That matters more than pretending the branch should already prove every broader OrchardCore lane.
The linked pressure branch is now pinned to released Ota v1.6.23 for stable reference. This
green matrix run is the proof artifact for the narrowed slice this note describes.
Why this repo mattered for Ota
OrchardCore helped confirm that Ota's current .NET surfaces are no longer theoretical.
They are strong enough to model a real ASP.NET Core repo slice with:
- first-class restore hydration
- structured finite dotnet commands
- workflow-owned setup
- explicit host/container mode truth
without falling back to raw shell or overclaiming repo coverage.
That is the real value of this pressure repo.
It did not need to expose a dramatic bug to matter. It proved that Ota's newer .NET contract
story is mature enough to use on a serious repository, provided the contract narrows honestly.
Links
- Contract: OrchardCore
ota.yaml - Matrix workflow: test-ota-contract-matrix.yml
- Current green matrix run: #28971743168
Originally posted here: https://ota.run/blog/pressure-testing-ota-on-orchardcore-3d2m
Top comments (1)
Making restore first-class is the move, and it quietly names two inputs at once that fail differently. The command names the dependency, which packages, but the restore's flakiness usually lives in the other one, the feed it reaches at run time. Same restore, same lockfile, green on Tuesday and red on Thursday because the feed moved or went slow, not because anything in the repo changed. So the honest version of dependency_hydration declares the feed posture too, which feed, pinned to what, offline or online, not just the verb, because that is where the non-determinism actually hides.
And the narrow proof is only as honest as where its boundary lives. You scoped out the functional lanes and the db paths in the writeup, but a downstream agent reads the contract, not the blog. The honest-narrow-net holds only if the contract carries its own "here is what I did not prove" as a first-class field, so the boundary travels with the artifact. Otherwise the scope is honest today and silently over-read tomorrow. Bounded honesty is exactly right, make the bound machine-readable too.