Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adding the client code for supporting experiments #5034

Open
wants to merge 15 commits into
base: master
Choose a base branch
from
10 changes: 10 additions & 0 deletions doc/admx/DesktopAppInstaller.admx
Copy link
Member

Choose a reason for hiding this comment

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

I imagine there is already a policy to disable experimentation across Windows as a whole. I found AllowExperimentation but I'm not sure if it does what I think.

If there is such a policy, I think we would be better off not having our own and just pointing people to that one. If somebody disables it system-wide, then our policy won't do anything because the infrastructure we use will be disabled. The only case where it would be useful to have both is if somebody wants to have experimentation in Windows as a whole, but not on winget specifically, which I don't think is a common scenario

Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,16 @@
<decimal value="0" />
</disabledValue>
</policy>
<policy name="EnableExperiments" class="Machine" displayName="$(string.EnableExperiments)" explainText="$(string.EnableExperimentsExplanation)" key="Software\Policies\Microsoft\Windows\AppInstaller" valueName="EnableExperiments">
<parentCategory ref="AppInstaller" />
<supportedOn ref="windows:SUPPORTED_Windows_10_0_RS5" />
<enabledValue>
<decimal value="1" />
</enabledValue>
<disabledValue>
<decimal value="0" />
</disabledValue>
</policy>
<policy name="EnableLocalManifestFiles" class="Machine" displayName="$(string.EnableLocalManifestFiles)" explainText="$(string.EnableLocalManifestFilesExplanation)" key="Software\Policies\Microsoft\Windows\AppInstaller" valueName="EnableLocalManifestFiles">
<parentCategory ref="AppInstaller" />
<supportedOn ref="windows:SUPPORTED_Windows_10_0_RS5" />
Expand Down
6 changes: 6 additions & 0 deletions doc/admx/en-US/DesktopAppInstaller.adml
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,12 @@ If you disable this setting, users will not be able to change settings for the W
If you enable or do not configure this setting, users will be able to enable experimental features for the Windows Package Manager.

If you disable this setting, users will not be able to enable experimental features for the Windows Package Manager.</string>
<string id="EnableExperiments">Enable Windows Package Manager Experiments</string>
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Adding @RDMacLachlan to help with the strings to be used in the adml file

Copy link
Member

Choose a reason for hiding this comment

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

I would suggest the policy be called "Allow" instead of "Enable" even if it is not consistent with the other policies.
To me, "Enable" means that the experiments will be turned on but that's not what happens. What happens is that experiments may be turned on depending on the control/treatment groups; which is better described by "Allow"

It probably should also mention that they are Microsoft-run experiments for new features/changes

<string id="EnableExperimentsExplanation">This policy controls whether users can enable experiments in the Windows Package Manager.
Copy link
Member

Choose a reason for hiding this comment

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

We may need to expand on what an experiment is, and how it differs from an experimental feature, so that IT admins can make the decision

Copy link
Contributor Author

Choose a reason for hiding this comment

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

+1 this is a placeholder text I added and will be replaced by PM's suggestion 😊

Copy link
Contributor

Choose a reason for hiding this comment

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

I would use "Experimentation" rather than "Experiments"

The policy controls whether users can have experiments run in WinGet on their device.

Copy link
Member

Choose a reason for hiding this comment

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

Does the policy control:

  1. experimentation all up
  2. experiment state being driven externally
  3. user control over experiment state

This string seems to indicate only 3, but my expectation would be either 1 or 2.


If you enable or do not configure this setting, users will be able to enable experiments for the Windows Package Manager.

If you disable this setting, users will not be able to enable experiments for the Windows Package Manager.</string>
<string id="EnableLocalManifestFiles">Enable Windows Package Manager Local Manifest Files</string>
<string id="EnableLocalManifestFilesExplanation">This policy controls whether users can install packages with local manifest files.

Expand Down
55 changes: 52 additions & 3 deletions src/AppInstallerCLI.sln
Original file line number Diff line number Diff line change
Expand Up @@ -212,6 +212,12 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Microsoft.Management.Deploy
{2B00D362-AC92-41F3-A8D2-5B1599BDCA01} = {2B00D362-AC92-41F3-A8D2-5B1599BDCA01}
EndProjectSection
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Internal", "Internal", "{800529ED-3374-49C4-BAD1-9B27647E4359}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Experiment", "Experiment", "{13E55125-0ABF-4975-9B5B-DD6E5527D47F}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Experiment", "Internal\Experiment\Experiment.vcxproj", "{98920AB6-27B0-4C0F-B336-FA49DE57A1BA}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.Management.Deployment.CsWinRTProjection", "Microsoft.Management.Deployment.CsWinRTProjection\Microsoft.Management.Deployment.CsWinRTProjection.csproj", "{9406322E-6272-487E-902A-9953889719EA}"
EndProject
Global
Expand Down Expand Up @@ -1072,7 +1078,9 @@ Global
{1F56BECB-D65D-4BBA-8788-6671B251392A}.ReleaseStatic|x86.Build.0 = ReleaseStatic|Any CPU
{1F56BECB-D65D-4BBA-8788-6671B251392A}.TestRelease|ARM64.ActiveCfg = Release|Any CPU
{1F56BECB-D65D-4BBA-8788-6671B251392A}.TestRelease|x64.ActiveCfg = Release|Any CPU
{1F56BECB-D65D-4BBA-8788-6671B251392A}.TestRelease|x64.Build.0 = Release|Any CPU
{1F56BECB-D65D-4BBA-8788-6671B251392A}.TestRelease|x86.ActiveCfg = Release|Any CPU
{1F56BECB-D65D-4BBA-8788-6671B251392A}.TestRelease|x86.Build.0 = Release|Any CPU
{167F634B-A3AD-494E-8E67-B888103E35FF}.Debug|ARM64.ActiveCfg = Debug|Any CPU
{167F634B-A3AD-494E-8E67-B888103E35FF}.Debug|ARM64.Build.0 = Debug|Any CPU
{167F634B-A3AD-494E-8E67-B888103E35FF}.Debug|x64.ActiveCfg = Debug|Any CPU
Expand Down Expand Up @@ -1162,20 +1170,29 @@ Global
{52EC37D6-088C-40D3-AD0B-BDE8F8DAF9EB}.Release|x86.ActiveCfg = Release|Any CPU
{52EC37D6-088C-40D3-AD0B-BDE8F8DAF9EB}.Release|x86.Build.0 = Release|Any CPU
{52EC37D6-088C-40D3-AD0B-BDE8F8DAF9EB}.ReleaseStatic|ARM64.ActiveCfg = Release|Any CPU
{52EC37D6-088C-40D3-AD0B-BDE8F8DAF9EB}.ReleaseStatic|ARM64.Build.0 = Release|Any CPU
{52EC37D6-088C-40D3-AD0B-BDE8F8DAF9EB}.ReleaseStatic|x64.ActiveCfg = Release|Any CPU
{52EC37D6-088C-40D3-AD0B-BDE8F8DAF9EB}.ReleaseStatic|x64.Build.0 = Release|Any CPU
{52EC37D6-088C-40D3-AD0B-BDE8F8DAF9EB}.ReleaseStatic|x86.ActiveCfg = Release|Any CPU
{52EC37D6-088C-40D3-AD0B-BDE8F8DAF9EB}.ReleaseStatic|x86.Build.0 = Release|Any CPU
{52EC37D6-088C-40D3-AD0B-BDE8F8DAF9EB}.TestRelease|ARM64.ActiveCfg = Release|Any CPU
{52EC37D6-088C-40D3-AD0B-BDE8F8DAF9EB}.TestRelease|ARM64.Build.0 = Release|Any CPU
{52EC37D6-088C-40D3-AD0B-BDE8F8DAF9EB}.TestRelease|x64.ActiveCfg = Release|Any CPU
{52EC37D6-088C-40D3-AD0B-BDE8F8DAF9EB}.TestRelease|x64.Build.0 = Release|Any CPU
{52EC37D6-088C-40D3-AD0B-BDE8F8DAF9EB}.TestRelease|x86.ActiveCfg = Release|Any CPU
{52EC37D6-088C-40D3-AD0B-BDE8F8DAF9EB}.TestRelease|x86.Build.0 = Release|Any CPU
{272B2B0E-40D4-4F0F-B187-519A6EF89B10}.Debug|ARM64.ActiveCfg = Debug|Any CPU
{272B2B0E-40D4-4F0F-B187-519A6EF89B10}.Debug|ARM64.Build.0 = Debug|Any CPU
{272B2B0E-40D4-4F0F-B187-519A6EF89B10}.Debug|x64.ActiveCfg = Debug|Any CPU
{272B2B0E-40D4-4F0F-B187-519A6EF89B10}.Debug|x64.Build.0 = Debug|Any CPU
{272B2B0E-40D4-4F0F-B187-519A6EF89B10}.Debug|x86.ActiveCfg = Debug|Any CPU
{272B2B0E-40D4-4F0F-B187-519A6EF89B10}.Debug|x86.Build.0 = Debug|Any CPU
{272B2B0E-40D4-4F0F-B187-519A6EF89B10}.Fuzzing|ARM64.ActiveCfg = Release|Any CPU
{272B2B0E-40D4-4F0F-B187-519A6EF89B10}.Fuzzing|x64.ActiveCfg = Release|Any CPU
{272B2B0E-40D4-4F0F-B187-519A6EF89B10}.Fuzzing|x86.ActiveCfg = Release|Any CPU
{272B2B0E-40D4-4F0F-B187-519A6EF89B10}.Fuzzing|ARM64.ActiveCfg = Debug|Any CPU
{272B2B0E-40D4-4F0F-B187-519A6EF89B10}.Fuzzing|ARM64.Build.0 = Debug|Any CPU
{272B2B0E-40D4-4F0F-B187-519A6EF89B10}.Fuzzing|x64.ActiveCfg = Debug|Any CPU
{272B2B0E-40D4-4F0F-B187-519A6EF89B10}.Fuzzing|x64.Build.0 = Debug|Any CPU
{272B2B0E-40D4-4F0F-B187-519A6EF89B10}.Fuzzing|x86.ActiveCfg = Debug|Any CPU
{272B2B0E-40D4-4F0F-B187-519A6EF89B10}.Fuzzing|x86.Build.0 = Debug|Any CPU
{272B2B0E-40D4-4F0F-B187-519A6EF89B10}.Release|ARM64.ActiveCfg = Release|Any CPU
{272B2B0E-40D4-4F0F-B187-519A6EF89B10}.Release|ARM64.Build.0 = Release|Any CPU
{272B2B0E-40D4-4F0F-B187-519A6EF89B10}.Release|x64.ActiveCfg = Release|Any CPU
Expand Down Expand Up @@ -1245,6 +1262,36 @@ Global
{0BA531C8-CF0C-405B-8221-0FE51BA529D1}.TestRelease|x64.Build.0 = Release|x64
{0BA531C8-CF0C-405B-8221-0FE51BA529D1}.TestRelease|x86.ActiveCfg = Release|Win32
{0BA531C8-CF0C-405B-8221-0FE51BA529D1}.TestRelease|x86.Build.0 = Release|Win32
{98920AB6-27B0-4C0F-B336-FA49DE57A1BA}.Debug|ARM64.ActiveCfg = Debug|ARM64
{98920AB6-27B0-4C0F-B336-FA49DE57A1BA}.Debug|ARM64.Build.0 = Debug|ARM64
{98920AB6-27B0-4C0F-B336-FA49DE57A1BA}.Debug|x64.ActiveCfg = Debug|x64
{98920AB6-27B0-4C0F-B336-FA49DE57A1BA}.Debug|x64.Build.0 = Debug|x64
{98920AB6-27B0-4C0F-B336-FA49DE57A1BA}.Debug|x86.ActiveCfg = Debug|Win32
{98920AB6-27B0-4C0F-B336-FA49DE57A1BA}.Debug|x86.Build.0 = Debug|Win32
{98920AB6-27B0-4C0F-B336-FA49DE57A1BA}.Fuzzing|ARM64.ActiveCfg = Fuzzing|x64
{98920AB6-27B0-4C0F-B336-FA49DE57A1BA}.Fuzzing|ARM64.Build.0 = Fuzzing|x64
{98920AB6-27B0-4C0F-B336-FA49DE57A1BA}.Fuzzing|x64.ActiveCfg = Fuzzing|x64
{98920AB6-27B0-4C0F-B336-FA49DE57A1BA}.Fuzzing|x64.Build.0 = Fuzzing|x64
{98920AB6-27B0-4C0F-B336-FA49DE57A1BA}.Fuzzing|x86.ActiveCfg = Fuzzing|Win32
{98920AB6-27B0-4C0F-B336-FA49DE57A1BA}.Fuzzing|x86.Build.0 = Fuzzing|Win32
{98920AB6-27B0-4C0F-B336-FA49DE57A1BA}.Release|ARM64.ActiveCfg = Release|ARM64
{98920AB6-27B0-4C0F-B336-FA49DE57A1BA}.Release|ARM64.Build.0 = Release|ARM64
{98920AB6-27B0-4C0F-B336-FA49DE57A1BA}.Release|x64.ActiveCfg = Release|x64
{98920AB6-27B0-4C0F-B336-FA49DE57A1BA}.Release|x64.Build.0 = Release|x64
{98920AB6-27B0-4C0F-B336-FA49DE57A1BA}.Release|x86.ActiveCfg = Release|Win32
{98920AB6-27B0-4C0F-B336-FA49DE57A1BA}.Release|x86.Build.0 = Release|Win32
{98920AB6-27B0-4C0F-B336-FA49DE57A1BA}.ReleaseStatic|ARM64.ActiveCfg = ReleaseStatic|ARM64
{98920AB6-27B0-4C0F-B336-FA49DE57A1BA}.ReleaseStatic|ARM64.Build.0 = ReleaseStatic|ARM64
{98920AB6-27B0-4C0F-B336-FA49DE57A1BA}.ReleaseStatic|x64.ActiveCfg = ReleaseStatic|x64
{98920AB6-27B0-4C0F-B336-FA49DE57A1BA}.ReleaseStatic|x64.Build.0 = ReleaseStatic|x64
{98920AB6-27B0-4C0F-B336-FA49DE57A1BA}.ReleaseStatic|x86.ActiveCfg = ReleaseStatic|Win32
{98920AB6-27B0-4C0F-B336-FA49DE57A1BA}.ReleaseStatic|x86.Build.0 = ReleaseStatic|Win32
{98920AB6-27B0-4C0F-B336-FA49DE57A1BA}.TestRelease|ARM64.ActiveCfg = Release|ARM64
{98920AB6-27B0-4C0F-B336-FA49DE57A1BA}.TestRelease|ARM64.Build.0 = Release|ARM64
{98920AB6-27B0-4C0F-B336-FA49DE57A1BA}.TestRelease|x64.ActiveCfg = Release|x64
{98920AB6-27B0-4C0F-B336-FA49DE57A1BA}.TestRelease|x64.Build.0 = Release|x64
{98920AB6-27B0-4C0F-B336-FA49DE57A1BA}.TestRelease|x86.ActiveCfg = Release|Win32
{98920AB6-27B0-4C0F-B336-FA49DE57A1BA}.TestRelease|x86.Build.0 = Release|Win32
{9406322E-6272-487E-902A-9953889719EA}.Debug|ARM64.ActiveCfg = Debug|Any CPU
{9406322E-6272-487E-902A-9953889719EA}.Debug|ARM64.Build.0 = Debug|Any CPU
{9406322E-6272-487E-902A-9953889719EA}.Debug|x64.ActiveCfg = Debug|Any CPU
Expand Down Expand Up @@ -1301,6 +1348,8 @@ Global
{5A52D9FC-0059-4A4A-8196-427A7AA0D1C5} = {7C218A3E-9BC8-48FF-B91B-BCACD828C0C9}
{1B9077B3-8923-4ECD-8FC9-B3190FCBE4D4} = {60618CAC-2995-4DF9-9914-45C6FC02C995}
{76B26B2C-602A-4AD0-9736-4162D3FCA92A} = {1A5D7A7D-5CB2-47D5-B40D-4E61CAEDC798}
{13E55125-0ABF-4975-9B5B-DD6E5527D47F} = {800529ED-3374-49C4-BAD1-9B27647E4359}
{98920AB6-27B0-4C0F-B336-FA49DE57A1BA} = {13E55125-0ABF-4975-9B5B-DD6E5527D47F}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {B6FDB70C-A751-422C-ACD1-E35419495857}
Expand Down
3 changes: 3 additions & 0 deletions src/AppInstallerCLIPackage/Shared/Strings/en-us/winget.resw
Original file line number Diff line number Diff line change
Expand Up @@ -897,6 +897,9 @@ They can be configured through the settings file 'winget settings'.</value>
<data name="PolicyEnableExperimentalFeatures" xml:space="preserve">
<value>Enable Windows App Installer Experimental Features</value>
</data>
<data name="PolicyEnableExperiments" xml:space="preserve">
<value>Enable Windows App Installer Experiments</value>
</data>
<data name="PolicyEnableMSStoreSource" xml:space="preserve">
<value>Enable Windows App Installer Microsoft Store Source</value>
</data>
Expand Down
1 change: 1 addition & 0 deletions src/AppInstallerCLITests/AppInstallerCLITests.vcxproj
Original file line number Diff line number Diff line change
Expand Up @@ -279,6 +279,7 @@
<ClCompile Include="Downloader.cpp" />
<ClCompile Include="DownloadFlow.cpp" />
<ClCompile Include="Errors.cpp" />
<ClCompile Include="Experiment.cpp" />
<ClCompile Include="ExperimentalFeature.cpp" />
<ClCompile Include="ExportFlow.cpp" />
<ClCompile Include="FileCache.cpp" />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -374,6 +374,9 @@
<ClCompile Include="Fonts.cpp">
<Filter>Source Files\Common</Filter>
</ClCompile>
<ClCompile Include="Experiment.cpp">
<Filter>Source Files\Repository</Filter>
AmelBawa-msft marked this conversation as resolved.
Show resolved Hide resolved
</ClCompile>
</ItemGroup>
<ItemGroup>
<None Include="PropertySheet.props" />
Expand Down
76 changes: 76 additions & 0 deletions src/AppInstallerCLITests/Experiment.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@

AmelBawa-msft marked this conversation as resolved.
Show resolved Hide resolved
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
#include "pch.h"
#include "TestCommon.h"
#include "TestSettings.h"
#include <winget/Experiment.h>
#include <AppInstallerStrings.h>

using namespace TestCommon;
using namespace AppInstaller::Settings;

#define SET_POLICY_STATE(_policy_, _state_) \
GroupPolicyTestOverride policies; \
policies.SetState(_policy_, _state_);

#define SET_USER_SETTINGS(_value_) \
TestUserSettings settings; \
settings.Set<Setting::Experiments>({ \
{"TestExperiment", _value_} \
});

#define ASSERT_EXPERIMENT(_isEnabled_, _toggleSource_) \
auto testExperimentState = Experiment::GetState(Experiment::Key::TestExperiment); \
REQUIRE(_isEnabled_ == testExperimentState.IsEnabled()); \
REQUIRE(_toggleSource_ == testExperimentState.ToggleSource());

TEST_CASE("Experiment_GroupPolicyControl", "[experiment]")
{
SECTION("Not configured")
{
SET_POLICY_STATE(TogglePolicy::Policy::Experiments, PolicyState::NotConfigured);
ASSERT_EXPERIMENT(true, ExperimentToggleSource::Default);
}

SECTION("Enabled")
{
SET_POLICY_STATE(TogglePolicy::Policy::Experiments, PolicyState::Enabled);
ASSERT_EXPERIMENT(true, ExperimentToggleSource::Default);
}

SECTION("Disabled")
{
SET_POLICY_STATE(TogglePolicy::Policy::Experiments, PolicyState::Disabled);
ASSERT_EXPERIMENT(false, ExperimentToggleSource::Policy);
}
}

TEST_CASE("Experiment_GroupPolicyDisabled_ReturnFalse", "[experiment]")
{
// If the policy is disabled, then also the user settings should be ignored.
SET_POLICY_STATE(TogglePolicy::Policy::Experiments, PolicyState::Disabled);
SET_USER_SETTINGS(true);
ASSERT_EXPERIMENT(false, ExperimentToggleSource::Policy);
}

TEST_CASE("Experiment_UserSettingsControl", "[experiment]")
{
SECTION("Experiments not configured in user settings")
{
// Default value are used
ASSERT_EXPERIMENT(true, ExperimentToggleSource::Default);
}

SECTION("Experiments enabled in user settings")
{
SET_USER_SETTINGS(true);
ASSERT_EXPERIMENT(true, ExperimentToggleSource::UserSetting);
}

SECTION("Experiments disabled in user settings")
{
SET_USER_SETTINGS(false);
ASSERT_EXPERIMENT(false, ExperimentToggleSource::UserSetting);
}
}
1 change: 1 addition & 0 deletions src/AppInstallerCLITests/GroupPolicy.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -402,6 +402,7 @@ TEST_CASE("GroupPolicy_AllEnabled", "[groupPolicy]")
SetRegistryValue(policiesKey.get(), EnableWindowsPackageManagerCommandLineInterfaces, 1);
SetRegistryValue(policiesKey.get(), ConfigurationPolicyValueName, 1);
SetRegistryValue(policiesKey.get(), ProxyCommandLineOptionsPolicyValueName, 1);
SetRegistryValue(policiesKey.get(), EnableExperimentsPolicyValueName , 1);

GroupPolicy groupPolicy{ policiesKey.get() };
for (const auto& policy : TogglePolicy::GetAllPolicies())
Expand Down
3 changes: 2 additions & 1 deletion src/AppInstallerCLITests/TestSettings.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ namespace TestCommon
const std::wstring EnableWindowsPackageManagerCommandLineInterfaces = L"EnableWindowsPackageManagerCommandLineInterfaces";
const std::wstring ConfigurationPolicyValueName = L"EnableWindowsPackageManagerConfiguration";
const std::wstring ProxyCommandLineOptionsPolicyValueName = L"EnableWindowsPackageManagerProxyCommandLineOptions";
const std::wstring EnableExperimentsPolicyValueName = L"EnableExperiments";

const std::wstring SourceUpdateIntervalPolicyValueName = L"SourceAutoUpdateInterval";
const std::wstring SourceUpdateIntervalPolicyOldValueName = L"SourceAutoUpdateIntervalInMinutes";
Expand Down Expand Up @@ -90,4 +91,4 @@ namespace TestCommon
};

#define REQUIRE_POLICY_EXCEPTION(_expr_, _policy_) REQUIRE_THROWS_MATCHES(_expr_, AppInstaller::Settings::GroupPolicyException, TestCommon::GroupPolicyExceptionMatcher(_policy_))
}
}
Loading
Loading