Add session resuming
This commit is contained in:
@@ -107,6 +107,7 @@ Targets are supplied after the code directory (or via `default_targets` in the m
|
||||
| `build-if-missing` | No-op when the image already exists; otherwise delegates to `build`. |
|
||||
| `rebuild` | Rebuild the image from scratch (`--no-cache`). |
|
||||
| `run` | Default goal. Runs the container with Codex as entrypoint and passes `codex_args`. |
|
||||
| `resume <session-id>` | Continues a Codex session by running `codex resume <session-id>` inside the container (builds if needed). |
|
||||
| `login` | Starts Codex in login mode to bootstrap `${HOME}/.codex`. |
|
||||
| `shell` | Launches `/bin/bash` inside the container for debugging. |
|
||||
| `stop` | Best-effort stop of the running container (if any). |
|
||||
|
||||
53
sloptrap
53
sloptrap
@@ -30,6 +30,8 @@ print_styled() {
|
||||
for arg in "$@"; do
|
||||
colored_args+=("$COLOR_HIGHLIGHT$arg$color")
|
||||
done
|
||||
# Format strings are defined within sloptrap, not user input.
|
||||
# shellcheck disable=SC2059
|
||||
printf "$fmt" "${colored_args[@]}"
|
||||
else
|
||||
printf '%b' "$fmt"
|
||||
@@ -50,6 +52,8 @@ print_styled_err() {
|
||||
for arg in "$@"; do
|
||||
colored_args+=("$COLOR_HIGHLIGHT$arg$color")
|
||||
done
|
||||
# Format strings are defined within sloptrap, not user input.
|
||||
# shellcheck disable=SC2059
|
||||
printf "$fmt" "${colored_args[@]}" >&2
|
||||
else
|
||||
printf '%b' "$fmt" >&2
|
||||
@@ -121,6 +125,7 @@ usage() {
|
||||
info_line "\n"
|
||||
info_line "Example targets:\n"
|
||||
comment_line " run Build if needed, then launch Codex\n"
|
||||
comment_line " resume <id> Build if needed, then run 'codex resume <id>'\n"
|
||||
comment_line " shell Drop into an interactive /bin/bash session\n"
|
||||
comment_line " clean Remove the project container/image cache\n"
|
||||
comment_line " prune Remove dangling/unused sloptrap images\n"
|
||||
@@ -1026,17 +1031,25 @@ prune_sloptrap_images() {
|
||||
run_or_print "${cmd[@]}"
|
||||
}
|
||||
|
||||
run_codex() {
|
||||
if ! $DRY_RUN; then
|
||||
status_line "Running %s\n" "$SLOPTRAP_IMAGE_NAME"
|
||||
fi
|
||||
run_codex_command() {
|
||||
local -a extra_args=("$@")
|
||||
local -a cmd=("${BASE_CONTAINER_CMD[@]}" "$SLOPTRAP_IMAGE_NAME")
|
||||
if [[ ${#CODEX_ARGS_ARRAY[@]} -gt 0 ]]; then
|
||||
cmd+=("${CODEX_ARGS_ARRAY[@]}")
|
||||
fi
|
||||
if [[ ${#extra_args[@]} -gt 0 ]]; then
|
||||
cmd+=("${extra_args[@]}")
|
||||
fi
|
||||
run_or_print "${cmd[@]}"
|
||||
}
|
||||
|
||||
run_codex() {
|
||||
if ! $DRY_RUN; then
|
||||
status_line "Running %s\n" "$SLOPTRAP_IMAGE_NAME"
|
||||
fi
|
||||
run_codex_command
|
||||
}
|
||||
|
||||
run_login_target() {
|
||||
if ! $DRY_RUN; then
|
||||
status_line "Login %s\n" "$SLOPTRAP_IMAGE_NAME"
|
||||
@@ -1053,6 +1066,23 @@ run_shell_target() {
|
||||
run_or_print "${cmd[@]}"
|
||||
}
|
||||
|
||||
run_resume_target() {
|
||||
local session_id=$1
|
||||
if ! $DRY_RUN; then
|
||||
status_line "Resume %s (%s)\n" "$SLOPTRAP_IMAGE_NAME" "$session_id"
|
||||
fi
|
||||
run_codex_command resume "$session_id"
|
||||
}
|
||||
|
||||
process_resume_target() {
|
||||
local session_id=$1
|
||||
if [[ -z $session_id ]]; then
|
||||
error "target 'resume' requires a session identifier"
|
||||
fi
|
||||
build_if_missing
|
||||
run_resume_target "$session_id"
|
||||
}
|
||||
|
||||
dispatch_target() {
|
||||
local target=$1
|
||||
case "$target" in
|
||||
@@ -1267,6 +1297,17 @@ if $AUTO_LOGIN; then
|
||||
dispatch_target login
|
||||
fi
|
||||
|
||||
for target in "${TARGETS[@]}"; do
|
||||
dispatch_target "$target"
|
||||
target_index=0
|
||||
while (( target_index < ${#TARGETS[@]} )); do
|
||||
current_target="${TARGETS[$target_index]}"
|
||||
if [[ $current_target == "resume" ]]; then
|
||||
if (( target_index + 1 >= ${#TARGETS[@]} )); then
|
||||
error "target 'resume' requires a session identifier"
|
||||
fi
|
||||
process_resume_target "${TARGETS[$((target_index + 1))]}"
|
||||
((target_index+=2))
|
||||
continue
|
||||
fi
|
||||
dispatch_target "$current_target"
|
||||
((target_index+=1))
|
||||
done
|
||||
|
||||
@@ -10,3 +10,4 @@ Current scenarios:
|
||||
- `manifest_injection/` — ensures disallowed `make.*` overrides abort parsing.
|
||||
- `helper_symlink/` — ensures `.sloptrap-ignores` cannot be a symlink to directories outside the project.
|
||||
- `secret_mask/` — verifies masked files remain hidden even when sloptrap remaps the workspace mount.
|
||||
- `resume_target/` — verifies the resume target passes the requested session identifier to Codex.
|
||||
|
||||
4
tests/resume_target/README.md
Normal file
4
tests/resume_target/README.md
Normal file
@@ -0,0 +1,4 @@
|
||||
# Resume Target Scenario
|
||||
|
||||
Empty project used by the regression suite to ensure the `resume` target
|
||||
invokes `codex resume <session-id>` inside the container.
|
||||
@@ -289,6 +289,23 @@ run_secret_mask() {
|
||||
teardown_stub_env
|
||||
}
|
||||
|
||||
run_resume_target() {
|
||||
local scenario_dir="$TEST_ROOT/resume_target"
|
||||
printf '==> resume_target\n'
|
||||
setup_stub_env
|
||||
local session_id="019a81b7-32d2-7622-8639-6698c6579625"
|
||||
if ! PATH="$STUB_BIN:$PATH" HOME="$STUB_HOME" FAKE_PODMAN_LOG="$STUB_LOG" \
|
||||
"$SLOPTRAP_BIN" "$scenario_dir" resume "$session_id" >/dev/null 2>&1; then
|
||||
record_failure "resume_target: sloptrap exited non-zero"
|
||||
teardown_stub_env
|
||||
return
|
||||
fi
|
||||
if ! grep -q -- "resume $session_id" "$STUB_LOG"; then
|
||||
record_failure "resume_target: resume invocation missing"
|
||||
fi
|
||||
teardown_stub_env
|
||||
}
|
||||
|
||||
run_shellcheck
|
||||
run_mount_injection
|
||||
run_root_target
|
||||
@@ -296,6 +313,7 @@ run_symlink_escape
|
||||
run_manifest_injection
|
||||
run_helper_symlink
|
||||
run_secret_mask
|
||||
run_resume_target
|
||||
|
||||
if [[ ${#failures[@]} -gt 0 ]]; then
|
||||
printf '\nTest failures:\n'
|
||||
|
||||
Reference in New Issue
Block a user