From 01eb87693ffb832aa8fb92692438a986ec7270e9 Mon Sep 17 00:00:00 2001 From: Pete Schwamb Date: Mon, 20 Mar 2023 21:22:42 -0500 Subject: [PATCH 01/12] Bump version for main to 3.2.1 --- Version.xcconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Version.xcconfig b/Version.xcconfig index 373efdca05..55cac4a860 100644 --- a/Version.xcconfig +++ b/Version.xcconfig @@ -7,7 +7,7 @@ // // Version [DEFAULT] -LOOP_MARKETING_VERSION = 3.3.0 +LOOP_MARKETING_VERSION = 3.2.1 CURRENT_PROJECT_VERSION = 57 // Optional override From 8177980f81c898d5427adcb69403251f1627c2e6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonas=20Bj=C3=B6rkert?= Date: Mon, 24 Apr 2023 23:08:11 +0200 Subject: [PATCH 02/12] readlink -f (#1984) --- Scripts/copy-plugins.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Scripts/copy-plugins.sh b/Scripts/copy-plugins.sh index 5be20f32e6..a81e221569 100755 --- a/Scripts/copy-plugins.sh +++ b/Scripts/copy-plugins.sh @@ -14,7 +14,7 @@ function copy_plugins { for f in "$1"/*.loopplugin; do plugin=$(basename "$f") echo Copying plugin: $plugin to frameworks directory in app - plugin_path="$(readlink "$f" || echo "$f")" + plugin_path="$(readlink -f "$f" || echo "$f")" plugin_as_framework_path="${BUILT_PRODUCTS_DIR}/${FRAMEWORKS_FOLDER_PATH}/${plugin%.*}.framework" rsync -va --exclude=Frameworks "$plugin_path/." "${plugin_as_framework_path}" # Rename .plugin to .framework @@ -29,7 +29,7 @@ function copy_plugins { framework=$(basename "$framework_path") echo "Copying plugin's framework $framework_path to ${BUILT_PRODUCTS_DIR}/${FRAMEWORKS_FOLDER_PATH}/." cp -avf "$framework_path" "${BUILT_PRODUCTS_DIR}/${FRAMEWORKS_FOLDER_PATH}/." - plugin_path="$(readlink "$f" || echo "$f")" + plugin_path="$(readlink -f "$f" || echo "$f")" if [ "$EXPANDED_CODE_SIGN_IDENTITY" != "-" ] && [ "$EXPANDED_CODE_SIGN_IDENTITY" != "" ]; then echo "Signing $framework for $plugin with $EXPANDED_CODE_SIGN_IDENTITY_NAME" /usr/bin/codesign --force --sign ${EXPANDED_CODE_SIGN_IDENTITY} --timestamp=none --preserve-metadata=identifier,entitlements,flags "${BUILT_PRODUCTS_DIR}/${FRAMEWORKS_FOLDER_PATH}/${framework}" From befcbcbe6733e52b315cb29904f7893e39da3514 Mon Sep 17 00:00:00 2001 From: Pete Schwamb Date: Mon, 24 Apr 2023 16:36:02 -0500 Subject: [PATCH 03/12] Bump version to 3.2.2 for Xcode 14.3 archiving --- Version.xcconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Version.xcconfig b/Version.xcconfig index 55cac4a860..fadcd37ef5 100644 --- a/Version.xcconfig +++ b/Version.xcconfig @@ -7,7 +7,7 @@ // // Version [DEFAULT] -LOOP_MARKETING_VERSION = 3.2.1 +LOOP_MARKETING_VERSION = 3.2.2 CURRENT_PROJECT_VERSION = 57 // Optional override From 085a805d7661732e5c493527cf97be9f66071864 Mon Sep 17 00:00:00 2001 From: Pete Schwamb Date: Tue, 19 Sep 2023 14:23:11 -0500 Subject: [PATCH 04/12] Backport cyclic dependency changes from dev for building on Xcode 15 --- Common/Extensions/NSBundle.swift | 41 ------------ Common/Models/BuildDetails.swift | 69 ++++++++++++++++++++ Loop.xcodeproj/project.pbxproj | 11 +++- Loop/BuildDetails.plist | 12 ++++ Loop/Managers/DeviceDataManager.swift | 18 ++--- Loop/Managers/LoopAppManager.swift | 2 +- Loop/Managers/ProfileExpirationAlerter.swift | 2 +- Loop/Views/SettingsView.swift | 2 +- Scripts/capture-build-details.sh | 25 ++----- 9 files changed, 109 insertions(+), 73 deletions(-) create mode 100644 Common/Models/BuildDetails.swift create mode 100644 Loop/BuildDetails.plist diff --git a/Common/Extensions/NSBundle.swift b/Common/Extensions/NSBundle.swift index 1d4873224e..5974614d47 100644 --- a/Common/Extensions/NSBundle.swift +++ b/Common/Extensions/NSBundle.swift @@ -53,47 +53,6 @@ extension Bundle { } } - var gitRevision: String? { - return object(forInfoDictionaryKey: "com-loopkit-Loop-git-revision") as? String - } - - var gitBranch: String? { - return object(forInfoDictionaryKey: "com-loopkit-Loop-git-branch") as? String - } - - var sourceRoot: String? { - return object(forInfoDictionaryKey: "com-loopkit-Loop-srcroot") as? String - } - - var buildDateString: String? { - return object(forInfoDictionaryKey: "com-loopkit-Loop-build-date") as? String - } - - var xcodeVersion: String? { - return object(forInfoDictionaryKey: "com-loopkit-Loop-xcode-version") as? String - } - - var profileExpiration: Date? { - return object(forInfoDictionaryKey: "com-loopkit-Loop-profile-expiration") as? Date - } - - var profileExpirationString: String { - if let profileExpiration = profileExpiration { - return "\(profileExpiration)" - } else { - return "N/A" - } - } - - // These strings are only configured if it is a workspace build - var workspaceGitRevision: String? { - return object(forInfoDictionaryKey: "com-loopkit-LoopWorkspace-git-revision") as? String - } - - var workspaceGitBranch: String? { - return object(forInfoDictionaryKey: "com-loopkit-LoopWorkspace-git-branch") as? String - } - var localCacheDuration: TimeInterval { guard let localCacheDurationDaysString = object(forInfoDictionaryKey: "LoopLocalCacheDurationDays") as? String, let localCacheDurationDays = Double(localCacheDurationDaysString) else { diff --git a/Common/Models/BuildDetails.swift b/Common/Models/BuildDetails.swift new file mode 100644 index 0000000000..63517e7e79 --- /dev/null +++ b/Common/Models/BuildDetails.swift @@ -0,0 +1,69 @@ +// +// BuildDetails.swift +// Loop +// +// Created by Pete Schwamb on 6/13/23. +// Copyright © 2023 LoopKit Authors. All rights reserved. +// + +import Foundation + +class BuildDetails { + + static var `default` = BuildDetails() + + let dict: [String: Any] + + init() { + guard let url = Bundle.main.url(forResource: "BuildDetails", withExtension: ".plist"), + let data = try? Data(contentsOf: url), + let parsed = try? PropertyListSerialization.propertyList(from: data, format: nil) as? [String: Any] else + { + dict = [:] + return + } + dict = parsed + } + + var buildDateString: String? { + return dict["com-loopkit-Loop-build-date"] as? String + } + + var xcodeVersion: String? { + return dict["com-loopkit-Loop-xcode-version"] as? String + } + + var gitRevision: String? { + return dict["com-loopkit-Loop-git-revision"] as? String + } + + var gitBranch: String? { + return dict["com-loopkit-Loop-git-branch"] as? String + } + + var sourceRoot: String? { + return dict["com-loopkit-Loop-srcroot"] as? String + } + + var profileExpiration: Date? { + return dict["com-loopkit-Loop-profile-expiration"] as? Date + } + + var profileExpirationString: String { + if let profileExpiration = profileExpiration { + return "\(profileExpiration)" + } else { + return "N/A" + } + } + + // These strings are only configured if it is a workspace build + var workspaceGitRevision: String? { + return dict["com-loopkit-LoopWorkspace-git-revision"] as? String + } + + var workspaceGitBranch: String? { + return dict["com-loopkit-LoopWorkspace-git-branch"] as? String + } +} + diff --git a/Loop.xcodeproj/project.pbxproj b/Loop.xcodeproj/project.pbxproj index 31b6ebff59..15b74d6643 100644 --- a/Loop.xcodeproj/project.pbxproj +++ b/Loop.xcodeproj/project.pbxproj @@ -3,7 +3,7 @@ archiveVersion = 1; classes = { }; - objectVersion = 52; + objectVersion = 54; objects = { /* Begin PBXBuildFile section */ @@ -438,6 +438,8 @@ C11B9D64286779C000500CF8 /* MockKitUI.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = C11B9D61286779C000500CF8 /* MockKitUI.framework */; }; C11B9D65286779C000500CF8 /* MockKitUI.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = C11B9D61286779C000500CF8 /* MockKitUI.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; C11BD0552523CFED00236B08 /* SimpleBolusViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = C11BD0542523CFED00236B08 /* SimpleBolusViewModel.swift */; }; + C11C5D152ABA0B38004BD0B5 /* BuildDetails.swift in Sources */ = {isa = PBXBuildFile; fileRef = C11C5D142ABA0B38004BD0B5 /* BuildDetails.swift */; }; + C11C5D172ABA2988004BD0B5 /* BuildDetails.plist in Resources */ = {isa = PBXBuildFile; fileRef = C11C5D162ABA2988004BD0B5 /* BuildDetails.plist */; }; C11C87DE1E21EAAD00BB71D3 /* HKUnit.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4F526D5E1DF2459000A04910 /* HKUnit.swift */; }; C1201E2C23ECDBD0002DA84A /* WatchContextRequestUserInfo.swift in Sources */ = {isa = PBXBuildFile; fileRef = C1201E2B23ECDBD0002DA84A /* WatchContextRequestUserInfo.swift */; }; C1201E2D23ECDF3D002DA84A /* WatchContextRequestUserInfo.swift in Sources */ = {isa = PBXBuildFile; fileRef = C1201E2B23ECDBD0002DA84A /* WatchContextRequestUserInfo.swift */; }; @@ -1482,6 +1484,8 @@ C11B9D60286779C000500CF8 /* MockKit.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; path = MockKit.framework; sourceTree = BUILT_PRODUCTS_DIR; }; C11B9D61286779C000500CF8 /* MockKitUI.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; path = MockKitUI.framework; sourceTree = BUILT_PRODUCTS_DIR; }; C11BD0542523CFED00236B08 /* SimpleBolusViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SimpleBolusViewModel.swift; sourceTree = ""; }; + C11C5D142ABA0B38004BD0B5 /* BuildDetails.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BuildDetails.swift; sourceTree = ""; }; + C11C5D162ABA2988004BD0B5 /* BuildDetails.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = BuildDetails.plist; sourceTree = ""; }; C1201E2B23ECDBD0002DA84A /* WatchContextRequestUserInfo.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WatchContextRequestUserInfo.swift; sourceTree = ""; }; C121D8CF29C7866D00DA0520 /* cs */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = cs; path = cs.lproj/Main.strings; sourceTree = ""; }; C121D8D029C7866D00DA0520 /* cs */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = cs; path = cs.lproj/Localizable.strings; sourceTree = ""; }; @@ -2110,6 +2114,7 @@ 7D7076511FE06EE1004AC8EA /* InfoPlist.strings */, 43EDEE6B1CF2E12A00393BE3 /* Loop.entitlements */, 43F5C2D41B92A4A6003EB13D /* Info.plist */, + C11C5D162ABA2988004BD0B5 /* BuildDetails.plist */, 43776F8F1B8022E90074EA36 /* AppDelegate.swift */, 1D12D3B82548EFDD00B53E8B /* main.swift */, 43776F9A1B8022E90074EA36 /* LaunchScreen.storyboard */, @@ -2618,6 +2623,7 @@ 4F11D3C120DD80B3006E072C /* WatchHistoricalGlucose.swift */, 4F7E8AC620E2AC0300AEA65E /* WatchPredictedGlucose.swift */, E9B08020253BBDE900BAD8F8 /* IntentExtensionInfo.swift */, + C11C5D142ABA0B38004BD0B5 /* BuildDetails.swift */, ); path = Models; sourceTree = ""; @@ -3497,6 +3503,7 @@ buildActionMask = 2147483647; files = ( C13255D6223E7BE2008AF50C /* BolusProgressTableViewCell.xib in Resources */, + C11C5D172ABA2988004BD0B5 /* BuildDetails.plist in Resources */, 43FCBBC21E51710B00343C1B /* LaunchScreen.storyboard in Resources */, B405E35A24D2B1A400DD058D /* HUDAssets.xcassets in Resources */, A966152623EA5A26005D8B29 /* DefaultAssets.xcassets in Resources */, @@ -3703,7 +3710,6 @@ inputFileListPaths = ( ); inputPaths = ( - "${BUILT_PRODUCTS_DIR}/${INFOPLIST_PATH}", ); name = "Capture Build Details"; outputFileListPaths = ( @@ -3870,6 +3876,7 @@ 1D82E6A025377C6B009131FB /* TrustedTimeChecker.swift in Sources */, A98556852493F901000FD662 /* AlertStore+SimulatedCoreData.swift in Sources */, 899433B823FE129800FA4BEA /* OverrideBadgeView.swift in Sources */, + C11C5D152ABA0B38004BD0B5 /* BuildDetails.swift in Sources */, 89D1503E24B506EB00EDE253 /* Dictionary.swift in Sources */, A96DAC2C2838F31200D94E38 /* SharedLogging.swift in Sources */, 4302F4E31D4EA54200F0FCAF /* InsulinDeliveryTableViewController.swift in Sources */, diff --git a/Loop/BuildDetails.plist b/Loop/BuildDetails.plist new file mode 100644 index 0000000000..fe23d977d4 --- /dev/null +++ b/Loop/BuildDetails.plist @@ -0,0 +1,12 @@ + + + + + + diff --git a/Loop/Managers/DeviceDataManager.swift b/Loop/Managers/DeviceDataManager.swift index 96452b2e29..4e1cbfdf1d 100644 --- a/Loop/Managers/DeviceDataManager.swift +++ b/Loop/Managers/DeviceDataManager.swift @@ -677,14 +677,14 @@ final class DeviceDataManager { let report = [ "## Build Details", "* appNameAndVersion: \(Bundle.main.localizedNameAndVersion)", - "* profileExpiration: \(Bundle.main.profileExpirationString)", - "* gitRevision: \(Bundle.main.gitRevision ?? "N/A")", - "* gitBranch: \(Bundle.main.gitBranch ?? "N/A")", - "* workspaceGitRevision: \(Bundle.main.workspaceGitRevision ?? "N/A")", - "* workspaceGitBranch: \(Bundle.main.workspaceGitBranch ?? "N/A")", - "* sourceRoot: \(Bundle.main.sourceRoot ?? "N/A")", - "* buildDateString: \(Bundle.main.buildDateString ?? "N/A")", - "* xcodeVersion: \(Bundle.main.xcodeVersion ?? "N/A")", + "* profileExpiration: \(BuildDetails.default.profileExpirationString)", + "* gitRevision: \(BuildDetails.default.gitRevision ?? "N/A")", + "* gitBranch: \(BuildDetails.default.gitBranch ?? "N/A")", + "* workspaceGitRevision: \(BuildDetails.default.workspaceGitRevision ?? "N/A")", + "* workspaceGitBranch: \(BuildDetails.default.workspaceGitBranch ?? "N/A")", + "* sourceRoot: \(BuildDetails.default.sourceRoot ?? "N/A")", + "* buildDateString: \(BuildDetails.default.buildDateString ?? "N/A")", + "* xcodeVersion: \(BuildDetails.default.xcodeVersion ?? "N/A")", "", "## FeatureFlags", "\(FeatureFlags)", @@ -1673,7 +1673,7 @@ extension GlucoseStore : CGMStalenessMonitorDelegate { } extension DeviceDataManager: SupportInfoProvider { private var branchNameIfNotReleaseBranch: String? { - return Bundle.main.gitBranch.filter { branch in + return BuildDetails.default.gitBranch.filter { branch in return branch != "" && branch != "main" && branch != "master" && diff --git a/Loop/Managers/LoopAppManager.swift b/Loop/Managers/LoopAppManager.swift index 6a160790ab..b50093d293 100644 --- a/Loop/Managers/LoopAppManager.swift +++ b/Loop/Managers/LoopAppManager.swift @@ -226,7 +226,7 @@ class LoopAppManager: NSObject { analyticsServicesManager.identifyAppName(Bundle.main.bundleDisplayName) - if let workspaceGitRevision = Bundle.main.workspaceGitRevision { + if let workspaceGitRevision = BuildDetails.default.workspaceGitRevision { analyticsServicesManager.identifyWorkspaceGitRevision(workspaceGitRevision) } diff --git a/Loop/Managers/ProfileExpirationAlerter.swift b/Loop/Managers/ProfileExpirationAlerter.swift index a28d452783..3aa742732b 100644 --- a/Loop/Managers/ProfileExpirationAlerter.swift +++ b/Loop/Managers/ProfileExpirationAlerter.swift @@ -20,7 +20,7 @@ class ProfileExpirationAlerter { let now = Date() - guard let profileExpiration = Bundle.main.profileExpiration, now > profileExpiration - expirationAlertWindow else { + guard let profileExpiration = BuildDetails.default.profileExpiration, now > profileExpiration - expirationAlertWindow else { return } diff --git a/Loop/Views/SettingsView.swift b/Loop/Views/SettingsView.swift index 90859273e3..8fca56689b 100644 --- a/Loop/Views/SettingsView.swift +++ b/Loop/Views/SettingsView.swift @@ -58,7 +58,7 @@ public struct SettingsView: View { servicesSection } supportSection - if let profileExpiration = Bundle.main.profileExpiration, FeatureFlags.profileExpirationSettingsViewEnabled { + if let profileExpiration = BuildDetails.default.profileExpiration, FeatureFlags.profileExpirationSettingsViewEnabled { profileExpirationSection(profileExpiration: profileExpiration) } } diff --git a/Scripts/capture-build-details.sh b/Scripts/capture-build-details.sh index 7543ec579c..6122592374 100755 --- a/Scripts/capture-build-details.sh +++ b/Scripts/capture-build-details.sh @@ -10,11 +10,9 @@ SCRIPT_DIRECTORY="$(dirname "${0}")" error() { echo "ERROR: ${*}" >&2 - echo "Usage: ${SCRIPT} [-r|--git-source-root git-source-root] [-p|--provisioning-profile-path provisioning-profile-path] [-i|--info-plist-path info-plist-path]" >&2 + echo "Usage: ${SCRIPT} [-r|--git-source-root git-source-root] [-p|--provisioning-profile-path provisioning-profile-path]" >&2 echo "Parameters:" >&2 - echo " -r|--git-source-root root location of git repository to gather information from; optional, defaults to \${WORKSPACE_ROOT} if present, otherwise defaults to \${SRCROOT}" >&2 echo " -p|--provisioning-profile-path path to the .mobileprovision provisioning profile file to check for expiration; optional, defaults to \${HOME}/Library/MobileDevice/Provisioning Profiles/\${EXPANDED_PROVISIONING_PROFILE}.mobileprovision" >&2 - echo " -i|--info-plist-path path to the Info.plist file to modify; optional, defaults to \${BUILT_PRODUCTS_DIR}/\${INFOPLIST_PATH}" >&2 exit 1 } @@ -26,17 +24,12 @@ info() { echo "INFO: ${*}" >&2 } -git_source_root="${WORKSPACE_ROOT:-${SRCROOT}}" -info_plist_path="${BUILT_PRODUCTS_DIR}/${INFOPLIST_PATH}" +info_plist_path="${BUILT_PRODUCTS_DIR}/${CONTENTS_FOLDER_PATH}/BuildDetails.plist" provisioning_profile_path="${HOME}/Library/MobileDevice/Provisioning Profiles/${EXPANDED_PROVISIONING_PROFILE}.mobileprovision" xcode_build_version=${XCODE_PRODUCT_BUILD_VERSION:-$(xcodebuild -version | grep version | cut -d ' ' -f 3)} while [[ $# -gt 0 ]] do case $1 in - -r|--git-source-root) - git_source_root="${2}" - shift 2 - ;; -i|--info-plist-path) info_plist_path="${2}" shift 2 @@ -52,16 +45,12 @@ if [ ${#} -ne 0 ]; then error "Unexpected arguments: ${*}" fi -if [ -z "${git_source_root}" ]; then - error "Must provide one of --git-source-root, \${WORKSPACE_ROOT}, or \${SRCROOT}." -fi - if [ "${info_plist_path}" == "/" -o ! -e "${info_plist_path}" ]; then - error "Must provide valid --info-plist-path, or have valid \${BUILT_PRODUCTS_DIR} and \${INFOPLIST_PATH} set." + error "File does not exist: ${info_plist_path}" + #error "Must provide valid --info-plist-path, or have valid \${BUILT_PRODUCTS_DIR} and \${INFOPLIST_PATH} set." fi -info "Gathering build details in ${git_source_root}" -cd "${git_source_root}" +info "Gathering build details in ${PWD}" if [ -e .git ]; then rev=$(git rev-parse HEAD) @@ -74,7 +63,7 @@ if [ -e .git ]; then fi fi -plutil -replace com-loopkit-Loop-srcroot -string "${git_source_root}" "${info_plist_path}" +plutil -replace com-loopkit-Loop-srcroot -string "${PWD}" "${info_plist_path}" plutil -replace com-loopkit-Loop-build-date -string "$(date)" "${info_plist_path}" plutil -replace com-loopkit-Loop-xcode-version -string "${xcode_build_version}" "${info_plist_path}" @@ -89,7 +78,7 @@ fi # determine if this is a workspace build # if so, fill out the git revision and branch -if [ -e ../LoopWorkspace.xcworkspace ] +if [ -e ../.git ] then pushd . > /dev/null cd .. From 976c9fc1b0be4d3885966b497e89965e376d5e87 Mon Sep 17 00:00:00 2001 From: Pete Schwamb Date: Tue, 19 Sep 2023 14:25:57 -0500 Subject: [PATCH 05/12] Bump version --- Version.xcconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Version.xcconfig b/Version.xcconfig index fadcd37ef5..69e2b6349d 100644 --- a/Version.xcconfig +++ b/Version.xcconfig @@ -7,7 +7,7 @@ // // Version [DEFAULT] -LOOP_MARKETING_VERSION = 3.2.2 +LOOP_MARKETING_VERSION = 3.2.3 CURRENT_PROJECT_VERSION = 57 // Optional override From 49feb51f07f8df6a384a3b2d1a2c81ef90917194 Mon Sep 17 00:00:00 2001 From: Pete Schwamb Date: Sat, 13 Jul 2024 14:13:57 -0500 Subject: [PATCH 06/12] Bump version for release --- Version.xcconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Version.xcconfig b/Version.xcconfig index 373efdca05..e8495a893f 100644 --- a/Version.xcconfig +++ b/Version.xcconfig @@ -7,7 +7,7 @@ // // Version [DEFAULT] -LOOP_MARKETING_VERSION = 3.3.0 +LOOP_MARKETING_VERSION = 3.4.0 CURRENT_PROJECT_VERSION = 57 // Optional override From 5c3b01f7e302dca9b8bbb12fd42fdd40ed52d2c1 Mon Sep 17 00:00:00 2001 From: Marion Barker <19607791+marionbarker@users.noreply.github.com> Date: Fri, 19 Jul 2024 14:28:59 -0700 Subject: [PATCH 07/12] Bump version to 3.4.1 for release (#2194) --- Version.xcconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Version.xcconfig b/Version.xcconfig index e8495a893f..f122effc95 100644 --- a/Version.xcconfig +++ b/Version.xcconfig @@ -7,7 +7,7 @@ // // Version [DEFAULT] -LOOP_MARKETING_VERSION = 3.4.0 +LOOP_MARKETING_VERSION = 3.4.1 CURRENT_PROJECT_VERSION = 57 // Optional override From 35e106302b846118771b09965a3b70037c6c4fa9 Mon Sep 17 00:00:00 2001 From: Marion Barker <19607791+marionbarker@users.noreply.github.com> Date: Sat, 5 Oct 2024 09:23:25 -0700 Subject: [PATCH 08/12] Xcode 16 profile support for main branch (#2228) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Cache profile expiration date in app and remove hardcoded provisioning profile path * Bump version to 3.4.2 for Xcode 16 patch --------- Co-authored-by: Jonas Björkert --- Common/Models/BuildDetails.swift | 40 ++++++++++++++++++++++++++++++-- Scripts/capture-build-details.sh | 14 ----------- Version.xcconfig | 2 +- 3 files changed, 39 insertions(+), 17 deletions(-) diff --git a/Common/Models/BuildDetails.swift b/Common/Models/BuildDetails.swift index 63517e7e79..4027b81f1e 100644 --- a/Common/Models/BuildDetails.swift +++ b/Common/Models/BuildDetails.swift @@ -13,6 +13,7 @@ class BuildDetails { static var `default` = BuildDetails() let dict: [String: Any] + private var cachedProfileExpirationDate: Date? init() { guard let url = Bundle.main.url(forResource: "BuildDetails", withExtension: ".plist"), @@ -23,6 +24,7 @@ class BuildDetails { return } dict = parsed + cachedProfileExpirationDate = loadProfileExpirationDate() } var buildDateString: String? { @@ -46,11 +48,11 @@ class BuildDetails { } var profileExpiration: Date? { - return dict["com-loopkit-Loop-profile-expiration"] as? Date + return cachedProfileExpirationDate } var profileExpirationString: String { - if let profileExpiration = profileExpiration { + if let profileExpiration = cachedProfileExpirationDate { return "\(profileExpiration)" } else { return "N/A" @@ -65,5 +67,39 @@ class BuildDetails { var workspaceGitBranch: String? { return dict["com-loopkit-LoopWorkspace-git-branch"] as? String } + + private func loadProfileExpirationDate() -> Date? { + guard + let profilePath = Bundle.main.path(forResource: "embedded", ofType: "mobileprovision"), + let profileData = try? Data(contentsOf: URL(fileURLWithPath: profilePath)), + let profileNSString = NSString(data: profileData, encoding: String.Encoding.ascii.rawValue) + else { + print( + "WARNING: Could not find or read `embedded.mobileprovision`. If running on Simulator, there are no provisioning profiles." + ) + return nil + } + + let regexPattern = "ExpirationDate[\\W]*?(.*?)" + guard let regex = try? NSRegularExpression(pattern: regexPattern, options: []), + let match = regex.firstMatch( + in: profileNSString as String, + options: [], + range: NSRange(location: 0, length: profileNSString.length) + ), + let range = Range(match.range(at: 1), in: profileNSString as String) + else { + print("Warning: Could not create regex or find match.") + return nil + } + + let dateString = String(profileNSString.substring(with: NSRange(range, in: profileNSString as String))) + let dateFormatter = DateFormatter() + dateFormatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ss'Z'" + dateFormatter.locale = Locale(identifier: "en_US_POSIX") + dateFormatter.timeZone = TimeZone(secondsFromGMT: 0) + + return dateFormatter.date(from: dateString) + } } diff --git a/Scripts/capture-build-details.sh b/Scripts/capture-build-details.sh index 6122592374..0e80f71d6c 100755 --- a/Scripts/capture-build-details.sh +++ b/Scripts/capture-build-details.sh @@ -25,7 +25,6 @@ info() { } info_plist_path="${BUILT_PRODUCTS_DIR}/${CONTENTS_FOLDER_PATH}/BuildDetails.plist" -provisioning_profile_path="${HOME}/Library/MobileDevice/Provisioning Profiles/${EXPANDED_PROVISIONING_PROFILE}.mobileprovision" xcode_build_version=${XCODE_PRODUCT_BUILD_VERSION:-$(xcodebuild -version | grep version | cut -d ' ' -f 3)} while [[ $# -gt 0 ]] do @@ -34,10 +33,6 @@ do info_plist_path="${2}" shift 2 ;; - -p|--provisioning-profile-path) - provisioning_profile_path="${2}" - shift 2 - ;; esac done @@ -67,15 +62,6 @@ plutil -replace com-loopkit-Loop-srcroot -string "${PWD}" "${info_plist_path}" plutil -replace com-loopkit-Loop-build-date -string "$(date)" "${info_plist_path}" plutil -replace com-loopkit-Loop-xcode-version -string "${xcode_build_version}" "${info_plist_path}" -if [ -e "${provisioning_profile_path}" ]; then - profile_expire_date=$(security cms -D -i "${provisioning_profile_path}" | plutil -p - | grep ExpirationDate | cut -b 23-) - # Convert to plutil format - profile_expire_date=$(date -j -f "%Y-%m-%d %H:%M:%S" "${profile_expire_date}" +"%Y-%m-%dT%H:%M:%SZ") - plutil -replace com-loopkit-Loop-profile-expiration -date "${profile_expire_date}" "${info_plist_path}" -else - warn "Invalid provisioning profile path ${provisioning_profile_path}" -fi - # determine if this is a workspace build # if so, fill out the git revision and branch if [ -e ../.git ] diff --git a/Version.xcconfig b/Version.xcconfig index f122effc95..e007339db5 100644 --- a/Version.xcconfig +++ b/Version.xcconfig @@ -7,7 +7,7 @@ // // Version [DEFAULT] -LOOP_MARKETING_VERSION = 3.4.1 +LOOP_MARKETING_VERSION = 3.4.2 CURRENT_PROJECT_VERSION = 57 // Optional override From a91352a5a15db26ab185b3326e7277b25e7c6f13 Mon Sep 17 00:00:00 2001 From: Marion Barker <19607791+marionbarker@users.noreply.github.com> Date: Sun, 6 Oct 2024 13:07:06 -0700 Subject: [PATCH 09/12] Bump version to 3.4.3 (#2236) --- Version.xcconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Version.xcconfig b/Version.xcconfig index e007339db5..6fb2bbb9ba 100644 --- a/Version.xcconfig +++ b/Version.xcconfig @@ -7,7 +7,7 @@ // // Version [DEFAULT] -LOOP_MARKETING_VERSION = 3.4.2 +LOOP_MARKETING_VERSION = 3.4.3 CURRENT_PROJECT_VERSION = 57 // Optional override From 20c313c0c3d5344e9b284d063349eedbcb8d7ba0 Mon Sep 17 00:00:00 2001 From: Marion Barker <19607791+marionbarker@users.noreply.github.com> Date: Wed, 9 Oct 2024 16:11:50 -0700 Subject: [PATCH 10/12] Patch for Loop 3.4.4 to restore TestFlight expiration date (#2242) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Adjust provisioning profile path in script for Xcode 16 compatibility * Bump version to 3.4.4 --------- Co-authored-by: Jonas Björkert --- Common/Models/BuildDetails.swift | 46 ++++---------------------------- Scripts/capture-build-details.sh | 26 +++++++++++++++++- Version.xcconfig | 2 +- 3 files changed, 31 insertions(+), 43 deletions(-) diff --git a/Common/Models/BuildDetails.swift b/Common/Models/BuildDetails.swift index 4027b81f1e..4a1a1894fc 100644 --- a/Common/Models/BuildDetails.swift +++ b/Common/Models/BuildDetails.swift @@ -13,18 +13,16 @@ class BuildDetails { static var `default` = BuildDetails() let dict: [String: Any] - private var cachedProfileExpirationDate: Date? init() { guard let url = Bundle.main.url(forResource: "BuildDetails", withExtension: ".plist"), - let data = try? Data(contentsOf: url), - let parsed = try? PropertyListSerialization.propertyList(from: data, format: nil) as? [String: Any] else + let data = try? Data(contentsOf: url), + let parsed = try? PropertyListSerialization.propertyList(from: data, format: nil) as? [String: Any] else { dict = [:] return } dict = parsed - cachedProfileExpirationDate = loadProfileExpirationDate() } var buildDateString: String? { @@ -48,11 +46,11 @@ class BuildDetails { } var profileExpiration: Date? { - return cachedProfileExpirationDate + return dict["com-loopkit-Loop-profile-expiration"] as? Date } var profileExpirationString: String { - if let profileExpiration = cachedProfileExpirationDate { + if let profileExpiration = profileExpiration { return "\(profileExpiration)" } else { return "N/A" @@ -65,41 +63,7 @@ class BuildDetails { } var workspaceGitBranch: String? { - return dict["com-loopkit-LoopWorkspace-git-branch"] as? String - } - - private func loadProfileExpirationDate() -> Date? { - guard - let profilePath = Bundle.main.path(forResource: "embedded", ofType: "mobileprovision"), - let profileData = try? Data(contentsOf: URL(fileURLWithPath: profilePath)), - let profileNSString = NSString(data: profileData, encoding: String.Encoding.ascii.rawValue) - else { - print( - "WARNING: Could not find or read `embedded.mobileprovision`. If running on Simulator, there are no provisioning profiles." - ) - return nil - } - - let regexPattern = "ExpirationDate[\\W]*?(.*?)" - guard let regex = try? NSRegularExpression(pattern: regexPattern, options: []), - let match = regex.firstMatch( - in: profileNSString as String, - options: [], - range: NSRange(location: 0, length: profileNSString.length) - ), - let range = Range(match.range(at: 1), in: profileNSString as String) - else { - print("Warning: Could not create regex or find match.") - return nil - } - - let dateString = String(profileNSString.substring(with: NSRange(range, in: profileNSString as String))) - let dateFormatter = DateFormatter() - dateFormatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ss'Z'" - dateFormatter.locale = Locale(identifier: "en_US_POSIX") - dateFormatter.timeZone = TimeZone(secondsFromGMT: 0) - - return dateFormatter.date(from: dateString) + return dict["com-loopkit-LoopWorkspace-git-branch"] as? String } } diff --git a/Scripts/capture-build-details.sh b/Scripts/capture-build-details.sh index 0e80f71d6c..07aab04a17 100755 --- a/Scripts/capture-build-details.sh +++ b/Scripts/capture-build-details.sh @@ -26,6 +26,7 @@ info() { info_plist_path="${BUILT_PRODUCTS_DIR}/${CONTENTS_FOLDER_PATH}/BuildDetails.plist" xcode_build_version=${XCODE_PRODUCT_BUILD_VERSION:-$(xcodebuild -version | grep version | cut -d ' ' -f 3)} + while [[ $# -gt 0 ]] do case $1 in @@ -33,6 +34,10 @@ do info_plist_path="${2}" shift 2 ;; + -p|--provisioning-profile-path) + provisioning_profile_path="${2}" + shift 2 + ;; esac done @@ -42,7 +47,6 @@ fi if [ "${info_plist_path}" == "/" -o ! -e "${info_plist_path}" ]; then error "File does not exist: ${info_plist_path}" - #error "Must provide valid --info-plist-path, or have valid \${BUILT_PRODUCTS_DIR} and \${INFOPLIST_PATH} set." fi info "Gathering build details in ${PWD}" @@ -62,6 +66,26 @@ plutil -replace com-loopkit-Loop-srcroot -string "${PWD}" "${info_plist_path}" plutil -replace com-loopkit-Loop-build-date -string "$(date)" "${info_plist_path}" plutil -replace com-loopkit-Loop-xcode-version -string "${xcode_build_version}" "${info_plist_path}" +# Determine the provisioning profile path +if [ -z "${provisioning_profile_path}" ]; then + if [ -e "${HOME}/Library/MobileDevice/Provisioning Profiles/${EXPANDED_PROVISIONING_PROFILE}.mobileprovision" ]; then + provisioning_profile_path="${HOME}/Library/MobileDevice/Provisioning Profiles/${EXPANDED_PROVISIONING_PROFILE}.mobileprovision" + elif [ -e "${HOME}/Library/Developer/Xcode/UserData/Provisioning Profiles/${EXPANDED_PROVISIONING_PROFILE}.mobileprovision" ]; then + provisioning_profile_path="${HOME}/Library/Developer/Xcode/UserData/Provisioning Profiles/${EXPANDED_PROVISIONING_PROFILE}.mobileprovision" + else + warn "Provisioning profile not found in expected locations" + fi +fi + +if [ -e "${provisioning_profile_path}" ]; then + profile_expire_date=$(security cms -D -i "${provisioning_profile_path}" | plutil -p - | grep ExpirationDate | cut -b 23-) + # Convert to plutil format + profile_expire_date=$(date -j -f "%Y-%m-%d %H:%M:%S" "${profile_expire_date}" +"%Y-%m-%dT%H:%M:%SZ") + plutil -replace com-loopkit-Loop-profile-expiration -date "${profile_expire_date}" "${info_plist_path}" +else + warn "Invalid provisioning profile path ${provisioning_profile_path}" +fi + # determine if this is a workspace build # if so, fill out the git revision and branch if [ -e ../.git ] diff --git a/Version.xcconfig b/Version.xcconfig index 6fb2bbb9ba..b6ea5fff3d 100644 --- a/Version.xcconfig +++ b/Version.xcconfig @@ -7,7 +7,7 @@ // // Version [DEFAULT] -LOOP_MARKETING_VERSION = 3.4.3 +LOOP_MARKETING_VERSION = 3.4.4 CURRENT_PROJECT_VERSION = 57 // Optional override From e1c2382dc0f22cc4c9c75e8b8b863716546853e3 Mon Sep 17 00:00:00 2001 From: Moti Nisenson-Ken Date: Mon, 6 Jan 2025 21:18:54 +0200 Subject: [PATCH 11/12] Force reload from UserDefaults --- .../Views/SettingsView+algorithmExperimentsSection.swift | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/Loop/Views/SettingsView+algorithmExperimentsSection.swift b/Loop/Views/SettingsView+algorithmExperimentsSection.swift index 54bd2c71a0..7f66560c43 100644 --- a/Loop/Views/SettingsView+algorithmExperimentsSection.swift +++ b/Loop/Views/SettingsView+algorithmExperimentsSection.swift @@ -39,8 +39,8 @@ public struct ExperimentRow: View { } public struct ExperimentsSettingsView: View { - @State private var isGlucoseBasedApplicationFactorEnabled = UserDefaults.standard.glucoseBasedApplicationFactorEnabled - @State private var isIntegralRetrospectiveCorrectionEnabled = UserDefaults.standard.integralRetrospectiveCorrectionEnabled + @State private var isGlucoseBasedApplicationFactorEnabled = false + @State private var isIntegralRetrospectiveCorrectionEnabled = false var automaticDosingStrategy: AutomaticDosingStrategy public var body: some View { @@ -75,6 +75,11 @@ public struct ExperimentsSettingsView: View { .padding() } .navigationBarTitleDisplayMode(.inline) + .onAppear { + // force reloading of data from UserDefaults + isGlucoseBasedApplicationFactorEnabled = UserDefaults.standard.glucoseBasedApplicationFactorEnabled + isIntegralRetrospectiveCorrectionEnabled = UserDefaults.standard.integralRetrospectiveCorrectionEnabled + } } } From 4eb434dcdcdb71091758aa64f4169552a28381a9 Mon Sep 17 00:00:00 2001 From: Moti Nisenson-Ken Date: Tue, 7 Jan 2025 09:26:56 +0200 Subject: [PATCH 12/12] Use AppStorage instead --- .../GlucoseBasedApplicationFactorSelectionView.swift | 3 --- ...IntegralRetrospectiveCorrectionSelectionView.swift | 3 --- .../SettingsView+algorithmExperimentsSection.swift | 11 +++-------- 3 files changed, 3 insertions(+), 14 deletions(-) diff --git a/Loop/Views/GlucoseBasedApplicationFactorSelectionView.swift b/Loop/Views/GlucoseBasedApplicationFactorSelectionView.swift index 09a68d58c1..0d88e65dfa 100644 --- a/Loop/Views/GlucoseBasedApplicationFactorSelectionView.swift +++ b/Loop/Views/GlucoseBasedApplicationFactorSelectionView.swift @@ -44,9 +44,6 @@ public struct GlucoseBasedApplicationFactorSelectionView: View { } } .padding() - .onChange(of: isGlucoseBasedApplicationFactorEnabled) { newValue in - UserDefaults.standard.glucoseBasedApplicationFactorEnabled = newValue - } } .navigationBarTitleDisplayMode(.inline) } diff --git a/Loop/Views/IntegralRetrospectiveCorrectionSelectionView.swift b/Loop/Views/IntegralRetrospectiveCorrectionSelectionView.swift index 9af84adf4f..8556e4fed6 100644 --- a/Loop/Views/IntegralRetrospectiveCorrectionSelectionView.swift +++ b/Loop/Views/IntegralRetrospectiveCorrectionSelectionView.swift @@ -27,9 +27,6 @@ public struct IntegralRetrospectiveCorrectionSelectionView: View { Divider() Toggle(NSLocalizedString("Enable Integral Retrospective Correction", comment: "Title for Integral Retrospective Correction toggle"), isOn: $isIntegralRetrospectiveCorrectionEnabled) - .onChange(of: isIntegralRetrospectiveCorrectionEnabled) { newValue in - UserDefaults.standard.integralRetrospectiveCorrectionEnabled = newValue - } .padding(.top, 20) } .padding() diff --git a/Loop/Views/SettingsView+algorithmExperimentsSection.swift b/Loop/Views/SettingsView+algorithmExperimentsSection.swift index 7f66560c43..795fbdd860 100644 --- a/Loop/Views/SettingsView+algorithmExperimentsSection.swift +++ b/Loop/Views/SettingsView+algorithmExperimentsSection.swift @@ -39,8 +39,8 @@ public struct ExperimentRow: View { } public struct ExperimentsSettingsView: View { - @State private var isGlucoseBasedApplicationFactorEnabled = false - @State private var isIntegralRetrospectiveCorrectionEnabled = false + @AppStorage(UserDefaults.Key.GlucoseBasedApplicationFactorEnabled.rawValue) private var isGlucoseBasedApplicationFactorEnabled = false + @AppStorage(UserDefaults.Key.IntegralRetrospectiveCorrectionEnabled.rawValue) private var isIntegralRetrospectiveCorrectionEnabled = false var automaticDosingStrategy: AutomaticDosingStrategy public var body: some View { @@ -75,17 +75,12 @@ public struct ExperimentsSettingsView: View { .padding() } .navigationBarTitleDisplayMode(.inline) - .onAppear { - // force reloading of data from UserDefaults - isGlucoseBasedApplicationFactorEnabled = UserDefaults.standard.glucoseBasedApplicationFactorEnabled - isIntegralRetrospectiveCorrectionEnabled = UserDefaults.standard.integralRetrospectiveCorrectionEnabled - } } } extension UserDefaults { - private enum Key: String { + fileprivate enum Key: String { case GlucoseBasedApplicationFactorEnabled = "com.loopkit.algorithmExperiments.glucoseBasedApplicationFactorEnabled" case IntegralRetrospectiveCorrectionEnabled = "com.loopkit.algorithmExperiments.integralRetrospectiveCorrectionEnabled" }