Some checks failed
Create issues from TODOs / todos (push) Failing after 3s
Close inactive issues / close-issues (push) Has been cancelled
Deploy GitHub Pages / deploy-preview (push) Has been cancelled
CI / ⚙️ Variables Setup (push) Has been cancelled
CI / ⚙️ Test Guard (push) Has been cancelled
CI / 🚀 Notify external services - draft (push) Has been cancelled
CI / 📦 Build Packages (push) Has been cancelled
CI / 📦 Meteor Build (coverage) (push) Has been cancelled
CI / 📦 Meteor Build (production) (push) Has been cancelled
CI / 🚢 Build Docker (amd64, [account-service presence-service omnichannel-transcript-service], ${{ (github.event_name != 'release' && github.ref != 'refs/heads/develop') && 'coverage' || 'production' }}) (push) Has been cancelled
CI / 🚢 Build Docker (amd64, [account-service presence-service omnichannel-transcript-service], fips) (push) Has been cancelled
CI / 🚢 Build Docker (amd64, [authorization-service queue-worker-service ddp-streamer-service], ${{ (github.event_name != 'release' && github.ref != 'refs/heads/develop') && 'coverage' || 'production' }}) (push) Has been cancelled
CI / 🚢 Build Docker (amd64, [authorization-service queue-worker-service ddp-streamer-service], fips) (push) Has been cancelled
CI / 🚢 Build Docker (amd64, [rocketchat], ${{ (github.event_name != 'release' && github.ref != 'refs/heads/develop') && 'coverage' || 'production' }}) (push) Has been cancelled
CI / 🚢 Build Docker (amd64, [rocketchat], coverage) (push) Has been cancelled
CI / 🚢 Build Docker (amd64, [rocketchat], fips) (push) Has been cancelled
CI / 🚢 Build Docker (arm64, [account-service presence-service omnichannel-transcript-service], ${{ (github.event_name != 'release' && github.ref != 'refs/heads/develop') && 'coverage' || 'production' }}) (push) Has been cancelled
CI / 🚢 Build Docker (arm64, [authorization-service queue-worker-service ddp-streamer-service], ${{ (github.event_name != 'release' && github.ref != 'refs/heads/develop') && 'coverage' || 'production' }}) (push) Has been cancelled
CI / 🚢 Build Docker (arm64, [rocketchat], ${{ (github.event_name != 'release' && github.ref != 'refs/heads/develop') && 'coverage' || 'production' }}) (push) Has been cancelled
CI / 🚢 Build Docker (arm64, [rocketchat], coverage) (push) Has been cancelled
CI / 🚢 Publish Docker Images (ghcr.io) (push) Has been cancelled
CI / 📦 Track Image Sizes (push) Has been cancelled
CI / 🔎 Code Check - Action Lint (push) Has been cancelled
CI / 🔎 Code Check (push) Has been cancelled
CI / 🔨 Test Storybook (push) Has been cancelled
CI / 🔨 Test Unit (push) Has been cancelled
CI / 🔨 Test API (CE) (push) Has been cancelled
CI / 🔨 Test API Livechat (CE) (push) Has been cancelled
CI / 🔨 Test UI (CE) (push) Has been cancelled
CI / 🔨 Test API (EE) (push) Has been cancelled
CI / 🔨 Test API Livechat (EE) (push) Has been cancelled
CI / 🔨 Test API Apps (deno-runtime - EE) (push) Has been cancelled
CI / 🔨 Test UI (EE) (push) Has been cancelled
CI / 🔨 Test API (FIPS) (push) Has been cancelled
CI / 🔨 Test API Livechat (FIPS) (push) Has been cancelled
CI / 🔨 Test UI (FIPS) (push) Has been cancelled
CI / 🔨 Test Federation Matrix (push) Has been cancelled
CI / 📊 Report Coverage (push) Has been cancelled
CI / ✅ Tests Done (push) Has been cancelled
CI / 🚀 Publish build assets (push) Has been cancelled
CI / 🚀 Publish Docker Images (DockerHub) (push) Has been cancelled
CI / 🚀 Notify external services (push) Has been cancelled
CI / Update Version Durability (push) Has been cancelled
Release / Release (push) Has been cancelled
Code scanning - action / CodeQL-Build (push) Failing after 2s
Auto-close duplicate issues / auto-close-duplicates (push) Failing after 1s
377 lines
12 KiB
Bash
Executable File
377 lines
12 KiB
Bash
Executable File
#!/bin/bash
|
||
|
||
# Federation Integration Test Runner
|
||
# This script builds Rocket.Chat locally and starts the federation services,
|
||
# then waits for Rocket.Chat to be ready before running the end-to-end tests.
|
||
|
||
set -e # Exit on any error
|
||
|
||
# Colors for output
|
||
RED='\033[0;31m'
|
||
GREEN='\033[0;32m'
|
||
YELLOW='\033[1;33m'
|
||
BLUE='\033[0;34m'
|
||
NC='\033[0m' # No Color
|
||
|
||
# Configuration
|
||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||
# Script moved under tests/scripts; package root is two levels up from script dir
|
||
PACKAGE_ROOT="$(dirname "$(dirname "$SCRIPT_DIR")")"
|
||
DOCKER_COMPOSE_FILE="$PACKAGE_ROOT/docker-compose.test.yml"
|
||
MAX_WAIT_TIME=240 # 4 minutes
|
||
CHECK_INTERVAL=5 # Check every 5 seconds
|
||
|
||
# Build configuration
|
||
# Use a temporary directory outside the repo to avoid symlink traversal issues during Meteor build
|
||
BUILD_DIR="$(mktemp -d "${FEDERATION_TEST_TMPDIR:-/tmp}/rc-federation-build-XXXXXX")"
|
||
ROCKETCHAT_ROOT="$(cd "$PACKAGE_ROOT/../../.." && pwd)" # Go up to project root
|
||
|
||
# Parse command line arguments
|
||
KEEP_RUNNING=false
|
||
INCLUDE_ELEMENT=false
|
||
USE_PREBUILT_IMAGE=false
|
||
PREBUILT_IMAGE=""
|
||
INTERRUPTED=false
|
||
NO_TEST=false
|
||
CI=false
|
||
LOGS=false
|
||
START_CONTAINERS=true
|
||
|
||
|
||
while [[ $# -gt 0 ]]; do
|
||
case $1 in
|
||
--start-containers-only)
|
||
NO_TEST=true
|
||
KEEP_RUNNING=true
|
||
shift
|
||
;;
|
||
--ci)
|
||
CI=true
|
||
KEEP_RUNNING=true
|
||
START_CONTAINERS=false
|
||
shift
|
||
;;
|
||
--logs)
|
||
LOGS=true
|
||
NO_TEST=true
|
||
START_CONTAINERS=false
|
||
shift
|
||
;;
|
||
--keep-running)
|
||
KEEP_RUNNING=true
|
||
shift
|
||
;;
|
||
--element)
|
||
INCLUDE_ELEMENT=true
|
||
shift
|
||
;;
|
||
--no-test)
|
||
NO_TEST=true
|
||
shift
|
||
;;
|
||
--image)
|
||
USE_PREBUILT_IMAGE=true
|
||
# If no IMAGE value is provided (or next token is another flag), default to latest
|
||
if [[ -z "${2:-}" || "$2" == -* ]]; then
|
||
PREBUILT_IMAGE="rocketchat/rocket.chat:latest"
|
||
shift 1
|
||
else
|
||
PREBUILT_IMAGE="$2"
|
||
shift 2
|
||
fi
|
||
;;
|
||
--help|-h)
|
||
echo "Usage: $0 [OPTIONS]"
|
||
echo "Options:"
|
||
echo " --start-containers-only Start containers and skip running tests"
|
||
echo " --ci Run tests in CI mode (keep containers running, no cleanup)"
|
||
echo " --logs Show logs of rc1 and hs1 containers"
|
||
echo " --keep-running Keep Docker containers running after tests complete"
|
||
echo " --element Include Element web client in the test environment"
|
||
echo " --no-test Start containers and skip running tests"
|
||
echo " --image [IMAGE] Use a pre-built Docker image instead of building locally"
|
||
echo " --help, -h Show this help message"
|
||
echo ""
|
||
echo "By default, builds Rocket.Chat locally and runs the 'test' profile"
|
||
echo "Use --image to test against a pre-built image (e.g., --image rocketchat/rocket.chat:latest)"
|
||
echo "If --image is provided without a value, defaults to rocketchat/rocket.chat:latest"
|
||
echo "Use --element to run all services including Element web client"
|
||
echo "Use --no-test to start containers and skip running tests"
|
||
exit 0
|
||
;;
|
||
*)
|
||
echo "Unknown option: $1"
|
||
echo "Use --help for usage information"
|
||
exit 1
|
||
;;
|
||
esac
|
||
done
|
||
|
||
# Logging functions
|
||
log_info() {
|
||
echo -e "${BLUE}ℹ️ [$(date '+%Y-%m-%d %H:%M:%S')] $1${NC}"
|
||
}
|
||
|
||
log_success() {
|
||
echo -e "${GREEN}✅ [$(date '+%Y-%m-%d %H:%M:%S')] $1${NC}"
|
||
}
|
||
|
||
log_warning() {
|
||
echo -e "${YELLOW}⚠️ [$(date '+%Y-%m-%d %H:%M:%S')] $1${NC}"
|
||
}
|
||
|
||
log_error() {
|
||
echo -e "${RED}❌ [$(date '+%Y-%m-%d %H:%M:%S')] $1${NC}"
|
||
}
|
||
|
||
docker_logs() {
|
||
echo ""
|
||
echo "ROCKET.CHAT (rc1) LOGS:"
|
||
echo "----------------------------------------"
|
||
docker compose -f "$DOCKER_COMPOSE_FILE" --profile "$COMPOSE_PROFILE" logs rc1
|
||
|
||
echo ""
|
||
echo "SYNAPSE (hs1) LOGS:"
|
||
echo "----------------------------------------"
|
||
docker compose -f "$DOCKER_COMPOSE_FILE" --profile "$COMPOSE_PROFILE" logs hs1
|
||
|
||
echo ""
|
||
echo "=========================================="
|
||
}
|
||
|
||
# Cleanup function
|
||
cleanup() {
|
||
if [ "$CI" = true ]; then
|
||
# Exit with the test result code
|
||
if [ -n "${TEST_EXIT_CODE:-}" ]; then
|
||
exit $TEST_EXIT_CODE
|
||
fi
|
||
fi
|
||
|
||
# Show container logs if tests failed
|
||
if [ -n "${TEST_EXIT_CODE:-}" ] && [ "$TEST_EXIT_CODE" -ne 0 ]; then
|
||
echo ""
|
||
echo "=========================================="
|
||
echo "CONTAINER LOGS (Test Failed)"
|
||
echo "=========================================="
|
||
|
||
docker_logs
|
||
fi
|
||
|
||
if [ "$KEEP_RUNNING" = true ]; then
|
||
log_info "Keeping Docker containers running (--keep-running flag set)"
|
||
log_info "Services are available at:"
|
||
log_info " - Rocket.Chat: https://rc1"
|
||
log_info " - Synapse: https://hs1"
|
||
log_info " - MongoDB: localhost:27017"
|
||
if [ "$INCLUDE_ELEMENT" = true ]; then
|
||
log_info " - Element: https://element"
|
||
fi
|
||
log_info "To stop containers manually, run: docker compose -f \"$DOCKER_COMPOSE_FILE\" --profile \"$COMPOSE_PROFILE\" down -v"
|
||
else
|
||
log_info "Cleaning up services..."
|
||
|
||
docker compose -f "$DOCKER_COMPOSE_FILE" --profile "$COMPOSE_PROFILE" down -v 2>/dev/null || true
|
||
|
||
log_success "Cleanup completed"
|
||
fi
|
||
|
||
# Remove temporary build directory if it exists
|
||
if [ -n "${BUILD_DIR:-}" ] && [ -d "$BUILD_DIR" ]; then
|
||
rm -rf "$BUILD_DIR" || true
|
||
fi
|
||
|
||
# Exit with the test result code
|
||
if [ -n "${TEST_EXIT_CODE:-}" ]; then
|
||
exit $TEST_EXIT_CODE
|
||
fi
|
||
}
|
||
|
||
# Setup signal handlers for cleanup
|
||
trap cleanup EXIT TERM
|
||
|
||
# Handle interrupt signal (Ctrl+C) immediately
|
||
trap 'INTERRUPTED=true; log_info "Received interrupt signal (Ctrl+C), stopping..."; cleanup; exit 130' INT
|
||
|
||
# Check if docker-compose.test.yml exists
|
||
if [ ! -f "$DOCKER_COMPOSE_FILE" ]; then
|
||
log_error "docker-compose.test.yml not found at $DOCKER_COMPOSE_FILE"
|
||
exit 1
|
||
fi
|
||
|
||
if [ "$INCLUDE_ELEMENT" = true ]; then
|
||
COMPOSE_PROFILE="element"
|
||
else
|
||
COMPOSE_PROFILE="test"
|
||
fi
|
||
|
||
if [ "$START_CONTAINERS" = true ]; then
|
||
# Build Rocket.Chat locally if not using pre-built image
|
||
if [ "$USE_PREBUILT_IMAGE" = false ]; then
|
||
log_info "🚀 Building Rocket.Chat locally..."
|
||
log_info "====================================="
|
||
|
||
# Clean up any existing build
|
||
log_info "Cleaning up previous build..."
|
||
rm -rf "$BUILD_DIR"
|
||
|
||
# Build the project
|
||
log_info "Building packages from project root..."
|
||
cd "$ROCKETCHAT_ROOT"
|
||
yarn build
|
||
|
||
# Build the Meteor bundle (must be run from the meteor directory)
|
||
log_info "Building Meteor bundle..."
|
||
cd "$ROCKETCHAT_ROOT/apps/meteor"
|
||
METEOR_DISABLE_OPTIMISTIC_CACHING=1 meteor build --server-only --directory "$BUILD_DIR"
|
||
|
||
log_success "Build completed!"
|
||
else
|
||
log_info "🚀 Using pre-built image: $PREBUILT_IMAGE"
|
||
log_info "====================================="
|
||
fi
|
||
|
||
log_info "🚀 Starting Federation Integration Tests"
|
||
log_info "====================================="
|
||
|
||
BUILD_PARAM=""
|
||
|
||
# Set environment variables for Docker Compose
|
||
if [ "$USE_PREBUILT_IMAGE" = true ]; then
|
||
export ROCKETCHAT_IMAGE="$PREBUILT_IMAGE"
|
||
log_info "Using pre-built image: $PREBUILT_IMAGE"
|
||
else
|
||
export ROCKETCHAT_BUILD_CONTEXT="$BUILD_DIR"
|
||
export ROCKETCHAT_DOCKERFILE="$ROCKETCHAT_ROOT/apps/meteor/.docker/Dockerfile.alpine"
|
||
BUILD_PARAM="--build"
|
||
log_info "Building from local context: $BUILD_DIR"
|
||
fi
|
||
|
||
# Start services
|
||
if [ "$INCLUDE_ELEMENT" = true ]; then
|
||
log_info "Starting all federation services including Element web client..."
|
||
else
|
||
log_info "Starting federation services (test profile only)..."
|
||
fi
|
||
|
||
docker compose -f "$DOCKER_COMPOSE_FILE" --profile "$COMPOSE_PROFILE" up -d $BUILD_PARAM
|
||
|
||
# Wait for rc1 container to be running
|
||
log_info "Waiting for rc1 container to start..."
|
||
timeout=60
|
||
while [ $timeout -gt 0 ] && [ "$INTERRUPTED" = false ]; do
|
||
if docker compose -f "$DOCKER_COMPOSE_FILE" ps rc1 --filter "status=running" | grep -q "rc1"; then
|
||
log_success "rc1 container is running"
|
||
break
|
||
fi
|
||
sleep 2
|
||
timeout=$((timeout - 2))
|
||
done
|
||
|
||
if [ "$INTERRUPTED" = true ]; then
|
||
log_info "Container startup interrupted by user"
|
||
exit 130
|
||
fi
|
||
|
||
if [ $timeout -le 0 ]; then
|
||
log_error "rc1 container failed to start within 60 seconds"
|
||
exit 1
|
||
fi
|
||
|
||
# Wait for both Rocket.Chat and Synapse to be ready
|
||
log_info "Waiting for Rocket.Chat and Synapse servers to be ready..."
|
||
|
||
# Function to wait for a service to be ready
|
||
wait_for_service() {
|
||
local url=$1
|
||
local name=$2
|
||
local host=$3
|
||
local elapsed=0
|
||
local ca_cert="${CA_CERT:-$PACKAGE_ROOT/docker-compose/traefik/certs/ca/rootCA.crt}"
|
||
|
||
# Derive host/port from URL when not explicitly provided
|
||
local host_with_port="${url#*://}"
|
||
host_with_port="${host_with_port%%/*}"
|
||
if [ -z "$host" ]; then
|
||
host="${host_with_port%%:*}"
|
||
fi
|
||
local port
|
||
if [[ "$host_with_port" == *:* ]]; then
|
||
port="${host_with_port##*:}"
|
||
else
|
||
if [[ "$url" == https://* ]]; then
|
||
port=443
|
||
else
|
||
port=80
|
||
fi
|
||
fi
|
||
|
||
log_info "Checking $name at $url (host $host -> 127.0.0.1:$port)..."
|
||
|
||
while [ $elapsed -lt $MAX_WAIT_TIME ] && [ "$INTERRUPTED" = false ]; do
|
||
# Capture curl output and error for debugging
|
||
curl_output=$(curl -fsS --cacert "$ca_cert" --resolve "${host}:${port}:127.0.0.1" "$url" 2>&1)
|
||
curl_exit_code=$?
|
||
|
||
if [ $curl_exit_code -eq 0 ]; then
|
||
log_success "$name is ready!"
|
||
return 0
|
||
fi
|
||
|
||
log_info "$name not ready yet, waiting... (${elapsed}s/${MAX_WAIT_TIME}s)"
|
||
log_info "Curl error: $curl_output"
|
||
sleep $CHECK_INTERVAL
|
||
elapsed=$((elapsed + CHECK_INTERVAL))
|
||
done
|
||
|
||
if [ "$INTERRUPTED" = true ]; then
|
||
log_info "Service check interrupted by user"
|
||
return 1
|
||
fi
|
||
|
||
log_error "$name failed to become ready within ${MAX_WAIT_TIME} seconds"
|
||
return 1
|
||
}
|
||
|
||
# Wait for Rocket.Chat
|
||
if ! wait_for_service "https://rc1/api/info" "Rocket.Chat" "rc1"; then
|
||
log_error "Last 50 lines of rc1 logs:"
|
||
docker compose -f "$DOCKER_COMPOSE_FILE" logs --tail 50 rc1
|
||
exit 1
|
||
fi
|
||
|
||
# Wait for Synapse
|
||
if ! wait_for_service "https://hs1/_matrix/client/versions" "Synapse" "hs1"; then
|
||
log_error "Last 50 lines of hs1 logs:"
|
||
docker compose -f "$DOCKER_COMPOSE_FILE" logs --tail 50 hs1
|
||
exit 1
|
||
fi
|
||
fi
|
||
|
||
# Run the end-to-end tests
|
||
if [ "$NO_TEST" = false ]; then
|
||
log_info "Running end-to-end tests..."
|
||
cd "$PACKAGE_ROOT"
|
||
|
||
set +e
|
||
IS_EE=true NODE_EXTRA_CA_CERTS=$(pwd)/docker-compose/traefik/certs/ca/rootCA.crt yarn test:federation
|
||
TEST_EXIT_CODE=$?
|
||
set -e
|
||
elif [ "$LOGS" = true ]; then
|
||
docker_logs
|
||
exit 0
|
||
else
|
||
log_info "No-test mode: skipping test execution"
|
||
log_info "Services are ready and running. You can now:"
|
||
log_info " - Access Rocket.Chat at: https://rc1"
|
||
log_info " - Access Synapse at: https://hs1"
|
||
log_info " - Access MongoDB at: localhost:27017"
|
||
if [ "$INCLUDE_ELEMENT" = true ]; then
|
||
log_info " - Access Element at: https://element"
|
||
fi
|
||
log_info ""
|
||
log_info "To run tests manually, execute: yarn testend-to-end"
|
||
log_info "To stop containers, use: docker compose -f $DOCKER_COMPOSE_FILE down"
|
||
TEST_EXIT_CODE=0
|
||
fi
|