Fix resolution of the external dependencies. - #11742
Fix resolution of the external dependencies.#11742Nikolay Rovinskiy (nick863) wants to merge 23 commits into
Conversation
commit: |
There was a problem hiding this comment.
Pull request overview
Updates the C# generator’s external NuGet dependency resolution so it can (when needed) fall back to the latest available version (optionally including prereleases) instead of only using a requested minimum version or whatever is already cached.
Changes:
- Added a helper to enumerate available package versions across enabled NuGet sources.
- Updated external type resolution to select a version based on
MinVersionpresence and prerelease status before downloading.
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated 3 comments.
| File | Description |
|---|---|
| packages/http-client-csharp/generator/Microsoft.TypeSpec.Generator/src/Utilities/NugetPackageResolver.cs | Adds GetAllVersions helper for collecting versions from enabled NuGet sources. |
| packages/http-client-csharp/generator/Microsoft.TypeSpec.Generator/src/Utilities/ExternalTypeReferenceResolver.cs | Uses version enumeration to choose a download version when the requested MinVersion isn’t available and to include prereleases when appropriate. |
Suppressed comments (1)
packages/http-client-csharp/generator/Microsoft.TypeSpec.Generator/src/Utilities/ExternalTypeReferenceResolver.cs:260
new NuGetVersion(external.MinVersion)will throw for an invalid/unsupported version string, which changes behavior compared to the previous string-based flow and ends up being swallowed by the broad catch (reported as "package not found"). Also,versions.Max()throws on an empty sequence, so missing packages/feeds can trigger an exception and skip the intended fallback selection.
NuGetVersion minVersion = new(external.MinVersion);
IList<NuGetVersion> versions = await NugetPackageResolver.GetAllVersions(external.Package!, nugetSettings, allowPrerelease: minVersion.IsPrerelease);
if (versions.Any(x => x == minVersion))
{
resolvedVersion = external.MinVersion;
}
else
{
resolvedVersion = versions.Max()?.ToString();
}
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
|
No changes needing a change description found. |
|
The resolved version should be based on the csproj/central package management. The MinVersion from the decorator is only meant to be used as a safety check - it doesn't influence the version that is used, but it can trigger an error if the min version doesn't align with the resolved version. Can you clarify what issue this is solving? |
I have updated the description. |
The minVersion should not be used to influence the version that is downloaded by the generator. It is only meant to be used as a compatibility floor. It is optional - it doesn't have to be specified at all. I'm not sure what problem this is solving. |
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 2 out of 2 changed files in this pull request and generated 1 comment.
Suppressed comments (2)
Previously missed (1) — in code that hasn't changed since the last review.
packages/http-client-csharp/generator/Microsoft.TypeSpec.Generator/src/Utilities/ExternalTypeReferenceResolver.cs:260
- If the configured feeds return no versions (e.g., package doesn't exist, or only prerelease versions exist but
allowPrereleaseis false),versions.Max()will throw on an empty sequence and the resolver will fall into the catch path. Handle the empty list explicitly so resolution can fail cleanly without relying on exceptions.
NuGetVersion minVersion = new(external.MinVersion);
IList<NuGetVersion> versions = await NugetPackageResolver.GetAllVersions(external.Package!, nugetSettings, allowPrerelease: minVersion.IsPrerelease);
if (versions.Any(x => x == minVersion))
{
resolvedVersion = external.MinVersion;
}
else
{
resolvedVersion = versions.Max()?.ToString();
}
packages/http-client-csharp/generator/Microsoft.TypeSpec.Generator/src/Utilities/ExternalTypeReferenceResolver.cs:266
- New behavior adds multiple version-selection branches (minVersion present + exact version missing -> pick latest; prerelease minVersion -> include prerelease; minVersion absent -> latest stable). There are existing unit tests for ExternalTypeReferenceResolver, but none cover these new branches. Add tests that exercise: (1) minVersion not in feed selects latest available version; (2) prerelease minVersion allows selecting a prerelease latest; (3) stable minVersion does not select prerelease when only prerelease versions exist.
if (!string.IsNullOrEmpty(external.MinVersion))
{
// If min version was provided, we
// 1. Search if it is in our repositories;
// 2. Get the latest one if it is not.
// 3. If our version is a pre release, include pre released versions in our search.
NuGetVersion minVersion = new(external.MinVersion);
IList<NuGetVersion> versions = await NugetPackageResolver.GetAllVersions(external.Package!, nugetSettings, allowPrerelease: minVersion.IsPrerelease);
if (versions.Any(x => x == minVersion))
{
resolvedVersion = external.MinVersion;
}
else
{
resolvedVersion = versions.Max()?.ToString();
}
}
else
{
// If min version was not provided, get the latest stable version.
resolvedVersion = await NugetPackageResolver.ResolveLatestPackageVersion(external.Package!, nugetSettings);
}
The problem is that we did not released the new stable version yet, while the downloaded version is 2.0.0. The logic in |
|
Thanks, that clarifies the reproduction. I think the root fix should be in project-reference resolution rather than selecting a package version from
With that flow, the reported case resolves the project's --generated by Copilot |
f530a05 to
970c165
Compare
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 3 out of 3 changed files in this pull request and generated 2 comments.
Suppressed comments (1)
packages/http-client-csharp/generator/Microsoft.TypeSpec.Generator/src/PostProcessing/GeneratedCodeWorkspace.cs:295
- Waiting for the process to exit before draining either redirected stream can deadlock once
dotnet restorefills an OS pipe buffer. This codebase already handles the same failure mode by reading stdout and stderr concurrently inGeneratorHandler.ReadProcessOutput(lines 340-346); start both reads before awaiting process exit here as well.
if (restore.Start())
{
await restore.WaitForExitAsync();
if (restore.ExitCode != 0)
{
string output = await restore.StandardOutput.ReadToEndAsync();
…ovins/fix_external_package_resolution
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 4 out of 4 changed files in this pull request and generated 3 comments.
Suppressed comments (5)
packages/http-client-csharp/generator/Microsoft.TypeSpec.Generator/src/PostProcessing/GeneratedCodeWorkspace.cs:318
projectFileDependencyGroupscontains the requested constraint, not the version selected by restore. For example, when a project requests1.0.0but only2.0.0exists, NuGet writesPackage >= 1.0.0here whiletargetscontainsPackage/2.0.0. This code therefore passes1.0.0to the exact-version lookup and rejects the package that restore just downloaded—the missing-minVersion scenario this PR is intended to fix. Read the selected version (and ideally its compile asset) fromtargetsinstead.
// We only support the greater-than-or-equal relation.
// Example: "My.Package >= 1.1.1"
if (packageVersionRelation.Length == 3 && string.Equals(packageVersionRelation[1], ">="))
{
hshFrameworks[currentFramework.Framework][packageVersionRelation[0].ToLower()] = packageVersionRelation[2];
packages/http-client-csharp/generator/Microsoft.TypeSpec.Generator/test/GeneratedCodeWorkspaceTests.cs:177
- This fake assembly does not reference Azure.Core, but its nuspec declares Azure.Core 1.61.0. Because the test redirects
NUGET_PACKAGESto an isolated cache and now runsdotnet restore, this forces a real feed lookup/download and makes the unit test non-hermetic. Remove the unused dependency, consistent withtest/common/FakeNuGetPackage.cs:35-53, which only emits dependencies explicitly required by the test assembly.
<dependencies>
packages/http-client-csharp/generator/Microsoft.TypeSpec.Generator/test/GeneratedCodeWorkspaceTests.cs:754
- Every package created by this helper unnecessarily depends on Azure.Core 1.61.0. The new production path runs
dotnet restoreagainst an isolated fake cache, so these otherwise self-contained tests must contact an external feed. Emit no dependencies here, as the shared hermetic helper does intest/common/FakeNuGetPackage.cs:35-53.
<dependencies>
packages/http-client-csharp/generator/Microsoft.TypeSpec.Generator/test/GeneratedCodeWorkspaceTests.cs:739
- NuGet's global-packages layout expects the manifest filename to use the normalized lowercase package ID. This mixed-case filename is not found by the exact-version local repository lookup on case-sensitive systems, so the newly added version-selection tests fail there. Match the shared helper at
test/common/FakeNuGetPackage.cs:111.
File.WriteAllText(Path.Combine(metadataPath, $"{packageName}.nuspec"), $"""
packages/http-client-csharp/generator/Microsoft.TypeSpec.Generator/src/Utilities/ExternalTypeReferenceResolver.cs:21
- After this change the resolver only consults the cache, but its failure reason at line 244 and the fallback diagnostics in
TypeFactory.cs:373-374still claim that configured feeds were searched. Package failures will therefore tell users that a feed lookup occurred when it did not. Update those messages to describe project restore/cache lookup.
/// looking up the package in the NuGet global cache and loading the assembly via reflection.
/// Used by <c>TypeFactory.CreateExternalType</c>
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 4 out of 4 changed files in this pull request and generated 2 comments.
Suppressed comments (3)
packages/http-client-csharp/generator/Microsoft.TypeSpec.Generator/src/PostProcessing/GeneratedCodeWorkspace.cs:339
- Deriving the assets directory from
OutputPathonly works when output and intermediate paths follow thebin/objconvention. Valid projects can configureOutputPathandBaseIntermediateOutputPathindependently, causing this method to return null even though restore produced an assets file. Query MSBuild'sProjectAssetsFile(orMSBuildProjectExtensionsPath) directly instead of rewritingOutputPath.
ArgumentList = { "msbuild", projectFilePath, "-getProperty:OutputPath" },
packages/http-client-csharp/generator/Microsoft.TypeSpec.Generator/test/GeneratedCodeWorkspaceTests.cs:480
- This local is never used and produces CS0219. Since the generator tree enables warnings as errors in
generator/Directory.Build.props:29, the test project will not build.
var nugetCacheDir = Path.Combine(_tempDirectory!, "NuGetCache");
packages/http-client-csharp/generator/Microsoft.TypeSpec.Generator/test/GeneratedCodeWorkspaceTests.cs:739
- NuGet's global-packages layout requires the nuspec filename to use the lowercased package ID. With names such as
First.Package, this uppercase filename prevents NuGet from recognizing the fake package on case-sensitive systems; the shared helper uses the required form attest/common/FakeNuGetPackage.cs:111.
File.WriteAllText(Path.Combine(metadataPath, $"{packageName}.nuspec"), $"""
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 4 out of 4 changed files in this pull request and generated 2 comments.
Suppressed comments (4)
Previously missed (1) — in code that hasn't changed since the last review.
packages/http-client-csharp/generator/Microsoft.TypeSpec.Generator/test/GeneratedCodeWorkspaceTests.cs:697
- NuGet's global-packages layout uses the normalized lowercase package ID for the manifest filename (
test/common/FakeNuGetPackage.cs:111). With names such asFirst.Package, this writesFirst.Package.nuspec; on case-sensitive systemsNuGetv3LocalRepository.FindPackagecannot find the fake package, so the exact-version tests fail. Normalize this filename too.
File.WriteAllText(Path.Combine(metadataPath, $"{packageName}.nuspec"), $"""
packages/http-client-csharp/generator/Microsoft.TypeSpec.Generator/test/GeneratedCodeWorkspaceTests.cs:477
- This local is never used, so it emits CS0219. Because
generator/Directory.Build.props:29treats warnings as errors, the test project will not compile; remove it.
var nugetCacheDir = Path.Combine(_tempDirectory!, "NuGetCache");
packages/http-client-csharp/generator/Microsoft.TypeSpec.Generator/test/GeneratedCodeWorkspaceTests.cs:180
- This fake package declares a real Azure.Core dependency even though the test only needs the package DLL. Since
NUGET_PACKAGESpoints to an empty temporary cache and the production path now runsdotnet restore, this forces the unit test to contact a NuGet feed and fail in offline/restricted environments. Keep the fake package dependency-free, astest/common/FakeNuGetPackage.cs:90-111does when no dependencies are requested.
<dependencies>
<group targetFramework="net10.0">
<dependency id="Azure.Core" version="1.61.0" exclude="Build,Analyzers" />
</group>
packages/http-client-csharp/generator/Microsoft.TypeSpec.Generator/test/GeneratedCodeWorkspaceTests.cs:715
- Every package created by this helper gains a real Azure.Core dependency. The tests now execute
dotnet restoreagainst an otherwise empty temporary cache, making them network-dependent even though none uses Azure.Core. Keep these fake packages dependency-free, matchingtest/common/FakeNuGetPackage.cs:90-111when no dependencies are requested.
<dependencies>
<group targetFramework="net10.0">
<dependency id="Azure.Core" version="1.61.0" exclude="Build,Analyzers" />
</group>
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 4 out of 4 changed files in this pull request and generated 1 comment.
Suppressed comments (4)
packages/http-client-csharp/generator/Microsoft.TypeSpec.Generator/src/Utilities/ExternalTypeReferenceResolver.cs:237
- Removing the download fallback makes package-backed external types fail on a clean machine whenever the package is not already represented by an existing
.csproj.CSharpGen.ExecuteAsyncinvokes this resolver before new-project scaffolding writes the project (CSharpGen.cs:34-42,165-168), soAddPackageReferencesFromProjectreturns early and nothing populates the cache. Keep a feed-resolution/download path driven byInputExternalTypeMetadata(including the stable/prerelease fallback rules), rather than relying exclusively on project restore.
string? assemblyPath = NugetPackageResolver.FindPackageAssembly(
globalPackagesFolder, external.Package!, external.MinVersion);
if (assemblyPath == null || !File.Exists(assemblyPath))
packages/http-client-csharp/generator/Microsoft.TypeSpec.Generator/src/PostProcessing/GeneratedCodeWorkspace.cs:372
- Parsing framework versions as
doubledoes not preserve TFM ordering. For example, supported TFMsnet48andnet472become0.48and4.72, sonet472is incorrectly selected as newer; multi-digit minor versions similarly misorder. Parse TFMs withNuGetFramework.ParseFolder/Versionsemantics and apply the intended framework-family precedence explicitly.
double current = 0.0;
Match numeral = Regex.Match(name, "\\d+[.]*\\d*$");
if (numeral.Success)
{
current = double.Parse(numeral.Value);
}
if (name.StartsWith("net4", StringComparison.InvariantCultureIgnoreCase))
{
current /= 100;
current += 2000.0;
packages/http-client-csharp/generator/Microsoft.TypeSpec.Generator/src/PostProcessing/GeneratedCodeWorkspace.cs:284
projectFileDependencyGroupscontains the declared dependency constraint, not the version NuGet actually selected. For the reported case it remainsPackage >= 3.0.0-alpha...even when restore falls forward to another version, so this method later looks for the unavailable minimum and discards the successfully restored package. Read the resolved package version from the selectedtargetsgraph (or use NuGet's lock-file model) while using this section only to identify direct dependencies.
if (prop.Value.ValueKind == JsonValueKind.Object && prop.NameEquals("projectFileDependencyGroups"))
packages/http-client-csharp/generator/Microsoft.TypeSpec.Generator/src/PostProcessing/GeneratedCodeWorkspace.cs:479
FindPackageAssemblyInVersiondeliberately chooses the asset nearest to the generator runtime (see NugetPackageResolver.cs:117-126), not the project target. Even for anetstandard2.0-only project this can register a package'snet8.0assembly, causing custom code to type-check against APIs unavailable in the generated project's target. Preserve the selected assets target and resolve the exact package version's assembly for that TFM (or add a separate exact compile-time lookup).
string? resolvedAssemblyPath = version is null
? NugetPackageResolver.FindPackageAssembly(globalPackagesFolder, refPackageName)
: NugetPackageResolver.FindPackageAssemblyInVersion(globalPackagesFolder, refPackageName, version);
| @@ -234,32 +234,6 @@ private static async Task<ResolutionResult> ResolveResultAsync(InputExternalType | |||
| string? assemblyPath = NugetPackageResolver.FindPackageAssembly( | |||
| globalPackagesFolder, external.Package!, external.MinVersion); | |||
There was a problem hiding this comment.
Please resolve this assembly from the version selected in the project assets graph rather than applying MinVersion to the entire cache again. AddPackageReferencesFromProject can add 2.5.0 from project.assets.json, but this call independently selects the highest cached version at or above the floor. With the project pinned to 2.5.0, minVersion 2.0.0, and 3.0.0 also cached, the resolver returns the type from 3.0.0. That makes reflection and generation use a different API surface from the SDK build and can mask a project version below the compatibility floor.
--generated by Copilot
| string[] packageVersionRelation = (packageAndVersion.GetString() ?? "").Split(); | ||
| // We only support the greater-than-or-equal relation. | ||
| // Example: "My.Package >= 1.1.1" | ||
| if (packageVersionRelation.Length == 3 && string.Equals(packageVersionRelation[1], ">=")) |
There was a problem hiding this comment.
Read the resolved package version and compile asset from the selected targets entry instead of parsing projectFileDependencyGroups. That section contains requested constraints. A restore of Azure.Core [1.50.0,1.62.0] produces Azure.Core >= 1.50.0 <= 1.62.0 here and Azure.Core/1.50.0 in targets; this three-token-only parser drops the dependency, after which the caller can select cached 1.62.0. Ranged and floating dependencies therefore still bind a different package than restore.
--generated by Copilot
| string? version = default; | ||
| hshNameVersion.TryGetValue(refPackageName.ToLower(), out version); | ||
| string? resolvedAssemblyPath = version is null | ||
| ? NugetPackageResolver.FindPackageAssembly(globalPackagesFolder, refPackageName) |
There was a problem hiding this comment.
This remains reproducible at the current head. AddPackageReferencesFromProject_ResolvesPackageWithNoVersion runs a project whose restore exits with NU1015, but execution continues and version being null makes the method load cached 4.2.0; the test passes. After any restore, MSBuild, or assets failure, return or skip instead of probing an unverified cache, otherwise generation can succeed against a package the project cannot build with.
--generated by Copilot
| Match numeral = Regex.Match(name, "\\d+[.]*\\d*$"); | ||
| if (numeral.Success) | ||
| { | ||
| current = double.Parse(numeral.Value); |
There was a problem hiding this comment.
This regression is present again at the current head. With CurrentCulture set to fr-FR, double.Parse throws FormatException for net8.0 at this line, so package-reference resolution fails on affected locales. Use InvariantCulture or compare parsed framework versions without double.
--generated by Copilot
| return hshFrameworks; | ||
| } | ||
|
|
||
| internal static async Task<string?> TryGetAssetsFile() |
There was a problem hiding this comment.
nit: can we use the .net pattern for TryGet here or rename the method to something else if we don't want to use that pattern ?
|
|
||
| internal static async Task<string?> TryGetAssetsFile() | ||
| { | ||
| string projectFilePath = Path.GetFullPath( |
There was a problem hiding this comment.
should we validate this file exists before we pass it to the process ?
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 4 out of 4 changed files in this pull request and generated 1 comment.
Suppressed comments (4)
packages/http-client-csharp/generator/Microsoft.TypeSpec.Generator/src/Utilities/ExternalTypeReferenceResolver.cs:21
- Removing the feed fallback makes this resolver cache-only, so it cannot implement the PR's stated missing-version behavior.
AddPackageReferencesFromProjectrestores only packages already present as<PackageReference>items; a package supplied solely byInputExternalTypeMetadatais not added there, andCSharpGeninvokes this resolver separately. Consequently the example package remains unresolved when absent from the cache, and the described stable/prerelease fallback never runs. The download/version-selection logic needs to remain in this resolver (including prerelease-aware latest-version selection).
/// looking up the package in the NuGet global cache and loading the assembly via reflection.
/// Used by <c>TypeFactory.CreateExternalType</c>
packages/http-client-csharp/generator/Microsoft.TypeSpec.Generator/src/PostProcessing/GeneratedCodeWorkspace.cs:305
projectFileDependencyGroupscontains the declared dependency constraint, not the version NuGet actually selected. If3.5.0is unavailable and restore resolves3.6.0, this value remainsPackage >= 3.5.0; the later exactFindPackageAssemblyInVersion(..., "3.5.0")lookup therefore misses the package that was just restored. Read the selected package identity/version from the chosen target (or NuGet's lock-file model) while using this group only to identify direct dependencies.
string[] packageVersionRelation = (packageAndVersion.GetString() ?? "").Split();
// We only support the greater-than-or-equal relation.
// Example: "My.Package >= 1.1.1"
if (packageVersionRelation.Length == 3 && string.Equals(packageVersionRelation[1], ">="))
{
hshFrameworks[currentFramework.Framework][packageVersionRelation[0].ToLower()] = packageVersionRelation[2];
packages/http-client-csharp/generator/Microsoft.TypeSpec.Generator/test/GeneratedCodeWorkspaceTests.cs:180
- This fake assembly does not reference
Azure.Core, but its new nuspec declares that real dependency. Because the test isolatesNUGET_PACKAGESand the production path now runsdotnet restore, the test must contact a feed forAzure.Coreand may fail—or bypass the assets-file path—offline. Keep the fake package hermetic by declaring no dependencies, as the shared helper does intest/common/FakeNuGetPackage.cs:84-126.
<dependencies>
<group targetFramework="net10.0">
<dependency id="Azure.Core" version="1.61.0" exclude="Build,Analyzers" />
</group>
packages/http-client-csharp/generator/Microsoft.TypeSpec.Generator/test/GeneratedCodeWorkspaceTests.cs:715
- Every package produced by this helper now declares an unused real
Azure.Coredependency. Since these tests use an isolated package cache and calldotnet restore, that makes their success depend on remote feed availability instead of remaining hermetic. Use an empty dependency set (or the existingFakeNuGetPackage.Createhelper intest/common/FakeNuGetPackage.cs:41-76).
<dependencies>
<group targetFramework="net10.0">
<dependency id="Azure.Core" version="1.61.0" exclude="Build,Analyzers" />
</group>
There was a problem hiding this comment.
🟡 Changes recommended
The fallback behavior is incomplete, first-time generation can no longer resolve external packages, and several new tests are invalid or non-hermetic.
Once you've addressed the issues Copilot identified, you can request another Copilot review.
Review details
Suppressed comments (5)
packages/http-client-csharp/generator/Microsoft.TypeSpec.Generator/src/Utilities/ExternalTypeReferenceResolver.cs:261
- This branch returns immediately when the project's resolved version is below
MinVersion, which contradicts the stated fallback sequence: it should first tryMinVersion, then the latest eligible version, and finally an already available version. The newTryResolve_ReturnsNullForHigherMinVersiontest currently codifies the opposite behavior. Keep the NuGet download/version-selection fallback here instead of caching a terminal failure.
if (!versionAcceptable)
{
var versionQualifier = string.IsNullOrEmpty(external.MinVersion)
? string.Empty
: $"(>= {external.MinVersion})";
return CacheResult(state, key, new ResolutionResult(
null,
$"The package '{external.Package}' minimal version declared in a typespec {versionQualifier} is higher then the one defined in project dependencies \"{packageInfo.PackageVersion}\"."));
packages/http-client-csharp/generator/Microsoft.TypeSpec.Generator/src/Utilities/ExternalTypeReferenceResolver.cs:271
- Resolution now fails whenever the package was not already added from the project. This breaks first-time
--new-projectgeneration:AddPackageReferencesFromProjectreturns because the csproj does not exist yet, andCSharpGenonly writes that csproj at the end of generation (lines 165-168). Preserve a direct NuGet resolution fallback based onexternal.Package/MinVersionbefore reporting the package missing.
if (packageInfo.AssemblyPath == null || !File.Exists(packageInfo.AssemblyPath) || !versionAcceptable)
{
var versionQualifier = string.IsNullOrEmpty(external.MinVersion)
? string.Empty
: $" (>= {external.MinVersion})";
return CacheResult(state, key, new ResolutionResult(
null,
$"package '{external.Package}'{versionQualifier} is not present in package dependencies."));
packages/http-client-csharp/generator/Microsoft.TypeSpec.Generator/test/GeneratedCodeWorkspaceTests.cs:186
- This fake package now depends on a real Azure.Core version even though its emitted source does not use Azure.Core. Since the test switches
NUGET_PACKAGESto a fresh directory and then runsdotnet restore, it must contact external feeds, making the unit test network/version dependent. Use the hermeticFakeNuGetPackage.Createpattern (test/common/FakeNuGetPackage.cs:41-76) with a locally created fake dependency, or omit this dependency.
<dependencies>
<group targetFramework="net10.0">
<dependency id="Azure.Core" version="1.61.0" exclude="Build,Analyzers" />
</group>
<group targetFramework="net8.0">
<dependency id="Azure.Core" version="1.61.0" exclude="Build,Analyzers" />
</group>
<group targetFramework=".NETStandard2.0">
<dependency id="Azure.Core" version="1.61.0" exclude="Build,Analyzers" />
</group>
packages/http-client-csharp/generator/Microsoft.TypeSpec.Generator/test/GeneratedCodeWorkspaceTests.cs:816
- This duplicated fake nuspec also introduces a real Azure.Core dependency into tests that run
dotnet restoreagainst a fresh package cache. That makes these unit cases depend on external feed availability. Followtest/common/FakeNuGetPackage.cs:41-76and create all needed packages locally, or remove the unused dependency declaration.
<dependencies>
<group targetFramework="net10.0">
<dependency id="Azure.Core" version="1.61.0" exclude="Build,Analyzers" />
</group>
<group targetFramework="net8.0">
<dependency id="Azure.Core" version="1.61.0" exclude="Build,Analyzers" />
</group>
<group targetFramework=".NETStandard2.0">
<dependency id="Azure.Core" version="1.61.0" exclude="Build,Analyzers" />
</group>
packages/http-client-csharp/generator/Microsoft.TypeSpec.Generator/test/GeneratedCodeWorkspaceTests.cs:792
- NuGet's global-packages layout uses the normalized lowercase package ID for the nuspec filename. Writing
First.Package.nuspecon a case-sensitive filesystem meansNuGetv3LocalRepository.FindPackagemay not recognize this fake package, causing the new restore-based tests to fail on Linux. Normalize the filename as the sharedFakeNuGetPackagehelper does.
File.WriteAllText(Path.Combine(metadataPath, $"{packageName}.nuspec"), $"""
- Files reviewed: 5/5 changed files
- Comments generated: 2
- Review effort level: Balanced
| string[] packageVersion = packageAndVersion.Name.Split('/'); | ||
| if (packageVersion.Length == 2) | ||
| { | ||
| hshFrameworks[currentFramework.GetShortFolderName()][packageVersion[0].ToLower()] = packageVersion[1]; | ||
| } |
| } | ||
| var csprojContent = $@"<Project Sdk=""Microsoft.NET.Sdk""> | ||
| <PropertyGroup> | ||
| <TargetFramework>netstandard2.0,net10.0</TargetFramework> |
Problem: Assume, we have the external assembly defined in a typespec as follows:
If the version 3.0.0-alpha.20260820.5 is not present in the repository, the
ExternalTypeReferenceResolverwill not download the needed assembly and the one already present will be used. This will result in some classes not being found as by default the latest stable version is being downloaded.Solution: Currently, the external package is resolved as follows:
In this PR we are adding more logic: