[wix-users] Versioning for Continuous Automated Builds

Edwin Castro egcastr at gmail.com
Wed May 30 20:56:20 PDT 2018


I'll cover the easy part first, using preprocessor variables for
Product/@Version.

In your source code, you'll want to set Product/@Version to a preprocessor
variable like so

<Product Version="$(var.ProductVersion)"  ...

Usually, you'd want to <?define?> ProductVersion so that it has a
meaningful value like so

<?define ProductVersion = "1.2.3"?>
<Product Version="$(var.ProductVersion)"  ...

But, of course, this only moves where ProductVersion is defined while still
hardcoding the version. You want to avoid defining ProductVersion in your
source code. This will make your build fail unless we define it in a way
that the build process can use. The details will vary depending on how your
build process works.

If you are using candle and light directly, then you want to define
ProductVersion in your candle command line like this:

candle.exe -dProductVersion=1.2.3  ...

Of course, you need to your build scripts to generate and/or auto-increment
the ProductVersion value somehow. Exactly how you do this depends on what
you use for your build scripts.

If you use the Visual Studio projects to build, then you can modify the
DefineConstants in your project.wixproj from:

<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|x86' ">
  <OutputPath>bin\$(Configuration)\</OutputPath>
  <IntermediateOutputPath>obj\$(Configuration)\</IntermediateOutputPath>
  <DefineConstants>Debug</DefineConstants>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|x86'
">
  <OutputPath>bin\$(Configuration)\</OutputPath>
  <IntermediateOutputPath>obj\$(Configuration)\</IntermediateOutputPath>
</PropertyGroup>

to

<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|x86' ">
  <OutputPath>bin\$(Configuration)\</OutputPath>
  <IntermediateOutputPath>obj\$(Configuration)\</IntermediateOutputPath>
  <DefineConstants>Debug;ProductVersion=$(ProductVersion)</DefineConstants>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|x86'
">
  <OutputPath>bin\$(Configuration)\</OutputPath>
  <IntermediateOutputPath>obj\$(Configuration)\</IntermediateOutputPath>
  <DefineConstants>ProductVersion=$(ProductVersion)</DefineConstants>
</PropertyGroup>

You can also modify DefineConstants from the project's properties in the
Build tab.

Note that ProductVersion=$(ProductVersion) has not actually defined what
ProductVersion will be. It only says to set the ProductVersion preprocessor
variable to the value of the ProductVersion property in the wixproj which
we haven't set at all yet. Once nice thing about the way msbuild works
(msbuild is the engine that actually builds your wixproj) is that
environment variables can be accessed automatically as properties so all
you need to do is set a ProductVersion environment variable with your
actual version number and build your project normally.

If you call msbuild directly from your build scripts then you could set a
property on the command line rather than set an environment  variable. That
would look like this:

msbuild.exe /p:ProductVersion=1.2.3  ...

That covers at a very high level some approaches on how to define
ProductVersion outside your project so you can change it every build. The
next step to figure out how exactly you change the ProductVersion every
build. That will depend a lot on how your company versions its software.

You can read the requirements imposed by the Windows Installer on
ProductVersion below:

https://msdn.microsoft.com/en-us/library/windows/desktop/aa370859(v=vs.85).aspx

Whatever you do MUST fall within those restrictions.

Most places I've heard about want to manually change the first three
version components and auto-increment the fourth component using the build
number from their build/CI system. This, of course, doesn't work with the
Windows Installer and doesn't match the remarks for the System.Version
class from the .NET Framework which has some solid advice on when version
should be changed.

https://docs.microsoft.com/en-us/dotnet/api/system.version

IF you followed the remarks for the System.Version class then the build
number from your build/CI system would be the third component for
ProductVersion (hey, maybe that's why the call the third component build)
and you manually change the first two components, major and minor. Using
this approach allows you to service released versions (think hotfixes) by
increasing the fourth component, release, and you'd implement as a small
update in patch.

But most organizations resist those guidelines and you're forced to
something clunky like arbitrarily combine version components in a way that
still works with the restrictions imposed by the Windows Installer. I'm
sure everybody on this mailing list has different advice and approaches on
what transform to apply. As a concrete example, my organization decided to
combine the third (buildNumber) and fourth (releaseNumber) components as
follows: buildNumber * 10000 + releaseNumber where releaseNumber is
incremented automatically for every build. This means that releaseNumber
must never be higher than 9999 as long as buildNumber is less than or equal
to 5 and when buildNumber is 6 then releaseNumber cannot be higher than
5535. Our buildNumber has never gone up higher than 1 so these rules worked
for us. Those rules may or may not work for you.

Once you come up with a strategy, use a script to "calculate" the
ProductVersion and pass it to your build using an approach similar to the
ones described above.

--
Edwin G. Castro



On Tue, May 29, 2018 at 9:36 AM, Ven H <venh.123 at gmail.com> wrote:

> Wow. Words of wisdom blended with experience, expertise and so much
> humility. Thanks a ton, Edwin, for that awesome and detailed explanation. I
> would like to take it further. When you say divide your package into
> smaller packages, can you please provide some more details on how to
> achieve it and how to manage manage product guids, upgrades and so on for
> all the packages together and what will be the points to keep in mind. If
> you could please provide some more details on how to go about, I would like
> to take it further.
>
> On the next part, I personally prefer Option 1 and I will tell my customer
> to go with that. So, can you please provide some more details about that as
> well?
>
> Regards,
> Venkatesh
>
> On Tue, May 29, 2018 at 7:31 PM, Edwin Castro <egcastr at gmail.com> wrote:
>
>> I'd recommend you always create and release major upgrades. In my opinion
>> that is the easiest to manage. That said, I think I remember you saying
>> once that your msi package was very, very large. Deliverying a large msi
>> package whenever anything changes might be overkill in your case. You might
>> then consider dividing your package into smaller packages you can deliver
>> independently from each other.
>>
>> Be adviced that a "patch" is a packaging option and not a type of
>> upgrade. For example, you can deliver a major upgrade via a regular msi
>> package OR a patch. I don't have practical experience with patches because
>> I avoid them so take the next opinion with a huge grain of salt... I
>> conceptually think that patches really don't mesh well with the concept of
>> continuous integration. A patch conceptually requires two msi packages to
>> create a "diff" from. In a continuous build scenario you need to be able to
>> answer the question of which msi package to use as the base msi package and
>> you can't answer that question effectively until after your first release.
>> In any case, you still need to create the "new" msi package for the "diff"
>> so I think it is always better to create major upgrade msi packages in
>> continuous builds and "manually" create patches when you actually need them
>> for a particular fix or customer. When I said "manual" above I meant
>> "automate the patch creation process so you can simply input the two msi
>> packages to 'diff' and manually invoke that script when you need it."
>>
>> For versioning, the only requirement is that your ProductVersion have
>> only 3 components less than the maximum: 255.255.65535. Note if you have a
>> 4th component, then the 4th component is ignored. I'd always set it to zero
>> as a reminder that it is always ignored.
>>
>> The type of upgrade dictates if you must change ProductVersion on every
>> build or not. For example, if you want to build major upgrades on every
>> build, you must change the ProductVersion on "every" build but you really
>> have two options.
>>
>> Option 1: always change ProductVersion. This allows you to test major
>> upgrades even from unreleased continuous builds in development. A very
>> useful tool but you do use up your available version numbers so that could
>> be a problem if you have a lot of continuous builds between releases.
>>
>> Option 2: change ProductVersion between releases. This allows you to keep
>> things simple as you can just keep the ProductVersion hardcoded and change
>> it only at the beginning of a new release. The downside is you can only
>> test major upgrades between a previous release and the current continuous
>> build since the ProductVersion is not changing from continuous build to
>> continuous build.
>>
>> We follow option 1 and we pass in our versioning information through
>> DefineConstants so the version information is available as preprocessor
>> variables. Let me know if you choose option 1 and I can provide more
>> details if you need help.
>>
>> --
>> Edwin G. Castro
>>
>>
>> On Tue, May 29, 2018, 06:15 Ven H via wix-users <
>> wix-users at lists.wixtoolset.org> wrote:
>>
>>> We have a requirement to generate MSI for automated builds. So, whenever
>>> code check-ins happen in SCM (this will also involve changes in Database
>>> scripts which have to be executed, IIS changes, registry changes, GAC
>>> changes, COM registration  etc. in addition to files), Jenkins will
>>> trigger
>>> a job at regular intervals by polling for changes in SCM. When this job
>>> runs, it has to create MSI. I have a couple of questions related to this.
>>>
>>> 1. Should I create a Patch or a Major Upgrade or a Minor Upgrade?
>>> Honestly,
>>> I am not sure how to create a Minor Upgrade though.
>>>
>>> 2. How should I manage versions in this case?
>>>
>>> Please help with your inputs.
>>>
>>> ____________________________________________________________________
>>> WiX Toolset Users Mailing List provided by FireGiant
>>> http://www.firegiant.com/
>>>
>>
>


More information about the wix-users mailing list