Files
orca/mobile/scripts/mobile-expo-cli.mjs
Jinjing 8a39450b18 refs/heads/handle-mobile-pull-request-issues (#6598)
* feat(mobile): add commit failure recovery panel with AI fix action

- Surfaces a "Commit failed" panel with a one-tap AI fix button when a
  git commit fails in the source control view or PR creation flow
- Detects commit failures specifically during the committing progress
  step and captures staged entries and commit message for context
- Extracts commit failure summary and prompt logic into
  `src/shared/source-control-commit-failure.ts` and PR checks prompt
  into `src/shared/pr-checks-fix-prompt.ts` so both desktop and mobile
  share the same implementations
- Adds auto-find of an available Metro port starting from 8081 and
  extracts expo CLI bootstrap into `mobile-expo-cli.mjs` shared by
  `start-emulator` and a new `start-expo.mjs` wrapper

* Share source-control AI prompts and simplify mobile PR actions

- Extract conflict, check-fixing, and commit-failure prompt builders
  to shared modules for reuse by both desktop and mobile.
- Configure Metro in the mobile package to watch and bundle modules
  from the repository-root shared directory.
- Remove the desktop-style merge method picker from the mobile PR
  actions panel, opting to use repository defaults automatically.
- Refactor mobile hosted review creation and git preparation logic
  into dedicated helper files.
2026-06-28 00:58:17 -07:00

58 lines
1.7 KiB
JavaScript

import { spawn } from 'node:child_process'
import { existsSync } from 'node:fs'
import path from 'node:path'
import process from 'node:process'
const expoBinNames =
process.platform === 'win32' ? ['expo.CMD', 'expo.cmd', 'expo.ps1', 'expo'] : ['expo']
function expoBinPaths(mobileDir) {
return expoBinNames.map((binName) => path.join(mobileDir, 'node_modules', '.bin', binName))
}
export function getMobileExpoExecutablePath(mobileDir) {
return expoBinPaths(mobileDir).find((binPath) => existsSync(binPath)) ?? null
}
function runPnpmInstall(mobileDir) {
return new Promise((resolve, reject) => {
const install = spawn('pnpm', ['install', '--frozen-lockfile'], {
cwd: mobileDir,
env: process.env,
shell: process.platform === 'win32',
stdio: 'inherit'
})
install.on('error', reject)
install.on('exit', (code, signal) => {
if (signal) {
reject(new Error(`pnpm install --frozen-lockfile was terminated by ${signal}`))
} else if (code === 0) {
resolve()
} else {
reject(new Error(`pnpm install --frozen-lockfile exited with code ${code}`))
}
})
})
}
export async function ensureMobileExpoCli(mobileDir, logger = {}) {
if (getMobileExpoExecutablePath(mobileDir)) {
return
}
const message = 'Mobile dependencies are missing; running pnpm install --frozen-lockfile...'
if (logger.logStep) {
logger.logStep('deps', message)
} else {
console.log(`[start] ${message}`)
}
await runPnpmInstall(mobileDir)
if (!getMobileExpoExecutablePath(mobileDir)) {
throw new Error('pnpm install completed, but node_modules/.bin/expo is still missing.')
}
logger.logSuccess?.('Mobile dependencies installed')
}