Variable Substitution in .config file with Octopus Deploy 3 - octopus-deploy

I am using Octopus Deploy v3 for my deployment.
Within my project I have defined a variable called data.folder
I am trying to use this variable to set the value in a transformation file that was deployed using a package
I have the following .config file
<?xml version="1.0"?>
<configuration xmlns:patch="http://www.sitecore.net/xmlconfig/" xmlns:set="http://www.sitecore.net/xmlconfig/set/" >
<sitecore>
<sc.variable name="dataFolder">
<patch:attribute name="value">/Data</patch:attribute>
</sc.variable>
</sitecore>
</configuration>
and the following .ci.config file
<?xml version="1.0"?>
<configuration
xmlns:patch="http://www.sitecore.net/xmlconfig/"
xmlns:set="http://www.sitecore.net/xmlconfig/set/"
xmlns:xdt="http://schemas.microsoft.com/XML-Document-Transform">
<sitecore>
<sc.variable name="dataFolder" xdt:Transform="Replace" xdt:Location="Match(name)" set:value="#{data.folder}" />
</sitecore>
</configuration>
Both of these files are located in folder App_Config\Include
As you can see I have set the variable in the transformation file to include the variable "{data.folder}"
Within Octopus, I have created a package deployment step, and have set the following features:
Custom installation directory
Configuration Variables
Configuration transforms
Substitute variables in files
Within the Substitute variables in files I have included the target files
App_Config\Include\Z_Project.#{Octopus.Environment.Id}.config
I believe that I have followed http://docs.octopusdeploy.com/display/OD/Substitute+Variables+in+Files correctly, however when the deployment runs. the variable in the .ci.config file is not being set.
I am sure I have made a very basic mistake, but I have no idea what I have done wrong
What do I need to get the transform file to use the variable from Octopus

It sounds like you've got the process correct in terms of the steps, the variables etc, but I don't think the transformation in the .ci.config file is correct after previewing a transformation.
It ends up like this
<sitecore>
<sc.variable name="dataFolder" set:value="#{data.folder}"/>
</sitecore>
try using
<sitecore>
<sc.variable name="dataFolder" xdt:Transform="Replace" xdt:Location="Match(name)">
<patch:attribute name="value">#{data.folder}</patch:attribute>
</sc.variable>
</sitecore>
Running this through Slow Cheetah (Visual Studio Gallery) performs the transformation correctly and provided everything else is setup in Octopus Deploy correctly this should get the value injected before the transformation happens.
Hope this helps

Related

Replace entire web.config with NuGet

Is there a way to have nuget replace the entire web.config when you install a package?
Let's say I create a custom package which contains a web.config. I want to install this custom package and have it completely overwrite the existing web.config in a given project instead of merging like it does by default. How can I accomplish this?
Seems to me you could use a XML-Document-Transform and xdt:Transform="Replace" the configuration section like so:
<?xml version="1.0"?>
<configuration xdt:Transform="Replace" xmlns:xdt="http://schemas.microsoft.com/XML-Document-Transform">
...
<system.webServer>
...
</system.webServer>
</configuration>
I haven't done this myself, and I'm not sure that a transform can be applied to the configuration element. Let me know if that doesn't work and I'll delete this answer.

SlowCheetah transforms for non-web app.config

I am confused by the rapid pace and terrific work done by Sayed Hashimi and company on SlowCheetah, specifically whether or not SlowCheetah is able to transform files on Build instead of just Package and Publish.
I have SlowCheetah installed and am able to auto-generate the build configuration instances for app.config of a console application I am working with the development team to deploy. On build, a new "SlowCheetah" directory is created under the $(ProjectDir)\obj\x86\$(BuildConfig) directory. The obj\x86\STAGE\SlowCheetah directory, for instance, contains an app.config file with the transform completed as indicated when right clicking the STAGE transform and selecting "View Transforms".
The \bin\$(BuildConfig) directory, however, contains the untransformed app.config file as well as all of the templates for each of the $(BuildConfig) transformations - instead of replacing the app.config file in the bin\x86\STAGE directory with the one from SlowCheetah.
The build completes without error.
Is this the expected action, or is something still not working correctly?
#sayed-ibrahim-hashimi Each $(Configuration) has a transform. The transforms displays properly when viewing in Visual Studio, and is properly transformed in the \slowcheetah directory under the \obj directory tree. Examples of transforms are:
<?xml version="1.0" encoding="utf-8" ?>
<!-- For more information on using transformations see the web.config examples at http://go.microsoft.com/fwlink/?LinkId=214134. -->
<configuration xmlns:xdt="http://schemas.microsoft.com/XML-Document-Transform
<connectionStrings>
<add name="Portal" connectionString="Data Source=transformtestserver.domain.local;Initial Catalog=TestDB;User Id=TestUser;Password=testpw1;" xdt:Transform="SetAttributes" xdt:Locator="Match(name)"/>
<add name="DictionaryDatabase" connectionString="Data Source=transformtestserver.domain.local;Initial Catalog=TestDB;User Id=TestUser;Password=testpw2;" xdt:Transform="SetAttributes" xdt:Locator="Match(name)"/>
<add name="LoggingDatabase" connectionString="Data Source=transformtestserver.domain.local;Initial Catalog=TestDB;User Id=TestUser;Password=testpw3;" xdt:Transform="SetAttributes" xdt:Locator="Match(name)"/>
</connectionStrings>
</configuration>
The problem may be related to the Nuget/solution configuration. The project I am working with is one part of a very large solution. I had a difficult time getting SlowCheetah installed and working - at one point finding Nuget said SlowCheetah was installed but the solution package directory did not contain SlowCheetah.
I setup a workaround in TeamCity to pickup the transformed app.config file from the \obj directory, but would really like to resolve the problem so I can rollout SC to the full development group. Is there a verbose log we can look at that might point out the details?
I faced with the same problem.
Local compilation in VS works great,
but on build Agent (TeamCity) the transformation magic not happend!
The solution I found relating to the location of the xml element in the proj file
<PropertyGroup Label="SlowCheetah">
<SlowCheetahToolsPath>$([System.IO.Path]::GetFullPath( $(MSBuildProjectDirectory)\..\packages\SlowCheetah.2.5.10.3\tools\))</SlowCheetahToolsPath>
<SlowCheetah_EnableImportFromNuGet Condition=" '$(SC_EnableImportFromNuGet)'=='' ">true</SlowCheetah_EnableImportFromNuGet>
<SlowCheetah_NuGetImportPath Condition=" '$(SlowCheetah_NuGetImportPath)'=='' ">$([System.IO.Path]::GetFullPath( $(MSBuildProjectDirectory)\Properties\SlowCheetah\SlowCheetah.Transforms.targets ))</SlowCheetah_NuGetImportPath>
<SlowCheetahTargets Condition=" '$(SlowCheetah_EnableImportFromNuGet)'=='true' and Exists('$(SlowCheetah_NuGetImportPath)') ">$(SlowCheetah_NuGetImportPath)</SlowCheetahTargets>
</PropertyGroup>
I have noticed is that when the PropertyGroup is above all ItemGroup`s ellements
MsBuild.exe at last did the Transformation
Look for duplicate SlowCheetahTargets section - I had an older version and a newer version and the older one was pointing to a location that no longer existed in the nuget packages directory.
Delete the whole property group for the older / duplicated SlowCheetahTargets section and that should fix it.

Can Web Deploy's setAcl provider be used on a sub-directory?

I'm trying to make a subdirectory in an MS Deploy package writable to the application pool user. Thanks to a helpful post about the setAcl provider by Kevin Leetham I was able to get most of what I need into my project file:
<MsDeploySourceManifest Include="setAcl"
Condition="$(IncludeSetAclProviderOnDestination)">
<Path>$(_MSDeployDirPath_FullPath)\doc\public</Path>
<setAclAccess>Read,Write,Modify</setAclAccess>
<setAclResourceType>Directory</setAclResourceType>
<AdditionalProviderSettings>setAclResourceType;setAclAccess</AdditionalProviderSettings>
</MsDeploySourceManifest>
Note that I've added "\doc\public" to the root deployment directory. In the resulting manifest that VS2010 builds, I see the following setAcl element:
<sitemanifest>
<contentPath path="C:\Source\...\obj\Debug\Package\PackageTmp" />
<setAcl path="C:\Source\...\obj\Debug\Package\PackageTmp"
setAclResourceType="Directory" />
<setAcl path="C:\Source\...\obj\Debug\Package\PackageTmp"
setAclUser="anonymousAuthenticationUser"
setAclResourceType="Directory" />
<setAcl path="C:\Source\...\obj\Debug\Package\PackageTmp\doc\public"
setAclResourceType="Directory"
setAclAccess="Read,Write,Modify" />
</sitemanifest>
That last line looks good: it's appended the subdirectory I want to be writable, and the access modifiers all seem to have transferred over well enough.
However, when I deploy this package I receive an error:
Error: A value for the 'setAclUser' setting must be specified when the
'setAcl' provider is used with a physical path.
This is a confusing error because I'm not trying to set an ACL on a physical path, exactly, but a subdirectory of a web application. Looking at the output of MS Deploy, it's easy to see the problem:
Info: Adding setAcl (REST Services\1.0.334).
Info: Adding setAcl (REST Services\1.0.334).
Info: Adding setAcl (C:\...\obj\Release\Package\PackageTmp\doc\public).
MS Deploy is apparently substituting the web application name for my absolute path "C:...\obj\Release\Package\PackageTmp", but when I append "\doc\public" to that absolute path it no longer recognizes it as a web application directory. This exact problem is described by another victim over on the ASP.NET forums without any resolution.
Does anyone know how to set an ACL on a particular subdirectory of a web application via Web Deploy without manually identifying the physical path and application pool user on the target host?
OK let me first say that this is way harder than it should be!
I think the reason why it is failing is because when you are publishing it cannot recognize the folder as being a folder in the IIS Application. The reason this is happening is because the full path is being transferred to the destination when the SetAcl provider is invoked. Instead of that we need an path which is relative to the IIS Application. For instance in your case it should be something like : "REST SERVICES/1.0.334/doc/public". The only way to do this is to create an MSDeploy parameter which gets populated with the correct value at publish time. You will have to do this in addition to creating your own SetAcl entry in the source manifest. Follow the steps below.
In the same directory as your project create a file with the name {ProjectName}.wpp.targets (where {ProjectName} is the name of your Web application project)
Inside the file paste the MSBuild content which is below this list
Reload the project in Visual Studio (VS caches the project files in memory so this cache needs to be cleared).
{ProjectName}.wpp.targets
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Target Name="SetupCustomAcls" AfterTargets="AddIisSettingAndFileContentsToSourceManifest">
<!-- This must be declared inside of a target because the property
$(_MSDeployDirPath_FullPath) will not be defined at that time. -->
<ItemGroup>
<MsDeploySourceManifest Include="setAcl">
<Path>$(_MSDeployDirPath_FullPath)\doc\public</Path>
<setAclAccess>Read,Write,Modify</setAclAccess>
<setAclResourceType>Directory</setAclResourceType>
<AdditionalProviderSettings>setAclResourceType;setAclAccess</AdditionalProviderSettings>
</MsDeploySourceManifest>
</ItemGroup>
</Target>
<Target Name="DeclareCustomParameters" AfterTargets="AddIisAndContentDeclareParametersItems">
<!-- This must be declared inside of a target because the property
$(_EscapeRegEx_MSDeployDirPath) will not be defined at that time. -->
<ItemGroup>
<MsDeployDeclareParameters Include="DocPublicSetAclParam">
<Kind>ProviderPath</Kind>
<Scope>setAcl</Scope>
<Match>^$(_EscapeRegEx_MSDeployDirPath)\\doc\\public$</Match>
<Value>$(_DestinationContentPath)/doc/public</Value>
<ExcludeFromSetParameter>True</ExcludeFromSetParameter>
</MsDeployDeclareParameters>
</ItemGroup>
</Target>
</Project>
To explain this a bit, the target SetupCustomAcls will cause a new SetAcl entry to be placed inside of the source manifest used during publishing. This target is executed after the AddIisSettingAndFileContentsToSourceManifest target executes, via the AfterTargets attribute. We do this to ensure that the item value is created at the right time and because we need to ensure that the property _MSDeployDirPath_FullPath is populated.
The DeclareCustomParameters is where the custom MSDeploy parameter will be created. That target will execute after the AddIisAndContentDeclareParametersItems target. We do this to ensure that the property _EscapeRegEx_MSDeployDirPath is populated. Notice inside that target when I declare the value of the parameter (inside the Value element) that I use the property _DestinationContentPath which is the MSBuild property containing the path to where your app is being deployed, i.e. REST Services/1.0.334.
Can you try that out and let me know if it worked for you or not?
FYI - this does work for a root website if you follow the convention specified in the post here:
http://forums.iis.net/p/1176955/1977169.aspx#1977169
<Match>^$(_EscapeRegEx_MSDeployDirPath)\\#(CustomDirAcl)$</Match>
<DefaultValue>{$(_MsDeployParameterNameForContentPath)}/#(CustomDirAcl)</DefaultValue>
<Value>$(_DestinationContentPath)/#(CustomDirAcl)</Value>
This post also has the benefit of being able to specify a block of subdirectories in a single ItemGroup.

Configuring Cruise Control Net with sourcesafe - Unable to load array item 'executable'

I'm trying to create a continuous integration environment. To do so, I've used a guide that can be found at http://www.15seconds.com/issue/040621.htm.
In this step by step, the goal is to create a CI with CCNet, NAnt, NUni, NDoc, FxCop and source safe.
I've been able to create my build by using the command prompt (despite the the different versions issues). The problem has come with the configuration of ccnet.config
I've made some changes because of the new versions, but I'm still getting errors when starting the CCNet server.
Can anyone help me to fix this issue or point where to find a guide with this scenario?
The error that I'm getting:
Unable to instantiate CruiseControl projects from configuration document.
Configuration document is likely missing Xml nodes required for properly populating CruiseControl configuration.
Unable to load array item 'executable' - Cannot convert from type System.String to ThoughtWorks.CruiseControl.Core.ITask for object with value: "\DevTools\nant\bin\NAnt.exe"
Xml: E:\DevTools\nant\bin\NAnt.exe
My CCNet config file below:
<cruisecontrol>
<project name="BuildingSolution">
<webURL>http://localhost/ccnet</webURL>
<modificationDelaySeconds>10</modificationDelaySeconds>
<triggers>
<intervaltrigger name="continuous" seconds="60" />
</triggers>
<sourcecontrol type="vss" autoGetSource="true">
<ssdir>E:\VSS\</ssdir>
<executable>C:\Program Files\Microsoft Visual SourceSafe\SS.EXE</executable>
<project>$/CCNet/slnCCNet.root/slnCCNet</project>
<username>Albert</username>
<password></password>
</sourcecontrol>
<prebuild type="nant">
<executable>E:\DevTools\nant\bin\NAnt.exe</executable>
<buildFile>E:\Builds\buildingsolution\WebForm.build</buildFile>
<logger>NAnt.Core.XmlLogger</logger>
<buildTimeoutSeconds>300</buildTimeoutSeconds>
</prebuild>
<tasks>
<nant>
<executable>E:\DevTools\nant\bin\nant.exe</executable>
<nologo>true</nologo>
<buildFile>E:\Builds\buildingsolution\WebForm.build</buildFile>
<logger>NAnt.Core.XmlLogger</logger>
<targetList>
<target>build</target>
</targetList>
<buildTimeoutSeconds>6000</buildTimeoutSeconds>
</nant>
</tasks>
<publishers>
<merge>
<files>
<file>E:\Builds\buildingsolution\latest\*-results.xml</file>
</files>
</merge>
<xmllogger />
</publishers>
</project>
</cruisecontrol>
enter code here
This is only a first guess but configuration in <prebuild> element might be broken. Try this:
<prebuild>
<nant>
<executable>E:\DevTools\nant\bin\NAnt.exe</executable>
<buildFile>E:\Builds\buildingsolution\WebForm.build</buildFile>
<logger>NAnt.Core.XmlLogger</logger>
<buildTimeoutSeconds>300</buildTimeoutSeconds>
</nant>
</prebuild>
Just like the <tasks> block the <prebuild> block is a collection of task elements. In Your case this is a single <nant> task.
Currently I don't have access to CCNET documentation since the ThoughtWorks server is down - once again. So I'm not able to verify my advice at the moment.
BTW: Did You know that You don't have to start the server in order to verify Your configuration. Check the configuration with CCValidator.exe from [installdir]\server prior to starting CCNET server.

Integrating MSTest with Cruise control for multiple projects

I have integrated MSTest with cruise control for single project by following the steps present in the below link.Its working fine
http://www.codeproject.com/KB/tips/VSTS2008_Tests_With_CCNET.aspx?display=Print.
But if i add multiple projects, the result file is getting over wrtitten by 2nd project result. I am not able to see the first project result.
Please let me know how i can display multiple project results in result fie.
... in the meantime I checked the problem in more detail and it seems that my 1st guess was right (although I didn't realize that no real build script but a simple batch is used):
Problem: A single working directory is used for all projects. Each project produces it's own results.xml file but since they are all stored in the same location results are overwritten.
Solution: Use a separate folder for the results of each project (e.g. the project's artifact directory which is passed from CruiseControl to the batch process as environment variable).
RunTests.bat:
del "%CCNetArtifactDirectory%\results.xml"
MSTest.exe /testcontainer:<PathtoTestProject>\Bin\Debug\TestAssembly.dll /resultsfile:"%CCNetArtifactDirectory%\results.xml"
ccnet.config:
<project name="ProjectA">
<cb:define projectArtifactDirectory="C:\path\to\data\of\ProjectA" />
...
<artifactDirectory>$(projectArtifactDirectory)</artifactDirectory>
...
<publishers>
<merge>
<files>
<file>$(projectArtifactDirectory)\results.xml</file>
</files>
</merge>
</publishers>
...
</project>

Resources