E2E Staging (iOS) #25
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: E2E Staging (iOS) | |
| on: | |
| schedule: | |
| - cron: "0 4 * * *" | |
| workflow_dispatch: | |
| inputs: | |
| e2e_branch: | |
| description: "Branch of synonymdev/bitkit-e2e-tests to use (main | default-feature-branch | custom branch name)" | |
| required: false | |
| default: "default-feature-branch" | |
| post_to_slack: | |
| description: "Post E2E staging summary to Slack (#bitkit-staging-nightly)" | |
| type: boolean | |
| default: false | |
| required: false | |
| env: | |
| TERM: xterm-256color | |
| FORCE_COLOR: 1 | |
| GIT_LFS_SKIP_SMUDGE: "1" | |
| SIMULATOR_NAME: "iPhone 17" | |
| IOS_VERSION: "26.2" | |
| concurrency: | |
| group: ${{ github.workflow }}-${{ github.ref }}-${{ github.event_name }} | |
| cancel-in-progress: true | |
| jobs: | |
| build-staging: | |
| runs-on: macos-latest | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@v7 | |
| - name: Set up Xcode | |
| uses: maxim-lobanov/setup-xcode@v1 | |
| with: | |
| xcode-version: "26.2" | |
| - name: System Information | |
| run: | | |
| echo "=== System Information ===" | |
| echo "macOS Version:" | |
| sw_vers | |
| echo "" | |
| echo "Xcode Version:" | |
| xcodebuild -version | |
| - name: Install xcbeautify | |
| run: | | |
| brew install xcbeautify | |
| - name: Cache Swift Package Manager | |
| uses: actions/cache@v6 | |
| with: | |
| path: | | |
| ~/Library/Caches/org.swift.swiftpm | |
| ~/Library/org.swift.swiftpm | |
| Bitkit.xcodeproj/project.xcworkspace/xcshareddata/swiftpm | |
| key: ${{ runner.os }}-spm-${{ hashFiles('**/Package.resolved') }} | |
| - name: Install dependencies | |
| run: | | |
| echo "⏱️ Starting dependency resolution at $(date)" | |
| xcodebuild -resolvePackageDependencies -onlyUsePackageVersionsFromResolvedFile | xcbeautify | |
| echo "✅ Dependencies resolved at $(date)" | |
| - name: Pre-start simulator | |
| run: | | |
| echo "⏱️ Starting simulator at $(date)" | |
| xcrun simctl boot "${{ env.SIMULATOR_NAME }}" || true | |
| echo "✅ Simulator started at $(date)" | |
| - name: Build iOS app (regtest) | |
| env: | |
| GITHUB_ACTOR: ${{ github.actor }} | |
| GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| GEO: false | |
| E2E_BACKEND: network | |
| E2E_NETWORK: regtest | |
| run: | | |
| echo "=== Building iOS app (regtest) ===" | |
| echo "Using simulator: ${{ env.SIMULATOR_NAME }} (iOS ${{ env.IOS_VERSION }})" | |
| if xcodebuild -showsdks | grep -q "iOS Simulator"; then | |
| echo "✅ iOS Simulator platform already installed" | |
| else | |
| echo "⚙️ iOS Simulator platform not found — downloading..." | |
| xcodebuild -downloadPlatform iOS | |
| fi | |
| xcodebuild -workspace Bitkit.xcodeproj/project.xcworkspace \ | |
| -scheme Bitkit \ | |
| -configuration Debug \ | |
| -destination "platform=iOS Simulator,name=${{ env.SIMULATOR_NAME }},OS=${{ env.IOS_VERSION }}" \ | |
| -derivedDataPath DerivedData \ | |
| SWIFT_ACTIVE_COMPILATION_CONDITIONS='DEBUG E2E_BUILD' \ | |
| -allowProvisioningUpdates \ | |
| build | |
| - name: Prepare app for E2E tests (regtest) | |
| run: | | |
| mkdir -p e2e-app | |
| cp -r DerivedData/Build/Products/Debug-iphonesimulator/Bitkit.app e2e-app/bitkit.app | |
| - name: Upload iOS app (regtest) | |
| uses: actions/upload-artifact@v7 | |
| with: | |
| name: bitkit-e2e-ios-staging_${{ github.run_number }} | |
| path: e2e-app/ | |
| e2e-branch: | |
| uses: synonymdev/bitkit-e2e-tests/.github/workflows/determine-e2e-branch.yml@main | |
| with: | |
| app_branch: ${{ github.head_ref || github.ref_name }} | |
| e2e_branch_input: ${{ github.event.inputs.e2e_branch || 'default-feature-branch' }} | |
| e2e-tests-staging: | |
| runs-on: macos-latest | |
| timeout-minutes: 90 | |
| needs: [build-staging, e2e-branch] | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| shard: | |
| - { name: multi_address, grep: "@multi_address_staging" } | |
| - { name: pubky, grep: "@pubky_staging" } | |
| - { name: transfer, grep: "@transfer_staging" } | |
| name: e2e-tests-staging - ${{ matrix.shard.name }} | |
| env: | |
| BACKEND: regtest | |
| steps: | |
| - name: Resolve E2E tests ref | |
| id: e2e-ref | |
| uses: synonymdev/bitkit-e2e-tests/.github/actions/resolve-e2e-ref@main | |
| with: | |
| selected: ${{ needs.e2e-branch.outputs.branch }} | |
| e2e_branch_input: ${{ github.event.inputs.e2e_branch || 'default-feature-branch' }} | |
| - name: Clone E2E tests | |
| uses: actions/checkout@v7 | |
| with: | |
| repository: synonymdev/bitkit-e2e-tests | |
| path: bitkit-e2e-tests | |
| ref: ${{ steps.e2e-ref.outputs.ref }} | |
| - name: Download iOS app (regtest) | |
| uses: actions/download-artifact@v8 | |
| with: | |
| name: bitkit-e2e-ios-staging_${{ github.run_number }} | |
| path: bitkit-e2e-tests/aut | |
| - name: List iOS app directory contents | |
| run: ls -l bitkit-e2e-tests/aut | |
| - name: Setup Node.js | |
| uses: actions/setup-node@v7 | |
| with: | |
| node-version: 22 | |
| - name: Cache npm cache | |
| uses: actions/cache@v6 | |
| with: | |
| path: ~/.npm | |
| key: ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }} | |
| restore-keys: | | |
| ${{ runner.os }}-node- | |
| - name: Install dependencies | |
| working-directory: bitkit-e2e-tests | |
| run: npm ci | |
| - name: Install ffmpeg | |
| run: | | |
| echo "Installing ffmpeg with Homebrew..." | |
| brew install ffmpeg | |
| echo "ffmpeg version: $(ffmpeg -version | head -1)" | |
| - name: Boot Simulator | |
| run: | | |
| echo "Erasing simulator..." | |
| xcrun simctl erase "${{ env.SIMULATOR_NAME }}" || true | |
| echo "Booting simulator..." | |
| xcrun simctl boot "${{ env.SIMULATOR_NAME }}" || true | |
| echo "Waiting for boot status..." | |
| xcrun simctl bootstatus "${{ env.SIMULATOR_NAME }}" -b | |
| echo "Opening Simulator app to ensure UI is ready..." | |
| open -a Simulator | |
| echo "Waiting for simulator to fully initialize..." | |
| sleep 30 | |
| echo "Verifying simulator state..." | |
| xcrun simctl list devices booted | |
| - name: Run E2E Tests 1 (${{ matrix.shard.name }}) | |
| continue-on-error: true | |
| id: test1 | |
| working-directory: bitkit-e2e-tests | |
| run: ./ci_run_ios.sh --mochaOpts.grep '${{ matrix.shard.grep }}' | |
| env: | |
| SIMULATOR_NAME: ${{ env.SIMULATOR_NAME }} | |
| SIMULATOR_OS_VERSION: ${{ env.IOS_VERSION }} | |
| RECORD_VIDEO: true | |
| ATTEMPT: 1 | |
| - name: Run E2E Tests 2 (${{ matrix.shard.name }}) | |
| continue-on-error: true | |
| if: steps.test1.outcome != 'success' | |
| id: test2 | |
| working-directory: bitkit-e2e-tests | |
| run: ./ci_run_ios.sh --mochaOpts.grep "${{ matrix.shard.grep }}" | |
| env: | |
| SIMULATOR_NAME: ${{ env.SIMULATOR_NAME }} | |
| SIMULATOR_OS_VERSION: ${{ env.IOS_VERSION }} | |
| RECORD_VIDEO: true | |
| ATTEMPT: 2 | |
| - name: Reset iOS Simulator before attempt 3 | |
| if: steps.test1.outcome != 'success' && steps.test2.outcome != 'success' | |
| run: | | |
| echo "🔁 Resetting iOS simulator before attempt 3..." | |
| xcrun simctl shutdown all || true | |
| xcrun simctl erase "${{ env.SIMULATOR_NAME }}" || true | |
| xcrun simctl boot "${{ env.SIMULATOR_NAME }}" || true | |
| xcrun simctl bootstatus "${{ env.SIMULATOR_NAME }}" -b | |
| open -a Simulator | |
| sleep 15 | |
| xcrun simctl list devices booted | |
| - name: Run E2E Tests 3 (${{ matrix.shard.name }}) | |
| if: steps.test1.outcome != 'success' && steps.test2.outcome != 'success' | |
| id: test3 | |
| working-directory: bitkit-e2e-tests | |
| run: ./ci_run_ios.sh --mochaOpts.grep "${{ matrix.shard.grep }}" | |
| env: | |
| SIMULATOR_NAME: ${{ env.SIMULATOR_NAME }} | |
| SIMULATOR_OS_VERSION: ${{ env.IOS_VERSION }} | |
| RECORD_VIDEO: true | |
| ATTEMPT: 3 | |
| - name: Upload E2E Artifacts (${{ matrix.shard.name }}) | |
| if: failure() | |
| uses: actions/upload-artifact@v7 | |
| with: | |
| name: e2e-artifacts-staging_${{ matrix.shard.name }}_${{ github.run_number }} | |
| path: bitkit-e2e-tests/artifacts/ | |
| slack-report: | |
| if: >- | |
| always() && | |
| (github.event_name == 'schedule' || | |
| (github.event_name == 'workflow_dispatch' && inputs.post_to_slack == true)) | |
| runs-on: ubuntu-latest | |
| needs: [build-staging, e2e-branch, e2e-tests-staging] | |
| steps: | |
| - name: Resolve E2E tests ref | |
| id: e2e-ref | |
| continue-on-error: true | |
| uses: synonymdev/bitkit-e2e-tests/.github/actions/resolve-e2e-ref@main | |
| with: | |
| selected: ${{ needs.e2e-branch.outputs.branch }} | |
| e2e_branch_input: ${{ github.event.inputs.e2e_branch || 'default-feature-branch' }} | |
| - name: Checkout E2E tests | |
| uses: actions/checkout@v7 | |
| with: | |
| repository: synonymdev/bitkit-e2e-tests | |
| ref: ${{ steps.e2e-ref.outputs.ref || 'main' }} | |
| - name: Post Slack summary | |
| env: | |
| SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK_URL_STAGING }} | |
| PLATFORM: ios | |
| STAGING_RESULT: ${{ needs.build-staging.result == 'success' && needs.e2e-branch.result == 'success' && needs.e2e-tests-staging.result == 'success' && 'success' || 'failure' }} | |
| BUILD_RESULT: ${{ needs.build-staging.result }} | |
| E2E_BRANCH_RESULT: ${{ needs.e2e-branch.result }} | |
| E2E_TESTS_RESULT: ${{ needs.e2e-tests-staging.result }} | |
| RUN_URL: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }} | |
| RUN_ATTEMPT: ${{ github.run_attempt }} | |
| E2E_TESTS_REF: ${{ steps.e2e-ref.outputs.ref }} | |
| run: python3 scripts/slack_summary.py e2e-staging |