first commit

This commit is contained in:
Beyhan Oğur
2026-04-26 21:52:23 +03:00
commit 880f412e2c
2662 changed files with 866266 additions and 0 deletions

View File

@@ -0,0 +1,299 @@
#!/usr/bin/env bash
set -euo pipefail
# Run integration tests with Bifrost binary and PostgreSQL
# Usage: ./run-integration-tests.sh <bifrost-binary-path> [port]
# Get the absolute path of the script directory
if command -v readlink >/dev/null 2>&1 && readlink -f "$0" >/dev/null 2>&1; then
SCRIPT_DIR="$(dirname "$(readlink -f "$0")")"
else
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd -P)"
fi
# Repository root (3 levels up from .github/workflows/scripts)
REPO_ROOT="$(cd "$SCRIPT_DIR/../../.." && pwd -P)"
# Parse arguments
if [ "${1:-}" = "" ]; then
echo "Usage: $0 <bifrost-binary-path> [port]" >&2
echo "" >&2
echo "Arguments:" >&2
echo " bifrost-binary-path Path to the bifrost-http binary" >&2
echo " port Port to run Bifrost on (default: 8080)" >&2
exit 1
fi
BIFROST_BINARY="$1"
PORT="${2:-8080}"
# PostgreSQL configuration (from environment or defaults)
POSTGRES_HOST="${POSTGRES_HOST:-localhost}"
POSTGRES_PORT="${POSTGRES_PORT:-5432}"
POSTGRES_USER="${POSTGRES_USER:-bifrost}"
POSTGRES_PASSWORD="${POSTGRES_PASSWORD:-bifrost_password}"
POSTGRES_DB="${POSTGRES_DB:-bifrost}"
POSTGRES_SSLMODE="${POSTGRES_SSLMODE:-disable}"
# Validate binary exists and is executable
if [ ! -f "$BIFROST_BINARY" ]; then
echo "❌ Error: Bifrost binary not found: $BIFROST_BINARY" >&2
exit 1
fi
if [ ! -x "$BIFROST_BINARY" ]; then
echo "❌ Error: Bifrost binary is not executable: $BIFROST_BINARY" >&2
exit 1
fi
echo "🧪 Running Bifrost Integration Tests"
echo " Binary: $BIFROST_BINARY"
echo " Port: $PORT"
# Create temp directory for merged config
TEMP_DIR=$(mktemp -d)
MERGED_CONFIG="$TEMP_DIR/config.json"
echo "📁 Using temp directory: $TEMP_DIR"
# Cleanup function
cleanup() {
local exit_code=$?
echo ""
echo "🧹 Cleaning up..."
# Kill Bifrost server if running
if [ -n "${BIFROST_PID:-}" ]; then
echo " Stopping Bifrost server (PID: $BIFROST_PID)..."
kill "$BIFROST_PID" 2>/dev/null || true
wait "$BIFROST_PID" 2>/dev/null || true
fi
# Remove temp directory
if [ -d "$TEMP_DIR" ]; then
echo " Removing temp directory..."
rm -rf "$TEMP_DIR"
fi
exit $exit_code
}
trap cleanup EXIT
# Create merged config
echo "📝 Creating merged config with PostgreSQL..."
# Base config from tests/integrations
BASE_CONFIG="$REPO_ROOT/tests/integrations/config.json"
if [ ! -f "$BASE_CONFIG" ]; then
echo "❌ Error: Base config not found: $BASE_CONFIG" >&2
exit 1
fi
# Use jq to merge configs if available, otherwise use Python
#
# NOTE: The following config merge INTENTIONALLY OVERWRITES any existing
# config_store and logs_store keys from the base config. This is required
# because:
# 1. Integration tests MUST use the local PostgreSQL instance to validate
# database-related functionality (config persistence, logging, etc.)
# 2. The base config (tests/integrations/config.json) typically has these
# stores disabled; we need to fully replace them with enabled PostgreSQL
# config pointing to the test container.
# 3. Deep-merging is NOT desired here - we need a complete, known-good
# PostgreSQL configuration regardless of what the base config contains.
#
# Edge cases handled:
# - Base config has no store keys: jq/Python adds them (no issue)
# - Base config has stores disabled: fully replaced with enabled PostgreSQL
# - Base config has different store type (e.g., sqlite): fully replaced
# - Base config has partial PostgreSQL config: fully replaced to ensure
# correct credentials for the test container
#
if command -v jq >/dev/null 2>&1; then
# jq '. + {...}' performs shallow merge at top level, fully replacing
# config_store and logs_store keys (intentional - see note above)
jq --arg host "$POSTGRES_HOST" \
--arg port "$POSTGRES_PORT" \
--arg user "$POSTGRES_USER" \
--arg pass "$POSTGRES_PASSWORD" \
--arg db "$POSTGRES_DB" \
--arg ssl "$POSTGRES_SSLMODE" \
'. + {
"config_store": {
"enabled": true,
"type": "postgres",
"config": {
"host": $host,
"port": $port,
"user": $user,
"password": $pass,
"db_name": $db,
"ssl_mode": $ssl
}
},
"logs_store": {
"enabled": true,
"type": "postgres",
"config": {
"host": $host,
"port": $port,
"user": $user,
"password": $pass,
"db_name": $db,
"ssl_mode": $ssl
}
}
}' "$BASE_CONFIG" > "$MERGED_CONFIG"
else
# Fallback to Python if jq is not available
# Same intentional overwrite behavior as jq path (see note above)
python3 - "$BASE_CONFIG" "$MERGED_CONFIG" << 'EOF'
import sys
import json
import os
base_path = sys.argv[1]
merged_path = sys.argv[2]
with open(base_path, "r") as f:
config = json.load(f)
postgres_config = {
"host": os.environ.get("POSTGRES_HOST", "localhost"),
"port": os.environ.get("POSTGRES_PORT", "5432"),
"user": os.environ.get("POSTGRES_USER", "bifrost"),
"password": os.environ.get("POSTGRES_PASSWORD", "bifrost_password"),
"db_name": os.environ.get("POSTGRES_DB", "bifrost"),
"ssl_mode": os.environ.get("POSTGRES_SSLMODE", "disable")
}
# Intentionally overwrite any existing store config to force PostgreSQL
# for integration tests (see detailed note in bash section above)
config["config_store"] = {
"enabled": True,
"type": "postgres",
"config": postgres_config
}
config["logs_store"] = {
"enabled": True,
"type": "postgres",
"config": postgres_config.copy()
}
with open(merged_path, "w") as f:
json.dump(config, f, indent=2)
EOF
fi
echo " ✅ Merged config created at: $MERGED_CONFIG"
# Reset PostgreSQL database
echo "🔄 Resetting PostgreSQL database..."
DOCKER_COMPOSE_FILE="$REPO_ROOT/.github/workflows/configs/docker-compose.yml"
if [ -f "$DOCKER_COMPOSE_FILE" ]; then
POSTGRES_CONTAINER=$(docker compose -f "$DOCKER_COMPOSE_FILE" ps -q postgres 2>/dev/null || true)
if [ -n "$POSTGRES_CONTAINER" ]; then
docker exec "$POSTGRES_CONTAINER" \
psql -U "$POSTGRES_USER" -d postgres -c "DROP DATABASE IF EXISTS $POSTGRES_DB; CREATE DATABASE $POSTGRES_DB;" \
2>/dev/null || echo " ⚠️ Could not reset database (container may not be running)"
echo " ✅ Database reset complete"
else
echo " ⚠️ PostgreSQL container not found, skipping database reset"
fi
else
echo " ⚠️ Docker compose file not found, skipping database reset"
fi
# Start Bifrost server
echo "🚀 Starting Bifrost server..."
SERVER_LOG="$TEMP_DIR/server.log"
"$BIFROST_BINARY" --app-dir "$TEMP_DIR" --port "$PORT" --log-level debug > "$SERVER_LOG" 2>&1 &
BIFROST_PID=$!
echo " Started Bifrost with PID: $BIFROST_PID"
# Wait for server to be ready
echo "⏳ Waiting for Bifrost to start..."
MAX_WAIT=60
ELAPSED=0
SERVER_READY=false
while [ $ELAPSED -lt $MAX_WAIT ]; do
if grep -q "successfully started bifrost" "$SERVER_LOG" 2>/dev/null; then
SERVER_READY=true
echo " ✅ Bifrost started successfully"
break
fi
# Check if server process is still running
if ! kill -0 "$BIFROST_PID" 2>/dev/null; then
echo " ❌ Bifrost process died unexpectedly"
echo " Server log:"
cat "$SERVER_LOG"
exit 1
fi
sleep 1
ELAPSED=$((ELAPSED + 1))
done
if [ "$SERVER_READY" = false ]; then
echo " ❌ Bifrost failed to start within ${MAX_WAIT}s"
echo " Server log:"
cat "$SERVER_LOG"
exit 1
fi
# Set environment variable for tests
export BIFROST_BASE_URL="http://localhost:$PORT"
echo " BIFROST_BASE_URL=$BIFROST_BASE_URL"
# Run Python integration tests
echo ""
echo "🧪 Running Python integration tests..."
echo "="
cd "$REPO_ROOT/tests/integrations"
# Check if uv is available
if command -v uv >/dev/null 2>&1; then
echo "📦 Installing dependencies with uv..."
uv sync --frozen --quiet
echo ""
echo "🏃 Running tests..."
TEST_EXIT_CODE=0
uv run python run_all_tests.py --verbose || TEST_EXIT_CODE=$?
else
echo "⚠️ uv not found, trying pip..."
# Create virtual environment if needed
if [ ! -d ".venv" ]; then
python3 -m venv .venv
fi
source .venv/bin/activate
pip install -q -e .
echo ""
echo "🏃 Running tests..."
TEST_EXIT_CODE=0
python run_all_tests.py --verbose || TEST_EXIT_CODE=$?
fi
echo ""
echo "="
if [ $TEST_EXIT_CODE -eq 0 ]; then
echo "✅ All integration tests passed!"
else
echo "❌ Some integration tests failed (exit code: $TEST_EXIT_CODE)"
fi
# Exit with test result code (cleanup trap will run)
exit $TEST_EXIT_CODE