Azure Devops Publish - Wrong AppSettings.JSON is Published - azure-devops

In my repo I have a .net 5 web application project that (for now) references another library that is setup as an executable also. Both of these project have their own appsettings.json.
When I publish, I notice that the appsettings.json that ends up in the final folder is always the one from the project being referenced and not the one from the project actually being published. This seems truly odd behavior.
I realize the "right" approach is for the web app to not directly reference the other exe project (already have a story to fix that), but it is still a current concern.
Is there a command argument to have publish prefer appsettings.json from the project being published, as opposed to what seems like arbitrarily selecting one of multiple (or preferring the file from a lower dependency)?
For now, I suspect I can add an additional step to my build to copy the correct config file into place before the publish is "complete", but hoping for a better solution (one that doesn't require extra copy file steps).

Is there a command argument to have publish prefer appsettings.json from the project being published, as opposed to what seems like arbitrarily selecting one of multiple (or preferring the file from a lower dependency)?
The best solution is definitely to find the cause of this issue.
For example, if I add following setting in the project file actually being published:
<ItemGroup>
<Content Update="appsettings.json" CopyToPublishDirectory="Never" />
</ItemGroup>
Then the dotnet will publish the file appsettings.json from the project being referenced.
Of course, the cause of your problem may be other possibilities, which requires more actual information about your project to be able to know.
So, the current solution for this issue, you could add above settings for the project being referenced.
With above setting, the file appsettings.json from the project being referenced will not be published.

Related

How to fix "Type or namespace name 'X' does not exist in the namespace 'Y'" error in Azure Devops

I am working in Azure Devops with a build pipeline for an ASP.NET web app.
Most settings leading up to the issue are pretty much the default settings, aside from the msbuild arguments in the build solution task, the build number, a powershell script at the beginning that should only be updating the version number, a command line task that I know isn't the cause since I added it after I first encountered the problem to deal with something else, and a couple of command line tasks simply displaying the contents of the D: folder.
The msbuild arguments are:
/p:DeployOnBuild=true /p:WebPublishMethod=Package /p:PackageAsSingleFile=true
/p:SkipInvalidConfigurations=true
/p:PackageLocation="$(build.artifactstagingdirectory)\\"
/p:UseWPP_CopyWebApplication=true /p:OutDir="$(build.artifactstagingdirectory)"
/p:Version=$(buildNumber)
The NuGet restore task is pointed to a feed in my Artifacts. The feed contains MyPackage.problem, MyPackage.problem.blah (where blah represents several different names), MyPackage.Other1, MyPackage.Other2, MyPackage.Other3, MyPackage.Other4, and 3 other packages. It's also getting a few packages from Nuget.org.
Everything seems to work fine until the build step, when I get the error
The type or namespace name 'problem' does not exist in the namespace
'MyPackage' (are you missing an assembly reference?)
My first attempt to troubleshoot involved looking inside the problem packages, and they were significantly different from the other packages: they had a .csproj file and several .cs files in the main directory, as well as a few folders that the other packages didn't have, though the names and numbers differed between them, and they were missing a lib folder. The other folders all seemed to be in order.
Update: not sure if this is relevant, but I took another look at the .nuspec files. I compared the .nuspec file from the MyPackage.problem made in Azure Devops and compared it to a properly structured version from before we began switching over to Azure Devops (and before I was working on the project) and the .nuspec file from the unpacked repository. They were identical, except in the first line the package made in Azure Devops had the following:
<?xml version="1.0" encoding="utf-8"?>
While the others had:
<?xml version="1.0"?>
From what I've found online, the "encoding="utf-8"" is normally present, but the fact that it was absent in both the unpacked repository file and the properly structured package makes me think it might potentially be relevant somehow.
I finally managed to figure it out, or at least it seems I did. The problem seemed to be that I was trying to use the Nuget Pack task to create the packages from the .nuspec files in the project which resulted in multiple separate packages due to the lack of a global .nuspec file. I talked to my superior and asked how the packages were made normally, outside of Azure Devops, and he pointed me towards instructions detailing how to create a package from a .dll file. Using a command line script task, I ran
nuget spec -AssemblyPath [path to .dll]
then used a copy files task to copy the .dll files (which had been created during the build solution task) from the build.artifactstagingdirectory to a lib/net40 folder in the working directory. After that, I ran the Nuget pack task, targeting the .nuspec file created by the command line script, and the package was created successfully with the correct structure, aside from including the other folders that had been in the working directory, but these didn't seem to hinder the functionality, and it would likely be fairly simple to exclude them if needed.

Azure DevOps - Using a secure file to store secrets referenced by app.confg

Context
creating an sdk that uses AWS DynamoDb in .NET 4.7.2. In my test project, I have an app.config file that references a secrets.confg file that stores my AWS keys. The secrets config is not included in any commits, for obvious reasons. However, I've uploaded secrets.config to my Library in DevOps as a "secure file". I also have a "download config file" task in the build process that downloads secrets.config to Agent.Temporary
Issue
I don't understand how modify the build process to "pick up" my secrets.config file so that when running my tests, the test project's app.config file knows where to look for secrets.config.
I've looked over a lot of documentation and I can't find exactly how to do this.
I figured this out by using a couple of tasks within the Build Configuration.
I added a Download Secure File task to download my app.config from the Library. And then setup a Copy Files task for each project that needed the app.config.
Each task set:
Source Folder to "$(Agent.TempDirectory)"
Contents to "app.config"
Target folder to "$(Build.SourcesDirectory)\Project.Tests\"
In the end, it wasn't any more complicated than that. I hope this will help others...

How do I build a VSTS project with an absolute-path reference folder?

I have two projects in TFS, WebSite and Reference, and they follow the structure:
$\
WebSite: Main project to be built
Reference: Repository with many referenceable dlls.
Website.dll uses dlls existing at Reference but, for several reasons, they are not contained in the same solution, and may be mapped to different folders that do not follow the VSTS structure.
So, in order to have the Website project compiling locally, the Reference's.dlls Hintpath at Website.csproj have been manually changed to a specific, absolute path, common to all developers' machine.
Now, we're experiencing with CI/CD, and we're thrilled with the hypothesis of having VSTS doing the dirty, tedious work of building/deploying. Thing is, since Reference.dll is not in the same project as Website, building ends up lacking essential libraries (the aforementioned Reference folder) and fails.
Is there a way of telling VSTS to GET Reference's dlls (which are compiled at this point), copy them to the directory Website.csproj is being built at and let them be used to build the main project?
What I've tried:
First:
Map Website and Reference in the Get Sources step
Using a Copy Files task, set Source FOlder as $\References and Target Folder as $(Agent.BuildDirectory)
Build
Now:
Added all the references in the main project.
In both cases, none of the references are found, and the
The type or namespace name '(namespacehere)' could not be found (are you missing a using directive or an assembly reference?)
errors are thrown.
I've been searching through the vsts help section, but can't seem to find any obvious solutions.
Any help is greatly appreciated.
It’s mainly caused by the Reference's dlls are not added in source control (TFVC repo).
First, please make sure you add the Reference's dlls into the website project. So the project file will contain the reference as below (ClassLibrary1.dll as the reference in below example):
<Reference Include="ClassLibrary1">
<HintPath>..\..\ClassLibrary1\ClassLibrary1\bin\Debug\netstandard2.0\ClassLibrary1.dll</HintPath>
</Reference>
Then you can use any of below options to make the referenced dlls work.
Option 1: add the referenced dlls into source control
If you have added .tfignore file into your TFVC repo, it will ignore files and folders under **\bin, so the reference dlls not checkin to TFVC repo by default. You can follow below options to checkin the reference dlls into TFVC repo:
Exclude the reference dlls in .tfignore
Exclude the dlls you want to refer in .tfignore. The format is:
!**\referencename.dll
Such as !**\ClassLibrary1.dll.
Add the reference dlls into source control
In VS -> Source Control Explorer -> Add items to folder -> selected the dlls.
Checkin and double check the dlls are added into TFVC repo
In VS pending changes window, there will show the dlls and the .tfignore file as Inculded changes, checkin the changes.
And double check the dlls are added into TFVC repo in VSTS web page.
Option 2: build the reference project before building website project
If you do not want to add the dlls into source control, you can also build the reference solution firstly so that the reference dlls will generate before build the website project. Details as below:
Edit build definition -> add VS Build task (specify reference solution) before building website project -> Save and queue the build.
Note: for option 2, the build configuration you specified in the relative path should be consistent with the build configuration in VSTS build definition.
Such as I specified Debug in the relative path ..\..\ClassLibrary1\ClassLibrary1\bin\Debug\netstandard2.0\ClassLibrary1.dll. So in my VSTS build definition, VS build task to build the reference project, the build configuration must be Debug.
Now, no matter which option you are using, VSTS build will not show the error message The type or namespace name '(namespacehere)' could not be found.
The correct way to approach this is to not store references in source control. Turn them into packages, store them in a package management feed, and restore them during build. Developers will automatically restore them on build.

Build Workspace mapping

I got two solution setting at same location. This two solution are sharing some of the projects along with some dedicated ones.
I have created two separate build definition with gated check in trigger but issue is that when I make any change in one solution it triggers both the build definition.
Can I somehow control the triggering of the build definition based on the solution that I am checking in?
You need to configure your workspace correctly for this to work. Any change in a Build definition's mapped workspace will cause a build to trigger. Due to this, it completely depends on your source control layout, whether it's possible to setup a build that only triggers when something changes that belongs to either solution.
This setup will become very hard to manage quite quickly, as such I recommend you put each set of projects in their own subfolder, that makes it a lot easier.
So ensure that you build definitions won't both trigger, open the Source Settings panel of your build definition and apply a cloak rule to each file or folder by changing "active" in the first column to "cloaked".
To cloak a file you need to enter its full path in TFS, the UI will only offer you a folder picker, but entering a path to a file will work.
These files should:
Not be needed to build the solution
and changes to should not trigger the build.
Do note that the cloak will cause Team Build to not get these files on the Build agent, so it's not possible to have files your build depends on, but not trigger the build when these files change.
You should create gated check-in build definitions per project not per solution.

TFS automated build + nuget package restore + shared projects in different solutions

I have a solution that contains shared projects with nuget package restore.
I have a second solution that references projects from the first solution.
I am trying to set up TFS to build the second solution, but it doesn't find references for the projects in shared solution because the packages folder for the first solution is in a different location than that of the second solution. I've included the first solution in the build, but now the build configuration doesn't exist in that solution.
First of all, it sounds as if the shared projects could be packaged themselves and as such be shared across these two solutions.
However, if you really don't want to do that, you might try the use the following NuGet commandline parameters and tweak the nuget.targets file in such way that they both point to the same package install directory. (note: you'll have to manually update the project references as well to point to the new packages location)
nuget.exe install -o "d:\some\dir"
You can simply modify the element in the nuget.targets file, or add this element in the csproj file's PropertyGroup with your own custom value.
<PropertyGroup>
<PackageOutputDir>d:\some\dir</PackageOutputDir>
</PropertyGroup>
One last remark: the output location path has to be the same on the client development machine as on the TFS build agents or it won't work.