chore: gha ios release | take 5 (#23203)

* chore: gha ios release | take 5

* code signing

* code signing 2

* manual signing for extensions

* chore(ios): add explicit code signing identity and debug output

* dev appbundle

* Deployment flow for development app

* skip waiting for change log

* refactor

* fix: ruby version

* fix: manual release lane

* build on main
This commit is contained in:
Alex
2025-10-31 09:05:03 -05:00
committed by GitHub
parent c69786b039
commit 7ea443b3a9
5 changed files with 221 additions and 57 deletions

View File

@@ -1,4 +1,5 @@
source "https://rubygems.org"
gem "fastlane"
gem "cocoapods"
gem "cocoapods"
gem "abbrev" # Required for Ruby 3.4+

View File

@@ -3,7 +3,7 @@
archiveVersion = 1;
classes = {
};
objectVersion = 54;
objectVersion = 77;
objects = {
/* Begin PBXBuildFile section */
@@ -133,15 +133,11 @@
/* Begin PBXFileSystemSynchronizedRootGroup section */
B231F52D2E93A44A00BC45D1 /* Core */ = {
isa = PBXFileSystemSynchronizedRootGroup;
exceptions = (
);
path = Core;
sourceTree = "<group>";
};
B2CF7F8C2DDE4EBB00744BF6 /* Sync */ = {
isa = PBXFileSystemSynchronizedRootGroup;
exceptions = (
);
path = Sync;
sourceTree = "<group>";
};
@@ -530,10 +526,14 @@
inputFileListPaths = (
"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-resources-${CONFIGURATION}-input-files.xcfilelist",
);
inputPaths = (
);
name = "[CP] Copy Pods Resources";
outputFileListPaths = (
"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-resources-${CONFIGURATION}-output-files.xcfilelist",
);
outputPaths = (
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-resources.sh\"\n";
@@ -562,10 +562,14 @@
inputFileListPaths = (
"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-input-files.xcfilelist",
);
inputPaths = (
);
name = "[CP] Embed Pods Frameworks";
outputFileListPaths = (
"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-output-files.xcfilelist",
);
outputPaths = (
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh\"\n";

View File

@@ -16,42 +16,81 @@
default_platform(:ios)
platform :ios do
desc "iOS Release to TestFlight"
lane :release_ci do
# Setup CI environment
setup_ci
# Load App Store Connect API Key
api_key = app_store_connect_api_key(
# Constants
TEAM_ID = "2F67MQ8R79"
CODE_SIGN_IDENTITY = "Apple Distribution: Hau Tran (#{TEAM_ID})"
BASE_BUNDLE_ID = "app.alextran.immich"
# Helper method to get App Store Connect API key
def get_api_key
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_filepath: "api_key.json"
key_filepath: "#{Dir.home}/.appstoreconnect/private_keys/AuthKey_#{ENV['APP_STORE_CONNECT_API_KEY_ID']}.p8",
duration: 1200,
in_house: false
)
end
# Helper method to configure code signing for all targets
def configure_code_signing(bundle_id_suffix: "")
bundle_suffix = bundle_id_suffix.empty? ? "" : ".#{bundle_id_suffix}"
# Import certificate and provisioning profile
import_certificate(
certificate_path: "certificate.p12",
certificate_password: ENV["IOS_CERTIFICATE_PASSWORD"],
keychain_name: ENV["KEYCHAIN_NAME"],
keychain_password: ENV["KEYCHAIN_PASSWORD"]
)
# Install provisioning profile
install_provisioning_profile(path: "profile.mobileprovision")
# Configure code signing
# Runner (main app)
update_code_signing_settings(
use_automatic_signing: false,
path: "./Runner.xcodeproj",
team_id: ENV["FASTLANE_TEAM_ID"],
profile_name: "app.alextran.immich AppStore"
team_id: ENV["FASTLANE_TEAM_ID"] || TEAM_ID,
code_sign_identity: CODE_SIGN_IDENTITY,
bundle_identifier: "#{BASE_BUNDLE_ID}#{bundle_suffix}",
profile_name: "#{BASE_BUNDLE_ID}#{bundle_suffix} AppStore",
targets: ["Runner"]
)
# ShareExtension
update_code_signing_settings(
use_automatic_signing: false,
path: "./Runner.xcodeproj",
team_id: ENV["FASTLANE_TEAM_ID"] || TEAM_ID,
code_sign_identity: CODE_SIGN_IDENTITY,
bundle_identifier: "#{BASE_BUNDLE_ID}#{bundle_suffix}.ShareExtension",
profile_name: "#{BASE_BUNDLE_ID}#{bundle_suffix}.ShareExtension AppStore",
targets: ["ShareExtension"]
)
# WidgetExtension
update_code_signing_settings(
use_automatic_signing: false,
path: "./Runner.xcodeproj",
team_id: ENV["FASTLANE_TEAM_ID"] || TEAM_ID,
code_sign_identity: CODE_SIGN_IDENTITY,
bundle_identifier: "#{BASE_BUNDLE_ID}#{bundle_suffix}.Widget",
profile_name: "#{BASE_BUNDLE_ID}#{bundle_suffix}.Widget AppStore",
targets: ["WidgetExtension"]
)
end
# Helper method to build and upload to TestFlight
def build_and_upload(
api_key:,
bundle_id_suffix: "",
configuration: "Release",
distribute_external: true,
version_number: nil
)
bundle_suffix = bundle_id_suffix.empty? ? "" : ".#{bundle_id_suffix}"
app_identifier = "#{BASE_BUNDLE_ID}#{bundle_suffix}"
# Set version number if provided
if version_number
increment_version_number(version_number: version_number)
end
# Increment build number
increment_build_number(
build_number: latest_testflight_build_number(
api_key: api_key,
app_identifier: "app.alextran.immich"
app_identifier: app_identifier
) + 1,
xcodeproj: "./Runner.xcodeproj"
)
@@ -60,25 +99,74 @@ platform :ios do
build_app(
scheme: "Runner",
workspace: "Runner.xcworkspace",
configuration: configuration,
export_method: "app-store",
xcargs: "CODE_SIGN_IDENTITY='#{CODE_SIGN_IDENTITY}' CODE_SIGN_STYLE=Manual",
export_options: {
provisioningProfiles: {
"app.alextran.immich" => "app.alextran.immich AppStore"
}
"#{app_identifier}" => "#{app_identifier} AppStore",
"#{app_identifier}.ShareExtension" => "#{app_identifier}.ShareExtension AppStore",
"#{app_identifier}.Widget" => "#{app_identifier}.Widget AppStore"
},
signingStyle: "manual",
signingCertificate: CODE_SIGN_IDENTITY
}
)
# Upload to TestFlight
upload_to_testflight(
api_key: api_key,
skip_waiting_for_build_processing: true
skip_waiting_for_build_processing: true,
distribute_external: distribute_external
)
end
desc "iOS Development Build to TestFlight (requires separate bundle ID)"
lane :release_dev do
api_key = get_api_key
# Install development provisioning profiles
install_provisioning_profile(path: "profile_dev.mobileprovision")
install_provisioning_profile(path: "profile_dev_share.mobileprovision")
install_provisioning_profile(path: "profile_dev_widget.mobileprovision")
# Configure code signing for dev bundle IDs
configure_code_signing(bundle_id_suffix: "development")
# Build and upload
build_and_upload(
api_key: api_key,
bundle_id_suffix: "development",
configuration: "Profile",
distribute_external: false
)
end
desc "iOS Release"
lane :release do
desc "iOS Release to TestFlight"
lane :release_ci do
api_key = get_api_key
# Install provisioning profiles
install_provisioning_profile(path: "profile.mobileprovision")
install_provisioning_profile(path: "profile_share.mobileprovision")
install_provisioning_profile(path: "profile_widget.mobileprovision")
# Configure code signing for production bundle IDs
configure_code_signing
# Build and upload with version number
build_and_upload(
api_key: api_key,
version_number: "2.1.0"
)
end
desc "iOS Manual Release"
lane :release_manual do
enable_automatic_code_signing(
path: "./Runner.xcodeproj",
targets: ["Runner", "ShareExtension", "WidgetExtension"]
)
increment_version_number(
version_number: "2.2.0"
@@ -86,9 +174,24 @@ platform :ios do
increment_build_number(
build_number: latest_testflight_build_number + 1,
)
build_app(scheme: "Runner",
workspace: "Runner.xcworkspace",
xcargs: "-allowProvisioningUpdates")
# Build archive with automatic signing
gym(
scheme: "Runner",
workspace: "Runner.xcworkspace",
configuration: "Release",
export_method: "app-store",
skip_package_ipa: false,
xcargs: "-allowProvisioningUpdates",
export_options: {
method: "app-store",
signingStyle: "automatic",
uploadBitcode: false,
uploadSymbols: true,
compileBitcode: false
}
)
upload_to_testflight(
skip_waiting_for_build_processing: true
)

View File

@@ -15,13 +15,29 @@ For _fastlane_ installation instructions, see [Installing _fastlane_](https://do
## iOS
### ios release
### ios release_dev
```sh
[bundle exec] fastlane ios release
[bundle exec] fastlane ios release_dev
```
iOS Release
iOS Development Build to TestFlight (requires separate bundle ID)
### ios release_ci
```sh
[bundle exec] fastlane ios release_ci
```
iOS Release to TestFlight
### ios release_manual
```sh
[bundle exec] fastlane ios release_manual
```
iOS Manual Release
----