Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .github/workflows/publish_ios_appstore.yml
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
name: Publish iOS App

# kappmaker-workflow-version: 3

# Builds and ships the iOS app on a GitHub macOS runner, so no Mac is needed
# locally. Signing certificates are created on the runner by fastlane `match`
# from your App Store Connect API key — nothing has to be exported from a Mac.
Expand Down
50 changes: 29 additions & 21 deletions MobileApp/fastlane/Fastfile
Original file line number Diff line number Diff line change
Expand Up @@ -227,7 +227,6 @@ platform :ios do
submit_for_review = options[:submit_for_review].to_s == "true"
upload_metadata = options[:upload_metadata].to_s == "true"
upload_screenshots = options[:upload_screenshots].to_s == "true"
bump_build = options[:bump_build].to_s != "false"

api_key = app_store_connect_api_key(
key_id: ENV.fetch("ASC_KEY_ID"),
Expand All @@ -239,22 +238,6 @@ platform :ios do

setup_ci if ENV["CI"]

# Apple rejects an already-seen build number, and CI builds from a clean
# checkout — so the number in git never advances on its own. Take whatever
# TestFlight has already seen and go one past it. This is the CI equivalent
# of running `kappmaker update-version` before publishing locally.
if bump_build
latest = latest_testflight_build_number(
api_key: api_key,
app_identifier: bundle_id,
initial_build_number: 0
) rescue 0
increment_build_number(
build_number: latest.to_i + 1,
xcodeproj: "iosApp/iosApp.xcodeproj"
)
UI.message("Build number set to #{latest.to_i + 1}")
end

# readonly:false so the FIRST run can create and store the certificate. Later
# runs find it already there and reuse it.
Expand All @@ -267,6 +250,31 @@ platform :ios do
keychain_password: ENV["MATCH_KEYCHAIN_PASSWORD"]
)

# match publishes what it installed through these env vars.
profile_name = ENV["sigh_#{bundle_id}_appstore_profile-name"]
team_id = ENV["sigh_#{bundle_id}_appstore_team-id"]
UI.user_error!("match did not install a profile for #{bundle_id}") if profile_name.to_s.empty?

# Signing must be set on the APP TARGET, and nowhere else.
#
# Through xcargs the settings hit EVERY target, and the Swift Package
# dependencies (Firebase, GoogleUtilities, nanopb, promises...) reject a
# provisioning profile outright — "does not support provisioning profiles".
# This action edits the pbxproj for the named target only.
#
# It also has to be manual: left on automatic, Xcode hunts for an iOS App
# DEVELOPMENT profile and fails, because match installed an App Store one.
# The project ships no DEVELOPMENT_TEAM either, so team_id comes from match.
update_code_signing_settings(
path: "iosApp/iosApp.xcodeproj",
use_automatic_signing: false,
team_id: team_id,
code_sign_identity: "Apple Distribution",
profile_name: profile_name,
targets: ["iosApp"],
build_configurations: ["Release"]
)

build_app(
scheme: "iosApp",
project: "iosApp/iosApp.xcodeproj",
Expand All @@ -275,9 +283,10 @@ platform :ios do
silent: false,
output_name: "iosApp",
output_directory: output_dir,
# Explicitly manual: match already installed the profile, and letting Xcode
# "help" here is what causes the certificate churn described above.
xcargs: "-allowProvisioningUpdates NO"
export_options: {
signingStyle: "manual",
provisioningProfiles: { bundle_id => profile_name }
}
)

ipa_path = File.join(output_dir, "iosApp.ipa")
Expand Down Expand Up @@ -309,5 +318,4 @@ platform :ios do
UI.success("Uploaded to TestFlight.")
end
end

end
Loading