Skip to content

Commit 41b712b

Browse files
authored
fix: Fix FileNotFoundException in MSBuild tasks
Fix FileNotFoundException caused by assembly resolution errors in the MSBuild task. Adds integration tests to verify MdDocs MSBuild tasks can run in the build for both the .NET Core SDK (2.1 and 3.1) and full/.NET Framework MSBuild. Fixes: #75 Pull-Request: #76
2 parents 3924daa + 402b34f commit 41b712b

13 files changed

+514
-16
lines changed

.gitmodules

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
[submodule "deps/utilities"]
2+
path = deps/utilities
3+
url = https://github.com/ap0llo/utilities.git

README.md

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,9 @@ corresponding sub-pages:
3333

3434
## Building from source
3535

36-
MdDocs is a .NET Core application and can be built using the .NET SDK 3.1
36+
ℹ This repository uses git submodules. Use `git clone --recursive` to check out submodules as well.
37+
38+
MdDocs is a .NET Core application and can be built using the .NET SDK 3.1 (see [global.json](./global.json))
3739

3840
```ps1
3941
dotnet restore .\src\MdDocs.sln
@@ -43,6 +45,13 @@ dotnet build .\src\MdDocs.sln
4345
dotnet pack .\src\MdDocs.sln
4446
```
4547

48+
To run tests, the .NET SK 2.1 (version 2.1.800) and a installation of Visual Studio 2019 is requried as well.
49+
(this only applies to the `MdDocs.MSBuild.IntegrationTest` project, all other test project should be executable with only the .NET Core 3.1 SDK).
50+
51+
```ps1
52+
dotnet test .\src\MdDocs.sln
53+
```
54+
4655
## Issues
4756

4857
If you run into any issues or if you are missing a feature, feel free
@@ -64,12 +73,17 @@ created by me without anyone else being involved in the discussion.
6473
- [CommandLineParser](https://github.com/gsscoder/commandline)
6574
- [Nerdbank.GitVersioning](https://github.com/AArnott/Nerdbank.GitVersioning/)
6675
- [Microsoft.Extensions.Logging](https://github.com/aspnet/Extensions)
76+
- [Microsoft.Extensions.Configuration](https://github.com/aspnet/Extensions)
6777
- [Microsoft.DotNet.Analyzers.Compatibility](https://github.com/dotnet/platform-compat)
6878
- [xUnit](http://xunit.github.io/)
6979
- [Xunit.Combinatorial](https://github.com/AArnott/Xunit.Combinatorial)
7080
- [Moq](https://github.com/moq/moq4)
7181
- [ApprovalTests](https://github.com/approvals/ApprovalTests.Net)
7282
- [Microsoft.CodeAnalysis.CSharp](https://github.com/dotnet/roslyn)
83+
- [Coverlet](https://github.com/tonerdo/coverlet)
84+
- [MSBuild](https://github.com/dotnet/msbuild/)
85+
- [SourceLink](https://github.com/dotnet/sourcelink)
86+
- [NuGet](https://github.com/NuGet/NuGet.Client)
7387

7488
## Versioning and Branching
7589

azure-pipelines.yml

Lines changed: 31 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ trigger:
2424

2525
pr:
2626
- master
27-
- releases/*
27+
- release/*
2828

2929
variables:
3030
# Build settings
@@ -42,25 +42,38 @@ variables:
4242
nuget_org_PackageName: 'Grynwald.MdDocs' # the name of the package being published
4343

4444
# GitHub settings
45-
github_createRelease: true # enable creation of GitHub releases when a package was uploaded to NuGet.org
4645
github_ServiceConnectionName: 'GitHub: ap0llo' # the name of the Azure DevOps service connection to use for creating GitHub releases
4746
github_repositoryName: 'ap0llo/mddocs' # the name of the github repo to create the release in
4847

48+
# Azure DevOps agent settings
49+
azuredevops_vmimage: windows-latest
50+
4951
jobs:
5052

5153
# Main Build and test job: Builds the projects and runs all tests
5254
- job: Build_and_Test
5355
displayName: 🛠 Build and Test
54-
pool: Hosted VS2017
56+
pool:
57+
vmImage: $(azuredevops_vmimage)
5558
steps:
5659

60+
- checkout: self
61+
submodules: true
62+
5763
# Install .NET Core SDK and runtime (version specified in global.json)
5864
- task: UseDotNet@2
5965
displayName: ⚙ Install .NET Core SDK
6066
inputs:
6167
packageType: sdk
6268
useGlobalJson: true
6369

70+
# Also install .NET Core 2.1 SDK because MSBuild integration tests run with both .NET Core 3.1 and 2.1
71+
- task: UseDotNet@2
72+
displayName: 'Install .NET Core 2.1 SDK'
73+
inputs:
74+
packageType: sdk
75+
version: 2.1.809
76+
6477
# Restore local .NET Core tools
6578
- task: DotNetCoreCLI@2
6679
displayName: 📥 Restore local tools
@@ -111,12 +124,15 @@ jobs:
111124
failIfCoverageEmpty: true
112125

113126
# Create NuGet Package and publish as build artifact
114-
- task: DotNetCoreCLI@2
127+
- task: CmdLine@2
115128
displayName: 📦 Pack NuGet package
116129
inputs:
117-
command: pack
118-
projects: $(solutionPath)
119-
arguments: '--configuration $(configuration) --output $(Build.ArtifactStagingDirectory) --no-build /warnaserror'
130+
script: >-
131+
dotnet pack $(solutionPath)
132+
--configuration $(configuration)
133+
--output $(Build.ArtifactStagingDirectory)
134+
--no-build
135+
/warnaserror
120136
- task: PublishBuildArtifacts@1
121137
displayName: '📤 Publish Artifacts: $(artifactsName_Binaries)'
122138
inputs:
@@ -146,7 +162,8 @@ jobs:
146162
# Job to push package to MyGet.org after build
147163
- job: Publish_to_MyGet
148164
displayName: 🚚 Publish to MyGet
149-
pool: Hosted VS2017
165+
pool:
166+
vmImage: $(azuredevops_vmimage)
150167
# Only run after main build job and only if the current branch is master or a release branch
151168
dependsOn: Build_and_Test
152169
condition: and(succeeded('Build_and_Test'), or(eq(variables['build.sourceBranch'], 'refs/heads/master'), startsWith(variables['Build.SourceBranch'], 'refs/heads/release/') ))
@@ -170,7 +187,8 @@ jobs:
170187
# Job to push package to NuGet.org after build (only for builds of release branches)
171188
- job: Publish_to_NuGet_org
172189
displayName: 🚚 Publish to NuGet.org
173-
pool: Hosted VS2017
190+
pool:
191+
vmImage: $(azuredevops_vmimage)
174192
# Only run after main build job and only if the current branch is a release branch
175193
dependsOn: Build_and_Test
176194
condition: |
@@ -199,7 +217,8 @@ jobs:
199217
# Job to create a GitHub release (only if a package was uploaded to NuGet.org)
200218
- job: Create_GitHub_Release
201219
displayName: 🔖 Create GitHub Release
202-
pool: Hosted VS2017
220+
pool:
221+
vmImage: $(azuredevops_vmimage)
203222
# Only run if build was successful and a package was uploaded to nuget.org
204223
dependsOn:
205224
- Build_and_Test
@@ -266,7 +285,8 @@ jobs:
266285
# Job to create a GitHub *DRAFT* release (only if a package was uploaded to myget.org)
267286
- job: Create_GitHub_Draft_Release
268287
displayName: 🔖 Create GitHub DRAFT Release
269-
pool: Hosted VS2017
288+
pool:
289+
vmImage: $(azuredevops_vmimage)
270290
# Only run if build was successful and a package was uploaded to nuget.org
271291
dependsOn:
272292
- Build_and_Test

deps/utilities

Submodule utilities added at 9ee5ba8

src/Directory.Build.targets

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,55 @@
3131
</ItemGroup>
3232

3333
</Target>
34+
3435

36+
<!--
37+
Some projects reference Microsoft.Extensions.* packages in version 3.1.0
38+
which shipped with broken timestamps for the files in the NuGet package
39+
(see https://github.com/dotnet/extensions/issues/2750).
40+
41+
This makes it impossible to repack the files in a NuGet package
42+
(which is required for both tools packages as well as the MSBuild package).
43+
To work around this, set a valid "modified" date on all assemblies in the output.
44+
45+
Note: Package versions after 3.1.0 fix this issue, but we need to reference
46+
3.1.0 because later versions cause file load errros when loaded by MSBuild breaking the MSBuild tasks
47+
https://github.com/ap0llo/mddocs/issues/75
48+
-->
49+
<Target Name="FixFileTimestampsInOutputPath" AfterTargets="AfterBuild">
50+
<ItemGroup>
51+
<_FixModifiedFile Include="$(OutputPath)/Microsoft.Extensions*" />
52+
</ItemGroup>
53+
<FixModifiedTime Files="@(_FixModifiedFile)" />
54+
</Target>
55+
56+
<Target Name="FixFileTimestampsOnPackageFiles" BeforeTargets="GenerateNuspec">
57+
<FixModifiedTime Files="@(_PackageFiles)" />
58+
</Target>
59+
60+
<UsingTask TaskName="FixModifiedTime"
61+
TaskFactory="RoslynCodeTaskFactory"
62+
AssemblyFile="$(MSBuildToolsPath)\Microsoft.Build.Tasks.Core.dll" >
63+
<ParameterGroup>
64+
<Files ParameterType="Microsoft.Build.Framework.ITaskItem[]" Required="true" />
65+
</ParameterGroup>
66+
<Task>
67+
<Using Namespace="System.IO" />
68+
<Code Type="Fragment" Language="cs">
69+
<![CDATA[
70+
foreach(var fileItem in Files)
71+
{
72+
var fullPath = fileItem.GetMetadata("FullPath");
73+
var fileInfo = new FileInfo(fullPath);
74+
if(fileInfo.LastWriteTime.Year == 1980)
75+
{
76+
Log.LogMessage($"Fixing timestamp of file '{fullPath}'");
77+
fileInfo.LastWriteTime = fileInfo.CreationTime;
78+
}
79+
}
80+
]]>
81+
</Code>
82+
</Task>
83+
</UsingTask>
3584

3685
</Project>

src/MdDocs.Common/Grynwald.MdDocs.Common.csproj

Lines changed: 26 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,13 +11,21 @@
1111
</ItemGroup>
1212

1313
<ItemGroup>
14-
<PackageReference Include="Grynwald.Utilities.Configuration" Version="1.6.11-pre" />
1514
<PackageReference Include="Grynwald.MarkdownGenerator" Version="2.5.34" />
1615
<PackageReference Include="Mono.Cecil" Version="0.11.2" />
1716
<PackageReference Include="Microsoft.Extensions.Logging.Abstractions" Version="3.1.7" />
18-
<PackageReference Include="Microsoft.Extensions.Configuration" Version="3.1.7" />
19-
<PackageReference Include="Microsoft.Extensions.Configuration.Binder" Version="3.1.7" />
20-
<PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="3.1.7" />
17+
18+
<!--
19+
Important: Keep version at 3.1.0, do not upgrade to newer versions of the 3.1.* line.
20+
Using later versions causes assembly load errors when MSBuild attemps to load the assemblies.
21+
https://github.com/ap0llo/mddocs/issues/75
22+
23+
The preview version 5 of these packages does not seem to have this issue,
24+
so this should be revisited after the relesae of .NET 5
25+
-->
26+
<PackageReference Include="Microsoft.Extensions.Configuration" Version="3.1.0" />
27+
<PackageReference Include="Microsoft.Extensions.Configuration.Binder" Version="3.1.0" />
28+
<PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="3.1.0" />
2129
</ItemGroup>
2230

2331

@@ -33,5 +41,19 @@
3341
<ItemGroup>
3442
<Compile Include="../shared/Nullable.cs" />
3543
</ItemGroup>
44+
45+
<!--
46+
Include Grynwald.Utilities.Configuration as source instead of using the NuGet package.
47+
48+
Utilities.Configuration depends on a different version of Microsoft.Extensions.Configuration than this project.
49+
Because Microsoft.Extension.Configuration assemblies are strong-named, this can lead to assembly load errors
50+
on .NET Framework. Usually this can be solved using assembly binding redirects, however through MdDocs.MSBuild,
51+
the assemblies are loaded into a process for which the binding redirects cannot be changed (MSBuild).
52+
To resolve this, the library is included as source, making it possible to build
53+
everything against the same version of Microsoft.Extensions.Configuration.
54+
-->
55+
<ItemGroup>
56+
<Compile Include="..\..\deps\utilities\src\Utilities.Configuration\**\*.cs" />
57+
</ItemGroup>
3658

3759
</Project>
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
<Project Sdk="Microsoft.NET.Sdk">
2+
3+
<PropertyGroup>
4+
<TargetFramework>netcoreapp3.1</TargetFramework>
5+
<IsPackable>false</IsPackable>
6+
</PropertyGroup>
7+
8+
<ItemGroup>
9+
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.2.0" />
10+
<PackageReference Include="xunit" Version="2.4.0" />
11+
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.0" />
12+
<PackageReference Include="coverlet.collector" Version="1.0.1" />
13+
<PackageReference Include="NuGet.Packaging" Version="5.7.0" />
14+
<PackageReference Include="Microsoft.Win32.Registry" Version="4.7.0" />
15+
<PackageReference Include="System.Security.Cryptography.ProtectedData" Version="4.7.0" />
16+
</ItemGroup>
17+
18+
<ItemGroup>
19+
<ProjectReference Include="..\MdDocs.MSBuild\Grynwald.MdDocs.MSBuild.csproj" />
20+
</ItemGroup>
21+
22+
<Target Name="BuildPackageToTestOutput" AfterTargets="Build">
23+
24+
<RemoveDir Directories="$(OutputPath)/packages/" />
25+
26+
<MSBuild Projects="..\MdDocs.MSBuild\Grynwald.MdDocs.MSBuild.csproj" Properties="PackageOutputPath=$(OutputPath)/packages/" Targets="Build;Pack" />
27+
</Target>
28+
29+
</Project>

0 commit comments

Comments
 (0)