diff --git a/.gitignore b/.gitignore index ad4dd9f005..e4c7e47f89 100644 --- a/.gitignore +++ b/.gitignore @@ -194,3 +194,6 @@ test/appium/tests/users.py ## git hooks lefthook.yml + +## metro server logs +metro-server-logs.log diff --git a/Makefile b/Makefile index 03654c49c2..4fe32474e0 100644 --- a/Makefile +++ b/Makefile @@ -267,7 +267,7 @@ run-clojure: ##@run Watch for and build Clojure changes for mobile run-metro: export TARGET := clojure run-metro: ##@run Start Metro to build React Native changes - @scripts/start-react-native.sh + @scripts/run-metro.sh run-re-frisk: export TARGET := clojure run-re-frisk: ##@run Start re-frisk server @@ -278,22 +278,15 @@ run-android: export TARGET := android # Disabled for debug builds to avoid 'maximum call stack exceeded' errors. # https://github.com/status-im/status-mobile/issues/18493 run-android: export ORG_GRADLE_PROJECT_hermesEnabled := false -# INFO: If it's empty (no devices attached, parsing issues, script error) - for Nix it's the same as not set. -run-android: export ANDROID_ABI_INCLUDE ?= $(shell ./scripts/adb_devices_abis.sh) run-android: ##@run Build Android APK and start it on the device - npx react-native run-android --appIdSuffix debug + @scripts/run-android.sh SIMULATOR=iPhone 13 # TODO: fix IOS_STATUS_GO_TARGETS to be either amd64 or arm64 when RN is upgraded run-ios: export TARGET := ios run-ios: export IOS_STATUS_GO_TARGETS := ios/arm64;iossimulator/amd64 -run-ios: export XCBeautify=$(shell which xcbeautify) # for react-native-cli to pick this up and to auto format output -run-ios: ##@run Build iOS app and start it in a simulator/device -ifneq ("$(SIMULATOR)", "") - npx react-native run-ios --simulator="$(SIMULATOR)" -else - npx react-native run-ios -endif +run-ios: ##@run Build iOS app and start it in on the simulator + @scripts/run-ios.sh "${SIMULATOR}" show-ios-devices: ##@other shows connected ios device and its name xcrun xctrace list devices diff --git a/doc/ide-setup.md b/doc/ide-setup.md index d1085018b5..aa400509d7 100644 --- a/doc/ide-setup.md +++ b/doc/ide-setup.md @@ -122,10 +122,9 @@ See below: Do the following: -Ensure you have 3 terminals running the following +Ensure you have 2 terminals running the following - `make run-clojure` -- `make run-metro` - `make run-ios` / `make run-android` [See the STARTING GUIDE for details](STARTING_GUIDE.md#development) diff --git a/doc/starting-guide.md b/doc/starting-guide.md index 9f8e55721b..0d1fff2514 100644 --- a/doc/starting-guide.md +++ b/doc/starting-guide.md @@ -15,8 +15,7 @@ This step will take a while the first time as it will download all dependencies. There are three steps necessary to start development, in this case for Android: 1. `make run-clojure` - Compiles Clojure into JavaScript, watches for changes on cljs files, and hot-reloads code in the app. -2. `make run-metro` - Starts metro bundler and watches JavaScript code. -3. `make run-android` or `make run-ios` - Builds the Android/iOS app and starts it on the device. +2. `make run-android` or `make run-ios` - Builds the Android/iOS app, starts it on the device and starts metro bundler. The first two will continue watching for changes and keep re-building the app. They need to be ready first. The last one will exit once the app is up and ready. diff --git a/ios/Podfile.lock b/ios/Podfile.lock index 486b75e855..f539dec0ed 100644 --- a/ios/Podfile.lock +++ b/ios/Podfile.lock @@ -793,7 +793,7 @@ CHECKOUT OPTIONS: :submodules: true SPEC CHECKSUMS: - boost: 57d2868c099736d80fcd648bf211b4431e51a558 + boost: 64032b9e9b938fda23325e68a3771f0fabf414dc BVLinearGradient: 612a04ff38e8480291f3379ee5b5a2c571f03fe0 CryptoSwift: c4f2debceb38bf44c80659afe009f71e23e4a082 DoubleConversion: 5189b271737e1565bdce30deb4a08d647e3f5f54 diff --git a/nix/mobile/android/release.nix b/nix/mobile/android/release.nix index 160e548562..fcd60d3d8a 100644 --- a/nix/mobile/android/release.nix +++ b/nix/mobile/android/release.nix @@ -40,8 +40,10 @@ let else if (elem buildType ["pr" "manual"]) then ".env.jenkins" else ".env"; - # There are only two types of Gradle build targets: pr and release - gradleBuildType = if buildType == "pr" then "Pr" else "Release"; + gradleBuildType = + if buildType == "pr" then "Pr" + else if buildType == "debug" then "Debug" + else "Release"; apksPath = "./android/app/build/outputs/apk/${toLower gradleBuildType}"; @@ -171,12 +173,14 @@ in stdenv.mkDerivation rec { ${adhocEnvVars} ${gradleCommand} popd > /dev/null ''; - doCheck = true; - checkPhase = '' + + doCheck = buildType != "debug"; + checkPhase = '' ls ${apksPath}/*.apk \ | xargs -n1 ${pkgs.unzip}/bin/unzip -qql \ | grep 'index.android.bundle' ''; + installPhase = '' mkdir -p $out cp ${apksPath}/*.apk $out/ diff --git a/scripts/run-android.sh b/scripts/run-android.sh new file mode 100755 index 0000000000..8f4c11aa84 --- /dev/null +++ b/scripts/run-android.sh @@ -0,0 +1,53 @@ +#!/usr/bin/env bash +set -euo pipefail +set -m # needed to access jobs + +GIT_ROOT=$(cd "${BASH_SOURCE%/*}" && git rev-parse --show-toplevel) + +# We run Metro in background while calling adb. +cleanupMetro() { + pkill -f run-metro.sh + rm -f metro-server-logs.log +} + +# Using function gives a neater jobspec name. +runMetro() { + nohup "${GIT_ROOT}/scripts/run-metro.sh" 2>&1 \ + | tee metro-server-logs.log +} + +waitForMetro() { + set +e # Allow grep command to fail in the loop. + TIMEOUT=5 + echo "Waiting for Metro server..." >&2 + while ! grep -q "Welcome to Metro" metro-server-logs.log; do + echo -n "." >&2 + sleep 1 + if ((TIMEOUT == 0)); then + echo -e "\nMetro server timed out, exiting" >&2 + set -e # Restore errexit for rest of script. + return 1 + fi + ((TIMEOUT--)) + done + set -e # Restore errexit for rest of script. +} + +# Generate android debug build. +export ANDROID_ABI_INCLUDE=$("${GIT_ROOT}/scripts/adb_devices_abis.sh") +export BUILD_ENV=debug +export BUILD_TYPE=debug +"${GIT_ROOT}/scripts/build-android.sh" + +# Install the APK on running emulator or android device. +adb install ./result/app-debug.apk + +trap cleanupMetro EXIT ERR INT QUIT +runMetro & +waitForMetro + +# Start the installed app. +adb shell monkey -p im.status.ethereum.debug 1 + +# bring metro job to foreground +fg 'runMetro' diff --git a/scripts/run-ios.sh b/scripts/run-ios.sh new file mode 100755 index 0000000000..c913d4895f --- /dev/null +++ b/scripts/run-ios.sh @@ -0,0 +1,72 @@ +#!/usr/bin/env bash +set -euo pipefail +set -m # needed to access jobs + +GIT_ROOT=$(cd "${BASH_SOURCE%/*}" && git rev-parse --show-toplevel) + +# We run Metro in background while calling adb. +cleanupMetro() { + pkill -f run-metro.sh + rm -f metro-server-logs.log +} + +# Using function gives a neater jobspec name. +runMetro() { + nohup "${GIT_ROOT}/scripts/run-metro.sh" 2>&1 \ + | tee metro-server-logs.log +} + +waitForMetro() { + set +e # Allow grep command to fail in the loop. + TIMEOUT=5 + echo "Waiting for Metro server..." >&2 + while ! grep -q "Welcome to Metro" metro-server-logs.log; do + echo -n "." >&2 + sleep 1 + if ((TIMEOUT == 0)); then + echo -e "\nMetro server timed out, exiting" >&2 + set -e # Restore errexit for rest of script. + return 1 + fi + ((TIMEOUT--)) + done + set -e # Restore errexit for rest of script. +} + +# Check if the first argument is provided +if [ -z "${1-}" ]; then + echo "Error: No simulator name provided." >&2 + exit 1 +fi + +SIMULATOR=${1} + +# get our desired UUID +UUID=$(xcrun simctl list devices | grep -E "$SIMULATOR \(" | head -n 1 | awk -F '[()]' '{print $2}') + +# get simulator status +SIMULATOR_STATE=$(xcrun simctl list devices | grep -E "$SIMULATOR \(" | head -n 1 | awk '{print $NF}') + +# sometimes a simulator is already running, shut it down to avoid errors +if [ "$SIMULATOR_STATE" != "(Shutdown)" ]; then + xcrun simctl shutdown "$UUID" +fi + +# boot up iOS for simulator +xcrun simctl boot "$UUID" + +# start the simulator +open -a Simulator --args -CurrentDeviceUDID "$UUID" + +#iOS build of debug scheme +xcodebuild -workspace "ios/StatusIm.xcworkspace" -configuration Debug -scheme StatusIm -destination id="$UUID" | xcbeautify + +trap cleanupMetro EXIT ERR INT QUIT +runMetro & +waitForMetro + +# launch the app when metro is ready +xcrun simctl launch "$UUID" im.status.ethereum.debug + +# bring metro job to foreground +fg 'runMetro' diff --git a/scripts/run-metro.sh b/scripts/run-metro.sh new file mode 100755 index 0000000000..37741881c6 --- /dev/null +++ b/scripts/run-metro.sh @@ -0,0 +1,5 @@ +#!/usr/bin/env bash + +pkill -f 'react-native start' + +react-native start --reset-cache diff --git a/scripts/start-react-native.sh b/scripts/start-react-native.sh deleted file mode 100755 index f137844bbb..0000000000 --- a/scripts/start-react-native.sh +++ /dev/null @@ -1,17 +0,0 @@ - -#!/usr/bin/env bash - -GIT_ROOT=$(cd "${BASH_SOURCE%/*}" && git rev-parse --show-toplevel) -source "${GIT_ROOT}/scripts/colors.sh" - -METRO_PORT=8081 -METRO_PID="$(lsof -i :${METRO_PORT} | awk 'NR!=1 {print $2}' | sort -u | tr '\r\n' ' ')" -if [ ! -z "$METRO_PID" ]; then - echo -e "${YLW}TCP port ${METRO_PORT} is required by the Metro packager.\nThe following processes currently have the port open, preventing Metro from starting:${RST}" - ps -fp $METRO_PID - echo -e "${YLW}Do you want to terminate them (y/n)?${RST}" - read -n 1 term - [[ $term == 'y' ]] && kill $METRO_PID -fi - -react-native start --reset-cache