Files
yattee/fastlane/Fastfile
Arkadiusz Fal 79e4a24f75 Auto-increment build number in release workflow
Query App Store Connect for the latest TestFlight build number across
all platforms (iOS, tvOS, macOS) and auto-increment it, eliminating
the need for the separate bump-build workflow.
2026-02-13 19:18:42 +01:00

289 lines
8.4 KiB
Ruby

# Yattee v2 Fastlane configuration
# Single unified "Yattee" scheme, platform selected via destination parameter
APP_NAME = ENV['APP_NAME'] || 'Yattee'
DEVELOPER_KEY_ID = ENV['DEVELOPER_KEY_ID']
DEVELOPER_KEY_ISSUER_ID = ENV['DEVELOPER_KEY_ISSUER_ID']
DEVELOPER_KEY_CONTENT = ENV['DEVELOPER_KEY_CONTENT']
TEAM_ID = ENV['TEAM_ID']
TEMP_KEYCHAIN_USER = ENV['TEMP_KEYCHAIN_USER']
TEMP_KEYCHAIN_PASSWORD = ENV['TEMP_KEYCHAIN_PASSWORD']
DEVELOPER_APP_IDENTIFIER = ENV['DEVELOPER_APP_IDENTIFIER']
GIT_AUTHORIZATION = ENV['GIT_AUTHORIZATION']
TESTFLIGHT_EXTERNAL_GROUPS = ENV['TESTFLIGHT_EXTERNAL_GROUPS']
XCODEPROJ = "#{APP_NAME}.xcodeproj"
SCHEME = APP_NAME
def delete_temp_keychain(name)
delete_keychain(
name: name
) if File.exist? File.expand_path("~/Library/Keychains/#{name}-db")
end
def create_temp_keychain(name, password)
create_keychain(
name: name,
password: password,
unlock: false,
timeout: 0
)
end
def ensure_temp_keychain(name, password)
delete_temp_keychain(name)
create_temp_keychain(name, password)
end
add_extra_platforms(platforms: [:tvos])
before_all do
update_fastlane
end
desc "Get latest TestFlight build number across all platforms"
lane :latest_build_number do
api_key = app_store_connect_api_key(
key_id: DEVELOPER_KEY_ID,
issuer_id: DEVELOPER_KEY_ISSUER_ID,
key_content: DEVELOPER_KEY_CONTENT,
is_key_content_base64: true
)
ios_build = latest_testflight_build_number(api_key: api_key, app_identifier: DEVELOPER_APP_IDENTIFIER, platform: "ios")
tvos_build = latest_testflight_build_number(api_key: api_key, app_identifier: DEVELOPER_APP_IDENTIFIER, platform: "appletvos")
macos_build = latest_testflight_build_number(api_key: api_key, app_identifier: DEVELOPER_APP_IDENTIFIER, platform: "osx")
max_build = [ios_build, tvos_build, macos_build].max
File.write("latest_build_number.txt", max_build.to_s)
UI.success("Latest TestFlight build number: #{max_build}")
max_build
end
desc "Bump build number and commit"
lane :bump_build do
increment_build_number(xcodeproj: XCODEPROJ)
commit_version_bump(
message: "Bump build number to #{get_build_number(xcodeproj: XCODEPROJ)}",
xcodeproj: XCODEPROJ
)
end
desc "Bump version number and commit"
lane :bump_version do
increment_version_number(xcodeproj: XCODEPROJ)
commit_version_bump(
message: "Bump version number to #{get_version_number(xcodeproj: XCODEPROJ, target: SCHEME)}",
xcodeproj: XCODEPROJ
)
end
platform :ios do
desc "Push a new beta build to TestFlight"
lane :beta do
ensure_temp_keychain(TEMP_KEYCHAIN_USER, TEMP_KEYCHAIN_PASSWORD)
api_key = app_store_connect_api_key(
key_id: DEVELOPER_KEY_ID,
issuer_id: DEVELOPER_KEY_ISSUER_ID,
key_content: DEVELOPER_KEY_CONTENT,
is_key_content_base64: true
)
build = get_build_number(xcodeproj: XCODEPROJ)
version = get_version_number(
xcodeproj: XCODEPROJ,
target: SCHEME
)
match(
type: 'appstore',
platform: 'ios',
app_identifier: ["#{DEVELOPER_APP_IDENTIFIER}", "#{DEVELOPER_APP_IDENTIFIER}.ShareExtension"],
git_basic_authorization: Base64.strict_encode64(GIT_AUTHORIZATION),
readonly: true,
keychain_name: TEMP_KEYCHAIN_USER,
keychain_password: TEMP_KEYCHAIN_PASSWORD,
api_key: api_key
)
build_app(
scheme: SCHEME,
destination: "generic/platform=iOS",
output_directory: "fastlane/builds/#{version}-#{build}/iOS",
output_name: "#{APP_NAME}-#{version}-iOS.ipa",
export_options: {
provisioningProfiles: {
"#{DEVELOPER_APP_IDENTIFIER}" => "match AppStore #{DEVELOPER_APP_IDENTIFIER}",
"#{DEVELOPER_APP_IDENTIFIER}.ShareExtension" => "match AppStore #{DEVELOPER_APP_IDENTIFIER}.ShareExtension"
}
}
)
changelog_path = File.expand_path('../CHANGELOG.md', __dir__)
changelog = File.exist?(changelog_path) ? File.read(changelog_path) : ""
upload_to_testflight(
api_key: api_key,
ipa: lane_context[SharedValues::IPA_OUTPUT_PATH],
changelog: changelog
)
end
end
platform :tvos do
desc "Push a new beta build to TestFlight"
lane :beta do
ensure_temp_keychain(TEMP_KEYCHAIN_USER, TEMP_KEYCHAIN_PASSWORD)
api_key = app_store_connect_api_key(
key_id: DEVELOPER_KEY_ID,
issuer_id: DEVELOPER_KEY_ISSUER_ID,
key_content: DEVELOPER_KEY_CONTENT,
is_key_content_base64: true
)
build = get_build_number(xcodeproj: XCODEPROJ)
version = get_version_number(
xcodeproj: XCODEPROJ,
target: SCHEME
)
match(
type: 'appstore',
platform: 'tvos',
app_identifier: "#{DEVELOPER_APP_IDENTIFIER}",
git_basic_authorization: Base64.strict_encode64(GIT_AUTHORIZATION),
readonly: true,
keychain_name: TEMP_KEYCHAIN_USER,
keychain_password: TEMP_KEYCHAIN_PASSWORD,
api_key: api_key
)
build_app(
scheme: SCHEME,
destination: "generic/platform=tvOS",
output_directory: "fastlane/builds/#{version}-#{build}/tvOS",
output_name: "#{APP_NAME}-#{version}-tvOS.ipa",
export_method: "app-store",
export_options: {
provisioningProfiles: {
"#{DEVELOPER_APP_IDENTIFIER}" => "match AppStore #{DEVELOPER_APP_IDENTIFIER} tvos"
}
}
)
changelog_path = File.expand_path('../CHANGELOG.md', __dir__)
changelog = File.exist?(changelog_path) ? File.read(changelog_path) : ""
upload_to_testflight(
api_key: api_key,
ipa: lane_context[SharedValues::IPA_OUTPUT_PATH],
changelog: changelog
)
end
end
platform :mac do
desc "Push a new beta build to TestFlight"
lane :beta do
ensure_temp_keychain(TEMP_KEYCHAIN_USER, TEMP_KEYCHAIN_PASSWORD)
api_key = app_store_connect_api_key(
key_id: DEVELOPER_KEY_ID,
issuer_id: DEVELOPER_KEY_ISSUER_ID,
key_content: DEVELOPER_KEY_CONTENT,
is_key_content_base64: true
)
build = get_build_number(xcodeproj: XCODEPROJ)
version = get_version_number(
xcodeproj: XCODEPROJ,
target: SCHEME
)
match(
type: 'appstore',
platform: 'macos',
additional_cert_types: ['mac_installer_distribution'],
app_identifier: "#{DEVELOPER_APP_IDENTIFIER}",
git_basic_authorization: Base64.strict_encode64(GIT_AUTHORIZATION),
readonly: true,
keychain_name: TEMP_KEYCHAIN_USER,
keychain_password: TEMP_KEYCHAIN_PASSWORD,
api_key: api_key
)
build_mac_app(
scheme: SCHEME,
output_directory: "fastlane/builds/#{version}-#{build}/macOS",
output_name: "#{APP_NAME}-#{version}-macOS.app",
export_method: "app-store",
export_options: {
provisioningProfiles: {
"#{DEVELOPER_APP_IDENTIFIER}" => "match AppStore #{DEVELOPER_APP_IDENTIFIER} macos"
}
}
)
changelog_path = File.expand_path('../CHANGELOG.md', __dir__)
changelog = File.exist?(changelog_path) ? File.read(changelog_path) : ""
upload_to_testflight(
api_key: api_key,
pkg: lane_context[SharedValues::PKG_OUTPUT_PATH],
changelog: changelog
)
end
desc "Build for Developer ID distribution and notarize"
lane :build_and_notarize do
ensure_temp_keychain(TEMP_KEYCHAIN_USER, TEMP_KEYCHAIN_PASSWORD)
api_key = app_store_connect_api_key(
key_id: DEVELOPER_KEY_ID,
issuer_id: DEVELOPER_KEY_ISSUER_ID,
key_content: DEVELOPER_KEY_CONTENT,
is_key_content_base64: true
)
build = get_build_number(xcodeproj: XCODEPROJ)
version = get_version_number(
xcodeproj: XCODEPROJ,
target: SCHEME
)
match(
type: 'developer_id',
platform: 'macos',
app_identifier: "#{DEVELOPER_APP_IDENTIFIER}",
git_basic_authorization: Base64.strict_encode64(GIT_AUTHORIZATION),
readonly: true,
keychain_name: TEMP_KEYCHAIN_USER,
keychain_password: TEMP_KEYCHAIN_PASSWORD,
api_key: api_key
)
build_mac_app(
scheme: SCHEME,
output_directory: "fastlane/builds/#{version}-#{build}/macOS",
output_name: APP_NAME,
export_method: "developer-id",
export_options: {
provisioningProfiles: {
"#{DEVELOPER_APP_IDENTIFIER}" => "match Direct #{DEVELOPER_APP_IDENTIFIER} macos"
}
}
)
notarize(
package: "fastlane/builds/#{version}-#{build}/macOS/#{APP_NAME}.app",
bundle_id: "#{DEVELOPER_APP_IDENTIFIER}",
api_key: api_key,
print_log: true
)
end
end