mirror of
https://github.com/openai/codex.git
synced 2026-04-26 15:45:02 +00:00
When running with remote executor the cwd is the remote path. Today we check for existence of a local directory on startup and attempt to load config from it. For remote executors don't do that.
190 lines
4.9 KiB
Bash
Executable File
190 lines
4.9 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
|
|
set -euo pipefail
|
|
|
|
usage() {
|
|
echo "Usage: $0 HOST [RSYNC_OPTION]..." >&2
|
|
}
|
|
|
|
if [[ $# -lt 1 ]]; then
|
|
usage
|
|
exit 2
|
|
fi
|
|
|
|
case "$1" in
|
|
-h|--help)
|
|
usage
|
|
exit 0
|
|
;;
|
|
esac
|
|
|
|
remote_host="$1"
|
|
shift
|
|
|
|
remote_path='~/code/codex-sync'
|
|
local_exec_server_port="${CODEX_REMOTE_EXEC_SERVER_LOCAL_PORT:-8765}"
|
|
remote_exec_server_start_timeout_seconds="${CODEX_REMOTE_EXEC_SERVER_START_TIMEOUT_SECONDS:-15}"
|
|
|
|
remote_exec_server_pid=''
|
|
remote_exec_server_log_path=''
|
|
remote_exec_server_pid_path=''
|
|
remote_repo_root=''
|
|
|
|
cleanup() {
|
|
local exit_code=$?
|
|
|
|
trap - EXIT INT TERM
|
|
|
|
if [[ -n "${remote_exec_server_pid_path}" ]]; then
|
|
ssh "${remote_host}" \
|
|
"if [[ -f '${remote_exec_server_pid_path}' ]]; then kill \$(cat '${remote_exec_server_pid_path}') >/dev/null 2>&1 || true; fi; rm -f '${remote_exec_server_pid_path}' '${remote_exec_server_log_path}'" \
|
|
>/dev/null 2>&1 || true
|
|
fi
|
|
|
|
exit "${exit_code}"
|
|
}
|
|
|
|
trap cleanup EXIT INT TERM
|
|
|
|
if ! command -v git >/dev/null 2>&1; then
|
|
echo "git is required" >&2
|
|
exit 1
|
|
fi
|
|
|
|
if ! command -v ssh >/dev/null 2>&1; then
|
|
echo "ssh is required" >&2
|
|
exit 1
|
|
fi
|
|
|
|
if ! command -v rsync >/dev/null 2>&1; then
|
|
echo "local rsync is required" >&2
|
|
exit 1
|
|
fi
|
|
|
|
repo_root="$(git rev-parse --show-toplevel 2>/dev/null)" || {
|
|
echo "run this script from inside a git repository" >&2
|
|
exit 1
|
|
}
|
|
|
|
ssh "${remote_host}" "mkdir -p ${remote_path}"
|
|
|
|
if ! ssh "${remote_host}" 'command -v rsync >/dev/null 2>&1'; then
|
|
echo "remote rsync is required on ${remote_host}" >&2
|
|
exit 1
|
|
fi
|
|
|
|
sync_instance_id="$(date +%s)-$$"
|
|
|
|
rsync \
|
|
--archive \
|
|
--compress \
|
|
--human-readable \
|
|
--itemize-changes \
|
|
--exclude '.git/' \
|
|
--exclude 'codex-rs/target/' \
|
|
--filter=':- .gitignore' \
|
|
"$@" \
|
|
"${repo_root}/" \
|
|
"${remote_host}:${remote_path}/" \
|
|
>&2
|
|
|
|
remote_exec_server_log_path="/tmp/codex-exec-server-${sync_instance_id}.log"
|
|
remote_exec_server_pid_path="/tmp/codex-exec-server-${sync_instance_id}.pid"
|
|
|
|
remote_start_output="$(
|
|
ssh "${remote_host}" bash -s -- \
|
|
"${remote_exec_server_log_path}" \
|
|
"${remote_exec_server_pid_path}" \
|
|
"${remote_exec_server_start_timeout_seconds}" <<'EOF'
|
|
set -euo pipefail
|
|
|
|
remote_exec_server_log_path="$1"
|
|
remote_exec_server_pid_path="$2"
|
|
remote_exec_server_start_timeout_seconds="$3"
|
|
remote_repo_root="$HOME/code/codex-sync"
|
|
remote_codex_rs="$remote_repo_root/codex-rs"
|
|
|
|
cd "${remote_codex_rs}"
|
|
cargo build -p codex-exec-server --bin codex-exec-server
|
|
|
|
rm -f "${remote_exec_server_log_path}" "${remote_exec_server_pid_path}"
|
|
nohup ./target/debug/codex-exec-server --listen ws://127.0.0.1:0 \
|
|
>"${remote_exec_server_log_path}" 2>&1 &
|
|
remote_exec_server_pid="$!"
|
|
echo "${remote_exec_server_pid}" >"${remote_exec_server_pid_path}"
|
|
|
|
deadline=$((SECONDS + remote_exec_server_start_timeout_seconds))
|
|
while (( SECONDS < deadline )); do
|
|
if [[ -s "${remote_exec_server_log_path}" ]]; then
|
|
listen_url="$(head -n 1 "${remote_exec_server_log_path}" || true)"
|
|
if [[ "${listen_url}" == ws://* ]]; then
|
|
printf 'remote_exec_server_pid=%s\n' "${remote_exec_server_pid}"
|
|
printf 'remote_exec_server_log_path=%s\n' "${remote_exec_server_log_path}"
|
|
printf 'remote_repo_root=%s\n' "${remote_repo_root}"
|
|
printf 'listen_url=%s\n' "${listen_url}"
|
|
exit 0
|
|
fi
|
|
fi
|
|
|
|
if ! kill -0 "${remote_exec_server_pid}" >/dev/null 2>&1; then
|
|
cat "${remote_exec_server_log_path}" >&2 || true
|
|
echo "remote exec server exited before reporting a listen URL" >&2
|
|
exit 1
|
|
fi
|
|
|
|
sleep 0.1
|
|
done
|
|
|
|
cat "${remote_exec_server_log_path}" >&2 || true
|
|
echo "timed out waiting for remote exec server listen URL" >&2
|
|
exit 1
|
|
EOF
|
|
)"
|
|
|
|
listen_url=''
|
|
while IFS='=' read -r key value; do
|
|
case "${key}" in
|
|
remote_exec_server_pid)
|
|
remote_exec_server_pid="${value}"
|
|
;;
|
|
remote_exec_server_log_path)
|
|
remote_exec_server_log_path="${value}"
|
|
;;
|
|
remote_repo_root)
|
|
remote_repo_root="${value}"
|
|
;;
|
|
listen_url)
|
|
listen_url="${value}"
|
|
;;
|
|
esac
|
|
done <<< "${remote_start_output}"
|
|
|
|
if [[ -z "${remote_exec_server_pid}" || -z "${listen_url}" || -z "${remote_repo_root}" ]]; then
|
|
echo "failed to parse remote exec server startup output" >&2
|
|
exit 1
|
|
fi
|
|
|
|
remote_exec_server_port="${listen_url##*:}"
|
|
if [[ -z "${remote_exec_server_port}" || "${remote_exec_server_port}" == "${listen_url}" ]]; then
|
|
echo "failed to parse remote exec server port from ${listen_url}" >&2
|
|
exit 1
|
|
fi
|
|
|
|
echo "Remote exec server: ${listen_url}"
|
|
echo "Remote exec server log: ${remote_exec_server_log_path}"
|
|
echo "Press Ctrl-C to stop the SSH tunnel and remote exec server."
|
|
echo "Start codex via: "
|
|
printf ' CODEX_EXEC_SERVER_URL=ws://127.0.0.1:%s codex -C %q\n' \
|
|
"${local_exec_server_port}" \
|
|
"${remote_repo_root}"
|
|
|
|
ssh \
|
|
-nNT \
|
|
-o ControlMaster=no \
|
|
-o ControlPath=none \
|
|
-o ExitOnForwardFailure=yes \
|
|
-o ServerAliveInterval=30 \
|
|
-o ServerAliveCountMax=3 \
|
|
-L "${local_exec_server_port}:127.0.0.1:${remote_exec_server_port}" \
|
|
"${remote_host}"
|