Guard the DI container's orderings and shape - #2119
Draft
NickJosevski wants to merge 1 commit into
Draft
NickJosevski wants to merge 1 commit into
NickJosevski wants to merge 1 commit into
Conversation
NickJosevski
force-pushed
the
nj/di-container-ordering-guard
branch
from
August 10, 2026 04:24
28bd8ba to
85142c0
Compare
Script wrappers form an execution chain and file-format replacers are tried in sequence, so a reordering changes deployment behaviour. Nothing currently detects that: every wrapper still constructs and every command still resolves, so the existing suite stays green. Two guards, both PlatformAgnostic: ContainerOrderingFixture asserts the orderings directly. The load-bearing one is ScriptWrapperPrioritiesAreUnique - ScriptEngine sorts with OrderByDescending, which is stable, so a shared priority silently hands the tie-break to the container's collection ordering. Priorities are distinct today (1003/1002/1001/ 1000/100), but AwsScriptWrapper, AzureContextScriptWrapper, GoogleCloudContextScriptWrapper and AzureServiceFabricPowerShellContext all sit on CloudAuthenticationPriority in their separate flavours, so a second cloud wrapper in one flavour would make the chain container-dependent. The rest pin the wrapper chain for a Kubernetes/AWS/PowerShell step, the file-format replacer order, and discoverer key uniqueness. ContainerSnapshotFixture compares a rendering of the whole container against an approved file: registrations, lifetimes, collection order, and the concrete types injected into every command. Targeted assertions only catch what someone thought of; this catches anything observable that moves. Re-approve with CALAMARI_APPROVE_CONTAINER_SNAPSHOT=1. The snapshot is normalised so one file serves every platform: the OS-chosen filesystem and certificate-store implementations collapse to placeholders, Autofac's __RegistrationOrder tick counter is dropped, and collection fields render distinct element types rather than counts. Baselined at Autofac 9.3.1, matching main. The instrument was built to catch the 4.8.0 -> 9.3.1 bump, which has since landed via #2131; rebasing across it reproduced exactly the predicted diff - the recorded version line plus five RegisterInstance registrations gaining AutoActivate - with the five ordering tests still passing. Those five are inert: none of the instances is IDisposable and the codebase has no OnActivating/OnActivated handlers. That rebase crossed eight commits of main, including Octostache 3.9.3, the unconditional docker credential helper and a new feature toggle. Nothing outside those six lines moved, which is the evidence that matters for a golden file: it is stable enough not to cry wolf. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
NickJosevski
force-pushed
the
nj/di-container-ordering-guard
branch
from
August 14, 2026 06:07
85142c0 to
b7fd680
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Adds two DI guards to
Calamari.Tests. No production code changes.Why
Script wrappers form an execution chain; file-format replacers are tried in sequence. A reordering changes deployment behaviour, but every wrapper still constructs and every command still resolves — so the existing suite stays green. Nothing currently detects it.
What
ContainerOrderingFixture— asserts the orderings directly. The load-bearing test isScriptWrapperPrioritiesAreUnique:ScriptEnginesorts withOrderByDescending, which is stable, so two wrappers sharing a priority silently hand the tie-break to the container's collection ordering.Priorities are distinct today (1003/1002/1001/1000/100) — but
AwsScriptWrapper,AzureContextScriptWrapper,GoogleCloudContextScriptWrapperandAzureServiceFabricPowerShellContextall sit onCloudAuthenticationPriorityin their separate flavours. A second cloud wrapper in any one flavour would make that chain container-dependent. Asserting the invariant is a better guard than pinning a sequence.The rest pin the wrapper chain for a Kubernetes/AWS/PowerShell step, the file-format replacer order, and discoverer key uniqueness.
ContainerSnapshotFixture— compares a rendering of the whole container againstContainerSnapshot.expected.txt: registrations, lifetimes, collection order, and the concrete types injected into every command. Targeted assertions only catch what someone thought of; this catches anything observable that moves. Re-approve withCALAMARI_APPROVE_CONTAINER_SNAPSHOT=1.Both are
PlatformAgnostic. The snapshot is normalised so one file serves every platform — OS-chosen filesystem and certificate-store implementations collapse to placeholders, Autofac's__RegistrationOrdertick counter is dropped, collection fields render distinct element types rather than counts.The expected file is deliberately not named
*.approved.*—.gitattributesmarks that patternbinary -text(protecting ~207 existing approved files from line-ending normalisation), which would hide the diff this test exists to surface.Rebased onto main — what that showed
Originally baselined at Autofac 4.8.0 so the upgrade would land as a reviewed diff. That upgrade has since merged via #2131, so this is now baselined at 9.3.1 to match main.
Rebasing across it reproduced exactly the predicted diff and nothing else — the recorded version line plus five
RegisterInstanceregistrations gainingAutoActivate, with all five ordering tests still passing:Those five are inert: none of the instances is
IDisposable, and the codebase has noOnActivating/OnActivatedhandlers. Autofac 9 simply attaches already-constructed instances at container-build time rather than at first resolve.The rebase crossed eight commits of main — Octostache 3.9.3 and the new date filters, the unconditional docker credential helper, a new feature toggle, removal of the net462 reference assemblies. Nothing outside those six lines moved. For a golden file that's the evidence that matters: it is stable enough not to cry wolf.
Verification
14 tests green locally (these 6, plus
CommandResolutionTestsandPrioritisedRegistrationFixture).The golden was captured on macOS. The normalisation should make it OS-invariant, but CI running it on Windows is the actual proof — if the platform mapping missed something it surfaces there as a clear diff rather than a mystery.
🤖 Generated with Claude Code