From 169e81b3dd5f8d66036949d2bad05132452c712a Mon Sep 17 00:00:00 2001
From: cdillard-NewRelic <cdillard-NewRelic@users.noreply.github.com>
Date: Tue, 26 Sep 2023 23:41:37 +0000
Subject: [PATCH 1/9] [7.4.7-rc.589] Staging Release

---
 Gemfile.lock          | 41 ++++++++++++++++++++---------------------
 NewRelicAgent.podspec |  4 ++--
 Package.swift         |  4 ++--
 3 files changed, 24 insertions(+), 25 deletions(-)

diff --git a/Gemfile.lock b/Gemfile.lock
index 0edfcc30..aeba6072 100644
--- a/Gemfile.lock
+++ b/Gemfile.lock
@@ -3,13 +3,13 @@ GEM
   specs:
     CFPropertyList (3.0.6)
       rexml
-    addressable (2.8.4)
+    addressable (2.8.5)
       public_suffix (>= 2.0.2, < 6.0)
     artifactory (3.0.15)
     atomos (0.1.3)
     aws-eventstream (1.2.0)
-    aws-partitions (1.785.0)
-    aws-sdk-core (3.178.0)
+    aws-partitions (1.828.0)
+    aws-sdk-core (3.183.1)
       aws-eventstream (~> 1, >= 1.0.2)
       aws-partitions (~> 1, >= 1.651.0)
       aws-sigv4 (~> 1.5)
@@ -17,8 +17,8 @@ GEM
     aws-sdk-kms (1.71.0)
       aws-sdk-core (~> 3, >= 3.177.0)
       aws-sigv4 (~> 1.1)
-    aws-sdk-s3 (1.129.0)
-      aws-sdk-core (~> 3, >= 3.177.0)
+    aws-sdk-s3 (1.136.0)
+      aws-sdk-core (~> 3, >= 3.181.0)
       aws-sdk-kms (~> 1)
       aws-sigv4 (~> 1.6)
     aws-sigv4 (1.6.0)
@@ -36,7 +36,7 @@ GEM
       unf (>= 0.0.5, < 1.0.0)
     dotenv (2.8.1)
     emoji_regex (3.2.3)
-    excon (0.100.0)
+    excon (0.103.0)
     faraday (1.10.3)
       faraday-em_http (~> 1.0)
       faraday-em_synchrony (~> 1.0)
@@ -66,7 +66,7 @@ GEM
     faraday_middleware (1.2.0)
       faraday (~> 1.0)
     fastimage (2.2.7)
-    fastlane (2.213.0)
+    fastlane (2.216.0)
       CFPropertyList (>= 2.3, < 4.0.0)
       addressable (>= 2.8, < 3.0.0)
       artifactory (~> 3.0)
@@ -87,6 +87,7 @@ GEM
       google-apis-playcustomapp_v1 (~> 0.1)
       google-cloud-storage (~> 1.31)
       highline (~> 2.0)
+      http-cookie (~> 1.0.5)
       json (< 3.0.0)
       jwt (>= 2.1.0, < 3)
       mini_magick (>= 4.9.4, < 5.0.0)
@@ -98,7 +99,7 @@ GEM
       security (= 0.1.3)
       simctl (~> 1.6.3)
       terminal-notifier (>= 2.0.0, < 3.0.0)
-      terminal-table (>= 1.4.5, < 2.0.0)
+      terminal-table (~> 3)
       tty-screen (>= 0.6.3, < 1.0.0)
       tty-spinner (>= 0.8.0, < 1.0.0)
       word_wrap (~> 1.0.0)
@@ -106,9 +107,9 @@ GEM
       xcpretty (~> 0.3.0)
       xcpretty-travis-formatter (>= 0.0.3)
     gh_inspector (1.1.3)
-    google-apis-androidpublisher_v3 (0.45.0)
+    google-apis-androidpublisher_v3 (0.50.0)
       google-apis-core (>= 0.11.0, < 2.a)
-    google-apis-core (0.11.0)
+    google-apis-core (0.11.1)
       addressable (~> 2.5, >= 2.5.1)
       googleauth (>= 0.16.2, < 2.a)
       httpclient (>= 2.8.1, < 3.a)
@@ -137,10 +138,9 @@ GEM
       google-cloud-core (~> 1.6)
       googleauth (>= 0.16.2, < 2.a)
       mini_mime (~> 1.0)
-    googleauth (1.6.0)
+    googleauth (1.8.1)
       faraday (>= 0.17.3, < 3.a)
       jwt (>= 1.4, < 3.0)
-      memoist (~> 0.16)
       multi_json (~> 1.11)
       os (>= 0.9, < 2.0)
       signet (>= 0.16, < 2.a)
@@ -151,9 +151,8 @@ GEM
     jmespath (1.6.2)
     json (2.6.3)
     jwt (2.7.1)
-    memoist (0.16.2)
     mini_magick (4.12.0)
-    mini_mime (1.1.2)
+    mini_mime (1.1.5)
     multi_json (1.15.0)
     multipart-post (2.3.0)
     nanaimo (0.3.0)
@@ -168,12 +167,12 @@ GEM
       trailblazer-option (>= 0.1.1, < 0.2.0)
       uber (< 0.2.0)
     retriable (3.1.2)
-    rexml (3.2.5)
+    rexml (3.2.6)
     rouge (2.0.7)
     ruby2_keywords (0.0.5)
     rubyzip (2.3.2)
     security (0.1.3)
-    signet (0.17.0)
+    signet (0.18.0)
       addressable (~> 2.8)
       faraday (>= 0.17.5, < 3.a)
       jwt (>= 1.5, < 3.0)
@@ -182,8 +181,8 @@ GEM
       CFPropertyList
       naturally
     terminal-notifier (2.0.0)
-    terminal-table (1.8.0)
-      unicode-display_width (~> 1.1, >= 1.1.1)
+    terminal-table (3.0.2)
+      unicode-display_width (>= 1.1.1, < 3)
     trailblazer-option (0.1.2)
     tty-cursor (0.7.1)
     tty-screen (0.8.1)
@@ -193,10 +192,10 @@ GEM
     unf (0.1.4)
       unf_ext
     unf_ext (0.0.8.2)
-    unicode-display_width (1.8.0)
+    unicode-display_width (2.4.2)
     webrick (1.8.1)
     word_wrap (1.0.0)
-    xcodeproj (1.22.0)
+    xcodeproj (1.23.0)
       CFPropertyList (>= 2.3.3, < 4.0)
       atomos (~> 0.1.3)
       claide (>= 1.0.2, < 2.0)
@@ -216,4 +215,4 @@ DEPENDENCIES
   fastlane
 
 BUNDLED WITH
-   2.4.14
+   2.4.19
diff --git a/NewRelicAgent.podspec b/NewRelicAgent.podspec
index 8100d0f2..4a04aa33 100644
--- a/NewRelicAgent.podspec
+++ b/NewRelicAgent.podspec
@@ -1,12 +1,12 @@
 
 Pod::Spec.new do |s|
   s.name                   = "NewRelicAgent"
-  s.version                = "7.4.5"
+  s.version                = "7.4.7-rc.589"
   s.summary                = "Real-time performance data with your next iOS app release."
   s.homepage               = "http://newrelic.com/mobile-monitoring"
   s.license                = { :type => "Commercial", :file => "LICENSE" }
   s.author                 = { "New Relic, Inc." => "support@newrelic.com" }
-  s.source                 = { :http => "https://download.newrelic.com/ios_agent/NewRelic_XCFramework_Agent_7.4.5.zip" }
+  s.source                 = { :http => "https://download.newrelic.com/ios-v5/NewRelic_XCFramework_Agent_7.4.7-rc.589.zip" }
   s.ios.deployment_target  = '9.0'
   s.tvos.deployment_target = '9.0'
   s.vendored_frameworks    = "NewRelic.xcframework"
diff --git a/Package.swift b/Package.swift
index 7fe9d4dd..9422c70d 100644
--- a/Package.swift
+++ b/Package.swift
@@ -19,8 +19,8 @@ let package = Package(
             name: "NewRelicPackage",
             dependencies: []),
         .binaryTarget(name: "NewRelic",
-                      url: "https://download.newrelic.com/ios_agent/NewRelic_XCFramework_Agent_7.4.6.zip",
-                      checksum: "fbc16421b13f5fbdc33693afac297bc4f5d66946ceefd53d8afb1696d6b934d2")
+                      url: "https://download.newrelic.com/ios-v5/NewRelic_XCFramework_Agent_7.4.7-rc.589.zip",
+                      checksum: "4d5b8b8415d7e4d98fc12f1bf78347fe4f52c85bea0660be96c17d2a1a705752")
     ]
 )
 

From fdaec87ff2e559a08b0b4870f4853861ba224232 Mon Sep 17 00:00:00 2001
From: Chris Dillard <cdillard@newrelic.com>
Date: Thu, 28 Sep 2023 13:49:50 -0600
Subject: [PATCH 2/9] do cocoapods, then swift pm

---
 .github/workflows/productionDeploy.yml | 58 +++++++++++++-------------
 1 file changed, 29 insertions(+), 29 deletions(-)

diff --git a/.github/workflows/productionDeploy.yml b/.github/workflows/productionDeploy.yml
index 8f36358c..b099244c 100644
--- a/.github/workflows/productionDeploy.yml
+++ b/.github/workflows/productionDeploy.yml
@@ -66,46 +66,46 @@ jobs:
     - name: Print XCFramework name
       run: echo "${{ env.version }}" 
 
-    # - name: Create Prod Podspec for XCFramework version
-    #   run: |
-    #      cd main
+    - name: Create Prod Podspec for XCFramework version
+      run: |
+         cd main
 
-    #      cp cocoapods/NewRelicAgent.podspec.template NewRelicAgent.podspec
-    #      REPLACE=X.XX
-    #      sed -i bak "s/$REPLACE/${{ env.version }}/g" NewRelicAgent.podspec
+         cp cocoapods/NewRelicAgent.podspec.template NewRelicAgent.podspec
+         REPLACE=X.XX
+         sed -i bak "s/$REPLACE/${{ env.version }}/g" NewRelicAgent.podspec
 
-    #      rm NewRelicAgent.podspecbak
+         rm NewRelicAgent.podspecbak
 
-    #      pod trunk push --allow-warnings NewRelicAgent.podspec
-    #   env:
-    #      COCOAPODS_TRUNK_TOKEN: ${{ secrets.COCOAPODS_TRUNK_TOKEN }}
+         pod trunk push --allow-warnings NewRelicAgent.podspec
+      env:
+         COCOAPODS_TRUNK_TOKEN: ${{ secrets.COCOAPODS_TRUNK_TOKEN }}
 
-    - name: Create Prod Package.swift for XCFramework version
-      run: |
-       cp main/NewRelic-SwiftPackage/Package.swift.template spm/Package.swift
-       cd spm
+    # - name: Create Prod Package.swift for XCFramework version
+    #   run: |
+    #    cp main/NewRelic-SwiftPackage/Package.swift.template spm/Package.swift
+    #    cd spm
 
-       REPLACEVER={{VERSION}}
-       REPLACECHECKSUM={{CHECKSUM}}
+    #    REPLACEVER={{VERSION}}
+    #    REPLACECHECKSUM={{CHECKSUM}}
 
-       XCFRAMEWORK_NAME="NewRelic_XCFramework_Agent_${{ env.version }}.zip"
-       curl https://download.newrelic.com/ios_agent/$XCFRAMEWORK_NAME -o $XCFRAMEWORK_NAME
-       SPM_CHECKSUM=`swift package compute-checksum  ${XCFRAMEWORK_NAME}`
+    #    XCFRAMEWORK_NAME="NewRelic_XCFramework_Agent_${{ env.version }}.zip"
+    #    curl https://download.newrelic.com/ios_agent/$XCFRAMEWORK_NAME -o $XCFRAMEWORK_NAME
+    #    SPM_CHECKSUM=`swift package compute-checksum  ${XCFRAMEWORK_NAME}`
 
-       sed -i bak "s/$REPLACEVER/${{ env.version }}/g" Package.swift
-       sed -i -e "s/$REPLACECHECKSUM/$SPM_CHECKSUM/g" Package.swift
+    #    sed -i bak "s/$REPLACEVER/${{ env.version }}/g" Package.swift
+    #    sed -i -e "s/$REPLACECHECKSUM/$SPM_CHECKSUM/g" Package.swift
 
-       rm Package.swift-e
-       rm Package.swiftbak
+    #    rm Package.swift-e
+    #    rm Package.swiftbak
 
-       rm $XCFRAMEWORK_NAME
+    #    rm $XCFRAMEWORK_NAME
                 
-       git add Package.swift
-       git commit -m "Added build ${{ env.version }}"
-       git tag ${{ env.version }}
-       git push origin main --tags
+    #    git add Package.swift
+    #    git commit -m "Added build ${{ env.version }}"
+    #    git tag ${{ env.version }}
+    #    git push origin main --tags
 
-       cp Package.swift ../main/
+    #    cp Package.swift ../main/
 
      # At this point we have NewRelicAgent.podspec and Package.swift corresponding to the production build sitting at the repo root.
      # The following step creates a PR containing that new NewRelicAgent.podspec and Package.swift file at the root of the repo.

From 52251d1e60399f3111120321141488dfd945ef23 Mon Sep 17 00:00:00 2001
From: Chris Dillard <cdillard@newrelic.com>
Date: Mon, 2 Oct 2023 11:37:50 -0600
Subject: [PATCH 3/9] push SPM change for 7.4.7

---
 .github/workflows/productionDeploy.yml | 58 +++++++++++++-------------
 1 file changed, 29 insertions(+), 29 deletions(-)

diff --git a/.github/workflows/productionDeploy.yml b/.github/workflows/productionDeploy.yml
index b099244c..8f36358c 100644
--- a/.github/workflows/productionDeploy.yml
+++ b/.github/workflows/productionDeploy.yml
@@ -66,46 +66,46 @@ jobs:
     - name: Print XCFramework name
       run: echo "${{ env.version }}" 
 
-    - name: Create Prod Podspec for XCFramework version
-      run: |
-         cd main
+    # - name: Create Prod Podspec for XCFramework version
+    #   run: |
+    #      cd main
 
-         cp cocoapods/NewRelicAgent.podspec.template NewRelicAgent.podspec
-         REPLACE=X.XX
-         sed -i bak "s/$REPLACE/${{ env.version }}/g" NewRelicAgent.podspec
+    #      cp cocoapods/NewRelicAgent.podspec.template NewRelicAgent.podspec
+    #      REPLACE=X.XX
+    #      sed -i bak "s/$REPLACE/${{ env.version }}/g" NewRelicAgent.podspec
 
-         rm NewRelicAgent.podspecbak
+    #      rm NewRelicAgent.podspecbak
 
-         pod trunk push --allow-warnings NewRelicAgent.podspec
-      env:
-         COCOAPODS_TRUNK_TOKEN: ${{ secrets.COCOAPODS_TRUNK_TOKEN }}
+    #      pod trunk push --allow-warnings NewRelicAgent.podspec
+    #   env:
+    #      COCOAPODS_TRUNK_TOKEN: ${{ secrets.COCOAPODS_TRUNK_TOKEN }}
 
-    # - name: Create Prod Package.swift for XCFramework version
-    #   run: |
-    #    cp main/NewRelic-SwiftPackage/Package.swift.template spm/Package.swift
-    #    cd spm
+    - name: Create Prod Package.swift for XCFramework version
+      run: |
+       cp main/NewRelic-SwiftPackage/Package.swift.template spm/Package.swift
+       cd spm
 
-    #    REPLACEVER={{VERSION}}
-    #    REPLACECHECKSUM={{CHECKSUM}}
+       REPLACEVER={{VERSION}}
+       REPLACECHECKSUM={{CHECKSUM}}
 
-    #    XCFRAMEWORK_NAME="NewRelic_XCFramework_Agent_${{ env.version }}.zip"
-    #    curl https://download.newrelic.com/ios_agent/$XCFRAMEWORK_NAME -o $XCFRAMEWORK_NAME
-    #    SPM_CHECKSUM=`swift package compute-checksum  ${XCFRAMEWORK_NAME}`
+       XCFRAMEWORK_NAME="NewRelic_XCFramework_Agent_${{ env.version }}.zip"
+       curl https://download.newrelic.com/ios_agent/$XCFRAMEWORK_NAME -o $XCFRAMEWORK_NAME
+       SPM_CHECKSUM=`swift package compute-checksum  ${XCFRAMEWORK_NAME}`
 
-    #    sed -i bak "s/$REPLACEVER/${{ env.version }}/g" Package.swift
-    #    sed -i -e "s/$REPLACECHECKSUM/$SPM_CHECKSUM/g" Package.swift
+       sed -i bak "s/$REPLACEVER/${{ env.version }}/g" Package.swift
+       sed -i -e "s/$REPLACECHECKSUM/$SPM_CHECKSUM/g" Package.swift
 
-    #    rm Package.swift-e
-    #    rm Package.swiftbak
+       rm Package.swift-e
+       rm Package.swiftbak
 
-    #    rm $XCFRAMEWORK_NAME
+       rm $XCFRAMEWORK_NAME
                 
-    #    git add Package.swift
-    #    git commit -m "Added build ${{ env.version }}"
-    #    git tag ${{ env.version }}
-    #    git push origin main --tags
+       git add Package.swift
+       git commit -m "Added build ${{ env.version }}"
+       git tag ${{ env.version }}
+       git push origin main --tags
 
-    #    cp Package.swift ../main/
+       cp Package.swift ../main/
 
      # At this point we have NewRelicAgent.podspec and Package.swift corresponding to the production build sitting at the repo root.
      # The following step creates a PR containing that new NewRelicAgent.podspec and Package.swift file at the root of the repo.

From 9e1d7838532cb504b5f5088e1e50fd05b0fe0534 Mon Sep 17 00:00:00 2001
From: mbruin-NR <118208503+mbruin-NR@users.noreply.github.com>
Date: Mon, 2 Oct 2023 14:05:21 -0400
Subject: [PATCH 4/9] Branching from the main for beta tests (#133)

* Branching from the main for beta tests

* This should fix the tvOS beta not being found

* Added tvOS app tests

* Added a step to the app unit tests to add a secret api key

* Fixed some typos
---
 .github/workflows/beta-tests.yml              | 125 ++++++++++++++++++
 .../NRTestApp_tvOS_Tests.swift                |  95 +++++++++++++
 .../NRTestApp_tvOS_TestsLaunchTests.swift     |  32 +++++
 .../NRTestApp.xcodeproj/project.pbxproj       | 123 ++++++++++++++++-
 .../xcschemes/NRTestApp (tvOS).xcscheme       |  11 ++
 fastlane/README.md                            |  40 ++++++
 fastlane/TestFastfile                         |  56 ++++++++
 fastlane/UtilityFastfile                      |  16 +++
 scripts/plist_editor.swift                    |  53 ++++++++
 9 files changed, 550 insertions(+), 1 deletion(-)
 create mode 100644 .github/workflows/beta-tests.yml
 create mode 100644 Test Harness/NRTestApp/NRTestApp(tvOS)Tests/NRTestApp_tvOS_Tests.swift
 create mode 100644 Test Harness/NRTestApp/NRTestApp(tvOS)Tests/NRTestApp_tvOS_TestsLaunchTests.swift
 create mode 100755 scripts/plist_editor.swift

diff --git a/.github/workflows/beta-tests.yml b/.github/workflows/beta-tests.yml
new file mode 100644
index 00000000..ac332b0d
--- /dev/null
+++ b/.github/workflows/beta-tests.yml
@@ -0,0 +1,125 @@
+name: beta-tests
+on: 
+  workflow_dispatch:
+    inputs:
+      xcode_version:
+        required: true
+        default: latest
+      os_version:
+        required: true
+        default: '17.0'
+
+jobs:
+  testIOSBeta:
+    name : TestIOSBeta
+    # runs-on: will be set to macos-latest when running on actual GHA. 
+    # *** runs-on: ubuntu-latest is used when running via act on mac os. ***
+    runs-on: macos-13 
+    steps:
+
+    - name: Print version info
+      run: echo "version=${{ github.event.inputs.xcode_version }}"
+
+    - uses: actions/checkout@master
+      with: 
+        submodules: true
+    
+    - uses: maxim-lobanov/setup-xcode@v1
+      with:
+        xcode-version: ${{ github.event.inputs.xcode_version }}
+
+    - name: Install lcov
+      run: brew install lcov
+
+    - name: Update gem
+      run: bundle update
+
+    - name: Install gems
+      run: bundle install
+
+    - name: Run tests on iOS (using fastlane)
+      run: bundle exec fastlane runIOSBetaTests os_version:${{ github.event.inputs.os_version }}
+
+  testIOSAppBeta:
+    name : TestIOSAppBeta
+    # runs-on: will be set to macos-latest when running on actual GHA. 
+    # *** runs-on: ubuntu-latest is used when running via act on mac os. ***
+    runs-on: macos-13 
+    steps:
+    - uses: actions/checkout@master
+      with: 
+        submodules: true
+    
+    - uses: maxim-lobanov/setup-xcode@v1
+      with:
+        xcode-version: ${{ github.event.inputs.xcode_version }}
+
+    - name: Install lcov
+      run: brew install lcov
+
+    - name: Update gem
+      run: bundle update
+
+    - name: Install gems
+      run: bundle install
+
+    - name: Run script to add New Relic API Key
+      run: bundle exec fastlane addAPIKeyToPlist valueToAdd:${{ secrets.NEWRELIC_API_KEY }}
+
+    - name: Run app tests on iOS (using fastlane)
+      run: bundle exec fastlane runIOSAppBetaTests os_version:${{ github.event.inputs.os_version }}
+
+  testTVOSBeta:
+    name : TestTVOSBeta
+    # runs-on: will be set to macos-latest when running on actual GHA. 
+    # *** runs-on: ubuntu-latest is used when running via act on mac os. ***
+    runs-on: macos-13 
+    steps:
+    - uses: actions/checkout@v3
+      with: 
+        submodules: true
+    
+    - uses: maxim-lobanov/setup-xcode@v1
+      with:
+        xcode-version: ${{ github.event.inputs.xcode_version }}
+
+    - name: Install lcov
+      run: brew install lcov
+
+    - name: Update gem
+      run: bundle update
+
+    - name: Install gems
+      run: bundle install
+
+    - name: Run tests on tvOS (using fastlane)
+      run: bundle exec fastlane runTVOSBetaTests os_version:${{ github.event.inputs.os_version }}
+
+  testTVOSAppBeta:
+    name : TestTVOSAppBeta
+    # runs-on: will be set to macos-latest when running on actual GHA. 
+    # *** runs-on: ubuntu-latest is used when running via act on mac os. ***
+    runs-on: macos-13 
+    steps:
+    - uses: actions/checkout@v3
+      with: 
+        submodules: true
+    
+    - uses: maxim-lobanov/setup-xcode@v1
+      with:
+        xcode-version: ${{ github.event.inputs.xcode_version }}
+
+    - name: Install lcov
+      run: brew install lcov
+
+    - name: Update gem
+      run: bundle update
+
+    - name: Install gems
+      run: bundle install
+
+    - name: Run script to add New Relic API Key
+      run: bundle exec fastlane addAPIKeyToPlist valueToAdd:${{ secrets.NEWRELIC_API_KEY }}
+
+    - name: Run app tests on tvOS (using fastlane)
+      run: bundle exec fastlane runTVOSAppBetaTests os_version:${{ github.event.inputs.os_version }}
diff --git a/Test Harness/NRTestApp/NRTestApp(tvOS)Tests/NRTestApp_tvOS_Tests.swift b/Test Harness/NRTestApp/NRTestApp(tvOS)Tests/NRTestApp_tvOS_Tests.swift
new file mode 100644
index 00000000..4eeb24a4
--- /dev/null
+++ b/Test Harness/NRTestApp/NRTestApp(tvOS)Tests/NRTestApp_tvOS_Tests.swift	
@@ -0,0 +1,95 @@
+//
+//  NRTestApp_tvOS_Tests.swift
+//  NRTestApp(tvOS)Tests
+//
+//  Created by Mike Bruin on 9/1/23.
+//
+
+import XCTest
+
+final class NRTestApp_tvOS_Tests: XCTestCase {
+
+    override func setUpWithError() throws {
+        // Put setup code here. This method is called before the invocation of each test method in the class.
+
+        // In UI tests it is usually best to stop immediately when a failure occurs.
+        continueAfterFailure = false
+
+        // In UI tests it’s important to set the initial state - such as interface orientation - required for your tests before they run. The setUp method is a good place to do this.
+    }
+
+    override func tearDownWithError() throws {
+        // Put teardown code here. This method is called after the invocation of each test method in the class.
+    }
+
+    func testExample() throws {
+        // UI tests must launch the application that they test.
+        let app = XCUIApplication()
+        app.launch()
+
+        // Use XCTAssert and related functions to verify your tests produce the correct results.
+    }
+
+    func testLaunchPerformance() throws {
+        if #available(macOS 10.15, iOS 13.0, tvOS 13.0, watchOS 7.0, *) {
+            // This measures how long it takes to launch your application.
+            measure(metrics: [XCTApplicationLaunchMetric()]) {
+                XCUIApplication().launch()
+            }
+        }
+    }
+    
+    func testSetMaxEventPoolSize(){
+        var i = 0
+        let app = XCUIApplication()
+        //max event pool size was set to 10 in app delegate
+        while i <= 10 {
+            app.launch()
+            app.terminate()
+            i += 1
+        }
+        XCTAssertNoThrow(app.launch(), "An event after max pool has been reached should not cause crash")
+    }
+    
+    func testNavigation() throws {
+        //Navigate through the app and make sure all screens load properly
+        let app = XCUIApplication()
+        app.launch()
+        
+        XCUIRemote.shared.press(.select)
+        XCUIRemote.shared.press(.menu)
+
+        sleep(1)
+        XCUIRemote.shared.press(.down)
+        sleep(1)
+        XCUIRemote.shared.press(.select)
+
+        sleep(1)
+        XCUIRemote.shared.press(.down)
+        sleep(1)
+        XCUIRemote.shared.press(.select)
+        sleep(1)
+        app.terminate()
+    }
+    
+    func testUtilities() throws {
+        //Navigate through the app and make sure all screens load properly
+        let app = XCUIApplication()
+        app.launch()
+        
+        let crashCell = app.tables.cells.staticTexts["Crash Now!"]
+        
+        XCUIRemote.shared.press(.select)
+        
+        for cell in app.tables.cells.allElementsBoundByIndex {
+            if !cell.staticTexts["Crash Now!"].exists {
+                XCUIRemote.shared.press(.select)
+            }
+            XCUIRemote.shared.press(.down)
+        }
+        
+        app.terminate()
+        app.launch()
+    }
+}
+
diff --git a/Test Harness/NRTestApp/NRTestApp(tvOS)Tests/NRTestApp_tvOS_TestsLaunchTests.swift b/Test Harness/NRTestApp/NRTestApp(tvOS)Tests/NRTestApp_tvOS_TestsLaunchTests.swift
new file mode 100644
index 00000000..e8aff5ef
--- /dev/null
+++ b/Test Harness/NRTestApp/NRTestApp(tvOS)Tests/NRTestApp_tvOS_TestsLaunchTests.swift	
@@ -0,0 +1,32 @@
+//
+//  NRTestApp_tvOS_TestsLaunchTests.swift
+//  NRTestApp(tvOS)Tests
+//
+//  Created by Mike Bruin on 9/1/23.
+//
+
+import XCTest
+
+final class NRTestApp_tvOS_TestsLaunchTests: XCTestCase {
+
+    override class var runsForEachTargetApplicationUIConfiguration: Bool {
+        true
+    }
+
+    override func setUpWithError() throws {
+        continueAfterFailure = false
+    }
+
+    func testLaunch() throws {
+        let app = XCUIApplication()
+        app.launch()
+
+        // Insert steps here to perform after app launch but before taking a screenshot,
+        // such as logging into a test account or navigating somewhere in the app
+
+        let attachment = XCTAttachment(screenshot: app.screenshot())
+        attachment.name = "Launch Screen"
+        attachment.lifetime = .keepAlways
+        add(attachment)
+    }
+}
diff --git a/Test Harness/NRTestApp/NRTestApp.xcodeproj/project.pbxproj b/Test Harness/NRTestApp/NRTestApp.xcodeproj/project.pbxproj
index ea7b7ef5..f39396c0 100644
--- a/Test Harness/NRTestApp/NRTestApp.xcodeproj/project.pbxproj	
+++ b/Test Harness/NRTestApp/NRTestApp.xcodeproj/project.pbxproj	
@@ -32,6 +32,8 @@
 		F8302B992970ADC1003EC291 /* UIImageView.swift in Sources */ = {isa = PBXBuildFile; fileRef = F8302B982970ADC1003EC291 /* UIImageView.swift */; };
 		F8302B9B2970B29D003EC291 /* Date.swift in Sources */ = {isa = PBXBuildFile; fileRef = F8302B9A2970B29D003EC291 /* Date.swift */; };
 		F8302B9D2970B3E0003EC291 /* ApodURL.swift in Sources */ = {isa = PBXBuildFile; fileRef = F8302B9C2970B3E0003EC291 /* ApodURL.swift */; };
+		F848CDE42AA270E80082052F /* NRTestApp_tvOS_Tests.swift in Sources */ = {isa = PBXBuildFile; fileRef = F848CDE32AA270E80082052F /* NRTestApp_tvOS_Tests.swift */; };
+		F848CDE62AA270E80082052F /* NRTestApp_tvOS_TestsLaunchTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = F848CDE52AA270E80082052F /* NRTestApp_tvOS_TestsLaunchTests.swift */; };
 		F86428412971BD5B002ABA01 /* UtilitiesViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = F86428402971BD5B002ABA01 /* UtilitiesViewController.swift */; };
 		F86428482971C661002ABA01 /* UtilViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = F86428472971C661002ABA01 /* UtilViewModel.swift */; };
 		F864284C2971DFA5002ABA01 /* triggerException.m in Sources */ = {isa = PBXBuildFile; fileRef = F864284B2971DFA5002ABA01 /* triggerException.m */; };
@@ -104,6 +106,13 @@
 			remoteGlobalIDString = 025658A824EB2AAC00FE3125;
 			remoteInfo = "Stress Tests";
 		};
+		F848CDE72AA270E80082052F /* PBXContainerItemProxy */ = {
+			isa = PBXContainerItemProxy;
+			containerPortal = F8302AED296F5EFA003EC291 /* Project object */;
+			proxyType = 1;
+			remoteGlobalIDString = F86428E92979CDAF002ABA01;
+			remoteInfo = "NRTestApp (tvOS)";
+		};
 /* End PBXContainerItemProxy section */
 
 /* Begin PBXCopyFilesBuildPhase section */
@@ -158,6 +167,9 @@
 		F8302B982970ADC1003EC291 /* UIImageView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UIImageView.swift; sourceTree = "<group>"; };
 		F8302B9A2970B29D003EC291 /* Date.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Date.swift; sourceTree = "<group>"; };
 		F8302B9C2970B3E0003EC291 /* ApodURL.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ApodURL.swift; sourceTree = "<group>"; };
+		F848CDE12AA270E80082052F /* NRTestApp(tvOS)Tests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = "NRTestApp(tvOS)Tests.xctest"; sourceTree = BUILT_PRODUCTS_DIR; };
+		F848CDE32AA270E80082052F /* NRTestApp_tvOS_Tests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NRTestApp_tvOS_Tests.swift; sourceTree = "<group>"; };
+		F848CDE52AA270E80082052F /* NRTestApp_tvOS_TestsLaunchTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NRTestApp_tvOS_TestsLaunchTests.swift; sourceTree = "<group>"; };
 		F86428402971BD5B002ABA01 /* UtilitiesViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UtilitiesViewController.swift; sourceTree = "<group>"; };
 		F86428472971C661002ABA01 /* UtilViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UtilViewModel.swift; sourceTree = "<group>"; };
 		F864284A2971DFA4002ABA01 /* NRTestApp-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "NRTestApp-Bridging-Header.h"; sourceTree = "<group>"; };
@@ -188,6 +200,13 @@
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 		};
+		F848CDDE2AA270E80082052F /* Frameworks */ = {
+			isa = PBXFrameworksBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
 		F86428E72979CDAF002ABA01 /* Frameworks */ = {
 			isa = PBXFrameworksBuildPhase;
 			buildActionMask = 2147483647;
@@ -206,6 +225,7 @@
 				F8302AF7296F5EFA003EC291 /* NRTestApp */,
 				F8302B0E296F5EFB003EC291 /* NRTestAppTests */,
 				F86428EB2979CDAF002ABA01 /* NRTestApp (tvOS) */,
+				F848CDE22AA270E80082052F /* NRTestApp(tvOS)Tests */,
 				F8302AF6296F5EFA003EC291 /* Products */,
 				F8302B8129705B28003EC291 /* Frameworks */,
 			);
@@ -217,6 +237,7 @@
 				F8302AF5296F5EFA003EC291 /* NRTestApp.app */,
 				F8302B0B296F5EFB003EC291 /* NRTestAppTests.xctest */,
 				F86428EA2979CDAF002ABA01 /* NRTestApp (tvOS).app */,
+				F848CDE12AA270E80082052F /* NRTestApp(tvOS)Tests.xctest */,
 			);
 			name = Products;
 			sourceTree = "<group>";
@@ -317,6 +338,15 @@
 			path = Extensions;
 			sourceTree = "<group>";
 		};
+		F848CDE22AA270E80082052F /* NRTestApp(tvOS)Tests */ = {
+			isa = PBXGroup;
+			children = (
+				F848CDE32AA270E80082052F /* NRTestApp_tvOS_Tests.swift */,
+				F848CDE52AA270E80082052F /* NRTestApp_tvOS_TestsLaunchTests.swift */,
+			);
+			path = "NRTestApp(tvOS)Tests";
+			sourceTree = "<group>";
+		};
 		F86428492971DF80002ABA01 /* Helpers */ = {
 			isa = PBXGroup;
 			children = (
@@ -390,6 +420,24 @@
 			productReference = F8302B0B296F5EFB003EC291 /* NRTestAppTests.xctest */;
 			productType = "com.apple.product-type.bundle.unit-test";
 		};
+		F848CDE02AA270E80082052F /* NRTestApp(tvOS)Tests */ = {
+			isa = PBXNativeTarget;
+			buildConfigurationList = F848CDF02AA270E80082052F /* Build configuration list for PBXNativeTarget "NRTestApp(tvOS)Tests" */;
+			buildPhases = (
+				F848CDDD2AA270E80082052F /* Sources */,
+				F848CDDE2AA270E80082052F /* Frameworks */,
+				F848CDDF2AA270E80082052F /* Resources */,
+			);
+			buildRules = (
+			);
+			dependencies = (
+				F848CDE82AA270E80082052F /* PBXTargetDependency */,
+			);
+			name = "NRTestApp(tvOS)Tests";
+			productName = "NRTestApp(tvOS)Tests";
+			productReference = F848CDE12AA270E80082052F /* NRTestApp(tvOS)Tests.xctest */;
+			productType = "com.apple.product-type.bundle.ui-testing";
+		};
 		F86428E92979CDAF002ABA01 /* NRTestApp (tvOS) */ = {
 			isa = PBXNativeTarget;
 			buildConfigurationList = F86429192979CDB1002ABA01 /* Build configuration list for PBXNativeTarget "NRTestApp (tvOS)" */;
@@ -416,7 +464,7 @@
 			isa = PBXProject;
 			attributes = {
 				BuildIndependentTargetsInParallel = 1;
-				LastSwiftUpdateCheck = 1420;
+				LastSwiftUpdateCheck = 1430;
 				LastUpgradeCheck = 1420;
 				TargetAttributes = {
 					F8302AF4296F5EFA003EC291 = {
@@ -427,6 +475,10 @@
 						CreatedOnToolsVersion = 14.2;
 						TestTargetID = F8302AF4296F5EFA003EC291;
 					};
+					F848CDE02AA270E80082052F = {
+						CreatedOnToolsVersion = 14.3.1;
+						TestTargetID = F86428E92979CDAF002ABA01;
+					};
 					F86428E92979CDAF002ABA01 = {
 						CreatedOnToolsVersion = 14.2;
 					};
@@ -454,6 +506,7 @@
 				F8302AF4296F5EFA003EC291 /* NRTestApp */,
 				F86428E92979CDAF002ABA01 /* NRTestApp (tvOS) */,
 				F8302B0A296F5EFB003EC291 /* NRTestAppTests */,
+				F848CDE02AA270E80082052F /* NRTestApp(tvOS)Tests */,
 			);
 		};
 /* End PBXProject section */
@@ -514,6 +567,13 @@
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 		};
+		F848CDDF2AA270E80082052F /* Resources */ = {
+			isa = PBXResourcesBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
 		F86428E82979CDAF002ABA01 /* Resources */ = {
 			isa = PBXResourcesBuildPhase;
 			buildActionMask = 2147483647;
@@ -605,6 +665,15 @@
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 		};
+		F848CDDD2AA270E80082052F /* Sources */ = {
+			isa = PBXSourcesBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+				F848CDE62AA270E80082052F /* NRTestApp_tvOS_TestsLaunchTests.swift in Sources */,
+				F848CDE42AA270E80082052F /* NRTestApp_tvOS_Tests.swift in Sources */,
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
 		F86428E62979CDAF002ABA01 /* Sources */ = {
 			isa = PBXSourcesBuildPhase;
 			buildActionMask = 2147483647;
@@ -638,6 +707,11 @@
 			target = F8302AF4296F5EFA003EC291 /* NRTestApp */;
 			targetProxy = F8302B0C296F5EFB003EC291 /* PBXContainerItemProxy */;
 		};
+		F848CDE82AA270E80082052F /* PBXTargetDependency */ = {
+			isa = PBXTargetDependency;
+			target = F86428E92979CDAF002ABA01 /* NRTestApp (tvOS) */;
+			targetProxy = F848CDE72AA270E80082052F /* PBXContainerItemProxy */;
+		};
 /* End PBXTargetDependency section */
 
 /* Begin PBXVariantGroup section */
@@ -910,6 +984,44 @@
 			};
 			name = Release;
 		};
+		F848CDE92AA270E80082052F /* Debug */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+				CODE_SIGN_STYLE = Automatic;
+				CURRENT_PROJECT_VERSION = 1;
+				DEVELOPMENT_TEAM = SU7SUNGZJP;
+				GENERATE_INFOPLIST_FILE = YES;
+				MARKETING_VERSION = 1.0;
+				PRODUCT_BUNDLE_IDENTIFIER = "newrelic.NRTestApp-tvOS-Tests";
+				PRODUCT_NAME = "$(TARGET_NAME)";
+				SDKROOT = appletvos;
+				SWIFT_EMIT_LOC_STRINGS = NO;
+				SWIFT_VERSION = 5.0;
+				TARGETED_DEVICE_FAMILY = 3;
+				TEST_TARGET_NAME = "NRTestApp (tvOS)";
+				TVOS_DEPLOYMENT_TARGET = 11.0;
+			};
+			name = Debug;
+		};
+		F848CDEA2AA270E80082052F /* Release */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+				CODE_SIGN_STYLE = Automatic;
+				CURRENT_PROJECT_VERSION = 1;
+				DEVELOPMENT_TEAM = SU7SUNGZJP;
+				GENERATE_INFOPLIST_FILE = YES;
+				MARKETING_VERSION = 1.0;
+				PRODUCT_BUNDLE_IDENTIFIER = "newrelic.NRTestApp-tvOS-Tests";
+				PRODUCT_NAME = "$(TARGET_NAME)";
+				SDKROOT = appletvos;
+				SWIFT_EMIT_LOC_STRINGS = NO;
+				SWIFT_VERSION = 5.0;
+				TARGETED_DEVICE_FAMILY = 3;
+				TEST_TARGET_NAME = "NRTestApp (tvOS)";
+				TVOS_DEPLOYMENT_TARGET = 11.0;
+			};
+			name = Release;
+		};
 		F864290E2979CDB1002ABA01 /* Debug */ = {
 			isa = XCBuildConfiguration;
 			buildSettings = {
@@ -1008,6 +1120,15 @@
 			defaultConfigurationIsVisible = 0;
 			defaultConfigurationName = Release;
 		};
+		F848CDF02AA270E80082052F /* Build configuration list for PBXNativeTarget "NRTestApp(tvOS)Tests" */ = {
+			isa = XCConfigurationList;
+			buildConfigurations = (
+				F848CDE92AA270E80082052F /* Debug */,
+				F848CDEA2AA270E80082052F /* Release */,
+			);
+			defaultConfigurationIsVisible = 0;
+			defaultConfigurationName = Release;
+		};
 		F86429192979CDB1002ABA01 /* Build configuration list for PBXNativeTarget "NRTestApp (tvOS)" */ = {
 			isa = XCConfigurationList;
 			buildConfigurations = (
diff --git a/Test Harness/NRTestApp/NRTestApp.xcodeproj/xcshareddata/xcschemes/NRTestApp (tvOS).xcscheme b/Test Harness/NRTestApp/NRTestApp.xcodeproj/xcshareddata/xcschemes/NRTestApp (tvOS).xcscheme
index bbd73d6c..44bb0c2c 100644
--- a/Test Harness/NRTestApp/NRTestApp.xcodeproj/xcshareddata/xcschemes/NRTestApp (tvOS).xcscheme	
+++ b/Test Harness/NRTestApp/NRTestApp.xcodeproj/xcshareddata/xcschemes/NRTestApp (tvOS).xcscheme	
@@ -50,6 +50,17 @@
                ReferencedContainer = "container:NRTestApp.xcodeproj">
             </BuildableReference>
          </TestableReference>
+         <TestableReference
+            skipped = "NO"
+            parallelizable = "YES">
+            <BuildableReference
+               BuildableIdentifier = "primary"
+               BlueprintIdentifier = "F848CDE02AA270E80082052F"
+               BuildableName = "NRTestApp(tvOS)Tests.xctest"
+               BlueprintName = "NRTestApp(tvOS)Tests"
+               ReferencedContainer = "container:NRTestApp.xcodeproj">
+            </BuildableReference>
+         </TestableReference>
       </Testables>
    </TestAction>
    <LaunchAction
diff --git a/fastlane/README.md b/fastlane/README.md
index 69f1edb9..809844d7 100644
--- a/fastlane/README.md
+++ b/fastlane/README.md
@@ -47,6 +47,22 @@ Run Agent tests for iOS and generate code coverage
 
 Run Agent tests for iOS
 
+### ios runIOSBetaTests
+
+```sh
+[bundle exec] fastlane ios runIOSBetaTests
+```
+
+Run Agent tests for iOS beta
+
+### ios runIOSAppBetaTests
+
+```sh
+[bundle exec] fastlane ios runIOSAppBetaTests
+```
+
+Run App tests for iOS beta
+
 ### ios runTVOSTests
 
 ```sh
@@ -55,6 +71,22 @@ Run Agent tests for iOS
 
 Run Agent tests for tvOS
 
+### ios runTVOSBetaTests
+
+```sh
+[bundle exec] fastlane ios runTVOSBetaTests
+```
+
+Run Agent tests for tvOS beta
+
+### ios runTVOSAppBetaTests
+
+```sh
+[bundle exec] fastlane ios runTVOSAppBetaTests
+```
+
+Run Agent tests for tvOS beta
+
 ### ios coverage
 
 ```sh
@@ -87,6 +119,14 @@ Run dSYM Upload Tools test
 
 Delete derived data and Frameworks and build directory
 
+### ios addAPIKeyToPlist
+
+```sh
+[bundle exec] fastlane ios addAPIKeyToPlist
+```
+
+Add an API key to the plist file
+
 ### ios internalOutputXCFramework
 
 ```sh
diff --git a/fastlane/TestFastfile b/fastlane/TestFastfile
index 2e65228b..9087bc1d 100644
--- a/fastlane/TestFastfile
+++ b/fastlane/TestFastfile
@@ -40,6 +40,34 @@ platform :ios do
     internalRunIOSTests
   end
 
+  desc "Run Agent tests for iOS beta"
+  lane :runIOSBetaTests do |options|
+
+    deleteBuildArtifacts
+
+    run_tests(
+      workspace: "Agent.xcworkspace",
+      code_coverage: false,
+      scheme: "Agent-iOS",
+      device: "iPhone 14 Pro Max (#{options[:os_version]})",
+      output_style: 'raw'
+    )
+  end
+
+  desc "Run App tests for iOS beta"
+  lane :runIOSAppBetaTests do |options|
+
+    deleteBuildArtifacts
+
+    run_tests(
+      workspace: "Agent.xcworkspace",
+      code_coverage: false,
+      scheme: "NRTestApp",
+      device: "iPhone 14 Pro Max (#{options[:os_version]})",
+      output_style: 'raw'
+    )
+  end
+
   # tvOS Tests
   
   desc "Run Agent tests for tvOS"
@@ -57,6 +85,34 @@ platform :ios do
     )
   end
 
+  desc "Run Agent tests for tvOS beta"
+  lane :runTVOSBetaTests do |options|
+    
+    deleteBuildArtifacts
+
+    run_tests(
+      workspace: "Agent.xcworkspace",
+      code_coverage: false,
+      scheme: "Agent-tvOS",
+      device: "Apple TV 4K (3rd generation) (at 1080p) (#{options[:os_version]})",
+      output_style: 'raw'
+    )
+  end
+
+  desc "Run Agent tests for tvOS beta"
+  lane :runTVOSAppBetaTests do |options|
+    
+    deleteBuildArtifacts
+
+    run_tests(
+      workspace: "Agent.xcworkspace",
+      code_coverage: false,
+      scheme: "NRTestApp (tvOS)",
+      device: "Apple TV 4K (3rd generation) (at 1080p) (#{options[:os_version]})",
+      output_style: 'raw'
+    )
+  end
+
   lane :coverage do 
     Dir.chdir("..") do
       begin
diff --git a/fastlane/UtilityFastfile b/fastlane/UtilityFastfile
index d75d29b7..3eee5def 100644
--- a/fastlane/UtilityFastfile
+++ b/fastlane/UtilityFastfile
@@ -31,4 +31,20 @@ platform :ios do
 
       end
   end
+
+  desc "Add an API key to the plist file"
+  lane :addAPIKeyToPlist do |options|
+      Dir.chdir("../scripts/") do
+        begin
+          sh ("./plist_editor.swift -valueToAdd #{options[:valueToAdd]}")
+
+        rescue => ex
+          # handle error
+        ensure
+          # do something that always run like clean up
+        end
+
+      end
+      
+  end
 end
diff --git a/scripts/plist_editor.swift b/scripts/plist_editor.swift
new file mode 100755
index 00000000..79a00809
--- /dev/null
+++ b/scripts/plist_editor.swift
@@ -0,0 +1,53 @@
+#!/usr/bin/swift
+
+import Foundation
+
+let plistPath = "../Test Harness/NRTestApp/NRAPI-Info.plist"
+var keyToChange = "NRAPIKey"
+
+let namedArguments = UserDefaults.standard
+
+guard let valueToAdd = namedArguments.string(forKey: "valueToAdd") else {
+    print("No value passed")
+    exit(1)
+}
+print("Value is: \(valueToAdd)")
+
+if let newKeyToChange = namedArguments.string(forKey: "keyToChange") {
+    keyToChange = newKeyToChange
+}
+print("Key is: \(keyToChange)")
+
+
+guard let plistData = FileManager.default.contents(atPath: plistPath) else {
+    print("Error: Unable to read .plist file.")
+    exit(1)
+}
+
+guard var plistDict = try? PropertyListSerialization.propertyList(from: plistData, options: [], format: nil) as? [String: Any] else {
+    print("Error: Unable to parse .plist file.")
+    exit(1)
+}
+
+if let value = plistDict[keyToChange] {
+    if value as! String == valueToAdd {
+        print("Key \(keyToChange) value is already \(valueToAdd)")
+        exit(0)
+    }
+    print("Warning: Key \(keyToChange) is already \(value) in .plist file. Overwriting value.")
+}
+
+plistDict[keyToChange] = valueToAdd
+
+guard let newPlistData = try? PropertyListSerialization.data(fromPropertyList: plistDict, format: .xml, options: 0) else {
+    print("Error: Unable to serialize updated .plist dictionary.")
+    exit(1)
+}
+
+do {
+    try newPlistData.write(to: URL(fileURLWithPath: plistPath))
+    print("Success: Added key \(keyToChange) with value \(valueToAdd) to .plist file.")
+} catch {
+    print("Error: Unable to write updated .plist file.")
+    exit(1)
+}

From 71c95bea934cd60fbd2bf5d6119b0fa64ea04fba Mon Sep 17 00:00:00 2001
From: "github-actions[bot]"
 <41898282+github-actions[bot]@users.noreply.github.com>
Date: Tue, 3 Oct 2023 08:22:01 -0600
Subject: [PATCH 5/9] [7.4.7] Production Release (#159)

* [create-pull-request] automated change

* Fix auto-prod PR to include Cocoapod spec update

---------

Co-authored-by: cdillard-NewRelic <cdillard-NewRelic@users.noreply.github.com>
Co-authored-by: Chris Dillard <cdillard@newrelic.com>
---
 NewRelicAgent.podspec | 4 ++--
 Package.swift         | 4 ++--
 2 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/NewRelicAgent.podspec b/NewRelicAgent.podspec
index 4a04aa33..a7616a00 100644
--- a/NewRelicAgent.podspec
+++ b/NewRelicAgent.podspec
@@ -1,12 +1,12 @@
 
 Pod::Spec.new do |s|
   s.name                   = "NewRelicAgent"
-  s.version                = "7.4.7-rc.589"
+  s.version                = "7.4.7"
   s.summary                = "Real-time performance data with your next iOS app release."
   s.homepage               = "http://newrelic.com/mobile-monitoring"
   s.license                = { :type => "Commercial", :file => "LICENSE" }
   s.author                 = { "New Relic, Inc." => "support@newrelic.com" }
-  s.source                 = { :http => "https://download.newrelic.com/ios-v5/NewRelic_XCFramework_Agent_7.4.7-rc.589.zip" }
+  s.source                 = { :http => "https://download.newrelic.com/ios_agent/NewRelic_XCFramework_Agent_7.4.7.zip" }
   s.ios.deployment_target  = '9.0'
   s.tvos.deployment_target = '9.0'
   s.vendored_frameworks    = "NewRelic.xcframework"
diff --git a/Package.swift b/Package.swift
index 9422c70d..d87f74fb 100644
--- a/Package.swift
+++ b/Package.swift
@@ -19,8 +19,8 @@ let package = Package(
             name: "NewRelicPackage",
             dependencies: []),
         .binaryTarget(name: "NewRelic",
-                      url: "https://download.newrelic.com/ios-v5/NewRelic_XCFramework_Agent_7.4.7-rc.589.zip",
-                      checksum: "4d5b8b8415d7e4d98fc12f1bf78347fe4f52c85bea0660be96c17d2a1a705752")
+                      url: "https://download.newrelic.com/ios_agent/NewRelic_XCFramework_Agent_7.4.7.zip",
+                      checksum: "dabdfd22b8526f2713bd1335d73097066c79e51d80cb3644eac262703c4911d4")
     ]
 )
 

From 9c84aa18cfa4601dd7ef245a028789c106eea19b Mon Sep 17 00:00:00 2001
From: cdillard-NewRelic <cdillard-NewRelic@users.noreply.github.com>
Date: Tue, 21 Nov 2023 21:27:22 +0000
Subject: [PATCH 6/9] [7.4.8-rc.710] Staging Release

---
 Gemfile.lock          | 42 +++++++++++++++++++-----------------------
 NewRelicAgent.podspec |  4 ++--
 Package.swift         |  4 ++--
 3 files changed, 23 insertions(+), 27 deletions(-)

diff --git a/Gemfile.lock b/Gemfile.lock
index aeba6072..dd1e2a24 100644
--- a/Gemfile.lock
+++ b/Gemfile.lock
@@ -8,20 +8,20 @@ GEM
     artifactory (3.0.15)
     atomos (0.1.3)
     aws-eventstream (1.2.0)
-    aws-partitions (1.828.0)
-    aws-sdk-core (3.183.1)
+    aws-partitions (1.854.0)
+    aws-sdk-core (3.187.1)
       aws-eventstream (~> 1, >= 1.0.2)
       aws-partitions (~> 1, >= 1.651.0)
       aws-sigv4 (~> 1.5)
       jmespath (~> 1, >= 1.6.1)
-    aws-sdk-kms (1.71.0)
-      aws-sdk-core (~> 3, >= 3.177.0)
+    aws-sdk-kms (1.72.0)
+      aws-sdk-core (~> 3, >= 3.184.0)
       aws-sigv4 (~> 1.1)
-    aws-sdk-s3 (1.136.0)
+    aws-sdk-s3 (1.137.0)
       aws-sdk-core (~> 3, >= 3.181.0)
       aws-sdk-kms (~> 1)
       aws-sigv4 (~> 1.6)
-    aws-sigv4 (1.6.0)
+    aws-sigv4 (1.6.1)
       aws-eventstream (~> 1, >= 1.0.2)
     babosa (1.0.4)
     claide (1.1.0)
@@ -32,11 +32,10 @@ GEM
     declarative (0.0.20)
     digest-crc (0.6.5)
       rake (>= 12.0.0, < 14.0.0)
-    domain_name (0.5.20190701)
-      unf (>= 0.0.5, < 1.0.0)
+    domain_name (0.6.20231109)
     dotenv (2.8.1)
     emoji_regex (3.2.3)
-    excon (0.103.0)
+    excon (0.104.0)
     faraday (1.10.3)
       faraday-em_http (~> 1.0)
       faraday-em_synchrony (~> 1.0)
@@ -66,7 +65,7 @@ GEM
     faraday_middleware (1.2.0)
       faraday (~> 1.0)
     fastimage (2.2.7)
-    fastlane (2.216.0)
+    fastlane (2.217.0)
       CFPropertyList (>= 2.3, < 4.0.0)
       addressable (>= 2.8, < 3.0.0)
       artifactory (~> 3.0)
@@ -107,9 +106,9 @@ GEM
       xcpretty (~> 0.3.0)
       xcpretty-travis-formatter (>= 0.0.3)
     gh_inspector (1.1.3)
-    google-apis-androidpublisher_v3 (0.50.0)
+    google-apis-androidpublisher_v3 (0.53.0)
       google-apis-core (>= 0.11.0, < 2.a)
-    google-apis-core (0.11.1)
+    google-apis-core (0.11.2)
       addressable (~> 2.5, >= 2.5.1)
       googleauth (>= 0.16.2, < 2.a)
       httpclient (>= 2.8.1, < 3.a)
@@ -122,19 +121,19 @@ GEM
       google-apis-core (>= 0.11.0, < 2.a)
     google-apis-playcustomapp_v1 (0.13.0)
       google-apis-core (>= 0.11.0, < 2.a)
-    google-apis-storage_v1 (0.19.0)
-      google-apis-core (>= 0.9.0, < 2.a)
+    google-apis-storage_v1 (0.29.0)
+      google-apis-core (>= 0.11.0, < 2.a)
     google-cloud-core (1.6.0)
       google-cloud-env (~> 1.0)
       google-cloud-errors (~> 1.0)
     google-cloud-env (1.6.0)
       faraday (>= 0.17.3, < 3.0)
     google-cloud-errors (1.3.1)
-    google-cloud-storage (1.44.0)
+    google-cloud-storage (1.45.0)
       addressable (~> 2.8)
       digest-crc (~> 0.4)
       google-apis-iamcredentials_v1 (~> 0.1)
-      google-apis-storage_v1 (~> 0.19.0)
+      google-apis-storage_v1 (~> 0.29.0)
       google-cloud-core (~> 1.6)
       googleauth (>= 0.16.2, < 2.a)
       mini_mime (~> 1.0)
@@ -160,8 +159,8 @@ GEM
     optparse (0.1.1)
     os (1.1.4)
     plist (3.7.0)
-    public_suffix (5.0.3)
-    rake (13.0.6)
+    public_suffix (5.0.4)
+    rake (13.1.0)
     representable (3.2.0)
       declarative (< 0.1.0)
       trailblazer-option (>= 0.1.1, < 0.2.0)
@@ -189,10 +188,7 @@ GEM
     tty-spinner (0.9.3)
       tty-cursor (~> 0.7)
     uber (0.1.0)
-    unf (0.1.4)
-      unf_ext
-    unf_ext (0.0.8.2)
-    unicode-display_width (2.4.2)
+    unicode-display_width (2.5.0)
     webrick (1.8.1)
     word_wrap (1.0.0)
     xcodeproj (1.23.0)
@@ -215,4 +211,4 @@ DEPENDENCIES
   fastlane
 
 BUNDLED WITH
-   2.4.19
+   2.4.22
diff --git a/NewRelicAgent.podspec b/NewRelicAgent.podspec
index 4a04aa33..ccc656f4 100644
--- a/NewRelicAgent.podspec
+++ b/NewRelicAgent.podspec
@@ -1,12 +1,12 @@
 
 Pod::Spec.new do |s|
   s.name                   = "NewRelicAgent"
-  s.version                = "7.4.7-rc.589"
+  s.version                = "7.4.8-rc.710"
   s.summary                = "Real-time performance data with your next iOS app release."
   s.homepage               = "http://newrelic.com/mobile-monitoring"
   s.license                = { :type => "Commercial", :file => "LICENSE" }
   s.author                 = { "New Relic, Inc." => "support@newrelic.com" }
-  s.source                 = { :http => "https://download.newrelic.com/ios-v5/NewRelic_XCFramework_Agent_7.4.7-rc.589.zip" }
+  s.source                 = { :http => "https://download.newrelic.com/ios-v5/NewRelic_XCFramework_Agent_7.4.8-rc.710.zip" }
   s.ios.deployment_target  = '9.0'
   s.tvos.deployment_target = '9.0'
   s.vendored_frameworks    = "NewRelic.xcframework"
diff --git a/Package.swift b/Package.swift
index 9422c70d..7df09001 100644
--- a/Package.swift
+++ b/Package.swift
@@ -19,8 +19,8 @@ let package = Package(
             name: "NewRelicPackage",
             dependencies: []),
         .binaryTarget(name: "NewRelic",
-                      url: "https://download.newrelic.com/ios-v5/NewRelic_XCFramework_Agent_7.4.7-rc.589.zip",
-                      checksum: "4d5b8b8415d7e4d98fc12f1bf78347fe4f52c85bea0660be96c17d2a1a705752")
+                      url: "https://download.newrelic.com/ios-v5/NewRelic_XCFramework_Agent_7.4.8-rc.710.zip",
+                      checksum: "c2be0fb063279bb7e2c31060bb30dd35509f930e11189a082b74a85611a641f5")
     ]
 )
 

From 9a7637d0dbc53bb0efd9c47e14bcc8466f79f252 Mon Sep 17 00:00:00 2001
From: Chris Dillard <cdillard@newrelic.com>
Date: Mon, 27 Nov 2023 15:05:44 -0700
Subject: [PATCH 7/9] Include Prod Podspec Job by default in productionDeploy

---
 .github/workflows/productionDeploy.yml | 20 ++++++++++----------
 1 file changed, 10 insertions(+), 10 deletions(-)

diff --git a/.github/workflows/productionDeploy.yml b/.github/workflows/productionDeploy.yml
index 8f36358c..e34f3c5d 100644
--- a/.github/workflows/productionDeploy.yml
+++ b/.github/workflows/productionDeploy.yml
@@ -66,19 +66,19 @@ jobs:
     - name: Print XCFramework name
       run: echo "${{ env.version }}" 
 
-    # - name: Create Prod Podspec for XCFramework version
-    #   run: |
-    #      cd main
+    - name: Create Prod Podspec for XCFramework version
+      run: |
+         cd main
 
-    #      cp cocoapods/NewRelicAgent.podspec.template NewRelicAgent.podspec
-    #      REPLACE=X.XX
-    #      sed -i bak "s/$REPLACE/${{ env.version }}/g" NewRelicAgent.podspec
+         cp cocoapods/NewRelicAgent.podspec.template NewRelicAgent.podspec
+         REPLACE=X.XX
+         sed -i bak "s/$REPLACE/${{ env.version }}/g" NewRelicAgent.podspec
 
-    #      rm NewRelicAgent.podspecbak
+         rm NewRelicAgent.podspecbak
 
-    #      pod trunk push --allow-warnings NewRelicAgent.podspec
-    #   env:
-    #      COCOAPODS_TRUNK_TOKEN: ${{ secrets.COCOAPODS_TRUNK_TOKEN }}
+         pod trunk push --allow-warnings NewRelicAgent.podspec
+      env:
+         COCOAPODS_TRUNK_TOKEN: ${{ secrets.COCOAPODS_TRUNK_TOKEN }}
 
     - name: Create Prod Package.swift for XCFramework version
       run: |

From daa3f04a9b194d10cb806a0f36dd0846379e5fb9 Mon Sep 17 00:00:00 2001
From: cdillard-NewRelic <cdillard-NewRelic@users.noreply.github.com>
Date: Mon, 11 Dec 2023 19:22:13 +0000
Subject: [PATCH 8/9] [create-pull-request] automated change

---
 NewRelicAgent.podspec | 4 ++--
 Package.swift         | 4 ++--
 2 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/NewRelicAgent.podspec b/NewRelicAgent.podspec
index a7616a00..2056c890 100644
--- a/NewRelicAgent.podspec
+++ b/NewRelicAgent.podspec
@@ -1,12 +1,12 @@
 
 Pod::Spec.new do |s|
   s.name                   = "NewRelicAgent"
-  s.version                = "7.4.7"
+  s.version                = "7.4.8"
   s.summary                = "Real-time performance data with your next iOS app release."
   s.homepage               = "http://newrelic.com/mobile-monitoring"
   s.license                = { :type => "Commercial", :file => "LICENSE" }
   s.author                 = { "New Relic, Inc." => "support@newrelic.com" }
-  s.source                 = { :http => "https://download.newrelic.com/ios_agent/NewRelic_XCFramework_Agent_7.4.7.zip" }
+  s.source                 = { :http => "https://download.newrelic.com/ios_agent/NewRelic_XCFramework_Agent_7.4.8.zip" }
   s.ios.deployment_target  = '9.0'
   s.tvos.deployment_target = '9.0'
   s.vendored_frameworks    = "NewRelic.xcframework"
diff --git a/Package.swift b/Package.swift
index d87f74fb..10ed37e1 100644
--- a/Package.swift
+++ b/Package.swift
@@ -19,8 +19,8 @@ let package = Package(
             name: "NewRelicPackage",
             dependencies: []),
         .binaryTarget(name: "NewRelic",
-                      url: "https://download.newrelic.com/ios_agent/NewRelic_XCFramework_Agent_7.4.7.zip",
-                      checksum: "dabdfd22b8526f2713bd1335d73097066c79e51d80cb3644eac262703c4911d4")
+                      url: "https://download.newrelic.com/ios_agent/NewRelic_XCFramework_Agent_7.4.8.zip",
+                      checksum: "96af08369f21b7c4b6b9ca5ea20d78752445f02d0223c44694012ad19530eba6")
     ]
 )
 

From 9f7ea1ae660c193dacc7de0178bc18a55198b6c2 Mon Sep 17 00:00:00 2001
From: Chris Dillard <103527346+cdillard-NewRelic@users.noreply.github.com>
Date: Wed, 7 Feb 2024 13:53:38 -0700
Subject: [PATCH 9/9] NR-220019: Adds GHA for Bespoke Branch Based Build (#198)

---
 .github/workflows/branchBuild.yml | 87 +++++++++++++++++++++++++++++++
 1 file changed, 87 insertions(+)
 create mode 100644 .github/workflows/branchBuild.yml

diff --git a/.github/workflows/branchBuild.yml b/.github/workflows/branchBuild.yml
new file mode 100644
index 00000000..fc4d1a0e
--- /dev/null
+++ b/.github/workflows/branchBuild.yml
@@ -0,0 +1,87 @@
+name: BespokeBuild
+on:  
+  workflow_dispatch:
+    # The input version number (ex: 7.4.0) and branch are required for the bespoke branch build. Branch is an automatically added selector for all github actions.
+    inputs:
+      version:
+        required: true
+
+concurrency:
+  group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
+  cancel-in-progress: true
+
+jobs:
+  deployS3:
+    name: DeployS3
+    # runs-on: will be set to macos-latest when running on actual GHA. 
+    # *** runs-on: ubuntu-latest is used when running via act on mac os. ***
+    runs-on: macos-13 
+    outputs:
+      version: ${{ steps.setOutput.outputs.version }}
+    steps:
+    - uses: actions/checkout@v3
+      with: 
+        submodules: true
+    
+    - uses: maxim-lobanov/setup-xcode@v1
+      with:
+        xcode-version: '14.3'
+
+    - name: Install the Apple certificate and provisioning profile
+      env:
+        BUILD_CERTIFICATE_BASE64: ${{ secrets.BUILD_CERTIFICATE_BASE64 }}
+        P12_PASSWORD: ${{ secrets.P12_PASSWORD }}
+        # BUILD_PROVISION_PROFILE_BASE64: ${{ secrets.BUILD_PROVISION_PROFILE_BASE64 }}
+        KEYCHAIN_PASSWORD: ${{ secrets.KEYCHAIN_PASSWORD }}
+      run: |
+        # create variables
+        CERTIFICATE_PATH=$RUNNER_TEMP/build_certificate.p12
+        PP_PATH=$RUNNER_TEMP/build_pp.mobileprovision
+        KEYCHAIN_PATH=$RUNNER_TEMP/app-signing.keychain-db
+
+        # import certificate and provisioning profile from secrets
+        echo -n "$BUILD_CERTIFICATE_BASE64" | base64 --decode -o $CERTIFICATE_PATH
+        # echo -n "$BUILD_PROVISION_PROFILE_BASE64" | base64 --decode -o $PP_PATH
+
+        # create temporary keychain
+        security create-keychain -p "$KEYCHAIN_PASSWORD" $KEYCHAIN_PATH
+        security set-keychain-settings -lut 21600 $KEYCHAIN_PATH
+        security unlock-keychain -p "$KEYCHAIN_PASSWORD" $KEYCHAIN_PATH
+
+        # import certificate to keychain
+        security import $CERTIFICATE_PATH -P "$P12_PASSWORD" -A -t cert -f pkcs12 -k $KEYCHAIN_PATH
+        security list-keychain -d user -s $KEYCHAIN_PATH
+
+        # # apply provisioning profile
+        # mkdir -p ~/Library/MobileDevice/Provisioning\ Profiles
+        # cp $PP_PATH ~/Library/MobileDevice/Provisioning\ Profiles
+
+    - name: Update gem
+      run: bundle update
+
+    - name: Install gems
+      run: bundle install
+
+    - name: Build NewRelic.xcframework (using fastlane)
+      run: bundle exec fastlane buildAndZip
+
+    - name: Get name
+      run: echo "version=$(cat fastlane/build_version)" >> $GITHUB_ENV
+
+    - id: setOutput
+      name: Print name
+      run: echo "version=${{ env.version }}"  >> $GITHUB_OUTPUT
+
+    - name: Deploy to staging S3
+      run: "aws s3 cp NewRelic_XCFramework_Agent_${{ env.version }}.zip s3://nr-downloads-main/ios-v5/"
+      env:
+        AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
+        AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
+        AWS_DEFAULT_REGION: ${{ secrets.AWS_DEFAULT_REGION }}
+        
+    - name: Upload build reports
+      if: failure() && steps.build-step.outcome != 'success'
+      uses: actions/upload-artifact@v3
+      with:
+        name: build-reports
+        path: /Users/runner/Library/Logs/fastlane/xcbuild/