-
Notifications
You must be signed in to change notification settings - Fork 1.4k
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
Implement store app installation from manifest #493
Conversation
@@ -192,7 +192,6 @@ namespace AppInstaller::CLI::Execution | |||
for (size_t i = 0; !m_canceled; ++i) | |||
{ | |||
constexpr size_t repetitionCount = 20; | |||
ApplyStyle(i % repetitionCount, repetitionCount, true); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ApplyStyle(i % repetitionCount, repetitionCount, true); [](start = 12, length = 55)
Why has this been removed? Seems unrelated. #Closed
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
When I run locally to verify the UI behavior, the spinner applies the theme color, but on exit, it's not reverting to default. And this method is called NoVT, so I thought we left it here by accident?
In reply to: 453968675 [](ancestors = 453968675)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No style is applied in the NoVT case. If you are seeing that happening, it is due to a different bug.
In reply to: 453998322 [](ancestors = 453998322,453968675)
if (installer.InstallerType == ManifestInstaller::InstallerTypeEnum::MSStore) | ||
{ | ||
return; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would rather change how this is decided to be run than to start building early outs into every function. Probably better to move calling it out of the base flow and into DownloadInstaller where it is needed. #Closed
// Feature toggle check | ||
if (!Settings::ExperimentalFeature::IsEnabled(Settings::ExperimentalFeature::Feature::ExperimentalMSStore)) | ||
{ | ||
context.Reporter.Error() << Resource::String::FeatureDisabledMessage << std::endl; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
context.Reporter.Error() << Resource::String::FeatureDisabledMessage << std::endl; [](start = 12, length = 82)
This is typically coupled with the string that indicates which feature needs to be enabled. I would suggest creating a Workflow object that can handle this generically. So when invoking this from ExecuteInstaller:
context <<
EnsureFeatureEnabled(Settings::ExperimentalFeature::Feature::ExperimentalMSStore) <<
MSStoreInstall;
That way it can be reused easily. #Closed
|
||
// Policy check | ||
AppInstallManager installManager; | ||
if (installManager.IsStoreBlockedByPolicyAsync(s_StoreClientName, s_StoreClientPublisher).get()) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
IsStoreBlockedByPolicyAsync [](start = 27, length = 27)
Given the name of this function, I would expect that it already knows the Store's identity and that I wouldn't need to provide it. #Closed
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, unfortunately this is how the api is supposed to be called. Maybe they are thinking about multiple stores when they design this API
In reply to: 454000116 [](ancestors = 454000116)
winrt::hstring(), | ||
nullptr).get(); | ||
|
||
auto installItem = installItems.GetAt(0); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
auto installItem = installItems.GetAt(0); [](start = 8, length = 41)
Do we not need to handle all of the items? A comment is probably required here. #Closed
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
From my reading of the docs, if the target is a bundle this will have every package. I think we do need to watch all of them.
In reply to: 454004580 [](ancestors = 454004580)
|
||
context.Reporter.ShowIndefiniteProgress(false); | ||
|
||
context.Reporter.ExecuteWithProgress(std::bind( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ExecuteWithProgress [](start = 25, length = 19)
ExecuteWithProgress handles the "show indefinite until progress" if you don't send any progress. I think you can roll the above while into the lower loop to achieve the same (don't call OnProgress until PercentComplete is > 0. #Closed
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
|
||
context.Reporter.ShowIndefiniteProgress(false); | ||
|
||
context.Reporter.ExecuteWithProgress(std::bind( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
std::bind [](start = 45, length = 9)
You don't need to bind; the whole point of that is to create a callable with IProgressCallback& progress as its only parameter. #Closed
{ | ||
installItem.Cancel(); | ||
} | ||
Sleep(500); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sleep(500); [](start = 20, length = 11)
I would suggest sleeping more like 100ms, otherwise cancellation appears to be sluggish. #Closed
static const ManifestVer PreviewManifestVersion = ManifestVer("0.1.0", false); | ||
static const ManifestVer PreviewManifestVersionV2 = ManifestVer("0.2.0", false); | ||
|
||
struct YamlManifestParser |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
YamlManifestParser [](start = 11, length = 18)
Can we drop Manifest from so many names since we are in the Manifest namespace?
Manifest::YamlParser::Create
Manifest::YamlParser::CreateFromPath
You don't need to have names repeated if you don't using namespace the previous names out. #Closed
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
AppInstaller::Manifest::Manifest* m_p_manifest; | ||
AppInstaller::Manifest::ManifestInstaller* m_p_installer; | ||
std::map<ManifestInstaller::InstallerSwitchType, Utility::NormalizedString>* m_p_switches; | ||
AppInstaller::Manifest::ManifestLocalization* m_p_localization; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Initialize all with nullptr. #Closed
RootFieldInfos = | ||
{ | ||
{ "ManifestVersion", PreviewManifestVersion, [this](const YAML::Node&) { /* ManifestVersion already processed */ }, false, | ||
// Regex here is to prevent leading 0s in the version, this also keeps consistent with other versions in the manifest |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Regex [](start = 15, length = 5)
Moving the regex seems to be too much. If we are separating the parser, it should be to have it parse the syntax of the format, and then we should add these semantics onto that.
Parser > Raw Manifest > Validation
Either that or the parser gets an interface to expose selection of individual values out via some syntax we define, and the top level parser gets passed a syntactic parser to provide that.
Basically, if we are separating the code out, it should be written to enable any syntax. #Closed
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
{ | ||
// MSStore type is not supported in community repo | ||
resultErrors.emplace_back( | ||
ManifestError::FieldNotSupported, "InstallerType", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ManifestError::FieldNotSupported, "InstallerType", [](start = 20, length = 50)
Probably need ValueNotSupported so that it can be more clear that it isn't InstallerType, but it's value that is bad. #Closed
errors.emplace_back(ManifestError::FieldUnknown, key, "", keyValuePair.first.Mark().line, keyValuePair.first.Mark().column, ValidationError::Level::Warning); | ||
resultErrors.emplace_back(ManifestError::RequiredFieldMissing, "Sha256"); | ||
} | ||
// ProductId should be used |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
should be [](start = 29, length = 9)
should not be used #Closed
{ | ||
static const uint64_t MaxSupportedMajorVersion = 1; | ||
static const ManifestVer PreviewManifestVersion = ManifestVer("0.1.0", false); | ||
static const ManifestVer PreviewManifestVersionV2 = ManifestVer("0.2.0", false); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
"0.2.0" [](start = 68, length = 7)
Per discussion, this should be 0.2.0-msstore #Closed
@@ -236,6 +240,10 @@ They can be configured through the settings file 'winget settings'.</value> | |||
<data name="InstallationDisclaimer2" xml:space="preserve"> | |||
<value>Microsoft is not responsible for, nor does it grant any licenses to, third-party packages.</value> | |||
</data> | |||
<data name="InstallationDisclaimerMSStore" xml:space="preserve"> | |||
<value>This package is provided through Microsoft Store. Winget may need to acquire the package from Microsoft Store on behalf of the current user.</value> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Winget [](start = 61, length = 6)
Should probably not be capitalized, as the proper noun is not. #Closed
<value>This feature is a work in progress, and may be changed dramatically or removed altogether in the future. To enable it, edit your settings ('winget settings') to include the experimental feature</value> | ||
<comment>{Locked="winget settings"}</comment> | ||
</data> | ||
<data name="FeatureDisabledMessageWithFeatureName" xml:space="preserve"> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
FeatureDisabledMessageWithFeatureName [](start = 14, length = 37)
The other value is already used this way, just as the exception message that gets output as:
:
Don't make a second one. #Closed
// Required Args: None | ||
// Inputs: Feature | ||
// Outputs: None | ||
void EnsureFeatureEnabled(Execution::Context& context); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
EnsureFeatureEnabled [](start = 9, length = 20)
Don't read the feature out of a context value, construct an object (see VerifyFile above). #Closed
@@ -236,6 +240,10 @@ They can be configured through the settings file 'winget settings'.</value> | |||
<data name="InstallationDisclaimer2" xml:space="preserve"> | |||
<value>Microsoft is not responsible for, nor does it grant any licenses to, third-party packages.</value> | |||
</data> | |||
<data name="InstallationDisclaimerMSStore" xml:space="preserve"> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
InstallationDisclaimerMSStore [](start = 14, length = 29)
If this is a placeholder, did you send mail to ask for an official message? #Pending
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@@ -192,6 +205,10 @@ namespace AppInstaller::CLI::Workflow | |||
case ManifestInstaller::InstallerTypeEnum::Msix: | |||
context << MsixInstall; | |||
break; | |||
case ManifestInstaller::InstallerTypeEnum::MSStore: | |||
context.Add<Execution::Data::Feature>(Settings::ExperimentalFeature::Feature::ExperimentalMSStore); | |||
context << EnsureFeatureEnabled << MSStoreInstall; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
EnsureFeatureEnabled [](start = 23, length = 20)
So this becomes:
context <<
EnsureFeatureEnabled(Settings::ExperimentalFeature::Feature::ExperimentalMSStore) <<
MSStoreInstall;
``` #Closed
// request in Store client installation queue. | ||
installItem.Cancel(); | ||
|
||
context.Reporter.Info() << Resource::String::MSStoreInstallFailed << ' ' << errorCode << std::endl; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
errorCode [](start = 92, length = 9)
I don't think HRESULT automatically outputs nicely. I would suggest adding an operator<<(HRESULT) to do so.
out << "0x" << std::hex << std::fill('0') << std::width(8) << hr; #Closed
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I created a #define so that not every long will be printed as HResult
In reply to: 455237189 [](ancestors = 455237189)
context.Reporter.ExecuteWithProgress( | ||
[&](IProgressCallback& progress) | ||
{ | ||
while (installItem.GetCurrentStatus().PercentComplete() < 100) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
installItem.GetCurrentStatus().PercentComplete() [](start = 23, length = 48)
Since you need this 3 times each iteration and it might require a cross process COM call to get, maybe just save it in a local each time through the loop? #Closed
{ | ||
context.Reporter.Error() << Resource::String::FeatureDisabledMessageWithFeatureName << ' ' << | ||
Settings::ExperimentalFeature::GetFeature(feature).Name() << std::endl; | ||
AICLI_LOG(CLI, Error, << Settings::ExperimentalFeature::GetFeature(feature).Name() << "feature is disabled. Execution cancelled."); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
feature [](start = 99, length = 7)
space in front of feature #Closed
nullptr).get(); | ||
|
||
// We install one package at a time so the AppInstallItem list returned should contain only one entry. | ||
auto installItem = installItems.GetAt(0); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
auto installItem = installItems.GetAt(0); [](start = 8, length = 41)
We should probably log a bunch of info about these requests so that we can easily associate them with store/deployment logs. Store request ids, PFNs, anything else that will make it easier to link the two. #Closed
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looking at the properties of AppInstallItem, only ProductId and PFN are related to our diagnosis. Logged these 2.
In reply to: 455243165 [](ancestors = 455243165)
if (!Settings::ExperimentalFeature::IsEnabled(m_feature)) | ||
{ | ||
context.Reporter.Error() << Resource::String::FeatureDisabledMessage << ' ' << | ||
Resource::String::FeatureDisabledFeatureName << ' ' << |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why not just: ": ". That is what is happening in the case that the whole command or an argument is not available. #Closed
for (auto const& installItem : installItems) | ||
{ | ||
const auto& status = installItem.GetCurrentStatus(); | ||
currentProgress += (uint64_t)(status.PercentComplete()); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
(uint64_t) [](start = 43, length = 10)
static_cast<uint64_t> #Closed
if (!SUCCEEDED(errorCode)) | ||
{ | ||
context.Reporter.Info() << Resource::String::MSStoreInstallFailed << ' ' << WINGET_OSTREAM_FORMAT_HRESULT(errorCode) << std::endl; | ||
AICLI_LOG(CLI, Error, << "MSStore install failed. ProductId: " << Utility::ConvertToUTF8(productId) << " HResult: " << errorCode); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
errorCode [](start = 147, length = 9)
WINGET_OSTREAM_FORMAT_HRESULT #Closed
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
exit
closed |
This is the first part of #117
Change
Validation
Microsoft Reviewers: Open in CodeFlow