Skip to content

Commit abd2772

Browse files
authored
[NuGet Symbol Server] Revalidate Symbols (#6547)
1 parent f45e233 commit abd2772

20 files changed

Lines changed: 332 additions & 18 deletions

src/NuGetGallery.Core/Entities/IPackageEntity.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ namespace NuGetGallery
77
/// The common entity type to be shared by <see cref="Package"/> and <see cref="SymbolPackage"/>
88
/// This allows us the generic type instantiation in dependency injection for the commonly required code.
99
/// </summary>
10-
public interface IPackageEntity
10+
public interface IPackageEntity : IEntity
1111
{
1212
string Id { get; }
1313

src/NuGetGallery.Core/Entities/Package.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ namespace NuGetGallery
1010
{
1111
[DisplayColumn("Title")]
1212
public class Package
13-
: IEntity, IPackageEntity
13+
: IPackageEntity
1414
{
1515

1616
#pragma warning disable 618 // TODO: remove Package.Authors completely once production services definitely no longer need it

src/NuGetGallery.Core/Entities/SymbolPackage.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
namespace NuGetGallery
88
{
99
public class SymbolPackage
10-
: IEntity, IPackageEntity, IEquatable<SymbolPackage>
10+
: IPackageEntity, IEquatable<SymbolPackage>
1111
{
1212
public int Key { get; set; }
1313

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
// Copyright (c) .NET Foundation. All rights reserved.
2+
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
3+
4+
using System.Linq;
5+
6+
namespace NuGetGallery.Extensions
7+
{
8+
public static class PackageExtensions
9+
{
10+
/// <summary>
11+
/// Get the latest(last) uploaded symbols package for the given package.
12+
/// </summary>
13+
/// <param name="package"><see cref="Package"/> for which latest symbol package is to be retrieved.</param>
14+
/// <returns>The latest symbol package if present, null otherwise</returns>
15+
public static SymbolPackage LatestSymbolPackage(this Package package)
16+
{
17+
return package
18+
.SymbolPackages?
19+
.OrderByDescending(sp => sp.Created)
20+
.FirstOrDefault();
21+
}
22+
}
23+
}

src/NuGetGallery.Core/NuGetGallery.Core.csproj

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -161,6 +161,7 @@
161161
<Compile Include="Entities\UserSecurityPolicy.cs" />
162162
<Compile Include="Entities\User.cs" />
163163
<Compile Include="Extensions\EntitiesContextExtensions.cs" />
164+
<Compile Include="Extensions\PackageExtensions.cs" />
164165
<Compile Include="Extensions\PackageRegistrationExtensions.cs" />
165166
<Compile Include="Extensions\PackageValidationSetExtensions.cs" />
166167
<Compile Include="Extensions\StorageExceptionExtensions.cs" />
@@ -296,10 +297,10 @@
296297
<Version>4.8.0-preview4.5287</Version>
297298
</PackageReference>
298299
<PackageReference Include="NuGet.Services.Validation">
299-
<Version>2.28.0-master-37018</Version>
300+
<Version>2.29.0</Version>
300301
</PackageReference>
301302
<PackageReference Include="NuGet.Services.Validation.Issues">
302-
<Version>2.28.0-master-37018</Version>
303+
<Version>2.29.0</Version>
303304
</PackageReference>
304305
<PackageReference Include="WindowsAzure.Storage">
305306
<Version>7.1.2</Version>

src/NuGetGallery/Areas/Admin/Views/Validation/Index.cshtml

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -60,9 +60,16 @@
6060
}
6161

6262
<b>@package.ValidatingType Key:</b> @package.PackageKey<br />
63-
@if (package.DeletedStatus == PackageDeletedStatus.NotDeleted && package.ValidatingType == ValidatingType.Package )
63+
@if (package.DeletedStatus == PackageDeletedStatus.NotDeleted)
6464
{
65-
<a href="@Url.RevalidatePackage(package.Id, package.NormalizedVersion)">Revalidate</a><br />
65+
if (package.ValidatingType == ValidatingType.Package)
66+
{
67+
<a href="@Url.RevalidatePackage(package.Id, package.NormalizedVersion)">Revalidate Package</a><br />
68+
}
69+
else if (package.ValidatingType == ValidatingType.SymbolPackage)
70+
{
71+
<a href="@Url.RevalidateSymbolsPackage(package.Id, package.NormalizedVersion)">Revalidate Symbols</a><br />
72+
}
6673
}
6774

6875
@if (package.DeletedStatus != PackageDeletedStatus.Unknown)

src/NuGetGallery/Controllers/PackagesController.cs

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
using NuGetGallery.Auditing;
2323
using NuGetGallery.Configuration;
2424
using NuGetGallery.Diagnostics;
25+
using NuGetGallery.Extensions;
2526
using NuGetGallery.Filters;
2627
using NuGetGallery.Helpers;
2728
using NuGetGallery.Infrastructure.Lucene;
@@ -1276,6 +1277,60 @@ public virtual async Task<ActionResult> Revalidate(string id, string version)
12761277
return SafeRedirect(Url.Package(id, version));
12771278
}
12781279

1280+
1281+
[UIAuthorize(Roles = "Admins")]
1282+
[RequiresAccountConfirmation("revalidate a symbols package")]
1283+
public virtual async Task<ActionResult> RevalidateSymbols(string id, string version)
1284+
{
1285+
var package = _packageService.FindPackageByIdAndVersion(id, version);
1286+
1287+
if (package == null)
1288+
{
1289+
return new HttpStatusCodeResult(HttpStatusCode.NotFound,
1290+
string.Format(Strings.PackageWithIdAndVersionNotFound, id, version));
1291+
}
1292+
1293+
try
1294+
{
1295+
// Select the latest symbols package for re-validation only if it is
1296+
// 1. Available
1297+
// 2. Or Pending validations
1298+
// 2. Or Failed Validations
1299+
var latestSymbolPackage = package.LatestSymbolPackage();
1300+
if (latestSymbolPackage == null)
1301+
{
1302+
return new HttpStatusCodeResult(HttpStatusCode.BadRequest,
1303+
string.Format(Strings.SymbolsPackage_PackageNotAvailable, id, version));
1304+
}
1305+
1306+
switch (latestSymbolPackage.StatusKey)
1307+
{
1308+
case PackageStatus.Available:
1309+
case PackageStatus.Validating:
1310+
case PackageStatus.FailedValidation:
1311+
// Allowed to revalidate
1312+
break;
1313+
case PackageStatus.Deleted:
1314+
return new HttpStatusCodeResult(HttpStatusCode.BadRequest,
1315+
string.Format(Strings.SymbolsPackage_RevalidateDeletedPackage, id, version));
1316+
default:
1317+
return new HttpStatusCodeResult(HttpStatusCode.BadRequest, $"Unkown Package status {latestSymbolPackage.StatusKey}!");
1318+
}
1319+
1320+
await _validationService.RevalidateAsync(latestSymbolPackage);
1321+
1322+
TempData["Message"] = "The symbols package is being revalidated.";
1323+
}
1324+
catch (Exception ex)
1325+
{
1326+
ex.Log();
1327+
1328+
TempData["Message"] = $"An error occurred while revalidating the symbols package. {ex.Message}";
1329+
}
1330+
1331+
return SafeRedirect(Url.Package(id, version));
1332+
}
1333+
12791334
[UIAuthorize(Roles = "Admins")]
12801335
[HttpPost]
12811336
[RequiresAccountConfirmation("delete a package")]

src/NuGetGallery/Services/AsynchronousPackageValidationInitiator.cs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ public async Task<PackageStatus> StartValidationAsync(TPackageEntity package)
4444
}
4545

4646
ValidatingType validatingType;
47+
var entityKey = package.Key == default(int) ? (int?)null : package.Key;
4748
if (package is Package)
4849
{
4950
validatingType = ValidatingType.Package;
@@ -61,7 +62,8 @@ public async Task<PackageStatus> StartValidationAsync(TPackageEntity package)
6162
package.Id,
6263
package.Version,
6364
Guid.NewGuid(),
64-
validatingType);
65+
validatingType,
66+
entityKey: entityKey);
6567

6668
var activityName = $"Enqueuing asynchronous package validation: " +
6769
$"{data.PackageId} {data.PackageVersion} {data.ValidatingType} ({data.ValidationTrackingId})";

src/NuGetGallery/Services/ITelemetryService.cs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -186,6 +186,13 @@ public interface ITelemetryService
186186
/// <param name="packageVersion">The version of the package that has the symbols uploaded.</param>
187187
void TrackSymbolPackageFailedGalleryValidationEvent(string packageId, string packageVersion);
188188

189+
/// <summary>
190+
/// Track metric for symbol package revalidation
191+
/// </summary>
192+
/// <param name="packageId">The id of the symbols package that has the symbols revalidated.</param>
193+
/// <param name="packageVersion">The version of the symbols package that has the symbols revalidated.</param>
194+
void TrackSymbolPackageRevalidate(string packageId, string packageVersion);
195+
189196
/// <summary>
190197
/// The typosquatting check result and total time for the uploaded package.
191198
/// </summary>

src/NuGetGallery/Services/IValidationService.cs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,13 @@ public interface IValidationService
3333
/// <param name="package">The package to start validation for.</param>
3434
Task RevalidateAsync(Package package);
3535

36+
/// <summary>
37+
/// Starts the asynchronous validation for the provided new symbols package but does not change the symbol package's
38+
/// <see cref="Package.PackageStatusKey"/>.
39+
/// </summary>
40+
/// <param name="symbolPackage">The symbols package to start validation for.</param>
41+
Task RevalidateAsync(SymbolPackage symbolPackage);
42+
3643
/// <summary>
3744
/// Whether the package's validation time exceeds the expected validation time.
3845
/// </summary>

0 commit comments

Comments
 (0)