diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 93e001b15..864b3f1f8 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -6,30 +6,30 @@ on: pull_request: branches: ["main"] -concurrency: - group: unit-tests-${{ github.ref }} - cancel-in-progress: false - -env: - SCCACHE_GHA_ENABLED: "true" - RUSTC_WRAPPER: "sccache" +# concurrency: +# group: unit-tests-${{ github.ref }} +# cancel-in-progress: false jobs: unit_test: name: Build and Test iPhone simulator - runs-on: macos-26 + #runs-on: macos-26 + runs-on: [self-hosted, macOS] steps: - - name: Select Xcode + - name: Setup sccache for GitHub-hosted + if: runner.environment == 'github-hosted' run: | - xcrun simctl list devices - + echo "SCCACHE_GHA_ENABLED=true" >> $GITHUB_ENV + echo "RUSTC_WRAPPER=sccache" >> $GITHUB_ENV + - name: Checkout uses: actions/checkout@v4 with: submodules: true - name: Cache Cargo Dependencies + if: runner.environment == 'github-hosted' uses: actions/cache@v4 with: path: | @@ -38,8 +38,9 @@ jobs: key: ${{ runner.os }}-cargo-deps-${{ hashFiles('core/Cargo.lock') }} restore-keys: | ${{ runner.os }}-cargo-deps- - + - name: Cache Cargo Target + if: runner.environment == 'github-hosted' uses: actions/cache@v4 with: path: | @@ -49,6 +50,7 @@ jobs: ${{ runner.os }}-cargo-deps- - name: Cache Swift Package Manager + if: runner.environment == 'github-hosted' uses: actions/cache@v4 with: path: | @@ -59,9 +61,11 @@ jobs: ${{ runner.os }}-spm- - name: Run sccache-cache + if: runner.environment == 'github-hosted' uses: mozilla-actions/sccache-action@v0.0.8 - + - name: Install just + if: runner.environment == 'github-hosted' run: brew install just - name: Install dependencies @@ -70,5 +74,11 @@ jobs: - name: Build Core run: just generate-stone + - name: Clean DerivedData + run: just clean + + - name: Build for Testing + run: just build-for-testing + - name: Unit Tests - run: just test-all + run: just test-without-building diff --git a/.github/workflows/ui_tests.yml b/.github/workflows/ui_tests.yml index 26affdd98..439f7fa1e 100644 --- a/.github/workflows/ui_tests.yml +++ b/.github/workflows/ui_tests.yml @@ -11,19 +11,18 @@ concurrency: group: ui-tests-${{ github.ref }} cancel-in-progress: false -env: - SCCACHE_GHA_ENABLED: "true" - RUSTC_WRAPPER: "sccache" - jobs: ui_test: name: Build and UI Test iPhone simulator - runs-on: macos-26 + #runs-on: macos-26 + runs-on: [self-hosted, macOS] steps: - - name: Select Xcode + - name: Setup sccache for GitHub-hosted + if: runner.environment == 'github-hosted' run: | - xcrun simctl list devices + echo "SCCACHE_GHA_ENABLED=true" >> $GITHUB_ENV + echo "RUSTC_WRAPPER=sccache" >> $GITHUB_ENV - name: Checkout uses: actions/checkout@v4 @@ -31,6 +30,7 @@ jobs: submodules: true - name: Cache Cargo Dependencies + if: runner.environment == 'github-hosted' uses: actions/cache@v4 with: path: | @@ -41,6 +41,7 @@ jobs: ${{ runner.os }}-cargo-deps- - name: Cache Cargo Target + if: runner.environment == 'github-hosted' uses: actions/cache@v4 with: path: | @@ -50,6 +51,7 @@ jobs: ${{ runner.os }}-cargo-deps- - name: Cache Swift Package Manager + if: runner.environment == 'github-hosted' uses: actions/cache@v4 with: path: | @@ -60,19 +62,24 @@ jobs: ${{ runner.os }}-spm- - name: Run sccache-cache + if: runner.environment == 'github-hosted' uses: mozilla-actions/sccache-action@v0.0.8 - - - name: Verify sccache usage - run: sccache --show-stats - + - name: Install just + if: runner.environment == 'github-hosted' run: brew install just - name: Install dependencies run: just install-toolchains + + - name: Clean DerivedData + run: just clean - name: Build Core run: just generate-stone + - name: Build for Testing + run: just build-for-testing + - name: UI Tests - run: just test-ui \ No newline at end of file + run: just test-ui-without-building \ No newline at end of file diff --git a/Gem.xcodeproj/project.pbxproj b/Gem.xcodeproj/project.pbxproj index f6df8417f..703330a0a 100644 --- a/Gem.xcodeproj/project.pbxproj +++ b/Gem.xcodeproj/project.pbxproj @@ -17,7 +17,6 @@ 833809D02D273E450055D91F /* WalletConnectorService in Frameworks */ = {isa = PBXBuildFile; productRef = 83385DDD2D27147900D76803 /* WalletConnectorService */; }; 833809D12D273E450055D91F /* WalletConnector in Frameworks */ = {isa = PBXBuildFile; productRef = 83FE37B32D273CC80048D54C /* WalletConnector */; }; 833931A52D2D5B1D0063BB6A /* PriceAlerts in Frameworks */ = {isa = PBXBuildFile; productRef = 833931A42D2D5B1D0063BB6A /* PriceAlerts */; }; - D9F015752F10654000000003 /* InAppNotifications in Frameworks */ = {isa = PBXBuildFile; productRef = D9F015752F10654000000002 /* InAppNotifications */; }; 833931A82D2D663C0063BB6A /* PriceService in Frameworks */ = {isa = PBXBuildFile; productRef = 833931A72D2D663C0063BB6A /* PriceService */; }; 833CDFD02D10622D00DAABEE /* ServicesFactory.swift in Sources */ = {isa = PBXBuildFile; fileRef = 833CDFCF2D10622D00DAABEE /* ServicesFactory.swift */; }; 8342EA032DB67EE3001B3780 /* WalletService in Frameworks */ = {isa = PBXBuildFile; productRef = 8342EA022DB67EE3001B3780 /* WalletService */; }; @@ -99,6 +98,7 @@ D83BDCB72E3E878A00E41807 /* PerpetualPositionNavigationStack.swift in Sources */ = {isa = PBXBuildFile; fileRef = D83BDCB52E3E878A00E41807 /* PerpetualPositionNavigationStack.swift */; }; D83BDCB92E3E8AA400E41807 /* ViewModelFactory.swift in Sources */ = {isa = PBXBuildFile; fileRef = D83BDCB82E3E8AA400E41807 /* ViewModelFactory.swift */; }; D83D3C252D6E62F4002959EA /* ScanService in Frameworks */ = {isa = PBXBuildFile; productRef = D83D3C242D6E62F4002959EA /* ScanService */; }; + D84941902F2563E100FCCCCD /* unit_app.xctestplan in Resources */ = {isa = PBXBuildFile; fileRef = D849418F2F2563E100FCCCCD /* unit_app.xctestplan */; }; D852CAFD2C9C9837004121D3 /* AddAssetPriceAlertNavigationStack.swift in Sources */ = {isa = PBXBuildFile; fileRef = D852CAFC2C9C9837004121D3 /* AddAssetPriceAlertNavigationStack.swift */; }; D852CB012C9CC315004121D3 /* PriceAlertsNavigationView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D852CB002C9CC315004121D3 /* PriceAlertsNavigationView.swift */; }; D85AD29D2CD337BE0010DEF8 /* SwapService in Frameworks */ = {isa = PBXBuildFile; productRef = D85AD29C2CD337BE0010DEF8 /* SwapService */; }; @@ -133,6 +133,7 @@ D8F5B86C2CCD52EB0007E615 /* Staking in Frameworks */ = {isa = PBXBuildFile; productRef = D8F5B86B2CCD52EB0007E615 /* Staking */; }; D8F5B86F2CCD639A0007E615 /* StakeService in Frameworks */ = {isa = PBXBuildFile; productRef = D8F5B86E2CCD639A0007E615 /* StakeService */; }; D8WIDGBF12345678901234 /* WidgetLocalization in Frameworks */ = {isa = PBXBuildFile; productRef = D8WIDGET12345678901234 /* WidgetLocalization */; }; + D9F015752F10654000000003 /* InAppNotifications in Frameworks */ = {isa = PBXBuildFile; productRef = D9F015752F10654000000002 /* InAppNotifications */; }; DF1167112BC36240000F8C8C /* PrivacyInfo.xcprivacy in Resources */ = {isa = PBXBuildFile; fileRef = DF486B6D2BBE320800B95732 /* PrivacyInfo.xcprivacy */; }; DF8421EE2C1526ED003F558C /* GemstonePrimitives in Frameworks */ = {isa = PBXBuildFile; productRef = DF8421ED2C1526ED003F558C /* GemstonePrimitives */; }; DF93C4EE2C969F4F00204ABD /* Gemstone in Frameworks */ = {isa = PBXBuildFile; productRef = DF93C4ED2C969F4F00204ABD /* Gemstone */; }; @@ -191,7 +192,6 @@ 8311A89A2DF9D35D00598C43 /* Validators */ = {isa = PBXFileReference; lastKnownFileType = wrapper; path = Validators; sourceTree = ""; }; 832F57E92D36A6D50066024D /* Preferences */ = {isa = PBXFileReference; lastKnownFileType = wrapper; path = Preferences; sourceTree = ""; }; 833931A32D2D54060063BB6A /* PriceAlerts */ = {isa = PBXFileReference; lastKnownFileType = wrapper; path = PriceAlerts; sourceTree = ""; }; - D9F015752F10654000000001 /* InAppNotifications */ = {isa = PBXFileReference; lastKnownFileType = wrapper; path = InAppNotifications; sourceTree = ""; }; 833CDFCF2D10622D00DAABEE /* ServicesFactory.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ServicesFactory.swift; sourceTree = ""; }; 8349F1452D5E4D04003A0A93 /* ManageWallets */ = {isa = PBXFileReference; lastKnownFileType = wrapper; path = ManageWallets; sourceTree = ""; }; 834B38182D1D858D009D58D4 /* LockManager */ = {isa = PBXFileReference; lastKnownFileType = wrapper; path = LockManager; sourceTree = ""; }; @@ -255,6 +255,7 @@ D83819492E256A5A0076CDB3 /* GemPriceWidget.appex */ = {isa = PBXFileReference; explicitFileType = "wrapper.app-extension"; includeInIndex = 0; path = GemPriceWidget.appex; sourceTree = BUILT_PRODUCTS_DIR; }; D83BDCB52E3E878A00E41807 /* PerpetualPositionNavigationStack.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PerpetualPositionNavigationStack.swift; sourceTree = ""; }; D83BDCB82E3E8AA400E41807 /* ViewModelFactory.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ViewModelFactory.swift; sourceTree = ""; }; + D849418F2F2563E100FCCCCD /* unit_app.xctestplan */ = {isa = PBXFileReference; lastKnownFileType = text; path = unit_app.xctestplan; sourceTree = ""; }; D852CAFC2C9C9837004121D3 /* AddAssetPriceAlertNavigationStack.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AddAssetPriceAlertNavigationStack.swift; sourceTree = ""; }; D852CB002C9CC315004121D3 /* PriceAlertsNavigationView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PriceAlertsNavigationView.swift; sourceTree = ""; }; D87316532E3AF1F000C11634 /* ChainServices */ = {isa = PBXFileReference; lastKnownFileType = wrapper; path = ChainServices; sourceTree = ""; }; @@ -282,6 +283,7 @@ D8D83C822CECF90A0083AA53 /* Swap */ = {isa = PBXFileReference; lastKnownFileType = wrapper; path = Swap; sourceTree = ""; }; D8EFE3EA2BAB580300608363 /* GemstonePrimitives */ = {isa = PBXFileReference; lastKnownFileType = wrapper; path = GemstonePrimitives; sourceTree = ""; }; D8F5B8682CCD50650007E615 /* Staking */ = {isa = PBXFileReference; lastKnownFileType = wrapper; path = Staking; sourceTree = ""; }; + D9F015752F10654000000001 /* InAppNotifications */ = {isa = PBXFileReference; lastKnownFileType = wrapper; path = InAppNotifications; sourceTree = ""; }; DF486B6D2BBE320800B95732 /* PrivacyInfo.xcprivacy */ = {isa = PBXFileReference; lastKnownFileType = text.xml; path = PrivacyInfo.xcprivacy; sourceTree = ""; }; DFBDD9AE2C77EC90002A1706 /* WalletCore */ = {isa = PBXFileReference; lastKnownFileType = wrapper; path = WalletCore; sourceTree = ""; }; /* End PBXFileReference section */ @@ -617,6 +619,7 @@ children = ( D8D726BF2C716C5B00A6B559 /* Screenshots */, C34C7CF729FDE942009EEC21 /* unit_frameworks.xctestplan */, + D849418F2F2563E100FCCCCD /* unit_app.xctestplan */, D87316B72E3AF30300C11634 /* ui_tests.xctestplan */, D8041FA12B193A2C002DC071 /* screenshots.xctestplan */, ); @@ -1068,6 +1071,7 @@ isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( + D84941902F2563E100FCCCCD /* unit_app.xctestplan in Resources */, C34C7CF829FDE942009EEC21 /* unit_frameworks.xctestplan in Resources */, ); runOnlyForDeploymentPostprocessing = 0; @@ -1843,10 +1847,6 @@ isa = XCSwiftPackageProductDependency; productName = PriceAlerts; }; - D9F015752F10654000000002 /* InAppNotifications */ = { - isa = XCSwiftPackageProductDependency; - productName = InAppNotifications; - }; 833931A72D2D663C0063BB6A /* PriceService */ = { isa = XCSwiftPackageProductDependency; productName = PriceService; @@ -2227,6 +2227,10 @@ isa = XCSwiftPackageProductDependency; productName = WidgetLocalization; }; + D9F015752F10654000000002 /* InAppNotifications */ = { + isa = XCSwiftPackageProductDependency; + productName = InAppNotifications; + }; DF8421ED2C1526ED003F558C /* GemstonePrimitives */ = { isa = XCSwiftPackageProductDependency; productName = GemstonePrimitives; diff --git a/GemTests/unit_app.xctestplan b/GemTests/unit_app.xctestplan new file mode 100644 index 000000000..96a3a570d --- /dev/null +++ b/GemTests/unit_app.xctestplan @@ -0,0 +1,25 @@ +{ + "configurations" : [ + { + "id" : "D85544DD-3036-48C8-AE04-E011CF15C0E6", + "name" : "Test Configuration", + "options" : { + + } + } + ], + "defaultOptions" : { + "language" : "en", + "region" : "US" + }, + "testTargets" : [ + { + "target" : { + "containerPath" : "container:Gem.xcodeproj", + "identifier" : "C30952C0299C39D80004C0F9", + "name" : "GemTests" + } + } + ], + "version" : 1 +} diff --git a/justfile b/justfile index 5f3b7f757..06ace8e6b 100644 --- a/justfile +++ b/justfile @@ -2,16 +2,12 @@ XCBEAUTIFY_ARGS := "--quieter --is-ci" BUILD_THREADS := `sysctl -n hw.ncpu` SIMULATOR_NAME := "iPhone 17" SIMULATOR_DEST := "platform=iOS Simulator,name=" + SIMULATOR_NAME +DERIVED_DATA := "build/DerivedData" +FAST_BUILD_FLAGS := "GCC_OPTIMIZATION_LEVEL=0 SWIFT_OPTIMIZATION_LEVEL=-Onone SWIFT_COMPILATION_MODE=incremental ENABLE_TESTABILITY=NO" default: @just --list -xcbeautify: - @xcbeautify {{XCBEAUTIFY_ARGS}} - -list: - just --list - bootstrap: install generate-stone @echo "<== Bootstrap done." @@ -34,7 +30,7 @@ install-swifttools: download-wallet-core VERSION: @echo "==> Install wallet-core {{VERSION}}" - curl -L https://github.com/trustwallet/wallet-core/releases/download/{{VERSION}}/Package.swift -o Packages/WalletCore/Package.swift + @curl -sL https://github.com/trustwallet/wallet-core/releases/download/{{VERSION}}/Package.swift -o Packages/WalletCore/Package.swift setup-git: @echo "==> Setup git submodules" @@ -42,44 +38,48 @@ setup-git: @git config submodule.recurse true core-upgrade: - git submodule update --recursive --remote + @git submodule update --recursive --remote spm-resolve-all: - sh scripts/spm-resolve-all.sh + @sh scripts/spm-resolve-all.sh -build: +_build action extra_flags="": @set -o pipefail && xcodebuild -project Gem.xcodeproj \ -scheme Gem \ ONLY_ACTIVE_ARCH=YES \ -destination "{{SIMULATOR_DEST}}" \ - -derivedDataPath build/DerivedData \ + -derivedDataPath {{DERIVED_DATA}} \ -parallelizeTargets \ -jobs {{BUILD_THREADS}} \ -showBuildTimingSummary \ - GCC_OPTIMIZATION_LEVEL=0 \ - SWIFT_OPTIMIZATION_LEVEL=-Onone \ - SWIFT_COMPILATION_MODE=incremental \ - ENABLE_TESTABILITY=NO \ - build | xcbeautify {{XCBEAUTIFY_ARGS}} + {{extra_flags}} \ + {{action}} | xcbeautify {{XCBEAUTIFY_ARGS}} + +# Example: just build +build: (_build "build" FAST_BUILD_FLAGS) + +# Example: just build-for-testing +build-for-testing: (_build "build-for-testing") clean: - @rm -rf build/DerivedData + @rm -rf {{DERIVED_DATA}} @echo "Build cache cleaned" run: build @echo "==> Installing app on simulator..." @xcrun simctl boot "{{SIMULATOR_NAME}}" 2>/dev/null || true @open -a Simulator - @xcrun simctl install "{{SIMULATOR_NAME}}" build/DerivedData/Build/Products/Debug-iphonesimulator/Gem.app + @xcrun simctl install "{{SIMULATOR_NAME}}" {{DERIVED_DATA}}/Build/Products/Debug-iphonesimulator/Gem.app @echo "==> Launching app..." @xcrun simctl launch --console-pty "{{SIMULATOR_NAME}}" com.gemwallet.ios +# Example: just build-package Primitives build-package PACKAGE: @set -o pipefail && xcodebuild -project Gem.xcodeproj \ -scheme {{PACKAGE}} \ ONLY_ACTIVE_ARCH=YES \ -destination "{{SIMULATOR_DEST}}" \ - -derivedDataPath build/DerivedData \ + -derivedDataPath {{DERIVED_DATA}} \ -parallelizeTargets \ -jobs {{BUILD_THREADS}} \ GCC_OPTIMIZATION_LEVEL=0 \ @@ -90,16 +90,24 @@ show-simulator: @echo "Destination: {{SIMULATOR_DEST}}" @xcrun simctl list devices | grep "iPhone" | head -5 || true -test-all: show-simulator +_test action target="": @set -o pipefail && xcodebuild -project Gem.xcodeproj \ -scheme Gem \ ONLY_ACTIVE_ARCH=YES \ -destination "{{SIMULATOR_DEST}}" \ - -derivedDataPath build/DerivedData \ + -derivedDataPath {{DERIVED_DATA}} \ + {{ if target != "" { "-only-testing " + target } else { "" } }} \ -parallel-testing-enabled YES \ -parallelizeTargets \ -jobs {{BUILD_THREADS}} \ - test | xcbeautify {{XCBEAUTIFY_ARGS}} + {{action}} | xcbeautify {{XCBEAUTIFY_ARGS}} + +test-all: (_test "test") + +test-without-building: (_test "test-without-building") + +# Example: just test PrimitivesTests +test TARGET: (_test "test" TARGET) test-ui: reset-simulator @set -o pipefail && xcodebuild -project Gem.xcodeproj \ @@ -107,29 +115,28 @@ test-ui: reset-simulator -testPlan ui_tests \ ONLY_ACTIVE_ARCH=YES \ -destination "{{SIMULATOR_DEST}}" \ + -derivedDataPath {{DERIVED_DATA}} \ -allowProvisioningUpdates \ -allowProvisioningDeviceRegistration \ test | xcbeautify {{XCBEAUTIFY_ARGS}} +test-ui-without-building: reset-simulator + @set -o pipefail && xcodebuild -project Gem.xcodeproj \ + -scheme GemUITests \ + -testPlan ui_tests \ + ONLY_ACTIVE_ARCH=YES \ + -destination "{{SIMULATOR_DEST}}" \ + -derivedDataPath {{DERIVED_DATA}} \ + -allowProvisioningUpdates \ + -allowProvisioningDeviceRegistration \ + test-without-building | xcbeautify {{XCBEAUTIFY_ARGS}} + reset-simulator NAME=SIMULATOR_NAME: @echo "==> Resetting {{NAME}} simulator to clean state" @xcrun simctl shutdown "{{NAME}}" 2>/dev/null || true @xcrun simctl erase "{{NAME}}" 2>/dev/null || true @xcrun simctl boot "{{NAME}}" 2>/dev/null || true -test TARGET: show-simulator - @set -o pipefail && xcodebuild -project Gem.xcodeproj \ - -scheme Gem \ - ONLY_ACTIVE_ARCH=YES \ - -destination "{{SIMULATOR_DEST}}" \ - -derivedDataPath build/DerivedData \ - -only-testing {{TARGET}} \ - -parallel-testing-enabled YES \ - -parallelizeTargets \ - -jobs {{BUILD_THREADS}} \ - test | xcbeautify {{XCBEAUTIFY_ARGS}} - - localize: @sh core/scripts/localize.sh ios Packages/Localization/Sources/Resources just generate-model