Move Map Libre API key to Xcode Cloud (#1313)

* Add config_production lane

* Add maplibre to .gitignore

* Add setupMapLibreKey

* Add documentation

* Fix failing UTs

* Fix more UTs

* Cleanup

* Add secrets.xcconfig

* Cleanup gitignore file

* Update post-checkout hook

* Cleanup SetupProject

* Update project

* Remove leftover in SetupProject

* Cleanup project.yml

* Add fastlane-plugin-xcconfig

* Improve test

* Update docs
This commit is contained in:
Alfonso Grillo 2023-07-14 10:19:38 +02:00 committed by GitHub
parent 027b6b21f7
commit a7256bb486
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
17 changed files with 160 additions and 13 deletions

View File

@ -4,3 +4,6 @@ git lfs post-checkout "$@"
#!/bin/bash
export PATH="$PATH:/opt/homebrew/bin"
# ignores updates of 'secrets.xcconfig' to avoid pushing sensitive data by mistake
git update-index --assume-unchanged secrets.xcconfig

View File

@ -967,6 +967,7 @@
40B21E611DADDEF00307E7AC /* String.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = String.swift; sourceTree = "<group>"; };
4132F882A984ED971338EE9D /* ReportContentScreenUITests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ReportContentScreenUITests.swift; sourceTree = "<group>"; };
4151163F666ED94FD959475A /* NotificationName.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotificationName.swift; sourceTree = "<group>"; };
41553551C55AD59885840F0E /* secrets.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = secrets.xcconfig; sourceTree = "<group>"; };
4176C3E20C772DE8D182863C /* LegalInformationScreen.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LegalInformationScreen.swift; sourceTree = "<group>"; };
421E716C521F96D24ECE69B3 /* NoticeRoomTimelineItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NoticeRoomTimelineItem.swift; sourceTree = "<group>"; };
421FA93BCC2840E66E4F306F /* NotificationSettingsScreenViewModelProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotificationSettingsScreenViewModelProtocol.swift; sourceTree = "<group>"; };
@ -2004,6 +2005,7 @@
isa = PBXGroup;
children = (
5D26A086A8278D39B5756D6F /* project.yml */,
41553551C55AD59885840F0E /* secrets.xcconfig */,
99B9B46F2D621380428E68F7 /* ElementX */,
A4852B57D55D71EEBFCD931D /* UnitTests */,
C0FAC17D4DD7D3A502822550 /* UITests */,
@ -3590,6 +3592,14 @@
path = Timeline;
sourceTree = "<group>";
};
"TEMP_FFE5FDBA-B4DD-4FF7-B172-18026F248E20" /* element-x-ios */ = {
isa = PBXGroup;
children = (
41553551C55AD59885840F0E /* secrets.xcconfig */,
);
path = "element-x-ios";
sourceTree = "<group>";
};
/* End PBXGroup section */
/* Begin PBXNativeTarget section */
@ -4822,6 +4832,7 @@
};
62E1B7866DF0ED442C39A83B /* Release */ = {
isa = XCBuildConfiguration;
baseConfigurationReference = 41553551C55AD59885840F0E /* secrets.xcconfig */;
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CODE_SIGN_ENTITLEMENTS = ElementX/SupportingFiles/ElementX.entitlements;
@ -4845,6 +4856,7 @@
};
6897D5BC19A2EA6ABD57DE7E /* Debug */ = {
isa = XCBuildConfiguration;
baseConfigurationReference = 41553551C55AD59885840F0E /* secrets.xcconfig */;
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CODE_SIGN_ENTITLEMENTS = ElementX/SupportingFiles/ElementX.entitlements;

View File

@ -205,7 +205,7 @@ final class AppSettings {
let darkTileMapStyleURL: URL = "https://api.maptiler.com/maps/dea61faf-292b-4774-9660-58fcef89a7f3"
// maptiler api key
let mapTilerApiKey = "fU3vlMsMn4Jb6dnEIFsx"
let mapTilerApiKey = InfoPlistReader.main.mapLibreAPIKey
// maptiler geocoding url
let geocodingURLFormatString = "https://api.maptiler.com/geocoding/%f,%f.json"

View File

@ -23,6 +23,7 @@ struct InfoPlistReader {
static let keychainAccessGroupIdentifier = "keychainAccessGroupIdentifier"
static let bundleShortVersion = "CFBundleShortVersionString"
static let bundleDisplayName = "CFBundleDisplayName"
static let mapLibreAPIKey = "mapLibreAPIKey"
}
/// Info.plist reader on the bundle object that contains the current executable.
@ -76,6 +77,11 @@ struct InfoPlistReader {
infoPlistStringValue(forKey: Keys.bundleDisplayName)
}
/// Map Libre API Key
var mapLibreAPIKey: String {
infoPlistStringValue(forKey: Keys.mapLibreAPIKey)
}
private func infoPlistStringValue(forKey key: String) -> String {
guard let result = bundle.object(forInfoDictionaryKey: key) as? String else {
fatalError("Add \(key) into your target's Info.plst")

View File

@ -60,5 +60,7 @@
<string>$(BASE_BUNDLE_IDENTIFIER)</string>
<key>keychainAccessGroupIdentifier</key>
<string>$(KEYCHAIN_ACCESS_GROUP_IDENTIFIER)</string>
<key>mapLibreAPIKey</key>
<string>$(MAPLIBRE_API_KEY)</string>
</dict>
</plist>

View File

@ -45,6 +45,10 @@ targets:
type: application
platform: iOS
configFiles:
Debug: ../../secrets.xcconfig
Release: ../../secrets.xcconfig
info:
path: ../SupportingFiles/Info.plist
properties:
@ -76,6 +80,7 @@ targets:
BGTaskSchedulerPermittedIdentifiers: [
io.element.elementx.background.refresh
]
mapLibreAPIKey: $(MAPLIBRE_API_KEY)
settings:

View File

@ -123,6 +123,7 @@ GEM
rest-client (~> 2.0, >= 2.0.2)
fastlane-plugin-sentry (1.15.0)
os (~> 1.1, >= 1.1.4)
fastlane-plugin-xcconfig (2.0.0)
fastlane-plugin-xcodegen (1.1.0)
fastlane-plugin-brew (~> 0.1.1)
gh_inspector (1.1.3)
@ -263,9 +264,10 @@ DEPENDENCIES
fastlane-plugin-browserstack
fastlane-plugin-diawi!
fastlane-plugin-sentry
fastlane-plugin-xcconfig
fastlane-plugin-xcodegen
slather
xcode-install
BUNDLED WITH
2.3.26
2.4.16

View File

@ -41,6 +41,10 @@ When you are experiencing an issue on ElementX iOS, please first search in [GitH
and then in [#element-x-ios:matrix.org](https://matrix.to/#/#element-x-ios:matrix.org).
If after your research you still have a question, ask at [#element-x-ios:matrix.org](https://matrix.to/#/#element-x-ios:matrix.org). Otherwise feel free to create a GitHub issue if you encounter a bug or a crash, by explaining clearly in detail what happened. You can also perform bug reporting (Rageshake) from the Element application by shaking your phone or going to the application settings. This is especially recommended when you encounter a crash.
## Forking
Please read our [forking guide](docs/FORKING.md).
## Copyright & License
Copyright (c) 2022 New Vector Ltd

View File

@ -88,10 +88,9 @@ class HomeScreenViewModelTests: XCTestCase {
let room: RoomProxyMock = .init(with: .init(id: mockRoomId, displayName: "Some room"))
room.leaveRoomClosure = { .failure(.failedLeavingRoom) }
clientProxy.roomForIdentifierMocks[mockRoomId] = room
let deferred = deferFulfillment(context.$viewState.first(), message: "viewState should be published.")
context.send(viewAction: .confirmLeaveRoom(roomIdentifier: mockRoomId))
try await deferred.fulfill()
XCTAssertNotNil(context.alertInfo)
let state = await context.nextViewState()
XCTAssertNotNil(state?.bindings.alertInfo)
}
func testLeaveRoomSuccess() async throws {

View File

@ -179,27 +179,59 @@ final class NotificationManagerTests: XCTestCase {
}
func test_MessageNotificationsRemoval() async throws {
let notificationPublisher = NotificationCenter.default.publisher(for: .roomMarkedAsRead).first()
var cancellables: Set<AnyCancellable> = .init()
let expectation1 = expectation(description: #function)
notificationPublisher
.sink { _ in
expectation1.fulfill()
}
.store(in: &cancellables)
// No interaction if the object is nil or of the wrong type
NotificationCenter.default.post(name: .roomMarkedAsRead, object: nil)
try await Task.sleep(for: .microseconds(200))
await fulfillment(of: [expectation1])
XCTAssertEqual(notificationCenter.deliveredNotificationsCallsCount, 0)
XCTAssertEqual(notificationCenter.removeDeliveredNotificationsCallsCount, 0)
let expectation2 = expectation(description: #function)
notificationPublisher
.sink { _ in
expectation2.fulfill()
}
.store(in: &cancellables)
NotificationCenter.default.post(name: .roomMarkedAsRead, object: 1)
try await Task.sleep(for: .microseconds(200))
await fulfillment(of: [expectation2])
XCTAssertEqual(notificationCenter.deliveredNotificationsCallsCount, 0)
XCTAssertEqual(notificationCenter.removeDeliveredNotificationsCallsCount, 0)
let expectation3 = expectation(description: #function)
notificationPublisher
.sink { _ in
expectation3.fulfill()
}
.store(in: &cancellables)
// The center calls the delivered and the removal functions when an id is passed
NotificationCenter.default.post(name: .roomMarkedAsRead, object: "RoomID")
try await Task.sleep(for: .microseconds(200))
await fulfillment(of: [expectation3])
XCTAssertEqual(notificationCenter.deliveredNotificationsCallsCount, 1)
XCTAssertEqual(notificationCenter.removeDeliveredNotificationsCallsCount, 1)
}
func test_InvitesNotificationsRemoval() async throws {
let notificationPublisher = NotificationCenter.default.publisher(for: .invitesScreenAppeared).first()
let expectation = expectation(description: #function)
var cancellables: Set<AnyCancellable> = .init()
notificationPublisher
.sink { _ in
expectation.fulfill()
}
.store(in: &cancellables)
NotificationCenter.default.post(name: .invitesScreenAppeared, object: nil)
try await Task.sleep(for: .microseconds(200))
await fulfillment(of: [expectation])
XCTAssertEqual(notificationCenter.deliveredNotificationsCallsCount, 1)
XCTAssertEqual(notificationCenter.removeDeliveredNotificationsCallsCount, 1)
}

View File

@ -8,4 +8,6 @@ install_xcode_cloud_brew_dependencies
if [ "$CI_WORKFLOW" = "Nightly" ]; then
bundle exec fastlane config_nightly
fi
else
bundle exec fastlane config_production
fi

32
docs/FORKING.md Normal file
View File

@ -0,0 +1,32 @@
# Forking
### Update the bundle identifier / app display name
To change the bundle identifier and the app display name for your app, open the `project.yml` file in the project root folder and change these settings:
```
BASE_BUNDLE_IDENTIFIER: io.element.elementx
APP_DISPLAY_NAME: Element X
```
After the changes run `xcodegen` to propagate them.
### Setup the location sharing
The location sharing feature on Element X is currently integrated with [MapLibre](https://maplibre.org).
The MapLibre SDK requires an API key to work, so you need to get one for yourself.
After you get an API key, you need to configure the project by adding it inside the file `secrets.xconfig` in the project root folder. After you are done, the file should contain a setting like this:
```
MAPLIBRE_API_KEY = your_map_libre_key
```
Its not recommended to push your API key in your repository since other people may get it.
One way to avoid pushing the API key by mistake is running on your machine the command:
```
git update-index assume-unchanged secrets.xcconfig
```
this will prevent pushing any update of the file`secrets.xcconfig`.

View File

@ -180,6 +180,9 @@ lane :config_nightly do
data = YAML.load_file target_file_path
data["settings"]["BASE_APP_GROUP_IDENTIFIER"] = "io.element.nightly"
data["settings"]["BASE_BUNDLE_IDENTIFIER"] = "io.element.elementx.nightly"
config_maplibre()
File.open(target_file_path, 'w') { |f| YAML.dump(data, f) }
xcodegen(spec: "project.yml")
@ -193,6 +196,11 @@ lane :config_nightly do
update_app_icon(caption_text: "Nightly #{release_version}", modulate: "100,20,100")
end
lane :config_production do
config_maplibre()
xcodegen(spec: "project.yml")
end
lane :upload_dsyms_to_sentry do |options|
auth_token = ENV["SENTRY_AUTH_TOKEN"]
UI.user_error!("Invalid Sentry Auth token.") unless !auth_token.to_s.empty?
@ -409,5 +417,15 @@ private_lane :create_simulator_if_necessary do |options|
rescue
sh("xcrun simctl create '#{simulator_name}' #{simulator_type}")
end
end
private_lane :config_maplibre do
api_key = ENV["MAPLIBRE_API_KEY"]
UI.user_error!("Invalid Map Libre API key.") unless !api_key.to_s.empty?
set_xcconfig_value(
path: './secrets.xcconfig',
name: 'MAPLIBRE_API_KEY',
value: api_key
)
end

View File

@ -6,3 +6,4 @@ gem 'fastlane-plugin-diawi', git: 'https://github.com/mhtranbn/fastlane-plugin-d
gem 'fastlane-plugin-xcodegen'
gem 'fastlane-plugin-sentry'
gem 'fastlane-plugin-browserstack'
gem 'fastlane-plugin-xcconfig'

View File

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

View File

@ -4,6 +4,7 @@ attributes:
fileGroups:
- project.yml
- secrets.xcconfig
options:
groupSortPosition: bottom

20
secrets.xcconfig Normal file
View File

@ -0,0 +1,20 @@
//
// Copyright 2023 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.
//
// Configuration settings file format documentation can be found at:
// https://help.apple.com/xcode/#/dev745c5c974
MAPLIBRE_API_KEY = your_key