Skip to content

Commit

Permalink
Merge pull request #483 from splitio/release_2.24.0
Browse files Browse the repository at this point in the history
Release 2.24.0
  • Loading branch information
javrudsky authored Dec 6, 2023
2 parents b3222fd + b603b29 commit 0725435
Show file tree
Hide file tree
Showing 17 changed files with 510 additions and 49 deletions.
39 changes: 39 additions & 0 deletions .github/workflows/test_ios_streaming_2.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
name: Build and Test iOS Streaming 1

on:
push:
branches:
- master
pull_request:
branches:
- master
- development

jobs:
build:
runs-on: [macos-latest]

steps:
- name: Select Xcode
uses: maxim-lobanov/setup-xcode@v1
with:
xcode-version: 13.2.1

- name: Checkout
uses: actions/checkout@v2
with:
fetch-depth: 0

- name: Test iOS Streaming integration
uses: sersoft-gmbh/xcodebuild-action@v1
with:
action: build test
build-settings: ONLY_ACTIVE_ARCH=NO TEST_AFTER_BUILD=YES
configuration: Debug
derived-data-path: "${{github.workspace}}/SplitApp"
destination: 'platform=iOS Simulator,OS=15.2,name=iPhone 12'
project: Split.xcodeproj
scheme: Split
sdk: 'iphonesimulator'
test-plan: 'SplitiOSStreaming_2'
use-xcpretty: true
3 changes: 3 additions & 0 deletions CHANGES.txt
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
2.24.0: (Dec 6, 2023)
- Added `prefix` configuration parameter, which allows to use a prefix when naming the SDK storage. Use this when using multiple `SplitFactory` instances with the same SDK key.

2.23.0: (Nov 1, 2023)
- Added support for Flag Sets on the SDK, which enables grouping feature flags and interacting with the group rather than individually (more details in our documentation):
- Added new variations of the get treatment methods to support evaluating flags in given flag set/s.
Expand Down
2 changes: 1 addition & 1 deletion Split.podspec
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
Pod::Spec.new do |s|
s.name = 'Split'
s.module_name = 'Split'
s.version = '2.23.0'
s.version = '2.24.0'
s.summary = 'iOS SDK for Split'
s.description = <<-DESC
This SDK is designed to work with Split, the platform for controlled rollouts, serving features to your users via the Split feature flag to manage your complete customer experience.
Expand Down
14 changes: 13 additions & 1 deletion Split.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
archiveVersion = 1;
classes = {
};
objectVersion = 54;
objectVersion = 52;
objects = {

/* Begin PBXBuildFile section */
Expand Down Expand Up @@ -825,6 +825,9 @@
95880CFC2AEFF193000498A0 /* Array+asSet.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9572BA7C2AC37B7400C10FC1 /* Array+asSet.swift */; };
95880CFD2AEFF1B2000498A0 /* Substring+asString.swift in Sources */ = {isa = PBXBuildFile; fileRef = 95737E0F2AD47A42007FD15C /* Substring+asString.swift */; };
95880D092AF201DC000498A0 /* SplitiOSStreaming_1.xctestplan in Resources */ = {isa = PBXBuildFile; fileRef = 95880D082AF201DC000498A0 /* SplitiOSStreaming_1.xctestplan */; };
958F98722B1124EC001F35B3 /* SplitBgSynchronizerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 958F98712B1124EC001F35B3 /* SplitBgSynchronizerTests.swift */; };
958F98742B1129D7001F35B3 /* KeyValueStorageMock.swift in Sources */ = {isa = PBXBuildFile; fileRef = 958F98732B1129D7001F35B3 /* KeyValueStorageMock.swift */; };
958F987B2B1669BC001F35B3 /* SplitiOSStreaming_2.xctestplan in Resources */ = {isa = PBXBuildFile; fileRef = 958F987A2B1669BC001F35B3 /* SplitiOSStreaming_2.xctestplan */; };
9595910526DFB1AB009E7944 /* DecompressionTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9595910426DFB1AB009E7944 /* DecompressionTest.swift */; };
9595910D26DFE149009E7944 /* lorem_ipsum_zlib.txt in Resources */ = {isa = PBXBuildFile; fileRef = 9595910C26DFE149009E7944 /* lorem_ipsum_zlib.txt */; };
9595911126DFFF87009E7944 /* CompressionUtil.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9595911026DFFF87009E7944 /* CompressionUtil.swift */; };
Expand Down Expand Up @@ -1829,6 +1832,9 @@
95825C012721F0F800A0CDAD /* UserKeyEncondingTest.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = UserKeyEncondingTest.swift; sourceTree = "<group>"; };
9583553F28464FD300014F0C /* SingleSyncTest.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SingleSyncTest.swift; sourceTree = "<group>"; };
95880D082AF201DC000498A0 /* SplitiOSStreaming_1.xctestplan */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = SplitiOSStreaming_1.xctestplan; sourceTree = "<group>"; };
958F98712B1124EC001F35B3 /* SplitBgSynchronizerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SplitBgSynchronizerTests.swift; sourceTree = "<group>"; };
958F98732B1129D7001F35B3 /* KeyValueStorageMock.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = KeyValueStorageMock.swift; sourceTree = "<group>"; };
958F987A2B1669BC001F35B3 /* SplitiOSStreaming_2.xctestplan */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = SplitiOSStreaming_2.xctestplan; sourceTree = "<group>"; };
9595910426DFB1AB009E7944 /* DecompressionTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DecompressionTest.swift; sourceTree = "<group>"; };
9595910C26DFE149009E7944 /* lorem_ipsum_zlib.txt */ = {isa = PBXFileReference; lastKnownFileType = text; path = lorem_ipsum_zlib.txt; sourceTree = "<group>"; };
9595911026DFFF87009E7944 /* CompressionUtil.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CompressionUtil.swift; sourceTree = "<group>"; };
Expand Down Expand Up @@ -2044,6 +2050,7 @@
950F72FD292E87A4008A0040 /* SplitiOSIntegration.xctestplan */,
956A7E1A2970B0F20080D53C /* SplitiOSStreaming.xctestplan */,
95880D082AF201DC000498A0 /* SplitiOSStreaming_1.xctestplan */,
958F987A2B1669BC001F35B3 /* SplitiOSStreaming_2.xctestplan */,
952FA1682A44C0FB00264AB5 /* SplitStreamingUT.xctestplan */,
95D83A962A561CB000ADA55E /* SplitPushManagerUT.xctestplan */,
95B0307B28D275020030EC8B /* SplitiOSUnit.xctestplan */,
Expand Down Expand Up @@ -2569,6 +2576,7 @@
95C1600E27D28FD4008562E3 /* PersistentAttributesStorageTests.swift */,
9557C1C92614F67700CD9B5C /* DbForTwoDifferentApiKeyTest.swift */,
9572BA842AC7611400C10FC1 /* FlagSetsCacheTests.swift */,
958F98712B1124EC001F35B3 /* SplitBgSynchronizerTests.swift */,
);
path = Storage;
sourceTree = "<group>";
Expand Down Expand Up @@ -2673,6 +2681,7 @@
594F5F5D253F641000A945B4 /* BackoffCounterTimerStub.swift */,
9573FB25273C50D400086DDE /* EvaluatorStub.swift */,
95E8193F2878922000D99093 /* LogPrinterStub.swift */,
958F98732B1129D7001F35B3 /* KeyValueStorageMock.swift */,
);
path = Fake;
sourceTree = "<group>";
Expand Down Expand Up @@ -3602,6 +3611,7 @@
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
files = (
958F987B2B1669BC001F35B3 /* SplitiOSStreaming_2.xctestplan in Resources */,
95880D092AF201DC000498A0 /* SplitiOSStreaming_1.xctestplan in Resources */,
599EA57622666B84006CBA89 /* LICENSE in Resources */,
3B6DEF5C20EA6AE50067435E /* .gitkeep in Resources */,
Expand Down Expand Up @@ -4092,6 +4102,7 @@
9572BA872AC76EA800C10FC1 /* FlagSetsCacheMock.swift in Sources */,
9546079625BF3945007FFD35 /* ImpressionsLoggerStub.swift in Sources */,
95F3EFF8258D36F800084AF8 /* HttpEventsRecorderTests.swift in Sources */,
958F98742B1129D7001F35B3 /* KeyValueStorageMock.swift in Sources */,
9519A92A27DA9AF000278AEC /* SynchronizerTest.swift in Sources */,
95623DA82757FDDE0006A8F1 /* TelemetryProducerStub.swift in Sources */,
95E819402878922000D99093 /* LogPrinterStub.swift in Sources */,
Expand Down Expand Up @@ -4165,6 +4176,7 @@
955428E02568155B00331356 /* PersistentImpressionsStorageTest.swift in Sources */,
5912D152219A022000BC698C /* CsvHelper.swift in Sources */,
9505682026825B53001D7B10 /* ImpressionsCounterTest.swift in Sources */,
958F98722B1124EC001F35B3 /* SplitBgSynchronizerTests.swift in Sources */,
59F4AABF2513A97B00A1C69A /* PeriodicSplitsSyncWorkerTest.swift in Sources */,
5982D934219F3D2E00230F44 /* MatcherEvalTests.swift in Sources */,
95C0577C294A247D007E4D6A /* UserConsentModeNoneTest.swift in Sources */,
Expand Down
3 changes: 3 additions & 0 deletions Split.xcodeproj/xcshareddata/xcschemes/Split.xcscheme
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,9 @@
<TestPlanReference
reference = "container:SplitiOSStreaming_1.xctestplan">
</TestPlanReference>
<TestPlanReference
reference = "container:SplitiOSStreaming_2.xctestplan">
</TestPlanReference>
</TestPlans>
<Testables>
<TestableReference
Expand Down
13 changes: 8 additions & 5 deletions Split/Api/DefaultSplitFactory.swift
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ public class DefaultSplitFactory: NSObject, SplitFactory {
// Creating Events Manager first speeds up init process
let eventsManager = components.getSplitEventsManagerCoordinator()

let databaseName = SplitDatabaseHelper.databaseName(apiKey: params.apiKey) ?? params.config.defaultDataFolder
let databaseName = SplitDatabaseHelper.databaseName(prefix: params.config.prefix, apiKey: params.apiKey) ?? params.config.defaultDataFolder

let storageContainer = try components.buildStorageContainer(databaseName: databaseName,
telemetryStorage: params.telemetryStorage,
Expand All @@ -84,7 +84,9 @@ public class DefaultSplitFactory: NSObject, SplitFactory {

userConsentManager = try components.buildUserConsentManager()

setupBgSync(config: params.config, apiKey: params.apiKey, userKey: params.key.matchingKey, storageContainer: storageContainer)
setupBgSync(config: params.config, apiKey: params.apiKey,
userKey: params.key.matchingKey,
storageContainer: storageContainer)

clientManager = DefaultClientManager(config: params.config,
key: params.key,
Expand Down Expand Up @@ -127,16 +129,17 @@ public class DefaultSplitFactory: NSObject, SplitFactory {
userConsentManager.set(newMode)
}

private func setupBgSync(config: SplitClientConfig,
private func setupBgSync(config: SplitClientConfig,
apiKey: String,
userKey: String,
storageContainer: SplitStorageContainer) {
#if os(iOS)
let dbKey = SplitDatabaseHelper.buildDbKey(prefix: config.prefix, sdkKey: apiKey)
if config.synchronizeInBackground {
SplitBgSynchronizer.shared.register(apiKey: apiKey, userKey: userKey)
SplitBgSynchronizer.shared.register(dbKey: dbKey, prefix: config.prefix, userKey: userKey)
storageContainer.splitsStorage.update(bySetsFilter: config.bySetsFilter())
} else {
SplitBgSynchronizer.shared.unregister(apiKey: apiKey, userKey: userKey)
SplitBgSynchronizer.shared.unregister(dbKey: dbKey, userKey: userKey)
}
#endif
}
Expand Down
5 changes: 5 additions & 0 deletions Split/Api/SplitClientConfig.swift
Original file line number Diff line number Diff line change
Expand Up @@ -314,6 +314,11 @@ public class SplitClientConfig: NSObject {
/// To get last definitions, the SDK have to be recreated
@objc public var syncEnabled = true

///
/// Prefix applied to the cache database name (Default: nil)
/// This is useful when using two factories with the same SDK Key to avoid having issues with the shared data
@objc public var prefix: String?

///
/// Update this variable to enable / disable telemetry for testing
///
Expand Down
41 changes: 24 additions & 17 deletions Split/Api/SplitDatabaseHelper.swift
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,8 @@ struct SplitDatabaseHelper {
static private let kDbExt = ["", "-shm", "-wal"]
static private let kExpirationPeriod = ServiceConstants.recordedDataExpirationPeriodInSeconds

static func currentEncryptionLevel(apiKey: String) -> SplitEncryptionLevel {
let rawValue = GlobalSecureStorage.shared.getInt(item: .dbEncryptionLevel(apiKey))
static func currentEncryptionLevel(dbKey: String) -> SplitEncryptionLevel {
let rawValue = GlobalSecureStorage.shared.getInt(item: .dbEncryptionLevel(dbKey))
?? SplitEncryptionLevel.none.rawValue
return SplitEncryptionLevel(rawValue: rawValue) ?? .none
}
Expand All @@ -23,23 +23,23 @@ struct SplitDatabaseHelper {
GlobalSecureStorage.shared.set(item: level.rawValue, for: .dbEncryptionLevel(apiKey))
}

static func currentEncryptionKey(for apiKey: String) -> Data? {
static func currentEncryptionKey(for dbKey: String) -> Data? {

// If there is a stored key, let's use it
if let encKey = GlobalSecureStorage.shared.getString(item: .dbEncryptionKey(apiKey)) {
if let encKey = GlobalSecureStorage.shared.getString(item: .dbEncryptionKey(dbKey)) {
return Base64Utils.decodeBase64NoPadding(encKey)
}

// If not, try to create a new one
if let newKey = DefaultKeyGenerator().generateKey(size: ServiceConstants.aes128KeyLength) {
setCurrentEncryptionKey(newKey, for: apiKey)
setCurrentEncryptionKey(newKey, for: dbKey)
return newKey
}

// If creation fails (even thought it shouldn't) let's use the api key
if let newKey = apiKey.dataBytes {
setCurrentEncryptionKey(newKey, for: apiKey)
return apiKey.dataBytes
if let newKey = dbKey.dataBytes {
setCurrentEncryptionKey(newKey, for: dbKey)
return dbKey.dataBytes
}

// If everything fails
Expand All @@ -57,7 +57,8 @@ struct SplitDatabaseHelper {
telemetryStorage: TelemetryStorage?,
testDatabase: SplitDatabase?) throws -> SplitStorageContainer {

let previousEncryptionLevel = currentEncryptionLevel(apiKey: apiKey)
let dbKey = buildDbKey(prefix: splitClientConfig.prefix, sdkKey: apiKey)
let previousEncryptionLevel = currentEncryptionLevel(dbKey: dbKey)
var splitDatabase = testDatabase
var dbHelper: CoreDataHelper?
if let testDb = testDatabase as? TestSplitDatabase {
Expand All @@ -74,17 +75,17 @@ struct SplitDatabaseHelper {
let encryptionLevel: SplitEncryptionLevel = splitClientConfig.encryptionEnabled ? .aes128Cbc : .none
var cipherKey: Data?
if encryptionLevel != .none {
cipherKey = currentEncryptionKey(for: apiKey)
cipherKey = currentEncryptionKey(for: dbKey)
}

if previousEncryptionLevel != encryptionLevel,
let dbCipherKey = cipherKey ?? currentEncryptionKey(for: apiKey) {
let dbCipherKey = cipherKey ?? currentEncryptionKey(for: dbKey) {
let dbCipher = try DbCipher(cipherKey: dbCipherKey,
from: previousEncryptionLevel,
to: encryptionLevel,
coreDataHelper: dbHelper)
dbCipher.apply()
setCurrentEncryptionLevel(encryptionLevel, for: apiKey)
setCurrentEncryptionLevel(encryptionLevel, for: dbKey)
}

if splitDatabase == nil {
Expand All @@ -99,7 +100,7 @@ struct SplitDatabaseHelper {
throw GenericError.couldNotCreateCache
}

let flagSetsCache: FlagSetsCache =
let flagSetsCache: FlagSetsCache =
DefaultFlagSetsCache(setsInFilter: splitClientConfig.bySetsFilter()?.values.asSet())
let persistentSplitsStorage = DefaultPersistentSplitsStorage(database: splitDatabase)
let splitsStorage = openSplitsStorage(database: splitDatabase, flagSetsCache: flagSetsCache)
Expand Down Expand Up @@ -151,8 +152,10 @@ struct SplitDatabaseHelper {
return DefaultPersistentSplitsStorage(database: database)
}

static func openSplitsStorage(database: SplitDatabase, flagSetsCache: FlagSetsCache) -> SplitsStorage {
return DefaultSplitsStorage(persistentSplitsStorage: openPersistentSplitsStorage(database: database), flagSetsCache: flagSetsCache)
static func openSplitsStorage(database: SplitDatabase,
flagSetsCache: FlagSetsCache) -> SplitsStorage {
return DefaultSplitsStorage(persistentSplitsStorage: openPersistentSplitsStorage(database: database),
flagSetsCache: flagSetsCache)
}

static func openPersistentMySegmentsStorage(database: SplitDatabase) -> PersistentMySegmentsStorage {
Expand Down Expand Up @@ -199,11 +202,11 @@ struct SplitDatabaseHelper {
return MainEventsStorage(persistentStorage: persistentStorage)
}

static func databaseName(apiKey: String) -> String? {
static func databaseName(prefix: String?, apiKey: String) -> String? {
if apiKey.count < kDbMagicCharsCount * 2 {
return nil
}
return "\(apiKey.prefix(kDbMagicCharsCount))\(apiKey.suffix(kDbMagicCharsCount))"
return "\(prefix ?? "")\(apiKey.prefix(kDbMagicCharsCount))\(apiKey.suffix(kDbMagicCharsCount))"
}

static func sanitizeForFolderName(_ string: String) -> String {
Expand Down Expand Up @@ -232,4 +235,8 @@ struct SplitDatabaseHelper {

return DefaultCipher(cipherKey: cipherKey)
}

static func buildDbKey(prefix: String?, sdkKey: String) -> String {
return "\(prefix ?? "")\(sdkKey)"
}
}
2 changes: 1 addition & 1 deletion Split/Common/Utils/Version.swift
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import Foundation

class Version {
private static let kSdkPlatform: String = "ios"
private static let kVersion = "2.23.0"
private static let kVersion = "2.24.0"

static var semantic: String {
return kVersion
Expand Down
2 changes: 1 addition & 1 deletion Split/FetcherEngine/Refresh/PeriodicSyncWorker.swift
Original file line number Diff line number Diff line change
Expand Up @@ -171,7 +171,7 @@ class PeriodicSplitsSyncWorker: BasePeriodicSyncWorker {
if !isSdkReadyFired() {
return
}
let storedChangeNumber = splitsStorage.changeNumber

guard let result = try? syncHelper.sync(since: splitsStorage.changeNumber) else {
return
}
Expand Down
Loading

0 comments on commit 0725435

Please sign in to comment.