Versão de incremento automático no Xcode

Um dia decidi estar um passo mais perto do emprego dos meus sonhos de “Engenheiro de Construção”.

Portanto, acho que seria ótimo apenas fazer um cmd + B (ou pressionar um Arquivo para exportar) e o número de compilação (ou versão) de um aplicativo é incrementado nos bastidores sem minha ajuda.

Vamos incrementar algo!

Antes de fazer o script, precisamos entender como os números de versão são atribuídos e incrementados.

O sistema de controle de versão mais comum é o SemVer.
Há uma breve descrição dele:

Dado um número de versão MAJOR.MINOR.PATCH, incremente:
1. Versão PRINCIPAL quando houver alterações de API incompatíveis,
2. Versão MINOR quando adicionar funcionalidade de maneira compatível com versões anteriores e
3. Versão PATCH quando fizer bug compatível com versões anteriores Conserta.

Em projetos Xcode, temos 2 propriedades para controle de versão:

CFBundleVersion (String – iOS, OS X) especifica o número da versão da compilação do pacote, que identifica uma iteração (lançada ou não) do pacote. O número da versão do build deve ser uma string composta por três inteiros não negativos separados por ponto, sendo o primeiro inteiro maior que zero. A string deve conter apenas caracteres numéricos (0-9) e ponto (.). Os zeros à esquerda são truncados de cada número inteiro e serão ignorados (ou seja, 1.02.3 é equivalente a 1.2.3).

Esta propriedade deve ser atualizada em cada iteração de compilação e o script tem a seguinte aparência:

# @desc Auto-increment the build number every time the project is run. 
# @usage
# 1. Select: your Target in Xcode
# 2. Select: Editor -> Sheme -> Edit scheme
# 3. Select: Build -> Pre-action -> + New Run Script Action
# 4. Paste code below in to new "Run Script" section
# 5. Select your target in "Provide build settings from"
# 6. Insure that your starting build number is set to a whole integer and not a float (e.g. 1, not 1.0)

buildNumber
=$(/usr/libexec/PlistBuddy -c "Print CFBundleVersion" "${PROJECT_DIR}/${INFOPLIST_FILE}")
buildNumber
=$(($buildNumber + 1))
/usr/libexec/PlistBuddy -c "Set :CFBundleVersion $buildNumber" "${PROJECT_DIR}/${INFOPLIST_FILE}"

Outra propriedade de versão importante é um

CFBundleShortVersionString (String – iOS, OS X) especifica o número da versão de lançamento do pacote, que identifica uma iteração lançada do aplicativo. O número da versão de lançamento é uma string composta por três inteiros separados por pontos.

E se usarmos um script de protocolo SemVer pode ter a seguinte aparência:

# @desc Auto-increment the version number (only) when a project is archived for export. 
# @usage
# 1. Select: your Target in Xcode
# 2. Select: Editor -> Sheme -> Edit scheme
# 3. Select: Build -> Pre-action -> + New Run Script Action
# 4. Paste code below in to new "Run Script" section
# 5. Select your target in "Provide build settings from"
# 6. Insure your starting version number is in SemVer format (e.g. 1.0.0)

# This splits a two-decimal version string, such as "0.1.2", allowing us to increment only the third position.
VERSION
=$(/usr/libexec/PlistBuddy -c "Print CFBundleShortVersionString" "${PROJECT_DIR}/${INFOPLIST_FILE}")
NEWSUBVERSION
=$(echo $VERSION | awk -F "." '{print $3}')
NEWSUBVERSION
=$(($NEWSUBVERSION + 1))
NEWVERSIONSTRING
=$(echo $VERSION | awk -F "." '{print $1 "." $2 ".'$NEWSUBVERSION'" }')
/usr/libexec/PlistBuddy -c "Set :CFBundleShortVersionString $NEWVERSIONSTRING" "${PROJECT_DIR}/${INFOPLIST_FILE}"

Se você descobrir que um protocolo SemVer não é o seu caminho e deseja incrementar diretamente através de 3 números de versão, como:

0.1.9 -> 0.2.0
0.9.9 -> 1.0.0

Seu script pode ter a seguinte aparência:

    # @desc Auto-increment the version number through all numbers (only) when a project is archived for export. 
# @usage
# 1. Select: your Target in Xcode
# 2. Select: Editor -> Sheme -> Edit scheme
# 3. Select: Build -> Pre-action -> + New Run Script Action
# 4. Paste code below in to new "Run Script" section
# 5. Select your target in "Provide build settings from"
# 6. Insure your starting version number is in SemVer format (e.g. 1.0.0)

version
=$(/usr/libexec/PlistBuddy -c "Print CFBundleShortVersionString" "${PROJECT_DIR}/${INFOPLIST_FILE}")
major
=$(echo $version | awk -F \. '{print $1}')
minor
=$(echo $version | awk -F \. '{print $2}')
patch
=$(echo $version | awk -F \. '{print $3}')

if [ $patch == 9 ]; then
if [ $minor == 9 ]; then
((major++))
minor
="0"
patch
="0"
else
((minor++))
patch
="0"
fi
else
((patch++))
fi
newversion
="$major.$minor.$patch"

/usr/libexec/PlistBuddy -c "Set :CFBundleShortVersionString $newversion" "${PROJECT_DIR}/${INFOPLIST_FILE}"

Algumas pessoas preferem usar arquivos .xcconfig como uma configuração básica para destinos diferentes.
Podemos adicionar campos personalizados para controle de versão

//  User-Defined
// {
APP_SHORT_VERSION
= 1.2.3
APP_BUNDLE_VERSION
= 1.2.3
// }

Cenário

Além disso, você pode incrementar a versão com o script

if [ "${CONFIGURATION}" = "Release" ]; then
version
=$(grep -o "VERSION = [0-9]*\.[0-9]*\.[0-9]*" ${SRCROOT}/App.xcconfig | tail -1 | tr -d 'VERSION = ')
major
=$(echo $version | awk -F \. '{print $1}')
minor
=$(echo $version | awk -F \. '{print $2}')
patch
=$(echo $version | awk -F \. '{print $3}')

if [ $patch == 9 ]; then
if [ $minor == 9 ]; then
((major++))
minor
="0"
patch
="0"
else
((minor++))
patch
="0"
fi
else
((patch++))
fi
incremented_version
="$major.$minor.$patch"
# replace version in file
$
(sed -i '' -e "s/${version}/${incremented_version}/" ${SRCROOT}/App.xcconfig)