diff --git a/CHANGELOG.md b/CHANGELOG.md index 5af8e12d2..886b2b14b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -26,6 +26,7 @@ - Agent: enable adaptive context pruning by default for tool-result trimming. - Doctor: check config/state permissions and offer to tighten them. — thanks @steipete - Doctor/Daemon: audit supervisor configs, add --repair/--force flows, surface service config audits in daemon status, and document user vs system services. — thanks @steipete +- Doctor: repair gateway service entrypoint when switching between npm and git installs; add Docker e2e coverage. — thanks @steipete - Daemon: align generated systemd unit with docs for network-online + restart delay. (#479) — thanks @azade-c - Daemon: add KillMode=process to systemd units to avoid podman restart hangs. (#541) — thanks @ogulcancelik - Doctor: run legacy state migrations in non-interactive mode without prompts. diff --git a/scripts/e2e/doctor-install-switch-docker.sh b/scripts/e2e/doctor-install-switch-docker.sh new file mode 100755 index 000000000..086202c81 --- /dev/null +++ b/scripts/e2e/doctor-install-switch-docker.sh @@ -0,0 +1,130 @@ +#!/usr/bin/env bash +set -euo pipefail + +ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)" +IMAGE_NAME="clawdbot-doctor-install-switch-e2e" + +echo "Building Docker image..." +docker build -t "$IMAGE_NAME" -f "$ROOT_DIR/scripts/e2e/Dockerfile" "$ROOT_DIR" + +echo "Running doctor install switch E2E..." +docker run --rm -t "$IMAGE_NAME" bash -lc ' + set -euo pipefail + + export PATH="/tmp/clawdbot-bin:$PATH" + mkdir -p /tmp/clawdbot-bin + + cat > /tmp/clawdbot-bin/systemctl <<"SYSTEMCTL" +#!/usr/bin/env bash +set -euo pipefail + +args=("$@") +if [[ "${args[0]:-}" == "--user" ]]; then + args=("${args[@]:1}") +fi +cmd="${args[0]:-}" +case "$cmd" in + status) + exit 0 + ;; + is-enabled) + unit="${args[1]:-}" + unit_path="$HOME/.config/systemd/user/${unit}" + if [ -f "$unit_path" ]; then + exit 0 + fi + exit 1 + ;; + show) + echo "ActiveState=inactive" + echo "SubState=dead" + echo "MainPID=0" + echo "ExecMainStatus=0" + echo "ExecMainCode=0" + exit 0 + ;; + *) + exit 0 + ;; +esac +SYSTEMCTL + chmod +x /tmp/clawdbot-bin/systemctl + + cat > /tmp/clawdbot-bin/loginctl <<"LOGINCTL" +#!/usr/bin/env bash +set -euo pipefail + +if [[ "$*" == *"show-user"* ]]; then + echo "Linger=yes" + exit 0 +fi +if [[ "$*" == *"enable-linger"* ]]; then + exit 0 +fi +exit 0 +LOGINCTL + chmod +x /tmp/clawdbot-bin/loginctl + + npm install -g --prefix /tmp/npm-prefix /app + + npm_bin="/tmp/npm-prefix/bin/clawdbot" + npm_entry="/tmp/npm-prefix/lib/node_modules/clawdbot/dist/entry.js" + git_entry="/app/dist/entry.js" + + assert_entrypoint() { + local unit_path="$1" + local expected="$2" + local exec_line="" + exec_line=$(grep -m1 "^ExecStart=" "$unit_path" || true) + if [ -z "$exec_line" ]; then + echo "Missing ExecStart in $unit_path" + exit 1 + fi + exec_line="${exec_line#ExecStart=}" + entrypoint=$(echo "$exec_line" | awk "{print \$2}") + if [ "$entrypoint" != "$expected" ]; then + echo "Expected entrypoint $expected, got $entrypoint" + exit 1 + fi + } + + run_flow() { + local name="$1" + local install_cmd="$2" + local install_expected="$3" + local doctor_cmd="$4" + local doctor_expected="$5" + + echo "== Flow: $name ==" + home_dir=$(mktemp -d "/tmp/clawdbot-switch-${name}.XXXXXX") + export HOME="$home_dir" + export USER="testuser" + + eval "$install_cmd" + + unit_path="$HOME/.config/systemd/user/clawdbot-gateway.service" + if [ ! -f "$unit_path" ]; then + echo "Missing unit file: $unit_path" + exit 1 + fi + assert_entrypoint "$unit_path" "$install_expected" + + eval "$doctor_cmd" + + assert_entrypoint "$unit_path" "$doctor_expected" + } + + run_flow \ + "npm-to-git" \ + "$npm_bin daemon install --force" \ + "$npm_entry" \ + "node $git_entry doctor --repair" \ + "$git_entry" + + run_flow \ + "git-to-npm" \ + "node $git_entry daemon install --force" \ + "$git_entry" \ + "$npm_bin doctor --repair" \ + "$npm_entry" +'