[DO NOT MERGE] CI vehicle — net10 superset + dotnet-script 2.0.1 - #2127
Draft
NickJosevski wants to merge 14 commits into
Draft
[DO NOT MERGE] CI vehicle — net10 superset + dotnet-script 2.0.1#2127NickJosevski wants to merge 14 commits into
NickJosevski wants to merge 14 commits into
Conversation
.NET 8 reaches end of support on 10 November 2026. Moving the SDK and moving the product target framework are two separate risks. Doing both together makes a failure hard to attribute. This commit moves only the toolchain. global.json goes to SDK 10.0.302. The Nuke build project targets net10.0. Frameworks.cs gains Net100 constants alongside the existing ones. The .NET 10 SDK audits transitive packages during restore. Auditing surfaced vulnerable dependencies reached through Octopus.Nuke.Common. TreatWarningsAsErrors turns those advisories into build errors. Fixed versions are pinned rather than the audit being suppressed. Signing.cs suppresses SYSLIB0057 at one call site. X509CertificateLoader only loads certificate files. No replacement exists for reading an Authenticode signature out of a signed PE. Verified: source/Calamari.sln builds at 164 warnings and 0 errors, identical to the pre-change baseline. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
The .NET 10 SDK raises NU1510 for direct references to packages the framework already provides. TreatWarningsAsErrors turns NU1510 into a build error. Removing the references now, on net8, keeps the change isolated from the framework move. Removed System.ValueTuple, System.ComponentModel.TypeConverter, System.Diagnostics.Tracing, System.IO.FileSystem, System.Runtime.InteropServices.RuntimeInformation, and the Microsoft.NETFramework.ReferenceAssemblies.net462 reference left over from #1669. System.Threading.AccessControl stays with NoWarn="NU1510". NuGet flags the package as likely unnecessary. That heuristic assumes a -windows target framework. These projects target plain net8.0 and need the package for SemaphoreSecurity. Verified: 164 warnings and 0 errors, identical to baseline. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Autofac 4.8.0 dates from 2018 and is five majors behind. Octopus Server already runs 9.3.1 on net10. Done while Calamari still targets net8. Autofac 9.3.1 resolves on net8. The DI upgrade is therefore verified against a known-good baseline instead of being entangled with the framework change. Notes for reviewers. ContainerBuilder.Update() is the headline Autofac 5 removal and was never used here. The .Update call sites in this repo belong to LibGit2Sharp. The API surface in use is mainstream and unchanged across the version range. The custom RegisterPrioritisedList<T> extension builds on Meta<T> and WithMetadata. Both APIs are stable. Verified: clean rebuild with no new warnings. 26 tests pass covering the custom registration ordering and flavour resolution. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Continues the dependency work on net8 before the target framework changes. System.Linq.Async goes to 7.0.1. .NET 10 pulls System.Linq.AsyncEnumerable into the core libraries. 7.0.1 is the version Octopus Server runs against net10. Serilog collapses a three-way version spread onto 4.0.2. Microsoft.Extensions.Http and Microsoft.Extensions.Logging go to 10.0.10. System.Text.Json and System.Text.Encoding.CodePages are deliberately left alone. Both become framework-provided on net10. Both are still required on net8. Removing them now would downgrade System.Text.Json to the in-box 8.x version and lose security fixes. Verified: 165 warnings and 0 errors. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Flips 41 projects to net10.0 and net10.0-windows. Also updates the build scripts and source/Directory.Build.props. Directory.Build.props compares the target framework as a string. Calamari.AzureWebApp.NetCoreShim stays on net462. Web Deploy is .NET Framework only. OctoVersion.Tool 1.0.50 already ships a net10.0 folder. No tool bump was needed. System.Text.Json and System.Text.Encoding.CodePages are removed here rather than earlier. Both raise NU1510 on net10. Both were genuinely required on net8. .NET 10 audits transitive packages during restore. Auditing surfaced vulnerable dependencies that net8 never reported. The direct references that pulled them in were upgraded rather than the audit being suppressed. WireMock.Net goes to 2.13.0. System.DirectoryServices.AccountManagement goes to 10.0.10. RestSharp is pinned to 112.1.0. Serilog goes to 4.4.0 for Serilog.Extensions.Logging 10.0.0. Certificate loading moves off the constructors obsoleted by SYSLIB0057. All four call sites load .pfx files. X509CertificateLoader.LoadPkcs12FromFile and LoadPkcs12CollectionFromFile are direct equivalents with no behaviour change. AzureWebAppBehaviour suppresses SYSLIB0014 around its ServicePointManager callback and carries a TODO. The callback looks like dead code. Web Deploy runs in a separate net462 child process. A callback registered in the parent cannot affect the child. The behaviour predates this change. Removing security-adjacent code deserves its own reviewed commit. Verified: 171 warnings and 0 errors on net10. build/_build.csproj clean. 24 DI and structured-variable tests pass against net10.0. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
build.sh and build.ps1 hardcode the SDK channel to 8.0 in an Octopus-local modification to the Nuke bootstrapper. The modification deliberately ignores global.json. Builds then roll forward to the latest patch automatically. On an agent without .NET preinstalled the bootstrapper would install an 8.0 SDK and then fail against a global.json requiring 10.0.302. Both bootstrappers now use the 10.0 channel. Verified end to end. ./build.sh --target PublishCalamariProjects --target-runtime linux-x64 succeeds. The published output is genuinely self-contained on the new runtime. Calamari.runtimeconfig.json reports net10.0 with Microsoft.NETCore.App 10.0.10 included. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Bundled dotnet-script 1.6.0 is a framework-dependent app targeting Microsoft.NETCore.App 8.0.0. Framework-dependent apps do not roll forward across a major version by default. On a machine with only .NET 10 installed dotnet-script fails to launch. Calamari itself is unaffected. Calamari ships self-contained. The failure is in the separate dotnet-script process. Setting DOTNET_ROLL_FORWARD=Major on that invocation lets dotnet-script run on whatever newer runtime is present. An explicit value already set in the environment is respected rather than overwritten. This is a customer-facing fix as much as a CI one. Without the fix a target with .NET 10 and no .NET 8 runtime cannot run C# script steps at all. SilentProcessRunner applies EnvironmentVars additively. Passing a dictionary where one was previously null does not discard the inherited environment. Not done here: upgrading the bundled dotnet-script. The 2.0.1 release zip Calamari vendors is still net8 targeted. Only the NuGet package ships a net10 build. The upgrade also changes the NuGet version dotnet-script bundles. The change invalidates the premise of UsingIsolatedAssemblyLoadContext. Verified: 10 DotnetScriptFixture tests pass. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
.NET 10 changed Environment.SetEnvironmentVariable(name, ""). On net8 an empty value deleted the variable. On net10 it stores an empty string. Verified directly against 8.0.27 and 10.0.10. Passing null still deletes on both. The proxy fixtures relied on the old behaviour. Two uses together account for 11 of the 13 test failures in PR #2091's chain 2026.3.533. Reset helpers passed string.Empty to mean unset. On net10 that leaves HTTP_PROXY, HTTPS_PROXY and NO_PROXY set to "". ProxyEnvironmentVariablesGenerator tests for presence rather than value. The generator therefore took the "proxy variables already exist" branch and leaked empty values into every later fixture in the run. ProxySettingsInitializerFixture passed "" for absent credentials and then asserted BeNull(). On net10 the read returns "". Reset helpers now pass null. Credential assertions use BeNullOrEmpty(). The assertion states the actual intent rather than a representation detail. The setter deliberately keeps "" so the empty-string case is now genuinely covered. No product change and no customer-visible behaviour change. All 30 uses of the idiom were in test code. Inherited environment variables behave identically on both runtimes. Calamari inherits its environment in production. Verified on net10.0 locally: ProxySettingsInitializerFixture 5/5, ScriptEngineFixture 1/1, SetupKubectlAuthenticationFixture 3/3. The five Bash and DotnetScript proxy cases need bash, pwsh and the proxy fixture host. Those share the same teardown mechanism and ScriptProxyFixtureBase got the same fix. CI is the confirmation. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
CodeGenerator.GenerateConsoleApplication hardcoded a net8-era toolchain. It wrote a global.json pinning SDK 8.0.10 and ran dotnet new console -f net8.0. The agents provide only a .NET 10 SDK. SDK 8.0.10 is unsatisfiable because rollForward latestFeature only rolls in the 8.0.x band. The test failed before it could exercise anything. That is the ExecuteManifestCommandFixture.WithInstructions failure on the Linux netcore-testing configs in PR #2091's chain 2026.3.534. It was the last remaining Linux test failure after the proxy fixture fix landed. Bumped to SDK 10.0.302 and net10.0, matching the repository's root global.json. Verification is partial. The SDK resolution error is gone. dotnet new console -f net10.0 succeeds and the project is created. The test still fails on an Apple Silicon dev machine for a pre-existing and unrelated reason. RID selection a few lines below sets osx-x64 for Mac and then overwrites it with linux-arm64 whenever ProcessArchitecture is Arm64. That check is not nested under the IsRunningOnNix branch. The generated app is published for linux-arm64 and exec'd on macOS. CI is unaffected and is the confirmation for this change. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
KubernetesContextScriptWrapperLiveFixtureEks.UsingEc2Instance provisions a
Debian 12 EC2 instance via terraform, uploads the built test assemblies, and
runs `dotnet test Calamari.Tests.dll` on it. test.sh installed only
dotnet-sdk-8.0, so once the assemblies became net10.0 the instance could not
run them. The non-zero exit surfaced as a terraform remote-exec provisioner
failure:
Error: remote-exec provisioner error
on ec2.kubernetes.tf line 55, in resource "kubernetes_cluster_role_binding" "default":
error executing "/tmp/terraform_*.sh": Process exited with status 145
Branch-correlated, not flaky or environmental: across the 30 most recent runs
of this test it failed 5/5 on pull/2091 and passed 25/25 everywhere else,
including refs/heads/main, release/2026.1, release/2026.2, and - on the very
same build configuration and agents in the dotnet10 experiment project -
pull/2110 and pull/2111.
Not a glibc issue. Debian 12 ships glibc 2.36, comfortably above .NET 10's 2.27
floor. This is purely a hardcoded SDK version in the test harness, the same
class of net8 leftover as CodeGenerator.cs, the TeamCity choco step and the
Calamari.TestContainers image templates.
Installs 10.0 alongside 8.0 rather than replacing it, matching how the other
three were fixed, so the script still works if run from a net8 branch.
Confirmed dotnet-sdk-10.0 is published in the feed test.sh configures
(packages.microsoft.com/debian/12 bookworm main binary-amd64).
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
The rebase onto main auto-merged both sides' SharpCompress and System.Linq.Async entries into the same ItemGroup, producing duplicates that failed restore with NU1504. Keeps the newer of each, which preserves both sides' intent: - SharpCompress 0.49.1 from main, dropping the 0.37.2 entry and its NoWarn NU1902 suppression (main re-armed that alerting in SF-1864) - System.Linq.Async 7.0.1 from this branch's dependency alignment Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
main added System.Text.Json 9.0.16 to Calamari.csproj after this branch diverged. On net10.0 it is framework-provided, so NuGet prunes it and NU1510 fails the restore under TreatWarningsAsErrors. The net10 shared framework ships a newer System.Text.Json than 9.0.16, so removing the explicit reference keeps the version floor main was after. Same rationale as "Remove framework-provided package references". Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
The net10 stack's dependency alignment and the merged #2120 dependency work both set Serilog in these projects, so replaying one onto the other produced duplicate PackageReference items and NU1504 at restore. Keep the higher version. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Roll-forward (DOTNET_ROLL_FORWARD=Major) gets bundled dotnet-script 1.6.0
launching on a net10-only machine, but that is only the first of two gates.
Once it launches, any `#r "nuget: <framework-provided package>"` fails:
Error loading lock file '.../net10.0/obj/project.assets.json' :
Cannot compare the value of a token type 'Number' to text.
The lock file ... does not contain a runtime target.
The .NET 10 SDK's new package pruning emits NU1510 - the same warning already
suppressed in Calamari.Common.csproj - and writes it into a new top-level
`logs` array in project.assets.json containing "warningLevel": 1, a JSON
number. dotnet-script 1.6.0 bundles NuGet.ProjectModel 6.10.0, which expects
text there, so the whole lock file fails to load and the runtime target is
reported missing.
2.0.1 bundles NuGet.ProjectModel 6.14.3 (upstream #791) and parses it
correctly. Verified against a net10-only runtime: 1.6.0 fails as above, 2.0.1
returns .NET 10.0.10 and a working result. Scripts with no `#r "nuget:"`, and
those referencing non-prunable packages such as Newtonsoft.Json, are
unaffected on either version.
The published 2.0.1 zip is still tfm net8.0 requiring Microsoft.NETCore.App
8.0.0, so this does NOT replace the roll-forward change - both are required.
Two behaviour changes to watch in testing, both upstream defaults in 2.0:
- Roslyn 4.11.0 -> 5.0.0-2.final (prerelease). ScriptCompiler hardcodes
LanguageVersion.Preview, so the language ceiling available to customer
scripts moves with it.
- Isolated assembly load context becomes the default. `--isolated-load-context`
was removed and inverted to `--disable-isolated-load-context`; Calamari
passes neither, so isolation is now on. Left at the upstream default
deliberately rather than pinned back, so pre-production exercises what
would actually ship.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
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.
Not for review or merge. Sibling of #2125; exists so TeamCity publishes a second pre-release for A/B testing on a pre-production cloud instance.
Identical to #2125 (net10 superset, includes
DOTNET_ROLL_FORWARD=Major) plus one commit: bundled dotnet-script 1.6.0 → 2.0.1.Why the bump is needed as well as roll-forward
Roll-forward gets dotnet-script launching on a net10-only machine. It does not make it work. Once launched,
#r "nuget: <framework-provided package>"fails:.NET 10 SDK package pruning emits NU1510 — the same warning already suppressed in
Calamari.Common.csproj— and writes it into a new top-levellogsarray containing"warningLevel": 1, a JSON number. dotnet-script 1.6.0 bundles NuGet.ProjectModel 6.10.0, which expects text there.2.0.1 bundles NuGet.ProjectModel 6.14.3 (upstream dotnet-script#791) and parses it. Verified against a net10-only runtime:
The published 2.0.1 zip is still
tfm: net8.0requiringMicrosoft.NETCore.App 8.0.0, so this does not replace the roll-forward change — both are required.Behaviour changes to watch in pre-production
Both are upstream 2.0 defaults, left unpinned deliberately so testing exercises what would actually ship:
ScriptCompilerhardcodesLanguageVersion.Preview, so the language ceiling available to customer scripts moves with it.--isolated-load-contextwas removed and inverted to--disable-isolated-load-context; Calamari passes neither.