This is an automated email from the ASF dual-hosted git repository.

hgruszecki pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/iggy.git


The following commit(s) were added to refs/heads/master by this push:
     new 658eb8910 ci: unify run-*-examples-from-readme.sh into single 
entrypoint with TLS support (#2920)
658eb8910 is described below

commit 658eb8910e98cd22b32a4655360fc7ffebb9ff23
Author: Atharva Lade <[email protected]>
AuthorDate: Mon Mar 16 06:23:34 2026 -0500

    ci: unify run-*-examples-from-readme.sh into single entrypoint with TLS 
support (#2920)
---
 .github/config/components.yml              |  18 +-
 .github/workflows/_test_examples.yml       |  46 ++--
 examples/csharp/README.md                  |   2 +-
 examples/go/README.md                      |  11 +-
 examples/node/package.json                 |   2 +-
 examples/node/test-examples.sh             | 145 -----------
 examples/python/README.md                  |   9 +
 examples/rust/README.md                    |   2 +-
 scripts/run-csharp-examples-from-readme.sh | 293 -----------------------
 scripts/run-examples-from-readme.sh        | 372 +++++++++++++++++++++++++++++
 scripts/run-go-examples-from-readme.sh     | 258 --------------------
 scripts/run-java-examples-from-readme.sh   | 221 -----------------
 scripts/run-node-examples-from-readme.sh   | 264 --------------------
 scripts/run-python-examples-from-readme.sh | 226 ------------------
 scripts/run-rust-examples-from-readme.sh   | 276 ---------------------
 scripts/utils.sh                           | 209 ++++++++++++++++
 16 files changed, 633 insertions(+), 1721 deletions(-)

diff --git a/.github/config/components.yml b/.github/config/components.yml
index fa9620be3..6d5eeade9 100644
--- a/.github/config/components.yml
+++ b/.github/config/components.yml
@@ -289,7 +289,8 @@ components:
       - "ci-infrastructure"
     paths:
       - "examples/rust/**"
-      - "scripts/run-rust-examples-from-readme.sh"
+      - "scripts/run-examples-from-readme.sh"
+      - "scripts/utils.sh"
     tasks: ["examples-rust"]
 
   examples-go:
@@ -300,7 +301,8 @@ components:
       - "ci-infrastructure"
     paths:
       - "examples/go/**"
-      - "scripts/run-go-examples-from-readme.sh"
+      - "scripts/run-examples-from-readme.sh"
+      - "scripts/utils.sh"
     tasks: ["examples-go"]
 
   examples-csharp:
@@ -311,7 +313,8 @@ components:
       - "ci-infrastructure"
     paths:
       - "examples/csharp/**"
-      - "scripts/run-csharp-examples-from-readme.sh"
+      - "scripts/run-examples-from-readme.sh"
+      - "scripts/utils.sh"
     tasks: ["examples-csharp"]
 
   examples-python:
@@ -322,7 +325,8 @@ components:
       - "ci-infrastructure"
     paths:
       - "examples/python/**"
-      - "scripts/run-python-examples-from-readme.sh"
+      - "scripts/run-examples-from-readme.sh"
+      - "scripts/utils.sh"
     tasks: ["examples-python"]
 
   examples-node:
@@ -333,7 +337,8 @@ components:
       - "ci-infrastructure"
     paths:
       - "examples/node/**"
-      - "scripts/run-node-examples-from-readme.sh"
+      - "scripts/run-examples-from-readme.sh"
+      - "scripts/utils.sh"
     tasks: ["examples-node"]
 
   examples-java:
@@ -344,7 +349,8 @@ components:
       - "ci-infrastructure"
     paths:
       - "examples/java/**"
-      - "scripts/run-java-examples-from-readme.sh"
+      - "scripts/run-examples-from-readme.sh"
+      - "scripts/utils.sh"
     tasks: ["examples-java"]
 
   web-ui:
diff --git a/.github/workflows/_test_examples.yml 
b/.github/workflows/_test_examples.yml
index 0e4efe365..a7eb51070 100644
--- a/.github/workflows/_test_examples.yml
+++ b/.github/workflows/_test_examples.yml
@@ -123,50 +123,40 @@ jobs:
             fi
           fi
 
+      - name: Build Node SDK for examples
+        if: startsWith(inputs.component, 'examples-') && inputs.task == 
'examples-node'
+        run: |
+          cd foreign/node
+          npm ci
+          npm run build
+          cd ../..
+          cd examples/node
+          npm ci
+          cd ../..
+
       - name: Run Rust examples
         if: startsWith(inputs.component, 'examples-') && inputs.task == 
'examples-rust'
-        run: |
-          echo "Running Rust examples tests..."
-          ./scripts/run-rust-examples-from-readme.sh
+        run: ./scripts/run-examples-from-readme.sh --language rust
 
       - name: Run Go examples
         if: startsWith(inputs.component, 'examples-') && inputs.task == 
'examples-go'
-        run: |
-          echo "Running Go examples tests..."
-          ./scripts/run-go-examples-from-readme.sh
+        run: ./scripts/run-examples-from-readme.sh --language go
 
-      - name: Run Csharp examples
+      - name: Run C# examples
         if: startsWith(inputs.component, 'examples-') && inputs.task == 
'examples-csharp'
-        run: |
-          echo "Running Csharp examples tests..."
-          ./scripts/run-csharp-examples-from-readme.sh
+        run: ./scripts/run-examples-from-readme.sh --language csharp
 
       - name: Run Python examples
         if: startsWith(inputs.component, 'examples-') && inputs.task == 
'examples-python'
-        run: |
-          echo "Running Python examples tests..."
-          ./scripts/run-python-examples-from-readme.sh
+        run: ./scripts/run-examples-from-readme.sh --language python
 
       - name: Run Node.js examples
         if: startsWith(inputs.component, 'examples-') && inputs.task == 
'examples-node'
-        run: |
-          echo "Running Node.js examples tests..."
-          # Build the local Node SDK first (examples use file: link to it)
-          cd foreign/node
-          npm ci
-          npm run build
-          cd ../..
-          # Install examples dependencies (will use the local SDK)
-          cd examples/node
-          npm ci
-          cd ../..
-          ./scripts/run-node-examples-from-readme.sh
+        run: ./scripts/run-examples-from-readme.sh --language node
 
       - name: Run Java examples
         if: startsWith(inputs.component, 'examples-') && inputs.task == 
'examples-java'
-        run: |
-          echo "Running Java examples tests..."
-          ./scripts/run-java-examples-from-readme.sh
+        run: ./scripts/run-examples-from-readme.sh --language java
 
       - name: Upload reports
         if: always()
diff --git a/examples/csharp/README.md b/examples/csharp/README.md
index 19e074650..995859aff 100644
--- a/examples/csharp/README.md
+++ b/examples/csharp/README.md
@@ -90,4 +90,4 @@ All examples can be executed directly from the repository. 
Follow these steps:
 
 These examples use IggyClient with TCP transport and demonstrate automatic 
stream/topic creation with basic message handling.
 
-The examples are automatically tested via 
`scripts/run-csharp-examples-from-readme.sh` to ensure they remain functional 
and up-to-date with the latest API changes.
+The examples are automatically tested via `scripts/run-examples-from-readme.sh 
--language csharp` to ensure they remain functional and up-to-date with the 
latest API changes.
diff --git a/examples/go/README.md b/examples/go/README.md
index c482fd7cb..83f260696 100644
--- a/examples/go/README.md
+++ b/examples/go/README.md
@@ -34,6 +34,15 @@ go run ./getting-started/producer/main.go
 go run ./getting-started/consumer/main.go
 ```
 
+## TLS Examples
+
+To test with a TLS-enabled server, start the server with TLS configured (see 
main README), then run:
+
+```bash
+go run ./getting-started/producer/main.go --tcp-server-address localhost:8090 
--tls --tls-ca-file ../../core/certs/iggy_ca_cert.pem
+go run ./getting-started/consumer/main.go --tcp-server-address localhost:8090 
--tls --tls-ca-file ../../core/certs/iggy_ca_cert.pem
+```
+
 ## Example Structure
 
 All examples can be executed directly from the repository. Follow these steps:
@@ -44,4 +53,4 @@ All examples can be executed directly from the repository. 
Follow these steps:
 
 These examples use IggyClient with TCP transport and demonstrate automatic 
stream/topic creation with basic message handling.
 
-The examples are automatically tested via 
`scripts/run-go-examples-from-readme.sh` to ensure they remain functional and 
up-to-date with the latest API changes.
+The examples are automatically tested via `scripts/run-examples-from-readme.sh 
--language go` to ensure they remain functional and up-to-date with the latest 
API changes.
diff --git a/examples/node/package.json b/examples/node/package.json
index a4160d50b..fa7ec2444 100644
--- a/examples/node/package.json
+++ b/examples/node/package.json
@@ -5,7 +5,7 @@
   "type": "module",
   "main": "index.js",
   "scripts": {
-    "test": "./test-examples.sh",
+    "test": "echo 'Use scripts/run-examples-from-readme.sh --language node 
from repo root'",
     "lint": "eslint src/**/*.ts",
     "lint:fix": "eslint src/**/*.ts --fix",
     "test:getting-started:producer": "tsx src/getting-started/producer.ts",
diff --git a/examples/node/test-examples.sh b/examples/node/test-examples.sh
deleted file mode 100755
index b2a5b5984..000000000
--- a/examples/node/test-examples.sh
+++ /dev/null
@@ -1,145 +0,0 @@
-#!/bin/bash
-# Licensed to the Apache Software Foundation (ASF) under one
-# or more contributor license agreements.  See the NOTICE file
-# distributed with this work for additional information
-# regarding copyright ownership.  The ASF licenses this file
-# to you under the Apache License, Version 2.0 (the
-# "License"); you may not use this file except in compliance
-# with the License.  You may obtain a copy of the License at
-#
-#   http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing,
-# software distributed under the License is distributed on an
-# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-# KIND, either express or implied.  See the License for the
-# specific language governing permissions and limitations
-# under the License.
-
-
-# Test script for Iggy Node.js examples
-# This script tests the examples by running them with a timeout
-
-set -e
-
-echo "๐Ÿงช Testing Iggy Node.js Examples"
-echo "================================="
-
-# Colors for output
-RED='\033[0;31m'
-GREEN='\033[0;32m'
-YELLOW='\033[1;33m'
-NC='\033[0m' # No Color
-
-# Function to test an example
-test_example() {
-    local name="$1"
-    local command="$2"
-    local timeout="${3:-10}"
-
-    echo -e "\n${YELLOW}Testing $name...${NC}"
-    echo "Command: $command"
-
-    # Run the command with timeout using background process
-    local output
-    local pid
-
-    # Start the command in background
-    # $command > /tmp/test_output_$$ 2>&1 &
-    $command > example_output.log 2>&1 &
-    pid=$!
-
-    # Wait for the specified timeout
-    local count=0
-    while [ $count -lt "$timeout" ]; do
-        if ! kill -0 $pid 2>/dev/null; then
-            # Process finished
-            output=$(cat example_output.log)
-            rm -f example_output.log
-
-            if wait $pid; then
-                echo -e "${GREEN}โœ… $name passed${NC}"
-                return 0
-            else
-                # Check if the output contains our expected error message
-                if echo "$output" | grep -q "This might be due to server 
version compatibility"; then
-                    echo -e "${YELLOW}โš ๏ธ  $name completed with known server 
compatibility issue${NC}"
-                    return 0
-                else
-                    echo -e "${RED}โŒ $name failed${NC}"
-                    echo "Output: $output"
-                    return 1
-                fi
-            fi
-        fi
-        sleep 1
-        count=$((count + 1))
-    done
-
-    # Timeout reached, kill the process
-    kill $pid 2>/dev/null
-    wait $pid 2>/dev/null
-    rm -f example_output.log
-
-    echo -e "${YELLOW}โฐ $name timed out after ${timeout}s (this is expected 
for long-running examples)${NC}"
-    return 0
-}
-
-# Check if Iggy server is running
-echo "Checking if Iggy server is running..."
-if ! curl -s http://localhost:3000/health > /dev/null 2>&1; then
-    echo -e "${YELLOW}โš ๏ธ  Iggy server not detected. Please start it with:${NC}"
-    echo "docker run --rm -p 8080:8080 -p 3000:3000 -p 8090:8090 
apache/iggy:latest"
-    echo ""
-    echo "Or build from source:"
-    echo "cd ../../ && cargo run --bin iggy-server"
-    echo ""
-    echo "Skipping tests..."
-    exit 0
-fi
-
-echo -e "${GREEN}โœ… Iggy server is running${NC}"
-
-# Test getting-started examples
-echo -e "\n${YELLOW}Testing Getting Started Examples${NC}"
-test_example "Getting Started Producer (TS)" "npm run 
test:getting-started:producer" 10
-test_example "Getting Started Consumer (TS)" "npm run 
test:getting-started:consumer" 8
-
-# Test basic examples
-echo -e "\n${YELLOW}Testing Basic Examples${NC}"
-test_example "Basic Producer" "npm run test:basic:producer" 10
-test_example "Basic Consumer" "npm run test:basic:consumer" 8
-
-# Message envelope examples
-echo -e "\n${YELLOW}Testing Message Envelope Examples${NC}"
-test_example "Message Envelope Producer" "npm run 
test:message-envelope:producer" 10
-test_example "Message Envelope Consumer" "npm run 
test:message-envelope:consumer" 8
-
-# Message headers examples
-echo -e "\n${YELLOW}Testing Message Headers Examples${NC}"
-test_example "Message Headers Producer" "npm run 
test:message-headers:producer" 10
-test_example "Message Headers Consumer" "npm run 
test:message-headers:consumer" 8
-
-# Multi-tenant examples
-echo -e "\n${YELLOW}Testing Multi-Tenant Examples${NC}"
-test_example "Multi-Tenant Producer" "npm run test:multi-tenant:producer" 10
-test_example "Multi-Tenant Consumer" "npm run test:multi-tenant:consumer" 8
-
-# Stream builder example
-echo -e "\n${YELLOW}Testing Stream Builder Example${NC}"
-test_example "Stream Builder" "npm run test:stream-builder" 8
-
-# Sink data producer
-echo -e "\n${YELLOW}Testing Sink Data Producer${NC}"
-test_example "Sink Data Producer" "npm run test:sink-data-producer" 8
-
-# TCP/TLS examples (require a TLS-enabled server)
-if [ "$IGGY_TCP_TLS_ENABLED" = "true" ]; then
-    echo -e "\n${YELLOW}Testing TCP/TLS Examples${NC}"
-    test_example "TCP/TLS Producer" "npm run test:tcp-tls:producer" 10
-    test_example "TCP/TLS Consumer" "npm run test:tcp-tls:consumer" 8
-else
-    echo -e "\n${YELLOW}Skipping TCP/TLS examples (set 
IGGY_TCP_TLS_ENABLED=true to run)${NC}"
-fi
-
-echo -e "\n${GREEN}๐ŸŽ‰ All tests completed!${NC}"
diff --git a/examples/python/README.md b/examples/python/README.md
index 0f2585b1d..aa7010f7a 100644
--- a/examples/python/README.md
+++ b/examples/python/README.md
@@ -70,3 +70,12 @@ python basic/consumer.py
 ```
 
 Demonstrates fundamental client connection, authentication, batch message 
sending, and polling with support for TCP/QUIC/HTTP protocols.
+
+## TLS Examples
+
+To test with a TLS-enabled server, start the server with TLS configured (see 
main README), then run:
+
+```bash
+uv run getting-started/producer.py --tcp-server-address localhost:8090 --tls 
--tls-ca-file ../../core/certs/iggy_ca_cert.pem
+uv run getting-started/consumer.py --tcp-server-address localhost:8090 --tls 
--tls-ca-file ../../core/certs/iggy_ca_cert.pem
+```
diff --git a/examples/rust/README.md b/examples/rust/README.md
index c5e61b01e..c86c5ad35 100644
--- a/examples/rust/README.md
+++ b/examples/rust/README.md
@@ -222,4 +222,4 @@ Most examples use shared utilities from 
`examples/rust/src/shared/` including:
 - Common argument parsing
 - Client setup helpers
 
-The examples are automatically tested via 
`scripts/run-rust-examples-from-readme.sh` to ensure they remain functional and 
up-to-date with the latest API changes.
+The examples are automatically tested via `scripts/run-examples-from-readme.sh 
--language rust` to ensure they remain functional and up-to-date with the 
latest API changes.
diff --git a/scripts/run-csharp-examples-from-readme.sh 
b/scripts/run-csharp-examples-from-readme.sh
deleted file mode 100755
index c05e48b5e..000000000
--- a/scripts/run-csharp-examples-from-readme.sh
+++ /dev/null
@@ -1,293 +0,0 @@
-#!/bin/bash
-
-# Licensed to the Apache Software Foundation (ASF) under one
-# or more contributor license agreements.  See the NOTICE file
-# distributed with this work for additional information
-# regarding copyright ownership.  The ASF licenses this file
-# to you under the Apache License, Version 2.0 (the
-# "License"); you may not use this file except in compliance
-# with the License.  You may obtain a copy of the License at
-#
-#   http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing,
-# software distributed under the License is distributed on an
-# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-# KIND, either express or implied.  See the License for the
-# specific language governing permissions and limitations
-# under the License.
-
-set -euo pipefail
-
-# Script to run Csharp examples from examples/csharp/README.md files
-# Usage: ./scripts/run-csharp-examples-from-readme.sh [OPTIONS]
-#
-# --csos   - Optional target OS (e.g., linux, darwin)
-# --csarch - Optional target architecture (e.g., amd64, arm64)
-# --target - Optional target architecture for rust (e.g., 
x86_64-unknown-linux-musl)
-#
-# This script will run all the commands from examples/csharp/README.md files
-# and check if they pass or fail.
-# If any command fails, it will print the command and exit with non-zero 
status.
-# If all commands pass, it will remove the log file and exit with zero status.
-#
-# Note: This script assumes that the iggy-server is not running and will start 
it in the background.
-#       It will wait until the server is started before running the commands.
-#       It will also terminate the server after running all the commands.
-#       Script executes every command in README files which is enclosed in 
backticks (`) and starts
-#       with `dotnet run --project src/xxx`. Other commands are ignored.
-#       Order of commands in README files is important as script will execute 
them from top to bottom.
-#
-
-readonly LOG_FILE="iggy-server.log"
-readonly PID_FILE="iggy-server.pid"
-readonly TIMEOUT=300
-
-# Get target architecture from argument or use default
-
-CSOS="" # chsarp target OS
-CSARCH="" # csharp target architecture
-TARGET="" # Iggy server target architecture
-
-while [[ $# -gt 0 ]]; do
-    case "$1" in
-        --csharpos)
-            CSOS="$2"
-            shift 2
-            ;;
-        --csharparch)
-            CSARCH="$2"
-            shift 2
-            ;;
-        --target)
-            TARGET="$2"
-            shift 2
-            ;;
-        *)
-            echo "Unknown option: $1"
-            echo "Usage: $0 [--csos CSOS] [--csarch CSARCH] [--target TARGET]"
-            exit 1
-            ;;
-    esac
-done
-
-# Remove old server data if present
-test -d local_data && rm -fr local_data
-test -e ${LOG_FILE} && rm ${LOG_FILE}
-test -e ${PID_FILE} && rm ${PID_FILE}
-
-# Check if server binary exists
-SERVER_BIN=""
-if [ -n "${TARGET}" ]; then
-    SERVER_BIN="target/${TARGET}/debug/iggy-server"
-else
-    SERVER_BIN="target/debug/iggy-server"
-fi
-
-if [ ! -f "${SERVER_BIN}" ]; then
-    echo "Error: Server binary not found at ${SERVER_BIN}"
-    echo "Please build the server binary before running this script:"
-    if [ -n "${TARGET}" ]; then
-        echo "  cargo build --target ${TARGET} --bin iggy-server"
-    else
-        echo "  cargo build --bin iggy-server"
-    fi
-    exit 1
-fi
-
-echo "Using server binary at ${SERVER_BIN}"
-
-# Run iggy server using the prebuilt binary
-echo "Starting server from ${SERVER_BIN}..."
-IGGY_ROOT_USERNAME=iggy IGGY_ROOT_PASSWORD=iggy ${SERVER_BIN} &>${LOG_FILE} &
-echo $! >${PID_FILE}
-
-# Wait until "Iggy server has started" string is present inside iggy-server.log
-SERVER_START_TIME=0
-while ! grep -q "has started" ${LOG_FILE}; do
-    if [ ${SERVER_START_TIME} -gt ${TIMEOUT} ]; then
-        echo "Server did not start within ${TIMEOUT} seconds."
-        ps fx
-        cat ${LOG_FILE}
-        exit 1
-    fi
-    echo "Waiting for Iggy server to start... ${SERVER_START_TIME}"
-    sleep 1
-    ((SERVER_START_TIME += 1))
-done
-
-# Execute all matching CLI commands from README.md and check if they pass or 
fail
-while IFS= read -r command; do
-    # Remove backticks from command
-    command=$(echo "${command}" | tr -d '`')
-    
-    # Add target flag if specified
-    if [ -n "${CSOS}" ]; then
-        command="${command//dotnet run /dotnet run --os ${CSOS} }"
-    fi
-    
-    if [ -n "${CSARCH}" ]; then
-        command="${command//dotnet run /dotnet run --arch ${CSARCH} }"
-    fi
-    
-    echo -e "\e[33mChecking CLI command:\e[0m ${command}"
-    echo ""
-
-    set +e
-    eval "${command}"
-    exit_code=$?
-    set -e
-
-    # Stop at first failure
-    if [ ${exit_code} -ne 0 ]; then
-        echo ""
-        echo -e "\e[31mCLI command failed:\e[0m ${command}"
-        echo ""
-        break
-    fi
-
-done < <(grep -E "^\`cargo r --bin iggy -- " README.md)
-
-# Execute all example commands from README.md and examples/rust/README.md and 
check if they pass or fail
-for readme_file in README.md examples/csharp/README.md; do
-    if [ ! -f "${readme_file}" ]; then
-        continue
-    fi
-
-    while IFS= read -r command; do
-        # Remove backticks and comments from command
-        command=$(echo "${command}" | tr -d '`' | sed 's/^#.*//')
-        # Skip empty lines
-        if [ -z "${command}" ]; then
-            continue
-        fi
-        
-        # Add target flag if specified
-        if [ -n "${CSOS}" ]; then
-            command="${command//dotnet run /dotnet run --os ${CSOS} }"
-        fi
-        
-        if [ -n "${CSARCH}" ]; then
-            command="${command//dotnet run /dotnet run --arch ${CSARCH} }"
-        fi
-        
-        echo -e "\e[33mChecking example command from ${readme_file}:\e[0m 
${command}"
-        echo ""
-
-        set +e
-        eval "${command}"
-        exit_code=$?
-        set -e
-
-        # Stop at first failure
-        if [ ${exit_code} -ne 0 ]; then
-            echo ""
-            echo -e "\e[31mExample command failed:\e[0m ${command}"
-            echo ""
-            break 2 # Break from both loops
-        fi
-        # Add a small delay between examples to avoid potential race conditions
-        sleep 2
-
-    done < <(grep -E "^dotnet run --project" "${readme_file}" | grep -v 
"TcpTls")
-done
-
-# Terminate non-TLS server
-kill -TERM "$(cat ${PID_FILE})"
-test -e ${PID_FILE} && rm ${PID_FILE}
-
-# Run TLS examples if non-TLS examples passed
-if [ "${exit_code}" -eq 0 ]; then
-    TLS_README="examples/csharp/README.md"
-    if [ -f "${TLS_README}" ] && grep -qE "^dotnet run --project.*TcpTls" 
"${TLS_README}"; then
-        echo ""
-        echo "=== Running TLS examples ==="
-        echo ""
-
-        # Clean up for fresh TLS start
-        test -d local_data && rm -fr local_data
-        test -e ${LOG_FILE} && rm ${LOG_FILE}
-
-        # Start TLS server
-        echo "Starting TLS server from ${SERVER_BIN}..."
-        IGGY_ROOT_USERNAME=iggy IGGY_ROOT_PASSWORD=iggy \
-            IGGY_TCP_TLS_ENABLED=true \
-            IGGY_TCP_TLS_CERT_FILE=core/certs/iggy_cert.pem \
-            IGGY_TCP_TLS_KEY_FILE=core/certs/iggy_key.pem \
-            ${SERVER_BIN} &>${LOG_FILE} &
-        echo $! >${PID_FILE}
-
-        # Wait for TLS server to start
-        SERVER_START_TIME=0
-        while ! grep -q "has started" ${LOG_FILE}; do
-            if [ ${SERVER_START_TIME} -gt ${TIMEOUT} ]; then
-                echo "TLS server did not start within ${TIMEOUT} seconds."
-                ps fx
-                cat ${LOG_FILE}
-                exit_code=1
-                break
-            fi
-            echo "Waiting for TLS Iggy server to start... ${SERVER_START_TIME}"
-            sleep 1
-            ((SERVER_START_TIME += 1))
-        done
-
-        if [ "${exit_code}" -eq 0 ]; then
-            while IFS= read -r command; do
-                # Remove backticks and comments from command
-                command=$(echo "${command}" | tr -d '`' | sed 's/^#.*//')
-                # Skip empty lines
-                if [ -z "${command}" ]; then
-                    continue
-                fi
-
-                # Add target flag if specified
-                if [ -n "${CSOS}" ]; then
-                    command="${command//dotnet run /dotnet run --os ${CSOS} }"
-                fi
-
-                if [ -n "${CSARCH}" ]; then
-                    command="${command//dotnet run /dotnet run --arch 
${CSARCH} }"
-                fi
-
-                echo -e "\e[33mChecking TLS example command:\e[0m ${command}"
-                echo ""
-
-                set +e
-                eval "${command}"
-                exit_code=$?
-                set -e
-
-                # Stop at first failure
-                if [ ${exit_code} -ne 0 ]; then
-                    echo ""
-                    echo -e "\e[31mTLS example command failed:\e[0m ${command}"
-                    echo ""
-                    break
-                fi
-                # Add a small delay between examples to avoid potential race 
conditions
-                sleep 2
-
-            done < <(grep -E "^dotnet run --project.*TcpTls" "${TLS_README}")
-        fi
-
-        # Terminate TLS server
-        if [ -e ${PID_FILE} ]; then
-            kill -TERM "$(cat ${PID_FILE})" 2>/dev/null || true
-            rm -f ${PID_FILE}
-        fi
-    fi
-fi
-
-# If everything is ok remove log and pid files otherwise cat server log
-if [ "${exit_code}" -eq 0 ]; then
-    echo "Test passed"
-else
-    echo "Test failed, see log file:"
-    test -e ${LOG_FILE} && cat ${LOG_FILE}
-fi
-
-test -e ${LOG_FILE} && rm ${LOG_FILE}
-test -e ${PID_FILE} && rm ${PID_FILE}
-
-exit "${exit_code}"
diff --git a/scripts/run-examples-from-readme.sh 
b/scripts/run-examples-from-readme.sh
new file mode 100755
index 000000000..35c8dc9c6
--- /dev/null
+++ b/scripts/run-examples-from-readme.sh
@@ -0,0 +1,372 @@
+#!/bin/bash
+
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+set -euo pipefail
+
+# Unified script to run SDK examples from README.md files.
+# Usage: ./scripts/run-examples-from-readme.sh [OPTIONS]
+#
+#   --language LANG   Language to test: rust|go|node|python|java|csharp 
(default: all)
+#   --target TARGET   Cargo target architecture for the server binary
+#   --skip-tls        Skip TLS example tests
+#
+# The script sources shared utilities from scripts/utils.sh, starts the iggy
+# server (built from source), parses example commands from each language's
+# README.md, and executes them. Non-TLS examples run first; then the server
+# is restarted with TLS for TLS-specific examples.
+
+SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
+# shellcheck source=scripts/utils.sh
+source "${SCRIPT_DIR}/utils.sh"
+
+ROOT_WORKDIR="$(pwd)"
+
+# ---------------------------------------------------------------------------
+# Argument parsing
+# ---------------------------------------------------------------------------
+LANGUAGE="all"
+TARGET=""
+SKIP_TLS=false
+
+while [[ $# -gt 0 ]]; do
+    case "$1" in
+        --language)   LANGUAGE="$2";  shift 2 ;;
+        --target)     TARGET="$2";    shift 2 ;;
+        --skip-tls)   SKIP_TLS=true;  shift   ;;
+        *)
+            echo "Unknown option: $1"
+            echo "Usage: $0 [--language LANG] [--target TARGET] [--skip-tls]"
+            exit 1
+            ;;
+    esac
+done
+
+# ---------------------------------------------------------------------------
+# Helpers
+# ---------------------------------------------------------------------------
+
+# Run a full non-TLS + TLS cycle for one language.
+# Arguments:
+#   $1 - language label (for logging)
+#   $2 - working directory (relative to repo root, or "." for root)
+#   $3 - space-separated list of README files (relative to workdir)
+#   $4 - grep pattern for non-TLS commands
+#   $5 - grep exclude pattern for non-TLS commands (empty = no exclude)
+#   $6 - grep pattern for TLS commands (empty = no TLS examples)
+#   $7 - per-command timeout in seconds (0 = no timeout)
+#   $8 - extra server args (e.g. "--fresh")
+#   $9 - optional pre-flight callback function name (run before non-TLS 
examples, with server already started)
+# shellcheck disable=SC2329
+run_language_examples() {
+    local lang="$1"
+    local workdir="$2"
+    local readme_files="$3"
+    local grep_pattern="$4"
+    local grep_exclude="$5"
+    local tls_grep_pattern="$6"
+    local cmd_timeout="$7"
+    local server_extra_args="$8"
+    local preflight_fn="${9:-}"
+
+    echo ""
+    echo "============================================================"
+    echo "  Running ${lang} examples"
+    echo "============================================================"
+    echo ""
+
+    EXAMPLES_EXIT_CODE=0
+
+    # --- Non-TLS pass ---
+    cleanup_server_state
+    # shellcheck disable=SC2086
+    start_plain_server ${server_extra_args}
+    wait_for_server_ready "${lang}"
+
+    # Run optional pre-flight callback (e.g. CLI commands from root README)
+    if [ -n "${preflight_fn}" ] && declare -f "${preflight_fn}" >/dev/null 
2>&1; then
+        ${preflight_fn}
+        if [ "${EXAMPLES_EXIT_CODE}" -ne 0 ]; then
+            cd "${ROOT_WORKDIR}"
+            stop_server
+            report_result "${EXAMPLES_EXIT_CODE}"
+            return "${EXAMPLES_EXIT_CODE}"
+        fi
+    fi
+
+    if [ "${workdir}" != "." ]; then
+        cd "${workdir}"
+    fi
+
+    for readme in ${readme_files}; do
+        if [ "${EXAMPLES_EXIT_CODE}" -ne 0 ]; then
+            break
+        fi
+        run_readme_commands "${readme}" "${grep_pattern}" "${cmd_timeout}" 
"${grep_exclude}"
+    done
+
+    cd "${ROOT_WORKDIR}"
+    stop_server
+
+    # --- TLS pass ---
+    if [ "${EXAMPLES_EXIT_CODE}" -eq 0 ] && [ "${SKIP_TLS}" = false ] && [ -n 
"${tls_grep_pattern}" ]; then
+        local has_tls=false
+        for readme in ${readme_files}; do
+            local readme_path="${readme}"
+            if [ "${workdir}" != "." ]; then
+                readme_path="${workdir}/${readme}"
+            fi
+            if [ -f "${readme_path}" ] && grep -qE "${tls_grep_pattern}" 
"${readme_path}" 2>/dev/null; then
+                has_tls=true
+                break
+            fi
+        done
+
+        if [ "${has_tls}" = true ]; then
+            echo ""
+            echo "=== Running ${lang} TLS examples ==="
+            echo ""
+
+            cleanup_server_state
+            # shellcheck disable=SC2086
+            start_tls_server ${server_extra_args}
+            wait_for_server_ready "${lang} TLS"
+
+            if [ "${workdir}" != "." ]; then
+                cd "${workdir}"
+            fi
+
+            for readme in ${readme_files}; do
+                if [ "${EXAMPLES_EXIT_CODE}" -ne 0 ]; then
+                    break
+                fi
+                run_readme_commands "${readme}" "${tls_grep_pattern}" 
"${cmd_timeout}"
+            done
+
+            cd "${ROOT_WORKDIR}"
+            stop_server
+        fi
+    fi
+
+    report_result "${EXAMPLES_EXIT_CODE}"
+    return "${EXAMPLES_EXIT_CODE}"
+}
+
+# ---------------------------------------------------------------------------
+# Per-language runners
+# ---------------------------------------------------------------------------
+
+# shellcheck disable=SC2329
+run_rust_examples() {
+    resolve_server_binary "${TARGET}"
+    resolve_cli_binary "${TARGET}"
+
+    if [ -n "${TARGET}" ]; then
+        TRANSFORM_COMMAND() {
+            echo "$1" | sed "s|cargo r |cargo r --target ${TARGET} |g" | sed 
"s|cargo run |cargo run --target ${TARGET} |g"
+        }
+    else
+        unset -f TRANSFORM_COMMAND 2>/dev/null || true
+    fi
+
+    # Pre-flight: run CLI commands from root README
+    _rust_preflight() {
+        run_readme_commands "README.md" '^\`cargo r --bin iggy -- '
+    }
+
+    run_language_examples \
+        "Rust" \
+        "." \
+        "README.md examples/rust/README.md" \
+        "^cargo run --example" \
+        "tcp-tls" \
+        "^cargo run --example.*tcp-tls" \
+        0 \
+        "" \
+        "_rust_preflight"
+}
+
+# shellcheck disable=SC2329
+run_node_examples() {
+    resolve_server_binary "${TARGET}"
+
+    export DEBUG=iggy:examples
+    unset -f TRANSFORM_COMMAND 2>/dev/null || true
+
+    run_language_examples \
+        "Node.js" \
+        "examples/node" \
+        "README.md" \
+        "^(npm run|tsx)" \
+        "tcp-tls" \
+        "^(npm run|tsx).*tcp-tls" \
+        0 \
+        ""
+}
+
+# shellcheck disable=SC2329
+run_go_examples() {
+    resolve_server_binary "${TARGET}"
+    unset -f TRANSFORM_COMMAND 2>/dev/null || true
+
+    run_language_examples \
+        "Go" \
+        "examples/go" \
+        "README.md" \
+        "^go run" \
+        "--tls" \
+        "^go run.*--tls" \
+        0 \
+        ""
+}
+
+# shellcheck disable=SC2329
+run_python_examples() {
+    resolve_server_binary "${TARGET}"
+    unset -f TRANSFORM_COMMAND 2>/dev/null || true
+
+    echo ""
+    echo "============================================================"
+    echo "  Running Python examples"
+    echo "============================================================"
+    echo ""
+
+    EXAMPLES_EXIT_CODE=0
+
+    # --- Non-TLS pass ---
+    cleanup_server_state
+    start_plain_server --fresh
+    wait_for_server_ready "Python"
+
+    cd examples/python || exit 1
+    echo "Syncing Python dependencies with uv..."
+    uv sync --frozen
+
+    run_readme_commands "README.md" "^uv run " 10 "--tls"
+
+    cd "${ROOT_WORKDIR}"
+    stop_server
+
+    # --- TLS pass ---
+    if [ "${EXAMPLES_EXIT_CODE}" -eq 0 ] && [ "${SKIP_TLS}" = false ]; then
+        local tls_readme="examples/python/README.md"
+        if [ -f "${tls_readme}" ] && grep -qE "^uv run.*tls" "${tls_readme}" 
2>/dev/null; then
+            echo ""
+            echo "=== Running Python TLS examples ==="
+            echo ""
+            cleanup_server_state
+            start_tls_server --fresh
+            wait_for_server_ready "Python TLS"
+
+            cd examples/python || exit 1
+            run_readme_commands "README.md" "^uv run.*tls" 10
+            cd "${ROOT_WORKDIR}"
+            stop_server
+        fi
+    fi
+
+    report_result "${EXAMPLES_EXIT_CODE}"
+    return "${EXAMPLES_EXIT_CODE}"
+}
+
+# shellcheck disable=SC2329
+run_java_examples() {
+    resolve_server_binary "${TARGET}"
+    unset -f TRANSFORM_COMMAND 2>/dev/null || true
+
+    run_language_examples \
+        "Java" \
+        "examples/java" \
+        "README.md" \
+        '^\./gradlew' \
+        "TcpTls" \
+        '^\./gradlew.*TcpTls' \
+        0 \
+        ""
+}
+
+# shellcheck disable=SC2329
+run_csharp_examples() {
+    resolve_server_binary "${TARGET}"
+    unset -f TRANSFORM_COMMAND 2>/dev/null || true
+
+    # Pre-flight: run CLI commands from root README
+    _csharp_preflight() {
+        run_readme_commands "README.md" '^\`cargo r --bin iggy -- '
+    }
+
+    run_language_examples \
+        "C#" \
+        "." \
+        "README.md examples/csharp/README.md" \
+        "^dotnet run --project" \
+        "TcpTls" \
+        "^dotnet run --project.*TcpTls" \
+        0 \
+        "" \
+        "_csharp_preflight"
+}
+
+# ---------------------------------------------------------------------------
+# Main
+# ---------------------------------------------------------------------------
+
+overall_exit_code=0
+
+run_one() {
+    local lang_fn="$1"
+    local lang_name="$2"
+
+    EXAMPLES_EXIT_CODE=0
+    unset -f TRANSFORM_COMMAND 2>/dev/null || true
+
+    set +e
+    ${lang_fn}
+    local rc=$?
+    set -e
+
+    unset -f TRANSFORM_COMMAND 2>/dev/null || true
+
+    if [ ${rc} -ne 0 ]; then
+        echo ""
+        echo -e "\e[31m${lang_name} examples FAILED (exit code ${rc})\e[0m"
+        overall_exit_code=1
+    fi
+    cd "${ROOT_WORKDIR}"
+}
+
+case "${LANGUAGE}" in
+    rust)   run_one run_rust_examples   "Rust"   ;;
+    node)   run_one run_node_examples   "Node"   ;;
+    go)     run_one run_go_examples     "Go"     ;;
+    python) run_one run_python_examples "Python" ;;
+    java)   run_one run_java_examples   "Java"   ;;
+    csharp) run_one run_csharp_examples "C#"     ;;
+    all)
+        for lang in rust node go python java csharp; do
+            run_one "run_${lang}_examples" "${lang}"
+        done
+        ;;
+    *)
+        echo "Unknown language: ${LANGUAGE}"
+        echo "Supported: rust, node, go, python, java, csharp, all"
+        exit 1
+        ;;
+esac
+
+exit "${overall_exit_code}"
diff --git a/scripts/run-go-examples-from-readme.sh 
b/scripts/run-go-examples-from-readme.sh
deleted file mode 100755
index 437b3f872..000000000
--- a/scripts/run-go-examples-from-readme.sh
+++ /dev/null
@@ -1,258 +0,0 @@
-#!/bin/bash
-
-# Licensed to the Apache Software Foundation (ASF) under one
-# or more contributor license agreements.  See the NOTICE file
-# distributed with this work for additional information
-# regarding copyright ownership.  The ASF licenses this file
-# to you under the Apache License, Version 2.0 (the
-# "License"); you may not use this file except in compliance
-# with the License.  You may obtain a copy of the License at
-#
-#   http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing,
-# software distributed under the License is distributed on an
-# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-# KIND, either express or implied.  See the License for the
-# specific language governing permissions and limitations
-# under the License.
-
-set -euo pipefail
-
-# Script to run Go examples from examples/go/README.md files
-# Usage: ./scripts/run-go-examples-from-readme.sh [OPTIONS]
-#
-# --goos   - Optional target OS (e.g., linux, darwin)
-# --goarch - Optional target architecture (e.g., amd64, arm64)
-# --target - Optional target architecture for rust (e.g., 
x86_64-unknown-linux-musl)
-# If not provided, uses the default target
-#
-# This script will run all the commands from examples/go/README.md files
-# and check if they pass or fail.
-# If any command fails, it will print the command and exit with non-zero 
status.
-# If all commands pass, it will remove the log file and exit with zero status.
-#
-# Note: This script assumes that the iggy-server is not running and will start 
it in the background.
-#       It will wait until the server is started before running the commands.
-#       It will also terminate the server after running all the commands.
-#       Script executes every command in examples/go/README.md files which is 
enclosed in backticks (`) and starts
-#       with `go run`. Other commands are ignored.
-#       Order of commands in README files is important as script will execute 
them from top to bottom.
-#
-
-readonly LOG_FILE="iggy-server.log"
-readonly PID_FILE="iggy-server.pid"
-readonly TIMEOUT=300
-
-GOOS="" # Go target OS
-GOARCH="" # Go target architecture
-TARGET="" # Iggy server target architecture
-
-# Get GOOS, GOARCH, and Cargo --target values from arguments or use defaults
-while [[ $# -gt 0 ]]; do
-    case "$1" in
-        --goos)
-            GOOS="$2"
-            shift 2
-            ;;
-        --goarch)
-            GOARCH="$2"
-            shift 2
-            ;;
-        --target)
-            TARGET="$2"
-            shift 2
-            ;;
-        *)
-            echo "Unknown option: $1"
-            echo "Usage: $0 [--goos GOOS] [--goarch GOARCH] [--target TARGET]"
-            exit 1
-            ;;
-    esac
-done
-
-if [ -n "${GOOS}" ]; then
-    echo "Using GOOS=${GOOS}"
-fi
-if [ -n "${GOARCH}" ]; then
-    echo "Using GOARCH=${GOARCH}"
-fi
-if [ -n "${TARGET}" ]; then
-    echo "Using cargo --target ${TARGET}"
-fi
-
-# Remove old server data if present
-test -d local_data && rm -fr local_data
-test -e ${LOG_FILE} && rm ${LOG_FILE}
-test -e ${PID_FILE} && rm ${PID_FILE}
-
-# Check if server binary exists
-SERVER_BIN=""
-if [ -n "${TARGET}" ]; then
-    SERVER_BIN="target/${TARGET}/debug/iggy-server"
-else
-    SERVER_BIN="target/debug/iggy-server"
-fi
-
-if [ ! -f "${SERVER_BIN}" ]; then
-    echo "Error: Server binary not found at ${SERVER_BIN}"
-    echo "Please build the server binary before running this script:"
-    if [ -n "${TARGET}" ]; then
-        echo "  cargo build --target ${TARGET} --bin iggy-server"
-    else
-        echo "  cargo build --bin iggy-server"
-    fi
-    exit 1
-fi
-
-echo "Using server binary at ${SERVER_BIN}"
-
-# Run iggy server using the prebuilt binary
-echo "Starting server from ${SERVER_BIN}..."
-IGGY_ROOT_USERNAME=iggy IGGY_ROOT_PASSWORD=iggy ${SERVER_BIN} &>${LOG_FILE} &
-echo $! >${PID_FILE}
-
-# Wait until "Iggy server has started" string is present inside iggy-server.log
-SERVER_START_TIME=0
-while ! grep -q "has started" ${LOG_FILE}; do
-    if [ ${SERVER_START_TIME} -gt ${TIMEOUT} ]; then
-        echo "Server did not start within ${TIMEOUT} seconds."
-        ps fx
-        cat ${LOG_FILE}
-        exit 1
-    fi
-    echo "Waiting for Iggy server to start... ${SERVER_START_TIME}"
-    sleep 1
-    ((SERVER_START_TIME += 1))
-done
-
-cd examples/go
-
-# Execute all example commands from examples/go/README.md and check if they 
pass or fail
-exit_code=0
-if [ -f "README.md" ]; then
-    while IFS= read -r command; do
-        # Remove backticks and comments from command
-        command=$(echo "${command}" | tr -d '`' | sed 's/^#.*//')
-        # Skip empty lines
-        if [ -z "${command}" ]; then
-            continue
-        fi
-        # Add GOOS/GOARCH env if specified
-        [ -n "${GOOS}" ] && command="GOOS=${GOOS} ${command}"
-        [ -n "${GOARCH}" ] && command="GOARCH=${GOARCH} ${command}"
-
-        echo -e "\e[33mChecking example command from 
examples/go/README.md:\e[0m ${command}"
-        echo ""
-
-        set +e
-        eval "${command}"
-        exit_code=$?
-        set -e
-
-        # Stop at first failure
-        if [ ${exit_code} -ne 0 ]; then
-            echo ""
-            echo -e "\e[31mExample command failed:\e[0m ${command}"
-            echo ""
-            break
-        fi
-        # Add a small delay between examples to avoid potential race conditions
-        sleep 2
-
-    done < <(grep -E "^go run" "README.md")
-fi
-
-cd ../..
-
-# Terminate server
-kill -TERM "$(cat ${PID_FILE})"
-test -e ${PID_FILE} && rm ${PID_FILE}
-
-# --- TLS Test Pass ---
-if [ "${exit_code}" -eq 0 ]; then
-    echo ""
-    echo -e "\e[36m=== Starting TLS test pass ===\e[0m"
-    echo ""
-
-    # Clean data and logs for fresh TLS start
-    rm -fr local_data
-    rm -f ${LOG_FILE}
-
-    # Start server with TLS enabled
-    echo "Starting server with TLS enabled..."
-    IGGY_ROOT_USERNAME=iggy IGGY_ROOT_PASSWORD=iggy IGGY_TCP_TLS_ENABLED=true 
${SERVER_BIN} &>${LOG_FILE} &
-    echo $! >${PID_FILE}
-
-    # Wait for server to start
-    SERVER_START_TIME=0
-    while ! grep -q "has started" ${LOG_FILE}; do
-        if [ ${SERVER_START_TIME} -gt ${TIMEOUT} ]; then
-            echo "TLS server did not start within ${TIMEOUT} seconds."
-            ps fx
-            cat ${LOG_FILE}
-            exit 1
-        fi
-        echo "Waiting for Iggy TLS server to start... ${SERVER_START_TIME}"
-        sleep 1
-        ((SERVER_START_TIME += 1))
-    done
-
-    # Verify TLS is enabled
-    if ! grep -q "tls: { enabled: true" ${LOG_FILE}; then
-        echo -e "\e[31mError: TLS not enabled on server\e[0m"
-        grep -A 5 "tcp:" ${LOG_FILE} || true
-        exit 1
-    fi
-    echo -e "\e[32mโœ“ TLS enabled on server\e[0m"
-
-    cd examples/go || exit 1
-
-    # Run getting-started examples with TLS flags
-    # Use localhost instead of 127.0.0.1 to match the cert's SAN 
(DNS:localhost)
-    TLS_CA_FILE="../../core/certs/iggy_ca_cert.pem"
-    TLS_ADDR="localhost:8090"
-
-    for cmd in \
-        "go run getting-started/producer/main.go --tcp-server-address 
${TLS_ADDR} --tls --tls-ca-file ${TLS_CA_FILE}" \
-        "go run getting-started/consumer/main.go --tcp-server-address 
${TLS_ADDR} --tls --tls-ca-file ${TLS_CA_FILE}"; do
-
-        echo -e "\e[33mChecking TLS example:\e[0m ${cmd}"
-        echo ""
-
-        set +e
-        eval "timeout 10 ${cmd}"
-        test_exit_code=$?
-        set -e
-
-        if [[ $test_exit_code -ne 0 && $test_exit_code -ne 124 ]]; then
-            echo ""
-            echo -e "\e[31mTLS example command failed:\e[0m ${cmd}"
-            echo ""
-            exit_code=$test_exit_code
-            break
-        fi
-        sleep 2
-    done
-
-    cd ../..
-
-    # Terminate TLS server
-    kill -TERM "$(cat ${PID_FILE})" 2>/dev/null || true
-    test -e ${PID_FILE} && rm ${PID_FILE}
-fi
-
-# If everything is ok remove log and pid files otherwise cat server log
-if [ "${exit_code}" -eq 0 ]; then
-    echo ""
-    echo -e "\e[32mโœ“ All tests passed (non-TLS + TLS)\e[0m"
-    echo ""
-else
-    echo "Test failed, see log file:"
-    test -e ${LOG_FILE} && cat ${LOG_FILE}
-fi
-
-test -e ${LOG_FILE} && rm ${LOG_FILE}
-test -e ${PID_FILE} && rm ${PID_FILE}
-
-exit "${exit_code}"
diff --git a/scripts/run-java-examples-from-readme.sh 
b/scripts/run-java-examples-from-readme.sh
deleted file mode 100755
index 0c78cda2d..000000000
--- a/scripts/run-java-examples-from-readme.sh
+++ /dev/null
@@ -1,221 +0,0 @@
-#!/bin/bash
-
-#
-# Licensed to the Apache Software Foundation (ASF) under one
-# or more contributor license agreements.  See the NOTICE file
-# distributed with this work for additional information
-# regarding copyright ownership.  The ASF licenses this file
-# to you under the Apache License, Version 2.0 (the
-# "License"); you may not use this file except in compliance
-# with the License.  You may obtain a copy of the License at
-#
-#   http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing,
-# software distributed under the License is distributed on an
-# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-# KIND, either express or implied.  See the License for the
-# specific language governing permissions and limitations
-# under the License.
-#
-
-set -euo pipefail
-
-# Script to run Java examples from examples/java/README.md
-# Usage: ./scripts/run-java-examples-from-readme.sh [TARGET]
-#
-# TARGET - Optional target architecture (e.g., x86_64-unknown-linux-musl)
-#          If not provided, uses the default target
-#
-# This script scans examples/java/README.md for commands starting with
-# `./gradlew` and executes them in order. If any command fails, the script
-# stops immediately and prints the relevant iggy-server logs.
-
-readonly LOG_FILE="iggy-server.log"
-readonly PID_FILE="iggy-server.pid"
-readonly TIMEOUT=300
-
-ROOT_WORKDIR="$(pwd)"
-TARGET="${1:-}"
-
-if [ -n "${TARGET}" ]; then
-    echo "Using target architecture: ${TARGET}"
-else
-    echo "Using default target architecture"
-fi
-
-# Remove old server data if present
-test -d local_data && rm -fr local_data
-test -e ${LOG_FILE} && rm ${LOG_FILE}
-test -e ${PID_FILE} && rm ${PID_FILE}
-
-# Check if server binary exists
-SERVER_BIN=""
-if [ -n "${TARGET}" ]; then
-    SERVER_BIN="target/${TARGET}/debug/iggy-server"
-else
-    SERVER_BIN="target/debug/iggy-server"
-fi
-
-if [ ! -f "${SERVER_BIN}" ]; then
-    echo "Error: Server binary not found at ${SERVER_BIN}"
-    echo "Please build the server binary before running this script:"
-    if [ -n "${TARGET}" ]; then
-        echo "  cargo build --target ${TARGET} --bin iggy-server"
-    else
-        echo "  cargo build --bin iggy-server"
-    fi
-    exit 1
-fi
-
-echo "Using server binary at ${SERVER_BIN}"
-
-# Run iggy server using the prebuilt binary
-echo "Starting server from ${SERVER_BIN}..."
-IGGY_ROOT_USERNAME=iggy IGGY_ROOT_PASSWORD=iggy ${SERVER_BIN} &>${LOG_FILE} &
-echo $! >${PID_FILE}
-
-# Wait until "Iggy server has started" string is present inside iggy-server.log
-SERVER_START_TIME=0
-while ! grep -q "has started" ${LOG_FILE}; do
-    if [ ${SERVER_START_TIME} -gt ${TIMEOUT} ]; then
-        echo "Server did not start within ${TIMEOUT} seconds."
-        ps fx
-        cat ${LOG_FILE}
-        exit 1
-    fi
-    echo "Waiting for Iggy server to start... ${SERVER_START_TIME}"
-    sleep 1
-    ((SERVER_START_TIME += 1))
-done
-
-cd examples/java
-
-exit_code=0
-README_FILE="README.md"
-
-if [ -f "${README_FILE}" ]; then
-    while IFS= read -r command; do
-        # Remove backticks and comments from command
-        command=$(echo "${command}" | tr -d '`' | sed 's/^#.*//')
-        # Skip empty lines
-        if [ -z "${command}" ]; then
-            continue
-        fi
-
-        echo -e "\e[33mChecking example command from ${README_FILE}:\e[0m 
${command}"
-        echo ""
-
-        set +e
-        eval "${command}"
-        exit_code=$?
-        set -e
-
-        if [ ${exit_code} -ne 0 ]; then
-            echo ""
-            echo -e "\e[31mExample command failed:\e[0m ${command}"
-            echo ""
-            break
-        fi
-
-        # Small delay between runs to avoid thrashing the server
-        sleep 2
-    done < <(grep -E '^\./gradlew' "${README_FILE}" | grep -v "TcpTls")
-else
-    echo "README file ${README_FILE} not found in examples/java."
-fi
-
-cd "${ROOT_WORKDIR}"
-
-# Terminate non-TLS server
-kill -TERM "$(cat ${PID_FILE})"
-test -e ${PID_FILE} && rm ${PID_FILE}
-
-# Run TLS examples if non-TLS examples passed
-if [ "${exit_code}" -eq 0 ]; then
-    TLS_README="examples/java/README.md"
-    if [ -f "${TLS_README}" ] && grep -qE '^\./gradlew.*TcpTls' 
"${TLS_README}"; then
-        echo ""
-        echo "=== Running TLS examples ==="
-        echo ""
-
-        # Clean up for fresh TLS start
-        test -d local_data && rm -fr local_data
-        test -e ${LOG_FILE} && rm ${LOG_FILE}
-
-        # Start TLS server
-        echo "Starting TLS server from ${SERVER_BIN}..."
-        IGGY_ROOT_USERNAME=iggy IGGY_ROOT_PASSWORD=iggy \
-            IGGY_TCP_TLS_ENABLED=true \
-            IGGY_TCP_TLS_CERT_FILE=core/certs/iggy_cert.pem \
-            IGGY_TCP_TLS_KEY_FILE=core/certs/iggy_key.pem \
-            ${SERVER_BIN} &>${LOG_FILE} &
-        echo $! >${PID_FILE}
-
-        # Wait for TLS server to start
-        SERVER_START_TIME=0
-        while ! grep -q "has started" ${LOG_FILE}; do
-            if [ ${SERVER_START_TIME} -gt ${TIMEOUT} ]; then
-                echo "TLS server did not start within ${TIMEOUT} seconds."
-                ps fx
-                cat ${LOG_FILE}
-                exit_code=1
-                break
-            fi
-            echo "Waiting for TLS Iggy server to start... ${SERVER_START_TIME}"
-            sleep 1
-            ((SERVER_START_TIME += 1))
-        done
-
-        if [ "${exit_code}" -eq 0 ]; then
-            cd examples/java
-
-            while IFS= read -r command; do
-                # Remove backticks and comments from command
-                command=$(echo "${command}" | tr -d '`' | sed 's/^#.*//')
-                # Skip empty lines
-                if [ -z "${command}" ]; then
-                    continue
-                fi
-
-                echo -e "\e[33mChecking TLS example command:\e[0m ${command}"
-                echo ""
-
-                set +e
-                eval "${command}"
-                exit_code=$?
-                set -e
-
-                if [ ${exit_code} -ne 0 ]; then
-                    echo ""
-                    echo -e "\e[31mTLS example command failed:\e[0m ${command}"
-                    echo ""
-                    break
-                fi
-
-                # Small delay between runs to avoid thrashing the server
-                sleep 2
-            done < <(grep -E '^\./gradlew.*TcpTls' 
"${ROOT_WORKDIR}/${TLS_README}")
-
-            cd "${ROOT_WORKDIR}"
-        fi
-
-        # Terminate TLS server
-        if [ -e ${PID_FILE} ]; then
-            kill -TERM "$(cat ${PID_FILE})" 2>/dev/null || true
-            rm -f ${PID_FILE}
-        fi
-    fi
-fi
-
-if [ "${exit_code}" -eq 0 ]; then
-    echo "Test passed"
-else
-    echo "Test failed, see log file:"
-    test -e ${LOG_FILE} && cat ${LOG_FILE}
-fi
-
-test -e ${LOG_FILE} && rm ${LOG_FILE}
-test -e ${PID_FILE} && rm ${PID_FILE}
-
-exit "${exit_code}"
diff --git a/scripts/run-node-examples-from-readme.sh 
b/scripts/run-node-examples-from-readme.sh
deleted file mode 100755
index 449f44d59..000000000
--- a/scripts/run-node-examples-from-readme.sh
+++ /dev/null
@@ -1,264 +0,0 @@
-#!/bin/bash
-
-# Licensed to the Apache Software Foundation (ASF) under one
-# or more contributor license agreements.  See the NOTICE file
-# distributed with this work for additional information
-# regarding copyright ownership.  The ASF licenses this file
-# to you under the Apache License, Version 2.0 (the
-# "License"); you may not use this file except in compliance
-# with the License.  You may obtain a copy of the License at
-#
-#   http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing,
-# software distributed under the License is distributed on an
-# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-# KIND, either express or implied.  See the License for the
-# specific language governing permissions and limitations
-# under the License.
-
-set -euo pipefail
-
-# Script to run Node.js examples from examples/nodejs/README.md files
-# Usage: ./scripts/run-node-examples-from-readme.sh [OPTIONS]
-#
-# --target - Optional target architecture for rust (e.g., 
x86_64-unknown-linux-musl)
-#
-# This script will run all the commands from examples/nodejs/README.md files
-# and check if they pass or fail.
-# If any command fails, it will print the command and exit with non-zero 
status.
-# If all commands pass, it will remove the log file and exit with zero status.
-#
-# Note: This script assumes that the iggy-server is not running and will start 
it in the background.
-#       It will wait until the server is started before running the commands.
-#       It will also terminate the server after running all the commands.
-#       Script executes every command in README files which is enclosed in 
backticks (`) and starts
-#       with `npm run` or `tsx`. Other commands are ignored.
-#       Order of commands in README files is important as script will execute 
them from top to bottom.
-#
-
-readonly LOG_FILE="iggy-server.log"
-readonly PID_FILE="iggy-server.pid"
-readonly TIMEOUT=300
-ROOT_WORKDIR="$(pwd)"
-#set debug env
-export DEBUG=iggy:examples
-# Get target architecture from argument or use default
-
-TARGET="" # Iggy server target architecture
-
-while [[ $# -gt 0 ]]; do
-    case "$1" in
-        --target)
-            TARGET="$2"
-            shift 2
-            ;;
-        *)
-            echo "Unknown option: $1"
-            echo "Usage: $0 [--target TARGET]"
-            exit 1
-            ;;
-    esac
-done
-
-# Remove old server data if present
-test -d local_data && rm -fr local_data
-test -e ${LOG_FILE} && rm ${LOG_FILE}
-test -e ${PID_FILE} && rm ${PID_FILE}
-
-# Check if server binary exists
-SERVER_BIN=""
-if [ -n "${TARGET}" ]; then
-    SERVER_BIN="target/${TARGET}/debug/iggy-server"
-else
-    SERVER_BIN="target/debug/iggy-server"
-fi
-
-if [ ! -f "${SERVER_BIN}" ]; then
-    echo "Error: Server binary not found at ${SERVER_BIN}"
-    echo "Please build the server binary before running this script:"
-    if [ -n "${TARGET}" ]; then
-        echo "  cargo build --target ${TARGET} --bin iggy-server"
-    else
-        echo "  cargo build --bin iggy-server"
-    fi
-    exit 1
-fi
-
-echo "Using server binary at ${SERVER_BIN}"
-
-# Run iggy server using the prebuilt binary
-echo "Starting server from ${SERVER_BIN}..."
-IGGY_ROOT_USERNAME=iggy IGGY_ROOT_PASSWORD=iggy ${SERVER_BIN} &>${LOG_FILE} &
-echo $! >${PID_FILE}
-
-# Wait until "Iggy server has started" string is present inside iggy-server.log
-SERVER_START_TIME=0
-while ! grep -q "has started" ${LOG_FILE}; do
-    if [ ${SERVER_START_TIME} -gt ${TIMEOUT} ]; then
-        echo "Server did not start within ${TIMEOUT} seconds."
-        ps fx
-        cat ${LOG_FILE}
-        exit 1
-    fi
-    echo "Waiting for Iggy server to start... ${SERVER_START_TIME}"
-    sleep 1
-    ((SERVER_START_TIME += 1))
-done
-
-# Execute all matching CLI commands from README.md and check if they pass or 
fail
-while IFS= read -r command; do
-    # Remove backticks from command
-    command=$(echo "${command}" | tr -d '`')
-    
-    echo -e "\e[33mChecking CLI command:\e[0m ${command}"
-    echo ""
-
-    set +e
-    eval "${command}"
-    exit_code=$?
-    set -e
-
-    # Stop at first failure
-    if [ ${exit_code} -ne 0 ]; then
-        echo ""
-        echo -e "\e[31mCLI command failed:\e[0m ${command}"
-        echo ""
-        break
-    fi
-
-done < <(grep -E "^\`cargo r --bin iggy -- " README.md)
-
-cd examples/node
-
-# Execute all non-TLS example commands from README.md and 
examples/node/README.md
-for readme_file in README.md examples/node/README.md; do
-    if [ ! -f "${readme_file}" ]; then
-        continue
-    fi
-
-    while IFS= read -r command; do
-        # Remove backticks and comments from command
-        command=$(echo "${command}" | tr -d '`' | sed 's/^#.*//')
-        # Skip empty lines
-        if [ -z "${command}" ]; then
-            continue
-        fi
-        
-        echo -e "\e[33mChecking example command from ${readme_file}:\e[0m 
${command}"
-        echo ""
-
-        set +e
-        eval "${command}"
-        exit_code=$?
-        set -e
-
-        # Stop at first failure
-        if [ ${exit_code} -ne 0 ]; then
-            echo ""
-            echo -e "\e[31mExample command failed:\e[0m ${command}"
-            echo ""
-            break 2 # Break from both loops
-        fi
-        # Add a small delay between examples to avoid potential race conditions
-        sleep 2
-
-    done < <(grep -E "^(npm run|tsx)" "${readme_file}" | grep -v "tcp-tls")
-done
-
-cd "${ROOT_WORKDIR}"
-
-# Stop the plain server before starting TLS server
-kill -TERM "$(cat ${PID_FILE})" 2>/dev/null || true
-sleep 2
-test -e ${PID_FILE} && rm ${PID_FILE}
-test -e ${LOG_FILE} && rm ${LOG_FILE}
-
-# Check if there are any TLS examples to run
-TLS_COMMANDS=""
-if [ -f "examples/node/README.md" ]; then
-    TLS_COMMANDS=$(grep -E "^(npm run|tsx)" "examples/node/README.md" | grep 
"tcp-tls" || true)
-fi
-
-if [ -n "${TLS_COMMANDS}" ] && [ "${exit_code}" -eq 0 ]; then
-    echo ""
-    echo "=== Starting TLS server for TLS examples ==="
-
-    # Remove old server data for clean TLS test
-    test -d local_data && rm -fr local_data
-
-    # Start TLS-enabled server
-    IGGY_ROOT_USERNAME=iggy IGGY_ROOT_PASSWORD=iggy \
-    IGGY_TCP_TLS_ENABLED=true \
-    IGGY_TCP_TLS_CERT_FILE=core/certs/iggy_cert.pem \
-    IGGY_TCP_TLS_KEY_FILE=core/certs/iggy_key.pem \
-    ${SERVER_BIN} &>${LOG_FILE} &
-    echo $! >${PID_FILE}
-
-    # Wait for TLS server to start
-    SERVER_START_TIME=0
-    while ! grep -q "has started" ${LOG_FILE}; do
-        if [ ${SERVER_START_TIME} -gt ${TIMEOUT} ]; then
-            echo "TLS server did not start within ${TIMEOUT} seconds."
-            cat ${LOG_FILE}
-            exit 1
-        fi
-        echo "Waiting for TLS Iggy server to start... ${SERVER_START_TIME}"
-        sleep 1
-        ((SERVER_START_TIME += 1))
-    done
-
-    cd examples/node
-
-    # Run only TLS examples
-    for readme_file in README.md examples/node/README.md; do
-        if [ ! -f "${readme_file}" ]; then
-            continue
-        fi
-
-        while IFS= read -r command; do
-            command=$(echo "${command}" | tr -d '`' | sed 's/^#.*//')
-            if [ -z "${command}" ]; then
-                continue
-            fi
-
-            echo -e "\e[33mChecking TLS example command from 
${readme_file}:\e[0m ${command}"
-            echo ""
-
-            set +e
-            eval "${command}"
-            exit_code=$?
-            set -e
-
-            if [ ${exit_code} -ne 0 ]; then
-                echo ""
-                echo -e "\e[31mTLS example command failed:\e[0m ${command}"
-                echo ""
-                break 2
-            fi
-            sleep 2
-
-        done < <(grep -E "^(npm run|tsx)" "${readme_file}" | grep "tcp-tls")
-    done
-
-    cd "${ROOT_WORKDIR}"
-
-    # Terminate TLS server
-    kill -TERM "$(cat ${PID_FILE})" 2>/dev/null || true
-fi
-
-# Cleanup
-test -e ${PID_FILE} && rm ${PID_FILE}
-
-# If everything is ok remove log and pid files otherwise cat server log
-if [ "${exit_code}" -eq 0 ]; then
-    echo "Test passed"
-else
-    echo "Test failed, see log file:"
-    test -e ${LOG_FILE} && cat ${LOG_FILE}
-fi
-
-test -e ${LOG_FILE} && rm ${LOG_FILE}
-test -e ${PID_FILE} && rm ${PID_FILE}
-
-exit "${exit_code}"
diff --git a/scripts/run-python-examples-from-readme.sh 
b/scripts/run-python-examples-from-readme.sh
deleted file mode 100755
index 08237c6e0..000000000
--- a/scripts/run-python-examples-from-readme.sh
+++ /dev/null
@@ -1,226 +0,0 @@
-#!/bin/bash
-# Licensed to the Apache Software Foundation (ASF) under one
-# or more contributor license agreements.  See the NOTICE file
-# distributed with this work for additional information
-# regarding copyright ownership.  The ASF licenses this file
-# to you under the Apache License, Version 2.0 (the
-# "License"); you may not use this file except in compliance
-# with the License.  You may obtain a copy of the License at
-#
-#   http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing,
-# software distributed under the License is distributed on an
-# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-# KIND, either express or implied.  See the License for the
-# specific language governing permissions and limitations
-# under the License.
-
-set -euo pipefail
-
-# Script to run Python examples from README.md and examples/python/README.md 
files
-# Usage: ./scripts/run-python-examples-from-readme.sh [TARGET]
-#
-# TARGET - Optional target architecture (e.g., x86_64-unknown-linux-musl)
-#          If not provided, uses the default target
-#
-# This script will run all the commands from both README.md and 
examples/python/README.md files
-# and check if they pass or fail.
-# If any command fails, it will print the command and exit with non-zero 
status.
-# If all commands pass, it will remove the log file and exit with zero status.
-#
-# Note: This script assumes that the iggy-server is not running and will start 
it in the background.
-#       It will wait until the server is started before running the commands.
-#       It will also terminate the server after running all the commands.
-#       Script executes every command in README files which is enclosed in 
backticks (`) and starts
-#       with `uv run `. Other commands are ignored.
-#       Order of commands in README files is important as script will execute 
them from top to bottom.
-
-readonly LOG_FILE="iggy-server.log"
-readonly PID_FILE="iggy-server.pid"
-readonly TIMEOUT=300
-
-TARGET="${1:-}" # Iggy server target architecture
-
-if [ -n "${TARGET}" ]; then
-    echo "Using target architecture: ${TARGET}"
-else
-    echo "Using default target architecture"
-fi
-
-# Remove old server data if present
-test -d local_data && rm -fr local_data
-test -e ${LOG_FILE} && rm ${LOG_FILE}
-test -e ${PID_FILE} && rm ${PID_FILE}
-
-# Check if server binary exists
-SERVER_BIN=""
-if [ -n "${TARGET}" ]; then
-    SERVER_BIN="target/${TARGET}/debug/iggy-server"
-else
-    SERVER_BIN="target/debug/iggy-server"
-fi
-
-if [ ! -f "${SERVER_BIN}" ]; then
-    echo "Error: Server binary not found at ${SERVER_BIN}"
-    echo "Please build the server binary before running this script:"
-    if [ -n "${TARGET}" ]; then
-        echo "  cargo build --target ${TARGET} --bin iggy-server"
-    else
-        echo "  cargo build --bin iggy-server"
-    fi
-    exit 1
-fi
-
-echo "Using server binary at ${SERVER_BIN}"
-
-# Run iggy server using the prebuilt binary
-echo "Starting server from ${SERVER_BIN}..."
-IGGY_ROOT_USERNAME=iggy IGGY_ROOT_PASSWORD=iggy ${SERVER_BIN} --fresh 
&>${LOG_FILE} &
-echo $! >${PID_FILE}
-
-# Wait until "Iggy server has started" string is present inside iggy-server.log
-SERVER_START_TIME=0
-while ! grep -q "has started" ${LOG_FILE}; do
-    if [ ${SERVER_START_TIME} -gt ${TIMEOUT} ]; then
-        echo "Server did not start within ${TIMEOUT} seconds."
-        ps fx
-        cat ${LOG_FILE}
-        exit 1
-    fi
-    echo "Waiting for Iggy server to start... ${SERVER_START_TIME}"
-    sleep 1
-    ((SERVER_START_TIME += 1))
-done
-
-cd examples/python || exit 1
-
-# Install example dependencies with uv (including local apache-iggy source 
mapping)
-echo "Syncing Python dependencies with uv..."
-uv sync --frozen
-
-# Execute all example commands from examples/python/README.md and check if 
they pass or fail
-exit_code=0
-if [ -f "README.md" ]; then
-    while IFS= read -r command; do
-        # Remove backticks and comments from command
-        command=$(echo "${command}" | tr -d '`' | sed 's/^#.*//')
-        # Skip empty lines
-        if [ -z "${command}" ]; then
-            continue
-        fi
-
-        echo -e "\e[33mChecking example command from 
examples/python/README.md:\e[0m ${command}"
-        echo ""
-
-        set +e
-        eval "timeout 10 ${command}"
-        test_exit_code=$?
-        set -e
-
-        # Stop at first failure
-        # Since examples might last longer, timeout error 124 is ignored here
-        if [[ $test_exit_code -ne 0 && $test_exit_code -ne 124 ]]; then
-            echo ""
-            echo -e "\e[31mExample command failed:\e[0m ${command}"
-            echo ""
-            exit_code=$test_exit_code
-            break
-        fi
-        # Add a small delay between examples to avoid potential race conditions
-        sleep 2
-
-    done < <(grep -E "^uv run " "README.md")
-fi
-
-# --- TLS Test Pass ---
-if [ "${exit_code}" -eq 0 ]; then
-    echo ""
-    echo -e "\e[36m=== Starting TLS test pass ===\e[0m"
-    echo ""
-
-    # Go back to repo root to manage server
-    cd ../..
-
-    # Stop non-TLS server
-    kill -TERM "$(cat ${PID_FILE})"
-    sleep 2
-
-    # Clean data and logs for fresh TLS start
-    rm -fr local_data
-    rm -f ${LOG_FILE}
-
-    # Start server with TLS enabled
-    echo "Starting server with TLS enabled..."
-    IGGY_ROOT_USERNAME=iggy IGGY_ROOT_PASSWORD=iggy IGGY_TCP_TLS_ENABLED=true 
${SERVER_BIN} --fresh &>${LOG_FILE} &
-    echo $! >${PID_FILE}
-
-    # Wait for server to start
-    SERVER_START_TIME=0
-    while ! grep -q "has started" ${LOG_FILE}; do
-        if [ ${SERVER_START_TIME} -gt ${TIMEOUT} ]; then
-            echo "TLS server did not start within ${TIMEOUT} seconds."
-            ps fx
-            cat ${LOG_FILE}
-            exit 1
-        fi
-        echo "Waiting for Iggy TLS server to start... ${SERVER_START_TIME}"
-        sleep 1
-        ((SERVER_START_TIME += 1))
-    done
-
-    cd examples/python || exit 1
-    # shellcheck disable=SC1091
-    source .venv/bin/activate
-
-    # Run getting-started examples with TLS flags
-    # Use localhost instead of 127.0.0.1 to match the cert's SAN 
(DNS:localhost)
-    TLS_CA_FILE="../../core/certs/iggy_ca_cert.pem"
-    TLS_ADDR="localhost:8090"
-
-    for cmd in \
-        "python getting-started/producer.py --tcp-server-address ${TLS_ADDR} 
--tls --tls-ca-file ${TLS_CA_FILE}" \
-        "python getting-started/consumer.py --tcp-server-address ${TLS_ADDR} 
--tls --tls-ca-file ${TLS_CA_FILE}"; do
-
-        echo -e "\e[33mChecking TLS example:\e[0m ${cmd}"
-        echo ""
-
-        set +e
-        eval "timeout 10 ${cmd}"
-        test_exit_code=$?
-        set -e
-
-        if [[ $test_exit_code -ne 0 && $test_exit_code -ne 124 ]]; then
-            echo ""
-            echo -e "\e[31mTLS example command failed:\e[0m ${cmd}"
-            echo ""
-            exit_code=$test_exit_code
-            break
-        fi
-        sleep 2
-    done
-
-fi
-
-# Clean up virtual environment
-deactivate 2>/dev/null || true
-rm -rf .venv
-
-cd ../..
-
-# Terminate server
-kill -TERM "$(cat ${PID_FILE})" 2>/dev/null || true
-test -e ${PID_FILE} && rm ${PID_FILE}
-
-# If everything is ok remove log and pid files otherwise cat server log
-if [ "${exit_code}" -eq 0 ]; then
-    echo "Test passed"
-else
-    echo "Test failed, see log file:"
-    test -e ${LOG_FILE} && cat ${LOG_FILE}
-fi
-
-test -e ${LOG_FILE} && rm ${LOG_FILE}
-test -e ${PID_FILE} && rm ${PID_FILE}
-
-exit "${exit_code}"
diff --git a/scripts/run-rust-examples-from-readme.sh 
b/scripts/run-rust-examples-from-readme.sh
deleted file mode 100755
index 97c4ac9eb..000000000
--- a/scripts/run-rust-examples-from-readme.sh
+++ /dev/null
@@ -1,276 +0,0 @@
-#!/bin/bash
-
-# Licensed to the Apache Software Foundation (ASF) under one
-# or more contributor license agreements.  See the NOTICE file
-# distributed with this work for additional information
-# regarding copyright ownership.  The ASF licenses this file
-# to you under the Apache License, Version 2.0 (the
-# "License"); you may not use this file except in compliance
-# with the License.  You may obtain a copy of the License at
-#
-#   http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing,
-# software distributed under the License is distributed on an
-# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-# KIND, either express or implied.  See the License for the
-# specific language governing permissions and limitations
-# under the License.
-
-set -euo pipefail
-
-# Script to run Rust examples from README.md and examples/rust/README.md files
-# Usage: ./scripts/run-rust-examples-from-readme.sh [TARGET]
-#
-# TARGET - Optional target architecture (e.g., x86_64-unknown-linux-musl)
-#          If not provided, uses the default target
-#
-# This script will run all the commands from both README.md and 
examples/rust/README.md files
-# and check if they pass or fail.
-# If any command fails, it will print the command and exit with non-zero 
status.
-# If all commands pass, it will remove the log file and exit with zero status.
-#
-# Note: This script assumes that the iggy-server is not running and will start 
it in the background.
-#       It will wait until the server is started before running the commands.
-#       It will also terminate the server after running all the commands.
-#       Script executes every command in README files which is enclosed in 
backticks (`) and starts
-#       with `cargo r --bin iggy -- ` or `cargo run --example`. Other commands 
are ignored.
-#       Order of commands in README files is important as script will execute 
them from top to bottom.
-#
-
-readonly LOG_FILE="iggy-server.log"
-readonly PID_FILE="iggy-server.pid"
-readonly TIMEOUT=300
-
-# Get target architecture from argument or use default
-TARGET="${1:-}"
-if [ -n "${TARGET}" ]; then
-    echo "Using target architecture: ${TARGET}"
-else
-    echo "Using default target architecture"
-fi
-
-# Remove old server data if present
-test -d local_data && rm -fr local_data
-test -e ${LOG_FILE} && rm ${LOG_FILE}
-test -e ${PID_FILE} && rm ${PID_FILE}
-
-# Check if server binary exists
-SERVER_BIN=""
-if [ -n "${TARGET}" ]; then
-    SERVER_BIN="target/${TARGET}/debug/iggy-server"
-else
-    SERVER_BIN="target/debug/iggy-server"
-fi
-
-if [ ! -f "${SERVER_BIN}" ]; then
-    echo "Error: Server binary not found at ${SERVER_BIN}"
-    echo "Please build the server binary before running this script:"
-    if [ -n "${TARGET}" ]; then
-        echo "  cargo build --target ${TARGET} --bin iggy-server"
-    else
-        echo "  cargo build --bin iggy-server"
-    fi
-    exit 1
-fi
-
-echo "Using server binary at ${SERVER_BIN}"
-
-# Check that CLI and examples are built
-CLI_BIN=""
-if [ -n "${TARGET}" ]; then
-    CLI_BIN="target/${TARGET}/debug/iggy"
-else
-    CLI_BIN="target/debug/iggy"
-fi
-
-if [ ! -f "${CLI_BIN}" ]; then
-    echo "Error: CLI binary not found at ${CLI_BIN}"
-    echo "Please build the CLI and examples before running this script:"
-    if [ -n "${TARGET}" ]; then
-        echo "  cargo build --target ${TARGET} --bin iggy --examples"
-    else
-        echo "  cargo build --bin iggy --examples"
-    fi
-    exit 1
-fi
-
-echo "Using CLI binary at ${CLI_BIN}"
-
-# Run iggy server using the prebuilt binary
-echo "Starting server from ${SERVER_BIN}..."
-IGGY_ROOT_USERNAME=iggy IGGY_ROOT_PASSWORD=iggy ${SERVER_BIN} &>${LOG_FILE} &
-echo $! >${PID_FILE}
-
-# Wait until "Iggy server has started" string is present inside iggy-server.log
-SERVER_START_TIME=0
-while ! grep -q "has started" ${LOG_FILE}; do
-    if [ ${SERVER_START_TIME} -gt ${TIMEOUT} ]; then
-        echo "Server did not start within ${TIMEOUT} seconds."
-        ps fx
-        cat ${LOG_FILE}
-        exit 1
-    fi
-    echo "Waiting for Iggy server to start... ${SERVER_START_TIME}"
-    sleep 1
-    ((SERVER_START_TIME += 1))
-done
-
-# Execute all matching CLI commands from README.md and check if they pass or 
fail
-while IFS= read -r command; do
-    # Remove backticks from command
-    command=$(echo "${command}" | tr -d '`')
-    # Add target flag if specified
-    if [ -n "${TARGET}" ]; then
-        command=$(echo "${command}" | sed "s/cargo r /cargo r --target 
${TARGET} /g" | sed "s/cargo run /cargo run --target ${TARGET} /g")
-    fi
-    echo -e "\e[33mChecking CLI command:\e[0m ${command}"
-    echo ""
-
-    set +e
-    eval "${command}"
-    exit_code=$?
-    set -e
-
-    # Stop at first failure
-    if [ ${exit_code} -ne 0 ]; then
-        echo ""
-        echo -e "\e[31mCLI command failed:\e[0m ${command}"
-        echo ""
-        break
-    fi
-
-done < <(grep -E "^\`cargo r --bin iggy -- " README.md)
-
-# Execute all example commands from README.md and examples/rust/README.md and 
check if they pass or fail
-for readme_file in README.md examples/rust/README.md; do
-    if [ ! -f "${readme_file}" ]; then
-        continue
-    fi
-
-    while IFS= read -r command; do
-        # Remove backticks and comments from command
-        command=$(echo "${command}" | tr -d '`' | sed 's/^#.*//')
-        # Skip empty lines
-        if [ -z "${command}" ]; then
-            continue
-        fi
-        # Add target flag if specified
-        if [ -n "${TARGET}" ]; then
-            command="${command//cargo run /cargo run --target ${TARGET} }"
-        fi
-        echo -e "\e[33mChecking example command from ${readme_file}:\e[0m 
${command}"
-        echo ""
-
-        set +e
-        eval "${command}"
-        exit_code=$?
-        set -e
-
-        # Stop at first failure
-        if [ ${exit_code} -ne 0 ]; then
-            echo ""
-            echo -e "\e[31mExample command failed:\e[0m ${command}"
-            echo ""
-            break 2 # Break from both loops
-        fi
-        # Add a small delay between examples to avoid potential race conditions
-        sleep 2
-
-    done < <(grep -E "^cargo run --example" "${readme_file}" | grep -v 
"tcp-tls")
-done
-
-# Terminate non-TLS server
-kill -TERM "$(cat ${PID_FILE})"
-test -e ${PID_FILE} && rm ${PID_FILE}
-
-# Run TLS examples if non-TLS examples passed
-if [ "${exit_code}" -eq 0 ]; then
-    TLS_README="examples/rust/README.md"
-    if [ -f "${TLS_README}" ] && grep -qE "^cargo run --example.*tcp-tls" 
"${TLS_README}"; then
-        echo ""
-        echo "=== Running TLS examples ==="
-        echo ""
-
-        # Clean up for fresh TLS start
-        test -d local_data && rm -fr local_data
-        test -e ${LOG_FILE} && rm ${LOG_FILE}
-
-        # Start TLS server
-        echo "Starting TLS server from ${SERVER_BIN}..."
-        IGGY_ROOT_USERNAME=iggy IGGY_ROOT_PASSWORD=iggy \
-            IGGY_TCP_TLS_ENABLED=true \
-            IGGY_TCP_TLS_CERT_FILE=core/certs/iggy_cert.pem \
-            IGGY_TCP_TLS_KEY_FILE=core/certs/iggy_key.pem \
-            ${SERVER_BIN} &>${LOG_FILE} &
-        echo $! >${PID_FILE}
-
-        # Wait for TLS server to start
-        SERVER_START_TIME=0
-        while ! grep -q "has started" ${LOG_FILE}; do
-            if [ ${SERVER_START_TIME} -gt ${TIMEOUT} ]; then
-                echo "TLS server did not start within ${TIMEOUT} seconds."
-                ps fx
-                cat ${LOG_FILE}
-                exit_code=1
-                break
-            fi
-            echo "Waiting for TLS Iggy server to start... ${SERVER_START_TIME}"
-            sleep 1
-            ((SERVER_START_TIME += 1))
-        done
-
-        if [ "${exit_code}" -eq 0 ]; then
-            while IFS= read -r command; do
-                # Remove backticks and comments from command
-                command=$(echo "${command}" | tr -d '`' | sed 's/^#.*//')
-                # Skip empty lines
-                if [ -z "${command}" ]; then
-                    continue
-                fi
-                # Add target flag if specified
-                if [ -n "${TARGET}" ]; then
-                    command="${command//cargo run /cargo run --target 
${TARGET} }"
-                fi
-
-                echo -e "\e[33mChecking TLS example command:\e[0m ${command}"
-                echo ""
-
-                set +e
-                eval "${command}"
-                exit_code=$?
-                set -e
-
-                # Stop at first failure
-                if [ ${exit_code} -ne 0 ]; then
-                    echo ""
-                    echo -e "\e[31mTLS example command failed:\e[0m ${command}"
-                    echo ""
-                    break
-                fi
-                # Add a small delay between examples to avoid potential race 
conditions
-                sleep 2
-
-            done < <(grep -E "^cargo run --example.*tcp-tls" "${TLS_README}")
-        fi
-
-        # Terminate TLS server
-        if [ -e ${PID_FILE} ]; then
-            kill -TERM "$(cat ${PID_FILE})" 2>/dev/null || true
-            rm -f ${PID_FILE}
-        fi
-    fi
-fi
-
-# If everything is ok remove log and pid files otherwise cat server log
-if [ "${exit_code}" -eq 0 ]; then
-    echo "Test passed"
-else
-    echo "Test failed, see log file:"
-    test -e ${LOG_FILE} && cat ${LOG_FILE}
-fi
-
-test -e ${LOG_FILE} && rm ${LOG_FILE}
-test -e ${PID_FILE} && rm ${PID_FILE}
-
-exit "${exit_code}"
diff --git a/scripts/utils.sh b/scripts/utils.sh
index c7ee15745..ddc89ce79 100755
--- a/scripts/utils.sh
+++ b/scripts/utils.sh
@@ -149,3 +149,212 @@ function on_exit_bench() {
         done
     fi
 }
+
+# ---------------------------------------------------------------------------
+# Server lifecycle helpers for example-runner scripts
+# ---------------------------------------------------------------------------
+
+readonly EXAMPLES_LOG_FILE="iggy-server.log"
+readonly EXAMPLES_PID_FILE="iggy-server.pid"
+readonly EXAMPLES_SERVER_TIMEOUT=300
+readonly EXAMPLES_STOP_TIMEOUT=5
+
+# Resolve and validate the server binary path.
+# Usage: resolve_server_binary [target]
+# Sets global SERVER_BIN.
+function resolve_server_binary() {
+    local target="${1:-}"
+    if [ -n "${target}" ]; then
+        SERVER_BIN="target/${target}/debug/iggy-server"
+    else
+        SERVER_BIN="target/debug/iggy-server"
+    fi
+
+    if [ ! -f "${SERVER_BIN}" ]; then
+        echo "Error: Server binary not found at ${SERVER_BIN}"
+        echo "Please build the server binary before running this script:"
+        if [ -n "${target}" ]; then
+            echo "  cargo build --target ${target} --bin iggy-server"
+        else
+            echo "  cargo build --bin iggy-server"
+        fi
+        exit 1
+    fi
+    echo "Using server binary at ${SERVER_BIN}"
+}
+
+# Resolve and validate the CLI binary path.
+# Usage: resolve_cli_binary [target]
+# Sets global CLI_BIN.
+function resolve_cli_binary() {
+    local target="${1:-}"
+    if [ -n "${target}" ]; then
+        CLI_BIN="target/${target}/debug/iggy"
+    else
+        CLI_BIN="target/debug/iggy"
+    fi
+
+    if [ ! -f "${CLI_BIN}" ]; then
+        echo "Error: CLI binary not found at ${CLI_BIN}"
+        echo "Please build the CLI and examples before running this script:"
+        if [ -n "${target}" ]; then
+            echo "  cargo build --target ${target} --bin iggy --examples"
+        else
+            echo "  cargo build --bin iggy --examples"
+        fi
+        exit 1
+    fi
+    echo "Using CLI binary at ${CLI_BIN}"
+}
+
+# Remove old server data, log, and PID files.
+function cleanup_server_state() {
+    rm -fr local_data
+    rm -f "${EXAMPLES_LOG_FILE}" "${EXAMPLES_PID_FILE}"
+}
+
+# Start the plain (non-TLS) iggy server in background.
+# Usage: start_plain_server [extra_args...]
+function start_plain_server() {
+    echo "Starting server from ${SERVER_BIN}..."
+    IGGY_ROOT_USERNAME=iggy IGGY_ROOT_PASSWORD=iggy \
+        ${SERVER_BIN} "$@" &>"${EXAMPLES_LOG_FILE}" &
+    echo $! >"${EXAMPLES_PID_FILE}"
+}
+
+# Start the TLS-enabled iggy server in background.
+# Usage: start_tls_server [extra_args...]
+function start_tls_server() {
+    echo "Starting TLS server from ${SERVER_BIN}..."
+    IGGY_ROOT_USERNAME=iggy IGGY_ROOT_PASSWORD=iggy \
+        IGGY_TCP_TLS_ENABLED=true \
+        IGGY_TCP_TLS_CERT_FILE=core/certs/iggy_cert.pem \
+        IGGY_TCP_TLS_KEY_FILE=core/certs/iggy_key.pem \
+        ${SERVER_BIN} "$@" &>"${EXAMPLES_LOG_FILE}" &
+    echo $! >"${EXAMPLES_PID_FILE}"
+}
+
+# Block until "has started" appears in the server log or timeout.
+# Usage: wait_for_server_ready [label]
+function wait_for_server_ready() {
+    local label="${1:-Iggy}"
+    local elapsed=0
+    while ! grep -q "has started" "${EXAMPLES_LOG_FILE}"; do
+        if [ ${elapsed} -gt ${EXAMPLES_SERVER_TIMEOUT} ]; then
+            echo "${label} server did not start within 
${EXAMPLES_SERVER_TIMEOUT} seconds."
+            ps fx 2>/dev/null || ps aux
+            cat "${EXAMPLES_LOG_FILE}"
+            exit 1
+        fi
+        echo "Waiting for ${label} server to start... ${elapsed}"
+        sleep 1
+        ((elapsed += 1))
+    done
+}
+
+# Gracefully stop the server: SIGTERM, wait up to EXAMPLES_STOP_TIMEOUT
+# seconds for exit, then SIGKILL if still alive.
+function stop_server() {
+    if [ ! -e "${EXAMPLES_PID_FILE}" ]; then
+        return
+    fi
+    local pid
+    pid="$(cat "${EXAMPLES_PID_FILE}")"
+    rm -f "${EXAMPLES_PID_FILE}"
+
+    kill -TERM "${pid}" 2>/dev/null || true
+
+    if wait_for_process_pid "${pid}" "${EXAMPLES_STOP_TIMEOUT}" 2>/dev/null; 
then
+        return
+    fi
+
+    echo "Server PID ${pid} did not exit after ${EXAMPLES_STOP_TIMEOUT}s, 
sending SIGKILL..."
+    kill -KILL "${pid}" 2>/dev/null || true
+    wait_for_process_pid "${pid}" 2 2>/dev/null || true
+}
+
+# Print final result and dump the log on failure.
+function report_result() {
+    local exit_code=$1
+    if [ "${exit_code}" -eq 0 ]; then
+        echo "Test passed"
+    else
+        echo "Test failed, see log file:"
+        test -e "${EXAMPLES_LOG_FILE}" && cat "${EXAMPLES_LOG_FILE}"
+    fi
+    rm -f "${EXAMPLES_LOG_FILE}" "${EXAMPLES_PID_FILE}"
+}
+
+# Portable timeout wrapper (macOS has gtimeout via coreutils, Linux has 
timeout).
+function portable_timeout() {
+    local secs="$1"
+    shift
+    if command -v timeout >/dev/null 2>&1; then
+        timeout "${secs}" "$@"
+    elif command -v gtimeout >/dev/null 2>&1; then
+        gtimeout "${secs}" "$@"
+    else
+        "$@"
+    fi
+}
+
+# Run commands extracted from a README file.
+# Usage: run_readme_commands readme_file grep_pattern [cmd_timeout 
[grep_exclude]]
+# Reads matching lines, strips backticks/comments, executes each.
+# Calls TRANSFORM_COMMAND function on each command if defined.
+# Returns: sets global EXAMPLES_EXIT_CODE.
+function run_readme_commands() {
+    local readme_file="$1"
+    local grep_pattern="$2"
+    local cmd_timeout="${3:-0}"
+    local grep_exclude="${4:-}"
+
+    if [ ! -f "${readme_file}" ]; then
+        return
+    fi
+
+    local commands
+    commands=$(grep -E "${grep_pattern}" "${readme_file}" || true)
+    if [ -n "${grep_exclude}" ]; then
+        commands=$(echo "${commands}" | grep -v "${grep_exclude}" || true)
+    fi
+    if [ -z "${commands}" ]; then
+        return
+    fi
+
+    while IFS= read -r command; do
+        command=$(echo "${command}" | tr -d '`' | sed 's/^#.*//')
+        if [ -z "${command}" ]; then
+            continue
+        fi
+
+        if declare -f TRANSFORM_COMMAND >/dev/null 2>&1; then
+            command=$(TRANSFORM_COMMAND "${command}")
+        fi
+
+        echo -e "\e[33mChecking command from ${readme_file}:\e[0m ${command}"
+        echo ""
+
+        set +e
+        if [ "${cmd_timeout}" -gt 0 ] 2>/dev/null; then
+            eval "portable_timeout ${cmd_timeout} ${command}"
+            local test_exit_code=$?
+            if [[ ${test_exit_code} -ne 0 && ${test_exit_code} -ne 124 ]]; then
+                EXAMPLES_EXIT_CODE=${test_exit_code}
+            fi
+        else
+            eval "${command}"
+            EXAMPLES_EXIT_CODE=$?
+        fi
+        set -e
+
+        if [ "${EXAMPLES_EXIT_CODE}" -ne 0 ]; then
+            echo ""
+            echo -e "\e[31mCommand failed:\e[0m ${command}"
+            echo ""
+            return
+        fi
+
+        sleep 2
+    done <<< "${commands}"
+}

Reply via email to