Automating Mac App Store Receipt Validation and Version Numbers

October 12, 2012
App Store Cocoa

I recently updated my MAS receipt validation code. The old code had a lot of deprecations and I wanted to get rid of those. I found this. It compiled with no warnings and worked great. I didn’t even need to have a fake receipt for development. (To get a development receipt, you need to launch the app outside of Xcode. OS X will then ask you for test user credentials that you set up in iTunes connect and then download a receipt you can use for testing). The only thing I didn’t like about it was that you had to hard code the version number of your app. This meant every time I released, I would have to remember to update the hard-coded version number. This seemed like a disaster waiting to happen. So, I decided to write a script to automate the process. When you released a new version to the app store, you have to increase the version number anyway, so why not automate the whole process.

Here’s set-version.rb:

#! /usr/bin/env ruby

#
# Ruby Script to set the version (build number and marketing version) of an Xcode
# project
#
# Execute and then build before submitting to App Store
#

if ARGV.count != 1
 puts "usage:tset-version <version>ntwhere version is of the format x.x.x"
 exit
end

version = ARGV\[0\]

#
# Next run agvtool to bump build number and set marketing version
#
puts "Running agvtool..."
result = system "agvtool bump -all"
unless result
 puts "Unable to bump build number"
 exit
end

result = system "agvtool new-marketing-version #{version} > agvtool.txt"
unless result
 puts "Unable to set version with agvtool"
 exit
end
\`rm agvtool.txt\`
puts ""

\# Next, generate .c file with version number. This file will be used by
# the receipt validation
#
puts "Updating version.m..."
result = system "sed -e 's/@".\*"/@"#{version}"/g' -i .old Numerology/version.m"
unless result
 puts "Unable to update version.m"
 exit
end
\`rm Numerology/version.m.old\`
puts ""

#
# Now check in changes
#
puts "Commiting Changes to Git..."
result = system "git commit -a -m"Updated build number and version to #{version}""
unless result
 puts "Unable to commit to Git"
 exit
end
puts ""

#
# First tag Git repository
#
puts "Tagging Git Repository with #{version}..."
result = system "git tag -a "#{version}" -m "#{version}""
unless result
 puts "Unable to tag git repository"
 exit
end
puts ""
puts "Version successfully updated to #{version}" 

To use it, you first need to do some setup.

  • Make sure you have setup your Xcode project to use agvtool for versioning.
  • Create a version.h and version.m that declares a global variable that will contain the version number string. Call it something like gVersionNumber. The files would look something like this:

version.h

extern NSString \*gVersionNumber;

version.c

NSString \*gVersionNumber = @"1.0";
  • Change the receipt validation code to use the variable you created above and include version.h

Once you do that, simply type ./set-version.rb and pass it the new version number. The script will:

  • run the agvtool to bump your build number and set your new marketing version (the version number).
  • Modify version.c with the new version number
  • Commit your changes to git
  • Tag the git repository with the new version number

It’s best to run this right before you do your final build so that the git tag contains all the code that will be in your release.