DEV Community

Cover image for Pressure-testing Ota on Azure SDK for .NET: typed NuGet hydration across ephemeral containers
Bobai Kato for Ota

Posted on • Originally published at ota.run

Pressure-testing Ota on Azure SDK for .NET: typed NuGet hydration across ephemeral containers

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.Core through the repository's NuGet.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.Config
Enter fullscreen mode Exit fullscreen mode

The 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/src
Enter fullscreen mode Exit fullscreen mode

This 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/packages
Enter fullscreen mode Exit fullscreen mode

Ota 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.cwd inside it, because restore writes shared intermediates under the repository artifacts/ tree;
  • typed dotnet_restore must 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"
Enter fullscreen mode Exit fullscreen mode

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


Originally Posted: https://ota.run/blog/pressure-testing-ota-on-azure-sdk-for-net-3v9q

Top comments (0)