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}"
+}