TeamCity building MSP files

739 views Asked by At

For background: I've got quite a nice TeamCity setup; containing a ci build and a release build which uses WiX to build my installers and patch all the version numbers. When I do a new release build, I'd like to automatically create MSP patches against a previous set of installers. I'm thinking either tagged RTM in TeamCity, or as a list of version numbers.

The approach I'm leaning towards is creating a separate config and getting the msi artifacts of all the previous builds that fit the criteria (tag or version number). Tag would seem a lot neater, but I can't see anything in the documentation about how you use it?

I've got a script to build the MSP patch, but it relies on a PCP file which needs to be edited in ORCA to describe the patch.

  1. In terms of editing the PCP, is there anything else I can use other than the ORCA to edit? I've been looking at moving to the WiX method here: http://wix.sourceforge.net/manual-wix3/patch_building.htm which looks promising.
  2. Does anyone know if you can access artifacts in TeamCity by Tag in the same or another build?
  3. Does anyone have any other insights into automatically building/chaining MSP patch files in TeamCity?
2

There are 2 answers

0
Rob Mensching On BEST ANSWER
  1. You can build the .PCP file using the PatchCreation element in the WiX toolset. That will probably give you the necessary flexiblity necessary to create the customized .PCP files.

  2. Sorry, don't use TeamCity.

  3. Sorry, don't use TeamCity. :)

0
Martin Clarke On

To add to Rob's answer:

#2. TeamCity can retrieve items by tag:

http://servername:8080/httpAuth/app/rest/buildTypes/id:bt13/builds?status=SUCCESS&tag=RTM

#3. I used the PatchCreation element (Rob suggested above) in the WiX toolset and he's right its flexible enough for this. Here is an outline of what I've built, it all seems to work quite well in testing,

The teamcity project has a number of build parameters, they are:

  1. New version number - default as changeme, so if its not been changed it breaks the build.

  2. Old version number - as above

  3. New build repo - this is the buildtypeid, look at querystring for your project and it will have buildTypeId=btXX. The XX is the number that should be supplied here.

  4. Old build repo - as above

The teamcity project has the following steps:

  1. MSBuild runner to run build.msbuild (see below)

  2. Run Candle on the patch.wxs to create a patch.wixobj file

  3. Run Light on patch.wixobj to create a patch.pcp

  4. Unpack new version (command: msiexec /q /a new.msi) -

  5. Unpack old version (command: msiexec /q /a old.msi) - choose a different working dir

  6. Create patch (command: msimsp -s patch.pcp p hotfix-%system.msiOldVersion%-%system.msiNewVersion%.msp -l patch.log

MSBuild to Create patch.pcp

<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" DefaultTargets="Build"  xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
  <!--<Import Project="references\MSBuild.Community.Tasks.Targets"/>-->
  <UsingTask AssemblyFile="references\MSBuild.Community.Tasks.dll" TaskName="WebDownload"/>
  <UsingTask AssemblyFile="references\MSBuild.Community.Tasks.dll" TaskName="TemplateFile"/>
  <Target Name="Build">
    <!-- preconditions for build -->
    <Error Condition="'$(msiOldVersion)' == 'changeme'" Text="Use run custom build, setting the client version of the msi"/>
    <Error Condition="'$(msiOldVersion)' == ''" Text="Use run custom build, setting the client version of the msi"/>
    <Error Condition="'$(msiNewVersion)' == 'changeme'" Text="Use run custom build, setting the new version of the msi"/>
    <Error Condition="'$(msiNewVersion)' == ''" Text="Use run custom build, setting the new version of the msi"/>
    <Message Text="Old Version: $(msiOldVersion)"/>
    <Message Text="New version: $(msiNewVersion)"/>

    <!-- download files from teamcity... -->
    <WebDownload FileUri="http://server:8080/httpAuth/repository/download/bt$(msiOldRepo)/trunk/Path/bin/Release/en-us/installer-v-v.$(msiOldVersion).msi" UserName="download" Password="abcdefgh" FileName="downloads/oldversion.msi"  />
    <WebDownload FileUri="http://server:8080/httpAuth/repository/download/bt$(msiNewRepo)/trunk/Path/bin/Release/en-us/installer-v.$(msiNewVersion).msi" UserName="download" Password="abcdefgh" FileName="downloads/newversion.msi"  />

    <!-- fill in blanks in patch.wxs -->
    <ItemGroup>
      <Tokens Include="oldVersion">
        <ReplacementValue>$(msiOldVersion)</ReplacementValue>
      </Tokens>
      <Tokens Include="newVersion">
        <ReplacementValue>$(msiNewVersion)</ReplacementValue>
      </Tokens>
    </ItemGroup>
    <TemplateFile Template="template.wxs" OutputFileName="patch.wxs" Tokens="@(Tokens)"/>    
  </Target>

Template.wxs used by MSBuild script

<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi">
  <PatchCreation
      Id="deadbeef-dead-beef-dead-beefdeadbeef"
      CleanWorkingFolder="no"
      OutputPath="patch.pcp"
      WholeFilesOnly="no">
    <PatchInformation
        Description="Small Update Patch"
        Comments="Small Update Patch"                        
        Manufacturer="Your Manufacturer"/>
    <PatchMetadata
        AllowRemoval="yes"
        Description="Hotfix"
        ManufacturerName="Your Manufacturer"
        MoreInfoURL="http://yourwebsite.com"
        TargetProductName="Your Product Name"        
        Classification="Hotfix"
        DisplayName="Hotfix - TBC"/>

    <Family DiskId="5000"
        MediaSrcProp="Sample"
        Name="Sample"
        SequenceStart="5000">
      <UpgradeImage SourceFile="downloads\newunpack\newVersion.msi" Id="SampleUpgrade">
        <TargetImage SourceFile="downloads\oldunpack\oldVersion.msi" Order="2"
            Id="SampleTarget" IgnoreMissingFiles="no" />
      </UpgradeImage>
    </Family>

    <PatchSequence PatchFamily="SamplePatchFamily"        
        Supersede="yes" />    
  </PatchCreation>
</Wix>