Skip to content

Instantly share code, notes, and snippets.

@vinhnx
Last active June 24, 2022 04:43
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
Star You must be signed in to star a gist
Save vinhnx/9e66b40e3a2b2f07e6aebaea7fccca02 to your computer and use it in GitHub Desktop.
advanced Fastfile config
# This file contains the fastlane.tools configuration
# You can find the documentation at https://docs.fastlane.tools
#
# For a list of all available actions, check out
#
# https://docs.fastlane.tools/actions
#
# Uncomment the line if you want fastlane to automatically update itself
# update_fastlane
default_platform(:ios)
platform :ios do
### BASE
# [!] NOTE [!]: you can put app_name here to start
app_name = "MyProject"
bundle_id = "com.myName.myProject"
### Constants
project = "#{app_name}.xcodeproj"
workspace = "#{app_name}.xcworkspace"
plist_path = "#{app_name}/#{app_name}-Info.plist"
### .ipa output folder
# [!] NOTE [!]: you can ignore `fastlane_builds` folder
# in .gitginore:
# `echo "\nfastlane_builds/*" >> .gitignore`
output_directory_staging = "fastlane_builds/staging"
output_directory_production = "fastlane_builds/production"
output_directory_appstore = "fastlane_builds/app_store"
### .ipa build path
pwd = `pwd`
project_directory = pwd[0..-11]
xcodeproj = "#{project_directory}/#{project}"
### Bundle IDs
staging_bundle_id = "#{bundle_id}.staging"
production_bundle_id = "#{bundle_id}.production"
appstore_bundle_id = bundle_id
### Provisioning Profile filename
staging_provisioning_profile = ""
production_provisioning_profile = ""
appstore_provisioning_profile = ""
### stages
before_all do
puts "starting Fastlane, have a coffee then sit back and relax..."
end
after_all do |lane|
notification(title: "[Fastlane]", message: "Completed #{lane} lane!")
end
error do |lane, exception|
clean_build_artifacts
notification(title: "[Fastlane] Lane #{lane} failed to executed!", message: exception.message)
end
### Version helper, semver
desc "Increment the app version patch (0.0.X)"
lane :bumpPatch do
increment_version_number(
bump_type: "patch"
)
commitVersionBumpWrapper
end
desc "Increment the app version minor (0.X.0)"
lane :bumpMinor do
increment_version_number(
bump_type: "minor"
)
commitVersionBumpWrapper
end
desc "Increment the app version major (X.0.0)"
lane :bumpMajor do
increment_version_number(
bump_type: "major"
)
commitVersionBumpWrapper
end
desc "Increment the app's version number (required for app store build)"
lane :bumpVersion do
# check whether we should increase build version number
precheck = prompt(text: "\nCurrent build version number: #{get_version_number}.\nWould you like to increase the build number? ".blue, boolean: true)
if precheck == true
# enter new version number
version_number = prompt(text: "\nCurrent build version number: #{get_version_number}" + "\nPlease enter new version number: ".yellow)
# increase version number then commit
confirm = prompt(text: "Confirm bump to: " + version_number + " ?", boolean: true)
raise "cancel..." if confirm == false
increment_version_number(version_number: version_number)
commitVersionBumpWrapper
end
end
lane :buildInteractive do
ensure_git_status_clean
# constants
staging = "staging"
production = "production"
valid_environments = [staging, production]
# prompt
choosing_environment = prompt(text: "\n> Preparing to build. Please choose build envoriment, possible values are: #{valid_environments}...".yellow)
environment = choosing_environment
# assert if `environment` is valid
if not valid_environments.include? environment
raise "\n> #{environment} is not either (#{staging}, #{production}), cancel..."
end
env_prompt = "[ENV: #{environment}]"
choosing_branch = prompt(text: "\n#{env_prompt} > Preparing to build. Current branch is `#{git_branch}`.\nWould you like to change branch?".blue, boolean: true)
branch = git_branch
if choosing_branch
# custom branch
branch = prompt(text: "\n#{env_prompt} > Please type a branch name to build from: ".yellow)
end
confirm = prompt(text: """
#{env_prompt}
* build environment: #{environment}
* git branch: #{branch}
Confirm build? (y/n)
""".red)
raise "cancel..." if confirm == false
ensure_lane(branch: branch)
if environment == staging
buildStagingNoPush
uploadStagingBuildToAppManager
elsif environment == production
buildProductionNoPush
uploadProductionBuildToAppManager
end
git_push_upstream(branch: branch)
end
lane :buildProductionInteractive do
buildInteractive
end
lane :buildStagingInteractive do
buildInteractive
end
desc "Increment the app's build number"
lane :bumpBuild do
new_build_number = get_build_number.to_i + 1
increment_build_number(build_number: new_build_number)
commitVersionBumpWrapper
end
lane :bumpBuildCustom do |options|
# usage: `fastlane bumpBuildCustom number:${NEW_BUILD_NUMBER}`
new_build_number = options[:number]
increment_build_number(build_number: new_build_number)
commitVersionBumpWrapper
end
### Test
desc "Runs all the tests"
lane :test do
scan
end
### git
lane :git_push_upstream do |options|
branch = options[:branch]
ensure_lane(branch: branch)
push_to_git_remote(
remote: "upstream",
local_branch: branch,
remote_branch: branch,
)
end
lane :gitPushUpstreamMaster do
ensureMaster
push_to_git_remote(
remote: "upstream",
local_branch: "master",
remote_branch: "master",
)
end
lane :ensure_lane do |options|
ensure_git_branch(branch: options[:branch])
end
desc "Make sure current branch is `master`"
lane :ensureMaster do
# reference: https://docs.fastlane.tools/actions/#source-control
ensure_git_branch(
branch: 'master'
)
end
desc "Make sure current branch is `develop`"
lane :ensureDevelop do
# reference: https://docs.fastlane.tools/actions/#source-control
ensure_git_branch(
branch: 'develop'
)
end
desc "Create/make app store git tag for release"
lane :makeAppStoreGitTag do
add_git_tag(
tag: "v" + get_version_number + "-" + get_build_number
)
end
desc "Push git tag to git `upstream`"
lane :pushGitTag do
push_git_tags(
remote: "upstream"
)
end
desc "Create release git tag and push to upstream"
lane :makeAndPushReleaseTag do
ensure_git_status_clean
ensureMaster
makeAppStoreGitTag
pushGitTag
end
### Build
## BULD STAGING AND PRODUCTION on APP MANAGER ##
desc "Build staging and production"
lane :buildStagingAndProduction do
buildStagingNoPush
buildProductionNoPush
uploadStagingBuildToAppManager
uploadProductionBuildToAppManager
end
desc "Build staging and production, then git push"
lane :buildStagingAndProductionThenPush do
buildStagingNoPush
buildProductionNoPush
uploadStagingBuildToAppManager
uploadProductionBuildToAppManager
gitPushUpstreamMaster
end
## STAGING ##
desc "Build staging => push to git upstream => upload to app manager"
lane :buildStaging do
buildStagingNoPush
gitPushUpstreamMaster
uploadStagingBuildToAppManager
end
desc "Build staging, but no git push"
lane :buildStagingNoPush do
ensure_git_status_clean
bumpBuild
# vars
scheme_name = "MyProject - Staging"
configuration = "Release - Staging"
export_method = "enterprise"
version = get_info_plist_value(path: plist_path, key: "CFBundleShortVersionString")
build = get_info_plist_value(path: plist_path, key: "CFBundleVersion")
output_name = "#{app_name}_STAGING_" + "v" + version + "-" + build
gym(
project: xcodeproj, # change to workspace: "your.xcworkspace" if you use CocoaPod
scheme: scheme_name,
configuration: configuration,
output_name: output_name,
output_directory: "./" + output_directory_staging,
export_options: {
method: export_method,
provisioningProfiles: {
staging_bundle_id => staging_provisioning_profile
}
}
)
end
## PRODUCTION ##
desc "Build production => push to git upstream => upload to app manager"
lane :buildProduction do
buildProductionNoPush
gitPushUpstreamMaster
uploadProductionBuildToAppManager
end
desc "Build production, but no git push"
lane :buildProductionNoPush do
ensure_git_status_clean
#bumpBuild
# vars
scheme_name = "MyProject - Production"
configuration = "Release - Production"
export_method = "enterprise"
version = get_info_plist_value(path: plist_path, key: "CFBundleShortVersionString")
build = get_info_plist_value(path: plist_path, key: "CFBundleVersion")
output_name = "#{app_name}_PRODUCTION_" + "v" + version + "-" + build
gym(
project: xcodeproj, # change to workspace: "your.xcworkspace" if you use CocoaPod
scheme: scheme_name,
configuration: configuration,
output_name: output_name,
output_directory: "./" + output_directory_production,
export_options: {
method: export_method,
provisioningProfiles: {
production_bundle_id => production_provisioning_profile
}
}
)
end
## APP STORE ##
desc "Build App Store dry run, no increase version number or build number (assume already did so)"
lane :buildAppStoreNoBump do |options|
ensureMaster
ensure_git_status_clean
makeAppStoreBuild
makeAppStoreGitTag
gitPushUpstreamMaster
pushGitTag
end
desc "Build App Store"
lane :buildAppStore do |options|
ensureMaster
ensure_git_status_clean
bumpVersion
bumpBuild
makeAppStoreBuild
makeAppStoreGitTag
gitPushUpstreamMaster
pushGitTag
end
desc "Build app store"
lane :makeAppStoreBuild do
# vars
scheme_name = "MyProject - App Store"
configuration = "Release"
export_method = "app-store"
version = get_info_plist_value(path: plist_path, key: "CFBundleShortVersionString")
build = get_info_plist_value(path: plist_path, key: "CFBundleVersion")
output_name = "#{app_name}_APPSTORE_" + "v" + version + "-" + build
gym(
project: xcodeproj, # change to workspace: "your.xcworkspace" if you use CocoaPod
scheme: scheme_name,
configuration: configuration,
output_name: output_name,
output_directory: "./" + output_directory_appstore,
export_options: {
method: export_method,
provisioningProfiles: {
appstore_bundle_id => appstore_provisioning_profile
}
}
)
end
# Helper
# build number (X)
lane :current_build_number do
puts "current build number is: #{get_build_number}"
end
# version number (X.Y.Z)
lane :current_version_number do
puts "current version number is: #{get_version_number}"
end
desc "Commit version bump wrapper"
lane :commitVersionBumpWrapper do
commit_version_bump(
xcodeproj: project, # optional, if you have multiple Xcode project files, you must specify your main project here
)
end
desc "run SwiftLint linter"
lane :run_swiftlint do
# [!] need to install swiftlint executable first
# https://github.com/realm/SwiftLint
# reference: https://docs.fastlane.tools/actions/swiftlint/
swiftlint(
mode: :lint, # SwiftLint mode: :lint (default) or :autocorrect
config_file: "#{project_directory}/.swiftlint.yml", # The path of the configuration file (optional)
ignore_exit_status: true # Allow fastlane to continue even if SwiftLint returns a non-zero exit status
)
end
desc "Build STAGING and upload to app manager, on custom branch (non-master)"
lane :buildAndUploadStagingCustomBranch do
# make sure git status is clean -> bump build number -> build archive -> upload to app manager
ensure_git_status_clean
# bumpBuild
buildStagingNoPush
uploadStagingBuildToAppManager
end
desc "Build PRODUCTION and upload to app manager, on custom branch (non-master)"
lane :buildAndUploadProductionCustomBranch do
# make sure git status is clean -> bump build number -> build archive -> upload to app manager
ensure_git_status_clean
# bumpBuild
buildProductionNoPush
uploadProductionBuildToAppManager
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment