mirror of
https://github.com/immich-app/immich.git
synced 2026-05-18 03:10:24 +03:00
feat: update iOS CI/CD with FUTO build credential (#28146)
* update email * Update fastfile * use different apple id * debug build * build only
This commit is contained in:
@@ -1,5 +1,5 @@
|
|||||||
app_identifier "app.alextran.immich" # The bundle identifier of your app
|
app_identifier "app.alextran.immich" # The bundle identifier of your app
|
||||||
apple_id "alex.tran1502@gmail.com" # Your Apple email address
|
apple_id "altran@futo.org" # Your Apple email address
|
||||||
|
|
||||||
|
|
||||||
# For more information about the Appfile, see:
|
# For more information about the Appfile, see:
|
||||||
|
|||||||
@@ -17,10 +17,11 @@ default_platform(:ios)
|
|||||||
|
|
||||||
platform :ios do
|
platform :ios do
|
||||||
# Constants
|
# Constants
|
||||||
TEAM_ID = "2F67MQ8R79"
|
TEAM_ID = "2W7AC6T8T5"
|
||||||
CODE_SIGN_IDENTITY = "Apple Distribution: Hau Tran (#{TEAM_ID})"
|
CODE_SIGN_IDENTITY = "Apple Distribution: FUTO Holdings, Inc. (#{TEAM_ID})"
|
||||||
BASE_BUNDLE_ID = "app.alextran.immich"
|
BASE_BUNDLE_ID = "app.alextran.immich"
|
||||||
|
DEV_BUNDLE_ID = "tech.futo.immich.testflight"
|
||||||
|
|
||||||
# Helper method to get App Store Connect API key
|
# Helper method to get App Store Connect API key
|
||||||
def get_api_key
|
def get_api_key
|
||||||
app_store_connect_api_key(
|
app_store_connect_api_key(
|
||||||
@@ -44,47 +45,45 @@ def get_version_from_pubspec
|
|||||||
end
|
end
|
||||||
|
|
||||||
# Helper method to configure code signing for all targets
|
# Helper method to configure code signing for all targets
|
||||||
def configure_code_signing(bundle_id_suffix: "", profile_name_main:, profile_name_share:, profile_name_widget:)
|
def configure_code_signing(base_bundle_id:, profile_name_main:, profile_name_share:, profile_name_widget:)
|
||||||
bundle_suffix = bundle_id_suffix.empty? ? "" : ".#{bundle_id_suffix}"
|
|
||||||
|
|
||||||
# Runner (main app)
|
# Runner (main app)
|
||||||
update_code_signing_settings(
|
update_code_signing_settings(
|
||||||
use_automatic_signing: false,
|
use_automatic_signing: false,
|
||||||
path: "./Runner.xcodeproj",
|
path: "./Runner.xcodeproj",
|
||||||
team_id: ENV["FASTLANE_TEAM_ID"] || TEAM_ID,
|
team_id: ENV["FASTLANE_TEAM_ID"] || TEAM_ID,
|
||||||
code_sign_identity: CODE_SIGN_IDENTITY,
|
code_sign_identity: CODE_SIGN_IDENTITY,
|
||||||
bundle_identifier: "#{BASE_BUNDLE_ID}#{bundle_suffix}",
|
bundle_identifier: base_bundle_id,
|
||||||
profile_name: profile_name_main,
|
profile_name: profile_name_main,
|
||||||
targets: ["Runner"]
|
targets: ["Runner"]
|
||||||
)
|
)
|
||||||
|
|
||||||
# ShareExtension
|
# ShareExtension
|
||||||
update_code_signing_settings(
|
update_code_signing_settings(
|
||||||
use_automatic_signing: false,
|
use_automatic_signing: false,
|
||||||
path: "./Runner.xcodeproj",
|
path: "./Runner.xcodeproj",
|
||||||
team_id: ENV["FASTLANE_TEAM_ID"] || TEAM_ID,
|
team_id: ENV["FASTLANE_TEAM_ID"] || TEAM_ID,
|
||||||
code_sign_identity: CODE_SIGN_IDENTITY,
|
code_sign_identity: CODE_SIGN_IDENTITY,
|
||||||
bundle_identifier: "#{BASE_BUNDLE_ID}#{bundle_suffix}.ShareExtension",
|
bundle_identifier: "#{base_bundle_id}.ShareExtension",
|
||||||
profile_name: profile_name_share,
|
profile_name: profile_name_share,
|
||||||
targets: ["ShareExtension"]
|
targets: ["ShareExtension"]
|
||||||
)
|
)
|
||||||
|
|
||||||
# WidgetExtension
|
# WidgetExtension
|
||||||
update_code_signing_settings(
|
update_code_signing_settings(
|
||||||
use_automatic_signing: false,
|
use_automatic_signing: false,
|
||||||
path: "./Runner.xcodeproj",
|
path: "./Runner.xcodeproj",
|
||||||
team_id: ENV["FASTLANE_TEAM_ID"] || TEAM_ID,
|
team_id: ENV["FASTLANE_TEAM_ID"] || TEAM_ID,
|
||||||
code_sign_identity: CODE_SIGN_IDENTITY,
|
code_sign_identity: CODE_SIGN_IDENTITY,
|
||||||
bundle_identifier: "#{BASE_BUNDLE_ID}#{bundle_suffix}.Widget",
|
bundle_identifier: "#{base_bundle_id}.Widget",
|
||||||
profile_name: profile_name_widget,
|
profile_name: profile_name_widget,
|
||||||
targets: ["WidgetExtension"]
|
targets: ["WidgetExtension"]
|
||||||
)
|
)
|
||||||
end
|
end
|
||||||
|
|
||||||
# Helper method to build and upload to TestFlight
|
# Helper method to build and upload to TestFlight
|
||||||
def build_and_upload(
|
def build_and_upload(
|
||||||
api_key:,
|
api_key:,
|
||||||
bundle_id_suffix: "",
|
base_bundle_id:,
|
||||||
configuration: "Release",
|
configuration: "Release",
|
||||||
distribute_external: true,
|
distribute_external: true,
|
||||||
version_number: nil,
|
version_number: nil,
|
||||||
@@ -92,9 +91,8 @@ end
|
|||||||
profile_name_share:,
|
profile_name_share:,
|
||||||
profile_name_widget:
|
profile_name_widget:
|
||||||
)
|
)
|
||||||
bundle_suffix = bundle_id_suffix.empty? ? "" : ".#{bundle_id_suffix}"
|
app_identifier = base_bundle_id
|
||||||
app_identifier = "#{BASE_BUNDLE_ID}#{bundle_suffix}"
|
|
||||||
|
|
||||||
# Set version number if provided
|
# Set version number if provided
|
||||||
if version_number
|
if version_number
|
||||||
increment_version_number(version_number: version_number)
|
increment_version_number(version_number: version_number)
|
||||||
@@ -138,31 +136,31 @@ end
|
|||||||
desc "iOS Development Build to TestFlight (requires separate bundle ID)"
|
desc "iOS Development Build to TestFlight (requires separate bundle ID)"
|
||||||
lane :gha_testflight_dev do
|
lane :gha_testflight_dev do
|
||||||
api_key = get_api_key
|
api_key = get_api_key
|
||||||
|
|
||||||
# Download and install provisioning profiles from App Store Connect
|
# Download and install provisioning profiles from App Store Connect
|
||||||
# Certificate is imported by GHA workflow into build.keychain
|
# Certificate is imported by GHA workflow into build.keychain
|
||||||
# Capture profile names after each sigh call
|
# Capture profile names after each sigh call
|
||||||
sigh(api_key: api_key, app_identifier: "#{BASE_BUNDLE_ID}.development", force: true)
|
sigh(api_key: api_key, app_identifier: DEV_BUNDLE_ID, force: true)
|
||||||
main_profile_name = lane_context[SharedValues::SIGH_NAME]
|
main_profile_name = lane_context[SharedValues::SIGH_NAME]
|
||||||
|
|
||||||
sigh(api_key: api_key, app_identifier: "#{BASE_BUNDLE_ID}.development.ShareExtension", force: true)
|
sigh(api_key: api_key, app_identifier: "#{DEV_BUNDLE_ID}.ShareExtension", force: true)
|
||||||
share_profile_name = lane_context[SharedValues::SIGH_NAME]
|
share_profile_name = lane_context[SharedValues::SIGH_NAME]
|
||||||
|
|
||||||
sigh(api_key: api_key, app_identifier: "#{BASE_BUNDLE_ID}.development.Widget", force: true)
|
sigh(api_key: api_key, app_identifier: "#{DEV_BUNDLE_ID}.Widget", force: true)
|
||||||
widget_profile_name = lane_context[SharedValues::SIGH_NAME]
|
widget_profile_name = lane_context[SharedValues::SIGH_NAME]
|
||||||
|
|
||||||
# Configure code signing for dev bundle IDs using the downloaded profile names
|
# Configure code signing for dev bundle IDs using the downloaded profile names
|
||||||
configure_code_signing(
|
configure_code_signing(
|
||||||
bundle_id_suffix: "development",
|
base_bundle_id: DEV_BUNDLE_ID,
|
||||||
profile_name_main: main_profile_name,
|
profile_name_main: main_profile_name,
|
||||||
profile_name_share: share_profile_name,
|
profile_name_share: share_profile_name,
|
||||||
profile_name_widget: widget_profile_name
|
profile_name_widget: widget_profile_name
|
||||||
)
|
)
|
||||||
|
|
||||||
# Build and upload
|
# Build and upload
|
||||||
build_and_upload(
|
build_and_upload(
|
||||||
api_key: api_key,
|
api_key: api_key,
|
||||||
bundle_id_suffix: "development",
|
base_bundle_id: DEV_BUNDLE_ID,
|
||||||
configuration: "Profile",
|
configuration: "Profile",
|
||||||
distribute_external: false,
|
distribute_external: false,
|
||||||
profile_name_main: main_profile_name,
|
profile_name_main: main_profile_name,
|
||||||
@@ -189,6 +187,7 @@ end
|
|||||||
|
|
||||||
# Configure code signing for production bundle IDs
|
# Configure code signing for production bundle IDs
|
||||||
configure_code_signing(
|
configure_code_signing(
|
||||||
|
base_bundle_id: BASE_BUNDLE_ID,
|
||||||
profile_name_main: main_profile_name,
|
profile_name_main: main_profile_name,
|
||||||
profile_name_share: share_profile_name,
|
profile_name_share: share_profile_name,
|
||||||
profile_name_widget: widget_profile_name
|
profile_name_widget: widget_profile_name
|
||||||
@@ -197,6 +196,7 @@ end
|
|||||||
# Build and upload with version number
|
# Build and upload with version number
|
||||||
build_and_upload(
|
build_and_upload(
|
||||||
api_key: api_key,
|
api_key: api_key,
|
||||||
|
base_bundle_id: BASE_BUNDLE_ID,
|
||||||
version_number: get_version_from_pubspec,
|
version_number: get_version_from_pubspec,
|
||||||
distribute_external: false,
|
distribute_external: false,
|
||||||
profile_name_main: main_profile_name,
|
profile_name_main: main_profile_name,
|
||||||
@@ -243,30 +243,30 @@ end
|
|||||||
|
|
||||||
desc "iOS Build Only (no TestFlight upload)"
|
desc "iOS Build Only (no TestFlight upload)"
|
||||||
lane :gha_build_only do
|
lane :gha_build_only do
|
||||||
# Use the same build process as production, just skip the upload
|
# Use the same build process as the dev TestFlight lane, just skip the upload
|
||||||
# This ensures PR builds validate the same way as production builds
|
# This ensures PR builds validate the same way as dev TestFlight builds
|
||||||
|
|
||||||
api_key = get_api_key
|
api_key = get_api_key
|
||||||
|
|
||||||
# Download and install provisioning profiles from App Store Connect
|
# Download and install provisioning profiles from App Store Connect
|
||||||
# Certificate is imported by GHA workflow into build.keychain
|
# Certificate is imported by GHA workflow into build.keychain
|
||||||
sigh(api_key: api_key, app_identifier: "#{BASE_BUNDLE_ID}.development", force: true)
|
sigh(api_key: api_key, app_identifier: DEV_BUNDLE_ID, force: true)
|
||||||
main_profile_name = lane_context[SharedValues::SIGH_NAME]
|
main_profile_name = lane_context[SharedValues::SIGH_NAME]
|
||||||
|
|
||||||
sigh(api_key: api_key, app_identifier: "#{BASE_BUNDLE_ID}.development.ShareExtension", force: true)
|
sigh(api_key: api_key, app_identifier: "#{DEV_BUNDLE_ID}.ShareExtension", force: true)
|
||||||
share_profile_name = lane_context[SharedValues::SIGH_NAME]
|
share_profile_name = lane_context[SharedValues::SIGH_NAME]
|
||||||
|
|
||||||
sigh(api_key: api_key, app_identifier: "#{BASE_BUNDLE_ID}.development.Widget", force: true)
|
sigh(api_key: api_key, app_identifier: "#{DEV_BUNDLE_ID}.Widget", force: true)
|
||||||
widget_profile_name = lane_context[SharedValues::SIGH_NAME]
|
widget_profile_name = lane_context[SharedValues::SIGH_NAME]
|
||||||
|
|
||||||
# Configure code signing for dev bundle IDs
|
# Configure code signing for dev bundle IDs
|
||||||
configure_code_signing(
|
configure_code_signing(
|
||||||
bundle_id_suffix: "development",
|
base_bundle_id: DEV_BUNDLE_ID,
|
||||||
profile_name_main: main_profile_name,
|
profile_name_main: main_profile_name,
|
||||||
profile_name_share: share_profile_name,
|
profile_name_share: share_profile_name,
|
||||||
profile_name_widget: widget_profile_name
|
profile_name_widget: widget_profile_name
|
||||||
)
|
)
|
||||||
|
|
||||||
# Build the app (same as gha_testflight_dev but without upload)
|
# Build the app (same as gha_testflight_dev but without upload)
|
||||||
build_app(
|
build_app(
|
||||||
scheme: "Runner",
|
scheme: "Runner",
|
||||||
@@ -277,9 +277,9 @@ end
|
|||||||
xcargs: "-skipMacroValidation CODE_SIGN_IDENTITY='#{CODE_SIGN_IDENTITY}' CODE_SIGN_STYLE=Manual",
|
xcargs: "-skipMacroValidation CODE_SIGN_IDENTITY='#{CODE_SIGN_IDENTITY}' CODE_SIGN_STYLE=Manual",
|
||||||
export_options: {
|
export_options: {
|
||||||
provisioningProfiles: {
|
provisioningProfiles: {
|
||||||
"#{BASE_BUNDLE_ID}.development" => main_profile_name,
|
DEV_BUNDLE_ID => main_profile_name,
|
||||||
"#{BASE_BUNDLE_ID}.development.ShareExtension" => share_profile_name,
|
"#{DEV_BUNDLE_ID}.ShareExtension" => share_profile_name,
|
||||||
"#{BASE_BUNDLE_ID}.development.Widget" => widget_profile_name
|
"#{DEV_BUNDLE_ID}.Widget" => widget_profile_name
|
||||||
},
|
},
|
||||||
signingStyle: "manual",
|
signingStyle: "manual",
|
||||||
signingCertificate: CODE_SIGN_IDENTITY
|
signingCertificate: CODE_SIGN_IDENTITY
|
||||||
|
|||||||
Reference in New Issue
Block a user