Skip to content

Commit e0b76ca

Browse files
authored
Merge pull request #67 from SubBoost/ryan/oneclick-update-health
fix(selfhost): keep app stable when starting cron
2 parents 7a62822 + ac5fe4b commit e0b76ca

2 files changed

Lines changed: 75 additions & 2 deletions

File tree

local/scripts/selfhost-shell.test.ts

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -261,9 +261,11 @@ ENV
261261
export SUBBOOST_DOCTOR_HEALTH_INTERVAL_SECONDS=0
262262
source local/scripts/subboost.sh
263263
sudo_do() { "$@"; }
264+
docker_calls_file="$home/docker-calls"
264265
docker() {
265266
if [ "$1" = "info" ]; then return 0; fi
266267
if [ "$1" = "compose" ]; then
268+
printf '%s\\n' "$*" >> "$docker_calls_file"
267269
case "$*" in
268270
"compose version"*) return 0 ;;
269271
*" config --services") printf 'app\\ndb\\ncron\\n'; return 0 ;;
@@ -302,6 +304,7 @@ ENV
302304
}
303305
update_cmd
304306
printf 'curl_count=%s\\n' "$(cat "$curl_count_file")"
307+
cat "$docker_calls_file"
305308
`;
306309

307310
const result = runBash(script);
@@ -311,6 +314,76 @@ ENV
311314
expect(result.stdout).not.toContain("健康检查: 异常");
312315
// wait_for_health checks live once per attempt, then status_cmd performs one final live+ready check.
313316
expect(result.stdout).toContain("curl_count=8");
317+
expect(result.stdout).toContain("up -d --no-deps cron");
318+
}, 10_000);
319+
320+
it("restarts rollback cron without recreating the healthy old app", () => {
321+
const script = `
322+
set -Eeuo pipefail
323+
home="$(mktemp -d)"
324+
trap 'rm -rf "$home"' EXIT
325+
mkdir -p "$home/bin"
326+
cat > "$home/.env" <<'ENV'
327+
SUBBOOST_IMAGE=image
328+
POSTGRES_DB=subboost
329+
POSTGRES_USER=subboost
330+
POSTGRES_PASSWORD=password
331+
DATABASE_URL=postgresql://subboost:password@db:5432/subboost?schema=public
332+
ENCRYPTION_KEY=key
333+
JWT_SECRET=jwt
334+
CRON_SECRET=cron
335+
APP_URL=http://127.0.0.1:31000
336+
SUBBOOST_PORT=31000
337+
ENV
338+
: > "$home/docker-compose.yml"
339+
export SUBBOOST_SCRIPT_SOURCE_ONLY=1
340+
export SUBBOOST_HOME="$home"
341+
export SUBBOOST_BIN="$home/bin/subboost"
342+
export SUBBOOST_DOCTOR_HEALTH_ATTEMPTS=1
343+
export SUBBOOST_DOCTOR_HEALTH_INTERVAL_SECONDS=0
344+
source local/scripts/subboost.sh
345+
sudo_do() { "$@"; }
346+
docker_calls_file="$home/docker-calls"
347+
docker() {
348+
if [ "$1" = "info" ]; then return 0; fi
349+
if [ "$1" = "compose" ]; then
350+
printf '%s\\n' "$*" >> "$docker_calls_file"
351+
case "$*" in
352+
"compose version"*) return 0 ;;
353+
*" config --services") printf 'app\\ndb\\ncron\\n'; return 0 ;;
354+
*" config" | *" pull" | *" stop cron app") return 0 ;;
355+
*"pg_dump -Fc"*) printf 'custom-dump'; return 0 ;;
356+
*"pg_restore --list"* | *"pg_restore --clean"*) cat >/dev/null; return 0 ;;
357+
*"candidate-compose.yml up -d --no-deps cron") return 1 ;;
358+
*" up -d "*) return 0 ;;
359+
*" ps -q app") printf 'app-id\\n'; return 0 ;;
360+
esac
361+
fi
362+
if [ "$1" = "inspect" ] && [ "$2" = "-f" ]; then
363+
printf 'sha256:old-image\\n'
364+
fi
365+
return 0
366+
}
367+
curl() { return 0; }
368+
update_status=0
369+
if update_cmd; then
370+
:
371+
else
372+
update_status=$?
373+
fi
374+
printf 'update_status=%s\\n' "$update_status"
375+
cat "$docker_calls_file"
376+
[ "$update_status" -eq 1 ]
377+
`;
378+
379+
const result = runBash(script);
380+
381+
expect(result.status, `stdout:\n${result.stdout}\nstderr:\n${result.stderr}`).toBe(0);
382+
expect(result.stdout).toContain("Candidate update failed: candidate cron startup failed");
383+
expect(result.stdout).toContain("Previous version restored successfully.");
384+
expect(result.stdout).toMatch(/candidate-compose\.yml.*up -d --no-deps cron/);
385+
expect(result.stdout).toMatch(/old-compose\.yml.*up -d --no-deps cron/);
386+
expect(result.stdout).not.toMatch(/old-compose\.yml.*up -d cron(?:\s|$)/);
314387
}, 10_000);
315388

316389
it("uses refreshed release metadata before pulling during update", () => {

local/scripts/subboost.sh

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -486,7 +486,7 @@ update_cmd() {
486486
activate_staged_file "${SUBBOOST_BIN:-/usr/local/bin/subboost}" || update_error="candidate manager activation failed"
487487
fi
488488
if [ -z "$update_error" ]; then
489-
compose_files "$candidate_env" "$candidate_compose" up -d cron || update_error="candidate cron startup failed"
489+
compose_files "$candidate_env" "$candidate_compose" up -d --no-deps cron || update_error="candidate cron startup failed"
490490
fi
491491

492492
if [ -n "$update_error" ]; then
@@ -523,7 +523,7 @@ update_cmd() {
523523
say "Rollback dump preserved at: $rollback_dump"
524524
return 1
525525
fi
526-
compose_files "$old_env" "$old_compose" up -d cron
526+
compose_files "$old_env" "$old_compose" up -d --no-deps cron
527527
docker_cmd image rm "$rollback_tag" >/dev/null 2>&1 || true
528528
say "Previous version restored successfully."
529529
return 1

0 commit comments

Comments
 (0)