8000 setup CI/CD by yangyansong-adbe · Pull Request #28 · adobe/aepsdk-userprofile-ios · GitHub
[go: up one dir, main page]
More Web Proxy on the site http://driver.im/
Skip to content

setup CI/CD #28

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 7 commits into from
Feb 3, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions .github/release-drafter.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
template: |
## What’s Changed

$CHANGES
6 changes: 4 additions & 2 deletions .github/workflows/swift.yml → .github/workflows/build.yml
Original file line number Diff line number Diff line change
@@ -1,14 +1,16 @@
name: UserProfile-CI
name: Build

on:
push:
branches:
- dev*
- main
- dev-*
pull_request:
branches:
- dev*
- main
- dev-*

jobs:
build:
Expand All @@ -28,7 +30,7 @@ jobs:
run: brew install swiftformat

- name: Install SwiftLint
run: brew install swiftlint
run: which swiftLint || brew install swiftlint

- name: Linting
run: make lint; make check-format
Expand Down
71 changes: 71 additions & 0 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
name: Release


on:
workflow_dispatch:
inputs:
tag:
desc 8000 ription: 'tag/version'
required: true
default: '1.0.0'

action_tag:
description: 'create tag ("no" to skip)'
required: true
default: 'yes'

jobs:
release_rules_engine:
runs-on: macos-latest
steps:
- uses: actions/checkout@v2
with:
ref: main

- name: Install jq
run: brew install jq

- name: Check version in Podspec
run: |
set -eo pipefail
echo Target version: ${{ github.event.inputs.tag }}
make check-version VERSION=${{ github.event.inputs.tag }}

- name: Pod repo update
run: |
pod repo update

- name: SPM integration test
if: ${{ github.event.inputs.action_tag == 'yes' }}
run: |
set -eo pipefail
echo SPM integration test starts:
make test-SPM-integration

- name: podspec file verification
if: ${{ github.event.inputs.action_tag == 'yes' }}
run: |
set -eo pipefail
echo podspec file verification starts:
make test-podspec

- uses: release-drafter/release-drafter@v5
if: ${{ github.event.inputs.action_tag == 'yes' }}
with:
name: v${{ github.event.inputs.tag }}
tag: ${{ github.event.inputs.tag }}
version: ${{ github.event.inputs.tag }}
publish: true
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

- name: Publish Pods
run: |
set -eo pipefail
gem install cocoapods
pod lib lint --allow-warnings --swift-version=5.1
pod trunk push AEPRulesEngine.podspec --allow-warnings --swift-version=5.1
env:
COCOAPODS_TRUNK_TOKEN: ${{ secrets.COCOAPODS_TRUNK_TOKEN }}


2 changes: 1 addition & 1 deletion .swift-version
Original file line number Diff line number Diff line change
@@ -1 +1 @@
5.0
5.1
2 changes: 2 additions & 0 deletions .swiftformat
Original file line number Diff line number Diff line change
@@ -1 +1,3 @@
--swiftversion 5.1

--disable typeSugar
9 changes: 2 additions & 7 deletions AEPUserProfile.podspec
Original file line number Diff line number Diff line change
Expand Up @@ -7,18 +7,13 @@ Pod::Spec.new do |s|
DESC
s.homepage = "https://github.com/adobe/aepsdk-userprofile-ios"
s.license = 'Apache V2'
s.author = "Adobe Experience Platform SDK Team"
s.author = "Adobe Experience Platform SDK Team"
s.source = { :git => "https://github.com/adobe/aepsdk-userprofile-ios", :tag => s.version.to_s }

s.ios.deployment_target = '10.0'

s.swift_version = '5.1'

s.swift_version = '5.1'
s.pod_target_xcconfig = { 'BUILD_LIBRARY_FOR_DISTRIBUTION' => 'YES' }

s.dependency 'AEPCore'
s.dependency 'AEPServices'

s.source_files = 'AEPUserProfile/Sources/**/*.swift'

end
4 changes: 4 additions & 0 deletions AEPUserProfile.xcodeproj/project.pbxproj 9E81
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
BB0103BA253F880700B41C38 /* UserProfileTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB0103B9253F880700B41C38 /* UserProfileTests.swift */; };
BB08376225411B6900253BE9 /* UserProfileFunctionalTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = BBE6C4DA2538B9220085876E /* UserProfileFunctionalTests.swift */; };
BB4CC52B253E481700A34A4E /* AEPUserProfile.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = BBE6C4CC2538B9220085876E /* AEPUserProfile.framework */; platformFilter = ios; };
BB87E3C62578022600C316E8 /* UserProfileV5Migrator.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB87E3C52578022600C316E8 /* UserProfileV5Migrator.swift */; };
BBE24F11253A065D00C23435 /* Event+UserProfile.swift in Sources */ = {isa = PBXBuildFile; fileRef = BBE24F10253A065D00C23435 /* Event+UserProfile.swift */; };
BBE6C4DD2538B9220085876E /* AEPUserProfile.h in Headers */ = {isa = PBXBuildFile; fileRef = BBE6C4CF2538B9220085876E /* AEPUserProfile.h */; settings = {ATTRIBUTES = (Public, ); }; };
BBE6C4EB2538B9790085876E /* UserProfileConstants.swift in Sources */ = {isa = PBXBuildFile; fileRef = BBE6C4E92538B9790085876E /* UserProfileConstants.swift */; };
Expand Down Expand Up @@ -92,6 +93,7 @@
7B2E802514D25DDCED194D71 /* Pods_AEPUserProfile.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_AEPUserProfile.framework; sourceTree = BUILT_PRODUCTS_DIR; };
98B786D3131F9375BB009B57 /* Pods-AEPUserProfile.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-AEPUserProfile.debug.xcconfig"; path = "Target Support Files/Pods-AEPUserProfile/Pods-AEPUserProfile.debug.xcconfig"; sourceTree = "<group>"; };
BB0103B9253F880700B41C38 /* UserProfileTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UserProfileTests.swift; sourceTree = "<group>"; };
BB87E3C52578022600C316E8 /* UserProfileV5Migrator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UserProfileV5Migrator.swift; sourceTree = "<group>"; };
BBE24F10253A065D00C23435 /* Event+UserProfile.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Event+UserProfile.swift"; sourceTree = "<group>"; };
BBE6C4CC2538B9220085876E /* AEPUserProfile.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = AEPUserProfile.framework; sourceTree = BUILT_PRODUCTS_DIR; };
BBE6C4CF2538B9220085876E /* AEPUserProfile.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AEPUserProfile.h; sourceTree = "<group>"; };
Expand Down Expand Up @@ -209,6 +211,7 @@
BBE6C4D02538B9220085876E /* Info.plist */,
BBE6C4F82538DC740085876E /* UserProfile+PublicAPI.swift */,
BBE24F10253A065D00C23435 /* Event+UserProfile.swift */,
BB87E3C52578022600C316E8 /* UserProfileV5Migrator.swift */,
);
path = Sources;
sourceTree = "<group>";
Expand Down Expand Up @@ -503,6 +506,7 @@
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
BB87E3C62578022600C316E8 /* UserProfileV5Migrator.swift in Sources */,
BBE6C4F92538DC740085876E /* UserProfile+PublicAPI.swift in Sources */,
BBE6C4EB2538B9790085876E /* UserProfileConstants.swift in Sources */,
BBE6C4EC2538B9790085876E /* UserProfile.swift in Sources */,
Expand Down
22 changes: 11 additions & 11 deletions AEPUserProfile/Sources/Event+UserProfile.swift
Original file line number Diff line number Diff line change
Expand Up @@ -17,52 +17,52 @@ extension Event {
// MARK: - UserProfile Request

var isUpdateAttributesEvent: Bool {
return data?[UserProfileConstants.UserProfile.EventDataKeys.UPDATE_DATA] != nil
data?[UserProfileConstants.UserProfile.EventDataKeys.UPDATE_DATA] != nil
}

var isGetAttributesEvent: Bool {
return data?[UserProfileConstants.UserProfile.EventDataKeys.GET_DATA_ATTRIBUTES] != nil
data?[UserProfileConstants.UserProfile.EventDataKeys.GET_DATA_ATTRIBUTES] != nil
}

// MARK: - RulesEngine Response

var isRulesConsequenceEvent: Bool {
return data?[UserProfileConstants.RulesEngine.EventDataKeys.TRIGGERED_CONSEQUENCE] != nil
data?[UserProfileConstants.RulesEngine.EventDataKeys.TRIGGERED_CONSEQUENCE] != nil
}

// MARK: - Consequence Data

private var consequence: [String: Any]? {
return data?[UserProfileConstants.RulesEngine.EventDataKeys.TRIGGERED_CONSEQUENCE] as? [String: Any]
data?[UserProfileConstants.RulesEngine.EventDataKeys.TRIGGERED_CONSEQUENCE] as? [String: Any]
}

var consequenceType: String? {
return consequence?[UserProfileConstants.RulesEngine.EventDataKeys.TYPE] as? String
consequence?[UserProfileConstants.RulesEngine.EventDataKeys.TYPE] as? String
}

private var detail: [String: Any]? {
return consequence?[UserProfileConstants.RulesEngine.EventDataKeys.DETAIL] as? [String: Any]
consequence?[UserProfileConstants.RulesEngine.EventDataKeys.DETAIL] as? [String: Any]
}

var detailKey: String? {
return detail?[UserProfileConstants.RulesEngine.EventDataKeys.DETAIL_KEY] as? String
detail?[UserProfileConstants.RulesEngine.EventDataKeys.DETAIL_KEY] as? String
}

var detailValue: String? {
return detail?[UserProfileConstants.RulesEngine.EventDataKeys.DETAIL_VALUE] as? String
detail?[UserProfileConstants.RulesEngine.EventDataKeys.DETAIL_VALUE] as? String
}

var detailOperation: String? {
return detail?[UserProfileConstants.RulesEngine.EventDataKeys.DETAIL_OPERATION] as? String
detail?[UserProfileConstants.RulesEngine.EventDataKeys.DETAIL_OPERATION] as? String
}

// MARK: - Error Response Data

var isErrorResponseEvent: Bool {
return data?[UserProfileConstants.UserProfile.EventDataKeys.ERROR_RESPONSE] != nil
data?[UserProfileConstants.UserProfile.EventDataKeys.ERROR_RESPONSE] != nil
}

var errorMessage: String? {
return data?[UserProfileConstants.UserProfile.EventDataKeys.ERROR_MESSAGE] as? String
data?[UserProfileConstants.UserProfile.EventDataKeys.ERROR_MESSAGE] as? String
}
}
8 changes: 7 additions & 1 deletion AEPUserProfile/Sources/UserProfile.swift
Original file line number Diff line number Diff line change
Expand Up @@ -49,13 +49,19 @@ public class UserProfile: NSObject, Extension {
registerListener(type: EventType.userProfile, source: EventSource.requestReset, listener: removeAttributes(event:))
registerListener(type: EventType.rulesEngine, source: EventSource.responseContent, listener: handleRulesEngineResponse(event:))
loadAttributes()
if let existingAttributes = UserProfileV5Migrator.existingAttributes() {
Log.trace(label: UserProfile.LOG_TAG, "Data migration starts")
attributes.merge(existingAttributes) { old, _ in old }
persistAttributes()
UserProfileV5Migrator.clearExistingAttributes()
}
createSharedState()
}

public func onUnregistered() {}

public func readyForEvent(_: Event) -> Bool {
return true
true
}

// MARK: - Event Listeners
Expand Down
4 changes: 4 additions & 0 deletions AEPUserProfile/Sources/UserProfileConstants.swift
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,10 @@ enum UserProfileConstants {
static let DATASTORE_NAME = EXTENSION_NAME
static let DATASTORE_KEY_ATTRIBUTES = "attributes"

enum V5Migration {
static let USER_PROFILE_KEY = "Adobe.ADBUserProfile.user_profile"
}

enum Configuration {
static let NAME = "com.adobe.module.configuration"
}
Expand Down
32 changes: 32 additions & 0 deletions AEPUserProfile/Sources/UserProfileV5Migrator.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
/*
Copyright 2020 Adobe. All rights reserved.
This file is licensed to you 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

< CEB7 span class='blob-code-inner blob-code-marker ' data-code-marker="+"> 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 REPRESENTATIONS
OF ANY KIND, either express or implied. See the License for the specific language
governing permissions and limitations under the License.
*/

import AEPCore
import AEPServices
import Foundation

enum UserProfileV5Migrator {
static func existingAttributes() -> [String: Any]? {
guard let json = UserDefaults.standard.object(forKey: UserProfileConstants.V5Migration.USER_PROFILE_KEY) as? String else {
return nil
}
guard let jsonData = json.data(using: .utf8), let attributes = try? JSONDecoder().decode([String: AnyCodable].self, from: jsonData) else {
Log.debug(label: UserProfile.LOG_TAG, "data migration - failed to load (json) user attributes from data storage")
return nil
}
return attributes.asDictionary()
}

static func clearExistingAttributes() {
UserDefaults.standard.removeObject(forKey: UserProfileConstants.V5Migration.USER_PROFILE_KEY)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,13 @@ import XCTest
class UserProfileFunctionalTests: XCTestCase {
private var theExpectation: XCTestExpectation?
private var v5Defaults: UserDefaults {
return UserDefaults(suiteName: "com.adobe.mobile.datastore") ?? UserDefaults.standard
UserDefaults(suiteName: "com.adobe.mobile.datastore") ?? UserDefaults.standard
}

override func setUpWithError() throws {
MobileCore.setLogLevel(.trace)
UserDefaults.standard.removeObject(forKey: "Adobe.com.adobe.module.userProfile.attributes")
UserDefaults.standard.removeObject(forKey: "Adobe.ADBUserProfile.user_profile")
}

override func tearDownWithError() throws {
Expand Down Expand Up @@ -270,6 +271,48 @@ class UserProfileFunctionalTests: XCTestCase {
MobileCore.unregisterExtension(UserProfile.self)
MobileCore.unregisterExtension(MonitorExtension.self)
}

func testDataMigration() throws {
// Given
let json = """
{
"d" : {
"a2" : "yy",
"a1" : "xx"
},
"b" : 123,
"c" : [
1,
2
],
"a" : "aaa"
}
"""
UserDefaults.standard.set(json, forKey: "Adobe.ADBUserProfile.user_profile")
let expectation = self.expectation(description: "register UserProfile extension")

MobileCore.registerExtensions([UserProfile.self, MonitorExtension.self]) {
expectation.fulfill()
}
waitForExpectations(timeout: 2)
// When
let expectGet = self.expectation(description: "getUserAttributes()")
UserProfile.getUserAttributes(attributeNames: []) {
_, error in
expectGet.fulfill()
XCTAssertEqual(AEPError.none, error)
let storedAttributes = UserDefaults.standard.object(forKey: "Adobe.com.adobe.module.userProfile.attributes") as? [String: Any]
XCTAssertEqual("aaa", storedAttributes?["a"] as? String)
XCTAssertEqual(123, storedAttributes?["b"] as? Int)
XCTAssertEqual([1, 2], storedAttributes?["c"] as? [Int])
XCTAssertEqual(["a1": "xx", "a2": "yy"], storedAttributes?["d"] as? [String: String])
MobileCore.unregisterExtension(UserProfile.self)
XCTAssertNil(UserDefaults.standard.object(forKey: "Adobe.ADBUserProfile.user_profile"))
}

// Then
waitForExpectations(timeout: 2)
}
}

@objc(MonitorExtension)
Expand Down Expand Up @@ -319,11 +362,11 @@ public class MonitorExtension: NSObject, Extension {
public func onUnregistered() {}

public var userProfileSharedStateData: [String: Any]? {
return getSharedState(extensionName: "com.adobe.module.userProfile", event: nil)?.value
getSharedState(extensionName: "com.adobe.module.userProfile", event: nil)?.value
}

public func readyForEvent(_: Event) -> Bool {
return true
true
}

public required init(runtime: ExtensionRuntime) {
Expand Down
Loading
0