Skip to content
This repository was archived by the owner on Jul 30, 2024. It is now read-only.

Commit 6de44bb

Browse files
authored
[Revalidation] Improve initialization (#509)
The revalidation job prioritizes packages that are installed by Visual Studio or .NET SDK. Before, the revalidation job required that Visual Studio and the .NET SDK were installed on the VM so that it could find these packages. This change removes that requirement by embedding a list of known preinstalled packages. Addresses https://github.com/NuGet/Engineering/issues/1545
1 parent 97f0725 commit 6de44bb

10 files changed

Lines changed: 71 additions & 27 deletions

File tree

src/NuGet.Services.Revalidate/Initialization/PackageFinder.cs

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
using System.Linq.Expressions;
99
using System.Threading;
1010
using Microsoft.Extensions.Logging;
11+
using Newtonsoft.Json;
1112
using NuGet.Versioning;
1213
using NuGetGallery;
1314

@@ -22,6 +23,8 @@ public class PackageFinder : IPackageFinder
2223
public const string DependencySetName = "Dependency";
2324
public const string RemainingSetName = "Remaining";
2425

26+
private const string PreinstalledPackagesResource = "NuGet.Services.Revalidate.Initialization.PreinstalledPackages.json";
27+
2528
private static int BatchSize = 1000;
2629
private static string MicrosoftAccountName = "Microsoft";
2730

@@ -46,16 +49,13 @@ public HashSet<int> FindMicrosoftPackages()
4649

4750
public HashSet<int> FindPreinstalledPackages(HashSet<int> except)
4851
{
49-
var preinstalledPackagesNames = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
52+
List<string> preinstalledPackagesNames;
53+
var assembly = typeof(PackageFinder).Assembly;
5054

51-
foreach (var path in _config.PreinstalledPaths)
55+
using (var resource = assembly.GetManifestResourceStream(PreinstalledPackagesResource))
56+
using (var reader = new StreamReader(resource))
5257
{
53-
var expandedPath = Environment.ExpandEnvironmentVariables(path);
54-
var packagesInPath = Directory.GetDirectories(expandedPath)
55-
.Select(d => d.Replace(expandedPath, "").Trim('\\').ToLowerInvariant())
56-
.Where(d => !d.StartsWith("."));
57-
58-
preinstalledPackagesNames.UnionWith(packagesInPath);
58+
preinstalledPackagesNames = JsonConvert.DeserializeObject<List<string>>(reader.ReadToEnd());
5959
}
6060

6161
var preinstalledPackages = FindRegistrationKeys(PreinstalledSetName, r => preinstalledPackagesNames.Contains(r.Id));

src/NuGet.Services.Revalidate/Initialization/PreinstalledPackages.json

Lines changed: 1 addition & 0 deletions
Large diffs are not rendered by default.

src/NuGet.Services.Revalidate/Job.cs

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,15 @@
44
using System;
55
using System.Collections.Generic;
66
using System.ComponentModel.Design;
7+
using System.IO;
8+
using System.Linq;
79
using System.Threading.Tasks;
810
using Autofac;
911
using Microsoft.Extensions.Configuration;
1012
using Microsoft.Extensions.DependencyInjection;
1113
using Microsoft.Extensions.Logging;
1214
using Microsoft.Extensions.Options;
15+
using Newtonsoft.Json;
1316
using NuGet.Jobs;
1417
using NuGet.Jobs.Configuration;
1518
using NuGet.Jobs.Validation;
@@ -25,19 +28,22 @@ namespace NuGet.Services.Revalidate
2528

2629
public class Job : JsonConfigurationJob
2730
{
31+
private const string RebuildPreinstalledSetArgumentName = "RebuildPreinstalledSet";
2832
private const string InitializeArgumentName = "Initialize";
2933
private const string VerifyInitializationArgumentName = "VerifyInitialization";
3034
private const string JobConfigurationSectionName = "RevalidateJob";
3135

3236
private static readonly TimeSpan RetryLaterSleepDuration = TimeSpan.FromMinutes(5);
3337

38+
private string _preinstalledSetPath;
3439
private bool _initialize;
3540
private bool _verifyInitialization;
3641

3742
public override void Init(IServiceContainer serviceContainer, IDictionary<string, string> jobArgsDictionary)
3843
{
3944
base.Init(serviceContainer, jobArgsDictionary);
4045

46+
_preinstalledSetPath = JobConfigurationManager.TryGetArgument(jobArgsDictionary, RebuildPreinstalledSetArgumentName);
4147
_initialize = JobConfigurationManager.TryGetBoolArgument(jobArgsDictionary, InitializeArgumentName);
4248
_verifyInitialization = JobConfigurationManager.TryGetBoolArgument(jobArgsDictionary, VerifyInitializationArgumentName);
4349

@@ -56,7 +62,28 @@ public override async Task Run()
5662
{
5763
using (var scope = _serviceProvider.CreateScope())
5864
{
59-
if (_initialize || _verifyInitialization)
65+
if (!string.IsNullOrEmpty(_preinstalledSetPath))
66+
{
67+
Logger.LogInformation("Rebuilding the preinstalled packages set...");
68+
69+
var config = scope.ServiceProvider.GetRequiredService<InitializationConfiguration>();
70+
var preinstalledPackagesNames = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
71+
72+
foreach (var path in config.PreinstalledPaths)
73+
{
74+
var expandedPath = Environment.ExpandEnvironmentVariables(path);
75+
var packagesInPath = Directory.GetDirectories(expandedPath)
76+
.Select(d => d.Replace(expandedPath, "").Trim('\\').ToLowerInvariant())
77+
.Where(d => !d.StartsWith("."));
78+
79+
preinstalledPackagesNames.UnionWith(packagesInPath);
80+
}
81+
82+
File.WriteAllText(_preinstalledSetPath, JsonConvert.SerializeObject(preinstalledPackagesNames));
83+
84+
Logger.LogInformation("Rebuilt the preinstalled package set. Found {PreinstalledPackages} package ids", preinstalledPackagesNames.Count);
85+
}
86+
else if (_initialize || _verifyInitialization)
6087
{
6188
var initializer = scope.ServiceProvider.GetRequiredService<InitializationManager>();
6289

src/NuGet.Services.Revalidate/NuGet.Services.Revalidate.csproj

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,9 @@
8989
<ItemGroup>
9090
<Content Include="Scripts\nssm.exe" />
9191
</ItemGroup>
92+
<ItemGroup>
93+
<EmbeddedResource Include="Initialization\PreinstalledPackages.json" />
94+
</ItemGroup>
9295
<ItemGroup>
9396
<ProjectReference Include="..\NuGet.Jobs.Common\NuGet.Jobs.Common.csproj">
9497
<Project>{4B4B1EFB-8F33-42E6-B79F-54E7F3293D31}</Project>

src/NuGet.Services.Revalidate/Program.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ class Program
1010
static void Main(string[] args)
1111
{
1212
var job = new Job();
13-
JobRunner.Run(job, args).GetAwaiter().GetResult();
13+
JobRunner.RunOnce(job, args).GetAwaiter().GetResult();
1414
}
1515
}
1616
}

src/NuGet.Services.Revalidate/Settings/dev.json

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,11 @@
33
"Initialization": {
44
"PreinstalledPaths": [
55
"C:\\Program Files (x86)\\Microsoft SDKs\\NuGetPackages",
6-
"%USERPROFILE%\\.dotnet\\NuGetFallbackFolder",
7-
"%USERPROFILE%\\.dotnet\\NuGetFallbackFolder\\.tools"
6+
"C:\\Program Files\\dotnet\\sdk\\NuGetFallbackFolder",
7+
"C:\\Program Files\\dotnet\\sdk\\NuGetFallbackFolder\\.tools"
88
],
99
"MaxPackageCreationDate": "2021-03-01T23:52:40.7022034+00:00", // TODO: Update this when repository signing is enabled
10-
"SleepDurationBetweenBatches": "00:00:01"
10+
"SleepDurationBetweenBatches": "00:00:30"
1111
},
1212

1313
"Health": {

src/NuGet.Services.Revalidate/Settings/int.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,8 @@
33
"Initialization": {
44
"PreinstalledPaths": [
55
"C:\\Program Files (x86)\\Microsoft SDKs\\NuGetPackages",
6-
"%USERPROFILE%\\.dotnet\\NuGetFallbackFolder",
7-
"%USERPROFILE%\\.dotnet\\NuGetFallbackFolder\\.tools"
6+
"C:\\Program Files\\dotnet\\sdk\\NuGetFallbackFolder",
7+
"C:\\Program Files\\dotnet\\sdk\\NuGetFallbackFolder\\.tools"
88
],
99
"MaxPackageCreationDate": "2021-03-01T23:52:40.7022034+00:00", // TODO: Update this when repository signing is enabled
1010
"SleepDurationBetweenBatches": "00:00:30"

src/NuGet.Services.Revalidate/Settings/prod.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,8 @@
33
"Initialization": {
44
"PreinstalledPaths": [
55
"C:\\Program Files (x86)\\Microsoft SDKs\\NuGetPackages",
6-
"%USERPROFILE%\\.dotnet\\NuGetFallbackFolder",
7-
"%USERPROFILE%\\.dotnet\\NuGetFallbackFolder\\.tools"
6+
"C:\\Program Files\\dotnet\\sdk\\NuGetFallbackFolder",
7+
"C:\\Program Files\\dotnet\\sdk\\NuGetFallbackFolder\\.tools"
88
],
99
"MaxPackageCreationDate": "2021-03-01T23:52:40.7022034+00:00", // TODO: Update this when repository signing is enabled
1010
"SleepDurationBetweenBatches": "00:00:30"

src/NuGet.Services.Revalidate/readme.md

Lines changed: 18 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,18 +3,31 @@
33
This job enqueues packages revalidation as fast as possible without affecting the
44
health of NuGet's ingestion pipeline. It does so in two phases:
55

6-
1. Initialization phase - the job determines which packages should be revalidated.
7-
2. Revalidation phase - packages are enqueued for revalidations
6+
1. Build Preinstalled Packages phase - the job builds a JSON file of packages that
7+
are installed by .NET SDK and Visual Studio
8+
2. Initialization phase - the job determines which packages should be revalidated.
9+
3. Revalidation phase - packages are enqueued for revalidations
810

9-
The initialization phase MUST complete before the revalidation phase is started.
11+
These phase MUST be completed in order.
12+
13+
# The Build Preinstalled Packages phase
14+
15+
This phase should run be at development time before the job is deployed:
16+
17+
```
18+
NuGet.Services.Revalidate.exe ^
19+
-Configuration "C:\Path\to\job\Settings\dev.json" ^
20+
-RebuildPreinstalledSet "C:\Path\to\job\Initialization\PreinstalledPackages.json" ^
21+
-Once
22+
```
1023

1124
# The Initialization Phase
1225

1326
To initialize the job, run:
1427

1528
```
1629
NuGet.Services.Revalidate.exe ^
17-
-Configuration "C:\Path\to\config.json" ^
30+
-Configuration "C:\Path\to\job\Settings\dev.json" ^
1831
-Initialize
1932
-VerifyInitialization
2033
-Once
@@ -36,6 +49,6 @@ To enqueue revalidations, run:
3649

3750
```
3851
NuGet.Services.Revalidate.exe ^
39-
-Configuration "C:\Path\to\config.json" ^
52+
-Configuration "C:\Path\to\job\Settings\dev.json" ^
4053
-Initialize
4154
```

tests/NuGet.Services.Revalidate.Tests/Initializer/PackageFinderFacts.cs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -74,8 +74,8 @@ public void FindsPreinstalledPackages()
7474
{
7575
_context.Mock(packageRegistrations: new[]
7676
{
77-
new PackageRegistration { Key = 1, Id = "System.Linq" },
78-
new PackageRegistration { Key = 2, Id = "Newtonsoft.Json" }
77+
new PackageRegistration { Key = 1, Id = "system.linq" },
78+
new PackageRegistration { Key = 2, Id = "newtonsoft.json" }
7979
});
8080

8181
var actual = _target.FindPreinstalledPackages(except: new HashSet<int>());
@@ -89,8 +89,8 @@ public void SkipsPackagesInExceptSet()
8989
{
9090
_context.Mock(packageRegistrations: new[]
9191
{
92-
new PackageRegistration { Key = 1, Id = "System.Linq" },
93-
new PackageRegistration { Key = 2, Id = "Newtonsoft.Json" }
92+
new PackageRegistration { Key = 1, Id = "system.linq" },
93+
new PackageRegistration { Key = 2, Id = "newtonsoft.json" }
9494
});
9595

9696
var actual = _target.FindPreinstalledPackages(except: new HashSet<int> { 1 });
@@ -104,7 +104,7 @@ public void SkipsPackagesWithNoRegistration()
104104
{
105105
_context.Mock(packageRegistrations: new[]
106106
{
107-
new PackageRegistration { Key = 1, Id = "System.Linq" },
107+
new PackageRegistration { Key = 1, Id = "system.linq" },
108108
});
109109

110110
var actual = _target.FindPreinstalledPackages(except: new HashSet<int>());

0 commit comments

Comments
 (0)