mirror of
https://github.com/stablyai/orca.git
synced 2026-11-02 10:08:13 +00:00
358 lines
15 KiB
YAML
358 lines
15 KiB
YAML
name: Mobile Checks
|
|
|
|
on:
|
|
pull_request:
|
|
types:
|
|
- opened
|
|
- synchronize
|
|
- reopened
|
|
- ready_for_review
|
|
- converted_to_draft
|
|
paths:
|
|
- 'mobile/**'
|
|
# Why all of src/shared: mobile imports hundreds of its modules, directly and through the RPC
|
|
# recordings and the host params check, so any shared edit can move a golden or break mobile's
|
|
# typecheck. Why the root lockfile: those modules resolve their packages from the root install.
|
|
- 'src/shared/**'
|
|
# Mobile's Node RPC recording tools import this package.
|
|
- 'src/packages/process-host/**'
|
|
- 'pnpm-lock.yaml'
|
|
# Mobile launch contracts exercise the real host dispatcher and durable receipt store.
|
|
- 'src/main/agent-launch/**'
|
|
- 'src/main/runtime/rpc/**'
|
|
- 'src/main/runtime/runtime-rpc/**'
|
|
- 'src/main/runtime/runtime-rpc.ts'
|
|
- 'src/main/runtime/device-registry.ts'
|
|
- 'src/main/runtime/orca-runtime.ts'
|
|
- 'src/main/runtime/agent-session-*.ts'
|
|
- 'src/main/native-chat/agent-session-wire/**'
|
|
- 'src/main/runtime/structured-attention-original-delivery.test-fixture.ts'
|
|
# Why: this job holds the only checks that load the Fastfile, so edits to
|
|
# it or to the release workflow it guards must re-run them.
|
|
- '.github/workflows/mobile.yml'
|
|
- 'config/mobile-ci.vitest.config.mjs'
|
|
- 'config/scripts/run-mobile-ci-tests.mjs'
|
|
# Mobile typechecks run through the root compiler selection.
|
|
- 'config/scripts/run-typecheck-projects-in-parallel.mjs'
|
|
- 'config/scripts/tsrs-typecheck-compiler.mjs'
|
|
- 'config/scripts/pinned-bun-executable.mjs'
|
|
- 'config/oxlint-code-quality-native-plugins.json'
|
|
- 'config/.bun-version'
|
|
- '.github/actions/install-node-dependencies/**'
|
|
- '.github/actions/setup-pnpm/**'
|
|
- '.github/actions/restore-pnpm-verification/**'
|
|
- '.github/workflows/mobile-ios-release.yml'
|
|
- 'config/scripts/mobile-release-check-scope*'
|
|
- 'config/scripts/mobile-test-change-scope*'
|
|
- 'config/scripts/pr-code-change-scope.mjs'
|
|
- 'config/scripts/pr-package-test-paths.mjs'
|
|
- 'config/scripts/pr-layout-oracle-route.mjs'
|
|
# Desktop suites do not feed mobile; keep fixtures and test/toolchain config inputs.
|
|
- '!src/shared/**/*.test.[jt]s'
|
|
- '!src/shared/**/*.test.[jt]sx'
|
|
- '!src/shared/**/*.test.[cm][jt]s'
|
|
- '!src/packages/process-host/**/*.test.[jt]s'
|
|
- '!src/packages/process-host/**/*.test.[jt]sx'
|
|
- '!src/packages/process-host/**/*.test.[cm][jt]s'
|
|
- '!src/main/**/*.test.[jt]s'
|
|
- '!src/main/**/*.test.[jt]sx'
|
|
- '!src/main/**/*.test.[cm][jt]s'
|
|
# Why main too: two pull requests can each pass against their own base and disagree once both
|
|
# land, and `verify` never runs on main. The same source paths as above, less the CI inputs only
|
|
# `verify` reads.
|
|
push:
|
|
branches:
|
|
- main
|
|
paths:
|
|
- 'mobile/**'
|
|
- 'src/shared/**'
|
|
- 'src/packages/process-host/**'
|
|
- 'pnpm-lock.yaml'
|
|
- 'src/main/agent-launch/**'
|
|
- 'src/main/runtime/rpc/**'
|
|
- 'src/main/runtime/runtime-rpc/**'
|
|
- 'src/main/runtime/runtime-rpc.ts'
|
|
- 'src/main/runtime/device-registry.ts'
|
|
- 'src/main/runtime/orca-runtime.ts'
|
|
- 'src/main/runtime/agent-session-*.ts'
|
|
- 'src/main/native-chat/agent-session-wire/**'
|
|
- 'src/main/runtime/structured-attention-original-delivery.test-fixture.ts'
|
|
- '.github/workflows/mobile.yml'
|
|
- 'config/mobile-ci.vitest.config.mjs'
|
|
- 'config/scripts/run-mobile-ci-tests.mjs'
|
|
- 'config/scripts/run-typecheck-projects-in-parallel.mjs'
|
|
- 'config/scripts/tsrs-typecheck-compiler.mjs'
|
|
- 'config/scripts/pinned-bun-executable.mjs'
|
|
- 'config/.bun-version'
|
|
- '.github/actions/install-node-dependencies/**'
|
|
- '.github/actions/setup-pnpm/**'
|
|
# Desktop suites do not feed mobile; keep fixtures and test/toolchain config inputs.
|
|
- '!src/shared/**/*.test.[jt]s'
|
|
- '!src/shared/**/*.test.[jt]sx'
|
|
- '!src/shared/**/*.test.[cm][jt]s'
|
|
- '!src/packages/process-host/**/*.test.[jt]s'
|
|
- '!src/packages/process-host/**/*.test.[jt]sx'
|
|
- '!src/packages/process-host/**/*.test.[cm][jt]s'
|
|
- '!src/main/**/*.test.[jt]s'
|
|
- '!src/main/**/*.test.[jt]sx'
|
|
- '!src/main/**/*.test.[cm][jt]s'
|
|
|
|
concurrency:
|
|
# Per commit on main, not per branch. GitHub cancels any PENDING run in a group when a new one
|
|
# queues, whatever `cancel-in-progress` says, so one shared main group drops the middle merge of
|
|
# three -- and a merge that breaks main there is exactly what `main-tests` checks for.
|
|
group: mobile-${{ github.event.pull_request.number || github.sha }}
|
|
cancel-in-progress: true
|
|
|
|
permissions:
|
|
contents: read
|
|
|
|
jobs:
|
|
verify:
|
|
name: Mobile verify
|
|
if: github.event_name == 'pull_request' && github.event.pull_request.draft != true
|
|
# Why ARM: 209s of this job is Vitest and nothing here needs x86: no Android SDK, emulator, gradle,
|
|
# Hermes or Watchman, no docker, and no artifacts. The Gemfile.lock lists the generic `ruby`
|
|
# platform, so frozen bundler installs without an aarch64-linux entry.
|
|
runs-on: blacksmith-4vcpu-ubuntu-2404-arm
|
|
|
|
env:
|
|
# Why: an unfrozen bundler silently re-resolves when Gemfile.lock drifts
|
|
# from the Gemfile, which is how the release jobs could land on different
|
|
# fastlane versions in the first place. Fail here instead.
|
|
BUNDLE_FROZEN: 'true'
|
|
ORCA_MOBILE_TYPECHECK_COMPILER: 'bun'
|
|
|
|
defaults:
|
|
run:
|
|
working-directory: mobile
|
|
|
|
steps:
|
|
- name: Checkout
|
|
uses: actions/checkout@v6
|
|
with:
|
|
fetch-depth: 2
|
|
|
|
- uses: ./.github/actions/install-node-dependencies
|
|
with:
|
|
cache-pnpm-store: 'false'
|
|
cache-dependency-path: |
|
|
pnpm-lock.yaml
|
|
mobile/pnpm-lock.yaml
|
|
|
|
- name: Detect Ruby release inputs
|
|
id: ruby-scope
|
|
shell: bash
|
|
working-directory: .
|
|
run: |
|
|
# Keep deletions when release files move into an application directory.
|
|
if ! git diff --name-only --no-renames -z HEAD^1 HEAD > "$RUNNER_TEMP/mobile-release-changes"; then
|
|
echo 'should_run=true' >> "$GITHUB_OUTPUT"
|
|
elif ! node config/scripts/mobile-release-check-scope.mjs "$RUNNER_TEMP/mobile-release-changes"; then
|
|
echo 'should_run=true' >> "$GITHUB_OUTPUT"
|
|
fi
|
|
|
|
# bundler-cache installs mobile/Gemfile.lock, so this job is also what
|
|
# proves the pinned fastlane the release workflow depends on still
|
|
# resolves — before a release run finds out.
|
|
- name: Setup Ruby and fastlane
|
|
id: ruby-tools
|
|
background: true
|
|
if: steps.ruby-scope.outputs.should_run != 'false'
|
|
uses: ruby/setup-ruby@v1
|
|
with:
|
|
ruby-version: '3.3'
|
|
bundler-cache: true
|
|
working-directory: mobile
|
|
|
|
- name: Install dependencies
|
|
run: pnpm install --frozen-lockfile
|
|
|
|
# Why here: pr.yml runs these import rules before mobile's install, when mobile's tsconfig
|
|
# (which extends expo's) can't load, so its import cycles were never seen. Zero tolerance.
|
|
- name: Lint mobile imports with mobile dependencies installed
|
|
working-directory: .
|
|
run: node node_modules/oxlint/bin/oxlint --config config/oxlint-code-quality-native-plugins.json mobile --deny-warnings
|
|
|
|
# Call installed tools so pnpm's dependency refresh cannot race between checks.
|
|
- name: Typecheck
|
|
id: production-types
|
|
background: true
|
|
run: node ../config/scripts/run-typecheck-projects-in-parallel.mjs --compiler=bun --bun-threads=2 --project=mobile/tsconfig.json
|
|
|
|
# Why a ratchet and not the raw typecheck: mobile/tsconfig.json excludes test files, so until
|
|
# tsconfig.test.json existed nothing checked them, and at introduction 127 of the 632 had
|
|
# drifted. This fails when a test file that checks today stops checking, when a test leaves
|
|
# the program, and on @ts-nocheck; the baseline may only shrink.
|
|
- name: Typecheck tests (ratchet)
|
|
id: test-types
|
|
background: true
|
|
run: node scripts/check-tests-typecheck-ratchet.mjs
|
|
|
|
# This includes the bridged replay of the whole recording corpus, which used to be a second
|
|
# step of its own behind RPC_FOUNDATION_BRIDGE=1. A gate nobody can forget to set is the point:
|
|
# it fails when a divergence class grows, when a divergence lands in no class at all, or when
|
|
# one of the 103 goldens inside the C1 page closure changes the verdict it is pinned to. It is
|
|
# ~3 min of test time on its own, and Vitest runs it on a worker beside the rest of the suite,
|
|
# so folding it in costs a fraction of that in wall time and one step less to skip.
|
|
- name: Detect mobile test inputs
|
|
id: test-scope
|
|
shell: bash
|
|
working-directory: .
|
|
run: |
|
|
if ! git diff --name-only --no-renames -z HEAD^1 HEAD > "$RUNNER_TEMP/mobile-test-changes"; then
|
|
echo 'should_run=true' >> "$GITHUB_OUTPUT"
|
|
elif ! node config/scripts/mobile-test-change-scope.mjs "$RUNNER_TEMP/mobile-test-changes"; then
|
|
echo 'should_run=true' >> "$GITHUB_OUTPUT"
|
|
fi
|
|
|
|
- name: Setup Bun for tests
|
|
if: steps.test-scope.outputs.should_run != 'false'
|
|
uses: oven-sh/setup-bun@0c5077e51419868618aeaa5fe8019c62421857d6 # v2.2.0
|
|
with:
|
|
bun-version-file: config/.bun-version
|
|
|
|
- name: Test
|
|
if: steps.test-scope.outputs.should_run != 'false'
|
|
env:
|
|
ORCA_BACKGROUND_LAUNCH: '1'
|
|
run: node ../config/scripts/run-mobile-ci-tests.mjs
|
|
|
|
# All checks read the completed install; compilers need not hold up test workers.
|
|
- wait: [production-types, test-types, ruby-tools]
|
|
|
|
# Reports, never gates: the goldens are content-addressed JSON, so their raw diff is hashes.
|
|
# This decodes which recorded behaviour the pull request moves into the job summary, and runs
|
|
# after a red Test too, when a reviewer most wants it.
|
|
- name: Summarize RPC recording changes
|
|
if: ${{ !cancelled() }}
|
|
continue-on-error: true
|
|
run: pnpm run rpc:diff HEAD^1 --summary "$GITHUB_STEP_SUMMARY"
|
|
|
|
- name: Test iOS release version resolution
|
|
if: steps.ruby-scope.outputs.should_run != 'false'
|
|
run: ruby fastlane/ios_release_version_test.rb
|
|
|
|
- name: Test TestFlight lane arguments
|
|
if: steps.ruby-scope.outputs.should_run != 'false'
|
|
run: ruby fastlane/fastfile_testflight_arguments_test.rb
|
|
|
|
# Why: nothing else in CI loads the Fastfile, so a syntax error, a broken
|
|
# require, or an undefined constant only surfaces mid-release — the
|
|
# ios-distribute job failed every run for six days that way. `lanes` just
|
|
# loads and lists, so it needs no App Store Connect credentials and makes
|
|
# no network calls to Apple.
|
|
- name: Smoke-check the Fastfile
|
|
if: steps.ruby-scope.outputs.should_run != 'false'
|
|
env:
|
|
FASTLANE_SKIP_UPDATE_CHECK: '1'
|
|
FASTLANE_OPT_OUT_USAGE: '1'
|
|
run: bundle exec fastlane lanes
|
|
|
|
- name: Smoke-check CocoaPods
|
|
if: steps.ruby-scope.outputs.should_run != 'false'
|
|
run: bundle exec pod --version
|
|
|
|
- name: Lint
|
|
run: pnpm lint
|
|
|
|
- name: Check formatting
|
|
run: pnpm format:check
|
|
|
|
# Reports, never gates: flags in the job summary when a pull request changes the Expo fingerprint,
|
|
# i.e. dev clients need a native rebuild. Only mobile's install, without scripts: the fingerprint
|
|
# hashes project sources and dependency paths, never installed package contents.
|
|
native-fingerprint:
|
|
name: Mobile native fingerprint
|
|
if: github.event_name == 'pull_request' && github.event.pull_request.draft != true
|
|
runs-on: blacksmith-2vcpu-ubuntu-2404
|
|
timeout-minutes: 15
|
|
continue-on-error: true
|
|
|
|
defaults:
|
|
run:
|
|
working-directory: mobile
|
|
|
|
steps:
|
|
- name: Checkout
|
|
uses: actions/checkout@v6
|
|
with:
|
|
fetch-depth: 2
|
|
persist-credentials: false
|
|
|
|
- uses: actions/setup-node@v6
|
|
with:
|
|
node-version-file: package.json
|
|
package-manager-cache: false
|
|
|
|
- name: Setup pnpm
|
|
uses: ./.github/actions/setup-pnpm
|
|
|
|
# The base commit may predate the fingerprint tools, so run the head's copy against both.
|
|
- name: Compare native fingerprint with the base
|
|
shell: bash
|
|
run: |
|
|
set -euo pipefail
|
|
tools="$RUNNER_TEMP/native-fingerprint"
|
|
mkdir -p "$tools"
|
|
cp scripts/native-client.mjs scripts/native-build-cache.cjs "$tools/"
|
|
pnpm install --frozen-lockfile --ignore-scripts
|
|
node "$tools/native-client.mjs" fingerprint --project . --out "$tools/head.json"
|
|
git checkout --quiet --detach HEAD^1
|
|
pnpm install --frozen-lockfile --ignore-scripts
|
|
node "$tools/native-client.mjs" fingerprint --project . --out "$tools/base.json"
|
|
node "$tools/native-client.mjs" compare "$tools/base.json" "$tools/head.json" \
|
|
--project . --summary "$GITHUB_STEP_SUMMARY"
|
|
|
|
main-tests:
|
|
name: Mobile tests on main
|
|
env:
|
|
ORCA_MOBILE_TYPECHECK_COMPILER: 'bun'
|
|
if: github.event_name == 'push'
|
|
# Why ARM: the same pure-Node Vitest run `verify` makes on a pull request.
|
|
runs-on: blacksmith-4vcpu-ubuntu-2404-arm
|
|
|
|
defaults:
|
|
run:
|
|
working-directory: mobile
|
|
|
|
steps:
|
|
- name: Checkout
|
|
uses: actions/checkout@v6
|
|
with:
|
|
persist-credentials: false
|
|
|
|
- uses: ./.github/actions/install-node-dependencies
|
|
with:
|
|
cache-dependency-path: |
|
|
pnpm-lock.yaml
|
|
mobile/pnpm-lock.yaml
|
|
|
|
- name: Install dependencies
|
|
run: pnpm install --frozen-lockfile
|
|
|
|
- name: Typecheck
|
|
id: production-types
|
|
background: true
|
|
run: node ../config/scripts/run-typecheck-projects-in-parallel.mjs --compiler=bun --bun-threads=2 --project=mobile/tsconfig.json
|
|
|
|
- name: Typecheck tests (ratchet)
|
|
id: test-types
|
|
background: true
|
|
run: node scripts/check-tests-typecheck-ratchet.mjs
|
|
|
|
# The whole suite, not only the recordings: the mutant and page-bridge suites read the goldens
|
|
# too. A red run here names each golden and the `rpc:record` command; the author of the merge
|
|
# that turned it red re-records in a follow-up.
|
|
- name: Setup Bun for tests
|
|
uses: oven-sh/setup-bun@0c5077e51419868618aeaa5fe8019c62421857d6 # v2.2.0
|
|
with:
|
|
bun-version-file: config/.bun-version
|
|
|
|
- name: Test
|
|
env:
|
|
ORCA_BACKGROUND_LAUNCH: '1'
|
|
run: node ../config/scripts/run-mobile-ci-tests.mjs
|
|
|
|
- wait: [production-types, test-types]
|