Configuration Transformation - Automatically transform local configuration - visual-studio

I am looking for a hopefully ready, out of the box solution for my problem here. Here is outline:
I would like to have a file named local.config that contains certain information about my local environment.
That file will be ignored and will never make its way to the build server (ignored from gitHub).
Whenever I build locally, transformation happen.
Whenever I build on the server, whatever information found in main app.config is used.

Both SlowCheeta and Configuration Transform should work for your needs.

Here is what I ended up doing and there is probably better ways to do what I was after but unfortunately (and the fault is on me for not formulating the question correctly).
Modify the cproj file with the following:
<UsingTask TaskName="TransformXml" AssemblyFile="$(MSBuildExtensionsPath)\Microsoft\VisualStudio\v10.0\Web\Microsoft.Web.Publishing.Tasks.dll" />
Place your config files and transforms into your project accordingly. Every time you build, the configuration is transformed just fine.
I did not like that fact I had to have an extra base.config file but apparently, transforming from source directly to the target makes the msbuild rather upset.

Related

Azure Pipeline File Transformation is not working. Why?

I'm still trying to create my first Azure Pipeline CI / CD. My CI part is working fine, my CD is also working except I cannot apply my Web.config file transformations.
Let me first show you what I have then I will ask several questions below. The build with generated artifact. I also copy manually my 3 config files.
Wen I open my WebAPI.zip file here is the path and content:
Here is my pipeline project
And the details of my staging phase:
When I run this full pipeline my config file is never transformed but I get no error. I just get a
2019-05-02T03:27:23.5778958Z ##[warning]Unable to apply transformation
for the given package.
I also have the debug log with full information but it doesn't give me much information for now. I will add it here later.
Questions
Azure Pipeline File Transformation is not working. Why?
Is it because the File Tranform task only look for config file in zip?
Is this system then just ignoring my tranformation file in root of artifact?
So I think my manual copy of config transformation file is obsolete?
How can I then add my transformation file into my zip?
In my csproj I already set all my tranformation files on Build action content, copy always, this is ignored too, is it normal?
EDIT 1
One more important question: Is it possible to simply ask the deployment system to ignore or not deploy my config file. It is not something I want to deploy every time. I like the idea I have to do it manually or from alternative deployment system. With this solution I can have some other issues if I save a version or build variable in my config file. Then is it possible to modify a already deployed file after deployment? I'm looking for workaround here. Example: I read a value in my existing config file then I increment this value by one or simply replace this value with another?
EDIT 2
I'm now able to add the config file to the WebApi.zip package on root and/or in bin folder. I followed the comment of Shayki Abramczyk bu using the xml transform of deploy. Still not working. And the errors messages are so poor. Seriously Microsoft? Is your transformation system even working? I see question similar to mine everywhere.
And now I get
The file is correct, transform works fine from Visual Studio Publish tool. I really think the xml transform tool from Microsoft in Azure is just not working.
EDIT 3
Is it possible to issues from my transformmations come from NLog because of the name and then special rule I apply on it?

Can multiple build configs share one config transformation?

I'm using SlowCheetah for XML transforming a bunch of config files in a project.
However, this same solution is part of a load balanced setup, where some config values differ between the different servers (two, in this case).
I have the following build configs
Debug
Release
Release.Test
Release.Prod1
Release.Prod2
Almost everything in Release.Prod1 and Release.Prod2 is identical, except for some values in one of the config files. Is there any way I can have a file like Something.Release.Prod.Config to be used on both of these build configs instead of having two identical files (Something.Release.Prod1.Config and Something.Release.Prod2.Config)?
...and to elaborate: In this case I am deploying to two environments, so one duplicated file is not really a huge crisis. What if you have ten or a hundred servers? I see no reason why a setup with a CI-server (Specifically TeamCity in this case) should not be able to do this, even though I suppose more customized setups are common in such environments.
How is this usually handled?
I suppose I can do some magic copying of files back and forth as a build step before the actual transformation happens, but this seems like a messy and overly complicated solution.
The configuration transformations are handled by the $(Configuration) variable in the TransformsFiles.targets file.
<TransformXml Source="#(_FilesToTransformNotAppConfig->'%(FullPath)')"
Transform="%(RelativeDir)%(Filename).$(Configuration)%(Extension)"
Destination="#(_FilesToTransformNotAppConfig->'$(OutDir)%(RelativeDir)%(Filename)%(Extension)')"
Condition=" Exists('%(RelativeDir)%(Filename).$(Configuration)%(Extension)') " />
Here, you can change $(Configuration) to be any other value, like "Environment". Then just set the "Environment" variable in your MSBuild args -
/p:Environment=Prod
This should allow you to keep your build settings and do your transforms independently.

Managing VS2010 References With CopyLocal=False

I'm trying to improve our build process, and to that end I've been looking at turning off copy local and having the whole solution build to a common \bin directory.
What however, is best practise for getting the no longer copied references into the bin directory? I don't want to do this in one of the actual implementation projects as many of them use the same referenced components, and it will mean a proliferation of post build steps.
I know I could create a custom msbuild file but then that would need to be run manually outside of visual studio (I think)? which seems like friction. Is there a way I can create an msbuild project for example, and then have that as part of my solution.
Or is it best just to manage this outside my solution build and have a copy_references.bat file which the dev has to run once to setup their environment getting them into the /bin/debug and /bin/release directories? This seems a bit fragile, but better than checking /bin and the files into svn directly.
One idea I've had is to create an empty c# component project and add the references to it, with copy local turned on. If this was then made a dependency of all other projects it would manage the copying.
Next question is how to manage this with nuget references? My preference is to not check the references into svn, but tell nuget to grab them. So this would also need to be a build step, but again at the solution level.
Additional Info
For a bit more background on why I am evaluating this approach, have a look here:
http://www.ndepend.com/Res%5CNDependWhiteBook_Assembly.pdf
The goal is to massively speed up compilation time by stopping all these redundant copies. Also side benefits if it works might be not having to manually work around the times dependency evaluation doesn't work. Causing one to have to pull referenced assemblies' dependencies into your top level project to ensure they end up in the bin folder.
I suppose in some ways the desire to turn off copy local is an artifact of the inefficiency of the ms build process at both tracing dependencies and evaluating the need to copy things.
You can override the $(OutDir) property globally and keep CopyLocal enabled. Since every project is copying to the same $(OutDir), you won't end up with too much duplication. This is pretty straight forward.
Much more involved, you can also create a shared import file that wires into the standard build and performs a custom post-build deployment. For example,
<Target Name="Deploy"
DependsOnTargets="Deploy)"
AfterTargets="Build">
... copy all output files ...
e.g. use wildcards $(OutDir)\*.dll
e.g. $(OutDir)\$(TargetName)$(TargetExt)
e.g. copy referenced assemblies and copy, see below
</Target>
To get the references, you can call the ResovleAssemblyReferences target and use Returns, or create your own target to get a specific collection as shown in the answer here,
Return the ReferenceCopyLocalPaths from <MSBuild> task
It can be rather involved, but easily configured if you can declare your own "rules" in an item array with metadata.

How to emulate /p msbuild parameter in Visual Studio build?

That the logical follow-up for the my previous question: "How to check all projects in solution for some criteria?"
I was given quite a good answer to use CustomAfterMicrosoftCommonTargets, CustomBeforeMicrosoftCommonTargets. They do work, so I decided not to stop in the middle.
Issue is that I don't want machine-wide tasks. It's not a good idea neither for me (it will affect other builds. sure, this can be handled, but still), nor for my teammates (I don't want to let them put something in system folders... ), nor for build server.
What is needed: solution to be built from scratch out of source control on clean machine with either Visual Studio or MSBuild.
It appeared that Custom*MicrosoftCommonTargets are regular properties.
So, how to specify this property? It works pretty fine when to set it from command line.
That's strange, but it appears that bit of magic present here: property passed as command line parameter to one build is transitively passed to all nested builds!
That's fine for build server. But this won't work with Visual Studio build. And even declaring solution-level property won't help: neither static, nor dynamic properties are transfer to nested builds.
...I have a hacky idea to set environment variable on before solution build and erase it on after. But I don't like it. Any better ideas?
I use a bit different technique then #Spider M9. I want that all projects in solution tree/all subdirectories from current directory use extended build throw Custom*MicrosoftCommonTargets. I don't like to be forced to change every new project to import custom targets/props.
I place special file, let's say msbuild.include, in the root directory and my custom targets loader for every project tries to find it in ., ..\, ..\..\, and so on. msbuild.include contains flags that triggers execution of custom actions. If loader can't find this file it disables loading all custom targets and stoppes. This gives me ability to use my build extensions with projects from work repositories and to not use with opensource projects.
If you are interested in I can publish loader. It's a pretty simple and elegant solution.
For example I can sign any assembly in all projects in all subfolders with my key.
I always set up every project to import a standard .props file. Use the GetDirectoryNameOfFileAbove property function (see MSDN) to find it. Do this as the first line of every project file. Once established, you can redirect from that file to other imports. Another trick is to have that standard import (that would obviously be under version control) import conditionally another .props file only if it exists. This optional file would not be in version control, but is available for any developer to create and modify with their own private/temporary properties or other behavior.

CruiseControl.NET Emails not containing build results or errors

I have some failing builds and the build data is missing from the emails sent from CCNET?
It contains tests run and modifications but no build or error data?
I don't think I have messed up the xsl's.. any thoughts?
UPDATE :
Yes i've looked at
http://confluence.public.thoughtworks.org/display/CCNET/Email+Publisher
and Yes in the publishers section i've called xmllogger before email
UPDATE :
I'm not sure if this means anything but.. in the compile.xsl it looks for
/cruisecontrol//buildresults//message
but there is no 'buildresults' node??
It just goes..
cruisecontrol --> build --> msbuild (then warnings, project, messages etc etc)
UPDATE :
Have the following in ccservice.exe.config. No mention of msbuild??
xsl\header.xsl
xsl\compile.xsl
xsl\unittests.xsl
xsl\fit.xsl
xsl\modifications.xsl
xsl\fxcop-summary.xsl
-- Lee
I had a similar problem yesterday with a new install of cruisecontrol as a service.
Make sure you have specified the correct xsl files in the ccnetservice.exe.config (if you are running the service) and ccnet.exe.config if you running the console version.
you need to restart the service/console app once these are updated.
HTH
Edit:
Are you using the standard msbuild logger, or Rodemeyer's one? If you are using Rodemeyer's, you need to use diffrent XSL transforms (msbuild2ccnet.xsl) to normal (compile.xsl, msbuild.xsl). There is a guide for that here
Check that your output is making it to the build log, located in server\<projectName>\artifacts.
If you have modified the xsl, make sure its in the correct folder (webdashboard\xsl and server\xsl). You can test the xsl works fine by copying the build log file (see server\<projectName>\artifacts directory). to a file, and adding the relevant XSL includes to the header then opening the XML file in a web browser)
EDIT:
in the <xslFiles> section of ccservice.exe.config, add another line like this:
<file name="xsl\compile-msbuild.xsl" />
or
<file name="xsl\msbuild.xsl" />
as i am not using the standard logger (you are though), i am uncertain as to which of those is needed. try one, then if that doesnt work, try the other!

Resources