Skip to content

fix(input): keep the keyboard dismissed after a drag that starts on the input #3080

fix(input): keep the keyboard dismissed after a drag that starts on the input

fix(input): keep the keyboard dismissed after a drag that starts on the input #3080

Workflow file for this run

name: CI
on:
push:
branches:
- main
pull_request:
branches:
- main
# The block renderers stack (#1026 → #1027 → #1028): its upper PRs target
# these branches until the one below merges. Drop once the stack is in.
- 'feat/block-renderers-*'
merge_group:
types:
- checks_requested
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
jobs:
changes:
runs-on: ubuntu-latest
outputs:
react-native: ${{ steps.filter.outputs.react-native }}
android: ${{ steps.filter.outputs.android }}
ios: ${{ steps.filter.outputs.ios }}
core: ${{ steps.filter.outputs.core }}
core-cpp: ${{ steps.filter.outputs.core-cpp }}
steps:
- name: Checkout
uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4.3.1
with:
fetch-depth: 0
- name: Detect changes
uses: dorny/paths-filter@d1c1ffe0248fe513906c8e24db8ea791d46f8590 # v3.0.3
id: filter
with:
filters: |
core:
- 'packages/core/**'
- 'package.json'
- '.github/**'
react-native:
- 'packages/react-native-enriched-markdown/**'
- 'packages/core/**'
- 'apps/react-native-example/**'
- 'apps/react-native-web-example/**'
- 'package.json'
- 'yarn.lock'
- '.nvmrc'
- '.yarnrc.yml'
- '.github/**'
android:
- 'packages/enriched-markdown-android/**'
- 'packages/core/**'
- 'vendor/vendor-grammars.mjs'
- 'vendor/gen-registry.mjs'
- 'vendor/grammar-versions.json'
- 'apps/android-example/**'
- 'package.json'
- 'yarn.lock'
- '.nvmrc'
- '.yarnrc.yml'
- '.github/**'
ios:
- 'packages/enriched-markdown-ios/**'
- 'packages/core/**'
- 'apps/ios-example/**'
- 'package.json'
- 'yarn.lock'
- '.nvmrc'
- '.yarnrc.yml'
- '.github/**'
core-cpp:
- 'packages/core/cpp/**'
- 'packages/react-native-enriched-markdown/src/web/wasm/**'
- 'scripts/fetch-md4c.sh'
- 'scripts/test-core-parser.sh'
- 'scripts/test-web-bundle.mjs'
- '.github/**'
# The parser is vendored from software-mansion-labs/md4c, so a sync can change
# how documents parse and can reintroduce a global symbol that collides with
# another embedded MD4C copy. Neither shows up in a native build.
core-parser:
needs: changes
if: needs.changes.outputs.core-cpp == 'true'
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4.3.1
- name: Setup
uses: ./.github/actions/setup
- name: Check the vendored parser and the AST it produces
run: ./scripts/test-core-parser.sh
# The web bundle is a committed build artifact that nothing rebuilds on
# install, so it silently falls behind packages/core/cpp.
- name: Check the committed WASM bundle against the same AST
run: node scripts/test-web-bundle.mjs
# Nothing else gates these sources: the clang-format hook is local and
# can be bypassed, and no other job formats packages/core/cpp.
- name: Check formatting
run: yarn lint-clang:core-parser
core-tests:
needs: changes
if: needs.changes.outputs.core == 'true'
runs-on: ubuntu-latest
strategy:
matrix:
include:
- build_type: RelWithDebInfo
sanitize: ''
- build_type: Debug
sanitize: ''
- build_type: Debug
sanitize: address,undefined
steps:
- name: Checkout
uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4.3.1
- name: Setup
uses: ./.github/actions/setup
- name: Lint C++ core formatting
if: matrix.build_type == 'RelWithDebInfo'
run: yarn workspace @enriched-markdown/core lint-clang
- name: Build and run C++ core tests (${{ matrix.build_type }}${{ matrix.sanitize && ', sanitized' || '' }})
env:
CORE_CMAKE_ARGS: -DCMAKE_BUILD_TYPE=${{ matrix.build_type }} -DCORE_SANITIZE=${{ matrix.sanitize }}
run: yarn core:test
rn-lint:
needs: changes
if: needs.changes.outputs.react-native == 'true'
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4.3.1
- name: Setup
uses: ./.github/actions/setup
- name: Lint files
run: yarn lint
- name: Typecheck files
run: yarn typecheck
# The web example resolves the library's `.web` files (moduleSuffixes),
# which the library's own typecheck never sees.
- name: Typecheck the web example
run: yarn workspace react-native-enriched-markdown-web-example typecheck
- name: Run unit tests
run: yarn test
rn-build-library:
needs: changes
if: needs.changes.outputs.react-native == 'true'
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4.3.1
- name: Setup
uses: ./.github/actions/setup
- name: Build package
run: yarn prepare
rn-build-android:
needs: changes
if: needs.changes.outputs.react-native == 'true'
runs-on: ubuntu-latest
env:
ANDROID_HOME: /usr/local/lib/android/sdk
ANDROID_SDK_ROOT: /usr/local/lib/android/sdk
TURBO_CACHE_DIR: .turbo/android
steps:
- name: Checkout
uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4.3.1
- name: Setup
uses: ./.github/actions/setup
- name: Build library and generate codegen
run: yarn prepare
- name: Cache turborepo for Android
uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4.3.0
with:
path: ${{ env.TURBO_CACHE_DIR }}
key: ${{ runner.os }}-turborepo-android-${{ hashFiles('yarn.lock', 'packages/react-native-enriched-markdown/android/**', 'packages/react-native-enriched-markdown/src/**', 'packages/core/cpp/**', 'apps/react-native-example/android/**') }}
restore-keys: |
${{ runner.os }}-turborepo-android-
- name: Check turborepo cache for Android
run: |
TURBO_CACHE_STATUS=$(yarn turbo run build:android \
--filter=react-native-enriched-markdown-example \
--cache-dir="${{ env.TURBO_CACHE_DIR }}" \
--dry=json | jq -r '.tasks[0].cache.status')
if [[ $TURBO_CACHE_STATUS == "HIT" ]]; then
echo "turbo_cache_hit=1" >> $GITHUB_ENV
fi
- name: Setup Android
if: env.turbo_cache_hit != 1
uses: ./.github/actions/setup-android
with:
gradle-wrapper-properties: apps/react-native-example/android/gradle/wrapper/gradle-wrapper.properties
- name: Build example for Android
env:
JAVA_OPTS: '-XX:MaxHeapSize=6g'
run: yarn turbo run build:android --cache-dir="${{ env.TURBO_CACHE_DIR }}"
rn-build-ios:
needs: changes
if: needs.changes.outputs.react-native == 'true'
runs-on: macos-latest-xlarge
env:
TURBO_CACHE_DIR: .turbo/ios
steps:
- name: Checkout
uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4.3.1
- name: Setup
uses: ./.github/actions/setup
- name: Build library
run: yarn prepare
- name: Set up Xcode
uses: maxim-lobanov/setup-xcode@ed7a3b1fda3918c0306d1b724322adc0b8cc0a90 # v1.7.0
with:
xcode-version: '26.3'
- name: Reset build folder and pods
run: rm -rf apps/react-native-example/build apps/react-native-example/ios/Pods apps/react-native-example/ios/Podfile.lock
- name: Cache turborepo for iOS
uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4.3.0
with:
path: ${{ env.TURBO_CACHE_DIR }}
key: ${{ runner.os }}-turborepo-ios-${{ hashFiles('yarn.lock', 'packages/react-native-enriched-markdown/ios/**', 'packages/react-native-enriched-markdown/src/**', 'packages/core/cpp/**', 'apps/react-native-example/ios/**') }}
restore-keys: |
${{ runner.os }}-turborepo-ios-
- name: Check turborepo cache for iOS
run: |
TURBO_CACHE_STATUS=$(yarn turbo run build:ios \
--filter=react-native-enriched-markdown-example \
--cache-dir="${{ env.TURBO_CACHE_DIR }}" \
--dry=json | jq -r '.tasks[0].cache.status')
if [[ $TURBO_CACHE_STATUS == "HIT" ]]; then
echo "turbo_cache_hit=1" >> $GITHUB_ENV
fi
- name: Restore cocoapods
if: env.turbo_cache_hit != 1
id: cocoapods-cache
uses: actions/cache/restore@0057852bfaa89a56745cba8c7296529d2fc39830 # v4.3.0
with:
path: |
**/ios/Pods
key: ${{ runner.os }}-cocoapods-${{ hashFiles('apps/react-native-example/ios/Podfile.lock') }}
restore-keys: |
${{ runner.os }}-cocoapods-
- name: Install cocoapods
if: env.turbo_cache_hit != 1
run: |
cd apps/react-native-example/ios
pod install
env:
NO_FLIPPER: 1
- name: Cache cocoapods
if: env.turbo_cache_hit != 1 && steps.cocoapods-cache.outputs.cache-hit != 'true'
uses: actions/cache/save@0057852bfaa89a56745cba8c7296529d2fc39830 # v4.3.0
with:
path: |
**/ios/Pods
key: ${{ steps.cocoapods-cache.outputs.cache-primary-key }}
- name: Build example for iOS
run: yarn turbo run build:ios --cache-dir="${{ env.TURBO_CACHE_DIR }}"
rn-android-unit-tests:
needs: changes
if: needs.changes.outputs.react-native == 'true'
runs-on: ubuntu-latest
env:
ANDROID_HOME: /usr/local/lib/android/sdk
ANDROID_SDK_ROOT: /usr/local/lib/android/sdk
TURBO_CACHE_DIR: .turbo/rn-android-test
steps:
- name: Checkout
uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4.3.1
- name: Setup
uses: ./.github/actions/setup
- name: Build library and generate codegen
run: yarn prepare
- name: Cache turborepo for RN Android unit tests
uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4.3.0
with:
path: ${{ env.TURBO_CACHE_DIR }}
key: ${{ runner.os }}-turborepo-rn-android-test-${{ hashFiles('yarn.lock', 'packages/react-native-enriched-markdown/android/**', 'packages/react-native-enriched-markdown/src/**', 'packages/core/cpp/**', 'apps/react-native-example/android/**') }}
restore-keys: |
${{ runner.os }}-turborepo-rn-android-test-
- name: Check turborepo cache for RN Android unit tests
run: |
TURBO_CACHE_STATUS=$(yarn test:android \
--cache-dir="${{ env.TURBO_CACHE_DIR }}" \
--dry=json | jq -r '.tasks[0].cache.status')
if [[ $TURBO_CACHE_STATUS == "HIT" ]]; then
echo "turbo_cache_hit=1" >> $GITHUB_ENV
fi
- name: Setup Android
if: env.turbo_cache_hit != 1
uses: ./.github/actions/setup-android
with:
gradle-wrapper-properties: apps/react-native-example/android/gradle/wrapper/gradle-wrapper.properties
- name: Run RN Android unit tests
env:
JAVA_OPTS: '-XX:MaxHeapSize=6g'
run: yarn test:android --cache-dir="${{ env.TURBO_CACHE_DIR }}"
rn-ios-unit-tests:
needs: changes
if: needs.changes.outputs.react-native == 'true'
runs-on: macos-latest-xlarge
env:
TURBO_CACHE_DIR: .turbo/rn-ios-test
steps:
- name: Checkout
uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4.3.1
- name: Setup
uses: ./.github/actions/setup
- name: Build library
run: yarn prepare
- name: Set up Xcode
uses: maxim-lobanov/setup-xcode@ed7a3b1fda3918c0306d1b724322adc0b8cc0a90 # v1.7.0
with:
xcode-version: '26.3'
- name: Reset build folder and pods
run: rm -rf apps/react-native-example/build apps/react-native-example/ios/Pods apps/react-native-example/ios/Podfile.lock
- name: Cache turborepo for RN iOS unit tests
uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4.3.0
with:
path: ${{ env.TURBO_CACHE_DIR }}
key: ${{ runner.os }}-turborepo-rn-ios-test-${{ hashFiles('yarn.lock', 'packages/react-native-enriched-markdown/ios/**', 'packages/react-native-enriched-markdown/src/**', 'packages/react-native-enriched-markdown/__tests__/ios/**', 'packages/core/cpp/**', 'apps/react-native-example/ios/**') }}
restore-keys: |
${{ runner.os }}-turborepo-rn-ios-test-
- name: Check turborepo cache for RN iOS unit tests
run: |
TURBO_CACHE_STATUS=$(yarn test:ios \
--cache-dir="${{ env.TURBO_CACHE_DIR }}" \
--dry=json | jq -r '.tasks[0].cache.status')
if [[ $TURBO_CACHE_STATUS == "HIT" ]]; then
echo "turbo_cache_hit=1" >> $GITHUB_ENV
fi
- name: Restore cocoapods
if: env.turbo_cache_hit != 1
id: cocoapods-cache
uses: actions/cache/restore@0057852bfaa89a56745cba8c7296529d2fc39830 # v4.3.0
with:
path: |
**/ios/Pods
key: ${{ runner.os }}-cocoapods-${{ hashFiles('apps/react-native-example/ios/Podfile.lock') }}
restore-keys: |
${{ runner.os }}-cocoapods-
- name: Install cocoapods
if: env.turbo_cache_hit != 1
run: |
cd apps/react-native-example/ios
pod install
env:
NO_FLIPPER: 1
- name: Cache cocoapods
if: env.turbo_cache_hit != 1 && steps.cocoapods-cache.outputs.cache-hit != 'true'
uses: actions/cache/save@0057852bfaa89a56745cba8c7296529d2fc39830 # v4.3.0
with:
path: |
**/ios/Pods
key: ${{ steps.cocoapods-cache.outputs.cache-primary-key }}
- name: Select iOS simulator
if: env.turbo_cache_hit != 1
run: |
UDID=$(xcrun simctl list devices available --json \
| jq -r '[.devices[] | .[] | select(.isAvailable and (.name | startswith("iPhone")))][0].udid')
if [[ -z "$UDID" || "$UDID" == "null" ]]; then
echo "No available iPhone simulator found"
xcrun simctl list devices
exit 1
fi
echo "IOS_SIMULATOR_UDID=$UDID" >> $GITHUB_ENV
- name: Run RN iOS unit tests
run: yarn test:ios --cache-dir="${{ env.TURBO_CACHE_DIR }}"
android-build:
needs: changes
if: needs.changes.outputs.android == 'true'
runs-on: ubuntu-latest
env:
ANDROID_HOME: /usr/local/lib/android/sdk
ANDROID_SDK_ROOT: /usr/local/lib/android/sdk
TURBO_CACHE_DIR: .turbo/android-native
steps:
- name: Checkout
uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4.3.1
- name: Setup
uses: ./.github/actions/setup
- name: Restore Android vendor files
uses: ./.github/actions/restore-android-vendor
- name: Cache turborepo for Android native
uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4.3.0
with:
path: ${{ env.TURBO_CACHE_DIR }}
key: ${{ runner.os }}-turborepo-android-native-build-${{ hashFiles('yarn.lock', 'packages/enriched-markdown-android/**', 'apps/android-example/**', 'packages/core/cpp/**', 'vendor/vendor-grammars.mjs', 'vendor/gen-registry.mjs', 'vendor/grammar-versions.json') }}
restore-keys: |
${{ runner.os }}-turborepo-android-native-build-
- name: Check turborepo cache for Android native build
run: |
TURBO_CACHE_STATUS=$(yarn turbo run build:android-native \
--filter=enriched-markdown-android-example \
--cache-dir="${{ env.TURBO_CACHE_DIR }}" \
--dry=json | jq -r '.tasks[0].cache.status')
if [[ $TURBO_CACHE_STATUS == "HIT" ]]; then
echo "turbo_cache_hit=1" >> $GITHUB_ENV
fi
- name: Setup Android
if: env.turbo_cache_hit != 1
uses: ./.github/actions/setup-android
with:
gradle-wrapper-properties: apps/android-example/gradle/wrapper/gradle-wrapper.properties
- name: Build Android example
env:
JAVA_OPTS: '-XX:MaxHeapSize=6g'
run: yarn turbo run build:android-native --filter=enriched-markdown-android-example --cache-dir="${{ env.TURBO_CACHE_DIR }}"
android-unit-tests:
needs: changes
if: needs.changes.outputs.android == 'true'
runs-on: ubuntu-latest
env:
ANDROID_HOME: /usr/local/lib/android/sdk
ANDROID_SDK_ROOT: /usr/local/lib/android/sdk
TURBO_CACHE_DIR: .turbo/android-native
steps:
- name: Checkout
uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4.3.1
- name: Setup
uses: ./.github/actions/setup
- name: Restore Android vendor files
uses: ./.github/actions/restore-android-vendor
- name: Cache turborepo for Android native tests
uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4.3.0
with:
path: ${{ env.TURBO_CACHE_DIR }}
key: ${{ runner.os }}-turborepo-android-native-test-${{ hashFiles('yarn.lock', 'packages/enriched-markdown-android/**', 'packages/core/cpp/**', 'vendor/vendor-grammars.mjs', 'vendor/gen-registry.mjs', 'vendor/grammar-versions.json') }}
restore-keys: |
${{ runner.os }}-turborepo-android-native-test-
- name: Check turborepo cache for Android native tests
run: |
TURBO_CACHE_STATUS=$(yarn test:android-native \
--cache-dir="${{ env.TURBO_CACHE_DIR }}" \
--dry=json | jq -r '.tasks[0].cache.status')
if [[ $TURBO_CACHE_STATUS == "HIT" ]]; then
echo "turbo_cache_hit=1" >> $GITHUB_ENV
fi
- name: Setup Android
if: env.turbo_cache_hit != 1
uses: ./.github/actions/setup-android
with:
gradle-wrapper-properties: packages/enriched-markdown-android/gradle/wrapper/gradle-wrapper.properties
- name: Run Android unit tests
env:
JAVA_OPTS: '-XX:MaxHeapSize=6g'
run: yarn test:android-native --cache-dir="${{ env.TURBO_CACHE_DIR }}"
android-kotlin-lint:
needs: changes
if: needs.changes.outputs.android == 'true'
runs-on: ubuntu-latest
env:
ANDROID_HOME: /usr/local/lib/android/sdk
ANDROID_SDK_ROOT: /usr/local/lib/android/sdk
TURBO_CACHE_DIR: .turbo/android-native
steps:
- name: Checkout
uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4.3.1
- name: Setup
uses: ./.github/actions/setup
- name: Restore Android vendor files
uses: ./.github/actions/restore-android-vendor
- name: Cache turborepo for Android native lint
uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4.3.0
with:
path: ${{ env.TURBO_CACHE_DIR }}
key: ${{ runner.os }}-turborepo-android-native-lint-${{ hashFiles('yarn.lock', 'packages/enriched-markdown-android/**') }}
restore-keys: |
${{ runner.os }}-turborepo-android-native-lint-
- name: Check turborepo cache for Android native lint
run: |
TURBO_CACHE_STATUS=$(yarn turbo run lint:android-native \
--filter=@enriched-markdown/android \
--cache-dir="${{ env.TURBO_CACHE_DIR }}" \
--dry=json | jq -r '.tasks[0].cache.status')
if [[ $TURBO_CACHE_STATUS == "HIT" ]]; then
echo "turbo_cache_hit=1" >> $GITHUB_ENV
fi
- name: Setup Android
if: env.turbo_cache_hit != 1
uses: ./.github/actions/setup-android
with:
gradle-wrapper-properties: packages/enriched-markdown-android/gradle/wrapper/gradle-wrapper.properties
- name: Run ktlint and Android Lint
run: yarn turbo run lint:android-native --filter=@enriched-markdown/android --cache-dir="${{ env.TURBO_CACHE_DIR }}"
ios-build:
needs: changes
if: needs.changes.outputs.ios == 'true'
runs-on: macos-latest-xlarge
env:
TURBO_CACHE_DIR: .turbo/ios-native
steps:
- name: Checkout
uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4.3.1
- name: Setup
uses: ./.github/actions/setup
- name: Restore iOS vendor files
uses: ./.github/actions/restore-ios-vendor
- name: Cache turborepo for iOS native build
uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4.3.0
with:
path: ${{ env.TURBO_CACHE_DIR }}
key: ${{ runner.os }}-turborepo-ios-native-build-${{ hashFiles('yarn.lock', 'packages/enriched-markdown-ios/**', 'apps/ios-example/**', 'packages/core/cpp/**') }}
restore-keys: |
${{ runner.os }}-turborepo-ios-native-build-
- name: Check turborepo cache for iOS native build
run: |
TURBO_CACHE_STATUS=$(yarn turbo run build:ios-native \
--filter=enriched-markdown-ios-example \
--cache-dir="${{ env.TURBO_CACHE_DIR }}" \
--dry=json | jq -r '.tasks[0].cache.status')
if [[ $TURBO_CACHE_STATUS == "HIT" ]]; then
echo "turbo_cache_hit=1" >> $GITHUB_ENV
fi
- name: Set up Xcode
if: env.turbo_cache_hit != 1
uses: maxim-lobanov/setup-xcode@ed7a3b1fda3918c0306d1b724322adc0b8cc0a90 # v1.7.0
with:
xcode-version: '26.3'
- name: Select iOS simulator
if: env.turbo_cache_hit != 1
run: |
UDID=$(xcrun simctl list devices available --json \
| jq -r '[.devices[] | .[] | select(.isAvailable and (.name | startswith("iPhone")))][0].udid')
if [[ -z "$UDID" || "$UDID" == "null" ]]; then
echo "No available iPhone simulator found"
xcrun simctl list devices
exit 1
fi
echo "IOS_SIMULATOR_UDID=$UDID" >> $GITHUB_ENV
- name: Build iOS example
run: yarn turbo run build:ios-native --filter=enriched-markdown-ios-example --cache-dir="${{ env.TURBO_CACHE_DIR }}"
ios-unit-tests:
needs: changes
if: needs.changes.outputs.ios == 'true'
runs-on: macos-latest
env:
TURBO_CACHE_DIR: .turbo/ios-native
steps:
- name: Checkout
uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4.3.1
- name: Setup
uses: ./.github/actions/setup
- name: Restore iOS vendor files
uses: ./.github/actions/restore-ios-vendor
- name: Cache turborepo for iOS native tests
uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4.3.0
with:
path: ${{ env.TURBO_CACHE_DIR }}
key: ${{ runner.os }}-turborepo-ios-native-test-${{ hashFiles('yarn.lock', 'packages/enriched-markdown-ios/**', 'packages/core/cpp/**') }}
restore-keys: |
${{ runner.os }}-turborepo-ios-native-test-
- name: Check turborepo cache for iOS native tests
run: |
TURBO_CACHE_STATUS=$(yarn test:ios-native \
--cache-dir="${{ env.TURBO_CACHE_DIR }}" \
--dry=json | jq -r '.tasks[0].cache.status')
if [[ $TURBO_CACHE_STATUS == "HIT" ]]; then
echo "turbo_cache_hit=1" >> $GITHUB_ENV
fi
- name: Set up Xcode
if: env.turbo_cache_hit != 1
uses: maxim-lobanov/setup-xcode@ed7a3b1fda3918c0306d1b724322adc0b8cc0a90 # v1.7.0
with:
xcode-version: '26.3'
- name: Select iOS simulator
if: env.turbo_cache_hit != 1
run: |
UDID=$(xcrun simctl list devices available --json \
| jq -r '[.devices[] | .[] | select(.isAvailable and (.name | startswith("iPhone")))][0].udid')
if [[ -z "$UDID" || "$UDID" == "null" ]]; then
echo "No available iPhone simulator found"
xcrun simctl list devices
exit 1
fi
echo "IOS_SIMULATOR_UDID=$UDID" >> $GITHUB_ENV
- name: Run iOS unit tests
run: yarn test:ios-native --cache-dir="${{ env.TURBO_CACHE_DIR }}"
ios-swift-lint:
needs: changes
if: needs.changes.outputs.ios == 'true'
runs-on: macos-latest
env:
TURBO_CACHE_DIR: .turbo/ios-native
SWIFTLINT_VERSION: 0.65.0
steps:
- name: Checkout
uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4.3.1
- name: Setup
uses: ./.github/actions/setup
- name: Restore iOS vendor files
uses: ./.github/actions/restore-ios-vendor
- name: Cache turborepo for iOS native lint
uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4.3.0
with:
path: ${{ env.TURBO_CACHE_DIR }}
key: ${{ runner.os }}-turborepo-ios-native-lint-${{ hashFiles('yarn.lock', 'packages/enriched-markdown-ios/**') }}
restore-keys: |
${{ runner.os }}-turborepo-ios-native-lint-
- name: Check turborepo cache for iOS native lint
run: |
TURBO_CACHE_STATUS=$(yarn turbo run lint:ios-native \
--filter=@enriched-markdown/ios \
--cache-dir="${{ env.TURBO_CACHE_DIR }}" \
--dry=json | jq -r '.tasks[0].cache.status')
if [[ $TURBO_CACHE_STATUS == "HIT" ]]; then
echo "turbo_cache_hit=1" >> $GITHUB_ENV
fi
- name: Install SwiftLint
if: env.turbo_cache_hit != 1
run: |
curl -fsSL -o "$RUNNER_TEMP/swiftlint.zip" \
"https://github.com/realm/SwiftLint/releases/download/${SWIFTLINT_VERSION}/portable_swiftlint.zip"
mkdir -p "$RUNNER_TEMP/swiftlint"
unzip -oq "$RUNNER_TEMP/swiftlint.zip" -d "$RUNNER_TEMP/swiftlint"
echo "$RUNNER_TEMP/swiftlint" >> $GITHUB_PATH
- name: Run Swift lint
run: yarn turbo run lint:ios-native --filter=@enriched-markdown/ios --cache-dir="${{ env.TURBO_CACHE_DIR }}"
ci-success:
needs:
- changes
- core-parser
- core-tests
- rn-lint
- rn-build-library
- rn-build-android
- rn-build-ios
- rn-android-unit-tests
- rn-ios-unit-tests
- android-build
- android-unit-tests
- android-kotlin-lint
- ios-build
- ios-unit-tests
- ios-swift-lint
if: always()
runs-on: ubuntu-latest
steps:
- name: Verify required checks
env:
REACT_NATIVE: ${{ needs.changes.outputs.react-native }}
ANDROID: ${{ needs.changes.outputs.android }}
IOS: ${{ needs.changes.outputs.ios }}
CORE_CPP: ${{ needs.changes.outputs.core-cpp }}
CORE_PARSER: ${{ needs.core-parser.result }}
CORE: ${{ needs.changes.outputs.core }}
CORE_TESTS: ${{ needs.core-tests.result }}
RN_LINT: ${{ needs.rn-lint.result }}
RN_BUILD_LIBRARY: ${{ needs.rn-build-library.result }}
RN_BUILD_ANDROID: ${{ needs.rn-build-android.result }}
RN_BUILD_IOS: ${{ needs.rn-build-ios.result }}
RN_ANDROID_UNIT_TESTS: ${{ needs.rn-android-unit-tests.result }}
RN_IOS_UNIT_TESTS: ${{ needs.rn-ios-unit-tests.result }}
ANDROID_BUILD: ${{ needs.android-build.result }}
ANDROID_UNIT_TESTS: ${{ needs.android-unit-tests.result }}
ANDROID_KOTLIN_LINT: ${{ needs.android-kotlin-lint.result }}
IOS_BUILD: ${{ needs.ios-build.result }}
IOS_UNIT_TESTS: ${{ needs.ios-unit-tests.result }}
IOS_SWIFT_LINT: ${{ needs.ios-swift-lint.result }}
CHANGES: ${{ needs.changes.result }}
run: |
if [[ "$CHANGES" != "success" ]]; then
echo "changes job failed"
exit 1
fi
check_required() {
local flag=$1
local result=$2
local name=$3
if [[ "$flag" == "true" && "$result" != "success" ]]; then
echo "Required job $name has result $result (expected success)"
exit 1
fi
}
if [[ "$REACT_NATIVE" != "true" && "$ANDROID" != "true" && "$IOS" != "true" && "$CORE_CPP" != "true" && "$CORE" != "true" ]]; then
echo "No relevant changes detected - CI passed"
exit 0
fi
check_required "$CORE_CPP" "$CORE_PARSER" "core-parser"
check_required "$CORE" "$CORE_TESTS" "core-tests"
check_required "$REACT_NATIVE" "$RN_LINT" "rn-lint"
check_required "$REACT_NATIVE" "$RN_BUILD_LIBRARY" "rn-build-library"
check_required "$REACT_NATIVE" "$RN_BUILD_ANDROID" "rn-build-android"
check_required "$REACT_NATIVE" "$RN_BUILD_IOS" "rn-build-ios"
check_required "$REACT_NATIVE" "$RN_ANDROID_UNIT_TESTS" "rn-android-unit-tests"
check_required "$REACT_NATIVE" "$RN_IOS_UNIT_TESTS" "rn-ios-unit-tests"
check_required "$ANDROID" "$ANDROID_BUILD" "android-build"
check_required "$ANDROID" "$ANDROID_UNIT_TESTS" "android-unit-tests"
check_required "$ANDROID" "$ANDROID_KOTLIN_LINT" "android-kotlin-lint"
check_required "$IOS" "$IOS_BUILD" "ios-build"
check_required "$IOS" "$IOS_UNIT_TESTS" "ios-unit-tests"
check_required "$IOS" "$IOS_SWIFT_LINT" "ios-swift-lint"
echo "All required checks passed"