Skip to content

    Back to articles

    5 min read

    Trial .NET 11 without changing the production build

    Make preview testing an opt-in lane

    I would add .NET 11 preview testing to a shared pipeline as a separate, opt-in job—not as a version change to the job that builds and releases production. That separation is the point: teams get an early compatibility signal without changing what an ordinary build means across every repository using the pipeline.

    The timing makes the distinction useful. Microsoft’s .NET 11 overview says general availability is expected in November 2026. The .NET site says .NET Conf 2026 begins November 10. Until the release is generally available, a preview result should help a team investigate; it should not quietly become a new production requirement.

    I would expose the lane through a boolean input on the reusable workflow, defaulting to off. A repository can opt in when it is ready to test, while repositories that do nothing keep using the established path. In GitHub Actions, the shape might look like this:

    on:
      workflow_call:
        inputs:
          dotnet11-preview:
            description: Run the .NET 11 preview compatibility lane
            type: boolean
            required: false
            default: false
    
    jobs:
      production-build:
        runs-on: ubuntu-latest
        steps:
          - uses: actions/checkout@v4
          # Keep the existing SDK setup, build, test, and release steps here.
    
      dotnet11-preview:
        if: ${{ inputs.dotnet11-preview }}
        runs-on: ubuntu-latest
        steps:
          - uses: actions/checkout@v4
          - uses: actions/setup-dotnet@v6
            with:
              dotnet-version: 11.0.x
              dotnet-quality: preview
          - run: dotnet --info
          - run: dotnet test src/Service.Tests/Service.Tests.csproj --framework net11.0

    This is a pattern, not a drop-in workflow: the project must support the target framework being tested, and the existing production steps belong in the production job unchanged. The setup-dotnet action documentation describes its SDK and preview-quality inputs.

    The preview lane should report separately from the production build. It can fail and give the team something to investigate without blocking a release that still uses the normal toolchain. If the organization later decides that preview compatibility should be required for a particular repository, that should be an explicit repository-level choice—not a side effect of updating a shared workflow.

    Keep SDK selection explicit

    Installing another SDK does not automatically mean every dotnet command will use it. A repository may have a global.json that selects the SDK version. The global.json overview explains how that file affects SDK selection. I would check this before treating a green preview job as evidence that the service was tested with the preview SDK.

    There are a few ways to keep the two lanes independent. A repository can use a separate preview-specific SDK configuration and run the preview commands from the directory where that configuration applies. Or the shared pipeline can provide a controlled preview working directory and configuration. The detail depends on how the repository is organized; the invariant does not: installing the preview SDK for one job must not change the SDK selected by the production job.

    I would also make the preview SDK selection visible in the job log. Printing dotnet --info makes it easier to distinguish “the preview job ran” from “the preview SDK actually ran.” If SDK resolution still points to the pinned production SDK, the lane is not testing what its name claims.

    Test a clear compatibility surface

    A useful first lane should answer a narrow question: does this service restore, build, and pass its tests when targeted at .NET 11 using the preview SDK and runtime? It should not try to answer every question about adoption, deployment, or production behavior at once.

    For a multi-targeted test project, a command such as dotnet test --framework net11.0 selects the target framework to exercise. I would keep the target-framework change opt-in as well, so adding preview coverage does not silently alter the framework used by the normal build. Where a repository cannot target the new framework yet, the lane can still test what it can—such as SDK compatibility—provided the job reports that narrower scope honestly rather than implying that it tested the application on the new runtime.

    I would not publish artifacts, update deployment manifests, or promote a preview-built package from this job. Those actions blur a compatibility check into a release path. The preview lane should produce diagnostic output and a test result; the established pipeline remains responsible for the artifacts that production consumes.

    A separate job also keeps the failure signal easier to interpret. If the preview lane fails while the regular build passes, the team can inspect whether the cause is a framework change, a dependency constraint, or a test assumption. That is a useful result even when the team chooses not to make a change immediately. The lane is there to discover friction early, not to manufacture pressure to adopt.

    Reuse the mechanism, not the decision

    A shared pipeline should standardize how a preview test runs: SDK setup, logging, test commands, and where results appear. It should not decide that every repository must test every preview, or that a preview failure blocks every release. Different services have different reasons to opt in, and that decision belongs with the team responsible for each service.

    This is the trade-off I would choose: centralize the mechanics, leave participation explicit, and keep production on its established toolchain until someone deliberately changes it. A reusable pipeline is valuable because it lets many repositories share a safe capability. It becomes a risk when a small shared edit silently changes the build contract for all of them.

    Drafted with AI assistance, reviewed and edited by Ali.