Skip to content

Commit

Permalink
fix: Fix FileNotFoundException in MSBuild tasks
Browse files Browse the repository at this point in the history
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
  • Loading branch information
ap0llo authored Sep 4, 2020
2 parents 3924daa + 402b34f commit 41b712b
Show file tree
Hide file tree
Showing 13 changed files with 514 additions and 16 deletions.
3 changes: 3 additions & 0 deletions .gitmodules
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
[submodule "deps/utilities"]
path = deps/utilities
url = https://github.com/ap0llo/utilities.git
16 changes: 15 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,9 @@ corresponding sub-pages:

## Building from source

MdDocs is a .NET Core application and can be built using the .NET SDK 3.1
ℹ This repository uses git submodules. Use `git clone --recursive` to check out submodules as well.

MdDocs is a .NET Core application and can be built using the .NET SDK 3.1 (see [global.json](./global.json))

```ps1
dotnet restore .\src\MdDocs.sln
Expand All @@ -43,6 +45,13 @@ dotnet build .\src\MdDocs.sln
dotnet pack .\src\MdDocs.sln
```

To run tests, the .NET SK 2.1 (version 2.1.800) and a installation of Visual Studio 2019 is requried as well.
(this only applies to the `MdDocs.MSBuild.IntegrationTest` project, all other test project should be executable with only the .NET Core 3.1 SDK).

```ps1
dotnet test .\src\MdDocs.sln
```

## Issues

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

## Versioning and Branching

Expand Down
42 changes: 31 additions & 11 deletions azure-pipelines.yml
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ trigger:

pr:
- master
- releases/*
- release/*

variables:
# Build settings
Expand All @@ -42,25 +42,38 @@ variables:
nuget_org_PackageName: 'Grynwald.MdDocs' # the name of the package being published

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

# Azure DevOps agent settings
azuredevops_vmimage: windows-latest

jobs:

# Main Build and test job: Builds the projects and runs all tests
- job: Build_and_Test
displayName: 🛠 Build and Test
pool: Hosted VS2017
pool:
vmImage: $(azuredevops_vmimage)
steps:

- checkout: self
submodules: true

# Install .NET Core SDK and runtime (version specified in global.json)
- task: UseDotNet@2
displayName: ⚙ Install .NET Core SDK
inputs:
packageType: sdk
useGlobalJson: true

# Also install .NET Core 2.1 SDK because MSBuild integration tests run with both .NET Core 3.1 and 2.1
- task: UseDotNet@2
displayName: 'Install .NET Core 2.1 SDK'
inputs:
packageType: sdk
version: 2.1.809

# Restore local .NET Core tools
- task: DotNetCoreCLI@2
displayName: 📥 Restore local tools
Expand Down Expand Up @@ -111,12 +124,15 @@ jobs:
failIfCoverageEmpty: true

# Create NuGet Package and publish as build artifact
- task: DotNetCoreCLI@2
- task: CmdLine@2
displayName: 📦 Pack NuGet package
inputs:
command: pack
projects: $(solutionPath)
arguments: '--configuration $(configuration) --output $(Build.ArtifactStagingDirectory) --no-build /warnaserror'
script: >-
dotnet pack $(solutionPath)
--configuration $(configuration)
--output $(Build.ArtifactStagingDirectory)
--no-build
/warnaserror
- task: PublishBuildArtifacts@1
displayName: '📤 Publish Artifacts: $(artifactsName_Binaries)'
inputs:
Expand Down Expand Up @@ -146,7 +162,8 @@ jobs:
# Job to push package to MyGet.org after build
- job: Publish_to_MyGet
displayName: 🚚 Publish to MyGet
pool: Hosted VS2017
pool:
vmImage: $(azuredevops_vmimage)
# Only run after main build job and only if the current branch is master or a release branch
dependsOn: Build_and_Test
condition: and(succeeded('Build_and_Test'), or(eq(variables['build.sourceBranch'], 'refs/heads/master'), startsWith(variables['Build.SourceBranch'], 'refs/heads/release/') ))
Expand All @@ -170,7 +187,8 @@ jobs:
# Job to push package to NuGet.org after build (only for builds of release branches)
- job: Publish_to_NuGet_org
displayName: 🚚 Publish to NuGet.org
pool: Hosted VS2017
pool:
vmImage: $(azuredevops_vmimage)
# Only run after main build job and only if the current branch is a release branch
dependsOn: Build_and_Test
condition: |
Expand Down Expand Up @@ -199,7 +217,8 @@ jobs:
# Job to create a GitHub release (only if a package was uploaded to NuGet.org)
- job: Create_GitHub_Release
displayName: 🔖 Create GitHub Release
pool: Hosted VS2017
pool:
vmImage: $(azuredevops_vmimage)
# Only run if build was successful and a package was uploaded to nuget.org
dependsOn:
- Build_and_Test
Expand Down Expand Up @@ -266,7 +285,8 @@ jobs:
# Job to create a GitHub *DRAFT* release (only if a package was uploaded to myget.org)
- job: Create_GitHub_Draft_Release
displayName: 🔖 Create GitHub DRAFT Release
pool: Hosted VS2017
pool:
vmImage: $(azuredevops_vmimage)
# Only run if build was successful and a package was uploaded to nuget.org
dependsOn:
- Build_and_Test
Expand Down
1 change: 1 addition & 0 deletions deps/utilities
Submodule utilities added at 9ee5ba
49 changes: 49 additions & 0 deletions src/Directory.Build.targets
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,55 @@
</ItemGroup>

</Target>


<!--
Some projects reference Microsoft.Extensions.* packages in version 3.1.0
which shipped with broken timestamps for the files in the NuGet package
(see https://github.com/dotnet/extensions/issues/2750).
This makes it impossible to repack the files in a NuGet package
(which is required for both tools packages as well as the MSBuild package).
To work around this, set a valid "modified" date on all assemblies in the output.
Note: Package versions after 3.1.0 fix this issue, but we need to reference
3.1.0 because later versions cause file load errros when loaded by MSBuild breaking the MSBuild tasks
https://github.com/ap0llo/mddocs/issues/75
-->
<Target Name="FixFileTimestampsInOutputPath" AfterTargets="AfterBuild">
<ItemGroup>
<_FixModifiedFile Include="$(OutputPath)/Microsoft.Extensions*" />
</ItemGroup>
<FixModifiedTime Files="@(_FixModifiedFile)" />
</Target>

<Target Name="FixFileTimestampsOnPackageFiles" BeforeTargets="GenerateNuspec">
<FixModifiedTime Files="@(_PackageFiles)" />
</Target>

<UsingTask TaskName="FixModifiedTime"
TaskFactory="RoslynCodeTaskFactory"
AssemblyFile="$(MSBuildToolsPath)\Microsoft.Build.Tasks.Core.dll" >
<ParameterGroup>
<Files ParameterType="Microsoft.Build.Framework.ITaskItem[]" Required="true" />
</ParameterGroup>
<Task>
<Using Namespace="System.IO" />
<Code Type="Fragment" Language="cs">
<![CDATA[
foreach(var fileItem in Files)
{
var fullPath = fileItem.GetMetadata("FullPath");
var fileInfo = new FileInfo(fullPath);
if(fileInfo.LastWriteTime.Year == 1980)
{
Log.LogMessage($"Fixing timestamp of file '{fullPath}'");
fileInfo.LastWriteTime = fileInfo.CreationTime;
}
}
]]>
</Code>
</Task>
</UsingTask>

</Project>
30 changes: 26 additions & 4 deletions src/MdDocs.Common/Grynwald.MdDocs.Common.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,21 @@
</ItemGroup>

<ItemGroup>
<PackageReference Include="Grynwald.Utilities.Configuration" Version="1.6.11-pre" />
<PackageReference Include="Grynwald.MarkdownGenerator" Version="2.5.34" />
<PackageReference Include="Mono.Cecil" Version="0.11.2" />
<PackageReference Include="Microsoft.Extensions.Logging.Abstractions" Version="3.1.7" />
<PackageReference Include="Microsoft.Extensions.Configuration" Version="3.1.7" />
<PackageReference Include="Microsoft.Extensions.Configuration.Binder" Version="3.1.7" />
<PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="3.1.7" />

<!--
Important: Keep version at 3.1.0, do not upgrade to newer versions of the 3.1.* line.
Using later versions causes assembly load errors when MSBuild attemps to load the assemblies.
https://github.com/ap0llo/mddocs/issues/75
The preview version 5 of these packages does not seem to have this issue,
so this should be revisited after the relesae of .NET 5
-->
<PackageReference Include="Microsoft.Extensions.Configuration" Version="3.1.0" />
<PackageReference Include="Microsoft.Extensions.Configuration.Binder" Version="3.1.0" />
<PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="3.1.0" />
</ItemGroup>


Expand All @@ -33,5 +41,19 @@
<ItemGroup>
<Compile Include="../shared/Nullable.cs" />
</ItemGroup>

<!--
Include Grynwald.Utilities.Configuration as source instead of using the NuGet package.
Utilities.Configuration depends on a different version of Microsoft.Extensions.Configuration than this project.
Because Microsoft.Extension.Configuration assemblies are strong-named, this can lead to assembly load errors
on .NET Framework. Usually this can be solved using assembly binding redirects, however through MdDocs.MSBuild,
the assemblies are loaded into a process for which the binding redirects cannot be changed (MSBuild).
To resolve this, the library is included as source, making it possible to build
everything against the same version of Microsoft.Extensions.Configuration.
-->
<ItemGroup>
<Compile Include="..\..\deps\utilities\src\Utilities.Configuration\**\*.cs" />
</ItemGroup>

</Project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFramework>netcoreapp3.1</TargetFramework>
<IsPackable>false</IsPackable>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.2.0" />
<PackageReference Include="xunit" Version="2.4.0" />
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.0" />
<PackageReference Include="coverlet.collector" Version="1.0.1" />
<PackageReference Include="NuGet.Packaging" Version="5.7.0" />
<PackageReference Include="Microsoft.Win32.Registry" Version="4.7.0" />
<PackageReference Include="System.Security.Cryptography.ProtectedData" Version="4.7.0" />
</ItemGroup>

<ItemGroup>
<ProjectReference Include="..\MdDocs.MSBuild\Grynwald.MdDocs.MSBuild.csproj" />
</ItemGroup>

<Target Name="BuildPackageToTestOutput" AfterTargets="Build">

<RemoveDir Directories="$(OutputPath)/packages/" />

<MSBuild Projects="..\MdDocs.MSBuild\Grynwald.MdDocs.MSBuild.csproj" Properties="PackageOutputPath=$(OutputPath)/packages/" Targets="Build;Pack" />
</Target>

</Project>
Loading

0 comments on commit 41b712b

Please sign in to comment.