fastlane: Add utilities to increment version numbers and allow uploading RCs to beta

Signed-off-by: Álvaro Brey <alvaro.brey@nextcloud.com>
This commit is contained in:
Álvaro Brey 2023-02-03 11:54:43 +01:00
parent 5a8bad3a58
commit 0825988be3
No known key found for this signature in database
GPG key ID: 2585783189A62105
2 changed files with 107 additions and 38 deletions

View file

@ -28,21 +28,37 @@ default_platform(:android)
BUNDLE_PATH = "app/build/outputs/bundle/playRelease/app-play-release.aab" BUNDLE_PATH = "app/build/outputs/bundle/playRelease/app-play-release.aab"
import("./utils.Fastfile") import("./common.Fastfile")
platform :android do platform :android do
desc "Build app bundle" desc "Build app bundle"
desc "Run tests and build app"
lane :releasePhase1 do lane :releasePhase1 do
test() test()
buildBundle() buildBundle()
end end
desc "Release previously built app to Google Play and create tag"
lane :releasePhase2 do
versionInfo = getVersionInfo()
versionComponents = parseVersionCode(versionInfo)
checkReleasable(versionComponents)
storeTrack = getPlayStoreTrack(versionComponents)
tagName = getTagName(versionComponents)
preReleaseChecks(versionInfo: versionInfo, tagName: tagName, type: versionComponents["type"], track: storeTrack)
checkArtifactsExist()
tag(tagName)
uploadToPlayStore()
end
desc "Run tests"
lane :test do lane :test do
gradle(task: "clean testPlayReleaseUnitTest testFdroidReleaseUnitTest") gradle(task: "clean testPlayReleaseUnitTest testFdroidReleaseUnitTest")
end end
lane :buildBundle do desc "Build app bundle"
lane :buildBundle do
gradle( gradle(
task: 'bundle', task: 'bundle',
flavor: 'play', flavor: 'play',
@ -57,29 +73,24 @@ desc "Build app bundle"
) )
end end
lane :releasePhase2 do
versionInfo = getVersionInfo()
promptVersion(versionInfo)
checkArtifactsExist()
tag(versionInfo)
uploadToPlayStore()
end
desc "Show versions and prompt for confirmation" desc "Show versions and prompt for confirmation"
private_lane :promptVersion do |versionInfo| private_lane :preReleaseChecks do |options|
versionInfo = options[:versionInfo]
tagName = options[:tagName]
currentBranch = git_branch() currentBranch = git_branch()
print "Version code: #{versionInfo["versionCode"]}\n" text = "Version code: #{versionInfo["versionCode"]}\n" +
print "Version name: #{versionInfo["versionName"]}\n" "Version name: #{versionInfo["versionName"]}\n" +
print "Current branch: #{currentBranch}\n" "Current branch: #{currentBranch}\n" +
print "Tag (to be created): #{versionInfo["versionName"]}\n" "Version type: #{options[:type]}\n" +
promptYesNo() "Tag: #{tagName}\n" +
"Track: #{options[:track]}"
promptYesNo(text: text)
end end
desc "Check if release artifacts exist" desc "Check if release artifacts exist"
private_lane :checkArtifactsExist do private_lane :checkArtifactsExist do
if !File.exist?("../#{BUNDLE_PATH}") if !File.exist?("../#{BUNDLE_PATH}")
print "Bundle not found at #{BUNDLE_PATH}\n" UI.user_error!("Bundle not found at #{BUNDLE_PATH}")
exit
end end
end end
@ -95,11 +106,12 @@ desc "Build app bundle"
end end
desc "Upload release artifacts to Google Play" desc "Upload release artifacts to Google Play"
private_lane :uploadToPlayStore do private_lane :uploadToPlayStore do |options|
upload_to_play_store( upload_to_play_store(
skip_upload_images: true, skip_upload_images: true,
skip_upload_apk: true, skip_upload_apk: true,
aab: BUNDLE_PATH, track: options[:track],
aab: BUNDLE_PATH
) )
end end

View file

@ -5,6 +5,10 @@ MAJOR_MULTIPLIER = 10000000
MINOR_MULTIPLIER = 10000 MINOR_MULTIPLIER = 10000
PATCH_MULTIPLIER = 100 PATCH_MULTIPLIER = 100
TYPE_ALPHA = "alpha"
TYPE_RC = "rc"
TYPE_FINAL = "final"
platform :android do platform :android do
desc "Print version info" desc "Print version info"
lane :printVersionInfo do lane :printVersionInfo do
@ -18,7 +22,7 @@ platform :android do
print "Build: #{versionComponents["build"]}\n" print "Build: #{versionComponents["build"]}\n"
end end
# Usage: fastlane incrementVersion [type:major|minor|patch|rc|final] # Usage: fastlane incrementVersion type:(major|minor|patch|rc|final)
# For major, minor, and patch: will increment that version number by 1 and set the smaller ones to 0 # For major, minor, and patch: will increment that version number by 1 and set the smaller ones to 0
# For rc, final: will set build number to first rc/first final or increment it by 1 # For rc, final: will set build number to first rc/first final or increment it by 1
desc "Increment version code and version name" desc "Increment version code and version name"
@ -29,9 +33,9 @@ platform :android do
versionNameGenerated = generateVersionName(newVersionComponents) versionNameGenerated = generateVersionName(newVersionComponents)
versionCodeGenerated = generateVersionCode(newVersionComponents) versionCodeGenerated = generateVersionCode(newVersionComponents)
print "Version code: #{versionInfo["versionCode"]} -> #{versionCodeGenerated}\n" promptYesNo(text: "Version code: #{versionInfo["versionCode"]} -> #{versionCodeGenerated}\n" +
print "Version name: #{versionInfo["versionName"]} -> #{versionNameGenerated}\n" "Version name: #{versionInfo["versionName"]} -> #{versionNameGenerated}"
promptYesNo() )
writeVersions(versionCode: versionCodeGenerated, versionName: versionNameGenerated) writeVersions(versionCode: versionCodeGenerated, versionName: versionNameGenerated)
end end
@ -44,12 +48,30 @@ platform :android do
minor = (versionCode / MINOR_MULTIPLIER) % 100 minor = (versionCode / MINOR_MULTIPLIER) % 100
major = (versionCode / MAJOR_MULTIPLIER) % 100 major = (versionCode / MAJOR_MULTIPLIER) % 100
{ "major" => major, "minor" => minor, "patch" => patch, "build" => build } type = getVersionType(build: build)
{ "major" => major, "minor" => minor, "patch" => patch, "build" => build, "type" => type }
end end
desc "Get version type from build number"
private_lane :getVersionType do |options|
build = options[:build]
if build < BUILD_NUMBER_RC_START
type = TYPE_ALPHA
elsif build < BUILD_NUMBER_FINAL_START
type = TYPE_RC
else
type = TYPE_FINAL
end
type
end
desc "Generate versionCode from version components" desc "Generate versionCode from version components"
private_lane :generateVersionCode do |versionComponents| private_lane :generateVersionCode do |versionComponents|
print "Generating version code from #{versionComponents}\n" puts "Generating version code from #{versionComponents}"
major = versionComponents["major"] major = versionComponents["major"]
minor = versionComponents["minor"] minor = versionComponents["minor"]
patch = versionComponents["patch"] patch = versionComponents["patch"]
@ -62,12 +84,13 @@ platform :android do
private_lane :generateVersionName do |versionComponents| private_lane :generateVersionName do |versionComponents|
suffix = "" suffix = ""
buildNumber = versionComponents["build"] buildNumber = versionComponents["build"]
puts "Generating version name from #{versionComponents}\n"
case case
when buildNumber >= BUILD_NUMBER_RC_START && buildNumber < BUILD_NUMBER_FINAL_START when versionComponents["type"] == TYPE_RC
rcNumber = (buildNumber - BUILD_NUMBER_RC_START) + 1 rcNumber = (buildNumber - BUILD_NUMBER_RC_START) + 1
suffix = " RC #{rcNumber}" suffix = " RC#{rcNumber}"
when buildNumber < BUILD_NUMBER_RC_START when versionComponents["type"] == TYPE_ALPHA
suffix = " Alpha #{buildNumber + 1}" suffix = " Alpha#{buildNumber + 1}"
end end
"#{versionComponents["major"]}.#{versionComponents["minor"]}.#{versionComponents["patch"]}#{suffix}" "#{versionComponents["major"]}.#{versionComponents["minor"]}.#{versionComponents["patch"]}#{suffix}"
end end
@ -111,28 +134,62 @@ platform :android do
versionComponents["patch"] = versionComponents["patch"] + 1 versionComponents["patch"] = versionComponents["patch"] + 1
versionComponents["build"] = 0 versionComponents["build"] = 0
when "rc" when "rc"
if versionComponents["build"] < BUILD_NUMBER_RC_START || versionComponents["build"] >= BUILD_NUMBER_FINAL_START if versionComponents["type"] != TYPE_RC
versionComponents["build"] = BUILD_NUMBER_RC_START versionComponents["build"] = BUILD_NUMBER_RC_START
else else
versionComponents["build"] = versionComponents["build"] + 1 versionComponents["build"] = versionComponents["build"] + 1
end end
when "final" when "final"
if versionComponents["build"] < BUILD_NUMBER_FINAL_START if versionComponents["type"] != TYPE_FINAL
versionComponents["build"] = BUILD_NUMBER_FINAL_START versionComponents["build"] = BUILD_NUMBER_FINAL_START
else else
versionComponents["build"] = versionComponents["build"] + 1 versionComponents["build"] = versionComponents["build"] + 1
end end
else else
print "Unknown or missing version type: #{options[:type]}\n" UI.user_error!("Unknown or missing version increment type #{options[:type]}. Usage: incrementVersion type:(major|minor|patch|rc|final)")
exit
end end
versionComponents["type"] = getVersionType(build: versionComponents["build"])
versionComponents versionComponents
end end
private_lane :promptYesNo do desc "Get tag name from version components"
answer = prompt(text: "is this okay?", boolean: true) private_lane :getTagName do |versionComponents|
if !answer if versionComponents["type"] == TYPE_FINAL
exit tag = "#{versionComponents["major"]}.#{versionComponents["minor"]}.#{versionComponents["patch"]}"
elsif versionComponents["type"] == TYPE_RC
rcNumber = (versionComponents["build"] - BUILD_NUMBER_RC_START) + 1
rcNumberPadded = "%02d" % rcNumber
tag = "rc-#{versionComponents["major"]}.#{versionComponents["minor"]}.#{versionComponents["patch"]}-#{rcNumberPadded}"
else
UI.user_error!("Build number cannot be tagged: #{versionComponents["build"]}")
end end
end end
desc "Check if version is releasable"
private_lane :checkReleasable do |versionComponents|
if versionComponents["type"] != TYPE_FINAL && versionComponents["type"] != TYPE_RC
UI.user_error!("Version is not releasable: #{versionComponents["type"]}")
end
end
desc "Get play store track from version type"
private_lane :getPlayStoreTrack do |versionComponents|
case versionComponents["type"]
when TYPE_RC
track = "beta"
when TYPE_FINAL
track = "production"
else
UI.user_error!("Version is not releasable: #{versionComponents["type"]}")
end
end
end
private_lane :promptYesNo do |options|
puts "\n" + options[:text]
answer = prompt(text: "is this okay?", boolean: true)
if !answer
UI.user_error!("Aborting")
end
end end