From 7c37234115fe3d4bb251d7a502f1895b88971f1a Mon Sep 17 00:00:00 2001 From: Dmitry Kropachev Date: Mon, 27 Jul 2026 12:46:15 -0400 Subject: [PATCH 1/3] ci: add Scylla test.py driver subset --- .github/workflows/scylla-driver-testpy.yml | 162 +++++++++++++++ scripts/run_scylla_driver_testpy.sh | 219 +++++++++++++++++++++ scripts/scylla-driver-testpy-tests.txt | 55 ++++++ 3 files changed, 436 insertions(+) create mode 100644 .github/workflows/scylla-driver-testpy.yml create mode 100755 scripts/run_scylla_driver_testpy.sh create mode 100644 scripts/scylla-driver-testpy-tests.txt diff --git a/.github/workflows/scylla-driver-testpy.yml b/.github/workflows/scylla-driver-testpy.yml new file mode 100644 index 0000000000..698d57bf9e --- /dev/null +++ b/.github/workflows/scylla-driver-testpy.yml @@ -0,0 +1,162 @@ +name: Scylla test.py driver compatibility + +on: + push: + branches: + - master + - 'branch-**' + paths: + - cassandra/** + - tests/** + - scripts/run_scylla_driver_testpy.sh + - scripts/scylla-driver-testpy-tests.txt + - .github/workflows/scylla-driver-testpy.yml + - pyproject.toml + - uv.lock + - setup.py + pull_request: + paths: + - cassandra/** + - tests/** + - scripts/run_scylla_driver_testpy.sh + - scripts/scylla-driver-testpy-tests.txt + - .github/workflows/scylla-driver-testpy.yml + - pyproject.toml + - uv.lock + - setup.py + workflow_dispatch: + +jobs: + testpy-driver-compat: + name: latest Scylla release test.py driver subset + if: "!contains(github.event.pull_request.labels.*.name, 'disable-integration-tests')" + runs-on: ubuntu-24.04 + timeout-minutes: 120 + env: + GET_VERSION_VERSION: 0.4.3 + TOXIPROXY_VERSION: 2.12.0 + + steps: + - name: Checkout driver + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + + - name: Install system dependencies + run: | + sudo apt-get update + sudo DEBIAN_FRONTEND=noninteractive apt-get install -y \ + build-essential \ + curl \ + libaio1t64 \ + libev4 \ + libev-dev \ + ldap-utils \ + sasl2-bin \ + slapd \ + tar \ + unzip + sudo mkdir -p /etc/openldap + sudo ln -sfn /etc/ldap/schema /etc/openldap/schema + if command -v apparmor_parser >/dev/null 2>&1 && [[ -f /etc/apparmor.d/usr.sbin.slapd ]]; then + sudo apparmor_parser -R /etc/apparmor.d/usr.sbin.slapd || true + fi + echo /usr/sbin >> "$GITHUB_PATH" + + - name: Install Scylla test.py service tools + run: | + mkdir -p "$RUNNER_TEMP/bin" + curl -fsSLo "$RUNNER_TEMP/bin/minio" https://dl.min.io/server/minio/release/linux-amd64/minio + curl -fsSLo "$RUNNER_TEMP/bin/mc" https://dl.min.io/client/mc/release/linux-amd64/mc + chmod +x "$RUNNER_TEMP/bin/minio" "$RUNNER_TEMP/bin/mc" + curl -fsSL "https://github.com/Shopify/toxiproxy/releases/download/v${TOXIPROXY_VERSION}/toxiproxy_${TOXIPROXY_VERSION}_linux_amd64.tar.gz" \ + | tar -xz -C "$RUNNER_TEMP/bin" toxiproxy-server toxiproxy-cli + printf '%s\n' \ + '#!/usr/bin/env bash' \ + 'exec /usr/sbin/slapd -u "$(id -un)" -g "$(id -gn)" "$@"' \ + > "$RUNNER_TEMP/bin/slapd" + chmod +x "$RUNNER_TEMP/bin/slapd" + echo "$RUNNER_TEMP/bin" >> "$GITHUB_PATH" + + - name: Install get-version + run: | + mkdir -p "$RUNNER_TEMP/bin" + curl -fsSLo "$RUNNER_TEMP/get-version.zip" \ + "https://github.com/scylladb-actions/get-version/releases/download/v${GET_VERSION_VERSION}/get-version_${GET_VERSION_VERSION}_linux_amd64v3.zip" + unzip -q -o "$RUNNER_TEMP/get-version.zip" -d "$RUNNER_TEMP/bin" + chmod +x "$RUNNER_TEMP/bin/get-version" + echo "$RUNNER_TEMP/bin" >> "$GITHUB_PATH" + + - name: Resolve latest stable Scylla release + id: scylla-release + run: | + stable_filter='^[0-9]{4}$.^[0-9]+$.^[0-9]+$ and LAST.LAST.LAST' + docker_version="$(get-version --source dockerhub-imagetag --repo scylladb/scylla -filters "$stable_filter" | tr -d '"')" + github_version="$(get-version --source github-tag --repo scylladb/scylladb --prefix scylla- --out-no-prefix --filters "$stable_filter" | tr -d '"')" + if [[ -z "$docker_version" || -z "$github_version" ]]; then + echo "Failed to resolve latest stable Scylla release" >&2 + exit 1 + fi + if [[ "$docker_version" != "$github_version" ]]; then + echo "Latest stable Scylla release mismatch: DockerHub=$docker_version GitHub=$github_version" >&2 + exit 1 + fi + git ls-remote --exit-code --refs --tags https://github.com/scylladb/scylladb.git "refs/tags/scylla-$docker_version" + echo "version=$docker_version" >> "$GITHUB_OUTPUT" + + - name: Checkout matching Scylla test.py + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + with: + repository: scylladb/scylladb + ref: scylla-${{ steps.scylla-release.outputs.version }} + path: scylladb + fetch-depth: 1 + + - name: Prepare Scylla test.py host compatibility + run: | + if [[ -f /usr/lib/ldap/back_mdb.so ]] && ! grep -q '^moduleload back_mdb' scylladb/test/resource/slapd.conf; then + sed -i '1imoduleload back_mdb\nmodulepath /usr/lib/ldap' scylladb/test/resource/slapd.conf + fi + + - name: Install uv + uses: astral-sh/setup-uv@08807647e7069bb48b6ef5acd8ec9567f424441b # v8.1.0 + with: + python-version: "3.13" + + - name: Build driver + run: uv sync --no-dev + + - name: Install ccm and Scylla test.py Python dependencies + run: | + uv pip install \ + "ccm @ git+https://github.com/scylladb/scylla-ccm.git@master" \ + aiohttp \ + allure-pytest \ + colorama \ + cryptography \ + humanfriendly \ + psutil \ + PyKMIP \ + "pytest~=8.0" \ + pytest-asyncio \ + pytest-repeat \ + pytest-timeout \ + pytest-xdist \ + requests \ + sqlalchemy \ + treelib \ + unidiff \ + universalasync + + - name: Cache Scylla ccm download + uses: actions/cache@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5 + with: + path: | + ~/.ccm/repository + ~/.ccm/scylla-repository + key: scylla-ccm-release-${{ steps.scylla-release.outputs.version }}-${{ runner.os }} + + - name: Run Scylla test.py driver subset + env: + SCYLLA_SOURCE_DIR: ${{ github.workspace }}/scylladb + SCYLLA_TESTPY_TMPDIR: ${{ runner.temp }}/scylla-testpy + SCYLLA_VERSION: ${{ steps.scylla-release.outputs.version }} + run: scripts/run_scylla_driver_testpy.sh diff --git a/scripts/run_scylla_driver_testpy.sh b/scripts/run_scylla_driver_testpy.sh new file mode 100755 index 0000000000..492b7b2de6 --- /dev/null +++ b/scripts/run_scylla_driver_testpy.sh @@ -0,0 +1,219 @@ +#!/usr/bin/env bash +set -euo pipefail + +stable_release_filter='^[0-9]{4}$.^[0-9]+$.^[0-9]+$ and LAST.LAST.LAST' +download_cluster_name="${SCYLLA_CCM_DOWNLOAD_CLUSTER:-scylla-driver-testpy-download}" + +driver_root="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)" +source_dir="${SCYLLA_SOURCE_DIR:-$driver_root/scylladb}" +tests_file="${SCYLLA_TESTPY_TESTS_FILE:-$driver_root/scripts/scylla-driver-testpy-tests.txt}" +tmpdir="${SCYLLA_TESTPY_TMPDIR:-${TMPDIR:-/tmp}/scylla-driver-testpy}" +jobs="${SCYLLA_TESTPY_JOBS:-1}" +max_failures="${SCYLLA_TESTPY_MAX_FAILURES:-1}" +timeout="${SCYLLA_TESTPY_TIMEOUT:-1800}" +session_timeout="${SCYLLA_TESTPY_SESSION_TIMEOUT:-7200}" + +trim() { + local value="$1" + value="${value#"${value%%[![:space:]]*}"}" + value="${value%"${value##*[![:space:]]}"}" + printf '%s' "$value" +} + +resolve_latest_stable_release() { + local docker_version github_version + + if ! command -v get-version >/dev/null 2>&1; then + echo "get-version is required when SCYLLA_VERSION is not set" >&2 + return 1 + fi + + docker_version="$(get-version \ + --source dockerhub-imagetag \ + --repo scylladb/scylla \ + -filters "$stable_release_filter" | tr -d '"')" + github_version="$(get-version \ + --source github-tag \ + --repo scylladb/scylladb \ + --prefix scylla- \ + --out-no-prefix \ + --filters "$stable_release_filter" | tr -d '"')" + + if [[ -z "$docker_version" || -z "$github_version" ]]; then + echo "failed to resolve latest stable Scylla release" >&2 + return 1 + fi + if [[ "$docker_version" != "$github_version" ]]; then + echo "latest Scylla release mismatch: DockerHub=$docker_version GitHub=$github_version" >&2 + return 1 + fi + + printf '%s' "$docker_version" +} + +read_selected_tests() { + local line selected + selected=() + while IFS= read -r line || [[ -n "$line" ]]; do + line="${line%%#*}" + line="$(trim "$line")" + [[ -z "$line" ]] && continue + selected+=("$line") + done < "$tests_file" + printf '%s\n' "${selected[@]}" +} + +find_scylla_executable() { + local version="$1" + local candidate + local -a candidates=( + "$HOME/.ccm/scylla-repository/release/$version/bin/scylla" + "$HOME/.ccm/repository/scylla-repository/release/$version/bin/scylla" + ) + + for candidate in "${candidates[@]}"; do + if [[ -x "$candidate" ]]; then + printf '%s' "$candidate" + return 0 + fi + done + + while IFS= read -r candidate; do + if [[ -x "$candidate" ]]; then + printf '%s' "$candidate" + return 0 + fi + done < <(find "$HOME/.ccm" -type f -path "*/release/$version/bin/scylla" 2>/dev/null | sort) + + return 1 +} + +pull_scylla_with_ccm() { + local version="$1" + local ccm="${CCM:-$driver_root/.venv/bin/ccm}" + + if [[ ! -x "$ccm" ]]; then + ccm="$(command -v ccm || true)" + fi + if [[ -z "$ccm" || ! -x "$ccm" ]]; then + echo "ccm is required to download Scylla release binaries" >&2 + return 1 + fi + + "$ccm" remove "$download_cluster_name" >/dev/null 2>&1 || true + "$ccm" create "$download_cluster_name" -n 1 --scylla --version "release:$version" + "$ccm" remove "$download_cluster_name" >/dev/null 2>&1 || true +} + +validate_selected_tests() { + local test_id test_file missing=0 + for test_id in "$@"; do + test_file="${test_id%%::*}" + if [[ ! -f "$source_dir/$test_file" ]]; then + echo "missing Scylla test file for $test_id" >&2 + missing=1 + fi + done + return "$missing" +} + +main() { + local version scylla_exe python_bin + local list_tests=0 + local -a tests passthrough_args pytest_args + + if [[ ! -f "$tests_file" ]]; then + echo "test selection file does not exist: $tests_file" >&2 + return 1 + fi + if [[ ! -f "$source_dir/test.py" ]]; then + echo "Scylla source checkout with test.py is required at: $source_dir" >&2 + return 1 + fi + + mapfile -t tests < <(read_selected_tests) + if [[ "${#tests[@]}" -eq 0 ]]; then + echo "no Scylla tests selected in $tests_file" >&2 + return 1 + fi + validate_selected_tests "${tests[@]}" + + version="${SCYLLA_VERSION:-}" + if [[ -z "$version" || "$version" == "latest" ]]; then + version="$(resolve_latest_stable_release)" + fi + version="${version#release:}" + + echo "Scylla release: $version" + echo "Scylla source: $source_dir" + echo "Selected Scylla tests (${#tests[@]}):" + printf ' %s\n' "${tests[@]}" + + if [[ "${SCYLLA_TESTPY_DRY_RUN:-0}" == "1" ]]; then + return 0 + fi + + scylla_exe="${SCYLLA_EXE:-}" + if [[ -z "$scylla_exe" ]]; then + if ! scylla_exe="$(find_scylla_executable "$version")"; then + pull_scylla_with_ccm "$version" + scylla_exe="$(find_scylla_executable "$version")" + fi + fi + if [[ ! -x "$scylla_exe" ]]; then + echo "Scylla executable is not available or executable: $scylla_exe" >&2 + return 1 + fi + + python_bin="${PYTHON:-$driver_root/.venv/bin/python}" + if [[ ! -x "$python_bin" ]]; then + python_bin="$(command -v python3 || command -v python)" + fi + + echo "Scylla executable: $scylla_exe" + + passthrough_args=() + for arg in "$@"; do + if [[ "$arg" == "--list" ]]; then + list_tests=1 + else + passthrough_args+=("$arg") + fi + done + + pytest_args=( + -p test.pylib.runner + --color=yes + --repeat=1 + --exe-path "$scylla_exe" + --tmpdir "$tmpdir" + ) + if [[ "$list_tests" == "1" ]]; then + pytest_args+=(--collect-only --quiet --no-header) + else + pytest_args+=( + --junit-xml "$tmpdir/report/pytest_driver_compat.xml" + -rf + -n "$jobs" + --maxfail "$max_failures" + --alluredir "$tmpdir/report/allure_driver_compat" + --dist=worksteal + --allure-no-capture + --timeout "$timeout" + --session-timeout "$session_timeout" + --log-level=INFO + ) + fi + pytest_args+=( + "${passthrough_args[@]}" + "${tests[@]}" + ) + + cd "$source_dir" + # Use Scylla's pytest runner plugin directly. The test.py wrapper probes + # configured build modes before its --exe-path hook can switch to custom_exe, + # which does not work for a source-only checkout plus a ccm-downloaded binary. + "$python_bin" -m pytest "${pytest_args[@]}" +} + +main "$@" diff --git a/scripts/scylla-driver-testpy-tests.txt b/scripts/scylla-driver-testpy-tests.txt new file mode 100644 index 0000000000..3ce74353dd --- /dev/null +++ b/scripts/scylla-driver-testpy-tests.txt @@ -0,0 +1,55 @@ +# Narrow Scylla test.py coverage for Python driver compatibility. +# +# Keep this list to tests that exercise non-standard Python driver behavior. +# Generic Scylla CQL, topology, auth, or service-level coverage belongs in +# Scylla CI, not in the driver compatibility job. + +# Driver-specific event decoding and control-connection watchers. +test/cluster/test_client_routes.py::test_events + +# Topology-change notification handling through a pinned control connection. +test/cluster/test_no_removed_node_event_on_ip_change.py::test_no_removed_node_event_on_ip_change + +# Prepared metadata ID and result metadata refresh behavior. +test/cluster/auth_cluster/test_prepared_metadata_id.py::test_prepared_list_metadata_ids +test/cluster/test_metadata_id.py::test_changed_prepared_statement_metadata_columns +test/cluster/test_metadata_id.py::test_changed_prepared_statement_metadata_types +test/cluster/test_metadata_id.py::test_changed_prepared_statement_metadata_udt + +# Driver control-connection service-level classification. +test/cluster/auth_cluster/test_raft_service_levels.py::test_driver_service_level_not_used_for_user_queries +test/cluster/auth_cluster/test_raft_service_levels.py::test_driver_service_level_used_for_driver_queries +test/cluster/auth_cluster/test_raft_service_levels.py::test_control_connection_not_reclassified_by_driver_queries + +# Driver startup options exposed by system.clients. +test/cqlpy/test_virtual_tables.py::test_clients + +# Driver per-shard connections and direct protocol messages used for service levels. +test/cqlpy/test_service_level_api.py::test_count_opened_cql_connections + +# Native protocol custom payload support. +test/cqlpy/test_native_transport.py::test_query_with_custom_payload +test/cqlpy/test_native_transport.py::test_execute_prepared_with_custom_payload +test/cqlpy/test_native_transport.py::test_batch_with_custom_payload +test/cqlpy/test_native_transport.py::test_request_with_multiple_payload_entries +test/cqlpy/test_native_transport.py::test_request_with_large_payload_value +test/cqlpy/test_native_transport.py::test_custom_payload_does_not_affect_query_result + +# Prepared statement routing-key metadata parsed by the driver. +test/cqlpy/test_prepare.py::test_single_pk_indexes +test/cqlpy/test_prepare.py::test_single_pk_no_indexes +test/cqlpy/test_prepare.py::test_composite_pk_indexes +test/cqlpy/test_prepare.py::test_composite_pk_no_indexes +test/cqlpy/test_prepare.py::test_single_pk_indexes_named_variables +test/cqlpy/test_prepare.py::test_composite_pk_indexes_named_variables +test/cqlpy/test_prepare.py::test_single_pk_indexes_duplicate_named_variables +test/cqlpy/test_prepare.py::test_single_pk_indexes_duplicate_named_variables_cassandra_compatiblity_mode +test/cqlpy/test_prepare.py::test_composite_pk_indexes_duplicate_named_variables +test/cqlpy/test_prepare.py::test_composite_pk_indexes_duplicate_named_variables_cassandra_compatibility_mode +test/cqlpy/test_prepare.py::test_duplicate_named_bind_marker_prepared +test/cqlpy/test_prepare.py::test_duplicate_named_bind_marker_prepared_cassandra_compatibility_mode + +# Driver serializer edge cases and Scylla-driver-specific collection binding. +test/cqlpy/test_type_varint.py::test_varint_key_representation +test/cqlpy/test_null.py::test_null_string_in_collection +test/cqlpy/test_null.py::test_null_int_in_collection From 29ec16bba9fd72803aa1c65c8caf05496e21f281 Mon Sep 17 00:00:00 2001 From: Dmitry Kropachev Date: Mon, 27 Jul 2026 15:21:13 -0400 Subject: [PATCH 2/3] ci: fix Scylla test.py subset collection --- .github/workflows/scylla-driver-testpy.yml | 1 + scripts/scylla-driver-testpy-tests.txt | 5 +---- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/.github/workflows/scylla-driver-testpy.yml b/.github/workflows/scylla-driver-testpy.yml index 698d57bf9e..5230061b6b 100644 --- a/.github/workflows/scylla-driver-testpy.yml +++ b/.github/workflows/scylla-driver-testpy.yml @@ -142,6 +142,7 @@ jobs: pytest-xdist \ requests \ sqlalchemy \ + tabulate \ treelib \ unidiff \ universalasync diff --git a/scripts/scylla-driver-testpy-tests.txt b/scripts/scylla-driver-testpy-tests.txt index 3ce74353dd..c91a51fe2c 100644 --- a/scripts/scylla-driver-testpy-tests.txt +++ b/scripts/scylla-driver-testpy-tests.txt @@ -19,7 +19,6 @@ test/cluster/test_metadata_id.py::test_changed_prepared_statement_metadata_udt # Driver control-connection service-level classification. test/cluster/auth_cluster/test_raft_service_levels.py::test_driver_service_level_not_used_for_user_queries test/cluster/auth_cluster/test_raft_service_levels.py::test_driver_service_level_used_for_driver_queries -test/cluster/auth_cluster/test_raft_service_levels.py::test_control_connection_not_reclassified_by_driver_queries # Driver startup options exposed by system.clients. test/cqlpy/test_virtual_tables.py::test_clients @@ -49,7 +48,5 @@ test/cqlpy/test_prepare.py::test_composite_pk_indexes_duplicate_named_variables_ test/cqlpy/test_prepare.py::test_duplicate_named_bind_marker_prepared test/cqlpy/test_prepare.py::test_duplicate_named_bind_marker_prepared_cassandra_compatibility_mode -# Driver serializer edge cases and Scylla-driver-specific collection binding. +# Driver serializer edge cases. test/cqlpy/test_type_varint.py::test_varint_key_representation -test/cqlpy/test_null.py::test_null_string_in_collection -test/cqlpy/test_null.py::test_null_int_in_collection From 8ec3ee48c9946b6d2ebf139693ab30841ab3628c Mon Sep 17 00:00:00 2001 From: Dmitry Kropachev Date: Mon, 27 Jul 2026 16:35:11 -0400 Subject: [PATCH 3/3] ci: harden Scylla test.py workflow --- .github/workflows/scylla-driver-testpy.yml | 46 ++++++++++++++-------- scripts/run_scylla_driver_testpy.sh | 37 ++++++++++++++--- 2 files changed, 62 insertions(+), 21 deletions(-) diff --git a/.github/workflows/scylla-driver-testpy.yml b/.github/workflows/scylla-driver-testpy.yml index 5230061b6b..c41f262899 100644 --- a/.github/workflows/scylla-driver-testpy.yml +++ b/.github/workflows/scylla-driver-testpy.yml @@ -26,6 +26,9 @@ on: - setup.py workflow_dispatch: +permissions: + contents: read + jobs: testpy-driver-compat: name: latest Scylla release test.py driver subset @@ -33,12 +36,21 @@ jobs: runs-on: ubuntu-24.04 timeout-minutes: 120 env: + GET_VERSION_SHA256: 2dfbf1afd596fc9efd68c7795bfa52df0fd69d0342237574a17521b14f173df3 GET_VERSION_VERSION: 0.4.3 + MC_SHA256: 01f866e9c5f9b87c2b09116fa5d7c06695b106242d829a8bb32990c00312e891 + MC_VERSION: RELEASE.2025-08-13T08-35-41Z + MINIO_SHA256: 7c5bd8512c6e966455b1d198209358b2d191c77a83ab377c4073281065fb855f + MINIO_VERSION: RELEASE.2025-09-07T16-13-09Z + SCYLLA_CCM_COMMIT: d15a2fab9d22fffad8a30c806a7c8e1632e58aae + TOXIPROXY_SHA256: 65e042d3fc2290c099527bc506446a6fd863a09f113b8944b636ece70221c2b3 TOXIPROXY_VERSION: 2.12.0 steps: - name: Checkout driver uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + with: + persist-credentials: false - name: Install system dependencies run: | @@ -64,11 +76,17 @@ jobs: - name: Install Scylla test.py service tools run: | mkdir -p "$RUNNER_TEMP/bin" - curl -fsSLo "$RUNNER_TEMP/bin/minio" https://dl.min.io/server/minio/release/linux-amd64/minio - curl -fsSLo "$RUNNER_TEMP/bin/mc" https://dl.min.io/client/mc/release/linux-amd64/mc - chmod +x "$RUNNER_TEMP/bin/minio" "$RUNNER_TEMP/bin/mc" - curl -fsSL "https://github.com/Shopify/toxiproxy/releases/download/v${TOXIPROXY_VERSION}/toxiproxy_${TOXIPROXY_VERSION}_linux_amd64.tar.gz" \ - | tar -xz -C "$RUNNER_TEMP/bin" toxiproxy-server toxiproxy-cli + curl -fsSLo "$RUNNER_TEMP/bin/minio" \ + "https://dl.min.io/server/minio/release/linux-amd64/archive/minio.${MINIO_VERSION}" + echo "${MINIO_SHA256} $RUNNER_TEMP/bin/minio" | sha256sum -c - + curl -fsSLo "$RUNNER_TEMP/bin/mc" \ + "https://dl.min.io/client/mc/release/linux-amd64/archive/mc.${MC_VERSION}" + echo "${MC_SHA256} $RUNNER_TEMP/bin/mc" | sha256sum -c - + curl -fsSLo "$RUNNER_TEMP/toxiproxy.tar.gz" \ + "https://github.com/Shopify/toxiproxy/releases/download/v${TOXIPROXY_VERSION}/toxiproxy_${TOXIPROXY_VERSION}_linux_amd64.tar.gz" + echo "${TOXIPROXY_SHA256} $RUNNER_TEMP/toxiproxy.tar.gz" | sha256sum -c - + tar -xzf "$RUNNER_TEMP/toxiproxy.tar.gz" -C "$RUNNER_TEMP/bin" toxiproxy-server toxiproxy-cli + chmod +x "$RUNNER_TEMP/bin/minio" "$RUNNER_TEMP/bin/mc" "$RUNNER_TEMP/bin/toxiproxy-server" "$RUNNER_TEMP/bin/toxiproxy-cli" printf '%s\n' \ '#!/usr/bin/env bash' \ 'exec /usr/sbin/slapd -u "$(id -un)" -g "$(id -gn)" "$@"' \ @@ -81,6 +99,7 @@ jobs: mkdir -p "$RUNNER_TEMP/bin" curl -fsSLo "$RUNNER_TEMP/get-version.zip" \ "https://github.com/scylladb-actions/get-version/releases/download/v${GET_VERSION_VERSION}/get-version_${GET_VERSION_VERSION}_linux_amd64v3.zip" + echo "${GET_VERSION_SHA256} $RUNNER_TEMP/get-version.zip" | sha256sum -c - unzip -q -o "$RUNNER_TEMP/get-version.zip" -d "$RUNNER_TEMP/bin" chmod +x "$RUNNER_TEMP/bin/get-version" echo "$RUNNER_TEMP/bin" >> "$GITHUB_PATH" @@ -88,19 +107,13 @@ jobs: - name: Resolve latest stable Scylla release id: scylla-release run: | - stable_filter='^[0-9]{4}$.^[0-9]+$.^[0-9]+$ and LAST.LAST.LAST' - docker_version="$(get-version --source dockerhub-imagetag --repo scylladb/scylla -filters "$stable_filter" | tr -d '"')" - github_version="$(get-version --source github-tag --repo scylladb/scylladb --prefix scylla- --out-no-prefix --filters "$stable_filter" | tr -d '"')" - if [[ -z "$docker_version" || -z "$github_version" ]]; then + version="$(scripts/run_scylla_driver_testpy.sh --resolve-scylla-version)" + if [[ -z "$version" ]]; then echo "Failed to resolve latest stable Scylla release" >&2 exit 1 fi - if [[ "$docker_version" != "$github_version" ]]; then - echo "Latest stable Scylla release mismatch: DockerHub=$docker_version GitHub=$github_version" >&2 - exit 1 - fi - git ls-remote --exit-code --refs --tags https://github.com/scylladb/scylladb.git "refs/tags/scylla-$docker_version" - echo "version=$docker_version" >> "$GITHUB_OUTPUT" + git ls-remote --exit-code --refs --tags https://github.com/scylladb/scylladb.git "refs/tags/scylla-$version" + echo "version=$version" >> "$GITHUB_OUTPUT" - name: Checkout matching Scylla test.py uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 @@ -109,6 +122,7 @@ jobs: ref: scylla-${{ steps.scylla-release.outputs.version }} path: scylladb fetch-depth: 1 + persist-credentials: false - name: Prepare Scylla test.py host compatibility run: | @@ -127,7 +141,7 @@ jobs: - name: Install ccm and Scylla test.py Python dependencies run: | uv pip install \ - "ccm @ git+https://github.com/scylladb/scylla-ccm.git@master" \ + "ccm @ git+https://github.com/scylladb/scylla-ccm.git@${SCYLLA_CCM_COMMIT}" \ aiohttp \ allure-pytest \ colorama \ diff --git a/scripts/run_scylla_driver_testpy.sh b/scripts/run_scylla_driver_testpy.sh index 492b7b2de6..c3a9e48050 100755 --- a/scripts/run_scylla_driver_testpy.sh +++ b/scripts/run_scylla_driver_testpy.sh @@ -12,6 +12,7 @@ jobs="${SCYLLA_TESTPY_JOBS:-1}" max_failures="${SCYLLA_TESTPY_MAX_FAILURES:-1}" timeout="${SCYLLA_TESTPY_TIMEOUT:-1800}" session_timeout="${SCYLLA_TESTPY_SESSION_TIMEOUT:-7200}" +custom_exe_marker_created=0 trim() { local value="$1" @@ -31,7 +32,7 @@ resolve_latest_stable_release() { docker_version="$(get-version \ --source dockerhub-imagetag \ --repo scylladb/scylla \ - -filters "$stable_release_filter" | tr -d '"')" + --filters "$stable_release_filter" | tr -d '"')" github_version="$(get-version \ --source github-tag \ --repo scylladb/scylladb \ @@ -105,6 +106,21 @@ pull_scylla_with_ccm() { "$ccm" remove "$download_cluster_name" >/dev/null 2>&1 || true } +prepare_custom_exe_mode() { + local marker="$source_dir/build.ninja" + + if [[ ! -e "$marker" ]]; then + : > "$marker" + custom_exe_marker_created=1 + fi +} + +cleanup_custom_exe_mode() { + if [[ "$custom_exe_marker_created" == "1" ]]; then + rm -f "$source_dir/build.ninja" + fi +} + validate_selected_tests() { local test_id test_file missing=0 for test_id in "$@"; do @@ -122,6 +138,17 @@ main() { local list_tests=0 local -a tests passthrough_args pytest_args + trap cleanup_custom_exe_mode EXIT + + if [[ "${1:-}" == "--resolve-scylla-version" ]]; then + version="${SCYLLA_VERSION:-}" + if [[ -z "$version" || "$version" == "latest" ]]; then + version="$(resolve_latest_stable_release)" + fi + printf '%s\n' "${version#release:}" + return 0 + fi + if [[ ! -f "$tests_file" ]]; then echo "test selection file does not exist: $tests_file" >&2 return 1 @@ -157,7 +184,7 @@ main() { if [[ -z "$scylla_exe" ]]; then if ! scylla_exe="$(find_scylla_executable "$version")"; then pull_scylla_with_ccm "$version" - scylla_exe="$(find_scylla_executable "$version")" + scylla_exe="$(find_scylla_executable "$version")" || true fi fi if [[ ! -x "$scylla_exe" ]]; then @@ -171,6 +198,7 @@ main() { fi echo "Scylla executable: $scylla_exe" + prepare_custom_exe_mode passthrough_args=() for arg in "$@"; do @@ -210,9 +238,8 @@ main() { ) cd "$source_dir" - # Use Scylla's pytest runner plugin directly. The test.py wrapper probes - # configured build modes before its --exe-path hook can switch to custom_exe, - # which does not work for a source-only checkout plus a ccm-downloaded binary. + # Use Scylla's pytest runner plugin directly. The build.ninja marker makes + # custom_exe path resolution work before --exe-path replaces the binary. "$python_bin" -m pytest "${pytest_args[@]}" }