name: CI on: push: branches: - master - '[0-9]+.[0-9]+.x' pull_request: branches: - "**" env: NX_CLOUD_ACCESS_TOKEN: ${{ secrets.NX_CLOUD_ACCESS_TOKEN }} NX_CLOUD_ENABLE_METRICS_COLLECTION: 'true' PNPM_HOME: ~/.pnpm # Pin corepack to the pnpm version from packageManager. Without this, corepack # falls back to "latest" in directories that have no packageManager field # (e.g. e2e temp dirs), pulling pnpm 11 and breaking install. COREPACK_DEFAULT_TO_LATEST: '0' jobs: main-linux: runs-on: ubuntu-latest env: NX_BATCH_MODE: 'true' NX_E2E_CI_CACHE_KEY: e2e-github-linux NX_DAEMON: 'true' NX_PERF_LOGGING: 'false' NX_VERBOSE_LOGGING: 'false' NX_NATIVE_LOGGING: 'false' NX_E2E_RUN_E2E: 'true' NX_CI_EXECUTION_ENV: 'linux' NX_CLOUD_NO_TIMEOUTS: 'true' NX_ALLOW_NON_CACHEABLE_DTE: 'true' NX_CLOUD_EXPERIMENTAL_POLLING: 'true' NX_CLOUD_CONTINUOUS_ASSIGNMENT: 'true' NX_CLOUD_VERBOSE_LOGGING: 'true' steps: - name: Checkout uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 with: fetch-depth: 0 filter: tree:0 - name: Set verbose logging from debug mode if: runner.debug == '1' run: echo "NX_VERBOSE_LOGGING=true" >> "$GITHUB_ENV" - name: Fetch Master run: git fetch origin master:master if: ${{ github.event_name == 'pull_request' }} - name: Set SHAs uses: nrwl/nx-set-shas@310288c04d90696f9f1bc27c5e3caea6642b53d4 # v5.0.0 with: main-branch-name: 'master' - name: Start CI Run run: npx nx-cloud@next start-ci-run --distribute-on="./.nx/workflows/dynamic-changesets.yaml" --stop-agents-after="e2e" - name: Setup dev tools with mise uses: jdx/mise-action@146a28175021df8ca24f8ee1828cc2a60f980bd5 # v3 - name: Enable corepack and install pnpm run: | corepack enable corepack prepare --activate - name: Get pnpm store directory id: pnpm-cache run: echo "STORE_PATH=$(pnpm store path)" >> $GITHUB_OUTPUT - name: Cache pnpm store uses: actions/cache@0400d5f644dc74513175e3cd8d07132dd4860809 # v4.2.4 with: path: ${{ steps.pnpm-cache.outputs.STORE_PATH }} key: ${{ runner.os }}-pnpm-store-${{ hashFiles('**/pnpm-lock.yaml') }} restore-keys: | ${{ runner.os }}-pnpm-store- - name: Setup Gradle uses: gradle/actions/setup-gradle@48b5f213c81028ace310571dc5ec0fbbca0b2947 # v4.4.3 - name: Install project dependencies run: pnpm install --frozen-lockfile - name: Restore .NET analyzer projects run: dotnet restore nx.sln - name: Nx Report run: pnpm nx report - name: Run Checks/Lint/Test/Build run: | pids=() pnpm nx record -- nx format:check & pids+=($!) pnpm nx record -- nx sync:check pids+=($!) pnpm nx build workspace-plugin && pnpm nx record -- pnpm nx-cloud conformance:check pids+=($!) pnpm nx run-many -t check-imports check-lock-files check-codeowners --parallel=1 --no-dte & pids+=($!) pnpm nx affected --targets=lint,test,build,e2e,e2e-ci,format-native,lint-native,gradle:build-ci,vale,run & pids+=($!) for pid in "${pids[@]}"; do wait "$pid" done timeout-minutes: 100 - name: Fix CI run: pnpm nx fix-ci if: failure() main-macos: runs-on: macos-latest concurrency: group: ${{ github.workflow }}-${{ github.ref }}${{ contains(github.event_name, 'push') && format('-{0}', github.sha) || '' }} cancel-in-progress: true env: NX_E2E_CI_CACHE_KEY: e2e-github-macos NX_PERF_LOGGING: 'false' NX_CI_EXECUTION_ENV: 'macos' SELECTED_PM: 'npm' steps: - name: Log concurrency info run: | echo "Concurrency group: ${{ github.workflow }}-${{ github.ref }}${{ contains(github.event_name, 'push') && format('-{0}', github.sha) || '' }}" echo "Concurrency cancel-in-progress: ${{ !contains(github.event_name, 'push') }}" echo "Concurrency cancel-event-name: ${{ github.event_name }}" if: always() - name: Checkout uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 with: fetch-depth: 0 filter: tree:0 - name: Set verbose logging from debug mode if: runner.debug == '1' run: echo "NX_VERBOSE_LOGGING=true" >> "$GITHUB_ENV" - name: Fetch Master run: git fetch origin master:master if: ${{ github.event_name == 'pull_request' }} - name: Setup dev tools with mise uses: jdx/mise-action@146a28175021df8ca24f8ee1828cc2a60f980bd5 # v3 - name: Enable corepack and install pnpm run: | corepack enable corepack prepare --activate - name: Set SHAs uses: nrwl/nx-set-shas@310288c04d90696f9f1bc27c5e3caea6642b53d4 # v5.0.0 with: main-branch-name: 'master' - name: Check for React Native changes id: check-changes run: | HAS_CHANGED=$(node ./scripts/check-react-native-changes.js $NX_BASE $NX_HEAD); if $HAS_CHANGED; then echo "has_changes=true" >> $GITHUB_OUTPUT echo "React Native projects are affected, will run macOS tests" else echo "has_changes=false" >> $GITHUB_OUTPUT echo "No React Native projects affected, skipping macOS tests" fi - name: Restore Homebrew packages if: steps.check-changes.outputs.has_changes == 'true' uses: actions/cache@0400d5f644dc74513175e3cd8d07132dd4860809 # v4.2.4 with: path: | /opt/homebrew ~/Library/Caches/Homebrew key: nrwl-nx-homebrew-packages - name: Configure Detox Environment, Install applesimutils if: steps.check-changes.outputs.has_changes == 'true' run: | # Ensure Xcode command line tools are installed and configured xcode-select --print-path || sudo xcode-select --reset sudo xcode-select -s /Applications/Xcode.app # Install or update applesimutils with error handling if ! brew list applesimutils &>/dev/null; then echo "Installing applesimutils..." HOMEBREW_NO_AUTO_UPDATE=1 brew tap wix/brew >/dev/null # Homebrew now refuses to load formulae from third-party taps unless trusted brew trust wix/brew HOMEBREW_NO_AUTO_UPDATE=1 brew install applesimutils >/dev/null || { echo "Failed to install applesimutils, retrying with update..." brew update brew trust wix/brew HOMEBREW_NO_AUTO_UPDATE=1 brew install applesimutils } else echo "Updating applesimutils..." HOMEBREW_NO_AUTO_UPDATE=1 brew upgrade applesimutils || true fi # Verify applesimutils installation applesimutils --version || (echo "applesimutils installation failed" && exit 1) # Configure environment for M-series Mac echo "DEVELOPER_DIR=/Applications/Xcode.app/Contents/Developer" >> $GITHUB_ENV echo "PLATFORM_NAME=iOS Simulator" >> $GITHUB_ENV # Set additional environment variables for better debugging echo "DETOX_DISABLE_TELEMETRY=1" >> $GITHUB_ENV echo "DETOX_LOG_LEVEL=trace" >> $GITHUB_ENV # Verify Xcode installation xcodebuild -version # List available simulators xcrun simctl list devices available timeout-minutes: 10 continue-on-error: false - name: Reset iOS Simulators if: steps.check-changes.outputs.has_changes == 'true' id: reset-simulators run: | echo "Resetting iOS Simulators..." # Kill simulator processes sudo killall -9 com.apple.CoreSimulator.CoreSimulatorService 2>/dev/null || true killall "Simulator" 2>/dev/null || true killall "iOS Simulator" 2>/dev/null || true # Wait for processes to terminate sleep 3 # Shutdown and erase all simulators (ignore failures) xcrun simctl shutdown all 2>/dev/null || true sleep 5 xcrun simctl erase all 2>/dev/null || true # If erase failed, try the nuclear option if xcrun simctl list devices | grep -q "Booted" 2>/dev/null; then echo "Standard reset failed, using nuclear option..." rm -rf ~/Library/Developer/CoreSimulator/Devices/* 2>/dev/null || true launchctl remove com.apple.CoreSimulator.CoreSimulatorService 2>/dev/null || true sleep 3 fi # Clean up additional directories rm -rf ~/Library/Developer/CoreSimulator/Caches/* 2>/dev/null || true rm -rf ~/Library/Logs/CoreSimulator/* 2>/dev/null || true rm -rf ~/Library/Developer/Xcode/DerivedData/* 2>/dev/null || true echo "Simulator reset completed" timeout-minutes: 5 continue-on-error: true - name: Verify Simulator Reset if: steps.check-changes.outputs.has_changes == 'true' && steps.reset-simulators.outcome == 'success' run: | # Verify CoreSimulator service restarted pgrep -fl "CoreSimulator" || (echo "CoreSimulator service not running" && exit 1) # Check simulator list is clean xcrun simctl list devices # Verify simulator runtime paths exist and are writable test -d ~/Library/Developer/CoreSimulator/Devices || (echo "Simulator devices directory missing" && exit 1) touch ~/Library/Developer/CoreSimulator/Devices/test || (echo "Simulator devices directory not writable" && exit 1) rm ~/Library/Developer/CoreSimulator/Devices/test timeout-minutes: 5 - name: Diagnose Simulator Reset Failure if: steps.check-changes.outputs.has_changes == 'true' && steps.reset-simulators.outcome == 'failure' run: | echo "Simulator reset failed. Collecting diagnostic information..." xcrun simctl list echo "Checking simulator logs..." ls -la ~/Library/Logs/CoreSimulator/ || echo "No simulator logs found" - name: Save Homebrew Cache if: steps.check-changes.outputs.has_changes == 'true' uses: actions/cache@0400d5f644dc74513175e3cd8d07132dd4860809 # v4.2.4 with: path: | /opt/homebrew ~/Library/Caches/Homebrew key: nrwl-nx-homebrew-packages - name: Get pnpm store directory if: steps.check-changes.outputs.has_changes == 'true' id: pnpm-cache-macos run: echo "STORE_PATH=$(pnpm store path)" >> $GITHUB_OUTPUT - name: Cache pnpm store if: steps.check-changes.outputs.has_changes == 'true' uses: actions/cache@0400d5f644dc74513175e3cd8d07132dd4860809 # v4.2.4 with: path: ${{ steps.pnpm-cache-macos.outputs.STORE_PATH }} key: ${{ runner.os }}-pnpm-store-${{ hashFiles('**/pnpm-lock.yaml') }} restore-keys: | ${{ runner.os }}-pnpm-store- - name: Install project dependencies if: steps.check-changes.outputs.has_changes == 'true' run: | pnpm install --frozen-lockfile pnpm playwright install --with-deps - name: Restore .NET packages if: steps.check-changes.outputs.has_changes == 'true' run: dotnet restore nx.sln - name: Run E2E Tests for macOS if: steps.check-changes.outputs.has_changes == 'true' run: | pnpm nx affected -t e2e-macos-local --parallel=1 --base=$NX_BASE --head=$NX_HEAD