⚠ This doc is intended for internal teams. For information about how to deal with MSBuild Change Waves as an MSBuild user, see ChangeWaves.md.
A Change Wave is a set of risky features developed under the same opt-out flag. The purpose of this is to warn developers of risky changes that will become standard functionality down the line. If there's something we think is worth the risk, we found that Change Waves were a good middle ground between making necessary changes and warning customers of what will soon be permanent.
Opt-out is a better approach for us because we'd likely get limited feedback when a feature impacts customer builds. When a feature does impact a customer negatively, it's a quick switch to disable and allows time to adapt. The key aspect to Change Waves is that it smooths the transition for customers adapting to risky changes that the MSBuild team feels strongly enough to take.
The opt-out comes in the form of setting the environment variable MSBUILDDISABLEFEATURESFROMVERSION
to the Change Wave (or version) that contains the feature you want disabled. This version happens to be the version of MSBuild that the features were developed for. See the mapping of change waves to features below.
This is determined on a case by case basis and should be discussed with the MSBuild team. A safe bet would be to check our currently active Change Waves and pick the version after the latest MSBuild version. This version corresponds to the latest version of Visual Studio.
Change Wave features should match the LTS version of VS they were released with. Any feature requiring a changewave during a non-LTS release of VS should use the NEXT version number.
For the purpose of providing an example, the rest of this document assumes we're developing a feature for MSBuild version 17.3.
The Process:
- Develop your feature.
- Create the Change Wave (if necessary)
- Condition your feature on that Change Wave
- Test your feature
- Document it
- Delete the wave as it cycles out
- In the
Microsoft.Build.Framework
project, openChangeWaves.cs
. - Add a static readonly Version to identify the new wave, following the format:
public static readonly Version Wave17_4 = new Version(17, 4);
- You may need to delete the lowest wave as new waves get added.
- Update the AllWaves array appropriately.
public static readonly Version[] AllWaves = { Wave17_0, Wave17_2, Wave17_4 };
Surround your feature with the following:
// If you pass an incorrectly formatted change wave, this will throw.
// Use the readonly Version that was created in the previous step.
if (ChangeWaves.AreFeaturesEnabled(ChangeWaves.Wave17_4))
{
<your feature>
}
If you need to condition a Task or Target, use the built in AreFeaturesEnabled
function.
<Target Name="SomeRiskyChange" Condition="$([MSBuild]::AreFeaturesEnabled('17.4'))">
<!-- Where '17.4' is the change wave assigned to your feature. -->
Create tests as you normally would. Include one test with environment variable MSBUILDDISABLEFEATURESFROMVERSION
set to ChangeWaves.Wave17_4
. Set this like so:
using TestEnvironment env = TestEnvironment.Create();
ChangeWaves.ResetStateForTests();
// Important: use the version here
env.SetEnvironmentVariable("MSBUILDDISABLEFEATURESFROMVERSION", ChangeWaves.Wave17_4.ToString());
BuildEnvironmentHelper.ResetInstance_ForUnitTestsOnly();
Important! If you need to build a project to test your feature (say, for tasks or targets), build via ProjectCollection
in your test.
Example:
using (TestEnvironment env = TestEnvironment.Create())
{
ChangeWaves.ResetStateForTests();
env.SetEnvironmentVariable("MSBUILDDISABLEFEATURESFROMVERSION", ChangeWaves.Wave17_4.ToString());
BuildEnvironmentHelper.ResetInstance_ForUnitTestsOnly();
string projectFile = @"
<Project>
<Target Name='HelloWorld' Condition=""$([MSBuild]::AreFeaturesEnabled('17.4'))"">
<Message Text='Hello World!'/>
</Target>
</Project>";
TransientTestFile file = env.CreateFile("proj.csproj", projectFile);
ProjectCollection collection = new ProjectCollection();
MockLogger log = new MockLogger();
collection.RegisterLogger(log);
collection.LoadProject(file.Path).Build().ShouldBeTrue();
log.AssertLogContains("Hello World!");
}
These features will eventually become standard functionality. When a change wave rotates out, do the following:
- Start by deleting the readonly
Wave17_4
that was created in Creating a Change Wave. - Remove
ChangeWave.AreFeaturesEnabled
or[MSBuild]::AreFeaturesEnabled
conditions surrounding features that were assigned that change wave. - Remove tests associated with ensuring features would not run if this wave were set.
- Clear all other issues that arose from deleting the version.