From fb54012f25746dd931625421638828c5a9a851c6 Mon Sep 17 00:00:00 2001 From: Dmitry Kropachev Date: Sun, 24 May 2026 00:22:01 -0400 Subject: [PATCH 01/32] ci: replace version helper with get-version action --- .github/workflows/build-lint-and-test.yml | 76 ++++---- ci/version_fetch.py | 212 ---------------------- 2 files changed, 37 insertions(+), 251 deletions(-) delete mode 100644 ci/version_fetch.py diff --git a/.github/workflows/build-lint-and-test.yml b/.github/workflows/build-lint-and-test.yml index 87b885eeb..e7755525c 100644 --- a/.github/workflows/build-lint-and-test.yml +++ b/.github/workflows/build-lint-and-test.yml @@ -60,7 +60,11 @@ jobs: strategy: matrix: - scylla-version: [ENTERPRISE-RELEASE, ENTERPRISE-PRIOR-RELEASE] + include: + - scylla-version: LTS-LATEST + scylla-filter: '^[0-9]{4}$.^[0-9]+$.^[0-9]+$ and LAST.1.LAST' + - scylla-version: LTS-PRIOR + scylla-filter: '^[0-9]{4}$.^[0-9]+$.^[0-9]+$ and LAST-1.1.LAST' fail-fast: false steps: @@ -81,43 +85,33 @@ jobs: - name: Get scylla version id: scylla-version - run: | - if [[ "${{ matrix.scylla-version }}" == "ENTERPRISE-RELEASE" ]]; then - echo "value=$(python3 ci/version_fetch.py --version-index 1 scylla-enterprise-stable:1 | tr -d '\"')" | tee -a $GITHUB_OUTPUT - elif [[ "${{ matrix.scylla-version }}" == "ENTERPRISE-PRIOR-RELEASE" ]]; then - echo "value=$(python3 ci/version_fetch.py --version-index 2 scylla-enterprise-stable:2 | tr -d '\"')" | tee -a $GITHUB_OUTPUT - elif [[ "${{ matrix.scylla-version }}" == "ENTERPRISE-RC" ]]; then - echo "value=$(python3 ci/version_fetch.py --version-index 1 scylla-enterprise-rc | tr -d '\"')" | tee -a $GITHUB_OUTPUT - elif [[ "${{ matrix.scylla-version }}" == "OSS-RELEASE" ]]; then - echo "value=$(python3 ci/version_fetch.py --version-index 1 scylla-oss-stable:1 | tr -d '\"')" | tee -a $GITHUB_OUTPUT - elif [[ "${{ matrix.scylla-version }}" == "OSS-PRIOR-RELEASE" ]]; then - echo "value=$(python3 ci/version_fetch.py --version-index 2 scylla-oss-stable:2 | tr -d '\"')" | tee -a $GITHUB_OUTPUT - elif [[ "${{ matrix.scylla-version }}" == "OSS-RC" ]]; then - echo "value=$(python3 ci/version_fetch.py --version-index 1 scylla-oss-rc | tr -d '\"')" | tee -a $GITHUB_OUTPUT - elif echo "${{ matrix.scylla-version }}" | grep -P '^[0-9\.]+'; then # If you want to run specific version do just that - echo "value=${{ matrix.scylla-version }}" | tee -a $GITHUB_OUTPUT - else - echo "Unknown scylla version name `${{ matrix.scylla-version }}`" - exit 1 - fi + uses: scylladb-actions/get-version@v0.4.5 + with: + source: dockerhub-imagetag + repo: scylladb/scylla + filters: ${{ matrix.scylla-filter }} + + - name: Resolve scylla version + id: scylla-version-value + run: echo "value=${{ fromJson(steps.scylla-version.outputs.versions)[0] }}" | tee -a "$GITHUB_OUTPUT" - name: Pull CCM image from the cache uses: actions/cache/restore@v4 id: pull-image with: path: ~/.ccm/scylla-repository - key: image-scylla-${{ runner.os }}-${{ steps.scylla-version.outputs.value }} + key: image-scylla-${{ runner.os }}-${{ steps.scylla-version-value.outputs.value }} - - name: Download Scylla (${{ steps.scylla-version.outputs.value }}) image + - name: Download Scylla (${{ steps.scylla-version-value.outputs.value }}) image if: steps.pull-image.outputs.cache-hit != 'true' - run: SCYLLA_VERSION="release:${{ steps.scylla-version.outputs.value }}" make download-ccm-scylla-image + run: SCYLLA_VERSION="release:${{ steps.scylla-version-value.outputs.value }}" make download-ccm-scylla-image - name: Save CCM image cache uses: actions/cache/save@v4 if: steps.pull-image.outputs.cache-hit != 'true' with: path: ~/.ccm/scylla-repository - key: image-scylla-${{ runner.os }}-${{ steps.scylla-version.outputs.value }} + key: image-scylla-${{ runner.os }}-${{ steps.scylla-version-value.outputs.value }} - name: Pull integration test binary uses: actions/cache/restore@v4 @@ -134,9 +128,9 @@ jobs: - name: Prepare environment run: make update-rust-tooling prepare-integration-test - - name: Run integration tests on Scylla ${{ steps.scylla-version.outputs.value }} + - name: Run integration tests on Scylla ${{ steps.scylla-version-value.outputs.value }} id: run-integration-tests - run: SCYLLA_VERSION="release:${{ steps.scylla-version.outputs.value }}" make run-test-integration-scylla + run: SCYLLA_VERSION="release:${{ steps.scylla-version-value.outputs.value }}" make run-test-integration-scylla - name: Upload test logs uses: actions/upload-artifact@v4 @@ -158,7 +152,7 @@ jobs: strategy: matrix: - cassandra-version: [RELEASE-3.X] + cassandra-version: [3-LATEST] java-version: [8] fail-fast: false @@ -185,32 +179,36 @@ jobs: - name: Get cassandra version id: cassandra-version - run: | - if [[ "${{ matrix.cassandra-version }}" == "RELEASE-3.X" ]]; then - echo "value=$(python3 ci/version_fetch.py --version-index 1 cassandra3-stable:1 | tr -d '\"')" | tee -a $GITHUB_OUTPUT - elif [[ "${{ matrix.cassandra-version }}" == "RELEASE-4.X" ]]; then - echo "value=$(python3 ci/version_fetch.py --version-index 1 cassandra4-stable:1 | tr -d '\"')" | tee -a $GITHUB_OUTPUT - else - echo "Unknown cassandra version name `${{ matrix.cassandra-version }}`" - fi + uses: scylladb-actions/get-version@v0.4.5 + with: + source: github-tag + repo: apache/cassandra + prefix: cassandra- + out-no-prefix: true + github-token: ${{ secrets.GITHUB_TOKEN }} + filters: '^[0-9]+$.^[0-9]+$.^[0-9]+$ and 3.LAST.LAST' + + - name: Resolve cassandra version + id: cassandra-version-value + run: echo "value=${{ fromJson(steps.cassandra-version.outputs.versions)[0] }}" | tee -a "$GITHUB_OUTPUT" - name: Pull CCM image from the cache uses: actions/cache/restore@v4 id: pull-image with: path: ~/.ccm/repository - key: image-cassandra-${{ runner.os }}-${{ steps.cassandra-version.outputs.value }} + key: image-cassandra-${{ runner.os }}-${{ steps.cassandra-version-value.outputs.value }} - - name: Download Cassandra (${{ steps.cassandra-version.outputs.value }}) image + - name: Download Cassandra (${{ steps.cassandra-version-value.outputs.value }}) image if: steps.pull-image.outputs.cache-hit != 'true' - run: CASSANDRA_VERSION="${{ steps.cassandra-version.outputs.value }}" make download-ccm-cassandra-image + run: CASSANDRA_VERSION="${{ steps.cassandra-version-value.outputs.value }}" make download-ccm-cassandra-image - name: Save CCM image cache uses: actions/cache/save@v4 if: steps.pull-image.outputs.cache-hit != 'true' with: path: ~/.ccm/repository - key: image-cassandra-${{ runner.os }}-${{ steps.cassandra-version.outputs.value }} + key: image-cassandra-${{ runner.os }}-${{ steps.cassandra-version-value.outputs.value }} - name: Pull integration test binary uses: actions/cache/restore@v4 diff --git a/ci/version_fetch.py b/ci/version_fetch.py deleted file mode 100644 index 81bfcc19a..000000000 --- a/ci/version_fetch.py +++ /dev/null @@ -1,212 +0,0 @@ -#!/usr/bin/python3 - -""" -This Python script allows you to list the -latest version numbers of Scylla and Cassandra. -You can specify whether you want the -versions of Scylla OSS or Scylla Enterprise, -either N latest stable X.Y.latest or -all non-obsolete RCs. You can also fetch -the latest version of Cassandra 3. -How are those versions fetched? We use Docker Hub -tags API. -""" - -import requests -import argparse -import re -import json -import sys - -DOCKER_HUB_TAGS_ENDPOINT = 'https://hub.docker.com/v2/namespaces/%s/repositories/%s/tags?page_size=1000' -DOCKER_HUB_SCYLLA_NAMESPACE = 'scylladb' - -SCYLLA_OSS = (DOCKER_HUB_SCYLLA_NAMESPACE, 'scylla') -SCYLLA_ENTERPRISE = (DOCKER_HUB_SCYLLA_NAMESPACE, 'scylla-enterprise') - -CASSANDRA_ENDPOINT = 'https://dlcdn.apache.org/cassandra/' -CASSANDRA_REGEX = re.compile(r'a href="([0-9])\.(\d+)\.(\d+)/"') - -VERSION_DEFINITION_RE = re.compile( - r'((?:(scylla-oss-stable):(\d+))|(?:(scylla-enterprise-stable)(:\d+)?)|(?:(cassandra3-stable)(:\d+)?)|(?:(cassandra4-stable)(:\d+)?)|(?:(scylla-oss-rc)(:\d+)?)|(?:(scylla-enterprise-rc)(:\d+)?))') -ONLY_DIGITS_RE = re.compile("^[0-9]+") - -class Version: - raw = "" - invalid = False - major = 0 - minor = 0 - minor_raw = "" - minor_rest = "" - patch = 0 - patch_raw = "" - patch_rest = "" - is_dev = False - - def __init__(self, ver): - self.raw = ver - chunks = ver.split(".", maxsplit=3) - if len(chunks) < 3: - self.invalid = True - return - - self.major, self.minor_raw, self.patch_raw = chunks - - try: - self.major = int(self.major) - except Exception: - self.invalid = True - return - - digits = ONLY_DIGITS_RE.match(self.minor_raw) - if digits: - try: - self.minor = int(self.minor_raw[digits.regs[0][0]:digits.regs[0][1]]) - self.minor_rest = self.minor_raw[digits.regs[0][1]:] - if self.minor_rest: - self.is_dev = True - except Exception: - self.invalid = True - else: - self.minor = 0 - - digits = ONLY_DIGITS_RE.match(self.patch_raw) - if digits: - try: - self.patch = int(self.patch_raw[digits.regs[0][0]:digits.regs[0][1]]) - self.patch_rest = self.patch_raw[digits.regs[0][1]:] - if self.patch_rest: - self.is_dev = True - except Exception: - self.invalid = True - else: - self.patch = 0 - - def __str__(self): - return self.raw - - def __repr__(self): - return self.raw - - def __lt__(self, other): - if self.major != other.major: - return self.major < other.major - if self.minor != other.minor: - return self.minor < other.minor - if self.patch != other.patch: - return self.patch < other.patch - if self.is_dev == other.is_dev: - return self.patch_rest < other.patch_rest - return self.is_dev - - -def fetch_docker_hub_tags(namespace, repository): - tags = [] - - # Fetch all pages of tags for a given repository - current_page_endpoint = DOCKER_HUB_TAGS_ENDPOINT % (namespace, repository) - while True: - # Fetch a page - tags_data = requests.get(current_page_endpoint).json() - - # Extract all tags from the response - tags.extend(map(lambda e: e['name'], tags_data['results'])) - - # Move to the next page if it's needed - if tags_data['next'] is not None: - current_page_endpoint = tags_data['next'] - else: - break - - result = [] - for tag in tags: - try: - ver = Version(tag) - if not ver.patch_raw or ver.invalid: - continue - result.append(ver) - except Exception: - continue - - return reversed(sorted(result)) - -rc_only = lambda x: x.is_dev -release_only = lambda x: not x.is_dev -scylla_oss_only = lambda x: x.major < 2000 -scylla_enterprise_only = lambda x: x.major > 2000 -cassandra_3_only = lambda x: x.major == 3 -cassandra_4_only = lambda x: x.major == 4 - -def filter_versions(all_versions, count, *filters): - result = [] - for ver in filter(lambda ver: all(map(lambda ft: ft(ver), filters)), all_versions): - for existing_ver in result: - if ver.major == existing_ver.major and ver.minor == existing_ver.minor: - break - else: - if len(result) >= count: - return result - result.append(ver) - return result - -def fetch_all_cassandra_versions(): - # Download folder listing for Cassandra download site - data = requests.get(CASSANDRA_ENDPOINT).text - - # Parse only those version numbers which match '3.NUM.NUM' - # into tuple (3, NUM, NUM) - data = CASSANDRA_REGEX.finditer(data) - data = map(lambda e: e.groups(), data) - data = map(lambda e: Version(f"{e[0]}.{e[1]}.{e[2]}"), data) - return reversed(sorted(data)) - - -if __name__ == '__main__': - total_result = [] - - def version_definition_type(arg): - if not VERSION_DEFINITION_RE.match(arg): - raise argparse.ArgumentTypeError(f"invalid version definition `{arg}`") - return arg - - parser = argparse.ArgumentParser(description='Get scylla and cassandra versions.') - parser.add_argument('definitions', metavar='VERSION-DEFINITION', type=version_definition_type, nargs='+', - help='A list of scylla and cassandra version definitions: scylla-oss-stable[:COUNT] | scylla-enterprise-stable[:COUNT] | cassandra3-stable[:COUNT] | cassandra4-stable[:COUNT] | scylla-oss-rc[:COUNT] | scylla-enterprise-rc[:COUNT]') - - parser.add_argument('--version-index', dest='version_index', type=int, default=0, help='print single version only') - - args = parser.parse_args() - - for version_def in args.definitions: - groups = VERSION_DEFINITION_RE.match(version_def).groups() - groups = [g for g in groups if g][1:] - - mode_name = groups[0] - versions_count = int(groups[1].replace(":","")) if len(groups) > 1 else 1 - - result = [] - if mode_name == 'scylla-oss-stable': - result = filter_versions(fetch_docker_hub_tags(*SCYLLA_OSS), versions_count, scylla_oss_only, release_only) - elif mode_name == 'scylla-enterprise-stable': - result = filter_versions(fetch_docker_hub_tags(*SCYLLA_ENTERPRISE), versions_count, scylla_enterprise_only, release_only) - elif mode_name == 'cassandra3-stable': - result = filter_versions(fetch_all_cassandra_versions(), versions_count, cassandra_3_only) - elif mode_name == 'cassandra4-stable': - result = filter_versions(fetch_all_cassandra_versions(), versions_count, cassandra_4_only) - elif mode_name == 'scylla-oss-rc': - result = filter_versions(fetch_docker_hub_tags(*SCYLLA_OSS), versions_count, scylla_oss_only, rc_only) - elif mode_name == 'scylla-enterprise-rc': - result = filter_versions(fetch_docker_hub_tags(*SCYLLA_ENTERPRISE), versions_count, scylla_enterprise_only, rc_only) - - total_result += result - - total_result = [str(k) for k in reversed(sorted(total_result))] - - if args.version_index == 0: - print(json.dumps(list(total_result))) - sys.exit(0) - if len(total_result) < args.version_index: - print("No versions found", file=sys.stderr) - sys.exit(1) - print(json.dumps(total_result[args.version_index-1])) - sys.exit(0) From b3d8395ec7a31b99c8fced50916c9cb219f8334c Mon Sep 17 00:00:00 2001 From: Dmitry Kropachev Date: Sun, 24 May 2026 00:54:03 -0400 Subject: [PATCH 02/32] ci: strip cassandra version prefix --- .github/workflows/build-lint-and-test.yml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.github/workflows/build-lint-and-test.yml b/.github/workflows/build-lint-and-test.yml index e7755525c..16b07b27e 100644 --- a/.github/workflows/build-lint-and-test.yml +++ b/.github/workflows/build-lint-and-test.yml @@ -190,7 +190,9 @@ jobs: - name: Resolve cassandra version id: cassandra-version-value - run: echo "value=${{ fromJson(steps.cassandra-version.outputs.versions)[0] }}" | tee -a "$GITHUB_OUTPUT" + run: | + value=${{ fromJson(steps.cassandra-version.outputs.versions)[0] }} + echo "value=${value#cassandra-}" | tee -a "$GITHUB_OUTPUT" - name: Pull CCM image from the cache uses: actions/cache/restore@v4 From 50bb4c5521abcedf46af1aa1a96e31310ea19f10 Mon Sep 17 00:00:00 2001 From: Dmitry Kropachev Date: Sun, 24 May 2026 07:53:06 -0400 Subject: [PATCH 03/32] ci: rename scylla integration checks --- .github/workflows/build-lint-and-test.yml | 34 ++++++++++++----------- 1 file changed, 18 insertions(+), 16 deletions(-) diff --git a/.github/workflows/build-lint-and-test.yml b/.github/workflows/build-lint-and-test.yml index 16b07b27e..5f1b32d4d 100644 --- a/.github/workflows/build-lint-and-test.yml +++ b/.github/workflows/build-lint-and-test.yml @@ -60,22 +60,13 @@ jobs: strategy: matrix: - include: - - scylla-version: LTS-LATEST - scylla-filter: '^[0-9]{4}$.^[0-9]+$.^[0-9]+$ and LAST.1.LAST' - - scylla-version: LTS-PRIOR - scylla-filter: '^[0-9]{4}$.^[0-9]+$.^[0-9]+$ and LAST-1.1.LAST' + scylla-version: [LATEST, PRIOR] fail-fast: false steps: - name: Checkout uses: actions/checkout@v4 - - name: Setup Python 3 - uses: actions/setup-python@v5 - with: - python-version: "3.11" - - name: Update apt cache run: sudo apt-get update -y @@ -83,13 +74,29 @@ jobs: run: | make install-ccm-if-missing + - name: Select scylla filter + id: scylla-filter + run: | + case "${{ matrix.scylla-version }}" in + LATEST) + printf 'value=%s\n' '^[0-9]{4}$.^[0-9]+$.^[0-9]+$ and LAST.LAST.LAST' >> "$GITHUB_OUTPUT" + ;; + PRIOR) + printf 'value=%s\n' '^[0-9]{4}$.^[0-9]+$.^[0-9]+$ and LAST.LAST.LAST-1' >> "$GITHUB_OUTPUT" + ;; + *) + echo "Unknown scylla version name ${{ matrix.scylla-version }}" + exit 1 + ;; + esac + - name: Get scylla version id: scylla-version uses: scylladb-actions/get-version@v0.4.5 with: source: dockerhub-imagetag repo: scylladb/scylla - filters: ${{ matrix.scylla-filter }} + filters: ${{ steps.scylla-filter.outputs.value }} - name: Resolve scylla version id: scylla-version-value @@ -166,11 +173,6 @@ jobs: java-version: ${{ matrix.java-version }} distribution: "adopt" - - name: Setup Python 3 - uses: actions/setup-python@v5 - with: - python-version: "3.11" - - name: Update apt cache run: sudo apt-get update -y From 87952c28232a53632b65bd56236ea9fb41e5dd37 Mon Sep 17 00:00:00 2001 From: Dmitry Kropachev Date: Sun, 24 May 2026 08:03:04 -0400 Subject: [PATCH 04/32] ci: restore ccm path for integration jobs --- .github/workflows/build-lint-and-test.yml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/.github/workflows/build-lint-and-test.yml b/.github/workflows/build-lint-and-test.yml index 5f1b32d4d..1f48f3d55 100644 --- a/.github/workflows/build-lint-and-test.yml +++ b/.github/workflows/build-lint-and-test.yml @@ -74,6 +74,9 @@ jobs: run: | make install-ccm-if-missing + - name: Add local bin to PATH + run: echo "$HOME/.local/bin" >> "$GITHUB_PATH" + - name: Select scylla filter id: scylla-filter run: | @@ -179,6 +182,9 @@ jobs: - name: Install CCM run: make install-ccm-if-missing + - name: Add local bin to PATH + run: echo "$HOME/.local/bin" >> "$GITHUB_PATH" + - name: Get cassandra version id: cassandra-version uses: scylladb-actions/get-version@v0.4.5 From fafda42ef738be56c609abc54a918ccb51b15dd6 Mon Sep 17 00:00:00 2001 From: Dmitry Kropachev Date: Sun, 24 May 2026 08:16:08 -0400 Subject: [PATCH 05/32] ci: make ccm path explicit in integration jobs --- .github/workflows/build-lint-and-test.yml | 19 ++++++------------- 1 file changed, 6 insertions(+), 13 deletions(-) diff --git a/.github/workflows/build-lint-and-test.yml b/.github/workflows/build-lint-and-test.yml index 1f48f3d55..06b9f97c5 100644 --- a/.github/workflows/build-lint-and-test.yml +++ b/.github/workflows/build-lint-and-test.yml @@ -71,11 +71,7 @@ jobs: run: sudo apt-get update -y - name: Install CCM - run: | - make install-ccm-if-missing - - - name: Add local bin to PATH - run: echo "$HOME/.local/bin" >> "$GITHUB_PATH" + run: PATH="$HOME/.local/bin:$PATH" make install-ccm-if-missing - name: Select scylla filter id: scylla-filter @@ -114,7 +110,7 @@ jobs: - name: Download Scylla (${{ steps.scylla-version-value.outputs.value }}) image if: steps.pull-image.outputs.cache-hit != 'true' - run: SCYLLA_VERSION="release:${{ steps.scylla-version-value.outputs.value }}" make download-ccm-scylla-image + run: PATH="$HOME/.local/bin:$PATH" SCYLLA_VERSION="release:${{ steps.scylla-version-value.outputs.value }}" make download-ccm-scylla-image - name: Save CCM image cache uses: actions/cache/save@v4 @@ -140,7 +136,7 @@ jobs: - name: Run integration tests on Scylla ${{ steps.scylla-version-value.outputs.value }} id: run-integration-tests - run: SCYLLA_VERSION="release:${{ steps.scylla-version-value.outputs.value }}" make run-test-integration-scylla + run: PATH="$HOME/.local/bin:$PATH" SCYLLA_VERSION="release:${{ steps.scylla-version-value.outputs.value }}" make run-test-integration-scylla - name: Upload test logs uses: actions/upload-artifact@v4 @@ -180,10 +176,7 @@ jobs: run: sudo apt-get update -y - name: Install CCM - run: make install-ccm-if-missing - - - name: Add local bin to PATH - run: echo "$HOME/.local/bin" >> "$GITHUB_PATH" + run: PATH="$HOME/.local/bin:$PATH" make install-ccm-if-missing - name: Get cassandra version id: cassandra-version @@ -211,7 +204,7 @@ jobs: - name: Download Cassandra (${{ steps.cassandra-version-value.outputs.value }}) image if: steps.pull-image.outputs.cache-hit != 'true' - run: CASSANDRA_VERSION="${{ steps.cassandra-version-value.outputs.value }}" make download-ccm-cassandra-image + run: PATH="$HOME/.local/bin:$PATH" CASSANDRA_VERSION="${{ steps.cassandra-version-value.outputs.value }}" make download-ccm-cassandra-image - name: Save CCM image cache uses: actions/cache/save@v4 @@ -237,7 +230,7 @@ jobs: - name: Run integration tests on Cassandra ${{ steps.cassandra-version.outputs.value }} id: run-integration-tests - run: CASSANDRA_VERSION="${{ steps.cassandra-version.outputs.value }}" make run-test-integration-cassandra + run: PATH="$HOME/.local/bin:$PATH" CASSANDRA_VERSION="${{ steps.cassandra-version.outputs.value }}" make run-test-integration-cassandra - name: Upload test logs uses: actions/upload-artifact@v4 From cd44dee7046f2a9c95108b8e13548f8a07bb85b9 Mon Sep 17 00:00:00 2001 From: Dmitry Kropachev Date: Sun, 24 May 2026 08:29:11 -0400 Subject: [PATCH 06/32] ci: export ccm path in integration jobs --- .github/workflows/build-lint-and-test.yml | 24 +++++++++++++++++------ 1 file changed, 18 insertions(+), 6 deletions(-) diff --git a/.github/workflows/build-lint-and-test.yml b/.github/workflows/build-lint-and-test.yml index 06b9f97c5..60f630c36 100644 --- a/.github/workflows/build-lint-and-test.yml +++ b/.github/workflows/build-lint-and-test.yml @@ -71,7 +71,9 @@ jobs: run: sudo apt-get update -y - name: Install CCM - run: PATH="$HOME/.local/bin:$PATH" make install-ccm-if-missing + run: | + export PATH="$HOME/.local/bin:$PATH" + make install-ccm-if-missing - name: Select scylla filter id: scylla-filter @@ -110,7 +112,9 @@ jobs: - name: Download Scylla (${{ steps.scylla-version-value.outputs.value }}) image if: steps.pull-image.outputs.cache-hit != 'true' - run: PATH="$HOME/.local/bin:$PATH" SCYLLA_VERSION="release:${{ steps.scylla-version-value.outputs.value }}" make download-ccm-scylla-image + run: | + export PATH="$HOME/.local/bin:$PATH" + SCYLLA_VERSION="release:${{ steps.scylla-version-value.outputs.value }}" make download-ccm-scylla-image - name: Save CCM image cache uses: actions/cache/save@v4 @@ -136,7 +140,9 @@ jobs: - name: Run integration tests on Scylla ${{ steps.scylla-version-value.outputs.value }} id: run-integration-tests - run: PATH="$HOME/.local/bin:$PATH" SCYLLA_VERSION="release:${{ steps.scylla-version-value.outputs.value }}" make run-test-integration-scylla + run: | + export PATH="$HOME/.local/bin:$PATH" + SCYLLA_VERSION="release:${{ steps.scylla-version-value.outputs.value }}" make run-test-integration-scylla - name: Upload test logs uses: actions/upload-artifact@v4 @@ -176,7 +182,9 @@ jobs: run: sudo apt-get update -y - name: Install CCM - run: PATH="$HOME/.local/bin:$PATH" make install-ccm-if-missing + run: | + export PATH="$HOME/.local/bin:$PATH" + make install-ccm-if-missing - name: Get cassandra version id: cassandra-version @@ -204,7 +212,9 @@ jobs: - name: Download Cassandra (${{ steps.cassandra-version-value.outputs.value }}) image if: steps.pull-image.outputs.cache-hit != 'true' - run: PATH="$HOME/.local/bin:$PATH" CASSANDRA_VERSION="${{ steps.cassandra-version-value.outputs.value }}" make download-ccm-cassandra-image + run: | + export PATH="$HOME/.local/bin:$PATH" + CASSANDRA_VERSION="${{ steps.cassandra-version-value.outputs.value }}" make download-ccm-cassandra-image - name: Save CCM image cache uses: actions/cache/save@v4 @@ -230,7 +240,9 @@ jobs: - name: Run integration tests on Cassandra ${{ steps.cassandra-version.outputs.value }} id: run-integration-tests - run: PATH="$HOME/.local/bin:$PATH" CASSANDRA_VERSION="${{ steps.cassandra-version.outputs.value }}" make run-test-integration-cassandra + run: | + export PATH="$HOME/.local/bin:$PATH" + CASSANDRA_VERSION="${{ steps.cassandra-version.outputs.value }}" make run-test-integration-cassandra - name: Upload test logs uses: actions/upload-artifact@v4 From b23099996c3851a262d5734ce98f64ab2f9d9e5a Mon Sep 17 00:00:00 2001 From: Dmitry Kropachev Date: Sun, 24 May 2026 09:32:37 -0400 Subject: [PATCH 07/32] ci: add scylla lts integration jobs --- .github/workflows/build-lint-and-test.yml | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/.github/workflows/build-lint-and-test.yml b/.github/workflows/build-lint-and-test.yml index 60f630c36..169b8b18b 100644 --- a/.github/workflows/build-lint-and-test.yml +++ b/.github/workflows/build-lint-and-test.yml @@ -60,7 +60,7 @@ jobs: strategy: matrix: - scylla-version: [LATEST, PRIOR] + scylla-version: [LATEST, PRIOR, LTS-LATEST, LTS-PRIOR] fail-fast: false steps: @@ -85,6 +85,12 @@ jobs: PRIOR) printf 'value=%s\n' '^[0-9]{4}$.^[0-9]+$.^[0-9]+$ and LAST.LAST.LAST-1' >> "$GITHUB_OUTPUT" ;; + LTS-LATEST) + printf 'value=%s\n' '^[0-9]{4}$.1$.^[0-9]+$ and LAST.LAST.LAST' >> "$GITHUB_OUTPUT" + ;; + LTS-PRIOR) + printf 'value=%s\n' '^[0-9]{4}$.1$.^[0-9]+$ and LAST.LAST.LAST-1' >> "$GITHUB_OUTPUT" + ;; *) echo "Unknown scylla version name ${{ matrix.scylla-version }}" exit 1 From 0014a9d830501fb6686f41f6010c065667a44643 Mon Sep 17 00:00:00 2001 From: Dmitry Kropachev Date: Sun, 24 May 2026 09:48:52 -0400 Subject: [PATCH 08/32] ci: fix scylla release line filters --- .github/workflows/build-lint-and-test.yml | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/.github/workflows/build-lint-and-test.yml b/.github/workflows/build-lint-and-test.yml index 169b8b18b..ce9d038d4 100644 --- a/.github/workflows/build-lint-and-test.yml +++ b/.github/workflows/build-lint-and-test.yml @@ -78,18 +78,20 @@ jobs: - name: Select scylla filter id: scylla-filter run: | + # Select the latest stable patch on each release line and drop + # prerelease tags before taking the requested position. case "${{ matrix.scylla-version }}" in LATEST) - printf 'value=%s\n' '^[0-9]{4}$.^[0-9]+$.^[0-9]+$ and LAST.LAST.LAST' >> "$GITHUB_OUTPUT" + printf 'value=%s\n' '^[0-9]{4}$.^[2-9][0-9]*$.LAST and *.*.^[0-9]+$ and LAST' >> "$GITHUB_OUTPUT" ;; PRIOR) - printf 'value=%s\n' '^[0-9]{4}$.^[0-9]+$.^[0-9]+$ and LAST.LAST.LAST-1' >> "$GITHUB_OUTPUT" + printf 'value=%s\n' '^[0-9]{4}$.^[2-9][0-9]*$.LAST and *.*.^[0-9]+$ and LAST-1' >> "$GITHUB_OUTPUT" ;; LTS-LATEST) - printf 'value=%s\n' '^[0-9]{4}$.1$.^[0-9]+$ and LAST.LAST.LAST' >> "$GITHUB_OUTPUT" + printf 'value=%s\n' '^[0-9]{4}$.1.LAST and *.*.^[0-9]+$ and LAST' >> "$GITHUB_OUTPUT" ;; LTS-PRIOR) - printf 'value=%s\n' '^[0-9]{4}$.1$.^[0-9]+$ and LAST.LAST.LAST-1' >> "$GITHUB_OUTPUT" + printf 'value=%s\n' '^[0-9]{4}$.1.LAST and *.*.^[0-9]+$ and LAST-1' >> "$GITHUB_OUTPUT" ;; *) echo "Unknown scylla version name ${{ matrix.scylla-version }}" @@ -107,7 +109,13 @@ jobs: - name: Resolve scylla version id: scylla-version-value - run: echo "value=${{ fromJson(steps.scylla-version.outputs.versions)[0] }}" | tee -a "$GITHUB_OUTPUT" + run: | + value='${{ fromJson(steps.scylla-version.outputs.versions)[0] }}' + if [ -z "$value" ]; then + echo "No Scylla version resolved for ${{ matrix.scylla-version }}" >&2 + exit 1 + fi + echo "value=$value" | tee -a "$GITHUB_OUTPUT" - name: Pull CCM image from the cache uses: actions/cache/restore@v4 From 7a3a82c398e066fa922cd7513ba6bc9eb33f3940 Mon Sep 17 00:00:00 2001 From: Dmitry Kropachev Date: Sun, 24 May 2026 10:03:24 -0400 Subject: [PATCH 09/32] ci: fix integration workflow env handling --- .github/workflows/build-lint-and-test.yml | 20 +++++++------------- 1 file changed, 7 insertions(+), 13 deletions(-) diff --git a/.github/workflows/build-lint-and-test.yml b/.github/workflows/build-lint-and-test.yml index ce9d038d4..550071e5f 100644 --- a/.github/workflows/build-lint-and-test.yml +++ b/.github/workflows/build-lint-and-test.yml @@ -72,8 +72,7 @@ jobs: - name: Install CCM run: | - export PATH="$HOME/.local/bin:$PATH" - make install-ccm-if-missing + PATH="$HOME/.local/bin:$PATH" make install-ccm-if-missing - name: Select scylla filter id: scylla-filter @@ -127,8 +126,7 @@ jobs: - name: Download Scylla (${{ steps.scylla-version-value.outputs.value }}) image if: steps.pull-image.outputs.cache-hit != 'true' run: | - export PATH="$HOME/.local/bin:$PATH" - SCYLLA_VERSION="release:${{ steps.scylla-version-value.outputs.value }}" make download-ccm-scylla-image + PATH="$HOME/.local/bin:$PATH" SCYLLA_VERSION="release:${{ steps.scylla-version-value.outputs.value }}" make download-ccm-scylla-image - name: Save CCM image cache uses: actions/cache/save@v4 @@ -155,8 +153,7 @@ jobs: - name: Run integration tests on Scylla ${{ steps.scylla-version-value.outputs.value }} id: run-integration-tests run: | - export PATH="$HOME/.local/bin:$PATH" - SCYLLA_VERSION="release:${{ steps.scylla-version-value.outputs.value }}" make run-test-integration-scylla + PATH="$HOME/.local/bin:$PATH" SCYLLA_VERSION="release:${{ steps.scylla-version-value.outputs.value }}" make run-test-integration-scylla - name: Upload test logs uses: actions/upload-artifact@v4 @@ -197,8 +194,7 @@ jobs: - name: Install CCM run: | - export PATH="$HOME/.local/bin:$PATH" - make install-ccm-if-missing + PATH="$HOME/.local/bin:$PATH" make install-ccm-if-missing - name: Get cassandra version id: cassandra-version @@ -227,8 +223,7 @@ jobs: - name: Download Cassandra (${{ steps.cassandra-version-value.outputs.value }}) image if: steps.pull-image.outputs.cache-hit != 'true' run: | - export PATH="$HOME/.local/bin:$PATH" - CASSANDRA_VERSION="${{ steps.cassandra-version-value.outputs.value }}" make download-ccm-cassandra-image + PATH="$HOME/.local/bin:$PATH" CASSANDRA_VERSION="${{ steps.cassandra-version-value.outputs.value }}" make download-ccm-cassandra-image - name: Save CCM image cache uses: actions/cache/save@v4 @@ -252,11 +247,10 @@ jobs: - name: Prepare environment run: make update-rust-tooling prepare-integration-test - - name: Run integration tests on Cassandra ${{ steps.cassandra-version.outputs.value }} + - name: Run integration tests on Cassandra ${{ steps.cassandra-version-value.outputs.value }} id: run-integration-tests run: | - export PATH="$HOME/.local/bin:$PATH" - CASSANDRA_VERSION="${{ steps.cassandra-version.outputs.value }}" make run-test-integration-cassandra + PATH="$HOME/.local/bin:$PATH" CASSANDRA_VERSION="${{ steps.cassandra-version-value.outputs.value }}" make run-test-integration-cassandra - name: Upload test logs uses: actions/upload-artifact@v4 From 320f5a53cd3faa7b5d18e0b723dabf4ef93513ac Mon Sep 17 00:00:00 2001 From: Dmitry Kropachev Date: Sun, 24 May 2026 10:16:30 -0400 Subject: [PATCH 10/32] ci: export ccm path in make recipes --- Makefile | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Makefile b/Makefile index a9b3532a6..7e739204e 100644 --- a/Makefile +++ b/Makefile @@ -7,6 +7,9 @@ SHELL := bash ifeq ($(OS),Windows_NT) SHELL := pwsh.exe .SHELLFLAGS := -NoProfile -Command $$ErrorActionPreference = 'Stop'; +else + # Keep pip-installed tools like `ccm` visible to make recipes. + export PATH := $(HOME)/.local/bin:$(PATH) endif UNAME_S := $(shell uname -s) From 991e947bf0e0752bfb172ebc44cf30c61e9c5d48 Mon Sep 17 00:00:00 2001 From: Dmitry Kropachev Date: Sun, 24 May 2026 10:28:37 -0400 Subject: [PATCH 11/32] ci: use explicit ccm path in make recipes --- Makefile | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/Makefile b/Makefile index 7e739204e..e74602307 100644 --- a/Makefile +++ b/Makefile @@ -10,6 +10,7 @@ ifeq ($(OS),Windows_NT) else # Keep pip-installed tools like `ccm` visible to make recipes. export PATH := $(HOME)/.local/bin:$(PATH) + CCM_BIN := $(shell command -v ccm 2>/dev/null || printf '%s' "$(HOME)/.local/bin/ccm") endif UNAME_S := $(shell uname -s) @@ -245,7 +246,7 @@ install-clang-format-if-missing: update-apt-cache-if-needed ) install-ccm-if-missing: - @ccm list >/dev/null 2>&1 || ( + @$(CCM_BIN) list >/dev/null 2>&1 || ( echo "CCM not found in the system, install it." pip3 install --user https://github.com/scylladb/scylla-ccm/archive/${CCM_COMMIT_ID}.zip ) @@ -434,14 +435,14 @@ download-ccm-scylla-image: install-ccm-if-missing @echo "Downloading scylla ${SCYLLA_VERSION} CCM image" @rm -rf /tmp/download-scylla.ccm || true @mkdir /tmp/download-scylla.ccm || true - @ccm create ccm_1 -i 127.0.1. -n 3:0 -v "${SCYLLA_VERSION}" --scylla --config-dir=/tmp/download-scylla.ccm + @$(CCM_BIN) create ccm_1 -i 127.0.1. -n 3:0 -v "${SCYLLA_VERSION}" --scylla --config-dir=/tmp/download-scylla.ccm @rm -rf /tmp/download-scylla.ccm download-ccm-cassandra-image: install-ccm-if-missing @echo "Downloading cassandra ${CASSANDRA_VERSION} CCM image" @rm -rf /tmp/download-cassandra.ccm || true @mkdir /tmp/download-cassandra.ccm || true - @ccm create ccm_1 -i 127.0.1. -n 3:0 -v "${CASSANDRA_VERSION}" --config-dir=/tmp/download-cassandra.ccm + @$(CCM_BIN) create ccm_1 -i 127.0.1. -n 3:0 -v "${CASSANDRA_VERSION}" --config-dir=/tmp/download-cassandra.ccm @rm -rf /tmp/download-cassandra.ccm run-test-integration-scylla: .prepare-environment-update-aio-max-nr From 656d2ad67a160987b980bbbf31869963569008e2 Mon Sep 17 00:00:00 2001 From: Dmitry Kropachev Date: Sun, 24 May 2026 10:44:01 -0400 Subject: [PATCH 12/32] ci: add local ccm shim --- Makefile | 6 +++--- ci/ccm | 4 ++++ 2 files changed, 7 insertions(+), 3 deletions(-) create mode 100755 ci/ccm diff --git a/Makefile b/Makefile index e74602307..684075ee3 100644 --- a/Makefile +++ b/Makefile @@ -8,9 +8,9 @@ ifeq ($(OS),Windows_NT) SHELL := pwsh.exe .SHELLFLAGS := -NoProfile -Command $$ErrorActionPreference = 'Stop'; else - # Keep pip-installed tools like `ccm` visible to make recipes. - export PATH := $(HOME)/.local/bin:$(PATH) - CCM_BIN := $(shell command -v ccm 2>/dev/null || printf '%s' "$(HOME)/.local/bin/ccm") + # Keep the in-repo CCM shim and pip-installed tools visible to make recipes. + export PATH := $(CURDIR)/ci:$(HOME)/.local/bin:$(PATH) + CCM_BIN := ccm endif UNAME_S := $(shell uname -s) diff --git a/ci/ccm b/ci/ccm new file mode 100755 index 000000000..edc92514f --- /dev/null +++ b/ci/ccm @@ -0,0 +1,4 @@ +#!/usr/bin/env bash +set -euo pipefail + +exec python3 -m ccmlib.bin "$@" From 476895e11a8159d613fe3ff04429a0f179356d3a Mon Sep 17 00:00:00 2001 From: Dmitry Kropachev Date: Sun, 24 May 2026 10:55:37 -0400 Subject: [PATCH 13/32] ci: install ccm with python3 pip --- Makefile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Makefile b/Makefile index 684075ee3..d8fd74f2b 100644 --- a/Makefile +++ b/Makefile @@ -248,11 +248,11 @@ install-clang-format-if-missing: update-apt-cache-if-needed install-ccm-if-missing: @$(CCM_BIN) list >/dev/null 2>&1 || ( echo "CCM not found in the system, install it." - pip3 install --user https://github.com/scylladb/scylla-ccm/archive/${CCM_COMMIT_ID}.zip + python3 -m pip install --user https://github.com/scylladb/scylla-ccm/archive/${CCM_COMMIT_ID}.zip ) install-ccm: - @pip3 install --user https://github.com/scylladb/scylla-ccm/archive/${CCM_COMMIT_ID}.zip + @python3 -m pip install --user https://github.com/scylladb/scylla-ccm/archive/${CCM_COMMIT_ID}.zip install-java8-if-missing: @dpkg -l openjdk-8-jre >/dev/null 2>&1 && exit 0 From 8370996bf483221344e6ab56a3640e4a30b25375 Mon Sep 17 00:00:00 2001 From: Dmitry Kropachev Date: Sun, 24 May 2026 11:08:10 -0400 Subject: [PATCH 14/32] ci: expose ccm user site in shim --- ci/ccm | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/ci/ccm b/ci/ccm index edc92514f..a06f6e9dc 100755 --- a/ci/ccm +++ b/ci/ccm @@ -1,4 +1,11 @@ #!/usr/bin/env bash set -euo pipefail +user_site="$(python3 -m site --user-site)" +if [ -n "${PYTHONPATH:-}" ]; then + export PYTHONPATH="${user_site}:${PYTHONPATH}" +else + export PYTHONPATH="${user_site}" +fi + exec python3 -m ccmlib.bin "$@" From e12fa38d7419553fc7e5e2ccb852829d1c7fde7b Mon Sep 17 00:00:00 2001 From: Dmitry Kropachev Date: Sun, 24 May 2026 11:20:57 -0400 Subject: [PATCH 15/32] ci: invoke installed ccm script from shim --- ci/ccm | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/ci/ccm b/ci/ccm index a06f6e9dc..59441d924 100755 --- a/ci/ccm +++ b/ci/ccm @@ -1,6 +1,11 @@ #!/usr/bin/env bash set -euo pipefail +user_ccm="$HOME/.local/bin/ccm" +if [ -x "$user_ccm" ]; then + exec "$user_ccm" "$@" +fi + user_site="$(python3 -m site --user-site)" if [ -n "${PYTHONPATH:-}" ]; then export PYTHONPATH="${user_site}:${PYTHONPATH}" @@ -8,4 +13,4 @@ else export PYTHONPATH="${user_site}" fi -exec python3 -m ccmlib.bin "$@" +exec python3 -c 'from ccmlib.bin import main; main()' "$@" From 8a93355fca91a77a0ae81ee9f445c2eb171d46c1 Mon Sep 17 00:00:00 2001 From: Dmitry Kropachev Date: Sun, 24 May 2026 11:32:16 -0400 Subject: [PATCH 16/32] ci: resolve ccm script from user base --- ci/ccm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ci/ccm b/ci/ccm index 59441d924..88c6b8e97 100755 --- a/ci/ccm +++ b/ci/ccm @@ -1,7 +1,7 @@ #!/usr/bin/env bash set -euo pipefail -user_ccm="$HOME/.local/bin/ccm" +user_ccm="$(python3 -m site --user-base)/bin/ccm" if [ -x "$user_ccm" ]; then exec "$user_ccm" "$@" fi From e15dd51c1923eb6d3f686743be48d179535f9860 Mon Sep 17 00:00:00 2001 From: Dmitry Kropachev Date: Sun, 24 May 2026 11:34:29 -0400 Subject: [PATCH 17/32] ci: prefer installed ccm on PATH --- Makefile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Makefile b/Makefile index d8fd74f2b..b1426bfab 100644 --- a/Makefile +++ b/Makefile @@ -8,8 +8,8 @@ ifeq ($(OS),Windows_NT) SHELL := pwsh.exe .SHELLFLAGS := -NoProfile -Command $$ErrorActionPreference = 'Stop'; else - # Keep the in-repo CCM shim and pip-installed tools visible to make recipes. - export PATH := $(CURDIR)/ci:$(HOME)/.local/bin:$(PATH) + # Keep the pip-installed CCM script visible to make recipes, with the in-repo shim as fallback. + export PATH := $(HOME)/.local/bin:$(CURDIR)/ci:$(PATH) CCM_BIN := ccm endif From 9b535474518d968efe5cae63561e208b499637ac Mon Sep 17 00:00:00 2001 From: Dmitry Kropachev Date: Sun, 24 May 2026 11:45:39 -0400 Subject: [PATCH 18/32] ci: run installed ccm script with python3 --- ci/ccm | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ci/ccm b/ci/ccm index 88c6b8e97..fe9709826 100755 --- a/ci/ccm +++ b/ci/ccm @@ -2,8 +2,8 @@ set -euo pipefail user_ccm="$(python3 -m site --user-base)/bin/ccm" -if [ -x "$user_ccm" ]; then - exec "$user_ccm" "$@" +if [ -f "$user_ccm" ]; then + exec python3 "$user_ccm" "$@" fi user_site="$(python3 -m site --user-site)" From 38ef04040f5f6957cb2a64dae41a18d2a3c24b0e Mon Sep 17 00:00:00 2001 From: Dmitry Kropachev Date: Sun, 24 May 2026 12:02:41 -0400 Subject: [PATCH 19/32] ci: resolve CCM from user bin --- Makefile | 4 ++-- tests/src/integration/ccm/bridge.cpp | 31 +++++++++++++++++++++++++++- 2 files changed, 32 insertions(+), 3 deletions(-) diff --git a/Makefile b/Makefile index b1426bfab..bf0885c87 100644 --- a/Makefile +++ b/Makefile @@ -8,9 +8,9 @@ ifeq ($(OS),Windows_NT) SHELL := pwsh.exe .SHELLFLAGS := -NoProfile -Command $$ErrorActionPreference = 'Stop'; else - # Keep the pip-installed CCM script visible to make recipes, with the in-repo shim as fallback. + # Prefer the pip-installed CCM script in the user bin directory. export PATH := $(HOME)/.local/bin:$(CURDIR)/ci:$(PATH) - CCM_BIN := ccm + CCM_BIN ?= $(HOME)/.local/bin/ccm endif UNAME_S := $(shell uname -s) diff --git a/tests/src/integration/ccm/bridge.cpp b/tests/src/integration/ccm/bridge.cpp index 037de3120..d499681b9 100644 --- a/tests/src/integration/ccm/bridge.cpp +++ b/tests/src/integration/ccm/bridge.cpp @@ -20,6 +20,7 @@ #define _CRTDBG_MAP_ALLOC #include #include +#include // Enable memory leak detection for new operator #ifdef _DEBUG @@ -47,6 +48,7 @@ #endif #endif +#include #include #include #include @@ -99,6 +101,33 @@ const std::vector CCM::Bridge::DEFAULT_DSE_WORKLOAD( using namespace CCM; +namespace { + +#ifdef _WIN32 +bool is_executable(const std::string& path) { return _access(path.c_str(), 0) == 0; } +#else +bool is_executable(const std::string& path) { return access(path.c_str(), X_OK) == 0; } +#endif + +std::string resolve_ccm_binary() { + const char* ccm_bin = std::getenv("CCM_BIN"); + if (ccm_bin != NULL && *ccm_bin != '\0') { + return std::string(ccm_bin); + } + + const char* home = std::getenv("HOME"); + if (home != NULL && *home != '\0') { + std::string user_ccm = std::string(home) + "/.local/bin/ccm"; + if (is_executable(user_ccm)) { + return user_ccm; + } + } + + return std::string("ccm"); +} + +} // namespace + CCM::Bridge::Bridge( CassVersion server_version /*= DEFAULT_CASSANDRA_VERSION*/, bool use_git /*= DEFAULT_USE_GIT*/, const std::string& branch_tag /* ""*/, bool use_install_dir /*=DEFAULT_USE_INSTALL_DIR*/, @@ -1368,7 +1397,7 @@ std::string CCM::Bridge::read_libssh2_terminal() { std::string CCM::Bridge::execute_ccm_command(const std::vector& command) { // Create the CCM command std::vector ccm_command; - ccm_command.push_back("ccm"); + ccm_command.push_back(resolve_ccm_binary()); ccm_command.insert(ccm_command.end(), command.begin(), command.end()); LOG(implode(ccm_command)); From 514e8c33873b30e640e970a3f9ec6a6da11cfa85 Mon Sep 17 00:00:00 2001 From: Dmitry Kropachev Date: Sun, 24 May 2026 12:13:27 -0400 Subject: [PATCH 20/32] ci: export CCM binary path --- Makefile | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/Makefile b/Makefile index bf0885c87..1017fa2c3 100644 --- a/Makefile +++ b/Makefile @@ -8,9 +8,10 @@ ifeq ($(OS),Windows_NT) SHELL := pwsh.exe .SHELLFLAGS := -NoProfile -Command $$ErrorActionPreference = 'Stop'; else - # Prefer the pip-installed CCM script in the user bin directory. + # Prefer the pip-installed CCM script resolved from Python's user base. export PATH := $(HOME)/.local/bin:$(CURDIR)/ci:$(PATH) - CCM_BIN ?= $(HOME)/.local/bin/ccm + CCM_BIN ?= $(shell python3 -m site --user-base)/bin/ccm + export CCM_BIN endif UNAME_S := $(shell uname -s) From d4463954d00ac8039f01daaae19af5788561e4b9 Mon Sep 17 00:00:00 2001 From: Dmitry Kropachev Date: Sun, 24 May 2026 12:25:56 -0400 Subject: [PATCH 21/32] ci: install CCM from git source --- Makefile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Makefile b/Makefile index 1017fa2c3..5034070d8 100644 --- a/Makefile +++ b/Makefile @@ -249,11 +249,11 @@ install-clang-format-if-missing: update-apt-cache-if-needed install-ccm-if-missing: @$(CCM_BIN) list >/dev/null 2>&1 || ( echo "CCM not found in the system, install it." - python3 -m pip install --user https://github.com/scylladb/scylla-ccm/archive/${CCM_COMMIT_ID}.zip + python3 -m pip install --user git+https://github.com/scylladb/scylla-ccm.git@${CCM_COMMIT_ID} ) install-ccm: - @python3 -m pip install --user https://github.com/scylladb/scylla-ccm/archive/${CCM_COMMIT_ID}.zip + @python3 -m pip install --user git+https://github.com/scylladb/scylla-ccm.git@${CCM_COMMIT_ID} install-java8-if-missing: @dpkg -l openjdk-8-jre >/dev/null 2>&1 && exit 0 From 48a134fdef05684e39890dc0c3c3509fda0a976e Mon Sep 17 00:00:00 2001 From: Dmitry Kropachev Date: Sun, 24 May 2026 12:37:16 -0400 Subject: [PATCH 22/32] ci: use repo-local CCM shim --- Makefile | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/Makefile b/Makefile index 5034070d8..f7f20de05 100644 --- a/Makefile +++ b/Makefile @@ -8,9 +8,10 @@ ifeq ($(OS),Windows_NT) SHELL := pwsh.exe .SHELLFLAGS := -NoProfile -Command $$ErrorActionPreference = 'Stop'; else - # Prefer the pip-installed CCM script resolved from Python's user base. + # Prefer the repo-local CCM shim, which can fall back to the pip-installed + # package from Python's user base when the console script is unavailable. export PATH := $(HOME)/.local/bin:$(CURDIR)/ci:$(PATH) - CCM_BIN ?= $(shell python3 -m site --user-base)/bin/ccm + CCM_BIN ?= $(CURDIR)/ci/ccm export CCM_BIN endif From 914b64caec4d3f209f986daa45132cb9dcd9cf95 Mon Sep 17 00:00:00 2001 From: Dmitry Kropachev Date: Sun, 24 May 2026 12:50:20 -0400 Subject: [PATCH 23/32] ci: install CCM from local checkout --- Makefile | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/Makefile b/Makefile index f7f20de05..93ad42a6a 100644 --- a/Makefile +++ b/Makefile @@ -250,11 +250,17 @@ install-clang-format-if-missing: update-apt-cache-if-needed install-ccm-if-missing: @$(CCM_BIN) list >/dev/null 2>&1 || ( echo "CCM not found in the system, install it." - python3 -m pip install --user git+https://github.com/scylladb/scylla-ccm.git@${CCM_COMMIT_ID} + tmp_ccm_dir=$$(mktemp -d) && \ + trap 'rm -rf "$$tmp_ccm_dir"' EXIT && \ + git clone --depth 1 --branch "${CCM_COMMIT_ID}" https://github.com/scylladb/scylla-ccm.git "$$tmp_ccm_dir" && \ + python3 -m pip install --user "$$tmp_ccm_dir" ) install-ccm: - @python3 -m pip install --user git+https://github.com/scylladb/scylla-ccm.git@${CCM_COMMIT_ID} + @tmp_ccm_dir=$$(mktemp -d) && \ + trap 'rm -rf "$$tmp_ccm_dir"' EXIT && \ + git clone --depth 1 --branch "${CCM_COMMIT_ID}" https://github.com/scylladb/scylla-ccm.git "$$tmp_ccm_dir" && \ + python3 -m pip install --user "$$tmp_ccm_dir" install-java8-if-missing: @dpkg -l openjdk-8-jre >/dev/null 2>&1 && exit 0 From 922bbe079b8f695527eb9a1f63c14b71115e8d95 Mon Sep 17 00:00:00 2001 From: Dmitry Kropachev Date: Sun, 24 May 2026 13:03:33 -0400 Subject: [PATCH 24/32] ci: run CCM from cloned source tree --- Makefile | 26 ++++++++++++++++---------- ci/ccm | 6 ++++++ 2 files changed, 22 insertions(+), 10 deletions(-) diff --git a/Makefile b/Makefile index 93ad42a6a..44d6b8d90 100644 --- a/Makefile +++ b/Makefile @@ -8,9 +8,11 @@ ifeq ($(OS),Windows_NT) SHELL := pwsh.exe .SHELLFLAGS := -NoProfile -Command $$ErrorActionPreference = 'Stop'; else - # Prefer the repo-local CCM shim, which can fall back to the pip-installed - # package from Python's user base when the console script is unavailable. + # Prefer the repo-local CCM shim, which can execute the cloned upstream tree + # and still fall back to a user-installed console script when present. export PATH := $(HOME)/.local/bin:$(CURDIR)/ci:$(PATH) + CCM_SOURCE_DIR ?= $(HOME)/.ccm/scylla-ccm + export CCM_SOURCE_DIR CCM_BIN ?= $(CURDIR)/ci/ccm export CCM_BIN endif @@ -182,6 +184,10 @@ ifndef CCM_COMMIT_ID export CCM_COMMIT_ID := master endif +ifndef CCM_PIP_DEPENDENCIES + CCM_PIP_DEPENDENCIES := ruamel-yaml psutil requests packaging boto3 tqdm urllib3 +endif + ifndef SCYLLA_VERSION SCYLLA_VERSION := release:2025.3 endif @@ -250,17 +256,17 @@ install-clang-format-if-missing: update-apt-cache-if-needed install-ccm-if-missing: @$(CCM_BIN) list >/dev/null 2>&1 || ( echo "CCM not found in the system, install it." - tmp_ccm_dir=$$(mktemp -d) && \ - trap 'rm -rf "$$tmp_ccm_dir"' EXIT && \ - git clone --depth 1 --branch "${CCM_COMMIT_ID}" https://github.com/scylladb/scylla-ccm.git "$$tmp_ccm_dir" && \ - python3 -m pip install --user "$$tmp_ccm_dir" + mkdir -p "$(dir $(CCM_SOURCE_DIR))" && \ + rm -rf "$(CCM_SOURCE_DIR)" && \ + git clone --depth 1 --branch "${CCM_COMMIT_ID}" https://github.com/scylladb/scylla-ccm.git "$(CCM_SOURCE_DIR)" && \ + python3 -m pip install --user ${CCM_PIP_DEPENDENCIES} ) install-ccm: - @tmp_ccm_dir=$$(mktemp -d) && \ - trap 'rm -rf "$$tmp_ccm_dir"' EXIT && \ - git clone --depth 1 --branch "${CCM_COMMIT_ID}" https://github.com/scylladb/scylla-ccm.git "$$tmp_ccm_dir" && \ - python3 -m pip install --user "$$tmp_ccm_dir" + @mkdir -p "$(dir $(CCM_SOURCE_DIR))" && \ + rm -rf "$(CCM_SOURCE_DIR)" && \ + git clone --depth 1 --branch "${CCM_COMMIT_ID}" https://github.com/scylladb/scylla-ccm.git "$(CCM_SOURCE_DIR)" && \ + python3 -m pip install --user ${CCM_PIP_DEPENDENCIES} install-java8-if-missing: @dpkg -l openjdk-8-jre >/dev/null 2>&1 && exit 0 diff --git a/ci/ccm b/ci/ccm index fe9709826..fbc66218b 100755 --- a/ci/ccm +++ b/ci/ccm @@ -1,6 +1,12 @@ #!/usr/bin/env bash set -euo pipefail +source_ccm="${CCM_SOURCE_DIR:-$HOME/.ccm/scylla-ccm}" +if [ -n "$source_ccm" ] && [ -f "$source_ccm/ccm" ]; then + export PYTHONPATH="$source_ccm${PYTHONPATH:+:$PYTHONPATH}" + exec python3 "$source_ccm/ccm" "$@" +fi + user_ccm="$(python3 -m site --user-base)/bin/ccm" if [ -f "$user_ccm" ]; then exec python3 "$user_ccm" "$@" From 9e09036f3a22f159138e1df02630c71ae627ad42 Mon Sep 17 00:00:00 2001 From: Dmitry Kropachev Date: Sun, 24 May 2026 13:36:58 -0400 Subject: [PATCH 25/32] ci: bump scylla driver and fix timeout test --- scylla-rust-wrapper/Cargo.lock | 24 +++++++++---------- scylla-rust-wrapper/Cargo.toml | 6 ++--- .../integration/tests/test_exec_profile.cpp | 5 ++-- 3 files changed, 18 insertions(+), 17 deletions(-) diff --git a/scylla-rust-wrapper/Cargo.lock b/scylla-rust-wrapper/Cargo.lock index 96d976693..b6b18ad7e 100644 --- a/scylla-rust-wrapper/Cargo.lock +++ b/scylla-rust-wrapper/Cargo.lock @@ -259,7 +259,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "39cab71617ae0d63f51a36d69f866391735b51691dbda63cf6f96d042b63efeb" dependencies = [ "libc", - "windows-sys 0.61.2", + "windows-sys 0.59.0", ] [[package]] @@ -726,7 +726,7 @@ version = "0.50.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7957b9740744892f114936ab4a57b3f487491bbeafaf8083688b16841a4240e5" dependencies = [ - "windows-sys 0.61.2", + "windows-sys 0.59.0", ] [[package]] @@ -1057,7 +1057,7 @@ dependencies = [ "errno", "libc", "linux-raw-sys 0.12.1", - "windows-sys 0.61.2", + "windows-sys 0.59.0", ] [[package]] @@ -1086,8 +1086,8 @@ checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" [[package]] name = "scylla" -version = "1.5.0" -source = "git+https://github.com/scylladb/scylla-rust-driver.git?rev=v1.5.0#d1a5c373a5fbab95f84635c25c5174480b7d6491" +version = "1.6.0" +source = "git+https://github.com/scylladb/scylla-rust-driver.git?rev=v1.6.0#33517599c1d4fcee899fe4fd40b1bfbd6bcb730e" dependencies = [ "arc-swap", "async-trait", @@ -1113,8 +1113,8 @@ dependencies = [ [[package]] name = "scylla-cql" -version = "1.5.0" -source = "git+https://github.com/scylladb/scylla-rust-driver.git?rev=v1.5.0#d1a5c373a5fbab95f84635c25c5174480b7d6491" +version = "1.6.0" +source = "git+https://github.com/scylladb/scylla-rust-driver.git?rev=v1.6.0#33517599c1d4fcee899fe4fd40b1bfbd6bcb730e" dependencies = [ "byteorder", "bytes", @@ -1132,8 +1132,8 @@ dependencies = [ [[package]] name = "scylla-macros" -version = "1.5.0" -source = "git+https://github.com/scylladb/scylla-rust-driver.git?rev=v1.5.0#d1a5c373a5fbab95f84635c25c5174480b7d6491" +version = "1.6.0" +source = "git+https://github.com/scylladb/scylla-rust-driver.git?rev=v1.6.0#33517599c1d4fcee899fe4fd40b1bfbd6bcb730e" dependencies = [ "darling", "proc-macro2", @@ -1143,8 +1143,8 @@ dependencies = [ [[package]] name = "scylla-proxy" -version = "0.0.5" -source = "git+https://github.com/scylladb/scylla-rust-driver.git?rev=v1.5.0#d1a5c373a5fbab95f84635c25c5174480b7d6491" +version = "0.0.6" +source = "git+https://github.com/scylladb/scylla-rust-driver.git?rev=v1.6.0#33517599c1d4fcee899fe4fd40b1bfbd6bcb730e" dependencies = [ "bigdecimal", "byteorder", @@ -1356,7 +1356,7 @@ dependencies = [ "getrandom 0.4.1", "once_cell", "rustix 1.1.4", - "windows-sys 0.61.2", + "windows-sys 0.59.0", ] [[package]] diff --git a/scylla-rust-wrapper/Cargo.toml b/scylla-rust-wrapper/Cargo.toml index 988f64f2c..bd251c79e 100644 --- a/scylla-rust-wrapper/Cargo.toml +++ b/scylla-rust-wrapper/Cargo.toml @@ -11,7 +11,7 @@ license = "MIT OR Apache-2.0" rust-version = "1.88" [dependencies] -scylla = { git = "https://github.com/scylladb/scylla-rust-driver.git", rev = "v1.5.0", features = [ +scylla = { git = "https://github.com/scylladb/scylla-rust-driver.git", rev = "v1.6.0", features = [ "openssl-010", "metrics", "unstable-cpp-rs", @@ -38,8 +38,8 @@ bindgen = "0.65" chrono = "0.4.20" [dev-dependencies] -scylla-proxy = { git = "https://github.com/scylladb/scylla-rust-driver.git", rev = "v1.5.0" } -scylla-cql = { git = "https://github.com/scylladb/scylla-rust-driver.git", rev = "v1.5.0" } +scylla-proxy = { git = "https://github.com/scylladb/scylla-rust-driver.git", rev = "v1.6.0" } +scylla-cql = { git = "https://github.com/scylladb/scylla-rust-driver.git", rev = "v1.6.0" } bytes = "1.10.0" itertools = "0.10.3" assert_matches = "1.5.0" diff --git a/tests/src/integration/tests/test_exec_profile.cpp b/tests/src/integration/tests/test_exec_profile.cpp index 7967fb774..4dc75dc01 100644 --- a/tests/src/integration/tests/test_exec_profile.cpp +++ b/tests/src/integration/tests/test_exec_profile.cpp @@ -267,9 +267,10 @@ CASSANDRA_INTEGRATION_TEST_F(ExecutionProfileTest, RequestTimeout) { ASSERT_EQ(CASS_OK, result.error_code()); // Execute a batched query with assigned profile (should timeout) - // NOTE: Selects are not allowed in batches but is OK for this test case + // Use a valid batch statement so the timeout path is exercised consistently + // across server versions. Batch batch; - batch.add(statement); + batch.add(insert_); batch.set_execution_profile("request_timeout"); batch.set_sleep_time(10); // Simulate >=10ms latency (well above 1ms timeout) result = session_.execute(batch, false); From 0b3cb133c19fa25959b43fb702e2ec786cd258a9 Mon Sep 17 00:00:00 2001 From: Dmitry Kropachev Date: Sun, 24 May 2026 13:51:53 -0400 Subject: [PATCH 26/32] packaging: raise smoke test connect timeout --- packaging/smoke-test-app/src/smoke_test.c | 1 + 1 file changed, 1 insertion(+) diff --git a/packaging/smoke-test-app/src/smoke_test.c b/packaging/smoke-test-app/src/smoke_test.c index b3bc8fdc3..4e7d02414 100644 --- a/packaging/smoke-test-app/src/smoke_test.c +++ b/packaging/smoke-test-app/src/smoke_test.c @@ -29,6 +29,7 @@ int main(int argc, char* argv[]) { smoke_status_t result = SMOKE_ERR; cass_cluster_set_contact_points(cluster, contact_point); + cass_cluster_set_connect_timeout(cluster, 30000); connect_future = cass_session_connect(session, cluster); if (cass_future_error_code(connect_future) != CASS_OK) { From 1e4f2fcf81b0607d068ec487c8715dda74fc3302 Mon Sep 17 00:00:00 2001 From: Dmitry Kropachev Date: Sun, 24 May 2026 14:08:04 -0400 Subject: [PATCH 27/32] packaging: extend smoke test connect timeout --- packaging/smoke-test-app/src/smoke_test.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packaging/smoke-test-app/src/smoke_test.c b/packaging/smoke-test-app/src/smoke_test.c index 4e7d02414..902d5cad8 100644 --- a/packaging/smoke-test-app/src/smoke_test.c +++ b/packaging/smoke-test-app/src/smoke_test.c @@ -29,7 +29,7 @@ int main(int argc, char* argv[]) { smoke_status_t result = SMOKE_ERR; cass_cluster_set_contact_points(cluster, contact_point); - cass_cluster_set_connect_timeout(cluster, 30000); + cass_cluster_set_connect_timeout(cluster, 60000); connect_future = cass_session_connect(session, cluster); if (cass_future_error_code(connect_future) != CASS_OK) { From 6a1175310cfe027c7a3ba071aec75f3d3694abff Mon Sep 17 00:00:00 2001 From: Dmitry Kropachev Date: Sun, 24 May 2026 14:23:27 -0400 Subject: [PATCH 28/32] packaging: extend smoke test timeout further --- packaging/smoke-test-app/src/smoke_test.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packaging/smoke-test-app/src/smoke_test.c b/packaging/smoke-test-app/src/smoke_test.c index 902d5cad8..ea346190f 100644 --- a/packaging/smoke-test-app/src/smoke_test.c +++ b/packaging/smoke-test-app/src/smoke_test.c @@ -29,7 +29,7 @@ int main(int argc, char* argv[]) { smoke_status_t result = SMOKE_ERR; cass_cluster_set_contact_points(cluster, contact_point); - cass_cluster_set_connect_timeout(cluster, 60000); + cass_cluster_set_connect_timeout(cluster, 120000); connect_future = cass_session_connect(session, cluster); if (cass_future_error_code(connect_future) != CASS_OK) { From e7da74d59f503f8ee43d4f3ce372a1e284eeab14 Mon Sep 17 00:00:00 2001 From: Dmitry Kropachev Date: Sun, 24 May 2026 14:42:07 -0400 Subject: [PATCH 29/32] packaging: advertise localhost in smoke test compose --- packaging/smoke-test-app/docker-compose.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packaging/smoke-test-app/docker-compose.yml b/packaging/smoke-test-app/docker-compose.yml index 34a036302..123753b48 100644 --- a/packaging/smoke-test-app/docker-compose.yml +++ b/packaging/smoke-test-app/docker-compose.yml @@ -15,7 +15,7 @@ services: public: ipv4_address: 172.44.0.2 command: | - --rpc-address 172.44.0.2 + --rpc-address 127.0.0.1 --listen-address 172.44.0.2 --skip-wait-for-gossip-to-settle 0 --ring-delay-ms 0 From 49ebbb126ec5c3a61032f3723a9a01b715b6d69c Mon Sep 17 00:00:00 2001 From: Dmitry Kropachev Date: Sun, 24 May 2026 14:53:53 -0400 Subject: [PATCH 30/32] packaging: broadcast localhost in smoke test compose --- packaging/smoke-test-app/docker-compose.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/packaging/smoke-test-app/docker-compose.yml b/packaging/smoke-test-app/docker-compose.yml index 123753b48..036659886 100644 --- a/packaging/smoke-test-app/docker-compose.yml +++ b/packaging/smoke-test-app/docker-compose.yml @@ -15,7 +15,8 @@ services: public: ipv4_address: 172.44.0.2 command: | - --rpc-address 127.0.0.1 + --rpc-address 172.44.0.2 + --broadcast-rpc-address 127.0.0.1 --listen-address 172.44.0.2 --skip-wait-for-gossip-to-settle 0 --ring-delay-ms 0 From d7e9b646809c47ee6ec6bd9f2ffd73649035d3cd Mon Sep 17 00:00:00 2001 From: Dmitry Kropachev Date: Sun, 24 May 2026 15:00:25 -0400 Subject: [PATCH 31/32] packaging: drop smoke-test compose healthcheck --- packaging/smoke-test-app/docker-compose.yml | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/packaging/smoke-test-app/docker-compose.yml b/packaging/smoke-test-app/docker-compose.yml index 036659886..14555cacb 100644 --- a/packaging/smoke-test-app/docker-compose.yml +++ b/packaging/smoke-test-app/docker-compose.yml @@ -22,15 +22,3 @@ services: --ring-delay-ms 0 --smp 2 --memory 1G - healthcheck: - test: - [ - "CMD", - "cqlsh", - "scylla", - "-e", - "select * from system.local WHERE key='local'", - ] - interval: 5s - timeout: 5s - retries: 60 From b4f0cf49b18cf6085210d224097de1e452547f1a Mon Sep 17 00:00:00 2001 From: Dmitry Kropachev Date: Sun, 24 May 2026 15:14:52 -0400 Subject: [PATCH 32/32] packaging: bind smoke test scylla on all interfaces --- packaging/smoke-test-app/docker-compose.yml | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/packaging/smoke-test-app/docker-compose.yml b/packaging/smoke-test-app/docker-compose.yml index 14555cacb..1e353a5ce 100644 --- a/packaging/smoke-test-app/docker-compose.yml +++ b/packaging/smoke-test-app/docker-compose.yml @@ -15,10 +15,22 @@ services: public: ipv4_address: 172.44.0.2 command: | - --rpc-address 172.44.0.2 + --rpc-address 0.0.0.0 --broadcast-rpc-address 127.0.0.1 - --listen-address 172.44.0.2 + --listen-address 0.0.0.0 --skip-wait-for-gossip-to-settle 0 --ring-delay-ms 0 --smp 2 --memory 1G + healthcheck: + test: + [ + "CMD", + "cqlsh", + "scylla", + "-e", + "select * from system.local WHERE key='local'", + ] + interval: 5s + timeout: 5s + retries: 60