08eadd8149
The single native pass resolved [".ios", ".android", ".native", ""], which models a platform that does not exist - on iOS Metro never falls back to .android files and vice versa. Replace it with tsconfig.check.ios.json and tsconfig.check.android.json, each mirroring Metro's real resolution order for its platform, alongside the existing web pass. pnpm typecheck now runs all three, and the lint workflow matrix runs them as separate jobs. The ambient check shims in src/platform are now excluded from passes they aren't written for (previously the web shims were silently included in the native pass via the "src" include glob), and a new Android-pass shim pins react-native-device-attest to its platform-neutral base class, whose Android variant omits the iOS-only getDeviceCheckToken static. The Android pass surfaced a real bug: Referrer.getReferrerInfo() is async on Android (the Play referrer API only exposes a promise) but sync on iOS/web, and the shared callers used it synchronously - so on Android the deepLink:referrerReceived metric fired with a Promise instead of data. The API is now uniformly promise-returning and the callers await it. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01BCuMKXWHuyGoNhTVAHBMyk
121 lines
4.3 KiB
YAML
121 lines
4.3 KiB
YAML
name: Lint
|
|
|
|
on:
|
|
pull_request:
|
|
push:
|
|
branches:
|
|
- main
|
|
concurrency:
|
|
group: '${{ github.workflow }}-${{ github.head_ref || github.ref }}'
|
|
cancel-in-progress: true
|
|
|
|
# These jobs only check out the repo and run checks, so read access to the
|
|
# repo contents is all the GITHUB_TOKEN needs.
|
|
permissions:
|
|
contents: read
|
|
|
|
jobs:
|
|
linting:
|
|
name: Run linters
|
|
runs-on: ubuntu-latest
|
|
strategy:
|
|
fail-fast: false
|
|
matrix:
|
|
job:
|
|
[lint, prettier, 'typecheck:ios', 'typecheck:android', 'typecheck:web']
|
|
steps:
|
|
- name: Check out Git repository
|
|
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
|
|
- name: Verify Node version pins match package.json
|
|
run: |
|
|
set -euo pipefail
|
|
expected=$(node -p "require('./package.json').engines.node.replace(/[^0-9.]/g, '')")
|
|
rc=0
|
|
check() {
|
|
if [ "$2" != "$expected" ]; then
|
|
echo "::error file=$1::Node version mismatch: $1 pins '$2' but package.json is '$expected'"
|
|
rc=1
|
|
fi
|
|
}
|
|
# FROM node:X.Y.Z - service runtime images
|
|
for f in Dockerfile.bskylink Dockerfile.bskyogcard; do
|
|
v=$(grep -oE 'FROM node:[0-9]+\.[0-9]+\.[0-9]+' "$f" | grep -oE '[0-9]+\.[0-9]+\.[0-9]+' | sort -u)
|
|
check "$f" "$v"
|
|
done
|
|
# ENV NODE_VERSION=X.Y.Z - Go images that nvm-install Node for the JS build stage
|
|
for f in Dockerfile.embedr; do
|
|
v=$(grep -oE 'NODE_VERSION=[0-9]+\.[0-9]+\.[0-9]+' "$f" | grep -oE '[0-9]+\.[0-9]+\.[0-9]+' | sort -u)
|
|
check "$f" "$v"
|
|
done
|
|
# eas.json "node": "X.Y.Z"
|
|
v=$(grep -oE '"node":[[:space:]]*"[0-9]+\.[0-9]+\.[0-9]+"' eas.json | grep -oE '[0-9]+\.[0-9]+\.[0-9]+' | sort -u)
|
|
check "eas.json" "$v"
|
|
exit $rc
|
|
- uses: pnpm/action-setup@0ebf47130e4866e96fce0953f49152a61190b271 # v6.0.9
|
|
- name: Install node
|
|
uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0
|
|
with:
|
|
node-version-file: package.json
|
|
cache: pnpm
|
|
- name: pnpm install
|
|
run: pnpm install --frozen-lockfile
|
|
- name: Check & compile i18n
|
|
run: pnpm intl:build
|
|
- name: Lint checks
|
|
run: pnpm ${{ matrix.job }}
|
|
# Aggregates the matrix results into a single stable check name so branch
|
|
# protection can require "Run linters" regardless of how many matrix jobs run.
|
|
# The result is asserted in `run` (not `if`) so a malformed expression can
|
|
# never silently skip the check and report a false pass.
|
|
linting-summary:
|
|
name: Run linters
|
|
if: always()
|
|
needs: [linting]
|
|
runs-on: ubuntu-latest
|
|
steps:
|
|
- name: Require linting to have succeeded
|
|
env:
|
|
RESULT: ${{ needs.linting.result }}
|
|
run: |
|
|
echo "linting result: $RESULT"
|
|
test "$RESULT" = "success"
|
|
testing:
|
|
name: Run tests
|
|
runs-on: ubuntu-latest
|
|
strategy:
|
|
fail-fast: false
|
|
matrix:
|
|
shard: [1, 2, 3, 4]
|
|
steps:
|
|
- name: Check out Git repository
|
|
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
|
|
- uses: pnpm/action-setup@0ebf47130e4866e96fce0953f49152a61190b271 # v6.0.9
|
|
- name: Install node
|
|
uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0
|
|
with:
|
|
node-version-file: package.json
|
|
cache: pnpm
|
|
- name: pnpm install
|
|
run: pnpm install --frozen-lockfile
|
|
- name: Check & compile i18n
|
|
run: pnpm intl:build
|
|
- name: Run tests
|
|
run: |
|
|
NODE_ENV=test pnpm test --forceExit --shard=${{ matrix.shard }}/${{ strategy.job-total }}
|
|
# Aggregates the sharded test results into a single stable check name so branch
|
|
# protection can require "Run tests" regardless of how many shards run.
|
|
# The result is asserted in `run` (not `if`) so a malformed expression can
|
|
# never silently skip the check and report a false pass.
|
|
testing-summary:
|
|
name: Run tests
|
|
if: always()
|
|
needs: [testing]
|
|
runs-on: ubuntu-latest
|
|
steps:
|
|
- name: Require testing to have succeeded
|
|
env:
|
|
RESULT: ${{ needs.testing.result }}
|
|
run: |
|
|
echo "testing result: $RESULT"
|
|
test "$RESULT" = "success"
|