SOLVED: Auto-incrementing build number / version number

MikeLorenzMikeLorenz USMember

Hi everyone!

Auto-incrementing IPA build numbers is very important to me, so I wanted to figure out how to do this w/ Xamarin. It took me a while but figure it out, so I decided I'd blog about it and share it with anyone here who's interested. Apologies in advance if this is old material covered elsewhere -- I couldn't find anything comprehensive.

Setting iOS version numbers in Xamarin

Posts

  • AshleyJacksonAshleyJackson GBMember ✭✭

    Hi, trying to read your link but just getting a 404

  • MikeLorenzMikeLorenz USMember

    Sorry, the new link is here.

  • anveanve DEMember ✭✭

    Where do I get PlistBuddy? It is a PowerPC application and doesn't run on the latest Mac OS X. How would the script does look like if only the build number is increased? Because I want to set the version number manually.

    Is there perhaps a more convenient way available?

  • FlorianBURELFlorianBUREL USMember, University

    Nice. Thanks!
    Any idea for the android part?

  • BobisbackBobisback USUniversity ✭✭

    Is there a updated link to this?

    Thanks,
    Bob

  • chrishollanderchrishollander USMember ✭✭

    this is cruel; this is exactly the info that i need, and both links are dead. any chance that the info could be reposted directly into the forum?

  • AnthonyXAnthonyX USMember

    for andoid builds I use the following build target in the .csproj . The version number is picked up from an environment var set on the bamboo CI build agent. works well with no need for external tool dependencies.

    Now just need similar approach for the ios builds ...

      <!--  Added to provide autoamtic build number of android package when building on bamboo agent-->
      <Target Name="BeforeBuild" Condition=" '$(bamboo_buildNumber)' > '1' ">
        <XmlPoke XmlInputPath="Properties\AndroidManifest.xml" Namespaces="&lt;Namespace Prefix='android' Uri='http://schemas.android.com/apk/res/android' /&gt;" Query="manifest/@android:versionCode" Value="$(bamboo_buildNumber)" />
        <XmlPoke XmlInputPath="Properties\AndroidManifest.xml" Namespaces="&lt;Namespace Prefix='android' Uri='http://schemas.android.com/apk/res/android' /&gt;" Query="manifest/@android:versionName" Value="1.0.$(bamboo_buildNumber)" />
      </Target>
    
    
  • Tro_SoloTro_Solo DEMember ✭✭

    For anyone still looking for a solution, Tyler Romeo of willowtreeapps.com has blogged about their solution which is using MSBuild and the XmlPoke task: https://willowtreeapps.com/ideas/automatic-build-numbering-with-xamarin/

    For future reference I'm going to add the custom MSBuild targets to this comment. Please note, that none of this is my code - all kudos should be aimed at Tyler Romeo directly.

    Android
    Add this to your Xamarin.Android.csproj file:

    <Target Name="BeforeBuild" Condition=" $(SetVersion) == true ">
      <!-- This parses the semantic version number from the shared code assembly (e.g. PCL) -->
      <GetAssemblyIdentity AssemblyFiles="$(AssemblyPath)">
        <Output TaskParameter="Assemblies" ItemName="AssemblyInfo" />
      </GetAssemblyIdentity>
      <PropertyGroup>
        <VersionNumber>$([System.Text.RegularExpressions.Regex]::Match(%(AssemblyInfo.Version), '[^.][^.]*.[^.]*.[^.]*'))</VersionNumber>
      </PropertyGroup>
      <XmlPoke XmlInputPath="Properties\AndroidManifest.xml" Namespaces="&lt;Namespace Prefix='android' Uri='http://schemas.android.com/apk/res/android' /&gt;" Query="manifest/@android:versionCode" Value="$(BuildNumber)" />
      <XmlPoke XmlInputPath="Properties\AndroidManifest.xml" Namespaces="&lt;Namespace Prefix='android' Uri='http://schemas.android.com/apk/res/android' /&gt;" Query="manifest/@android:versionName" Value="$(VersionNumber).$(BuildNumber)" />
    </Target>
    

    iOS
    Add this to your Xamarin.iOS.csproj file:

    <Target Name="BeforeBuild" Condition=" $(SetVersion) == true ">
      <!-- This parses the semantic version number from the shared code assembly (e.g. PCL) -->
      <GetAssemblyIdentity AssemblyFiles="$(AssemblyPath)">
        <Output TaskParameter="Assemblies" ItemName="AssemblyInfo" />
      </GetAssemblyIdentity>
      <PropertyGroup>
        <VersionNumber>$([System.Text.RegularExpressions.Regex]::Match(%(AssemblyInfo.Version), '[^.][^.]*.[^.]*.[^.]*'))</VersionNumber>
      </PropertyGroup>
      <XmlPoke XmlInputPath="Resources/Info.plist" Query="//dict/key[. = 'CFBundleVersion']/following-sibling::string[1]" Value="$(BuildNumber)" />
      <XmlPoke XmlInputPath="Resources/Info.plist" Query="//dict/key[. = 'CFBundleShortVersionString']/following-sibling::string[1]" Value="$(VersionNumber)" />
    </Target>
    

    Last, but not least, on your CI server add /p:SetVersion=true /p:BuildNumber={build number} /p:AssemblyPath={path to assembly file with shared assembly version} to the list of MSbuild arguments.

  • OmarOsOmarOs USMember
    edited August 16
    I am pretty new to Xamarin and using CI
    My question is, what exactly is the AssemblyPath on CI? Thank you.
  • Tro_SoloTro_Solo DEMember ✭✭

    Hi @OmarOs.
    The value of the AssemblyPath parameter should refer to the location of the .dll file of your Xamarin.Forms PCL project. Given your project would be named My.Simple.Example and using the same namespace, the default directory structure would be %WORKSPACE%\My\Simple\Example\bin\Release\My.Simple.Example.dll - assuming you use the default OutputPath of bin\Release\ (which is defined within the .csproj file of your project).
    I don't know which CI you're using, but using something like /p:AssemblyPath=%WORKSPACE%\My\Simple\Example\My.Simple.Example.dll works for our Jenkins CI server which is running on a Windows machine.

    Please note, that this file will be generated during the build process, hence the PCL part of the Xamarin.Forms project must be built before the platform specific projects (e.g. My.Simple.Example.Droid or My.Simple.Example.iOS). Usually, the IDE will take care of this dependency structure and update the .sln file accordingly, so probably you don't have to worry about it.

  • ShraddhaChavanShraddhaChavan USMember

    Hi @Tro_Solo, I tried to implement this into VSTS build definition however I am getting below error message:

    MSBUILD : error MSB1005: Specify a property and its value.
    Switch: /property:SetVersion=true;

    For switch syntax, type "MSBuild /help"
    Process 'msbuild.exe' exited with code '1'.

    I have added the code in android proj.cs file and defines MS build arguments with: /property:SetVersion=true; BuildNumber={build number}; AssemblyPath=drop\projectname.Core.dll

    we have three core PCL projects along with three main platform projects android/ios and UWP. We also have three different build definitions in VSTS and the source is Git controlled. I have given assembly path of the most common project between three platforms. Not sure if I am defining this wrong or missing something specifically in VSTS.

    Thank you!

  • BalakrishnanSBalakrishnanS USMember ✭✭

    @Tro_Solo said:
    For anyone still looking for a solution, Tyler Romeo of willowtreeapps.com has blogged about their solution which is using MSBuild and the XmlPoke task: https://willowtreeapps.com/ideas/automatic-build-numbering-with-xamarin/

    For future reference I'm going to add the custom MSBuild targets to this comment. Please note, that none of this is my code - all kudos should be aimed at Tyler Romeo directly.

    Android
    Add this to your Xamarin.Android.csproj file:

    <Target Name="BeforeBuild" Condition=" $(SetVersion) == true ">
      <!-- This parses the semantic version number from the shared code assembly (e.g. PCL) -->
      <GetAssemblyIdentity AssemblyFiles="$(AssemblyPath)">
        <Output TaskParameter="Assemblies" ItemName="AssemblyInfo" />
      </GetAssemblyIdentity>
      <PropertyGroup>
        <VersionNumber>$([System.Text.RegularExpressions.Regex]::Match(%(AssemblyInfo.Version), '[^.][^.]*.[^.]*.[^.]*'))</VersionNumber>
      </PropertyGroup>
      <XmlPoke XmlInputPath="Properties\AndroidManifest.xml" Namespaces="&lt;Namespace Prefix='android' Uri='http://schemas.android.com/apk/res/android' /&gt;" Query="manifest/@android:versionCode" Value="$(BuildNumber)" />
      <XmlPoke XmlInputPath="Properties\AndroidManifest.xml" Namespaces="&lt;Namespace Prefix='android' Uri='http://schemas.android.com/apk/res/android' /&gt;" Query="manifest/@android:versionName" Value="$(VersionNumber).$(BuildNumber)" />
    </Target>
    

    iOS
    Add this to your Xamarin.iOS.csproj file:

    <Target Name="BeforeBuild" Condition=" $(SetVersion) == true ">
      <!-- This parses the semantic version number from the shared code assembly (e.g. PCL) -->
      <GetAssemblyIdentity AssemblyFiles="$(AssemblyPath)">
        <Output TaskParameter="Assemblies" ItemName="AssemblyInfo" />
      </GetAssemblyIdentity>
      <PropertyGroup>
        <VersionNumber>$([System.Text.RegularExpressions.Regex]::Match(%(AssemblyInfo.Version), '[^.][^.]*.[^.]*.[^.]*'))</VersionNumber>
      </PropertyGroup>
      <XmlPoke XmlInputPath="Resources/Info.plist" Query="//dict/key[. = 'CFBundleVersion']/following-sibling::string[1]" Value="$(BuildNumber)" />
      <XmlPoke XmlInputPath="Resources/Info.plist" Query="//dict/key[. = 'CFBundleShortVersionString']/following-sibling::string[1]" Value="$(VersionNumber)" />
    </Target>
    

    Last, but not least, on your CI server add /p:SetVersion=true /p:BuildNumber={build number} /p:AssemblyPath={path to assembly file with shared assembly version} to the list of MSbuild arguments.

    Hi Can you tell me In which section of the project file I need to include this script in IOS and Android project file.

Sign In or Register to comment.