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`. |
|
| `build-if-missing` | No-op when the image already exists; otherwise delegates to `build`. |
|
||||||
| `rebuild` | Rebuild the image from scratch (`--no-cache`). |
|
| `rebuild` | Rebuild the image from scratch (`--no-cache`). |
|
||||||
| `run` | Default goal. Runs the container with Codex as entrypoint and passes `codex_args`. |
|
| `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`. |
|
| `login` | Starts Codex in login mode to bootstrap `${HOME}/.codex`. |
|
||||||
| `shell` | Launches `/bin/bash` inside the container for debugging. |
|
| `shell` | Launches `/bin/bash` inside the container for debugging. |
|
||||||
| `stop` | Best-effort stop of the running container (if any). |
|
| `stop` | Best-effort stop of the running container (if any). |
|
||||||
|
|||||||
53
sloptrap
53
sloptrap
@@ -30,6 +30,8 @@ print_styled() {
|
|||||||
for arg in "$@"; do
|
for arg in "$@"; do
|
||||||
colored_args+=("$COLOR_HIGHLIGHT$arg$color")
|
colored_args+=("$COLOR_HIGHLIGHT$arg$color")
|
||||||
done
|
done
|
||||||
|
# Format strings are defined within sloptrap, not user input.
|
||||||
|
# shellcheck disable=SC2059
|
||||||
printf "$fmt" "${colored_args[@]}"
|
printf "$fmt" "${colored_args[@]}"
|
||||||
else
|
else
|
||||||
printf '%b' "$fmt"
|
printf '%b' "$fmt"
|
||||||
@@ -50,6 +52,8 @@ print_styled_err() {
|
|||||||
for arg in "$@"; do
|
for arg in "$@"; do
|
||||||
colored_args+=("$COLOR_HIGHLIGHT$arg$color")
|
colored_args+=("$COLOR_HIGHLIGHT$arg$color")
|
||||||
done
|
done
|
||||||
|
# Format strings are defined within sloptrap, not user input.
|
||||||
|
# shellcheck disable=SC2059
|
||||||
printf "$fmt" "${colored_args[@]}" >&2
|
printf "$fmt" "${colored_args[@]}" >&2
|
||||||
else
|
else
|
||||||
printf '%b' "$fmt" >&2
|
printf '%b' "$fmt" >&2
|
||||||
@@ -121,6 +125,7 @@ usage() {
|
|||||||
info_line "\n"
|
info_line "\n"
|
||||||
info_line "Example targets:\n"
|
info_line "Example targets:\n"
|
||||||
comment_line " run Build if needed, then launch Codex\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 " shell Drop into an interactive /bin/bash session\n"
|
||||||
comment_line " clean Remove the project container/image cache\n"
|
comment_line " clean Remove the project container/image cache\n"
|
||||||
comment_line " prune Remove dangling/unused sloptrap images\n"
|
comment_line " prune Remove dangling/unused sloptrap images\n"
|
||||||
@@ -1026,17 +1031,25 @@ prune_sloptrap_images() {
|
|||||||
run_or_print "${cmd[@]}"
|
run_or_print "${cmd[@]}"
|
||||||
}
|
}
|
||||||
|
|
||||||
run_codex() {
|
run_codex_command() {
|
||||||
if ! $DRY_RUN; then
|
local -a extra_args=("$@")
|
||||||
status_line "Running %s\n" "$SLOPTRAP_IMAGE_NAME"
|
|
||||||
fi
|
|
||||||
local -a cmd=("${BASE_CONTAINER_CMD[@]}" "$SLOPTRAP_IMAGE_NAME")
|
local -a cmd=("${BASE_CONTAINER_CMD[@]}" "$SLOPTRAP_IMAGE_NAME")
|
||||||
if [[ ${#CODEX_ARGS_ARRAY[@]} -gt 0 ]]; then
|
if [[ ${#CODEX_ARGS_ARRAY[@]} -gt 0 ]]; then
|
||||||
cmd+=("${CODEX_ARGS_ARRAY[@]}")
|
cmd+=("${CODEX_ARGS_ARRAY[@]}")
|
||||||
fi
|
fi
|
||||||
|
if [[ ${#extra_args[@]} -gt 0 ]]; then
|
||||||
|
cmd+=("${extra_args[@]}")
|
||||||
|
fi
|
||||||
run_or_print "${cmd[@]}"
|
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() {
|
run_login_target() {
|
||||||
if ! $DRY_RUN; then
|
if ! $DRY_RUN; then
|
||||||
status_line "Login %s\n" "$SLOPTRAP_IMAGE_NAME"
|
status_line "Login %s\n" "$SLOPTRAP_IMAGE_NAME"
|
||||||
@@ -1053,6 +1066,23 @@ run_shell_target() {
|
|||||||
run_or_print "${cmd[@]}"
|
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() {
|
dispatch_target() {
|
||||||
local target=$1
|
local target=$1
|
||||||
case "$target" in
|
case "$target" in
|
||||||
@@ -1267,6 +1297,17 @@ if $AUTO_LOGIN; then
|
|||||||
dispatch_target login
|
dispatch_target login
|
||||||
fi
|
fi
|
||||||
|
|
||||||
for target in "${TARGETS[@]}"; do
|
target_index=0
|
||||||
dispatch_target "$target"
|
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
|
done
|
||||||
|
|||||||
@@ -10,3 +10,4 @@ Current scenarios:
|
|||||||
- `manifest_injection/` — ensures disallowed `make.*` overrides abort parsing.
|
- `manifest_injection/` — ensures disallowed `make.*` overrides abort parsing.
|
||||||
- `helper_symlink/` — ensures `.sloptrap-ignores` cannot be a symlink to directories outside the project.
|
- `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.
|
- `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
|
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_shellcheck
|
||||||
run_mount_injection
|
run_mount_injection
|
||||||
run_root_target
|
run_root_target
|
||||||
@@ -296,6 +313,7 @@ run_symlink_escape
|
|||||||
run_manifest_injection
|
run_manifest_injection
|
||||||
run_helper_symlink
|
run_helper_symlink
|
||||||
run_secret_mask
|
run_secret_mask
|
||||||
|
run_resume_target
|
||||||
|
|
||||||
if [[ ${#failures[@]} -gt 0 ]]; then
|
if [[ ${#failures[@]} -gt 0 ]]; then
|
||||||
printf '\nTest failures:\n'
|
printf '\nTest failures:\n'
|
||||||
|
|||||||
Reference in New Issue
Block a user