Skip to content

Instantly share code, notes, and snippets.

@FranDepascuali
Last active December 6, 2024 01:57
Show Gist options
  • Save FranDepascuali/4cbd5d1709bfc7ffce478040418434b9 to your computer and use it in GitHub Desktop.
Save FranDepascuali/4cbd5d1709bfc7ffce478040418434b9 to your computer and use it in GitHub Desktop.
Publish a new fastlane version of a RN iOS app
# Import the iOS-specific Fastlane configuration
import("../ios/fastlane/ios_fastfile")
# Shared lanes for version management and release notes generation
lane :get_version_from_tag do |options|
# Ensure required environment variables are present
ensure_env_vars(
env_vars: ['GIT_TAG']
)
# Get the tag prefix from options and validate
tag_prefix = options[:tag_prefix]
if tag_prefix.nil?
UI.user_error!("No tag_prefix passed.")
end
# Process the git tag to extract version
git_tag = ENV["GIT_TAG"].dup
unless git_tag.include?(tag_prefix)
UI.user_error!("Invalid git_tag. Valid tag must contain #{tag_prefix}")
end
# Remove prefix to get clean version number
git_tag.sub!(tag_prefix, "")
git_tag
end
lane :release_notes do |options|
# Ensure required environment variables are present
ensure_env_vars(
env_vars: ['GIT_TAG']
)
# Get the current git tag
git_tag = ENV["GIT_TAG"]
puts "Deleting tag #{git_tag}"
# Handle tag management
if `git tag -l "#{git_tag}"`.empty?
puts "Tag #{git_tag} does not exist, skipping deletion."
else
sh("git tag -d #{git_tag}")
puts "Tag #{git_tag} deleted."
end
# Generate changelog from git commits
tag_match_pattern = options[:tag_match_pattern]
merge_commit_filtering = options[:merge_commit_filtering] || "only_include_merges"
notes = changelog_from_git_commits(
merge_commit_filtering: merge_commit_filtering,
tag_match_pattern: tag_match_pattern,
)
puts "Tagging #{git_tag}"
# Recreate the tag
add_git_tag(
tag: git_tag
)
# Extract issue references from commit messages
# Looks for lines starting with your issue tracking prefix
issues = notes.split("\n").select { |line| line.start_with?("[ISSUE-") }.join("\n")
puts "Listing issues: \n" + issues
issues
end
platform :ios do
desc "Push a new prod build to testflight"
lane :ios_prod do |values|
ensure_env_vars(
env_vars: [
'MATCH_PASSWORD',
'GIT_TAG',
'APP_STORE_CONNECT_API_KEY_ID',
'APP_STORE_CONNECT_API_KEY_ISSUER_ID',
'APP_STORE_CONNECT_API_KEY_PRIVATE_KEY'
]
)
# Build the iOS application using yarn
yarn(command: "build:ios")
# Handle CI-specific certificate fetching
if is_ci
fetch_certificates(readonly: true)
cocoapods(podfile: "./ios/Podfile")
end
# Extract version number from tag (e.g., p1.0.0 -> 1.0.0)
version_number = get_version_from_tag(tag_prefix: "p.")
increment_version_number(
version_number: version_number,
xcodeproj: "./ios/[YOUR_PROJECT].xcodeproj"
)
build_number = number_of_commits(all: true)
increment_build_number(
build_number: build_number,
xcodeproj: "./ios/[YOUR_PROJECT].xcodeproj"
)
xcargs = ""
scheme = "[YOUR_SCHEME_NAME]"
build_app(
scheme: scheme,
configuration: "Release",
workspace: "./ios/[YOUR_PROJECT].xcworkspace",
xcargs: xcargs,
export_method: "app-store",
export_options: {
'signingStyle' => 'manual',
provisioningProfiles: {
"[YOUR_BUNDLE_IDENTIFIER]" => "match AppStore [YOUR_BUNDLE_IDENTIFIER]"
}
}
)
# Configure App Store Connect API
app_store_connect_api_key(
key_id: ENV["APP_STORE_CONNECT_API_KEY_ID"],
issuer_id: ENV["APP_STORE_CONNECT_API_KEY_ISSUER_ID"],
key_content: ENV["APP_STORE_CONNECT_API_KEY_PRIVATE_KEY"]
)
# Upload to TestFlight
upload_to_testflight(
skip_submission: true,
skip_waiting_for_build_processing: true,
changelog: release_notes(tag_match_pattern: "p.*")
)
# Commit version changes
commit_message = "Version #{version_number} (#{build_number})"
git_commit(path: ".", message: commit_message)
# Upload to App Store
upload_to_app_store(
build_number: "#{build_number}",
app_version: version_number,
force: true,
skip_metadata: true,
skip_screenshots: true,
precheck_include_in_app_purchases: false,
)
end
desc 'Register devices'
lane :register_devices_custom do |options|
# Device registration documentation
# To register a device:
# 1. Connect the device to your Mac
# 2. Open Xcode -> Window -> Devices and Simulators
# 3. Find your device name and identifier
# 4. Add the device using the format below
register_devices_and_update_certificates(devices: {
# 'user@example.com' => 'device-udid-here',
})
end
desc 'Register new devices'
lane :register_devices_and_update_certificates do |options|
# Register devices in App Store Connect
register_devices(devices: options[:devices])
# Update provisioning profiles for new devices
fetch_certificates(readonly: false, force_for_new_devices: true)
end
desc 'Fetch certificates and provisioning profiles'
lane :fetch_certificates do |options|
readonly = options[:readonly].nil? ? true : options[:readonly]
force_for_new_devices = options[:force_for_new_devices].nil? ? false : options[:force_for_new_devices]
fetch_development_certificates(readonly: readonly, force_for_new_devices: force_for_new_devices)
fetch_distribution_certificates(readonly: readonly, force_for_new_devices: force_for_new_devices)
end
desc 'Fetch development certificates'
lane :fetch_development_certificates do |options|
readonly = options[:readonly].nil? ? true : options[:readonly]
force_for_new_devices = options[:force_for_new_devices].nil? ? false : options[:force_for_new_devices]
# Development certificates for each environment
match(type: 'development', app_identifier: '[YOUR_BUNDLE_ID].debug', readonly: readonly, force_for_new_devices: force_for_new_devices)
match(type: 'development', app_identifier: '[YOUR_BUNDLE_ID].beta', readonly: readonly, force_for_new_devices: force_for_new_devices)
match(type: 'development', app_identifier: '[YOUR_BUNDLE_ID]', readonly: readonly, force_for_new_devices: force_for_new_devices)
end
desc 'Fetch distribution certificates'
lane :fetch_distribution_certificates do |options|
readonly = options[:readonly].nil? ? true : options[:readonly]
force_for_new_devices = options[:force_for_new_devices].nil? ? false : options[:force_for_new_devices)
# Distribution certificates for each environment
match(type: 'adhoc', app_identifier: '[YOUR_BUNDLE_ID].debug', readonly: readonly, force_for_new_devices: force_for_new_devices)
match(type: 'adhoc', app_identifier: '[YOUR_BUNDLE_ID].beta', readonly: readonly, force_for_new_devices: force_for_new_devices)
match(type: 'appstore', app_identifier: '[YOUR_BUNDLE_ID]', readonly: readonly, force_for_new_devices: force_for_new_devices)
end
end
git_url([GITHUB_MATCH_CERTIFICATES_REPO])
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment