From cedafaec0e530dfe8deb8511edcf28d2ec806cf7 Mon Sep 17 00:00:00 2001 From: Serge Mera Date: Fri, 20 May 2022 17:27:12 +0000 Subject: [PATCH] Merged PR 662608: Reapply NuGet resolver schedules real pips Same commit as before plus: * Force check the nuget package fp on disk (apparently this was off by default because dotnet core didn't support nuget at that time) (that should fix the DFA we saw, which is a layout difference between a public vs internal package when an agent gets reused) * Capture stderr when executing the cred provider, for better error diagnostics. From the issues we saw, there is still one that I was not able to repro (https://dev.azure.com/mseng/Domino/_build/results?buildId=17296398&view=logs&j=cfa20e98-6997-523c-4233-f0a7302c929f&t=144c797d-20c9-5763-9672-cca1a82cd366). I'll keep trying, but the stderr should be able to tell us more if that happens again. Hopefully we can spot this before I merge this. --- .../Msvc/Native/Tools/Link/Link.dsc | 4 +- .../Public/Managed/Tools/NuGet/empty.config | 9 +- .../Sdk/Public/Managed/Tools/NuGet/pack.dsc | 3 +- .../Prelude.Configuration.Resolvers.dsc | 6 +- .../BuildXL/Testing/QTest/qtestFramework.dsc | 4 +- .../Dll/BasicFrontEndEngineAbstraction.cs | 22 +- .../Dll/FrontEndEngineImplementation.cs | 8 + .../Engine/UnitTests/Engine/BaseEngineTest.cs | 4 +- .../Engine/LazyMaterializationBuildTests.cs | 1 - .../UnitTests/Engine/Test.BuildXL.Engine.dsc | 36 +- .../Scheduler/PipFingerprinterTests.cs | 6 + .../Core/FrontEndHostController.Nuget.cs | 47 +- Public/Src/FrontEnd/Core/NugetCache.cs | 2 +- Public/Src/FrontEnd/Core/PackageHashFile.cs | 2 +- .../FrontEnd/Nuget/BuildXL.FrontEnd.Nuget.dsc | 18 +- .../NugetFailedWithNonZeroExitCodeFailure.cs | 38 - .../FrontEnd/Nuget/Failures/NugetFailure.cs | 83 +- .../Nuget/Failures/NugetInvocationFailure.cs | 31 + .../FrontEnd/Nuget/NugetAnalyzedPackage.cs | 17 +- Public/Src/FrontEnd/Nuget/NugetFrontEnd.cs | 2 +- .../FrontEnd/Nuget/NugetInspectedPackage.cs | 31 + .../FrontEnd/Nuget/NugetPackageInspector.cs | 365 ++++++++ .../Src/FrontEnd/Nuget/NugetSpecGenerator.cs | 102 ++- Public/Src/FrontEnd/Nuget/PackageOnDisk.cs | 10 +- Public/Src/FrontEnd/Nuget/Tracing/Log.cs | 127 +-- .../Src/FrontEnd/Nuget/Tracing/LogEventId.cs | 71 +- .../Nuget/WorkspaceNugetModuleResolver.cs | 817 ++++-------------- .../AmbientTransformer.Process.cs | 9 + .../FrontEnd/Sdk/FrontEndEngineAbstraction.cs | 5 + Public/Src/FrontEnd/Sdk/FrontEndHost.cs | 1 + .../Sdk/SimpleFrontEndEngineAbstraction.cs | 8 +- .../Helper/TestEngineAbstraction.cs | 6 + Public/Src/FrontEnd/UnitTests/Core/DsTest.cs | 3 + .../UnitTests/Libs/Prelude.Context.ts | 2 +- .../UnitTests/Nuget/NuSpecGeneratorTests.cs | 80 +- .../UnitTests/Nuget/NugetResolverUnitTests.cs | 16 +- .../UnitTests/Nuget/PackageGenerator.cs | 4 +- .../FakeNugetResolverSettingsProvider.cs | 12 - .../TestAutoCompleteProvider.cs | 3 +- .../Pips/Dll/Graph/ExtraFingerprintSalts.cs | 11 +- Public/Src/Pips/Dll/Graph/PipFingerprinter.cs | 2 +- Public/Src/Pips/Dll/Operations/Pip.cs | 5 + .../Pips/Dll/Operations/Process.Options.cs | 5 + Public/Src/Pips/Dll/Operations/Process.cs | 4 + Public/Src/Sandbox/MacOs/deployment.dsc | 38 +- .../BxlScriptAnalyzer/WorkspaceBuilder.cs | 2 +- Public/Src/Tools/FileDownloader/Downloader.cs | 188 +--- .../FileDownloader/Tool.FileDownloader.dsc | 1 + Public/Src/Tools/NugetDownloader/App.config | 6 + .../Tools/NugetDownloader/ConsoleLogger.cs | 84 ++ .../Tool.NugetDownloader.dsc.literal | 125 +++ .../LiteralFiles/module.config.dsc.literal | 6 + .../Tools/NugetDownloader/NugetDownloader.cs | 149 ++++ .../NugetDownloader/NugetDownloaderArgs.cs | 93 ++ .../NugetDownloader/Tool.NugetDownloader.dsc | 62 ++ .../FrontEndConfigurationExtensions.cs | 2 +- .../Resolvers/INugetConfiguration.cs | 4 +- .../Mutable/NuGetResolverSettings.cs | 3 +- .../Resolvers/Mutable/NugetConfiguration.cs | 15 +- .../Src/Utilities/Native/BuildXL.Native.dsc | 2 +- .../Utilities/ZeroLeftPaddedStreamTests.cs | 93 ++ .../Utilities/ZeroLeftPaddedStream.cs | 158 ++++ .../AuthenticationFailure.cs | 37 + .../BuildXL.Utilties.VstsAuthentication.dsc | 25 + .../VSTSAuthenticationHelper.cs | 335 +++++++ Shared/Scripts/Init.cmd | 1 + ....IdentityModel.Clients.ActiveDirectory.dll | Bin 0 -> 998464 bytes Shared/Tools/Newtonsoft.Json.dll | Bin 0 -> 483840 bytes Shared/Tools/NuGet.Common.dll | Bin 0 -> 97144 bytes Shared/Tools/NuGet.Protocol.dll | Bin 0 -> 715856 bytes Shared/Tools/PowerArgs.dll | Bin 0 -> 806400 bytes Shared/Tools/readme.txt | 3 + cg/nuget/cgmanifest.json | 42 +- config.dsc | 20 +- 74 files changed, 2301 insertions(+), 1235 deletions(-) delete mode 100644 Public/Src/FrontEnd/Nuget/Failures/NugetFailedWithNonZeroExitCodeFailure.cs create mode 100644 Public/Src/FrontEnd/Nuget/Failures/NugetInvocationFailure.cs create mode 100644 Public/Src/FrontEnd/Nuget/NugetInspectedPackage.cs create mode 100644 Public/Src/FrontEnd/Nuget/NugetPackageInspector.cs create mode 100644 Public/Src/Tools/NugetDownloader/App.config create mode 100644 Public/Src/Tools/NugetDownloader/ConsoleLogger.cs create mode 100644 Public/Src/Tools/NugetDownloader/LiteralFiles/Tool.NugetDownloader.dsc.literal create mode 100644 Public/Src/Tools/NugetDownloader/LiteralFiles/module.config.dsc.literal create mode 100644 Public/Src/Tools/NugetDownloader/NugetDownloader.cs create mode 100644 Public/Src/Tools/NugetDownloader/NugetDownloaderArgs.cs create mode 100644 Public/Src/Tools/NugetDownloader/Tool.NugetDownloader.dsc create mode 100644 Public/Src/Utilities/UnitTests/Utilities/ZeroLeftPaddedStreamTests.cs create mode 100644 Public/Src/Utilities/Utilities/ZeroLeftPaddedStream.cs create mode 100644 Public/Src/Utilities/VstsAuthentication/AuthenticationFailure.cs create mode 100644 Public/Src/Utilities/VstsAuthentication/BuildXL.Utilties.VstsAuthentication.dsc create mode 100644 Public/Src/Utilities/VstsAuthentication/VSTSAuthenticationHelper.cs create mode 100644 Shared/Tools/Microsoft.IdentityModel.Clients.ActiveDirectory.dll create mode 100644 Shared/Tools/Newtonsoft.Json.dll create mode 100644 Shared/Tools/NuGet.Common.dll create mode 100644 Shared/Tools/NuGet.Protocol.dll create mode 100644 Shared/Tools/PowerArgs.dll create mode 100644 Shared/Tools/readme.txt diff --git a/Public/Sdk/Experimental/Msvc/Native/Tools/Link/Link.dsc b/Public/Sdk/Experimental/Msvc/Native/Tools/Link/Link.dsc index a39b90dfa..64d0389c0 100644 --- a/Public/Sdk/Experimental/Msvc/Native/Tools/Link/Link.dsc +++ b/Public/Sdk/Experimental/Msvc/Native/Tools/Link/Link.dsc @@ -179,9 +179,9 @@ export function evaluate(args: Arguments): Result { ], allowedSurvivingChildProcessNames: [ "mspdbsrv.exe", - "VCTIP.exe", "conhost.exe", - ] + ], + unsafe: { childProcessesToBreakawayFromSandbox: [a`vctip.exe`] } }); let midlOutput = { diff --git a/Public/Sdk/Public/Managed/Tools/NuGet/empty.config b/Public/Sdk/Public/Managed/Tools/NuGet/empty.config index 0b66186ce..a342b8dfb 100644 --- a/Public/Sdk/Public/Managed/Tools/NuGet/empty.config +++ b/Public/Sdk/Public/Managed/Tools/NuGet/empty.config @@ -27,13 +27,16 @@ Each time a new nuget version is updated we must make sure that any configuratio - - - + + + + + + \ No newline at end of file diff --git a/Public/Sdk/Public/Managed/Tools/NuGet/pack.dsc b/Public/Sdk/Public/Managed/Tools/NuGet/pack.dsc index 32c029b2b..047ba8347 100644 --- a/Public/Sdk/Public/Managed/Tools/NuGet/pack.dsc +++ b/Public/Sdk/Public/Managed/Tools/NuGet/pack.dsc @@ -14,7 +14,8 @@ export const tool : Transformer.ToolDefinition = { exe: Nuget.Contents.all.getFile(r`tools/NuGet.exe`), description: "NuGet pack", untrackedDirectoryScopes: [ - d`${Context.getMount("ProgramData").path}/Nuget` + d`${Context.getMount("ProgramData").path}/Nuget`, + ...addIfLazy(Context.isWindowsOS(), () => [d`${Context.getMount("ProgramFilesX86").path}/Nuget`]), ], dependsOnWindowsDirectories: true, dependsOnAppDataDirectory: true, diff --git a/Public/Sdk/Public/Prelude/Prelude.Configuration.Resolvers.dsc b/Public/Sdk/Public/Prelude/Prelude.Configuration.Resolvers.dsc index 23fd509dc..73ddedcd0 100644 --- a/Public/Sdk/Public/Prelude/Prelude.Configuration.Resolvers.dsc +++ b/Public/Sdk/Public/Prelude/Prelude.Configuration.Resolvers.dsc @@ -839,7 +839,11 @@ interface UntrackingSettings { } interface NuGetConfiguration extends ToolConfiguration { - credentialProviders?: ToolConfiguration[]; + /** + * The download timeout, in minutes, for each NuGet download pip. Defaults to 20m. + * Equivalent to configuring timeoutInMilliseconds for the corresponding Transformers.ToolDefinition + */ + downloadTimeoutMin?: number } interface ScriptResolverDefaults { diff --git a/Public/Sdk/SelfHost/BuildXL/Testing/QTest/qtestFramework.dsc b/Public/Sdk/SelfHost/BuildXL/Testing/QTest/qtestFramework.dsc index 3a1e53002..26048b306 100644 --- a/Public/Sdk/SelfHost/BuildXL/Testing/QTest/qtestFramework.dsc +++ b/Public/Sdk/SelfHost/BuildXL/Testing/QTest/qtestFramework.dsc @@ -181,9 +181,9 @@ function runTest(args : TestRunArguments) : File[] { testAssembly: args.testDeployment.primaryFile.path, qTestType: Qtest.QTestType.msTest_latest, qTestDirToDeploy: args.testDeployment.contents, - qTestAdapterPath: Transformer.sealDirectory({ + qTestAdapterPath: Transformer.sealPartialDirectory({ root: testAdapterPath, - files: globR(testAdapterPath, "*") + files: rootTestAdapterPath.contents.filter(f => f.path.isWithin(testAdapterPath)), }), qTestDotNetFramework: getQTestDotNetFramework(), qTestPlatform: Qtest.QTestPlatform.x64, diff --git a/Public/Src/Engine/Dll/BasicFrontEndEngineAbstraction.cs b/Public/Src/Engine/Dll/BasicFrontEndEngineAbstraction.cs index 6e735db49..fcc5a8c71 100644 --- a/Public/Src/Engine/Dll/BasicFrontEndEngineAbstraction.cs +++ b/Public/Src/Engine/Dll/BasicFrontEndEngineAbstraction.cs @@ -23,10 +23,24 @@ namespace BuildXL.Engine { } - /// - public void SetMountsTable(MountsTable mountsTable) + /// + /// Adds all the mounts specified in the given mounts table + /// + public void UpdateMountsTable(MountsTable mountsTable) { - m_customMountsTable = mountsTable.AllMountsSoFar.ToDictionary(mount => mount.Name.ToString(m_pathTable.StringTable), mount => mount); + var allMounts = mountsTable.AllMountsSoFar.ToDictionary(mount => mount.Name.ToString(m_pathTable.StringTable), mount => mount); + + if (m_customMountsTable == null) + { + m_customMountsTable = allMounts; + } + else + { + foreach (var mount in allMounts) + { + m_customMountsTable[mount.Key] = mount.Value; + } + } } /// @@ -41,7 +55,7 @@ namespace BuildXL.Engine return false; } - SetMountsTable(mountsTable); + UpdateMountsTable(mountsTable); return true; } diff --git a/Public/Src/Engine/Dll/FrontEndEngineImplementation.cs b/Public/Src/Engine/Dll/FrontEndEngineImplementation.cs index 437dcf972..274068f0c 100644 --- a/Public/Src/Engine/Dll/FrontEndEngineImplementation.cs +++ b/Public/Src/Engine/Dll/FrontEndEngineImplementation.cs @@ -93,6 +93,7 @@ namespace BuildXL.Engine private readonly MountsTable m_mountsTable; private readonly LoggingContext m_loggingContext; + private readonly DirectoryTranslator m_directoryTranslator; /// /// Creates an instance of . @@ -130,6 +131,7 @@ namespace BuildXL.Engine m_snapshotCollector = snapshotCollector; GetTimerUpdatePeriod = timerUpdatePeriod; Layout = configuration.Layout; + m_directoryTranslator = directoryTranslator; if (ShouldUseSpecCache(configuration)) { @@ -184,6 +186,12 @@ namespace BuildXL.Engine }); } + /// + public override AbsolutePath Translate(AbsolutePath path) + { + return m_directoryTranslator?.Translate(path, PathTable) ?? path; + } + private bool ShouldUseSpecCache(IConfiguration configuration) { var sourceDirectory = configuration.Layout.SourceDirectory.ToString(PathTable); diff --git a/Public/Src/Engine/UnitTests/Engine/BaseEngineTest.cs b/Public/Src/Engine/UnitTests/Engine/BaseEngineTest.cs index 0af9e12cd..2c96ffeff 100644 --- a/Public/Src/Engine/UnitTests/Engine/BaseEngineTest.cs +++ b/Public/Src/Engine/UnitTests/Engine/BaseEngineTest.cs @@ -197,7 +197,7 @@ function execute(args: Transformer.ExecuteArguments): Transformer.ExecuteResult } - protected void AddSdk(string sdkLocation) + protected void AddSdk(string relativeSdkLocation) { Configuration.Resolvers.Add( new SourceResolverSettings @@ -206,7 +206,7 @@ function execute(args: Transformer.ExecuteArguments): Transformer.ExecuteResult Modules = new List> { new DiscriminatingUnion( - AbsolutePath.Create(Context.PathTable, sdkLocation)), + AbsolutePath.Create(Context.PathTable, TestDeploymentDir).Combine(Context.PathTable, RelativePath.Create(Context.StringTable, relativeSdkLocation))), }, }); } diff --git a/Public/Src/Engine/UnitTests/Engine/LazyMaterializationBuildTests.cs b/Public/Src/Engine/UnitTests/Engine/LazyMaterializationBuildTests.cs index f240ace29..fb8ea94e9 100644 --- a/Public/Src/Engine/UnitTests/Engine/LazyMaterializationBuildTests.cs +++ b/Public/Src/Engine/UnitTests/Engine/LazyMaterializationBuildTests.cs @@ -35,7 +35,6 @@ namespace Test.BuildXL.Engine { private CacheInitializer m_cacheInitializer; - /* The build used for tests in this class generate the following layout * * \HelloWorldFinal.exe.config (source) diff --git a/Public/Src/Engine/UnitTests/Engine/Test.BuildXL.Engine.dsc b/Public/Src/Engine/UnitTests/Engine/Test.BuildXL.Engine.dsc index c303a9d93..0b000bab3 100644 --- a/Public/Src/Engine/UnitTests/Engine/Test.BuildXL.Engine.dsc +++ b/Public/Src/Engine/UnitTests/Engine/Test.BuildXL.Engine.dsc @@ -3,6 +3,8 @@ import * as DetoursServices from "BuildXL.Sandbox.Windows"; import * as Xml from "Sdk.Xml"; +import * as Deployment from "Sdk.Deployment"; +import {Transformer} from "Sdk.Transformers"; namespace Engine { @@ -23,8 +25,34 @@ namespace Engine { }, ]; - // Update the value of this variable if you change the version of Microsoft.Net.Compilers in config.dsc. - const microsoftNetCompilerSpec = f`${Context.getMount("FrontEnd").path}/Nuget/specs/Microsoft.Net.Compilers/4.0.1/module.config.bm`; + // We generate specs as if the compilers package was source files, but point it to the downloaded NuGet + const compilerSpecsDir = Context.getNewOutputDirectory("compilers-specs"); + const microsoftNetCompilerSpec = Transformer.writeAllText(p`${compilerSpecsDir}/module.config.bm`, + "module({name: 'Microsoft.Net.Compilers', version: '4.0.1', nameResolutionSemantics: NameResolutionSemantics.implicitProjectReferences});"); + const specFile = Transformer.writeAllLines(p`${compilerSpecsDir}/package.dsc`, [ + "import {Transformer} from 'Sdk.Transformers';", + "namespace Contents {", + "export declare const qualifier: {};", + "@@public export const all: StaticDirectory = Transformer.sealPartialDirectory(d`package`, globR(d`package`, '*'));", + "}" + ]); + + // Deploy the compilers package plus the specs that refer to it + const deployable : Deployment.Definition = { + contents: [ + { + subfolder: a`compilers`, + contents: [ + { + subfolder: a`package`, + contents: [importFrom('Microsoft.Net.Compilers').Contents.all] + }, + specFile, + microsoftNetCompilerSpec + ] + } + ] + }; @@public export const categoriesToRunInParallel = [ @@ -47,12 +75,11 @@ namespace Engine { }, parallelGroups: categoriesToRunInParallel, testRunData: { - MicrosoftNetCompilersSdkLocation: microsoftNetCompilerSpec, + MicrosoftNetCompilersSdkLocation: "compilers/module.config.bm", }, tools: { exec: { dependencies: [ - microsoftNetCompilerSpec, importFrom("Microsoft.Net.Compilers").Contents.all, importFrom("Microsoft.NETCore.Compilers").Contents.all, ] @@ -87,6 +114,7 @@ namespace Engine { ], runtimeContent: [ ...libsUsedForTesting, + deployable ], }); } diff --git a/Public/Src/Engine/UnitTests/Scheduler/PipFingerprinterTests.cs b/Public/Src/Engine/UnitTests/Scheduler/PipFingerprinterTests.cs index 017e325dd..77994a616 100644 --- a/Public/Src/Engine/UnitTests/Scheduler/PipFingerprinterTests.cs +++ b/Public/Src/Engine/UnitTests/Scheduler/PipFingerprinterTests.cs @@ -882,6 +882,7 @@ namespace Test.BuildXL.Scheduler bool preservePathSetCasing = source.Vary(p => p.PreservePathSetCasing); bool writingToStandardErrorFailsExecution = source.Vary(p => p.WritingToStandardErrorFailsExecution); bool disableFullReparsePointResolving = source.Vary(p => p.DisableFullReparsePointResolving); + bool bypassFingerprintSalt = source.Vary(p => p.BypassFingerprintSalt); Process.Options options = Process.Options.None; if (hasUntrackedChildProcesses) @@ -940,6 +941,11 @@ namespace Test.BuildXL.Scheduler options |= Process.Options.DisableFullReparsePointResolving; } + if (bypassFingerprintSalt) + { + options |= Process.Options.BypassFingerprintSalt; + } + return new Process( executable: executable, workingDirectory: workingDirectory, diff --git a/Public/Src/FrontEnd/Core/FrontEndHostController.Nuget.cs b/Public/Src/FrontEnd/Core/FrontEndHostController.Nuget.cs index 17ccdd4b1..d5a67fb38 100644 --- a/Public/Src/FrontEnd/Core/FrontEndHostController.Nuget.cs +++ b/Public/Src/FrontEnd/Core/FrontEndHostController.Nuget.cs @@ -52,6 +52,7 @@ namespace BuildXL.FrontEnd.Core string weakPackageFingerprint, PackageIdentity package, AbsolutePath packageTargetFolder, + AbsolutePath pathToNuspec, Func>>> producePackage) { // Check if we can reuse a package that is layed out on disk already. @@ -97,6 +98,7 @@ namespace BuildXL.FrontEnd.Core weakPackageFingerprint, package, packageTargetFolder, + pathToNuspec, possiblePackageContents.Result), justification: "Okay to ignore putting in cache failure, will happen next time" ); @@ -208,7 +210,10 @@ namespace BuildXL.FrontEnd.Core return false; } - Logger.PackagePresumedUpToDateWithoutHashComparison(LoggingContext, package.GetFriendlyName()); + if (!FrontEndConfiguration.RespectWeakFingerprintForNugetUpToDateCheck()) + { + Logger.PackagePresumedUpToDateWithoutHashComparison(LoggingContext, package.GetFriendlyName()); + } return true; } @@ -354,7 +359,7 @@ namespace BuildXL.FrontEnd.Core // Saving package's hash file on disk. // But we can do this only when the content is not empty. - var packagesContent = packageDescriptor.Contents.Select(k => k.Key).ToList(); + var packagesContent = packageDescriptor.Contents.Select(k => k.Key).ToList(); if (packagesContent.Count == 0) { @@ -363,9 +368,6 @@ namespace BuildXL.FrontEnd.Core return PackageDownloadResult.RecoverableError(package); } - var newPackageHash = new PackageHashFile(weakPackageFingerprintHash.Hash.ToHex(), weakPackageFingerprint, packagesContent); - TryUpdatePackageHashFile(loggingContext, package, packageHashFile, packageHash, newPackageHash); - m_logger.PackageRestoredFromCache(loggingContext, package.GetFriendlyName()); if (forcePopulatePackageCache) @@ -394,11 +396,20 @@ namespace BuildXL.FrontEnd.Core } } + // The hash file is stored as part of the package, so we have the package layout available there + var maybePackageHashFile = PackageHashFile.TryReadFrom(GetPackageHashFile(packageTargetFolder)); + + if (!maybePackageHashFile.Succeeded) + { + m_logger.DownloadPackageFailedDueToCacheError(loggingContext, friendlyName, maybePackageHashFile.Failure.Describe()); + return PackageDownloadResult.RecoverableError(package); + } + // Step: Return descriptor indicating it was successfully restored from the cache return PackageDownloadResult.FromCache( package, packageTargetFolder, - packageDescriptor.Contents.Select(c => RelativePath.Create(FrontEndContext.StringTable, c.Key)).ToList(), + maybePackageHashFile.Result.Content.Select(entry => RelativePath.Create(FrontEndContext.StringTable, entry)).ToList(), weakPackageFingerprintHash.Hash.ToHex()); } @@ -407,6 +418,7 @@ namespace BuildXL.FrontEnd.Core string weakPackageFingerprint, PackageIdentity package, AbsolutePath packageTargetFolder, + AbsolutePath pathToNuspec, IReadOnlyList packageContent) { var friendlyName = package.GetFriendlyName(); @@ -423,11 +435,22 @@ namespace BuildXL.FrontEnd.Core // Cache was already initialized var cache = await m_nugetCache; - // Step: Store all the files into the content cache + // Generate the hash file, since that is stored as part of the cache content + var weakPackageFingerprintHash = cache.GetDownloadFingerprint(weakPackageFingerprint); + // The content should have relative paths + var content = packageContents.Select(rp => rp.ToString(PathTable.StringTable)).ToList(); + var newHash = new PackageHashFile(weakPackageFingerprintHash.Hash.ToHex(), weakPackageFingerprint, content); + var packageHashFile = GetPackageHashFile(packageTargetFolder); + TryUpdatePackageHashFile(loggingContext, package, packageHashFile, oldHash: null, newHash: newHash); + + // Step: Store the nuspec and the hash file into the content cache var stringKeyedHashes = new List(); - foreach (var relativePath in packageContents) + + foreach (var absolutePath in new[] { pathToNuspec, AbsolutePath.Create(PathTable, packageHashFile)}) { - var targetFileLocation = packageTargetFolder.Combine(PathTable, relativePath).Expand(PathTable); + var targetFileLocation = absolutePath.Expand(PathTable); + var result = packageTargetFolder.TryGetRelative(PathTable, absolutePath, out var relativePath); + Contract.Assert(result); ContentHash contentHash; try @@ -453,7 +476,6 @@ namespace BuildXL.FrontEnd.Core } } - var weakPackageFingerprintHash = cache.GetDownloadFingerprint(weakPackageFingerprint); // Step: Create a descriptor and store that in the fingerprint store under the weak fingerprint. var cacheDescriptor = PackageDownloadDescriptor.Create( friendlyName, @@ -471,11 +493,6 @@ namespace BuildXL.FrontEnd.Core m_logger.PackageNotFoundInCacheAndDownloaded(loggingContext, package.Id, package.Version, weakPackageFingerprintHash.Hash.ToHex(), weakPackageFingerprint); - // The content should have relative paths - var content = packageContents.Select(rp => rp.ToString(PathTable.StringTable)).ToList(); - var newHash = new PackageHashFile(weakPackageFingerprintHash.Hash.ToHex(), weakPackageFingerprint, content); - TryUpdatePackageHashFile(loggingContext, package, GetPackageHashFile(packageTargetFolder), oldHash: null, newHash: newHash); - return Unit.Void; } diff --git a/Public/Src/FrontEnd/Core/NugetCache.cs b/Public/Src/FrontEnd/Core/NugetCache.cs index 99548e9b6..4f673203d 100644 --- a/Public/Src/FrontEnd/Core/NugetCache.cs +++ b/Public/Src/FrontEnd/Core/NugetCache.cs @@ -132,7 +132,7 @@ namespace BuildXL.FrontEnd.Core private static ContentFingerprint CreateDownloadFingerprint(string baseText) { // In case something in the cached Bond data becomes incompatible, we must not match. - const string VersionText = ", BondDataVersion=2;FingerprintVersion=1"; + const string VersionText = ", BondDataVersion=2;FingerprintVersion=5"; var fingerprint = FingerprintUtilities.Hash(baseText + VersionText); return new ContentFingerprint(fingerprint); } diff --git a/Public/Src/FrontEnd/Core/PackageHashFile.cs b/Public/Src/FrontEnd/Core/PackageHashFile.cs index b0d36d60b..47b6223af 100644 --- a/Public/Src/FrontEnd/Core/PackageHashFile.cs +++ b/Public/Src/FrontEnd/Core/PackageHashFile.cs @@ -31,7 +31,7 @@ namespace BuildXL.FrontEnd.Core // The file format change will force specs regeneration. // Change the version if the nuget spec generation has changed in a backward incompatible way. - private const string HashFileFormatVersion = "9"; + private const string HashFileFormatVersion = "10"; /// /// The minimal number of lines for the hash file. diff --git a/Public/Src/FrontEnd/Nuget/BuildXL.FrontEnd.Nuget.dsc b/Public/Src/FrontEnd/Nuget/BuildXL.FrontEnd.Nuget.dsc index 97df9362e..d6679eaf1 100644 --- a/Public/Src/FrontEnd/Nuget/BuildXL.FrontEnd.Nuget.dsc +++ b/Public/Src/FrontEnd/Nuget/BuildXL.FrontEnd.Nuget.dsc @@ -14,9 +14,11 @@ namespace Nuget { sources: globR(d`.`, "*.cs"), references: [ ...addIf(BuildXLSdk.isFullFramework, + NetFx.Netstandard.dll, + NetFx.System.IO.Compression.dll, NetFx.System.Xml.dll, NetFx.System.Xml.Linq.dll, - NetFx.Netstandard.dll + NetFx.System.Net.Http.dll ), ...addIf(BuildXLSdk.isFullFramework, importFrom("System.Memory").withQualifier({targetFramework: "netstandard2.0"}).pkg @@ -33,6 +35,7 @@ namespace Nuget { importFrom("BuildXL.Engine").Processes.dll, importFrom("BuildXL.Pips").dll, importFrom("BuildXL.Utilities").dll, + importFrom("BuildXL.Utilities").VstsAuthentication.dll, importFrom("BuildXL.Utilities").Collections.dll, importFrom("BuildXL.Utilities").Configuration.dll, importFrom("BuildXL.Utilities").Interop.dll, @@ -42,12 +45,21 @@ namespace Nuget { importFrom("BuildXL.Utilities").Script.Constants.dll, importFrom("Newtonsoft.Json").pkg, - importFrom("NuGet.Versioning").pkg, + importFrom("NuGet.Versioning").withQualifier({targetFramework: "netstandard2.0"}).pkg, + importFrom("NuGet.Protocol").withQualifier({targetFramework: "netstandard2.0"}).pkg, + importFrom("NuGet.Configuration").withQualifier({targetFramework: "netstandard2.0"}).pkg, + importFrom("NuGet.Common").withQualifier({targetFramework: "netstandard2.0"}).pkg, + importFrom("NuGet.Frameworks").withQualifier({targetFramework: "netstandard2.0"}).pkg, + importFrom("NuGet.Packaging").withQualifier({targetFramework: "netstandard2.0"}).pkg, ...BuildXLSdk.tplPackages, ], + runtimeContent: [ + // Keep in sync with path at Public\Sdk\Public\Tools\NugetDownloader\Tool.NugetDownloader.dsc + importFrom("BuildXL.Tools").NugetDownloader.dll + ], internalsVisibleTo: [ "Test.BuildXL.FrontEnd.Nuget" - ] + ], }); } diff --git a/Public/Src/FrontEnd/Nuget/Failures/NugetFailedWithNonZeroExitCodeFailure.cs b/Public/Src/FrontEnd/Nuget/Failures/NugetFailedWithNonZeroExitCodeFailure.cs deleted file mode 100644 index 4b704e3cf..000000000 --- a/Public/Src/FrontEnd/Nuget/Failures/NugetFailedWithNonZeroExitCodeFailure.cs +++ /dev/null @@ -1,38 +0,0 @@ -// Copyright (c) Microsoft Corporation. -// Licensed under the MIT License. - -using System; -using BuildXL.Utilities.Configuration; -using static BuildXL.Utilities.FormattableStringEx; -namespace BuildXL.FrontEnd.Nuget -{ - /// - /// Nuget.exe failed with non-zero exit code. - /// - public sealed class NugetFailedWithNonZeroExitCodeFailure : NugetFailure - { - private readonly INugetPackage m_package; - private readonly int m_exitCode; - private readonly string m_stdOut; - private readonly string m_stdErr; - - /// - public NugetFailedWithNonZeroExitCodeFailure(INugetPackage package, int exitCode, string stdOut, string stdErr) - : base(FailureType.PackageNotFound) - { - m_package = package; - m_exitCode = exitCode; - - m_stdOut = stdOut?.Trim(); - m_stdErr = stdErr?.Trim(); - } - - /// - public override string Describe() - { - var separator = !string.IsNullOrEmpty(m_stdOut) && !string.IsNullOrEmpty(m_stdErr) ? Environment.NewLine : string.Empty; - var output = I($"{m_stdOut}{separator}{m_stdErr}"); - return I($"Package nuget://{m_package.Id}/{m_package.Version} could not be restored because nuget.exe failed with exit code '{m_exitCode}'. \r\nTools output:\r\n{output}\r\nSee the buildxl log for more details."); - } - } -} diff --git a/Public/Src/FrontEnd/Nuget/Failures/NugetFailure.cs b/Public/Src/FrontEnd/Nuget/Failures/NugetFailure.cs index 4ec98de31..f82e117a6 100644 --- a/Public/Src/FrontEnd/Nuget/Failures/NugetFailure.cs +++ b/Public/Src/FrontEnd/Nuget/Failures/NugetFailure.cs @@ -4,6 +4,7 @@ using System; using System.Collections.Generic; using System.Diagnostics.ContractsLight; +using System.Linq; using BuildXL.Utilities; using BuildXL.Utilities.Configuration; using TypeScript.Net.Extensions; @@ -21,13 +22,21 @@ namespace BuildXL.FrontEnd.Nuget public readonly FailureType Type; /// - public readonly Exception Exception; + public readonly string Message; /// public NugetFailure(FailureType failureType, Exception e = null) { Type = failureType; - Exception = e; + + Message = GetAllMessages(e); + } + + /// + public NugetFailure(FailureType failureType, string message) + { + Type = failureType; + Message = message; } /// @@ -58,20 +67,28 @@ namespace BuildXL.FrontEnd.Nuget } /// - /// Nuget.exe failed to restore a package. + /// Nuget invocation failure /// - public static NugetFailure CreateNugetInvocationFailure(INugetPackage package, int exitCode, string stdOut, string stdErr) + public static NugetFailure CreateNugetInvocationFailure(INugetPackage package, Exception e) { - Contract.Requires(package != null); - Contract.Requires(exitCode != 0); + return CreateNugetInvocationFailure(package, GetAllMessages(e)); + } + + /// + /// Nuget invocation failure + /// + public static NugetFailure CreateNugetInvocationFailure(INugetPackage package, string message) + { + Contract.RequiresNotNull(package); + Contract.RequiresNotNull(message); // If the stdOut has the following text: 'NotFound http' or 'WARNING: Unable to find version', it means that the package name or version are not found. - if (stdOut.Contains("NotFound http") || stdOut.Contains("WARNING: Unable to find version")) + if (message.Contains("NotFound http") || message.Contains("WARNING: Unable to find version")) { return new CanNotFindPackageFailure(package); } - return new NugetFailedWithNonZeroExitCodeFailure(package, exitCode, stdOut, stdErr); + return new NugetInvocationFailure(package, message); } /// @@ -89,10 +106,10 @@ namespace BuildXL.FrontEnd.Nuget { if (Package != null) { - return I($"Failed to retrieve nuget package '{Package.Id}' version '{Package.Version}' due to {Type.ToString()}. {Exception?.ToStringDemystified()}"); + return I($"Failed to retrieve nuget package '{Package.Id}' version '{Package.Version}' due to {Type.ToString()}. {Message}"); } - return I($"Failed to process nuget packages due to {Type.ToString()}. {Exception?.ToStringDemystified()}"); + return I($"Failed to process nuget packages due to {Type.ToString()}. {Message}"); } /// @@ -110,30 +127,15 @@ namespace BuildXL.FrontEnd.Nuget /// public enum FailureType { - /// - FetchNugetExe, - /// FetchCredentialProvider, - /// - WriteConfigFile, - /// WriteSpecFile, /// CleanTargetFolder, - /// - NugetFailedWithNonZeroExitCode, - - /// - NugetFailedWithIoException, - - /// - ListPackageContents, - /// ReadNuSpecFile, @@ -160,6 +162,37 @@ namespace BuildXL.FrontEnd.Nuget /// UnhandledError, + + /// + NoBaseAddressForRepository, + } + + private static string GetAllMessages(Exception e) + { + if (e is null) + { + return string.Empty; + } + + if (e is AggregateException aggregateException) + { + return string.Join(Environment.NewLine, aggregateException.Flatten().InnerExceptions.SelectMany(ie => GetInnerExceptions(ie)).Select(ex => ex.Message)); + } + else + { + return string.Join(Environment.NewLine, GetInnerExceptions(e).Select(e => e.Message)); + } + } + + private static IEnumerable GetInnerExceptions(Exception ex) + { + var innerException = ex; + do + { + yield return innerException; + innerException = innerException.InnerException; + } + while (innerException != null); } } } diff --git a/Public/Src/FrontEnd/Nuget/Failures/NugetInvocationFailure.cs b/Public/Src/FrontEnd/Nuget/Failures/NugetInvocationFailure.cs new file mode 100644 index 000000000..e559daef8 --- /dev/null +++ b/Public/Src/FrontEnd/Nuget/Failures/NugetInvocationFailure.cs @@ -0,0 +1,31 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +using BuildXL.Utilities.Configuration; +using static BuildXL.Utilities.FormattableStringEx; +namespace BuildXL.FrontEnd.Nuget +{ + /// + /// Nuget invocation failed. + /// + public sealed class NugetInvocationFailure : NugetFailure + { + private readonly INugetPackage m_package; + private readonly string m_message; + + /// + public NugetInvocationFailure(INugetPackage package, string message) + : base(FailureType.PackageNotFound) + { + m_package = package; + + m_message = message?.Trim(); + } + + /// + public override string Describe() + { + return I($"Package nuget://{m_package.Id}/{m_package.Version} could not be restored. {m_message}."); + } + } +} diff --git a/Public/Src/FrontEnd/Nuget/NugetAnalyzedPackage.cs b/Public/Src/FrontEnd/Nuget/NugetAnalyzedPackage.cs index 4769091af..7e5b42a69 100644 --- a/Public/Src/FrontEnd/Nuget/NugetAnalyzedPackage.cs +++ b/Public/Src/FrontEnd/Nuget/NugetAnalyzedPackage.cs @@ -38,6 +38,14 @@ namespace BuildXL.FrontEnd.Nuget /// public MultiValueDictionary DependenciesPerFramework { get; } + + /// + /// Credential provider path that is used to retrieve the package + /// + /// + /// AbsolutePath.Invalid if none is to be used + /// + public AbsolutePath CredentialProviderPath { get; } /// public bool IsManagedPackage { get; set; } @@ -129,7 +137,8 @@ namespace BuildXL.FrontEnd.Nuget NugetFrameworkMonikers nugetFrameworkMonikers, PackageOnDisk packageOnDisk, Dictionary packagesOnConfig, - bool doNotEnforceDependencyVersions) + bool doNotEnforceDependencyVersions, + AbsolutePath credentialProviderPath) { m_context = context; PackageOnDisk = packageOnDisk; @@ -142,6 +151,7 @@ namespace BuildXL.FrontEnd.Nuget AssemblyToTargetFramework = new MultiValueDictionary(); m_dependencies = new List(); DependenciesPerFramework = new MultiValueDictionary(); + CredentialProviderPath = credentialProviderPath; } /// @@ -156,13 +166,14 @@ namespace BuildXL.FrontEnd.Nuget [CanBeNull] XDocument nuSpec, PackageOnDisk packageOnDisk, Dictionary packagesOnConfig, - bool doNotEnforceDependencyVersions) + bool doNotEnforceDependencyVersions, + AbsolutePath credentialProviderPath) { Contract.Requires(context != null); Contract.Requires(packageOnDisk != null); var analyzedPackage = new NugetAnalyzedPackage(context, nugetFrameworkMonikers, packageOnDisk, - packagesOnConfig, doNotEnforceDependencyVersions); + packagesOnConfig, doNotEnforceDependencyVersions, credentialProviderPath); analyzedPackage.ParseManagedSemantics(); if (nuSpec != null && !analyzedPackage.TryParseDependenciesFromNuSpec(nuSpec)) diff --git a/Public/Src/FrontEnd/Nuget/NugetFrontEnd.cs b/Public/Src/FrontEnd/Nuget/NugetFrontEnd.cs index 3070838b9..2aa9b07ea 100644 --- a/Public/Src/FrontEnd/Nuget/NugetFrontEnd.cs +++ b/Public/Src/FrontEnd/Nuget/NugetFrontEnd.cs @@ -41,7 +41,7 @@ namespace BuildXL.FrontEnd.Nuget public IReadOnlyCollection SupportedResolvers { get; } = new[] { WorkspaceNugetModuleResolver.NugetResolverName }; /// - public bool ShouldRestrictBuildParameters { get; } = true; + public bool ShouldRestrictBuildParameters { get; } = false; /// public void InitializeFrontEnd(FrontEndHost host, FrontEndContext context, IConfiguration configuration) diff --git a/Public/Src/FrontEnd/Nuget/NugetInspectedPackage.cs b/Public/Src/FrontEnd/Nuget/NugetInspectedPackage.cs new file mode 100644 index 000000000..64578faa7 --- /dev/null +++ b/Public/Src/FrontEnd/Nuget/NugetInspectedPackage.cs @@ -0,0 +1,31 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +using System.Collections.Generic; +using System.Diagnostics.ContractsLight; +using BuildXL.Utilities; + +namespace BuildXL.FrontEnd.Nuget +{ + /// + /// The result of inspecting a package with + /// + public readonly struct NugetInspectedPackage + { + /// + public readonly string Nuspec { get; } + + /// + public readonly IReadOnlyList Content { get; } + + /// + public NugetInspectedPackage(string nuspec, IReadOnlyList content) + { + Contract.RequiresNotNull(nuspec); + Contract.RequiresNotNull(content); + + Nuspec = nuspec; + Content = content; + } + } +} diff --git a/Public/Src/FrontEnd/Nuget/NugetPackageInspector.cs b/Public/Src/FrontEnd/Nuget/NugetPackageInspector.cs new file mode 100644 index 000000000..02d303881 --- /dev/null +++ b/Public/Src/FrontEnd/Nuget/NugetPackageInspector.cs @@ -0,0 +1,365 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +using System; +using System.Collections.Generic; +using System.Diagnostics.ContractsLight; +using System.IO; +using System.IO.Compression; +using System.Linq; +using System.Net.Http; +using System.Net.Http.Headers; +using System.Text; +using System.Threading; +using System.Threading.Tasks; +using BuildXL.FrontEnd.Nuget.Tracing; +using BuildXL.Utilities; +using BuildXL.Utilities.Configuration; +using BuildXL.Utilities.Instrumentation.Common; +using BuildXL.Utilities.VstsAuthentication; +using NuGet.Configuration; +using NuGet.Packaging; +using NuGet.Protocol; + +namespace BuildXL.FrontEnd.Nuget +{ + /// + /// Retrieves NuGet package layouts and specs from a set of feeds + /// + /// + /// Packages are not necessarily downloaded in full in order to inspect them, and partial downloads are always attempted first + /// + public class NugetPackageInspector + { + // A 5K chunk looks reasonable as the initial download: most package central directory fits in 5K, so no extra requests are needed + private const long MinimalChunkSizeInBytes = 5_000; + // On every partial download iteration we linearly grow using a 20K base (i.e. 20, 40, 60, 80, etc.) + private const long IncrementChunkSizeInBytes = 20_000; + + private readonly CancellationToken m_cancellationToken; + private readonly LoggingContext m_loggingContext; + private readonly IEnumerable<(string repositoryName, Uri repositoryUri)> m_repositories; + private readonly StringTable m_stringTable; + private readonly Func> m_discoverCredentialProvider; + private IReadOnlyDictionary m_packageBaseAddress; + private readonly Lazy>> m_initializationResult; + + /// + public NugetPackageInspector( + IEnumerable<(string repositoryName, Uri repositoryUri)> repositories, + StringTable stringTable, + Func> discoverCredentialProvider, + CancellationToken cancellationToken, + Utilities.Instrumentation.Common.LoggingContext loggingContext) + { + Contract.RequiresNotNull(repositories); + Contract.RequiresNotNull(discoverCredentialProvider); + + m_cancellationToken = cancellationToken; + m_loggingContext = loggingContext; + m_repositories = repositories; + m_stringTable = stringTable; + m_discoverCredentialProvider = discoverCredentialProvider; + + m_initializationResult = new Lazy>>(async () => { + + var logger = new StringBuilder(); + + try + { + return (await VSTSAuthenticationHelper.TryCreateSourceRepositories(m_repositories, m_discoverCredentialProvider, m_cancellationToken, logger)) + .Then(sourceRepositories => + { + var packageBaseAddressMutable = new Dictionary(); + foreach (var sourceRepository in sourceRepositories) + { + var serviceIndexResource = sourceRepository.GetResource(m_cancellationToken); + + if (serviceIndexResource == null) + { + return new NugetFailure(NugetFailure.FailureType.NoBaseAddressForRepository, $"Cannot find index service for ${sourceRepository.PackageSource.SourceUri}"); + } + + foreach (Uri packageBaseAddress in serviceIndexResource.GetServiceEntryUris(ServiceTypes.PackageBaseAddress)) + { + packageBaseAddressMutable[packageBaseAddress] = sourceRepository.PackageSource.Credentials; + } + } + + m_packageBaseAddress = packageBaseAddressMutable; + + return true; + }); + + } + catch (Exception e) when (e is AggregateException || e is HttpRequestException) + { + return new NugetFailure(NugetFailure.FailureType.NoBaseAddressForRepository, e); + } + finally + { + var log = logger.ToString(); + if (!string.IsNullOrWhiteSpace(log)) + { + Logger.Log.NuGetInspectionInitializationInfo(m_loggingContext, log); + } + } + }, + LazyThreadSafetyMode.ExecutionAndPublication); + } + + /// + /// Whether has been succesfully called + /// + /// Thread safe + public async Task IsInitializedAsync() => m_initializationResult.IsValueCreated && (await m_initializationResult.Value).Succeeded; + + /// + /// Retrieves the index sources of the specified repositories and initializes the base addresses + /// + /// Thread safe. Subsequents initializations have no effect and return the same result as the first one did. + public Task> TryInitAsync() => m_initializationResult.Value; + + /// + /// Tries to retrieve the layout and nuspec of the given package + /// + /// Thread safe + public async Task> TryInspectAsync(INugetPackage identity) + { + Contract.Assert(await IsInitializedAsync(), "TryInitAsync() must be succesfully called first"); + + if (m_packageBaseAddress.Count == 0) + { + return new NugetFailure(NugetFailure.FailureType.NoBaseAddressForRepository); + } + + // Build the URI for the requested package and try to inspect it + var packageIdLowerCase = identity.Id.ToLowerInvariant(); + var version = new NuGet.Versioning.NuGetVersion(identity.Version).ToNormalizedString(); + + Possible maybeInspectedPackage = default; + foreach (var baseAddress in m_packageBaseAddress) + { + // URIs for retrieving the nuspec and the nupkg + var packageUri = $"{baseAddress.Key.AbsoluteUri}{packageIdLowerCase}/{version}/{packageIdLowerCase}.{version}.nupkg"; + var nuspecUri = $"{baseAddress.Key.AbsoluteUri}{packageIdLowerCase}/{version}/{packageIdLowerCase}.nuspec"; + + maybeInspectedPackage = await TryInspectPackageAsync(identity, new Uri(packageUri), new Uri(nuspecUri), baseAddress.Value); + if (maybeInspectedPackage.Succeeded) + { + return maybeInspectedPackage; + } + } + + return maybeInspectedPackage.Failure; + } + + private async Task> TryInspectPackageAsync(INugetPackage identity, Uri nupkgUri, Uri nuspecUri, PackageSourceCredential packageSourceCredential) + { + AuthenticationHeaderValue authenticationHeader = null; + + // If the download URI is pointing to a VSTS feed and we get a valid auth token, make it part of the request + // We only want to send the token over HTTPS and to a VSTS domain to avoid security issues + if (packageSourceCredential != null) + { + authenticationHeader = VSTSAuthenticationHelper.GetAuthenticationHeaderFromPAT(packageSourceCredential.PasswordText); + } + + // We want to be able to read the zip file central directory, where the layout of the package is. This is at the end of a zip file, + // so we'll start requesting partial chunks of the content starting from the end and increasingly request more until we can understand + // the zip central directory + + int retries = 3; + + while (true) + { + try + { + using (var httpClient = new HttpClient()) + { + httpClient.Timeout = TimeSpan.FromMinutes(1); + + // Use authentication if defined + if (authenticationHeader != null) + { + httpClient.DefaultRequestHeaders.Accept.Clear(); + httpClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json")); + httpClient.DefaultRequestHeaders.Authorization = authenticationHeader; + } + + // We need the nuspec file for analyzing the package + var response = await httpClient.GetAsync(nuspecUri, m_cancellationToken); + + if (!response.IsSuccessStatusCode) + { + return NugetFailure.CreateNugetInvocationFailure(identity, response.ReasonPhrase); + } + + var nuspec = await response.Content.ReadAsStringAsync(); + + // Now inspect the content of the nupkg + return (await InspectContentAsync(identity, nupkgUri, authenticationHeader, httpClient)).Then(content => new NugetInspectedPackage(nuspec, content)); + } + } + catch (Exception e) when (e is HttpRequestException || e is AggregateException || e is TaskCanceledException) + { + retries--; + + if (retries == 0) + { + return NugetFailure.CreateNugetInvocationFailure(identity, e); + } + } + } + } + + private async Task>> InspectContentAsync(INugetPackage identity, Uri nupkgUri, AuthenticationHeaderValue authenticationHeader, HttpClient httpClient) + { + long? chunkStart = null; + HttpResponseMessage response; + bool forceFullDownload = false; + var partialPackage = new MemoryStream(); + + try + { + // How many chunks we downloaded so far for the given package + int chunkCount = 0; + + while (true) + { + // Only set a download range if we are not forcing a full download + if (!forceFullDownload) + { + // Set the range header to retrieve a particular range of the content + if (!chunkStart.HasValue) + { + // We don't know the total size yet, this is the first request. Start with MinimalChunkSizeInBytes. + httpClient.DefaultRequestHeaders.Add("Range", "bytes=-" + MinimalChunkSizeInBytes); + } + else + { + // This is not the first time we request a chunk, and that means the content we retrieved son far is not enough to read the zip central directory. + // So we already know where the chunk starts (and ends) + httpClient.DefaultRequestHeaders.Add("Range", $"bytes={chunkStart}-{chunkStart + (chunkCount * IncrementChunkSizeInBytes) - 1}"); + } + } + + // TODO: redirect handling may be needed here + response = await httpClient.GetAsync(nupkgUri, HttpCompletionOption.ResponseHeadersRead, m_cancellationToken); + + // In the rare case where the initial chunk is bigger than the package, we might get this. Just force full download and retry + if (response.StatusCode == System.Net.HttpStatusCode.RequestedRangeNotSatisfiable) + { + httpClient.DefaultRequestHeaders.Remove("Range"); + forceFullDownload = true; + continue; + } + + if (!response.IsSuccessStatusCode) + { + break; + } + + // Check whether the service decided to ignore the partial request, and instead downloaded the whole thing + if (response.StatusCode == System.Net.HttpStatusCode.OK) + { + forceFullDownload = true; + } + + long totalLength = 0; + if (!forceFullDownload) + { + totalLength = response.Content.Headers.ContentRange.Length.Value; + + if (!chunkStart.HasValue) + { + // We just did the first request, chunk start points to MinimalChunkSizeInBytes from the end + chunkStart = totalLength - MinimalChunkSizeInBytes; + } + } +#if NET_COREAPP_60 + using (var chunk = await response.Content.ReadAsStreamAsync(m_cancellationToken)) +#else + using (var chunk = await response.Content.ReadAsStreamAsync()) +#endif + { + // Unfortunately the .net framework does not support prepending a stream, so we do it manually + // TODO: If this becomes a perf/footprint issue we could write a stream wrapper that knows how to compose streams. But + // the expectation is that we shouldn't need to iterate over the same package for very long until we can read it + partialPackage = await PrependToStreamAsync(chunk, partialPackage); + } + + // We don't want to get in the business of decoding a zip file. For that we use ZipArchive and check whether we get an exception + // when we read it. + // However, ZipArchive expects a stream with the proper length, since it does some validations about the location of the central + // directory baed on that. To avoid creating a stream of the real size (some packages are GB big), we use a ZeroPaddedStream that + // wraps the original stream but pretends to have the required size + IReadOnlyCollection entries; + try + { + var zf = new ZipArchive(forceFullDownload + ? partialPackage + : new ZeroLeftPaddedStream(partialPackage, totalLength), ZipArchiveMode.Read); + entries = zf.Entries; + } + catch (InvalidDataException ex) + { + // We downloaded the package in full but we cannot recognize it as a zip + if (forceFullDownload) + { + return NugetFailure.CreateNugetInvocationFailure(identity, $"Cannot inspect package layout: {ex.ToStringDemystified()} "); + } + + // This check is just a heuristics for the rare case when we already downloaded more than 10% of the package total + // size but we can't still read the zip central directory. At this point we can rather download the whole package + if (partialPackage.Length < totalLength * .1) + { + chunkCount++; + // We were not able to read the package central directory with what we downloaded so far. Request another chunk and + // try again + chunkStart -= chunkCount * IncrementChunkSizeInBytes; + httpClient.DefaultRequestHeaders.Remove("Range"); + + continue; + } + + httpClient.DefaultRequestHeaders.Remove("Range"); + forceFullDownload = true; + continue; + } + + return entries + .Select(entry => entry.FullName.Contains('%') ? System.Net.WebUtility.UrlDecode(entry.FullName) : entry.FullName) + .Where(entry => PackageHelper.IsPackageFile(entry, PackageSaveMode.Files | PackageSaveMode.Nuspec)) + .Select(entry => RelativePath.Create(m_stringTable, entry)).ToArray(); + } + } + finally + { + partialPackage.Dispose(); + } + + return NugetFailure.CreateNugetInvocationFailure(identity, $"Cannot inspect package layout: {response.RequestMessage} "); + } + + private async Task PrependToStreamAsync(Stream prefix, MemoryStream stream) + { + // If the destination stream is empty, just copy the prefix over + if (stream.Length == 0) + { + await prefix.CopyToAsync(stream, m_cancellationToken); + return stream; + } + + var tempPackage = new MemoryStream(); + await prefix.CopyToAsync(tempPackage, m_cancellationToken); + + stream.Position = 0; + await stream.CopyToAsync(tempPackage, m_cancellationToken); + + stream.Dispose(); + + return tempPackage; + } + } +} diff --git a/Public/Src/FrontEnd/Nuget/NugetSpecGenerator.cs b/Public/Src/FrontEnd/Nuget/NugetSpecGenerator.cs index cb9bd5bce..daa084428 100644 --- a/Public/Src/FrontEnd/Nuget/NugetSpecGenerator.cs +++ b/Public/Src/FrontEnd/Nuget/NugetSpecGenerator.cs @@ -14,6 +14,8 @@ using TypeScript.Net.Extensions; using TypeScript.Net.Types; using static TypeScript.Net.DScript.SyntaxFactory; using static BuildXL.FrontEnd.Nuget.SyntaxFactoryEx; +using BuildXL.FrontEnd.Sdk; +using BuildXL.FrontEnd.Script.Literals; namespace BuildXL.FrontEnd.Nuget { @@ -25,22 +27,31 @@ namespace BuildXL.FrontEnd.Nuget private readonly PathTable m_pathTable; private readonly PackageOnDisk m_packageOnDisk; private readonly NugetAnalyzedPackage m_analyzedPackage; - + private readonly IReadOnlyDictionary m_repositories; private readonly NugetFrameworkMonikers m_nugetFrameworkMonikers; - + private readonly AbsolutePath m_sourceDirectory; private readonly PathAtom m_xmlExtension; private readonly PathAtom m_pdbExtension; + private readonly int? m_timeoutInMinutes; /// Current spec generation format version - public const int SpecGenerationFormatVersion = 11; + public const int SpecGenerationFormatVersion = 12; /// - public NugetSpecGenerator(PathTable pathTable, NugetAnalyzedPackage analyzedPackage) + public NugetSpecGenerator( + PathTable pathTable, + NugetAnalyzedPackage analyzedPackage, + IReadOnlyDictionary repositories, + AbsolutePath sourceDirectory, + int? timeoutInMinutes = null) { m_pathTable = pathTable; m_analyzedPackage = analyzedPackage; + m_repositories = repositories; m_packageOnDisk = analyzedPackage.PackageOnDisk; m_nugetFrameworkMonikers = new NugetFrameworkMonikers(pathTable.StringTable); + m_sourceDirectory = sourceDirectory; + m_timeoutInMinutes = timeoutInMinutes; m_xmlExtension = PathAtom.Create(pathTable.StringTable, ".xml"); m_pdbExtension = PathAtom.Create(pathTable.StringTable, ".pdb"); @@ -53,13 +64,13 @@ namespace BuildXL.FrontEnd.Nuget /// The generated format is: /// [optional] import of managed sdk core /// [optional] qualifier declaration - /// const packageRoot = d`absolute path to the package roo`; /// @@public - /// export const contents: StaticDirectory = Transformer.sealDirectory( - /// packageRoot, - /// [ - /// f`${packageRoot}/file`, - /// ]); + /// export const contents: StaticDirectory = NuGetDownloader.downloadPackage( + /// { + /// id: "package ID", + /// version: "X.XX", + /// ... + /// } /// @@public /// export const pkg: NugetPackage = {contents ...}; /// @@ -68,8 +79,8 @@ namespace BuildXL.FrontEnd.Nuget { var sourceFileBuilder = new SourceFileBuilder(); - // 0. Import {Transformer} from "Sdk.Transformers" to be able to seal directories - sourceFileBuilder.Statement(ImportDeclaration(new [] { "Transformer" }, "Sdk.Transformers")); + // 0. Import * as NugetDownloader from "BuildXL.Tools.NugetDownloader" to be able to download NuGet packages + sourceFileBuilder.Statement(ImportDeclaration("NugetDownloader", "BuildXL.Tools.NugetDownloader")); // 1. Optional import of managed sdk. if (analyzedPackage.IsManagedPackage) @@ -88,12 +99,7 @@ namespace BuildXL.FrontEnd.Nuget .SemicolonAndBlankLine(); } - // 3. Declare a public directory that points to the package root, for convenience reasons - sourceFileBuilder - .Statement(new VariableDeclarationBuilder().Name("packageRoot").Initializer(PropertyAccess("Contents", "packageRoot")).Build()) - .SemicolonAndBlankLine(); - - // Create a sealed directory declaration with all the package content + // Create a seal directory declaration with all the package content sourceFileBuilder .Statement(CreatePackageContents()) .SemicolonAndBlankLine(); @@ -279,24 +285,59 @@ namespace BuildXL.FrontEnd.Nuget private IStatement CreatePackageContents() { - var relativepath = "../../../pkgs/" + m_packageOnDisk.Package.Id + "." + m_packageOnDisk.Package.Version; + // Arguments for calling the nuget downloader SDK + var downloadCallArgs = new List<(string, IExpression expression)>(4) + { + ("id", new LiteralExpression(m_analyzedPackage.Id)), + ("version", new LiteralExpression(m_analyzedPackage.Version)), + ("downloadDirectory", Identifier("outputDir")), + ("extractedFiles", new ArrayLiteralExpression(m_analyzedPackage.PackageOnDisk.Contents + .Select(relativePath => PathLikeLiteral(InterpolationKind.RelativePathInterpolation, relativePath.ToString(m_pathTable.StringTable, PathFormat.Script))))), + ("repositories", new ArrayLiteralExpression(m_repositories.Select(kvp => new ArrayLiteralExpression(new LiteralExpression(kvp.Key), new LiteralExpression(kvp.Value))))) + }; + + // If a credential provider was used to inspect the package, pass it as an argument to be able to retrieve it. + if (m_analyzedPackage.CredentialProviderPath.IsValid) + { + // If the credential provider is within the source tree, express it in terms of a mount, so the generated + // spec is more resilient to cache hits across machines + IExpression path; + if (m_sourceDirectory.TryGetRelative(m_pathTable, m_analyzedPackage.CredentialProviderPath, out var relativeCredentialProviderPath)) + { + path = PathLikeLiteral( + InterpolationKind.FileInterpolation, + new PropertyAccessExpression(new CallExpression(new PropertyAccessExpression("Context", "getMount"), new LiteralExpression("SourceRoot")), "path") , + "/" + relativeCredentialProviderPath.ToString(m_pathTable.StringTable, PathFormat.Script)); + } + else + { + path = PathLikeLiteral(InterpolationKind.FileInterpolation, m_analyzedPackage.CredentialProviderPath.ToString(m_pathTable, PathFormat.Script)); + } + + downloadCallArgs.Add(("credentialProviderPath", path)); + } + + if (m_timeoutInMinutes != null) + { + downloadCallArgs.Add(("timeoutInMinutes", new LiteralExpression(m_timeoutInMinutes.Value))); + } return new ModuleDeclaration( "Contents", Qualifier(new TypeLiteralNode()), - PathLikeConstVariableDeclaration("packageRoot", InterpolationKind.DirectoryInterpolation, relativepath, Visibility.Export), + + new VariableDeclarationBuilder().Name("outputDir").Visibility(Visibility.None).Type(new TypeReferenceNode("Directory")).Initializer( + new CallExpression(new PropertyAccessExpression("Context", "getNewOutputDirectory"), new LiteralExpression("nuget"))).Build(), + new VariableDeclarationBuilder() .Name("all") .Visibility(Visibility.Public) .Type(new TypeReferenceNode("StaticDirectory")) .Initializer( - new CallExpression( - new PropertyAccessExpression("Transformer", "sealDirectory"), - new Identifier("packageRoot"), - new ArrayLiteralExpression( - m_packageOnDisk.Contents.OrderBy(path => path.ToString(m_pathTable.StringTable)).Select(GetFileExpressionForPath) - .ToArray()))) + new CallExpression( + new PropertyAccessExpression("NugetDownloader", "downloadPackage"), + ObjectLiteral(downloadCallArgs.ToArray()))) .Build() ); } @@ -377,11 +418,10 @@ namespace BuildXL.FrontEnd.Nuget private IExpression GetFileExpressionForPath(RelativePath relativePath) { - // f`{packageRoot}/relativePath` - return PathLikeLiteral( - InterpolationKind.FileInterpolation, - Identifier("packageRoot"), - "/" + relativePath.ToString(m_pathTable.StringTable, PathFormat.Script)); + // all.assertExistence(r`relativePath`) + return new CallExpression(new PropertyAccessExpression("Contents", "all", "getFile"), PathLikeLiteral( + InterpolationKind.RelativePathInterpolation, + relativePath.ToString(m_pathTable.StringTable, PathFormat.Script))); } private IExpression CreateSimpleBinary(RelativePath binaryFile) diff --git a/Public/Src/FrontEnd/Nuget/PackageOnDisk.cs b/Public/Src/FrontEnd/Nuget/PackageOnDisk.cs index a80642e0e..6f49386b2 100644 --- a/Public/Src/FrontEnd/Nuget/PackageOnDisk.cs +++ b/Public/Src/FrontEnd/Nuget/PackageOnDisk.cs @@ -68,7 +68,9 @@ namespace BuildXL.FrontEnd.Nuget out AbsolutePath nuSpecFile, out AbsolutePath moduleConfigFile) { - nuSpecFile = AbsolutePath.Invalid; + // The nuspec file is always at the root of the package. + nuSpecFile = packageDownloadResult.TargetLocation.Combine(pathTable, nuspecFileName); + moduleConfigFile = AbsolutePath.Invalid; foreach (var relativePath in packageDownloadResult.Contents) @@ -77,11 +79,7 @@ namespace BuildXL.FrontEnd.Nuget if (!relativePath.IsEmpty) { var fileName = relativePath.GetName(); - if (fileName.CaseInsensitiveEquals(pathTable.StringTable, nuspecFileName)) - { - nuSpecFile = packageDownloadResult.TargetLocation.Combine(pathTable, relativePath); - } - else if (IsModuleConfigFileName(fileName, pathTable.StringTable)) + if (IsModuleConfigFileName(fileName, pathTable.StringTable)) { moduleConfigFile = packageDownloadResult.TargetLocation.Combine(pathTable, relativePath); } diff --git a/Public/Src/FrontEnd/Nuget/Tracing/Log.cs b/Public/Src/FrontEnd/Nuget/Tracing/Log.cs index d9bdbe9d0..3444e5028 100644 --- a/Public/Src/FrontEnd/Nuget/Tracing/Log.cs +++ b/Public/Src/FrontEnd/Nuget/Tracing/Log.cs @@ -23,33 +23,6 @@ namespace BuildXL.FrontEnd.Nuget.Tracing /// public static Logger Log { get; } = new LoggerImpl(); - [GeneratedEvent( - (ushort)LogEventId.LaunchingNugetExe, - EventGenerators = EventGenerators.LocalOnly, - EventLevel = Level.Verbose, - Keywords = (int)Keywords.Diagnostics, - EventTask = (ushort)Tasks.Parser, - Message = "Package nuget://{id}/{version} is being restored by launching nuget.exe with commandline: {commandline}")] - public abstract void LaunchingNugetExe(LoggingContext context, string id, string version, string commandline); - - [GeneratedEvent( - (ushort)LogEventId.CredentialProviderRequiresToolUrl, - EventGenerators = EventGenerators.LocalOnly, - EventLevel = Level.Error, - Keywords = (ushort)(Keywords.UserMessage | Keywords.UserError), - EventTask = (ushort)Tasks.Parser, - Message = "CredentialProviders for the Nuget resolver are required to specify ToolUrl. '{toolName}' does not do so.")] - public abstract void CredentialProviderRequiresToolUrl(LoggingContext context, string toolName); - - [GeneratedEvent( - (ushort)LogEventId.NugetDownloadInvalidHash, - EventGenerators = EventGenerators.LocalOnly, - EventLevel = Level.Warning, - Keywords = (ushort)Keywords.UserMessage, - EventTask = (ushort)Tasks.Parser, - Message = "Configured downloadHash '{hash}' for tool '{toolName}' is invalid. Attempt to download tool without hash guard.")] - public abstract void NugetDownloadInvalidHash(LoggingContext context, string toolName, string hash); - [GeneratedEvent( (ushort)LogEventId.NugetFailedToCleanTargetFolder, EventGenerators = EventGenerators.LocalOnly, @@ -60,74 +33,13 @@ namespace BuildXL.FrontEnd.Nuget.Tracing public abstract void NugetFailedToCleanTargetFolder(LoggingContext context, string id, string version, string targetLocation, string message); [GeneratedEvent( - (ushort)LogEventId.NugetFailedWithNonZeroExitCode, - EventGenerators = EventGenerators.LocalOnly, - EventLevel = Level.Error, - Keywords = (ushort)Keywords.UserMessage, - EventTask = (ushort)Tasks.Parser, - Message = - "Package nuget://{id}/{version} could not be downloaded because nuget.exe failed with exit code '{exitcode}'. \r\nTools output:\r\n{output}\r\nSee the buildxl log for more details.")] - public abstract void NugetFailedWithNonZeroExitCode(LoggingContext context, string id, string version, int exitcode, string output); - - [GeneratedEvent( - (ushort)LogEventId.NugetFailedDueToSomeWellKnownIssue, - EventGenerators = EventGenerators.LocalOnly, - EventLevel = Level.Error, - Keywords = (ushort)Keywords.UserMessage, - EventTask = (ushort)Tasks.Parser, - Message = - "Package nuget://{id}/{version} could not be restored. {message}\r\nSee the buildxl log for more details.")] - public abstract void NugetFailedDueToSomeWellKnownIssue(LoggingContext context, string id, string version, string message); - - [GeneratedEvent( - (ushort)LogEventId.NugetFailedWithNonZeroExitCodeDetailed, + (ushort)LogEventId.NugetInspectionInitialization, EventGenerators = EventGenerators.LocalOnly, EventLevel = Level.Verbose, Keywords = (ushort)Keywords.UserMessage, EventTask = (ushort)Tasks.Parser, - Message = - "Package nuget://{id}/{version} could not be downloaded because nuget.exe failed with exit code '{exitcode}'. The standard output was:\r\n{stdOut}\r\n. The standard Error was:\r\n{stdErr}")] - public abstract void NugetFailedWithNonZeroExitCodeDetailed( - LoggingContext context, - string id, - string version, - int exitcode, - string stdOut, - string stdErr); - - [GeneratedEvent( - (ushort)LogEventId.NugetFailedToListPackageContents, - EventGenerators = EventGenerators.LocalOnly, - EventLevel = Level.Error, - Keywords = (ushort)Keywords.UserMessage, - EventTask = (ushort)Tasks.Parser, - Message = - "Package nuget://{id}/{version} could not be downloaded because we could not list the content of the folder '{packageFolder}': {message}")] - public abstract void NugetFailedToListPackageContents(LoggingContext context, string id, string version, string packageFolder, string message); - - [GeneratedEvent( - (ushort)LogEventId.NugetFailedToWriteConfigurationFile, - EventGenerators = EventGenerators.LocalOnly, - EventLevel = Level.Error, - Keywords = (ushort)Keywords.UserMessage, - EventTask = (ushort)Tasks.Parser, - Message = "Could not be write configuration file to '{configFile}': {message}")] - public abstract void NugetFailedToWriteConfigurationFile(LoggingContext context, string configFile, string message); - - [GeneratedEvent( - (ushort)LogEventId.NugetFailedToWriteConfigurationFileForPackage, - EventGenerators = EventGenerators.LocalOnly, - EventLevel = Level.Error, - Keywords = (ushort)Keywords.UserMessage, - EventTask = (ushort)Tasks.Parser, - Message = - "Package nuget://{id}/{version} could not be processed because we could not write configuration file to '{configFile}': {message}")] - public abstract void NugetFailedToWriteConfigurationFileForPackage( - LoggingContext context, - string id, - string version, - string configFile, - string message); + Message = "Nuget inspection info: {message}")] + public abstract void NuGetInspectionInitializationInfo(LoggingContext context, string message); [GeneratedEvent( (ushort)LogEventId.NugetFailedToWriteSpecFileForPackage, @@ -169,21 +81,6 @@ namespace BuildXL.FrontEnd.Nuget.Tracing "Package nuget://{id}/{version} could not be processed because the nuspec file cannot be found at '{expectedPath}'.")] public abstract void NugetFailedNuSpecFileNotFound(LoggingContext context, string id, string version, string expectedPath); - [GeneratedEvent( - (ushort)LogEventId.NugetFailedWithInvalidNuSpecXml, - EventGenerators = EventGenerators.LocalOnly, - EventLevel = Level.Error, - Keywords = (ushort)(Keywords.UserMessage | Keywords.UserError), - EventTask = (ushort)Tasks.Parser, - Message = - "Package nuget://{id}/{version} could not be processed because the nuspec file at: '{nuspecFile}' has unexpected xml contents: {illegalXmlElement}")] - public abstract void NugetFailedWithInvalidNuSpecXml( - LoggingContext context, - string id, - string version, - string nuspecFile, - string illegalXmlElement); - [GeneratedEvent( (ushort)LogEventId.NugetPackageVersionIsInvalid, EventGenerators = EventGenerators.LocalOnly, @@ -193,16 +90,6 @@ namespace BuildXL.FrontEnd.Nuget.Tracing Message = "Invalid nuget version '{version}' found in config.dsc for package '{packageName}'. Expected version format is 'A.B.C.D'.")] public abstract void ConfigNugetPackageVersionIsInvalid(LoggingContext context, string version, string packageName); - [GeneratedEvent( - (ushort)LogEventId.NugetLaunchFailed, - EventGenerators = EventGenerators.LocalOnly, - EventLevel = Level.Verbose, - Keywords = (ushort)Keywords.UserMessage, - EventTask = (ushort)Tasks.Parser, - Message = - "Package nuget://{id}/{version} could not be downloaded because nuget.exe could not be launched: {message}")] - public abstract void NugetLaunchFailed(LoggingContext context, string id, string version, string message); - [GeneratedEvent( (ushort)LogEventId.NugetStatistics, EventGenerators = EventGenerators.LocalOnly, @@ -218,7 +105,7 @@ namespace BuildXL.FrontEnd.Nuget.Tracing EventGenerators = EventGenerators.LocalOnly, EventLevel = Level.Informational, EventTask = (ushort)Tasks.Parser, - Message = "Restoring NuGet packages ({packagesDownloadedCount} of {totalPackagesCount} done).", + Message = "Inspecting NuGet packages ({packagesDownloadedCount} of {totalPackagesCount} done).", Keywords = (int)Keywords.UserMessage | (int)Keywords.Overwritable)] public abstract void NugetPackageDownloadedCount(LoggingContext context, long packagesDownloadedCount, long totalPackagesCount); @@ -227,7 +114,7 @@ namespace BuildXL.FrontEnd.Nuget.Tracing EventGenerators = EventGenerators.LocalOnly, EventLevel = Level.Informational, EventTask = (ushort)Tasks.Parser, - Message = "Restored {totalPackagesCount} NuGet packages in {totalMilliseconds}ms.", + Message = "Inspected {totalPackagesCount} NuGet packages in {totalMilliseconds}ms.", Keywords = (int)Keywords.UserMessage | (int)Keywords.Overwritable)] public abstract void NugetPackagesAreRestored(LoggingContext context, long totalPackagesCount, long totalMilliseconds); @@ -254,7 +141,7 @@ namespace BuildXL.FrontEnd.Nuget.Tracing EventGenerators = EventGenerators.LocalOnly, EventLevel = Level.Verbose, EventTask = (ushort)Tasks.Parser, - Message = "Package nuget://{id}/{version} could not be restored because of an unhandled error '{error}'.", + Message = "Package nuget://{id}/{version} could not be inspected because of an unhandled error '{error}'.", Keywords = (int)Keywords.UserMessage | (int)Keywords.Overwritable)] public abstract void NugetUnhandledError(LoggingContext context, string id, string version, string error); @@ -264,7 +151,7 @@ namespace BuildXL.FrontEnd.Nuget.Tracing EventLevel = Level.Informational, EventTask = (ushort)Tasks.Parser, Message = - "Restoring NuGet packages ({packagesDownloadedCount} of {totalPackagesCount} done). Remaining {packagesToDownloadDetail}", + "Inspecting NuGet packages ({packagesDownloadedCount} of {totalPackagesCount} done). Remaining {packagesToDownloadDetail}", Keywords = (int)Keywords.UserMessage | (int)Keywords.OverwritableOnly)] public abstract void NugetPackageDownloadedCountWithDetails(LoggingContext context, long packagesDownloadedCount, long totalPackagesCount, string packagesToDownloadDetail); diff --git a/Public/Src/FrontEnd/Nuget/Tracing/LogEventId.cs b/Public/Src/FrontEnd/Nuget/Tracing/LogEventId.cs index 3e282e76f..84b8da6a3 100644 --- a/Public/Src/FrontEnd/Nuget/Tracing/LogEventId.cs +++ b/Public/Src/FrontEnd/Nuget/Tracing/LogEventId.cs @@ -14,40 +14,41 @@ namespace BuildXL.FrontEnd.Nuget.Tracing None = 0, // reserved 11300 .. 11400 for nuget - LaunchingNugetExe = 11300, - CredentialProviderRequiresToolUrl, - NugetDownloadInvalidHash, - NugetFailedToCleanTargetFolder, - NugetFailedWithNonZeroExitCode, - NugetFailedWithNonZeroExitCodeDetailed, - NugetFailedToListPackageContents, - NugetFailedToWriteConfigurationFile, - NugetFailedToWriteConfigurationFileForPackage, - NugetFailedToWriteSpecFileForPackage, - NugetFailedToReadNuSpecFile, - NugetFailedWithInvalidNuSpecXml, - NugetPackageVersionIsInvalid, - NugetLaunchFailed, - NugetStatistics, - NugetPackagesRestoredCount, - NugetPackagesAreRestored, - NugetDependencyVersionWasNotSpecifiedButConfigOneWasChosen, - NugetDependencyVersionWasPickedWithinRange, - NugetDependencyVersionDoesNotMatch, - NugetUnknownFramework, - NugetPackageDownloadDetails, - NugetFailedNuSpecFileNotFound, - NugetFailedDueToSomeWellKnownIssue, - NugetRegenerateNugetSpecs, - NugetRegeneratingNugetSpecs, - NugetUnhandledError, - ForcePopulateTheCacheOptionWasSpecified, - NugetConcurrencyLevel, - UsePackagesFromDisOptionWasSpecified, - NugetFailedDownloadPackagesAndGenerateSpecs, - NugetFailedDownloadPackage, - NugetFailedGenerationResultFromDownloadedPackage, - NugetFailedToWriteGeneratedSpecStateFile, - NugetCannotReuseSpecOnDisk, + // Reserved LaunchingNugetExe = 11300, + // Reserved CredentialProviderRequiresToolUrl = 11301, + // Reserved NugetDownloadInvalidHash = 11302, + NugetFailedToCleanTargetFolder = 11303, + // Reserved NugetFailedWithNonZeroExitCode = 11304, + // Reserved NugetFailedWithNonZeroExitCodeDetailed = 11305, + // Reserved NugetFailedToListPackageContents = 11306, + // Reserved NugetFailedToWriteConfigurationFile = 11307, + // Reserved NugetFailedToWriteConfigurationFileForPackage = 11308, + NugetFailedToWriteSpecFileForPackage = 11309, + NugetFailedToReadNuSpecFile = 11310, + // Reserved NugetFailedWithInvalidNuSpecXml = 11311, + NugetPackageVersionIsInvalid = 11312, + // Reserved NugetLaunchFailed = 11313, + NugetStatistics = 11314, + NugetPackagesRestoredCount = 11315, + NugetPackagesAreRestored = 11316, + NugetDependencyVersionWasNotSpecifiedButConfigOneWasChosen = 11317, + NugetDependencyVersionWasPickedWithinRange = 11318, + NugetDependencyVersionDoesNotMatch = 11319, + NugetUnknownFramework = 11320, + NugetPackageDownloadDetails = 11321, + NugetFailedNuSpecFileNotFound = 11322, + // Reserved NugetFailedDueToSomeWellKnownIssue = 11323, + NugetRegenerateNugetSpecs = 11324, + NugetRegeneratingNugetSpecs = 11325, + NugetUnhandledError = 11326, + ForcePopulateTheCacheOptionWasSpecified = 11327, + NugetConcurrencyLevel = 11328, + UsePackagesFromDisOptionWasSpecified = 11329, + NugetFailedDownloadPackagesAndGenerateSpecs = 11330, + NugetFailedDownloadPackage = 11331, + NugetFailedGenerationResultFromDownloadedPackage = 11332, + NugetFailedToWriteGeneratedSpecStateFile = 11333, + NugetCannotReuseSpecOnDisk = 11334, + NugetInspectionInitialization = 11335, } } diff --git a/Public/Src/FrontEnd/Nuget/WorkspaceNugetModuleResolver.cs b/Public/Src/FrontEnd/Nuget/WorkspaceNugetModuleResolver.cs index 7a325dcaf..56eeb8bcf 100644 --- a/Public/Src/FrontEnd/Nuget/WorkspaceNugetModuleResolver.cs +++ b/Public/Src/FrontEnd/Nuget/WorkspaceNugetModuleResolver.cs @@ -62,6 +62,8 @@ namespace BuildXL.FrontEnd.Nuget private const string SpecGenerationVersionFileSuffix = ".version"; + private const string NugetCredentialProviderEnv = "NUGET_CREDENTIALPROVIDERS_PATH"; + private NugetFrameworkMonikers m_nugetFrameworkMonikers; // These are set during Initialize @@ -82,8 +84,6 @@ namespace BuildXL.FrontEnd.Nuget private NugetResolverOutputLayout m_resolverOutputLayout; private IConfiguration m_configuration; - private readonly Lazy m_nugetToolFolder; - /// public string Kind => KnownResolverKind.NugetResolverKind; @@ -101,10 +101,6 @@ namespace BuildXL.FrontEnd.Nuget m_embeddedSpecsResolver = new WorkspaceSourceModuleResolver(stringTable, statistics, logger: null); m_useMonoBasedNuGet = OperatingSystemHelper.IsUnixOS; - - m_nugetToolFolder = new Lazy( - () => m_host.GetFolderForFrontEnd(NugetResolverName).Combine(PathTable, "nuget"), - LazyThreadSafetyMode.ExecutionAndPublication); } /// @@ -393,21 +389,58 @@ namespace BuildXL.FrontEnd.Nuget private Task> DownloadPackagesAndGenerateSpecsIfNeededInternal() { - return m_nugetGenerationResult.GetOrCreate(this, @this => @this.DownloadPackagesAndGenerateSpecsAsync()); + return m_nugetGenerationResult.GetOrCreate(this, @this => Task.FromResult(@this.DownloadPackagesAndGenerateSpecs())); } - private AbsolutePath GetNugetToolFolder() + private Possible TryResolveCredentialProvider() { - return m_nugetToolFolder.Value; + if (!m_host.Engine.TryGetBuildParameter(NugetCredentialProviderEnv, nameof(NugetFrontEnd), out string credentialProvidersPaths)) + { + return new NugetFailure(NugetFailure.FailureType.FetchCredentialProvider, $"Environment variable {NugetCredentialProviderEnv} is not set"); + } + + // Here we do something slightly simpler than what NuGet does and just look for the first credential + // provider we can find + AbsolutePath credentialProviderPath = AbsolutePath.Invalid; + foreach (string path in credentialProvidersPaths.Split(new[] { Path.PathSeparator }, StringSplitOptions.RemoveEmptyEntries)) + { + if (!AbsolutePath.TryCreate(m_context.PathTable, path, out var absolutePath)) + { + break; + } + + // Use the engine to enumerate, since the result of the enumeration should be sensitive + // to the graph building process + credentialProviderPath = m_host.Engine.EnumerateFiles(absolutePath, "CredentialProvider*.exe").FirstOrDefault(); + if (credentialProviderPath.IsValid) + { + break; + } + } + + if (!credentialProviderPath.IsValid) + { + return new NugetFailure(NugetFailure.FailureType.FetchCredentialProvider, $"Unable to authenticate using a credential provider: Credential provider was not found under '{credentialProvidersPaths}'."); + } + + // We want to rebuild the build graph if the credential provider changed. Running the whole auth process under detours sounds like too much, + // let's just read the credential provider main .exe so presence/hash gets recorded instead. + m_host.Engine.TryGetFrontEndFile(credentialProviderPath, nameof(NugetFrontEnd), out _); + + return m_host.Engine.Translate(credentialProviderPath); } - private AbsolutePath GetNugetConfigPath() + private Possible DownloadPackagesAndGenerateSpecs() { - return GetNugetToolFolder().Combine(PathTable, "NuGet.config"); - } + var maybeCredentialProviderPath = TryResolveCredentialProvider(); + + var nugetInspector = new NugetPackageInspector( + m_resolverSettings.Repositories.Select(kvp => (kvp.Key, new Uri(kvp.Value))), + PathTable.StringTable, + () => maybeCredentialProviderPath.Then(path => path.ToString(PathTable)), + m_context.CancellationToken, + m_context.LoggingContext); - private async Task> DownloadPackagesAndGenerateSpecsAsync() - { // Log if the full package restore is requested. if (m_configuration.FrontEnd.ForcePopulatePackageCache()) { @@ -429,26 +462,6 @@ namespace BuildXL.FrontEnd.Nuget using (var nugetEndToEndStopWatch = m_statistics.EndToEnd.Start()) { - var possiblePaths = await TryDownloadNugetAsync(m_resolverSettings.Configuration, GetNugetToolFolder()); - if (!possiblePaths.Succeeded) - { - Logger.Log.NugetFailedDownloadPackagesAndGenerateSpecs(m_context.LoggingContext, possiblePaths.Failure.DescribeIncludingInnerFailures()); - return possiblePaths.Failure; - } - - var possibleNugetConfig = CreateNuGetConfig(m_repositories); - - var possibleNuGetConfig = TryWriteXmlConfigFile( - package: null, - targetFile: GetNugetConfigPath(), - xmlDoc: possibleNugetConfig.Result); - - if (!possibleNuGetConfig.Succeeded) - { - Logger.Log.NugetFailedDownloadPackagesAndGenerateSpecs(m_context.LoggingContext, possibleNuGetConfig.Failure.DescribeIncludingInnerFailures()); - return possibleNuGetConfig.Failure; - } - // Will contain all packages successfully downloaded and analyzed var restoredPackagesById = new Dictionary(); @@ -468,16 +481,32 @@ namespace BuildXL.FrontEnd.Nuget { var aggregateResult = new Possible[nugetProgress.Length]; - Parallel.For(fromInclusive: 0, + if (!m_host.Engine.TryGetBuildParameter(NugetCredentialProviderEnv, nameof(NugetFrontEnd), out string allCredentialProviderPaths)) + { + allCredentialProviderPaths = string.Empty; + } + + var loopState = Parallel.For(fromInclusive: 0, toExclusive: aggregateResult.Length, new ParallelOptions() { MaxDegreeOfParallelism = concurrencyLevel, CancellationToken = m_context.CancellationToken, }, - (index) => + (index, state) => { - aggregateResult[index] = TryRestorePackageAsync(nugetProgress[index], possiblePaths.Result).GetAwaiter().GetResult(); + aggregateResult[index] = TryInspectPackageAsync( + nugetProgress[index], + maybeCredentialProviderPath.Succeeded ? maybeCredentialProviderPath.Result : AbsolutePath.Invalid, + allCredentialProviderPaths, + nugetInspector).GetAwaiter().GetResult(); + + // Let's not schedule more work in the parallel for if one of the inspections failed + if (!aggregateResult[index].Succeeded) + { + state.Break(); + } + return; }); @@ -505,6 +534,16 @@ namespace BuildXL.FrontEnd.Nuget } else { + // If the package result is null, that means there was at least one failure and the parallel for ended prematurely, but the failure + // happened after the current index + if (packageResult.Result == null) + { + // There should be at least one failure and the loop state should not be completed + Contract.Assert(!loopState.IsCompleted); + // Just skip this iteration. The failure is ahead of the current index and we'll eventually reach it + continue; + } + packageResult.Result.NugetName = nugetPackage.Package.Id; restoredPackagesById[packageResult.Result.ActualId] = packageResult.Result; } @@ -549,12 +588,12 @@ namespace BuildXL.FrontEnd.Nuget { if (m_configuration.DoesSourceDiskDriveHaveSeekPenalty(PathTable)) { - nugetConcurrency = Environment.ProcessorCount / 2; + nugetConcurrency = Environment.ProcessorCount; message = I($"Lowering restore package concurrency to {nugetConcurrency} because a source drive is on HDD."); } else { - nugetConcurrency = Math.Min(16, Environment.ProcessorCount * 2); + nugetConcurrency = Math.Min(128, Environment.ProcessorCount * 4); message = I($"Increasing restore package concurrency to {nugetConcurrency} because a source drive is on SSD."); } } @@ -564,9 +603,11 @@ namespace BuildXL.FrontEnd.Nuget return nugetConcurrency; } - private async Task> TryRestorePackageAsync( + private async Task> TryInspectPackageAsync( NugetProgress progress, - IReadOnlyList credentialProviderPaths) + AbsolutePath selectedCredentialProviderPath, + string allCredentialProviderPaths, + NugetPackageInspector nugetInspector) { progress.StartRunning(); @@ -579,11 +620,9 @@ namespace BuildXL.FrontEnd.Nuget var layout = NugetPackageOutputLayout.Create( PathTable, package, - nugetTool: credentialProviderPaths[0], - nugetConfig: GetNugetConfigPath(), resolverLayout: m_resolverOutputLayout); - var possiblePkg = await TryRestorePackageWithCache(package, progress, layout, credentialProviderPaths); + var possiblePkg = await TryInpectPackageWithCache(package, progress, layout, allCredentialProviderPaths, nugetInspector); if (!possiblePkg.Succeeded) { @@ -596,6 +635,7 @@ namespace BuildXL.FrontEnd.Nuget var analyzedPackage = AnalyzeNugetPackage( possiblePkg.Result, + selectedCredentialProviderPath, m_resolverSettings.DoNotEnforceDependencyVersions); if (!analyzedPackage.Succeeded) { @@ -780,60 +820,6 @@ namespace BuildXL.FrontEnd.Nuget return true; } - private Possible CreateNuGetConfig(IReadOnlyDictionary repositories) - { - XElement credentials = null; - if (m_useMonoBasedNuGet) - { - var localNuGetConfigPath = Path.Combine( - Environment.GetFolderPath(Environment.SpecialFolder.UserProfile), - ".config", - "NuGet", - "NuGet.Config"); - - try - { - // Sadly nuget goes all over the disk to chain configs, but when it comes to the credentials it decides not to properly merge them. - // So for now we have to hack and read the credentials from the users profile and stick them in the local config.... - if (FileUtilities.Exists(localNuGetConfigPath)) - { - ExceptionUtilities.HandleRecoverableIOException( - () => - { - var doc = XDocument.Load(localNuGetConfigPath); - credentials = doc.Element("configuration")?.Element("packageSourceCredentials"); - }, - e => throw new BuildXLException($"Failed to load nuget config {localNuGetConfigPath}", e)); - } - } - catch (BuildXLException e) - { - Logger.Log.NugetFailedToWriteConfigurationFile( - m_context.LoggingContext, - localNuGetConfigPath, - e.LogEventMessage); - return new NugetFailure(NugetFailure.FailureType.WriteConfigFile, e.InnerException); - } - } - - return new XDocument( - new XElement( - "configuration", - new XElement( - "packageRestore", - new XElement("clear"), - new XElement("add", new XAttribute("key", "enabled"), new XAttribute("value", "True"))), - new XElement( - "disabledPackageSources", - new XElement("clear")), - credentials, - new XElement( - "packageSources", - new XElement("clear"), - repositories.Select( - kv => new XElement("add", new XAttribute("key", kv.Key), new XAttribute("value", kv.Value)))))); - } - private Possible TryWriteSourceFile(INugetPackage package, AbsolutePath targetFile, ISourceFile sourceFile) { Contract.Requires(package != null); @@ -873,45 +859,6 @@ namespace BuildXL.FrontEnd.Nuget return targetFile; } - private Possible TryWriteXmlConfigFile(INugetPackage package, AbsolutePath targetFile, XDocument xmlDoc) - { - var targetFilePath = targetFile.ToString(PathTable); - - try - { - FileUtilities.CreateDirectory(Path.GetDirectoryName(targetFilePath)); - ExceptionUtilities.HandleRecoverableIOException( - () => - xmlDoc.Save(targetFilePath, SaveOptions.DisableFormatting), - e => - { - throw new BuildXLException("Cannot save document", e); - }); - } - catch (BuildXLException e) - { - if (package == null) - { - Logger.Log.NugetFailedToWriteConfigurationFile(m_context.LoggingContext, targetFilePath, e.LogEventMessage); - } - else - { - Logger.Log.NugetFailedToWriteConfigurationFileForPackage( - m_context.LoggingContext, - package.Id, - package.Version, - targetFilePath, - e.LogEventMessage); - } - - return new NugetFailure(package, NugetFailure.FailureType.WriteConfigFile, e.InnerException); - } - - m_host.Engine.RecordFrontEndFile(targetFile, NugetResolverName); - - return targetFile; - } - private AbsolutePath GetPackageSpecDir(NugetAnalyzedPackage analyzedPackage) { return m_resolverOutputLayout.GeneratedSpecsFolder @@ -1008,8 +955,9 @@ namespace BuildXL.FrontEnd.Nuget // No-op if the directory exists FileUtilities.CreateDirectory(packageSpecDirStr); - - var nugetSpecGenerator = new NugetSpecGenerator(PathTable, analyzedPackage); + + var nugetSpecGenerator = new NugetSpecGenerator(PathTable, analyzedPackage, m_resolverSettings.Repositories, + m_configuration.Layout.SourceDirectory, m_resolverSettings.Configuration.DownloadTimeoutMin); var possibleProjectFile = TryWriteSourceFile( analyzedPackage.PackageOnDisk.Package, @@ -1044,6 +992,7 @@ namespace BuildXL.FrontEnd.Nuget internal Possible AnalyzeNugetPackage( PackageOnDisk packageOnDisk, + AbsolutePath credentialProviderPath, bool doNotEnforceDependencyVersions) { Contract.Requires(packageOnDisk != null); @@ -1057,7 +1006,7 @@ namespace BuildXL.FrontEnd.Nuget } var result = NugetAnalyzedPackage.TryAnalyzeNugetPackage(m_context, m_nugetFrameworkMonikers, maybeNuspecXdoc.Result, - packageOnDisk, m_packageRegistry.AllPackagesById, doNotEnforceDependencyVersions); + packageOnDisk, m_packageRegistry.AllPackagesById, doNotEnforceDependencyVersions, credentialProviderPath); if (result == null) { @@ -1119,8 +1068,7 @@ namespace BuildXL.FrontEnd.Nuget } } - - private string CreateRestoreFingerPrint(INugetPackage package, IEnumerable credentialProviderPaths) + private string CreateRestoreFingerPrint(INugetPackage package, string credentialProviderPaths) { var fingerprintParams = new List { @@ -1130,7 +1078,7 @@ namespace BuildXL.FrontEnd.Nuget }; if (credentialProviderPaths != null) { - fingerprintParams.Add("cred=" + UppercaseSortAndJoinStrings(credentialProviderPaths.Select(p => p.ToString(PathTable)))); + fingerprintParams.Add("cred=" + credentialProviderPaths); } return "nuget://" + string.Join("&", fingerprintParams); @@ -1149,11 +1097,12 @@ namespace BuildXL.FrontEnd.Nuget return restoreFingerPrint + "&" + string.Join("&", fingerprintParams); } - private async Task> TryRestorePackageWithCache( + private async Task> TryInpectPackageWithCache( INugetPackage package, NugetProgress progress, NugetPackageOutputLayout layout, - IEnumerable credentialProviderPaths) + string credentialProviderPaths, + NugetPackageInspector nugetInspector) { var packageRestoreFingerprint = CreateRestoreFingerPrint(package, credentialProviderPaths); var identity = PackageIdentity.Nuget(package.Id, package.Version, package.Alias); @@ -1165,10 +1114,23 @@ namespace BuildXL.FrontEnd.Nuget packageRestoreFingerprint, identity, layout.PackageFolder, - () => + layout.PathToNuspec, + async () => { progress.StartDownloadFromNuget(); - return TryDownloadPackage(package, layout, credentialProviderPaths); + + // We want to delay initialization until the first inspection that is actually needed + // Initializing the inspector involves resolving the index service for each specified repository + if (!await nugetInspector.IsInitializedAsync()) + { + var initResult = await nugetInspector.TryInitAsync(); + if (!initResult.Succeeded) + { + return initResult.Failure; + } + } + + return await TryInspectPackage(package, layout, nugetInspector); }); return maybePackage.Then(downloadResult => @@ -1183,34 +1145,71 @@ namespace BuildXL.FrontEnd.Nuget return string.Join(",", values.Select(s => s.ToUpperInvariant()).OrderBy(s => s)); } - private async Task>> TryDownloadPackage( - INugetPackage package, NugetPackageOutputLayout layout, IEnumerable credentialProviderPaths) + private async Task>> TryInspectPackage( + INugetPackage package, + NugetPackageOutputLayout layout, + NugetPackageInspector nugetInspector) { - var xmlConfigResult = TryWriteXmlConfigFile(package, layout.PackagesConfigFile, GetPackagesXml(package)); - if (!xmlConfigResult.Succeeded) - { - return xmlConfigResult.Failure; - } - var cleanUpResult = TryCleanupPackagesFolder(package, layout); if (!cleanUpResult.Succeeded) { return cleanUpResult.Failure; } - var nugetExeResult = await TryLaunchNugetExeAsync(package, layout, credentialProviderPaths); - if (!nugetExeResult.Succeeded) + // Inspect the package (get nuspec and layout) + var maybeInspectedPackage = await nugetInspector.TryInspectAsync(package); + if (!maybeInspectedPackage.Succeeded) { - return nugetExeResult.Failure; + return maybeInspectedPackage.Failure; } - var contentResult = TryEnumerateDirectory(package, layout.PackageDirectory); - if (!contentResult.Succeeded) - { - return contentResult.Failure; - } + var inspectedPackage = maybeInspectedPackage.Result; - return contentResult.Result; + // Serialize the nuspec to disk. In this way we can also use the bxl cache to avoid + // downloading this content again. The hash file will contain the layout, which is serialized + // later + try + { +#if NET_FRAMEWORK + return ExceptionUtilities.HandleRecoverableIOException( + () => +#else + return await ExceptionUtilities.HandleRecoverableIOException( + async () => +#endif + { + FileUtilities.CreateDirectoryWithRetry(layout.PackageFolder.ToString(PathTable)); + + // XML files need to be serialized with the right enconding, so let's use XDocument + // for that + var xdocument = XDocument.Parse(inspectedPackage.Nuspec); + + using (var nuspec = new FileStream(layout.PathToNuspec.ToString(PathTable), FileMode.Create)) + { +#if NET_FRAMEWORK + xdocument.Save(nuspec); +#else + await xdocument.SaveAsync(nuspec, SaveOptions.None, m_context.CancellationToken); +#endif + } + + return new Possible>(inspectedPackage.Content); + }, + e => + { + throw new BuildXLException("Cannot write package's nuspec file to disk", e); + }); + } + catch (BuildXLException e) + { + Logger.Log.NugetFailedToWriteSpecFileForPackage( + m_context.LoggingContext, + package.Id, + package.Version, + layout.PathToNuspec.ToString(PathTable), + e.LogEventMessage); + return new NugetFailure(package, NugetFailure.FailureType.WriteSpecFile, e.InnerException); + } } private Possible TryCleanupPackagesFolder(INugetPackage package, NugetPackageOutputLayout layout) @@ -1255,466 +1254,6 @@ namespace BuildXL.FrontEnd.Nuget } } - private async Task> TryLaunchNugetExeAsync(INugetPackage package, NugetPackageOutputLayout layout, IEnumerable credentialProviderPaths) - { - var fileAccessManifest = GenerateFileAccessManifest(layout, credentialProviderPaths); - - var buildParameters = BuildParameters - .GetFactory() - .PopulateFromEnvironment(); - - var tool = layout.NugetTool.ToString(PathTable); - - var argumentsBuilder = new StringBuilder(); - if (m_useMonoBasedNuGet) - { - argumentsBuilder.AppendFormat("\"{0}\"", tool); - argumentsBuilder.Append(" "); - - if (!buildParameters.ToDictionary().TryGetValue("MONO_HOME", out var monoHome)) - { - return new NugetFailure(package, NugetFailure.FailureType.MissingMonoHome); - } - - tool = Path.Combine(monoHome, "mono"); - } - - // TODO:escape quotes properly - argumentsBuilder - .AppendFormat("restore \"{0}\"", layout.PackagesConfigFile.ToString(PathTable)) - .AppendFormat(" -OutputDirectory \"{0}\"", layout.PackageRootFolder.ToString(PathTable)) - .Append(" -Verbosity detailed") - .AppendFormat(" -ConfigFile \"{0}\"", layout.NugetConfig.ToString(PathTable)) - .Append(" -PackageSaveMode nuspec") - .Append(" -NoCache") - // Currently we have to hack nuget to MsBuild version 4 which should come form the current CLR. - .Append(" -MsBuildVersion 4"); - - if (!m_host.Configuration.Interactive) - { - // Prevent Nuget from showing any UI when not in interactive mode - argumentsBuilder.Append(" -NonInteractive"); - } - - var arguments = argumentsBuilder.ToString(); - - Logger.Log.LaunchingNugetExe(m_context.LoggingContext, package.Id, package.Version, tool + " " + arguments); - try - { - // For NugetFrontEnd always create a new ConHost process. - // The NugetFrontEnd is normally executed only once, so the overhead is low. - // Also the NugetFrontEnd is a really long running process, so creating the ConHost is relatively - // very cheap. It provides guarantee if the process pollutes the ConHost env, - // it will not affect the server ConHost. - var info = - new SandboxedProcessInfo( - m_context.PathTable, - new NugetFileStorage(layout.PackageTmpDirectory), - tool, - fileAccessManifest, - disableConHostSharing: true, - ContainerConfiguration.DisabledIsolation, - loggingContext: m_context.LoggingContext, - sandboxConnection: m_useMonoBasedNuGet ? new SandboxConnectionFake() : null) - { - Arguments = arguments, - WorkingDirectory = layout.TempDirectory.ToString(PathTable), - PipSemiStableHash = 0, - PipDescription = "NuGet FrontEnd", - EnvironmentVariables = GetNugetEnvironmentVariables(), - Timeout = TimeSpan.FromMinutes(20), // Limit the time nuget has to download each nuget package - }; - - return await RetryOnFailure( - runNuget: async () => - { - var process = await SandboxedProcessFactory.StartAsync(info, forceSandboxing: !m_useMonoBasedNuGet); - var result = await process.GetResultAsync(); - return (result, result.ExitCode == 0); - }, - onError: async result => - { - // Log the result before trying again - var (stdOut, stdErr) = await GetStandardOutAndError(result); - - Logger.Log.NugetFailedWithNonZeroExitCodeDetailed( - m_context.LoggingContext, - package.Id, - package.Version, - result.ExitCode, - stdOut, - stdErr); - - return (stdOut, stdErr); - }, - onFinalFailure: (exitCode, stdOut, stdErr) => - { - // Give up and fail - return NugetFailure.CreateNugetInvocationFailure(package, exitCode, stdOut, stdErr); - }); - } - catch (BuildXLException e) - { - Logger.Log.NugetLaunchFailed(m_context.LoggingContext, package.Id, package.Version, e.LogEventMessage); - return new NugetFailure(package, NugetFailure.FailureType.NugetFailedWithIoException); - } - catch (Exception e) - { - return new NugetFailure(package, NugetFailure.FailureType.NugetFailedWithIoException, e); - } - - async Task<(string stdOut, string stdErr)> GetStandardOutAndError(SandboxedProcessResult result) - { - try - { - await result.StandardOutput.SaveAsync(); - var stdOut = await result.StandardOutput.ReadValueAsync(); - - await result.StandardError.SaveAsync(); - var stdErr = await result.StandardError.ReadValueAsync(); - - return (stdOut, stdErr); - } - catch (BuildXLException e) - { - return (e.LogEventMessage, string.Empty); - } - } - - BuildParameters.IBuildParameters GetNugetEnvironmentVariables() - { - // the environment variable names below should use the casing appropriate for the target OS - // (on Windows it won't matter, but on Unix-like systems, including Cygwin environment on Windows, - // it matters, and has to be all upper-cased). See also doc comment for IBuildParameters.Select - return buildParameters - .Select( - new[] - { - "ComSpec", - "PATH", - "PATHEXT", - "NUMBER_OF_PROCESSORS", - "OS", - "PROCESSOR_ARCHITECTURE", - "PROCESSOR_IDENTIFIER", - "PROCESSOR_LEVEL", - "PROCESSOR_REVISION", - "SystemDrive", - "SystemRoot", - "SYSTEMTYPE", - "NUGET_CREDENTIALPROVIDERS_PATH", - "__CLOUDBUILD_AUTH_HELPER_CONFIG__", - "__Q_DPAPI_Secrets_Dir", - - // Nuget Credential Provider env variables - "1ESSHAREDASSETS_BUILDXL_FEED_PAT", - "CLOUDBUILD_BUILDXL_SELFHOST_FEED_PAT", - - // Auth material needed for low-privilege build. - "QAUTHMATERIALROOT", - - // Used by the artifacts credential provider. See here for more information on how this variable is configured - https://github.com/microsoft/artifacts-credprovider#azure-devops-server - "VSS_NUGET_EXTERNAL_FEED_ENDPOINTS" - }) - .Override( - new Dictionary() - { - {"TMP", layout.TempDirectoryAsString}, - {"TEMP", layout.TempDirectoryAsString}, - {"NUGET_PACKAGES", layout.TempDirectoryAsString}, - {"NUGET_ROOT", layout.TempDirectoryAsString}, - }); - } - } - - private class SandboxConnectionFake : ISandboxConnection - { - public SandboxKind Kind => SandboxKind.MacOsKext; - - public int NumberOfKextConnections => 1; - - public ulong MinReportQueueEnqueueTime { get; set; } - - public TimeSpan CurrentDrought - { - get - { - var nowNs = Sandbox.GetMachAbsoluteTime(); - var minReportTimeNs = MinReportQueueEnqueueTime; - return TimeSpan.FromTicks(nowNs > minReportTimeNs ? (long)((nowNs - minReportTimeNs) / 100) : 0); - } - } - - public void Dispose() { } - - public bool IsInTestMode => true; - - public bool NotifyUsage(uint cpuUsage, uint availableRamMB) { return true; } - - public bool NotifyPipStarted(LoggingContext loggingContext, FileAccessManifest fam, SandboxedProcessUnix process) { return true; } - - public IEnumerable<(string, string)> AdditionalEnvVarsToSet(long pipId) - { - return Enumerable.Empty<(string, string)>(); - } - - public void NotifyPipProcessTerminated(long pipId, int processId) { } - - public void NotifyRootProcessExited(long pipId, SandboxedProcessUnix process) { } - - public bool NotifyPipFinished(long pipId, SandboxedProcessUnix process) { return true; } - - public void ReleaseResources() { } - } - - private static async Task> RetryOnFailure( - Func> runNuget, - Func> onError, - Func> onFinalFailure, - int retryCount = MaxRetryCount, - int retryDelayMs = RetryDelayMs) - { - Contract.Assert(retryCount >= 1, "Maximum retry count must be greater than or equal to one. Found " + retryCount); - - var pass = false; - var iteration = 1; - - while (!pass) - { - var tuple = await runNuget(); - var result = tuple.result; - pass = tuple.isPassed; - - if (!pass) - { - var (stdOut, stdErr) = await onError(result); - - if (iteration >= retryCount) - { - return onFinalFailure(result.ExitCode, stdOut, stdErr); - } - - // Try again! - iteration++; - - await Task.Delay(retryDelayMs); - } - } - - return Unit.Void; - } - - private FileAccessManifest GenerateFileAccessManifest(NugetPackageOutputLayout layout, IEnumerable credentialProviderPaths) - { - var fileAccessManifest = new FileAccessManifest(PathTable) - { - // TODO: If this is set to true, then NuGet will fail if TMG Forefront client is running. - // Filtering out in SandboxedProcessReport won't work because Detours already blocks the access to FwcWsp.dll. - // Almost all machines in Office run TMG Forefront client. - // So far for WDG, FailUnexpectedFileAccesses is false due to allowlists. - // As a consequence, the file access manifest below gets nullified. - FailUnexpectedFileAccesses = false, - ReportFileAccesses = true, - MonitorNtCreateFile = true, - MonitorZwCreateOpenQueryFile = true, - }; - - fileAccessManifest.AddScope(layout.TempDirectory, FileAccessPolicy.MaskAll, FileAccessPolicy.AllowAllButSymlinkCreation); - fileAccessManifest.AddScope(layout.PackageRootFolder, FileAccessPolicy.MaskAll, FileAccessPolicy.AllowAllButSymlinkCreation); - if (!OperatingSystemHelper.IsUnixOS) - { - fileAccessManifest.AddScope( - AbsolutePath.Create(PathTable, SpecialFolderUtilities.GetFolderPath(Environment.SpecialFolder.Windows)), - FileAccessPolicy.MaskAll, - FileAccessPolicy.AllowAllButSymlinkCreation); - } - - fileAccessManifest.AddPath(layout.NugetTool, values: FileAccessPolicy.AllowRead, mask: FileAccessPolicy.MaskNothing); - fileAccessManifest.AddPath(layout.NugetToolExeConfig, values: FileAccessPolicy.AllowReadIfNonexistent, mask: FileAccessPolicy.MaskNothing); - fileAccessManifest.AddPath(layout.NugetConfig, values: FileAccessPolicy.AllowRead, mask: FileAccessPolicy.MaskNothing); - fileAccessManifest.AddPath(layout.PackagesConfigFile, values: FileAccessPolicy.AllowRead, mask: FileAccessPolicy.MaskNothing); - - // Nuget is picky - fileAccessManifest.AddScope(layout.ResolverFolder, FileAccessPolicy.MaskAll, FileAccessPolicy.AllowAllButSymlinkCreation); - - // Nuget fails if it can't access files in the users (https://github.com/NuGet/Home/issues/2676) profile. - // We'll have to explicitly set all config in our nuget.config file and override anything the user can set and allow the read here. - var roamingAppDataNuget = AbsolutePath.Create(PathTable, SpecialFolderUtilities.GetFolderPath(Environment.SpecialFolder.ApplicationData)).Combine(PathTable, "NuGet"); - fileAccessManifest.AddScope(roamingAppDataNuget, FileAccessPolicy.MaskAll, FileAccessPolicy.AllowAllButSymlinkCreation); - - var localAppDataNuget = AbsolutePath.Create(PathTable, SpecialFolderUtilities.GetFolderPath(Environment.SpecialFolder.LocalApplicationData)).Combine(PathTable, "NuGet"); - fileAccessManifest.AddScope(localAppDataNuget, FileAccessPolicy.MaskAll, FileAccessPolicy.AllowAllButSymlinkCreation); - - // Nuget also probes in ProgramData on the machine. - var commonAppDataNuget = AbsolutePath.Create(PathTable, SpecialFolderUtilities.GetFolderPath(Environment.SpecialFolder.CommonApplicationData)).Combine(PathTable, "NuGet"); - fileAccessManifest.AddScope(commonAppDataNuget, FileAccessPolicy.MaskAll, FileAccessPolicy.AllowAllButSymlinkCreation); - - foreach (var providerPath in credentialProviderPaths) - { - fileAccessManifest.AddPath(providerPath, values: FileAccessPolicy.AllowRead, mask: FileAccessPolicy.MaskNothing); - fileAccessManifest.AddPath( - providerPath.ChangeExtension(PathTable, PathAtom.Create(PathTable.StringTable, ".exe.config")), - values: FileAccessPolicy.AllowRead, - mask: FileAccessPolicy.MaskNothing); - } - - return fileAccessManifest; - } - - private static XDocument GetPackagesXml(INugetPackage package) - { - - var version = package.Version; - var plusIndex = version.IndexOf('+'); - if (plusIndex > 0) - { - version = version.Substring(0, plusIndex); - } - return new XDocument( - new XElement( - "packages", - new XElement( - "package", - new XAttribute("id", package.Id), - new XAttribute("version", version)))); - } - - private Possible, NugetFailure> TryEnumerateDirectory(INugetPackage package, string packagePath) - { - var enumerateDirectoryResult = EnumerateDirectoryRecursively(packagePath, out var contents); - - if (!enumerateDirectoryResult.Succeeded) - { - var message = enumerateDirectoryResult.GetNativeErrorMessage(); - Logger.Log.NugetFailedToListPackageContents(m_context.LoggingContext, package.Id, package.Version, packagePath, message); - return new NugetFailure(package, NugetFailure.FailureType.ListPackageContents, enumerateDirectoryResult.CreateExceptionForError()); - } - - return contents; - } - - private EnumerateDirectoryResult EnumerateDirectoryRecursively(string packagePath, out List resultingContent) - { - resultingContent = new List(); - return EnumerateDirectoryRecursively(RelativePath.Empty, resultingContent); - - EnumerateDirectoryResult EnumerateDirectoryRecursively(RelativePath relativePath, List contents) - { - var result = FileUtilities.EnumerateDirectoryEntries( - Path.Combine(packagePath, relativePath.ToString(m_context.StringTable)), - (name, attr) => - { - var nestedRelativePath = relativePath.Combine(PathAtom.Create(m_context.StringTable, name)); - if ((attr & FileAttributes.Directory) != 0) - { - EnumerateDirectoryRecursively(nestedRelativePath, contents); - } - else - { - contents.Add(nestedRelativePath); - } - }); - - return result; - } - } - - private async Task> TryDownloadNugetAsync(INugetConfiguration configuration, AbsolutePath targetFolder) - { - configuration = configuration ?? new NugetConfiguration(); - - var downloads = new Task>[1 + configuration.CredentialProviders.Count]; - var paths = new AbsolutePath[downloads.Length]; - - var nugetTargetLocation = targetFolder.Combine(m_context.PathTable, "nuget.exe"); - - var nugetLocation = configuration.ToolUrl; - if (string.IsNullOrEmpty(nugetLocation)) - { - var version = configuration.Version ?? "latest"; - nugetLocation = string.Format(CultureInfo.InvariantCulture, "https://dist.nuget.org/win-x86-commandline/{0}/nuget.exe", version); - } - - TryGetExpectedContentHash(configuration, out var expectedHash); - - downloads[0] = m_host.DownloadFile(nugetLocation, nugetTargetLocation, expectedHash, NugetResolverName); - paths[0] = nugetTargetLocation; - - for (var i = 0; i < configuration.CredentialProviders.Count; i++) - { - var credentialProvider = configuration.CredentialProviders[i]; - var credentialProviderName = NugetResolverName + ".credentialProvider." + i.ToString(CultureInfo.InvariantCulture); - - TryGetExpectedContentHash(credentialProvider, out var expectedProviderHash); - - var toolUrl = credentialProvider.ToolUrl; - if (string.IsNullOrEmpty(toolUrl)) - { - // TODO: Have better provenance for configuration values. - Logger.Log.CredentialProviderRequiresToolUrl(m_context.LoggingContext, credentialProviderName); - return new NugetFailure(NugetFailure.FailureType.FetchCredentialProvider); - } - - var fileNameStart = toolUrl.LastIndexOfAny(new[] { '/', '\\' }); - var fileName = fileNameStart >= 0 ? toolUrl.Substring(fileNameStart + 1) : toolUrl; - var targetLocation = targetFolder.Combine(m_context.PathTable, fileName); - downloads[i + 1] = m_host.DownloadFile(toolUrl, targetLocation, expectedProviderHash, credentialProviderName); - paths[i + 1] = targetLocation; - } - - var results = await Task.WhenAll(downloads); - - foreach (var result in results) - { - if (!result.Succeeded) - { - return result.Failure; - } - } - - return paths; - } - - /// - private bool TryGetExpectedContentHash(IArtifactLocation artifactLocation, out ContentHash? expectedHash) - { - expectedHash = null; - if (!string.IsNullOrEmpty(artifactLocation.Hash)) - { - if (!ContentHash.TryParse(artifactLocation.Hash, out var contentHash)) - { - // TODO: better provenance for configuration settings. - Logger.Log.NugetDownloadInvalidHash( - m_context.LoggingContext, - "nuget.exe", - artifactLocation.Hash); - return false; - } - - expectedHash = contentHash; - } - - return true; - } - - /// - private sealed class NugetFileStorage : ISandboxedProcessFileStorage - { - private readonly string m_directory; - - /// - public NugetFileStorage(string directory) - { - m_directory = directory; - } - - /// - public string GetFileName(SandboxedProcessFile file) - { - return Path.Combine(m_directory, file.DefaultFileName()); - } - } - /// /// Helper class that holds all folders required for a nuget resolver /// @@ -1753,50 +1292,30 @@ namespace BuildXL.FrontEnd.Nuget { private readonly NugetResolverOutputLayout m_resolverLayout; - public NugetPackageOutputLayout(PathTable pathTable, INugetPackage package, AbsolutePath nugetTool, AbsolutePath nugetConfig, NugetResolverOutputLayout resolverLayout) + public NugetPackageOutputLayout(PathTable pathTable, INugetPackage package, NugetResolverOutputLayout resolverLayout) { m_resolverLayout = resolverLayout; - Package = package; - NugetTool = nugetTool; - NugetConfig = nugetConfig; var idAndVersion = package.Id + "." + package.Version; - NugetToolExeConfig = nugetTool.ChangeExtension(pathTable, PathAtom.Create(pathTable.StringTable, ".exe.config")); // All the folders should include version to avoid potential race conditions during nuget execution. PackageFolder = PackageRootFolder.Combine(pathTable, idAndVersion); PackageDirectory = PackageFolder.ToString(pathTable); PackageTmpDirectory = TempDirectory.Combine(pathTable, idAndVersion).ToString(pathTable); - PackagesConfigFile = ConfigRootFolder.Combine(pathTable, idAndVersion).Combine(pathTable, "packages.config"); + PathToNuspec = PackageFolder.Combine(pathTable, $"{package.Id}.nuspec"); } public static NugetPackageOutputLayout Create(PathTable pathTable, INugetPackage package, - AbsolutePath nugetTool, AbsolutePath nugetConfig, NugetResolverOutputLayout resolverLayout) + NugetResolverOutputLayout resolverLayout) { - return new NugetPackageOutputLayout(pathTable, package, nugetTool, nugetConfig, resolverLayout); + return new NugetPackageOutputLayout(pathTable, package, resolverLayout); } - public INugetPackage Package { get; } - - public AbsolutePath ResolverFolder => m_resolverLayout.ResolverFolder; - - public string ResolverDirectory => m_resolverLayout.ResolverDirectory; - - public AbsolutePath NugetTool { get; } - - public AbsolutePath NugetToolExeConfig { get; } - - public AbsolutePath NugetConfig { get; } - public AbsolutePath TempDirectory => m_resolverLayout.TempDirectory; - public string TempDirectoryAsString => m_resolverLayout.TempDirectoryAsString; - public AbsolutePath PackageRootFolder => m_resolverLayout.PackageRootFolder; - public AbsolutePath ConfigRootFolder => m_resolverLayout.ConfigRootFolder; - - public AbsolutePath PackagesConfigFile { get; } + public AbsolutePath PathToNuspec { get; } public AbsolutePath PackageFolder { get; } diff --git a/Public/Src/FrontEnd/Script/Ambients/Transformers/AmbientTransformer.Process.cs b/Public/Src/FrontEnd/Script/Ambients/Transformers/AmbientTransformer.Process.cs index ddb585f96..ed822ace9 100644 --- a/Public/Src/FrontEnd/Script/Ambients/Transformers/AmbientTransformer.Process.cs +++ b/Public/Src/FrontEnd/Script/Ambients/Transformers/AmbientTransformer.Process.cs @@ -181,6 +181,8 @@ namespace BuildXL.FrontEnd.Script.Ambients.Transformers private SymbolAtom m_semaphoreInfoLimit; private SymbolAtom m_semaphoreInfoName; private SymbolAtom m_semaphoreInfoIncrementBy; + // Explicitly not exposed in DScript since bypassing the salts is not officially supported, and only used for internally scheduled pips + private SymbolAtom m_unsafeBypassFingerprintSalt; private CallSignature ExecuteSignature => CreateSignature( required: RequiredParameters(AmbientTypes.ExecuteArgumentsType), @@ -332,6 +334,7 @@ namespace BuildXL.FrontEnd.Script.Ambients.Transformers m_unsafeTrustStaticallyDeclaredAccesses = Symbol("trustStaticallyDeclaredAccesses"); m_unsafeDisableFullReparsePointResolving = Symbol("disableFullReparsePointResolving"); m_unsafeDisableSandboxing = Symbol("disableSandboxing"); + m_unsafeBypassFingerprintSalt = Symbol("bypassFingerprintSalt"); // Semaphore info. m_semaphoreInfoLimit = Symbol("limit"); @@ -1416,6 +1419,12 @@ namespace BuildXL.FrontEnd.Script.Ambients.Transformers { processBuilder.Options |= Process.Options.DisableSandboxing; } + + // UnsafeExecuteArguments.bypassFingerprintSalt + if (Converter.ExtractOptionalBoolean(unsafeOptionsObjLit, m_unsafeBypassFingerprintSalt) == true) + { + processBuilder.Options |= Process.Options.BypassFingerprintSalt; + } } private PipId InterpretFinalizationPipArguments(Context context, ObjectLiteral obj) diff --git a/Public/Src/FrontEnd/Sdk/FrontEndEngineAbstraction.cs b/Public/Src/FrontEnd/Sdk/FrontEndEngineAbstraction.cs index 27a62361c..b8168762f 100644 --- a/Public/Src/FrontEnd/Sdk/FrontEndEngineAbstraction.cs +++ b/Public/Src/FrontEnd/Sdk/FrontEndEngineAbstraction.cs @@ -222,6 +222,11 @@ namespace BuildXL.FrontEnd.Sdk return EnumerateEntries(path, pattern, recursive, directories: true); } + /// + /// Translates an absolute path according to the defined translations + /// + public abstract AbsolutePath Translate(AbsolutePath path); + /// /// A simple IO based file system entry enumeration helper /// diff --git a/Public/Src/FrontEnd/Sdk/FrontEndHost.cs b/Public/Src/FrontEnd/Sdk/FrontEndHost.cs index 5e696d3cf..9aee2fae5 100644 --- a/Public/Src/FrontEnd/Sdk/FrontEndHost.cs +++ b/Public/Src/FrontEnd/Sdk/FrontEndHost.cs @@ -121,6 +121,7 @@ namespace BuildXL.FrontEnd.Sdk string weakPackageFingerprint, PackageIdentity package, AbsolutePath packageTargetFolder, + AbsolutePath pathToNuspec, Func>>> producePackage); /// diff --git a/Public/Src/FrontEnd/Sdk/SimpleFrontEndEngineAbstraction.cs b/Public/Src/FrontEnd/Sdk/SimpleFrontEndEngineAbstraction.cs index 5aaa1987e..cd8d847e4 100644 --- a/Public/Src/FrontEnd/Sdk/SimpleFrontEndEngineAbstraction.cs +++ b/Public/Src/FrontEnd/Sdk/SimpleFrontEndEngineAbstraction.cs @@ -65,6 +65,12 @@ namespace BuildXL.FrontEnd.Sdk }; } + /// + public override AbsolutePath Translate(AbsolutePath path) + { + return path; + } + /// /// This method is not implemented. /// @@ -86,7 +92,7 @@ namespace BuildXL.FrontEnd.Sdk return false; } - stream = m_fileSystem.OpenText(AbsolutePath.Create(m_pathTable, physicalPath)).BaseStream; + stream = m_fileSystem.OpenText(AbsolutePath.Create(m_pathTable, physicalPath)).BaseStream; return true; } diff --git a/Public/Src/FrontEnd/SdkTesting/Helper/TestEngineAbstraction.cs b/Public/Src/FrontEnd/SdkTesting/Helper/TestEngineAbstraction.cs index 017a9e88c..15cfd3d5e 100644 --- a/Public/Src/FrontEnd/SdkTesting/Helper/TestEngineAbstraction.cs +++ b/Public/Src/FrontEnd/SdkTesting/Helper/TestEngineAbstraction.cs @@ -42,6 +42,12 @@ namespace BuildXL.FrontEnd.Script.Testing.Helper }; } + /// + public override AbsolutePath Translate(AbsolutePath path) + { + return path; + } + /// public override bool TryGetFrontEndFile(AbsolutePath path, string frontEnd, out Stream stream) { diff --git a/Public/Src/FrontEnd/UnitTests/Core/DsTest.cs b/Public/Src/FrontEnd/UnitTests/Core/DsTest.cs index 0efb4a63f..902a87937 100644 --- a/Public/Src/FrontEnd/UnitTests/Core/DsTest.cs +++ b/Public/Src/FrontEnd/UnitTests/Core/DsTest.cs @@ -30,6 +30,7 @@ using BuildXL.FrontEnd.Workspaces.Core; using BuildXL.Native.IO; using BuildXL.Pips.Filter; using BuildXL.Utilities; +using BuildXL.Utilities.Collections; using BuildXL.Utilities.Configuration; using BuildXL.Utilities.Configuration.Mutable; using BuildXL.Utilities.Instrumentation.Common; @@ -1074,6 +1075,8 @@ namespace Test.BuildXL.FrontEnd.Core frontEndFactory.InitializeFrontEnds(controller, FrontEndContext, engine.Configuration); var frontEndEngineAbstraction = new BasicFrontEndEngineAbstraction(FrontEndContext.PathTable, engineContext.FileSystem, engine.Configuration); + frontEndEngineAbstraction.TryPopulateWithDefaultMountsTable(LoggingContext, engineContext, engine.Configuration, CollectionUtilities.EmptyDictionary()); + controller.SetState(frontEndEngineAbstraction, GetPipGraph(), config); var evaluationFilter = fileToProcess.IsValid ? EvaluationFilter.FromSingleSpecPath(FrontEndContext.SymbolTable, FrontEndContext.PathTable, fileToProcess) : EvaluationFilter.Empty; diff --git a/Public/Src/FrontEnd/UnitTests/Libs/Prelude.Context.ts b/Public/Src/FrontEnd/UnitTests/Libs/Prelude.Context.ts index 86a39be29..86f6cefe5 100644 --- a/Public/Src/FrontEnd/UnitTests/Libs/Prelude.Context.ts +++ b/Public/Src/FrontEnd/UnitTests/Libs/Prelude.Context.ts @@ -98,7 +98,7 @@ namespace Context { */ interface CurrentHostInformation { /** The current Os type */ - os: "win" | "mac" | "unix"; + os: "win" | "macOS" | "unix"; /** The current cpu architecture */ cpuArchitecture: "x64" | "x86"; /** Wheter the current build is run with elevated permissions (admin/sudo) */ diff --git a/Public/Src/FrontEnd/UnitTests/Nuget/NuSpecGeneratorTests.cs b/Public/Src/FrontEnd/UnitTests/Nuget/NuSpecGeneratorTests.cs index 946c60db1..0687193a1 100644 --- a/Public/Src/FrontEnd/UnitTests/Nuget/NuSpecGeneratorTests.cs +++ b/Public/Src/FrontEnd/UnitTests/Nuget/NuSpecGeneratorTests.cs @@ -11,17 +11,18 @@ using Xunit; using Xunit.Abstractions; using Test.BuildXL.TestUtilities.Xunit; using System; +using BuildXL.Utilities; namespace Test.BuildXL.FrontEnd.Nuget { public class NuSpecGeneratorTests { - private const int CurrentSpecGenVersion = 11; + private const int CurrentSpecGenVersion = 12; private readonly ITestOutputHelper m_output; private readonly FrontEndContext m_context; private readonly PackageGenerator m_packageGenerator; - + private readonly Dictionary m_repositories; private static readonly INugetPackage s_myPackage = new NugetPackage() { Id = "MyPkg", Version = "1.99" }; private static readonly INugetPackage s_systemCollections = new NugetPackage() { Id = "System.Collections", Version = "4.0.11" }; private static readonly INugetPackage s_systemCollectionsConcurrent = new NugetPackage() { Id = "System.Collections.Concurrent", Version = "4.0.12" }; @@ -42,6 +43,8 @@ namespace Test.BuildXL.FrontEnd.Nuget var monikers = new NugetFrameworkMonikers(m_context.StringTable); m_packageGenerator = new PackageGenerator(m_context, monikers); + + m_repositories = new Dictionary() { ["BuildXL"] = "https://pkgs.dev.azure.com/cloudbuild/_packaging/BuildXL.Selfhost/nuget/v3/index.json" }; } [Fact] @@ -70,11 +73,11 @@ namespace Test.BuildXL.FrontEnd.Nuget ", s_packagesOnConfig, new string[] { "lib/net45/my.dll", "lib/net451/my.dll", "lib/netstandard2.0/my.dll"}); - var spec = new NugetSpecGenerator(m_context.PathTable, pkg).CreateScriptSourceFile(pkg); + var spec = new NugetSpecGenerator(m_context.PathTable, pkg, m_repositories, AbsolutePath.Invalid).CreateScriptSourceFile(pkg); var text = spec.ToDisplayStringV2(); m_output.WriteLine(text); - string expectedSpec = $@"import {{Transformer}} from ""Sdk.Transformers""; + string expectedSpec = $@"import * as NugetDownloader from ""BuildXL.Tools.NugetDownloader""; import * as Managed from ""Sdk.Managed""; export declare const qualifier: {{ @@ -82,22 +85,23 @@ export declare const qualifier: {{ targetRuntime: ""win-x64"" | ""osx-x64"" | ""linux-x64"", }}; -const packageRoot = Contents.packageRoot; - namespace Contents {{ export declare const qualifier: {{ }}; - export const packageRoot = d`../../../pkgs/TestPkg.1.999`; + const outputDir: Directory = Context.getNewOutputDirectory(""nuget""); @@public - export const all: StaticDirectory = Transformer.sealDirectory( - packageRoot, - [ - f`${{packageRoot}}/lib/net45/my.dll`, - f`${{packageRoot}}/lib/net451/my.dll`, - f`${{packageRoot}}/lib/netstandard2.0/my.dll`, - f`${{packageRoot}}/TestPkg.nuspec`, - ] - ); + export const all: StaticDirectory = NugetDownloader.downloadPackage({{ + id: ""TestPkg"", + version: ""1.999"", + downloadDirectory: outputDir, + extractedFiles: [ + r`TestPkg.nuspec`, + r`lib/net45/my.dll`, + r`lib/net451/my.dll`, + r`lib/netstandard2.0/my.dll`, + ], + repositories: [[""BuildXL"", ""https://pkgs.dev.azure.com/cloudbuild/_packaging/BuildXL.Selfhost/nuget/v3/index.json""]], + }}); }} @@public @@ -108,9 +112,12 @@ export const pkg: Managed.ManagedNugetPackage = (() => {{ ""TestPkg"", ""1.999"", Contents.all, - [Managed.Factory.createBinaryFromFiles(f`${{packageRoot}}/lib/net45/my.dll`)], - [Managed.Factory.createBinaryFromFiles(f`${{packageRoot}}/lib/net45/my.dll`)], - [importFrom(""System.Collections"").pkg, importFrom(""System.Collections.Concurrent"").pkg] + [Managed.Factory.createBinaryFromFiles(Contents.all.getFile(r`lib/net45/my.dll`))], + [Managed.Factory.createBinaryFromFiles(Contents.all.getFile(r`lib/net45/my.dll`))], + [ + importFrom(""System.Collections"").pkg, + importFrom(""System.Collections.Concurrent"").pkg, + ] ); case ""net451"": case ""net452"": @@ -122,9 +129,12 @@ export const pkg: Managed.ManagedNugetPackage = (() => {{ ""TestPkg"", ""1.999"", Contents.all, - [Managed.Factory.createBinaryFromFiles(f`${{packageRoot}}/lib/net451/my.dll`)], - [Managed.Factory.createBinaryFromFiles(f`${{packageRoot}}/lib/net451/my.dll`)], - [importFrom(""System.Collections"").pkg, importFrom(""System.Collections.Concurrent"").pkg] + [Managed.Factory.createBinaryFromFiles(Contents.all.getFile(r`lib/net451/my.dll`))], + [Managed.Factory.createBinaryFromFiles(Contents.all.getFile(r`lib/net451/my.dll`))], + [ + importFrom(""System.Collections"").pkg, + importFrom(""System.Collections.Concurrent"").pkg, + ] ); case ""netstandard2.0"": case ""netcoreapp2.0"": @@ -139,9 +149,9 @@ export const pkg: Managed.ManagedNugetPackage = (() => {{ ""TestPkg"", ""1.999"", Contents.all, - [Managed.Factory.createBinaryFromFiles(f`${{packageRoot}}/lib/netstandard2.0/my.dll`)], + [Managed.Factory.createBinaryFromFiles(Contents.all.getFile(r`lib/netstandard2.0/my.dll`))], [ - Managed.Factory.createBinaryFromFiles(f`${{packageRoot}}/lib/netstandard2.0/my.dll`), + Managed.Factory.createBinaryFromFiles(Contents.all.getFile(r`lib/netstandard2.0/my.dll`)), ], [...addIfLazy(qualifier.targetFramework === ""netstandard2.0"", () => [importFrom(""Newtonsoft.Json"").pkg])] ); @@ -150,9 +160,9 @@ export const pkg: Managed.ManagedNugetPackage = (() => {{ }}; }} )();"; - XAssert.AreEqual(expectedSpec, text); + XAssert.AreEqual(expectedSpec.Trim(), text.Trim()); - const string CurrentSpecHash = "FDBA16F722AB64B5C61F4CBAD40500C9B1944E39"; + const string CurrentSpecHash = "1291F51E8E59ED9C2F967C01D49CC39FE6DEB9D8"; ValidateCurrentSpecGenVersion(expectedSpec, CurrentSpecHash); } @@ -160,25 +170,29 @@ export const pkg: Managed.ManagedNugetPackage = (() => {{ public void GenerateNuSpecForStub() { var pkg = m_packageGenerator.AnalyzePackageStub(s_packagesOnConfig); - var spec = new NugetSpecGenerator(m_context.PathTable, pkg).CreateScriptSourceFile(pkg); + var spec = new NugetSpecGenerator(m_context.PathTable, pkg, m_repositories, AbsolutePath.Invalid).CreateScriptSourceFile(pkg); var text = spec.ToDisplayStringV2(); m_output.WriteLine(text); - string expectedSpec = @"import {Transformer} from ""Sdk.Transformers""; + string expectedSpec = @"import * as NugetDownloader from ""BuildXL.Tools.NugetDownloader""; export declare const qualifier: { targetFramework: ""net10"" | ""net11"" | ""net20"" | ""net35"" | ""net40"" | ""net45"" | ""net451"" | ""net452"" | ""net46"" | ""net461"" | ""net462"" | ""net472"" | ""netstandard1.0"" | ""netstandard1.1"" | ""netstandard1.2"" | ""netstandard1.3"" | ""netstandard1.4"" | ""netstandard1.5"" | ""netstandard1.6"" | ""netstandard2.0"" | ""netcoreapp2.0"" | ""netcoreapp2.1"" | ""netcoreapp2.2"" | ""netcoreapp3.0"" | ""netcoreapp3.1"" | ""net5.0"" | ""net6.0"" | ""netstandard2.1"", targetRuntime: ""win-x64"" | ""osx-x64"" | ""linux-x64"", }; -const packageRoot = Contents.packageRoot; - namespace Contents { export declare const qualifier: { }; - export const packageRoot = d`../../../pkgs/TestPkgStub.1.999`; + const outputDir: Directory = Context.getNewOutputDirectory(""nuget""); @@public - export const all: StaticDirectory = Transformer.sealDirectory(packageRoot, []); + export const all: StaticDirectory = NugetDownloader.downloadPackage({ + id: ""TestPkgStub"", + version: ""1.999"", + downloadDirectory: outputDir, + extractedFiles: [], + repositories: [[""BuildXL"", ""https://pkgs.dev.azure.com/cloudbuild/_packaging/BuildXL.Selfhost/nuget/v3/index.json""]], + }); } @@public @@ -189,7 +203,7 @@ export const pkg: NugetPackage = { };"; XAssert.ArrayEqual(SplitToLines(expectedSpec), SplitToLines(text)); - const string CurrentSpecHash = "8550BF2B35888E3C0095095F44E2EB06FC2F0576"; + const string CurrentSpecHash = "389BC336BD4B206394E01B1E76A859E6561CE30D"; ValidateCurrentSpecGenVersion(expectedSpec, CurrentSpecHash); } diff --git a/Public/Src/FrontEnd/UnitTests/Nuget/NugetResolverUnitTests.cs b/Public/Src/FrontEnd/UnitTests/Nuget/NugetResolverUnitTests.cs index 22da60f0b..7b671cada 100644 --- a/Public/Src/FrontEnd/UnitTests/Nuget/NugetResolverUnitTests.cs +++ b/Public/Src/FrontEnd/UnitTests/Nuget/NugetResolverUnitTests.cs @@ -64,7 +64,7 @@ namespace Test.BuildXL.FrontEnd.Nuget var nugetResolver = CreateWorkspaceNugetResolverForTesting(); var allPackages = new Dictionary { [packageOnDisk.Package.Id] = packageOnDisk.Package }; - var analyzedPackage = nugetResolver.AnalyzeNugetPackage(packageOnDisk, false); + var analyzedPackage = nugetResolver.AnalyzeNugetPackage(packageOnDisk, AbsolutePath.Invalid, false); XAssert.IsTrue(analyzedPackage.Succeeded); @@ -86,7 +86,7 @@ namespace Test.BuildXL.FrontEnd.Nuget var allPackages = new Dictionary { [packageOnDisk.Package.Id] = packageOnDisk.Package }; - var analyzedPackage = nugetResolver.AnalyzeNugetPackage(packageOnDisk, false); + var analyzedPackage = nugetResolver.AnalyzeNugetPackage(packageOnDisk, AbsolutePath.Invalid, false); XAssert.IsTrue(analyzedPackage.Succeeded); @@ -105,10 +105,10 @@ namespace Test.BuildXL.FrontEnd.Nuget var packageText = File.ReadAllText(packageDsc); XAssert.IsFalse(packageText.Contains("export * from")); XAssert.IsFalse(packageText.Contains("/Foo.Bar.dsc\"")); - XAssert.IsTrue(packageText.Contains("/pkgs/Foo.Bar.1.2`")); - XAssert.IsTrue(packageText.Contains("packageRoot = d`")); - XAssert.IsTrue(packageText.Contains("f`${packageRoot}/Folder/a.txt`")); - XAssert.IsTrue(packageText.Contains("f`${packageRoot}/Folder/b.txt`")); + XAssert.IsTrue(packageText.Contains(@"id: ""Foo.Bar""")); + XAssert.IsTrue(packageText.Contains(@"version: ""1.2""")); + XAssert.IsTrue(packageText.Contains("r`Folder/a.txt`")); + XAssert.IsTrue(packageText.Contains("r`Folder/b.txt`")); } [Fact] @@ -140,7 +140,7 @@ namespace Test.BuildXL.FrontEnd.Nuget var pathTable = m_testContext.PathTable; var packageOnDisk = CreateTestPackageOnDisk(includeScriptSpec: false, version: version); var nugetResolver = CreateWorkspaceNugetResolverForTesting(); - var analyzedPackage = nugetResolver.AnalyzeNugetPackage(packageOnDisk, false); + var analyzedPackage = nugetResolver.AnalyzeNugetPackage(packageOnDisk, AbsolutePath.Invalid, false); XAssert.IsTrue(analyzedPackage.Succeeded); var allPackages = new Dictionary { [packageOnDisk.Package.Id] = analyzedPackage.Result }; XAssert.IsTrue(analyzedPackage.Succeeded); @@ -314,7 +314,7 @@ $@"module({{ { var allPackages = packagesOnDisk.ToDictionary(kvp => kvp.Package.Id, kvp => kvp.Package); - var allAnalyzedPackages = packagesOnDisk.ToDictionary(package => package.Package.Id, package => resolver.AnalyzeNugetPackage(package, false).Result); + var allAnalyzedPackages = packagesOnDisk.ToDictionary(package => package.Package.Id, package => resolver.AnalyzeNugetPackage(package, AbsolutePath.Invalid, false).Result); resolver.SetDownloadedPackagesForTesting(allAnalyzedPackages); diff --git a/Public/Src/FrontEnd/UnitTests/Nuget/PackageGenerator.cs b/Public/Src/FrontEnd/UnitTests/Nuget/PackageGenerator.cs index 693a211f4..7da2b4a8c 100644 --- a/Public/Src/FrontEnd/UnitTests/Nuget/PackageGenerator.cs +++ b/Public/Src/FrontEnd/UnitTests/Nuget/PackageGenerator.cs @@ -44,7 +44,7 @@ namespace Test.BuildXL.FrontEnd.Nuget paths, "testPackageHash")); - return NugetAnalyzedPackage.TryAnalyzeNugetPackage(m_context, m_monikers, XDocument.Parse(xml), packageOnDisk, packagesOnConfig, false); + return NugetAnalyzedPackage.TryAnalyzeNugetPackage(m_context, m_monikers, XDocument.Parse(xml), packageOnDisk, packagesOnConfig, false, AbsolutePath.Invalid); } public NugetAnalyzedPackage AnalyzePackageStub(Dictionary packagesOnConfig) @@ -58,7 +58,7 @@ namespace Test.BuildXL.FrontEnd.Nuget new PackageIdentity("nuget", nugetPackage.Id, nugetPackage.Version, nugetPackage.Alias), packageFolder: AbsolutePath.Create(m_context.PathTable, X("/X/Pkgs/TestPkgStub/1.999")))); - return NugetAnalyzedPackage.TryAnalyzeNugetPackage(m_context, m_monikers, nuSpec: null, packageOnDisk, packagesOnConfig, false); + return NugetAnalyzedPackage.TryAnalyzeNugetPackage(m_context, m_monikers, nuSpec: null, packageOnDisk, packagesOnConfig, false, AbsolutePath.Invalid); } } } diff --git a/Public/Src/FrontEnd/UnitTests/Script.Workspaces.Utilities/FakeNugetResolverSettingsProvider.cs b/Public/Src/FrontEnd/UnitTests/Script.Workspaces.Utilities/FakeNugetResolverSettingsProvider.cs index f231231af..11a098e5c 100644 --- a/Public/Src/FrontEnd/UnitTests/Script.Workspaces.Utilities/FakeNugetResolverSettingsProvider.cs +++ b/Public/Src/FrontEnd/UnitTests/Script.Workspaces.Utilities/FakeNugetResolverSettingsProvider.cs @@ -86,18 +86,6 @@ namespace Test.DScript.Workspaces.Utilities { return new MalformedConfigurationFailure("An array literal is expected for NuGet credential providers"); } - - var credentialProviders = expression.Cast(); - foreach (var element in credentialProviders.Elements) - { - var elementResult = ParseNugetConfigurationFrom(element.As()); - if (!elementResult.Succeeded) - { - return elementResult; - } - - result.CredentialProviders.Add(elementResult.Result); - } } if (configurationExpression.TryFindAssignmentPropertyInitializer(NaiveConfigurationParsingUtilities.ToolUrlFieldName, out expression)) diff --git a/Public/Src/IDE/UnitTests/LanguageServer/TestAutoCompleteProvider.cs b/Public/Src/IDE/UnitTests/LanguageServer/TestAutoCompleteProvider.cs index c7d8524fc..735deb43f 100644 --- a/Public/Src/IDE/UnitTests/LanguageServer/TestAutoCompleteProvider.cs +++ b/Public/Src/IDE/UnitTests/LanguageServer/TestAutoCompleteProvider.cs @@ -145,11 +145,12 @@ namespace BuildXL.Ide.LanguageServer.UnitTests .OrderBy(ci => ci.Label) .ToArray(); - Assert.Equal(1, completionItems.Length); + Assert.Equal(2, completionItems.Length); // TODO: Change to just BuildXL.DScript check after April 15, 2019 when deployed bits have updated. Assert.True(completionItems[0].Label == "BuildXL.DScript.LanguageServer.UnitTests.Data.Module" || completionItems[0].Label == "BuildXLScript.LanguageServer.UnitTests.Data.Module"); + Assert.True(completionItems[1].Label == "BuildXL.Tools.NugetDownloader"); } [Fact] diff --git a/Public/Src/Pips/Dll/Graph/ExtraFingerprintSalts.cs b/Public/Src/Pips/Dll/Graph/ExtraFingerprintSalts.cs index b24318790..c8aa5e7ea 100644 --- a/Public/Src/Pips/Dll/Graph/ExtraFingerprintSalts.cs +++ b/Public/Src/Pips/Dll/Graph/ExtraFingerprintSalts.cs @@ -413,9 +413,9 @@ namespace BuildXL.Pips.Graph /// /// Add fields to fingerprint /// - public void AddFingerprint(IHashingHelper fingerprinter) + public void AddFingerprint(IHashingHelper fingerprinter, bool bypassFingerprintSaltAndVersion) { - if (!string.IsNullOrEmpty(FingerprintSalt)) + if (!bypassFingerprintSaltAndVersion && !string.IsNullOrEmpty(FingerprintSalt)) { fingerprinter.Add(nameof(FingerprintSalt), FingerprintSalt); } @@ -455,14 +455,17 @@ namespace BuildXL.Pips.Graph fingerprinter.Add(nameof(ExplicitlyReportDirectoryProbes), 1); } - fingerprinter.Add(nameof(FingerprintVersion), (int)FingerprintVersion); + if (!bypassFingerprintSaltAndVersion) + { + fingerprinter.Add(nameof(FingerprintVersion), (int)FingerprintVersion); + } } private CalculatedFingerprintTuple ComputeWeakFingerprint() { using (var hasher = new CoreHashingHelper(true)) { - AddFingerprint(hasher); + AddFingerprint(hasher, bypassFingerprintSaltAndVersion: false); return new CalculatedFingerprintTuple(hasher.GenerateHash(), hasher.FingerprintInputText); } } diff --git a/Public/Src/Pips/Dll/Graph/PipFingerprinter.cs b/Public/Src/Pips/Dll/Graph/PipFingerprinter.cs index 03a5d9eac..c3cb1882a 100644 --- a/Public/Src/Pips/Dll/Graph/PipFingerprinter.cs +++ b/Public/Src/Pips/Dll/Graph/PipFingerprinter.cs @@ -173,7 +173,7 @@ namespace BuildXL.Pips.Graph Contract.Requires(fingerprinter != null); Contract.Requires(pip != null); - fingerprinter.AddNested(PipFingerprintField.ExecutionAndFingerprintOptions, fp => m_extraFingerprintSalts.AddFingerprint(fp)); + fingerprinter.AddNested(PipFingerprintField.ExecutionAndFingerprintOptions, fp => m_extraFingerprintSalts.AddFingerprint(fp, pip.BypassFingerprintSalt)); // Fingerprints must change when outputs are hashed with a different algorithm. fingerprinter.Add(PipFingerprintField.ContentHashAlgorithmName, s_outputContentHashAlgorithmName); diff --git a/Public/Src/Pips/Dll/Operations/Pip.cs b/Public/Src/Pips/Dll/Operations/Pip.cs index e100616f1..4cf81c370 100644 --- a/Public/Src/Pips/Dll/Operations/Pip.cs +++ b/Public/Src/Pips/Dll/Operations/Pip.cs @@ -70,6 +70,11 @@ namespace BuildXL.Pips.Operations [PipCaching(FingerprintingRole = FingerprintingRole.None)] public abstract PipType PipType { get; } + /// + /// When set, the pip fingerprint is not sensitive to fingerprint salts. This excludes both EngineEnvironmentSettings.DebugFingerprintSalt and PipFingerprintingVersion.TwoPhaseV2 + /// + public virtual bool BypassFingerprintSalt => false; + /// internal Pip() { diff --git a/Public/Src/Pips/Dll/Operations/Process.Options.cs b/Public/Src/Pips/Dll/Operations/Process.Options.cs index 6940e970c..8d4a1bab0 100644 --- a/Public/Src/Pips/Dll/Operations/Process.Options.cs +++ b/Public/Src/Pips/Dll/Operations/Process.Options.cs @@ -182,6 +182,11 @@ namespace BuildXL.Pips.Operations /// Whether to disable sandboxing for this process /// DisableSandboxing = 1 << 21, + + /// + /// When set, the pip fingerprint is not sensitive to fingerprint salts. This excludes both and PipFingerprintingVersion.TwoPhaseV2 + /// + BypassFingerprintSalt = 1 << 22, } } } diff --git a/Public/Src/Pips/Dll/Operations/Process.cs b/Public/Src/Pips/Dll/Operations/Process.cs index 857d115ef..ff04e4caf 100644 --- a/Public/Src/Pips/Dll/Operations/Process.cs +++ b/Public/Src/Pips/Dll/Operations/Process.cs @@ -842,6 +842,10 @@ namespace BuildXL.Pips.Operations /// public bool HasSharedOpaqueDirectoryOutputs => DirectoryOutputs.Any(d => d.IsSharedOpaque); + /// + [PipCaching(FingerprintingRole = FingerprintingRole.Semantic)] + public override bool BypassFingerprintSalt => (ProcessOptions & Options.BypassFingerprintSalt) != 0; + /// /// What policy to apply when merging redirected outputs back /// diff --git a/Public/Src/Sandbox/MacOs/deployment.dsc b/Public/Src/Sandbox/MacOs/deployment.dsc index e23646b25..56d786c93 100644 --- a/Public/Src/Sandbox/MacOs/deployment.dsc +++ b/Public/Src/Sandbox/MacOs/deployment.dsc @@ -7,8 +7,6 @@ import * as SdkDeployment from "Sdk.Deployment"; namespace Deployment { export declare const qualifier: {configuration: "debug" | "release"}; - const pkgPath = d`${importFrom("runtime.osx-x64.BuildXL").Contents.all.root}/runtimes/osx-x64/native`; - @@public export const macBinaryUsage = Context.getCurrentHost().os === "macOS" ? (BuildXLSdk.Flags.isValidatingOsxRuntime ? "package" : "build") @@ -22,7 +20,9 @@ namespace Deployment { contents: macBinaryUsage === "none" ? [] : macBinaryUsage === "package" - ? [ SdkDeployment.createFromDisk(d`${pkgPath}/${qualifier.configuration}/BuildXLSandbox.kext`) ] + ? [ SdkDeployment.createFromFilteredStaticDirectory( + importFrom("runtime.osx-x64.BuildXL").Contents.all.ensureContents({subFolder: r`runtimes/osx-x64/native/${qualifier.configuration}/BuildXLSandbox.kext`}), + r`.`)] : [{ subfolder: a`Contents`, contents: [ @@ -47,7 +47,9 @@ namespace Deployment { contents: macBinaryUsage === "none" ? [] : macBinaryUsage === "package" - ? [ SdkDeployment.createFromDisk(d`${pkgPath}/${qualifier.configuration}/BuildXLSandbox.kext.dSYM`) ] + ? [ SdkDeployment.createFromFilteredStaticDirectory( + importFrom("runtime.osx-x64.BuildXL").Contents.all.ensureContents({subFolder: r`runtimes/osx-x64/native/${qualifier.configuration}/BuildXLSandbox.kext.dSYM`}), + r`.`)] : [{ subfolder: a`Contents`, contents: [ @@ -83,30 +85,34 @@ namespace Deployment { @@public export const sandboxMonitor: SdkDeployment.Definition = { - contents: [ + contents: macBinaryUsage === "build" - ? Sandbox.monitor - : f`${pkgPath}/${qualifier.configuration}/SandboxMonitor` - ] + ? [Sandbox.monitor] + : macBinaryUsage === "package" + ? [importFrom("runtime.osx-x64.BuildXL").Contents.all.getFile(r`runtimes/osx-x64/native/${qualifier.configuration}/SandboxMonitor`)] + : [] }; @@public export const interopLibrary: SdkDeployment.Definition = { contents: macBinaryUsage === "build" ? [ Sandbox.libInterop, Sandbox.libDetours ] - : [ - f`${pkgPath}/${qualifier.configuration}/libBuildXLInterop.dylib`, - f`${pkgPath}/${qualifier.configuration}/libBuildXLDetours.dylib` - ] + : macBinaryUsage === "package" + ? [ + importFrom("runtime.osx-x64.BuildXL").Contents.all.getFile(r`runtimes/osx-x64/native/${qualifier.configuration}/libBuildXLInterop.dylib`), + importFrom("runtime.osx-x64.BuildXL").Contents.all.getFile(r`runtimes/osx-x64/native/${qualifier.configuration}/libBuildXLDetours.dylib`) + ] + : [] }; @@public export const coreDumpTester: SdkDeployment.Definition = { - contents: [ + contents: macBinaryUsage === "build" - ? Sandbox.coreDumpTester - : f`${pkgPath}/${qualifier.configuration}/CoreDumpTester` - ] + ? [Sandbox.coreDumpTester] + : macBinaryUsage === "package" + ? [importFrom("runtime.osx-x64.BuildXL").Contents.all.getFile(r`runtimes/osx-x64/native/${qualifier.configuration}/CoreDumpTester`)] + : [] }; @@public diff --git a/Public/Src/Tools/BxlScriptAnalyzer/WorkspaceBuilder.cs b/Public/Src/Tools/BxlScriptAnalyzer/WorkspaceBuilder.cs index 6261dc80c..c6a44fc35 100644 --- a/Public/Src/Tools/BxlScriptAnalyzer/WorkspaceBuilder.cs +++ b/Public/Src/Tools/BxlScriptAnalyzer/WorkspaceBuilder.cs @@ -218,7 +218,7 @@ namespace BuildXL.FrontEnd.Script.Analyzer Contract.AssertNotNull(frontEndEngineAbstraction); AddConfigurationMounts(config, mountsTable); - languageServiceEngine.SetMountsTable(mountsTable); + languageServiceEngine.UpdateMountsTable(mountsTable); } if (frontEndEngineAbstraction == null) diff --git a/Public/Src/Tools/FileDownloader/Downloader.cs b/Public/Src/Tools/FileDownloader/Downloader.cs index 3917ce9a6..3aae6b4b4 100644 --- a/Public/Src/Tools/FileDownloader/Downloader.cs +++ b/Public/Src/Tools/FileDownloader/Downloader.cs @@ -2,21 +2,19 @@ // Licensed under the MIT License. using System; -using System.ComponentModel; using System.Diagnostics; using System.IO; -using System.Linq; using System.Net.Http; using System.Net.Http.Headers; +using System.Text; +using System.Threading; using System.Threading.Tasks; using BuildXL.Cache.ContentStore.Hashing; using BuildXL.Native.IO; using BuildXL.Storage; using BuildXL.ToolSupport; using BuildXL.Utilities; -using Microsoft.IdentityModel.Clients.ActiveDirectory; -using Newtonsoft.Json; -using Newtonsoft.Json.Linq; +using BuildXL.Utilities.VstsAuthentication; namespace Tool.Download { @@ -94,11 +92,15 @@ namespace Tool.Download var httpRequest = new HttpRequestMessage(HttpMethod.Get, arguments.Url); + var logger = new StringBuilder(); + // If the download URI is pointing to a VSTS feed and we get a valid auth token, make it part of the request // We only want to send the token over HTTPS and to a VSTS domain to avoid security issues - if (IsVSTSPackageSecureURI(arguments.Url) && - await TryGetAuthenticationHeaderAsync(arguments.Url) is var authHeader && - authHeader != null) + if (VSTSAuthenticationHelper.IsVSTSPackageSecureURI(arguments.Url) && + await VSTSAuthenticationHelper.IsAuthenticationRequiredAsync(arguments.Url, CancellationToken.None, logger) && + await VSTSAuthenticationHelper.TryGetAuthenticationCredentialsAsync(arguments.Url, CancellationToken.None) is var maybeAuthCredentials && + maybeAuthCredentials.Succeeded && + VSTSAuthenticationHelper.GetAuthenticationHeaderFromPAT(maybeAuthCredentials.Result.pat) is var authHeader) { httpRequest.Headers.Accept.Clear(); httpRequest.Headers.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json")); @@ -162,175 +164,5 @@ namespace Tool.Download return await ContentHashingUtilities.HashContentStreamAsync(fs, hashType); } - - private bool IsVSTSPackageSecureURI(Uri downloadURI) - { - return downloadURI.Scheme == "https" && - (downloadURI.Host.EndsWith(".pkgs.visualstudio.com", StringComparison.OrdinalIgnoreCase) || downloadURI.Host.EndsWith(".pkgs.dev.azure.com", StringComparison.OrdinalIgnoreCase)) ; - } - - /// - /// Tries to authenticate using a credential provider and fallback to IWA if that fails. - /// - private async Task TryGetAuthenticationHeaderAsync(Uri uri) - { - var result = await TryGetAuthenticationHeaderValueWithCredentialProviderAsync(uri); - if (result != null) - { - return result; - } - - return await TryGetAuthenticationHeaderWithIWAAsync(uri); - } - - /// - /// Tries to get an authentication token using Integrated Windows Authentication with the current logged in user - /// - /// Null if authentication fails - /// - /// The auth token is acquired to address simple auth cases for retrieving packages from VSTS feeds from Windows domain - /// joined machines where IWA is enabled. - /// See https://github.com/AzureAD/microsoft-authentication-library-for-dotnet/wiki/Integrated-Windows-Authentication - /// - private async Task TryGetAuthenticationHeaderWithIWAAsync(Uri uri) - { - var authenticationContext = new AuthenticationContext(m_authority); - - try - { - var userCredential = new UserCredential($"{Environment.UserName}@{Tenant}"); - - // Many times the user UPN cannot be automatically retrieved, so we build it based on the current username and tenant. This might - // not be perfect but should work for most cases. Getting the UPN for a given user from AD requires authentication as well. - var result = await authenticationContext.AcquireTokenAsync(Resource, Client, userCredential); ; - return new AuthenticationHeaderValue("Bearer", result.AccessToken); - } - catch (AdalException ex) - { - Console.WriteLine($"Download resolver was not able to authenticate using Integrated Windows Authentication for '{uri}': {ex.Message}"); - // Getting an auth token via IWA is on a best effort basis. If anything fails, we silently continue without auth - return null; - } - } - - /// - /// Tries to get an authentication token using a credential provider - /// - /// Null if authentication fails - /// - /// The credential provider is discovered following the definition here: https://docs.microsoft.com/en-us/nuget/reference/extensibility/nuget-exe-credential-providers - /// using an environment variable. - /// Observe the link above is for nuget specifically, but the authentication here is used for VSTS feeds in general - /// - private async Task TryGetAuthenticationHeaderValueWithCredentialProviderAsync(Uri uri) - { - string credentialProviderPath = DiscoverCredentialProvider(uri); - - if (credentialProviderPath == null) - { - // Failure has been logged already - return null; - } - - // Call the provider with the requested URI in non-interactive mode. - var processInfo = new ProcessStartInfo - { - FileName = credentialProviderPath, - Arguments = $"-Uri {uri.AbsoluteUri} -NonInteractive", - RedirectStandardOutput = true, - CreateNoWindow = true, - }; - - using (var process = Process.Start(processInfo)) - { - try - { - #pragma warning disable AsyncFixer02 // WaitForExitAsync should be used instead - process?.WaitForExit(); - #pragma warning restore AsyncFixer02 - } - catch (Exception e) when (e is SystemException || e is Win32Exception) - { - ReportAuthenticationViaCredentialProviderFailed(uri, $"Credential provider execution '{credentialProviderPath}' failed. Error: {e.Message}"); - return null; - } - - if (process == null) - { - // The process was not started - ReportAuthenticationViaCredentialProviderFailed(uri, $"Could not start credential provider process '{credentialProviderPath}'."); - return null; - } - - // Check whether the authorization succeeded - if (process.ExitCode == 0) - { - try - { - // The response should be a well-formed JSON with a 'password' entry representing the PAT - var response = (JObject)await JToken.ReadFromAsync(new JsonTextReader(process.StandardOutput)); - var pat = response.GetValue("Password"); - - if (pat == null) - { - ReportAuthenticationViaCredentialProviderFailed(uri, $"Could not find a 'password' entry in the JSON response of '{credentialProviderPath}'."); - return null; - } - - // We got a PAT back. Create an authentication header with a base64 encoding of the retrieved PAT - return new AuthenticationHeaderValue("Basic", - Convert.ToBase64String( - System.Text.ASCIIEncoding.ASCII.GetBytes( - string.Format("{0}:{1}", "", pat)))); - } - catch (JsonReaderException) - { - ReportAuthenticationViaCredentialProviderFailed(uri, $"The credential provider '{credentialProviderPath}' response is not a well-formed JSON."); - return null; - } - } - - ReportAuthenticationViaCredentialProviderFailed(uri, $"The credential provider '{credentialProviderPath}' returned a non-succesful exit code: {process.ExitCode}."); - } - - return null; - } - - private string DiscoverCredentialProvider(Uri uri) - { - var paths = Environment.GetEnvironmentVariable("NUGET_CREDENTIALPROVIDERS_PATH"); - - if (paths == null) - { - ReportAuthenticationViaCredentialProviderFailed(uri, $"NUGET_CREDENTIALPROVIDERS_PATH is not set."); - return null; - } - - // Here we do something slightly simpler than what NuGet does and just look for the first credential - // provider we can find - string credentialProviderPath = null; - foreach (string path in paths.Split(new[] { Path.PathSeparator }, StringSplitOptions.RemoveEmptyEntries)) - { - credentialProviderPath = Directory.EnumerateFiles(path, "credentialprovider*.exe", SearchOption.TopDirectoryOnly).FirstOrDefault(); - if (credentialProviderPath != null) - { - break; - } - } - - if (credentialProviderPath == null) - { - ReportAuthenticationViaCredentialProviderFailed(uri, $"Credential provider was not found under '{paths}'."); - - return null; - } - - return credentialProviderPath; - } - - private void ReportAuthenticationViaCredentialProviderFailed(Uri url, string details) - { - Console.WriteLine($"Download resolver was not able to authenticate using a credential provider for '{url}': {details}") ; - } } } diff --git a/Public/Src/Tools/FileDownloader/Tool.FileDownloader.dsc b/Public/Src/Tools/FileDownloader/Tool.FileDownloader.dsc index 20ef01191..ca401cb02 100644 --- a/Public/Src/Tools/FileDownloader/Tool.FileDownloader.dsc +++ b/Public/Src/Tools/FileDownloader/Tool.FileDownloader.dsc @@ -21,6 +21,7 @@ namespace FileDownloader { sources: globR(d`.`, "Downloader*.cs"), references:[ importFrom("Newtonsoft.Json").pkg, + importFrom("BuildXL.Utilities").VstsAuthentication.dll, importFrom("BuildXL.Utilities").Collections.dll, importFrom("BuildXL.Utilities").Native.dll, importFrom("BuildXL.Utilities.Instrumentation").Common.dll, diff --git a/Public/Src/Tools/NugetDownloader/App.config b/Public/Src/Tools/NugetDownloader/App.config new file mode 100644 index 000000000..cd04a1cba --- /dev/null +++ b/Public/Src/Tools/NugetDownloader/App.config @@ -0,0 +1,6 @@ + + + + + + diff --git a/Public/Src/Tools/NugetDownloader/ConsoleLogger.cs b/Public/Src/Tools/NugetDownloader/ConsoleLogger.cs new file mode 100644 index 000000000..6d79a7323 --- /dev/null +++ b/Public/Src/Tools/NugetDownloader/ConsoleLogger.cs @@ -0,0 +1,84 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +using System; +using System.Threading.Tasks; +using NuGet.Common; + +namespace NugetDownloader +{ + /// + /// Logs all messages to the console + /// + internal class ConsoleLogger : ILogger + { + /// + public void Log(LogLevel level, string data) + { + Console.WriteLine($"[{level}]:{data}"); + } + + /// + public void Log(ILogMessage message) + { + Console.WriteLine(message.FormatWithCode()); + } + + /// + public Task LogAsync(LogLevel level, string data) + { + Log(level, data); + return Task.CompletedTask; + } + + /// + public Task LogAsync(ILogMessage message) + { + Log(message); + return Task.CompletedTask; + + } + + /// + public void LogDebug(string data) + { + Log(LogLevel.Debug, data); + } + + /// + public void LogError(string data) + { + Log(LogLevel.Error, data); + } + + /// + public void LogInformation(string data) + { + Log(LogLevel.Information, data); + } + + /// + public void LogInformationSummary(string data) + { + Log(LogLevel.Information, data); + } + + /// + public void LogMinimal(string data) + { + Log(LogLevel.Information, data); + } + + /// + public void LogVerbose(string data) + { + Log(LogLevel.Verbose, data); + } + + /// + public void LogWarning(string data) + { + Log(LogLevel.Warning, data); + } + } +} diff --git a/Public/Src/Tools/NugetDownloader/LiteralFiles/Tool.NugetDownloader.dsc.literal b/Public/Src/Tools/NugetDownloader/LiteralFiles/Tool.NugetDownloader.dsc.literal new file mode 100644 index 000000000..a1656a314 --- /dev/null +++ b/Public/Src/Tools/NugetDownloader/LiteralFiles/Tool.NugetDownloader.dsc.literal @@ -0,0 +1,125 @@ +// Copyright (c) Microsoft. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. + +import {Artifact, Cmd, Transformer, Tool} from "Sdk.Transformers"; + +export declare const qualifier: {}; + +const downloaderDefinition: Transformer.ToolDefinition = { + // CODESYNC: keep in sync with deployment at Public\Src\FrontEnd\Nuget\BuildXL.FrontEnd.Nuget.dsc + exe: Context.isWindowsOS()? f`${Context.getBuildEngineDirectory()}/NugetDownloader.exe` : f`${Context.getBuildEngineDirectory()}/NugetDownloader`, + description: "BuildXL NuGet downloader", + dependsOnWindowsDirectories: true, + dependsOnAppDataDirectory: true, + prepareTempDirectory: true, + untrackedDirectoryScopes: [ + d`${Context.getMount("ProgramData").path}/Microsoft/NetFramework/BreadcrumbStore`, + ...addIfLazy(Context.isWindowsOS(), () => [d`${Context.getMount("LocalLow").path}/Microsoft/CryptnetUrlCache`]), + ...addIfLazy(Context.getCurrentHost().os === "macOS", () => [d`/dev/dtracehelper`, d`/private/var/run/mDNSResponder`, d`/private/var/folders`, d`/dev/tty`, d`/usr/share/zoneinfo`, d`/usr/share/icu`]), + d`${Context.getMount("UserProfile").path}/.dotnet/corefx/cryptography` + ], +}; + + +/** + * Arguments for downloading a NuGet package under a specified directory + */ +@@public +export interface Arguments extends Transformer.RunnerArguments { + id: string; + version: string; + downloadDirectory: Directory; + extractedFiles: RelativePath[]; + repositories: [string, string][]; + credentialProviderPath?: File; + timeoutInMinutes?: number; +} + +/** + * Downloads a NuGet package as specified in the arguments and returns the outputs that result of the execution in a static directory + */ +@@public +export function downloadPackage(args: Arguments) : PartialStaticContentDirectory { + + const arguments: Argument[] = [ + Cmd.option("/id:", args.id), + Cmd.option("/version:", args.version), + Cmd.option("/downloadDirectory:", Artifact.none(args.downloadDirectory)), + Cmd.options("/repositories:", args.repositories.map(kvp => kvp[0] + "=" + kvp[1])), + ]; + + // NuGet extraction always injects a parent folder with the package id + version as the name + const directoryName = `${args.id}.${args.version}`; + + // Build the list of expected outputs + const outputs : File[] = args.extractedFiles.map(relativePath => f`${args.downloadDirectory}/${directoryName}/${relativePath}`); + + // In some cases the package is expected to be empty. In that case, don't run anything and just return an empty seal dir + if (outputs.length === 0) + { + return Transformer.sealPartialDirectory(d`${args.downloadDirectory.combine(directoryName)}`, []); + } + + let tool = downloaderDefinition; + + // The timeout is not available per-pip but at the tool level + if (args.timeoutInMinutes !== undefined) { + tool = tool.merge({ + timeoutInMilliseconds: args.timeoutInMinutes * 60 * 1000, + // We could have a separate argument for this, but for now let's keep it simple + warningTimeoutInMilliseconds: args.timeoutInMinutes * 60 * 1000 + }); + } + + // Nuget tries to read the user settings config file, and if it is not there, it creates it. + // The creation does not behave well with concurrent executions and write locks issues arise. + // Let's give each nuget pip a different app data directory + const redirectedAppData = Context.getTempDirectory("redirectedAppData"); + + const transformerExecuteArgs : Transformer.ExecuteArguments = { + description: `Downloading NuGet package '${args.id}.${args.version}'`, + tool: tool, + arguments: arguments, + workingDirectory: args.downloadDirectory, + tags: ["nuget", ...(args.tags || [])], + environmentVariables: [ + ...addIf(args.credentialProviderPath !== undefined, {name: "NUGET_CREDENTIALPROVIDERS_PATH", value: args.credentialProviderPath}), + ...addIf(Environment.hasVariable("VSS_NUGET_EXTERNAL_FEED_ENDPOINTS"), {name: "VSS_NUGET_EXTERNAL_FEED_ENDPOINTS", value: Environment.getStringValue("VSS_NUGET_EXTERNAL_FEED_ENDPOINTS")}), + // In case the artifacts credential provider is being used, make sure we don't cache the token, so we avoid dealing with IsRetry + {name: "NUGET_CREDENTIALPROVIDER_SESSIONTOKENCACHE_ENABLED", value: "False"}, + // On linux/mac the NuGet SDK needs this variable defined. It doesn't really matter where it is pointing to. + ...addIf(!Context.isWindowsOS(), {name: "DOTNET_CLI_HOME", value: redirectedAppData}), + {name: "AppData", value: redirectedAppData} + ], + outputs: outputs, + tempDirectory: redirectedAppData, + unsafe: { + passThroughEnvironmentVariables: [ + "LocalAppData", + "QAUTHMATERIALROOT", + "__CREDENTIAL_PROVIDER_LOG_DIR", + "__CLOUDBUILD_AUTH_HELPER_ROOT__", + "__CLOUDBUILD_AUTH_HELPER_CONFIG__", + ], + requireGlobalDependencies: false, + // The only child process this tool spawns is the credential provider process. This process may write log files that are hard to predict upfront. + hasUntrackedChildProcesses: true, + // This is to avoid a cache miss on a NuGet download due to changes on the nuget download tool (changes in downtream dependencies for the + // most part, e.g. some framework dll that is changed because of some unrelated change in Bxl) + // This is a confidence vote since we own the nuget downloader tool. If for any reason the nuget pips need invalidation, that can + // be manually triggered by bumping the NuGet spec fingerprint version. + untrackedScopes: [Context.getBuildEngineDirectory()], + // Make NuGet pips so fingerprint salts (the general fingerprint V2 version and the debug salt passed with /p:BUILDXL_FINGERPRINT_SALT) are not + // included in the weak fingerprint. Observe this option is not exposed in DScript, so we are forcing the hand of the type checker with the cast above + // to not complain about this extra field (which will be picked up at runtime) + bypassFingerprintSalt: true + }, + // This is to avoid DFAs under the credential provider directory, which is an arbitrarily specified directory that would need to + // be contained in a statically declared read mount otherwise + allowUndeclaredSourceReads: true, + }; + + const result = Transformer.execute(transformerExecuteArgs); + + return Transformer.sealPartialDirectory(d`${args.downloadDirectory.combine(directoryName)}`, result.getOutputFiles()); +} \ No newline at end of file diff --git a/Public/Src/Tools/NugetDownloader/LiteralFiles/module.config.dsc.literal b/Public/Src/Tools/NugetDownloader/LiteralFiles/module.config.dsc.literal new file mode 100644 index 000000000..96fcccb69 --- /dev/null +++ b/Public/Src/Tools/NugetDownloader/LiteralFiles/module.config.dsc.literal @@ -0,0 +1,6 @@ +// Copyright (c) Microsoft. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. + +module({ + name: "BuildXL.Tools.NugetDownloader" +}); diff --git a/Public/Src/Tools/NugetDownloader/NugetDownloader.cs b/Public/Src/Tools/NugetDownloader/NugetDownloader.cs new file mode 100644 index 000000000..e513584a6 --- /dev/null +++ b/Public/Src/Tools/NugetDownloader/NugetDownloader.cs @@ -0,0 +1,149 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +using System; +using System.Diagnostics; +using System.IO; +using System.Linq; +using System.Text; +using System.Threading; +using System.Threading.Tasks; +using BuildXL.Native.IO; +using BuildXL.ToolSupport; +using BuildXL.Utilities; +using BuildXL.Utilities.VstsAuthentication; +using NuGet.Common; +using NuGet.Configuration; +using NuGet.Packaging; +using NuGet.Packaging.Signing; +using NuGet.Protocol.Core.Types; +using NugetDownloader; + +namespace Tool.Download +{ + /// + /// Downloads a Nuget into a given directory from a collection of source repositories + /// + internal sealed class NugetDownloader : ToolProgram + { + private NugetDownloader() : base("NugetDownloader") + { + } + + /// + public static int Main(string[] arguments) + { + return new NugetDownloader().MainHandler(arguments); + } + + /// + public override bool TryParse(string[] rawArgs, out NugetDownloaderArgs arguments) + { + try + { + arguments = new NugetDownloaderArgs(rawArgs); + return true; + } + catch (Exception ex) + { + Console.Error.WriteLine(ex.GetLogEventMessage()); + arguments = null; + return false; + } + } + + /// + public override int Run(NugetDownloaderArgs arguments) + { + return TryDownloadNugetToDiskAsync(arguments).GetAwaiter().GetResult(); + } + + /// + /// Attempts to download and extract a NuGet package to disk. + /// + private async Task TryDownloadNugetToDiskAsync(NugetDownloaderArgs arguments) + { + Console.WriteLine($"Download started for package '{arguments.Id}' and version '{arguments.Version}' to '{arguments.DownloadDirectory}'."); + + var stopwatch = Stopwatch.StartNew(); + + SourceCacheContext cache = new SourceCacheContext(); + + var authLogger = new StringBuilder(); + var maybeRepositories = await VSTSAuthenticationHelper.TryCreateSourceRepositories(arguments.Repositories.Select(kvp => (kvp.Key, kvp.Value)), CancellationToken.None, authLogger); + + // Informational data + Console.WriteLine(authLogger.ToString()); + + if (!maybeRepositories.Succeeded) + { + Console.Error.WriteLine($"Failed to access the specified repositories: " + maybeRepositories.Failure.Describe()); + return 1; + } + + bool found = false; + ILogger logger = new ConsoleLogger(); + foreach (var sourceRepository in maybeRepositories.Result) + { + Console.Write($"Finding resource against source repository '{sourceRepository.PackageSource.Name}={sourceRepository.PackageSource.SourceUri}'. Authentication is on: {sourceRepository.PackageSource.Credentials != null}"); + + // TODO: maybe we need a retry here? or define a default retry in the DScript SDK? + FindPackageByIdResource resource = await sourceRepository.GetResourceAsync(); + + if (resource == null) + { + Console.Write($"Resource under source repository '{sourceRepository.PackageSource.Name}={sourceRepository.PackageSource.SourceUri}' not found."); + continue; + } + + var destinationFilePath = Path.Combine(Path.GetTempPath(), Path.GetRandomFileName()); + + // We don't really need to materialize the nupkg file on disk, but a memory stream has a 2GB limitation, and NuGet packages + // can be larger than that. Just place it on disk and remove it after we are done extracting. + using (var packageStream = new FileStream( + destinationFilePath, + FileMode.Create, + FileAccess.ReadWrite, + FileShare.ReadWrite | FileShare.Delete, + bufferSize: 4096)) + { + if (await resource.CopyNupkgToStreamAsync( + arguments.Id, + arguments.Version, + packageStream, + cache, + logger, + CancellationToken.None)) + { + found = true; + + await PackageExtractor.ExtractPackageAsync( + sourceRepository.PackageSource.Source, + packageStream, + new PackagePathResolver(arguments.DownloadDirectory), + new PackageExtractionContext( + PackageSaveMode.Files | PackageSaveMode.Nuspec, + XmlDocFileSaveMode.None, + ClientPolicyContext.GetClientPolicy(NullSettings.Instance, logger), + logger), + CancellationToken.None); + + FileUtilities.DeleteFile(destinationFilePath); + + break; + } + } + } + + if (!found) + { + Console.Error.WriteLine($"Could not find NuGet package '{arguments.Id}' with version '{arguments.Version.ToNormalizedString()}' under any of the provided repositories."); + return 1; + } + + Console.WriteLine($"Finished downloading package '{arguments.Id}' with version '{arguments.Version}' in {stopwatch.ElapsedMilliseconds}ms"); + + return 0; + } + } +} diff --git a/Public/Src/Tools/NugetDownloader/NugetDownloaderArgs.cs b/Public/Src/Tools/NugetDownloader/NugetDownloaderArgs.cs new file mode 100644 index 000000000..57a01ea32 --- /dev/null +++ b/Public/Src/Tools/NugetDownloader/NugetDownloaderArgs.cs @@ -0,0 +1,93 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +using System; +using System.Collections.Generic; +using BuildXL.ToolSupport; +using NuGet.Versioning; + +namespace Tool.Download +{ + /// + internal sealed partial class NugetDownloaderArgs : CommandLineUtilities + { + /// + /// package id of the download + /// + public string Id { get; } + + /// + /// package version of the download + /// + public NuGetVersion Version { get; } + + /// + /// The directory to place the downloaded file + /// + public string DownloadDirectory { get; } + + /// + /// The Nuget feeds (name and Uri) where to download the package from + /// + public IReadOnlyDictionary Repositories { get; } + + /// + public NugetDownloaderArgs(string[] args) + : base(args) + { + var repositories = new Dictionary(); + + foreach (Option opt in Options) + { + if (opt.Name.Equals("id", StringComparison.OrdinalIgnoreCase)) + { + Id = opt.Value; + } + else if (opt.Name.Equals("version", StringComparison.OrdinalIgnoreCase)) + { + if (!NuGetVersion.TryParse(opt.Value, out NuGetVersion version)) + { + throw Error($"Malformed version: {opt.Value}."); + } + + Version = version; + } + else if (opt.Name.Equals("downloadDirectory", StringComparison.OrdinalIgnoreCase)) + { + DownloadDirectory = opt.Value; + } + else if (opt.Name.Equals("repositories", StringComparison.OrdinalIgnoreCase)) + { + var kvp = ParseKeyValuePair(opt); + repositories[kvp.Key] = new Uri(kvp.Value); + } + else + { + throw Error($"Unsupported option: {opt.Name}."); + } + } + + Repositories = repositories; + + if (Id == null) + { + throw Error($"Missing mandatory argument 'id'"); + } + + if (Version == null) + { + throw Error($"Missing mandatory argument 'version'"); + } + + if (Repositories.Count == 0) + { + throw Error($"Missing mandatory argument 'repositories'"); + } + + if (string.IsNullOrWhiteSpace(DownloadDirectory)) + { + throw Error($"Missing mandatory argument 'DownloadDirectory'"); + } + } + } +} diff --git a/Public/Src/Tools/NugetDownloader/Tool.NugetDownloader.dsc b/Public/Src/Tools/NugetDownloader/Tool.NugetDownloader.dsc new file mode 100644 index 000000000..3944d54f5 --- /dev/null +++ b/Public/Src/Tools/NugetDownloader/Tool.NugetDownloader.dsc @@ -0,0 +1,62 @@ +// Copyright (c) Microsoft. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. + +import * as Managed from "Sdk.Managed"; +import * as BuildXLSdk from "Sdk.BuildXL"; +import {Transformer} from "Sdk.Transformers"; +import * as Deployment from "Sdk.Deployment"; +import * as MSBuild from "Sdk.Selfhost.MSBuild"; +import * as Frameworks from "Sdk.Managed.Frameworks"; +import * as Shared from "Sdk.Managed.Shared"; + +namespace NugetDownloader { + + export declare const qualifier : BuildXLSdk.DefaultQualifierWithNet472; + + // These are the specs that define the nuget downloader SDK. Since this is a bxl-provided tool + // and customers don't have direct exposure to it, they are not places under the usual SDK folder, but + // deployed as part of bxl binaries + @@public + export const specDeployment: Deployment.Definition = { + contents: [ + {subfolder: r`Sdk/Sdk.NugetDownloader`, contents: [ + {file: f`LiteralFiles/Tool.NugetDownloader.dsc.literal`, targetFileName: a`Tool.NugetDownloader.dsc`}, + {file: f`LiteralFiles/module.config.dsc.literal`, targetFileName: a`module.config.dsc`},] + } + ] + }; + + @@public + export const dll = BuildXLSdk.executable({ + assemblyName: "NugetDownloader", + skipDocumentationGeneration: true, + skipDefaultReferences: true, + sources: globR(d`.`, "*.cs"), + references:[ + ...addIf(BuildXLSdk.isFullFramework, + NetFx.Netstandard.dll + ), + importFrom("BuildXL.Utilities").VstsAuthentication.dll, + importFrom("BuildXL.Utilities").ToolSupport.dll, + importFrom("BuildXL.Utilities").Native.dll, + importFrom("BuildXL.Utilities").dll, + + importFrom("NuGet.Versioning").withQualifier({targetFramework: "netstandard2.0"}).pkg, + importFrom("NuGet.Protocol").withQualifier({targetFramework: "netstandard2.0"}).pkg, + importFrom("NuGet.Configuration").withQualifier({targetFramework: "netstandard2.0"}).pkg, + importFrom("NuGet.Common").withQualifier({targetFramework: "netstandard2.0"}).pkg, + importFrom("NuGet.Frameworks").withQualifier({targetFramework: "netstandard2.0"}).pkg, + importFrom("NuGet.Packaging").withQualifier({targetFramework: "netstandard2.0"}).pkg, + ], + runtimeContentToSkip:[ + importFrom("Newtonsoft.Json").withQualifier({targetFramework: "netstandard2.0"}).pkg, + ], + runtimeContent: [ + f`App.config`, + specDeployment + ], + deploymentOptions: { ignoredSelfContainedRuntimeFilenames: [a`System.Collections.Immutable.dll`] }, + }); +} + + diff --git a/Public/Src/Utilities/Configuration/FrontEndConfigurationExtensions.cs b/Public/Src/Utilities/Configuration/FrontEndConfigurationExtensions.cs index 323217081..017b00fe7 100644 --- a/Public/Src/Utilities/Configuration/FrontEndConfigurationExtensions.cs +++ b/Public/Src/Utilities/Configuration/FrontEndConfigurationExtensions.cs @@ -33,7 +33,7 @@ namespace BuildXL.Utilities.Configuration public const bool DefaultForcePopulatePackageCache = false; /// - public const bool DefaultRespectWeakFingerprint = false; + public const bool DefaultRespectWeakFingerprint = true; /// public const bool DefaultForceGenerateNuGetSpecs = false; diff --git a/Public/Src/Utilities/Configuration/Resolvers/INugetConfiguration.cs b/Public/Src/Utilities/Configuration/Resolvers/INugetConfiguration.cs index 93dcf23c0..33ec05c37 100644 --- a/Public/Src/Utilities/Configuration/Resolvers/INugetConfiguration.cs +++ b/Public/Src/Utilities/Configuration/Resolvers/INugetConfiguration.cs @@ -11,8 +11,8 @@ namespace BuildXL.Utilities.Configuration public partial interface INugetConfiguration : IArtifactLocation { /// - /// Optional credential helper to use for NuGet + /// The download timeout, in minutes, for each NuGet download pip /// - IReadOnlyList CredentialProviders { get; } + int? DownloadTimeoutMin { get; } } } diff --git a/Public/Src/Utilities/Configuration/Resolvers/Mutable/NuGetResolverSettings.cs b/Public/Src/Utilities/Configuration/Resolvers/Mutable/NuGetResolverSettings.cs index b329aacad..ede9c39aa 100644 --- a/Public/Src/Utilities/Configuration/Resolvers/Mutable/NuGetResolverSettings.cs +++ b/Public/Src/Utilities/Configuration/Resolvers/Mutable/NuGetResolverSettings.cs @@ -16,6 +16,7 @@ namespace BuildXL.Utilities.Configuration.Mutable Repositories = new Dictionary(); Packages = new List(); DoNotEnforceDependencyVersions = false; + Configuration = new NugetConfiguration(); } /// @@ -25,7 +26,7 @@ namespace BuildXL.Utilities.Configuration.Mutable Contract.Assume(template != null); Contract.Assume(pathRemapper != null); - Configuration = template.Configuration == null ? null : new NugetConfiguration(template.Configuration); + Configuration = new NugetConfiguration(template.Configuration); Repositories = new Dictionary(template.Repositories.Count); foreach (var kv in template.Repositories) { diff --git a/Public/Src/Utilities/Configuration/Resolvers/Mutable/NugetConfiguration.cs b/Public/Src/Utilities/Configuration/Resolvers/Mutable/NugetConfiguration.cs index 4de7ab5b6..7a1b1559d 100644 --- a/Public/Src/Utilities/Configuration/Resolvers/Mutable/NugetConfiguration.cs +++ b/Public/Src/Utilities/Configuration/Resolvers/Mutable/NugetConfiguration.cs @@ -1,9 +1,6 @@ // Copyright (c) Microsoft Corporation. // Licensed under the MIT License. -using System.Collections.Generic; -using System.Diagnostics.CodeAnalysis; - namespace BuildXL.Utilities.Configuration.Mutable { /// @@ -12,21 +9,17 @@ namespace BuildXL.Utilities.Configuration.Mutable /// public NugetConfiguration() { - CredentialProviders = new List(); + DownloadTimeoutMin = 20; } /// public NugetConfiguration(INugetConfiguration template) : base(template) { - CredentialProviders = new List(template.CredentialProviders); + DownloadTimeoutMin = template.DownloadTimeoutMin; } - /// - [SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")] - public List CredentialProviders { get; set; } - - /// - IReadOnlyList INugetConfiguration.CredentialProviders => CredentialProviders; + /// + public int? DownloadTimeoutMin { get; set; } } } diff --git a/Public/Src/Utilities/Native/BuildXL.Native.dsc b/Public/Src/Utilities/Native/BuildXL.Native.dsc index acaff8cd2..22d11ca27 100644 --- a/Public/Src/Utilities/Native/BuildXL.Native.dsc +++ b/Public/Src/Utilities/Native/BuildXL.Native.dsc @@ -51,7 +51,7 @@ namespace Native { export const nativeLinux = [ ...addIfLazy(qualifier.targetRuntime === "linux-x64", () => [ - ...globR(d`${importFrom("runtime.linux-x64.BuildXL").Contents.all.root}/runtimes/linux-x64/native/${qualifier.configuration}`, "*.so") + ...importFrom("runtime.linux-x64.BuildXL").Contents.all.ensureContents({subFolder: r`runtimes/linux-x64/native/${qualifier.configuration}`}).getContent() ]), ]; diff --git a/Public/Src/Utilities/UnitTests/Utilities/ZeroLeftPaddedStreamTests.cs b/Public/Src/Utilities/UnitTests/Utilities/ZeroLeftPaddedStreamTests.cs new file mode 100644 index 000000000..98c7e7f78 --- /dev/null +++ b/Public/Src/Utilities/UnitTests/Utilities/ZeroLeftPaddedStreamTests.cs @@ -0,0 +1,93 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +using System.IO; +using BuildXL.Utilities; +using Test.BuildXL.TestUtilities.Xunit; +using Xunit; +using Xunit.Abstractions; + +namespace Test.BuildXL.Utilities +{ + public class ZeroLeftPaddedStreamTests : XunitBuildXLTest + { + public ZeroLeftPaddedStreamTests(ITestOutputHelper output) + : base(output) { } + + [Fact] + public void TestBasicFunctionality() + { + var underlyingStream = new MemoryStream(new byte[5] { 1, 2, 3, 4, 5 }); + var paddedStream = new ZeroLeftPaddedStream(underlyingStream, 10); + + // Total length should be 10, even if the underlying stream is smaller + XAssert.AreEqual(10, paddedStream.Length); + + // Check Position works + paddedStream.Position = 9; + XAssert.AreEqual(9, paddedStream.Position); + + // Read the whole stream. We should get zeros in the first 5 positions + paddedStream.Position = 0; + XAssert.AreEqual(0, paddedStream.Position); + var result = new byte[10]; + var bytesRead = paddedStream.Read(result, 0, 10); + XAssert.AreArraysEqual(new byte[] { 0, 0, 0, 0, 0, 1, 2, 3, 4, 5 }, result, true); + XAssert.AreEqual(10, bytesRead); + + // Read a part of the stream offsetting the destination + System.Array.Clear(result, 0, 10); + paddedStream.Position = 4; + bytesRead = paddedStream.Read(result, 1, 3); + XAssert.AreArraysEqual(new byte[] { 0, 0, 1, 2, 0, 0, 0, 0, 0, 0 }, result, true); + XAssert.AreEqual(3, bytesRead); + } + + [Fact] + public void TestSeek() + { + var underlyingStream = new MemoryStream(new byte[5] { 1, 2, 3, 4, 5 }); + var paddedStream = new ZeroLeftPaddedStream(underlyingStream, 10); + + var result = new byte[2]; + + var newPos = paddedStream.Seek(4, SeekOrigin.Begin); + XAssert.AreEqual(4, newPos); + paddedStream.Read(result, 0, 2); + XAssert.AreEqual(0, result[0]); + XAssert.AreEqual(1, result[1]); + + newPos = paddedStream.Seek(7, SeekOrigin.Begin); + XAssert.AreEqual(7, newPos); + paddedStream.Read(result, 0, 2); + XAssert.AreEqual(3, result[0]); + XAssert.AreEqual(4, result[1]); + + newPos = paddedStream.Seek(-1, SeekOrigin.End); + XAssert.AreEqual(9, newPos); + paddedStream.Read(result, 0, 1); + XAssert.AreEqual(5, result[0]); + + newPos = paddedStream.Seek(-6, SeekOrigin.End); + XAssert.AreEqual(4, newPos); + paddedStream.Read(result, 0, 2); + XAssert.AreEqual(0, result[0]); + XAssert.AreEqual(1, result[1]); + + paddedStream.Position = 6; + newPos = paddedStream.Seek(-2, SeekOrigin.Current); + XAssert.AreEqual(4, newPos); + paddedStream.Read(result, 0, 2); + XAssert.AreEqual(0, result[0]); + XAssert.AreEqual(1, result[1]); + + paddedStream.Position = 4; + newPos = paddedStream.Seek(2, SeekOrigin.Current); + XAssert.AreEqual(6, newPos); + paddedStream.Read(result, 0, 2); + XAssert.AreEqual(2, result[0]); + XAssert.AreEqual(3, result[1]); + } + } +} + diff --git a/Public/Src/Utilities/Utilities/ZeroLeftPaddedStream.cs b/Public/Src/Utilities/Utilities/ZeroLeftPaddedStream.cs new file mode 100644 index 000000000..40e91baef --- /dev/null +++ b/Public/Src/Utilities/Utilities/ZeroLeftPaddedStream.cs @@ -0,0 +1,158 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +using System; +using System.Diagnostics.ContractsLight; +using System.IO; + +namespace BuildXL.Utilities +{ + /// + /// Wraps a seekable stream to expose it with a configurable minimum size, left padding with zeros if needed. + /// + /// + /// No extra memory is taken by the padded portion of the stream + /// If the underlying stream is modified, then the behavior of this class is non-deterministic + /// + public class ZeroLeftPaddedStream : Stream + { + private readonly Stream m_stream; + private long m_currentPos = 0; + private readonly long m_gap; + + /// + public ZeroLeftPaddedStream(Stream stream, long minimumLength = 0) + { + Contract.RequiresNotNull(stream); + Contract.Requires(stream.CanSeek); + + m_stream = stream; + MinimumLength = minimumLength; + m_gap = Math.Max(0, MinimumLength - m_stream.Length); + } + + /// + /// The miminum legth the stream has + /// + public long MinimumLength { set; get; } + + /// + public override bool CanRead => m_stream.CanRead; + + /// + public override bool CanSeek => m_stream.CanSeek; + + /// + /// Always false + /// + public override bool CanWrite => false; + + /// + public override long Length => m_stream.Length + m_gap; + + /// + public override long Position { + get => m_currentPos; + set + { + m_stream.Position = Math.Max(0, value - m_gap); + m_currentPos = Math.Min(value, Length); + } + } + + /// + public override void Flush() + { + m_stream.Flush(); + } + + /// + public override int Read(byte[] buffer, int offset, int count) + { + int bytesRead = 0; + + if (Position < m_gap) + { + // Produce the padded area of the stream with 0-bytes + long maxPaddedCount = m_gap - Position; + int paddedCount = Math.Min(count, maxPaddedCount > int.MaxValue ? int.MaxValue : (int) maxPaddedCount); + if (paddedCount > 0) + { + Array.Clear(buffer, offset, paddedCount); + bytesRead = paddedCount; + } + + // Read the reminder, if any, from the underlying stream + if (paddedCount < count) + { + bytesRead += m_stream.Read(buffer, offset + paddedCount, count - paddedCount); + } + } + else + { + // The position is beyond the padded area, just do a regular read on the underlying stream + bytesRead = m_stream.Read(buffer, offset, count); + } + + Position += count; + + return bytesRead; + } + + /// + public override long Seek(long offset, SeekOrigin origin) + { + // Compute the origin of the seek in terms of the starting index on the stream + long originIndex = origin switch + { + SeekOrigin.Begin => 0, + SeekOrigin.Current => Position, + SeekOrigin.End => Length, + _ => throw new ArgumentOutOfRangeException(nameof(origin), $"Not expected value {origin}") + }; + + // This is the final index of the stream + long finalIndex = Math.Min(Length, originIndex + offset); + + if (finalIndex < 0) + { + throw new ArgumentException("Attempt to seek before the beginning of the stream"); + } + + if (finalIndex >= m_gap) + { + m_stream.Seek(finalIndex - m_gap, SeekOrigin.Begin); + } + else + { + m_stream.Seek(0, SeekOrigin.Begin); + } + + Position = finalIndex; + + return Position; + } + + /// + /// Always throws + /// + /// + /// Shouldn't be called since this stream is non-writable + /// + public override void SetLength(long value) + { + throw new NotImplementedException(); + } + + /// + /// Always throws + /// + /// + /// Shouldn't be called since this stream is non-writable + /// + public override void Write(byte[] buffer, int offset, int count) + { + throw new NotImplementedException(); + } + } +} diff --git a/Public/Src/Utilities/VstsAuthentication/AuthenticationFailure.cs b/Public/Src/Utilities/VstsAuthentication/AuthenticationFailure.cs new file mode 100644 index 000000000..8dd0388ad --- /dev/null +++ b/Public/Src/Utilities/VstsAuthentication/AuthenticationFailure.cs @@ -0,0 +1,37 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +namespace BuildXL.Utilities.VstsAuthentication +{ + /// + /// An authentication related failure when dealing with authenticated NuGet feeds + /// + public class AuthenticationFailure : Failure + { + private readonly string m_failure; + + /// + public AuthenticationFailure(string failure) + { + m_failure = failure; + } + + /// + public override BuildXLException CreateException() + { + return new BuildXLException(m_failure); + } + + /// + public override string Describe() + { + return m_failure; + } + + /// + public override BuildXLException Throw() + { + throw CreateException(); + } + } +} diff --git a/Public/Src/Utilities/VstsAuthentication/BuildXL.Utilties.VstsAuthentication.dsc b/Public/Src/Utilities/VstsAuthentication/BuildXL.Utilties.VstsAuthentication.dsc new file mode 100644 index 000000000..6238cf47a --- /dev/null +++ b/Public/Src/Utilities/VstsAuthentication/BuildXL.Utilties.VstsAuthentication.dsc @@ -0,0 +1,25 @@ +// Copyright (c) Microsoft. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. + +namespace VstsAuthentication { + @@public + export const dll = BuildXLSdk.library({ + assemblyName: "BuildXL.Utilities.VstsAuthentication", + sources: globR(d`.`, "*.cs"), + references: [ + $.dll, + Native.dll, + importFrom("Newtonsoft.Json").withQualifier({targetFramework: "netstandard2.0"}).pkg, + importFrom("NuGet.Versioning").withQualifier({targetFramework: "netstandard2.0"}).pkg, + importFrom("NuGet.Protocol").withQualifier({targetFramework: "netstandard2.0"}).pkg, + importFrom("NuGet.Configuration").withQualifier({targetFramework: "netstandard2.0"}).pkg, + importFrom("NuGet.Common").withQualifier({targetFramework: "netstandard2.0"}).pkg, + importFrom("NuGet.Frameworks").withQualifier({targetFramework: "netstandard2.0"}).pkg, + importFrom("NuGet.Packaging").withQualifier({targetFramework: "netstandard2.0"}).pkg, + ...addIfLazy(BuildXLSdk.isFullFramework, () => [ + NetFx.System.Net.Http.dll, + NetFx.Netstandard.dll, + ]), + ], + }); +} \ No newline at end of file diff --git a/Public/Src/Utilities/VstsAuthentication/VSTSAuthenticationHelper.cs b/Public/Src/Utilities/VstsAuthentication/VSTSAuthenticationHelper.cs new file mode 100644 index 000000000..15ff82305 --- /dev/null +++ b/Public/Src/Utilities/VstsAuthentication/VSTSAuthenticationHelper.cs @@ -0,0 +1,335 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Diagnostics; +using System.IO; +using System.Linq; +using System.Net.Http.Headers; +using System.Threading; +using System.Threading.Tasks; +using System.Diagnostics.ContractsLight; +using Newtonsoft.Json; +using Newtonsoft.Json.Linq; +using NuGet.Configuration; +using NuGet.Protocol; +using NuGet.Protocol.Core.Types; +using System.Net.Http; +using BuildXL.Native.IO; +using System.Text; + +namespace BuildXL.Utilities.VstsAuthentication +{ + /// + /// Helper to get authentication credentials against VSTS connections + /// + public static class VSTSAuthenticationHelper + { + // Constant value to target Azure DevOps. + private const string Resource = "499b84ac-1321-427f-aa17-267ca6975798"; + // Visual Studio IDE client ID originally provisioned by Azure Tools. + private const string Client = "872cd9fa-d31f-45e0-9eab-6e460a02d1f1"; + // Microsoft tenant + private const string Tenant = "microsoft.com"; + // Microsoft authority + private const string Authority = $"https://login.windows.net/microsoft.com"; + + /// + /// Creates a collection of given a collection of URIs + /// + /// + /// The credential provider is discovered by searching under the paths specified in NUGET_CREDENTIALPROVIDERS_PATH environment variable + /// + public static Task>> TryCreateSourceRepositories( + IEnumerable<(string repositoryName, Uri repositoryUri)> repositories, + CancellationToken cancellationToken, + StringBuilder logger) + { + return TryCreateSourceRepositories(repositories, TryDiscoverCredentialProvider, cancellationToken, logger); + } + + /// + /// Creates a collection of given a collection of URIs + /// + /// + /// For the repositories identified as VSTS ones, credential provider authentication is performed + /// + public static async Task>> TryCreateSourceRepositories( + IEnumerable<(string repositoryName, Uri repositoryUri)> repositories, + Func> discoverCredentialProvider, + CancellationToken cancellationToken, + StringBuilder logger) + { + Contract.RequiresNotNull(repositories); + + var sourceRepositories = new List(); + + Lazy> credentialProviderPath = new Lazy>(discoverCredentialProvider); + + // For each repository, authenticate if we are dealing with a VSTS feed and retrieve the base addresses + foreach (var repository in repositories) + { + Uri uri = repository.repositoryUri; + string uriAsString = uri.AbsoluteUri; + var packageSource = new PackageSource(uriAsString, repository.repositoryName); + + logger.AppendLine($"Analyzing {uri.AbsoluteUri}"); + // For now we only support authentication against VSTS feeds. Feeds outside of that will attempt to connect unauthenticated + if (IsVSTSPackageSecureURI(uri) && await IsAuthenticationRequiredAsync(uri, cancellationToken, logger)) + { + logger.AppendLine($"Authentication required for {uri.AbsoluteUri}. Trying to acquire credentials."); + + if (!credentialProviderPath.Value.Succeeded) + { + return credentialProviderPath.Value.Failure; + } + + if (await TryGetAuthenticationCredentialsAsync(uri, credentialProviderPath.Value.Result, cancellationToken) is var maybeCredentials) + { + var maybePackageSourceCredential = maybeCredentials + .Then(credentials => new PackageSourceCredential(uriAsString, credentials.username, credentials.pat, true, string.Empty)); + + if (maybePackageSourceCredential.Succeeded) + { + logger.AppendLine($"Authentication successfully acquired for {uri.AbsoluteUri}"); + + packageSource.Credentials = maybePackageSourceCredential.Result; + } + else + { + logger.AppendLine($"Failed to authenticate {uri.AbsoluteUri}: {maybePackageSourceCredential.Failure.DescribeIncludingInnerFailures()}"); + return maybePackageSourceCredential.Failure; + } + } + } + + logger.AppendLine($"Authentication not required for {uri.AbsoluteUri}"); + + var sourceRepository = Repository.Factory.GetCoreV3(packageSource); + sourceRepositories.Add(sourceRepository); + } + + return sourceRepositories; + } + + /// + /// Whether the provided Uri requires authentication + /// + public static async Task IsAuthenticationRequiredAsync(Uri uri, CancellationToken cancellationToken, StringBuilder logger) + { + logger.AppendLine($"Checking whether authentication is required for {uri.AbsoluteUri}"); + try + { + var handler = new HttpClientHandler() + { + AllowAutoRedirect = false + }; + + using (var httpClient = new HttpClient(handler)) + { + httpClient.Timeout = TimeSpan.FromSeconds(5); + + int retries = 3; + + while (true) + { + try + { + var httpResponse = await httpClient.GetAsync(uri, cancellationToken); + + + logger.AppendLine($"Response for {uri.AbsoluteUri} is: {httpResponse.StatusCode}"); + + return (httpResponse.StatusCode == System.Net.HttpStatusCode.Unauthorized || httpResponse.StatusCode == System.Net.HttpStatusCode.Redirect) && httpResponse.Headers.WwwAuthenticate.Any(); + } + catch (TaskCanceledException) + { + logger.AppendLine($"Request for {uri.AbsoluteUri} timed out. Retries left: {retries}"); + + retries--; + + // The service seems to be unavailable. Let the pipeline deal with the unavailability, since it will likely result in a better error message + if (retries == 0) + { + return false; + } + } + } + } + } + catch (Exception ex) when (ex is HttpRequestException || ex is AggregateException) + { + logger.AppendLine($"Exception for {uri.AbsoluteUri}: {ex.Message}"); + + // The service seems to be have a problem. Let's pretend it does need auth and let the rest of the pipeline deal with the unavailability, since it will likely result in a better error message + return true; + } + } + + /// + /// Whether the URI is pointing to a VSTS URI + /// + public static bool IsVSTSPackageSecureURI(Uri downloadURI) + { + return downloadURI.Scheme == "https" && + (downloadURI.Host.EndsWith("pkgs.visualstudio.com", StringComparison.OrdinalIgnoreCase) || downloadURI.Host.EndsWith("pkgs.dev.azure.com", StringComparison.OrdinalIgnoreCase)); + } + + /// + /// Returns an HTTP-based header from a PAT, which can be injected in an HTTP header request message + /// + public static AuthenticationHeaderValue GetAuthenticationHeaderFromPAT(string pat) + { + return new AuthenticationHeaderValue("Basic", + Convert.ToBase64String( + System.Text.ASCIIEncoding.ASCII.GetBytes( + string.Format("{0}:{1}", "", pat)))); + } + + /// + /// + /// + /// + /// The credential provider is discovered by searching under the paths specified in NUGET_CREDENTIALPROVIDERS_PATH environment variable + /// + public static Task> TryGetAuthenticationCredentialsAsync( + Uri uri, + CancellationToken cancellationToken) + { + return TryDiscoverCredentialProvider() + .ThenAsync(async credentialProviderPath => await TryGetAuthenticationCredentialsAsync(uri, credentialProviderPath, cancellationToken)); + } + + /// + /// Tries to get an authentication token using a credential provider + /// + /// + /// The credential provider is discovered following the definition here: https://docs.microsoft.com/en-us/nuget/reference/extensibility/nuget-exe-credential-providers + /// using an environment variable. + /// Observe the link above is for nuget specifically, but the authentication here is used for VSTS feeds in general + /// + public static Task> TryGetAuthenticationCredentialsAsync( + Uri uri, + string credentialProviderPath, + CancellationToken cancellationToken, + bool forceJson = false) + { + // Call the provider with the requested URI in non-interactive mode. + // Some credential providers support specifying JSON as the output format. We first try without this option (some other providers will fail if specified) + // but if the provider succeeds but we can't recognize the output as a JSON one, we try again with this option set + var processInfo = new ProcessStartInfo + { + FileName = credentialProviderPath, + Arguments = $"-Uri {uri.AbsoluteUri} -NonInteractive{(forceJson? " -F JSON" : string.Empty)}", + RedirectStandardOutput = true, + RedirectStandardError = true, + CreateNoWindow = true, + }; + + return RunCredentialProvider(uri, credentialProviderPath, processInfo, forceJson, cancellationToken); + } + + private static async Task> RunCredentialProvider( + Uri uri, + string credentialProviderPath, + ProcessStartInfo processInfo, + bool jsonWasForced, + CancellationToken cancellationToken) + { + var failureCommon = $"Unable to authenticate using a credential provider for '{uri}':"; + + using (var process = Process.Start(processInfo)) + { + try + { +#pragma warning disable AsyncFixer02 // WaitForExitAsync should be used instead + process?.WaitForExit(); +#pragma warning restore AsyncFixer02 + } + catch (Exception e) when (e is SystemException || e is Win32Exception) + { + return new AuthenticationFailure($"{failureCommon} Credential provider execution '{credentialProviderPath}' failed. Error: {e.Message}"); + } + + if (process == null) + { + // The process was not started + return new AuthenticationFailure($"{failureCommon} Could not start credential provider process '{credentialProviderPath}'."); + } + + // Check whether the authorization succeeded + if (process.ExitCode == 0) + { + try + { + // The response should be a well-formed JSON with a 'password' entry representing the PAT + var response = (JObject)await JToken.ReadFromAsync(new JsonTextReader(process.StandardOutput), cancellationToken); + var pat = response.GetValue("Password"); + + if (pat == null) + { + return new AuthenticationFailure($"{failureCommon} Could not find a 'password' entry in the JSON response of '{credentialProviderPath}'."); + } + + // We got a PAT back. Create an authentication header with a base64 encoding of the retrieved PAT + return (response.GetValue("Username")?.ToString(), pat.ToString()); + + } + catch (JsonReaderException) + { + // The JSON is malformed. If we were already forcing JSON, then that's an error. Otherwise, we try again but now forcing JSON + if (jsonWasForced) + { + return new AuthenticationFailure($"{failureCommon} The credential provider '{credentialProviderPath}' response is not a well-formed JSON."); + } + + return await TryGetAuthenticationCredentialsAsync(uri, credentialProviderPath, cancellationToken, forceJson: true); + } + } + + return new AuthenticationFailure($"{failureCommon} The credential provider '{credentialProviderPath}' returned a non-succesful exit code: {process.ExitCode}. Details: {await process.StandardError.ReadToEndAsync()}"); + } + } + + private static Possible TryDiscoverCredentialProvider() + { + var credentialProviderPaths = Environment.GetEnvironmentVariable("NUGET_CREDENTIALPROVIDERS_PATH"); + + if (credentialProviderPaths == null) + { + return new AuthenticationFailure("Unable to authenticate using a credential provider: NUGET_CREDENTIALPROVIDERS_PATH is not set."); + } + + // Here we do something slightly simpler than what NuGet does and just look for the first credential + // provider we can find + string credentialProviderPath = null; + foreach (string path in credentialProviderPaths.Split(new[] { Path.PathSeparator }, StringSplitOptions.RemoveEmptyEntries)) + { + string directory = path; + + // In some cases the entry can point directly to the credential .exe. Let's treat that uniformly and enumerate its parent directory + if (FileUtilities.TryProbePathExistence(path, followSymlink: false) is var maybeExistence && + maybeExistence.Succeeded && + maybeExistence.Result == PathExistence.ExistsAsFile) + { + directory = Directory.GetParent(path).FullName; + } + + credentialProviderPath = Directory.EnumerateFiles(directory, "CredentialProvider*.exe", SearchOption.TopDirectoryOnly).FirstOrDefault(); + if (credentialProviderPath != null) + { + break; + } + } + + if (credentialProviderPath == null) + { + return new AuthenticationFailure($"Unable to authenticate using a credential provider: Credential provider was not found under '{credentialProviderPaths}'."); + } + + return credentialProviderPath; + } + } +} diff --git a/Shared/Scripts/Init.cmd b/Shared/Scripts/Init.cmd index 2b67c8fff..78dff39c4 100644 --- a/Shared/Scripts/Init.cmd +++ b/Shared/Scripts/Init.cmd @@ -114,6 +114,7 @@ REM ********************************* REM We'll conditionally set the credential provider if not set on the machine. REM If not set we will set it to the local one in the enlistment but iwth the b-drive substitution if NOT DEFINED NUGET_CREDENTIALPROVIDERS_PATH ( + ECHO NUGET_CREDENTIALPROVIDERS_PATH not set. Setting it to %TOOLROOT% set NUGET_CREDENTIALPROVIDERS_PATH=%TOOLROOT% ) goto :EOF diff --git a/Shared/Tools/Microsoft.IdentityModel.Clients.ActiveDirectory.dll b/Shared/Tools/Microsoft.IdentityModel.Clients.ActiveDirectory.dll new file mode 100644 index 0000000000000000000000000000000000000000..2a22068cea23bfa6b67f9cf841533f81f42ab5f4 GIT binary patch literal 998464 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

Lt&xtVn*?lj;eElL?8y6=%9~ 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

b~!sp?2N; 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

-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�n-r7%61ZuG)+A$&vsdSF&40HH3H09%JIJ3Rs!Lvny>CkW$inXuP3)it$Zn&Q} zmh?7qj7^=xZUWgy%fx70~CfydM4f z2d9-E7Lw7<(9az&1}|t8d`)Xmg@N+8{`n10SA1AWOCgO34OA{j-Q|WcVgk^i-pdYQ&c;31Yuz`;S1n#zt3E2>_GgHXJ#w;31vGNiO%C5hl zFdNXF$p}?j9?xXBOF3|Zb)!&~Y)tmNBgx)S#r@mXi? zw1tz5Fm3n2j-!$jVZoFwvfr2p6j-f)!F%kmZCB94O|zU9r>`C9xp{$TS(VCL4=ZpX znqBhJe!eJpHQ&7jJ=y&$=6cYB5-i8r20h3{E*9=5^INij5DaCv8l^ZTRT_UglUhL4 z4jBq~<~+*+I@UH~Olv=76rLbigLV@YOm6mo!oX9(3ei)=e<;bchCBn(XNa2BnuzQYM2QIwFyC7Xx?eOm&9(vCC~d zZ+&k+5TREIDR-Ns@MlKiobDK+m)8pX4}JU4gYn37w%c=qe%OdITf&D`0+*-jlO-cQ z`la>bi)$8&&@cuh6J3VVCT6~i9=986)=`~}tEwQ_2Q93>x?3A(d47*=2I z(LEa>8RxuFf_39q7It?>h-OQAYPlbgvck*7=yJajLOsmy% zr}7KyG3}Zik_V%)E2oPR1DvuQ^tHnm+uJz@LI#!E@($w;YS=HEaLy=JYnZRIav1JS zSCNkIC!d630h}QQEkH01-O8gQ!w^qr@1eBMg;W+NHY8}A^ecFQD&tL81h4CEbQw>@ zKj9IKf#F@~9cd5ge&(}~5=$TdJ8&T-Jz^>(yK=59!!@^B1`|(3rQD2+jj!cSdlrr- zXI7@L8kZX!9+873HYEAhNZ>(fClwT{aiO!))?x??Dh98!xg^Y6t3a3sV*#&N>W8S( z`kHDm5gZKfblXgB7mO}{`ZK}kWqO}!9$jM% z@y?%$u)TRO8f)E!MBuGvg!qv^GF3mG3f~JH@;(?CxGSeHva33nqO1inu9j>X_+qM# zDKcJcQYk``LJ)cNJW$I*RGrViCA@El6^L@FY~_)Uk@D!MkRdTS>yIHm{%0EE-DE$8 z9Fn7wSGrHjIY2ffu7=lbVoL`vYCAnOw1b}62UkcT_wg3ca>k&A zeC;r^fUixTJ^d{F4*2eKGVIQrAyvpd`^P{b-o8Olh;MdG6XI!i#fNw}g*(K@8lxc| zcAD3>PG3;dZ3op1WqV=TJ>Q|XU=U{xIrqzP1-0!rNkY;n<{h1j9+Op2$-evT>=9zd zMAqx%YpTKK#yJ$yYyLxYtaUY>hG#g8rzEBA3n@0Idb3tiNP1{LsBi9i{&<(PwophE zUOGbj>_UJok--ep!+Q#Oc4Vw6J3!MI64dU+5Al&DiO~?b)5_);79nbC74$ZZ1TWbU z4-xXBCwnG?%B&@kFS@oH^mO`&aWs~tdE1T|1Z(vNV{i=ELf*?b>06d;3;8>%Wx;qm z6Fq4@*cd384io1_Pzo;2d=~&g&F~l4|XkghsP}pzT=t!t%c2}WJ zUTGfkIf=lf9s7H zoRQB0HID@&&>2RCuKJk5ytO>_G805$l?lRviUmBRH4nz?_F&<@wp!921q0?b{y~5H zfns(Qa>Rpu1t6#+lR)xWub_`x;Jn%qRME4s+UZaEjzZAaSTg3YN-d|ZGJ)XFD+BSVRemeCD7yd`J%R#Uxo$GZH==B!m}Tq_Zg zn<(MkX#kyG5J6WuIViu9UtKBT7=_DEcLLH&v0{&hn~I2h=>V6^Rz>Jy3Ve54w@b@1 zY{b7N8=?5Ba0M^M_3{CTVRhLd!xhv>ch;tL->+D$hpk|2(JOKG9_(&N|j=&iK4| zWRBjTjfoAiXgSeY1$QdYzGx;*$`GSIcP?K({pRt*&MI7FM0Q+vqNWWsB|;Mw z+$W)hO7>-H=8WerDVMF<7^mqMWHnWg*rTiDCWa3_4cbIetyP2(KqM zkv^Y83$-+&LnGGr03C+P5l@=(tcwv?*1@a7yoZ)`lhL-BUDlTs9xynNb+BN*Zge>7 zmfLb{gRGD~JYx^-9_l@iuOm}ivu8^=FU9x-IW^NK=fXZ$&S_LmB(iH&mpX@hhv-HK z7w(~@M?R#eQ<0GlSpjgSG$P$2K1aN_moM-oBEeTAzu<>w+?LiB8)r|hHXe4O*7N6Z zCjIVxo>+GA%PbY$JWCX8i*;^TR%PgTWqZGTFwgOm`y%&!!v@bQQ`pO1pg=fYaPUR$ zuJ~vv_Z*s?VS9&FEp%5gpD46zNBU(-r)J7y;D8J|&7>HtTI}Q5ZN?FbthfB28A^dm zyjD*qRs!AsLc0Jp6f){06f9K+U6%E30(l3+eC__xYOy9Q375F0FTTa|^ zuafpS8ccVvLsidcb`QG@TP-kHhkE1b-pcC5oH5)prlYUrvL4HeL-K4o3dn77D&VO{ zv2^g(4z`#?BDbj9y){29X9wbzACj%$($7M>?7nXeleZUKL+8u(SXkZNZI5QsFp|Ua zDHK)q9MYb84t=HFbMZcz6T;q;O&CTI6R-9KnNCatja&LSjaM1DtL$zWmHV7o`@~b0 zEm>X^o`YlI7%j5Z!jm{}bmx2oljrOCkGSz5Y)vHC{gmm~c-2Vf6Iq^Mym!O%7m3^# z(48?WCoA&(S100rmvQVpyU9nd8P9*uP;*N9UGG*shvb+yo2(g@by3BsP?Eu-MY(id z$Wt|+Q_KjTGm}-+&xi3??Z=NKCb|aKFr(qmF40S~9uX@mU*<{@2P_p8-!4Ea$ew|! z{*qGXxE*y<+q|_`M_{jz$d69liA~fp8WweQNXIJ|&8EQ-_*3DCIx?=dTwa4oTI^_A zox?h?R+hN|8Dx7}i#aGo9k#s7HwM*dzl()IBB@{}k;9F8oObj~sHy_zAu<)$Bzrp4 z?etTw(?-^&$2R&5b2o0sV+2E7McqSkQD-Zh*tAlVWui|$q^Bjqd4EESgUi#n$ii-d zc}hK2!0Be365zv$naGV>g^O zQBs^;0awUT$cAoDrZc&IS`XZSHm$CUXxioNU)OD)U#`Jh&=U4{!EOYDPL@cQD;v=m zRO#27-IvLAkmVWmwh4?oC#Tz{PTGU4g3W4%S7DyK{v13?GO{F*=DI=4Yk`b<7if1B z;`;^dvO>XqkuNCF!7Y%5Hyhq79P(T-ZYkny0B}5g1tiRSt<*~Gj(LZ`MkjrHK;$$N zj*5hGZ8{sMTibj&^EV_nzR2yU5oF_%e#C30tf*xmL0#tdd`|f;opnlba$YmiN|-AV zS0`;5hX7%>*i#K8wGuYF+N%M5&h8P}j%Keyw#vI4ZXo~5NlqU?iEvI~gb zmzCNQmfZ(nW9uIBB9>q>4YA*XTKkEP`}E9*RG_JDCuBrisL z4tqSW=d>l)bGk-@C+HN5)^j;ycF*k`!|AzopgA1Z?^kMCrKimLrkay$Wf06}BTr~Y z{Hp9;+@7rGX$-kHZs!fO60OIrk-SqB%C+w?L0Cw zD}F;8r;{F;WR5uLQC=#EEjR8N0RDh{rrz-sJq}1rao8GDI-HHgfLG@_^(_TYBu~(h zQ0v4c&%=?(9c5pW)D-7RB)@YdJkVT0cP1x}uu%mzu(sJ8f0m&sTh_-SqqPF$mpn?z zQ4+A7Njc-fw&wDNrftZTlf)~NJu$%^u^*&!F(vIf}NVMmfy-Bz71ihSE<9XPdpdNV= zFBW-Tp495)h&)BDOrB=;1=hU!u8GP%UN3+bPlz8G;0*giJV)Fo(G$*a_qUqHX2lAd62xDDMyj@TZyFJdy8MoUDn0I zpMASu=Oi%X=`LBQ)S*8k5RH*Wo;hG$V^_DcS4(+WKtCz`pWnDcaySW8t{F6N@ zK)x5m_os%O7jRW~kb~eb8>QdOj;8I-DeodwbE_c{dyY|8s#zg>wl#pW<4k!H!C<0y zv`0r65xciSw*OepyMWJ<%R84qb8j5)UZ$X(p>BRiJSmW+r6tJ?yRG$L!L;?DPV%1Uk!EyntE za^*A_QY0dSt+BUN;9caNtHJ{ z=Sf*I%hPk~n$GL$Tu>V?Lg-=68c(;hx88Mh|2|W98Tt-~@7$QAJM2nvD7nlRL`I!o zon%*uB+#7<(A1*pxt-ku7^$kuM3M&d{H;OjIl~8ko;SrR`+}TZ{$x1oMxNvAlhZ%R zU_JW5Dl0k24iV*-4Y^z=GiZ*Gj%JO7>1dL#9bmMNB$hCHC?d3S+!?>8 z+*tkz^=#h2QtRkzWebGvGSWKi9NI&1$$oj;YO0>5Py#R^o1g$ObKxvHrX?R_J4Ix~ zW%LQFNLKyWtAeLQKss5(Ri_kRzccI8o#8k{e>G{-#d11QRv=`8icL{gLJP?%y52$y zt1@%b=Z~?z!Sf^!~(P-11pf>t4 zM*2Rzgfe?$+GUro?Dbra>|&fNp{oy>^W`HJ-u5Ncl*@Evd}9`Gx0pOvRY|)HMT}26 zvKNu_(!9XF(V`~R@9y>u9r1K0_Pww=6Qr)ByF1A9lVvz{IIDZg%U0MlMi|eCB^nhm zRqCH>RatfhQJuDZK+&B*RH@sb`BapZ9FY|}b*yojmi`on*(_n&offet>3HWXvuXg} zHVZE{Z-GH2+`xuhi8qw+LTGR2xpJm?vR+cY3wU+s%mZbEP=suYmKE6okaeSyb?nbG z>$B&wd#T9|qOyA38{Cttm?)F7n6r>C(~8cXnq_?&kM~6MvrE~i{fAs>X|m%91{$hk zXP$Cpl77-mlUd;OD~;!WXpF9r_}vyE_X52+iPE`0G05FC$@Q~?yZ^`D+rC(OWO-sw zA%qY@G@=pBFf^^1o>}d@baqSXm+9@7B~?`_UA3xGs?6%@wx-Fwb@OIbN?Ccc@6A+I zcJJ(z))-^VVwPpuPm4bovn*yY#w^D8lQI72PyS%`zwz&Pe&t=f#U^4 zGm|YX*EF)ji3+{BmU6LTlS{8y#2JKh8D3%UB?O9*TLNon_HkzOLAh;7hYFU)s7?!# zVRZ|eHktTHhPQ~PBL@*=g}MQ4vE$5l(!y%pxlK9Xz{3&RJUj-ehdnV zT4J$mv3Y?H0Ed5HU{*H*rnuNo$}x5YQ*fs#NGg+p_sre4)eMuD1EUAirRv;kgDkfY zQOjXt5M)(l^qv|r;Lo`=p(|}>JXa6$)52Iq?D3_B22iABi#Bu06ZVov-X_AhQBZgH z!F&lB_F%SLtQPwx8zN07XJ&rFCs|}q0o(^c#Kr)z%6uh*?=RYDv+AfXd*h}AxFoy1 zW~YVll5;{S2NUofj0SM#%q8b*m8b;SjD2JTdv+DpQ2gew#W#7)1FYZ(yQU(7%tkZ< zV}1nLLitsenaKqR3qx^Nr^i-@^Sw~N(5JppClJj}1c%IXXDQx>2F>iv3}iA&2m#Ab z8d#Ls*AzCyR0yP#HI8O11roPu$PxG}5tfo>QgU2kLE7--pdN6x#`@M^$wEReq}rf3 z4L*XXL}jCmuBNX9;i83CA`_I>I1lHr5<-T;j6!gPH4z{tuG(|NDs5liRd0@bF44(**!M{tibGZ7 z1Z=P}bW3hl#U`fI0S|_*8nJBX6NO`e6pve^FM-G8tR#$sW~ zCo9~Ct3k>K?c+&1P_)6UB~H*%v#^KRWx0|fG7lo0f;c5OvE9AoN+p69p`Y5F#bO)i za#)h=o*wU^3Felu04Z5wW}V57R(e%nTwzQzjJ_6z$T-MP4w*`!<4wos+_`%(h>&Sf;YZ<06<1M?z=!-CH5j3c&Q4Ij1 z^+!LudL3<0f~jt0m2lacYJqmprQmjc{k=notOOA1bRMNm5A`KtMtMPDvTr1L^QFSO z_j-WD94LieQFOheXPSwzRp`e*eG7L|IDp-CY(}U2D2|KGu@$uBWUCIru{HFL$#9*` z2RXTMwxP^nzMlfGV&fwnBMU4XYXuhcoEB#=j#&Uvu-51=@;;3o1uo#G>72@o)Ev*Wz za|hNvgX`oq5gJb}x%n}lt~$N{pyuKl&_NweWfOeIq~7;PAn78wW`HbO13*QLl+FPH zk15)a(`i!4H*y6H2>T#82+rot9)2DWBGGK|I$ z#*uZ63{fJ?Sn;57nM6(MHLPE$Noow*JqD%`a6c)r8w;opCQ^@p9V_~&iDKv-tyrL> zEe)IvL7oy^6L7Ys+&Z#-sscP+@Jcn}y~FAKRSk;H*oZEPp!6zIU0ocX!F|kw6m|8(Z6o)TIco-^Ks6ZnM^^Q4dR8Mi6-L=@ zJFalf#Tfh%tvz~ajdAF~u;a3~Jt(i3>QKGbRJ#UN;3zeX`KykjX7CeQb{Zpp4>x^J zdbvUeQS(g8NV3DQT7aQh$Ky`_WV6f=KaPQW=GTg2DylBlB(kV$yqJ25&G|^b9~d?3 zcJ#yA^~C|!7fUU4fJ>-?^@Xw2hnNF9@Fa^2JEema_C-aCZ3X}LQkHG)#j{XDd6 zX#zi5o%SG*p=c)!B<8xIk-Adqs7c=;EhrRZ!_Y>c*nm85CD;zIVYds=O0OOfYBqx4 z)_6HuaS(Q{`=v$!9zgln0OHQ0qRk{wpQb#~rytfRfW--eZGC%3P0HO_fa(j3Rd{Ru z_+)!FJt_c8qtFR8s`>;b>4Qw4zVO%s`y$FE5X#Fzq}XmD56ucsiJAEpoC&$ly@6St zQr(1bHsvlvoG?S>lQYRtinsaTAUh<=+P)oN&Om^BStL{xF&0Ew0g^P(TMxPJ zOi>?9;o)}A);s!`i`6%}sSg&IH+thf8vq|h4uN2=i9yMZmjif{4vVV^vqT&)8N1d* zurb%6;BJ7sd%7Iu?Onip;>bC2ft(>%0HXloirTlHh}?U1#CrRbBqz`Udf9Y;QKSt? z^Ke(K$fLP`z}89-Xr=Xm{x=k*l2OHjG%Y=;4%jg}K{S;@C(zyL=M;0KZi6iCy1RY* zG>@{>p_iX)P&=m8#k1p~Fmkdc{iWZ+cxWOaU`ib{Bn^!%i>Oy6K5pO!F{*-w6;7fh_pR3v}@ zyR^8npmrkrETf!;xpO#hEMvbaQ!m0BfOf#p z<->+40kOPxQC_GSNfnVOB|xNQLFFqehTU>~jp22yIyd2wGNbi)nbM_wGo{Q>p~6uH zv5{CZ85HI|*k*CagKnb-{Gq%L_e%R)`@j|)7{ca!wL)M7Ny_Ttsx<=U8N!?C1j+Wk76{_PcK>kct)HMt~K_ z-`y$x_^@6(m_ka2mxkGD1LmzW6cSMoTd`&dxV^neRVh4Hz*1@oYhb`+-3-T0)aT)J z(16z;gPVzf*FgLBjX?SC&dz&(RRU~S2@q9EKs=W*4LAoqc~Bx)S_#bQTY-&%_T4v6 zo(&O#R+eKyGb|%;Y5t*x@L(Ea_bC~+_&g3gk)50s&;+Vdm`@Gh>Eb2QQ`9*rx5(-aq0rln%GNO*SL3_?o;TQnNsm5#=_52apF z(QB-d)v(JgH21fSNu6yYtfwuAHNJPaFim=|$`NqXITGcSj>PQl56fq@RPP((){Nv3 z8r<_RhNYOpjA0ZfWlhvB#EAQLd%dllr4g6M3mcCyG#_U0!5BvD9t}FpYCV119>es+ z)t6z4`5lXEU2@ksc{@~ysUB%5;c0Czl(;7o@iaMS6mfyqlK%!oiD{-d41^I49a`J0}H9Y}OXe zx=E&WzSq<_0`|H_VvN@H3Srqspn7m3$r#*AABz%E>y^XuV{Z!;VJ``*dP)+n^(m>! zmbs=Pwgu`&TA($9*oOfD+C~cc)8BK>@a2pMdG=F=Hupg1dX?ZSC2eS%a7a=YXAs z1Ue6D`v&$+9S}Yj6Ug>k7VJrk3+1UV)r3-ysF(mTZB`{(tK>ezGi^dZqiZ1#lHQbn zJimf7^hlP*WKPogW@@-QXVD@*pL1D-(wh&B8CegF*v`;CyOcmr`zbOOtZ@lNJuKtwM%u z4xv`mKZyy3Gn%%YMGBxT;}A|!P@ldB$2 zVp3UPTN6`8fhHYhf9P4v{T7sPpk28Tx5;fl#)|LND|a3lm$!y7(qd@E4YFajNOmcj z!%a0t+nea6a?o!>CH>gL&{y)XEHwIC%j>-J=#dzj@dzj@R+_gxb1FnK5XS%}d}|tc zyTrEI6pRhYroa;HYC7y2!wA)WbM)K+f&DO^#kmRxH{UWe@>R79)8Zhj+)iiM#ArA4 zg#FHk3&6ZRkfPm2i3UKJH5y)l$%MAx5K%a$4vL)h2X?+kJITk_j~BBC^cV)a;B9zb zL%{SMb2<%#neEZ7g`JE*)1%+(^klN4q|d>god}v-sDhn(NcRd|*zy^1gR0{}iAhfZ z-^OVKZgic1+LY+9=EWXl58jptn(mc=y_X9b2l5Fe)IMDFmnhLmZ5N@%1KEEtefxXg zXG6k?a{@pqk25|+>RY&E5H51=^>zouAY9=sglX8m7Rq!(=(H&d*h(`kD_06dYxABB zGBEHFoZ@an#rB}%MaJ$uyoUP#H$F}tbRWdqCs9FIzr{)GhP%VvGk?>RUW z>)dupDC8WnduUI5gRlt8XkxcKF@$qhSsa?~+Vl)p2XA5$A9N4xFFSp0evEJ#ZQEq5 zmlL6k;vIk1CN`zAVtphP;EKTzD4>J5*&H|I_6jgI(gMJ(Cr`g;O%or+qgJ0jOE;(0CG|d;3!Pj7&~j<+*ST+!_FiepBBQ#1tnn$9h&otF@`6Ru>>rSu9}oL z+pTD)XcZ{RJ^)YqneR-G?_Pg5Z7$|d7Q_ul0N{v?sm`&t7CCeSFI_BwKg%sxikJO~ z2bI3-X6Q1dU`HJ1qLV3jia~&%fzP1T={|)DN7x3Ed=GBatiM=P3T)B|KncP79ot;O z*B|5X^aSs~$|9~0FJU$Z3_=NWwsLqv)7cEz16OqnW%lfi>?A-e?OYfKeL&+Jw5u2b8Zs01(t+xP@!Ov6ApJH zYLhnrG9~>~8t&0_(Y#jjk|tm${KFJz!1U0Z2=Us)b+nQ<135F;>}(Gfo&e9t-T`bx zsRqekU~(e%v<+BUPbL_{-z|=JKjbCV2h$_ST9g4W zi)bv4P!&?e1F6=uH*d^ zd=7;s!^92I-qpq?Zs&fE>uMB+@dVn2w-P2%8<)+x+}n7J8n@3L-dhM&{pJmDF=T4P z+Y#_RNYeA=M+?trd!L24h-+wfx?E1rN;1r!706!_f?6<;)UIztit!jo?$o4?NA6>5 z1G|pK=fa%31;rz=VDV4{*k#3NL_Dr#1_73WeHcRH?X8-w?Sf{8Jm;_zZJd}!yLxzd z7|oD)C#_5r(1*b-kGF^QZYo0Ylxhc=O*t&Q(c!c=8J7}BLn!2B%ljjwuj-Hz$ zb@se;&(JX2dDrw)4LdhQYFJ4}&Wa`aZl>AcslL8I99^|vu93sn+!QY!?PGny$sDBe zHYWLi8AQ+_Lj`IVXgsW2rM!QM2g}qdzAI;+ZW?CaH|8hU{=imSh>Q!(k|WA~x92DJ z3l}u3)xNQku>siU0ZZrXh~$$^*@C$d$P%mr&u|T2vBjOMk;58-Jcpw`DoiVk3cng^ zZdBVt;3Jp#1-C)G?WaZp#hCK}@lIO`H42K{p1T)>?L)-wz(RIxJ@NWJOi6Juy8G}q z@4vtMkaG-QC}16}31@V-Y+OE3Uh2~xwU1pjVJNC|2QIVH}HR6akzx8p_vzc6%g z+yJrl7L_gV%wtfNJ%Q(YBskCywrcu?DY39f2X_GVl{Y#kt}yeoe>RO@+CWqY*xCZ0u}$#A!9PlAm>UJi&}_=M#G}bHsANY_1{%N$bXv^5~Mn zRu@v28`bkD8TX#}EG>WfyTt}y2u61$d^iqYRE$kEa zm+CI6;DeG>B><+OTu7*`&ikVcTLVxV;|X$*eq(f-B<=7vQ5@q2a0guFF`0nfm4$vvJ4HG=8fk;d4aW{wQ8 zH_Abf>JSVa9P@^={D>5%6e0H^6Tw>xn_{T}tnrTg+t`((@7O@FCzr0J;D^(P_x7d< z0F9fNfSQGuQWwy9;;LdP#&ppsjQT?#nxG=?>{$b(VU7M41^=&lmsEu79`Le+8CrTNu~@B63}-+^B|JIWKv?BZN->W z0DX;=TQM8drIYp;nw0>$x{F(J=H(IM33zp#r_`kDWA7Z>AtD$rdIh8s056rF(5i}? zJ*!H@)X$}wXeGJ#RhGkCX*q0;@ltv*Y|udE zM6gfpm3VeEeMo1RdwSwW{n_0c1#=Kx;z1{PbHut;L2-D~0|V=O5a!jq4>R}S$lV7m zBzB<@Hm|UyfCmOKzG*^-V5X)_2-&ZoNDjl|p+?%d5-6vVhWYd+iK#$FSM}-4-HpS= zJz#~-Dnok`W{{znSB{~)BXv!iiVc=6a|`F>kHK$*N64{Am~WCcv?ba4fkj;SNRufjzwUHJY?poza-n?N5p zA8>~43MU;kJGlmJ9XuCE5%yl1pEPbQaXJd!Af?ij1Pv`_k_n9Ee43MS=&MKIl+gR` z`*Mo70mmW7Da=M{=Kv$0;M{v_S5({%yc#Xw6Ew##e+)p%Fspen-KJ@@OK;Ey%AaG9 z7cd6}R8JFZvQ#Pa(kmus^cOB_Vw22Zj>341iWrZ>5RXS3OP=jj0_4JCGuq4(CI2cu z(d*GzxAxGiqidZx&8>$AY9JDJzt>a-`#9}M1+ssoBGTj(htYL?+c3fxHSNpV96g9v z4JFJ9C!%r0C$i<+k!@75`@pR-oL*_48qtY}MofqqL6E56<%Mqz-#W6=W?`?JY=^lF zwDrW8*iz~eK1+BsQ2;lgVJiVYqAp>>+h~xnv+!vbVGL^d4sWj&a2(0V2I|tHjTMwD zI!Cj?sv%Y-I#6LeZU@f`iG#Y3$XE86VHBEl2l9{J$f-F%84FV7k^tweSQDLUYApvC zpu0g11k)NxpF)q;#DN;1M0503GqC%h(>&IwK(uoJQ?+q;wRL*3wGT6e`zaTTG94f& zJIHSn7mY5WAQ8P*$gDi34Wr67CWYMAjE7?t3L;Pg7>=#|Z9A{1KtI1JQ&VGXUj3-u z_RAV&Ljx~IaMMePXp=rgh5R)Qv$r7%mt>0r9k>GQh^~STcw$$BF*Y%w7(UtF)g-LO z7D~zn4iToWHO)5dkfT=2pu~*|im9uRot81bN>y}?^)VCU9p%nT4eVFgPm`>RODrCn zxHW*K#+E(b%gLBclHk0iW!?c01>}r)F7og#%3@|0YiqTJSU?RClWNFbq^Us-OAXJ= zM`I07OBGOM!3-bn&#=3(hZOWo65!Pugqw$;9cF%h{jp{TX?m%D25ai3V{@37>mG(D zT1QQ(zR)?deFdw7iGs3e1B=wmlnil=Vy~m*rd=l%b+DMXr{~QDQZZMtD8n%Os%=&t zUQ$TrC+v(xgtd!oAPP9z1$CGuQ;qKBT_Et;Zk zXx(rTABtCVujc{xa&N6LF>+^N;}G9fSIl7|{|c|x{KV7=@9;~cbiy`Xyd~?F8(5X<>12J8Nxr~vS;aH`7^+gT?%?3#5VjfkqHPR~E~P~= z5Kupb8kT9@3f^c^ZQwkQe3g~94dd+iCVyo>YNL74-2&yw%sNG(76=~R(zz3G`z|{H z{j%|ng`hYyvX5BfMtck*NzguB0JLvnF)6YIxPD7OF2i>4EE&ARVYNh};07$m)L8=y zoJNwOO)@Z1_aV*HER=|eg=h8VtA*Jh?E)5LlTwheaATApOwd9=Y*PHpb`VvKYah$w z*l7)9hF$g*WXS@MPmD%c;DBg?Lji94=-Fycd%~^de>Pt(puo4E(C5VkD>zXu4v_<< zOIM81{U5R-CD z>_ZIn=dh3kls2)QZXQk_A|IT>Mx!Q2y!pd8DE1J?lE4^1$FYyF(~XGB9k;KpAkxP4k+R zBO=c?$0|q8mfLAGtbbLSaY_~woFljsP8sf~e|Cz=F#CfUmF`fPzz+Q6%oGOQXY;c$ z=;txfFv9G17yJD2I)NN!))QfnnO~3errQ5>Tg#3YIdIVYOI+}Ze3k6{J?sqd%75X8 zTx?@lSE8(3>{erU##*W6dkmEf-*qAW=&;1TOkA}u;V5S z4D6~f`?kAR_VobI$ju)s1*^~=Q4fdbN3Qtr2&!u#ctGBAKqz_}Ac$cTW-i&~^l~*o zBynA_Q z)r1)L(b7a2T*Sfp1G#UKu8oxZ;)PN^GGYLh?I>y@FjzVAPZTU@KxeH5`S&j=RH7i$ zhj?J5aUR1?^jhXIlx6)>gJ7odY>GpH`=_uPp2&@OQ0t( z4`M|^&+UN+UfNQ>e(nUG?DGRo%%o`Q3y3`%LfNY!w9=Ac-0n0S{Fb68n1@roL8!`E zQww1&Ed-1aSSFtRw(weW3)jGkO0+So4Y|UFow?FombS3w^|2Faol5F`Q$m&C#2>DO za5I%ophTHH{d-_=VO3m!Y)Y_11;`c*fS4pBdnFah!}sG_)^Uucp)@XAJ)GKo4ovPQ zFSt=#E1@gEem^pTS}YO5mAd$>1sdBH;2;0=WOw)8DXbn(d7!czVkP6jUytUA`!){jJ=h*?IuJiV@}k*vXti6V>dJu}?O5w3wmF;wJ_g4z z0^e&Hiz+wdayfZV_M-EK>!2I4?Rj{+7uI@@{5l@4_~dZNc%MTP7^!5FOJ>U(GO_gN3c8rv7ku`C-0tqI83_EFTK^W+r5X=mv|~>X~F@nli94(H3`3VaV(4< z87t`4wFgYA=8#?E`XYc6cihm1AI<>WtKWf)ydc5*htxxPGPW-WwS%PX@qkrmOCDZq z?1qIjIb_IMh_>GXt2~2hMI(Fi z0!;+i!yFbZx0tQPdz8WG)y`!FlI$@2z*P zF3;d91edvwADl(8lQAHhKL&s3eZ}0E@g^sceRqvpeTPZ@hz{;Y0?bei@PS?BJMdrD z2U98*#ii_@P*TMcY4-Y)gAbJuLuwRNZ^LeZxdNFKtD{$a1X@^x@#s+1QfB~zC78h= zHHCl@08;|L&7#^CJHc&IQ|MSN1~TPM4YJkBrkx^XW-r!6;q~!@)46m;DMu}A5LF8s zMB(uWH^6V3^}(Z)R5lA}A)ElRNhXQgk$~MIOL;0`7ZCh9hU;+c1*|A>L$`XmiT@fZ zO>tAxHVwNb-cbnjXwXVVVCvF?cayuDx-Qp(IU6v+fyWIQvGmf^i}k$-WA@&K=)^NZ zV!(KO!wu(TwphWrV408Qw4T%UsgT+|+kGdE`IBJ(JO-{7b-`78*KRs=U$ zs%Hb53*nfRqoGK^4oUqNkeme!()!44J5G#jYb;_+V;E_`lPh@w{ncwGDTcix2( z40FK1TW@&)q%^?kbPcJBPG8QSd{+c(V79?fc@zjIU;reU9svR;_Xc2HFBpJ}++#7i zYo6;hz1ASt?wmK&bGn(1(9rZp(`>{6+91Zk&N?6pgl`yk7DF0(PI`7bt}2i+*>2we zmUaXPCoPOsa%{`EFeV6x$oV3NEYbEF-yB}bRNG2QZ)IDle(Gu8xRIqZP#i445ySpj z1Vh!1Lamo*V@M~PsJ;NoBA)Ak;kT{n-`H0Ud zP(YmHix-GCG7dwt2pbm!3!@4FyW?rA{A?wG;iW!Y@&V5M95^v0kOw$qIn1HTVdyoW zN63)f6CjXY1w;i#<)bzWNThL)wWw&4g8A}DP(%Mh9$b6&0Gq^vEl@=shC7rE8$v~2 zJPEa3{%H+no|xgYVy z2X(_xLgM{4ew*Dqu4>Na4zS3${Nu3g+4QIfa<4$1z!wP|tvP^$WiBi{%wfu5Lq-BGpph_vYrr5u;A^2lFfm`of?3*jt;0VDb)+Os9S(2na3GB9t?f_;+Aj;8tX9~vtULZmddAD3c-WYK zIdd|l^_c*lR5-5!Vo^gV>KTFF;0Zuaq20Omau`vax;K?Iou)}diDjkhW7*JP4+hyr zBX~2{P_NX$G6q0aI{=o4=X1$K?zTYh`~Xfj@NG&~U0p9=`IJVn{_z-$piT|wqi6pB zPMpDMd^q1ffwA@ytjLFpNB9M!vx51Noq#J~n@vC_^=eg+ZDhh!2DM7in$(b|Y=W>g zIGIK#dr_Yf&1%Y8MD0_GE(&e50jiqQL$uudp~3Uj67Gjq52(|C#WSuh8px+TF<6H3 zn3fDWZi7%fFP8QQjj4{}tbzU8L5W zlCvD;esAESR%YKJKq#a14*I@5J%AShtBYf6^XbLQ%$x!=E`-J)E3PVv8kNvTI3U4x zr8H2gp5S>)`R)~ne))hfEYg^FK`F`VE3iT#46}LbjW}w-{LNH2G#1pQ76t4GUyPNP z;A${(>we)b$!4WoDno88c_Y!r0sJ6@4qQdF5Y%#vheWIJ+@O00pC7C+cL~9DCl)Zy zamB;}=7f)cMRP|YPS9O>HYr8yPVK(2*TJE8ya9y8w~*awlYq^#$~-$}0t67dQu6yI z^d5^~Zmf{CnbyVa9kLfV;$B^{g@Frr zz)%GQJ1;aVxYvg~hKAJcB*KxRffj4ydUPP=GQkx$dU8c5DVa0Z23QAs35!BD!#PGh zyObQwQ9CEv*`qq$bxq__SczQ`Edzvh=LDN(|AbBN^d6+|SnjFs8qkplkkb(;iXVaQ z=?FhpY-5TIc-b^(mTHC%?gLJ#8@?sW6W)J91koVw<{${W(iB36?IayEhr@65@O`)t zu_vwVgV`r5i;x_kZ{DYgH}Y17ye))7>Z%qAjFEYFZ!rVK!6Op3MpT-o4AAb%90o-A=g9! zobsEDg0h$)zQHJ&Unlc8v!d4<7^guct{Qi6!yMQD1mIp2-(YEQIEn{b;Me8^>Wv9l z>0Y**;QPTJ3K~j{o@I5DhVvJ_mYvKB*5;DM{R}R^=vRC)SGpZ(Y#^`JvYUKCA_0&q zh4_8}XadlJQkfYWtZ0x6Racqmz<_es!Fl3A0xNgH*EDzvI*6v~21k3m@veC9R}nr} zU3J4_nw&ip!mb(PNYTQljU1$cjP>$*iN>J1!C7 z-sjEoNWvDFe;8`L)LhV>1hG@^6o%agH0(-^^GElAp)e4V+7>Y7i$^%yWr4e=DZt8{ zWB1r2OLPMsEU4MNsUu|MVmUQvV^bo*5#o#`lFC!9*<+i2n)n9(eZjZ3S^shQ0+uWZ zTE|e_IRO)O!W4HOK!*y%2lM9gje*&GtTpVm7StwEg1!nxj8ZZ-2Z%o1gBY8@(%nZ{ zEIQUrN3_bRB$xTYT;%)8f#Upjb&cHmDg+D5Gti+ zO6HA95R7yR#ic}I9V-eNyM1zY2oPJ=1C(bSQWLl0qVERj-K(ajuucDXHgQYQOMMRnZv6;Uv-{Zb%5}LEk-u znTM7xSrD~oesua!U&vICSKwzyplCjCX968rXE_dXNKY|(8&?E< z1O~v}BWkkw>~%?|)L_Bkjt-4obvI7qD`wr{XtvyO;G`$i-->GX9FTlFZ&wt|TlL{S zkQCra#x|7T3Yo#6)h&KYP$89PE@o*89|!yI(R^cEpSD%#(_SyUX%dG4U

tBt6#j%&F|fJG6Us9{-#4 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