3
votes

I have a cake build script with my .NET server project which needs to be built on our new Azure DevOps pipeline. The script works locally but does not work on Azure DevOps. There are possible reasons for this which may be that I have a Unit Tests project (xUnit) built on .NET Core 2.1 while all the other projects in solution are .NET Framework 4.6.1 (we just added in the xUnit project which my only option was to add it in as a .NET Core project).

I wrote my cake script which works locally. It looks like this:

//Always lock down versions of tools so that we can ensure a tool works before upgrading instead of auto-upgrading.
#tool "nuget:?package=xunit.runner.console&version=2.4.1"
#tool "nuget:?package=ReportUnit&version=1.2.1"

var target = Argument("target", "Build");
var configuration = Argument("configuration", "Dev");
var solution = @".\MyCompany.MyProduct.IntegrationLayer.sln";
var report = Directory(@".\reports");
var xunitReport = report + Directory("xunit");

Task("Clean")
    .Does(() =>
{
    Information("Cleaning out directories {0} for {1}...", configuration, solution);
        CleanDirectories("./**/bin/" + configuration);
        CleanDirectories("./**/obj/" + configuration);
});

Task("Restore")
    .IsDependentOn("Clean")
    .Does(() =>
{
    //This can restore both .NET Core and Framework NuGet packages.
    Information("Restoring Nuget packages for {0}...", solution);
    DotNetCoreRestore();
});

Task("Build")
    .IsDependentOn("Restore")
    .Does(() =>
{
    //If we change all the projects and solution to .NET Core, then we will need to change this build call to DotNetCoreBuild().
    //Because we have a mixed solution (unit tests are .NET Core and all other projects are .NET Framework), we need to still use MSBuild.
    Information("Building solution {0} using the {1} configuration...", solution, configuration);
    MSBuild(solution, new MSBuildSettings {
        Configuration = configuration
    });
});

Task("UnitTests")
    .IsDependentOn("Build")
    .Does(() =>
{
    Information("Unit testing solution {0} using the {1} configuration...", solution, configuration);
    var projects = GetFiles("./UnitTests/*.csproj");
    foreach(var project in projects)
    {
        DotNetCoreTest(
            project.FullPath,
            new DotNetCoreTestSettings()
            {
                Configuration = configuration,
                NoBuild = true
            });
    }
});

Task("UnitTestsOnly")
    .Does(() =>
{
    Information("Unit testing solution {0} using the {1} configuration...", solution, configuration);
    var projects = GetFiles("./UnitTests/*.csproj");
    foreach(var project in projects)
    {
        DotNetCoreTest(
            project.FullPath,
            new DotNetCoreTestSettings()
            {
                Configuration = configuration,
                NoBuild = true
            });
    }
});

RunTarget(target);

Now when I run this in Azure DevOps, I get 10 errors for each project similar to this example below:

"D:\a\1\s\PPIL\MyCompany.MyProduct.IntegrationLayer.sln" (Build target) (1) ->
"D:\a\1\s\PPIL\MC.MP.IL.DatabaseDataReset\MC.MP.IL.DatabaseDataReset.csproj" (default target) (11) ->
  D:\a\1\s\PPIL\MC.MP.IL.DatabaseDataReset\MC.MP.IL.DatabaseDataReset.csproj(123,5): error : This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them.  For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is ..\packages\Microsoft.VisualStudio.SlowCheetah.3.1.66\build\Microsoft.VisualStudio.SlowCheetah.targets.

I am unsure of exactly the problem. It could be because we have a mixed project. It could be because the file structure. I don't know what options or settings I would need to set in the cake commands for build or restore. It could also be when I run this locally, I run it in the same folder as the Cake script, but it appears to be running in the root folder for my repo which is one folder up from the solution folder for this solution.

Where in my script am I going wrong? My restore step seems fine except it only restores the UnitTests project (which does depend on all other projects). Is it the restore? Is there a setting I am missing in the build or the restore? Thanks in advance.

2
Is it possible that you're not doing Nuget restore on your .Net framework dependencies? It looks like your "restore" task is only restoring the .Net Core packages... It may also explain why it "works on your machine" - you already have all dependencies installed - maybe you can try on a clean VMAmittai Shapira

2 Answers

2
votes

So the answer was that I had get all of the project files and run "NuGetRestore" method on each of them excluding the .NET Core UnitTests project. Then I can run the DotNetCoreRestore method which just restores the .NET Core UnitTests project.

I also found I should clean the packages directory as that is good practice.

0
votes

As you can see in How to restore only specific Solution Folder with msbuild command you can use specific .proj file two distinguish those projects and work with them very easily

But I suggest you use below command to restore all your projects without any problem, if you have visual studio 2019

        MSBuildSettings settings = new MSBuildSettings
        {
            ArgumentCustomization = args =>
                .Append("-p:RestoreUseSkipNonexistentTargets=false")
                .Append("-p:RestorePackagesConfig=true"),
            ToolPath = msBuildPath
        };

        MSBuild("YourSolution.sln", settings.WithTarget("restore"));

With above code you can restore all projects regardless of project type and .Net framework or .Net core