Skip to content

Commit db114bd

Browse files
Use environment variable for CachePlugins feature flag
- Changed from static dictionary to environment variable check (MSBUILD_CACHEPLUGINS_DISABLED) - VS can now control the feature via remote flag by setting the environment variable - Updated tests to use environment variable instead of SetFeatureAvailability - Follows the same pattern as other MSBuild features like MSBUILD_TELEMETRY_OPTOUT - All 100 project cache tests pass Co-authored-by: YuliiaKovalova <[email protected]>
1 parent 70d613e commit db114bd

File tree

2 files changed

+51
-48
lines changed

2 files changed

+51
-48
lines changed

src/Build.UnitTests/ProjectCache/ProjectCacheTests.cs

Lines changed: 37 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -1753,14 +1753,13 @@ static void Main()
17531753
[Fact]
17541754
public void CachePluginsFeatureFlagDisablesCache()
17551755
{
1756-
// This test verifies that when the CachePlugins feature is disabled,
1756+
// This test verifies that when the CachePlugins feature is disabled via environment variable,
17571757
// the cache plugin is not used even when configured.
17581758

1759+
_env.SetEnvironmentVariable("MSBUILD_CACHEPLUGINS_DISABLED", "1");
1760+
17591761
try
17601762
{
1761-
// Disable the cache plugins feature
1762-
Framework.Features.SetFeatureAvailability("CachePlugins", Framework.FeatureStatus.NotAvailable);
1763-
17641763
var testData = new GraphCacheResponse(
17651764
new Dictionary<int, int[]?>
17661765
{
@@ -1802,8 +1801,7 @@ public void CachePluginsFeatureFlagDisablesCache()
18021801
}
18031802
finally
18041803
{
1805-
// Restore the feature to its default state
1806-
Framework.Features.ResetFeatureStatusForTests();
1804+
_env.SetEnvironmentVariable("MSBUILD_CACHEPLUGINS_DISABLED", null);
18071805
}
18081806
}
18091807

@@ -1813,55 +1811,47 @@ public void CachePluginsFeatureFlagEnabled()
18131811
// This test verifies that when the CachePlugins feature is enabled (default),
18141812
// the cache plugin is used as expected.
18151813

1816-
try
1817-
{
1818-
// Explicitly enable the cache plugins feature (though it should be enabled by default)
1819-
Framework.Features.SetFeatureAvailability("CachePlugins", Framework.FeatureStatus.Available);
1820-
1821-
var testData = new GraphCacheResponse(
1822-
new Dictionary<int, int[]?>
1823-
{
1824-
{1, null}
1825-
},
1826-
new Dictionary<int, CacheResult>
1827-
{
1828-
{1, GraphCacheResponse.SuccessfulProxyTargetResult()}
1829-
});
1830-
1831-
var graph = testData.CreateGraph(_env);
1814+
// Ensure the environment variable is not set (feature enabled by default)
1815+
_env.SetEnvironmentVariable("MSBUILD_CACHEPLUGINS_DISABLED", null);
18321816

1833-
var mockCache = new InstanceMockCache(testData);
1834-
1835-
var buildParameters = new BuildParameters
1817+
var testData = new GraphCacheResponse(
1818+
new Dictionary<int, int[]?>
18361819
{
1837-
ProjectCacheDescriptor = ProjectCacheDescriptor.FromInstance(mockCache)
1838-
};
1839-
1840-
MockLogger logger;
1841-
GraphBuildResult graphResult;
1842-
using (var buildSession = new Helpers.BuildManagerSession(_env, buildParameters))
1820+
{1, null}
1821+
},
1822+
new Dictionary<int, CacheResult>
18431823
{
1844-
logger = buildSession.Logger;
1845-
graphResult = buildSession.BuildGraph(graph);
1846-
}
1824+
{1, GraphCacheResponse.SuccessfulProxyTargetResult()}
1825+
});
18471826

1848-
graphResult.OverallResult.ShouldBe(BuildResultCode.Success);
1827+
var graph = testData.CreateGraph(_env);
18491828

1850-
// Verify that cache WAS used (plugin methods were called)
1851-
mockCache.BeginBuildCalled.ShouldBeTrue("BeginBuildAsync should be called when feature is enabled");
1852-
mockCache.Requests.ShouldNotBeEmpty("GetCacheResultAsync should be called when feature is enabled");
1853-
mockCache.EndBuildCalled.ShouldBeTrue("EndBuildAsync should be called when feature is enabled");
1829+
var mockCache = new InstanceMockCache(testData);
18541830

1855-
// The build should have succeeded using the cache
1856-
logger.FullLog.ShouldContain("MockCache: BeginBuildAsync");
1857-
logger.FullLog.ShouldContain("MockCache: GetCacheResultAsync");
1858-
logger.FullLog.ShouldContain("MockCache: EndBuildAsync");
1859-
}
1860-
finally
1831+
var buildParameters = new BuildParameters
18611832
{
1862-
// Restore the feature to its default state
1863-
Framework.Features.ResetFeatureStatusForTests();
1833+
ProjectCacheDescriptor = ProjectCacheDescriptor.FromInstance(mockCache)
1834+
};
1835+
1836+
MockLogger logger;
1837+
GraphBuildResult graphResult;
1838+
using (var buildSession = new Helpers.BuildManagerSession(_env, buildParameters))
1839+
{
1840+
logger = buildSession.Logger;
1841+
graphResult = buildSession.BuildGraph(graph);
18641842
}
1843+
1844+
graphResult.OverallResult.ShouldBe(BuildResultCode.Success);
1845+
1846+
// Verify that cache WAS used (plugin methods were called)
1847+
mockCache.BeginBuildCalled.ShouldBeTrue("BeginBuildAsync should be called when feature is enabled");
1848+
mockCache.Requests.ShouldNotBeEmpty("GetCacheResultAsync should be called when feature is enabled");
1849+
mockCache.EndBuildCalled.ShouldBeTrue("EndBuildAsync should be called when feature is enabled");
1850+
1851+
// The build should have succeeded using the cache
1852+
logger.FullLog.ShouldContain("MockCache: BeginBuildAsync");
1853+
logger.FullLog.ShouldContain("MockCache: GetCacheResultAsync");
1854+
logger.FullLog.ShouldContain("MockCache: EndBuildAsync");
18651855
}
18661856
}
18671857
}

src/Framework/Features.cs

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,6 @@ private static Dictionary<string, FeatureStatus> CreateDefaultFeatureStatusMap()
4343
return new Dictionary<string, FeatureStatus>
4444
{
4545
{ "BuildCheck.Beta", FeatureStatus.Preview },
46-
{ "CachePlugins", FeatureStatus.Available }, // Project cache plugins (e.g., Quickbuild) are enabled by default but can be remotely disabled.
4746
{ "EvaluationContext_SharedSDKCachePolicy", FeatureStatus.Available }, // EvaluationContext supports the SharingPolicy.SharedSDKCache flag.
4847
{ "TerminalLogger_MultiLineHandler", FeatureStatus.Available }, // TerminalLogger has better explicit support for rendering multi-line messages
4948
// Add more features here.
@@ -57,6 +56,20 @@ private static Dictionary<string, FeatureStatus> CreateDefaultFeatureStatusMap()
5756
/// <returns>A feature status <see cref="FeatureStatus"/>.</returns>
5857
public static FeatureStatus CheckFeatureAvailability(string featureName)
5958
{
59+
// Special handling for CachePlugins feature - controlled via environment variable
60+
// This allows remote feature flags in VS to disable cache plugins by setting the environment variable
61+
if (featureName == "CachePlugins")
62+
{
63+
string? envValue = System.Environment.GetEnvironmentVariable("MSBUILD_CACHEPLUGINS_DISABLED");
64+
if (!string.IsNullOrEmpty(envValue) &&
65+
(envValue.Equals("1", System.StringComparison.OrdinalIgnoreCase) ||
66+
envValue.Equals("true", System.StringComparison.OrdinalIgnoreCase)))
67+
{
68+
return FeatureStatus.NotAvailable;
69+
}
70+
return FeatureStatus.Available;
71+
}
72+
6073
return _featureStatusMap.TryGetValue(featureName, out FeatureStatus status) ?
6174
status : FeatureStatus.Undefined;
6275
}

0 commit comments

Comments
 (0)