Skip to content

(ci) Run e2e tests as part of PR/CI checks #4

(ci) Run e2e tests as part of PR/CI checks

(ci) Run e2e tests as part of PR/CI checks #4

Workflow file for this run

name: E2E Tests
on:
push:
branches: ["master", "main"]
pull_request:
branches: ["master", "main"]
workflow_dispatch:
jobs:
e2e-tests:
runs-on: ubuntu-latest
timeout-minutes: 15
steps:
- name: Checkout code
uses: actions/checkout@v5
- name: Set up Go
uses: actions/setup-go@v5
with:
go-version-file: 'go.mod'
- name: Start Kafka 4.0 with KRaft
run: |
docker run -d \
--name broker \
--network host \
-e KAFKA_NODE_ID=1 \
-e KAFKA_PROCESS_ROLES=broker,controller \
-e KAFKA_LISTENERS=PLAINTEXT://localhost:9092,CONTROLLER://localhost:9093 \
-e KAFKA_ADVERTISED_LISTENERS=PLAINTEXT://localhost:9092 \
-e KAFKA_CONTROLLER_LISTENER_NAMES=CONTROLLER \
-e KAFKA_LISTENER_SECURITY_PROTOCOL_MAP=CONTROLLER:PLAINTEXT,PLAINTEXT:PLAINTEXT \
-e KAFKA_CONTROLLER_QUORUM_VOTERS=1@localhost:9093 \
-e KAFKA_OFFSETS_TOPIC_REPLICATION_FACTOR=1 \
-e KAFKA_TRANSACTION_STATE_LOG_REPLICATION_FACTOR=1 \
-e KAFKA_TRANSACTION_STATE_LOG_MIN_ISR=1 \
-e KAFKA_GROUP_INITIAL_REBALANCE_DELAY_MS=0 \
-e KAFKA_NUM_PARTITIONS=3 \
apache/kafka:4.0.0
# Wait for Kafka to be ready
echo "Waiting for Kafka to start..."
for i in {1..60}; do
# Check if Kafka is listening on port 9092
if nc -z localhost 9092 2>/dev/null; then
echo "Kafka port 9092 is open!"
# Give it a couple more seconds to fully initialize
sleep 3
# Try to get metadata using kafka-metadata.sh or kafka-broker-api-versions.sh
if docker exec broker /opt/kafka/bin/kafka-metadata.sh --bootstrap-server localhost:9092 describe --status > /dev/null 2>&1 || \
docker exec broker /opt/kafka/bin/kafka-broker-api-versions.sh --bootstrap-server localhost:9092 > /dev/null 2>&1; then
echo "Kafka is ready and responding to requests!"
break
fi
fi
if [ $i -eq 60 ]; then
echo "Kafka failed to start within 60 seconds"
echo "=== Kafka logs ==="
docker logs broker
exit 1
fi
echo "Attempt $i/60: Kafka not ready yet, waiting..."
sleep 1
done
# Verify Kafka is running
echo "Verifying Kafka cluster..."
docker exec broker /opt/kafka/bin/kafka-broker-api-versions.sh --bootstrap-server localhost:9092 || \
docker exec broker /opt/kafka/bin/kafka-metadata.sh --bootstrap-server localhost:9092 describe --status
echo "Kafka cluster is up and running!"
- name: Create KMinion configuration
run: |
cat > kminion-config.yaml << 'EOF'
kafka:
brokers:
- localhost:9092
clientId: kminion-e2e-test
minion:
endToEnd:
enabled: true
probeInterval: 500ms
topicManagement:
enabled: true
name: kminion-end-to-end
replicationFactor: 1
partitionsPerBroker: 1
reconciliationInterval: 10s
producer:
ackSla: 5s
requiredAcks: all
consumer:
groupIdPrefix: kminion-end-to-end
deleteStaleConsumerGroups: false
roundtripSla: 10s
commitSla: 5s
exporter:
namespace: kminion
port: 8080
logger:
level: info
EOF
- name: Build KMinion
run: |
go build -o kminion .
- name: Start KMinion with E2E tests
run: |
export CONFIG_FILEPATH=kminion-config.yaml
./kminion > kminion.log 2>&1 &
KMINION_PID=$!
echo "KMINION_PID=$KMINION_PID" >> $GITHUB_ENV
# Wait for KMinion to start
echo "Waiting for KMinion to start..."
for i in {1..30}; do
if curl -s http://localhost:8080/metrics > /dev/null 2>&1; then
echo "KMinion is ready!"
break
fi
if [ $i -eq 30 ]; then
echo "KMinion failed to start within 30 seconds"
cat kminion.log
exit 1
fi
echo "Attempt $i/30: KMinion not ready yet, waiting..."
sleep 1
done
- name: Wait for E2E tests to run
run: |
echo "Waiting for E2E tests to produce metrics..."
sleep 30
- name: Validate E2E metrics
run: |
echo "Fetching metrics from KMinion..."
METRICS=$(curl -s http://localhost:8080/metrics)
echo "=== KMinion Metrics Output ==="
echo "$METRICS" | grep -E "kminion_end_to_end_" || true
echo "=============================="
# Check for essential E2E metrics
REQUIRED_METRICS=(
"kminion_end_to_end_messages_produced_total"
"kminion_end_to_end_messages_received_total"
"kminion_end_to_end_produce_latency_seconds"
"kminion_end_to_end_roundtrip_latency_seconds"
"kminion_end_to_end_offset_commit_latency_seconds"
)
MISSING_METRICS=()
for metric in "${REQUIRED_METRICS[@]}"; do
if ! echo "$METRICS" | grep -q "^${metric}"; then
MISSING_METRICS+=("$metric")
fi
done
if [ ${#MISSING_METRICS[@]} -ne 0 ]; then
echo "ERROR: Missing required E2E metrics:"
printf '%s\n' "${MISSING_METRICS[@]}"
echo ""
echo "=== Full KMinion logs ==="
cat kminion.log
exit 1
fi
# Verify messages were produced and received
PRODUCED=$(echo "$METRICS" | grep "^kminion_end_to_end_messages_produced_total" | awk '{print $2}')
RECEIVED=$(echo "$METRICS" | grep "^kminion_end_to_end_messages_received_total" | awk '{print $2}')
echo "Messages produced: $PRODUCED"
echo "Messages received: $RECEIVED"
if [ -z "$PRODUCED" ] || [ "$PRODUCED" = "0" ]; then
echo "ERROR: No messages were produced"
cat kminion.log
exit 1
fi
if [ -z "$RECEIVED" ] || [ "$RECEIVED" = "0" ]; then
echo "ERROR: No messages were received"
cat kminion.log
exit 1
fi
echo "✅ E2E tests passed successfully!"
echo " - Messages produced: $PRODUCED"
echo " - Messages received: $RECEIVED"
- name: Show logs on failure
if: failure()
run: |
echo "=== Kafka logs ==="
docker logs broker || echo "No Kafka logs found"
echo ""
echo "=== KMinion logs ==="
cat kminion.log || echo "No KMinion logs found"
- name: Cleanup
if: always()
run: |
# Stop KMinion
if [ ! -z "$KMINION_PID" ]; then
kill $KMINION_PID || true
fi
# Stop and remove Kafka container
docker stop broker || true
docker rm broker || true
# Wait a bit for graceful shutdown
sleep 2