Teamcity: Pass Environment parameter to dependent build - build-process

I use two build configurations.
Root
Sub
The buildfile for 'Sub' requires a environment parameter 'Param' to run. Can I pass this parameter from my 'Root' configuration to the 'Sub' configuration in Teamcity.

Each build configuration has a configuration code i.e. bt123
Let's say your Root configuration has the code, bt123, and has a variable called java_dir
Your Sub configuration, can reference it like this
Name: JAVA_DIR
Value: %dep.bt123.env.JAVA_DIR%
The easiest way to do this, is to select the small box with lines in the right of the text field, "Value". This will provide a drop list where you should be able to find the variable from bt123.. Just start by typing bt123, and you will see all the variables available.
Hope this helps.
Here is a link to the version 10 documentation regarding dependency properties.
https://confluence.jetbrains.com/display/TCD10/Predefined+Build+Parameters#PredefinedBuildParameters-DependenciesProperties
These options have been available since at least TeamCity 8.x.

Related

Using Octopus to configure log4net.config in .NET Core 3.1 Web API project

I'm using Octopus as part of our deployment for a .NET Core 3.1 Web API project.
log4net.config exists in .\Utility\Logs.
I'm trying to follow the pattern here:
https://help.octopus.com/t/transformation-best-practice-log4net-config-or-any-non-web-app-config/9906/4
As I understand it, this consists of three parts:
Create Log4Net.DeploymentTransform.config, with the variables in #{name} format - this has been done.
Turn on the "Substitute variables in files" feature, and point at the Log4Net.DeploymentTransform.config transformation file (variable replacement happens before transformation). That would result in the #{LogFileLocation} variable being replaced with whatever value was set for your LogFileLocation variable in the current scope.
This is done and is working.when my app is deployed, Log4Net.DeploymentTransform.config is there as well and the variable has been successfully set in it.
You'd also turn on the configuration transforms feature, and fill out the additional transforms section in the configuration transforms feature to identify your transform file (e.g. Log4Net.DeploymentTransform.config => log4net.config).
This is not working, the content of Log4Net.DeploymentTransform.config is not being copied on top of log4net.config, though they are in the same folder upon deployment.
Here is what I did in our "deploy step"
Which sure looks like what the article is saying to do.
What else should I check? Any idea why step 3 isn't occurring?
Your syntax looks correct for the files - have you checked to ensure that you have the xdt attributes set?
In the example forum post you shared, the log4net and appender elements are tagged with xmlns:xdt, xdt:Transform and xdt:Match attributes that help the XDT layer determine how to transform the files.
A quick example - I created a Log4NetConfigTest package with two files -
Utility/Logs/log4net.config
Utility/Logs/log4net.trasnform.config
I used the same sample code from the forum post as well.
Here's the set up for my package deployment configurations:
With that set up (and my LogFileLocation project variable set), I was able to see the following in my task log for the deployment:
Deploying package: C:\Octopus\Files\Log4NetConfigTest#S1.0.0#20004C95A0E0094490814B5A365DDAD2.zip
Transforming 'C:\Octopus\Applications\Development\Log4NetConfigTest\1.0.0_1\Utility\Logs\log4net.config' using 'C:\Octopus\Applications\Development\Log4NetConfigTest\1.0.0_1\Utility\Logs\log4net.transform.config'.
No matching appSetting, applicationSetting, nor connectionString names were found in: C:\Octopus\Applications\Development\Log4NetConfigTest\1.0.0_1\Utility\Logs\log4net.config
The task log confirmed that Octopus did apply the transformations, and once deployed, I confirmed that my new test log location was present and correct in both the base configuration and the transformation file.

SSDT - pre-build automation - setting 'buildAction' flag for stored procedure

I am wondering if anyone has an example of setting a Pre-Build Event (project properties, Build events) on an SSDT project so that we can change a files 'Build Action' from 'build' to None given a project configuration.
Something like: if $configuration is x then set buildAction = 'none' on abc.sql else set buildAction = 'build'
Regards
If you have different implementations of the same stored procedure, then you'll probably have 2 options:
Create conditional logic inside SP. You'll need to define variable value when publishing and in the code you'll have something like:
IF ('$(EnvVar)' = 'PROD')
BEGIN
-- code needed to be executed in PROD
END
IF ('$(EnvVar)' = 'DEV')
BEGIN
-- code needed to be executed in DEV
END
Create 2 (or you might need more) projects that would have that single procedure (or set of objects) with different implementations. Then add the reference to your main project with an option "The same database". Then create different publish profiles in the projects and use proper connection strings there.
I resolved this by using a pre-build event to copy a clone of the stored procs into the correct location depending on the build setting. So I have marked the above as an answer as well.
I could have also used a .tt file to generate the stored procedure at build time.

Override publish folder (url) of publish profile during the build pipeline

We have one ASP.Net solution with several projects. each project have build.pubxml with unique folder path.
For example:
In project Test we have this line inside the build.pubxml:
<publishUrl>C:\publish\SolutionName\Test</publishUrl>
In project Exam we have this line inside the build.pubxml:
<publishUrl>C:\publish\SolutionName\Exam</publishUrl>
In the build pipeline (in TFS) with have MSBuild step with this argument:
/p:PublishProfile=build.pubxml
After the build we got 2 folders - Test and Exam in C:\publish\SolutionName.
So far so good.
The problem is we have few branches, and we want to separate the publish folder for each branch, so we added .pubxml for each branch and in the build pipeline we specified the correct one. but is make are a lot of work on each new branch created and can cause mistakes.
We tried to pass the /p:publishUrl=C:\publish\BranchName in the MSBuild but then we got a one folder with all the content of Test and Exam and not two folders.
The idea is to have only one .pubxml file for each project with a parameter and pass the value in the pipeline, for example:
<publishUrl>C:\publish\$(Parameter)\Test</publishUrl>
And in the build we will pass the parameter according to the branch.
It is possible to do something like this?
It is possible to do something like this?
The answer is Yes. Since msbuild accepts Global Properties in command-line. If we define one Property in build.pubxml like <publishUrl>C:\PublishFolders\$(BranchID)\xxx(Test,Exam...)</publishUrl>, then we can simply pass the value in msbuild arguments like this:
Then we'll get Test and Exam folders under C:\PublishFolders\NewTest. Also we can choose to pass the pipeline predefined variables to the command like: /p:BranchID=$(Build.SourceBranch)...
This works for build in local machine, tfs and Azure Devops pipeline. Hope all above helps :)

How to use environment variable in xcconfig #include?

in my project, I want to refer to an other xcconfig file, located in InDesign SDK. As this SDK may be installed at different locations, depending upon the machine, I prefer to declare an environment variable for locating it.
Nest step is obviously to use variable (aptly named ID_CS5_SDK_DIR) in my xcconfig include directive.
Unfortunatly, when I try the simple
// InDesign sdk project build settings (based on common build settings)
#include "$(ID_CS5_SDK_ROOT)/build/mac/prj/_shared_build_settings/common.xcconfig"
XCode throws me a
[WARN]AutocatPlugin.xcconfig line 7: Unable to find included file "$(ID_CS5_SDK_ROOT)/build/mac/prj/_shared_build_settings/common.xcconfig"
How can I make it work ?
I've been trying to do this too and also came to the conclusion that it is not possible.
I once tried to achieve that and came to the conclusion that you can't. I would be happy if someone proves us it's possible though then delete my answer
It seems like .xcconfig files can only DEFINE and set value to environment variables (which prevail only throughout the build session) but not USE or evaluate environment variables.
Maybe it is because .xcconfig files serve as a base layer of build-settings, and are not parsed.
Unfortunately this is not possible, but instead of making one include the other, you can use two different xcconfig files per target. Just select one for the Project and one for the Target.
If you put the environment variable in /etc/config/launchd.conf and then reboot it will be accessible to the .xcconfig file.
Short Instructions for experienced users:
Edit the read-only file /etc/launchd.conf and add 'setenv VARIABLENAME /FOLDER/PATH' to the file, then reboot.
Steps For Inexperienced Users
Open Application/Utilities/Terminal, and entersudo nano /etc/launchd.conf
Create the Environment Variable by adding a line like setenv VARIABLENAME FOLDER/PATH and then pressing ENTER.
Save the file using Ctrl-O, Ctrl-M, (Possibly Ctrl-Y to overwrite), then Ctrl-X to exit the editor.
(Optional) type cat /etc/launchd.conf to see that your changes are present
Restart your computer. (Logoff doesn't work)
You can now access the variable in your .xcconfig file as$(VARIABLENAME)
Notes:
This creates a GLOBAL environment variable, accessible to all users. It probably doesn't make sense to set this to something in your home directory (e.g ~/MyFolder). If you do this, however, you need to use the full pathname, such as /Users/MyUserName/MyFolder).
References:
Stack Overflow - Setting Environment Variables in OSX
Stack Overflow - Are there any differences between /etc and /private /etc

Specify different path for provider iisApp when creating package with msdeploy

How I make the package
I make the msdeploy package like this:
msdeploy.exe -verb:sync -source:iisApp=c:\content\ -dest:package=c:\pkg.zip
The c:\content directory has a single index.html file.
Result
The output looks like this:
Info: Adding package (package).
Info: Adding child iisApp (c:\content\).
Info: Adding child createApp (c:\content\).
Info: Adding child contentPath (c:\content\).
Info: Adding child dirPath (c:\content\).
Info: Adding child filePath (c:\content\index.html).
Total changes: 6 (6 added, 0 deleted, 0 updated, 0 parameters changed, 0 bytes copied)
If I extract the content of c:\pkg.zip into directory c:\pkg it looks like this:
archive.xml
systemInfo.xml
Content\c_C
Content\c_C\content
Content\c_C\content\index.html
If I dump the package like this:
msdeploy.exe -verb:dump -source:package=c:\pkg.zip -xml
I get:
<output>
<MSDeploy.iisApp>
<iisApp path="c:\content\">
<createApp
path="c:\content\"
isDest="False"
managedRuntimeVersion=""
enable32BitAppOnWin64=""
managedPipelineMode=""
applicationPool=""
appExists="True" />
<contentPath path="c:\content\">
<dirPath
path="c:\content\"
securityDescriptor="D:"
parentSecurityDescriptors=""
attributes="Directory">
<filePath
path="index.html"
size="0"
attributes="Archive"
lastWriteTime="07/07/2011 20:58:00"
securityDescriptor="D:" />
</dirPath>
</contentPath>
</iisApp>
</MSDeploy.iisApp>
</output>
How I want it to be
I don't want the package to depend upon the current location of the site files. I'm going to send the package to a customer, and I don't want any detailes about the packaging process to get shipped with the package. I want the content of the package c:\pkg.zip to be like this:
archive.xml
systemInfo.xml
Content\index.html
I want the package to be able to create an IIS application, so I need a virtual path. I also want to install the package into the default location. So the physical path also has to change. I want the dump to look something like this:
<output>
<MSDeploy.iisApp>
<iisApp path="Default Web Site\Site">
<createApp
path="Default Web Site\Site"
isDest="False"
managedRuntimeVersion=""
enable32BitAppOnWin64=""
managedPipelineMode=""
applicationPool=""
appExists="False" />
<contentPath path="c:\inetpub\wwwroot\site">
<dirPath
path="c:\inetpub\wwwroot\site"
securityDescriptor="D:"
parentSecurityDescriptors=""
attributes="Directory">
<filePath
path="index.html"
size="0"
attributes="Archive"
lastWriteTime="07/07/2011 20:58:00"
securityDescriptor="D:" />
</dirPath>
</contentPath>
</iisApp>
</MSDeploy.iisApp>
</output>
I have changed the iisApp and createApp provider path attributes to be Default Web Site\Site. And I changed the contentPath and dirPath provider path attributes to be c:\inetpub\wwwroot\site.
Questions
How can I accomplish this?
You need to look at MS Deploy replace rules, a useful feature well hidden on the MS Deploy Team Blog.
In your case, you will need to extend your command line with a pile of replace expressions, something like this:
msdeploy.exe
-verb:sync
-source:iisApp=c:\content\
-dest:package=c:\pkg.zip
-replace:objectName=iisApp,targetAttributeName=path,
replace="Default Website\Site"
-replace:objectName=createApp,targetAttributeName=path,
replace="Default Website\Site"
-replace:objectName=contentPath,targetAttributeName=path,
replace="c:\inetpub\wwwroot\site"
-replace:objectName=dirPath,targetAttributeName=path,match="^c:\content",
replace="c:\inetpub\wwwroot\site"
Running this should produce your desired output.
In the above sample, the first 3 replace rules match by tag name (objectName) and attribute name (targetAttributeName), and overwrites with the specified replace string.
The last replace rule will match all path attributes of all dirPath tags beginning with "c:\content" and will replace only that part of the attribute value with the replace string.
Finally, I haven't found a way to avoid having the package zip-file contain the original source folder names. The only workaround would be to package from a neutral, temporary location like "c:\site".
So the procedure is:
Copy your stuff to a neutral, temporary location.
Create your package from here.
Use the verb:dump to see the generated xml.
Create your package again with added replace rules for everything you want changed in the package.
Take a headache pill ;-)
I had more or less the same problems.
First things first:
The long deployment-machine-specific paths
To that effect, I used a trick found at http://sedodream.com/2013/01/13/WebPackagingFixingTheLongPathIssue.aspx
As suggested in the post, one can modify the desired (you can have several) .pubxml file under the Properties/PublishProfiles folder in your project. This is the approach I followed since it allowed me to customize the behavior per publishing profile.
If I'm not mistaken though, I believe you can apply the same modification to the {project-name}.wpp.targets file (which probably doesn't exists yet) on the project root directory. Changes here though, affect the web publishing pipeline (wpp) and thus all publishing profiles found in the project.
However...
This approach is just about to spoil your deployment when it comes time to replace your connection strings with those provided by your publishing profile. The reason: the above trick doesn't affect connection strings since they are being created automatically by the wpp at build time. Buh-huh!
The solution I found for that problem was twofold:
1.) Created a parameters.xml file where I manually declared the connection strings. Ok, maybe I copied them from the parameters.xml file within my package's .zip file since I was deploying to a package. That helped.
They look somegthing like this:
<parameter name="myConnection-Web.config Connection String" defaultValue="" tags="SqlConnectionString"
description="myConnection Connection String used in web.config by the application to access the database.">
<parameterEntry kind="XmlFile" scope="DeploymentPackage\\Web\.config$" match="/configuration/connectionStrings/add[#name='myConnection']/#connectionString" />
</parameter>
2.) Included the following line at the top of the same .pubxml file we modified earlier
<AutoParameterizationWebConfigConnectionStrings>false</AutoParameterizationWebConfigConnectionStrings>
And... VoilĂ !
Create ISS App
With the above approach hopefully you declared several parameters, including the connection strings.
When you create a package, however, regardless of wheter you created a parameters.xml or not, a *.SetParameters.xml template file is created for you. Within it you will see as the very first parameter the "IIS Web Application Name", which will default to whatever you inserted in your publishing profile. You can change that; to whatever you want.
Remember I said template before? I meant it; it's just a template. You're suppose to take that *.SetParameters.xml file and make as many copies of it as needed. What are they for? Environment related parameters. You could have a:
DEV.SetParameters.xml
QA.SetParameters.xml
Staging.SetParameters.xml
Production.SetParameters.xml
... and so on and so forth
and then use the parameters file best suited for the job (or the environment) like so:
{yourProjectName}.deploy.cmd /Y /M:{targetServer} [...] -setParamFile:QA.SetParameters.xml
or its equivalent MsDeploy command line of course.
Now, by default, the manifest created for you at build time, and stashed within your package under the archive.xml file, will use an iisApp provider first and foremost. This is good, cause this provider, unlike the createApp provider, will actually create the directory for you if it doesn't exist. At least according to this note from TechNet:
"Unlike the iisApp provider, if the physical folder for the new application does not exist, the createApp provider does not create a physical folder underneath the folder of the parent site; it only creates a reference in configuration to such a folder. If you want a physical folder created, you will have to create it manually before or after using createApp. For this reason, you should normally use the iisApp provider instead. The iisApp provider is the more appropriate choice because it uses the createApp provider as an initial step in a series of steps that include the creation of the application in configuration, the creation of a physical folder for the application if the folder does not exist, and the copying of content files into the folder of the new application."
I would be happy to include the links... but since I don't have 10+ points I'm allowed only one per post. Go figure! :)
So, in short...
... by the work done on the first part, you probably won't need to do much in order to have the folder created at deploy time in the target server.
In case you do need to override that though, you can either define your own manifest file and deploy off of it (a separate topic)... or you can follow #peter_raven advice and override its value using the -Replace rules from MsDeploy.
Either one would work as a charm.
The package prefix is removed by supplying the kind, scope, and match properties as shown below:
"msdeploy.exe" \
-verb:sync \
-source:iisApp="[Path to your website contents]" \
-declareParam:name="IIS Web Application Name",kind="ProviderPath",scope="IisApp",match="^C:\\path\\to\\your\\site\\folder",defaultValue="Default Web Site/SomeSite" \
-dest:package=[WebDeployPackageName].zip
I've managed to resolve a problem with manually defined connection strings while using the solution from #SkyFighter. Now one can use the auto-parameterization feature and have the connection string parameters with correct scopes.
Fortunately there is a place inside WPP to inject into. Unfortunately I had to use AfterTarget/BeforeTarget rather than SomeTargetDependsOn variables to narrow down the new target's placement.
And here is the target itself:
<Target Name="Replace_WebConfigsToAutoParmeterizeCS_TransformScope"
AfterTargets="PreAutoParameterizationWebConfigConnectionStrings"
BeforeTargets="AutoParameterizationWebConfigConnectionStringsCore"
Condition=" '$(EnableAddReplaceToUpdatePacakgePath)'=='true' ">
<ItemGroup>
<_WebConfigsToAutoParmeterizeCS>
<TransformScope>$([System.String]::Copy('%(TransformScope)').Replace('$([System.IO.Path]::GetFullPath($(WPPAllFilesInSingleFolder)))', '$(PackagePath)'))</TransformScope>
</_WebConfigsToAutoParmeterizeCS>
</ItemGroup>
</Target>
It is driven by the same variables as in the Sayed's sample for fixing long paths. So place this target anywhere those variables already available.
P.S. This trick/hack requires at least MSBuild v3.5 where metadata manipulation was first introduced.

Resources