harb/containers/bootstrap.sh
johba e5e1308e72 refactor: consolidate CI and local dev orchestration (#108)
## Summary
- Extract shared bootstrap functions into `scripts/bootstrap-common.sh` (eliminates ~120 lines of duplicated forge/cast commands from e2e.yml)
- Create reusable `scripts/wait-for-service.sh` for health checks (replaces 60-line inline wait-for-stack)
- Merge dev and CI entrypoints into unified scripts branching on `CI` env var (delete `docker/ci-entrypoints/`)
- Replace 4 per-service CI Dockerfiles with parameterized `docker/Dockerfile.service-ci`
- Add `sync-tax-rates.mjs` to CI image builder stage
- Fix: CI now grants txnBot recenter access (was missing)
- Fix: txnBot funding parameterized (CI=10eth, local=1eth)
- Delete 5 obsolete migration docs and 4 DinD integration files

Net: -1540 lines removed

Closes #107

## Test plan
- [ ] E2E pipeline passes (bootstrap sources shared script, services use old images with commands override)
- [ ] build-ci-images pipeline builds all 4 services with unified Dockerfile
- [ ] Local dev stack boots via `./scripts/dev.sh start`

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-authored-by: openhands <openhands@all-hands.dev>
Reviewed-on: https://codeberg.org/johba/harb/pulls/108
2026-02-03 12:07:28 +01:00

162 lines
5.1 KiB
Bash
Executable file

#!/usr/bin/env bash
set -euo pipefail
# Install jq if not available
if ! command -v jq >/dev/null 2>&1; then
apk add --no-cache jq >/dev/null 2>&1 || apt-get update && apt-get install -y jq >/dev/null 2>&1 || true
fi
ROOT_DIR=/workspace
GIT_BRANCH="${GIT_BRANCH:-}"
# Checkout branch if specified
if [[ -n "$GIT_BRANCH" ]]; then
cd "$ROOT_DIR"
git config --global --add safe.directory "$ROOT_DIR" 2>/dev/null || true
CURRENT=$(git rev-parse --abbrev-ref HEAD 2>/dev/null || echo "unknown")
if [[ "$CURRENT" != "$GIT_BRANCH" ]]; then
echo "[bootstrap] Switching to branch: $GIT_BRANCH"
# Try local branch first, then remote
if git rev-parse --verify "$GIT_BRANCH" >/dev/null 2>&1; then
git checkout "$GIT_BRANCH" 2>/dev/null || echo "[bootstrap] WARNING: Could not checkout $GIT_BRANCH"
else
git fetch origin "$GIT_BRANCH" 2>/dev/null || true
git checkout "$GIT_BRANCH" 2>/dev/null || echo "[bootstrap] WARNING: Could not checkout $GIT_BRANCH"
fi
fi
fi
STATE_DIR=$ROOT_DIR/tmp/containers
LOG_DIR=$STATE_DIR/logs
SETUP_LOG=$LOG_DIR/setup.log
MNEMONIC_FILE=$ROOT_DIR/onchain/.secret.local
mkdir -p "$LOG_DIR"
: >"$SETUP_LOG"
# ── Configure shared bootstrap variables ──
ANVIL_RPC=${ANVIL_RPC:-"http://anvil:8545"}
CONTRACT_ENV=$STATE_DIR/contracts.env
LOG_FILE=$SETUP_LOG
ONCHAIN_DIR=$ROOT_DIR/onchain
TXNBOT_FUND_VALUE=${TXNBOT_FUND_VALUE:-1ether}
# Source shared bootstrap functions
# shellcheck source=../scripts/bootstrap-common.sh
source "$ROOT_DIR/scripts/bootstrap-common.sh"
# ── Local-only helpers ─────────────────────────────────────────────────
maybe_set_deployer_from_mnemonic() {
if [[ -n "$DEPLOYER_PK" && "$DEPLOYER_PK" != "$DEFAULT_DEPLOYER_PK" ]]; then
return
fi
if [[ -f "$MNEMONIC_FILE" ]]; then
local mnemonic pk addr
mnemonic="$(tr -d '\n\r' <"$MNEMONIC_FILE")"
if [[ -n "$mnemonic" ]]; then
pk="$(cast wallet private-key --mnemonic "$mnemonic" --mnemonic-derivation-path "m/44'/60'/0'/0/0")"
addr="$(cast wallet address --private-key "$pk")"
DEPLOYER_PK=${pk}
DEPLOYER_ADDR=${addr}
fi
fi
}
derive_txnbot_wallet() {
if [[ -f "$MNEMONIC_FILE" ]]; then
local mnemonic
mnemonic="$(tr -d '\n\r' <"$MNEMONIC_FILE")"
if [[ -n "$mnemonic" ]]; then
TXNBOT_PRIVATE_KEY="$(cast wallet private-key --mnemonic "$mnemonic" --mnemonic-index 2)"
TXNBOT_ADDRESS="$(cast wallet address --private-key "$TXNBOT_PRIVATE_KEY")"
bootstrap_log "Derived txnBot wallet: $TXNBOT_ADDRESS (account index 2)"
return
fi
fi
# Fallback to hardcoded Anvil account 1
TXNBOT_PRIVATE_KEY=$DEFAULT_TXNBOT_PK
TXNBOT_ADDRESS=$DEFAULT_TXNBOT_ADDR
bootstrap_log "Using default txnBot wallet: $TXNBOT_ADDRESS"
}
write_ponder_env() {
cat >"$ROOT_DIR/services/ponder/.env.local" <<EOPONDER
PONDER_NETWORK=BASE_SEPOLIA_LOCAL_FORK
KRAIKEN_ADDRESS=$KRAIKEN
STAKE_ADDRESS=$STAKE
START_BLOCK=$DEPLOY_BLOCK
PONDER_RPC_URL_BASE_SEPOLIA_LOCAL_FORK=$ANVIL_RPC
DATABASE_URL=postgresql://ponder:ponder_local@postgres:5432/ponder_local
DATABASE_SCHEMA=ponder_local_${DEPLOY_BLOCK}
EOPONDER
}
write_txn_bot_env() {
local txnbot_env=$STATE_DIR/txnBot.env
local provider_url=${TXNBOT_PROVIDER_URL:-$ANVIL_RPC}
local graphql_endpoint=${TXNBOT_GRAPHQL_ENDPOINT:-http://ponder:42069/graphql}
cat >"$txnbot_env" <<EOTXNBOT
ENVIRONMENT=BASE_SEPOLIA_LOCAL_FORK
PROVIDER_URL=$provider_url
PRIVATE_KEY=$TXNBOT_PRIVATE_KEY
LM_CONTRACT_ADDRESS=$LIQUIDITY_MANAGER
STAKE_CONTRACT_ADDRESS=$STAKE
GRAPHQL_ENDPOINT=$graphql_endpoint
WALLET_ADDRESS=$TXNBOT_ADDRESS
PORT=43069
EOTXNBOT
}
prime_chain() {
bootstrap_log "Pre-mining 5 blocks (minimal warmup for fast Ponder sync)..."
if cast rpc --rpc-url "$ANVIL_RPC" anvil_mine "0x5" "0x1" >/dev/null 2>&1; then
bootstrap_log "Mined 5 blocks"
else
bootstrap_log "Batch mining failed, using individual evm_mine calls"
for i in {1..5}; do
cast rpc --rpc-url "$ANVIL_RPC" evm_mine >/dev/null 2>&1 || true
done
fi
bootstrap_log "Pre-mining complete"
}
# ── Main ───────────────────────────────────────────────────────────────
main() {
local start_time
start_time=$(date +%s%3N)
bootstrap_log "Waiting for Anvil"
wait_for_rpc
maybe_set_deployer_from_mnemonic
derive_txnbot_wallet
run_forge_script
extract_addresses
write_contracts_env
fund_liquidity_manager
grant_recenter_access
call_recenter
seed_application_state
write_deployments_json
write_ponder_env
write_txn_bot_env
fund_txn_bot_wallet
prime_chain &
local prime_pid=$!
wait "$prime_pid"
local end_time
end_time=$(date +%s%3N)
local elapsed_ms=$((end_time - start_time))
local elapsed_sec
elapsed_sec=$(awk -v ms="$elapsed_ms" 'BEGIN { printf "%.3f", ms/1000 }')
bootstrap_log "Bootstrap complete in ${elapsed_sec}s"
bootstrap_log "Kraiken: $KRAIKEN"
bootstrap_log "Stake: $STAKE"
bootstrap_log "LiquidityManager: $LIQUIDITY_MANAGER"
bootstrap_log "txnBot: $TXNBOT_ADDRESS"
}
main "$@"