Nuget package restore - Passing in parameters to MsBuild c# API - msbuild

I am looking to write a wrapper for the MSBuild C# api. I have the build all working fine, but for some odd reason I'm struggling to get Nuget package restore to run even when I pass in the parameters.
I am running this in a service that runs as NETWORK SERVICE
The command ""..\.nuget\nuget.exe" install "C:\BuildTemp\application1\packages.config" -source "" -RequireConsent -o "..\packages"" exited with code 1.
Am I passing them in correctly?
var pc = new ProjectCollection();
var buildProperties = new Dictionary<string, string>
{
{"Configuration", "Release"},
{"Platform", "Any CPU"},
{"OutputPath", _outputPath},
{"EnableNuGetPackageRestore", "true"}
};
var buildParameters = new BuildParameters(pc);
var buildRequest = new BuildRequestData("C:\myapplication.csproj",
buildProperties,
null,
new[] { "Clean", "Rebuild" },
null);
UPDATE: this appears to work in some environments and not others. Why would this be?

So I tested out this command on my local machine:
.\.nuget\NuGet.exe install Akavache\packages.config -source "" -RequireConsent -o packages
and I get an error:
Invalid URI: The format of the URI could not be determined.
which I believe is related to this bit:
-source ""
As I can drop that value and have it run again without an error.
Which begs the question, where are the package sources defined?
Inside the NuGet.targets file there's a section like this:
<ItemGroup Condition=" '$(PackageSources)' == '' ">
<!-- Package sources used to restore packages. By default, registered sources under %APPDATA%\NuGet\NuGet.Config will be used -->
<!-- The official NuGet package source (https://nuget.org/api/v2/) will be excluded if package sources are specified and it does not appear in the list -->
<!--
<PackageSource Include="https://nuget.org/api/v2/" />
<PackageSource Include="https://my-nuget-source/nuget/" />
-->
</ItemGroup>
So I propose that when you say it works "in some environments and not others" that you don't have a config file at %APPDATA%\NuGet\NuGet.Config for the service account.
Can you try changing this section in your Nuget.targets file in source control to be:
<ItemGroup Condition=" '$(PackageSources)' == '' ">
<PackageSource Include="https://nuget.org/api/v2/" />
</ItemGroup>
And see if that resolves your issues in the other environments?

Related

Is there a way to force NuGet to restore the latest package version during pipeline execution?

We are using an internal NuGet feed in our Azure DevOps environment to host many different packages, which are consumed in many different projects. I would like to configure the pipeline so that whenever an internal package is referenced, it is always resolved to the latest version. All of the internal references are configured with wildcards in the PackageReference tag of the .vbproj file, like so:
<PackageReference Include="MyPackageName" Version="*" />
And the restore command in the YAML file is configured like so:
- task: NuGetCommand#2
condition: and(succeeded(), eq(variables['ModifiedProject'], 'true'))
displayName: 'NuGet restore'
inputs:
command: 'restore'
restoreSolution: '$(ModifiedProject.Directory)/$(ModifiedProject.Solution)'
feedsToUse: 'select'
vstsFeed: '[guid]/[guid]'
noCache: true
The projects build successfully, but they still end up using the oldest version of the package instead of restoring the newest version. Is there a way to force the restore task to default to the newest package version?
I ended up finding a workaround for this issue by using the Azure DevOps REST API. My objective was to get the pipeline to flow through these basic steps:
After all build steps have been completed successfully, push the new package version into the artifact feed.
Use the REST API to unlist the old package version, leaving only the newest version available.
Because of the use of floating versions in the PackageReference tags, any projects that depend on these packages will then automatically pull the newest version when they are built in their respective pipelines.
I was only comfortable going this route because "deleting" a package in Azure doesn't really delete it, it just gets moved to the Recycle Bin. In the event there is a breaking change that is discovered post-push, we can always restore a previous version to the feed. Given that this process is being used exclusively for our 50+ internal packages with their own testing processes, it definitely seems like a safe route to go, and far more efficient than any other option I can find. However, I don't think I will mark this as a definitive answer to the question, because it still feels a bit hacky and I'd prefer there was a legitimate option to force newest versions in Azure's NuGetCommand#2 task.
Code
As mentioned, I used Azure's well-documented REST API for these functions, particularly the areas governing artifacts. Although there is a page dedicated to deleting a package from a NuGet feed, I couldn't get their specification to work. I ended up inspecting the calls made from the UI and copying those, while still using my own token for authentication. This method does the history "trimming" I needed:
public void TrimPackageFeed(string feedName, string packageName)
{
var packageVersions = GetPackageVersions(feedName, packageName);
var deprecated = packageVersions.Where(x => !x.IsLatest && !x.IsDeleted)?.ToList();
if (deprecated != null && deprecated.Any())
{
foreach (var version in deprecated)
{
var url = $"{version.Links.Feed.Value.Replace("feeds.dev.azure.com", "pkgs.dev.azure.com")}/nuget/packagesBatch";
var payload = new AzurePackagePayload
{
Data = null,
Operation = 2,
Packages = new List<AzurePackagePayloadItem>
{
new AzurePackagePayloadItem
{
ID = packageName,
Version = version.Version
}
}
};
ApiRequest(url, Method.POST, null, JsonConvert.SerializeObject(payload));
}
}
}
I built this as a .NET Core 3.1 command line app, published as a self-contained executable within our build repo. I used C# because it's most familiar to me, but I'm confident this could be scripted in any language (probably even just PowerShell). I then appended the following task to the end of my YAML pipeline definition:
- task: CmdLine#2
condition: and(succeeded(), eq(variables['ModifiedProject'], 'true'))
displayName: 'Trim package feed'
inputs:
script: |
AzureApiClient -action trim-package-feed -feed FeedNameHere -package $(ModifiedProject.AssemblyName)
workingDirectory: 'Azure\AzureApiClient\Output'
failOnStderr: true
The package gets pushed to the feed, then the assembly name is passed to my API client which will trim the historical versions and leaves only the new version available to restore.
If you are using a self-hosted agent to run the pipeline, you can try to clear the local nuget cache, delete all the nuget packages in the global nuget cache under C:\Users\xxx\.nuget\packages or use clean nuget caches.
If the package to be consumed is just pushed into the feed, you need to wait for a while . There has to be a delay in populating packages on the feed.
In addition , you can try to use dotnet restore task to see if this issue still occurs . Here is a ticket with similar issue you can refer to .

Aurelia and webpack during dotnet publish in ASP.NET Core 2.0 and Visual Studio 2017

The ASP.NET Core 2.0 project brings in Aurelia using
au new --here
I want to create the following artefacts when publishing the solution
\wwwroot\dist\app.bundle.js
\wwwroot\dist\vendor.bundle.js
I can achieve this by manually running
npx webpack --config webpack.netcore.config.js
But I would like to kickoff webpack builds when I publish:
dotnet publish -c Release
My ultimate aim is to have VSTS CI/CD process use MSBuild to automatically bundle the SPA files as required above.
Please note, during development I am already using hot module replacement via
using Microsoft.AspNetCore.SpaServices.Webpack;
And
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
app.UseWebpackDevMiddleware(new WebpackDevMiddlewareOptions
{
HotModuleReplacement = true,
ConfigFile="webpack.netcore.config.js",
HotModuleReplacementClientOptions = new Dictionary<string,string>{
{"reload", "true"}
}
});
}
This works as expected. But now I need to achieve the same during publishing.
As a quick fix I've added a post-build event
<Target Name="PostBuild" AfterTargets="PostBuildEvent">
<Exec Command="npx webpack --config webpack.netcore.config.js" />
</Target>
How do I get the custom MSBuild RunWebpack target explained here?
So I also ran into the same issue. I noticed that in the webpack.config.js file it had the following lines:
output: {
path: outDir,
publicPath: baseUrl,
filename: production ? '[name].[chunkhash].bundle.js' : '[name].[hash].bundle.js',
sourceMapFilename: production ? '[name].[chunkhash].bundle.map' : '[name].[hash].bundle.map',
chunkFilename: production ? '[name].[chunkhash].chunk.js' : '[name].[hash].chunk.js'
},
But in the webpack.netcore.config.js file it had:
config.output.filename = '[name].bundle.js';
So when you publish it, it expects .net core to copy the app.bundle.js and vendor.bundle.js files but they aren't there, because webpack has it under a different file name due to caching purposes.
So replace that line with the following:
config.output.filename = '[name].[chunkhash].bundle.js';

update Migration Command Fails for ConfigurationDbContext and PersistentGrantDbContext

I have been trying to get IdentityServer4 version 1.5.2 to work for a few days now without success. I am using VS2017
My Entity classes,DataContexts, repositories and migrations are resident in a .Net Standard Library (1.6). So far so good except when I run update-migration command for "PersistenGrantDbContext" and "ConfigurationDbCOntext". I get the error message
Could not load file or assembly 'System.Data.SqlClient, Version=4.1.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a'. The system cannot find the file specified.
The datacontext classes that i created myself dont seem to have this problem after implementing "IDbContextFactory" interface
Here I have the implementation for the two culprits
public class TemporaryDbContextFactoryScopes : IDbContextFactory<PersistedGrantDbContext>
{
public PersistedGrantDbContext Create(DbContextFactoryOptions options)
{
var builder = new DbContextOptionsBuilder<PersistedGrantDbContext>();
builder.UseSqlServer("Server=-------;Database=-----------;Trusted_Connection=True;MultipleActiveResultSets=true",
optionsBuilder => optionsBuilder.MigrationsAssembly(typeof(UserDbContext).GetTypeInfo().Assembly.GetName().Name));
return new PersistedGrantDbContext(builder.Options, new OperationalStoreOptions());
}
}
public class TemporaryDbContextFactoryOperational : IDbContextFactory<ConfigurationDbContext>
{
public ConfigurationDbContext Create(DbContextFactoryOptions options)
{
var builder = new DbContextOptionsBuilder<ConfigurationDbContext>();
builder.UseSqlServer("Server=---------;Database=--------;Trusted_Connection=True;MultipleActiveResultSets=true",
optionsBuilder => optionsBuilder.MigrationsAssembly(typeof(UserDbContext).GetTypeInfo().Assembly.GetName().Name));
return new ConfigurationDbContext(builder.Options, new ConfigurationStoreOptions());
}
}
I have installed the latest version of System.Data.SqlClient still not working
Just wanted to share what I did to get things rolling. Not sure if that is the right approach though
First I did this in the class library .csproj
<DotNetCliToolReference Include="Microsoft.EntityFrameworkCore.Tools.DotNet" Version="1.0.1" />
<DotNetCliToolReference Include="Microsoft.Extensions.SecretManager.Tools" Version="1.0.1" />
which turned out to be a bad idea because that was throwing out that error now without it running my migrations with my web app as my start up project return the error "Not context blah blah with name blah blah found"
So I realised contexts that I created myself worked without glitches so I did this for PersistentGrantDBCOntext and COnfigurationGrantDbContext
public class PGrantDbContext: PersistedGrantDbContext
{
public PGrantDbContext(DbContextOptions<PersistedGrantDbContext> options, OperationalStoreOptions storeOptions) : base(options, storeOptions)
{
}
}
and
public ConfigDbContext(DbContextOptions<ConfigurationDbContext> options, ConfigurationStoreOptions storeOptions):base(options,storeOptions)
{
}
and everything went smoothly.
Just not so sure if it is the right approach though
I was also in a similar situation few weeks ago and here's how I solved it.
Very similar to yours, I have two projects called Company.Identity (.NETCoreApp) as my Identity Project and Company.Identity.Data (.NETStandard 1.6) for migrations. I Use Company.Identity Project as the startup project for migration purposes as it is in the same solution as my data project and I didn't want to clutter the solution with yet another project just as a startup project for migrations.
I followed the tutorial in here.
The cli tool reference <DotNetCliToolReference Include="Microsoft.EntityFrameworkCore.Tools.DotNet" Version="1.0.1" /> is in my Company.Identity.csproj file.
I followed all the steps in the above tutorial except for the following difference
In ConfigureServices method in the Company.Identity Startup class, I have set the migrationsAssembly to Company.Identity.Data
var migrationsAssembly = "Company.Identity.Data";
Note that Company.Identity project has already got IdentityServer4.EntityFramework nuget package installed. This enabled me to add the migration for PersistedGrantDbContext. But when I tried to run migration for ConfigurationDbContext it gave me a build error. This was because the migrations generated for PersistedGrantDbContext requried IdentityServer4.EntityFramework nuget package. So I had to install that in the Company.Identity.Data project
I was able to add migrations using the following commands after above changes through command prompt in my Company.Identity project.
dotnet ef migrations add InitialIdentityServerPersistedGrantDbMigration -c PersistedGrantDbContext -o Migrations/IdentityServer/PersistedGrantDb -p ../Company.Identity.Data
dotnet ef migrations add InitialIdentityServerConfigurationDbMigration -c ConfigurationDbContext -o Migrations/IdentityServer/ConfigurationDb -p ../Company.Identity.Data
Hope that helps
this may help you specially if you have docker-compose in your project. i was able to resolve this issue by removing the docker-compose project and then creating the migrations then adding it again.
https://stackoverflow.com/a/60320410/4977086

MSBuild 15: The "Error" task could not be instantiated

I'm attempting to programmatically build a project which uses C#7, and therefore MSBuild 15, but this task is failing seemingly because of mismatched assembly references.
Here is my code:
string projectFilePath = Path.Combine(args.Any() ? args.First() :#"C:\Users\newsoni\Documents\Visual Studio 2017\Projects\ConsoleApp2\ConsoleApp2.sln");
ProjectCollection pc = new ProjectCollection();
Dictionary<string, string> globalProperty = new Dictionary<string, string>();
globalProperty.Add("Configuration", "Debug");
globalProperty.Add("Platform", "x86");
BuildParameters bp = new BuildParameters(pc);
bp.Loggers = new ILogger[] { new Logger(), new ConsoleLogger(), };
BuildRequestData BuidlRequest = new BuildRequestData(projectFilePath, globalProperty, "4.0", new string[] { "Build" }, null);
BuildResult buildResult = BuildManager.DefaultBuildManager.Build(bp, BuidlRequest);
Here is the error message:
C:\Users\newsoni\Documents\Visual Studio 2017\Projects\ConsoleApp2\ConsoleApp2.sln.metaproj : error MSB4127: The "Error" task could not be instantiated from the assembly "Microsoft.Build.Tasks.v4.0, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a". Please verify the task assembly has been built using the same version of the Microsoft.Build.Framework assembly as the one installed on your computer and that your host application is not missing a binding redirect for Microsoft.Build.Framework. Unable to cast object of type 'Microsoft.Build.Tasks.Error' to type 'Microsoft.Build.Framework.ITask'.
C:\Users\newsoni\Documents\Visual Studio 2017\Projects\ConsoleApp2\ConsoleApp2.sln.metaproj : error MSB4060: The "Error" task has been declared or used incorrectly, or failed during construction. Check the spelling of the task name and the assembly name.
Here is a link to a project you can use to recreate the issue:
https://drive.google.com/a/xibis.com/file/d/0B-mqMIMqm_XHcVRJQmtxQkd1b3c/view?usp=sharing
You will have to change the path in the code to a project on your own machine, but it doesn't seem to matter if this is a VS 2017 project or earlier.
One other thing that may or may not be relevant, I noticed that the Microsoft.WebApplication.Build.Tasks.Dll in this folder:
C:\Program Files (x86)\MSBuild\Microsoft\VisualStudio\v15.0\WebApplications
Still seems to be referencing Microsoft.Build.Framework.dll version 14, not 15 as I would have expected.
It turns out there are two issues in my test project. The first is due to the naming of the project.
However there is a second issue which is due to the references not being correct. To use MSBuild 15 programmtically you must install the following packages:
Install-Package Microsoft.Build -Version 15.1.1012
Install-Package Microsoft.Build.Framework -Version 15.1.1012
Install-Package Microsoft.Build.Tasks.Core -Version 15.1.1012
Install-Package Microsoft.Build.Utilities.Core -Version 15.1.1012
Install-Package Microsoft.Net.Compilers -Version 2.2.0
There is one more step which is nuts and completely undiscoverable. You must now add a reference to this DLL which should be relative to your solution folder:
packages\Microsoft.Net.Compilers.2.2.0\tools\Microsoft.Build.Tasks.CodeAnalysis.dll
I opened a support ticket with Microsoft and they have confirmed that this is a bug in Visual Studio 2017.
They are aiming to get a fix for this into update 3 for Visual Studio, but this may slip.
This issue tracks the bug:
https://github.com/Microsoft/msbuild/issues/2194
There is no workaround at present for this API, but you can invoke the MSBuild exe using Process as an alternative.
If you have MSBuild installed on your PC, either directly or through Visual Studio, the proper fix is to use the package Microsoft.Build.Locator which will find that installed version and execute the build using it.
Install these packages
Microsoft.Build
Microsoft.Build.Framework
Microsoft.Build.Locator
The first 2 are needed so that the code can compile but should be excluded from the project output.
In your application startup add the following line of code, this only has to run once.
Microsoft.Build.Locator.MSBuildLocator.RegisterDefaults();
Remove any additional binding redirects in your app.config that are specific to Microsoft.Build or other build libraries. The call to the Microsoft.Build.Locator assembly will ensure that these redirects take place automatically.
References
Update an existing application for MSBuild 15
Github MSBuildLocator.

How to set up TeamCity to use own HTTP authenticated NuGet service?

a problem is that TeamCity is unable to authorize into NuGet service which runs on same TeamCity instance.
Below you can find how the Build configuration looks now:
I also added Build Feature for NuGet Credentials:
With this configuration I receive following errors in log:
Restoring NuGet package Nuget.Package.Name.0.1.0.41.
Please provide credentials for: http://teamcity-nuget-server.cloudapp.azure.com/httpAuth/app/nuget/v1/FeedService.svc
UserName: GET http://www.nuget.org/Packages(Id='Nuget.Package.Name';,Version='0.1.0.41')
NotFound http://www.nuget.org/Packages(Id='Nuget.Package.Name';,Version='0.1.0.41') 194ms
GET http://www.nuget.org/FindPackagesById()?id='Nuget.Package.Name';
NotFound http://www.nuget.org/FindPackagesById()?id='Nuget.Package.Name'; 105ms
WARNING: Unable to find version '0.1.0.41' of package 'Nuget.Package.Name'.
C:\Windows\system32\config\systemprofile\AppData\Local\NuGet\Cache: Package 'Nuget.Package.Name.0.1.0.41' is not found on source 'C:\Windows\system32\config\systemprofile\AppData\Local\NuGet\Cache'.
C:\Windows\system32\config\systemprofile\.nuget\packages\: Package 'Nuget.Package.Name.0.1.0.41' is not found on source 'C:\Windows\system32\config\systemprofile\.nuget\packages\'.
http://teamcity-nuget-server.cloudapp.azure.com/httpAuth/app/nuget/v1/FeedService.svc: Unable to load the service index for source http://teamcity-nuget-server.cloudapp.azure.com/httpAuth/app/nuget/v1/FeedService.svc.
Cannot prompt for input in non-interactive mode.
http://nuget.org: The V2 feed at 'http://www.nuget.org/FindPackagesById()?id='Nuget.Package.Name'' returned an unexpected status code '404 Not Found'.
Errors in packages.config projects
Unable to find version '0.1.0.41' of package 'Nuget.Package.Name'.
C:\Windows\system32\config\systemprofile\AppData\Local\NuGet\Cache: Package 'Nuget.Package.Name.0.1.0.41' is not found on source 'C:\Windows\system32\config\systemprofile\AppData\Local\NuGet\Cache'.
C:\Windows\system32\config\systemprofile\.nuget\packages\: Package 'Nuget.Package.Name.0.1.0.41' is not found on source 'C:\Windows\system32\config\systemprofile\.nuget\packages\'.
http://teamcity-nuget-server.cloudapp.azure.com/httpAuth/app/nuget/v1/FeedService.svc: Unable to load the service index for source http://teamcity-nuget-server.cloudapp.azure.com/httpAuth/app/nuget/v1/FeedService.svc.
Cannot prompt for input in non-interactive mode.
http://nuget.org: The V2 feed at 'http://www.nuget.org/FindPackagesById()?id='Nuget.Package.Name'' returned an unexpected status code '404 Not Found'.
NuGet Config files used:
C:\Windows\system32\config\systemprofile\AppData\Roaming\NuGet\NuGet.Config
Feeds used:
C:\Windows\system32\config\systemprofile\AppData\Local\NuGet\Cache
C:\Windows\system32\config\systemprofile\.nuget\packages\
http://teamcity-nuget-server.cloudapp.azure.com/httpAuth/app/nuget/v1/FeedService.svc
http://nuget.org
I tried several other configurations, i.e using %teamcity.nuget.feed.server% and even %teamcity.nuget.feed.auth.server%. I also tried to remove build feature with NuGet credentials (since documentation says it doesn't need to authenticate with self hosted NuGet service). Tried to remove http://nuget.org source as well. Nothing works.
There are several issues in TeamCity: one with NuGet version 3.3.0 and higher: https://youtrack.jetbrains.com/issue/TW-44438 and the second with local agent: https://youtrack.jetbrains.com/issue/TW-44479. Please check the tickets linked. You can try to use earlier NuGet version or try the workaround.
I think your problem is that you are using NuGet 3 but the package source is pointing to the v2 Feed.
Update your "NuGet.config" (C:\Windows\system32\config\systemprofile\AppData\Roaming\NuGet\NuGet.Config) with the following package sources:
<packageSources>
<add key="NuGet official package source" value="https://api.nuget.org/v3/index.json" />
</packageSources>