From 8177654e7edc8e9d027c20d3256a6f94b51ed184 Mon Sep 17 00:00:00 2001 From: Steve Benedick Date: Mon, 9 Oct 2023 12:44:42 -0600 Subject: [PATCH 1/7] -fix threading issue when using raw request apis --- AEPTarget/Sources/Target.swift | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/AEPTarget/Sources/Target.swift b/AEPTarget/Sources/Target.swift index f5a03c0..14a568d 100644 --- a/AEPTarget/Sources/Target.swift +++ b/AEPTarget/Sources/Target.swift @@ -916,8 +916,9 @@ public class Target: NSObject, Extension { Log.debug(label: Target.LOG_TAG, "handleRawRequest - Target response is received with code: \(connection.responseCode ?? -1) and data: \(connection.responseString ?? "").") self.targetState.updateSessionTimestamp() self.processTargetRawResponse(event: event, isContentRequest: isContentRequest, connection: connection) - } - startEvents() + + self.startEvents() + } } /// Processes the network response after the Target delivery API call for raw request. From 2777175c3fef62f9f6231d3ba4d9ca8a57c282dc Mon Sep 17 00:00:00 2001 From: Steve Benedick Date: Tue, 10 Oct 2023 14:01:51 -0600 Subject: [PATCH 2/7] -adding thread safe access to our containers in TargetState --- .../xcschemes/AEPTargetDemoApp.xcscheme | 8 ++++++ AEPTarget/Sources/Target.swift | 4 +-- AEPTarget/Sources/TargetState.swift | 28 ++++++++++++++++--- Podfile.lock | 28 +++++++++---------- 4 files changed, 48 insertions(+), 20 deletions(-) diff --git a/AEPTarget.xcodeproj/xcshareddata/xcschemes/AEPTargetDemoApp.xcscheme b/AEPTarget.xcodeproj/xcshareddata/xcschemes/AEPTargetDemoApp.xcscheme index cc228d1..d476db1 100644 --- a/AEPTarget.xcodeproj/xcshareddata/xcschemes/AEPTargetDemoApp.xcscheme +++ b/AEPTarget.xcodeproj/xcshareddata/xcschemes/AEPTargetDemoApp.xcscheme @@ -44,6 +44,7 @@ buildConfiguration = "Debug" selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB" selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB" + enableAddressSanitizer = "YES" launchStyle = "0" useCustomWorkingDirectory = "NO" ignoresPersistentStateOnLaunch = "NO" @@ -60,6 +61,13 @@ ReferencedContainer = "container:AEPTarget.xcodeproj"> + + + + = 4.0.0) - AEPServices (>= 4.0.0) - - AEPCore (4.0.0): + - AEPCore (4.1.0): - AEPRulesEngine (>= 4.0.0) - - AEPServices (>= 4.0.0) - - AEPIdentity (4.0.0): - - AEPCore (>= 4.0.0) - - AEPLifecycle (4.0.0): - - AEPCore (>= 4.0.0) + - AEPServices (>= 4.1.0) + - AEPIdentity (4.1.0): + - AEPCore (>= 4.1.0) + - AEPLifecycle (4.1.0): + - AEPCore (>= 4.1.0) - AEPRulesEngine (4.0.0) - - AEPServices (4.0.0) - - AEPSignal (4.0.0): - - AEPCore (>= 4.0.0) + - AEPServices (4.1.0) + - AEPSignal (4.1.0): + - AEPCore (>= 4.1.0) - SwiftLint (0.52.0) - SwiftyJSON (5.0.1) @@ -45,12 +45,12 @@ SPEC REPOS: SPEC CHECKSUMS: AEPAnalytics: a510eb9653fac7f913965ad4291c8d51f74ffdcd AEPAssurance: 4fa3138ddd7308c1f9923570f4d2b0b8526a916f - AEPCore: dd7cd69696c768c610e6adc0307032985a381c7e - AEPIdentity: 45ee1c3717e08ff3ca60930caf4a869d60d7bf08 - AEPLifecycle: 59be1b5381d8ec4939ece43516ea7d2de4aaba65 + AEPCore: 20fb832a7467b25ca4aca186c0a5a1e3c0c6abc3 + AEPIdentity: 88671626d6043a488896ee7d71483a8bcec80739 + AEPLifecycle: 97693ea99ef9deb818b726a4e429ef96abb1353e AEPRulesEngine: 458450a34922823286ead045a0c2bd8c27e224c6 - AEPServices: ca493988df250d84fda050124ff7549bcc43c65f - AEPSignal: b2b332adf4d8a9af6a1b57f5dd8c2e1ea6d5c112 + AEPServices: d94555679870311d2f1391c5d7a5de590fd1f3c0 + AEPSignal: 9152e68bae462276f57ac63666e879cc7ff7c302 SwiftLint: 13280e21cdda6786ad908dc6e416afe5acd1fcb7 SwiftyJSON: 2f33a42c6fbc52764d96f13368585094bfd8aa5e From 68494d27be85a91cf20bc52087cc1c23ebaa6ed2 Mon Sep 17 00:00:00 2001 From: Swarna Saraf Date: Wed, 11 Oct 2023 11:19:58 -0700 Subject: [PATCH 3/7] Added support for X-EXC-SDK & X-EXC-SDK-Version headers (#148) * Added support for X-EXC-SDK & X-EXC-SDK-Version headers * Incorporated feedback --- AEPTarget.xcodeproj/project.pbxproj | 4 +- AEPTarget/Sources/Target.swift | 24 ++++++++-- AEPTarget/Sources/TargetConstants.swift | 14 +++++- .../TargetIntegrationTests.swift | 48 +++++++++++++++++++ .../TestHelpers/TargetTestConstants.swift | 1 + 5 files changed, 85 insertions(+), 6 deletions(-) diff --git a/AEPTarget.xcodeproj/project.pbxproj b/AEPTarget.xcodeproj/project.pbxproj index 8a5babd..613cc0e 100644 --- a/AEPTarget.xcodeproj/project.pbxproj +++ b/AEPTarget.xcodeproj/project.pbxproj @@ -1174,7 +1174,7 @@ "@executable_path/Frameworks", "@loader_path/Frameworks", ); - MARKETING_VERSION = 4.0.1; + MARKETING_VERSION = 4.0.2; PRODUCT_BUNDLE_IDENTIFIER = com.adobe.aep.target; PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)"; PROVISIONING_PROFILE_SPECIFIER = ""; @@ -1205,7 +1205,7 @@ "@executable_path/Frameworks", "@loader_path/Frameworks", ); - MARKETING_VERSION = 4.0.1; + MARKETING_VERSION = 4.0.2; PRODUCT_BUNDLE_IDENTIFIER = com.adobe.aep.target; PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)"; PROVISIONING_PROFILE_SPECIFIER = ""; diff --git a/AEPTarget/Sources/Target.swift b/AEPTarget/Sources/Target.swift index f5a03c0..73ef27d 100644 --- a/AEPTarget/Sources/Target.swift +++ b/AEPTarget/Sources/Target.swift @@ -569,6 +569,17 @@ public class Target: NSObject, Extension { return String(format: TargetConstants.DELIVERY_API_URL_BASE, String(format: TargetConstants.API_URL_HOST_BASE, clientCode), clientCode, targetState.sessionId) } + private func getSdkVersion(eventHubData: [String: Any]?) -> String { + guard let eventHubData = eventHubData else { + return "" + } + + let coreVersion = eventHubData[TargetConstants.EventHub.SharedState.Keys.VERSION] as? String ?? "unknown" + + // sdkVersion is a combination of Mobile Core+Target SDK version + return "\(coreVersion)+\(TargetConstants.EXTENSION_VERSION)" + } + /// Prepares for the target requests and checks whether a target request can be sent. /// - returns: error indicating why the request can't be sent, nil otherwise private func prepareForTargetRequest() -> String? { @@ -667,8 +678,6 @@ public class Target: NSObject, Extension { return "Failed to generate request parameter(JSON) for target delivery API call" } - let headers = [TargetConstants.HEADER_CONTENT_TYPE: TargetConstants.HEADER_CONTENT_TYPE_JSON] - guard let clientCode = targetState.clientCode else { return "Missing client code" } @@ -678,6 +687,11 @@ public class Target: NSObject, Extension { } let timeout = targetState.networkTimeout + let headers = [ + TargetConstants.HEADER_CONTENT_TYPE: TargetConstants.HEADER_CONTENT_TYPE_JSON, + TargetConstants.HEADER_X_EXC_SDK: TargetConstants.HEADER_X_EXC_SDK_TARGET_MOBILE, + TargetConstants.HEADER_X_EXC_SDK_VERSION: getSdkVersion(eventHubData: getSharedState(extensionName: TargetConstants.EventHub.EXTENSION_NAME, event: event)?.value), + ] // https://developers.adobetarget.com/api/delivery-api/#tag/Delivery-API let request = NetworkRequest(url: url, httpMethod: .post, connectPayload: requestJson, httpHeaders: headers, connectTimeout: timeout, readTimeout: timeout) @@ -904,7 +918,11 @@ public class Target: NSObject, Extension { } let timeout = targetState.networkTimeout - let headers = [TargetConstants.HEADER_CONTENT_TYPE: TargetConstants.HEADER_CONTENT_TYPE_JSON] + let headers = [ + TargetConstants.HEADER_CONTENT_TYPE: TargetConstants.HEADER_CONTENT_TYPE_JSON, + TargetConstants.HEADER_X_EXC_SDK: TargetConstants.HEADER_X_EXC_SDK_TARGET_MOBILE, + TargetConstants.HEADER_X_EXC_SDK_VERSION: getSdkVersion(eventHubData: getSharedState(extensionName: TargetConstants.EventHub.EXTENSION_NAME, event: event)?.value), + ] // https://developers.adobetarget.com/api/delivery-api/#tag/Delivery-API let request = NetworkRequest(url: url, httpMethod: .post, connectPayload: requestJson, httpHeaders: headers, connectTimeout: timeout, readTimeout: timeout) diff --git a/AEPTarget/Sources/TargetConstants.swift b/AEPTarget/Sources/TargetConstants.swift index fa70e3a..c62284c 100644 --- a/AEPTarget/Sources/TargetConstants.swift +++ b/AEPTarget/Sources/TargetConstants.swift @@ -15,14 +15,17 @@ import Foundation enum TargetConstants { static let EXTENSION_NAME = "com.adobe.module.target" static let FRIENDLY_NAME = "Target" - static let EXTENSION_VERSION = "4.0.1" + static let EXTENSION_VERSION = "4.0.2" static let DATASTORE_NAME = EXTENSION_NAME static let DEFAULT_SESSION_TIMEOUT: Int = 30 * 60 // 30 mins static let DELIVERY_API_URL_BASE = "https://%@/rest/v1/delivery/?client=%@&sessionId=%@" static let EDGE_HOST_BASE = "mboxedge%@" static let API_URL_HOST_BASE = "%@.tt.omtrdc.net" static let HEADER_CONTENT_TYPE = "Content-Type" + static let HEADER_X_EXC_SDK = "X-EXC-SDK" + static let HEADER_X_EXC_SDK_VERSION = "X-EXC-SDK-Version" static let HEADER_CONTENT_TYPE_JSON = "application/json" + static let HEADER_X_EXC_SDK_TARGET_MOBILE = "AdobeTargetMobile" static let A4T_ACTION_NAME = "AnalyticsForTarget" static let MAP_TO_CONTEXT_DATA_KEYS: [String: String] = [ @@ -234,6 +237,15 @@ enum TargetConstants { } } + enum EventHub { + static let EXTENSION_NAME = "com.adobe.module.eventhub" + enum SharedState { + enum Keys { + static let VERSION = "version" + } + } + } + enum Identity { static let EXTENSION_NAME = "com.adobe.module.identity" enum SharedState { diff --git a/AEPTarget/Tests/IntegrationTests/TargetIntegrationTests.swift b/AEPTarget/Tests/IntegrationTests/TargetIntegrationTests.swift index 0658fa9..89551ba 100644 --- a/AEPTarget/Tests/IntegrationTests/TargetIntegrationTests.swift +++ b/AEPTarget/Tests/IntegrationTests/TargetIntegrationTests.swift @@ -185,6 +185,12 @@ class TargetIntegrationTests: XCTestCase { mockNetworkService.mock { request in Log.debug(label: self.T_LOG_TAG, "request url is: \(request.url.absoluteString)") if request.url.absoluteString.contains("https://amsdk.tt.omtrdc.net/rest/v1/delivery/?client=acopprod3&sessionId=") { + // verify request headers + let coreVersion = self.getLastValidSharedState("com.adobe.module.eventhub")?.value?["version"] ?? "unknown" + let requestHeaders: [String: String] = request.httpHeaders + XCTAssertEqual("AdobeTargetMobile", requestHeaders["X-EXC-SDK"]) + XCTAssertEqual("\(coreVersion)+\(TargetTestConstants.EXTENSION_VERSION)", requestHeaders["X-EXC-SDK-Version"]) + if let payloadDictionary = try? JSONSerialization.jsonObject(with: request.connectPayload, options: .allowFragments) as? [String: Any] { Log.debug(label: self.T_LOG_TAG, "request payload is: \n \(self.prettify(payloadDictionary))") @@ -407,6 +413,12 @@ class TargetIntegrationTests: XCTestCase { ServiceProvider.shared.networkService = mockNetworkService mockNetworkService.mock { request in if request.url.absoluteString.contains("https://amsdk.tt.omtrdc.net/rest/v1/delivery/?client=acopprod3&sessionId=") { + // verify request headers + let coreVersion = self.getLastValidSharedState("com.adobe.module.eventhub")?.value?["version"] ?? "unknown" + let requestHeaders: [String: String] = request.httpHeaders + XCTAssertEqual("AdobeTargetMobile", requestHeaders["X-EXC-SDK"]) + XCTAssertEqual("\(coreVersion)+\(TargetTestConstants.EXTENSION_VERSION)", requestHeaders["X-EXC-SDK-Version"]) + return (data: responseString.data(using: .utf8), response: validResponse, error: nil) } return nil @@ -1093,6 +1105,12 @@ class TargetIntegrationTests: XCTestCase { ServiceProvider.shared.networkService = mockNetworkService mockNetworkService.mock { request in if request.url.absoluteString.contains("https://amsdk.tt.omtrdc.net/rest/v1/delivery/?client=acopprod3&sessionId=") { + // verify request headers + let coreVersion = self.getLastValidSharedState("com.adobe.module.eventhub")?.value?["version"] ?? "unknown" + let requestHeaders: [String: String] = request.httpHeaders + XCTAssertEqual("AdobeTargetMobile", requestHeaders["X-EXC-SDK"]) + XCTAssertEqual("\(coreVersion)+\(TargetTestConstants.EXTENSION_VERSION)", requestHeaders["X-EXC-SDK-Version"]) + let connectPayloadString = String(decoding: request.connectPayload, as: UTF8.self) if connectPayloadString.contains("ADCKKBC") { targetRequestExpectation.fulfill() @@ -1219,6 +1237,12 @@ class TargetIntegrationTests: XCTestCase { ServiceProvider.shared.networkService = mockNetworkService mockNetworkService.mock { request in if request.url.absoluteString.contains("https://amsdk.tt.omtrdc.net/rest/v1/delivery/?client=acopprod3&sessionId=") { + // verify request headers + let coreVersion = self.getLastValidSharedState("com.adobe.module.eventhub")?.value?["version"] ?? "unknown" + let requestHeaders: [String: String] = request.httpHeaders + XCTAssertEqual("AdobeTargetMobile", requestHeaders["X-EXC-SDK"]) + XCTAssertEqual("\(coreVersion)+\(TargetTestConstants.EXTENSION_VERSION)", requestHeaders["X-EXC-SDK-Version"]) + let connectPayloadString = String(decoding: request.connectPayload, as: UTF8.self) if connectPayloadString.contains("ADCKKBC") { targetRequestExpectation.fulfill() @@ -1662,6 +1686,12 @@ class TargetIntegrationTests: XCTestCase { ServiceProvider.shared.networkService = mockNetworkService mockNetworkService.mock { request in if request.url.absoluteString.contains("https://acopprod3.tt.omtrdc.net/rest/v1/delivery/?client=acopprod3&sessionId=") { + // verify request headers + let coreVersion = self.getLastValidSharedState("com.adobe.module.eventhub")?.value?["version"] ?? "unknown" + let requestHeaders: [String: String] = request.httpHeaders + XCTAssertEqual("AdobeTargetMobile", requestHeaders["X-EXC-SDK"]) + XCTAssertEqual("\(coreVersion)+\(TargetTestConstants.EXTENSION_VERSION)", requestHeaders["X-EXC-SDK-Version"]) + return (data: responseString.data(using: .utf8), response: validResponse, error: nil) } return nil @@ -1802,6 +1832,12 @@ class TargetIntegrationTests: XCTestCase { ServiceProvider.shared.networkService = mockNetworkService mockNetworkService.mock { request in if request.url.absoluteString.contains("https://acopprod3.tt.omtrdc.net/rest/v1/delivery/?client=acopprod3&sessionId=") { + // verify request headers + let coreVersion = self.getLastValidSharedState("com.adobe.module.eventhub")?.value?["version"] ?? "unknown" + let requestHeaders: [String: String] = request.httpHeaders + XCTAssertEqual("AdobeTargetMobile", requestHeaders["X-EXC-SDK"]) + XCTAssertEqual("\(coreVersion)+\(TargetTestConstants.EXTENSION_VERSION)", requestHeaders["X-EXC-SDK-Version"]) + return (data: responseString.data(using: .utf8), response: validResponse, error: nil) } return nil @@ -1954,6 +1990,12 @@ class TargetIntegrationTests: XCTestCase { ServiceProvider.shared.networkService = mockNetworkService mockNetworkService.mock { request in if request.url.absoluteString.contains("https://acopprod3.tt.omtrdc.net/rest/v1/delivery/?client=acopprod3&sessionId=") { + // verify request headers + let coreVersion = self.getLastValidSharedState("com.adobe.module.eventhub")?.value?["version"] ?? "unknown" + let requestHeaders: [String: String] = request.httpHeaders + XCTAssertEqual("AdobeTargetMobile", requestHeaders["X-EXC-SDK"]) + XCTAssertEqual("\(coreVersion)+\(TargetTestConstants.EXTENSION_VERSION)", requestHeaders["X-EXC-SDK-Version"]) + return (data: responseString.data(using: .utf8), response: validResponse, error: nil) } @@ -2096,6 +2138,12 @@ class TargetIntegrationTests: XCTestCase { } if request.url.absoluteString.contains("https://mboxedge35.tt.omtrdc.net/rest/v1/delivery/?client=acopprod3&sessionId=") { + // verify request headers + let coreVersion = self.getLastValidSharedState("com.adobe.module.eventhub")?.value?["version"] ?? "unknown" + let requestHeaders: [String: String] = request.httpHeaders + XCTAssertEqual("AdobeTargetMobile", requestHeaders["X-EXC-SDK"]) + XCTAssertEqual("\(coreVersion)+\(TargetTestConstants.EXTENSION_VERSION)", requestHeaders["X-EXC-SDK-Version"]) + targetNotificationExpectation.fulfill() return nil } diff --git a/AEPTarget/Tests/TestHelpers/TargetTestConstants.swift b/AEPTarget/Tests/TestHelpers/TargetTestConstants.swift index 2493a71..3d8d7b8 100644 --- a/AEPTarget/Tests/TestHelpers/TargetTestConstants.swift +++ b/AEPTarget/Tests/TestHelpers/TargetTestConstants.swift @@ -11,6 +11,7 @@ */ enum TargetTestConstants { + static let EXTENSION_VERSION = "4.0.2" // preview parameters static let PREVIEW_MESSAGE_ID = "target-preview-message-id" static let PREVIEW_PARAMETERS = "at_preview_params" From 4893311c7087bab345c01837c905526095620cc3 Mon Sep 17 00:00:00 2001 From: Swarna Saraf Date: Wed, 11 Oct 2023 13:57:01 -0700 Subject: [PATCH 4/7] X-EXC-SDK support for Target requests (#150) * More fixes for X-EXC-SDK header * Feedback fixes --- AEPTarget/Sources/Target.swift | 28 ++++++++++++++++--- AEPTarget/Sources/TargetConstants.swift | 4 ++- .../TargetIntegrationTests.swift | 16 +++++------ 3 files changed, 35 insertions(+), 13 deletions(-) diff --git a/AEPTarget/Sources/Target.swift b/AEPTarget/Sources/Target.swift index e0009f8..fe4c015 100644 --- a/AEPTarget/Sources/Target.swift +++ b/AEPTarget/Sources/Target.swift @@ -580,6 +580,24 @@ public class Target: NSObject, Extension { return "\(coreVersion)+\(TargetConstants.EXTENSION_VERSION)" } + private func getSdkInfo(eventHubData: [String: Any]?) -> String { + let sdkBase = TargetConstants.HEADER_X_EXC_SDK_BASE_TARGET_MOBILE_IOS + + guard let eventHubData = eventHubData else { + return sdkBase + } + + guard let wrapper = eventHubData[TargetConstants.EventHub.SharedState.Keys.WRAPPER] as? [String: Any], + let wrapperFriendlyName = wrapper[TargetConstants.EventHub.SharedState.Keys.WRAPPER_FRIENDLY_NAME] as? String, + wrapperFriendlyName != "None" + else { + return sdkBase + } + + // sdkInfo is of the format AdobeTargetMobile-iOS- + return "\(sdkBase)-\(wrapperFriendlyName)" + } + /// Prepares for the target requests and checks whether a target request can be sent. /// - returns: error indicating why the request can't be sent, nil otherwise private func prepareForTargetRequest() -> String? { @@ -686,11 +704,12 @@ public class Target: NSObject, Extension { return "Failed to generate the url for target API call" } + let eventHubSharedState = getSharedState(extensionName: TargetConstants.EventHub.EXTENSION_NAME, event: event)?.value let timeout = targetState.networkTimeout let headers = [ TargetConstants.HEADER_CONTENT_TYPE: TargetConstants.HEADER_CONTENT_TYPE_JSON, - TargetConstants.HEADER_X_EXC_SDK: TargetConstants.HEADER_X_EXC_SDK_TARGET_MOBILE, - TargetConstants.HEADER_X_EXC_SDK_VERSION: getSdkVersion(eventHubData: getSharedState(extensionName: TargetConstants.EventHub.EXTENSION_NAME, event: event)?.value), + TargetConstants.HEADER_X_EXC_SDK: getSdkInfo(eventHubData: eventHubSharedState), + TargetConstants.HEADER_X_EXC_SDK_VERSION: getSdkVersion(eventHubData: eventHubSharedState), ] // https://developers.adobetarget.com/api/delivery-api/#tag/Delivery-API @@ -917,11 +936,12 @@ public class Target: NSObject, Extension { return } + let eventHubSharedState = getSharedState(extensionName: TargetConstants.EventHub.EXTENSION_NAME, event: event)?.value let timeout = targetState.networkTimeout let headers = [ TargetConstants.HEADER_CONTENT_TYPE: TargetConstants.HEADER_CONTENT_TYPE_JSON, - TargetConstants.HEADER_X_EXC_SDK: TargetConstants.HEADER_X_EXC_SDK_TARGET_MOBILE, - TargetConstants.HEADER_X_EXC_SDK_VERSION: getSdkVersion(eventHubData: getSharedState(extensionName: TargetConstants.EventHub.EXTENSION_NAME, event: event)?.value), + TargetConstants.HEADER_X_EXC_SDK: getSdkInfo(eventHubData: eventHubSharedState), + TargetConstants.HEADER_X_EXC_SDK_VERSION: getSdkVersion(eventHubData: eventHubSharedState), ] // https://developers.adobetarget.com/api/delivery-api/#tag/Delivery-API diff --git a/AEPTarget/Sources/TargetConstants.swift b/AEPTarget/Sources/TargetConstants.swift index c62284c..ae41e3e 100644 --- a/AEPTarget/Sources/TargetConstants.swift +++ b/AEPTarget/Sources/TargetConstants.swift @@ -25,7 +25,7 @@ enum TargetConstants { static let HEADER_X_EXC_SDK = "X-EXC-SDK" static let HEADER_X_EXC_SDK_VERSION = "X-EXC-SDK-Version" static let HEADER_CONTENT_TYPE_JSON = "application/json" - static let HEADER_X_EXC_SDK_TARGET_MOBILE = "AdobeTargetMobile" + static let HEADER_X_EXC_SDK_BASE_TARGET_MOBILE_IOS = "AdobeTargetMobile-iOS" static let A4T_ACTION_NAME = "AnalyticsForTarget" static let MAP_TO_CONTEXT_DATA_KEYS: [String: String] = [ @@ -242,6 +242,8 @@ enum TargetConstants { enum SharedState { enum Keys { static let VERSION = "version" + static let WRAPPER = "wrapper" + static let WRAPPER_FRIENDLY_NAME = "friendlyName" } } } diff --git a/AEPTarget/Tests/IntegrationTests/TargetIntegrationTests.swift b/AEPTarget/Tests/IntegrationTests/TargetIntegrationTests.swift index 89551ba..9b1f240 100644 --- a/AEPTarget/Tests/IntegrationTests/TargetIntegrationTests.swift +++ b/AEPTarget/Tests/IntegrationTests/TargetIntegrationTests.swift @@ -188,7 +188,7 @@ class TargetIntegrationTests: XCTestCase { // verify request headers let coreVersion = self.getLastValidSharedState("com.adobe.module.eventhub")?.value?["version"] ?? "unknown" let requestHeaders: [String: String] = request.httpHeaders - XCTAssertEqual("AdobeTargetMobile", requestHeaders["X-EXC-SDK"]) + XCTAssertEqual("AdobeTargetMobile-iOS", requestHeaders["X-EXC-SDK"]) XCTAssertEqual("\(coreVersion)+\(TargetTestConstants.EXTENSION_VERSION)", requestHeaders["X-EXC-SDK-Version"]) if let payloadDictionary = try? JSONSerialization.jsonObject(with: request.connectPayload, options: .allowFragments) as? [String: Any] @@ -416,7 +416,7 @@ class TargetIntegrationTests: XCTestCase { // verify request headers let coreVersion = self.getLastValidSharedState("com.adobe.module.eventhub")?.value?["version"] ?? "unknown" let requestHeaders: [String: String] = request.httpHeaders - XCTAssertEqual("AdobeTargetMobile", requestHeaders["X-EXC-SDK"]) + XCTAssertEqual("AdobeTargetMobile-iOS", requestHeaders["X-EXC-SDK"]) XCTAssertEqual("\(coreVersion)+\(TargetTestConstants.EXTENSION_VERSION)", requestHeaders["X-EXC-SDK-Version"]) return (data: responseString.data(using: .utf8), response: validResponse, error: nil) @@ -1108,7 +1108,7 @@ class TargetIntegrationTests: XCTestCase { // verify request headers let coreVersion = self.getLastValidSharedState("com.adobe.module.eventhub")?.value?["version"] ?? "unknown" let requestHeaders: [String: String] = request.httpHeaders - XCTAssertEqual("AdobeTargetMobile", requestHeaders["X-EXC-SDK"]) + XCTAssertEqual("AdobeTargetMobile-iOS", requestHeaders["X-EXC-SDK"]) XCTAssertEqual("\(coreVersion)+\(TargetTestConstants.EXTENSION_VERSION)", requestHeaders["X-EXC-SDK-Version"]) let connectPayloadString = String(decoding: request.connectPayload, as: UTF8.self) @@ -1240,7 +1240,7 @@ class TargetIntegrationTests: XCTestCase { // verify request headers let coreVersion = self.getLastValidSharedState("com.adobe.module.eventhub")?.value?["version"] ?? "unknown" let requestHeaders: [String: String] = request.httpHeaders - XCTAssertEqual("AdobeTargetMobile", requestHeaders["X-EXC-SDK"]) + XCTAssertEqual("AdobeTargetMobile-iOS", requestHeaders["X-EXC-SDK"]) XCTAssertEqual("\(coreVersion)+\(TargetTestConstants.EXTENSION_VERSION)", requestHeaders["X-EXC-SDK-Version"]) let connectPayloadString = String(decoding: request.connectPayload, as: UTF8.self) @@ -1689,7 +1689,7 @@ class TargetIntegrationTests: XCTestCase { // verify request headers let coreVersion = self.getLastValidSharedState("com.adobe.module.eventhub")?.value?["version"] ?? "unknown" let requestHeaders: [String: String] = request.httpHeaders - XCTAssertEqual("AdobeTargetMobile", requestHeaders["X-EXC-SDK"]) + XCTAssertEqual("AdobeTargetMobile-iOS", requestHeaders["X-EXC-SDK"]) XCTAssertEqual("\(coreVersion)+\(TargetTestConstants.EXTENSION_VERSION)", requestHeaders["X-EXC-SDK-Version"]) return (data: responseString.data(using: .utf8), response: validResponse, error: nil) @@ -1835,7 +1835,7 @@ class TargetIntegrationTests: XCTestCase { // verify request headers let coreVersion = self.getLastValidSharedState("com.adobe.module.eventhub")?.value?["version"] ?? "unknown" let requestHeaders: [String: String] = request.httpHeaders - XCTAssertEqual("AdobeTargetMobile", requestHeaders["X-EXC-SDK"]) + XCTAssertEqual("AdobeTargetMobile-iOS", requestHeaders["X-EXC-SDK"]) XCTAssertEqual("\(coreVersion)+\(TargetTestConstants.EXTENSION_VERSION)", requestHeaders["X-EXC-SDK-Version"]) return (data: responseString.data(using: .utf8), response: validResponse, error: nil) @@ -1993,7 +1993,7 @@ class TargetIntegrationTests: XCTestCase { // verify request headers let coreVersion = self.getLastValidSharedState("com.adobe.module.eventhub")?.value?["version"] ?? "unknown" let requestHeaders: [String: String] = request.httpHeaders - XCTAssertEqual("AdobeTargetMobile", requestHeaders["X-EXC-SDK"]) + XCTAssertEqual("AdobeTargetMobile-iOS", requestHeaders["X-EXC-SDK"]) XCTAssertEqual("\(coreVersion)+\(TargetTestConstants.EXTENSION_VERSION)", requestHeaders["X-EXC-SDK-Version"]) return (data: responseString.data(using: .utf8), response: validResponse, error: nil) @@ -2141,7 +2141,7 @@ class TargetIntegrationTests: XCTestCase { // verify request headers let coreVersion = self.getLastValidSharedState("com.adobe.module.eventhub")?.value?["version"] ?? "unknown" let requestHeaders: [String: String] = request.httpHeaders - XCTAssertEqual("AdobeTargetMobile", requestHeaders["X-EXC-SDK"]) + XCTAssertEqual("AdobeTargetMobile-iOS", requestHeaders["X-EXC-SDK"]) XCTAssertEqual("\(coreVersion)+\(TargetTestConstants.EXTENSION_VERSION)", requestHeaders["X-EXC-SDK-Version"]) targetNotificationExpectation.fulfill() From 51e18e186e52af2663318183bbf960f85597d43a Mon Sep 17 00:00:00 2001 From: Steve Benedick Date: Wed, 11 Oct 2023 15:04:38 -0600 Subject: [PATCH 5/7] -adding update versions gh action workflow --- .github/workflows/update_versions.yml | 47 ++++++++++++ Makefile | 4 ++ Script/update-versions.sh | 100 ++++++++++++++++++++++++++ 3 files changed, 151 insertions(+) create mode 100644 .github/workflows/update_versions.yml create mode 100755 Script/update-versions.sh diff --git a/.github/workflows/update_versions.yml b/.github/workflows/update_versions.yml new file mode 100644 index 0000000..4ef3c68 --- /dev/null +++ b/.github/workflows/update_versions.yml @@ -0,0 +1,47 @@ +# This is a basic workflow that is manually triggered + +name: Update Versions + +# Controls when the action will run. Workflow runs when manually triggered using the UI +# or API. +on: + workflow_dispatch: + # Inputs the workflow accepts. + inputs: + version: + description: 'New version to use for the Target extension. Example: 4.0.2' + required: true + + branch: + description: 'Branch to be used when updating versions' + required: true + + core-dependency: + description: 'If a version is provided, update AEPCore dependency in podspec and Package.swift' + required: false + +# A workflow run is made up of one or more jobs that can run sequentially or in parallel +jobs: + update-versions: + runs-on: macos-latest + + # Steps represent a sequence of tasks that will be executed as part of the job + steps: + + - name: Checkout + uses: actions/checkout@v3.1.0 + with: + ref: ${{ github.event.inputs.branch }} + + - name: Update AEPTarget + run: (sh ./Script/update-versions.sh -n Target -v ${{ github.event.inputs.version }} -d "AEPCore ${{ github.event.inputs.core-dependency }}") + + - name: Create Pull Request + uses: peter-evans/create-pull-request@v4.2.3 + with: + token: ${{ github.token }} + commit-message: Updating version to ${{ github.event.inputs.version }}. + branch: version-${{ github.event.inputs.version }}-update + delete-branch: true + title: Updating version to ${{ github.event.inputs.version }} + body: Updating version to ${{ github.event.inputs.version }} diff --git a/Makefile b/Makefile index a593c6d..b4aa3d9 100644 --- a/Makefile +++ b/Makefile @@ -87,3 +87,7 @@ test-podspec: pod-lint: (pod lib lint --allow-warnings --verbose --swift-version=5.1) + +# used to test update-versions.sh script locally +test-update-version: + (sh ./Script/update-versions.sh -n Target -v 9.9.9 -d "AEPCore 9.9.3") diff --git a/Script/update-versions.sh b/Script/update-versions.sh new file mode 100755 index 0000000..465ccba --- /dev/null +++ b/Script/update-versions.sh @@ -0,0 +1,100 @@ +#!/bin/bash + +# make this script executable from terminal: +# chmod 755 update-versions.sh + +set -e # Any subsequent(*) commands which fail will cause the shell script to exit immediately + +ROOT_DIR=$(git rev-parse --show-toplevel) +LINE="================================================================================" +VERSION_REGEX="[0-9]+\.[0-9]+\.[0-9]+" +DEPENDENCIES=none + +# make a "dictionary" to help us find the correct spm repo per dependency (if necessary) +# IMPORTANT - this will be used in a regex search so escape special chars +# usage : +# getRepo AEPCore + +declare "repos_AEPCore=https:\/\/github\.com\/adobe\/aepsdk-core-ios\.git" + +getRepo() { + local extensionName=$1 + local url="repos_$extensionName" + echo "${!url}" +} + +help() +{ + echo "" + echo "Usage: $0 -n EXTENSION_NAME -v NEW_VERSION -d \"PODSPEC_DEPENDENCY_1, PODSPEC_DEPENDENCY_2\"" + echo "" + echo -e " -n\t- Name of the extension getting a version update. \n\t Example: Edge, Analytics\n" + echo -e " -v\t- New version to use for the extension. \n\t Example: 4.0.2\n" + echo -e " -d (optional)\t- Dependency(ies) that require updating in the extension's podspec and Package.swift file. \n\t Example: -d \"AEPCore 4.0.2\" (update the dependency on AEPCore to version 4.0.2 or newer)\n" + exit 1 # Exit script after printing help +} + +while getopts "n:v:d:" opt +do + case "$opt" in + n ) NAME="$OPTARG" ;; + v ) NEW_VERSION="$OPTARG" ;; + d ) DEPENDENCIES="$OPTARG" ;; + ? ) help ;; # Print help in case parameter is non-existent + esac +done + +# Print help in case parameters are empty +if [ -z "$NAME" ] || [ -z "$NEW_VERSION" ] +then + echo "********** USAGE ERROR **********" + echo "Some or all of the parameters are empty. See usage below:"; + help +fi + +PODSPEC_FILE=$ROOT_DIR"/AEP"$NAME.podspec +SPM_FILE=$ROOT_DIR/Package.swift + +# Begin script in case all parameters are correct +echo "" +echo "$LINE" +echo "Changing version of AEP$NAME to $NEW_VERSION with the following minimum version dependencies: $DEPENDENCIES" +echo "$LINE" + +# Replace extension version in podspec +echo "Changing value of 's.version' to '$NEW_VERSION' in '$PODSPEC_FILE'" +sed -i '' -E "/^ *s.version/{s/$VERSION_REGEX/$NEW_VERSION/;}" $PODSPEC_FILE + +# Replace dependencies in podspec and Package.swift +if [ "$DEPENDENCIES" != "none" ]; then + IFS="," + dependenciesArray=($(echo "$DEPENDENCIES")) + + IFS=" " + for dependency in "${dependenciesArray[@]}"; do + dependencyArray=(${dependency// / }) + dependencyName=${dependencyArray[0]} + dependencyVersion=${dependencyArray[1]} + + if [ "$dependencyVersion" != "" ]; then + echo "Changing value of 's.dependency' for '$dependencyName' to '>= $dependencyVersion' in '$PODSPEC_FILE'" + sed -i '' -E "/^ *s.dependency +'$dependencyName'/{s/$VERSION_REGEX/$dependencyVersion/;}" $PODSPEC_FILE + + spmRepoUrl=$(getRepo $dependencyName) + if [ "$spmRepoUrl" != "" ]; then + echo "Changing value of '.upToNextMajor(from:)' for '$spmRepoUrl' to '$dependencyVersion' in '$SPM_FILE'" + sed -i '' -E "/$spmRepoUrl\", \.upToNextMajor/{s/$VERSION_REGEX/$dependencyVersion/;}" $SPM_FILE + fi + fi + done +fi + +# Replace version in Constants file +CONSTANTS_FILE=$ROOT_DIR"/AEP$NAME/Sources/"$NAME"Constants.swift" +echo "Changing value of 'EXTENSION_VERSION' to '$NEW_VERSION' in '$CONSTANTS_FILE'" +sed -i '' -E "/^ +static let EXTENSION_VERSION/{s/$VERSION_REGEX/$NEW_VERSION/;}" $CONSTANTS_FILE + +# Replace marketing versions in project.pbxproj +PROJECT_PBX_FILE=$ROOT_DIR"/AEP$NAME.xcodeproj/project.pbxproj" +echo "Changing value of 'MARKETING_VERSION' to '$NEW_VERSION' in '$PROJECT_PBX_FILE'" +sed -i '' -E "/^\t+MARKETING_VERSION = /{s/$VERSION_REGEX/$NEW_VERSION/;}" $PROJECT_PBX_FILE \ No newline at end of file From 2c3aba4f36c1928ca3dcdc9247a0b31ee148eca5 Mon Sep 17 00:00:00 2001 From: Steve Benedick Date: Wed, 11 Oct 2023 16:37:54 -0600 Subject: [PATCH 6/7] -add update for test constants file --- Script/update-versions.sh | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/Script/update-versions.sh b/Script/update-versions.sh index 465ccba..af6ab6f 100755 --- a/Script/update-versions.sh +++ b/Script/update-versions.sh @@ -94,6 +94,11 @@ CONSTANTS_FILE=$ROOT_DIR"/AEP$NAME/Sources/"$NAME"Constants.swift" echo "Changing value of 'EXTENSION_VERSION' to '$NEW_VERSION' in '$CONSTANTS_FILE'" sed -i '' -E "/^ +static let EXTENSION_VERSION/{s/$VERSION_REGEX/$NEW_VERSION/;}" $CONSTANTS_FILE +# Replace version in TestConstants file +TEST_CONSTANTS_FILE=$ROOT_DIR"/AEP$NAME/Tests/TestHelpers/"$NAME"TestConstants.swift" +echo "Changing value of 'EXTENSION_VERSION' to '$NEW_VERSION' in '$TEST_CONSTANTS_FILE'" +sed -i '' -E "/^ +static let EXTENSION_VERSION/{s/$VERSION_REGEX/$NEW_VERSION/;}" $TEST_CONSTANTS_FILE + # Replace marketing versions in project.pbxproj PROJECT_PBX_FILE=$ROOT_DIR"/AEP$NAME.xcodeproj/project.pbxproj" echo "Changing value of 'MARKETING_VERSION' to '$NEW_VERSION' in '$PROJECT_PBX_FILE'" From 7e61def427cea654e1b3059220eff72ef347a0d9 Mon Sep 17 00:00:00 2001 From: Steve Benedick Date: Wed, 11 Oct 2023 16:55:14 -0600 Subject: [PATCH 7/7] -update version in podspec --- AEPTarget.podspec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/AEPTarget.podspec b/AEPTarget.podspec index e077721..de3e7da 100644 --- a/AEPTarget.podspec +++ b/AEPTarget.podspec @@ -1,6 +1,6 @@ Pod::Spec.new do |s| s.name = "AEPTarget" - s.version = "4.0.1" + s.version = "4.0.2" s.summary = "Experience Platform Target extension for Adobe Experience Platform Mobile SDK. Written and maintained by Adobe." s.description = <<-DESC The Experience Platform Target extension provides APIs that allow use of the Target product in the Adobe Experience Platform SDK.