Use XcodeGen files for app variants and setup Enterprise submodule. (#2976)

- Create an app.yml with the base app variant.
- Override app.yml contents on Nightly/PR builds.
- Add AppHooks mechanism.
- Add Enterprise submodule.
- Conditionally import Enterprise/fastlane/Fastfile if available.
This commit is contained in:
Doug 2024-06-27 18:18:17 +01:00 committed by GitHub
parent b7345aafca
commit 3cc4145a4c
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
15 changed files with 116 additions and 26 deletions

3
.gitmodules vendored Normal file
View File

@ -0,0 +1,3 @@
[submodule "Enterprise"]
path = Enterprise
url = git@github.com:element-hq/element-ios-enterprise

View File

@ -762,6 +762,7 @@
B444F9C184A377C1B481F07F /* XCUIElement.swift in Sources */ = {isa = PBXBuildFile; fileRef = E992D7B8BE54B2AB454613AF /* XCUIElement.swift */; }; B444F9C184A377C1B481F07F /* XCUIElement.swift in Sources */ = {isa = PBXBuildFile; fileRef = E992D7B8BE54B2AB454613AF /* XCUIElement.swift */; };
B4A0C69370E6008A971463E7 /* BugReportScreenViewModelProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4C89820BB2B88D4EA28131C /* BugReportScreenViewModelProtocol.swift */; }; B4A0C69370E6008A971463E7 /* BugReportScreenViewModelProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4C89820BB2B88D4EA28131C /* BugReportScreenViewModelProtocol.swift */; };
B4AAB3257A83B73F53FB2689 /* StateStoreViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6F3DFE5B444F131648066F05 /* StateStoreViewModel.swift */; }; B4AAB3257A83B73F53FB2689 /* StateStoreViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6F3DFE5B444F131648066F05 /* StateStoreViewModel.swift */; };
B50C95B6D1EABFE1CEA50959 /* AppHooks.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2B048CB133239700CD890F5D /* AppHooks.swift */; };
B5321A1F5B26A0F3EC54909E /* CollapsibleFlowLayoutTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = AC5F5209279A752D98AAC4B2 /* CollapsibleFlowLayoutTests.swift */; }; B5321A1F5B26A0F3EC54909E /* CollapsibleFlowLayoutTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = AC5F5209279A752D98AAC4B2 /* CollapsibleFlowLayoutTests.swift */; };
B53D292A5CA61E371C4CD785 /* GenericCallLinkCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 514923AA9640C34F39E0500A /* GenericCallLinkCoordinator.swift */; }; B53D292A5CA61E371C4CD785 /* GenericCallLinkCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 514923AA9640C34F39E0500A /* GenericCallLinkCoordinator.swift */; };
B5479997ECC516C121E6625E /* LocationMarkerView.swift in Sources */ = {isa = PBXBuildFile; fileRef = FFECCE59967018204876D0A5 /* LocationMarkerView.swift */; }; B5479997ECC516C121E6625E /* LocationMarkerView.swift in Sources */ = {isa = PBXBuildFile; fileRef = FFECCE59967018204876D0A5 /* LocationMarkerView.swift */; };
@ -1324,6 +1325,7 @@
2AB2C848BB9A7A9B618B7B89 /* TextBasedRoomTimelineTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TextBasedRoomTimelineTests.swift; sourceTree = "<group>"; }; 2AB2C848BB9A7A9B618B7B89 /* TextBasedRoomTimelineTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TextBasedRoomTimelineTests.swift; sourceTree = "<group>"; };
2AE807361805463F5AEDD1CA /* VoiceMessagePreviewComposer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VoiceMessagePreviewComposer.swift; sourceTree = "<group>"; }; 2AE807361805463F5AEDD1CA /* VoiceMessagePreviewComposer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VoiceMessagePreviewComposer.swift; sourceTree = "<group>"; };
2AF715D4FD4710EBB637D661 /* SettingsScreenViewModelProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SettingsScreenViewModelProtocol.swift; sourceTree = "<group>"; }; 2AF715D4FD4710EBB637D661 /* SettingsScreenViewModelProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SettingsScreenViewModelProtocol.swift; sourceTree = "<group>"; };
2B048CB133239700CD890F5D /* AppHooks.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppHooks.swift; sourceTree = "<group>"; };
2BB385E148DE55C85C0A02D6 /* SoftLogoutScreenModels.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SoftLogoutScreenModels.swift; sourceTree = "<group>"; }; 2BB385E148DE55C85C0A02D6 /* SoftLogoutScreenModels.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SoftLogoutScreenModels.swift; sourceTree = "<group>"; };
2BDB3E65A79779EDA5D33D8A /* AudioPlayerState.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AudioPlayerState.swift; sourceTree = "<group>"; }; 2BDB3E65A79779EDA5D33D8A /* AudioPlayerState.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AudioPlayerState.swift; sourceTree = "<group>"; };
2BFDCA5A09EE70BC17F2EFA7 /* URLComponents.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = URLComponents.swift; sourceTree = "<group>"; }; 2BFDCA5A09EE70BC17F2EFA7 /* URLComponents.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = URLComponents.swift; sourceTree = "<group>"; };
@ -3708,6 +3710,14 @@
path = Items; path = Items;
sourceTree = "<group>"; sourceTree = "<group>";
}; };
769D25068533684018BA0F82 /* Hooks */ = {
isa = PBXGroup;
children = (
2B048CB133239700CD890F5D /* AppHooks.swift */,
);
path = Hooks;
sourceTree = "<group>";
};
7803E03F759061C948D66B7E /* AppLock */ = { 7803E03F759061C948D66B7E /* AppLock */ = {
isa = PBXGroup; isa = PBXGroup;
children = ( children = (
@ -4970,6 +4980,7 @@
C0937E3B06A8F0E2DB7C8241 /* Other */, C0937E3B06A8F0E2DB7C8241 /* Other */,
2ECFF6B05DAA37EB10DBF7E8 /* UITests */, 2ECFF6B05DAA37EB10DBF7E8 /* UITests */,
337015ADFBA3AB96660DB3A6 /* Generated */, 337015ADFBA3AB96660DB3A6 /* Generated */,
769D25068533684018BA0F82 /* Hooks */,
31CE4DA53232AA534057F912 /* Mocks */, 31CE4DA53232AA534057F912 /* Mocks */,
4C826614718790C58C17117F /* UnitTests */, 4C826614718790C58C17117F /* UnitTests */,
); );
@ -5896,6 +5907,7 @@
A021827B528F1EDC9101CA58 /* AppCoordinatorProtocol.swift in Sources */, A021827B528F1EDC9101CA58 /* AppCoordinatorProtocol.swift in Sources */,
4FF90E2242DBD596E1ED2E27 /* AppCoordinatorStateMachine.swift in Sources */, 4FF90E2242DBD596E1ED2E27 /* AppCoordinatorStateMachine.swift in Sources */,
9D9690D2FD4CD26FF670620F /* AppDelegate.swift in Sources */, 9D9690D2FD4CD26FF670620F /* AppDelegate.swift in Sources */,
B50C95B6D1EABFE1CEA50959 /* AppHooks.swift in Sources */,
6851B077B4C913CC12DB6E77 /* AppLockFlowCoordinator.swift in Sources */, 6851B077B4C913CC12DB6E77 /* AppLockFlowCoordinator.swift in Sources */,
06F8EDF52E33A2D36BCC1161 /* AppLockScreen.swift in Sources */, 06F8EDF52E33A2D36BCC1161 /* AppLockScreen.swift in Sources */,
9912F9EB2D6589141A2957B4 /* AppLockScreenCoordinator.swift in Sources */, 9912F9EB2D6589141A2957B4 /* AppLockScreenCoordinator.swift in Sources */,

View File

@ -29,6 +29,7 @@ class AppCoordinator: AppCoordinatorProtocol, AuthenticationFlowCoordinatorDeleg
private let appMediator: AppMediator private let appMediator: AppMediator
private let appSettings: AppSettings private let appSettings: AppSettings
private let appDelegate: AppDelegate private let appDelegate: AppDelegate
private let appHooks: AppHooks
private let elementCallService: ElementCallServiceProtocol private let elementCallService: ElementCallServiceProtocol
/// Common background task to continue long-running tasks in the background. /// Common background task to continue long-running tasks in the background.
@ -65,10 +66,13 @@ class AppCoordinator: AppCoordinatorProtocol, AuthenticationFlowCoordinatorDeleg
@Consumable private var storedAppRoute: AppRoute? @Consumable private var storedAppRoute: AppRoute?
init(appDelegate: AppDelegate) { init(appDelegate: AppDelegate) {
let appHooks = AppHooks()
appHooks.configure()
windowManager = WindowManager(appDelegate: appDelegate) windowManager = WindowManager(appDelegate: appDelegate)
appMediator = AppMediator(windowManager: windowManager) appMediator = AppMediator(windowManager: windowManager)
let appSettings = AppSettings() let appSettings = appHooks.runAppSettingsHook(AppSettings())
MXLog.configure(logLevel: appSettings.logLevel) MXLog.configure(logLevel: appSettings.logLevel)
@ -83,6 +87,7 @@ class AppCoordinator: AppCoordinatorProtocol, AuthenticationFlowCoordinatorDeleg
self.appDelegate = appDelegate self.appDelegate = appDelegate
self.appSettings = appSettings self.appSettings = appSettings
self.appHooks = appHooks
appRouteURLParser = AppRouteURLParser(appSettings: appSettings) appRouteURLParser = AppRouteURLParser(appSettings: appSettings)
elementCallService = ElementCallService() elementCallService = ElementCallService()

View File

@ -74,6 +74,14 @@ final class AppSettings {
store = userDefaults store = userDefaults
} }
// MARK: - Hooks
func override(defaultHomeserverAddress: String? = nil) {
if let defaultHomeserverAddress {
self.defaultHomeserverAddress = defaultHomeserverAddress
}
}
// MARK: - Application // MARK: - Application
/// Whether or not the app is a development build that isn't in production. /// Whether or not the app is a development build that isn't in production.
@ -94,7 +102,7 @@ final class AppSettings {
/// The default homeserver address used. This is intentionally a string without a scheme /// The default homeserver address used. This is intentionally a string without a scheme
/// so that it can be passed to Rust as a ServerName for well-known discovery. /// so that it can be passed to Rust as a ServerName for well-known discovery.
let defaultHomeserverAddress = "matrix.org" private(set) var defaultHomeserverAddress = "matrix.org"
/// An override of the homeserver's Sliding Sync proxy URL. This allows development against servers /// An override of the homeserver's Sliding Sync proxy URL. This allows development against servers
/// that don't yet have an officially trusted proxy configured in their well-known. /// that don't yet have an officially trusted proxy configured in their well-known.

View File

@ -0,0 +1,45 @@
//
// Copyright 2024 New Vector Ltd
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
import Foundation
// MARK: Registration
class AppHooks: AppHooksProtocol {
private(set) var appSettingsHook: AppSettingsHookProtocol?
func registerAppSettingsHook(_ hook: AppSettingsHookProtocol) {
appSettingsHook = hook
}
func runAppSettingsHook(_ appSettings: AppSettings) -> AppSettings {
guard let appSettingsHook else { return appSettings }
return appSettingsHook.run(appSettings: appSettings)
}
}
protocol AppHooksProtocol {
func configure()
}
extension AppHooksProtocol {
func configure() { }
}
// MARK: Protocols
protocol AppSettingsHookProtocol {
func run(appSettings: AppSettings) -> AppSettings
}

View File

@ -31,7 +31,7 @@ class MockPostHogFactory: PostHogFactory {
self.mock = mock self.mock = mock
} }
func createPostHog(config: PostHogConfig) -> ElementX.PHGPostHogProtocol { func createPostHog(config: PostHogConfig) -> PHGPostHogProtocol {
mock mock
} }
} }

View File

@ -118,6 +118,7 @@ targets:
PRODUCT_BUNDLE_IDENTIFIER: $(BASE_BUNDLE_IDENTIFIER) PRODUCT_BUNDLE_IDENTIFIER: $(BASE_BUNDLE_IDENTIFIER)
MARKETING_VERSION: $(MARKETING_VERSION) MARKETING_VERSION: $(MARKETING_VERSION)
CURRENT_PROJECT_VERSION: $(CURRENT_PROJECT_VERSION) CURRENT_PROJECT_VERSION: $(CURRENT_PROJECT_VERSION)
ASSETCATALOG_COMPILER_APPICON_NAME: AppIcon
DEVELOPMENT_TEAM: $(DEVELOPMENT_TEAM) DEVELOPMENT_TEAM: $(DEVELOPMENT_TEAM)
CODE_SIGN_ENTITLEMENTS: ElementX/SupportingFiles/ElementX.entitlements CODE_SIGN_ENTITLEMENTS: ElementX/SupportingFiles/ElementX.entitlements
SWIFT_OBJC_BRIDGING_HEADER: ElementX/SupportingFiles/ElementX-Bridging-Header.h SWIFT_OBJC_BRIDGING_HEADER: ElementX/SupportingFiles/ElementX-Bridging-Header.h

1
Enterprise Submodule

@ -0,0 +1 @@
Subproject commit e03750f654cd3800c14b41827fb3f6ab57f7d5f0

7
app.yml Normal file
View File

@ -0,0 +1,7 @@
settings:
APP_DISPLAY_NAME: Element X
PRODUCTION_APP_NAME: Element
BASE_APP_GROUP_IDENTIFIER: io.element
BASE_BUNDLE_IDENTIFIER: io.element.elementx
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME: "colors/accent-color"
DEVELOPMENT_TEAM: 7J4U792NQT

View File

@ -8,6 +8,10 @@ install_xcode_cloud_brew_dependencies
if [ "$CI_WORKFLOW" = "Nightly" ]; then if [ "$CI_WORKFLOW" = "Nightly" ]; then
bundle exec fastlane config_nightly build_number:"$CI_BUILD_NUMBER" bundle exec fastlane config_nightly build_number:"$CI_BUILD_NUMBER"
elif [ "$CI_WORKFLOW" = "Enterprise" ]; then
# Not sure what Xcode Cloud does, might need to also
# git submodule update --init --recursive
bundle exec fastlane config_enterprise
else else
bundle exec fastlane config_production bundle exec fastlane config_production
fi fi

View File

@ -1,6 +1,11 @@
require 'yaml' require 'yaml'
require 'semantic' require 'semantic'
enterprise = '../Enterprise/fastlane/Fastfile'
if File.exist?(enterprise)
import enterprise
end
before_all do before_all do
xcversion(version: "15.2") xcversion(version: "15.2")
@ -146,14 +151,18 @@ lane :integration_tests do
) )
end end
lane :config_production do
config_secrets()
xcodegen(spec: "project.yml")
end
lane :config_nightly do |options| lane :config_nightly do |options|
build_number = options[:build_number] build_number = options[:build_number]
UI.user_error!("Invalid build number.") unless !build_number.to_s.empty? UI.user_error!("Invalid build number.") unless !build_number.to_s.empty?
target_file_path = "../project.yml" target_file_path = "../project.yml"
data = YAML.load_file target_file_path data = YAML.load_file target_file_path
data["settings"]["BASE_APP_GROUP_IDENTIFIER"] = "io.element.nightly" data["include"].append({ "path" => "fastlane/nightly.yml" })
data["settings"]["BASE_BUNDLE_IDENTIFIER"] = "io.element.elementx.nightly"
config_secrets() config_secrets()
@ -170,11 +179,6 @@ lane :config_nightly do |options|
update_app_icon(caption_text: "#{release_version}(#{build_number})", modulate: "100,20,100") update_app_icon(caption_text: "#{release_version}(#{build_number})", modulate: "100,20,100")
end end
lane :config_production do
config_secrets()
xcodegen(spec: "project.yml")
end
$sentry_retry=0 $sentry_retry=0
lane :upload_dsyms_to_sentry do |options| lane :upload_dsyms_to_sentry do |options|
auth_token = ENV["SENTRY_AUTH_TOKEN"] auth_token = ENV["SENTRY_AUTH_TOKEN"]
@ -302,8 +306,7 @@ end
private_lane :config_xcodegen_alpha do private_lane :config_xcodegen_alpha do
target_file_path = "../project.yml" target_file_path = "../project.yml"
data = YAML.load_file target_file_path data = YAML.load_file target_file_path
data["settings"]["BASE_APP_GROUP_IDENTIFIER"] = "io.element.pr" data["include"].append({ "path" => "fastlane/alpha.yml" })
data["settings"]["BASE_BUNDLE_IDENTIFIER"] = "io.element.elementx.pr"
File.open(target_file_path, 'w') { |f| YAML.dump(data, f) } File.open(target_file_path, 'w') { |f| YAML.dump(data, f) }
xcodegen(spec: "project.yml") xcodegen(spec: "project.yml")

View File

@ -45,14 +45,6 @@ For _fastlane_ installation instructions, see [Installing _fastlane_](https://do
### config_nightly
```sh
[bundle exec] fastlane config_nightly
```
### config_production ### config_production
```sh ```sh
@ -61,6 +53,14 @@ For _fastlane_ installation instructions, see [Installing _fastlane_](https://do
### config_nightly
```sh
[bundle exec] fastlane config_nightly
```
### upload_dsyms_to_sentry ### upload_dsyms_to_sentry
```sh ```sh

3
fastlane/alpha.yml Normal file
View File

@ -0,0 +1,3 @@
settings:
BASE_APP_GROUP_IDENTIFIER: io.element.pr
BASE_BUNDLE_IDENTIFIER: io.element.elementx.pr

3
fastlane/nightly.yml Normal file
View File

@ -0,0 +1,3 @@
settings:
BASE_APP_GROUP_IDENTIFIER: io.element.nightly
BASE_BUNDLE_IDENTIFIER: io.element.elementx.nightly

View File

@ -21,21 +21,16 @@ options:
settings: settings:
CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED: YES CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED: YES
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME: "colors/accent-color"
ENABLE_BITCODE: NO ENABLE_BITCODE: NO
BASE_APP_GROUP_IDENTIFIER: io.element
APP_GROUP_IDENTIFIER: group.$(BASE_APP_GROUP_IDENTIFIER) APP_GROUP_IDENTIFIER: group.$(BASE_APP_GROUP_IDENTIFIER)
BASE_BUNDLE_IDENTIFIER: io.element.elementx
APP_NAME: ElementX APP_NAME: ElementX
APP_DISPLAY_NAME: Element X
PRODUCTION_APP_NAME: Element
KEYCHAIN_ACCESS_GROUP_IDENTIFIER: $(AppIdentifierPrefix)$(BASE_BUNDLE_IDENTIFIER) KEYCHAIN_ACCESS_GROUP_IDENTIFIER: $(AppIdentifierPrefix)$(BASE_BUNDLE_IDENTIFIER)
MARKETING_VERSION: 1.6.13 MARKETING_VERSION: 1.6.13
CURRENT_PROJECT_VERSION: 1 CURRENT_PROJECT_VERSION: 1
DEVELOPMENT_TEAM: 7J4U792NQT
SUPPORTS_MACCATALYST: NO SUPPORTS_MACCATALYST: NO
include: include:
- path: app.yml
- path: ElementX/SupportingFiles/target.yml - path: ElementX/SupportingFiles/target.yml
- path: UnitTests/SupportingFiles/target.yml - path: UnitTests/SupportingFiles/target.yml
- path: PreviewTests/SupportingFiles/target.yml - path: PreviewTests/SupportingFiles/target.yml