From be0e06bc9822f58d782a7e420e1750e843643abf Mon Sep 17 00:00:00 2001 From: Steve Kirkland-Walton Date: Mon, 21 Aug 2023 16:42:12 +0100 Subject: [PATCH 1/5] Update to Maze Runner v8 --- docker-compose.yml | 4 +- dockerfiles/Dockerfile.node | 2 +- dockerfiles/Dockerfile.react-native-cli-tool | 2 +- test/node/Gemfile | 2 +- test/node/Gemfile.lock | 107 +++++++++++------- .../node/features/fixtures/docker-compose.yml | 2 + test/node/features/proxy.feature | 2 +- test/node/features/unhandled_errors.feature | 4 +- test/react-native-cli/Gemfile | 2 +- test/react-native-cli/Gemfile.lock | 83 ++++++++------ test/react-native/Gemfile | 2 +- test/react-native/Gemfile.lock | 83 ++++++++------ test/react-native/features/app.feature | 2 +- test/react-native/features/session.feature | 2 +- 14 files changed, 175 insertions(+), 124 deletions(-) diff --git a/docker-compose.yml b/docker-compose.yml index 434bf37a09..a002466c7d 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -188,7 +188,7 @@ services: - ./test/react-native-cli/features/:/app/features react-native-maze-runner: - image: 855461928731.dkr.ecr.us-west-1.amazonaws.com/maze-runner-releases:latest-v7-cli + image: 855461928731.dkr.ecr.us-west-1.amazonaws.com/maze-runner-releases:latest-v8-cli environment: <<: *common-environment BITBAR_USERNAME: @@ -207,7 +207,7 @@ services: - /var/run/docker.sock:/var/run/docker.sock react-native-cli-maze-runner: - image: 855461928731.dkr.ecr.us-west-1.amazonaws.com/maze-runner-releases:latest-v7-cli + image: 855461928731.dkr.ecr.us-west-1.amazonaws.com/maze-runner-releases:latest-v8-cli environment: <<: *common-environment BITBAR_USERNAME: diff --git a/dockerfiles/Dockerfile.node b/dockerfiles/Dockerfile.node index b29044d015..eb25763019 100644 --- a/dockerfiles/Dockerfile.node +++ b/dockerfiles/Dockerfile.node @@ -21,7 +21,7 @@ RUN npm pack --verbose packages/plugin-koa/ RUN npm pack --verbose packages/plugin-restify/ # The maze-runner node tests -FROM 855461928731.dkr.ecr.us-west-1.amazonaws.com/maze-runner-releases:latest-v7-cli as node-maze-runner +FROM 855461928731.dkr.ecr.us-west-1.amazonaws.com/maze-runner-releases:latest-v8-cli as node-maze-runner WORKDIR /app/ COPY packages/node/ . COPY test/node/features test/node/features diff --git a/dockerfiles/Dockerfile.react-native-cli-tool b/dockerfiles/Dockerfile.react-native-cli-tool index 07bdc15912..b7e392f23f 100644 --- a/dockerfiles/Dockerfile.react-native-cli-tool +++ b/dockerfiles/Dockerfile.react-native-cli-tool @@ -16,7 +16,7 @@ RUN npx lerna run build --scope @bugsnag/react-native-cli RUN npm pack --verbose packages/react-native-cli/ # The maze-runner test image -FROM 855461928731.dkr.ecr.us-west-1.amazonaws.com/maze-runner-releases:latest-v7-cli as react-native-cli-maze-runner +FROM 855461928731.dkr.ecr.us-west-1.amazonaws.com/maze-runner-releases:latest-v8-cli as react-native-cli-maze-runner WORKDIR /app diff --git a/test/node/Gemfile b/test/node/Gemfile index bd133a4451..29d3f3cccb 100644 --- a/test/node/Gemfile +++ b/test/node/Gemfile @@ -1,6 +1,6 @@ source 'https://rubygems.org' -gem 'bugsnag-maze-runner', git: 'https://github.com/bugsnag/maze-runner', tag: 'v7.6.0' +gem 'bugsnag-maze-runner', '~>8.0' # Use a branch of Maze Runner #gem 'bugsnag-maze-runner', git: 'https://github.com/bugsnag/maze-runner', branch: 'tms/use-maze-check' diff --git a/test/node/Gemfile.lock b/test/node/Gemfile.lock index b9ab0e431d..12713cd4f6 100644 --- a/test/node/Gemfile.lock +++ b/test/node/Gemfile.lock @@ -1,37 +1,35 @@ -GIT - remote: https://github.com/bugsnag/maze-runner - revision: fe12189f83aad154f54221ee0fcd41b483d3c0d1 - tag: v6.8.0 +GEM + remote: https://rubygems.org/ specs: - bugsnag-maze-runner (6.8.0) - appium_lib (~> 11.2.0) + appium_lib (12.0.1) + appium_lib_core (~> 5.0) + nokogiri (~> 1.8, >= 1.8.1) + tomlrb (>= 1.1, < 3.0) + appium_lib_core (5.4.0) + faye-websocket (~> 0.11.0) + selenium-webdriver (~> 4.2, < 4.6) + bugsnag (6.26.0) + concurrent-ruby (~> 1.0) + bugsnag-maze-runner (8.4.0) + appium_lib (~> 12.0.0) + appium_lib_core (~> 5.4.0) bugsnag (~> 6.24) cucumber (~> 7.1) cucumber-expressions (~> 6.0.0) curb (~> 0.9.6) + dogstatsd-ruby (~> 5.5.0) + json_schemer (~> 0.2.24) optimist (~> 3.0.1) os (~> 1.0.0) + rack (~> 2.2) rake (~> 12.3.3) rubyzip (~> 2.3.2) - selenium-webdriver (~> 3.11) + selenium-webdriver (~> 4.0) test-unit (~> 3.5.2) webrick (~> 1.7.0) - -GEM - remote: https://rubygems.org/ - specs: - appium_lib (11.2.0) - appium_lib_core (~> 4.1) - nokogiri (~> 1.8, >= 1.8.1) - tomlrb (~> 1.1) - appium_lib_core (4.7.1) - faye-websocket (~> 0.11.0) - selenium-webdriver (~> 3.14, >= 3.14.1) - bugsnag (6.24.1) - concurrent-ruby (~> 1.0) builder (3.2.4) - childprocess (3.0.0) - concurrent-ruby (1.1.9) + childprocess (4.1.0) + concurrent-ruby (1.2.2) cucumber (7.1.0) builder (~> 3.2, >= 3.2.4) cucumber-core (~> 10.1, >= 10.1.0) @@ -45,10 +43,10 @@ GEM mime-types (~> 3.3, >= 3.3.1) multi_test (~> 0.1, >= 0.1.2) sys-uname (~> 1.2, >= 1.2.2) - cucumber-core (10.1.0) + cucumber-core (10.1.1) cucumber-gherkin (~> 22.0, >= 22.0.0) cucumber-messages (~> 17.1, >= 17.1.1) - cucumber-tag-expressions (~> 4.0, >= 4.0.2) + cucumber-tag-expressions (~> 4.1, >= 4.1.0) cucumber-create-meta (6.0.4) cucumber-messages (~> 17.1, >= 17.1.1) sys-uname (~> 1.2, >= 1.2.2) @@ -60,41 +58,62 @@ GEM cucumber-messages (~> 17.1, >= 17.1.0) cucumber-messages (17.1.1) cucumber-tag-expressions (4.1.0) - cucumber-wire (6.2.0) + cucumber-wire (6.2.1) cucumber-core (~> 10.1, >= 10.1.0) cucumber-cucumber-expressions (~> 14.0, >= 14.0.0) - cucumber-messages (~> 17.1, >= 17.1.1) curb (0.9.11) - diff-lcs (1.4.4) + diff-lcs (1.5.0) + dogstatsd-ruby (5.5.0) + ecma-re-validator (0.4.0) + regexp_parser (~> 2.2) eventmachine (1.2.7) - faye-websocket (0.11.1) + faye-websocket (0.11.3) eventmachine (>= 0.12.0) websocket-driver (>= 0.5.1) - ffi (1.15.4) - mime-types (3.4.1) + ffi (1.15.5) + hana (1.3.7) + json_schemer (0.2.25) + ecma-re-validator (~> 0.3) + hana (~> 1.3) + regexp_parser (~> 2.0) + simpleidn (~> 0.2) + uri_template (~> 0.7) + mime-types (3.5.0) mime-types-data (~> 3.2015) - mime-types-data (3.2021.1115) - mini_portile2 (2.6.1) + mime-types-data (3.2023.0808) + mini_portile2 (2.8.4) multi_test (0.1.2) - nokogiri (1.12.5) - mini_portile2 (~> 2.6.1) + nokogiri (1.15.4) + mini_portile2 (~> 2.8.2) racc (~> 1.4) optimist (3.0.1) os (1.0.1) - power_assert (2.0.1) - racc (1.6.0) + power_assert (2.0.3) + racc (1.7.1) + rack (2.2.8) rake (12.3.3) + regexp_parser (2.8.1) + rexml (3.2.6) rubyzip (2.3.2) - selenium-webdriver (3.142.7) - childprocess (>= 0.5, < 4.0) - rubyzip (>= 1.2.2) - sys-uname (1.2.2) + selenium-webdriver (4.5.0) + childprocess (>= 0.5, < 5.0) + rexml (~> 3.2, >= 3.2.5) + rubyzip (>= 1.2.2, < 3.0) + websocket (~> 1.0) + simpleidn (0.2.1) + unf (~> 0.1.4) + sys-uname (1.2.3) ffi (~> 1.1) - test-unit (3.5.3) + test-unit (3.5.9) power_assert - tomlrb (1.3.0) + tomlrb (2.0.3) + unf (0.1.4) + unf_ext + unf_ext (0.0.8.2) + uri_template (0.7.0) webrick (1.7.0) - websocket-driver (0.7.5) + websocket (1.2.9) + websocket-driver (0.7.6) websocket-extensions (>= 0.1.0) websocket-extensions (0.1.5) @@ -102,7 +121,7 @@ PLATFORMS ruby DEPENDENCIES - bugsnag-maze-runner! + bugsnag-maze-runner (~> 8.0) BUNDLED WITH 2.2.20 diff --git a/test/node/features/fixtures/docker-compose.yml b/test/node/features/fixtures/docker-compose.yml index 7cf0ceb10e..444c186ad0 100644 --- a/test/node/features/fixtures/docker-compose.yml +++ b/test/node/features/fixtures/docker-compose.yml @@ -275,4 +275,6 @@ services: networks: default: + external: true name: ${NETWORK_NAME:-js-maze-runner} + diff --git a/test/node/features/proxy.feature b/test/node/features/proxy.feature index 1826cc5a86..8358877ce2 100644 --- a/test/node/features/proxy.feature +++ b/test/node/features/proxy.feature @@ -18,4 +18,4 @@ Scenario: using options to configure a proxy Scenario: making sure no request get through a bad proxy And I run the service "proxy" with the command "node scenarios/misconfigured-proxy" And I wait for 1 second - Then I should receive no requests + Then I should receive no errors diff --git a/test/node/features/unhandled_errors.feature b/test/node/features/unhandled_errors.feature index 22aa6b1ea6..8e698a6b8d 100644 --- a/test/node/features/unhandled_errors.feature +++ b/test/node/features/unhandled_errors.feature @@ -22,7 +22,7 @@ Scenario: reporting thrown exception which is not caught Scenario: not reporting uncaughtExceptions when autoDetectErrors is off And I run the service "unhandled" with the command "node scenarios/thrown-error-not-caught-auto-notify-off" And I wait for 1 second - Then I should receive no requests + Then I should receive no errors Scenario: reporting unhandled promise rejections And I run the service "unhandled" with the command "node scenarios/unhandled-promise-rejection" @@ -53,7 +53,7 @@ Scenario: reporting unhandled promise rejections Scenario: not reporting unhandledRejections when autoDetectErrors is off And I run the service "unhandled" with the command "node scenarios/unhandled-promise-rejection-auto-notify-off" And I wait for 1 second - Then I should receive no requests + Then I should receive no errors Scenario: using contextualize to add context to an error And I run the service "unhandled" with the command "node scenarios/contextualize" diff --git a/test/react-native-cli/Gemfile b/test/react-native-cli/Gemfile index bcc82390d2..c703a18be5 100644 --- a/test/react-native-cli/Gemfile +++ b/test/react-native-cli/Gemfile @@ -2,7 +2,7 @@ source 'https://rubygems.org' gem 'cocoapods' -gem 'bugsnag-maze-runner', git: 'https://github.com/bugsnag/maze-runner', tag: 'v7.4.0' +gem 'bugsnag-maze-runner', '~>8.4.0' # Use a branch of Maze Runner #gem 'bugsnag-maze-runner', git: 'https://github.com/bugsnag/maze-runner', branch: 'tms/use-maze-check' diff --git a/test/react-native-cli/Gemfile.lock b/test/react-native-cli/Gemfile.lock index 8b0833ee30..f203f7f864 100644 --- a/test/react-native-cli/Gemfile.lock +++ b/test/react-native-cli/Gemfile.lock @@ -1,23 +1,3 @@ -GIT - remote: https://github.com/bugsnag/maze-runner - revision: fc5e8c39582b067743ffb18c946f2c9e8fd27311 - tag: v7.4.0 - specs: - bugsnag-maze-runner (7.4.0) - appium_lib (~> 12.0) - appium_lib_core (~> 5.4.0) - bugsnag (~> 6.24) - cucumber (~> 7.1) - cucumber-expressions (~> 6.0.0) - curb (~> 0.9.6) - optimist (~> 3.0.1) - os (~> 1.0.0) - rake (~> 12.3.3) - rubyzip (~> 2.3.2) - selenium-webdriver (~> 4.0) - test-unit (~> 3.5.2) - webrick (~> 1.7.0) - GEM remote: https://rubygems.org/ specs: @@ -42,8 +22,25 @@ GEM faye-websocket (~> 0.11.0) selenium-webdriver (~> 4.2, < 4.6) atomos (0.1.3) - bugsnag (6.24.2) + bugsnag (6.26.0) concurrent-ruby (~> 1.0) + bugsnag-maze-runner (8.4.0) + appium_lib (~> 12.0.0) + appium_lib_core (~> 5.4.0) + bugsnag (~> 6.24) + cucumber (~> 7.1) + cucumber-expressions (~> 6.0.0) + curb (~> 0.9.6) + dogstatsd-ruby (~> 5.5.0) + json_schemer (~> 0.2.24) + optimist (~> 3.0.1) + os (~> 1.0.0) + rack (~> 2.2) + rake (~> 12.3.3) + rubyzip (~> 2.3.2) + selenium-webdriver (~> 4.0) + test-unit (~> 3.5.2) + webrick (~> 1.7.0) builder (3.2.4) childprocess (4.1.0) claide (1.1.0) @@ -119,40 +116,52 @@ GEM cucumber-cucumber-expressions (~> 14.0, >= 14.0.0) curb (0.9.11) diff-lcs (1.5.0) + dogstatsd-ruby (5.5.0) + ecma-re-validator (0.4.0) + regexp_parser (~> 2.2) escape (0.0.4) ethon (0.15.0) ffi (>= 1.15.0) eventmachine (1.2.7) - faye-websocket (0.11.1) + faye-websocket (0.11.3) eventmachine (>= 0.12.0) websocket-driver (>= 0.5.1) ffi (1.15.5) fourflusher (2.3.1) fuzzy_match (2.0.4) gh_inspector (1.1.3) + hana (1.3.7) httpclient (2.8.3) i18n (1.10.0) concurrent-ruby (~> 1.0) json (2.6.1) - mime-types (3.4.1) + json_schemer (0.2.25) + ecma-re-validator (~> 0.3) + hana (~> 1.3) + regexp_parser (~> 2.0) + simpleidn (~> 0.2) + uri_template (~> 0.7) + mime-types (3.5.0) mime-types-data (~> 3.2015) - mime-types-data (3.2022.0105) - mini_portile2 (2.8.0) + mime-types-data (3.2023.0808) + mini_portile2 (2.8.4) minitest (5.15.0) molinillo (0.8.0) multi_test (0.1.2) nanaimo (0.3.0) nap (1.1.0) netrc (0.11.0) - nokogiri (1.13.9) - mini_portile2 (~> 2.8.0) + nokogiri (1.15.4) + mini_portile2 (~> 2.8.2) racc (~> 1.4) optimist (3.0.1) os (1.0.1) - power_assert (2.0.2) + power_assert (2.0.3) public_suffix (4.0.6) - racc (1.6.0) + racc (1.7.1) + rack (2.2.8) rake (12.3.3) + regexp_parser (2.8.1) rexml (3.2.5) ruby-macho (2.5.1) rubyzip (2.3.2) @@ -161,18 +170,24 @@ GEM rexml (~> 3.2, >= 3.2.5) rubyzip (>= 1.2.2, < 3.0) websocket (~> 1.0) - sys-uname (1.2.2) + simpleidn (0.2.1) + unf (~> 0.1.4) + sys-uname (1.2.3) ffi (~> 1.1) - test-unit (3.5.5) + test-unit (3.5.9) power_assert tomlrb (2.0.3) typhoeus (1.4.0) ethon (>= 0.9.0) tzinfo (2.0.4) concurrent-ruby (~> 1.0) + unf (0.1.4) + unf_ext + unf_ext (0.0.8.2) + uri_template (0.7.0) webrick (1.7.0) websocket (1.2.9) - websocket-driver (0.7.5) + websocket-driver (0.7.6) websocket-extensions (>= 0.1.0) websocket-extensions (0.1.5) xcodeproj (1.21.0) @@ -188,8 +203,8 @@ PLATFORMS ruby DEPENDENCIES - bugsnag-maze-runner! + bugsnag-maze-runner (~> 8.4.0) cocoapods BUNDLED WITH - 2.3.0 + 2.4.8 diff --git a/test/react-native/Gemfile b/test/react-native/Gemfile index 4eb2c78891..9ae53510db 100644 --- a/test/react-native/Gemfile +++ b/test/react-native/Gemfile @@ -2,7 +2,7 @@ source 'https://rubygems.org' gem 'cocoapods' -gem 'bugsnag-maze-runner', git: 'https://github.com/bugsnag/maze-runner', tag: 'v7.7.0' +gem 'bugsnag-maze-runner', '~>8.4.0' # Use a branch of Maze Runner #gem 'bugsnag-maze-runner', git: 'https://github.com/bugsnag/maze-runner', branch: 'tms/use-maze-check' diff --git a/test/react-native/Gemfile.lock b/test/react-native/Gemfile.lock index 4a81844517..f203f7f864 100644 --- a/test/react-native/Gemfile.lock +++ b/test/react-native/Gemfile.lock @@ -1,23 +1,3 @@ -GIT - remote: https://github.com/bugsnag/maze-runner - revision: 07e5d231773bc740b1d8de4d5c311b5c73f86e12 - tag: v7.7.0 - specs: - bugsnag-maze-runner (7.7.0) - appium_lib (~> 12.0) - appium_lib_core (~> 5.4.0) - bugsnag (~> 6.24) - cucumber (~> 7.1) - cucumber-expressions (~> 6.0.0) - curb (~> 0.9.6) - optimist (~> 3.0.1) - os (~> 1.0.0) - rake (~> 12.3.3) - rubyzip (~> 2.3.2) - selenium-webdriver (~> 4.0) - test-unit (~> 3.5.2) - webrick (~> 1.7.0) - GEM remote: https://rubygems.org/ specs: @@ -42,8 +22,25 @@ GEM faye-websocket (~> 0.11.0) selenium-webdriver (~> 4.2, < 4.6) atomos (0.1.3) - bugsnag (6.25.0) + bugsnag (6.26.0) concurrent-ruby (~> 1.0) + bugsnag-maze-runner (8.4.0) + appium_lib (~> 12.0.0) + appium_lib_core (~> 5.4.0) + bugsnag (~> 6.24) + cucumber (~> 7.1) + cucumber-expressions (~> 6.0.0) + curb (~> 0.9.6) + dogstatsd-ruby (~> 5.5.0) + json_schemer (~> 0.2.24) + optimist (~> 3.0.1) + os (~> 1.0.0) + rack (~> 2.2) + rake (~> 12.3.3) + rubyzip (~> 2.3.2) + selenium-webdriver (~> 4.0) + test-unit (~> 3.5.2) + webrick (~> 1.7.0) builder (3.2.4) childprocess (4.1.0) claide (1.1.0) @@ -119,40 +116,52 @@ GEM cucumber-cucumber-expressions (~> 14.0, >= 14.0.0) curb (0.9.11) diff-lcs (1.5.0) + dogstatsd-ruby (5.5.0) + ecma-re-validator (0.4.0) + regexp_parser (~> 2.2) escape (0.0.4) ethon (0.15.0) ffi (>= 1.15.0) eventmachine (1.2.7) - faye-websocket (0.11.1) + faye-websocket (0.11.3) eventmachine (>= 0.12.0) websocket-driver (>= 0.5.1) ffi (1.15.5) fourflusher (2.3.1) fuzzy_match (2.0.4) gh_inspector (1.1.3) + hana (1.3.7) httpclient (2.8.3) i18n (1.10.0) concurrent-ruby (~> 1.0) json (2.6.1) - mime-types (3.4.1) + json_schemer (0.2.25) + ecma-re-validator (~> 0.3) + hana (~> 1.3) + regexp_parser (~> 2.0) + simpleidn (~> 0.2) + uri_template (~> 0.7) + mime-types (3.5.0) mime-types-data (~> 3.2015) - mime-types-data (3.2022.0105) - mini_portile2 (2.8.0) + mime-types-data (3.2023.0808) + mini_portile2 (2.8.4) minitest (5.15.0) molinillo (0.8.0) multi_test (0.1.2) nanaimo (0.3.0) nap (1.1.0) netrc (0.11.0) - nokogiri (1.13.9) - mini_portile2 (~> 2.8.0) + nokogiri (1.15.4) + mini_portile2 (~> 2.8.2) racc (~> 1.4) optimist (3.0.1) os (1.0.1) - power_assert (2.0.2) + power_assert (2.0.3) public_suffix (4.0.6) - racc (1.6.1) + racc (1.7.1) + rack (2.2.8) rake (12.3.3) + regexp_parser (2.8.1) rexml (3.2.5) ruby-macho (2.5.1) rubyzip (2.3.2) @@ -161,18 +170,24 @@ GEM rexml (~> 3.2, >= 3.2.5) rubyzip (>= 1.2.2, < 3.0) websocket (~> 1.0) - sys-uname (1.2.2) + simpleidn (0.2.1) + unf (~> 0.1.4) + sys-uname (1.2.3) ffi (~> 1.1) - test-unit (3.5.5) + test-unit (3.5.9) power_assert tomlrb (2.0.3) typhoeus (1.4.0) ethon (>= 0.9.0) tzinfo (2.0.4) concurrent-ruby (~> 1.0) + unf (0.1.4) + unf_ext + unf_ext (0.0.8.2) + uri_template (0.7.0) webrick (1.7.0) websocket (1.2.9) - websocket-driver (0.7.5) + websocket-driver (0.7.6) websocket-extensions (>= 0.1.0) websocket-extensions (0.1.5) xcodeproj (1.21.0) @@ -188,8 +203,8 @@ PLATFORMS ruby DEPENDENCIES - bugsnag-maze-runner! + bugsnag-maze-runner (~> 8.4.0) cocoapods BUNDLED WITH - 2.3.0 + 2.4.8 diff --git a/test/react-native/features/app.feature b/test/react-native/features/app.feature index d01beb4f2c..291dc054af 100644 --- a/test/react-native/features/app.feature +++ b/test/react-native/features/app.feature @@ -125,4 +125,4 @@ Scenario: Setting releaseStage and enabledReleaseStages to enable delivery Scenario: Setting releaseStage and enabledReleaseStages to disable delivery When I run "AppConfigEnabledReleaseStagesNoSendScenario" And I wait for 5 seconds - Then I should receive no requests + Then I should receive no errors diff --git a/test/react-native/features/session.feature b/test/react-native/features/session.feature index ac8f924e78..addbaa0f4c 100644 --- a/test/react-native/features/session.feature +++ b/test/react-native/features/session.feature @@ -21,7 +21,7 @@ Scenario: Automatic session on app start Scenario: Automatic sessions disabled When I run "SessionAutoDisabledScenario" And I wait for 5 seconds - Then I should receive no requests + Then I should receive no sessions Scenario: Manual JS sessions (JS Controls) When I run "SessionJsControlledManualJsScenario" From d92f95d9f9ea325c8f58c42e856caf848d29b90c Mon Sep 17 00:00:00 2001 From: Steve Kirkland-Walton Date: Thu, 24 Aug 2023 12:13:05 +0100 Subject: [PATCH 2/5] Return RN CLI tests to v7 for now --- dockerfiles/Dockerfile.react-native-cli-tool | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dockerfiles/Dockerfile.react-native-cli-tool b/dockerfiles/Dockerfile.react-native-cli-tool index b7e392f23f..07bdc15912 100644 --- a/dockerfiles/Dockerfile.react-native-cli-tool +++ b/dockerfiles/Dockerfile.react-native-cli-tool @@ -16,7 +16,7 @@ RUN npx lerna run build --scope @bugsnag/react-native-cli RUN npm pack --verbose packages/react-native-cli/ # The maze-runner test image -FROM 855461928731.dkr.ecr.us-west-1.amazonaws.com/maze-runner-releases:latest-v8-cli as react-native-cli-maze-runner +FROM 855461928731.dkr.ecr.us-west-1.amazonaws.com/maze-runner-releases:latest-v7-cli as react-native-cli-maze-runner WORKDIR /app From a3cc40dd50fb8fd0676ad78e2cf0cefdf49a1f6c Mon Sep 17 00:00:00 2001 From: Josh <46817760+joshedney@users.noreply.github.com> Date: Fri, 8 Sep 2023 12:34:39 +0100 Subject: [PATCH 3/5] [PLAT-10144] Update React Native CLI to install BugSnag CLI (#1990) Install the bugsnag-cli as part of the react native cli to upload react native android symbol files --- .../react-native-android-pipeline.full.yml | 92 +- .../full/react-native-cli-pipeline.full.yml | 75 +- packages/react-native-cli/package-lock.json | 1860 +++++++++-------- packages/react-native-cli/package.json | 4 + .../commands/AutomateSymbolicationCommand.ts | 130 +- packages/react-native-cli/src/lib/Gradle.ts | 113 +- packages/react-native-cli/src/lib/Npm.ts | 22 + .../src/lib/__test__/Gradle.test.ts | 134 +- ...er-with-mappings-and-both-endpoints.gradle | 1 - ...er-with-mappings-and-bugsnag-config.gradle | 4 +- ...h-mappings-and-empty-bugsnag-config.gradle | 2 - ...r-with-mappings-and-upload-endpoint.gradle | 1 - ...s-both-endpoints-and-bugsnag-config.gradle | 2 - ...s-build-endpoint-and-bugsnag-config.gradle | 2 +- ...d-endpoint-and-empty-bugsnag-config.gradle | 2 - ...-upload-endpoint-and-bugsnag-config.gradle | 4 +- ...d-endpoint-and-empty-bugsnag-config.gradle | 2 - .../app-build-after-with-mappings.gradle | 1 - .../app-build-after-with-no-mappings.gradle | 219 ++ ...pp-build-before-with-bugsnag-config.gradle | 4 + .../app-build-before-with-mappings.gradle | 1 - scripts/react-native-cli-helper.js | 4 + test/react-native-cli/Gemfile | 2 +- test/react-native-cli/Gemfile.lock | 8 +- .../build-app-tests/build-android-app.feature | 13 +- .../cli-tests/automate-symbolication.feature | 50 +- .../features/fixtures/rn-cli-init-android.sh | 28 +- .../features/fixtures/rn-cli-init-ios.sh | 2 +- .../steps/react-native-source-maps-steps.rb | 8 + test/react-native-cli/features/steps/steps.rb | 48 + 30 files changed, 1639 insertions(+), 1199 deletions(-) create mode 100644 packages/react-native-cli/src/lib/__test__/fixtures/app-build-after-with-no-mappings.gradle create mode 100644 test/react-native-cli/features/steps/react-native-source-maps-steps.rb diff --git a/.buildkite/full/react-native-android-pipeline.full.yml b/.buildkite/full/react-native-android-pipeline.full.yml index 85e6661125..a11460605e 100644 --- a/.buildkite/full/react-native-android-pipeline.full.yml +++ b/.buildkite/full/react-native-android-pipeline.full.yml @@ -187,13 +187,13 @@ steps: run: react-native-maze-runner service-ports: true command: - - --app=build/rn0.60.apk - - --farm=bb - - --device=ANDROID_10|ANDROID_11|ANDROID_12 - - --a11y-locator - - --fail-fast - - --no-tunnel - - --aws-public-ip + - --app=build/rn0.60.apk + - --farm=bb + - --device=ANDROID_10|ANDROID_11|ANDROID_12 + - --a11y-locator + - --fail-fast + - --no-tunnel + - --aws-public-ip env: SKIP_NAVIGATION_SCENARIOS: "true" concurrency: 25 @@ -212,13 +212,13 @@ steps: run: react-native-maze-runner service-ports: true command: - - --app=build/rn0.66.apk - - --farm=bb - - --device=ANDROID_10|ANDROID_11|ANDROID_12 - - --a11y-locator - - --fail-fast - - --no-tunnel - - --aws-public-ip + - --app=build/rn0.66.apk + - --farm=bb + - --device=ANDROID_10|ANDROID_11|ANDROID_12 + - --a11y-locator + - --fail-fast + - --no-tunnel + - --aws-public-ip env: SKIP_NAVIGATION_SCENARIOS: "true" concurrency: 25 @@ -367,14 +367,14 @@ steps: run: react-native-maze-runner service-ports: true command: - - --app=build/r_navigation_0.60.apk - - --farm=bb - - --device=ANDROID_10|ANDROID_11|ANDROID_12 - - --a11y-locator - - --fail-fast - - --no-tunnel - - --aws-public-ip - - features/navigation.feature + - --app=build/r_navigation_0.60.apk + - --farm=bb + - --device=ANDROID_10|ANDROID_11|ANDROID_12 + - --a11y-locator + - --fail-fast + - --no-tunnel + - --aws-public-ip + - features/navigation.feature concurrency: 25 concurrency_group: 'bitbar-app' concurrency_method: eager @@ -391,14 +391,14 @@ steps: run: react-native-maze-runner service-ports: true command: - - --app=build/r_navigation_0.69.apk - - --farm=bb - - --device=ANDROID_10|ANDROID_11|ANDROID_12 - - --a11y-locator - - --fail-fast - - --no-tunnel - - --aws-public-ip - - features/navigation.feature + - --app=build/r_navigation_0.69.apk + - --farm=bb + - --device=ANDROID_10|ANDROID_11|ANDROID_12 + - --a11y-locator + - --fail-fast + - --no-tunnel + - --aws-public-ip + - features/navigation.feature concurrency: 25 concurrency_group: 'bitbar-app' concurrency_method: eager @@ -415,14 +415,14 @@ steps: run: react-native-maze-runner service-ports: true command: - - --app=build/r_native_navigation_0.60.apk - - --farm=bb - - --device=ANDROID_10|ANDROID_11|ANDROID_12 - - --a11y-locator - - --fail-fast - - --no-tunnel - - --aws-public-ip - - features/navigation.feature + - --app=build/r_native_navigation_0.60.apk + - --farm=bb + - --device=ANDROID_10|ANDROID_11|ANDROID_12 + - --a11y-locator + - --fail-fast + - --no-tunnel + - --aws-public-ip + - features/navigation.feature concurrency: 25 concurrency_group: 'bitbar-app' concurrency_method: eager @@ -439,14 +439,14 @@ steps: run: react-native-maze-runner service-ports: true command: - - --app=build/r_native_navigation_0.66.apk - - --farm=bb - - --device=ANDROID_10|ANDROID_11|ANDROID_12 - - --a11y-locator - - --fail-fast - - --no-tunnel - - --aws-public-ip - - features/navigation.feature + - --app=build/r_native_navigation_0.66.apk + - --farm=bb + - --device=ANDROID_10|ANDROID_11|ANDROID_12 + - --a11y-locator + - --fail-fast + - --no-tunnel + - --aws-public-ip + - features/navigation.feature concurrency: 25 concurrency_group: 'bitbar-app' concurrency_method: eager diff --git a/.buildkite/full/react-native-cli-pipeline.full.yml b/.buildkite/full/react-native-cli-pipeline.full.yml index b9823b470c..982081db12 100644 --- a/.buildkite/full/react-native-cli-pipeline.full.yml +++ b/.buildkite/full/react-native-cli-pipeline.full.yml @@ -339,22 +339,6 @@ steps: artifact_paths: - build/rn0_67.apk - - label: ":android: Init and build RN 0.67 apk (Hermes)" - key: "rn-cli-0-67-hermes-apk" - depends_on: - - "android-builder-cli-image" - timeout_in_minutes: 15 - env: - DEBUG: true - REACT_NATIVE_VERSION: rn0_67_hermes - plugins: - - docker-compose#v4.12.0: - run: react-native-cli-android-builder - command: ["features/build-app-tests/build-android-app.feature"] - artifact_paths: - - build/rn0_67_hermes.apk - - - label: ":android: Init and build RN 0.69 apk (Non-hermes)" key: "rn-cli-0-69-apk" depends_on: @@ -490,19 +474,6 @@ steps: commands: - test/react-native-cli/scripts/init-and-build-test.sh rn0_67 - - label: ":ios: Init and build RN 0.67 ipa (Hermes)" - key: "rn-cli-0-67-hermes-ipa" - timeout_in_minutes: 60 - agents: - queue: "opensource-arm-mac-cocoa-12" - env: - DEBUG: true - LANG: "en_US.UTF-8" - DEVELOPER_DIR: "/Applications/Xcode13.app" - artifact_paths: build/rn0_67_hermes.ipa - commands: - - test/react-native-cli/scripts/init-and-build-test.sh rn0_67_hermes - - label: ":ios: Init and build RN 0.69 ipa (Non-hermes)" key: "rn-cli-0-69-ipa" timeout_in_minutes: 30 @@ -726,30 +697,7 @@ steps: concurrency_group: 'bitbar-app' concurrency_method: eager - - label: ":bitbar: :android: RN 0.67 Android end-to-end tests (Hermes)" - depends_on: "rn-cli-0-67-hermes-apk" - timeout_in_minutes: 10 - plugins: - artifacts#v1.9.0: - download: "build/rn0_67_hermes.apk" - upload: ./test/react-native-cli/maze_output/**/* - docker-compose#v4.12.0: - pull: react-native-cli-maze-runner - run: react-native-cli-maze-runner - service-ports: true - command: - - --app=build/rn0_67_hermes.apk - - --farm=bb - - --device=ANDROID_10|ANDROID_11|ANDROID_12 - - --a11y-locator - - --no-tunnel - - --aws-public-ip - - features/run-app-tests - concurrency: 25 - concurrency_group: 'bitbar-app' - concurrency_method: eager - - - label: ":bitbar: :android: RN 0.69 Android end-to-end tests (Non-hermes)" + - label: ":runner: RN 0.69 Android end-to-end tests (Non-hermes)" depends_on: "rn-cli-0-69-apk" timeout_in_minutes: 10 plugins: @@ -964,27 +912,6 @@ steps: concurrency_group: "browserstack-app" concurrency_method: eager - - label: ":browserstack: :ios: RN 0.67 iOS end-to-end tests (Hermes)" - depends_on: "rn-cli-0-67-hermes-ipa" - timeout_in_minutes: 10 - plugins: - artifacts#v1.5.0: - download: "build/rn0_67_hermes.ipa" - upload: ./test/react-native-cli/maze_output/**/* - docker-compose#v4.12.0: - pull: react-native-cli-maze-runner - run: react-native-cli-maze-runner - use-aliases: true - command: - - --app=build/rn0_67_hermes.ipa - - --farm=bs - - --device=IOS_14 - - --a11y-locator - - features/run-app-tests - concurrency: 5 - concurrency_group: "browserstack-app" - concurrency_method: eager - - label: ":browserstack: :ios: RN 0.69 iOS end-to-end tests (Non-hermes)" depends_on: "rn-cli-0-69-ipa" timeout_in_minutes: 10 diff --git a/packages/react-native-cli/package-lock.json b/packages/react-native-cli/package-lock.json index 38ef6320e2..b11d973f46 100644 --- a/packages/react-native-cli/package-lock.json +++ b/packages/react-native-cli/package-lock.json @@ -1,876 +1,988 @@ { - "name": "@bugsnag/react-native-cli", - "version": "7.16.5", - "lockfileVersion": 2, - "requires": true, - "packages": { - "": { - "name": "@bugsnag/react-native-cli", - "version": "7.14.2", - "license": "MIT", - "dependencies": { - "command-line-args": "^5.1.1", - "command-line-usage": "^6.1.0", - "consola": "^2.15.0", - "glob": "^7.1.6", - "plist": "^3.0.1", - "prompts": "^2.4.0", - "xcode": "^3.0.1" - }, - "bin": { - "bugsnag-react-native-cli": "bin/cli" - }, - "devDependencies": { - "@types/command-line-args": "^5.0.0", - "@types/command-line-usage": "^5.0.1", - "@types/prompts": "^2.0.9", - "typescript": "^4.1.3" - } - }, - "node_modules/@types/command-line-args": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/@types/command-line-args/-/command-line-args-5.0.0.tgz", - "integrity": "sha512-4eOPXyn5DmP64MCMF8ePDvdlvlzt2a+F8ZaVjqmh2yFCpGjc1kI3kGnCFYX9SCsGTjQcWIyVZ86IHCEyjy/MNg==", - "dev": true - }, - "node_modules/@types/command-line-usage": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/@types/command-line-usage/-/command-line-usage-5.0.1.tgz", - "integrity": "sha512-/xUgezxxYePeXhg5S04hUjxG9JZi+rJTs1+4NwpYPfSaS7BeDa6tVJkH6lN9Cb6rl8d24Fi2uX0s0Ngg2JT6gg==", - "dev": true - }, - "node_modules/@types/node": { - "version": "14.14.7", - "resolved": "https://registry.npmjs.org/@types/node/-/node-14.14.7.tgz", - "integrity": "sha512-Zw1vhUSQZYw+7u5dAwNbIA9TuTotpzY/OF7sJM9FqPOF3SPjKnxrjoTktXDZgUjybf4cWVBP7O8wvKdSaGHweg==", - "dev": true - }, - "node_modules/@types/prompts": { - "version": "2.0.9", - "resolved": "https://registry.npmjs.org/@types/prompts/-/prompts-2.0.9.tgz", - "integrity": "sha512-TORZP+FSjTYMWwKadftmqEn6bziN5RnfygehByGsjxoK5ydnClddtv6GikGWPvCm24oI+YBwck5WDxIIyNxUrA==", - "dev": true, - "dependencies": { - "@types/node": "*" - } - }, - "node_modules/ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dependencies": { - "color-convert": "^1.9.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/array-back": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/array-back/-/array-back-3.1.0.tgz", - "integrity": "sha512-TkuxA4UCOvxuDK6NZYXCalszEzj+TLszyASooky+i742l9TqsOdYCMJJupxRic61hwquNtppB3hgcuq9SVSH1Q==", - "engines": { - "node": ">=6" - } - }, - "node_modules/balanced-match": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", - "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" - }, - "node_modules/base64-js": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", - "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ] - }, - "node_modules/big-integer": { - "version": "1.6.48", - "resolved": "https://registry.npmjs.org/big-integer/-/big-integer-1.6.48.tgz", - "integrity": "sha512-j51egjPa7/i+RdiRuJbPdJ2FIUYYPhvYLjzoYbcMMm62ooO6F94fETG4MTs46zPAF9Brs04OajboA/qTGuz78w==", - "engines": { - "node": ">=0.6" - } - }, - "node_modules/bplist-creator": { - "version": "0.0.8", - "resolved": "https://registry.npmjs.org/bplist-creator/-/bplist-creator-0.0.8.tgz", - "integrity": "sha512-Za9JKzD6fjLC16oX2wsXfc+qBEhJBJB1YPInoAQpMLhDuj5aVOv1baGeIQSq1Fr3OCqzvsoQcSBSwGId/Ja2PA==", - "dependencies": { - "stream-buffers": "~2.2.0" - } - }, - "node_modules/bplist-parser": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/bplist-parser/-/bplist-parser-0.2.0.tgz", - "integrity": "sha512-z0M+byMThzQmD9NILRniCUXYsYpjwnlO8N5uCFaCqIOpqRsJCrQL9NK3JsD67CN5a08nF5oIL2bD6loTdHOuKw==", - "dependencies": { - "big-integer": "^1.6.44" - }, - "engines": { - "node": ">= 5.10.0" - } - }, - "node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "node_modules/chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "dependencies": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/color-convert": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", - "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", - "dependencies": { - "color-name": "1.1.3" - } - }, - "node_modules/color-name": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=" - }, - "node_modules/command-line-args": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/command-line-args/-/command-line-args-5.1.1.tgz", - "integrity": "sha512-hL/eG8lrll1Qy1ezvkant+trihbGnaKaeEjj6Scyr3DN+RC7iQ5Rz84IeLERfAWDGo0HBSNAakczwgCilDXnWg==", - "dependencies": { - "array-back": "^3.0.1", - "find-replace": "^3.0.0", - "lodash.camelcase": "^4.3.0", - "typical": "^4.0.0" - }, - "engines": { - "node": ">=4.0.0" - } - }, - "node_modules/command-line-usage": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/command-line-usage/-/command-line-usage-6.1.0.tgz", - "integrity": "sha512-Ew1clU4pkUeo6AFVDFxCbnN7GIZfXl48HIOQeFQnkO3oOqvpI7wdqtLRwv9iOCZ/7A+z4csVZeiDdEcj8g6Wiw==", - "dependencies": { - "array-back": "^4.0.0", - "chalk": "^2.4.2", - "table-layout": "^1.0.0", - "typical": "^5.2.0" - }, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/command-line-usage/node_modules/array-back": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/array-back/-/array-back-4.0.1.tgz", - "integrity": "sha512-Z/JnaVEXv+A9xabHzN43FiiiWEE7gPCRXMrVmRm00tWbjZRul1iHm7ECzlyNq1p4a4ATXz+G9FJ3GqGOkOV3fg==", - "engines": { - "node": ">=8" - } - }, - "node_modules/command-line-usage/node_modules/typical": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/typical/-/typical-5.2.0.tgz", - "integrity": "sha512-dvdQgNDNJo+8B2uBQoqdb11eUCE1JQXhvjC/CZtgvZseVd5TYMXnq0+vuUemXbd/Se29cTaUuPX3YIc2xgbvIg==", - "engines": { - "node": ">=8" - } - }, - "node_modules/concat-map": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=" - }, - "node_modules/consola": { - "version": "2.15.0", - "resolved": "https://registry.npmjs.org/consola/-/consola-2.15.0.tgz", - "integrity": "sha512-vlcSGgdYS26mPf7qNi+dCisbhiyDnrN1zaRbw3CSuc2wGOMEGGPsp46PdRG5gqXwgtJfjxDkxRNAgRPr1B77vQ==" - }, - "node_modules/deep-extend": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", - "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==", - "engines": { - "node": ">=4.0.0" - } - }, - "node_modules/escape-string-regexp": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", - "engines": { - "node": ">=0.8.0" - } - }, - "node_modules/find-replace": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/find-replace/-/find-replace-3.0.0.tgz", - "integrity": "sha512-6Tb2myMioCAgv5kfvP5/PkZZ/ntTpVK39fHY7WkWBgvbeE+VHd/tZuZ4mrC+bxh4cfOZeYKVPaJIZtZXV7GNCQ==", - "dependencies": { - "array-back": "^3.0.1" - }, - "engines": { - "node": ">=4.0.0" - } - }, - "node_modules/fs.realpath": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=" - }, - "node_modules/glob": { - "version": "7.1.6", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", - "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==", - "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.0.4", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - }, - "engines": { - "node": "*" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", - "engines": { - "node": ">=4" - } - }, - "node_modules/inflight": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", - "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", - "dependencies": { - "once": "^1.3.0", - "wrappy": "1" - } - }, - "node_modules/inherits": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" - }, - "node_modules/kleur": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/kleur/-/kleur-3.0.3.tgz", - "integrity": "sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==", - "engines": { - "node": ">=6" - } - }, - "node_modules/lodash.camelcase": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz", - "integrity": "sha1-soqmKIorn8ZRA1x3EfZathkDMaY=" - }, - "node_modules/minimatch": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", - "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", - "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" - } - }, - "node_modules/once": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", - "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", - "dependencies": { - "wrappy": "1" - } - }, - "node_modules/path-is-absolute": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", - "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/plist": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/plist/-/plist-3.0.1.tgz", - "integrity": "sha512-GpgvHHocGRyQm74b6FWEZZVRroHKE1I0/BTjAmySaohK+cUn+hZpbqXkc3KWgW3gQYkqcQej35FohcT0FRlkRQ==", - "dependencies": { - "base64-js": "^1.2.3", - "xmlbuilder": "^9.0.7", - "xmldom": "0.1.x" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/prompts": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/prompts/-/prompts-2.4.0.tgz", - "integrity": "sha512-awZAKrk3vN6CroQukBL+R9051a4R3zCZBlJm/HBfrSZ8iTpYix3VX1vU4mveiLpiwmOJT4wokTF9m6HUk4KqWQ==", - "dependencies": { - "kleur": "^3.0.3", - "sisteransi": "^1.0.5" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/reduce-flatten": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/reduce-flatten/-/reduce-flatten-2.0.0.tgz", - "integrity": "sha512-EJ4UNY/U1t2P/2k6oqotuX2Cc3T6nxJwsM0N0asT7dhrtH1ltUxDn4NalSYmPE2rCkVpcf/X6R0wDwcFpzhd4w==", - "engines": { - "node": ">=6" - } - }, - "node_modules/simple-plist": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/simple-plist/-/simple-plist-1.1.1.tgz", - "integrity": "sha512-pKMCVKvZbZTsqYR6RKgLfBHkh2cV89GXcA/0CVPje3sOiNOnXA8+rp/ciAMZ7JRaUdLzlEM6JFfUn+fS6Nt3hg==", - "dependencies": { - "bplist-creator": "0.0.8", - "bplist-parser": "0.2.0", - "plist": "^3.0.1" - } - }, - "node_modules/sisteransi": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/sisteransi/-/sisteransi-1.0.5.tgz", - "integrity": "sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==" - }, - "node_modules/stream-buffers": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/stream-buffers/-/stream-buffers-2.2.0.tgz", - "integrity": "sha1-kdX1Ew0c75bc+n9yaUUYh0HQnuQ=", - "engines": { - "node": ">= 0.10.0" - } - }, - "node_modules/supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dependencies": { - "has-flag": "^3.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/table-layout": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/table-layout/-/table-layout-1.0.1.tgz", - "integrity": "sha512-dEquqYNJiGwY7iPfZ3wbXDI944iqanTSchrACLL2nOB+1r+h1Nzu2eH+DuPPvWvm5Ry7iAPeFlgEtP5bIp5U7Q==", - "dependencies": { - "array-back": "^4.0.1", - "deep-extend": "~0.6.0", - "typical": "^5.2.0", - "wordwrapjs": "^4.0.0" - }, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/table-layout/node_modules/array-back": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/array-back/-/array-back-4.0.1.tgz", - "integrity": "sha512-Z/JnaVEXv+A9xabHzN43FiiiWEE7gPCRXMrVmRm00tWbjZRul1iHm7ECzlyNq1p4a4ATXz+G9FJ3GqGOkOV3fg==", - "engines": { - "node": ">=8" - } - }, - "node_modules/table-layout/node_modules/typical": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/typical/-/typical-5.2.0.tgz", - "integrity": "sha512-dvdQgNDNJo+8B2uBQoqdb11eUCE1JQXhvjC/CZtgvZseVd5TYMXnq0+vuUemXbd/Se29cTaUuPX3YIc2xgbvIg==", - "engines": { - "node": ">=8" - } - }, - "node_modules/typescript": { - "version": "4.1.3", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.1.3.tgz", - "integrity": "sha512-B3ZIOf1IKeH2ixgHhj6la6xdwR9QrLC5d1VKeCSY4tvkqhF2eqd9O7txNlS0PO3GrBAFIdr3L1ndNwteUbZLYg==", - "dev": true, - "bin": { - "tsc": "bin/tsc", - "tsserver": "bin/tsserver" - }, - "engines": { - "node": ">=4.2.0" - } - }, - "node_modules/typical": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/typical/-/typical-4.0.0.tgz", - "integrity": "sha512-VAH4IvQ7BDFYglMd7BPRDfLgxZZX4O4TFcRDA6EN5X7erNJJq+McIEp8np9aVtxrCJ6qx4GTYVfOWNjcqwZgRw==", - "engines": { - "node": ">=8" - } - }, - "node_modules/uuid": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-7.0.3.tgz", - "integrity": "sha512-DPSke0pXhTZgoF/d+WSt2QaKMCFSfx7QegxEWT+JOuHF5aWrKEn0G+ztjuJg/gG8/ItK+rbPCD/yNv8yyih6Cg==", - "bin": { - "uuid": "dist/bin/uuid" - } - }, - "node_modules/wordwrapjs": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/wordwrapjs/-/wordwrapjs-4.0.0.tgz", - "integrity": "sha512-Svqw723a3R34KvsMgpjFBYCgNOSdcW3mQFK4wIfhGQhtaFVOJmdYoXgi63ne3dTlWgatVcUc7t4HtQ/+bUVIzQ==", - "dependencies": { - "reduce-flatten": "^2.0.0", - "typical": "^5.0.0" - }, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/wordwrapjs/node_modules/typical": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/typical/-/typical-5.2.0.tgz", - "integrity": "sha512-dvdQgNDNJo+8B2uBQoqdb11eUCE1JQXhvjC/CZtgvZseVd5TYMXnq0+vuUemXbd/Se29cTaUuPX3YIc2xgbvIg==", - "engines": { - "node": ">=8" - } - }, - "node_modules/wrappy": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" - }, - "node_modules/xcode": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/xcode/-/xcode-3.0.1.tgz", - "integrity": "sha512-kCz5k7J7XbJtjABOvkc5lJmkiDh8VhjVCGNiqdKCscmVpdVUpEAyXv1xmCLkQJ5dsHqx3IPO4XW+NTDhU/fatA==", - "dependencies": { - "simple-plist": "^1.1.0", - "uuid": "^7.0.3" - }, - "engines": { - "node": ">=10.0.0" - } - }, - "node_modules/xmlbuilder": { - "version": "9.0.7", - "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-9.0.7.tgz", - "integrity": "sha1-Ey7mPS7FVlxVfiD0wi35rKaGsQ0=", - "engines": { - "node": ">=4.0" - } - }, - "node_modules/xmldom": { - "version": "0.1.31", - "resolved": "https://registry.npmjs.org/xmldom/-/xmldom-0.1.31.tgz", - "integrity": "sha512-yS2uJflVQs6n+CyjHoaBmVSqIDevTAWrzMmjG1Gc7h1qQ7uVozNhEPJAwZXWyGQ/Gafo3fCwrcaokezLPupVyQ==", - "deprecated": "Deprecated due to CVE-2021-21366 resolved in 0.5.0", - "engines": { - "node": ">=0.1" - } - } - }, - "dependencies": { - "@types/command-line-args": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/@types/command-line-args/-/command-line-args-5.0.0.tgz", - "integrity": "sha512-4eOPXyn5DmP64MCMF8ePDvdlvlzt2a+F8ZaVjqmh2yFCpGjc1kI3kGnCFYX9SCsGTjQcWIyVZ86IHCEyjy/MNg==", - "dev": true - }, - "@types/command-line-usage": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/@types/command-line-usage/-/command-line-usage-5.0.1.tgz", - "integrity": "sha512-/xUgezxxYePeXhg5S04hUjxG9JZi+rJTs1+4NwpYPfSaS7BeDa6tVJkH6lN9Cb6rl8d24Fi2uX0s0Ngg2JT6gg==", - "dev": true - }, - "@types/node": { - "version": "14.14.7", - "resolved": "https://registry.npmjs.org/@types/node/-/node-14.14.7.tgz", - "integrity": "sha512-Zw1vhUSQZYw+7u5dAwNbIA9TuTotpzY/OF7sJM9FqPOF3SPjKnxrjoTktXDZgUjybf4cWVBP7O8wvKdSaGHweg==", - "dev": true - }, - "@types/prompts": { - "version": "2.0.9", - "resolved": "https://registry.npmjs.org/@types/prompts/-/prompts-2.0.9.tgz", - "integrity": "sha512-TORZP+FSjTYMWwKadftmqEn6bziN5RnfygehByGsjxoK5ydnClddtv6GikGWPvCm24oI+YBwck5WDxIIyNxUrA==", - "dev": true, - "requires": { - "@types/node": "*" - } - }, - "ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "requires": { - "color-convert": "^1.9.0" - } - }, - "array-back": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/array-back/-/array-back-3.1.0.tgz", - "integrity": "sha512-TkuxA4UCOvxuDK6NZYXCalszEzj+TLszyASooky+i742l9TqsOdYCMJJupxRic61hwquNtppB3hgcuq9SVSH1Q==" - }, - "balanced-match": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", - "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" - }, - "base64-js": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", - "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==" - }, - "big-integer": { - "version": "1.6.48", - "resolved": "https://registry.npmjs.org/big-integer/-/big-integer-1.6.48.tgz", - "integrity": "sha512-j51egjPa7/i+RdiRuJbPdJ2FIUYYPhvYLjzoYbcMMm62ooO6F94fETG4MTs46zPAF9Brs04OajboA/qTGuz78w==" - }, - "bplist-creator": { - "version": "0.0.8", - "resolved": "https://registry.npmjs.org/bplist-creator/-/bplist-creator-0.0.8.tgz", - "integrity": "sha512-Za9JKzD6fjLC16oX2wsXfc+qBEhJBJB1YPInoAQpMLhDuj5aVOv1baGeIQSq1Fr3OCqzvsoQcSBSwGId/Ja2PA==", - "requires": { - "stream-buffers": "~2.2.0" - } - }, - "bplist-parser": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/bplist-parser/-/bplist-parser-0.2.0.tgz", - "integrity": "sha512-z0M+byMThzQmD9NILRniCUXYsYpjwnlO8N5uCFaCqIOpqRsJCrQL9NK3JsD67CN5a08nF5oIL2bD6loTdHOuKw==", - "requires": { - "big-integer": "^1.6.44" - } - }, - "brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "requires": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "requires": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - } - }, - "color-convert": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", - "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", - "requires": { - "color-name": "1.1.3" - } - }, - "color-name": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=" - }, - "command-line-args": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/command-line-args/-/command-line-args-5.1.1.tgz", - "integrity": "sha512-hL/eG8lrll1Qy1ezvkant+trihbGnaKaeEjj6Scyr3DN+RC7iQ5Rz84IeLERfAWDGo0HBSNAakczwgCilDXnWg==", - "requires": { - "array-back": "^3.0.1", - "find-replace": "^3.0.0", - "lodash.camelcase": "^4.3.0", - "typical": "^4.0.0" - } - }, - "command-line-usage": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/command-line-usage/-/command-line-usage-6.1.0.tgz", - "integrity": "sha512-Ew1clU4pkUeo6AFVDFxCbnN7GIZfXl48HIOQeFQnkO3oOqvpI7wdqtLRwv9iOCZ/7A+z4csVZeiDdEcj8g6Wiw==", - "requires": { - "array-back": "^4.0.0", - "chalk": "^2.4.2", - "table-layout": "^1.0.0", - "typical": "^5.2.0" - }, - "dependencies": { - "array-back": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/array-back/-/array-back-4.0.1.tgz", - "integrity": "sha512-Z/JnaVEXv+A9xabHzN43FiiiWEE7gPCRXMrVmRm00tWbjZRul1iHm7ECzlyNq1p4a4ATXz+G9FJ3GqGOkOV3fg==" - }, - "typical": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/typical/-/typical-5.2.0.tgz", - "integrity": "sha512-dvdQgNDNJo+8B2uBQoqdb11eUCE1JQXhvjC/CZtgvZseVd5TYMXnq0+vuUemXbd/Se29cTaUuPX3YIc2xgbvIg==" - } - } - }, - "concat-map": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=" - }, - "consola": { - "version": "2.15.0", - "resolved": "https://registry.npmjs.org/consola/-/consola-2.15.0.tgz", - "integrity": "sha512-vlcSGgdYS26mPf7qNi+dCisbhiyDnrN1zaRbw3CSuc2wGOMEGGPsp46PdRG5gqXwgtJfjxDkxRNAgRPr1B77vQ==" - }, - "deep-extend": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", - "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==" - }, - "escape-string-regexp": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=" - }, - "find-replace": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/find-replace/-/find-replace-3.0.0.tgz", - "integrity": "sha512-6Tb2myMioCAgv5kfvP5/PkZZ/ntTpVK39fHY7WkWBgvbeE+VHd/tZuZ4mrC+bxh4cfOZeYKVPaJIZtZXV7GNCQ==", - "requires": { - "array-back": "^3.0.1" - } - }, - "fs.realpath": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=" - }, - "glob": { - "version": "7.1.6", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", - "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==", - "requires": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.0.4", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - } - }, - "has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=" - }, - "inflight": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", - "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", - "requires": { - "once": "^1.3.0", - "wrappy": "1" - } - }, - "inherits": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" - }, - "kleur": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/kleur/-/kleur-3.0.3.tgz", - "integrity": "sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==" - }, - "lodash.camelcase": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz", - "integrity": "sha1-soqmKIorn8ZRA1x3EfZathkDMaY=" - }, - "minimatch": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", - "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", - "requires": { - "brace-expansion": "^1.1.7" - } - }, - "once": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", - "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", - "requires": { - "wrappy": "1" - } - }, - "path-is-absolute": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", - "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=" - }, - "plist": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/plist/-/plist-3.0.1.tgz", - "integrity": "sha512-GpgvHHocGRyQm74b6FWEZZVRroHKE1I0/BTjAmySaohK+cUn+hZpbqXkc3KWgW3gQYkqcQej35FohcT0FRlkRQ==", - "requires": { - "base64-js": "^1.2.3", - "xmlbuilder": "^9.0.7", - "xmldom": "0.1.x" - } - }, - "prompts": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/prompts/-/prompts-2.4.0.tgz", - "integrity": "sha512-awZAKrk3vN6CroQukBL+R9051a4R3zCZBlJm/HBfrSZ8iTpYix3VX1vU4mveiLpiwmOJT4wokTF9m6HUk4KqWQ==", - "requires": { - "kleur": "^3.0.3", - "sisteransi": "^1.0.5" - } - }, - "reduce-flatten": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/reduce-flatten/-/reduce-flatten-2.0.0.tgz", - "integrity": "sha512-EJ4UNY/U1t2P/2k6oqotuX2Cc3T6nxJwsM0N0asT7dhrtH1ltUxDn4NalSYmPE2rCkVpcf/X6R0wDwcFpzhd4w==" - }, - "simple-plist": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/simple-plist/-/simple-plist-1.1.1.tgz", - "integrity": "sha512-pKMCVKvZbZTsqYR6RKgLfBHkh2cV89GXcA/0CVPje3sOiNOnXA8+rp/ciAMZ7JRaUdLzlEM6JFfUn+fS6Nt3hg==", - "requires": { - "bplist-creator": "0.0.8", - "bplist-parser": "0.2.0", - "plist": "^3.0.1" - } - }, - "sisteransi": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/sisteransi/-/sisteransi-1.0.5.tgz", - "integrity": "sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==" - }, - "stream-buffers": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/stream-buffers/-/stream-buffers-2.2.0.tgz", - "integrity": "sha1-kdX1Ew0c75bc+n9yaUUYh0HQnuQ=" - }, - "supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "requires": { - "has-flag": "^3.0.0" - } - }, - "table-layout": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/table-layout/-/table-layout-1.0.1.tgz", - "integrity": "sha512-dEquqYNJiGwY7iPfZ3wbXDI944iqanTSchrACLL2nOB+1r+h1Nzu2eH+DuPPvWvm5Ry7iAPeFlgEtP5bIp5U7Q==", - "requires": { - "array-back": "^4.0.1", - "deep-extend": "~0.6.0", - "typical": "^5.2.0", - "wordwrapjs": "^4.0.0" - }, - "dependencies": { - "array-back": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/array-back/-/array-back-4.0.1.tgz", - "integrity": "sha512-Z/JnaVEXv+A9xabHzN43FiiiWEE7gPCRXMrVmRm00tWbjZRul1iHm7ECzlyNq1p4a4ATXz+G9FJ3GqGOkOV3fg==" - }, - "typical": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/typical/-/typical-5.2.0.tgz", - "integrity": "sha512-dvdQgNDNJo+8B2uBQoqdb11eUCE1JQXhvjC/CZtgvZseVd5TYMXnq0+vuUemXbd/Se29cTaUuPX3YIc2xgbvIg==" - } - } - }, - "typescript": { - "version": "4.1.3", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.1.3.tgz", - "integrity": "sha512-B3ZIOf1IKeH2ixgHhj6la6xdwR9QrLC5d1VKeCSY4tvkqhF2eqd9O7txNlS0PO3GrBAFIdr3L1ndNwteUbZLYg==", - "dev": true - }, - "typical": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/typical/-/typical-4.0.0.tgz", - "integrity": "sha512-VAH4IvQ7BDFYglMd7BPRDfLgxZZX4O4TFcRDA6EN5X7erNJJq+McIEp8np9aVtxrCJ6qx4GTYVfOWNjcqwZgRw==" - }, - "uuid": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-7.0.3.tgz", - "integrity": "sha512-DPSke0pXhTZgoF/d+WSt2QaKMCFSfx7QegxEWT+JOuHF5aWrKEn0G+ztjuJg/gG8/ItK+rbPCD/yNv8yyih6Cg==" - }, - "wordwrapjs": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/wordwrapjs/-/wordwrapjs-4.0.0.tgz", - "integrity": "sha512-Svqw723a3R34KvsMgpjFBYCgNOSdcW3mQFK4wIfhGQhtaFVOJmdYoXgi63ne3dTlWgatVcUc7t4HtQ/+bUVIzQ==", - "requires": { - "reduce-flatten": "^2.0.0", - "typical": "^5.0.0" - }, - "dependencies": { - "typical": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/typical/-/typical-5.2.0.tgz", - "integrity": "sha512-dvdQgNDNJo+8B2uBQoqdb11eUCE1JQXhvjC/CZtgvZseVd5TYMXnq0+vuUemXbd/Se29cTaUuPX3YIc2xgbvIg==" - } - } - }, - "wrappy": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" - }, - "xcode": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/xcode/-/xcode-3.0.1.tgz", - "integrity": "sha512-kCz5k7J7XbJtjABOvkc5lJmkiDh8VhjVCGNiqdKCscmVpdVUpEAyXv1xmCLkQJ5dsHqx3IPO4XW+NTDhU/fatA==", - "requires": { - "simple-plist": "^1.1.0", - "uuid": "^7.0.3" - } - }, - "xmlbuilder": { - "version": "9.0.7", - "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-9.0.7.tgz", - "integrity": "sha1-Ey7mPS7FVlxVfiD0wi35rKaGsQ0=" - }, - "xmldom": { - "version": "0.1.31", - "resolved": "https://registry.npmjs.org/xmldom/-/xmldom-0.1.31.tgz", - "integrity": "sha512-yS2uJflVQs6n+CyjHoaBmVSqIDevTAWrzMmjG1Gc7h1qQ7uVozNhEPJAwZXWyGQ/Gafo3fCwrcaokezLPupVyQ==" - } - } + "name": "@bugsnag/react-native-cli", + "version": "7.16.5", + "lockfileVersion": 2, + "requires": true, + "packages": { + "": { + "name": "@bugsnag/react-native-cli", + "version": "7.16.5", + "license": "MIT", + "dependencies": { + "command-line-args": "^5.1.1", + "command-line-usage": "^6.1.0", + "consola": "^2.15.0", + "detect-indent": "^6.1.0", + "glob": "^7.1.6", + "plist": "^3.0.1", + "prompts": "^2.4.0", + "semver": "^7.5.4", + "xcode": "^3.0.1" + }, + "bin": { + "bugsnag-react-native-cli": "bin/cli" + }, + "devDependencies": { + "@types/command-line-args": "^5.0.0", + "@types/command-line-usage": "^5.0.1", + "@types/glob": "^8.1.0", + "@types/prompts": "^2.0.9", + "@types/semver": "^7.5.0", + "typescript": "^4.1.3" + } + }, + "node_modules/@types/command-line-args": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/@types/command-line-args/-/command-line-args-5.0.0.tgz", + "integrity": "sha512-4eOPXyn5DmP64MCMF8ePDvdlvlzt2a+F8ZaVjqmh2yFCpGjc1kI3kGnCFYX9SCsGTjQcWIyVZ86IHCEyjy/MNg==", + "dev": true + }, + "node_modules/@types/command-line-usage": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/@types/command-line-usage/-/command-line-usage-5.0.1.tgz", + "integrity": "sha512-/xUgezxxYePeXhg5S04hUjxG9JZi+rJTs1+4NwpYPfSaS7BeDa6tVJkH6lN9Cb6rl8d24Fi2uX0s0Ngg2JT6gg==", + "dev": true + }, + "node_modules/@types/glob": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/@types/glob/-/glob-8.1.0.tgz", + "integrity": "sha512-IO+MJPVhoqz+28h1qLAcBEH2+xHMK6MTyHJc7MTnnYb6wsoLR29POVGJ7LycmVXIqyy/4/2ShP5sUwTXuOwb/w==", + "dev": true, + "dependencies": { + "@types/minimatch": "^5.1.2", + "@types/node": "*" + } + }, + "node_modules/@types/minimatch": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/@types/minimatch/-/minimatch-5.1.2.tgz", + "integrity": "sha512-K0VQKziLUWkVKiRVrx4a40iPaxTUefQmjtkQofBkYRcoaaL/8rhwDWww9qWbrgicNOgnpIsMxyNIUM4+n6dUIA==", + "dev": true + }, + "node_modules/@types/node": { + "version": "14.14.7", + "resolved": "https://registry.npmjs.org/@types/node/-/node-14.14.7.tgz", + "integrity": "sha512-Zw1vhUSQZYw+7u5dAwNbIA9TuTotpzY/OF7sJM9FqPOF3SPjKnxrjoTktXDZgUjybf4cWVBP7O8wvKdSaGHweg==", + "dev": true + }, + "node_modules/@types/prompts": { + "version": "2.0.9", + "resolved": "https://registry.npmjs.org/@types/prompts/-/prompts-2.0.9.tgz", + "integrity": "sha512-TORZP+FSjTYMWwKadftmqEn6bziN5RnfygehByGsjxoK5ydnClddtv6GikGWPvCm24oI+YBwck5WDxIIyNxUrA==", + "dev": true, + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/semver": { + "version": "7.5.0", + "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.5.0.tgz", + "integrity": "sha512-G8hZ6XJiHnuhQKR7ZmysCeJWE08o8T0AXtk5darsCaTVsYZhhgUrq53jizaR2FvsoeCwJhlmwTjkXBY5Pn/ZHw==", + "dev": true + }, + "node_modules/ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dependencies": { + "color-convert": "^1.9.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/array-back": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/array-back/-/array-back-3.1.0.tgz", + "integrity": "sha512-TkuxA4UCOvxuDK6NZYXCalszEzj+TLszyASooky+i742l9TqsOdYCMJJupxRic61hwquNtppB3hgcuq9SVSH1Q==", + "engines": { + "node": ">=6" + } + }, + "node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" + }, + "node_modules/base64-js": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", + "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/big-integer": { + "version": "1.6.48", + "resolved": "https://registry.npmjs.org/big-integer/-/big-integer-1.6.48.tgz", + "integrity": "sha512-j51egjPa7/i+RdiRuJbPdJ2FIUYYPhvYLjzoYbcMMm62ooO6F94fETG4MTs46zPAF9Brs04OajboA/qTGuz78w==", + "engines": { + "node": ">=0.6" + } + }, + "node_modules/bplist-creator": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/bplist-creator/-/bplist-creator-0.0.8.tgz", + "integrity": "sha512-Za9JKzD6fjLC16oX2wsXfc+qBEhJBJB1YPInoAQpMLhDuj5aVOv1baGeIQSq1Fr3OCqzvsoQcSBSwGId/Ja2PA==", + "dependencies": { + "stream-buffers": "~2.2.0" + } + }, + "node_modules/bplist-parser": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/bplist-parser/-/bplist-parser-0.2.0.tgz", + "integrity": "sha512-z0M+byMThzQmD9NILRniCUXYsYpjwnlO8N5uCFaCqIOpqRsJCrQL9NK3JsD67CN5a08nF5oIL2bD6loTdHOuKw==", + "dependencies": { + "big-integer": "^1.6.44" + }, + "engines": { + "node": ">= 5.10.0" + } + }, + "node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dependencies": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dependencies": { + "color-name": "1.1.3" + } + }, + "node_modules/color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=" + }, + "node_modules/command-line-args": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/command-line-args/-/command-line-args-5.1.1.tgz", + "integrity": "sha512-hL/eG8lrll1Qy1ezvkant+trihbGnaKaeEjj6Scyr3DN+RC7iQ5Rz84IeLERfAWDGo0HBSNAakczwgCilDXnWg==", + "dependencies": { + "array-back": "^3.0.1", + "find-replace": "^3.0.0", + "lodash.camelcase": "^4.3.0", + "typical": "^4.0.0" + }, + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/command-line-usage": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/command-line-usage/-/command-line-usage-6.1.0.tgz", + "integrity": "sha512-Ew1clU4pkUeo6AFVDFxCbnN7GIZfXl48HIOQeFQnkO3oOqvpI7wdqtLRwv9iOCZ/7A+z4csVZeiDdEcj8g6Wiw==", + "dependencies": { + "array-back": "^4.0.0", + "chalk": "^2.4.2", + "table-layout": "^1.0.0", + "typical": "^5.2.0" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/command-line-usage/node_modules/array-back": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/array-back/-/array-back-4.0.1.tgz", + "integrity": "sha512-Z/JnaVEXv+A9xabHzN43FiiiWEE7gPCRXMrVmRm00tWbjZRul1iHm7ECzlyNq1p4a4ATXz+G9FJ3GqGOkOV3fg==", + "engines": { + "node": ">=8" + } + }, + "node_modules/command-line-usage/node_modules/typical": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/typical/-/typical-5.2.0.tgz", + "integrity": "sha512-dvdQgNDNJo+8B2uBQoqdb11eUCE1JQXhvjC/CZtgvZseVd5TYMXnq0+vuUemXbd/Se29cTaUuPX3YIc2xgbvIg==", + "engines": { + "node": ">=8" + } + }, + "node_modules/concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=" + }, + "node_modules/consola": { + "version": "2.15.0", + "resolved": "https://registry.npmjs.org/consola/-/consola-2.15.0.tgz", + "integrity": "sha512-vlcSGgdYS26mPf7qNi+dCisbhiyDnrN1zaRbw3CSuc2wGOMEGGPsp46PdRG5gqXwgtJfjxDkxRNAgRPr1B77vQ==" + }, + "node_modules/deep-extend": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", + "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==", + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/detect-indent": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/detect-indent/-/detect-indent-6.1.0.tgz", + "integrity": "sha512-reYkTUJAZb9gUuZ2RvVCNhVHdg62RHnJ7WJl8ftMi4diZ6NWlciOzQN88pUhSELEwflJht4oQDv0F0BMlwaYtA==", + "engines": { + "node": ">=8" + } + }, + "node_modules/escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/find-replace": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/find-replace/-/find-replace-3.0.0.tgz", + "integrity": "sha512-6Tb2myMioCAgv5kfvP5/PkZZ/ntTpVK39fHY7WkWBgvbeE+VHd/tZuZ4mrC+bxh4cfOZeYKVPaJIZtZXV7GNCQ==", + "dependencies": { + "array-back": "^3.0.1" + }, + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=" + }, + "node_modules/glob": { + "version": "7.1.6", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", + "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==", + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", + "engines": { + "node": ">=4" + } + }, + "node_modules/inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", + "dependencies": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" + }, + "node_modules/kleur": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/kleur/-/kleur-3.0.3.tgz", + "integrity": "sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==", + "engines": { + "node": ">=6" + } + }, + "node_modules/lodash.camelcase": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz", + "integrity": "sha1-soqmKIorn8ZRA1x3EfZathkDMaY=" + }, + "node_modules/lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/minimatch": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", + "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "dependencies": { + "wrappy": "1" + } + }, + "node_modules/path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/plist": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/plist/-/plist-3.0.1.tgz", + "integrity": "sha512-GpgvHHocGRyQm74b6FWEZZVRroHKE1I0/BTjAmySaohK+cUn+hZpbqXkc3KWgW3gQYkqcQej35FohcT0FRlkRQ==", + "dependencies": { + "base64-js": "^1.2.3", + "xmlbuilder": "^9.0.7", + "xmldom": "0.1.x" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/prompts": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/prompts/-/prompts-2.4.0.tgz", + "integrity": "sha512-awZAKrk3vN6CroQukBL+R9051a4R3zCZBlJm/HBfrSZ8iTpYix3VX1vU4mveiLpiwmOJT4wokTF9m6HUk4KqWQ==", + "dependencies": { + "kleur": "^3.0.3", + "sisteransi": "^1.0.5" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/reduce-flatten": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/reduce-flatten/-/reduce-flatten-2.0.0.tgz", + "integrity": "sha512-EJ4UNY/U1t2P/2k6oqotuX2Cc3T6nxJwsM0N0asT7dhrtH1ltUxDn4NalSYmPE2rCkVpcf/X6R0wDwcFpzhd4w==", + "engines": { + "node": ">=6" + } + }, + "node_modules/semver": { + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", + "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/simple-plist": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/simple-plist/-/simple-plist-1.1.1.tgz", + "integrity": "sha512-pKMCVKvZbZTsqYR6RKgLfBHkh2cV89GXcA/0CVPje3sOiNOnXA8+rp/ciAMZ7JRaUdLzlEM6JFfUn+fS6Nt3hg==", + "dependencies": { + "bplist-creator": "0.0.8", + "bplist-parser": "0.2.0", + "plist": "^3.0.1" + } + }, + "node_modules/sisteransi": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/sisteransi/-/sisteransi-1.0.5.tgz", + "integrity": "sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==" + }, + "node_modules/stream-buffers": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/stream-buffers/-/stream-buffers-2.2.0.tgz", + "integrity": "sha1-kdX1Ew0c75bc+n9yaUUYh0HQnuQ=", + "engines": { + "node": ">= 0.10.0" + } + }, + "node_modules/supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dependencies": { + "has-flag": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/table-layout": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/table-layout/-/table-layout-1.0.1.tgz", + "integrity": "sha512-dEquqYNJiGwY7iPfZ3wbXDI944iqanTSchrACLL2nOB+1r+h1Nzu2eH+DuPPvWvm5Ry7iAPeFlgEtP5bIp5U7Q==", + "dependencies": { + "array-back": "^4.0.1", + "deep-extend": "~0.6.0", + "typical": "^5.2.0", + "wordwrapjs": "^4.0.0" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/table-layout/node_modules/array-back": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/array-back/-/array-back-4.0.1.tgz", + "integrity": "sha512-Z/JnaVEXv+A9xabHzN43FiiiWEE7gPCRXMrVmRm00tWbjZRul1iHm7ECzlyNq1p4a4ATXz+G9FJ3GqGOkOV3fg==", + "engines": { + "node": ">=8" + } + }, + "node_modules/table-layout/node_modules/typical": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/typical/-/typical-5.2.0.tgz", + "integrity": "sha512-dvdQgNDNJo+8B2uBQoqdb11eUCE1JQXhvjC/CZtgvZseVd5TYMXnq0+vuUemXbd/Se29cTaUuPX3YIc2xgbvIg==", + "engines": { + "node": ">=8" + } + }, + "node_modules/typescript": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.1.3.tgz", + "integrity": "sha512-B3ZIOf1IKeH2ixgHhj6la6xdwR9QrLC5d1VKeCSY4tvkqhF2eqd9O7txNlS0PO3GrBAFIdr3L1ndNwteUbZLYg==", + "dev": true, + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=4.2.0" + } + }, + "node_modules/typical": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/typical/-/typical-4.0.0.tgz", + "integrity": "sha512-VAH4IvQ7BDFYglMd7BPRDfLgxZZX4O4TFcRDA6EN5X7erNJJq+McIEp8np9aVtxrCJ6qx4GTYVfOWNjcqwZgRw==", + "engines": { + "node": ">=8" + } + }, + "node_modules/uuid": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-7.0.3.tgz", + "integrity": "sha512-DPSke0pXhTZgoF/d+WSt2QaKMCFSfx7QegxEWT+JOuHF5aWrKEn0G+ztjuJg/gG8/ItK+rbPCD/yNv8yyih6Cg==", + "bin": { + "uuid": "dist/bin/uuid" + } + }, + "node_modules/wordwrapjs": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/wordwrapjs/-/wordwrapjs-4.0.0.tgz", + "integrity": "sha512-Svqw723a3R34KvsMgpjFBYCgNOSdcW3mQFK4wIfhGQhtaFVOJmdYoXgi63ne3dTlWgatVcUc7t4HtQ/+bUVIzQ==", + "dependencies": { + "reduce-flatten": "^2.0.0", + "typical": "^5.0.0" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/wordwrapjs/node_modules/typical": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/typical/-/typical-5.2.0.tgz", + "integrity": "sha512-dvdQgNDNJo+8B2uBQoqdb11eUCE1JQXhvjC/CZtgvZseVd5TYMXnq0+vuUemXbd/Se29cTaUuPX3YIc2xgbvIg==", + "engines": { + "node": ">=8" + } + }, + "node_modules/wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" + }, + "node_modules/xcode": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/xcode/-/xcode-3.0.1.tgz", + "integrity": "sha512-kCz5k7J7XbJtjABOvkc5lJmkiDh8VhjVCGNiqdKCscmVpdVUpEAyXv1xmCLkQJ5dsHqx3IPO4XW+NTDhU/fatA==", + "dependencies": { + "simple-plist": "^1.1.0", + "uuid": "^7.0.3" + }, + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/xmlbuilder": { + "version": "9.0.7", + "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-9.0.7.tgz", + "integrity": "sha1-Ey7mPS7FVlxVfiD0wi35rKaGsQ0=", + "engines": { + "node": ">=4.0" + } + }, + "node_modules/xmldom": { + "version": "0.1.31", + "resolved": "https://registry.npmjs.org/xmldom/-/xmldom-0.1.31.tgz", + "integrity": "sha512-yS2uJflVQs6n+CyjHoaBmVSqIDevTAWrzMmjG1Gc7h1qQ7uVozNhEPJAwZXWyGQ/Gafo3fCwrcaokezLPupVyQ==", + "deprecated": "Deprecated due to CVE-2021-21366 resolved in 0.5.0", + "engines": { + "node": ">=0.1" + } + }, + "node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" + } + }, + "dependencies": { + "@types/command-line-args": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/@types/command-line-args/-/command-line-args-5.0.0.tgz", + "integrity": "sha512-4eOPXyn5DmP64MCMF8ePDvdlvlzt2a+F8ZaVjqmh2yFCpGjc1kI3kGnCFYX9SCsGTjQcWIyVZ86IHCEyjy/MNg==", + "dev": true + }, + "@types/command-line-usage": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/@types/command-line-usage/-/command-line-usage-5.0.1.tgz", + "integrity": "sha512-/xUgezxxYePeXhg5S04hUjxG9JZi+rJTs1+4NwpYPfSaS7BeDa6tVJkH6lN9Cb6rl8d24Fi2uX0s0Ngg2JT6gg==", + "dev": true + }, + "@types/glob": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/@types/glob/-/glob-8.1.0.tgz", + "integrity": "sha512-IO+MJPVhoqz+28h1qLAcBEH2+xHMK6MTyHJc7MTnnYb6wsoLR29POVGJ7LycmVXIqyy/4/2ShP5sUwTXuOwb/w==", + "dev": true, + "requires": { + "@types/minimatch": "^5.1.2", + "@types/node": "*" + } + }, + "@types/minimatch": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/@types/minimatch/-/minimatch-5.1.2.tgz", + "integrity": "sha512-K0VQKziLUWkVKiRVrx4a40iPaxTUefQmjtkQofBkYRcoaaL/8rhwDWww9qWbrgicNOgnpIsMxyNIUM4+n6dUIA==", + "dev": true + }, + "@types/node": { + "version": "14.14.7", + "resolved": "https://registry.npmjs.org/@types/node/-/node-14.14.7.tgz", + "integrity": "sha512-Zw1vhUSQZYw+7u5dAwNbIA9TuTotpzY/OF7sJM9FqPOF3SPjKnxrjoTktXDZgUjybf4cWVBP7O8wvKdSaGHweg==", + "dev": true + }, + "@types/prompts": { + "version": "2.0.9", + "resolved": "https://registry.npmjs.org/@types/prompts/-/prompts-2.0.9.tgz", + "integrity": "sha512-TORZP+FSjTYMWwKadftmqEn6bziN5RnfygehByGsjxoK5ydnClddtv6GikGWPvCm24oI+YBwck5WDxIIyNxUrA==", + "dev": true, + "requires": { + "@types/node": "*" + } + }, + "@types/semver": { + "version": "7.5.0", + "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.5.0.tgz", + "integrity": "sha512-G8hZ6XJiHnuhQKR7ZmysCeJWE08o8T0AXtk5darsCaTVsYZhhgUrq53jizaR2FvsoeCwJhlmwTjkXBY5Pn/ZHw==", + "dev": true + }, + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "requires": { + "color-convert": "^1.9.0" + } + }, + "array-back": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/array-back/-/array-back-3.1.0.tgz", + "integrity": "sha512-TkuxA4UCOvxuDK6NZYXCalszEzj+TLszyASooky+i742l9TqsOdYCMJJupxRic61hwquNtppB3hgcuq9SVSH1Q==" + }, + "balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" + }, + "base64-js": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", + "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==" + }, + "big-integer": { + "version": "1.6.48", + "resolved": "https://registry.npmjs.org/big-integer/-/big-integer-1.6.48.tgz", + "integrity": "sha512-j51egjPa7/i+RdiRuJbPdJ2FIUYYPhvYLjzoYbcMMm62ooO6F94fETG4MTs46zPAF9Brs04OajboA/qTGuz78w==" + }, + "bplist-creator": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/bplist-creator/-/bplist-creator-0.0.8.tgz", + "integrity": "sha512-Za9JKzD6fjLC16oX2wsXfc+qBEhJBJB1YPInoAQpMLhDuj5aVOv1baGeIQSq1Fr3OCqzvsoQcSBSwGId/Ja2PA==", + "requires": { + "stream-buffers": "~2.2.0" + } + }, + "bplist-parser": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/bplist-parser/-/bplist-parser-0.2.0.tgz", + "integrity": "sha512-z0M+byMThzQmD9NILRniCUXYsYpjwnlO8N5uCFaCqIOpqRsJCrQL9NK3JsD67CN5a08nF5oIL2bD6loTdHOuKw==", + "requires": { + "big-integer": "^1.6.44" + } + }, + "brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "requires": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + }, + "color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "requires": { + "color-name": "1.1.3" + } + }, + "color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=" + }, + "command-line-args": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/command-line-args/-/command-line-args-5.1.1.tgz", + "integrity": "sha512-hL/eG8lrll1Qy1ezvkant+trihbGnaKaeEjj6Scyr3DN+RC7iQ5Rz84IeLERfAWDGo0HBSNAakczwgCilDXnWg==", + "requires": { + "array-back": "^3.0.1", + "find-replace": "^3.0.0", + "lodash.camelcase": "^4.3.0", + "typical": "^4.0.0" + } + }, + "command-line-usage": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/command-line-usage/-/command-line-usage-6.1.0.tgz", + "integrity": "sha512-Ew1clU4pkUeo6AFVDFxCbnN7GIZfXl48HIOQeFQnkO3oOqvpI7wdqtLRwv9iOCZ/7A+z4csVZeiDdEcj8g6Wiw==", + "requires": { + "array-back": "^4.0.0", + "chalk": "^2.4.2", + "table-layout": "^1.0.0", + "typical": "^5.2.0" + }, + "dependencies": { + "array-back": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/array-back/-/array-back-4.0.1.tgz", + "integrity": "sha512-Z/JnaVEXv+A9xabHzN43FiiiWEE7gPCRXMrVmRm00tWbjZRul1iHm7ECzlyNq1p4a4ATXz+G9FJ3GqGOkOV3fg==" + }, + "typical": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/typical/-/typical-5.2.0.tgz", + "integrity": "sha512-dvdQgNDNJo+8B2uBQoqdb11eUCE1JQXhvjC/CZtgvZseVd5TYMXnq0+vuUemXbd/Se29cTaUuPX3YIc2xgbvIg==" + } + } + }, + "concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=" + }, + "consola": { + "version": "2.15.0", + "resolved": "https://registry.npmjs.org/consola/-/consola-2.15.0.tgz", + "integrity": "sha512-vlcSGgdYS26mPf7qNi+dCisbhiyDnrN1zaRbw3CSuc2wGOMEGGPsp46PdRG5gqXwgtJfjxDkxRNAgRPr1B77vQ==" + }, + "deep-extend": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", + "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==" + }, + "detect-indent": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/detect-indent/-/detect-indent-6.1.0.tgz", + "integrity": "sha512-reYkTUJAZb9gUuZ2RvVCNhVHdg62RHnJ7WJl8ftMi4diZ6NWlciOzQN88pUhSELEwflJht4oQDv0F0BMlwaYtA==" + }, + "escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=" + }, + "find-replace": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/find-replace/-/find-replace-3.0.0.tgz", + "integrity": "sha512-6Tb2myMioCAgv5kfvP5/PkZZ/ntTpVK39fHY7WkWBgvbeE+VHd/tZuZ4mrC+bxh4cfOZeYKVPaJIZtZXV7GNCQ==", + "requires": { + "array-back": "^3.0.1" + } + }, + "fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=" + }, + "glob": { + "version": "7.1.6", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", + "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==", + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, + "has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=" + }, + "inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", + "requires": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" + }, + "kleur": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/kleur/-/kleur-3.0.3.tgz", + "integrity": "sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==" + }, + "lodash.camelcase": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz", + "integrity": "sha1-soqmKIorn8ZRA1x3EfZathkDMaY=" + }, + "lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "requires": { + "yallist": "^4.0.0" + } + }, + "minimatch": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", + "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "requires": { + "brace-expansion": "^1.1.7" + } + }, + "once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "requires": { + "wrappy": "1" + } + }, + "path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=" + }, + "plist": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/plist/-/plist-3.0.1.tgz", + "integrity": "sha512-GpgvHHocGRyQm74b6FWEZZVRroHKE1I0/BTjAmySaohK+cUn+hZpbqXkc3KWgW3gQYkqcQej35FohcT0FRlkRQ==", + "requires": { + "base64-js": "^1.2.3", + "xmlbuilder": "^9.0.7", + "xmldom": "0.1.x" + } + }, + "prompts": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/prompts/-/prompts-2.4.0.tgz", + "integrity": "sha512-awZAKrk3vN6CroQukBL+R9051a4R3zCZBlJm/HBfrSZ8iTpYix3VX1vU4mveiLpiwmOJT4wokTF9m6HUk4KqWQ==", + "requires": { + "kleur": "^3.0.3", + "sisteransi": "^1.0.5" + } + }, + "reduce-flatten": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/reduce-flatten/-/reduce-flatten-2.0.0.tgz", + "integrity": "sha512-EJ4UNY/U1t2P/2k6oqotuX2Cc3T6nxJwsM0N0asT7dhrtH1ltUxDn4NalSYmPE2rCkVpcf/X6R0wDwcFpzhd4w==" + }, + "semver": { + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", + "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", + "requires": { + "lru-cache": "^6.0.0" + } + }, + "simple-plist": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/simple-plist/-/simple-plist-1.1.1.tgz", + "integrity": "sha512-pKMCVKvZbZTsqYR6RKgLfBHkh2cV89GXcA/0CVPje3sOiNOnXA8+rp/ciAMZ7JRaUdLzlEM6JFfUn+fS6Nt3hg==", + "requires": { + "bplist-creator": "0.0.8", + "bplist-parser": "0.2.0", + "plist": "^3.0.1" + } + }, + "sisteransi": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/sisteransi/-/sisteransi-1.0.5.tgz", + "integrity": "sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==" + }, + "stream-buffers": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/stream-buffers/-/stream-buffers-2.2.0.tgz", + "integrity": "sha1-kdX1Ew0c75bc+n9yaUUYh0HQnuQ=" + }, + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "requires": { + "has-flag": "^3.0.0" + } + }, + "table-layout": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/table-layout/-/table-layout-1.0.1.tgz", + "integrity": "sha512-dEquqYNJiGwY7iPfZ3wbXDI944iqanTSchrACLL2nOB+1r+h1Nzu2eH+DuPPvWvm5Ry7iAPeFlgEtP5bIp5U7Q==", + "requires": { + "array-back": "^4.0.1", + "deep-extend": "~0.6.0", + "typical": "^5.2.0", + "wordwrapjs": "^4.0.0" + }, + "dependencies": { + "array-back": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/array-back/-/array-back-4.0.1.tgz", + "integrity": "sha512-Z/JnaVEXv+A9xabHzN43FiiiWEE7gPCRXMrVmRm00tWbjZRul1iHm7ECzlyNq1p4a4ATXz+G9FJ3GqGOkOV3fg==" + }, + "typical": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/typical/-/typical-5.2.0.tgz", + "integrity": "sha512-dvdQgNDNJo+8B2uBQoqdb11eUCE1JQXhvjC/CZtgvZseVd5TYMXnq0+vuUemXbd/Se29cTaUuPX3YIc2xgbvIg==" + } + } + }, + "typescript": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.1.3.tgz", + "integrity": "sha512-B3ZIOf1IKeH2ixgHhj6la6xdwR9QrLC5d1VKeCSY4tvkqhF2eqd9O7txNlS0PO3GrBAFIdr3L1ndNwteUbZLYg==", + "dev": true + }, + "typical": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/typical/-/typical-4.0.0.tgz", + "integrity": "sha512-VAH4IvQ7BDFYglMd7BPRDfLgxZZX4O4TFcRDA6EN5X7erNJJq+McIEp8np9aVtxrCJ6qx4GTYVfOWNjcqwZgRw==" + }, + "uuid": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-7.0.3.tgz", + "integrity": "sha512-DPSke0pXhTZgoF/d+WSt2QaKMCFSfx7QegxEWT+JOuHF5aWrKEn0G+ztjuJg/gG8/ItK+rbPCD/yNv8yyih6Cg==" + }, + "wordwrapjs": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/wordwrapjs/-/wordwrapjs-4.0.0.tgz", + "integrity": "sha512-Svqw723a3R34KvsMgpjFBYCgNOSdcW3mQFK4wIfhGQhtaFVOJmdYoXgi63ne3dTlWgatVcUc7t4HtQ/+bUVIzQ==", + "requires": { + "reduce-flatten": "^2.0.0", + "typical": "^5.0.0" + }, + "dependencies": { + "typical": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/typical/-/typical-5.2.0.tgz", + "integrity": "sha512-dvdQgNDNJo+8B2uBQoqdb11eUCE1JQXhvjC/CZtgvZseVd5TYMXnq0+vuUemXbd/Se29cTaUuPX3YIc2xgbvIg==" + } + } + }, + "wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" + }, + "xcode": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/xcode/-/xcode-3.0.1.tgz", + "integrity": "sha512-kCz5k7J7XbJtjABOvkc5lJmkiDh8VhjVCGNiqdKCscmVpdVUpEAyXv1xmCLkQJ5dsHqx3IPO4XW+NTDhU/fatA==", + "requires": { + "simple-plist": "^1.1.0", + "uuid": "^7.0.3" + } + }, + "xmlbuilder": { + "version": "9.0.7", + "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-9.0.7.tgz", + "integrity": "sha1-Ey7mPS7FVlxVfiD0wi35rKaGsQ0=" + }, + "xmldom": { + "version": "0.1.31", + "resolved": "https://registry.npmjs.org/xmldom/-/xmldom-0.1.31.tgz", + "integrity": "sha512-yS2uJflVQs6n+CyjHoaBmVSqIDevTAWrzMmjG1Gc7h1qQ7uVozNhEPJAwZXWyGQ/Gafo3fCwrcaokezLPupVyQ==" + }, + "yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" + } + } } diff --git a/packages/react-native-cli/package.json b/packages/react-native-cli/package.json index e5a66c5462..74ffff63d7 100644 --- a/packages/react-native-cli/package.json +++ b/packages/react-native-cli/package.json @@ -23,15 +23,19 @@ "command-line-args": "^5.1.1", "command-line-usage": "^6.1.0", "consola": "^2.15.0", + "detect-indent": "^6.1.0", "glob": "^7.1.6", "plist": "^3.0.1", "prompts": "^2.4.0", + "semver": "^7.5.4", "xcode": "^3.0.1" }, "devDependencies": { "@types/command-line-args": "^5.0.0", "@types/command-line-usage": "^5.0.1", + "@types/glob": "^8.1.0", "@types/prompts": "^2.0.9", + "@types/semver": "^7.5.0", "typescript": "^4.1.3" } } diff --git a/packages/react-native-cli/src/commands/AutomateSymbolicationCommand.ts b/packages/react-native-cli/src/commands/AutomateSymbolicationCommand.ts index d2a63b7abd..3895accf66 100644 --- a/packages/react-native-cli/src/commands/AutomateSymbolicationCommand.ts +++ b/packages/react-native-cli/src/commands/AutomateSymbolicationCommand.ts @@ -1,10 +1,14 @@ import prompts from 'prompts' +import { promises as fs } from 'fs' +import { join } from 'path' import logger from '../Logger' import { updateXcodeProject } from '../lib/Xcode' -import { install, detectInstalled, guessPackageManager } from '../lib/Npm' +import { install, detectInstalledVersion, detectInstalled, guessPackageManager } from '../lib/Npm' import onCancel from '../lib/OnCancel' -import { enableReactNativeMappings } from '../lib/Gradle' +import { checkReactNativeMappings, addUploadEndpoint, addBuildEndpoint } from '../lib/Gradle' import { UrlType, OnPremiseUrls } from '../lib/OnPremise' +import detectIndent from 'detect-indent' +import semver from 'semver' const DSYM_INSTRUCTIONS = `To configure your project to upload dSYMs, follow the iOS symbolication guide: @@ -14,6 +18,20 @@ const DSYM_INSTRUCTIONS = `To configure your project to upload dSYMs, follow the ` +const HERMES_INSTRUCTIONS = `You are running a version of React Native that we cannot automatically integrate with due to known issues with the build when Hermes is enabled. + + If you cannot upgrade to a later version of React Native (version 0.68 or above), you can use an older version of this CLI (version 7.20.x or earlier) + + or follow the manual integration instructions in our online docs: https://docs.bugsnag.com/platforms/react-native/react-native/manual-setup/') + +` + +const BUGSNAG_CLI_INSTRUCTIONS = `bugsnag:upload-android task added to your package.json - run this task to upload Android source maps after a build. + + See https://docs.bugsnag.com/platforms/react-native/react-native/showing-full-stacktraces for details. + +` + export default async function run (projectRoot: string, urls: OnPremiseUrls): Promise { try { const { iosIntegration } = await prompts({ @@ -38,17 +56,48 @@ export default async function run (projectRoot: string, urls: OnPremiseUrls): Pr const { androidIntegration } = await prompts({ type: 'confirm', name: 'androidIntegration', - message: 'Do you want to automatically upload JavaScript source maps as part of the Gradle build?', + message: 'Do you want to install the BugSnag CLI to allow you to upload JavaScript source maps?', initial: true }, { onCancel }) - if (androidIntegration) { - await enableReactNativeMappings(projectRoot, urls[UrlType.UPLOAD], urls[UrlType.BUILD], logger) + if (iosIntegration) { + await installJavaScriptPackage(projectRoot) } - if (androidIntegration || iosIntegration) { - await installJavaScriptPackage(projectRoot) + if (androidIntegration) { + await installBugsnagCliPackage(projectRoot, urls) + const reactNativeVersion = await detectInstalledVersion('react-native', projectRoot) + + if (reactNativeVersion) { + if (semver.lt(reactNativeVersion, '0.68.0')) { + await prompts({ + type: 'text', + name: 'hermesInstructions', + message: HERMES_INSTRUCTIONS, + initial: 'Hit enter to continue …' + }, { onCancel }) + } + } + + const { packageJsonIntegration } = await prompts({ + type: 'confirm', + name: 'packageJsonIntegration', + message: 'Do you want to add an NPM task to your package.json that you can run to upload Android source maps?', + initial: true + }, { onCancel }) + + if (packageJsonIntegration) { + await writeToPackageJson(join(projectRoot, 'package.json'), urls[UrlType.UPLOAD], urls[UrlType.BUILD]) + } + + await prompts({ + type: 'text', + name: 'bugsnagCliInstructions', + message: BUGSNAG_CLI_INSTRUCTIONS, + initial: 'Hit enter to continue …' + }, { onCancel }) } + return true } catch (e) { logger.error(e) @@ -56,6 +105,40 @@ export default async function run (projectRoot: string, urls: OnPremiseUrls): Pr } } +async function installBugsnagCliPackage (projectRoot: string, urls: OnPremiseUrls): Promise { + await checkReactNativeMappings(projectRoot, logger) + + if (urls[UrlType.BUILD]) { + await addBuildEndpoint(projectRoot, urls[UrlType.BUILD] as string, logger) + } + + if (urls[UrlType.UPLOAD]) { + await addUploadEndpoint(projectRoot, urls[UrlType.UPLOAD] as string, logger) + } + + const alreadyInstalled = await detectInstalled('@bugsnag/cli', projectRoot) + + if (alreadyInstalled) { + logger.warn('@bugsnag/cli is already installed, skipping') + return + } + + logger.info('Adding @bugsnag/cli dependency') + + const packageManager = await guessPackageManager(projectRoot) + + const { version } = await prompts({ + type: 'text', + name: 'version', + message: 'If you want the latest version of @bugsnag/cli hit enter, otherwise type the version you want', + initial: 'latest' + }, { onCancel }) + + await install(packageManager, '@bugsnag/cli', version, true, projectRoot) + + logger.success('@bugsnag/cli dependency is installed') +} + async function installJavaScriptPackage (projectRoot: string): Promise { const alreadyInstalled = await detectInstalled('@bugsnag/source-maps', projectRoot) @@ -79,3 +162,36 @@ async function installJavaScriptPackage (projectRoot: string): Promise { logger.success('@bugsnag/source-maps dependency is installed') } + +async function writeToPackageJson (packageJsonPath: string, uploadUrl?: string, buildUrl?: string): Promise { + try { + const data = await fs.readFile(packageJsonPath, 'utf8') + const packageJson = JSON.parse(data) + + // Default to two spaces if indent cannot be detected + const existingIndent = detectIndent(data).indent || ' ' + + let uploadCommand = 'bugsnag-cli upload react-native-android' + let buildCommand = 'bugsnag-cli create-build' + + if (uploadUrl) { + uploadCommand += ` --upload-api-root-url=${uploadUrl}` + } + + if (buildUrl) { + buildCommand += ` --build-api-root-url=${buildUrl}` + } + + packageJson.scripts = { + ...packageJson.scripts, + 'bugsnag:create-build': buildCommand, + 'bugsnag:upload-android': uploadCommand + } + + const updatedPackageJson = JSON.stringify(packageJson, null, existingIndent) + + await fs.writeFile(packageJsonPath, updatedPackageJson, 'utf8') + } catch (err) { + console.error(`Error writing package.json: ${err}`) + } +} diff --git a/packages/react-native-cli/src/lib/Gradle.ts b/packages/react-native-cli/src/lib/Gradle.ts index 4fce6e413f..e96d8b4eaa 100644 --- a/packages/react-native-cli/src/lib/Gradle.ts +++ b/packages/react-native-cli/src/lib/Gradle.ts @@ -8,8 +8,8 @@ const GRADLE_PLUGIN_APPLY = 'apply plugin: "com.bugsnag.android.gradle"' const GRADLE_PLUGIN_APPLY_REGEX = /apply plugin: ["']com\.bugsnag\.android\.gradle["']/ const GRADLE_ANDROID_PLUGIN_REGEX = /classpath\(["']com.android.tools.build:gradle:[^0-9]*([^'"]+)["']\)/ const DOCS_LINK = 'https://docs.bugsnag.com/build-integrations/gradle/#installation' -const ENABLE_REACT_NATIVE_MAPPINGS = 'bugsnag {\n uploadReactNativeMappings = true\n}\n' -const ENABLE_REACT_NATIVE_MAPPINGS_REGEX = /^\s*bugsnag {[^}]*uploadReactNativeMappings[^}]*?}/m +const BUGSNAG_CONFIGURATION_BLOCK = 'bugsnag {\n}\n' +const BUGSNAG_CONFIGURATION_BLOCK_REGEX = /^\s*bugsnag {[^}]*?}/m const UPLOAD_ENDPOINT_REGEX = /^\s*bugsnag {[^}]*endpoint[^}]*?}/m const BUILD_ENDPOINT_REGEX = /^\s*bugsnag {[^}]*releasesEndpoint[^}]*?}/m @@ -30,6 +30,10 @@ export async function getSuggestedBugsnagGradleVersion (projectRoot: string, log } else if (major === 7) { return '7.+' } else { + const versionMatchResult = fileContents.match(/classpath\(["']com.android.tools.build:gradle["']\)/) + if (versionMatchResult) { + return '7.+' + } logger.warn(`Cannot determine an appropriate version of the Bugsnag Android Gradle plugin for use in this project. Please see ${DOCS_LINK} for information on Gradle and the Android Gradle Plugin (AGP) compatibility`) @@ -44,7 +48,7 @@ export async function modifyRootBuildGradle (projectRoot: string, pluginVersion: try { await insertValueAfterPattern( topLevelBuildGradlePath, - /[\r\n]\s*classpath\(["']com.android.tools.build:gradle:.+["']\)/, + [/[\r\n]\s*classpath\(["']com.android.tools.build:gradle:.+["']\)/, /[\r\n]\s*classpath\(["']com.android.tools.build:gradle["']\)/], GRADLE_PLUGIN_IMPORT(pluginVersion), GRADLE_PLUGIN_IMPORT_REGEX, logger @@ -81,7 +85,7 @@ export async function modifyAppBuildGradle (projectRoot: string, logger: Logger) try { await insertValueAfterPattern( appBuildGradlePath, - /^apply from: ["']\.\.\/\.\.\/node_modules\/react-native\/react\.gradle["']$/m, + [/^apply from: ["']\.\.\/\.\.\/node_modules\/react-native\/react\.gradle["']$/m, /^apply from: file\(["']..\/\.\.\/node_modules\/@react-native-community\/cli-platform-android\/native_modules\.gradle["']\); applyNativeModulesAppBuildGradle\(project\)$/m], GRADLE_PLUGIN_APPLY, GRADLE_PLUGIN_APPLY_REGEX, logger @@ -111,10 +115,8 @@ See ${DOCS_LINK} for more information` logger.success('Finished modifying android/app/build.gradle') } -export async function enableReactNativeMappings ( +export async function checkReactNativeMappings ( projectRoot: string, - uploadEndpoint: string|undefined, - buildEndpoint: string|undefined, logger: Logger ): Promise { logger.debug('Enabling Bugsnag Android Gradle plugin React Native mappings') @@ -123,75 +125,45 @@ export async function enableReactNativeMappings ( try { const fileContents = await fs.readFile(appBuildGradlePath, 'utf8') - // If the file contains a 'bugsnag' configuration section already, add the - // 'uploadReactNativeMappings' flag to it - if (/^\s*bugsnag {/m.test(fileContents)) { - await insertValueAfterPattern( - appBuildGradlePath, - /^\s*bugsnag {[^}]*?(?=})/m, - ' uploadReactNativeMappings = true\n', - ENABLE_REACT_NATIVE_MAPPINGS_REGEX, - logger - ) - } else { - // If the file doesn't contain bugsnag config already, add it now - await insertValueAfterPattern( - appBuildGradlePath, - /$/, - ENABLE_REACT_NATIVE_MAPPINGS, - ENABLE_REACT_NATIVE_MAPPINGS_REGEX, - logger - ) - } - } catch (e) { - if (e.message === 'Pattern not found') { - logger.warn( - `The gradle file was in an unexpected format and so couldn't be updated automatically. - -Enable React Native mappings to your app module's build.gradle: - -${ENABLE_REACT_NATIVE_MAPPINGS} - -See ${DOCS_LINK} for more information` - ) - - return - } - - if (e.code === 'ENOENT') { + if (/^\s*uploadReactNativeMappings\s*=\s*true/m.test(fileContents)) { logger.warn( - `A gradle file was not found at the expected location and so couldn't be updated automatically. - -Enable React Native mappings to your app module's build.gradle: + `The uploadReactNativeMappings option for the Bugsnag Gradle plugin is currently enabled in ${appBuildGradlePath}. -${ENABLE_REACT_NATIVE_MAPPINGS} +This is no longer required as mappings will be uploaded by the BugSnag CLI. -See ${DOCS_LINK} for more information` +Please remove this line or disable it in your builds to prevent duplicate uploads.` ) - - return } - - throw e - } - - if (uploadEndpoint) { - await addUploadEndpoint(appBuildGradlePath, uploadEndpoint, logger) - } - - if (buildEndpoint) { - await addBuildEndpoint(appBuildGradlePath, buildEndpoint, logger) + } catch (e) { + // No action required } +} - logger.success('React Native mappings enabled in android/app/build.gradle') +async function insertBugsnagConfigBlock ( + appBuildGradlePath: string, + logger: Logger +): Promise { + logger.debug('Inserting Bugsnag config block') + + await insertValueAfterPattern( + appBuildGradlePath, + [/$/], + BUGSNAG_CONFIGURATION_BLOCK, + BUGSNAG_CONFIGURATION_BLOCK_REGEX, + logger + ) + logger.success('Bugsnag config block inserted into android/app/build.gradle') } -async function addUploadEndpoint (appBuildGradlePath: string, uploadEndpoint: string, logger: Logger): Promise { +export async function addUploadEndpoint (projectRoot: string, uploadEndpoint: string, logger: Logger): Promise { try { - // We know the 'bugsnag' section must exist after enabling RN mappings + const appBuildGradlePath = path.join(projectRoot, 'android', 'app', 'build.gradle') + + await insertBugsnagConfigBlock(appBuildGradlePath, logger) + await insertValueAfterPattern( appBuildGradlePath, - /^\s*bugsnag {[^}]*?(?=})/m, + [/^\s*bugsnag {[^}]*?(?=})/m], ` endpoint = "${uploadEndpoint}"\n`, UPLOAD_ENDPOINT_REGEX, logger @@ -227,12 +199,15 @@ See ${DOCS_LINK} for more information` } } -async function addBuildEndpoint (appBuildGradlePath: string, buildEndpoint: string, logger: Logger): Promise { +export async function addBuildEndpoint (projectRoot: string, buildEndpoint: string, logger: Logger): Promise { try { - // We know the 'bugsnag' section must exist after enabling RN mappings + const appBuildGradlePath = path.join(projectRoot, 'android', 'app', 'build.gradle') + + await insertBugsnagConfigBlock(appBuildGradlePath, logger) + await insertValueAfterPattern( appBuildGradlePath, - /^\s*bugsnag {[^}]*?(?=})/m, + [/^\s*bugsnag {[^}]*?(?=})/m, /''/], ` releasesEndpoint = "${buildEndpoint}"\n`, BUILD_ENDPOINT_REGEX, logger @@ -268,7 +243,7 @@ See ${DOCS_LINK} for more information` } } -async function insertValueAfterPattern (file: string, pattern: RegExp, value: string, presencePattern: RegExp, logger: Logger): Promise { +async function insertValueAfterPattern (file: string, patterns: RegExp[], value: string, presencePattern: RegExp, logger: Logger): Promise { const fileContents = await fs.readFile(file, 'utf8') if (presencePattern.test(fileContents)) { @@ -276,7 +251,7 @@ async function insertValueAfterPattern (file: string, pattern: RegExp, value: st return } - const match = fileContents.match(pattern) + const match = patterns.map(search => fileContents.match(search)).find(m => !!m) if (!match || match.index === undefined || !match.input) { throw new Error('Pattern not found') } diff --git a/packages/react-native-cli/src/lib/Npm.ts b/packages/react-native-cli/src/lib/Npm.ts index c0ef1befba..23dcf12f07 100644 --- a/packages/react-native-cli/src/lib/Npm.ts +++ b/packages/react-native-cli/src/lib/Npm.ts @@ -44,6 +44,28 @@ const npmCommand = (module: string, version: string, dev: boolean): Command => [ !dev ? ['install', '--save', `${module}@${version}`] : ['install', '--save-dev', `${module}@${version}`] ] +export async function detectInstalledVersion (module: string, projectRoot: string): Promise { + try { + const pkg = JSON.parse(await fs.readFile(join(projectRoot, 'package.json'), 'utf8')) + + if (pkg.dependencies && pkg.dependencies[module]) { + return pkg.dependencies[module] + } + + if (pkg.devDependencies && pkg.devDependencies[module]) { + return pkg.devDependencies[module] + } + + if (pkg.peerDependencies && pkg.peerDependencies[module]) { + return pkg.peerDependencies[module] + } + + return undefined + } catch (e) { + throw new Error('Could not load package.json. Is this the project root?') + } +} + export async function detectInstalled (module: string, projectRoot: string): Promise { try { const pkg = JSON.parse(await fs.readFile(join(projectRoot, 'package.json'), 'utf8')) diff --git a/packages/react-native-cli/src/lib/__test__/Gradle.test.ts b/packages/react-native-cli/src/lib/__test__/Gradle.test.ts index 6b6c3d03c4..e6092f17b7 100644 --- a/packages/react-native-cli/src/lib/__test__/Gradle.test.ts +++ b/packages/react-native-cli/src/lib/__test__/Gradle.test.ts @@ -1,4 +1,4 @@ -import { getSuggestedBugsnagGradleVersion, modifyAppBuildGradle, modifyRootBuildGradle, enableReactNativeMappings } from '../Gradle' +import { getSuggestedBugsnagGradleVersion, modifyAppBuildGradle, modifyRootBuildGradle, checkReactNativeMappings, addUploadEndpoint, addBuildEndpoint } from '../Gradle' import logger from '../../Logger' import path from 'path' import { promises as fs } from 'fs' @@ -152,9 +152,9 @@ test('modifyAppBuildGradle(): passes on unknown errors', async () => { await expect(modifyAppBuildGradle('/random/path', logger)).rejects.toThrowError('Unknown error') }) -test('enableReactNativeMappings(): success without initial bugsnag config', async () => { +test('checkReactNativeMappings(): success without initial bugsnag config', async () => { const buildGradle = await loadFixture(path.join(__dirname, 'fixtures', 'app-build-before.gradle')) - const expected = await loadFixture(path.join(__dirname, 'fixtures', 'app-build-after-with-mappings.gradle')) + const expected = await loadFixture(path.join(__dirname, 'fixtures', 'app-build-after-with-no-mappings.gradle')) const readFileMock = fs.readFile as jest.MockedFunction readFileMock.mockResolvedValue(buildGradle) @@ -166,13 +166,14 @@ test('enableReactNativeMappings(): success without initial bugsnag config', asyn expect(encoding).toBe('utf8') }) - await enableReactNativeMappings('/random/path', undefined, undefined, logger) + await checkReactNativeMappings('/random/path', logger) expect(readFileMock).toHaveBeenCalledWith('/random/path/android/app/build.gradle', 'utf8') - expect(writeFileMock).toHaveBeenCalledWith('/random/path/android/app/build.gradle', expected, 'utf8') + expect(writeFileMock).not.toHaveBeenCalled() + expect(buildGradle).toStrictEqual(expected) }) -test('enableReactNativeMappings(): success with initial bugsnag config', async () => { +test('checkReactNativeMappings(): success with initial bugsnag config', async () => { const buildGradle = await loadFixture(path.join(__dirname, 'fixtures', 'app-build-before-with-bugsnag-config.gradle')) const expected = await loadFixture(path.join(__dirname, 'fixtures', 'app-build-after-with-mappings-and-bugsnag-config.gradle')) @@ -180,19 +181,21 @@ test('enableReactNativeMappings(): success with initial bugsnag config', async ( readFileMock.mockResolvedValue(buildGradle) const writeFileMock = fs.writeFile as jest.MockedFunction + writeFileMock.mockImplementation((file, contents, encoding) => { expect(file).toBe('/random/path/android/app/build.gradle') expect(contents).toBe(expected) expect(encoding).toBe('utf8') }) - await enableReactNativeMappings('/random/path', undefined, undefined, logger) + await checkReactNativeMappings('/random/path', logger) expect(readFileMock).toHaveBeenCalledWith('/random/path/android/app/build.gradle', 'utf8') - expect(writeFileMock).toHaveBeenCalledWith('/random/path/android/app/build.gradle', expected, 'utf8') + expect(writeFileMock).not.toHaveBeenCalled() + expect(buildGradle).toStrictEqual(expected) }) -test('enableReactNativeMappings(): success with empty initial bugsnag config', async () => { +test('checkReactNativeMappings(): success with empty initial bugsnag config', async () => { const buildGradle = await loadFixture(path.join(__dirname, 'fixtures', 'app-build-before-with-empty-bugsnag-config.gradle')) const expected = await loadFixture(path.join(__dirname, 'fixtures', 'app-build-after-with-mappings-and-empty-bugsnag-config.gradle')) @@ -206,13 +209,14 @@ test('enableReactNativeMappings(): success with empty initial bugsnag config', a expect(encoding).toBe('utf8') }) - await enableReactNativeMappings('/random/path', undefined, undefined, logger) + await checkReactNativeMappings('/random/path', logger) expect(readFileMock).toHaveBeenCalledWith('/random/path/android/app/build.gradle', 'utf8') - expect(writeFileMock).toHaveBeenCalledWith('/random/path/android/app/build.gradle', expected, 'utf8') + expect(writeFileMock).not.toHaveBeenCalled() + expect(buildGradle).toStrictEqual(expected) }) -test('enableReactNativeMappings(): failure mappings already enabled', async () => { +test('checkReactNativeMappings(): failure mappings already enabled', async () => { const buildGradle = await loadFixture(path.join(__dirname, 'fixtures', 'app-build-before-with-mappings.gradle')) const expected = buildGradle @@ -226,61 +230,27 @@ test('enableReactNativeMappings(): failure mappings already enabled', async () = expect(encoding).toBe('utf8') }) - await enableReactNativeMappings('/random/path', undefined, undefined, logger) + await checkReactNativeMappings('/random/path', logger) expect(readFileMock).toHaveBeenCalledWith('/random/path/android/app/build.gradle', 'utf8') expect(writeFileMock).not.toHaveBeenCalled() - expect(logger.warn).toHaveBeenCalledWith('Value already found in file, skipping.') }) -test('enableReactNativeMappings(): failure gradle file not found', async () => { +test('checkReactNativeMappings(): failure gradle file not found', async () => { const readFileMock = fs.readFile as jest.MockedFunction readFileMock.mockRejectedValue(await generateNotFoundError()) const writeFileMock = fs.writeFile as jest.MockedFunction writeFileMock.mockResolvedValue() - await enableReactNativeMappings('/random/path', undefined, undefined, logger) - - expect(readFileMock).toHaveBeenCalledWith('/random/path/android/app/build.gradle', 'utf8') - expect(writeFileMock).not.toHaveBeenCalled() - expect(logger.warn).toHaveBeenCalledWith(expect.stringContaining( - "A gradle file was not found at the expected location and so couldn't be updated automatically." - )) -}) - -test('enableReactNativeMappings(): failure pattern not found', async () => { - const readFileMock = fs.readFile as jest.MockedFunction - readFileMock.mockRejectedValue(new Error('Pattern not found')) - - const writeFileMock = fs.writeFile as jest.MockedFunction - writeFileMock.mockResolvedValue() - - await enableReactNativeMappings('/random/path', undefined, undefined, logger) - - expect(readFileMock).toHaveBeenCalledWith('/random/path/android/app/build.gradle', 'utf8') - expect(writeFileMock).not.toHaveBeenCalled() - expect(logger.warn).toHaveBeenCalledWith(expect.stringContaining( - "The gradle file was in an unexpected format and so couldn't be updated automatically." - )) -}) - -test('enableReactNativeMappings(): failure unexpected error', async () => { - const error = new Error('oops!') - - const readFileMock = fs.readFile as jest.MockedFunction - readFileMock.mockRejectedValue(error) - - const writeFileMock = fs.writeFile as jest.MockedFunction - writeFileMock.mockResolvedValue() - - await expect(enableReactNativeMappings('/random/path', undefined, undefined, logger)).rejects.toThrow(error) + await checkReactNativeMappings('/random/path', logger) expect(readFileMock).toHaveBeenCalledWith('/random/path/android/app/build.gradle', 'utf8') expect(writeFileMock).not.toHaveBeenCalled() + expect(logger.warn).not.toHaveBeenCalled() }) -test('enableReactNativeMappings(): success without initial bugsnag config and custom upload endpoint', async () => { +test('addUploadEndpoint(): success without initial bugsnag config and custom upload endpoint', async () => { const buildGradle = await loadFixture(path.join(__dirname, 'fixtures', 'app-build-before.gradle')) const expectedMappings = await loadFixture(path.join(__dirname, 'fixtures', 'app-build-after-with-mappings.gradle')) const expectedUploadEndpoint = await loadFixture(path.join(__dirname, 'fixtures', 'app-build-after-with-mappings-and-upload-endpoint.gradle')) @@ -302,7 +272,8 @@ test('enableReactNativeMappings(): success without initial bugsnag config and cu expect(encoding).toBe('utf8') }) - await enableReactNativeMappings('/random/path', 'https://upload.example.com', undefined, logger) + await checkReactNativeMappings('/random/path', logger) + await addUploadEndpoint('/random/path', 'https://upload.example.com', logger) expect(readFileMock).toHaveBeenNthCalledWith(1, '/random/path/android/app/build.gradle', 'utf8') expect(readFileMock).toHaveBeenNthCalledWith(2, '/random/path/android/app/build.gradle', 'utf8') @@ -311,7 +282,7 @@ test('enableReactNativeMappings(): success without initial bugsnag config and cu expect(writeFileMock).toHaveBeenNthCalledWith(2, '/random/path/android/app/build.gradle', expectedUploadEndpoint, 'utf8') }) -test('enableReactNativeMappings(): success with initial bugsnag config and custom upload endpoint', async () => { +test('addUploadEndpoint(): success with initial bugsnag config and custom upload endpoint', async () => { const buildGradle = await loadFixture(path.join(__dirname, 'fixtures', 'app-build-before-with-bugsnag-config.gradle')) const expectedMappings = await loadFixture(path.join(__dirname, 'fixtures', 'app-build-after-with-mappings-and-bugsnag-config.gradle')) const expectedUploadEndpoint = await loadFixture(path.join(__dirname, 'fixtures', 'app-build-after-with-mappings-upload-endpoint-and-bugsnag-config.gradle')) @@ -333,16 +304,17 @@ test('enableReactNativeMappings(): success with initial bugsnag config and custo expect(encoding).toBe('utf8') }) - await enableReactNativeMappings('/random/path', 'https://upload.example.com', undefined, logger) + await addUploadEndpoint('/random/path', 'https://upload.example.com', logger) expect(readFileMock).toHaveBeenNthCalledWith(1, '/random/path/android/app/build.gradle', 'utf8') expect(readFileMock).toHaveBeenNthCalledWith(2, '/random/path/android/app/build.gradle', 'utf8') - expect(writeFileMock).toHaveBeenNthCalledWith(1, '/random/path/android/app/build.gradle', expectedMappings, 'utf8') - expect(writeFileMock).toHaveBeenNthCalledWith(2, '/random/path/android/app/build.gradle', expectedUploadEndpoint, 'utf8') + expect(writeFileMock).not.toHaveBeenCalled() + expect(buildGradle).toStrictEqual(expectedMappings) + expect(buildGradle).toStrictEqual(expectedUploadEndpoint) }) -test('enableReactNativeMappings(): success with initial bugsnag config and custom build endpoint', async () => { +test('addBuildEndpoint(): success with initial bugsnag config and custom build endpoint', async () => { const buildGradle = await loadFixture(path.join(__dirname, 'fixtures', 'app-build-before-with-bugsnag-config.gradle')) const expectedMappings = await loadFixture(path.join(__dirname, 'fixtures', 'app-build-after-with-mappings-and-bugsnag-config.gradle')) const expectedBuildEndpoint = await loadFixture(path.join(__dirname, 'fixtures', 'app-build-after-with-mappings-build-endpoint-and-bugsnag-config.gradle')) @@ -364,18 +336,19 @@ test('enableReactNativeMappings(): success with initial bugsnag config and custo expect(encoding).toBe('utf8') }) - await enableReactNativeMappings('/random/path', undefined, 'https://build.example.com', logger) + await addBuildEndpoint('/random/path', 'https://build.example.com', logger) expect(readFileMock).toHaveBeenNthCalledWith(1, '/random/path/android/app/build.gradle', 'utf8') expect(readFileMock).toHaveBeenNthCalledWith(2, '/random/path/android/app/build.gradle', 'utf8') - expect(writeFileMock).toHaveBeenNthCalledWith(1, '/random/path/android/app/build.gradle', expectedMappings, 'utf8') - expect(writeFileMock).toHaveBeenNthCalledWith(2, '/random/path/android/app/build.gradle', expectedBuildEndpoint, 'utf8') + expect(writeFileMock).not.toHaveBeenCalled() + expect(buildGradle).toStrictEqual(expectedMappings) + expect(buildGradle).toStrictEqual(expectedBuildEndpoint) }) -test('enableReactNativeMappings(): success with empty initial bugsnag config and custom upload endpoint', async () => { +test('addUploadEndpoint(): success with empty initial bugsnag config and custom upload endpoint', async () => { const buildGradle = await loadFixture(path.join(__dirname, 'fixtures', 'app-build-before-with-empty-bugsnag-config.gradle')) - const expectedMappings = await loadFixture(path.join(__dirname, 'fixtures', 'app-build-after-with-mappings-and-empty-bugsnag-config.gradle')) + const expectedMappings = await loadFixture(path.join(__dirname, 'fixtures', 'app-build-after-with-mappings-upload-endpoint-and-empty-bugsnag-config.gradle')) const expectedUploadEndpoint = await loadFixture(path.join(__dirname, 'fixtures', 'app-build-after-with-mappings-upload-endpoint-and-empty-bugsnag-config.gradle')) const readFileMock = fs.readFile as jest.MockedFunction @@ -395,18 +368,18 @@ test('enableReactNativeMappings(): success with empty initial bugsnag config and expect(encoding).toBe('utf8') }) - await enableReactNativeMappings('/random/path', 'https://upload.example.com', undefined, logger) + await addUploadEndpoint('/random/path', 'https://upload.example.com', logger) expect(readFileMock).toHaveBeenNthCalledWith(1, '/random/path/android/app/build.gradle', 'utf8') expect(readFileMock).toHaveBeenNthCalledWith(2, '/random/path/android/app/build.gradle', 'utf8') expect(writeFileMock).toHaveBeenNthCalledWith(1, '/random/path/android/app/build.gradle', expectedMappings, 'utf8') - expect(writeFileMock).toHaveBeenNthCalledWith(2, '/random/path/android/app/build.gradle', expectedUploadEndpoint, 'utf8') + expect(writeFileMock).toHaveBeenNthCalledWith(1, '/random/path/android/app/build.gradle', expectedUploadEndpoint, 'utf8') }) -test('enableReactNativeMappings(): success with empty initial bugsnag config and custom build endpoint', async () => { +test('addBuildEndpoint(): success with empty initial bugsnag config and custom build endpoint', async () => { const buildGradle = await loadFixture(path.join(__dirname, 'fixtures', 'app-build-before-with-empty-bugsnag-config.gradle')) - const expectedMappings = await loadFixture(path.join(__dirname, 'fixtures', 'app-build-after-with-mappings-and-empty-bugsnag-config.gradle')) + const expectedMappings = await loadFixture(path.join(__dirname, 'fixtures', 'app-build-after-with-mappings-build-endpoint-and-empty-bugsnag-config.gradle')) const expectedBuildEndpoint = await loadFixture(path.join(__dirname, 'fixtures', 'app-build-after-with-mappings-build-endpoint-and-empty-bugsnag-config.gradle')) const readFileMock = fs.readFile as jest.MockedFunction @@ -426,16 +399,16 @@ test('enableReactNativeMappings(): success with empty initial bugsnag config and expect(encoding).toBe('utf8') }) - await enableReactNativeMappings('/random/path', undefined, 'https://build.example.com', logger) + await addBuildEndpoint('/random/path', 'https://build.example.com', logger) expect(readFileMock).toHaveBeenNthCalledWith(1, '/random/path/android/app/build.gradle', 'utf8') expect(readFileMock).toHaveBeenNthCalledWith(2, '/random/path/android/app/build.gradle', 'utf8') expect(writeFileMock).toHaveBeenNthCalledWith(1, '/random/path/android/app/build.gradle', expectedMappings, 'utf8') - expect(writeFileMock).toHaveBeenNthCalledWith(2, '/random/path/android/app/build.gradle', expectedBuildEndpoint, 'utf8') + expect(writeFileMock).toHaveBeenNthCalledWith(1, '/random/path/android/app/build.gradle', expectedBuildEndpoint, 'utf8') }) -test('enableReactNativeMappings(): success with initial bugsnag config and custom endpoints', async () => { +test('addUploadEndpoint() and addBuildEndpoint(): success with initial bugsnag config and custom endpoints', async () => { const buildGradle = await loadFixture(path.join(__dirname, 'fixtures', 'app-build-before-with-bugsnag-config.gradle')) const expectedMappings = await loadFixture(path.join(__dirname, 'fixtures', 'app-build-after-with-mappings-and-bugsnag-config.gradle')) const expectedUploadEndpoint = await loadFixture(path.join(__dirname, 'fixtures', 'app-build-after-with-mappings-upload-endpoint-and-bugsnag-config.gradle')) @@ -463,18 +436,20 @@ test('enableReactNativeMappings(): success with initial bugsnag config and custo expect(encoding).toBe('utf8') }) - await enableReactNativeMappings('/random/path', 'https://upload.example.com', 'https://build.example.com', logger) + await addUploadEndpoint('/random/path', 'https://upload.example.com', logger) + await addBuildEndpoint('/random/path', 'https://build.example.com', logger) expect(readFileMock).toHaveBeenNthCalledWith(1, '/random/path/android/app/build.gradle', 'utf8') expect(readFileMock).toHaveBeenNthCalledWith(2, '/random/path/android/app/build.gradle', 'utf8') expect(readFileMock).toHaveBeenNthCalledWith(3, '/random/path/android/app/build.gradle', 'utf8') - expect(writeFileMock).toHaveBeenNthCalledWith(1, '/random/path/android/app/build.gradle', expectedMappings, 'utf8') - expect(writeFileMock).toHaveBeenNthCalledWith(2, '/random/path/android/app/build.gradle', expectedUploadEndpoint, 'utf8') - expect(writeFileMock).toHaveBeenNthCalledWith(3, '/random/path/android/app/build.gradle', expectedFinal, 'utf8') + expect(writeFileMock).not.toHaveBeenCalled() + expect(buildGradle).toStrictEqual(expectedMappings) + expect(buildGradle).toStrictEqual(expectedUploadEndpoint) + expect(buildGradle).toStrictEqual(expectedFinal) }) -test('enableReactNativeMappings(): success without initial bugsnag config and custom endpoints', async () => { +test('addUploadEndpoint() and addBuildEndpoint(: success without initial bugsnag config and custom endpoints', async () => { const buildGradle = await loadFixture(path.join(__dirname, 'fixtures', 'app-build-before.gradle')) const expectedMappings = await loadFixture(path.join(__dirname, 'fixtures', 'app-build-after-with-mappings.gradle')) const expectedUploadEndpoint = await loadFixture(path.join(__dirname, 'fixtures', 'app-build-after-with-mappings-and-upload-endpoint.gradle')) @@ -492,25 +467,20 @@ test('enableReactNativeMappings(): success without initial bugsnag config and cu expect(file).toBe('/random/path/android/app/build.gradle') expect(contents).toBe(expectedMappings) expect(encoding).toBe('utf8') - }).mockImplementationOnce((file, contents, encoding) => { - expect(file).toBe('/random/path/android/app/build.gradle') - expect(contents).toBe(expectedUploadEndpoint) - expect(encoding).toBe('utf8') }).mockImplementationOnce((file, contents, encoding) => { expect(file).toBe('/random/path/android/app/build.gradle') expect(contents).toBe(expectedFinal) expect(encoding).toBe('utf8') }) - await enableReactNativeMappings('/random/path', 'https://upload.example.com', 'https://build.example.com', logger) + await addUploadEndpoint('/random/path', 'https://upload.example.com', logger) + await addBuildEndpoint('/random/path', 'https://build.example.com', logger) expect(readFileMock).toHaveBeenNthCalledWith(1, '/random/path/android/app/build.gradle', 'utf8') expect(readFileMock).toHaveBeenNthCalledWith(2, '/random/path/android/app/build.gradle', 'utf8') - expect(readFileMock).toHaveBeenNthCalledWith(3, '/random/path/android/app/build.gradle', 'utf8') expect(writeFileMock).toHaveBeenNthCalledWith(1, '/random/path/android/app/build.gradle', expectedMappings, 'utf8') - expect(writeFileMock).toHaveBeenNthCalledWith(2, '/random/path/android/app/build.gradle', expectedUploadEndpoint, 'utf8') - expect(writeFileMock).toHaveBeenNthCalledWith(3, '/random/path/android/app/build.gradle', expectedFinal, 'utf8') + expect(writeFileMock).toHaveBeenNthCalledWith(2, '/random/path/android/app/build.gradle', expectedFinal, 'utf8') }) test('getSuggestedBugsnagGradleVersion(): success', async () => { diff --git a/packages/react-native-cli/src/lib/__test__/fixtures/app-build-after-with-mappings-and-both-endpoints.gradle b/packages/react-native-cli/src/lib/__test__/fixtures/app-build-after-with-mappings-and-both-endpoints.gradle index a5154824fa..e115815166 100644 --- a/packages/react-native-cli/src/lib/__test__/fixtures/app-build-after-with-mappings-and-both-endpoints.gradle +++ b/packages/react-native-cli/src/lib/__test__/fixtures/app-build-after-with-mappings-and-both-endpoints.gradle @@ -219,7 +219,6 @@ task copyDownloadableDepsToLibs(type: Copy) { apply from: file("../../node_modules/@react-native-community/cli-platform-android/native_modules.gradle"); applyNativeModulesAppBuildGradle(project) bugsnag { - uploadReactNativeMappings = true endpoint = "https://upload.example.com" diff --git a/packages/react-native-cli/src/lib/__test__/fixtures/app-build-after-with-mappings-and-bugsnag-config.gradle b/packages/react-native-cli/src/lib/__test__/fixtures/app-build-after-with-mappings-and-bugsnag-config.gradle index ac4c457c95..4a04a4bc92 100644 --- a/packages/react-native-cli/src/lib/__test__/fixtures/app-build-after-with-mappings-and-bugsnag-config.gradle +++ b/packages/react-native-cli/src/lib/__test__/fixtures/app-build-after-with-mappings-and-bugsnag-config.gradle @@ -222,5 +222,7 @@ bugsnag { config = yes options = set to things - uploadReactNativeMappings = true + endpoint = "https://upload.example.com" + + releasesEndpoint = "https://build.example.com" } diff --git a/packages/react-native-cli/src/lib/__test__/fixtures/app-build-after-with-mappings-and-empty-bugsnag-config.gradle b/packages/react-native-cli/src/lib/__test__/fixtures/app-build-after-with-mappings-and-empty-bugsnag-config.gradle index 7d3d8f8b9e..959f528b86 100644 --- a/packages/react-native-cli/src/lib/__test__/fixtures/app-build-after-with-mappings-and-empty-bugsnag-config.gradle +++ b/packages/react-native-cli/src/lib/__test__/fixtures/app-build-after-with-mappings-and-empty-bugsnag-config.gradle @@ -219,6 +219,4 @@ task copyDownloadableDepsToLibs(type: Copy) { apply from: file("../../node_modules/@react-native-community/cli-platform-android/native_modules.gradle"); applyNativeModulesAppBuildGradle(project) bugsnag { - - uploadReactNativeMappings = true } diff --git a/packages/react-native-cli/src/lib/__test__/fixtures/app-build-after-with-mappings-and-upload-endpoint.gradle b/packages/react-native-cli/src/lib/__test__/fixtures/app-build-after-with-mappings-and-upload-endpoint.gradle index 0b2410a1e5..c723991ab4 100644 --- a/packages/react-native-cli/src/lib/__test__/fixtures/app-build-after-with-mappings-and-upload-endpoint.gradle +++ b/packages/react-native-cli/src/lib/__test__/fixtures/app-build-after-with-mappings-and-upload-endpoint.gradle @@ -219,7 +219,6 @@ task copyDownloadableDepsToLibs(type: Copy) { apply from: file("../../node_modules/@react-native-community/cli-platform-android/native_modules.gradle"); applyNativeModulesAppBuildGradle(project) bugsnag { - uploadReactNativeMappings = true endpoint = "https://upload.example.com" } diff --git a/packages/react-native-cli/src/lib/__test__/fixtures/app-build-after-with-mappings-both-endpoints-and-bugsnag-config.gradle b/packages/react-native-cli/src/lib/__test__/fixtures/app-build-after-with-mappings-both-endpoints-and-bugsnag-config.gradle index 1764b74ae1..4a04a4bc92 100644 --- a/packages/react-native-cli/src/lib/__test__/fixtures/app-build-after-with-mappings-both-endpoints-and-bugsnag-config.gradle +++ b/packages/react-native-cli/src/lib/__test__/fixtures/app-build-after-with-mappings-both-endpoints-and-bugsnag-config.gradle @@ -222,8 +222,6 @@ bugsnag { config = yes options = set to things - uploadReactNativeMappings = true - endpoint = "https://upload.example.com" releasesEndpoint = "https://build.example.com" diff --git a/packages/react-native-cli/src/lib/__test__/fixtures/app-build-after-with-mappings-build-endpoint-and-bugsnag-config.gradle b/packages/react-native-cli/src/lib/__test__/fixtures/app-build-after-with-mappings-build-endpoint-and-bugsnag-config.gradle index ea46301ca0..4a04a4bc92 100644 --- a/packages/react-native-cli/src/lib/__test__/fixtures/app-build-after-with-mappings-build-endpoint-and-bugsnag-config.gradle +++ b/packages/react-native-cli/src/lib/__test__/fixtures/app-build-after-with-mappings-build-endpoint-and-bugsnag-config.gradle @@ -222,7 +222,7 @@ bugsnag { config = yes options = set to things - uploadReactNativeMappings = true + endpoint = "https://upload.example.com" releasesEndpoint = "https://build.example.com" } diff --git a/packages/react-native-cli/src/lib/__test__/fixtures/app-build-after-with-mappings-build-endpoint-and-empty-bugsnag-config.gradle b/packages/react-native-cli/src/lib/__test__/fixtures/app-build-after-with-mappings-build-endpoint-and-empty-bugsnag-config.gradle index 9592eac5e3..f03d5f7bb1 100644 --- a/packages/react-native-cli/src/lib/__test__/fixtures/app-build-after-with-mappings-build-endpoint-and-empty-bugsnag-config.gradle +++ b/packages/react-native-cli/src/lib/__test__/fixtures/app-build-after-with-mappings-build-endpoint-and-empty-bugsnag-config.gradle @@ -220,7 +220,5 @@ apply from: file("../../node_modules/@react-native-community/cli-platform-androi bugsnag { - uploadReactNativeMappings = true - releasesEndpoint = "https://build.example.com" } diff --git a/packages/react-native-cli/src/lib/__test__/fixtures/app-build-after-with-mappings-upload-endpoint-and-bugsnag-config.gradle b/packages/react-native-cli/src/lib/__test__/fixtures/app-build-after-with-mappings-upload-endpoint-and-bugsnag-config.gradle index a429f7c1d5..4a04a4bc92 100644 --- a/packages/react-native-cli/src/lib/__test__/fixtures/app-build-after-with-mappings-upload-endpoint-and-bugsnag-config.gradle +++ b/packages/react-native-cli/src/lib/__test__/fixtures/app-build-after-with-mappings-upload-endpoint-and-bugsnag-config.gradle @@ -222,7 +222,7 @@ bugsnag { config = yes options = set to things - uploadReactNativeMappings = true - endpoint = "https://upload.example.com" + + releasesEndpoint = "https://build.example.com" } diff --git a/packages/react-native-cli/src/lib/__test__/fixtures/app-build-after-with-mappings-upload-endpoint-and-empty-bugsnag-config.gradle b/packages/react-native-cli/src/lib/__test__/fixtures/app-build-after-with-mappings-upload-endpoint-and-empty-bugsnag-config.gradle index aafbc63214..c723991ab4 100644 --- a/packages/react-native-cli/src/lib/__test__/fixtures/app-build-after-with-mappings-upload-endpoint-and-empty-bugsnag-config.gradle +++ b/packages/react-native-cli/src/lib/__test__/fixtures/app-build-after-with-mappings-upload-endpoint-and-empty-bugsnag-config.gradle @@ -220,7 +220,5 @@ apply from: file("../../node_modules/@react-native-community/cli-platform-androi bugsnag { - uploadReactNativeMappings = true - endpoint = "https://upload.example.com" } diff --git a/packages/react-native-cli/src/lib/__test__/fixtures/app-build-after-with-mappings.gradle b/packages/react-native-cli/src/lib/__test__/fixtures/app-build-after-with-mappings.gradle index b5487fbea4..959f528b86 100644 --- a/packages/react-native-cli/src/lib/__test__/fixtures/app-build-after-with-mappings.gradle +++ b/packages/react-native-cli/src/lib/__test__/fixtures/app-build-after-with-mappings.gradle @@ -219,5 +219,4 @@ task copyDownloadableDepsToLibs(type: Copy) { apply from: file("../../node_modules/@react-native-community/cli-platform-android/native_modules.gradle"); applyNativeModulesAppBuildGradle(project) bugsnag { - uploadReactNativeMappings = true } diff --git a/packages/react-native-cli/src/lib/__test__/fixtures/app-build-after-with-no-mappings.gradle b/packages/react-native-cli/src/lib/__test__/fixtures/app-build-after-with-no-mappings.gradle new file mode 100644 index 0000000000..675cca427d --- /dev/null +++ b/packages/react-native-cli/src/lib/__test__/fixtures/app-build-after-with-no-mappings.gradle @@ -0,0 +1,219 @@ +apply plugin: "com.android.application" + +import com.android.build.OutputFile + +/** + * The react.gradle file registers a task for each build variant (e.g. bundleDebugJsAndAssets + * and bundleReleaseJsAndAssets). + * These basically call `react-native bundle` with the correct arguments during the Android build + * cycle. By default, bundleDebugJsAndAssets is skipped, as in debug/dev mode we prefer to load the + * bundle directly from the development server. Below you can see all the possible configurations + * and their defaults. If you decide to add a configuration block, make sure to add it before the + * `apply from: "../../node_modules/react-native/react.gradle"` line. + * + * project.ext.react = [ + * // the name of the generated asset file containing your JS bundle + * bundleAssetName: "index.android.bundle", + * + * // the entry file for bundle generation. If none specified and + * // "index.android.js" exists, it will be used. Otherwise "index.js" is + * // default. Can be overridden with ENTRY_FILE environment variable. + * entryFile: "index.android.js", + * + * // https://reactnative.dev/docs/performance#enable-the-ram-format + * bundleCommand: "ram-bundle", + * + * // whether to bundle JS and assets in debug mode + * bundleInDebug: false, + * + * // whether to bundle JS and assets in release mode + * bundleInRelease: true, + * + * // whether to bundle JS and assets in another build variant (if configured). + * // See http://tools.android.com/tech-docs/new-build-system/user-guide#TOC-Build-Variants + * // The configuration property can be in the following formats + * // 'bundleIn${productFlavor}${buildType}' + * // 'bundleIn${buildType}' + * // bundleInFreeDebug: true, + * // bundleInPaidRelease: true, + * // bundleInBeta: true, + * + * // whether to disable dev mode in custom build variants (by default only disabled in release) + * // for example: to disable dev mode in the staging build type (if configured) + * devDisabledInStaging: true, + * // The configuration property can be in the following formats + * // 'devDisabledIn${productFlavor}${buildType}' + * // 'devDisabledIn${buildType}' + * + * // the root of your project, i.e. where "package.json" lives + * root: "../../", + * + * // where to put the JS bundle asset in debug mode + * jsBundleDirDebug: "$buildDir/intermediates/assets/debug", + * + * // where to put the JS bundle asset in release mode + * jsBundleDirRelease: "$buildDir/intermediates/assets/release", + * + * // where to put drawable resources / React Native assets, e.g. the ones you use via + * // require('./image.png')), in debug mode + * resourcesDirDebug: "$buildDir/intermediates/res/merged/debug", + * + * // where to put drawable resources / React Native assets, e.g. the ones you use via + * // require('./image.png')), in release mode + * resourcesDirRelease: "$buildDir/intermediates/res/merged/release", + * + * // by default the gradle tasks are skipped if none of the JS files or assets change; this means + * // that we don't look at files in android/ or ios/ to determine whether the tasks are up to + * // date; if you have any other folders that you want to ignore for performance reasons (gradle + * // indexes the entire tree), add them here. Alternatively, if you have JS files in android/ + * // for example, you might want to remove it from here. + * inputExcludes: ["android/**", "ios/**"], + * + * // override which node gets called and with what additional arguments + * nodeExecutableAndArgs: ["node"], + * + * // supply additional arguments to the packager + * extraPackagerArgs: [] + * ] + */ + +project.ext.react = [ + enableHermes: true, // clean and rebuild if changing +] + +apply from: "../../node_modules/react-native/react.gradle" + +/** + * Set this to true to create two separate APKs instead of one: + * - An APK that only works on ARM devices + * - An APK that only works on x86 devices + * The advantage is the size of the APK is reduced by about 4MB. + * Upload all the APKs to the Play Store and people will download + * the correct one based on the CPU architecture of their device. + */ +def enableSeparateBuildPerCPUArchitecture = false + +/** + * Run Proguard to shrink the Java bytecode in release builds. + */ +def enableProguardInReleaseBuilds = true + +/** + * The preferred build flavor of JavaScriptCore. + * + * For example, to use the international variant, you can use: + * `def jscFlavor = 'org.webkit:android-jsc-intl:+'` + * + * The international variant includes ICU i18n library and necessary data + * allowing to use e.g. `Date.toLocaleString` and `String.localeCompare` that + * give correct results when using with locales other than en-US. Note that + * this variant is about 6MiB larger per architecture than default. + */ +def jscFlavor = 'org.webkit:android-jsc:+' + +/** + * Whether to enable the Hermes VM. + * + * This should be set on project.ext.react and mirrored here. If it is not set + * on project.ext.react, JavaScript will not be compiled to Hermes Bytecode + * and the benefits of using Hermes will therefore be sharply reduced. + */ +def enableHermes = project.ext.react.get("enableHermes", false); + +android { + compileSdkVersion rootProject.ext.compileSdkVersion + + compileOptions { + sourceCompatibility JavaVersion.VERSION_1_8 + targetCompatibility JavaVersion.VERSION_1_8 + } + + defaultConfig { + applicationId "com.reactnativetest" + minSdkVersion rootProject.ext.minSdkVersion + targetSdkVersion rootProject.ext.targetSdkVersion + versionCode 1 + versionName "1.0" + } + splits { + abi { + reset() + enable enableSeparateBuildPerCPUArchitecture + universalApk false // If true, also generate a universal APK + include "armeabi-v7a", "x86", "arm64-v8a", "x86_64" + } + } + signingConfigs { + debug { + storeFile file('debug.keystore') + storePassword 'android' + keyAlias 'androiddebugkey' + keyPassword 'android' + } + } + buildTypes { + debug { + signingConfig signingConfigs.debug + } + release { + // Caution! In production, you need to generate your own keystore file. + // see https://reactnative.dev/docs/signed-apk-android. + signingConfig signingConfigs.debug + minifyEnabled enableProguardInReleaseBuilds + proguardFiles getDefaultProguardFile("proguard-android.txt"), "proguard-rules.pro" + } + } + + // applicationVariants are e.g. debug, release + applicationVariants.all { variant -> + variant.outputs.each { output -> + // For each separate APK per architecture, set a unique version code as described here: + // https://developer.android.com/studio/build/configure-apk-splits.html + def versionCodes = ["armeabi-v7a": 1, "x86": 2, "arm64-v8a": 3, "x86_64": 4] + def abi = output.getFilter(OutputFile.ABI) + if (abi != null) { // null for the universal-debug, universal-release variants + output.versionCodeOverride = + versionCodes.get(abi) * 1048576 + defaultConfig.versionCode + } + + } + } +} + +dependencies { + implementation fileTree(dir: "libs", include: ["*.jar"]) + //noinspection GradleDynamicVersion + implementation "com.facebook.react:react-native:+" // From node_modules + + implementation "androidx.swiperefreshlayout:swiperefreshlayout:1.0.0" + + debugImplementation("com.facebook.flipper:flipper:${FLIPPER_VERSION}") { + exclude group:'com.facebook.fbjni' + } + + debugImplementation("com.facebook.flipper:flipper-network-plugin:${FLIPPER_VERSION}") { + exclude group:'com.facebook.flipper' + exclude group:'com.squareup.okhttp3', module:'okhttp' + } + + debugImplementation("com.facebook.flipper:flipper-fresco-plugin:${FLIPPER_VERSION}") { + exclude group:'com.facebook.flipper' + } + + if (enableHermes) { + def hermesPath = "../../node_modules/hermes-engine/android/"; + debugImplementation files(hermesPath + "hermes-debug.aar") + releaseImplementation files(hermesPath + "hermes-release.aar") + } else { + implementation jscFlavor + } +} + +// Run this once to be able to run the application with BUCK +// puts all compile dependencies into folder libs for BUCK to use +task copyDownloadableDepsToLibs(type: Copy) { + from configurations.compile + into 'libs' +} + +apply from: file("../../node_modules/@react-native-community/cli-platform-android/native_modules.gradle"); applyNativeModulesAppBuildGradle(project) diff --git a/packages/react-native-cli/src/lib/__test__/fixtures/app-build-before-with-bugsnag-config.gradle b/packages/react-native-cli/src/lib/__test__/fixtures/app-build-before-with-bugsnag-config.gradle index d40d08de24..4a04a4bc92 100644 --- a/packages/react-native-cli/src/lib/__test__/fixtures/app-build-before-with-bugsnag-config.gradle +++ b/packages/react-native-cli/src/lib/__test__/fixtures/app-build-before-with-bugsnag-config.gradle @@ -221,4 +221,8 @@ apply from: file("../../node_modules/@react-native-community/cli-platform-androi bugsnag { config = yes options = set to things + + endpoint = "https://upload.example.com" + + releasesEndpoint = "https://build.example.com" } diff --git a/packages/react-native-cli/src/lib/__test__/fixtures/app-build-before-with-mappings.gradle b/packages/react-native-cli/src/lib/__test__/fixtures/app-build-before-with-mappings.gradle index b5487fbea4..959f528b86 100644 --- a/packages/react-native-cli/src/lib/__test__/fixtures/app-build-before-with-mappings.gradle +++ b/packages/react-native-cli/src/lib/__test__/fixtures/app-build-before-with-mappings.gradle @@ -219,5 +219,4 @@ task copyDownloadableDepsToLibs(type: Copy) { apply from: file("../../node_modules/@react-native-community/cli-platform-android/native_modules.gradle"); applyNativeModulesAppBuildGradle(project) bugsnag { - uploadReactNativeMappings = true } diff --git a/scripts/react-native-cli-helper.js b/scripts/react-native-cli-helper.js index 1b2ee6e13e..85547a01ca 100644 --- a/scripts/react-native-cli-helper.js +++ b/scripts/react-native-cli-helper.js @@ -48,6 +48,10 @@ module.exports = { common.run('./gradlew assembleRelease', true) } + common.changeDir(`${destFixtures}/${rnVersion}`) + const bugsnagCliCommand = './node_modules/.bin/bugsnag-cli upload react-native-android --upload-api-root-url=http://localhost:9339 --overwrite' + common.run(bugsnagCliCommand, true) + // Finally, copy the APK back to the host common.run(`mkdir -p ${baseDir}/build`) fs.copyFileSync(`${destFixtures}/${rnVersion}/android/app/build/outputs/apk/release/app-release.apk`, diff --git a/test/react-native-cli/Gemfile b/test/react-native-cli/Gemfile index c703a18be5..840eaa18fd 100644 --- a/test/react-native-cli/Gemfile +++ b/test/react-native-cli/Gemfile @@ -2,7 +2,7 @@ source 'https://rubygems.org' gem 'cocoapods' -gem 'bugsnag-maze-runner', '~>8.4.0' +gem 'bugsnag-maze-runner', '~>8.5.0' # Use a branch of Maze Runner #gem 'bugsnag-maze-runner', git: 'https://github.com/bugsnag/maze-runner', branch: 'tms/use-maze-check' diff --git a/test/react-native-cli/Gemfile.lock b/test/react-native-cli/Gemfile.lock index f203f7f864..dde68cba10 100644 --- a/test/react-native-cli/Gemfile.lock +++ b/test/react-native-cli/Gemfile.lock @@ -24,7 +24,7 @@ GEM atomos (0.1.3) bugsnag (6.26.0) concurrent-ruby (~> 1.0) - bugsnag-maze-runner (8.4.0) + bugsnag-maze-runner (8.5.0) appium_lib (~> 12.0.0) appium_lib_core (~> 5.4.0) bugsnag (~> 6.24) @@ -141,7 +141,7 @@ GEM regexp_parser (~> 2.0) simpleidn (~> 0.2) uri_template (~> 0.7) - mime-types (3.5.0) + mime-types (3.5.1) mime-types-data (~> 3.2015) mime-types-data (3.2023.0808) mini_portile2 (2.8.4) @@ -203,8 +203,8 @@ PLATFORMS ruby DEPENDENCIES - bugsnag-maze-runner (~> 8.4.0) + bugsnag-maze-runner (~> 8.5.0) cocoapods BUNDLED WITH - 2.4.8 + 2.3.18 diff --git a/test/react-native-cli/features/build-app-tests/build-android-app.feature b/test/react-native-cli/features/build-app-tests/build-android-app.feature index c1b2b4091d..5fd46a45e2 100644 --- a/test/react-native-cli/features/build-app-tests/build-android-app.feature +++ b/test/react-native-cli/features/build-app-tests/build-android-app.feature @@ -2,12 +2,11 @@ Feature: Tests for building a React Native app (for Android only) that was initi Scenario: A CLI initialized React Native Android app invokes a source map upload When I build the Android app - And I wait to receive 2 builds + And I wait to receive 1 sourcemaps - Then the build is valid for the Build API - And I discard the oldest build + Then the sourcemap is valid for the Build API - Then the Content-Type header is valid multipart form-data - And the build payload field "apiKey" equals "1234567890ABCDEF1234567890ABCDEF" - And the build payload field "platform" equals "android" - And the build payload field "overwrite" equals "true" + Then the sourcemaps Content-Type header is valid multipart form-data + And the sourcemap payload field "apiKey" equals "1234567890ABCDEF1234567890ABCDEF" + And the sourcemap payload field "platform" equals "android" + And the sourcemap payload field "overwrite" equals "true" diff --git a/test/react-native-cli/features/cli-tests/automate-symbolication.feature b/test/react-native-cli/features/cli-tests/automate-symbolication.feature index 6e7f24763f..4cd487d120 100644 --- a/test/react-native-cli/features/cli-tests/automate-symbolication.feature +++ b/test/react-native-cli/features/cli-tests/automate-symbolication.feature @@ -25,13 +25,18 @@ Scenario: successfully modify project """ And I wait for the current stdout line to match the regex "Hit enter to continue" When I input a return interactively - And I wait for the current stdout line to match the regex "Do you want to automatically upload JavaScript source maps as part of the Gradle build\?" + And I wait for the current stdout line to match the regex "Do you want to install the BugSnag CLI to allow you to upload JavaScript source maps\?" When I input a return interactively And I wait for the current stdout line to match the regex "If you want the latest version of @bugsnag/source-maps hit enter, otherwise type the version you want" When I input a return interactively - Then I wait for the shell to output a match for the regex "@bugsnag/source-maps dependency is installed" to stdout + And I wait for the current stdout line to match the regex "If you want the latest version of @bugsnag/cli hit enter, otherwise type the version you want" + When I input a return interactively + Then I wait for the shell to output a match for the regex "@bugsnag/cli dependency is installed" to stdout + When RN version is 0.68 or lower dismiss the warning message + And I wait for the current stdout line to match the regex "Do you want to add an NPM task to your package.json that you can run to upload Android source maps\?" + When I input "n" interactively Then the last interactive command exited successfully - And bugsnag source maps library is in the package.json file + And bugsnag cli library is in the package.json file And the iOS build has been modified to upload source maps And the Bugsnag Android Gradle plugin is not installed And the Android build has been modified to upload source maps @@ -61,13 +66,18 @@ Scenario: successfully modify project, choosing source-maps version """ And I wait for the current stdout line to match the regex "Hit enter to continue" When I input a return interactively - And I wait for the current stdout line to match the regex "Do you want to automatically upload JavaScript source maps as part of the Gradle build\?" + And I wait for the current stdout line to match the regex "Do you want to install the BugSnag CLI to allow you to upload JavaScript source maps\?" When I input a return interactively And I wait for the current stdout line to match the regex "If you want the latest version of @bugsnag/source-maps hit enter, otherwise type the version you want" - When I input "1.0.0-beta.1" interactively - Then I wait for the shell to output a match for the regex "@bugsnag/source-maps dependency is installed" to stdout + When I input a return interactively + And I wait for the current stdout line to match the regex "If you want the latest version of @bugsnag/cli hit enter, otherwise type the version you want" + When I input "1.1.8" interactively + Then I wait for the shell to output a match for the regex "@bugsnag/cli dependency is installed" to stdout + When RN version is 0.68 or lower dismiss the warning message + And I wait for the current stdout line to match the regex "Do you want to add an NPM task to your package.json that you can run to upload Android source maps\?" + When I input "n" interactively Then the last interactive command exited successfully - And bugsnag source maps library version "^1.0.0-beta.1" is in the package.json file + And bugsnag cli library version "^1.1.8" is in the package.json file And the iOS build has been modified to upload source maps And the Bugsnag Android Gradle plugin is not installed And the Android build has been modified to upload source maps @@ -101,13 +111,18 @@ Scenario: successfully modify project with custom endpoints """ And I wait for the current stdout line to match the regex "Hit enter to continue" When I input a return interactively - And I wait for the current stdout line to match the regex "Do you want to automatically upload JavaScript source maps as part of the Gradle build\?" + And I wait for the current stdout line to match the regex "Do you want to install the BugSnag CLI to allow you to upload JavaScript source maps\?" When I input a return interactively And I wait for the current stdout line to match the regex "If you want the latest version of @bugsnag/source-maps hit enter, otherwise type the version you want" When I input a return interactively - Then I wait for the shell to output a match for the regex "@bugsnag/source-maps dependency is installed" to stdout + And I wait for the current stdout line to match the regex "If you want the latest version of @bugsnag/cli hit enter, otherwise type the version you want" + When I input a return interactively + Then I wait for the shell to output a match for the regex "@bugsnag/cli dependency is installed" to stdout + When RN version is 0.68 or lower dismiss the warning message + And I wait for the current stdout line to match the regex "Do you want to add an NPM task to your package.json that you can run to upload Android source maps\?" + When I input "n" interactively Then the last interactive command exited successfully - And bugsnag source maps library is in the package.json file + And bugsnag cli library is in the package.json file And the iOS build has been modified to upload source maps to "https://upload.example.com" And the Bugsnag Android Gradle plugin is not installed And the Android build has been modified to upload source maps to "https://upload.example.com" @@ -138,7 +153,7 @@ Scenario: opt not to modify the Android project """ And I wait for the current stdout line to match the regex "Hit enter to continue" When I input a return interactively - And I wait for the current stdout line to match the regex "Do you want to automatically upload JavaScript source maps as part of the Gradle build\?" + And I wait for the current stdout line to match the regex "Do you want to install the BugSnag CLI to allow you to upload JavaScript source maps\?" When I input "n" interactively And I wait for the current stdout line to match the regex "If you want the latest version of @bugsnag/source-maps hit enter, otherwise type the version you want" When I input a return interactively @@ -174,13 +189,16 @@ Scenario: opt not to modify the iOS project """ And I wait for the current stdout line to match the regex "Hit enter to continue" When I input a return interactively - And I wait for the current stdout line to match the regex "Do you want to automatically upload JavaScript source maps as part of the Gradle build\?" + And I wait for the current stdout line to match the regex "Do you want to install the BugSnag CLI to allow you to upload JavaScript source maps\?" When I input "y" interactively - And I wait for the current stdout line to match the regex "If you want the latest version of @bugsnag/source-maps hit enter, otherwise type the version you want" + And I wait for the current stdout line to match the regex "If you want the latest version of @bugsnag/cli hit enter, otherwise type the version you want" When I input a return interactively - Then I wait for the shell to output a match for the regex "@bugsnag/source-maps dependency is installed" to stdout + Then I wait for the shell to output a match for the regex "@bugsnag/cli dependency is installed" to stdout + When RN version is 0.68 or lower dismiss the warning message + And I wait for the current stdout line to match the regex "Do you want to add an NPM task to your package.json that you can run to upload Android source maps\?" + When I input "n" interactively Then the last interactive command exited successfully - And bugsnag source maps library is in the package.json file + And bugsnag cli library is in the package.json file And the iOS build has not been modified to upload source maps And the Bugsnag Android Gradle plugin is not installed And the Android build has been modified to upload source maps @@ -210,7 +228,7 @@ Scenario: opt not to modify either project """ And I wait for the current stdout line to match the regex "Hit enter to continue" When I input a return interactively - And I wait for the current stdout line to match the regex "Do you want to automatically upload JavaScript source maps as part of the Gradle build\?" + And I wait for the current stdout line to match the regex "Do you want to install the BugSnag CLI to allow you to upload JavaScript source maps\?" When I input "n" interactively And I wait for the current stdout line to match the regex "\/app #" Then the last interactive command exited successfully diff --git a/test/react-native-cli/features/fixtures/rn-cli-init-android.sh b/test/react-native-cli/features/fixtures/rn-cli-init-android.sh index 40c827158a..fa4ce730c5 100755 --- a/test/react-native-cli/features/fixtures/rn-cli-init-android.sh +++ b/test/react-native-cli/features/fixtures/rn-cli-init-android.sh @@ -3,6 +3,19 @@ set timeout -1 set notifierVersion [lindex $argv 0]; set rnVersion [lindex $argv 1]; +set rnVersionInt "" +set substringToTrim ".expo.ejected" + +# Extract the substring starting from the third character +set rnVersionInt [string range $rnVersion 2 end] + +# Replace underscore (_) with a period (.) +set rnVersionInt2 [string map {_ .} $rnVersionInt] + +set rnVersionInt3 [string map [list $substringToTrim ""] $rnVersionInt2] + +# Convert float string to float value using bc +regsub -all {^0+} $rnVersionInt3 "" $rnVersionInt3 puts "Using notifier version: $notifierVersion" puts "Using React Native version: $rnVersion" @@ -43,10 +56,21 @@ send -- n expect "This will enable you to see full native stacktraces. It can't be done automatically." send -- \r -expect "Do you want to automatically upload JavaScript source maps as part of the Gradle build?" +expect "Do you want to install the BugSnag CLI to allow you to upload JavaScript source maps?" send -- y -expect "If you want the latest version of @bugsnag/source-maps hit enter, otherwise type the version you want" +expect "If you want the latest version of @bugsnag/cli hit enter, otherwise type the version you want" send -- latest\r +if {[expr $rnVersionInt3 < 0.68]} { + expect "or follow the manual integration instructions in our online docs: https://docs.bugsnag.com/platforms/react-native/react-native/manual-setup/')" + send -- \r +} + +expect "Do you want to add an NPM task to your package.json that you can run to upload Android source maps?" +send -- \r + +expect "See https://docs.bugsnag.com/platforms/react-native/react-native/showing-full-stacktraces for details." +send -- \r + expect eof diff --git a/test/react-native-cli/features/fixtures/rn-cli-init-ios.sh b/test/react-native-cli/features/fixtures/rn-cli-init-ios.sh index 3ef39e4707..09ae24e5bb 100755 --- a/test/react-native-cli/features/fixtures/rn-cli-init-ios.sh +++ b/test/react-native-cli/features/fixtures/rn-cli-init-ios.sh @@ -43,7 +43,7 @@ send -- y expect "This will enable you to see full native stacktraces. It can't be done automatically." send -- \r -expect "Do you want to automatically upload JavaScript source maps as part of the Gradle build?" +expect "Do you want to install the BugSnag CLI to allow you to upload JavaScript source maps?" send -- n expect "If you want the latest version of @bugsnag/source-maps hit enter, otherwise type the version you want" diff --git a/test/react-native-cli/features/steps/react-native-source-maps-steps.rb b/test/react-native-cli/features/steps/react-native-source-maps-steps.rb new file mode 100644 index 0000000000..d6ec593a8e --- /dev/null +++ b/test/react-native-cli/features/steps/react-native-source-maps-steps.rb @@ -0,0 +1,8 @@ +# Tests whether the top-most payload is valid for the Bugsnag build API +# APIKey fields and headers are tested against the '$api_key' global variable +Then('the sourcemap is valid for the Build API') do + steps %( + And the sourcemap payload field "apiKey" equals "#{$api_key}" + And the sourcemap payload field "appVersion" is not null + ) +end diff --git a/test/react-native-cli/features/steps/steps.rb b/test/react-native-cli/features/steps/steps.rb index e22c5c0046..ac13e270aa 100644 --- a/test/react-native-cli/features/steps/steps.rb +++ b/test/react-native-cli/features/steps/steps.rb @@ -94,6 +94,13 @@ def parse_package_json Maze.check.include(json['devDependencies'], '@bugsnag/source-maps') end +Then('bugsnag cli library is in the package.json file') do + json = parse_package_json + + Maze.check.include(json, 'devDependencies') + Maze.check.include(json['devDependencies'], '@bugsnag/cli') +end + Then('bugsnag source maps library version {string} is in the package.json file') do |expected| json = parse_package_json @@ -102,6 +109,15 @@ def parse_package_json Maze.check.equal(json['devDependencies']['@bugsnag/source-maps'], expected) end +Then('bugsnag cli library version {string} is in the package.json file') do |expected| + json = parse_package_json + + Maze.check.include(json, 'devDependencies') + Maze.check.include(json['devDependencies'], '@bugsnag/cli') + Maze.check.equal(json['devDependencies']['@bugsnag/cli'], expected) +end + + Then('bugsnag source maps library is not in the package.json file') do json = parse_package_json @@ -424,3 +440,35 @@ def parse_xml_file(path) actual = Maze::Server.builds.current[:request]['content-type'] Maze.check.match(expected, actual) end + +Then('the sourcemaps Content-Type header is valid multipart form-data') do + expected = /^multipart\/form-data; boundary=([^;]+)/ + actual = Maze::Server.sourcemaps.current[:request]['content-type'] + Maze.check.match(expected, actual) +end + +def rn_version_less_than(string_value, float_value) + stripped_string = string_value[2..-1] + replaced_string = stripped_string.gsub("_", ".") + converted_float = replaced_string.to_f + return converted_float < float_value +end + +When('RN version is 0.68 or lower dismiss the warning message') do + rn_version_lower = rn_version_less_than(ENV['REACT_NATIVE_VERSION'], 0.69) + case rn_version_lower + when true + steps %Q{ + And I wait for the interactive shell to output the following lines in stdout + """ + You are running a version of React Native that we cannot automatically integrate with due to known issues with the build when Hermes is enabled. + + If you cannot upgrade to a later version of React Native (version 0.68 or above), you can use an older version of this CLI (version 7.20.x or earlier) + + or follow the manual integration instructions in our online docs: https://docs.bugsnag.com/platforms/react-native/react-native/manual-setup/') + """ + And I wait for the current stdout line to match the regex "Hit enter to continue" + When I input a return interactively + } + end +end From 6134e814822ee4ee76eb123dfc522bcd41175ae3 Mon Sep 17 00:00:00 2001 From: Josh Edney Date: Tue, 12 Sep 2023 15:24:33 +0100 Subject: [PATCH 4/5] update changelog for release --- CHANGELOG.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9c07eaff5e..069796feb9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,11 @@ # Changelog +## 7.22.0 (2023-09-13) + +### Changes + +(react-native-cli) Update the react native cli to install and configure the `@bugsnag/cli` package to upload javascript source maps for react native android [#1998](https://github.com/bugsnag/bugsnag-js/pull/1990) + ## 7.21.0 (2023-08-15) This release adds support for apps using React Native New Architecture From 7ebb69f047bd174381c68470801ddacd173ead6a Mon Sep 17 00:00:00 2001 From: Yousif <74918474+yousif-bugsnag@users.noreply.github.com> Date: Wed, 13 Sep 2023 08:33:23 +0100 Subject: [PATCH 5/5] Update CHANGELOG.md --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 069796feb9..fa4cc5cf70 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,7 +4,7 @@ ### Changes -(react-native-cli) Update the react native cli to install and configure the `@bugsnag/cli` package to upload javascript source maps for react native android [#1998](https://github.com/bugsnag/bugsnag-js/pull/1990) +(react-native-cli) Update the react native cli to install and configure the `@bugsnag/cli` package to upload javascript source maps for react native android [#1990](https://github.com/bugsnag/bugsnag-js/pull/1990) ## 7.21.0 (2023-08-15)