mirror of
https://github.com/stablyai/orca.git
synced 2026-11-15 02:17:31 +00:00
* Bound every pull request CI job with timeout-minutes * ci: bound the PR-triggered jobs added since #28784 with timeout-minutes Sized from recent run times: containers 1.2 min max, mac-native-owner-smoke 5.5, contract 1.2. Secret scan (1.8 max) and mobile_web_app (5.4 max) get roomier limits. * ci: check PR job time limits in code_paths so workflow-only PRs are covered A PR that changes only mobile.yml or cloud-verify.yml skips the root unit shards, so the timeout test never ran for it. Run the check from code_paths, which runs on every PR, as check-required-pr-context already does. * ci: use a uniform 3h ceiling on newly bounded PR jobs to stop runaway jobs The goal is only to stop jobs that would otherwise run to GitHub's 6h default, not to tune per-job limits. The guard keeps requiring a limit below 360 minutes on every PR job but no longer enforces a lower value. --------- Co-authored-by: Kelvin Amoaba <97001695+AmoabaKelvin@users.noreply.github.com> Co-authored-by: Neil <neil@stably.ai>
396 lines
17 KiB
YAML
396 lines
17 KiB
YAML
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/rpc/server/runtime-rpc.ts'
|
||
- 'src/main/runtime/rpc/server/pairing/device-registry.ts'
|
||
- 'src/main/runtime/orca-runtime.ts'
|
||
- 'src/main/runtime/agent-session-*.ts'
|
||
- 'src/main/runtime/agent-session/records/agent-session-*.ts'
|
||
- 'src/main/runtime/agent-session/agent-session-account-*.ts'
|
||
- 'src/main/runtime/agent-session/agent-session-acquisition-*.ts'
|
||
- 'src/main/runtime/agent-session/agent-session-conversation-*.ts'
|
||
- 'src/main/runtime/agent-session/agent-session-death-*.ts'
|
||
- 'src/main/runtime/agent-session/agent-session-launch-*.ts'
|
||
- 'src/main/runtime/agent-session/agent-session-operation-*.ts'
|
||
- 'src/main/runtime/agent-session/agent-session-rewind-*.ts'
|
||
- 'src/main/runtime/agent-session/agent-session-runtime-*.ts'
|
||
- 'src/main/runtime/agent-session/agent-session-unsaved-*.ts'
|
||
# The phone/host contract program's unmocked desktop sources and its declaration owner's inputs.
|
||
- 'src/main/runtime/integrations/github/runtime-github-repository-query-commands.ts'
|
||
- 'src/main/github/issue-field-options.ts'
|
||
- 'config/tsconfig.test.mobile-host-declarations.json'
|
||
- 'config/tsconfig.node.json'
|
||
- 'src/types/build-constants.d.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/mobile-web/check-entry/run-mobile-ci-tests.mjs'
|
||
# Mobile typechecks run through the root compiler selection.
|
||
- 'config/scripts/typecheck/project-execution/run-typecheck-projects-in-parallel.mjs'
|
||
- 'config/scripts/typecheck/project-execution/tsrs-typecheck-compiler.mjs'
|
||
- 'config/scripts/tool-invocation/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/workflow/source-routing/pr-code-change-scope.mjs'
|
||
- 'config/scripts/workflow/source-routing/pr-xterm-patch-prefixes.mjs'
|
||
- 'config/scripts/workflow/source-routing/pr-package-test-paths.mjs'
|
||
- 'config/scripts/workflow/source-routing/pr-layout-oracle-route.mjs'
|
||
- 'config/scripts/workflow/source-routing/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/rpc/server/runtime-rpc.ts'
|
||
- 'src/main/runtime/rpc/server/pairing/device-registry.ts'
|
||
- 'src/main/runtime/orca-runtime.ts'
|
||
- 'src/main/runtime/agent-session-*.ts'
|
||
- 'src/main/runtime/agent-session/records/agent-session-*.ts'
|
||
- 'src/main/runtime/agent-session/agent-session-account-*.ts'
|
||
- 'src/main/runtime/agent-session/agent-session-acquisition-*.ts'
|
||
- 'src/main/runtime/agent-session/agent-session-conversation-*.ts'
|
||
- 'src/main/runtime/agent-session/agent-session-death-*.ts'
|
||
- 'src/main/runtime/agent-session/agent-session-launch-*.ts'
|
||
- 'src/main/runtime/agent-session/agent-session-operation-*.ts'
|
||
- 'src/main/runtime/agent-session/agent-session-rewind-*.ts'
|
||
- 'src/main/runtime/agent-session/agent-session-runtime-*.ts'
|
||
- 'src/main/runtime/agent-session/agent-session-unsaved-*.ts'
|
||
# The phone/host contract program's unmocked desktop sources and its declaration owner's inputs.
|
||
- 'src/main/runtime/integrations/github/runtime-github-repository-query-commands.ts'
|
||
- 'src/main/github/issue-field-options.ts'
|
||
- 'config/tsconfig.test.mobile-host-declarations.json'
|
||
- 'config/tsconfig.node.json'
|
||
- 'src/types/build-constants.d.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/mobile-web/check-entry/run-mobile-ci-tests.mjs'
|
||
- 'config/scripts/typecheck/project-execution/run-typecheck-projects-in-parallel.mjs'
|
||
- 'config/scripts/typecheck/project-execution/tsrs-typecheck-compiler.mjs'
|
||
- 'config/scripts/tool-invocation/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
|
||
timeout-minutes: 180
|
||
|
||
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-web/check-entry/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/typecheck/project-execution/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. It then emits phone and host
|
||
# declarations and strictly checks the phone/host contract tests against them.
|
||
- 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-web/check-entry/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
|
||
|
||
# Compiler work (including the ratchet's declaration emission) finishes before Vitest workers start.
|
||
- wait: [production-types, test-types]
|
||
|
||
- name: Test
|
||
if: steps.test-scope.outputs.should_run != 'false'
|
||
env:
|
||
ORCA_BACKGROUND_LAUNCH: '1'
|
||
run: node ../config/scripts/mobile-web/check-entry/run-mobile-ci-tests.mjs
|
||
|
||
# The Ruby checks below read the completed fastlane install.
|
||
- wait: 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
|
||
|
||
# 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
|
||
timeout-minutes: 180
|
||
|
||
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/typecheck/project-execution/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
|
||
|
||
- wait: [production-types, test-types]
|
||
|
||
- name: Test
|
||
env:
|
||
ORCA_BACKGROUND_LAUNCH: '1'
|
||
run: node ../config/scripts/mobile-web/check-entry/run-mobile-ci-tests.mjs
|