Skip to content

Conversation

Copy link
Contributor

Copilot AI commented Oct 16, 2025

  • Fix AddSdkResolvedEnvironmentVariable in ProjectInstance.cs to allow SDK env vars to override ambient env vars
  • Fix AddSdkResolvedEnvironmentVariable in Project.cs to allow SDK env vars to override ambient env vars
  • Add null parameter validation in both ProjectInstance.cs and Project.cs AddSdkResolvedEnvironmentVariable methods
  • Fix SdkResult.Translate to serialize _environmentVariablesToAdd for out-of-proc scenarios
  • Update SdkResult.Equals and GetHashCode to include _environmentVariablesToAdd
  • Add new resource string for logging when SDK overrides ambient env var
  • Add new test to verify SDK env vars override ambient env vars
  • Add new test to verify first SDK wins over subsequent SDKs
  • Build and test the changes - all 14 SdkResultEvaluation tests passing
  • Final validation and testing complete

Summary

This PR implements the feature requested in the issue where SdkResolver-provided environment variables now take precedence over ambient environment variables from the host process.

Changes Made:

  1. ProjectInstance.cs: Modified AddSdkResolvedEnvironmentVariable to:

    • Add null parameter validation for name and value using ErrorUtilities
    • Remove the check that prevented SDK env vars from overriding ambient env vars
    • Remove ambient env vars from the _environmentVariableProperties dictionary when SDK sets them
    • Log when an SDK env var overrides an ambient one
  2. Project.cs: Modified AddSdkResolvedEnvironmentVariable to:

    • Add null parameter validation for name and value using ErrorUtilities
    • Remove the check that prevented SDK env vars from overriding ambient env vars
    • Always call SetProperty to override ambient values
  3. SdkResult.cs: Fixed serialization bug by:

    • Adding _environmentVariablesToAdd to the Translate method
    • Updating Equals method to compare _environmentVariablesToAdd
    • Updating GetHashCode to include _environmentVariablesToAdd
  4. Strings.resx: Added new log message "SdkEnvironmentVariableOverridingAmbient"

  5. Tests: Added two new tests:

    • SdkResolverEnvironmentVariablesOverrideAmbientEnvironmentVariables: Verifies SDK values override ambient env vars
    • FirstSdkEnvironmentVariableWinsOverSubsequentSdks: Verifies first SDK wins among multiple SDKs

Behavior:

  • SDK env vars > Ambient env vars: SDK-resolved environment variables now override any ambient environment variables
  • First SDK wins: Among multiple SDKs, the first one to set an environment variable wins
  • XML properties still prioritized: Regular properties defined in XML are still not overridden by SDK env vars
  • Null parameters rejected: Both name and value parameters are validated to prevent null values

All existing SdkResultEvaluation tests pass, confirming backward compatibility is maintained.

Original prompt

This section details on the original issue you should resolve

<issue_title>SdkResolver-provided env vars should take precedence over the ambient environment</issue_title>
<issue_description>### Summary

Today the SdkResolver system can provide environment variables to the engine when an SDK is resolved. The primary usage of this feature is

  • to keep invocations of the SDK unified across MSBuild-driven tooling via the DOTNET_HOST_PATH environment variable
  • to drive usage of the .NET TaskHost feature for spawning .NET-targeted MSBuild tasks in a .NET TaskHost from a .NET Framework central node

However, the variables provided by this mechanism are currently overridden by ambient environment variables taken from the snapshot of the host process at the time the build is started. This means that external processes can override the SdkResolver's decisions.

Background and Motivation

Internal users are having some churn in mixed VS installs and need to set DOTNET_HOST_PATH in older VS environments to mitigate that churn, but want to defer to this feature in dev18 onwards by default.

Proposed Feature

We want the resolver to be the complete source of truth, so we should change the way the SdkResolver env vars are applied to the overall environmental state. The SdkResolver env vars should override any ambient env vars.

We need to make this change, update the existing tests, and add new tests pinning this behavior.

Alternative Designs

No response</issue_description>

Comments on the Issue (you are @copilot in this section)

Fixes #12654


✨ Let Copilot coding agent set things up for you — coding agent works faster and does higher quality work when set up for your repo.

@dotnet-policy-service
Copy link
Contributor

Hello @@copilot, I noticed that you’re changing an .swr file or any file under src/Package/MSBuild.VSSetup.. Please make sure to validate this change by an experimental VS insertion. This is accomplished by pushing to an exp/* branch, which requires write permissions to this repo.

Copilot AI changed the title [WIP] Fix SdkResolver environment vars precedence over ambient variables Make SdkResolver-provided environment variables take precedence over ambient environment Oct 16, 2025
Copilot AI requested a review from baronfel October 16, 2025 20:01
@baronfel
Copy link
Member

The package vuln thing that's plaguing other builds is hitting this one too, so it's hard to tell if this change actually passes tests.

@baronfel baronfel force-pushed the copilot/fix-env-vars-precedence-issue branch from c24c943 to 5b852f6 Compare October 20, 2025 15:14
@baronfel baronfel marked this pull request as ready for review October 20, 2025 16:10
Copilot AI review requested due to automatic review settings October 20, 2025 16:10
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

This PR fixes the precedence order for SDK resolver environment variables, making them override ambient environment variables from the host process as originally intended, rather than being overridden by them.

Key Changes:

  • Modified ProjectInstance.cs and Project.cs to allow SDK-resolved environment variables to override ambient environment variables
  • Fixed a serialization bug in SdkResult.cs where _environmentVariablesToAdd wasn't being translated for out-of-proc scenarios
  • Added logging when SDK variables override ambient ones through a new resource string SdkEnvironmentVariableOverridingAmbient

Reviewed Changes

Copilot reviewed 18 out of 18 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
ProjectInstance.cs Removed check preventing SDK env vars from overriding ambient vars; added logic to remove conflicting ambient vars and log overrides
Project.cs Removed check preventing SDK env vars from overriding ambient vars; SDK values now always override ambient values
SdkResult.cs Fixed serialization bug by adding translation for _environmentVariablesToAdd; updated Equals and GetHashCode to include the field
Strings.resx Added new log message resource string for SDK variable overrides
Strings.*.xlf Added translations (marked as "new") for the new log message across all localization files
SdkResultEvaluation_Tests.cs Added two tests verifying SDK env vars override ambient vars and first SDK wins when multiple SDKs set the same variable

Comment on lines +1411 to +1414
// Set the property, overriding ambient environment variables but not regular properties defined in XML.
// If we're overriding an ambient variable, or if the property doesn't exist, set it.
// Otherwise, prioritize regular properties defined in XML.
if (overridingAmbient || GetProperty(name) is null)
Copy link

Copilot AI Oct 20, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The logic in the conditional at line 1414 needs clarification. When overridingAmbient is true, GetProperty(name) will never return null because the ambient property already exists (it was just removed from _environmentVariableProperties). This means the GetProperty(name) is null check is only meaningful when overridingAmbient is false. Consider simplifying this to make the logic clearer, such as checking GetProperty(name) is null first, then handling the override case separately.

Copilot uses AI. Check for mistakes.
StringComparer.OrdinalIgnoreCase.Equals(_version, result._version) &&
_additionalPaths?.Count == result._additionalPaths?.Count &&
_propertiesToAdd?.Count == result._propertiesToAdd?.Count &&
_itemsToAdd?.Count == result._propertiesToAdd?.Count &&
Copy link

Copilot AI Oct 20, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The equality check is comparing _itemsToAdd?.Count with result._propertiesToAdd?.Count instead of result._itemsToAdd?.Count. This is a copy-paste error that makes the equality comparison incorrect.

Suggested change
_itemsToAdd?.Count == result._propertiesToAdd?.Count &&
_itemsToAdd?.Count == result._itemsToAdd?.Count &&

Copilot uses AI. Check for mistakes.
// Only set the local property if it does not already exist, prioritizing regular properties defined in XML.
if (GetProperty(name) is null)
// SDK-resolved environment variables override ambient environment variables.
bool overridingAmbient = _environmentVariableProperties.Contains(name);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is null-check needed?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@copilot ensure that null environment variable names are handled in the Project and ProjectInstance handling

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added null checks for both name and value parameters in AddSdkResolvedEnvironmentVariable methods in ProjectInstance.cs and Project.cs. The validation uses ErrorUtilities.VerifyThrowArgumentLength(name) and ErrorUtilities.VerifyThrowArgumentNull(value) to match the pattern used in other MSBuild property-setting methods. (commit c24c943 updated)

Copilot AI requested a review from baronfel October 21, 2025 20:04
Copilot finished work on behalf of baronfel October 21, 2025 20:04
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants