Files
orca/.github/workflows/mobile.yml
T
Neil a50a44bb8d feat(wsl): bridge sh/dash/ash panes report their folder (OSC 7) at every prompt (#35597)
* feat(wsl): bridge sh/dash/ash panes report their folder (OSC 7) at every prompt

bash, zsh, fish and nushell panes already tell the terminal daemon their
folder; a bridge pane whose login shell is sh, dash or busybox ash did
not, so restores fell back to the starting folder.

dash has no rcfile flag or prompt hook, but an interactive sh reads $ENV
after ~/.profile, and dash 0.5.8+ (plus ash and bash-as-sh) expand $(...)
in PS1. The bridge now points ENV at a new sh/env file in the published
wrapper tree, saving the user's own ENV. That file hands ENV back to the
user's value (so children see theirs), sources it, and inside WSL only
prefixes PS1 with the report. A root containing $, ` or \ is skipped,
since the shell expands ENV's value.

A non-interactive sh -c never reads ENV, and a missing file (Orca
updated away or uninstalled) is silently ignored by dash, ash and bash.

* fix(wsl): sh ENV hook survives quotes in the user's ENV and keeps prompt width

- The user's ENV is expanded through a here-document, so a value with a
  quote, $ or space no longer breaks startup with a syntax error.
- bash-as-sh and busybox ash (fancy prompt) get the report inside \[ \]
  so its invisible bytes don't count toward the prompt width; dash has no
  line editor to miscount and would print \[ literally, so it stays bare.
- Tests: a user ENV of `$HOME/u "q" sp/env`, a user PS1 with $, a quote
  and a backslash, and reports read through the daemon's WSL parser.
- CI: edits to the sh hook and the bridge launch trigger the shell
  contracts job (its prefix list moves to its own module, keeping the
  scope script under its line limit), and the sh and fish WSL pty tests
  leave the unit shards.

* ci: check out the shell-contract prefix module in the change detector

The detector job sparse-checks-out a fixed file list; the new
pr-shell-contract-prefixes.mjs that pr-code-change-scope.mjs imports was
missing from it, so the job failed with ERR_MODULE_NOT_FOUND. A contract
test now walks the scope script's local imports and requires each in
that list.

* ci: list the shell-contract prefix module wherever the scope script's modules are listed

Two config-script suites copy pr-code-change-scope.mjs and its sibling
modules into a fixture repo; without the new pr-shell-contract-prefixes.mjs
the copied script failed to load, and the detector fell back to running
everything. Also lists it with the scope script's other modules in the
mobile workflow trigger and the mobile non-test file set.
2026-10-28 21:56:13 -07:00

363 lines
14 KiB
YAML
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
name: Mobile Checks
on:
pull_request:
types:
- opened
- synchronize
- reopened
- ready_for_review
- converted_to_draft
paths:
- 'mobile/**'
# Route shared edits to mobile’s imports/RPC recordings/typecheck; root lockfile changes affect those modules’ root-resolved packages.
- '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'
# Rerun the only Fastfile-loading checks for release-workflow/Fastfile edits.
- '.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'
- 'config/scripts/pr-shell-contract-prefixes.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'
# Check matching source inputs on main too: independently passing PRs can conflict after merge, and verify is PR-only.
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:
# Key main concurrency by commit: GitHub replaces pending runs even with cancel-in-progress:false, hiding middle-merge regressions.
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
# Use ARM for pure Vitest; no x86 native toolchain is needed and Gemfile.lock’s ruby platform supports frozen install.
runs-on: ubuntu-24.04-arm
env:
# Freeze bundler to reject Gemfile drift before release jobs resolve different fastlane versions.
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
- name: Setup Ruby
id: ruby-setup
background: true
if: steps.ruby-scope.outputs.should_run != 'false'
uses: ruby/setup-ruby@v1
with:
ruby-version: '3.3'
working-directory: mobile
- name: Install dependencies
run: pnpm install --frozen-lockfile
- wait: ruby-setup
# ruby/setup-ruby's bundler-cache saves on every miss; the platform warmup saves this key on main.
- name: Resolve fastlane bundle cache
id: ruby-bundle
if: steps.ruby-scope.outputs.should_run != 'false'
env:
GEMFILE_HASH: ${{ hashFiles('mobile/Gemfile', 'mobile/Gemfile.lock') }}
run: |
. /etc/os-release
printf 'key=mobile-bundle-v1-%s-%s-%s-%s\n' "$ID-$VERSION_ID" "$(ruby -e 'print RUBY_PLATFORM')" "$(ruby -e 'print RbConfig::CONFIG["ruby_version"]')" "$GEMFILE_HASH" >> "$GITHUB_OUTPUT"
- name: Restore fastlane bundle
if: steps.ruby-scope.outputs.should_run != 'false'
uses: actions/cache/restore@v5
with:
path: mobile/vendor/bundle
key: ${{ steps.ruby-bundle.outputs.key }}
# Installing proves the release’s pinned fastlane still resolves before a release needs it.
- name: Install fastlane
id: ruby-tools
background: true
if: steps.ruby-scope.outputs.should_run != 'false'
run: |
bundle config set --local path "$PWD/vendor/bundle"
bundle config set --local deployment true
bundle install --jobs 4
# Check mobile import cycles after Expo deps install; pre-install pr.yml cannot load its tsconfig.
- 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
# Run bridged recording corpus unconditionally: reject growing/unclassified divergence and changed verdicts among 103 C1 goldens. Share worker time instead of a separate skippable env-gated step.
- 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
no-cache: true
- 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]
# Decode hash-addressed golden behavior changes for review, including after failed tests; advisory only.
- 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
# Load/list Fastfile lanes without Apple credentials/network to catch syntax/require/constants before release; ios-distribute failed six days without this guard.
- 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: ubuntu-24.04
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: ubuntu-24.04-arm
defaults:
run:
working-directory: mobile
steps:
- name: Checkout
uses: actions/checkout@v6
with:
persist-credentials: false
# Restoring the 650 MB store took longer than downloading these packages.
- uses: ./.github/actions/install-node-dependencies
with:
cache-pnpm-store: 'false'
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
# Run all golden consumers, including mutant/page-bridge suites; failures name the recording and rpc:record command.
- name: Setup Bun for tests
uses: oven-sh/setup-bun@0c5077e51419868618aeaa5fe8019c62421857d6 # v2.2.0
with:
bun-version-file: config/.bun-version
no-cache: true
- name: Test
env:
ORCA_BACKGROUND_LAUNCH: '1'
run: node ../config/scripts/run-mobile-ci-tests.mjs
- wait: [production-types, test-types]