Pressure-testing Ota on Azure SDK for .NET: typed NuGet hydration across ephemeral containers
How Ota 1.6.25 governs a narrow Azure.Core restore and no-restore build path across native and ephemeral-container execution without claiming Azure SDK repository-wide readiness.
Overview
Azure SDK for .NET is a large multi-service repository. Its contributor, test, API-compatibility, code-generation, live-resource, and release paths are not one runnable surface.
The Ota contract therefore owns one useful contributor slice and names it plainly:
- restore the dependencies for
sdk/core/Azure.Corethrough the repository'sNuGet.Config; - build that library with
--no-restore; - execute the same sequence in native mode and in a fresh .NET SDK container.
That is enough to pressure a real boundary without pretending that a green build means the Azure SDK repository, its services, or its releases are ready.
The Contract
The repository owns package-source policy. Ota owns the typed restore operation that consumes it:
tasks: setup: prepare: kind: dependency_hydration medium: package_dependencies source: kind: dotnet_restore cwd: sdk/core/Azure.Core/src config_file: ../../../../NuGet.ConfigThe later build is deliberately no-restore:
tasks: build: depends_on: [setup] command: exe: dotnet args: [build, --no-restore, --framework, net10.0] cwd: sdk/core/Azure.Core/srcThis makes the boundary testable. If restore state does not reach the build, --no-restore fails instead of silently going back to the network.
Ephemeral Container Cache Ownership
The selected container context is ephemeral, so restore and build do not share a long-lived container. The contract declares the NuGet cache as Ota-managed attachment state:
execution: contexts: dotnet:container: backend: container lifecycle: ephemeral container: image: mcr.microsoft.com/dotnet/sdk:10.0.103 attachments: isolated_paths: - .nuget/packagesOta derives NUGET_PACKAGES for the selected context and carries that cache across the restore and later no-restore build containers. The repo does not need to duplicate a host cache path or a Docker volume name in a helper script.
Azure SDK exposed two Ota corrections while this was pressure-tested:
- command tasks must mount the contract root, then apply
command.cwdinside it, because restore
writes shared intermediates under the repository artifacts/ tree;
- typed
dotnet_restoremust carry the resolved NuGet package cache into later ephemeral tasks,
not merely report that restore exited successfully.
Those are runner ownership fixes. They are not Azure-specific workflow glue.
.NET Version Truth
The contract follows global.json, which requests 10.0.103 with rollForward: feature:
toolchains: dotnet: version: ">=10.0.103, <10.1.0"That admits valid servicing releases in the same feature band. An exact patch equality would turn the repository's declared roll-forward policy into a false readiness failure.
Released Matrix
The requalification matrix installs Ota from the contract as released v1.6.25, verifies the binary version before any Ota command runs, and pins all GitHub Actions by immutable revision.
The released four-lane matrix is green. Every lane recorded ota v1.6.25 (source, commit a3e9f98f3) before running Ota.
It covers:
validate, Doctor, task/workflow discovery, and safe/unsafe task-surface discovery;- task and workflow dry-runs on Ubuntu, macOS, Windows, and Ubuntu container mode;
- real restore, no-restore build, and declared workflow execution in each advertised mode;
- retained version, diagnosis, contract snapshot, and archived workflow receipt artifacts on every result.
The receipts agree on one contract snapshot: sha256:f7a96703141dc4e6cbb9626e0f893f4692d781db48113ac639c18770d972134b. The Ubuntu container receipt records dotnet:container with ephemeral lifecycle; the other three receipts record the native context. A historical matrix that installed an implementation branch is not evidence for this release claim.
What It Does Not Prove
This is selected-lane evidence only. It does not prove:
- every Azure SDK client library, test suite, API-compatibility check, generator, or release build;
- Azure credentials, live-resource tests, external package-feed availability, or service behavior;
- application correctness, package publication, or repository-wide readiness;
- container execution on macOS or Windows, where those lanes exercise native contract execution;
- hermetic replay or a contract-pinned expected identity for the SDK image tag.
The last point is an intentional limitation to keep visible: this contract records the configured SDK image tag, not an immutable image digest. A mutable tag is not a maintainer-declared immutable input, so this is not a claim of a pinned container base.
Why This Matters
The useful result is not that Ota can invoke dotnet restore.
It is that the contract declares dependency intent once, while the runner owns the workspace and cache continuity needed to make a later no-restore build meaningful across fresh containers. The result remains narrow, inspectable, and honest about the much larger Azure SDK surface it does not govern.
Links
- Upstream repository: Azure/azure-sdk-for-net
- Pressure contract: Azure SDK
ota.yaml - Pressure matrix: Azure SDK Ota contract matrix
- Released Ota evidence: green Azure SDK matrix run
Take action