Configure diagnostics (and MapLibre) using Pkl. (#3820)

* Bump the version for the next release.

* Ignore all generated sources.

* Use Pkl+XcodeGen to inject secrets instead of the project.

* Inject the PostHog/Sentry/Rageshake configuration from the environment.

* Fix bad unicode.

* Fix unit tests.
This commit is contained in:
Doug
2025-02-24 18:36:08 +00:00
committed by GitHub
parent 99141735c8
commit b249f0449a
18 changed files with 95 additions and 99 deletions

View File

@@ -5,5 +5,5 @@ 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 ElementX/SupportingFiles/secrets.xcconfig
# ignores updates of 'Secrets.swift' to avoid pushing sensitive data by mistake
git update-index --assume-unchanged ElementX/SupportingFiles/Secrets.swift

View File

@@ -41,6 +41,10 @@ jobs:
run: bundle exec fastlane config_enterprise
env:
MAPLIBRE_API_KEY: WeDontNeedOneForUnitTests
SENTRY_DSN: https://sentry.localhost
POSTHOG_HOST: https://posthog.localhost
POSTHOG_API_KEY: WeDontNeedOneForUnitTests
RAGESHAKE_SERVER_URL: https://rageshake.localhost
- name: SwiftFormat
run: swiftformat --lint .

4
.gitignore vendored
View File

@@ -37,3 +37,7 @@ build
## macOS Files
.DS_Store
._*
# This is a temporary file that is used to generate Secrets.swift
# That file doesn't need to be ignored, as it we assumed-unchanged it post-checkout.
Secrets/secrets.yml

View File

@@ -1,6 +1,6 @@
--swiftversion 5.6
--exclude ElementX/Sources/Generated,vendor,**/Package.swift,ElementX/Sources/Mocks/Generated
--exclude **/Sources/**/Generated,vendor,**/Package.swift,Secrets/**
--disable wrapMultiLineStatementBraces
--disable hoistPatternLet

View File

@@ -180,6 +180,7 @@
21AFEFB8CEFE56A3811A1F5B /* VoiceMessageCacheTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 283974987DA7EC61D2AB57D9 /* VoiceMessageCacheTests.swift */; };
21F29351EDD7B2A5534EE862 /* SecureBackupKeyBackupScreen.swift in Sources */ = {isa = PBXBuildFile; fileRef = AD558A898847C179E4B7A237 /* SecureBackupKeyBackupScreen.swift */; };
22882C710BC99EC34A5024A0 /* UITestsScreenIdentifier.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6CEBE5EA91E8691EDF364EC2 /* UITestsScreenIdentifier.swift */; };
22B380C579C148BA0BFB5952 /* Secrets.swift in Sources */ = {isa = PBXBuildFile; fileRef = D3557ACB95D0F666EF5AF0CE /* Secrets.swift */; };
22C5483D01EEB290B8339817 /* HomeScreenInviteCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = D8FC33C3F6BF597E095CE9FA /* HomeScreenInviteCell.swift */; };
230981086F0199F913434D6B /* EncryptionSettingsUITests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3BF8E5D4C95974B96A18C80E /* EncryptionSettingsUITests.swift */; };
2335D1AB954C151FD8779F45 /* RoomPermissionsTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = F0096BC5DA86AF6B6E5742AC /* RoomPermissionsTests.swift */; };
@@ -2353,6 +2354,7 @@
D28F7A6CEEA4A2815B0F0F55 /* SettingsFlowCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SettingsFlowCoordinator.swift; sourceTree = "<group>"; };
D316BB02636AF2174F2580E6 /* SoftLogoutScreenViewModelProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SoftLogoutScreenViewModelProtocol.swift; sourceTree = "<group>"; };
D33116993D54FADC0C721C1F /* Application.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Application.swift; sourceTree = "<group>"; };
D3557ACB95D0F666EF5AF0CE /* Secrets.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Secrets.swift; sourceTree = "<group>"; };
D38391154120264910D19528 /* PollMock.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PollMock.swift; sourceTree = "<group>"; };
D39D7F513A36C9C1951DB44C /* AnalyticsSettingsScreen.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AnalyticsSettingsScreen.swift; sourceTree = "<group>"; };
D3F219838588C62198E726E3 /* LABiometryType.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LABiometryType.swift; sourceTree = "<group>"; };
@@ -2439,7 +2441,6 @@
E5FDFAA04174CC99FB66391C /* EditRoomAddressScreenViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EditRoomAddressScreenViewModel.swift; sourceTree = "<group>"; };
E60757AFE04391B43EA568B8 /* nl */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = nl; path = nl.lproj/InfoPlist.strings; sourceTree = "<group>"; };
E6372DD10DED30E7AD7BCE21 /* RoomListFiltersView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomListFiltersView.swift; sourceTree = "<group>"; };
E65DA46BD5CA83747AE144F3 /* secrets.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = secrets.xcconfig; sourceTree = "<group>"; };
E66763BD54A3A1D9C6E6F2F1 /* PinnedItemsIndicatorView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PinnedItemsIndicatorView.swift; sourceTree = "<group>"; };
E6935A55AB3B0C94BC566DD6 /* EncryptionResetPasswordScreenCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EncryptionResetPasswordScreenCoordinator.swift; sourceTree = "<group>"; };
E6E6BDF9D26DB05C88901416 /* RedactedRoomTimelineItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RedactedRoomTimelineItem.swift; sourceTree = "<group>"; };
@@ -2500,6 +2501,7 @@
F17EFA1D3D09FC2F9C5E1CB2 /* MediaProvider.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MediaProvider.swift; sourceTree = "<group>"; };
F1B8500C152BC59445647DA8 /* UnsupportedRoomTimelineItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UnsupportedRoomTimelineItem.swift; sourceTree = "<group>"; };
F276F31C1AEC19E52B951B62 /* SendInviteConfirmationView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SendInviteConfirmationView.swift; sourceTree = "<group>"; };
F2DC502B1A566E99969D34DD /* nb */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = nb; path = nb.lproj/InfoPlist.strings; sourceTree = "<group>"; };
F2E4EF80DFB8FE7C4469B15D /* RoomDirectorySearchScreen.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomDirectorySearchScreen.swift; sourceTree = "<group>"; };
F31F59030205A6F65B057E1A /* MatrixEntityRegexTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MatrixEntityRegexTests.swift; sourceTree = "<group>"; };
F348B5F2C12F9D4F4B4D3884 /* VideoRoomTimelineItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VideoRoomTimelineItem.swift; sourceTree = "<group>"; };
@@ -2796,7 +2798,6 @@
9C5E81214D27A6B898FC397D /* ElementX.entitlements */,
81B17DB1BC3B0C62AF84D230 /* Info.plist */,
048A21188AB19349D026BECD /* PrivacyInfo.xcprivacy */,
E65DA46BD5CA83747AE144F3 /* secrets.xcconfig */,
B050A6B233D95807A09289E7 /* Settings.bundle */,
F012CB5EE3F2B67359F6CC52 /* target.yml */,
);
@@ -2952,6 +2953,14 @@
path = View;
sourceTree = "<group>";
};
2197234282B4BC0CE79AAC74 /* Secrets */ = {
isa = PBXGroup;
children = (
D3557ACB95D0F666EF5AF0CE /* Secrets.swift */,
);
path = Secrets;
sourceTree = "<group>";
};
21E5BB69FC9058BED96B9EFD /* Sources */ = {
isa = PBXGroup;
children = (
@@ -3488,6 +3497,7 @@
A8002CB4F20B6282850A614C /* DevelopmentAssets */,
B04B538A859CD012755DC19C /* NSE */,
1803CD2B96BF06009334BB61 /* PreviewTests */,
2197234282B4BC0CE79AAC74 /* Secrets */,
D0111119CDF3E28E6D7768E8 /* ShareExtension */,
681566846AF307E9BA4C72C6 /* Products */,
);
@@ -7450,6 +7460,7 @@
0437765FF480249486893CC7 /* ScreenTrackerViewModifier.swift in Sources */,
0BFA67AFD757EE2BA569836A /* ScrollViewAdapter.swift in Sources */,
67160204A8D362BB7D4AD259 /* Search.swift in Sources */,
22B380C579C148BA0BFB5952 /* Secrets.swift in Sources */,
339BC18777912E1989F2F17D /* Section.swift in Sources */,
F833D5B5BE6707F961FA88DB /* SecureBackupController.swift in Sources */,
2D0E3983288E2D35613AD681 /* SecureBackupControllerMock.swift in Sources */,
@@ -7896,6 +7907,7 @@
7199693797B66245EF97BCF5 /* id */,
44C314C00533E2C297796B60 /* it */,
0BA7D6C94A50428463D09AF0 /* ka */,
F2DC502B1A566E99969D34DD /* nb */,
E60757AFE04391B43EA568B8 /* nl */,
997BF045585AF6DB2EBC5755 /* pl */,
A8DF55467ED4CE76B7AE9A33 /* pt */,
@@ -7982,7 +7994,6 @@
};
62E1B7866DF0ED442C39A83B /* Release */ = {
isa = XCBuildConfiguration;
baseConfigurationReference = E65DA46BD5CA83747AE144F3 /* secrets.xcconfig */;
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CODE_SIGN_ENTITLEMENTS = ElementX/SupportingFiles/ElementX.entitlements;
@@ -8011,7 +8022,6 @@
};
6897D5BC19A2EA6ABD57DE7E /* Debug */ = {
isa = XCBuildConfiguration;
baseConfigurationReference = E65DA46BD5CA83747AE144F3 /* secrets.xcconfig */;
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CODE_SIGN_ENTITLEMENTS = ElementX/SupportingFiles/ElementX.entitlements;
@@ -8135,7 +8145,7 @@
IPHONEOS_DEPLOYMENT_TARGET = 17.6;
KEYCHAIN_ACCESS_GROUP_IDENTIFIER = "$(AppIdentifierPrefix)$(BASE_BUNDLE_IDENTIFIER)";
MACOSX_DEPLOYMENT_TARGET = 14.6;
MARKETING_VERSION = 25.02.1;
MARKETING_VERSION = 25.03.0;
MTL_ENABLE_DEBUG_INFO = NO;
MTL_FAST_MATH = YES;
PRODUCTION_APP_NAME = Element;
@@ -8212,7 +8222,7 @@
IPHONEOS_DEPLOYMENT_TARGET = 17.6;
KEYCHAIN_ACCESS_GROUP_IDENTIFIER = "$(AppIdentifierPrefix)$(BASE_BUNDLE_IDENTIFIER)";
MACOSX_DEPLOYMENT_TARGET = 14.6;
MARKETING_VERSION = 25.02.1;
MARKETING_VERSION = 25.03.0;
MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
MTL_FAST_MATH = YES;
ONLY_ACTIVE_ARCH = YES;

View File

@@ -200,8 +200,8 @@ final class AppSettings {
// MARK: - Bug report
let bugReportServiceBaseURL: URL = "https://riot.im/bugreports"
let bugReportSentryURL: URL = "https://f39ac49e97714316965b777d9f3d6cd8@sentry.tools.element.io/44"
let bugReportServiceBaseURL: URL! = URL(string: Secrets.rageshakeServerURL)
let bugReportSentryURL: URL! = URL(string: Secrets.sentryDSN)
// Use the name allocated by the bug report server
let bugReportApplicationId = "element-x-ios"
/// The maximum size of the upload request. Default value is just below CloudFlare's max request size.
@@ -209,21 +209,14 @@ final class AppSettings {
// MARK: - Analytics
#if DEBUG
/// The configuration to use for analytics during development. Set `isEnabled` to false to disable analytics in debug builds.
/// **Note:** Analytics are disabled by default for forks. If you are maintaining a fork, set custom configurations.
let analyticsConfiguration = AnalyticsConfiguration(isEnabled: InfoPlistReader.main.bundleIdentifier.starts(with: "io.element."),
host: "https://posthog.element.dev",
apiKey: "phc_VtA1L35nw3aeAtHIx1ayrGdzGkss7k1xINeXcoIQzXN",
termsURL: "https://element.io/cookie-policy")
#else
/// The configuration to use for analytics. Set `isEnabled` to false to disable analytics.
/// **Note:** Analytics are disabled by default for forks. If you are maintaining a fork, set custom configurations.
///
/// **Note:** Analytics are disabled by default for forks. If you are maintaining a fork you will
/// need to regenerate the Secrets file with your PostHog server and API key before enabling.
let analyticsConfiguration = AnalyticsConfiguration(isEnabled: InfoPlistReader.main.bundleIdentifier.starts(with: "io.element."),
host: "https://posthog.element.io",
apiKey: "phc_Jzsm6DTm6V2705zeU5dcNvQDlonOR68XvX2sh1sEOHO",
termsURL: URL("https://element.io/cookie-policy"))
#endif
host: Secrets.postHogHost,
apiKey: Secrets.postHogAPIKey,
termsURL: "https://element.io/cookie-policy")
/// Whether the user has opted in to send analytics.
@UserPreference(key: UserDefaultsKeys.analyticsConsentState, defaultValue: AnalyticsConsentState.unknown, storageType: .userDefaults(store))
@@ -273,7 +266,7 @@ final class AppSettings {
let mapTilerBaseURL: URL = "https://api.maptiler.com/maps"
// maptiler api key
let mapTilerApiKey = InfoPlistReader.main.mapLibreAPIKey
let mapTilerApiKey = Secrets.mapLibreAPIKey
// MARK: - Presence

View File

@@ -15,7 +15,6 @@ struct InfoPlistReader {
static let bundleShortVersion = "CFBundleShortVersionString"
static let bundleDisplayName = "CFBundleDisplayName"
static let productionAppName = "productionAppName"
static let mapLibreAPIKey = "mapLibreAPIKey"
static let utExportedTypeDeclarationsKey = "UTExportedTypeDeclarations"
static let utTypeIdentifierKey = "UTTypeIdentifier"
static let utDescriptionKey = "UTTypeDescription"
@@ -88,12 +87,6 @@ struct InfoPlistReader {
infoPlistValue(forKey: Keys.productionAppName)
}
// MARK: - MapLibre
var mapLibreAPIKey: String {
infoPlistValue(forKey: Keys.mapLibreAPIKey)
}
// MARK: - Custom App Scheme
var appScheme: String {

View File

@@ -117,8 +117,6 @@
<string>$(BASE_BUNDLE_IDENTIFIER)</string>
<key>keychainAccessGroupIdentifier</key>
<string>$(KEYCHAIN_ACCESS_GROUP_IDENTIFIER)</string>
<key>mapLibreAPIKey</key>
<string>$(MAPLIBRE_API_KEY)</string>
<key>productionAppName</key>
<string>$(PRODUCTION_APP_NAME)</string>
</dict>

View File

@@ -1,21 +0,0 @@
//
// 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
// MARK: - MapLibre
MAPLIBRE_API_KEY = your_key

View File

@@ -42,10 +42,6 @@ targets:
type: application
platform: iOS
configFiles:
Debug: ../SupportingFiles/secrets.xcconfig
Release: ../SupportingFiles/secrets.xcconfig
info:
path: ../SupportingFiles/Info.plist
properties:
@@ -109,8 +105,6 @@ targets:
LSHandlerRank: Owner
LSItemContentTypes: $(PILLS_UT_TYPE_IDENTIFIER)
LSSupportsOpeningDocumentsInPlace: false
mapLibreAPIKey: $(MAPLIBRE_API_KEY)
settings:
base:
@@ -226,6 +220,7 @@ targets:
excludes:
- Other/Extensions/XCTestCase.swift
- Other/Extensions/XCUIElement.swift
- path: ../../Secrets/Secrets.swift
- path: ../Resources
- path: ../SupportingFiles
- path: ../../Tools/Scripts/Templates/SimpleScreenExample/ElementX

17
Secrets/Secrets.pkl Normal file
View File

@@ -0,0 +1,17 @@
//
// Copyright 2025 New Vector Ltd.
//
// SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial
// Please see LICENSE files in the repository root for full details.
//
// Analytics and Diagnostics
sentryDSN = read("env:SENTRY_DSN")
postHogHost = read("env:POSTHOG_HOST")
postHogAPIKey = read("env:POSTHOG_API_KEY")
rageshakeServerURL = read("env:RAGESHAKE_SERVER_URL")
// Maps
mapLibreAPIKey = read("env:MAPLIBRE_API_KEY")

19
Secrets/Secrets.swift Normal file
View File

@@ -0,0 +1,19 @@
// swiftlint:disable all
// Generated using SwiftGen https://github.com/SwiftGen/SwiftGen
import Foundation
// swiftlint:disable superfluous_disable_command
// swiftlint:disable file_length
// MARK: - YAML Files
// swiftlint:disable identifier_name line_length number_separator type_body_length
internal enum Secrets {
internal static let mapLibreAPIKey: String = "your_key"
internal static let postHogAPIKey: String = "your_key"
internal static let postHogHost: String = "https://posthog.localhost"
internal static let rageshakeServerURL: String = "https://rageshake.localhost"
internal static let sentryDSN: String = "https://sentry.localhost"
}
// swiftlint:enable identifier_name line_length number_separator type_body_length

View File

@@ -30,14 +30,14 @@ setup_xcode_cloud_environment () {
}
install_xcode_cloud_brew_dependencies () {
brew update && brew install xcodegen pkl
brew update && brew install xcodegen swiftgen pkl
}
setup_github_actions_environment() {
unset HOMEBREW_NO_INSTALL_FROM_API
export HOMEBREW_NO_INSTALLED_DEPENDENTS_CHECK=1
brew update && brew install xcodegen swiftlint swiftformat git-lfs pkl a7ex/homebrew-formulae/xcresultparser
brew update && brew install xcodegen swiftlint swiftformat swiftgen git-lfs pkl a7ex/homebrew-formulae/xcresultparser
bundle config path vendor/bundle
bundle install --jobs 4 --retry 3

View File

@@ -17,19 +17,20 @@ The location sharing feature on Element X is currently integrated with [MapLibre
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:
After you get an API key, you need to configure the project by exporting it and regenerating the `Secrets.swift` file:
```
MAPLIBRE_API_KEY = your_map_libre_key
export MAPLIBRE_API_KEY=your_map_libre_key
bundle exec fastlane config_secrets
```
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
git update-index assume-unchanged Secrets/Secrets.swift
```
this will prevent pushing any update of the file`secrets.xcconfig`.
this will prevent pushing any update of the file `Secrets.swift`.
Finally you need to setup your map styles overriding the values you find in the code:

View File

@@ -408,14 +408,9 @@ private_lane :create_simulator_if_necessary do |options|
end
end
private_lane :config_secrets do
maplibre_api_key = ENV["MAPLIBRE_API_KEY"]
UI.user_error!("Invalid Map Libre API key.") unless !maplibre_api_key.to_s.empty?
set_xcconfig_value(
path: './ElementX/SupportingFiles/secrets.xcconfig',
name: 'MAPLIBRE_API_KEY',
value: maplibre_api_key,
mask_value: true
)
lane :config_secrets do
Dir.chdir "../Secrets" do
sh("pkl eval -f yaml -o secrets.yml Secrets.pkl")
sh("swiftgen run yaml -n inline-swift5 --param enumName=Secrets -o Secrets.swift secrets.yml")
end
end

View File

@@ -101,6 +101,14 @@ For _fastlane_ installation instructions, see [Installing _fastlane_](https://do
### config_secrets
```sh
[bundle exec] fastlane config_secrets
```
----
This README.md is auto-generated and will be re-generated every time [_fastlane_](https://fastlane.tools) is run.

View File

@@ -41,7 +41,7 @@ settings:
APP_GROUP_IDENTIFIER: group.$(BASE_APP_GROUP_IDENTIFIER)
APP_NAME: ElementX
KEYCHAIN_ACCESS_GROUP_IDENTIFIER: "$(AppIdentifierPrefix)$(BASE_BUNDLE_IDENTIFIER)"
MARKETING_VERSION: 25.02.1
MARKETING_VERSION: 25.03.0
CURRENT_PROJECT_VERSION: 1
SUPPORTS_MACCATALYST: false

View File

@@ -1,20 +0,0 @@
//
// 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