From a6f2850c8f170ad586f48e491d86e34c48393c52 Mon Sep 17 00:00:00 2001 From: Tim Kim <95260439+timkimadobe@users.noreply.github.com> Date: Wed, 27 Nov 2024 14:43:20 -0800 Subject: [PATCH] Migrate to GitHub Actions reusable workflows (#97) * Migrate update versions to use reusable workflow * Migrate build and test to GHA and update Makefile for consistency Remove local scripts and CircleCI config * Migrate release workflow to reusable workflow * Enable codecov * bundle install with 2.5.23 * Update AEPTestUtils to 5.2.2 (Core) * Update functional tests to use longer default timeout for network request assertions * Update Gemfile cocoapods to 1.16.2 * Update file structure to revert back to objectVersion 54 --- .circleci/config.yml | 127 ------------------ .github/workflows/build-and-test.yml | 31 +++++ .github/workflows/release.yml | 120 +++++------------ .github/workflows/update-versions.yml | 45 +++++++ .github/workflows/update_versions.yml | 47 ------- AEPEdgeBridge.xcodeproj/project.pbxproj | 12 ++ Gemfile | 2 +- Gemfile.lock | 77 +++++++---- Makefile | 64 +++++++-- Podfile | 4 +- Podfile.lock | 44 +++--- Script/update-versions.sh | 100 -------------- Script/version.sh | 29 ---- .../EdgeBridgeFunctionalTests.swift | 19 +-- .../util/FunctionalTestConstants.swift | 20 +++ 15 files changed, 282 insertions(+), 459 deletions(-) delete mode 100644 .circleci/config.yml create mode 100644 .github/workflows/build-and-test.yml create mode 100644 .github/workflows/update-versions.yml delete mode 100644 .github/workflows/update_versions.yml delete mode 100644 Script/update-versions.sh delete mode 100755 Script/version.sh create mode 100644 Tests/FunctionalTests/util/FunctionalTestConstants.swift diff --git a/.circleci/config.yml b/.circleci/config.yml deleted file mode 100644 index 51ac782..0000000 --- a/.circleci/config.yml +++ /dev/null @@ -1,127 +0,0 @@ -# For a detailed guide to building and testing on iOS, read the docs: -# https://circleci.com/docs/2.0/testing-ios/ - -version: 2.1 - -orbs: - # codecov: codecov/codecov@3.2.5 - macos: circleci/macos@2 - -# Workflows orchestrate a set of jobs to be run -workflows: - build-test: - jobs: - - validate-code - - test-ios: - requires: - - validate-code - - build_xcframework_and_app: - requires: - - validate-code - -commands: - install_dependencies: - steps: - # restore pods related caches - - restore_cache: - name: Restoring Gemfile Cache - keys: - - 1-gems-{{ checksum "Gemfile.lock" }} - - # make sure we're on the right version of cocoapods - - run: - name: Verify Cocoapods Version - command: bundle check || bundle install --path vendor/bundle - - # save cocoapods version gem data - - save_cache: - name: Saving Gemfile Cache - key: 1-gems-{{ checksum "Gemfile.lock" }} - paths: - - vendor/bundle - - # restore pods related caches - - restore_cache: - name: Restoring CocoaPods Cache - keys: - - cocoapods-cache-v2-{{ arch }}-{{ .Branch }}-{{ checksum "Podfile.lock" }} - - cocoapods-cache-v2-{{ arch }}-{{ .Branch }} - - cocoapods-cache-v2 - - # install CocoaPods - using default CocoaPods version, not the bundle - - run: - name: Repo Update & Install CocoaPods - command: make ci-pod-install - - # save pods related files - - save_cache: - name: Saving CocoaPods Cache - key: cocoapods-cache-v2-{{ arch }}-{{ .Branch }}-{{ checksum "Podfile.lock" }} - paths: - - ./Pods - - ./SampleApps/TestApp/Pods - - ~/.cocoapods - - prestart_ios_simulator: - steps: - - macos/preboot-simulator: - platform: "iOS" - version: "17.2" - device: "iPhone 15" - -jobs: - validate-code: - macos: - xcode: 15.1.0 # Specify the Xcode version to use - - steps: - - checkout - - - install_dependencies - - - run: - name: Lint Source Code - command: make lint - - test-ios: - macos: - xcode: 15.1.0 # Specify the Xcode version to use - - steps: - - checkout - - - install_dependencies - - - prestart_ios_simulator - - - run: - name: Run iOS Tests - command: make test-ios - - # Code coverage upload using Codecov - # See options explanation here: https://docs.codecov.com/docs/codecov-uploader - # - codecov/upload: - # flags: ios-tests - # upload_name: Coverage Report for iOS Tests - # xtra_args: -c -v --xc --xp iosresults.xcresult - - build_xcframework_and_app: - macos: - xcode: 15.1.0 # Specify the Xcode version to use - - steps: - - checkout - # verify XCFramework archive builds - - run: - name: Build XCFramework - command: | - if [[ "${CIRCLE_BRANCH}" == "main" || "${CIRCLE_BRANCH}" == "staging" ]]; then - make archive - fi - # verify test app builds - - run: - name: Build Test App - command: | - if [[ "${CIRCLE_BRANCH}" == "main" || "${CIRCLE_BRANCH}" == "staging" ]]; then - make build-app - fi \ No newline at end of file diff --git a/.github/workflows/build-and-test.yml b/.github/workflows/build-and-test.yml new file mode 100644 index 0000000..dafe179 --- /dev/null +++ b/.github/workflows/build-and-test.yml @@ -0,0 +1,31 @@ +# +# Copyright 2024 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 +# +# 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. +# + +name: Build and Test + +on: + pull_request: + +jobs: + build-and-test: + name: "CI" + uses: adobe/aepsdk-commons/.github/workflows/ios-build-and-test.yml@gha-ios-5.0.0 + with: + ios-device-names: '["iPhone 15"]' + ios-versions: '["18.1"]' + tvos-device-names: '["Apple TV"]' + tvos-versions: '["18.1"]' + run-test-ios-unit: true + run-test-ios-functional: true + run-build-xcframework-and-app: true + enable-codecov: true + secrets: inherit \ No newline at end of file diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index dffaf1c..8335435 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -1,101 +1,45 @@ +# +# Copyright 2024 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 +# +# 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. +# + name: Release on: workflow_dispatch: inputs: tag: - description: 'tag/version' + description: 'The tag (version) to be released (ex: 1.2.3).' + type: string required: true - default: '1.0.0' - action_tag: - description: 'create tag ("no" to skip)' + create-github-release: + description: 'Create a GitHub release with uploaded artifacts. If the provided `tag` does not exist, it will be created.' + type: boolean required: true - default: 'yes' + default: true - release_AEPEdgeBridge: - description: 'release AEPEdgeBridge to Cocoapods ("no" to skip)' + pod-publish-extensions: + description: 'Publish AEPEdgeBridge to Cocoapods.' + type: boolean required: true - default: 'yes' + default: true jobs: - release_edgebridge: - runs-on: macos-13 - steps: - - uses: actions/checkout@v2 - with: - ref: main - - uses: maxim-lobanov/setup-xcode@v1 - with: - xcode-version: '15.0.1' - - - name: Install jq - run: brew install jq - - - name: Install cocoapods - run: gem install cocoapods - - - name: Install xcodegen - run: brew install xcodegen - - - 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 - - - name: Build Artifacts - if: ${{ github.event.inputs.action_tag == 'yes' }} - run: | - make archive - make zip - - - name: Create GH Release - id: create_release - 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: Upload - AEPEdgeBridge - uses: actions/upload-release-asset@v1 - if: ${{ github.event.inputs.action_tag == 'yes' }} - with: - upload_url: ${{ steps.create_release.outputs.upload_url }} - asset_path: ./build/AEPEdgeBridge.xcframework.zip - asset_name: AEPEdgeBridge-${{ github.event.inputs.tag }}.xcframework.zip - asset_content_type: application/zip - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - - - name: Publish Pods - AEPEdgeBridge - if: ${{ github.event.inputs.release_AEPEdgeBridge == 'yes' }} - run: | - set -eo pipefail - pod trunk push AEPEdgeBridge.podspec --allow-warnings --synchronous - pod repo update - env: - COCOAPODS_TRUNK_TOKEN: ${{ secrets.COCOAPODS_TRUNK_TOKEN }} + release: + permissions: + contents: write + uses: adobe/aepsdk-commons/.github/workflows/ios-release.yml@gha-ios-5.0.0 + with: + tag: ${{ github.event.inputs.tag }} + create-github-release: ${{ github.event.inputs.create-github-release == 'true' && 'AEPEdgeBridge' || '' }} + pod-publish-extensions: ${{ github.event.inputs.pod-publish-extensions == 'true' && 'AEPEdgeBridge' || '' }} + version-validation-paths: AEPEdgeBridge.podspec, AEPEdgeBridge.xcodeproj/project.pbxproj, Sources/EdgeBridgeConstants.swift + secrets: inherit \ No newline at end of file diff --git a/.github/workflows/update-versions.yml b/.github/workflows/update-versions.yml new file mode 100644 index 0000000..9afe480 --- /dev/null +++ b/.github/workflows/update-versions.yml @@ -0,0 +1,45 @@ +# +# Copyright 2024 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 +# +# 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. +# + +name: Update Versions + +on: + workflow_dispatch: + inputs: + version: + description: 'The new version to use for the extension (ex: 1.2.3).' + type: string + required: true + + branch: + description: 'The target branch where the version update will be applied and the pull request will be merged into.' + type: string + required: true + + core-dependency: + description: 'If a version is provided, update AEPCore dependency in podspec and Package.swift.' + type: string + required: false + default: '' + +jobs: + update-versions: + permissions: + contents: write + pull-requests: write + uses: adobe/aepsdk-commons/.github/workflows/versions.yml@gha-ios-5.0.0 + with: + version: ${{ github.event.inputs.version }} + branch: ${{ github.event.inputs.branch }} + dependencies: AEPCore ${{ github.event.inputs.core-dependency }} + paths: Package.swift:swift_spm, AEPEdgeBridge.podspec, AEPEdgeBridge.xcodeproj/project.pbxproj, Sources/EdgeBridgeConstants.swift + update: true \ No newline at end of file diff --git a/.github/workflows/update_versions.yml b/.github/workflows/update_versions.yml deleted file mode 100644 index 7434a72..0000000 --- a/.github/workflows/update_versions.yml +++ /dev/null @@ -1,47 +0,0 @@ -# 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 extension. Example: 1.5.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 extension version (with core dependency update) - run: (sh ./Script/update-versions.sh -n EdgeBridge -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/AEPEdgeBridge.xcodeproj/project.pbxproj b/AEPEdgeBridge.xcodeproj/project.pbxproj index 3dc3946..5e13749 100644 --- a/AEPEdgeBridge.xcodeproj/project.pbxproj +++ b/AEPEdgeBridge.xcodeproj/project.pbxproj @@ -23,6 +23,7 @@ /* Begin PBXBuildFile section */ 0334655BE881D0E2693A80C8 /* Pods_FunctionalTests.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4B8946EAB205F842FB9989F1 /* Pods_FunctionalTests.framework */; }; 49FD17161BDF671E27C6E44D /* Pods_UnitTests.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = CBE94B923FF16061DAFA46C6 /* Pods_UnitTests.framework */; }; + 4C089BCA2CF54A8A00CB500C /* FunctionalTestConstants.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4C089BC92CF54A8A00CB500C /* FunctionalTestConstants.swift */; }; 54AC083B374F80848671988A /* Pods_TestAppSwiftUI.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 37582C0001AF4867A5B12392 /* Pods_TestAppSwiftUI.framework */; }; 5B1D20FED82EBE279C912E01 /* Pods_AEPEdgeBridge.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = C7B429386A4136B8FC9E467B /* Pods_AEPEdgeBridge.framework */; }; BF4A717926DDAE4C00612434 /* AssuranceView.swift in Sources */ = {isa = PBXBuildFile; fileRef = BF4A717826DDAE4B00612434 /* AssuranceView.swift */; }; @@ -118,6 +119,7 @@ 2FC88F9B7B3097FE2B546558 /* Pods-TestAppSwiftUI.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-TestAppSwiftUI.release.xcconfig"; path = "Target Support Files/Pods-TestAppSwiftUI/Pods-TestAppSwiftUI.release.xcconfig"; sourceTree = ""; }; 37582C0001AF4867A5B12392 /* Pods_TestAppSwiftUI.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_TestAppSwiftUI.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 4B8946EAB205F842FB9989F1 /* Pods_FunctionalTests.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_FunctionalTests.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + 4C089BC92CF54A8A00CB500C /* FunctionalTestConstants.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FunctionalTestConstants.swift; sourceTree = ""; }; 5477DBC630212B20C449C9E4 /* Pods-UnitTests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-UnitTests.debug.xcconfig"; path = "Target Support Files/Pods-UnitTests/Pods-UnitTests.debug.xcconfig"; sourceTree = ""; }; 58C935A34A4326E61B9488B1 /* Pods-FunctionalTests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-FunctionalTests.release.xcconfig"; path = "Target Support Files/Pods-FunctionalTests/Pods-FunctionalTests.release.xcconfig"; sourceTree = ""; }; BF4A717826DDAE4B00612434 /* AssuranceView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AssuranceView.swift; sourceTree = ""; }; @@ -205,6 +207,14 @@ name = Frameworks; sourceTree = ""; }; + 4C089BCE2CF54F4100CB500C /* util */ = { + isa = PBXGroup; + children = ( + 4C089BC92CF54A8A00CB500C /* FunctionalTestConstants.swift */, + ); + path = util; + sourceTree = ""; + }; BF5DCF3B2818A5680057D7D3 /* resources */ = { isa = PBXGroup; children = ( @@ -277,6 +287,7 @@ D4D5B4F2242EBFAE00CAB6E4 /* FunctionalTests */ = { isa = PBXGroup; children = ( + 4C089BCE2CF54F4100CB500C /* util */, D4D5B53724325AB700CAB6E4 /* Info.plist */, BF5DCF392817AE200057D7D3 /* EdgeBridgeFunctionalTests.swift */, ); @@ -751,6 +762,7 @@ files = ( D4A473CB2485A8F300D31710 /* TestUtils.swift in Sources */, BF5DCF3A2817AE200057D7D3 /* EdgeBridgeFunctionalTests.swift in Sources */, + 4C089BCA2CF54A8A00CB500C /* FunctionalTestConstants.swift in Sources */, D45F2E6C25ED8EB1000AC350 /* TestableExtensionRuntime.swift in Sources */, D49A6295250AEEF000B7C4A3 /* UserDefaults+Test.swift in Sources */, D49A6290250AE4F500B7C4A3 /* EventHub+Test.swift in Sources */, diff --git a/Gemfile b/Gemfile index 2ab46a2..20cc021 100644 --- a/Gemfile +++ b/Gemfile @@ -1,3 +1,3 @@ source 'https://rubygems.org' -gem 'cocoapods', '= 1.14.3' +gem 'cocoapods', '= 1.16.2' diff --git a/Gemfile.lock b/Gemfile.lock index 7595432..a89506d 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -5,24 +5,32 @@ GEM base64 nkf rexml - activesupport (6.1.7.7) - concurrent-ruby (~> 1.0, >= 1.0.2) + activesupport (7.2.2) + base64 + benchmark (>= 0.3) + bigdecimal + concurrent-ruby (~> 1.0, >= 1.3.1) + connection_pool (>= 2.2.5) + drb i18n (>= 1.6, < 2) + logger (>= 1.4.2) minitest (>= 5.1) - tzinfo (~> 2.0) - zeitwerk (~> 2.3) - addressable (2.8.6) - public_suffix (>= 2.0.2, < 6.0) + securerandom (>= 0.3) + tzinfo (~> 2.0, >= 2.0.5) + addressable (2.8.7) + public_suffix (>= 2.0.2, < 7.0) algoliasearch (1.27.5) httpclient (~> 2.8, >= 2.8.3) json (>= 1.5.1) atomos (0.1.3) base64 (0.2.0) + benchmark (0.4.0) + bigdecimal (3.1.8) claide (1.1.0) - cocoapods (1.14.3) + cocoapods (1.16.2) addressable (~> 2.8) claide (>= 1.0.2, < 2.0) - cocoapods-core (= 1.14.3) + cocoapods-core (= 1.16.2) cocoapods-deintegrate (>= 1.0.3, < 2.0) cocoapods-downloader (>= 2.1, < 3.0) cocoapods-plugins (>= 1.0.0, < 2.0) @@ -36,8 +44,8 @@ GEM molinillo (~> 0.8.0) nap (~> 1.0) ruby-macho (>= 2.3.0, < 3.0) - xcodeproj (>= 1.23.0, < 2.0) - cocoapods-core (1.14.3) + xcodeproj (>= 1.27.0, < 2.0) + cocoapods-core (1.16.2) activesupport (>= 5.0, < 8) addressable (~> 2.8) algoliasearch (~> 1.0) @@ -57,45 +65,68 @@ GEM netrc (~> 0.11) cocoapods-try (1.2.0) colored2 (3.1.2) - concurrent-ruby (1.2.3) + concurrent-ruby (1.3.4) + connection_pool (2.4.1) + drb (2.2.1) escape (0.0.4) ethon (0.16.0) ffi (>= 1.15.0) - ffi (1.16.3) + ffi (1.17.0) + ffi (1.17.0-aarch64-linux-gnu) + ffi (1.17.0-aarch64-linux-musl) + ffi (1.17.0-arm-linux-gnu) + ffi (1.17.0-arm-linux-musl) + ffi (1.17.0-arm64-darwin) + ffi (1.17.0-x86-linux-gnu) + ffi (1.17.0-x86-linux-musl) + ffi (1.17.0-x86_64-darwin) + ffi (1.17.0-x86_64-linux-gnu) + ffi (1.17.0-x86_64-linux-musl) fourflusher (2.3.1) fuzzy_match (2.0.4) gh_inspector (1.1.3) httpclient (2.8.3) - i18n (1.14.4) + i18n (1.14.6) concurrent-ruby (~> 1.0) - json (2.7.1) - minitest (5.22.3) + json (2.8.2) + logger (1.6.1) + minitest (5.25.2) molinillo (0.8.0) - nanaimo (0.3.0) + nanaimo (0.4.0) nap (1.1.0) netrc (0.11.0) nkf (0.2.0) public_suffix (4.0.7) - rexml (3.2.6) + rexml (3.3.9) ruby-macho (2.5.1) + securerandom (0.3.2) typhoeus (1.4.1) ethon (>= 0.9.0) tzinfo (2.0.6) concurrent-ruby (~> 1.0) - xcodeproj (1.24.0) + xcodeproj (1.27.0) CFPropertyList (>= 2.3.3, < 4.0) atomos (~> 0.1.3) claide (>= 1.0.2, < 2.0) colored2 (~> 3.1) - nanaimo (~> 0.3.0) - rexml (~> 3.2.4) - zeitwerk (2.6.13) + nanaimo (~> 0.4.0) + rexml (>= 3.3.6, < 4.0) PLATFORMS + aarch64-linux-gnu + aarch64-linux-musl + arm-linux-gnu + arm-linux-musl + arm64-darwin ruby + x86-linux-gnu + x86-linux-musl + x86_64-darwin + x86_64-linux-gnu + x86_64-linux-musl DEPENDENCIES - cocoapods (= 1.14.3) + cocoapods (= 1.16.2) BUNDLED WITH - 1.17.2 + 2.5.23 diff --git a/Makefile b/Makefile index c16a95d..e834056 100644 --- a/Makefile +++ b/Makefile @@ -11,6 +11,47 @@ SIMULATOR_ARCHIVE_DSYM_PATH = $(CURR_DIR)/build/ios_simulator.xcarchive/dSYMs/ IOS_ARCHIVE_PATH = $(CURR_DIR)/build/ios.xcarchive/Products/Library/Frameworks/ IOS_ARCHIVE_DSYM_PATH = $(CURR_DIR)/build/ios.xcarchive/dSYMs/ +# Values with defaults +IOS_DEVICE_NAME ?= iPhone 15 +# If OS version is not specified, uses the first device name match in the list of available simulators +IOS_VERSION ?= +ifeq ($(strip $(IOS_VERSION)),) + IOS_DESTINATION = "platform=iOS Simulator,name=$(IOS_DEVICE_NAME)" +else + IOS_DESTINATION = "platform=iOS Simulator,name=$(IOS_DEVICE_NAME),OS=$(IOS_VERSION)" +endif + +TVOS_DEVICE_NAME ?= Apple TV +# If OS version is not specified, uses the first device name match in the list of available simulators +TVOS_VERSION ?= +ifeq ($(strip $(TVOS_VERSION)),) + TVOS_DESTINATION = "platform=tvOS Simulator,name=$(TVOS_DEVICE_NAME)" +else + TVOS_DESTINATION = "platform=tvOS Simulator,name=$(TVOS_DEVICE_NAME),OS=$(TVOS_VERSION)" +endif + +clean-derived-data: + @if [ -z "$(SCHEME)" ]; then \ + echo "Error: SCHEME variable is not set."; \ + exit 1; \ + fi; \ + if [ -z "$(DESTINATION)" ]; then \ + echo "Error: DESTINATION variable is not set."; \ + exit 1; \ + fi; \ + echo "Cleaning derived data for scheme: $(SCHEME) with destination: $(DESTINATION)"; \ + DERIVED_DATA_PATH=`xcodebuild -workspace $(PROJECT_NAME).xcworkspace -scheme "$(SCHEME)" -destination "$(DESTINATION)" -showBuildSettings | grep -m1 'BUILD_DIR' | awk '{print $$3}' | sed 's|/Build/Products||'`; \ + echo "DerivedData Path: $$DERIVED_DATA_PATH"; \ + \ + LOGS_TEST_DIR=$$DERIVED_DATA_PATH/Logs/Test; \ + echo "Logs Test Path: $$LOGS_TEST_DIR"; \ + \ + if [ -d "$$LOGS_TEST_DIR" ]; then \ + echo "Removing existing .xcresult files in $$LOGS_TEST_DIR"; \ + rm -rf "$$LOGS_TEST_DIR"/*.xcresult; \ + else \ + echo "Logs/Test directory does not exist. Skipping cleanup."; \ + fi; clean: rm -rf build @@ -61,13 +102,21 @@ build-app: pod-install @echo "######################################################################" xcodebuild clean build -workspace $(PROJECT_NAME).xcworkspace -scheme $(TEST_APP_IOS_SCHEME) -destination 'generic/platform=iOS Simulator' -test: test-ios +test: unit-test-ios functional-test-ios -test-ios: clean-ios-test-files +unit-test-ios: @echo "######################################################################" - @echo "### Testing iOS" + @echo "### Unit Testing iOS" @echo "######################################################################" - xcodebuild test -workspace $(PROJECT_NAME).xcworkspace -scheme $(PROJECT_NAME) -destination 'platform=iOS Simulator,name=iPhone 15' -derivedDataPath build/out -resultBundlePath iosresults.xcresult -enableCodeCoverage YES + @$(MAKE) clean-derived-data SCHEME=UnitTests DESTINATION=$(IOS_DESTINATION) + xcodebuild test -workspace $(PROJECT_NAME).xcworkspace -scheme "UnitTests" -destination $(IOS_DESTINATION) -enableCodeCoverage YES ADB_SKIP_LINT=YES + +functional-test-ios: + @echo "######################################################################" + @echo "### Functional Testing iOS" + @echo "######################################################################" + @$(MAKE) clean-derived-data SCHEME=FunctionalTests DESTINATION=$(IOS_DESTINATION) + xcodebuild test -workspace $(PROJECT_NAME).xcworkspace -scheme "FunctionalTests" -destination $(IOS_DESTINATION) -enableCodeCoverage YES ADB_SKIP_LINT=YES build-ios: @echo "######################################################################" @@ -85,15 +134,8 @@ lint-autocorrect: lint: ./Pods/SwiftLint/swiftlint lint Sources TestApps/ -# make check-version VERSION=5.0.0 -check-version: - sh ./Script/version.sh $(VERSION) - test-SPM-integration: sh ./Script/test-SPM.sh test-podspec: sh ./Script/test-podspec.sh - -test-version-update: - sh ./Script/update-versions.sh -n EdgeBridge -v 9.9.9 diff --git a/Podfile b/Podfile index 166b10a..871c01f 100644 --- a/Podfile +++ b/Podfile @@ -24,13 +24,13 @@ end target 'UnitTests' do core_pods - pod 'AEPTestUtils', :git => 'https://github.com/adobe/aepsdk-testutils-ios.git', :tag => '5.1.0' + pod 'AEPTestUtils', :git => 'https://github.com/adobe/aepsdk-core-ios.git', :tag => 'testutils-5.2.2' end target 'FunctionalTests' do core_pods edge_pods - pod 'AEPTestUtils', :git => 'https://github.com/adobe/aepsdk-testutils-ios.git', :tag => '5.1.0' + pod 'AEPTestUtils', :git => 'https://github.com/adobe/aepsdk-core-ios.git', :tag => 'testutils-5.2.2' end target 'TestAppSwiftUI' do diff --git a/Podfile.lock b/Podfile.lock index 48b47a9..3f4bd73 100644 --- a/Podfile.lock +++ b/Podfile.lock @@ -2,21 +2,21 @@ PODS: - AEPAssurance (5.0.1): - AEPCore (< 6.0.0, >= 5.0.0) - AEPServices (< 6.0.0, >= 5.0.0) - - AEPCore (5.2.0): + - AEPCore (5.3.1): - AEPRulesEngine (< 6.0.0, >= 5.0.0) - - AEPServices (< 6.0.0, >= 5.2.0) - - AEPEdge (5.0.2): - - AEPCore (< 6.0.0, >= 5.1.0) + - AEPServices (< 6.0.0, >= 5.3.1) + - AEPEdge (5.0.3): + - AEPCore (< 6.0.0, >= 5.3.1) - AEPEdgeIdentity (< 6.0.0, >= 5.0.0) - AEPEdgeIdentity (5.0.0): - AEPCore (< 6.0.0, >= 5.0.0) - - AEPLifecycle (5.2.0): - - AEPCore (< 6.0.0, >= 5.2.0) + - AEPLifecycle (5.3.1): + - AEPCore (< 6.0.0, >= 5.3.1) - AEPRulesEngine (5.0.0) - - AEPServices (5.2.0) - - AEPTestUtils (5.1.0): - - AEPCore (>= 5.2.0) - - AEPServices (>= 5.2.0) + - AEPServices (5.3.1) + - AEPTestUtils (5.2.2): + - AEPCore (< 6.0.0, >= 5.2.0) + - AEPServices (< 6.0.0, >= 5.2.0) - SwiftLint (0.52.0) DEPENDENCIES: @@ -25,7 +25,7 @@ DEPENDENCIES: - AEPEdge - AEPEdgeIdentity - AEPLifecycle - - AEPTestUtils (from `https://github.com/adobe/aepsdk-testutils-ios.git`, tag `5.1.0`) + - AEPTestUtils (from `https://github.com/adobe/aepsdk-core-ios.git`, tag `testutils-5.2.2`) - SwiftLint (= 0.52.0) SPEC REPOS: @@ -41,25 +41,25 @@ SPEC REPOS: EXTERNAL SOURCES: AEPTestUtils: - :git: https://github.com/adobe/aepsdk-testutils-ios.git - :tag: 5.1.0 + :git: https://github.com/adobe/aepsdk-core-ios.git + :tag: testutils-5.2.2 CHECKOUT OPTIONS: AEPTestUtils: - :git: https://github.com/adobe/aepsdk-testutils-ios.git - :tag: 5.1.0 + :git: https://github.com/adobe/aepsdk-core-ios.git + :tag: testutils-5.2.2 SPEC CHECKSUMS: AEPAssurance: df04baeace42befb0cc213fd6cdfe51651d11ba6 - AEPCore: db53082c207c28166ed6aa9ae6262a55e95c78aa - AEPEdge: edf73ae8900016940cd7fcb29a89a576a1c6b0ae + AEPCore: 28191f2df03225a5e88b6f8f343f7e18a604c9ef + AEPEdge: 105afc7958acd7c016d57f7ac1d6f632bf05e6ee AEPEdgeIdentity: 3161ff33434586962946912d6b8e9e8fca1c4d23 - AEPLifecycle: 0e2ddb26751320b88ea7471e63751f38c4ccdc10 + AEPLifecycle: b2c4d928a8556410b8d2ef5763432bc97ebde417 AEPRulesEngine: fe5800653a4bee07b1e41e61b4d5551f0dba557b - AEPServices: d959143d13fde7e8464c19527df6baacdef765ce - AEPTestUtils: b2c941b4f72deaff090e3e82b8c1ac31fedc1c84 + AEPServices: fcba979e90f6916b066aa66f016700d7b7534d96 + AEPTestUtils: 61de2086056f4aa3223dc7d035991ef4fdacbfdb SwiftLint: 13280e21cdda6786ad908dc6e416afe5acd1fcb7 -PODFILE CHECKSUM: b41815d0b57c8a3387c9e217e84ddfc6d26dc725 +PODFILE CHECKSUM: ab023bfb377bd9fe329464e9be31de7a99f5d0ef -COCOAPODS: 1.14.3 +COCOAPODS: 1.16.2 diff --git a/Script/update-versions.sh b/Script/update-versions.sh deleted file mode 100644 index 3170410..0000000 --- a/Script/update-versions.sh +++ /dev/null @@ -1,100 +0,0 @@ -#!/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"/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 diff --git a/Script/version.sh b/Script/version.sh deleted file mode 100755 index c09b397..0000000 --- a/Script/version.sh +++ /dev/null @@ -1,29 +0,0 @@ -#!/usr/bin/env bash - -set -e - -if which jq >/dev/null; then - echo "jq is installed" -else - echo "error: jq not installed.(brew install jq)" -fi - -NC='\033[0m' -RED='\033[0;31m' -GREEN='\033[0;32m' -BLUE='\033[0;34m' - -echo "Target version - ${BLUE}$1${NC}" -echo "------------------AEPEdgeBridge-------------------" -PODSPEC_VERSION=$(pod ipc spec AEPEdgeBridge.podspec | jq '.version' | tr -d '"') -echo "Local podspec version - ${BLUE}${PODSPEC_VERSION}${NC}" -SOUCE_CODE_VERSION=$(cat ./Sources/EdgeBridgeConstants.swift | egrep '\s*EXTENSION_VERSION\s*=\s*\"(.*)\"' | ruby -e "puts gets.scan(/\"(.*)\"/)[0] " | tr -d '"') -echo "Souce code version - ${BLUE}${SOUCE_CODE_VERSION}${NC}" - -if [[ "$1" == "$PODSPEC_VERSION" ]] && [[ "$1" == "$SOUCE_CODE_VERSION" ]]; then - echo "${GREEN}Pass!${NC}" -else - echo "${RED}[Error]${NC} Version do not match!" - exit -1 -fi -exit 0 diff --git a/Tests/FunctionalTests/EdgeBridgeFunctionalTests.swift b/Tests/FunctionalTests/EdgeBridgeFunctionalTests.swift index 852c4a2..add0593 100644 --- a/Tests/FunctionalTests/EdgeBridgeFunctionalTests.swift +++ b/Tests/FunctionalTests/EdgeBridgeFunctionalTests.swift @@ -21,16 +21,17 @@ import AEPServices import AEPTestUtils class EdgeBridgeFunctionalTests: TestBase, AnyCodableAsserts { + private let TIMEOUT_SEC: TimeInterval = FunctionalTestConstants.Defaults.TIMEOUT_SEC private let edgeInteractEndpoint = "https://edge.adobedc.net/ee/v1/interact?" private let mockNetworkService: MockNetworkService = MockNetworkService() public class override func setUp() { super.setUp() - TestBase.debugEnabled = true } override func setUp() { + loggingEnabled = true super.setUp() ServiceProvider.shared.networkService = mockNetworkService continueAfterFailure = false @@ -49,7 +50,7 @@ class EdgeBridgeFunctionalTests: TestBase, AnyCodableAsserts { print("Extensions registration is complete") waitForRegistration.countDown() }) - XCTAssertEqual(DispatchTimeoutResult.success, waitForRegistration.await(timeout: 2)) + XCTAssertEqual(DispatchTimeoutResult.success, waitForRegistration.await(timeout: TIMEOUT_SEC)) MobileCore.updateConfigurationWith(configDict: ["edge.configId": "12345-example"]) assertExpectedEvents(ignoreUnexpectedEvents: false) @@ -73,8 +74,8 @@ class EdgeBridgeFunctionalTests: TestBase, AnyCodableAsserts { waitForProcessing() // verify - mockNetworkService.assertAllNetworkRequestExpectations() - let networkRequests = mockNetworkService.getNetworkRequestsWith(url: edgeInteractEndpoint, httpMethod: .post) + mockNetworkService.assertAllNetworkRequestExpectations(timeout: TIMEOUT_SEC) + let networkRequests = mockNetworkService.getNetworkRequestsWith(url: edgeInteractEndpoint, httpMethod: .post, timeout: TIMEOUT_SEC) XCTAssertEqual(1, networkRequests.count) let expectedJSON = """ @@ -119,8 +120,8 @@ class EdgeBridgeFunctionalTests: TestBase, AnyCodableAsserts { waitForProcessing() // verify - mockNetworkService.assertAllNetworkRequestExpectations() - let networkRequests = mockNetworkService.getNetworkRequestsWith(url: edgeInteractEndpoint, httpMethod: .post) + mockNetworkService.assertAllNetworkRequestExpectations(timeout: TIMEOUT_SEC) + let networkRequests = mockNetworkService.getNetworkRequestsWith(url: edgeInteractEndpoint, httpMethod: .post, timeout: TIMEOUT_SEC) XCTAssertEqual(1, networkRequests.count) let expectedJSON = """ @@ -169,8 +170,8 @@ class EdgeBridgeFunctionalTests: TestBase, AnyCodableAsserts { waitForProcessing() // verify - mockNetworkService.assertAllNetworkRequestExpectations() - let networkRequests = mockNetworkService.getNetworkRequestsWith(url: edgeInteractEndpoint, httpMethod: .post) + mockNetworkService.assertAllNetworkRequestExpectations(timeout: TIMEOUT_SEC) + let networkRequests = mockNetworkService.getNetworkRequestsWith(url: edgeInteractEndpoint, httpMethod: .post, timeout: TIMEOUT_SEC) XCTAssertEqual(1, networkRequests.count) // Data is defined in the rule, not from the dispatched PII event @@ -222,7 +223,7 @@ class EdgeBridgeFunctionalTests: TestBase, AnyCodableAsserts { MobileCore.updateConfigurationWith(configDict: ["rules.url": "https://rules.com/\(localRulesName).zip"]) - mockNetworkService.assertAllNetworkRequestExpectations() + mockNetworkService.assertAllNetworkRequestExpectations(timeout: TIMEOUT_SEC) } /// Waits for a specified interval without blocking main thread. diff --git a/Tests/FunctionalTests/util/FunctionalTestConstants.swift b/Tests/FunctionalTests/util/FunctionalTestConstants.swift new file mode 100644 index 0000000..62f190f --- /dev/null +++ b/Tests/FunctionalTests/util/FunctionalTestConstants.swift @@ -0,0 +1,20 @@ +// +// Copyright 2024 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 +// +// 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 Foundation + +enum FunctionalTestConstants { + enum Defaults { + // Default timeout for assertions. Set to a high value to accommodate slower CI runners. + static let TIMEOUT_SEC: TimeInterval = 10 + } +}