Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 3 additions & 21 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -33,34 +33,16 @@ defaults:

jobs:
build:
runs-on: windows-latest
runs-on: ubuntu-latest
steps:
- name: 🤘 checkout
uses: actions/checkout@v4

- name: ⚙ msbuild
uses: microsoft/[email protected]

- name: 🙏 build
shell: pwsh
working-directory: src/NuGetizer.Tests
run: |
dotnet restore Scenarios/given_a_packaging_project/a.nuproj
# THIS IS IMPORTANT: WE NEED TO BUILD WITH DESKTOP MSBUILD
msbuild -r

- name: 🐛 logs
uses: actions/upload-artifact@v4
if: runner.debug && always()
with:
name: binlog-build-${{ github.run_number }}
path: src/NuGetizer.Tests/msbuild.binlog

- name: 🧪 test
run: |
dotnet tool update -g dotnet-retest
# THIS IS IMPORTANT: WE TEST BUT NEVER BUILD (to keep desktop-built artifacts)
dotnet retest -- --no-build
# Build and test in one command - no longer need Desktop MSBuild
dotnet retest -- src/NuGetizer.Tests/NuGetizer.Tests.csproj

- name: 📦 pack
run: dotnet pack -m:1 -c:${{ env.Configuration }}
Expand Down
7 changes: 7 additions & 0 deletions global.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"sdk": {
"version": "9.0.100",
"rollForward": "latestMinor",
"allowPrerelease": false
}
}
115 changes: 92 additions & 23 deletions src/NuGetizer.Tests/ModuleInitializer.cs
Original file line number Diff line number Diff line change
@@ -1,51 +1,120 @@
using System;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Loader;

namespace NuGetizer.Tests
{
static class ModuleInitializer
{
static readonly string logFile = Environment.ExpandEnvironmentVariables(@"%TEMP%\NuGetizer.txt");
static readonly string logFile = Path.Combine(Path.GetTempPath(), "NuGetizer.txt");
static string sdkPath;

[ModuleInitializer]
internal static void Run()
{
AppDomain.CurrentDomain.AssemblyResolve += OnAssemblyResolve;
// Get the .NET SDK path by running 'dotnet --info'
sdkPath = GetDotNetSdkPath();

File.AppendAllText(logFile, $"Initializing MSBuild to {ThisAssembly.Project.MSBuildBinPath}\r\n");
File.AppendAllText(logFile, $"Initializing MSBuild from SDK at {sdkPath}\r\n");

var binPath = ThisAssembly.Project.MSBuildBinPath;
Microsoft.Build.Locator.MSBuildLocator.RegisterMSBuildPath(binPath);
// Set up assembly resolution to prefer SDK assemblies
AssemblyLoadContext.Default.Resolving += OnAssemblyResolving;

// Set environment variables so SDKs can be resolved.
Environment.SetEnvironmentVariable("MSBUILD_EXE_PATH", Path.Combine(binPath, "MSBuild.exe"), EnvironmentVariableTarget.Process);
// Set environment variables so SDKs can be resolved
var msbuildExe = Path.Combine(sdkPath, "MSBuild.dll");
Environment.SetEnvironmentVariable("MSBUILD_EXE_PATH", msbuildExe, EnvironmentVariableTarget.Process);
}

static Assembly OnAssemblyResolve(object sender, ResolveEventArgs args)
static Assembly OnAssemblyResolving(AssemblyLoadContext context, AssemblyName assemblyName)
{
var name = new AssemblyName(args.Name).Name;
var file = Path.Combine(ThisAssembly.Project.MSBuildBinPath, name + ".dll");

File.AppendAllText(logFile, $"Resolving {name}\r\n");

if (name.StartsWith("Microsoft.Build") && File.Exists(file))
{
File.AppendAllText(logFile, $"Found {file}\r\n");
return Assembly.LoadFrom(file);
}
else
// Resolve MSBuild, NuGet and related assemblies from the SDK directory
if (assemblyName.Name != null &&
(assemblyName.Name.StartsWith("Microsoft.Build") ||
assemblyName.Name.StartsWith("Microsoft.CodeAnalysis") ||
assemblyName.Name.StartsWith("NuGet.") ||
assemblyName.Name.StartsWith("System.Collections.Immutable") ||
assemblyName.Name.StartsWith("System.Reflection.Metadata") ||
assemblyName.Name.StartsWith("System.Security.Cryptography")))
{
file = Path.Combine(ThisAssembly.Project.MSBuildProjectDirectory, ThisAssembly.Project.OutputPath, name + ".dll");
if (File.Exists(file))
var assemblyPath = Path.Combine(sdkPath, assemblyName.Name + ".dll");
if (File.Exists(assemblyPath))
{
File.AppendAllText(logFile, $"Found {file}\r\n");
return Assembly.LoadFrom(file);
File.AppendAllText(logFile, $"Loading {assemblyName.Name} from SDK at {assemblyPath}\r\n");
return context.LoadFromAssemblyPath(assemblyPath);
}
}

return null;
}

static string GetDotNetSdkPath()
{
try
{
// Use 'dotnet --list-sdks' to find the SDK path
var process = new Process
{
StartInfo = new ProcessStartInfo
{
FileName = "dotnet",
Arguments = "--list-sdks",
RedirectStandardOutput = true,
RedirectStandardError = true,
UseShellExecute = false,
CreateNoWindow = true
}
};

process.Start();
var output = process.StandardOutput.ReadToEnd();
process.WaitForExit();

// Parse the output to get SDK paths, use the latest SDK
// Output format: "9.0.100 [/usr/share/dotnet/sdk]"
var lines = output.Split(new[] { '\r', '\n' }, StringSplitOptions.RemoveEmptyEntries);

// Use the latest SDK (last line)
if (lines.Length > 0)
{
var lastLine = lines.Last();
var startIndex = lastLine.IndexOf('[');
var endIndex = lastLine.IndexOf(']');
if (startIndex >= 0 && endIndex > startIndex)
{
var sdkBase = lastLine.Substring(startIndex + 1, endIndex - startIndex - 1);
var version = lastLine.Substring(0, startIndex).Trim();
var sdkPath = Path.Combine(sdkBase, version);
File.AppendAllText(logFile, $"Using latest SDK at {sdkPath}\r\n");
return sdkPath;
}
}

// Fallback: try to use DOTNET_ROOT or common paths
var dotnetRoot = Environment.GetEnvironmentVariable("DOTNET_ROOT");
if (!string.IsNullOrEmpty(dotnetRoot))
{
var sdkDir = Path.Combine(dotnetRoot, "sdk");
if (Directory.Exists(sdkDir))
{
var versions = Directory.GetDirectories(sdkDir)
.OrderByDescending(d => d)
.FirstOrDefault();
if (versions != null)
return versions;
}
}

throw new InvalidOperationException("Could not locate .NET SDK path");
}
catch (Exception ex)
{
File.AppendAllText(logFile, $"Error finding SDK path: {ex}\r\n");
throw;
}
}
}
}
23 changes: 7 additions & 16 deletions src/NuGetizer.Tests/NuGetizer.Tests.csproj
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFramework>net472</TargetFramework>
<TargetFramework>net9.0</TargetFramework>
<DefaultItemExcludes>$(DefaultItemExcludes);Scenarios\**\*</DefaultItemExcludes>
<LangVersion>Preview</LangVersion>
</PropertyGroup>
Expand All @@ -19,17 +19,20 @@
<PackageReference Include="Microsoft.Build.Tasks.Core" Version="17.10.46" ExcludeAssets="runtime" />
<PackageReference Include="Microsoft.Build.Locator" Version="1.9.1" />
<PackageReference Include="MSBuild.StructuredLogger" Version="2.3.17" />
<PackageReference Include="Microsoft.Build.Framework" Version="17.13.9" ExcludeAssets="runtime" />
<PackageReference Include="Microsoft.Build.Utilities.Core" Version="17.13.9" ExcludeAssets="runtime" />
<PackageReference Include="System.Security.Cryptography.Pkcs" Version="9.0.0" ExcludeAssets="all" />
<PackageReference Include="System.IO.Compression" Version="4.3.0" />
<PackageReference Include="System.IO.Compression.ZipFile" Version="4.3.0" />
<PackageReference Include="NuGet.Packaging" Version="6.12.1" />
<PackageReference Include="NuGet.Packaging" Version="6.14.0" />
<PackageReference Include="ThisAssembly.Project" Version="2.0.14" PrivateAssets="all" />
<PackageReference Include="ThisAssembly.Strings" Version="2.0.14" PrivateAssets="all" />
</ItemGroup>

<ItemGroup>
<None Include="Scenarios\**\*.*" Exclude="Scenarios\**\obj\**\*.*;Scenarios\**\bin\**\*.*" CopyToOutputDirectory="PreserveNewest" />
<None Update="Content\**\*.*" CopyToOutputDirectory="PreserveNewest" />
<Content Include="..\NuGetizer.Tasks\bin\$(Configuration)\*.*" CopyToOutputDirectory="PreserveNewest" Visible="false" />
<Content Include="..\NuGetizer.Tasks\bin\$(Configuration)\*.*" Exclude="..\NuGetizer.Tasks\bin\$(Configuration)\Microsoft.Build*.dll" CopyToOutputDirectory="PreserveNewest" Visible="false" />
<Compile Remove="ModuleInitializerAttribute.cs" Condition="'$(TargetFramework)' == 'net6.0'" />
</ItemGroup>
<ItemGroup>
Expand All @@ -39,10 +42,6 @@
<ItemGroup>
<ProjectProperty Include="NuGetRestoreTargets" />
<ProjectProperty Include="NuGetTargets" />
<ProjectProperty Include="MSBuildBinPath" />
<ProjectProperty Include="MSBuildToolsPath" />
<ProjectProperty Include="MSBuildToolsPath32" />
<ProjectProperty Include="MSBuildToolsPath64" />
<ProjectProperty Include="PrivateRepositoryUrl" />
<ProjectProperty Include="MSBuildProjectDirectory" />
<ProjectProperty Include="OutputPath" />
Expand All @@ -56,15 +55,7 @@

<Target Name="EnsureProjectInformation" BeforeTargets="InjectThisAssemblyProject;GenerateMSBuildEditorConfigFileShouldRun" DependsOnTargets="InitializeSourceControlInformation" />

<Target Name="ClearMSBuild" AfterTargets="Build">
<ItemGroup>
<MSBuildAssembly Include="$(OutputPath)\Microsoft.Build*.dll" Exclude="$(OutputPath)\Microsoft.Build.Locator.dll" />
</ItemGroup>
<Delete Files="@(MSBuildAssembly)">
<Output TaskParameter="DeletedFiles" ItemName="DeletedFiles" />
</Delete>
<Message Text="Deleted: @(DeletedFiles)" Importance="high" />
</Target>


<Import Project="NuGetizer.Tests.targets" />

Expand Down
Loading