Teamcity meta-runner with multiple runners - exiting a runner without failing the build - powershell

OK, so here's a TeamCity meta-runner with 2 separate runners inside. Essentially the first runner will have a bunch of logic in it that determines if a deploy should occur or not.
<build-runners>
<runner name="Step 1" type="jetbrains_powershell">
<parameters>
<param name="jetbrains_powershell_bitness" value="x86" />
<param name="jetbrains_powershell_execution" value="PS1" />
<param name="jetbrains_powershell_minVersion" value="4.0" />
<param name="jetbrains_powershell_script_code"><![CDATA[
#Bunch of powershell logic here... under some conditions we want nothing deployed
#Now I want to exit the whole build step, not just this single runner
Exit #<- Fails the whole build, not what I want
]"]]></param>
<param name="jetbrains_powershell_script_mode" value="CODE" />
<param name="teamcity.step.mode" value="default" />
</parameters>
</runner>
<runner name="Deploy Project" type="octopus.deploy.release">
<parameters>
<param name="octopus_additionalcommandlinearguments" value="" />
<param name="octopus_deployto" value="%Octopus.EnvironmentName%" />
<param name="octopus_host" value="%system.Octopus-ServerUrl%" />
<param name="octopus_project_name" value="%ProjectName%" />
<param name="octopus_releasenumber" value="%ProjectRelease%" />
<param name="octopus_version" value="3.0+" />
<param name="octopus_waitfordeployments" value="true" />
<param name="secure:octopus_apikey" value="123123" />
<param name="teamcity.step.mode" value="default" />
</parameters>
</runner>
</build-runners>
What is a way I can exit the whole meta-runner step so it continues just fine with the next build step?

Response from vendor:
"It seems there is no clean way to skip remaining meta-runner steps without affecting build (successful) status. If you do not mind settings build to failed, you can try Execute "If all previous steps finished successfully" in the meta-runner steps to skip."
While the meta-runner feature is quite good in TeamCity, it does have its limitations.

Related

finding target worksheet for action in twb (xml) file

My intention is to find target worksheet for actions in tableau workbook. where should I search for that target worksheet correspond to some particular action in twb(xml) file?
For example:
<actions>
<action caption='Filter 1 (generated)' name='[Action1]'>
<activation auto-clear='true' type='on-select' />
<source dashboard='Figure 8-60 thought 8-65' type='sheet' worksheet='Heat Map' />
<command command='tsc:tsl-filter'>
<param name='special-fields' value='all' />
<param name='target' value='Figure 8-60 thought 8-65' />
</command>
</action>
<action caption='Filter 2 (generated)' name='[Action2]'>
<activation auto-clear='true' type='on-select' />
<source dashboard='Figure 8-59' type='sheet' worksheet='Poor Filter Design' />
<command command='tsc:tsl-filter'>
<param name='special-fields' value='all' />
<param name='target' value='Figure 8-59' />
</command>
</action>
<action caption='Filter 3 (generated)' name='[Action3]'>
<activation auto-clear='true' type='on-select' />
<source dashboard='Figure 8-59' type='sheet' worksheet='Good Filter Design' />
<command command='tsc:tsl-filter'>
<param name='special-fields' value='all' />
<param name='target' value='Figure 8-59' />
</command>
</action>
</actions>
As you can see above code filter1 action got a param tag inside that target attribute is present, but the value present there is a dashoard name. What i want is target woksheet corresponded to the action filter.
Tried to play a bit with .twb file and got this for dashboard actions:
<actions>
<action caption='Filter 1 (generated)' name='[Action1]'>
<activation auto-clear='true' type='on-select' />
<source dashboard='Dashboard 1' type='sheet' worksheet='Sheet 3' />
<command command='tsc:tsl-filter'>
<param name='special-fields' value='all' />
<param name='target' value='Dashboard 1' />
</command>
</action>
<action caption='Filter 2 (generated)' name='[Action2]'>
<activation auto-clear='true' type='on-select' />
<source dashboard='Dashboard 2' type='sheet' worksheet='Sheet 2' />
<command command='tsc:tsl-filter'>
<param name='special-fields' value='all' />
<param name='target' value='Dashboard 2' />
</command>
</action>
<action caption='Filter 3 (generated)' name='[Action3]'>
<activation auto-clear='true' type='on-select' />
<source dashboard='Dashboard 2' type='sheet' worksheet='Sheet 3' />
<command command='tsc:tsl-filter'>
<param name='special-fields' value='all' />
<param name='target' value='Dashboard 2' />
</command>
</action>
</actions>
Honestly I couldn't find any direct link to the target sheet while source sheet is always available in actions, This can be observed in Actions window.
But I was able to see the actions that were mapped to target sheets if we go to the individual sheet actions instead of dashboard actions where we can see target as dashboard.
See below data where I have created a dummy dashboard to check actions.
These are the actions that created in report:
<group caption='Action (Product Category)' hidden='true' name='[Action (Product Category)]' name-style='unqualified' user:auto-column='sheet_link'>
<groupfilter function='crossjoin'>
<groupfilter function='level-members' level='[Product Category]' />
</groupfilter>
</group>
<group caption='Action (Product Sub-Category)' hidden='true' name='[Action (Product Sub-Category)]' name-style='unqualified' user:auto-column='sheet_link'>
<groupfilter function='crossjoin'>
<groupfilter function='level-members' level='[Product Sub-Category]' />
</groupfilter>
</group>
Along with this if we go to individual sheets then we can see the actions mapped first one is for Sheet 2 and other is for Sheet 3:
<filter class='categorical' column='[federated.0idnrl40bk56fg130xiy30dnljux].[Action (Product Category)]'>
<groupfilter function='level-members' level='[Product Category]' user:ui-enumeration='all' user:ui-marker='enumerate' />
</filter>
<slices>
<column>[federated.0idnrl40bk56fg130xiy30dnljux].[Action (Product Category)]</column>
</slices>
<filter class='categorical' column='[federated.0idnrl40bk56fg130xiy30dnljux].[Action (Product Sub-Category)]'>
<groupfilter function='level-members' level='[Product Sub-Category]' user:ui-enumeration='all' user:ui-marker='enumerate' />
</filter>
<slices>
<column>[federated.0idnrl40bk56fg130xiy30dnljux].[Action (Product Sub-Category)]</column>
</slices>
If we keep track of actions that were created in dashboards then we can easily tell what all sheets are joined in a dashboard using the name of the actions.
Would like to know your thoughts and observations aswell.
Changing the names of the actions
Going into the .twb XML and changing the order of the <> blocks.
Going into the .twb XML and changing the internal Action1, Action2, etc. names. Doing this I'm able to change which of Dashboard 2 and Dashboard 3 is opened.
adding a Web Page object to Dashboard 1 and then a URL action using about:blank as the target, on the idea that maybe URL actions take precedence over filter actions.

Passing values within a TeamCity metarunner

I have a TeamCity metarunner that consolidates two runners. The first runner does a bunch of Powershell stuff to get the right Octopus release to deploy, and it works fine. The second runner tries to deploy that.
<build-runners>
<runner name="Get project release for current branch" type="jetbrains_powershell">
<parameters>
<param name="jetbrains_powershell_bitness" value="x86" />
<param name="jetbrains_powershell_execution" value="PS1" />
<param name="jetbrains_powershell_minVersion" value="4.0" />
<param name="jetbrains_powershell_script_code"><![CDATA[
#Do some powershell stuff here to get the right release
$ProjectRelease="1.2.3.45"
Write-Output "##teamcity[setParameter name='ProjectRelease' value='$ProjectRelease']"
Start-Sleep -s 10
]]></param>
<param name="jetbrains_powershell_script_mode" value="CODE" />
<param name="teamcity.step.mode" value="default" />
</parameters>
</runner>
<runner name="Deploy Project" type="octopus.deploy.release">
<parameters>
<param name="octopus_additionalcommandlinearguments" value="--specificmachines=%AgentList%" />
<param name="octopus_deployto" value="%Octopus.EnvironmentName%" />
<param name="octopus_host" value="%system.Octopus-prod_ServerUrl%" />
<param name="octopus_project_name" value="%ProjectName%" />
<param name="octopus_releasenumber" value="%ProjectRelease%" />
<param name="octopus_version" value="3.0+" />
<param name="octopus_waitfordeployments" value="true" />
<param name="secure:octopus_apikey" value="zxx318ab49dce685b0ae65d94a963ff326672f51fb87c685575c3b6ed4f6eb8a569" />
<param name="teamcity.step.mode" value="default" />
</parameters>
</runner>
</build-runners>
So you can see %ProjectRelease% gets set to 1.2.3.45, and this value can then be used in subsequent build steps - all good there. However for the second runner, on the line:
<param name="octopus_releasenumber" value="%ProjectRelease%" />
%ProjectRelease% is still equal to the default value ("To be populated" and not "1.2.3.45"). How can I pass this value to the Deploy Project runner?
OK, so I found a solution to this, but it is kind of hacky.
By naming ProjectRelease to env.ProjectRelease (and don't forget to add it as a parameter) it becomes an environment parameter which is updated in real time, and thus will work.
Apparently the line:
Write-Output "##teamcity[setParameter name='ProjectRelease' value='$ProjectRelease']"
...doesn't set the parameter until after the whole script has finished. Please let me know if there is a more elegant solution than this!
You should be able to set parameters for the whole metarunner farther up in the xml.
For example:
<?xml version="1.0" encoding="UTF-8"?>
<meta-runner name="YourMetaRunnerName">
<description>YourMetaRunner Description </description>
<settings>
<parameters>
<!-- meta-runner parameters accessible in all build runners
below -->
<param name="ProjectRelease"value="Release.1.2.3.45"/>
You will then be able to use these parameters in subsequent build runners within the MetaRunner. This should be a more contained solution.

Why is NAnt executing my sql scripts in the wrong order?

Here is my Script:
<?xml version="1.0"?>
<project name="createAndPopulateDB" default="deploy">
<property name="sql.connstring" value="Provider=SQLOLEDB;Server=G-PC\sqlexpress;Integrated Security=SSPI" />
<property name="createDB" value="BuildTestDatabase.sql" />
<property name="populateDB" value="CreateTables.sql"/>
<target name="deploy">
<echo message="* Connecting to ${sql.connstring}"/>
<foreach item="File" property="sql.script">
<in>
<items>
<include name="${createDB}" />
<include name="${populateDB}" />
</items>
</in>
<do>
<echo message="* Executing ${path::get-file-name(sql.script)}"/>
<sql connstring="${sql.connstring}" delimiter="go" delimstyle="Line" batch="false" source="${sql.script}"/>
</do>
</foreach>
</target>
</project>
The NAnt script is supposed to call two tsql programs. The first tsql is designed to drop a database if it is present, and if it isn't, create it. The second checks to see if a table is present, and if so, delete it. Similarly if it isn't, it populates the created database with a simple table.
My question is why does it run the populateDB script first?
I found that the best way to determine the order in which the tsql programs are run is through a depends attribute attached to separate targets. This will run them in a predetermined order and is extremely easy to follow logically if the NAnt script is a part of a repository.

Can I store my .flv files on a file system and have the play in my web page?

When my .flv and .swf files are referenced through an http:// address they work fine but when I reference them via UNC path, they don't work. Any idea if it's possible to for it to work?
This works:
<object width="640" height="360">
<param name="movie" value="/flash/FLVPlayer_Progressive.swf" />
<param name="salign" value="lt" />
<param name="quality" value="high" />
<param name="scale" value="noscale" />
<param name="FlashVars" value="&MM_ComponentVersion=1&skinName=/flash/clearSkin_3&streamName=/flash/Ch1_Trial&autoPlay=false&autoRewind=false" />
<embed src="/flash/FLVPlayer_Progressive.swf" flashvars="&MM_ComponentVersion=1&skinName=/flash/clearSkin_3&streamName=/flash/Ch1_Trial&autoPlay=false&autoRewind=false"
quality="high" scale="noscale" width="640" height="360" name="FLVPlayer" salign="LT" type="application/x-shockwave-flash" pluginspage="http://www.macromedia.com/go/getflashplayer" />
</object>
This does not work:
<object width="640" height="360">
<param name="movie" value="/flash/FLVPlayer_Progressive.swf" />
<param name="salign" value="lt" />
<param name="quality" value="high" />
<param name="scale" value="noscale" />
<param name="FlashVars" value="&MM_ComponentVersion=1&skinName=/flash/clearSkin_3&streamName=\\flashfileserver\flash\Ch1_Trial&autoPlay=false&autoRewind=false" />
<embed src="/flash/FLVPlayer_Progressive.swf" flashvars="&MM_ComponentVersion=1&skinName=/flash/clearSkin_3&streamName=\\flashfileserver\flash\Ch1_Trial&autoPlay=false&autoRewind=false"
quality="high" scale="noscale" width="640" height="360" name="FLVPlayer" salign="LT" type="application/x-shockwave-flash" pluginspage="http://www.macromedia.com/go/getflashplayer" />
</object>
Thanks in advance
I believe this is due to same origin policy. Resources can only be loaded from the same server that served the script/plugin/etc. Otherwise, whats to stop the script/plugin/etc from opening a file on your local system and then send the content to a third party.
http://en.wikipedia.org/wiki/Same_origin_policy

nant logs with data and time stamp

How to run NAnt scripts in command line and get the timings of each task on the log file?
using nant <record> task or
NAnt -buildfile:testscript.build testnanttarget
This produces console output but I can't see any timing information.
All I want each log message prefixed with datatime.
You can use the tstamp task to display the current date/time. Just include it everywhere where you want timing information. It will not prefix each line with a timestamp, but at least you can time some strategic points.
<tstamp />
Here is a sample of tstamp
<echo>
-----------------------------------------------------------------------------------------------------------------
-----------------------------------------------------------------------------------------------------------------
TASK : INITIALIZE
-----------------------------------------------------------------------------------------------------------------
-----------------------------------------------------------------------------------------------------------------
</echo>
<loadtasks assembly="nantcontrib-0.85/bin/NAnt.Contrib.Tasks.dll" />
<!-- http://www.basilv.com/psd/blog/2007/how-to-add-logging-to-ant-builds -->
<tstamp>
<formatter property="timestamp" pattern="yyMMdd_HHmm"/>
</tstamp>
<property name="build.log.filename" value="build_${timestamp}.log"/>
<echo message="build.log.filename: ${build.log.filename}" />
<record name="${build.log.dir}/${build.log.filename}" action="Start" level="Verbose"/>
<echo message="Build logged to ${build.log.filename}"/>
<echo message="Build Start at: ${datetime::now()}" />
</target>