openvibers/openvibe.games Commits

Games: the legacy deploy fallback is deleted; deploy.sh only runs ovhost (#26)

OP OpenVibers committed 10 Oct 2026 · a1dec68b44 · 4 files, +14 −104

Plan T1 ("deploy-legacy.sh, OVHOST_LEGACY" in the migration-era list). Games deploys with `sudo ovhost deploy games` (since 2026-09-27). This deletes `deploy/scripts/deploy-legacy.sh` and the wrapper's fallback to it: `deploy.sh` runs `ovhost deploy|rollback|plan games`, passes exit codes through, and exits 1 when ovhost is missing. The README documents that. `apps/server/scripts/deployWrapper.test.ts` checks the ovhost calls, the missing-ovhost failure and that no legacy path remains (vitest: 3 passed). Drafted by a Codex job and reviewed here.

Changes

ddiff --git a/README.md b/README.md
iindex 0fa5f50..ddb7656 100644
---- a/README.md
++++ b/README.md
@@@ -143,10 +143,7 @@ the restart (the SDK migrator applies any new migration as the owner before serv
restored, reinstalled and rebuilt and the server restarted again. Players online are reported and
reconnect; `--wait-idle` holds the restart until nobody plays, `--rollback` runs `ovhost rollback games`,
`DRY_RUN=1` prints `ovhost plan games`. Do not pull by hand first (ovhost would find nothing new; pass
--`--restart` if you did). When ovhost is missing, too old or does not deploy Games with that strategy, the
--wrapper runs `deploy/scripts/deploy-legacy.sh`: the procedure as it was run by hand
--(`sudo git -c safe.directory=/opt/openvibe.games pull`, `pnpm install --frozen-lockfile`, `pnpm build`,
--`sudo systemctl restart openvibe-games`).
++`--restart` if you did). The wrapper exits with an error if ovhost is missing.
Rollback: `sudo deploy/scripts/deploy.sh --rollback` (`ovhost rollback games`), which rebuilds the previous
commit. Migrations are additive and applied at boot, so an older build starts on the newer schema; the SDK
ddiff --git a/apps/server/scripts/deployWrapper.test.ts b/apps/server/scripts/deployWrapper.test.ts
iindex 551e7bb..386b51b 100644
---- a/apps/server/scripts/deployWrapper.test.ts
++++ b/apps/server/scripts/deployWrapper.test.ts
@@@ -1,5 +1,5 @@
import { spawnSync } from 'node:child_process'
--import { chmodSync, mkdtempSync, readFileSync, rmSync, writeFileSync } from 'node:fs'
++import { chmodSync, existsSync, mkdtempSync, readFileSync, rmSync, writeFileSync } from 'node:fs'
import { tmpdir } from 'node:os'
import { dirname, join } from 'node:path'
import { fileURLToPath } from 'node:url'
@@@ -7,9 +7,7 @@ import { afterAll, describe, expect, it } from 'vitest'
/**
* deploy/scripts/deploy.sh is a thin wrapper around `ovhost deploy games` (OpenVibe.Host, strategy
-- * pnpm-build; roadmap WS-N task 11), with deploy-legacy.sh (the production procedure as it was run by
-- * hand) as its fallback. A fake ovhost records what the wrapper asks for; a fake legacy script records
-- * the fallback.
++ * pnpm-build; roadmap WS-N task 11). A fake ovhost records what the wrapper asks for.
*/
const ROOT = join(dirname(fileURLToPath(import.meta.url)), '..', '..', '..')
@@@ -20,20 +18,11 @@ const ovhost = join(tmp, 'ovhost')
writeFileSync(
ovhost,
`#!/usr/bin/env bash
--if [ "$1" = capabilities ]; then
-- [ -n "$FAKE_OLD" ] && exit 1
-- printf '%b\\n' "\${FAKE_CAPS:-ovhost=0.3.0\\ndeploy-api=1\\nservice=games\\nstrategy=pnpm-build\\nmanaged=yes\\nlayout=git}"
-- exit 0
--fi
echo "ovhost $*" >> "${log}"
exit "\${FAKE_EXIT:-0}"
`,
)
chmodSync(ovhost, 0o755)
--const legacy = join(tmp, 'legacy.sh')
--writeFileSync(legacy, `#!/usr/bin/env bash\necho "legacy" >> "${log}"\n`)
--chmodSync(legacy, 0o755)
--
interface Run {
code: number | null
out: string
@@@ -47,7 +36,6 @@ function run(args: string[] = [], env: Record<string, string> = {}): Run {
PATH: process.env.PATH ?? '',
OVHOST: ovhost,
OVHOST_SUDO: '',
-- DEPLOY_LEGACY: legacy,
...env,
},
encoding: 'utf8',
@@@ -74,32 +62,18 @@ describe('deploy/scripts/deploy.sh', () => {
expect(run(['--nope']).code).toBe(1)
})
-- it('falls back to deploy-legacy.sh when ovhost is missing, too old or not deploying games with pnpm-build', () => {
-- let r = run([], { FAKE_OLD: '1' })
-- expect(r.calls).toEqual(['legacy'])
-- expect(r.out).toMatch(/too old/)
-- r = run([], { FAKE_CAPS: 'deploy-api=1\\nstrategy=none\\nmanaged=no' })
-- expect(r.calls).toEqual(['legacy'])
-- expect(r.out).toMatch(/does not deploy games with strategy pnpm-build \(none\)/)
-- expect(run([], { OVHOST: join(tmp, 'missing') }).calls).toEqual(['legacy'])
-- // The legacy procedure cannot roll back, wait for idle or plan: nothing runs rather than something else.
-- for (const args of [['--rollback'], ['--wait-idle']]) {
-- r = run(args, { OVHOST_LEGACY: '1' })
++ it('exits with a clear error when ovhost is missing', () => {
++ for (const args of [[], ['--rollback'], ['--wait-idle']]) {
++ const r = run(args, { OVHOST: join(tmp, 'missing') })
expect(r.code).toBe(1)
expect(r.calls).toEqual([])
++ expect(r.out).toMatch(/ovhost not found/)
}
})
-- it('keeps the production procedure as the fallback', () => {
-- const text = readFileSync(join(ROOT, 'deploy', 'scripts', 'deploy-legacy.sh'), 'utf8')
-- for (const step of [
-- 'sudo git -c safe.directory="$REPO" pull',
-- 'pnpm install --frozen-lockfile',
-- 'pnpm build',
-- 'sudo systemctl restart openvibe-games',
-- ]) {
-- expect(text).toContain(step)
-- }
++ it('has no legacy deploy path', () => {
++ expect(existsSync(join(ROOT, 'deploy', 'scripts', 'deploy-legacy.sh'))).toBe(false)
expect(readFileSync(WRAPPER, 'utf8')).toMatch(/^set -euo pipefail$/m)
++ expect(readFileSync(WRAPPER, 'utf8')).not.toMatch(/legacy|capabilities/i)
})
})
ddiff --git a/deploy/scripts/deploy-legacy.sh b/deploy/scripts/deploy-legacy.sh
ddeleted file mode 100755
iindex 8fc7032..0000000
---- a/deploy/scripts/deploy-legacy.sh
++++ /dev/null
@@@ -1,35 +0,0 @@
--#!/usr/bin/env bash
--# OpenVibe.Games — the production deploy as it was done by hand before `ovhost deploy games`, kept as the
--# fallback of deploy/scripts/deploy.sh (roadmap WS-N task 11). The same commands, in the same order:
--#
--# sudo git -c safe.directory=/opt/openvibe.games pull
--# pnpm install --frozen-lockfile
--# pnpm build
--# sudo systemctl restart openvibe-games
--#
--# plus a readiness wait and the best-effort release notification the other repositories' scripts send. It
--# has no protected-session check, no dependency check and no rollback: ovhost has those.
--set -euo pipefail
--REPO="${REPO:-/opt/openvibe.games}"
--READY_URL="${READY_URL:-http://127.0.0.1:8000/api/ready}"
--cd "$REPO"
--sudo git -c safe.directory="$REPO" pull
--pnpm install --frozen-lockfile
--pnpm build
--sudo systemctl restart openvibe-games
--for _ in $(seq 1 60); do
-- if curl -sf --max-time 2 "$READY_URL" >/dev/null; then echo "[games] ready ($(git -c safe.directory="$REPO" rev-parse --short=12 HEAD))"; break; fi
-- sleep 1
--done
--curl -sf --max-time 2 "$READY_URL" >/dev/null || { echo "[games] ✗ not ready after 60 s: journalctl -u openvibe-games -n 50" >&2; exit 3; }
--# Release notification (WS-P task 9): best effort, skipped without an ovhost that has `announce`.
--OVHOST_BIN=$(command -v "${OVHOST:-ovhost}" 2>/dev/null || true)
--if [ -n "$OVHOST_BIN" ]; then
-- case "$("$OVHOST_BIN" --help 2>/dev/null || true)" in
-- *"announce <service>"*)
-- SUDO=""; [ "$(id -u)" -eq 0 ] || SUDO="sudo -n"
-- timeout 20 $SUDO "$OVHOST_BIN" announce games 2>&1 || echo "release notification not sent (the deploy stands)" ;;
-- *) echo "release notification skipped: this ovhost has no announce" ;;
-- esac
--fi
--exit 0
ddiff --git a/deploy/scripts/deploy.sh b/deploy/scripts/deploy.sh
iindex d1ca0ea..3b73307 100755
---- a/deploy/scripts/deploy.sh
++++ b/deploy/scripts/deploy.sh
@@@ -16,15 +16,9 @@
# reported and reconnect (drain policy report); --wait-idle holds the restart until nobody plays. Do not pull
# by hand first: ovhost would find nothing new (pass --restart if you did).
#
--# Fallback: deploy-legacy.sh (the procedure as it was run by hand) when ovhost is missing or too old (no
--# `capabilities`, deploy-api < 1), or the host inventory does not deploy games with strategy pnpm-build;
--# OVHOST_LEGACY=1 forces it. It takes no flags: --rollback, --wait-idle and DRY_RUN=1 are refused there.
set -euo pipefail
SERVICE=games
--STRATEGY=pnpm-build
--HERE=$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)
--LEGACY="${DEPLOY_LEGACY:-$HERE/deploy-legacy.sh}"
OVHOST="${OVHOST:-/usr/local/bin/ovhost}"
if [ "${OVHOST_SUDO-auto}" = auto ]; then if [ "$(id -u)" -eq 0 ]; then SUDO=(); else SUDO=(sudo); fi; elif [ -n "${OVHOST_SUDO}" ]; then SUDO=("$OVHOST_SUDO"); else SUDO=(); fi
@@@ -39,30 +33,10 @@ while [ "$#" -gt 0 ]; do
esac
done
--legacy() {
-- echo "[games] $1 — running deploy-legacy.sh (the previous deploy procedure) instead"
-- if [ "$CMD" = rollback ] || [ "${DRY_RUN:-0}" = 1 ] || [[ " ${FLAGS[*]:-} " == *" --wait-idle "* ]]; then
-- echo "[games] ✗ deploy-legacy.sh has no --rollback, --wait-idle or DRY_RUN; nothing was done" >&2
-- exit 1
-- fi
-- exec bash "$LEGACY"
--}
--
--REASON=""
--probe() {
-- if [ "${OVHOST_LEGACY:-0}" = 1 ]; then REASON="OVHOST_LEGACY=1"; return 1; fi
-- if ! command -v "$OVHOST" >/dev/null 2>&1; then REASON="ovhost not found ($OVHOST)"; return 1; fi
-- local caps api
-- if ! caps=$("${SUDO[@]}" "$OVHOST" capabilities "$SERVICE" 2>/dev/null); then REASON="this ovhost has no 'capabilities' (too old) or no inventory entry for $SERVICE"; return 1; fi
-- api=$(printf '%s\n' "$caps" | sed -n 's/^deploy-api=//p')
-- case "$api" in ''|*[!0-9]*) REASON="this ovhost reports no deploy-api (too old)"; return 1 ;; esac
-- if [ "$api" -lt 1 ]; then REASON="this ovhost's deploy-api is $api, 1 is needed"; return 1; fi
-- if ! printf '%s\n' "$caps" | grep -qx "strategy=$STRATEGY"; then REASON="the host inventory does not deploy $SERVICE with strategy $STRATEGY ($(printf '%s\n' "$caps" | sed -n 's/^strategy=//p'))"; return 1; fi
-- if ! printf '%s\n' "$caps" | grep -qx "managed=yes"; then REASON="ovhost does not manage $SERVICE"; return 1; fi
-- return 0
--}
--
--probe || legacy "$REASON"
++if ! command -v "$OVHOST" >/dev/null 2>&1; then
++ echo "[games] ✗ ovhost not found ($OVHOST); install or configure ovhost before deploying" >&2
++ exit 1
++fi
if [ "${DRY_RUN:-0}" = 1 ]; then exec "${SUDO[@]}" "$OVHOST" plan "$SERVICE"; fi
echo "[games] ovhost $CMD $SERVICE ${FLAGS[*]:-}"