-
Notifications
You must be signed in to change notification settings - Fork 653
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Stability of MSBuild integration for future .NET Core releases #1537
Comments
Thanks @stazz for detailed explanation, we might consider the approach you suggested |
Hi @stazz it's definately something to consider. Couple of points thinking out loud. A csproj file built with dot net would need the global tool installed, but built with msbuild it wouldnt. Today we can build the same csproj file with either, there are no platform specific instructions which is nicer imho but probs not a deal breaker. If we invoked the global tool as part of the build presumably we would have to pass any msbuild properties needed to gitversion and then get its STDOUT and then set the same msbuild properties during the build that the task sets today. This means the task could be dumbed down, and dependencies removed (presumably we'd need to remove all dependencies because we will no longer have utilpack to restore them for us) but we would still need a task, and now we might need two tasks, one per platform (but hopefully not, hopefully we coukd keep a single task targeting netstandard for this that runs on mono, desktop and core - it was dependency resolution that made this originally non trivial but bow if we dont have any dependencies it might just work..). We'd have to think whether we need to extend gitversion command line for this mode of operation (i.e to support gitversiontask in its new endeavours) Arguably if this is workable, we should use a consistent approach on Net Desktop as well, i.e by calling GitVersion.exe inatead of dotnet gitversion global tool - keeping as much of the logic as unified accross platforms and as consistent as possible. Utilpack msbuild was / is attractive because it lets you write a single msbuild task targeting netstandard that runs everywhere taking care of platform differences = less platform specific divergence in our code base. I'd support any change that is done in a way that keeps platform specific code as light as possible :-) I have an extension of your idea @stazz what do.you think of this:
Any thoughts? I am wondering if utilpack might still be adding value in the above proposition, in its ability to resolve dependencies accross platform, for anything that we might need to bundle inside the gitversiontask nuget package (newtonsoft.json ?) I.e not restored via nuget. |
I understand the need to keep as little platform-specific code as possible. It appeals to me as well, and was the motivation behind UtilPack task factory itself. Those 4 points you mention are definetly a step in a right direction in the sense of minimizing platform-specific code and still preserving the robustness of task for future, possibly binary-incompatible NuGet releases. The most hard thing would be probably point 2, because to even get stuff like NuGet package directory, and dedicated directory for specific package + version within the NuGet package directory requires using NuGet APIs. I could hardcode the logic without using NuGet-dependant code, but that might once again break in some future release. But it's definetly doable, just need to make it as parametrizable as possible :) |
I've been thinking about this, and the recently opened issue ( #1554 ) has poked at those thoughts. I think @dazinator has a viable approach idea. The value of the UtilPack in that scenario would indeed be that you could build for one target (e.g. netstandard1.3) and the UtilPack would take care of running everything for you. The only thing to settle in that case would be how to convey output/input parameters, as then they would collapse into the string array and a single integer (+ whatever files may be read/written). In a technical view, this would cause the following changes:
This way another process will be spawned which can load the specific NuGet packages from same directory without being disturbed by the NuGet version changes in .NET Core SDK itself. The process would be still running via NuGetUtils.MSBuild.Exec own entrypoint, which will take care of loading all dependant assemblies from their locations in NuGet package folder etc. What do you think about this? I think it's a nice way to be able to lock down the NuGet version even on .NET Core, and only kink to clean is the heuristics of how to pass task parameters to the target entrypoint via string array. |
Interesting idea. So to check if I understand correctly:
Am I close? |
You are actually pretty much there. I have some old code lying around somewhere for stuff like process listening for named semaphore for cancellation, etc. That allows for the child process to at least try graceful shutdown when the parent (msbuild) process is requesting cancellation. About the msbuild dependencies: I guess you have two choices, since there will be some need to deduce what kind of input and output parameters are needed for task, when msbuild requests them from the task factory.
My personal preference would be option number 2, as it cuts down the size of your dependencies substantially, but I guess I am a bit biased in this situation. ;) An example of how your code would look like in scenario 2: // Let the NuGetUtils.MSBuild.Exec know the entrypoint for this assembly
[assembly: NuGetUtils.Lib.EntryPoint.ConfiguredEntryPointAttribute(
typeof(GitVersionTask),
nameof(GitVersionTask.Execute)
)]
public static class GitVersionTask {
// The input parameter is created from command-line args by NuGetUtils.MSBuild.Exec, using standard Microsoft.Extensions.CommandLine package utilities
// And the command lines are passed to this process by task factory which started this process.
public static GitVersionTaskOutput Execute(
GitVersionTaskInput input,
CancellationToken token // This is optional but is handy
) {
if (input.Validate()) { // Extension method, see below
// Do the stuff here. Notice that you can not use any MSBuild stuff here (logging etc)
} else {
throw new ArgumentException("Invalid arguments.");
}
}
// This is like marking properties with [Required] msbuild attributes, but you need to write the actual code yourself.
// On a plus side, you can write any kind of complex logic here.
private static Boolean Validate(
this GitVersionTaskInput input
) {
return !String.IsNullOrEmpty( input?.RequiredOption );
}
}
public sealed class GitVersionTaskInput {
// All properties must have both getter and setter, for Microsoft.Extensions.Configuration packages
public String RequiredOption { get; set; }
public String OptionalOption { get; set; }
}
public sealed class GitVersionTaskOutput {
// Setter optional here, I think (haven't tried yet)
public String SomeProperty { get; set; }
} You can already try this code out using the .NET Global Tool NuGetUtils.Tool.Exec. All except the output parameter functionality is already in the current release, and if you're familiar how In any case, the NuGetUtils.MSBuild.Exec has learned to cache restore results to disk, so only the first restore will be really slow one, the rest after that (even in new msbuild process) should be fast. Unless, of course, someone clears the cache folder on disk. :) |
Resolved by #1677. |
Hi,
When helping with issue #1503 the concern was arised that any new .NET Core releases have potential to break the UtilPack task factory used by GitVersionTask. This stems from the fact that while it is possible to lock down the NuGet assemblies version on .NET Desktop (and Mono), it is not possible to do so on .NET Core. This because NuGet assemblies are part of Trusted Platform Assembly list when
dotnet build
command is invoked, and it is not possible to load another version of them by the task factory. This will cause crashes as new versions of .NET Core introduce potentially binary-incompatible changes to the used APIs of NuGet assemblies.So the root problem can be solved if there is a way to lock down NuGet assembly version on .NET Core
build
environment. One such way is to use .NET Core Global Tools, since they run using plaindotnet
instead ofdotnet build
.It seems that you are publishing GitVersionTask already as .NET Core Global Tool, according to #1463 . Maybe the most straightforward way is to just invoke the GitVersionTask as global tool from .targets file, installing it if it is missing from local system? Would it produce all information that is required by the .targets file?
This would essentially split the behaviour of GitVersionTask in MSBuild usage into two parts:
The text was updated successfully, but these errors were encountered: