Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
e972c31
feat(ruby): replace Docker cluster with cluster_manager.py
alexr-bq Jun 3, 2026
450df43
fix(ci): build Valkey from source instead of using packages.valkey.io
alexr-bq Jun 3, 2026
dbe3d86
fix: resolve RuboCop offenses in test cluster infrastructure
alexr-bq Jun 3, 2026
3739a4f
refactor: rename test:valkey to test:standalone, run both by default
alexr-bq Jun 3, 2026
bb4eef3
refactor(ruby): unify test structure with shared ValkeyTests modules
alexr-bq Jun 4, 2026
d6e6dbd
fix(ruby): separate test classes for modules with custom setup methods
alexr-bq Jun 4, 2026
d9d3261
fix(ruby): add cluster-mode skips for cross-slot operations
alexr-bq Jun 4, 2026
c922ce6
chore: remove spec files and notes from git tracking
alexr-bq Jun 4, 2026
a2ac515
refactor(ruby): restore _test suffix to test/valkey module files
alexr-bq Jun 4, 2026
cd3433e
chore(ruby): exclude test/valkey and test/lint from lost_tests check
alexr-bq Jun 4, 2026
23a53b9
fix(ruby): add cluster-mode skips for MULTI/EXEC and cross-slot tests
alexr-bq Jun 4, 2026
12c61ec
fix(ruby): add flush delay in OpenTelemetry test setup
alexr-bq Jun 4, 2026
38a4471
fix(ruby): add cluster-mode skips for CrossSlot and destructive tests
alexr-bq Jun 4, 2026
ba844ca
style(ruby): fix rubocop offenses in test files
alexr-bq Jun 4, 2026
477f8f9
fix(ruby): use _new_client helper in test_client_kill tests
alexr-bq Jun 4, 2026
fa6d493
fix(ruby): skip CLIENT KILL tests in cluster mode
alexr-bq Jun 4, 2026
dd4c28e
Address PR feedback
alexr-bq Jun 9, 2026
42a48f2
chore(ruby): address PR review feedback
alexr-bq Jun 10, 2026
f814874
Merge branch 'main' into cluster-test-infra
alexr-bq Jun 10, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
93 changes: 24 additions & 69 deletions .github/workflows/CI.yml
Original file line number Diff line number Diff line change
Expand Up @@ -225,7 +225,7 @@ jobs:
bundler-cache: true

- name: Run standalone tests
run: bundle exec rake test:valkey
run: bundle exec rake test:standalone
Comment thread
Aryex marked this conversation as resolved.

- name: Stop Valkey containers
if: always()
Expand All @@ -248,27 +248,27 @@ jobs:
- 3.1
- 3.0

services:
valkey-cluster:
image: grokzen/redis-cluster:7.0.15
ports:
- 7000:7000
- 7001:7001
- 7002:7002
- 7003:7003
- 7004:7004
- 7005:7005
options: >-
--health-cmd "redis-cli -p 7000 ping && redis-cli -p 7001 ping && redis-cli -p 7002 ping"
--health-interval 15s
--health-timeout 10s
--health-retries 15

steps:
- uses: actions/checkout@v4
with:
submodules: recursive

- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: '3.11'

- name: Build and install Valkey from source
run: |
echo "Building Valkey 8.0.0 from source..."
git clone https://github.com/valkey-io/valkey.git
cd valkey
git checkout 8.0.0
make BUILD_TLS=yes -j4
sudo make install
echo "Verifying Valkey installation..."
valkey-server --version

- name: Download native library
uses: actions/download-artifact@v4
with:
Expand All @@ -281,59 +281,14 @@ jobs:
ruby-version: ${{ matrix.ruby }}
bundler-cache: true

- name: Configure cluster nodes
run: |
echo "=== Disabling protected mode on all nodes ==="
for port in 7000 7001 7002 7003 7004 7005; do
echo "Configuring port $port..."
docker exec $(docker ps -q | head -n1) redis-cli -p $port config set protected-mode no || echo "Failed to configure port $port"
done

- name: Wait for cluster to be ready
run: |
echo "=== Waiting for Redis cluster to be fully ready ==="
max_attempts=60
attempt=1

while [ $attempt -le $max_attempts ]; do
echo "Attempt $attempt/$max_attempts: Checking cluster state..."

# Check if all nodes are responding
all_nodes_up=true
for port in 7000 7001 7002 7003 7004 7005; do
if ! docker exec $(docker ps -q | head -n1) redis-cli -p $port ping > /dev/null 2>&1; then
echo " Node $port is not responding"
all_nodes_up=false
break
fi
done

if [ "$all_nodes_up" = true ]; then
# Check cluster state
cluster_state=$(docker exec $(docker ps -q | head -n1) redis-cli -p 7000 cluster info | grep "cluster_state" | cut -d: -f2 | tr -d '\r')
echo " Cluster state: $cluster_state"

if [ "$cluster_state" = "ok" ]; then
echo "✅ Cluster is ready!"
break
fi
fi

echo " Cluster not ready yet, waiting 5 seconds..."
sleep 5
attempt=$((attempt + 1))
done

if [ $attempt -gt $max_attempts ]; then
echo "❌ Cluster failed to become ready within timeout"
echo "=== Final cluster info ==="
docker exec $(docker ps -q | head -n1) redis-cli -p 7000 cluster info || echo "Failed to get cluster info"
echo "=== Cluster nodes ==="
docker exec $(docker ps -q | head -n1) redis-cli -p 7000 cluster nodes || echo "Failed to get cluster nodes"
exit 1
fi

- name: Run cluster tests
run: bundle exec rake test:cluster
timeout-minutes: 25

- name: Upload cluster logs on failure
if: failure()
uses: actions/upload-artifact@v4
with:
name: cluster-logs-${{ matrix.ruby }}
path: valkey-glide/utils/clusters/
retention-days: 7
2 changes: 1 addition & 1 deletion .github/workflows/cd.yml
Original file line number Diff line number Diff line change
Expand Up @@ -280,7 +280,7 @@ jobs:
# The installed gem has the native library, local lib doesn't
rm -rf lib/
# Run tests - they will use the installed gem
rake test:valkey
rake test:standalone

- name: Stop Valkey
if: always()
Expand Down
14 changes: 7 additions & 7 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -54,12 +54,12 @@ bin/setup # bundle install
bundle exec rubocop

# Testing
bundle exec rake test # standalone (default)
bundle exec rake test:valkey # standalone explicitly
bundle exec rake test:cluster # cluster (needs nodes 7000-7005)
bundle exec rake test # standalone + cluster
bundle exec rake test:standalone # standalone only
bundle exec rake test:cluster # cluster only (needs nodes 7000-7005)

# Verbose / CI mode
CI=1 bundle exec rake test:valkey
CI=1 bundle exec rake test:standalone

# Console
bundle exec bin/console
Expand All @@ -72,7 +72,7 @@ bundle exec bin/console
bundle exec ruby test/valkey/string_commands_test.rb

# Run with custom port
VALKEY_PORT=6379 TIMEOUT=10 bundle exec rake test:valkey
VALKEY_PORT=6379 TIMEOUT=10 bundle exec rake test:standalone

# Load gem from lib/ without install
RUBYOPT="-I$(pwd)/lib" ruby -r valkey -e 'p Valkey.new.ping'
Expand All @@ -82,7 +82,7 @@ RUBYOPT="-I$(pwd)/lib" ruby -r valkey -e 'p Valkey.new.ping'

| Suite | Server requirement |
|-------|-------------------|
| `test:valkey` | Standalone Valkey/Redis on `localhost:6379` (DB 15) |
| `test:standalone` | Standalone Valkey/Redis on `localhost:6379` (DB 15) |
| `test:cluster` | 6-node cluster on `127.0.0.1:7000`–`7005` |
| SSL tests | TLS Valkey on port `6380` + certs in `test/fixtures/ssl/` |
| Module tests | JSON, Bloom, Search modules loaded (see CI workflow) |
Expand Down Expand Up @@ -191,7 +191,7 @@ valkey-glide-ruby/
## Quality Gates (Agent Checklist)

- [ ] `bundle exec rubocop` passes
- [ ] `bundle exec rake test:valkey` passes (with Valkey running)
- [ ] `bundle exec rake test:standalone` passes (with Valkey running)
- [ ] `bundle exec rake test:cluster` passes (if cluster commands touched)
- [ ] New commands have tests in `test/valkey/` and lint coverage where applicable
- [ ] `RequestType` matches glide-core enum
Expand Down
6 changes: 3 additions & 3 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,14 +27,14 @@ Valkey GLIDE Ruby (`valkey-rb`) is the official Ruby binding for Valkey and Redi

### Before Task Completion

- Tests cover the change and pass (`bundle exec rake test:valkey` at minimum)
- Tests cover the change and pass (`bundle exec rake test:standalone` at minimum)
- `bundle exec rubocop` passes for changed Ruby files
- If FFI binary updated, smoke-test: `Valkey.new.ping` on target OS

### Before Push

- `git pull --rebase` on your base branch; resolve conflicts
- Run tests for relevant scope (`test:valkey` and/or `test:cluster`)
- Run tests for relevant scope (`test:standalone` and/or `test:cluster`)

### Before PR Creation/Update

Expand Down Expand Up @@ -108,7 +108,7 @@ When working on a feature, read these paths first:
```bash
bin/setup
bundle exec rubocop
bundle exec rake test:valkey # needs localhost:6379
bundle exec rake test:standalone # needs localhost:6379
bundle exec rake test:cluster # needs cluster 7000-7005
```

Expand Down
2 changes: 1 addition & 1 deletion CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ For issues that affect the shared Rust core or other language clients, consider
3. Run local checks (see [DEVELOPER.md](./DEVELOPER.md)):
```bash
bundle exec rubocop
bundle exec rake test:valkey # standalone — requires Valkey on :6379
bundle exec rake test:standalone # standalone — requires Valkey on :6379
bundle exec rake test:cluster # if cluster-related — requires nodes :7000–:7005
```
4. Commit with **DCO sign-off** and **conventional commits**:
Expand Down
8 changes: 4 additions & 4 deletions DEVELOPER.md
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ valkey-glide-ruby/
│ └── cd.yml # Build and publish gem
├── valkey.gemspec
├── Gemfile
└── Rakefile # test:valkey, test:cluster, native:build
└── Rakefile # test:standalone, test:cluster, native:build
```

## Prerequisites
Expand Down Expand Up @@ -211,13 +211,13 @@ docker run -d --name redis-cluster -p 7000-7005:7000-7005 grokzen/redis-cluster:
# All default (standalone) tests
bundle exec rake test
# or
bundle exec rake test:valkey
bundle exec rake test:standalone

# Cluster tests only
bundle exec rake test:cluster

# Verbose output (also enabled when CI=1)
CI=1 bundle exec rake test:valkey
CI=1 bundle exec rake test:standalone
```

### SSL Tests
Expand All @@ -243,7 +243,7 @@ Load modules when starting Valkey if you run module-specific tests locally.
### Environment Overrides

```bash
VALKEY_PORT=6379 TIMEOUT=10 bundle exec rake test:valkey
VALKEY_PORT=6379 TIMEOUT=10 bundle exec rake test:standalone
```

## Linters
Expand Down
11 changes: 8 additions & 3 deletions Rakefile
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,7 @@ task native: "native:build"
# =============================================================================

namespace :test do
groups = %i[valkey cluster]
groups = %i[standalone cluster]
Comment thread
Aryex marked this conversation as resolved.
groups.each do |group|
Rake::TestTask.new(group) do |t|
t.libs << "test"
Expand All @@ -122,10 +122,15 @@ namespace :test do
end
end

lost_tests = Dir["test/**/*_test.rb"] - groups.map { |g| Dir["test/#{g}/**/*_test.rb"] }.flatten
# Exclude module directories (valkey/, lint/) from lost_tests check
# These contain reusable test modules, not standalone test files
module_dirs = %w[valkey lint]
lost_tests = Dir["test/**/*_test.rb"] -
groups.map { |g| Dir["test/#{g}/**/*_test.rb"] }.flatten -
module_dirs.map { |d| Dir["test/#{d}/**/*_test.rb"] }.flatten
abort "The following test files are in no group:\n#{lost_tests.join("\n")}" unless lost_tests.empty?
end

task test: ["test:valkey"]
task test: ["test:standalone", "test:cluster"]

task default: :test
84 changes: 71 additions & 13 deletions test/cluster/cluster_commands_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,19 +2,77 @@

require "test_helper"

class TestClusterCommandsOnClusters < Minitest::Test
# Cluster test class for command modules WITHOUT custom setup methods
# These modules can safely share a test class
class TestClusterCommands < Minitest::Test
include Helper::Cluster
# include Lint::StringCommands # Run string tests first (while cluster is healthy)
# include Lint::ServerCommands # Server commands work in cluster mode
include Lint::HashCommands # Hash commands work in cluster mode
include Lint::StreamCommands # Stream commands work in cluster mode
include Lint::ConnectionCommands # Run connection tests (cluster-aware)
include Lint::PubSubCommands # Pub/Sub works in cluster mode
include Lint::FunctionCommands # Function commands work in cluster mode (per-node)
include Lint::ModuleCommands # Module commands work in cluster mode (per-node)
include Lint::JsonCommands # JSON commands work in cluster mode (requires module on all nodes)
include Lint::ClusterCommands # Run cluster commands second (after string tests)
include Lint::ConnectionOptions # Connection options work in cluster mode

# Lint modules without conflicting setup methods
include Lint::BitmapCommands
include Lint::ConnectionCommands
include Lint::ConnectionOptions
include Lint::FunctionCommands
include Lint::GenericCommands
include Lint::HashCommands
include Lint::HyperLogLog
include Lint::Lists
include Lint::PubSubCommands
include Lint::ScriptingCommands
include Lint::ServerCommands
include Lint::SetCommands
include Lint::SortedSetCommands
include Lint::StreamCommands
include Lint::StringCommands
include Lint::TransactionCommands

# Cluster-specific commands
include Lint::ClusterCommands

# ValkeyTests modules without conflicting setup methods
include ValkeyTests::Bitpos
include ValkeyTests::GenericCommands
include ValkeyTests::Scanning
include ValkeyTests::ScriptingCommands
include ValkeyTests::ScriptingCommandsIntegration
include ValkeyTests::Sorting
include ValkeyTests::Statistics
include ValkeyTests::URIConnection
include ValkeyTests::Utils

# Eval/Evalsha property tests
include ValkeyTests::EvalEvalshaBasicProperties
include ValkeyTests::EvalEvalshaValidationProperties
include ValkeyTests::EvalEvalshaTypeProperties
end

# Modules WITH custom setup methods need their own test class
# to avoid setup interference between different command groups

class TestClusterGeoCommands < Minitest::Test
include Helper::Cluster
include Lint::GeoCommands
end

class TestClusterJsonCommands < Minitest::Test
include Helper::Cluster
include Lint::JsonCommands
end

class TestClusterModuleCommands < Minitest::Test
include Helper::Cluster
include Lint::ModuleCommands
end

class TestClusterVectorSearchCommands < Minitest::Test
include Helper::Cluster
include Lint::VectorSearchCommands
end

# ValkeyTests modules with setup/teardown
class TestClusterFunctionCommands < Minitest::Test
include Helper::Cluster
include ValkeyTests::FunctionCommands
end

# TODO: Enable module and load module in cluster setup CI
# NOTE: Module tests (JsonCommands, ModuleCommands, VectorSearchCommands)
# require modules loaded on all cluster nodes
Loading
Loading