From 5c676dfa664508c3e81f1dcc13a4aa3e991bc108 Mon Sep 17 00:00:00 2001 From: Radmir Date: Fri, 13 Mar 2026 13:41:25 +0500 Subject: [PATCH 1/8] Add upgrade tests workflow and UI test Add a GitHub Actions workflow (upgrade_tests.yml) to run upgrade verification on a self-hosted macOS runner: it creates a simulator, installs/builds an old tagged release to create a wallet, then checks out the current SHA and verifies the wallet survives the upgrade. Add a new UITest (UpgradeVerificationTests.swift) that asserts onboarding is skipped and the Bitcoin receive flow still shows the expected address. Update Gem.xcodeproj to include the new test file and extend the justfile to add test-upgrade-setup and test-upgrade-verify targets and allow running _test-ui for a specific test target. --- .github/workflows/upgrade_tests.yml | 77 +++++++++++++++++++ Gem.xcodeproj/project.pbxproj | 4 + .../UpgradeVerificationTests.swift | 30 ++++++++ justfile | 9 ++- 4 files changed, 119 insertions(+), 1 deletion(-) create mode 100644 .github/workflows/upgrade_tests.yml create mode 100644 GemUITestsAppTests/UpgradeVerificationTests.swift diff --git a/.github/workflows/upgrade_tests.yml b/.github/workflows/upgrade_tests.yml new file mode 100644 index 000000000..22a9772ec --- /dev/null +++ b/.github/workflows/upgrade_tests.yml @@ -0,0 +1,77 @@ +name: Upgrade Tests + +on: + workflow_dispatch: + inputs: + old_version: + description: "Old version tag to upgrade from" + required: true + default: "1.3.327" + +concurrency: + group: upgrade-tests-${{ github.ref }} + cancel-in-progress: false + +jobs: + upgrade_test: + name: Upgrade from ${{ github.event.inputs.old_version || '1.3.327' }} + runs-on: [self-hosted, macOS] + + env: + OLD_VERSION: ${{ github.event.inputs.old_version || '1.3.327' }} + + steps: + - name: Setup simulator for runner + run: | + SIMULATOR_NAME="${{ runner.name }}-iPhone" + echo "SIMULATOR_NAME=$SIMULATOR_NAME" >> $GITHUB_ENV + xcrun simctl list devices -j | jq -r ".devices[][] | select(.name == \"$SIMULATOR_NAME\") | .udid" | xargs -I {} xcrun simctl delete {} 2>/dev/null || true + xcrun simctl create "$SIMULATOR_NAME" "iPhone 17" + + # Phase 1: Install old version and create wallet + - name: Checkout old version + uses: actions/checkout@v4 + with: + ref: ${{ env.OLD_VERSION }} + submodules: true + + - name: Install dependencies (old) + run: just install-toolchains + + - name: Build Core (old) + run: just generate-stone + + - name: Resolve SPM Dependencies (old) + run: just spm-resolve + + - name: Build for Testing (old) + run: just build-for-testing-ui + + - name: Reset simulator + run: just reset-simulator + + - name: Create wallet on old version + run: just test-upgrade-setup + + # Phase 2: Upgrade to current version and verify + - name: Checkout current branch + uses: actions/checkout@v4 + with: + ref: ${{ github.sha }} + submodules: true + clean: false + + - name: Install dependencies (current) + run: just install-toolchains + + - name: Build Core (current) + run: just generate-stone + + - name: Resolve SPM Dependencies (current) + run: just spm-resolve + + - name: Build for Testing (current) + run: just build-for-testing-ui + + - name: Verify wallet survived upgrade + run: just test-upgrade-verify diff --git a/Gem.xcodeproj/project.pbxproj b/Gem.xcodeproj/project.pbxproj index 8cede2732..9e5a00a75 100644 --- a/Gem.xcodeproj/project.pbxproj +++ b/Gem.xcodeproj/project.pbxproj @@ -68,6 +68,7 @@ B6B86A102D702E7C00D31D65 /* SwapNavigationView.swift in Sources */ = {isa = PBXBuildFile; fileRef = B6B86A0F2D702E7C00D31D65 /* SwapNavigationView.swift */; }; B6C8F2AF2EDE2691005915E4 /* UITestKitConstants.swift in Sources */ = {isa = PBXBuildFile; fileRef = B6C8F2AD2EDE2691005915E4 /* UITestKitConstants.swift */; }; B6CBBC552ED9A80B0043443B /* CreateWalletUITests.swift in Sources */ = {isa = PBXBuildFile; fileRef = B6CBBC542ED9A80B0043443B /* CreateWalletUITests.swift */; }; + B6D1A0012EE3000000UPGRADE /* UpgradeVerificationTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = B6D1A0002EE3000000UPGRADE /* UpgradeVerificationTests.swift */; }; C30952B4299C39D70004C0F9 /* App.swift in Sources */ = {isa = PBXBuildFile; fileRef = C30952B3299C39D70004C0F9 /* App.swift */; }; C34C7CF829FDE942009EEC21 /* unit_frameworks.xctestplan in Resources */ = {isa = PBXBuildFile; fileRef = C34C7CF729FDE942009EEC21 /* unit_frameworks.xctestplan */; }; C35DA07C2A9C3B4B008CCEFA /* Settings in Frameworks */ = {isa = PBXBuildFile; productRef = C35DA07B2A9C3B4B008CCEFA /* Settings */; }; @@ -226,6 +227,7 @@ B6B86A0F2D702E7C00D31D65 /* SwapNavigationView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SwapNavigationView.swift; sourceTree = ""; }; B6C8F2AD2EDE2691005915E4 /* UITestKitConstants.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UITestKitConstants.swift; sourceTree = ""; }; B6CBBC542ED9A80B0043443B /* CreateWalletUITests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CreateWalletUITests.swift; sourceTree = ""; }; + B6D1A0002EE3000000UPGRADE /* UpgradeVerificationTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UpgradeVerificationTests.swift; sourceTree = ""; }; B6EA21D42E27E21700F1C849 /* Support */ = {isa = PBXFileReference; lastKnownFileType = wrapper; path = Support; sourceTree = ""; }; C30952B0299C39D70004C0F9 /* Gem.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Gem.app; sourceTree = BUILT_PRODUCTS_DIR; }; C30952B3299C39D70004C0F9 /* App.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = App.swift; sourceTree = ""; }; @@ -567,6 +569,7 @@ B68058302ED9C6F7001273D6 /* Extensions */, B69D9C852ED85EA000A04F7F /* ImportWalletReceiveBitcoinUITests.swift */, B6CBBC542ED9A80B0043443B /* CreateWalletUITests.swift */, + B6D1A0002EE3000000UPGRADE /* UpgradeVerificationTests.swift */, ); path = GemUITestsAppTests; sourceTree = ""; @@ -1169,6 +1172,7 @@ files = ( B69D9C872ED85EA000A04F7F /* ImportWalletReceiveBitcoinUITests.swift in Sources */, B6CBBC552ED9A80B0043443B /* CreateWalletUITests.swift in Sources */, + B6D1A0012EE3000000UPGRADE /* UpgradeVerificationTests.swift in Sources */, B68058312ED9C6F7001273D6 /* XCTestCase+GemUITestsAppTests.swift in Sources */, B6C8F2AF2EDE2691005915E4 /* UITestKitConstants.swift in Sources */, B68058322ED9C6F7001273D6 /* XCUIApplication+GemUITestsAppTests.swift in Sources */, diff --git a/GemUITestsAppTests/UpgradeVerificationTests.swift b/GemUITestsAppTests/UpgradeVerificationTests.swift new file mode 100644 index 000000000..dd34a48bc --- /dev/null +++ b/GemUITestsAppTests/UpgradeVerificationTests.swift @@ -0,0 +1,30 @@ +// Copyright (c). Gem Wallet. All rights reserved. + +import XCTest + +@MainActor +final class UpgradeVerificationTests: XCTestCase { + + override func setUpWithError() throws { + try super.setUpWithError() + continueAfterFailure = false + } + + func testWalletSurvivedUpgrade() throws { + let app = XCUIApplication() + setupPermissionHandler() + app.launch() + + XCTAssertFalse(app.isOnboarding, "App should not show onboarding after upgrade — wallet data was lost") + + // WalletScene + app.buttons["receive_button"].firstMatch.tap() + + // SelectAssetScene + app.buttons["Bitcoin, BTC"].firstMatch.tap() + + // ReceiveScene + app.buttons["Copy"].firstMatch.tap() + XCTAssertTrue(app.buttons[UITestKitConstants.bitcoinAddress].exists, "Bitcoin address mismatch after upgrade") + } +} diff --git a/justfile b/justfile index 118b9046a..5661484c2 100644 --- a/justfile +++ b/justfile @@ -120,7 +120,7 @@ test-without-building: (_test "test-without-building") # Example: just test PrimitivesTests test TARGET: (_test "test" TARGET) -_test-ui action: +_test-ui action target="": @set -o pipefail && xcodebuild -project Gem.xcodeproj \ -scheme GemUITests \ -testPlan ui_tests \ @@ -130,6 +130,7 @@ _test-ui action: -clonedSourcePackagesDirPath {{SPM_CACHE}} \ -allowProvisioningUpdates \ -allowProvisioningDeviceRegistration \ + {{ if target != "" { "-only-testing " + target } else { "" } }} \ {{action}} | xcbeautify {{XCBEAUTIFY_ARGS}} test-ui: reset-simulator (_test-ui "test") @@ -138,6 +139,12 @@ build-for-testing-ui: (_test-ui "build-for-testing") test-ui-without-building: reset-simulator (_test-ui "test-without-building") +# Run ImportWalletReceiveBitcoinUITests without building (phase 1 of upgrade test) +test-upgrade-setup: (_test-ui "test-without-building" "GemUITests/ImportWalletReceiveBitcoinUITests") + +# Run UpgradeVerificationTests without building and without resetting the simulator (phase 2 of upgrade test) +test-upgrade-verify: (_test-ui "test-without-building" "GemUITests/UpgradeVerificationTests") + reset-simulator NAME=SIMULATOR_NAME: @echo "==> Resetting {{NAME}} simulator to clean state" @xcrun simctl shutdown "{{NAME}}" 2>/dev/null || true From c75830c1ea76c3be6cd2a0dca91b2e8b704ab46e Mon Sep 17 00:00:00 2001 From: Radmir Date: Fri, 13 Mar 2026 13:57:37 +0500 Subject: [PATCH 2/8] Temporarily enable pull_request trigger for testing Add a pull_request trigger scoped to the main branch to exercise the upgrade_tests workflow on this branch. A TODO notes that the pull_request trigger should be removed before merging; workflow_dispatch inputs are unchanged. --- .github/workflows/upgrade_tests.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.github/workflows/upgrade_tests.yml b/.github/workflows/upgrade_tests.yml index 22a9772ec..e729a8e08 100644 --- a/.github/workflows/upgrade_tests.yml +++ b/.github/workflows/upgrade_tests.yml @@ -1,6 +1,9 @@ name: Upgrade Tests on: + # TODO: Remove pull_request trigger before merging — added only to test the workflow on this branch + pull_request: + branches: ["main"] workflow_dispatch: inputs: old_version: From a9aae64509289d03aa12ff249cc5fc3d43503205 Mon Sep 17 00:00:00 2001 From: Radmir Date: Fri, 13 Mar 2026 14:17:23 +0500 Subject: [PATCH 3/8] Use xcodebuild in upgrade_tests; bump default Update the upgrade_tests GitHub Actions workflow to use explicit xcodebuild commands for resolving packages, building UI tests, and running a targeted test, replacing several just tasks. Bump the default old_version input (and related env/job name) from 1.3.327 to 1.3.335 and clarify the input description (must be >= 1.3.328). Reorganize and rename steps to separate Phase 1 (build/run old version to create wallet) and Phase 2 (build/run current version to verify), and pipe xcodebuild output through xcbeautify for cleaner CI logs. --- .github/workflows/upgrade_tests.yml | 47 +++++++++++++++++++++-------- 1 file changed, 34 insertions(+), 13 deletions(-) diff --git a/.github/workflows/upgrade_tests.yml b/.github/workflows/upgrade_tests.yml index e729a8e08..8da83a5dc 100644 --- a/.github/workflows/upgrade_tests.yml +++ b/.github/workflows/upgrade_tests.yml @@ -7,9 +7,9 @@ on: workflow_dispatch: inputs: old_version: - description: "Old version tag to upgrade from" + description: "Old version tag to upgrade from (must be >= 1.3.328)" required: true - default: "1.3.327" + default: "1.3.335" concurrency: group: upgrade-tests-${{ github.ref }} @@ -17,11 +17,11 @@ concurrency: jobs: upgrade_test: - name: Upgrade from ${{ github.event.inputs.old_version || '1.3.327' }} + name: Upgrade from ${{ github.event.inputs.old_version || '1.3.335' }} runs-on: [self-hosted, macOS] env: - OLD_VERSION: ${{ github.event.inputs.old_version || '1.3.327' }} + OLD_VERSION: ${{ github.event.inputs.old_version || '1.3.335' }} steps: - name: Setup simulator for runner @@ -31,7 +31,7 @@ jobs: xcrun simctl list devices -j | jq -r ".devices[][] | select(.name == \"$SIMULATOR_NAME\") | .udid" | xargs -I {} xcrun simctl delete {} 2>/dev/null || true xcrun simctl create "$SIMULATOR_NAME" "iPhone 17" - # Phase 1: Install old version and create wallet + # Phase 1: Build and run old version to create wallet - name: Checkout old version uses: actions/checkout@v4 with: @@ -45,18 +45,39 @@ jobs: run: just generate-stone - name: Resolve SPM Dependencies (old) - run: just spm-resolve + run: xcodebuild -resolvePackageDependencies -project Gem.xcodeproj -scheme Gem -derivedDataPath build/DerivedData -clonedSourcePackagesDirPath build/SourcePackages - - name: Build for Testing (old) - run: just build-for-testing-ui + - name: Build for Testing UI (old) + run: | + set -o pipefail && xcodebuild -project Gem.xcodeproj \ + -scheme GemUITests \ + -testPlan ui_tests \ + ONLY_ACTIVE_ARCH=YES \ + -destination "platform=iOS Simulator,name=$SIMULATOR_NAME" \ + -derivedDataPath build/DerivedData \ + -clonedSourcePackagesDirPath build/SourcePackages \ + -allowProvisioningUpdates \ + -allowProvisioningDeviceRegistration \ + build-for-testing | xcbeautify --quieter --is-ci - name: Reset simulator run: just reset-simulator - - name: Create wallet on old version - run: just test-upgrade-setup - - # Phase 2: Upgrade to current version and verify + - name: "Phase 1: Create wallet on old version" + run: | + set -o pipefail && xcodebuild -project Gem.xcodeproj \ + -scheme GemUITests \ + -testPlan ui_tests \ + ONLY_ACTIVE_ARCH=YES \ + -destination "platform=iOS Simulator,name=$SIMULATOR_NAME" \ + -derivedDataPath build/DerivedData \ + -clonedSourcePackagesDirPath build/SourcePackages \ + -allowProvisioningUpdates \ + -allowProvisioningDeviceRegistration \ + -only-testing GemUITests/ImportWalletReceiveBitcoinUITests \ + test-without-building | xcbeautify --quieter --is-ci + + # Phase 2: Build and run current version to verify wallet survived - name: Checkout current branch uses: actions/checkout@v4 with: @@ -76,5 +97,5 @@ jobs: - name: Build for Testing (current) run: just build-for-testing-ui - - name: Verify wallet survived upgrade + - name: "Phase 2: Verify wallet survived upgrade" run: just test-upgrade-verify From fc6d65f078e6723134f194c02d28e165347eff36 Mon Sep 17 00:00:00 2001 From: Radmir Date: Fri, 13 Mar 2026 14:28:08 +0500 Subject: [PATCH 4/8] Add waitForExistence checks to UI upgrade test Improve stability of UpgradeVerificationTests by waiting for UI elements before interacting with them. Store buttons in local variables and assert their existence with timeouts (10s for asset and action buttons, 5s for the address) to reduce flakiness when tapping elements after an app upgrade. --- GemUITestsAppTests/UpgradeVerificationTests.swift | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/GemUITestsAppTests/UpgradeVerificationTests.swift b/GemUITestsAppTests/UpgradeVerificationTests.swift index dd34a48bc..d75082633 100644 --- a/GemUITestsAppTests/UpgradeVerificationTests.swift +++ b/GemUITestsAppTests/UpgradeVerificationTests.swift @@ -18,13 +18,19 @@ final class UpgradeVerificationTests: XCTestCase { XCTAssertFalse(app.isOnboarding, "App should not show onboarding after upgrade — wallet data was lost") // WalletScene - app.buttons["receive_button"].firstMatch.tap() + let receiveButton = app.buttons["receive_button"].firstMatch + XCTAssertTrue(receiveButton.waitForExistence(timeout: 10), "receive_button not found") + receiveButton.tap() // SelectAssetScene - app.buttons["Bitcoin, BTC"].firstMatch.tap() + let bitcoinButton = app.buttons["Bitcoin, BTC"].firstMatch + XCTAssertTrue(bitcoinButton.waitForExistence(timeout: 10), "Bitcoin asset not found") + bitcoinButton.tap() // ReceiveScene - app.buttons["Copy"].firstMatch.tap() - XCTAssertTrue(app.buttons[UITestKitConstants.bitcoinAddress].exists, "Bitcoin address mismatch after upgrade") + let copyButton = app.buttons["Copy"].firstMatch + XCTAssertTrue(copyButton.waitForExistence(timeout: 10), "Copy button not found") + copyButton.tap() + XCTAssertTrue(app.buttons[UITestKitConstants.bitcoinAddress].waitForExistence(timeout: 5), "Bitcoin address mismatch after upgrade") } } From eab27256124696b155df189f4b5eada33549d4b4 Mon Sep 17 00:00:00 2001 From: Radmir Date: Fri, 13 Mar 2026 15:12:13 +0500 Subject: [PATCH 5/8] Adjust UI test message and wallet service mock Refines tests to improve clarity and stability. In UpgradeVerificationTests the Bitcoin asset assertion message was updated to mention 'after upgrade' and a subsequent bitcoin address existence assertion was removed (to avoid a brittle check). In WalletServiceTests the WalletService.mock is now created with an injected walletStore backed by a mocked DB pre-populated with the Ethereum chain so the test has the expected initial state for deleteLastWalletNotifiesObservers. --- GemUITestsAppTests/UpgradeVerificationTests.swift | 3 +-- .../WalletService/Tests/WalletServiceTests.swift | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/GemUITestsAppTests/UpgradeVerificationTests.swift b/GemUITestsAppTests/UpgradeVerificationTests.swift index d75082633..ed3bce1f2 100644 --- a/GemUITestsAppTests/UpgradeVerificationTests.swift +++ b/GemUITestsAppTests/UpgradeVerificationTests.swift @@ -24,13 +24,12 @@ final class UpgradeVerificationTests: XCTestCase { // SelectAssetScene let bitcoinButton = app.buttons["Bitcoin, BTC"].firstMatch - XCTAssertTrue(bitcoinButton.waitForExistence(timeout: 10), "Bitcoin asset not found") + XCTAssertTrue(bitcoinButton.waitForExistence(timeout: 10), "Bitcoin asset not found after upgrade") bitcoinButton.tap() // ReceiveScene let copyButton = app.buttons["Copy"].firstMatch XCTAssertTrue(copyButton.waitForExistence(timeout: 10), "Copy button not found") copyButton.tap() - XCTAssertTrue(app.buttons[UITestKitConstants.bitcoinAddress].waitForExistence(timeout: 5), "Bitcoin address mismatch after upgrade") } } diff --git a/Packages/FeatureServices/WalletService/Tests/WalletServiceTests.swift b/Packages/FeatureServices/WalletService/Tests/WalletServiceTests.swift index a86e6ab0f..43f869e88 100644 --- a/Packages/FeatureServices/WalletService/Tests/WalletServiceTests.swift +++ b/Packages/FeatureServices/WalletService/Tests/WalletServiceTests.swift @@ -217,7 +217,7 @@ struct WalletServiceTests { @Test func deleteLastWalletNotifiesObservers() async throws { let preferences = ObservablePreferences.mock() - let service = WalletService.mock(preferences: preferences) + let service = WalletService.mock(walletStore: .mock(db: .mockWithChains([.ethereum])), preferences: preferences) let wallet = try await service.loadOrCreateWallet( name: "Wallet", From dac6c06007cfd09945bd742e04c302011acca728 Mon Sep 17 00:00:00 2001 From: Radmir Date: Fri, 13 Mar 2026 15:28:06 +0500 Subject: [PATCH 6/8] Update upgrade verification UI test flow Replace the old Receive->SelectAsset->Copy flow with a Wallet-detail based verification. The test now navigates to the Wallets screen, opens wallet settings (gearshape), taps Show Secret Phrase, proceeds through the security reminder, and verifies the displayed secret phrase words against UITestKitConstants. This adapts the test to the updated UI and ensures the wallet keys were not corrupted after upgrade. --- .../UpgradeVerificationTests.swift | 35 +++++++++++-------- 1 file changed, 21 insertions(+), 14 deletions(-) diff --git a/GemUITestsAppTests/UpgradeVerificationTests.swift b/GemUITestsAppTests/UpgradeVerificationTests.swift index ed3bce1f2..640f8010c 100644 --- a/GemUITestsAppTests/UpgradeVerificationTests.swift +++ b/GemUITestsAppTests/UpgradeVerificationTests.swift @@ -17,19 +17,26 @@ final class UpgradeVerificationTests: XCTestCase { XCTAssertFalse(app.isOnboarding, "App should not show onboarding after upgrade — wallet data was lost") - // WalletScene - let receiveButton = app.buttons["receive_button"].firstMatch - XCTAssertTrue(receiveButton.waitForExistence(timeout: 10), "receive_button not found") - receiveButton.tap() - - // SelectAssetScene - let bitcoinButton = app.buttons["Bitcoin, BTC"].firstMatch - XCTAssertTrue(bitcoinButton.waitForExistence(timeout: 10), "Bitcoin asset not found after upgrade") - bitcoinButton.tap() - - // ReceiveScene - let copyButton = app.buttons["Copy"].firstMatch - XCTAssertTrue(copyButton.waitForExistence(timeout: 10), "Copy button not found") - copyButton.tap() + // Navigate to wallet detail + app.buttons["Wallet"].firstMatch.tap() + app.tapWalletBar() + + // WalletsScene + let gearButton = app.buttons["gearshape"].firstMatch + XCTAssertTrue(gearButton.waitForExistence(timeout: 10), "No wallets found after upgrade") + gearButton.tap() + + // WalletDetailScene + let showPhraseButton = app.buttons["Show Secret Phrase"].firstMatch + XCTAssertTrue(showPhraseButton.waitForExistence(timeout: 10), "Show Secret Phrase not found") + showPhraseButton.tap() + + // SecurityReminderScene + app.tapContinue() + + // ShowSecretDataScene + let expectedWords = UITestKitConstants.words.components(separatedBy: " ") + let displayedWords = app.getWords() + XCTAssertEqual(displayedWords, expectedWords, "Secret phrase mismatch after upgrade — keys were corrupted") } } From ec134c61a259f687ba50cb56e12c83267ff62277 Mon Sep 17 00:00:00 2001 From: Radmir Date: Tue, 17 Mar 2026 11:40:28 +0500 Subject: [PATCH 7/8] Replace CI upgrade test with local script Remove GitHub Actions workflow and consolidate upgrade test into a single `just test-upgrade ` command that uses git worktree for isolation. --- .github/workflows/upgrade_tests.yml | 101 --------------------------- build-system/scripts/upgrade-test.sh | 82 ++++++++++++++++++++++ justfile | 11 ++- 3 files changed, 86 insertions(+), 108 deletions(-) delete mode 100644 .github/workflows/upgrade_tests.yml create mode 100755 build-system/scripts/upgrade-test.sh diff --git a/.github/workflows/upgrade_tests.yml b/.github/workflows/upgrade_tests.yml deleted file mode 100644 index 8da83a5dc..000000000 --- a/.github/workflows/upgrade_tests.yml +++ /dev/null @@ -1,101 +0,0 @@ -name: Upgrade Tests - -on: - # TODO: Remove pull_request trigger before merging — added only to test the workflow on this branch - pull_request: - branches: ["main"] - workflow_dispatch: - inputs: - old_version: - description: "Old version tag to upgrade from (must be >= 1.3.328)" - required: true - default: "1.3.335" - -concurrency: - group: upgrade-tests-${{ github.ref }} - cancel-in-progress: false - -jobs: - upgrade_test: - name: Upgrade from ${{ github.event.inputs.old_version || '1.3.335' }} - runs-on: [self-hosted, macOS] - - env: - OLD_VERSION: ${{ github.event.inputs.old_version || '1.3.335' }} - - steps: - - name: Setup simulator for runner - run: | - SIMULATOR_NAME="${{ runner.name }}-iPhone" - echo "SIMULATOR_NAME=$SIMULATOR_NAME" >> $GITHUB_ENV - xcrun simctl list devices -j | jq -r ".devices[][] | select(.name == \"$SIMULATOR_NAME\") | .udid" | xargs -I {} xcrun simctl delete {} 2>/dev/null || true - xcrun simctl create "$SIMULATOR_NAME" "iPhone 17" - - # Phase 1: Build and run old version to create wallet - - name: Checkout old version - uses: actions/checkout@v4 - with: - ref: ${{ env.OLD_VERSION }} - submodules: true - - - name: Install dependencies (old) - run: just install-toolchains - - - name: Build Core (old) - run: just generate-stone - - - name: Resolve SPM Dependencies (old) - run: xcodebuild -resolvePackageDependencies -project Gem.xcodeproj -scheme Gem -derivedDataPath build/DerivedData -clonedSourcePackagesDirPath build/SourcePackages - - - name: Build for Testing UI (old) - run: | - set -o pipefail && xcodebuild -project Gem.xcodeproj \ - -scheme GemUITests \ - -testPlan ui_tests \ - ONLY_ACTIVE_ARCH=YES \ - -destination "platform=iOS Simulator,name=$SIMULATOR_NAME" \ - -derivedDataPath build/DerivedData \ - -clonedSourcePackagesDirPath build/SourcePackages \ - -allowProvisioningUpdates \ - -allowProvisioningDeviceRegistration \ - build-for-testing | xcbeautify --quieter --is-ci - - - name: Reset simulator - run: just reset-simulator - - - name: "Phase 1: Create wallet on old version" - run: | - set -o pipefail && xcodebuild -project Gem.xcodeproj \ - -scheme GemUITests \ - -testPlan ui_tests \ - ONLY_ACTIVE_ARCH=YES \ - -destination "platform=iOS Simulator,name=$SIMULATOR_NAME" \ - -derivedDataPath build/DerivedData \ - -clonedSourcePackagesDirPath build/SourcePackages \ - -allowProvisioningUpdates \ - -allowProvisioningDeviceRegistration \ - -only-testing GemUITests/ImportWalletReceiveBitcoinUITests \ - test-without-building | xcbeautify --quieter --is-ci - - # Phase 2: Build and run current version to verify wallet survived - - name: Checkout current branch - uses: actions/checkout@v4 - with: - ref: ${{ github.sha }} - submodules: true - clean: false - - - name: Install dependencies (current) - run: just install-toolchains - - - name: Build Core (current) - run: just generate-stone - - - name: Resolve SPM Dependencies (current) - run: just spm-resolve - - - name: Build for Testing (current) - run: just build-for-testing-ui - - - name: "Phase 2: Verify wallet survived upgrade" - run: just test-upgrade-verify diff --git a/build-system/scripts/upgrade-test.sh b/build-system/scripts/upgrade-test.sh new file mode 100755 index 000000000..14ed8f8ec --- /dev/null +++ b/build-system/scripts/upgrade-test.sh @@ -0,0 +1,82 @@ +#!/usr/bin/env bash +set -euo pipefail + +COMMIT="${1:?Usage: just upgrade-test }" +REPO_ROOT="$(git rev-parse --show-toplevel)" +WORKTREE_DIR="/tmp/gem-upgrade-test-$$" +SIMULATOR_NAME="${SIMULATOR_NAME:-iPhone 17}" +SIMULATOR_DEST="platform=iOS Simulator,name=$SIMULATOR_NAME" +OLD_DERIVED_DATA="$WORKTREE_DIR/build/DerivedData" +OLD_SPM_CACHE="$WORKTREE_DIR/build/SourcePackages" +BUILD_THREADS="$(sysctl -n hw.ncpu)" + +cleanup() { + echo "==> Cleaning up worktree" + cd "$REPO_ROOT" + git worktree remove --force "$WORKTREE_DIR" 2>/dev/null || true +} +trap cleanup EXIT + +echo "==> Phase 1: Build old version ($COMMIT)" + +git worktree add "$WORKTREE_DIR" "$COMMIT" +cd "$WORKTREE_DIR" +git submodule update --init + +echo "==> Generating stone (old)" +just generate-stone + +echo "==> Building old version for UI testing" +set -o pipefail && xcodebuild -project Gem.xcodeproj \ + -scheme GemUITests \ + -testPlan ui_tests \ + ONLY_ACTIVE_ARCH=YES \ + -destination "$SIMULATOR_DEST" \ + -derivedDataPath "$OLD_DERIVED_DATA" \ + -clonedSourcePackagesDirPath "$OLD_SPM_CACHE" \ + -allowProvisioningUpdates \ + -allowProvisioningDeviceRegistration \ + -parallelizeTargets \ + -jobs "$BUILD_THREADS" \ + build-for-testing | xcbeautify --quieter --is-ci + +echo "==> Resetting simulator" +cd "$REPO_ROOT" +just reset-simulator + +echo "==> Running ImportWalletReceiveBitcoinUITests (old version)" +cd "$WORKTREE_DIR" +set -o pipefail && xcodebuild -project Gem.xcodeproj \ + -scheme GemUITests \ + -testPlan ui_tests \ + ONLY_ACTIVE_ARCH=YES \ + -destination "$SIMULATOR_DEST" \ + -derivedDataPath "$OLD_DERIVED_DATA" \ + -clonedSourcePackagesDirPath "$OLD_SPM_CACHE" \ + -allowProvisioningUpdates \ + -allowProvisioningDeviceRegistration \ + -only-testing GemUITests/ImportWalletReceiveBitcoinUITests \ + test-without-building | xcbeautify --quieter --is-ci + +echo "==> Phase 2: Build current version" +cd "$REPO_ROOT" + +just build-for-testing-ui + +DERIVED_DATA="build/DerivedData" +SPM_CACHE="build/SourcePackages" + +echo "==> Running UpgradeVerificationTests (current version)" +set -o pipefail && xcodebuild -project Gem.xcodeproj \ + -scheme GemUITests \ + -testPlan ui_tests \ + ONLY_ACTIVE_ARCH=YES \ + -destination "$SIMULATOR_DEST" \ + -derivedDataPath "$DERIVED_DATA" \ + -clonedSourcePackagesDirPath "$SPM_CACHE" \ + -allowProvisioningUpdates \ + -allowProvisioningDeviceRegistration \ + -only-testing GemUITests/UpgradeVerificationTests \ + test-without-building | xcbeautify --quieter --is-ci + +echo "==> Upgrade test passed!" diff --git a/justfile b/justfile index 5661484c2..17bcd462e 100644 --- a/justfile +++ b/justfile @@ -120,7 +120,7 @@ test-without-building: (_test "test-without-building") # Example: just test PrimitivesTests test TARGET: (_test "test" TARGET) -_test-ui action target="": +_test-ui action: @set -o pipefail && xcodebuild -project Gem.xcodeproj \ -scheme GemUITests \ -testPlan ui_tests \ @@ -130,7 +130,6 @@ _test-ui action target="": -clonedSourcePackagesDirPath {{SPM_CACHE}} \ -allowProvisioningUpdates \ -allowProvisioningDeviceRegistration \ - {{ if target != "" { "-only-testing " + target } else { "" } }} \ {{action}} | xcbeautify {{XCBEAUTIFY_ARGS}} test-ui: reset-simulator (_test-ui "test") @@ -139,11 +138,9 @@ build-for-testing-ui: (_test-ui "build-for-testing") test-ui-without-building: reset-simulator (_test-ui "test-without-building") -# Run ImportWalletReceiveBitcoinUITests without building (phase 1 of upgrade test) -test-upgrade-setup: (_test-ui "test-without-building" "GemUITests/ImportWalletReceiveBitcoinUITests") - -# Run UpgradeVerificationTests without building and without resetting the simulator (phase 2 of upgrade test) -test-upgrade-verify: (_test-ui "test-without-building" "GemUITests/UpgradeVerificationTests") +# Run full upgrade test: build old version, create wallet, build current, verify wallet survives +test-upgrade COMMIT: + @bash build-system/scripts/upgrade-test.sh {{COMMIT}} reset-simulator NAME=SIMULATOR_NAME: @echo "==> Resetting {{NAME}} simulator to clean state" From 68bda9c9f42147d53c76165cf2758fa7118840cc Mon Sep 17 00:00:00 2001 From: Radmir Date: Wed, 18 Mar 2026 00:26:17 +0500 Subject: [PATCH 8/8] Remove SPM cache Update build-system/scripts/upgrade-test.sh to remove explicit SPM cache and parallel build settings. Deleted OLD_SPM_CACHE and SPM_CACHE variables and removed BUILD_THREADS. Also removed -clonedSourcePackagesDirPath, -parallelizeTargets and -jobs from xcodebuild invocations, simplifying the script's build/test commands. --- build-system/scripts/upgrade-test.sh | 8 -------- 1 file changed, 8 deletions(-) diff --git a/build-system/scripts/upgrade-test.sh b/build-system/scripts/upgrade-test.sh index 14ed8f8ec..f58cb38a0 100755 --- a/build-system/scripts/upgrade-test.sh +++ b/build-system/scripts/upgrade-test.sh @@ -7,8 +7,6 @@ WORKTREE_DIR="/tmp/gem-upgrade-test-$$" SIMULATOR_NAME="${SIMULATOR_NAME:-iPhone 17}" SIMULATOR_DEST="platform=iOS Simulator,name=$SIMULATOR_NAME" OLD_DERIVED_DATA="$WORKTREE_DIR/build/DerivedData" -OLD_SPM_CACHE="$WORKTREE_DIR/build/SourcePackages" -BUILD_THREADS="$(sysctl -n hw.ncpu)" cleanup() { echo "==> Cleaning up worktree" @@ -33,11 +31,8 @@ set -o pipefail && xcodebuild -project Gem.xcodeproj \ ONLY_ACTIVE_ARCH=YES \ -destination "$SIMULATOR_DEST" \ -derivedDataPath "$OLD_DERIVED_DATA" \ - -clonedSourcePackagesDirPath "$OLD_SPM_CACHE" \ -allowProvisioningUpdates \ -allowProvisioningDeviceRegistration \ - -parallelizeTargets \ - -jobs "$BUILD_THREADS" \ build-for-testing | xcbeautify --quieter --is-ci echo "==> Resetting simulator" @@ -52,7 +47,6 @@ set -o pipefail && xcodebuild -project Gem.xcodeproj \ ONLY_ACTIVE_ARCH=YES \ -destination "$SIMULATOR_DEST" \ -derivedDataPath "$OLD_DERIVED_DATA" \ - -clonedSourcePackagesDirPath "$OLD_SPM_CACHE" \ -allowProvisioningUpdates \ -allowProvisioningDeviceRegistration \ -only-testing GemUITests/ImportWalletReceiveBitcoinUITests \ @@ -64,7 +58,6 @@ cd "$REPO_ROOT" just build-for-testing-ui DERIVED_DATA="build/DerivedData" -SPM_CACHE="build/SourcePackages" echo "==> Running UpgradeVerificationTests (current version)" set -o pipefail && xcodebuild -project Gem.xcodeproj \ @@ -73,7 +66,6 @@ set -o pipefail && xcodebuild -project Gem.xcodeproj \ ONLY_ACTIVE_ARCH=YES \ -destination "$SIMULATOR_DEST" \ -derivedDataPath "$DERIVED_DATA" \ - -clonedSourcePackagesDirPath "$SPM_CACHE" \ -allowProvisioningUpdates \ -allowProvisioningDeviceRegistration \ -only-testing GemUITests/UpgradeVerificationTests \