- Added comprehensive bounds checking to prevent buffer overruns in multicall parsing - Implemented graduated validation system (Strict/Moderate/Permissive) to reduce false positives - Added LRU caching system for address validation with 10-minute TTL - Enhanced ABI decoder with missing Universal Router and Arbitrum-specific DEX signatures - Fixed duplicate function declarations and import conflicts across multiple files - Added error recovery mechanisms with multiple fallback strategies - Updated tests to handle new validation behavior for suspicious addresses - Fixed parser test expectations for improved validation system - Applied gofmt formatting fixes to ensure code style compliance - Fixed mutex copying issues in monitoring package by introducing MetricsSnapshot - Resolved critical security vulnerabilities in heuristic address extraction - Progress: Updated TODO audit from 10% to 35% complete 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
180 lines
6.7 KiB
Bash
Executable File
180 lines
6.7 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
|
|
set -euo pipefail
|
|
|
|
ROOT_DIR=$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)
|
|
cd "$ROOT_DIR"
|
|
|
|
LOG_DIR="${LOCAL_STAGING_LOG_DIR:-$ROOT_DIR/reports/ci/local-staging}"
|
|
mkdir -p "$LOG_DIR"
|
|
|
|
export GOCACHE="${LOCAL_STAGING_GOCACHE:-$ROOT_DIR/.gocache}"
|
|
export GOMODCACHE="${LOCAL_STAGING_GOMODCACHE:-$ROOT_DIR/.gomodcache}"
|
|
mkdir -p "$GOCACHE" "$GOMODCACHE"
|
|
|
|
BRANCH="${LOCAL_STAGING_BRANCH:-$(git rev-parse --abbrev-ref HEAD)}"
|
|
GO_IMAGE="${LOCAL_STAGING_GO_IMAGE:-docker.io/library/golang:1.24}"
|
|
GOLANGCI_IMAGE="${LOCAL_STAGING_GOLANGCI_IMAGE:-docker.io/golangci/golangci-lint:v1.60.1}"
|
|
HELM_IMAGE="${LOCAL_STAGING_HELM_IMAGE:-docker.io/alpine/helm:3.15.2}"
|
|
KUBECTL_IMAGE="${LOCAL_STAGING_KUBECTL_IMAGE:-docker.io/bitnami/kubectl:1.30.1}"
|
|
|
|
IMAGE_NAME="${LOCAL_STAGING_IMAGE_NAME:-mev-bot}"
|
|
IMAGE_TAG="${LOCAL_STAGING_IMAGE_TAG:-staging-local}"
|
|
IMAGE_REF="${IMAGE_NAME}:${IMAGE_TAG}"
|
|
IMAGE_TAR="${LOCAL_STAGING_IMAGE_TAR:-$ROOT_DIR/${IMAGE_NAME}-${IMAGE_TAG}.tar}"
|
|
|
|
HELM_RELEASE="${LOCAL_STAGING_HELM_RELEASE:-mev-bot}"
|
|
HELM_NAMESPACE="${LOCAL_STAGING_HELM_NAMESPACE:-mev-bot-staging}"
|
|
HELM_CHART="${LOCAL_STAGING_HELM_CHART:-charts/mev-bot}"
|
|
HELM_DRY_RUN="${LOCAL_STAGING_HELM_DRY_RUN:-true}"
|
|
KUBECONFIG_PATH="${LOCAL_STAGING_KUBECONFIG:-$HOME/.kube/config}"
|
|
|
|
SKIP_DOCKER="${LOCAL_STAGING_SKIP_DOCKER:-false}"
|
|
SKIP_DEPLOY="${LOCAL_STAGING_SKIP_DEPLOY:-false}"
|
|
|
|
CONTAINER_RUNTIME="${LOCAL_STAGING_RUNTIME:-}"
|
|
if [[ -z "$CONTAINER_RUNTIME" ]]; then
|
|
if command -v podman >/dev/null 2>&1; then
|
|
CONTAINER_RUNTIME=podman
|
|
elif command -v docker >/dev/null 2>&1; then
|
|
CONTAINER_RUNTIME=docker
|
|
else
|
|
echo "ERROR: Neither podman nor docker is available. Install one or set LOCAL_STAGING_RUNTIME." >&2
|
|
exit 1
|
|
fi
|
|
fi
|
|
|
|
if ! command -v "$CONTAINER_RUNTIME" >/dev/null 2>&1; then
|
|
echo "ERROR: Container runtime '$CONTAINER_RUNTIME' not found in PATH" >&2
|
|
exit 1
|
|
fi
|
|
|
|
CONTAINER_CMD=("$CONTAINER_RUNTIME")
|
|
if [[ "$CONTAINER_RUNTIME" == "podman" ]]; then
|
|
CONTAINER_CMD+=("--remote")
|
|
fi
|
|
|
|
CONTAINER_USER="$(id -u):$(id -g)"
|
|
RUNTIME_ARGS=(-u "$CONTAINER_USER" -v "$ROOT_DIR":/work -w /work -v "$GOCACHE":/gocache -v "$GOMODCACHE":/gomodcache -e GOCACHE=/gocache -e GOMODCACHE=/gomodcache)
|
|
if [[ "$CONTAINER_RUNTIME" == "podman" ]]; then
|
|
RUNTIME_ARGS+=(--security-opt label=disable)
|
|
fi
|
|
|
|
run_step() {
|
|
local name="$1"
|
|
shift
|
|
local logfile="$LOG_DIR/${name}.log"
|
|
printf '[%s] Starting %s\n' "$(date '+%Y-%m-%d %H:%M:%S')" "$name"
|
|
if "$@" |& tee "$logfile"; then
|
|
printf '[%s] Completed %s\n' "$(date '+%Y-%m-%d %H:%M:%S')" "$name"
|
|
else
|
|
printf '[%s] Failed %s; see %s\n' "$(date '+%Y-%m-%d %H:%M:%S')" "$name" "$logfile"
|
|
exit 1
|
|
fi
|
|
}
|
|
|
|
log() {
|
|
printf '[%s] %s\n' "$(date '+%Y-%m-%d %H:%M:%S')" "$*"
|
|
}
|
|
|
|
require_cmd() {
|
|
if ! command -v "$1" >/dev/null 2>&1; then
|
|
echo "ERROR: Required command '$1' not found" >&2
|
|
exit 1
|
|
fi
|
|
}
|
|
|
|
run_container_step() {
|
|
local step="$1"
|
|
local image="$2"
|
|
shift 2
|
|
local cmd="$*"
|
|
run_step "$step" "${CONTAINER_CMD[@]}" run --rm "${RUNTIME_ARGS[@]}" "$image" bash -lc "$cmd"
|
|
}
|
|
|
|
run_container_step_env() {
|
|
local step="$1"
|
|
local image="$2"
|
|
shift 2
|
|
local env_args=()
|
|
while [[ $# -gt 0 && "$1" == --env=* ]]; do
|
|
env_args+=("${1/--env=/}")
|
|
shift
|
|
done
|
|
local cmd="$*"
|
|
local run_args=("${RUNTIME_ARGS[@]}")
|
|
for env in "${env_args[@]}"; do
|
|
run_args+=(-e "$env")
|
|
done
|
|
run_step "$step" "${CONTAINER_CMD[@]}" run --rm "${run_args[@]}" "$image" bash -lc "$cmd"
|
|
}
|
|
|
|
require_cmd git
|
|
|
|
log "Running local staging pipeline for branch ${BRANCH} using ${CONTAINER_CMD[*]}"
|
|
log "Logs: $LOG_DIR"
|
|
|
|
HOST_GOROOT="${LOCAL_STAGING_GOROOT:-}"
|
|
if [[ -z "$HOST_GOROOT" ]] && command -v go >/dev/null 2>&1; then
|
|
HOST_GOROOT=$(go env GOROOT 2>/dev/null || true)
|
|
fi
|
|
if [[ -n "$HOST_GOROOT" && -d "$HOST_GOROOT" ]]; then
|
|
RUNTIME_ARGS+=(-v "$HOST_GOROOT":/goroot:ro -e GOROOT=/goroot)
|
|
GO_BIN_PATH="/goroot/bin:/usr/local/go/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
|
|
else
|
|
GO_BIN_PATH="/usr/local/go/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
|
|
fi
|
|
|
|
run_container_step_env setup-dependencies "$GO_IMAGE" "export PATH=$GO_BIN_PATH; go mod download && go mod verify"
|
|
|
|
run_container_step_env lint "$GOLANGCI_IMAGE" --env=GOLANGCI_LINT_CACHE=/tmp/golangci-lint --env=PATH="$GO_BIN_PATH" "golangci-lint run --timeout=10m"
|
|
|
|
run_container_step_env unit-tests "$GO_IMAGE" "export PATH=$GO_BIN_PATH; go test -race -coverprofile=coverage.out ./..."
|
|
if [[ -f coverage.out ]]; then
|
|
mv coverage.out "$LOG_DIR/coverage.out"
|
|
fi
|
|
|
|
run_container_step_env math-audit "$GO_IMAGE" "export PATH=$GO_BIN_PATH; go run ./tools/math-audit --vectors default --report reports/math/latest"
|
|
|
|
run_container_step_env profit-simulation "$GO_IMAGE" "export PATH=$GO_BIN_PATH; ./scripts/run_profit_simulation.sh"
|
|
|
|
if [[ "$SKIP_DOCKER" != "true" ]]; then
|
|
run_step docker-build "${CONTAINER_CMD[@]}" build -t "$IMAGE_REF" .
|
|
run_step docker-save "${CONTAINER_CMD[@]}" save "$IMAGE_REF" -o "$IMAGE_TAR"
|
|
else
|
|
log "Skipping Docker/Podman build and save (LOCAL_STAGING_SKIP_DOCKER=true)"
|
|
fi
|
|
|
|
if [[ "$SKIP_DEPLOY" != "true" ]]; then
|
|
HELM_RUN_ARGS=("${RUNTIME_ARGS[@]}")
|
|
if [[ -f "$KUBECONFIG_PATH" ]]; then
|
|
HELM_RUN_ARGS+=(-v "$KUBECONFIG_PATH":/kubeconfig:ro -e KUBECONFIG=/kubeconfig)
|
|
elif [[ "$HELM_DRY_RUN" == "false" ]]; then
|
|
echo "ERROR: kubeconfig not found at $KUBECONFIG_PATH" >&2
|
|
exit 1
|
|
fi
|
|
HELM_CMD=(helm upgrade --install "$HELM_RELEASE" "$HELM_CHART" --set "image.tag=${IMAGE_TAG}" --namespace "$HELM_NAMESPACE")
|
|
if [[ "$HELM_DRY_RUN" != "false" ]]; then
|
|
HELM_CMD+=('--dry-run')
|
|
fi
|
|
run_step helm-upgrade "${CONTAINER_CMD[@]}" run --rm "${HELM_RUN_ARGS[@]}" "$HELM_IMAGE" bash -lc "${HELM_CMD[*]}"
|
|
|
|
if command -v kubectl >/dev/null 2>&1 && [[ "$HELM_DRY_RUN" == "false" ]]; then
|
|
run_step rollout-status kubectl rollout status "deploy/${HELM_RELEASE}" -n "$HELM_NAMESPACE" --timeout=120s
|
|
run_step rollout-logs kubectl logs "deploy/${HELM_RELEASE}" -n "$HELM_NAMESPACE" --tail=100
|
|
elif [[ "$HELM_DRY_RUN" == "false" ]]; then
|
|
KUBE_RUN_ARGS=("${RUNTIME_ARGS[@]}")
|
|
if [[ -f "$KUBECONFIG_PATH" ]]; then
|
|
KUBE_RUN_ARGS+=(-v "$KUBECONFIG_PATH":/kubeconfig:ro -e KUBECONFIG=/kubeconfig)
|
|
fi
|
|
run_step rollout-status "${CONTAINER_CMD[@]}" run --rm "${KUBE_RUN_ARGS[@]}" "$KUBECTL_IMAGE" bash -lc "kubectl rollout status deploy/${HELM_RELEASE} -n ${HELM_NAMESPACE} --timeout=120s"
|
|
run_step rollout-logs "${CONTAINER_CMD[@]}" run --rm "${KUBE_RUN_ARGS[@]}" "$KUBECTL_IMAGE" bash -lc "kubectl logs deploy/${HELM_RELEASE} -n ${HELM_NAMESPACE} --tail=100"
|
|
else
|
|
log "Skipping rollout status/log tail (dry run or kube tooling unavailable)"
|
|
fi
|
|
else
|
|
log "Skipping deploy stage (LOCAL_STAGING_SKIP_DEPLOY=true)"
|
|
fi
|
|
|
|
log "Local staging pipeline completed"
|