Skip to content

Commit

Permalink
Embed NuGet files in binlog after restore
Browse files Browse the repository at this point in the history
  • Loading branch information
jeffkl committed Feb 7, 2023
1 parent 419ab86 commit 0936da1
Show file tree
Hide file tree
Showing 9 changed files with 105 additions and 11 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,7 @@ public async Task<bool> RestoreAsync(string entryProjectFilePath, IDictionary<st

try
{
return await BuildTasksUtility.RestoreAsync(
bool result = await BuildTasksUtility.RestoreAsync(
dependencyGraphSpec: dependencyGraphSpec,
interactive: IsOptionTrue(nameof(RestoreTaskEx.Interactive), options),
recursive: IsOptionTrue(nameof(RestoreTaskEx.Recursive), options),
Expand All @@ -127,7 +127,25 @@ public async Task<bool> RestoreAsync(string entryProjectFilePath, IDictionary<st
restorePC: IsOptionTrue(nameof(RestoreTaskEx.RestorePackagesConfig), options),
cleanupAssetsForUnsupportedProjects: IsOptionTrue(nameof(RestoreTaskEx.CleanupAssetsForUnsupportedProjects), options),
log: MSBuildLogger,
cancellationToken: CancellationToken.None);
cancellationToken: CancellationToken.None);

// If the MSBuildBinaryLoggerEnabled environment variable is set, return the paths to all of the projects used during restore so that the assets file and other NuGet files
// can be embedded in the binlog
if (string.Equals(Environment.GetEnvironmentVariable("MSBUILDBINARYLOGGERENABLED"), bool.TrueString, StringComparison.OrdinalIgnoreCase))
{
IReadOnlyList<PackageSpec> projects = dependencyGraphSpec.Projects;

for (int i = 0; i < projects.Count; i++)
{
LoggingQueue.Enqueue(new ConsoleOutLogMessage
{
Message = projects[i].RestoreMetadata.OutputPath,
MessageType = ConsoleOutLogMessageType.RestoredProjectOutputPath
});
}
}

return result;
}
catch (Exception e)
{
Expand Down
5 changes: 5 additions & 0 deletions src/NuGet.Core/NuGet.Build.Tasks/ConsoleOutLogMessageType.cs
Original file line number Diff line number Diff line change
Expand Up @@ -27,5 +27,10 @@ public enum ConsoleOutLogMessageType
/// The message is a message.
/// </summary>
Message,

/// <summary>
/// The message is a restored project's output path.
/// </summary>
RestoredProjectOutputPath
}
}
2 changes: 2 additions & 0 deletions src/NuGet.Core/NuGet.Build.Tasks/GlobalSuppressions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -68,3 +68,5 @@
[assembly: SuppressMessage("Build", "CA1819:Properties should not return arrays", Justification = "<Pending>", Scope = "member", Target = "~P:NuGet.Build.Tasks.WriteRestoreGraphTask.RestoreGraphItems")]
[assembly: SuppressMessage("Performance", "CA1819:Properties should not return arrays", Justification = "MSBuild tasks expect arrays.", Scope = "member", Target = "~P:NuGet.Build.Tasks.CheckForDuplicateNuGetItemsTask.Items")]
[assembly: SuppressMessage("Performance", "CA1819:Properties should not return arrays", Justification = "MSBuild tasks expect arrays.", Scope = "member", Target = "~P:NuGet.Build.Tasks.CheckForDuplicateNuGetItemsTask.DeduplicatedItems")]
[assembly: SuppressMessage("Performance", "CA1819:Properties should not return arrays", Justification = "MSBuild tasks expect arrays.", Scope = "member", Target = "~P:NuGet.Build.Tasks.RestoreTask.RestoredProjectOutputPaths")]
[assembly: SuppressMessage("Performance", "CA1819:Properties should not return arrays", Justification = "MSBuild tasks expect arrays.", Scope = "member", Target = "~P:NuGet.Build.Tasks.StaticGraphRestoreTaskBase.RestoredProjectOutputPaths")]
13 changes: 10 additions & 3 deletions src/NuGet.Core/NuGet.Build.Tasks/NuGet.RestoreEx.targets
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,15 @@ Copyright (c) .NET Foundation. All rights reserved.
RestorePackagesConfig="$(RestorePackagesConfig)"
SolutionPath="$(SolutionPath)"
ProcessFileName="$(NuGetConsoleProcessFileName)"
MSBuildStartupDirectory="$(MSBuildStartupDirectory)"
/>
MSBuildStartupDirectory="$(MSBuildStartupDirectory)">
<Output TaskParameter="RestoredProjectOutputPaths" ItemName="_RestoredProjectOutputPaths" />
</RestoreTaskEx>

<ItemGroup Condition="@(_RestoredProjectOutputPaths->Count()) > 0">
<EmbedInBinlog Include="%(_RestoredProjectOutputPaths.Identity)project.assets.json;
%(_RestoredProjectOutputPaths.Identity)*.nuget.dgspec.json;
%(_RestoredProjectOutputPaths.Identity)*.nuget.g.*" />
</ItemGroup>
</Target>

<!--
Expand All @@ -53,5 +60,5 @@ Copyright (c) .NET Foundation. All rights reserved.
MSBuildStartupDirectory="$(MSBuildStartupDirectory)"
/>
</Target>

</Project>
10 changes: 9 additions & 1 deletion src/NuGet.Core/NuGet.Build.Tasks/NuGet.targets
Original file line number Diff line number Diff line change
Expand Up @@ -139,7 +139,15 @@ Copyright (c) .NET Foundation. All rights reserved.
HideWarningsAndErrors="$(HideWarningsAndErrors)"
Interactive="$(NuGetInteractive)"
RestoreForceEvaluate="$(RestoreForceEvaluate)"
RestorePackagesConfig="$(RestorePackagesConfig)"/>
RestorePackagesConfig="$(RestorePackagesConfig)">
<Output TaskParameter="RestoredProjectOutputPaths" ItemName="_RestoredProjectOutputPaths" />
</RestoreTask>

<ItemGroup Condition="@(_RestoredProjectOutputPaths->Count()) > 0">
<EmbedInBinlog Include="%(_RestoredProjectOutputPaths.Identity)project.assets.json;
%(_RestoredProjectOutputPaths.Identity)*.nuget.dgspec.json;
%(_RestoredProjectOutputPaths.Identity)*.nuget.g.*" />
</ItemGroup>
</Target>

<!--
Expand Down
22 changes: 22 additions & 0 deletions src/NuGet.Core/NuGet.Build.Tasks/RestoreTask.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,13 @@
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.Build.Framework;
using Microsoft.Build.Utilities;
using NuGet.Commands;
using NuGet.Common;

Expand Down Expand Up @@ -73,6 +75,12 @@ public class RestoreTask : Microsoft.Build.Utilities.Task, ICancelableTask, IDis
/// <returns></returns>
public bool RestorePackagesConfig { get; set; }

/// <summary>
/// Gets or sets the output path for all of the restored projects.
/// </summary>
[Output]
public ITaskItem[] RestoredProjectOutputPaths { get; set; }

public override bool Execute()
{
#if DEBUG
Expand Down Expand Up @@ -127,6 +135,20 @@ private async Task<bool> ExecuteAsync(Common.ILogger log)

var dgFile = MSBuildRestoreUtility.GetDependencySpec(wrappedItems);

// If the MSBuildBinaryLoggerEnabled environment variable is set, return the paths to all of the projects used during restore so that the assets file and other NuGet files
// can be embedded in the binlog
if (string.Equals(Environment.GetEnvironmentVariable("MSBUILDBINARYLOGGERENABLED"), bool.TrueString, StringComparison.OrdinalIgnoreCase))
{
IReadOnlyList<ProjectModel.PackageSpec> projects = dgFile.Projects;

RestoredProjectOutputPaths = new ITaskItem[projects.Count];

for (int i = 0; i < projects.Count; i++)
{
RestoredProjectOutputPaths[i] = new TaskItem(projects[i].RestoreMetadata.OutputPath);
}
}

return await BuildTasksUtility.RestoreAsync(
dependencyGraphSpec: dgFile,
interactive: Interactive,
Expand Down
22 changes: 21 additions & 1 deletion src/NuGet.Core/NuGet.Build.Tasks/StaticGraphRestoreTaskBase.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,11 @@
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.

using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;

#if !IS_CORECLR

Expand All @@ -14,6 +16,7 @@

using System.Threading;
using Microsoft.Build.Framework;
using Microsoft.Build.Utilities;
using NuGet.Common;

namespace NuGet.Build.Tasks
Expand Down Expand Up @@ -62,6 +65,9 @@ public abstract class StaticGraphRestoreTaskBase : Microsoft.Build.Utilities.Tas
/// </summary>
public bool Recursive { get; set; }

[Output]
public ITaskItem[] RestoredProjectOutputPaths { get; set; }

/// <summary>
/// Gets or sets the full path to the solution file (if any) that is being built.
/// </summary>
Expand Down Expand Up @@ -92,8 +98,10 @@ public override bool Execute()
#endif
MSBuildLogger logger = new MSBuildLogger(Log);

List<string> restoredOutputPaths = new List<string>();

using (var semaphore = new SemaphoreSlim(initialCount: 0, maxCount: 1))
using (var loggingQueue = new TaskLoggingQueue(Log))
using (var loggingQueue = new TaskLoggingQueue(Log, restoredOutputPaths))
using (var process = new Process())
{
process.EnableRaisingEvents = true;
Expand Down Expand Up @@ -136,6 +144,18 @@ public override bool Execute()
// The process may have exited, in this case ignore the exception
}
}

if (restoredOutputPaths.Any())
{
RestoredProjectOutputPaths = new ITaskItem[restoredOutputPaths.Count];

int i = 0;

foreach (var item in restoredOutputPaths)
{
RestoredProjectOutputPaths[i++] = new TaskItem(item);
}
}
}
catch (Exception e) when (
e is OperationCanceledException
Expand Down
12 changes: 11 additions & 1 deletion src/NuGet.Core/NuGet.Build.Tasks/TaskLoggingQueue.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.

using System;
using System.Collections.Generic;
using Microsoft.Build.Framework;
using Microsoft.Build.Utilities;
using Newtonsoft.Json;
Expand All @@ -19,13 +20,18 @@ internal class TaskLoggingQueue : LoggingQueue<string>
/// </summary>
private readonly TaskLoggingHelper _log;

private readonly ICollection<string> _restoredProjectOutputPaths;

/// <summary>
/// Initializes a new instance of the TaskLoggingHelperQueue class.
/// </summary>
/// <param name="taskLoggingHelper">The <see cref="Task" /> to create a logging queue for.</param>
public TaskLoggingQueue(TaskLoggingHelper taskLoggingHelper)
/// <param name="restoredProjectOutputPaths">Receives the list of output paths for the restored projects.</param>
public TaskLoggingQueue(TaskLoggingHelper taskLoggingHelper, ICollection<string> restoredProjectOutputPaths)
{
_log = taskLoggingHelper ?? throw new ArgumentNullException(nameof(taskLoggingHelper));

_restoredProjectOutputPaths = restoredProjectOutputPaths ?? throw new ArgumentNullException(nameof(restoredProjectOutputPaths));
}

/// <summary>
Expand Down Expand Up @@ -90,6 +96,10 @@ protected override void Process(string message)
_log.LogMessageFromText(consoleOutLogMessage.Message, consoleOutLogMessage.Importance);
return;

case ConsoleOutLogMessageType.RestoredProjectOutputPath:
_restoredProjectOutputPaths.Add(consoleOutLogMessage.Message);
return;

default:
throw new ArgumentOutOfRangeException(
paramName: nameof(message),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@
#endif

using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using FluentAssertions;
using Microsoft.Build.Framework;
#if IS_DESKTOP
Expand All @@ -27,7 +29,7 @@ public void TaskLoggingQueue_Process_HandleBadMessage()

var buildEngine = new TestBuildEngine();

using (var loggingQueue = new TaskLoggingQueue(new TaskLoggingHelper(buildEngine, nameof(TaskLoggingQueueTests))))
using (var loggingQueue = new TaskLoggingQueue(new TaskLoggingHelper(buildEngine, nameof(TaskLoggingQueueTests)), new List<string>()))
{
loggingQueue.Enqueue(badMessage);
}
Expand Down Expand Up @@ -57,7 +59,7 @@ public void TaskLoggingQueue_Process_LogsMessages(string messageType, string mes

var buildEngine = new TestBuildEngine();

using (var loggingQueue = new TaskLoggingQueue(new TaskLoggingHelper(buildEngine, nameof(TaskLoggingQueueTests))))
using (var loggingQueue = new TaskLoggingQueue(new TaskLoggingHelper(buildEngine, nameof(TaskLoggingQueueTests)), new List<string>()))
{
loggingQueue.Enqueue(expected.ToJson());
}
Expand All @@ -77,7 +79,7 @@ public void TaskLoggingQueue_Process_ThrowsIfInvalidMessageType()

Action act = () =>
{
using (var loggingQueue = new TaskLoggingQueue(new TaskLoggingHelper(buildEngine, nameof(TaskLoggingQueueTests))))
using (var loggingQueue = new TaskLoggingQueue(new TaskLoggingHelper(buildEngine, nameof(TaskLoggingQueueTests)), new List<string>()))
{
loggingQueue.Enqueue(badMessage);
}
Expand Down

0 comments on commit 0936da1

Please sign in to comment.