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

Stage 1 of Package Reference Compatibility Validation #346

Closed
wants to merge 5 commits into from

Conversation

nkolev92
Copy link
Member

@nkolev92 nkolev92 commented Feb 21, 2018

Part of NuGet/Home#6533

ServerCommon PR:
NuGet/ServerCommon#138

I will update the common packages later.

Add an in-proc validator for package reference compatibility, that persist the issues in it's own table, that should allow us to nuke it later.

The validator always "succeeds" because don't want to fail validation, and we don't have the means to rerun a validation right now.

Stage 2 will make it out of proc.

@@ -40,6 +40,13 @@
"SubscriptionName": ""
}
},
"PackageCompatibility": {
"ServiceBus": {
"ConnectionString": "servicebus string",
Copy link
Member

Choose a reason for hiding this comment

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

nit: empty strings like the other ones

Copy link
Member Author

Choose a reason for hiding this comment

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

cleaned up.

@joelverhagen
Copy link
Member

Got a link to the ServerCommon PR as well?

return validatorStatus.ToValidationResult();
}

// Add the status, so subsequent calls don't try to reevaluate the same thing
Copy link
Member

Choose a reason for hiding this comment

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

nit: re-evaluate

{
public PackageCompatibilityValidationMessage(string packageId, string packageVersion, Uri nupkgUri, Guid validationId)
{
PackageId = packageId;
Copy link
Member

Choose a reason for hiding this comment

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

null checks


namespace Validation.PackageCompatibility.Core.Messages
{
public class PackageCompatibilityValidationMessageSerializer : IBrokeredMessageSerializer<PackageCompatibilityValidationMessage>
Copy link
Member

Choose a reason for hiding this comment

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

This code is not needed right now, right?

}
catch (DbUpdateConcurrencyException e)
{
_logger.LogWarning("trouble saving changes async - {0}", e.Message);
Copy link
Member

Choose a reason for hiding this comment

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

How could this case happen?

Copy link
Member Author

Choose a reason for hiding this comment

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

Meant to use DbUpdateException.

Just in case.

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 instead recommend having a big try/catch around your entire validation flow so that it does not effect package publish.

Copy link
Member Author

Choose a reason for hiding this comment

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

[assembly: AssemblyTitle("Validation.PackageCompatibility.Core")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("HP Inc.")]
Copy link
Member

Choose a reason for hiding this comment

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

HP?

Copy link
Member Author

Choose a reason for hiding this comment

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

No clue lol.

It's supposed to be autogened.
Didn't find any mentions of HP in the code otherwise.

<Version>4.7.0-preview1-4929</Version>
</PackageReference>
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
Copy link
Member

Choose a reason for hiding this comment

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

This needs our sign targets -- see other csproj

Copy link
Member Author

Choose a reason for hiding this comment

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

added it.

@@ -85,6 +85,11 @@
<Name>Validation.PackageSigning.Core</Name>
</ProjectReference>
</ItemGroup>
<ItemGroup>
Copy link
Member

Choose a reason for hiding this comment

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

Is this necessary?

Copy link
Member Author

@nkolev92 nkolev92 Feb 21, 2018

Choose a reason for hiding this comment

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

Yes, otherwise the packaging version gets bumped up because of the different version in NuGet.PackageCompatibility.Core project.

Attempting to get the same version throughout the whole solution breaks some signing APIs.

@nkolev92
Copy link
Member Author

🔔
@joelverhagen

@@ -163,12 +163,20 @@
</site>
<site name="Validation.Callback.Vcs" id="2">
<application path="/" applicationPool="Clr4IntegratedAppPool">
<virtualDirectory path="/" physicalPath="C:\src\NuGet.Jobs\src\Validation.Callback.Vcs" />
Copy link
Member

Choose a reason for hiding this comment

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

This sutff shouldn't change

Copy link
Member Author

Choose a reason for hiding this comment

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

Why isn't this in ignore?

@@ -86,7 +91,7 @@ public override void Init(IDictionary<string, string> jobArgsDictionary)
return;
}

var runner = GetRequiredService<OrchestrationRunner>();
var runner = GetRequiredService<OrchestrationRunner>();
Copy link
Member

Choose a reason for hiding this comment

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

nit: trailing spaces

// Try check the whole thing
try
{
var validatorStatus = await _validatorStateService.GetStatusAsync(request);
Copy link
Member

Choose a reason for hiding this comment

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

nit: move all of the code in the try into a helper method to minimize chance of putting logic outside of the try

}
catch (Exception e)
{
_logger.LogWarning($"Validation failed for the validation request {0}.{Environment.NewLine}Exception: {1}", request.ToString(), e.ToString());
Copy link
Member

Choose a reason for hiding this comment

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

LogWarning has an overload that accepts an exception I think.

private static void ConfigurePackageCompatibilityValidator(ContainerBuilder builder)
{

// Configure the validator state service for the package compatibility validator.
Copy link
Contributor

Choose a reason for hiding this comment

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

Configure [](start = 15, length = 9)

There's an extra line on 357 and on 376

@@ -5,6 +5,8 @@
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Reflection;
Copy link
Contributor

Choose a reason for hiding this comment

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

Are these usings necessary?

Copy link
Member Author

Choose a reason for hiding this comment

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

cleaned up.

}
catch (Exception e)
{
_logger.LogWarning($"Validation failed for the validation request {0}.{Environment.NewLine}Exception: {1}", request.ToString(), e.ToString());
Copy link
Contributor

Choose a reason for hiding this comment

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

Let the logger call ToString. ToString may be expensive and the logger may choose to not emit the log.

Copy link
Member Author

Choose a reason for hiding this comment

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

Changed that up, after getting the same feedback from @joelverhagen

);

// Do validation
await Validate(message, CancellationToken.None);
Copy link
Contributor

Choose a reason for hiding this comment

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

Validate [](start = 22, length = 8)

If Validate throws, won't a validation get "stuck" in Incomplete state? Should Validate happen before the TryAddValidatorStatusAsync?

{
public class PackageCompatibilityValidationMessage
{
public PackageCompatibilityValidationMessage(string packageId, string packageVersion, Uri nupkgUri, Guid validationId)
Copy link
Contributor

Choose a reason for hiding this comment

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

PackageCompatibilityValidationMessage [](start = 15, length = 37)

Is this just used for the PackageCompatibilityValidator.Validate method? A public class seems like over kill, maybe a private class in PackageCompatibilityValidator would be better. Also, are all of these parameters used? It seems like PackageId is not.

Copy link
Member Author

Choose a reason for hiding this comment

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

In phase 2, this validation will run in it's own proc, and it'll be used there for logging and better visibility, analogous to the way the package id/version are used in the signing validation.

}
catch (DbUpdateException e)
{
_logger.LogWarning("trouble saving changes async - {0}", e.Message);
Copy link
Contributor

Choose a reason for hiding this comment

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

Message [](start = 75, length = 7)

You should log the full exception instead of e.Message as the real exception may be hidden in a InnerException. If the database fails to save here, won't the PackageCompatibilityValidator think that it's successfully finished SetPackageCompatibilityState and set the validator status to ValidationStatus.Succeeded?

/// <summary>
/// Configuration for initializing the <see cref="PackageCompatibilityValidator"/>.
/// </summary>
public class PackageCompatibilityValidator : IValidator
Copy link
Contributor

Choose a reason for hiding this comment

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

PackageCompatibilityValidator [](start = 17, length = 29)

Validators that are outside of the NuGet.Services.Validation.Orchestrator project are not supported today. This is a low-priority "bug" in the Orchestrator that we will fix in the future. The type that extends IValidator will need to be moved, the implementation can be kept here.

See this:

IEnumerable<Type> candidateTypes = GetCandidateTypes(Assembly.GetCallingAssembly());

Copy link
Member Author

Choose a reason for hiding this comment

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

That's useful feedback.

This is currently in the Orchestrator project though, just making sure you noticed that.

Copy link
Contributor

Choose a reason for hiding this comment

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

Oh. I can't read :)

}

// Add the status, so subsequent calls don't try to re-evaluate the same thing
await _validatorStateService.TryAddValidatorStatusAsync(request, validatorStatus, ValidationStatus.Incomplete);
Copy link
Contributor

Choose a reason for hiding this comment

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

TryAddValidatorStatusAsync [](start = 41, length = 26)

TryAddValidatorStatusAsync can return a ValidationStatus that is NOT Incomplete. In such a case, you should immediately return the other status.

This could happen if the message to validate a package is duplicated and one message finishes validating the package AFTER both validators have verified that the validation hasn't started yet.

validatorStatus.State = ValidationStatus.Succeeded;

await _validatorStateService.SaveStatusAsync(validatorStatus);
return validatorStatus.ToValidationResult();
Copy link
Contributor

Choose a reason for hiding this comment

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

ToValidationResult [](start = 35, length = 18)

You should be returning the status according to the SaveStatusAsync as two threads may attempt the SaveStatusAsync call. It seems like today this won't be an issue as wewill only persist Succeeded, but I would rather be resilient to future changes :)

@loic-sharma loic-sharma requested a review from agr February 21, 2018 21:46
@nkolev92
Copy link
Member Author

🔔
@joelverhagen @loic-sharma
I refactored around the validator code after some discussions.
This way it won't get stuck in a non-terminal state.

@nkolev92 nkolev92 changed the title WIP - Stage 1 of Package Reference Compatibility Validation Stage 1 of Package Reference Compatibility Validation Feb 21, 2018
}
catch (Exception e)
{
_logger.LogWarning(0, e, "Validation failed for the validation request {request}", request);
Copy link
Member

Choose a reason for hiding this comment

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

just request ID

Copy link
Member

Choose a reason for hiding this comment

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

er, Validation ID

// Treat every validation as succeeded, as we don't want to block
validatorStatus.State = ValidationStatus.Succeeded;

var result = await _validatorStateService.SaveStatusAsync(validatorStatus);
Copy link
Member

Choose a reason for hiding this comment

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

If this case fails do we really want to fail push?

Copy link
Member Author

Choose a reason for hiding this comment

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

Why would this fail?

What state would the validation be stuck in this case?

Copy link
Member Author

Choose a reason for hiding this comment

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

Refactor it back to the "old" state.

It's not the prettiest but, it makes sure we're not in a weird state even though it doesn't hurt it.

@joelverhagen
Copy link
Member

Looks good so far. Things to do prior to checking in:

  • Verify that checking into dev branch is fine with this stuff, /cc @skofman1
  • Test on DEV environment (I can help with this)

}
catch (Exception e)
{
_logger.LogWarning(0, e, "Validation failed in the validator for the following request {request}", request.ValidationId);
Copy link
Contributor

Choose a reason for hiding this comment

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

Nit: for the following request {request} -> for the following validation id {ValidationId}. Same thing with line 82

@nkolev92
Copy link
Member Author

I've added some more changes.

IPackageDownloader packageDownloader,
ILogger<PackageCompatibilityValidator> logger)
{
_validatorStateService = validatorStateService;
Copy link
Contributor

Choose a reason for hiding this comment

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

null checks

_validationContext.PackageCompatibilityIssues.Add(
new PackageCompatibilityIssue()
{
ClientIssueCode = log.Code.ToString(),
Copy link
Contributor

Choose a reason for hiding this comment

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

Storing the client issue code as is, can cause issues if you want to have server specific validations that are not available on client side.
For Package Signing Joel has a server side error code that "wraps" all client side error codes, and granular server side error codes for other problems.
I recommend the same approach here.

Copy link
Member Author

Choose a reason for hiding this comment

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

I discussed this with @joelverhagen.
The idea for the Package Reference validations is that they'll always be client controlled.
The APIs used are the exact ones as the one in the client code.

Also not reusing that table allows us more freedom to evolve the design moving forward.

@@ -71,6 +78,7 @@
"AnnouncementsUrl": "https://github.com/NuGet/Announcements/issues",
"TwitterUrl": "https://twitter.com/nuget"
},
"PackageDownloadTimeout": "10:00",
Copy link
Contributor

Choose a reason for hiding this comment

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

if this is specific to PackageCompatibility validator, please move the config there.

Copy link
Member Author

Choose a reason for hiding this comment

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

This is only here, because the validator is currently running in-proc.
Once the validator is in it's own process it will get moved out of here.

@skofman1
Copy link
Contributor

I'm ok with checking this in to DEV branch, however, it shouldn't run as is because downloading the package in the Orchestrator might impact perf.

joelverhagen pushed a commit that referenced this pull request Sep 27, 2019
joelverhagen pushed a commit that referenced this pull request Sep 27, 2019
* Feed2Catalog:  replace inner loops with one outer loop (#329)
Resolve NuGet/Engineering#1526.
* V3:  rename asynchronous IStorage methods (#336)
Progress on NuGet/NuGetGallery#6267.
* Test:  fix flaky basic search tests (#337)
Progress on NuGet/NuGetGallery#6292.
* Add signing to search service (#338)
Progress on https://github.com/NuGet/Engineering/issues/1644
* Test:  add registration tests (#341)
Progress on NuGet/NuGetGallery#6317.
* remove unused scripts (#340)
* MonitoringProcessor:  improve throughput (#342)
Progress on NuGet/NuGetGallery#6327.
* Catalog2Dnx:  improve throughput (#335)
Progress on NuGet/NuGetGallery#6267.
* Functional tests should not be dependent on a specific hash and file size of the test package (#343)
* Add MicroBuild dependency and signing of output DLLs (#345)
Progress on https://github.com/NuGet/Engineering/issues/1644
* Rewrite SafeRoleEnvironment to not use Assembly.LoadWithPartialName (#339)
* Test:  improve and add registration tests (#346)
More progress on NuGet/NuGetGallery#6317.
* Use ServerCommon commit that is consistent with other repositories (#347)
Progress on https://github.com/NuGet/Engineering/issues/1644
* [Monitoring] Ensure packages are signed (#348)
This adds a validation to ensure indexed packages are signed by verifying that the package contains a [package signature file](https://github.com/NuGet/Home/wiki/Package-Signatures-Technical-Details#-the-package-signature-file).
This validation is disabled for now. To enable this validation, the flag `-expectsSignature true` must be added to ng.exe's command line arguments. This validation will be enabled once all packages are repository signed.
Part of NuGet/Engineering#1627
* V3:  make stylistic consistency and cleanup changes (#349)
Progress on NuGet/NuGetGallery#6411.
@nkolev92
Copy link
Member Author

Unfortunately this work didn't get merged a few years back and I don't see this getting put high on the priority list soon again.
Closing this PR.

@nkolev92 nkolev92 closed this Apr 29, 2020
@joelverhagen
Copy link
Member

😭

joelverhagen pushed a commit that referenced this pull request Oct 26, 2020
joelverhagen pushed a commit that referenced this pull request Oct 26, 2020
* Feed2Catalog:  replace inner loops with one outer loop (#329)
Resolve NuGet/Engineering#1526.
* V3:  rename asynchronous IStorage methods (#336)
Progress on NuGet/NuGetGallery#6267.
* Test:  fix flaky basic search tests (#337)
Progress on NuGet/NuGetGallery#6292.
* Add signing to search service (#338)
Progress on https://github.com/NuGet/Engineering/issues/1644
* Test:  add registration tests (#341)
Progress on NuGet/NuGetGallery#6317.
* remove unused scripts (#340)
* MonitoringProcessor:  improve throughput (#342)
Progress on NuGet/NuGetGallery#6327.
* Catalog2Dnx:  improve throughput (#335)
Progress on NuGet/NuGetGallery#6267.
* Functional tests should not be dependent on a specific hash and file size of the test package (#343)
* Add MicroBuild dependency and signing of output DLLs (#345)
Progress on https://github.com/NuGet/Engineering/issues/1644
* Rewrite SafeRoleEnvironment to not use Assembly.LoadWithPartialName (#339)
* Test:  improve and add registration tests (#346)
More progress on NuGet/NuGetGallery#6317.
* Use ServerCommon commit that is consistent with other repositories (#347)
Progress on https://github.com/NuGet/Engineering/issues/1644
* [Monitoring] Ensure packages are signed (#348)
This adds a validation to ensure indexed packages are signed by verifying that the package contains a [package signature file](https://github.com/NuGet/Home/wiki/Package-Signatures-Technical-Details#-the-package-signature-file).
This validation is disabled for now. To enable this validation, the flag `-expectsSignature true` must be added to ng.exe's command line arguments. This validation will be enabled once all packages are repository signed.
Part of NuGet/Engineering#1627
* V3:  make stylistic consistency and cleanup changes (#349)
Progress on NuGet/NuGetGallery#6411.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
4 participants