Files
uupl-smart-contract/tools/doctor.sh
T

64 lines
3.6 KiB
Bash
Executable File

#!/usr/bin/env bash
set -euo pipefail
ROOT=$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")/.." && pwd -P)
FAILURES=0
fail() { printf 'FAIL: %s\n' "$1" >&2; FAILURES=$((FAILURES + 1)); }
have() {
local name=$1 link=$2
if ! command -v "$name" >/dev/null 2>&1; then
fail "$name is missing — install from $link"
return 1
fi
}
exact_version() {
local name=$1 expected=$2 actual=$3 link=$4
if [[ "$actual" == "$expected" ]]; then printf 'ok: %s %s\n' "$name" "$actual"
else fail "$name must be $expected (found $actual) — install from $link"; fi
}
port_free() {
local port=$1
if (exec 9<>"/dev/tcp/127.0.0.1/$port") 2>/dev/null; then
fail "127.0.0.1:$port is occupied; stop that external service before starting the demo"
else
printf 'ok: 127.0.0.1:%s is available\n' "$port"
fi
}
printf '%s\n' 'Checking the pinned V1 demo environment (read-only).'
if have git https://git-scm.com/downloads; then printf 'ok: %s\n' "$(git --version)"; fi
if have forge https://getfoundry.sh; then exact_version forge 1.7.1 "$(forge --version | sed -nE 's/^forge Version: ([^ ]+).*/\1/p')" https://getfoundry.sh; fi
if have anvil https://getfoundry.sh; then exact_version anvil 1.7.1 "$(anvil --version | sed -nE 's/^anvil Version: ([^ ]+).*/\1/p')" https://getfoundry.sh; fi
if have cast https://getfoundry.sh; then exact_version cast 1.7.1 "$(cast --version | sed -nE 's/^cast Version: ([^ ]+).*/\1/p')" https://getfoundry.sh; fi
if have node https://nodejs.org/en/download; then exact_version Node 24.18.0 "$(node --version | sed 's/^v//')" https://nodejs.org/en/download; fi
if have npm https://docs.npmjs.com/downloading-and-installing-node-js-and-npm; then exact_version npm 11.17.0 "$(npm --version)" https://docs.npmjs.com/downloading-and-installing-node-js-and-npm; fi
if have bash https://www.gnu.org/software/bash/; then printf 'ok: %s\n' "$(bash --version | sed -n '1p')"; fi
if have make https://www.gnu.org/software/make/; then printf 'ok: %s\n' "$(make --version | sed -n '1p')"; fi
if have curl https://curl.se/download.html; then printf 'ok: %s\n' "$(curl --version | sed -n '1p')"; fi
if git -C "$ROOT" submodule status --recursive | while IFS= read -r line; do [[ "$line" == ' '* ]] || exit 1; done; then
printf '%s\n' 'ok: recursive Git submodules are initialized at recorded commits'
else
fail 'recursive Git submodules are missing or differ from recorded commits — run make setup'
fi
if [[ -d "$ROOT/node_modules" ]]; then printf '%s\n' 'ok: root node_modules is installed'; else fail 'root node_modules is missing — run make setup'; fi
if [[ -d "$ROOT/web/node_modules" ]]; then printf '%s\n' 'ok: web node_modules is installed'; else fail 'web node_modules is missing — run make setup'; fi
if command -v node >/dev/null 2>&1 && [[ -d "$ROOT/node_modules" ]]; then
node "$ROOT/tools/check-upgrades-cli.mjs" || fail 'the pinned offline OpenZeppelin upgrades CLI is unavailable — run make setup'
fi
for path in "$ROOT" "$ROOT/deployments" "$ROOT/web/public" "$ROOT/web/src/generated"; do
if [[ -d "$path" && -w "$path" ]]; then printf 'ok: writable runtime directory %s\n' "${path#"$ROOT/"}"; else fail "runtime directory is not writable: $path"; fi
done
if [[ -d "$ROOT/.demo" ]]; then [[ -w "$ROOT/.demo" ]] || fail "$ROOT/.demo is not writable"; fi
port_free 8545
port_free 5173
for variable in BASE_SEPOLIA_RPC_URL BASE_SEPOLIA_ACCOUNT; do
if [[ -n ${!variable:-} ]]; then printf 'optional: %s is configured\n' "$variable"; else printf 'optional: %s is not configured (local demo unaffected)\n' "$variable"; fi
done
if ((FAILURES)); then printf 'Doctor found %d problem(s).\n' "$FAILURES" >&2; exit 1; fi
printf '%s\n' 'Doctor passed.'