diff --git a/.buildkite/pipeline.full.yml b/.buildkite/pipeline.full.yml index 50a51885a..4bcf09aec 100644 --- a/.buildkite/pipeline.full.yml +++ b/.buildkite/pipeline.full.yml @@ -18,22 +18,22 @@ steps: queue: opensource plugins: artifacts#v1.9.3: - download: "features/fixtures/ios/output/ipa_url_bb.txt" + download: "features/fixtures/ios/output/ipa_url_bb_release.txt" upload: "maze_output/failed/**/*" docker-compose#v4.7.0: pull: cocoa-maze-runner-bitbar run: cocoa-maze-runner-bitbar service-ports: true command: - - "--app=@/app/build/ipa_url_bb.txt" + - "--app=@/app/build/ipa_url_bb_release.txt" - "--farm=bb" - "--device=IOS_16" - "--no-tunnel" - "--aws-public-ip" - "--fail-fast" # PLAT-11155: App hang scenarios run on BrowserStack - - "--exclude=features/app_hangs.feature" - - "--exclude=features/[e-z].*.feature$" + - "features/release" + - "--exclude=features/release/[e-z].*.feature$" concurrency: 25 concurrency_group: 'bitbar' concurrency_method: eager @@ -50,20 +50,21 @@ steps: queue: opensource plugins: artifacts#v1.9.3: - download: "features/fixtures/ios/output/ipa_url_bb.txt" + download: "features/fixtures/ios/output/ipa_url_bb_release.txt" upload: "maze_output/failed/**/*" docker-compose#v4.7.0: pull: cocoa-maze-runner-bitbar run: cocoa-maze-runner-bitbar service-ports: true command: - - "--app=@/app/build/ipa_url_bb.txt" + - "--app=@/app/build/ipa_url_bb_release.txt" - "--farm=bb" - "--device=IOS_16" - "--no-tunnel" - "--aws-public-ip" - "--fail-fast" - - "--exclude=features/[a-d].*.feature$" + - "features/release" + - "--exclude=features/release/[a-d].*.feature$" concurrency: 25 concurrency_group: 'bitbar' concurrency_method: eager @@ -79,7 +80,7 @@ steps: queue: opensource plugins: artifacts#v1.9.3: - download: "features/fixtures/ios/output/ipa_url_bb.txt" + download: "features/fixtures/ios/output/ipa_url_bb_release.txt" upload: "maze_output/failed/**/*" docker-compose#v4.7.0: pull: cocoa-maze-runner-bitbar @@ -87,9 +88,9 @@ steps: service-ports: true command: # PLAT-11155: App hang scenarios run on BrowserStack - - "--exclude=features/app_hangs.feature" - - "--exclude=features/[e-z].*.feature$" - - "--app=@/app/build/ipa_url_bb.txt" + - "features/release" + - "--exclude=features/release/[e-z].*.feature$" + - "--app=@/app/build/ipa_url_bb_release.txt" - "--farm=bb" - "--device=IOS_15" - "--no-tunnel" @@ -106,15 +107,16 @@ steps: queue: opensource plugins: artifacts#v1.9.3: - download: "features/fixtures/ios/output/ipa_url_bb.txt" + download: "features/fixtures/ios/output/ipa_url_bb_release.txt" upload: "maze_output/failed/**/*" docker-compose#v4.7.0: pull: cocoa-maze-runner-bitbar run: cocoa-maze-runner-bitbar service-ports: true command: - - "--exclude=features/[a-d].*.feature$" - - "--app=@/app/build/ipa_url_bb.txt" + - "features/release" + - "--exclude=features/release/[a-d].*.feature$" + - "--app=@/app/build/ipa_url_bb_release.txt" - "--farm=bb" - "--device=IOS_15" - "--no-tunnel" @@ -132,22 +134,22 @@ steps: queue: opensource plugins: artifacts#v1.9.3: - download: "features/fixtures/ios/output/ipa_url_bb.txt" + download: "features/fixtures/ios/output/ipa_url_bb_release.txt" upload: "maze_output/failed/**/*" docker-compose#v4.7.0: pull: cocoa-maze-runner-bitbar run: cocoa-maze-runner-bitbar service-ports: true command: - - "--app=@/app/build/ipa_url_bb.txt" + - "--app=@/app/build/ipa_url_bb_release.txt" - "--farm=bb" - "--device=IOS_14" - "--no-tunnel" - "--aws-public-ip" - "--fail-fast" # PLAT-11155: App hang scenarios run on BrowserStack - - "--exclude=features/app_hangs.feature" - - "--exclude=features/[e-z].*.feature$" + - "features/release" + - "--exclude=features/release/[e-z].*.feature$" concurrency: 25 concurrency_group: 'bitbar' concurrency_method: eager @@ -164,20 +166,21 @@ steps: queue: opensource plugins: artifacts#v1.9.3: - download: "features/fixtures/ios/output/ipa_url_bb.txt" + download: "features/fixtures/ios/output/ipa_url_bb_release.txt" upload: "maze_output/failed/**/*" docker-compose#v4.7.0: pull: cocoa-maze-runner-bitbar run: cocoa-maze-runner-bitbar service-ports: true command: - - "--app=@/app/build/ipa_url_bb.txt" + - "--app=@/app/build/ipa_url_bb_release.txt" - "--farm=bb" - "--device=IOS_14" - "--no-tunnel" - "--aws-public-ip" - "--fail-fast" - - "--exclude=features/[a-d].*.feature$" + - "features/release" + - "--exclude=features/release/[a-d].*.feature$" concurrency: 25 concurrency_group: 'bitbar' concurrency_method: eager @@ -194,22 +197,22 @@ steps: queue: opensource plugins: artifacts#v1.9.3: - download: "features/fixtures/ios/output/ipa_url_bb.txt" + download: "features/fixtures/ios/output/ipa_url_bb_release.txt" upload: "maze_output/failed/**/*" docker-compose#v4.7.0: pull: cocoa-maze-runner-bitbar run: cocoa-maze-runner-bitbar service-ports: true command: - - "--app=@/app/build/ipa_url_bb.txt" + - "--app=@/app/build/ipa_url_bb_release.txt" - "--farm=bb" - "--device=IOS_13" - "--no-tunnel" - "--aws-public-ip" - "--fail-fast" # PLAT-11155: App hang scenarios run on BrowserStack - - "--exclude=features/app_hangs.feature" - - "--exclude=features/[e-z].*.feature$" + - "features/release" + - "--exclude=features/release/[e-z].*.feature$" concurrency: 25 concurrency_group: 'bitbar' concurrency_method: eager @@ -226,20 +229,21 @@ steps: queue: opensource plugins: artifacts#v1.9.3: - download: "features/fixtures/ios/output/ipa_url_bb.txt" + download: "features/fixtures/ios/output/ipa_url_bb_release.txt" upload: "maze_output/failed/**/*" docker-compose#v4.7.0: pull: cocoa-maze-runner-bitbar run: cocoa-maze-runner-bitbar service-ports: true command: - - "--app=@/app/build/ipa_url_bb.txt" + - "--app=@/app/build/ipa_url_bb_release.txt" - "--farm=bb" - "--device=IOS_13" - "--no-tunnel" - "--aws-public-ip" - "--fail-fast" - - "--exclude=features/[a-d].*.feature$" + - "features/release" + - "--exclude=features/release/[a-d].*.feature$" concurrency: 25 concurrency_group: 'bitbar' concurrency_method: eager @@ -260,13 +264,13 @@ steps: queue: opensource plugins: artifacts#v1.5.0: - download: "features/fixtures/ios/output/ipa_url_bs.txt" + download: "features/fixtures/ios/output/ipa_url_bs_release.txt" upload: "maze_output/failed/**/*" docker-compose#v3.7.0: pull: cocoa-maze-runner run: cocoa-maze-runner command: - - "--app=@build/ipa_url_bs.txt" + - "--app=@build/ipa_url_bs_release.txt" - "--farm=bs" - "--device=IOS_16" - "--appium-version=1.21.0" @@ -291,13 +295,13 @@ steps: queue: opensource plugins: artifacts#v1.5.0: - download: "features/fixtures/ios/output/ipa_url_bs.txt" + download: "features/fixtures/ios/output/ipa_url_bs_release.txt" upload: "maze_output/failed/**/*" docker-compose#v3.7.0: pull: cocoa-maze-runner run: cocoa-maze-runner command: - - "--app=@build/ipa_url_bs.txt" + - "--app=@build/ipa_url_bs_release.txt" - "--farm=bs" - "--device=IOS_15" - "--appium-version=1.21.0" @@ -320,13 +324,13 @@ steps: queue: opensource plugins: artifacts#v1.5.0: - download: "features/fixtures/ios/output/ipa_url_bs.txt" + download: "features/fixtures/ios/output/ipa_url_bs_release.txt" upload: "maze_output/failed/**/*" docker-compose#v3.7.0: pull: cocoa-maze-runner run: cocoa-maze-runner command: - - "--app=@build/ipa_url_bs.txt" + - "--app=@build/ipa_url_bs_release.txt" - "--farm=bs" - "--device=IOS_14" - "--appium-version=1.21.0" @@ -349,13 +353,13 @@ steps: queue: opensource plugins: artifacts#v1.5.0: - download: "features/fixtures/ios/output/ipa_url_bs.txt" + download: "features/fixtures/ios/output/ipa_url_bs_release.txt" upload: "maze_output/failed/**/*" docker-compose#v3.7.0: pull: cocoa-maze-runner run: cocoa-maze-runner command: - - "--app=@build/ipa_url_bs.txt" + - "--app=@build/ipa_url_bs_release.txt" - "--farm=bs" - "--device=IOS_13" - "--appium-version=1.21.0" @@ -377,13 +381,14 @@ steps: queue: macos-13-arm plugins: artifacts#v1.5.0: - download: "features/fixtures/macos/output/macOSTestApp.zip" + download: "features/fixtures/macos/output/macOSTestApp_Release.zip" upload: - "macOSTestApp.log" - "maze_output/failed/**/*" commands: - bundle install - - bundle exec maze-runner + - bundle exec maze-runner + features/release --os=macos --fail-fast @@ -395,13 +400,14 @@ steps: queue: macos-12-arm plugins: artifacts#v1.5.0: - download: "features/fixtures/macos/output/macOSTestApp.zip" + download: "features/fixtures/macos/output/macOSTestApp_Release.zip" upload: - "macOSTestApp.log" - "maze_output/failed/**/*" commands: - bundle install - - bundle exec maze-runner + - bundle exec maze-runner + features/release --os=macos --fail-fast @@ -413,11 +419,12 @@ steps: queue: macos-11 plugins: artifacts#v1.5.0: - download: ["features/fixtures/macos/output/macOSTestApp.zip"] + download: ["features/fixtures/macos/output/macOSTestApp_Release.zip"] upload: ["macOSTestApp.log", "maze_output/failed/**/*"] commands: - bundle install - bundle exec maze-runner + features/release --os=macos --fail-fast @@ -429,11 +436,12 @@ steps: queue: macos-10.15 plugins: artifacts#v1.5.0: - download: ["features/fixtures/macos/output/macOSTestApp.zip"] + download: ["features/fixtures/macos/output/macOSTestApp_Release.zip"] upload: ["macOSTestApp.log", "maze_output/failed/**/*"] commands: - bundle install - bundle exec maze-runner + features/release --os=macos --fail-fast @@ -445,11 +453,12 @@ steps: queue: opensource-mac-cocoa-10.14 plugins: artifacts#v1.5.0: - download: ["features/fixtures/macos/output/macOSTestApp.zip"] + download: ["features/fixtures/macos/output/macOSTestApp_Release.zip"] upload: ["macOSTestApp.log", "maze_output/failed/**/*"] commands: - bundle install - bundle exec maze-runner + features/release --os=macos --fail-fast @@ -461,11 +470,12 @@ steps: queue: opensource-mac-cocoa-10.13 plugins: artifacts#v1.5.0: - download: ["features/fixtures/macos/output/macOSTestApp.zip"] + download: ["features/fixtures/macos/output/macOSTestApp_Release.zip"] upload: ["macOSTestApp.log", "maze_output/failed/**/*"] commands: - bundle install - bundle exec maze-runner + features/release --os=macos --fail-fast diff --git a/.buildkite/pipeline.yml b/.buildkite/pipeline.yml index c1474331c..dfe9eb0ee 100644 --- a/.buildkite/pipeline.yml +++ b/.buildkite/pipeline.yml @@ -30,15 +30,21 @@ steps: env: XCODE_VERSION: 15.3.0 artifact_paths: - - features/fixtures/ios/output/iOSTestApp.ipa - - features/fixtures/macos/output/macOSTestApp.zip - - features/fixtures/ios/output/ipa_url_bb.txt - - features/fixtures/ios/output/ipa_url_bs.txt + - features/fixtures/ios/output/iOSTestApp_Release.ipa + - features/fixtures/ios/output/iOSTestApp_Debug.ipa + - features/fixtures/macos/output/macOSTestApp_Release.zip + - features/fixtures/macos/output/macOSTestApp_Debug.zip + - features/fixtures/ios/output/ipa_url_bb_release.txt + - features/fixtures/ios/output/ipa_url_bs_release.txt + - features/fixtures/ios/output/ipa_url_bb_debug.txt + - features/fixtures/ios/output/ipa_url_bs_debug.txt commands: - bundle install - make test-fixtures - - bundle exec upload-app --farm=bb --app=./features/fixtures/ios/output/iOSTestApp.ipa --app-id-file=./features/fixtures/ios/output/ipa_url_bb.txt - - bundle exec upload-app --farm=bs --app=./features/fixtures/ios/output/iOSTestApp.ipa --app-id-file=./features/fixtures/ios/output/ipa_url_bs.txt + - bundle exec upload-app --farm=bb --app=./features/fixtures/ios/output/iOSTestApp_Release.ipa --app-id-file=./features/fixtures/ios/output/ipa_url_bb_release.txt + - bundle exec upload-app --farm=bs --app=./features/fixtures/ios/output/iOSTestApp_Release.ipa --app-id-file=./features/fixtures/ios/output/ipa_url_bs_release.txt + - bundle exec upload-app --farm=bb --app=./features/fixtures/ios/output/iOSTestApp_Debug.ipa --app-id-file=./features/fixtures/ios/output/ipa_url_bb_debug.txt + - bundle exec upload-app --farm=bs --app=./features/fixtures/ios/output/iOSTestApp_Debug.ipa --app-id-file=./features/fixtures/ios/output/ipa_url_bs_debug.txt - label: Carthage timeout_in_minutes: 15 @@ -195,13 +201,14 @@ steps: queue: macos-14 plugins: artifacts#v1.5.0: - download: "features/fixtures/macos/output/macOSTestApp.zip" + download: "features/fixtures/macos/output/macOSTestApp_Release.zip" upload: - "macOSTestApp.log" - "maze_output/failed/**/*" commands: - bundle install - bundle exec maze-runner + features/release --os=macos --fail-fast @@ -213,14 +220,14 @@ steps: queue: macos-13-arm plugins: artifacts#v1.5.0: - download: "features/fixtures/macos/output/macOSTestApp.zip" + download: "features/fixtures/macos/output/macOSTestApp_Release.zip" upload: - "macOSTestApp.log" - "maze_output/failed/**/*" commands: - bundle install - bundle exec maze-runner - features/barebone_tests.feature + features/release/barebone_tests.feature --os=macos --fail-fast @@ -232,14 +239,14 @@ steps: queue: macos-12-arm plugins: artifacts#v1.5.0: - download: "features/fixtures/macos/output/macOSTestApp.zip" + download: "features/fixtures/macos/output/macOSTestApp_Release.zip" upload: - "macOSTestApp.log" - "maze_output/failed/**/*" commands: - bundle install - bundle exec maze-runner - features/barebone_tests.feature + features/release/barebone_tests.feature --os=macos --fail-fast @@ -256,7 +263,7 @@ steps: - make -C features/fixtures/macos-stress-test - echo "--- Test" - bundle exec maze-runner - features/stress_test.feature + features/release/stress_test.feature --os=macos --no-log-requests artifact_paths: @@ -271,12 +278,12 @@ steps: queue: macos-11 plugins: artifacts#v1.5.0: - download: ["features/fixtures/macos/output/macOSTestApp.zip"] + download: ["features/fixtures/macos/output/macOSTestApp_Release.zip"] upload: ["macOSTestApp.log", "maze_output/failed/**/*"] commands: - bundle install - bundle exec maze-runner - features/barebone_tests.feature + features/release/barebone_tests.feature --os=macos --fail-fast @@ -288,12 +295,12 @@ steps: queue: macos-10.15 plugins: artifacts#v1.5.0: - download: ["features/fixtures/macos/output/macOSTestApp.zip"] + download: ["features/fixtures/macos/output/macOSTestApp_Release.zip"] upload: ["macOSTestApp.log", "maze_output/failed/**/*"] commands: - bundle install - bundle exec maze-runner - features/barebone_tests.feature + features/release/barebone_tests.feature --os=macos --fail-fast @@ -305,14 +312,14 @@ steps: queue: opensource-mac-cocoa-10.14 plugins: artifacts#v1.5.0: - download: "features/fixtures/macos/output/macOSTestApp.zip" + download: "features/fixtures/macos/output/macOSTestApp_Release.zip" upload: - "macOSTestApp.log" - "maze_output/failed/**/*" commands: - bundle install - bundle exec maze-runner - features/barebone_tests.feature + features/release/barebone_tests.feature --os=macos --fail-fast @@ -324,14 +331,14 @@ steps: queue: opensource-mac-cocoa-10.13 plugins: artifacts#v1.5.0: - download: "features/fixtures/macos/output/macOSTestApp.zip" + download: "features/fixtures/macos/output/macOSTestApp_Release.zip" upload: - "macOSTestApp.log" - "maze_output/failed/**/*" commands: - bundle install - bundle exec maze-runner - features/barebone_tests.feature + features/release/barebone_tests.feature --os=macos --fail-fast @@ -351,21 +358,21 @@ steps: queue: opensource plugins: artifacts#v1.5.0: - download: "features/fixtures/ios/output/ipa_url_bs.txt" + download: "features/fixtures/ios/output/ipa_url_bs_release.txt" upload: "maze_output/failed/**/*" docker-compose#v3.7.0: pull: cocoa-maze-runner run: cocoa-maze-runner service-ports: true command: - - "--app=@/app/build/ipa_url_bs.txt" + - "--app=@/app/build/ipa_url_bs_release.txt" - "--farm=bs" - "--device=IOS_17" - "--appium-version=1.21.0" - "--a11y-locator" - "--fail-fast" - - "--exclude=features/app_hangs.feature" - - "--exclude=features/[e-z].*.feature$" + - "features/release" + - "--exclude=features/release/[e-z].*.feature$" concurrency: 25 concurrency_group: 'browserstack-app' concurrency_method: eager @@ -382,20 +389,21 @@ steps: queue: opensource plugins: artifacts#v1.5.0: - download: "features/fixtures/ios/output/ipa_url_bs.txt" + download: "features/fixtures/ios/output/ipa_url_bs_release.txt" upload: "maze_output/failed/**/*" docker-compose#v3.7.0: pull: cocoa-maze-runner run: cocoa-maze-runner service-ports: true command: - - "--app=@/app/build/ipa_url_bs.txt" + - "--app=@/app/build/ipa_url_bs_release.txt" - "--farm=bs" - "--device=IOS_17" - "--appium-version=1.21.0" - "--a11y-locator" - "--fail-fast" - - "--exclude=features/[a-d].*.feature$" + - "features/release" + - "--exclude=features/release/[a-d].*.feature$" concurrency: 25 concurrency_group: 'browserstack-app' concurrency_method: eager @@ -413,13 +421,13 @@ steps: queue: opensource plugins: artifacts#v1.5.0: - download: "features/fixtures/ios/output/ipa_url_bs.txt" + download: "features/fixtures/ios/output/ipa_url_bs_release.txt" upload: "maze_output/failed/**/*" docker-compose#v3.7.0: pull: cocoa-maze-runner run: cocoa-maze-runner command: - - "--app=@build/ipa_url_bs.txt" + - "--app=@build/ipa_url_bs_release.txt" - "--farm=bs" - "--device=IOS_17" - "--appium-version=1.21.0" @@ -437,7 +445,7 @@ steps: ############################################################################## # - # Basic build E2E tests + # Basic build E2E tests - Release Configuration # # @@ -452,20 +460,20 @@ steps: queue: opensource plugins: artifacts#v1.9.3: - download: "features/fixtures/ios/output/ipa_url_bb.txt" + download: "features/fixtures/ios/output/ipa_url_bb_release.txt" upload: "maze_output/failed/**/*" docker-compose#v4.7.0: pull: cocoa-maze-runner-bitbar run: cocoa-maze-runner-bitbar service-ports: true command: - - "--app=@/app/build/ipa_url_bb.txt" + - "--app=@/app/build/ipa_url_bb_release.txt" - "--farm=bb" - "--device=IOS_16" - "--no-tunnel" - "--aws-public-ip" - "--fail-fast" - - "features/barebone_tests.feature" + - "features/release/barebone_tests.feature" concurrency: 25 concurrency_group: 'bitbar' concurrency_method: eager @@ -482,20 +490,20 @@ steps: queue: opensource plugins: artifacts#v1.9.3: - download: "features/fixtures/ios/output/ipa_url_bb.txt" + download: "features/fixtures/ios/output/ipa_url_bb_release.txt" upload: "maze_output/failed/**/*" docker-compose#v4.7.0: pull: cocoa-maze-runner-bitbar run: cocoa-maze-runner-bitbar service-ports: true command: - - "--app=@/app/build/ipa_url_bb.txt" + - "--app=@/app/build/ipa_url_bb_release.txt" - "--farm=bb" - "--device=IOS_15" - "--no-tunnel" - "--aws-public-ip" - "--fail-fast" - - "features/barebone_tests.feature" + - "features/release/barebone_tests.feature" concurrency: 25 concurrency_group: 'bitbar' concurrency_method: eager @@ -512,20 +520,20 @@ steps: queue: opensource plugins: artifacts#v1.9.3: - download: "features/fixtures/ios/output/ipa_url_bb.txt" + download: "features/fixtures/ios/output/ipa_url_bb_release.txt" upload: "maze_output/failed/**/*" docker-compose#v4.7.0: pull: cocoa-maze-runner-bitbar run: cocoa-maze-runner-bitbar service-ports: true command: - - "--app=@/app/build/ipa_url_bb.txt" + - "--app=@/app/build/ipa_url_bb_release.txt" - "--farm=bb" - "--device=IOS_14" - "--no-tunnel" - "--aws-public-ip" - "--fail-fast" - - "features/barebone_tests.feature" + - "features/release/barebone_tests.feature" concurrency: 25 concurrency_group: 'bitbar' concurrency_method: eager @@ -542,20 +550,20 @@ steps: queue: opensource plugins: artifacts#v1.9.3: - download: "features/fixtures/ios/output/ipa_url_bb.txt" + download: "features/fixtures/ios/output/ipa_url_bb_release.txt" upload: "maze_output/failed/**/*" docker-compose#v4.7.0: pull: cocoa-maze-runner-bitbar run: cocoa-maze-runner-bitbar service-ports: true command: - - "--app=@/app/build/ipa_url_bb.txt" + - "--app=@/app/build/ipa_url_bb_release.txt" - "--farm=bb" - "--device=IOS_13" - "--no-tunnel" - "--aws-public-ip" - "--fail-fast" - - "features/barebone_tests.feature" + - "features/release/barebone_tests.feature" concurrency: 25 concurrency_group: 'bitbar' concurrency_method: eager @@ -564,6 +572,105 @@ steps: - exit_status: -1 # Agent was lost limit: 2 + ############################################################################## + # + # Debug configration E2E tests + # + + - label: ':browserstack: iOS 17 debug configuration tests' + depends_on: + - cocoa_fixture + timeout_in_minutes: 60 + agents: + queue: opensource + plugins: + artifacts#v1.9.3: + download: "features/fixtures/ios/output/ipa_url_bs_debug.txt" + upload: "maze_output/failed/**/*" + docker-compose#v4.7.0: + pull: cocoa-maze-runner + run: cocoa-maze-runner + command: + - "--app=@/app/build/ipa_url_bs_debug.txt" + - "--farm=bs" + - "--device=IOS_17" + - "--fail-fast" + - "features/debug" + concurrency: 5 + concurrency_group: 'browserstack-app' + concurrency_method: eager + retry: + automatic: + - exit_status: -1 # Agent was lost + limit: 2 + + - label: ':bitbar: iOS 13 debug configuration tests' + depends_on: + - cocoa_fixture + timeout_in_minutes: 60 + agents: + queue: opensource + plugins: + artifacts#v1.9.3: + download: "features/fixtures/ios/output/ipa_url_bb_debug.txt" + upload: "maze_output/failed/**/*" + docker-compose#v4.7.0: + pull: cocoa-maze-runner-bitbar + run: cocoa-maze-runner-bitbar + service-ports: true + command: + - "--app=@/app/build/ipa_url_bb_debug.txt" + - "--farm=bb" + - "--device=IOS_13" + - "--no-tunnel" + - "--aws-public-ip" + - "--fail-fast" + - "features/debug" + concurrency: 25 + concurrency_group: 'bitbar' + concurrency_method: eager + retry: + automatic: + - exit_status: -1 # Agent was lost + limit: 2 + + - label: 'macOS 14 debug E2E tests' + depends_on: + - cocoa_fixture + timeout_in_minutes: 10 + agents: + queue: macos-14 + plugins: + artifacts#v1.5.0: + download: "features/fixtures/macos/output/macOSTestApp_Debug.zip" + upload: + - "macOSTestApp.log" + - "maze_output/failed/**/*" + commands: + - bundle install + - bundle exec maze-runner + features/debug + --os=macos + --fail-fast + + - label: 'macOS 10.13 debug E2E tests' + depends_on: + - cocoa_fixture + timeout_in_minutes: 10 + agents: + queue: opensource-mac-cocoa-10.13 + plugins: + artifacts#v1.5.0: + download: "features/fixtures/macos/output/macOSTestApp_Debug.zip" + upload: + - "macOSTestApp.log" + - "maze_output/failed/**/*" + commands: + - bundle install + - bundle exec maze-runner + features/debug + --os=macos + --fail-fast ############################################################################## # diff --git a/.github/workflows/pull_request.yml b/.github/workflows/pull_request.yml index 1af84fae0..cc52ec08e 100644 --- a/.github/workflows/pull_request.yml +++ b/.github/workflows/pull_request.yml @@ -4,10 +4,10 @@ on: [pull_request] jobs: analyze: - runs-on: macos-11 + runs-on: macos-14 env: # Infer 1.0.1 cannot parse the iOS 15 SDK headers - DEVELOPER_DIR: /Applications/Xcode_12.5.1.app + DEVELOPER_DIR: /Applications/Xcode_15.4.app steps: - name: Checkout pull request HEAD uses: actions/checkout@v2 @@ -21,7 +21,7 @@ jobs: run: make oclint danger: - runs-on: macos-11 + runs-on: macos-14 steps: - name: Checkout target branch uses: actions/checkout@v2 @@ -31,7 +31,7 @@ jobs: run: xcodebuild -project Bugsnag.xcodeproj -configuration Release -target Bugsnag-iOS -destination generic/platform=iOS -quiet clean build VALID_ARCHS=arm64 RUN_CLANG_STATIC_ANALYZER=NO && mv build build.base - name: Checkout pull request merge branch uses: actions/checkout@v2 - with: + with: clean: false fetch-depth: 100 - name: Build framework diff --git a/.jazzy.yaml b/.jazzy.yaml index 051ca70b3..d4c5f6992 100644 --- a/.jazzy.yaml +++ b/.jazzy.yaml @@ -2,11 +2,11 @@ author_url: "https://www.bugsnag.com" author: "Bugsnag Inc" clean: false # avoid deleting docs/.git framework_root: "Bugsnag" -github_file_prefix: "https://github.com/bugsnag/bugsnag-cocoa/tree/v6.30.0/Bugsnag" +github_file_prefix: "https://github.com/bugsnag/bugsnag-cocoa/tree/v6.30.1/Bugsnag" github_url: "https://github.com/bugsnag/bugsnag-cocoa" hide_documentation_coverage: true module: "Bugsnag" -module_version: "6.30.0" +module_version: "6.30.1" objc: true output: "docs" readme: "README.md" diff --git a/Bugsnag.podspec.json b/Bugsnag.podspec.json index 56b984b3f..a9b136bd4 100644 --- a/Bugsnag.podspec.json +++ b/Bugsnag.podspec.json @@ -1,6 +1,6 @@ { "name": "Bugsnag", - "version": "6.30.0", + "version": "6.30.1", "summary": "The Bugsnag crash reporting framework for Apple platforms.", "homepage": "https://bugsnag.com", "license": "MIT", @@ -9,7 +9,7 @@ }, "source": { "git": "https://github.com/bugsnag/bugsnag-cocoa.git", - "tag": "v6.30.0" + "tag": "v6.30.1" }, "ios": { "frameworks": [ diff --git a/Bugsnag.xcodeproj/project.pbxproj b/Bugsnag.xcodeproj/project.pbxproj index 4939f4dc0..c1ede6ab0 100644 --- a/Bugsnag.xcodeproj/project.pbxproj +++ b/Bugsnag.xcodeproj/project.pbxproj @@ -1577,7 +1577,7 @@ 093EB6652AFE4580006EB7E3 /* BSGTestCase.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = BSGTestCase.mm; sourceTree = ""; }; 09E312ED2BF230660081F219 /* BugsnagCocoaPerformanceFromBugsnagCocoa.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = BugsnagCocoaPerformanceFromBugsnagCocoa.h; sourceTree = ""; }; 09E312EE2BF230660081F219 /* BugsnagCocoaPerformanceFromBugsnagCocoa.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = BugsnagCocoaPerformanceFromBugsnagCocoa.m; sourceTree = ""; }; - 09E312F72BF248DD0081F219 /* BugsnagCorrelation.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = BugsnagCorrelation.h; path = ../include/Bugsnag/BugsnagCorrelation.h; sourceTree = ""; }; + 09E312F72BF248DD0081F219 /* BugsnagCorrelation.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = BugsnagCorrelation.h; sourceTree = ""; }; 09E312FD2BF34D6D0081F219 /* BugsnagCorrelation.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = BugsnagCorrelation.m; sourceTree = ""; }; 09E3132E2BF3867C0081F219 /* BugsnagPerformanceBridgeTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = BugsnagPerformanceBridgeTests.m; sourceTree = ""; }; 3A700A8024A63A8E0068CD1B /* BugsnagThread.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = BugsnagThread.h; sourceTree = ""; }; diff --git a/Bugsnag/Helpers/BSGRunContext.m b/Bugsnag/Helpers/BSGRunContext.m index 58015b685..9b6411ae5 100644 --- a/Bugsnag/Helpers/BSGRunContext.m +++ b/Bugsnag/Helpers/BSGRunContext.m @@ -461,7 +461,7 @@ static void UpdateTaskMemory(void) { setMemoryUsage(footprint, task_vm.limit_bytes_remaining); } else { #if !TARGET_OS_OSX - if (@available(iOS 13.0, tvOS 13.0, watchOS 6.0, *)) { + if (@available(iOS 13.0, tvOS 13.0, watchOS 6.0, macCatalyst 13.1, *)) { setMemoryUsage(footprint, os_proc_available_memory()); } #endif diff --git a/Bugsnag/Payload/BugsnagNotifier.m b/Bugsnag/Payload/BugsnagNotifier.m index ef1d791d1..cd5fd9a43 100644 --- a/Bugsnag/Payload/BugsnagNotifier.m +++ b/Bugsnag/Payload/BugsnagNotifier.m @@ -23,7 +23,7 @@ - (instancetype)init { #else _name = @"Bugsnag Objective-C"; #endif - _version = @"6.30.0"; + _version = @"6.30.1"; _url = @"https://github.com/bugsnag/bugsnag-cocoa"; _dependencies = @[]; } diff --git a/Bugsnag/include/Bugsnag/BugsnagCorrelation.h b/Bugsnag/include/Bugsnag/BugsnagCorrelation.h deleted file mode 100644 index ac5902987..000000000 --- a/Bugsnag/include/Bugsnag/BugsnagCorrelation.h +++ /dev/null @@ -1,29 +0,0 @@ -// -// BugsnagCorrelation.h -// Bugsnag -// -// Created by Karl Stenerud on 13.05.24. -// Copyright © 2024 Bugsnag Inc. All rights reserved. -// - -#import -#import - -NS_ASSUME_NONNULL_BEGIN - -BUGSNAG_EXTERN -@interface BugsnagCorrelation: NSObject - -@property (readonly, nonatomic, strong, nullable) NSString *traceId; - -@property (readonly, nonatomic, strong, nullable) NSString *spanId; - -- (instancetype) initWithTraceId:(NSString * _Nullable) traceId spanId:(NSString * _Nullable)spanId; - -- (instancetype) initWithJsonDictionary:(NSDictionary * _Nullable) dict; - -- (NSDictionary *) toJsonDictionary; - -@end - -NS_ASSUME_NONNULL_END diff --git a/BugsnagNetworkRequestPlugin.podspec.json b/BugsnagNetworkRequestPlugin.podspec.json index 247d6721a..918311e9a 100644 --- a/BugsnagNetworkRequestPlugin.podspec.json +++ b/BugsnagNetworkRequestPlugin.podspec.json @@ -1,16 +1,16 @@ { "name": "BugsnagNetworkRequestPlugin", - "version": "6.30.0", + "version": "6.30.1", "summary": "Network request monitoring support for Bugsnag.", "homepage": "https://bugsnag.com", "license": "MIT", "authors": { "Bugsnag": "notifiers@bugsnag.com" }, - "readme": "https://raw.githubusercontent.com/bugsnag/bugsnag-cocoa/v6.30.0/BugsnagNetworkRequestPlugin/README.md", + "readme": "https://raw.githubusercontent.com/bugsnag/bugsnag-cocoa/v6.30.1/BugsnagNetworkRequestPlugin/README.md", "source": { "git": "https://github.com/bugsnag/bugsnag-cocoa.git", - "tag": "v6.30.0" + "tag": "v6.30.1" }, "dependencies": { "Bugsnag": "~> 6.13" diff --git a/CHANGELOG.md b/CHANGELOG.md index 725a31f49..28471f98c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,16 @@ Changelog ========= +## 6.30.1 (2024-07-25) + +### Bug Fixes + +* Removed duplicate BugsnagCorrelation.h header file that was causing warnings when building an app. + [1682](https://github.com/bugsnag/bugsnag-cocoa/pull/1682) + +* Mac Catalyst targets now only attempt to call os_proc_available_memory() from version 13.1. + [1680](https://github.com/bugsnag/bugsnag-cocoa/pull/1680) + ## 6.30.0 (2024-07-04) ### Enhancements diff --git a/Framework/Info.plist b/Framework/Info.plist index 34c3136e1..cf0f480cc 100644 --- a/Framework/Info.plist +++ b/Framework/Info.plist @@ -15,7 +15,7 @@ CFBundlePackageType FMWK CFBundleShortVersionString - 6.30.0 + 6.30.1 CFBundleVersion 1 diff --git a/Makefile b/Makefile index 1413b0e7e..7e647c78b 100644 --- a/Makefile +++ b/Makefile @@ -132,8 +132,10 @@ test: ## Run unit tests @$(XCODEBUILD) $(BUILD_FLAGS) $(BUILD_ONLY_FLAGS) test $(FORMATTER) test-fixtures: ## Build the end-to-end test fixture - @./features/scripts/export_ios_app.sh - @./features/scripts/export_mac_app.sh + @./features/scripts/export_ios_app.sh Release + @./features/scripts/export_ios_app.sh Debug + @./features/scripts/export_mac_app.sh Release + @./features/scripts/export_mac_app.sh Debug e2e_ios_local: @./features/scripts/export_ios_app.sh diff --git a/Tests/BugsnagTests/Info.plist b/Tests/BugsnagTests/Info.plist index 6172fbf46..1783e9ee7 100644 --- a/Tests/BugsnagTests/Info.plist +++ b/Tests/BugsnagTests/Info.plist @@ -15,7 +15,7 @@ CFBundlePackageType $(PRODUCT_BUNDLE_PACKAGE_TYPE) CFBundleShortVersionString - 6.30.0 + 6.30.1 CFBundleVersion 1 diff --git a/Tests/TestHost-iOS/Info.plist b/Tests/TestHost-iOS/Info.plist index c5b1a316f..4713c1963 100644 --- a/Tests/TestHost-iOS/Info.plist +++ b/Tests/TestHost-iOS/Info.plist @@ -15,7 +15,7 @@ CFBundlePackageType $(PRODUCT_BUNDLE_PACKAGE_TYPE) CFBundleShortVersionString - 6.30.0 + 6.30.1 CFBundleVersion 1 LSRequiresIPhoneOS diff --git a/VERSION b/VERSION index 137f5acd5..306b5efd0 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -6.30.0 +6.30.1 diff --git a/features/app_hangs.feature b/features/app_hangs.feature index a335068e7..065b9816d 100644 --- a/features/app_hangs.feature +++ b/features/app_hangs.feature @@ -72,7 +72,7 @@ Feature: App hangs | ios | com.bugsnag.fixtures.cocoa | | macos | com.bugsnag.fixtures.macOSTestApp | And the error payload field "events.0.app.isLaunching" is true - And the error payload field "events.0.app.releaseStage" equals "development" + And the error payload field "events.0.app.releaseStage" equals "production" And the error payload field "events.0.app.type" equals the platform-dependent string: | ios | iOS | | macos | macOS | diff --git a/features/crashprobe.feature b/features/debug/crashprobe.feature similarity index 100% rename from features/crashprobe.feature rename to features/debug/crashprobe.feature diff --git a/features/cross_notifier_notify.feature b/features/debug/cross_notifier_notify.feature similarity index 100% rename from features/cross_notifier_notify.feature rename to features/debug/cross_notifier_notify.feature diff --git a/features/debug/handled_errors.feature b/features/debug/handled_errors.feature new file mode 100644 index 000000000..c8c4a2b4a --- /dev/null +++ b/features/debug/handled_errors.feature @@ -0,0 +1,21 @@ +Feature: Handled Errors and Exceptions + + Background: + Given I clear all persistent data + + Scenario: Reporting a handled exception's stacktrace + When I run "NSExceptionShiftScenario" + And I wait to receive an error + Then the error is valid for the error reporting API + And the error payload field "events" is an array with 1 elements + And the exception "errorClass" equals "Tertiary failure" + And the exception "message" equals "invalid invariant" + And the event "severity" equals "warning" + And the event "unhandled" is false + And the event "severityReason.type" equals "handledException" + And the event "exceptions.0.stacktrace.0.method" equals one of: + | | + | __exceptionPreprocess | + And the "method" of stack frame 1 equals "objc_exception_throw" + And the "method" of stack frame 2 equals "-[NSExceptionShiftScenario causeAnException]" + And the "method" of stack frame 3 equals "-[NSExceptionShiftScenario run]" diff --git a/features/unhandled_nsexception.feature b/features/debug/unhandled_nsexception.feature similarity index 100% rename from features/unhandled_nsexception.feature rename to features/debug/unhandled_nsexception.feature diff --git a/features/app_and_device_attributes.feature b/features/release/app_and_device_attributes.feature similarity index 99% rename from features/app_and_device_attributes.feature rename to features/release/app_and_device_attributes.feature index f732922e6..d56dbc7db 100644 --- a/features/app_and_device_attributes.feature +++ b/features/release/app_and_device_attributes.feature @@ -45,7 +45,7 @@ Feature: App and Device attributes present | ios | com.bugsnag.fixtures.cocoa | | macos | com.bugsnag.fixtures.macOSTestApp | And the error payload field "events.0.app.isLaunching" is true - And the error payload field "events.0.app.releaseStage" equals "development" + And the error payload field "events.0.app.releaseStage" equals "production" And the error payload field "events.0.app.type" equals the platform-dependent string: | ios | iOS | | macos | macOS | diff --git a/features/auto_detect_errors.feature b/features/release/auto_detect_errors.feature similarity index 100% rename from features/auto_detect_errors.feature rename to features/release/auto_detect_errors.feature diff --git a/features/barebone_tests.feature b/features/release/barebone_tests.feature similarity index 99% rename from features/barebone_tests.feature rename to features/release/barebone_tests.feature index d6664c37c..981e86175 100644 --- a/features/barebone_tests.feature +++ b/features/release/barebone_tests.feature @@ -24,7 +24,7 @@ Feature: Barebone tests | watchos | com.bugsnag.fixtures.watchOSTestApp.watchkitapp.watchkitextension | And the event "app.inForeground" is true And the event "app.isLaunching" is true - And the event "app.releaseStage" equals "development" + And the event "app.releaseStage" equals "production" And the event "app.type" equals the platform-dependent string: | ios | iOS | | macos | macOS | @@ -162,7 +162,7 @@ Feature: Barebone tests And the event "app.bundleVersion" equals "12301" And the event "app.inForeground" is true And the event "app.isLaunching" is true - And the event "app.releaseStage" equals "development" + And the event "app.releaseStage" equals "production" And the event "app.type" equals the platform-dependent string: | ios | iOS | | macos | macOS | diff --git a/features/breadcrumb_callbacks.feature b/features/release/breadcrumb_callbacks.feature similarity index 100% rename from features/breadcrumb_callbacks.feature rename to features/release/breadcrumb_callbacks.feature diff --git a/features/breadcrumbs.feature b/features/release/breadcrumbs.feature similarity index 100% rename from features/breadcrumbs.feature rename to features/release/breadcrumbs.feature diff --git a/features/config_from_plist.feature b/features/release/config_from_plist.feature similarity index 100% rename from features/config_from_plist.feature rename to features/release/config_from_plist.feature diff --git a/features/context.feature b/features/release/context.feature similarity index 100% rename from features/context.feature rename to features/release/context.feature diff --git a/features/release/crashprobe.feature b/features/release/crashprobe.feature new file mode 100644 index 000000000..1986131ca --- /dev/null +++ b/features/release/crashprobe.feature @@ -0,0 +1,230 @@ +Feature: Reporting crash events + + Background: + Given I clear all persistent data + + Scenario: Executing privileged instruction + When I run "PrivilegedInstructionScenario" and relaunch the crashed app + And I configure Bugsnag for "PrivilegedInstructionScenario" + And I wait to receive an error + Then the error is valid for the error reporting API + And the error payload field "events" is an array with 1 elements + And the exception "errorClass" equals one of: + | Intel | EXC_BAD_ACCESS | + | ARM | EXC_BAD_INSTRUCTION | + And the "method" of stack frame 0 equals "-[PrivilegedInstructionScenario run]" + And the "isPC" of stack frame 0 is true + And on x86, the "isLR" of stack frame 0 is null + + Scenario: Calling __builtin_trap() + When I run "BuiltinTrapScenario" and relaunch the crashed app + And I configure Bugsnag for "BuiltinTrapScenario" + And I wait to receive an error + Then the error is valid for the error reporting API + And the error payload field "events" is an array with 1 elements + And the exception "errorClass" equals one of: + | Intel | EXC_BAD_INSTRUCTION | + | ARM | EXC_BREAKPOINT | + And the "method" of stack frame 0 equals "-[BuiltinTrapScenario run]" + And the "isPC" of stack frame 0 is true + And on x86, the "isLR" of stack frame 0 is null + + Scenario: Calling non-existent method + When I run "NonExistentMethodScenario" and relaunch the crashed app + And I configure Bugsnag for "NonExistentMethodScenario" + And I wait to receive an error + Then the error is valid for the error reporting API + And the error payload field "events" is an array with 1 elements + And the exception "message" starts with "-[NonExistentMethodScenario santaclaus:]: unrecognized selector sent to instance" + And the exception "errorClass" equals "NSInvalidArgumentException" + And the event "exceptions.0.stacktrace.0.method" equals one of: + | | + | __exceptionPreprocess | + And the event "exceptions.0.stacktrace.1.method" equals one of: + | | + | objc_exception_throw | + And the event "exceptions.0.stacktrace.2.method" equals one of: + | | + | -[NSObject(NSObject) doesNotRecognizeSelector:] | + And the event "exceptions.0.stacktrace.3.method" equals one of: + | | + | ___forwarding___ | + And the "method" of stack frame 4 equals "_CF_forwarding_prep_0" + # Skipped pending PLAT-10759 + #And the "method" of stack frame 5 equals "-[NonExistentMethodScenario run]" + And the "isPC" of stack frame 0 is null + And the "isLR" of stack frame 0 is null + + Scenario: Trigger a crash after overwriting the link register + When I run "OverwriteLinkRegisterScenario" and relaunch the crashed app + And I configure Bugsnag for "OverwriteLinkRegisterScenario" + And I wait to receive an error + Then the error is valid for the error reporting API + And the exception "errorClass" equals "EXC_BAD_ACCESS" + And the exception "message" equals "Attempted to dereference null pointer." + And the "method" of stack frame 0 equals "-[OverwriteLinkRegisterScenario run]" + And the "isPC" of stack frame 0 is true + And the "isLR" of stack frame 0 is null + + Scenario: Attempt to write into a read-only page + When I run "ReadOnlyPageScenario" and relaunch the crashed app + And I configure Bugsnag for "ReadOnlyPageScenario" + And I wait to receive an error + Then the error is valid for the error reporting API + And the exception "errorClass" equals "EXC_BAD_ACCESS" + And the "method" of stack frame 0 equals "-[ReadOnlyPageScenario run]" + And the "isPC" of stack frame 0 is true + And the "isLR" of stack frame 0 is null + + Scenario: Stack overflow + When I run "StackOverflowScenario" and relaunch the crashed app + And I configure Bugsnag for "StackOverflowScenario" + And I wait to receive an error + Then the error is valid for the error reporting API + And the exception "message" equals "Stack overflow in -[StackOverflowScenario run]" + And the exception "errorClass" equals "EXC_BAD_ACCESS" + And the "method" of stack frame 0 equals "-[StackOverflowScenario run]" + And the "method" of stack frame 1 equals "-[StackOverflowScenario run]" + And the "method" of stack frame 2 equals "-[StackOverflowScenario run]" + And the "method" of stack frame 3 equals "-[StackOverflowScenario run]" + And the "method" of stack frame 4 equals "-[StackOverflowScenario run]" + And the "method" of stack frame 5 equals "-[StackOverflowScenario run]" + And the "method" of stack frame 6 equals "-[StackOverflowScenario run]" + And the "method" of stack frame 7 equals "-[StackOverflowScenario run]" + And the "method" of stack frame 8 equals "-[StackOverflowScenario run]" + And the "method" of stack frame 9 equals "-[StackOverflowScenario run]" + + Scenario: Crash inside objc_msgSend() + When I run "ObjCMsgSendScenario" and relaunch the crashed app + And I configure Bugsnag for "ObjCMsgSendScenario" + And I wait to receive an error + Then the error is valid for the error reporting API + And the exception "errorClass" equals "EXC_BAD_ACCESS" + And the exception "message" equals one of: + | ARM | Attempted to dereference garbage pointer 0x38. | + | Intel | Attempted to dereference garbage pointer 0x40. | + And the "method" of stack frame 0 equals "objc_msgSend" + And the "isPC" of stack frame 0 is true + And the "isLR" of stack frame 0 is null + + Scenario: Attempt to execute an instruction undefined on the current architecture + When I run "UndefinedInstructionScenario" and relaunch the crashed app + And I configure Bugsnag for "UndefinedInstructionScenario" + And I wait to receive an error + Then the error is valid for the error reporting API + And the exception "errorClass" equals "EXC_BAD_INSTRUCTION" + And the "method" of stack frame 0 equals "-[UndefinedInstructionScenario run]" + And the "isPC" of stack frame 0 is true + And on x86, the "isLR" of stack frame 0 is null + + Scenario: Send a message to an object whose memory has already been freed + When I run "ReleasedObjectScenario" and relaunch the crashed app + And I configure Bugsnag for "ReleasedObjectScenario" + And I wait to receive an error + Then the error is valid for the error reporting API + And the exception "message" matches "Attempted to dereference (garbage|null) pointer" + And the exception "errorClass" equals "EXC_BAD_ACCESS" + And the "method" of stack frame 0 equals "objc_msgSend" + And the stacktrace contains methods: + | -[ReleasedObjectScenario run] | + And the "isPC" of stack frame 0 is true + And the "isLR" of stack frame 0 is null + + # TODO: Skipped Pending PLAT-12398 + @skip_macos + Scenario: Crash within Swift code + When I run "SwiftCrashScenario" and relaunch the crashed app + And I configure Bugsnag for "SwiftCrashScenario" + And I wait to receive an error + Then the error is valid for the error reporting API + And the exception "errorClass" equals "Fatal error" + And the exception "message" equals "Unexpectedly found nil while unwrapping an Optional value" + And the event "metaData.error.crashInfo" matches "Fatal error: Unexpectedly found nil while unwrapping an Optional value" + And the "isPC" of stack frame 0 is true + And on x86, the "isLR" of stack frame 0 is null + + Scenario: Assertion failure in Swift code + When I run "SwiftAssertionScenario" and relaunch the crashed app + And I configure Bugsnag for "SwiftAssertionScenario" + And I wait to receive an error + Then the error is valid for the error reporting API + And the exception "errorClass" equals "Fatal error" + And the exception "message" equals "several unfortunate things just happened" + And the event "metaData.error.crashInfo" matches "Fatal error: several unfortunate things just happened" + And the "isPC" of stack frame 0 is true + And on x86, the "isLR" of stack frame 0 is null + + Scenario: Dereference a null pointer + When I run "NullPointerScenario" and relaunch the crashed app + And I configure Bugsnag for "NullPointerScenario" + And I wait to receive an error + Then the error is valid for the error reporting API + And the exception "message" equals "Attempted to dereference null pointer." + And the exception "errorClass" equals "EXC_BAD_ACCESS" + And the "method" of stack frame 0 equals "-[NullPointerScenario run]" + And the "isPC" of stack frame 0 is true + And the "isLR" of stack frame 0 is null + + Scenario: Trigger a crash with libsystem_pthread's _pthread_list_lock held + When I run "AsyncSafeThreadScenario" and relaunch the crashed app + And I configure Bugsnag for "AsyncSafeThreadScenario" + And I wait to receive an error + Then the error is valid for the error reporting API + And the error payload field "events" is an array with 1 elements + And the exception "message" equals "Attempted to dereference garbage pointer 0x1." + And the exception "errorClass" equals "EXC_BAD_ACCESS" + And the stacktrace contains methods: + # |pthread_getname_np| + | -[AsyncSafeThreadScenario run] | + And the "isPC" of stack frame 0 is true + And the "isLR" of stack frame 0 is null + + Scenario: Trigger a crash with simulated malloc() lock held + When I run "AsyncSafeMallocScenario" and relaunch the crashed app + And I configure Bugsnag for "AsyncSafeMallocScenario" + And I wait to receive an error + And the exception "errorClass" equals "SIGABRT" + And the "isPC" of stack frame 0 is true + And the "isLR" of stack frame 0 is null + + Scenario: Read a garbage pointer + When I run "ReadGarbagePointerScenario" and relaunch the crashed app + And I configure Bugsnag for "ReadGarbagePointerScenario" + And I wait to receive an error + Then the error is valid for the error reporting API + And the exception "message" starts with "Attempted to dereference garbage pointer" + And the exception "errorClass" equals "EXC_BAD_ACCESS" + And the "method" of stack frame 0 equals "-[ReadGarbagePointerScenario run]" + And the "isPC" of stack frame 0 is true + And the "isLR" of stack frame 0 is null + + Scenario: Access a non-object as an object + When I run "AccessNonObjectScenario" and relaunch the crashed app + And I configure Bugsnag for "AccessNonObjectScenario" + And I wait to receive an error + Then the error is valid for the error reporting API + And the exception "message" equals "Attempted to dereference garbage pointer 0x10." + And the exception "errorClass" equals "EXC_BAD_ACCESS" + And the "method" of stack frame 0 equals "objc_msgSend" + And the "isPC" of stack frame 0 is true + And the "isLR" of stack frame 0 is null + + Scenario: Misuse of libdispatch + When I run "DispatchCrashScenario" and relaunch the crashed app + And I configure Bugsnag for "DispatchCrashScenario" + And I wait to receive an error + Then the error is valid for the error reporting API + And the exception "errorClass" equals one of: + | ARM | EXC_BREAKPOINT | + | Intel | EXC_BAD_INSTRUCTION | + And the exception "message" starts with "BUG IN CLIENT OF LIBDISPATCH: dispatch_" + And the event "metaData.error.crashInfo" starts with "BUG IN CLIENT OF LIBDISPATCH: dispatch_" + And the "isPC" of stack frame 0 is true + And the "isLR" of stack frame 0 is null + + Scenario: Concurrent crashes should result in a single valid crash report + Given I run "ConcurrentCrashesScenario" and relaunch the crashed app + And I configure Bugsnag for "ConcurrentCrashesScenario" + And I wait to receive an error + Then the error is valid for the error reporting API + And the event "unhandled" is true diff --git a/features/release/cross_notifier_notify.feature b/features/release/cross_notifier_notify.feature new file mode 100644 index 000000000..392241b49 --- /dev/null +++ b/features/release/cross_notifier_notify.feature @@ -0,0 +1,64 @@ +Feature: Communicating events between notifiers + + Other Bugsnag libraries include bugsnag-cocoa as a dependency for capturing + native cocoa crashes, but may have additional events to report, both + handled and unhandled. Those events should be reported correctly when + using bugsnag-cocoa as the delivery layer. + + Background: + Given I clear all persistent data + + Scenario: Report a handled event through internalNotify() + Report a handled exception, including a custom stacktrace and severity. + Event counts in the report's session should match the handled-ness. + + When I run "HandledInternalNotifyScenario" + And I wait to receive a session + And I wait to receive an error + Then the session is valid for the session reporting API + And the session payload field "sessions.0.id" is stored as the value "session_id" + + Then the error is valid for the error reporting API + And the exception "errorClass" equals "Handled Error!" + And the exception "message" equals "Internally reported a handled event" + And the exception "type" equals "unreal" + And the event "severity" equals "warning" + And the event "severityReason.type" equals "handledException" + + And the "method" of stack frame 0 equals "foo()" + And the "file" of stack frame 0 equals "src/Giraffe.mm" + And the "lineNumber" of stack frame 0 equals 200 + And the event "unhandled" is false + + And the error payload field "events" is an array with 1 elements + And the error payload field "events.0.session.events.handled" equals 1 + And the error payload field "events.0.session.events.unhandled" equals 0 + And the error payload field "events.0.session.id" equals the stored value "session_id" + + Scenario: Report an unhandled event through internalNotify() + Report an unhandled exception, including a custom stacktrace and severity. + Event counts in the report's session should match the handled-ness. + + When I run "UnhandledInternalNotifyScenario" + And I wait to receive a session + And I wait to receive an error + Then the session is valid for the session reporting API + And the session payload field "sessions.0.id" is stored as the value "session_id" + + Then the error is valid for the error reporting API + And the exception "errorClass" equals "Unhandled Error?!" + And the exception "message" equals "Internally reported an unhandled event" + And the exception "type" equals "fake" + And the event "severity" equals "info" + And the event "severityReason.type" equals "userCallbackSetSeverity" + + And the "method" of stack frame 0 equals "bar()" + And the "file" of stack frame 0 equals "foo.js" + And the "lineNumber" of stack frame 0 equals 43 + And the event "unhandled" is true + And the event "severityReason.unhandledOverridden" is true + + And the error payload field "events" is an array with 1 elements + And the error payload field "events.0.session.events.handled" equals 0 + And the error payload field "events.0.session.events.unhandled" equals 1 + And the error payload field "events.0.session.id" equals the stored value "session_id" diff --git a/features/delivery.feature b/features/release/delivery.feature similarity index 99% rename from features/delivery.feature rename to features/release/delivery.feature index 477d76831..3b75d6d00 100644 --- a/features/delivery.feature +++ b/features/release/delivery.feature @@ -160,6 +160,8 @@ Feature: Delivery of errors And the event "usage.system.stringsTruncated" is not null @skip_ios_17 + # TODO: Skipped Pending PLAT-12398 + @skip_macos Scenario Outline: Attempt Delivery On Crash When I set the app to "" mode And I run "AttemptDeliveryOnCrashScenario" diff --git a/features/discard_classes.feature b/features/release/discard_classes.feature similarity index 100% rename from features/discard_classes.feature rename to features/release/discard_classes.feature diff --git a/features/enabled_error_types.feature b/features/release/enabled_error_types.feature similarity index 100% rename from features/enabled_error_types.feature rename to features/release/enabled_error_types.feature diff --git a/features/error_reporting_thread.feature b/features/release/error_reporting_thread.feature similarity index 100% rename from features/error_reporting_thread.feature rename to features/release/error_reporting_thread.feature diff --git a/features/event_callbacks.feature b/features/release/event_callbacks.feature similarity index 100% rename from features/event_callbacks.feature rename to features/release/event_callbacks.feature diff --git a/features/handled_errors.feature b/features/release/handled_errors.feature similarity index 94% rename from features/handled_errors.feature rename to features/release/handled_errors.feature index 3061b0b33..973e67296 100644 --- a/features/handled_errors.feature +++ b/features/release/handled_errors.feature @@ -64,9 +64,6 @@ Feature: Handled Errors and Exceptions And the event "exceptions.0.stacktrace.0.method" equals one of: | | | __exceptionPreprocess | - And the "method" of stack frame 1 equals "objc_exception_throw" - And the "method" of stack frame 2 equals "-[NSExceptionShiftScenario causeAnException]" - And the "method" of stack frame 3 equals "-[NSExceptionShiftScenario run]" Scenario: Reporting handled errors concurrently When I run "ManyConcurrentNotifyScenario" diff --git a/features/internal_workings.feature b/features/release/internal_workings.feature similarity index 100% rename from features/internal_workings.feature rename to features/release/internal_workings.feature diff --git a/features/last_run_info.feature b/features/release/last_run_info.feature similarity index 100% rename from features/last_run_info.feature rename to features/release/last_run_info.feature diff --git a/features/metadata_merging.feature b/features/release/metadata_merging.feature similarity index 100% rename from features/metadata_merging.feature rename to features/release/metadata_merging.feature diff --git a/features/metadata_redaction.feature b/features/release/metadata_redaction.feature similarity index 100% rename from features/metadata_redaction.feature rename to features/release/metadata_redaction.feature diff --git a/features/out_of_memory.feature b/features/release/out_of_memory.feature similarity index 100% rename from features/out_of_memory.feature rename to features/release/out_of_memory.feature diff --git a/features/plugin_interface.feature b/features/release/plugin_interface.feature similarity index 100% rename from features/plugin_interface.feature rename to features/release/plugin_interface.feature diff --git a/features/recrash_reports.feature b/features/release/recrash_reports.feature similarity index 100% rename from features/recrash_reports.feature rename to features/release/recrash_reports.feature diff --git a/features/release_stage_errors.feature b/features/release/release_stage_errors.feature similarity index 100% rename from features/release_stage_errors.feature rename to features/release/release_stage_errors.feature diff --git a/features/release_stage_sessions.feature b/features/release/release_stage_sessions.feature similarity index 100% rename from features/release_stage_sessions.feature rename to features/release/release_stage_sessions.feature diff --git a/features/runtime_versions.feature b/features/release/runtime_versions.feature similarity index 100% rename from features/runtime_versions.feature rename to features/release/runtime_versions.feature diff --git a/features/session_callbacks.feature b/features/release/session_callbacks.feature similarity index 100% rename from features/session_callbacks.feature rename to features/release/session_callbacks.feature diff --git a/features/session_stopping.feature b/features/release/session_stopping.feature similarity index 100% rename from features/session_stopping.feature rename to features/release/session_stopping.feature diff --git a/features/session_tracking.feature b/features/release/session_tracking.feature similarity index 98% rename from features/session_tracking.feature rename to features/release/session_tracking.feature index ee1a17892..4b90d1e07 100644 --- a/features/session_tracking.feature +++ b/features/release/session_tracking.feature @@ -10,7 +10,7 @@ Feature: Session Tracking And the session payload field "sessions" is an array with 1 elements And the session payload field "app.version" equals "1.0.3" And the session payload field "app.bundleVersion" equals "5" - And the session payload field "app.releaseStage" equals "development" + And the session payload field "app.releaseStage" equals "production" And the session payload field "app.type" equals the platform-dependent string: | ios | iOS | | macos | macOS | @@ -32,7 +32,7 @@ Feature: Session Tracking And the session payload field "sessions" is an array with 1 elements And the session payload field "app.version" equals "2.0.14" And the session payload field "app.bundleVersion" equals "5" - And the session payload field "app.releaseStage" equals "development" + And the session payload field "app.releaseStage" equals "production" And the session payload field "app.type" equals the platform-dependent string: | ios | iOS | | macos | macOS | diff --git a/features/stress_test.feature b/features/release/stress_test.feature similarity index 100% rename from features/stress_test.feature rename to features/release/stress_test.feature diff --git a/features/telemetry.feature b/features/release/telemetry.feature similarity index 100% rename from features/telemetry.feature rename to features/release/telemetry.feature diff --git a/features/thermal_state.feature b/features/release/thermal_state.feature similarity index 100% rename from features/thermal_state.feature rename to features/release/thermal_state.feature diff --git a/features/threads.feature b/features/release/threads.feature similarity index 100% rename from features/threads.feature rename to features/release/threads.feature diff --git a/features/unhandled_cpp_exception.feature b/features/release/unhandled_cpp_exception.feature similarity index 100% rename from features/unhandled_cpp_exception.feature rename to features/release/unhandled_cpp_exception.feature diff --git a/features/unhandled_mach_exception.feature b/features/release/unhandled_mach_exception.feature similarity index 100% rename from features/unhandled_mach_exception.feature rename to features/release/unhandled_mach_exception.feature diff --git a/features/release/unhandled_nsexception.feature b/features/release/unhandled_nsexception.feature new file mode 100644 index 000000000..d67158fb2 --- /dev/null +++ b/features/release/unhandled_nsexception.feature @@ -0,0 +1,39 @@ +Feature: Uncaught NSExceptions are captured by Bugsnag + + Background: + Given I clear all persistent data + + Scenario: Throw a NSException + When I run "ObjCExceptionScenario" and relaunch the crashed app + And I configure Bugsnag for "ObjCExceptionScenario" + And I wait to receive an error + Then the error is valid for the error reporting API + And the exception "message" equals "An uncaught exception! SCREAM." + And the exception "errorClass" equals "NSGenericException" + And the "method" of stack frame 0 equals the platform-dependent string: + | ios | | + | macos | __exceptionPreprocess | + And the error payload field "events.0.device.time" is a date + And the event "severity" equals "error" + And the event "unhandled" is true + And the event "severityReason.type" equals "unhandledException" + And on iOS 12 and later, the event "threads.0.name" equals "BSG MAIN THREAD" + And on macOS 10.14 and later, the event "threads.0.name" equals "BSG MAIN THREAD" + + Scenario: Throw a NSException with unhandled override + When I run "ObjCExceptionOverrideScenario" and relaunch the crashed app + And I configure Bugsnag for "ObjCExceptionOverrideScenario" + And I wait to receive an error + Then the error is valid for the error reporting API + And the exception "message" equals "An uncaught exception! SCREAM." + And the exception "errorClass" equals "NSGenericException" + And the "method" of stack frame 0 equals the platform-dependent string: + | ios | | + | macos | __exceptionPreprocess | + And the error payload field "events.0.device.time" is a date + And the event "severity" equals "error" + And the event "unhandled" is false + And the event "severityReason.unhandledOverridden" is true + And the event "severityReason.type" equals "unhandledException" + And on iOS 12 and later, the event "threads.0.name" equals "メインスレッド" + And on macOS 10.14 and later, the event "threads.0.name" equals "メインスレッド" diff --git a/features/unhandled_signal.feature b/features/release/unhandled_signal.feature similarity index 100% rename from features/unhandled_signal.feature rename to features/release/unhandled_signal.feature diff --git a/features/user.feature b/features/release/user.feature similarity index 100% rename from features/user.feature rename to features/release/user.feature diff --git a/features/user_persistence.feature b/features/release/user_persistence.feature similarity index 100% rename from features/user_persistence.feature rename to features/release/user_persistence.feature diff --git a/features/scripts/export_ios_app.sh b/features/scripts/export_ios_app.sh index 5e7d3d7c3..ffa1c02cd 100755 --- a/features/scripts/export_ios_app.sh +++ b/features/scripts/export_ios_app.sh @@ -2,33 +2,45 @@ set -o errexit -cd features/fixtures/ios - -echo "--- iOSTestApp: xcodebuild archive" - -# -# Using CLANG_ENABLE_MODULES=NO to surface build errors -# https://github.com/bugsnag/bugsnag-cocoa/pull/1284 -# - -xcrun xcodebuild \ - -scheme iOSTestApp \ - -workspace iOSTestApp.xcworkspace \ - -destination generic/platform=iOS \ - -configuration Debug \ - -archivePath archive/iosTestApp.xcarchive \ - -allowProvisioningUpdates \ - -quiet \ - archive \ - CLANG_ENABLE_MODULES=NO \ - GCC_PREPROCESSOR_DEFINITIONS='$(inherited) BSG_LOG_LEVEL=BSG_LOGLEVEL_DEBUG BSG_KSLOG_ENABLED=1' - -echo "--- iOSTestApp: xcodebuild -exportArchive" - -xcrun xcodebuild \ - -exportArchive \ - -archivePath archive/iosTestApp.xcarchive \ - -destination generic/platform=iOS \ - -exportPath output/ \ - -quiet \ - -exportOptionsPlist exportOptions.plist +# "Release" or "Debug" must be specified +if [ "$1" != "Release" ] && [ "$1" != "Debug" ]; then + echo "Usage: $0 [release|debug]" + exit 1 +fi + +BUILD_CONFIGURATION=$1 +pushd features/fixtures/ios + + echo "--- iOSTestApp: xcodebuild archive" + + # + # Using CLANG_ENABLE_MODULES=NO to surface build errors + # https://github.com/bugsnag/bugsnag-cocoa/pull/1284 + # + + xcrun xcodebuild \ + -scheme iOSTestApp \ + -workspace iOSTestApp.xcworkspace \ + -destination generic/platform=iOS \ + -configuration ${BUILD_CONFIGURATION} \ + -archivePath archive/iosTestApp.xcarchive \ + -allowProvisioningUpdates \ + -quiet \ + archive \ + CLANG_ENABLE_MODULES=NO \ + GCC_PREPROCESSOR_DEFINITIONS='$(inherited) BSG_LOG_LEVEL=BSG_LOGLEVEL_DEBUG BSG_KSLOG_ENABLED=1' + + echo "--- iOSTestApp: xcodebuild -exportArchive" + + xcrun xcodebuild \ + -exportArchive \ + -archivePath archive/iosTestApp.xcarchive \ + -destination generic/platform=iOS \ + -exportPath output/ \ + -quiet \ + -exportOptionsPlist exportOptions.plist + + pushd output + mv iOSTestApp.ipa iOSTestApp_$BUILD_CONFIGURATION.ipa + popd +popd diff --git a/features/scripts/export_mac_app.sh b/features/scripts/export_mac_app.sh index 03ffc0a6a..91a05c2fc 100755 --- a/features/scripts/export_mac_app.sh +++ b/features/scripts/export_mac_app.sh @@ -2,47 +2,55 @@ set -euo pipefail -cd features/fixtures/macos - -echo "--- macOSTestApp: pod install" - -pod install - -echo "--- macOSTestApp: xcodebuild archive" - -BUILD_ARGS=( - -workspace macOSTestApp.xcworkspace - -scheme macOSTestApp - -destination generic/platform=macOS - -configuration Debug - -archivePath archive/macOSTestApp.xcarchive - -quiet - archive - ONLY_ACTIVE_ARCH=NO -) - -if [ "${ENABLE_CODE_COVERAGE:-}" = YES ]; then - BUILD_ARGS+=( - OTHER_CFLAGS='$(inherited) -fprofile-instr-generate -fcoverage-mapping' - OTHER_LDFLAGS='$(inherited) -fprofile-instr-generate' - OTHER_SWIFT_FLAGS='$(inherited) -profile-generate -profile-coverage-mapping' - ) +# "Release" or "Debug" must be specified +if [ "$1" != "Release" ] && [ "$1" != "Debug" ]; then + echo "Usage: $0 [release|debug]" + exit 1 fi -xcodebuild "${BUILD_ARGS[@]}" +BUILD_CONFIGURATION=$1 + +pushd features/fixtures/macos -echo "--- macOSTestApp: xcodebuild -exportArchive" + echo "--- macOSTestApp: pod install" -xcrun xcodebuild \ - -exportArchive \ - -exportPath output/ \ - -exportOptionsPlist exportOptions.plist \ - -archivePath archive/macOSTestApp.xcarchive \ - -destination generic/platform=macOS \ - -quiet + pod install -cd output + echo "--- macOSTestApp: xcodebuild archive" -echo "--- macOSTestApp: zip" + BUILD_ARGS=( + -workspace macOSTestApp.xcworkspace + -scheme macOSTestApp + -destination generic/platform=macOS + -configuration ${BUILD_CONFIGURATION} + -archivePath archive/macOSTestApp.xcarchive + -quiet + archive + ONLY_ACTIVE_ARCH=NO + ) -zip -qr macOSTestApp.zip macOSTestApp.app + if [ "${ENABLE_CODE_COVERAGE:-}" = YES ]; then + BUILD_ARGS+=( + OTHER_CFLAGS='$(inherited) -fprofile-instr-generate -fcoverage-mapping' + OTHER_LDFLAGS='$(inherited) -fprofile-instr-generate' + OTHER_SWIFT_FLAGS='$(inherited) -profile-generate -profile-coverage-mapping' + ) + fi + + xcodebuild "${BUILD_ARGS[@]}" + + echo "--- macOSTestApp: xcodebuild -exportArchive" + + xcrun xcodebuild \ + -exportArchive \ + -exportPath output/ \ + -exportOptionsPlist exportOptions.plist \ + -archivePath archive/macOSTestApp.xcarchive \ + -destination generic/platform=macOS \ + -quiet + + pushd output + echo "--- macOSTestApp: zip" + zip -qr macOSTestApp_$BUILD_CONFIGURATION.zip macOSTestApp.app + popd +popd diff --git a/features/steps/app_steps.rb b/features/steps/app_steps.rb index 9c7a6d26c..1f55c8db9 100644 --- a/features/steps/app_steps.rb +++ b/features/steps/app_steps.rb @@ -162,7 +162,7 @@ def run_macos_app end dir = 'features/fixtures/macos/output' exe = "#{dir}/macOSTestApp.app/Contents/MacOS/macOSTestApp" - system("unzip -qd #{dir} #{dir}/macOSTestApp.zip", exception: true) unless File.exist? exe + system("unzip -qd #{dir} #{dir}/macOSTestApp*.zip", exception: true) unless File.exist? exe $fixture_pid = Process.spawn($app_env, exe, %i[err out] => '/dev/null') end diff --git a/scripts/build-xcframework.sh b/scripts/build-xcframework.sh index 06e233567..c5955b91b 100755 --- a/scripts/build-xcframework.sh +++ b/scripts/build-xcframework.sh @@ -15,16 +15,17 @@ set -e -u -o pipefail # Configuration # ------------------------------------------------------------------- -# Base name of the .xcodeproj directory -PROJECT_NAME=Bugsnag - -# Targets that are suffixed with the platform (e.g. XYZ-iOS, XYZ-macOS etc) -NAMESPACED_TARGETS=( "Bugsnag" ) - -# Targets that are not namespaced -GENERIC_TARGETS=( ) - -# Platforms we are building for: iOS, macOS, tvOS, watchOS (in future: visionOS) +# Framework: The base name we want to give our xcframework. +# Project / Workspace Path: Local path to the .xcodeproj or .xcworkspace we want to load from +# Scheme: The base name of the scheme to build with (minus any "-iOS" type suffix) +# Namespaced: If TRUE, the schemes to load all have an ("-iOS", "-macOS") style namespaced suffix. +TARGETS=( +# [Framework] [Project/WS Path] [Scheme] [NAMESPACED] + "Bugsnag Bugsnag.xcworkspace Bugsnag TRUE" + "BugsnagNetworkRequestPlugin Bugsnag.xcworkspace BugsnagNetworkRequestPlugin TRUE" +) + +# Platforms we are building for PLATFORMS=( "iOS" "macOS" "tvOS" "watchOS" ) @@ -39,83 +40,109 @@ XCFW_DIR="${PROJECT_DIR}/build/xcframeworks" INTERMEDIATES_DIR="${XCFW_DIR}/intermediates" PRODUCTS_DIR="${XCFW_DIR}/products" -rm -rf "${XCFW_DIR}" -mkdir -p "${INTERMEDIATES_DIR}" -mkdir -p "${PRODUCTS_DIR}" - ## -# Build a target. This function tries to sort out whether the target is namespaced or not -# (i.e. if it's named XYZ or XYZ-iOS) so that it produces a consistently named output file -# (such as XYZ-iOS.framework, XYZ-iOS-simulator.framework). +# Build a framework. # # Args: -# 1: Name of compilation target -# 2: Name of platform to build for (iOS, macOS, etc) +# 1: The base name of the framework to produce +# 2: Path to the project or workspace file (relative to the project root) +# 3: The scheme to build +# 4: The platform to build for (iOS, macOS, etc) # # Return: A set of commandline argumets for the final framework build. ## -build_target() { - target=$1 - platform=$2 - - framework_name=${target} - if [[ ${framework_name} == *${platform} ]]; then - # If our target is named "XYZ-iOS", remove the "-iOS" part from the framework name - framework_name="${framework_name%-${platform}}" +build_framework() { + local framework_basename=$1 + local proj_ws_path=$2 + local scheme=$3 + local platform=$4 + + local destination="generic/platform=${platform}" + local archive_path="${INTERMEDIATES_DIR}/${framework_basename}-${platform}" + local proj_ws_arg="-project ${PROJECT_DIR}/${proj_ws_path}" + if [[ $proj_ws_path == *xcworkspace ]]; then + proj_ws_arg="-workspace ${PROJECT_DIR}/${proj_ws_path}" fi - destination="generic/platform=${platform}" - archive_path="${INTERMEDIATES_DIR}/${target}" - if [[ ${archive_path} != *${platform} ]]; then - # Make sure our archive path is namespaced with the platform - archive_path="${archive_path}-${platform}" - fi # Note: Redirecting xcodebuild's stdout to stderr because we need stdout for ourselves. - xcodebuild archive -project ${PROJECT_DIR}/${PROJECT_NAME}.xcodeproj \ - -scheme ${target} \ + xcodebuild archive $proj_ws_arg \ + -scheme ${scheme} \ -configuration Release \ SKIP_INSTALL=NO \ BUILD_LIBRARY_FOR_DISTRIBUTION=YES \ -destination "${destination}" \ -archivePath "${archive_path}" 1>&2 - echo "-archive ${archive_path}.xcarchive -framework ${framework_name}.framework" + echo "-archive ${archive_path}.xcarchive -framework ${framework_basename}.framework" if [ "${platform}" != "macOS" ]; then # For non-macos targrets, build for the simulator as well. destination="${destination} Simulator" archive_path="${archive_path}-simulator" - xcodebuild archive -project ${PROJECT_DIR}/${PROJECT_NAME}.xcodeproj \ - -scheme ${target} \ + xcodebuild archive $proj_ws_arg \ + -scheme ${scheme} \ -configuration Release \ SKIP_INSTALL=NO \ BUILD_LIBRARY_FOR_DISTRIBUTION=YES \ -destination "${destination}" \ -archivePath "${archive_path}" 1>&2 - echo "-archive ${archive_path}.xcarchive -framework ${framework_name}.framework" + echo "-archive ${archive_path}.xcarchive -framework ${framework_basename}.framework" fi } -if [[ ${#NAMESPACED_TARGETS[@]} -gt 0 ]]; then - for target in "${NAMESPACED_TARGETS[@]}"; do - xcframework_args="" - for platform in "${PLATFORMS[@]}"; do - new_args=$( build_target ${target}-${platform} ${platform} ) - xcframework_args="${xcframework_args} ${new_args}" - done - xcodebuild -create-xcframework ${xcframework_args} -output "${PRODUCTS_DIR}/${target}.xcframework" +fixup_xcframework() { + # Swift compiler bug: Having a class with the same name as the module breaks things. + # + # The dependent module including such a module will generate class definitions like this: + # "MyClass : MyModuleName.MyInterface {" + # When it should generate: + # "MyClass : MyInterface {" + # + # So we search for this prefix and strip it out. + # + # https://developer.apple.com/forums/thread/123253 + + local framework_basename="$1" + local framework_path="${PRODUCTS_DIR}/${framework_basename}.xcframework" + + for target_record in "${TARGETS[@]}"; do + local target_args=($target_record) + local target_framework=${target_args[0]} + + find "$framework_path" -name "*.swiftinterface" -exec sed -i -e "s/$target_framework\\.//g" {} \; done -fi +} + +build_frameworks() { + for target_record in "${TARGETS[@]}"; do + local target_args=($target_record) + local framework=${target_args[0]} + local project=${target_args[1]} + local scheme=${target_args[2]} + local namespaced=${target_args[3]} -if [[ ${#GENERIC_TARGETS[@]} -gt 0 ]]; then - for target in "${GENERIC_TARGETS[@]}"; do - xcframework_args="" + echo "Building ${framework}.xcframework" + local xcframework_args="" for platform in "${PLATFORMS[@]}"; do - new_args=$( build_target ${target} ${platform} ) - xcframework_args="${xcframework_args} ${new_args}" + local current_scheme="$scheme" + if [ "$namespaced" = "TRUE" ]; then + current_scheme="${current_scheme}-${platform}" + fi + local added_args=$( build_framework ${framework} ${project} ${current_scheme} ${platform} ) + xcframework_args="${xcframework_args} ${added_args}" done - xcodebuild -create-xcframework ${xcframework_args} -output "${PRODUCTS_DIR}/${target}.xcframework" + xcodebuild -create-xcframework ${xcframework_args} -output "${PRODUCTS_DIR}/${framework}.xcframework" + fixup_xcframework $framework + pushd "${PRODUCTS_DIR}" + zip --symlinks -rq "${framework}.xcframework.zip" "${framework}.xcframework" + popd done -fi +} + +rm -rf "${XCFW_DIR}" +mkdir -p "${INTERMEDIATES_DIR}" +mkdir -p "${PRODUCTS_DIR}" + +build_frameworks echo echo "** build-frameworks.sh: script completed successfully **"