summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPavel <[email protected]>2025-06-24 13:29:25 +0300
committerGitHub <[email protected]>2025-06-24 13:29:25 +0300
commit4541608b62176767f43fb9aabdc8cb5095af6283 (patch)
tree89a87f37e573fa98c4ac1ba5109f73c222bd4136
parent3a99069cf3656d577efeeeb64a831926bf670080 (diff)
Custom compatibility tags (#19415) (#19610)
-rw-r--r--.github/workflows/regression_run_compatibility.yml28
-rw-r--r--ydb/tests/compatibility/README.md38
-rw-r--r--ydb/tests/compatibility/ya.make3
-rw-r--r--ydb/tests/library/compatibility/binaries/downloader/__main__.py38
-rw-r--r--ydb/tests/library/compatibility/binaries/ya.make34
-rw-r--r--ydb/tests/library/compatibility/fixtures.py92
6 files changed, 145 insertions, 88 deletions
diff --git a/.github/workflows/regression_run_compatibility.yml b/.github/workflows/regression_run_compatibility.yml
index 12eca6795f6..5134c969c71 100644
--- a/.github/workflows/regression_run_compatibility.yml
+++ b/.github/workflows/regression_run_compatibility.yml
@@ -1,16 +1,27 @@
name: Regression-run_compatibility
+run-name: >-
+ ${{
+ inputs.initial_version_ref != '' && inputs.initial_version_ref || 'default-init'}} -> ${{
+ inputs.inter_version_ref != '' && inputs.inter_version_ref || 'default-inter'}} -> ${{
+ inputs.target_version_ref != '' && inputs.target_version_ref || 'default-target'}}
on:
schedule:
- cron: "0 23 * * *" # At 23:00 every day
workflow_dispatch:
inputs:
- use_default_branches:
- description: 'If true, start main and all current stable branches. If false, start only the selected branch.'
- type: boolean
+ initial_version_ref:
+ description: Initial(oldest) version (ex. stable-24-4, should exist on S3)
+ type: string
+ required: false
+ inter_version_ref:
+ description: Intermediate version (ex. stable-25-1-2/25.1.1.18, should exist on S3)
+ type: string
+ required: false
+ target_version_ref:
+ description: Target(newest) version ("current" - compiles binary from the chosen branch)
+ type: string
required: false
- default: true
-
jobs:
main:
name: Regression-run_compatibility
@@ -22,5 +33,10 @@ jobs:
build_preset: ["relwithdebinfo", "release-asan", "release-tsan", "release-msan"]
with:
test_targets: ydb/tests/compatibility/
- branches: ${{ (inputs.use_default_branches == true || github.event_name == 'schedule') && '["main", "stable-25-1", "stable-25-1-analytics"]' || github.ref_name }}
+ branches: ${{ github.ref_name }}
build_preset: ${{ matrix.build_preset }}
+ additional_ya_make_args: >-
+ ${{
+ inputs.initial_version_ref != '' && format(' -DYDB_COMPAT_INIT_REF={0} ', inputs.initial_version_ref) || ''}}${{
+ inputs.inter_version_ref != '' && format(' -DYDB_COMPAT_INTER_REF={0} ', inputs.inter_version_ref) || ''}}${{
+ inputs.target_version_ref != '' && format(' -DYDB_COMPAT_TARGET_REF={0}', inputs.target_version_ref) || ''}}
diff --git a/ydb/tests/compatibility/README.md b/ydb/tests/compatibility/README.md
index cdae5d76fdf..d92fa615724 100644
--- a/ydb/tests/compatibility/README.md
+++ b/ydb/tests/compatibility/README.md
@@ -4,7 +4,7 @@
## Механика работы тестов
-Тестовая обвязка скачивает YDB последней стабильной версии. После этого тестам доступны два бинарных файла: текущий (собранный из текущего среза исходников) и предыдущий. Таким образом, в этих тестах можно использовать тестовый кластер не только с одной версией YDB, но и с двумя. Текущая версия условно называется **current**, а предыдущая — **last**.
+Тестовая обвязка скачивает YDB последней стабильной версии. После этого тестам доступны два бинарных файла: текущий (собранный из текущего среза исходников) и предыдущий. Таким образом, в этих тестах можно использовать тестовый кластер не только с одной версией YDB, но и с двумя. Текущая версия условно называется **current/target**, а предыдущая — **initial**.
## Как написать тест
@@ -20,14 +20,14 @@
### MixedClusterFixture
-Фикстура поднимает кластер, который состоит из нод версий current и last. Позволяет протестировать работу в режиме, когда часть нод у нас уже обновилась, а часть еще нет.
+Фикстура поднимает кластер, который состоит из нод версий current и init. Позволяет протестировать работу в режиме, когда часть нод у нас уже обновилась, а часть еще нет.
Имеет параметризацию (то есть каждый написанный такой тест превращается в несколько):
-- поднимается смешанный кластер last+current
-- поднимается кластер исключительно на версии last
+- поднимается смешанный кластер init+current
+- поднимается кластер исключительно на версии init
- поднимается кластер исключительно на версии current
-Последние два нужны, чтобы отвечать на вопрос "а работает ли такой сценарий в принципе, когда кластер состоит из нод одной версии". Если получается так, что тест last+current не проходит, а в отсутствие разных версий тест завершается успешно, то это сильный сигнал к тому, что где-то поломана совместимость.
+Последние два нужны, чтобы отвечать на вопрос "а работает ли такой сценарий в принципе, когда кластер состоит из нод одной версии". Если получается так, что тест init+current не проходит, а в отсутствие разных версий тест завершается успешно, то это сильный сигнал к тому, что где-то поломана совместимость.
#### Для чего использовать
@@ -35,11 +35,11 @@
### RestartToAnotherVersionFixture
-Фикстура сначала поднимает кластер в одной комбинации (например, все ноды last), а потом позволяет остановить кластер и поднять кластер с другими версиями (например, все ноды current).
+Фикстура сначала поднимает кластер в одной комбинации (например, все ноды init), а потом позволяет остановить кластер и поднять кластер с другими версиями (например, все ноды current).
Имеет параметризацию (то есть каждый написанный такой тест превращается в несколько):
-- обновление last → current
-- обновление current → last
+- обновление init → current
+- обновление current → init
- обновление current → current
Список не исчерпывающий, полный можно посмотреть в коде фикстуры.
@@ -52,9 +52,9 @@
### RollingUpgradeAndDowngradeFixture
-Фикстура позволяет протестировать сценарий роллинг-апгрейда и даунгрейда. Реализует сценарий "имеется кластер last версии, он понодно заменяется на current версию, потом обратно на last".
+Фикстура позволяет протестировать сценарий роллинг-апгрейда и даунгрейда. Реализует сценарий "имеется кластер init версии, он понодно заменяется на current версию, потом обратно на init".
-Сама фикстура сначала поднимает кластер версии last, потом заменяет ноды на версию current, а потом обратно понодно заменяет на last, эмулируя откат.
+Сама фикстура сначала поднимает кластер версии init, потом заменяет ноды на версию current, а потом обратно понодно заменяет на init, эмулируя откат.
Шаг апгрейда/даунгрейда (замена версии ноды на другую) вызывается из теста следующим образом:
@@ -65,20 +65,20 @@ for _ in self.roll():
На каждой итерации цикла тестовое окружение заменяет одну ноду на другую версию.
-Схематично можно изобразить следующим образом (L — last, C — current, каждый столбец — это версия ноды кластера, каждая строка — текущее состояние кластера в теле цикла):
+Схематично можно изобразить следующим образом (I — init, C — current, каждый столбец — это версия ноды кластера, каждая строка — текущее состояние кластера в теле цикла):
```
-LLLLLLLLL
-CLLLLLLLL
-CCLLLLLLL
+IIIIIIIII
+CIIIIIIII
+CCIIIIIII
...
-CCCCCCCCL
+CCCCCCCCI
CCCCCCCCC
-LCCCCCCCC
-LLCCCCCCC
+ICCCCCCCC
+IICCCCCCC
...
-LLLLLLLLC
-LLLLLLLLL
+IIIIIIIIC
+IIIIIIIII
```
#### Для чего использовать
diff --git a/ydb/tests/compatibility/ya.make b/ydb/tests/compatibility/ya.make
index 537e2359c96..1f3a7ab7db7 100644
--- a/ydb/tests/compatibility/ya.make
+++ b/ydb/tests/compatibility/ya.make
@@ -29,9 +29,10 @@ REQUIREMENTS(ram:all)
INCLUDE(${ARCADIA_ROOT}/ydb/tests/large.inc)
INCLUDE(${ARCADIA_ROOT}/ydb/tests/tools/s3_recipe/recipe.inc)
+
DEPENDS(
- ydb/apps/ydb
ydb/tests/library/compatibility/binaries
+ ydb/apps/ydb
)
PEERDIR(
diff --git a/ydb/tests/library/compatibility/binaries/downloader/__main__.py b/ydb/tests/library/compatibility/binaries/downloader/__main__.py
index f1df08a3217..f5b893b4043 100644
--- a/ydb/tests/library/compatibility/binaries/downloader/__main__.py
+++ b/ydb/tests/library/compatibility/binaries/downloader/__main__.py
@@ -11,24 +11,30 @@ AWS_BUCKET = "ydb-builds"
def main():
- s3_client = boto3.client(
- service_name="s3",
- endpoint_url=AWS_ENDPOINT,
- config=Config(signature_version=UNSIGNED)
- )
+ mode = sys.argv[1]
+ if mode == 'download':
+ s3_client = boto3.client(
+ service_name="s3",
+ endpoint_url=AWS_ENDPOINT,
+ config=Config(signature_version=UNSIGNED)
+ )
+ s3_bucket = AWS_BUCKET
+ remote_src = sys.argv[2]
+ local_dst = sys.argv[3]
+ binary_name = sys.argv[4]
+ s3_client.download_file(s3_bucket, remote_src, local_dst)
- s3_bucket = AWS_BUCKET
- remote_src = sys.argv[1]
- local_dst = sys.argv[2]
- binary_name = sys.argv[3]
- s3_client.download_file(s3_bucket, remote_src, local_dst)
+ # chmod +x
+ st = os.stat(local_dst)
+ os.chmod(local_dst, st.st_mode | stat.S_IEXEC)
- # chmod +x
- st = os.stat(local_dst)
- os.chmod(local_dst, st.st_mode | stat.S_IEXEC)
-
- with open(local_dst + "-name", "w") as f:
- f.write(binary_name)
+ with open(local_dst + "-name", "w") as f:
+ f.write(binary_name)
+ elif mode == 'append-version':
+ local_dst = sys.argv[2]
+ binary_name = sys.argv[3]
+ with open(local_dst, "w") as f:
+ f.write(binary_name)
if __name__ == "__main__":
diff --git a/ydb/tests/library/compatibility/binaries/ya.make b/ydb/tests/library/compatibility/binaries/ya.make
index 2d4e6c96eb1..4d64a24111c 100644
--- a/ydb/tests/library/compatibility/binaries/ya.make
+++ b/ydb/tests/library/compatibility/binaries/ya.make
@@ -2,14 +2,40 @@ RECURSE(downloader)
UNION()
+IF(NOT ${YDB_COMPAT_INIT_REF})
+ SET(YDB_COMPAT_INIT_REF stable-24-4)
+ENDIF()
+IF(NOT ${YDB_COMPAT_INTER_REF})
+ SET(YDB_COMPAT_INTER_REF stable-25-1-2)
+ENDIF()
+IF(NOT ${YDB_COMPAT_TARGET_REF})
+ SET(YDB_COMPAT_TARGET_REF current)
+ENDIF()
+
RUN_PROGRAM(
- ydb/tests/library/compatibility/binaries/downloader stable-25-1/release/ydbd ydbd-last-stable 25-1
- OUT_NOAUTO ydbd-last-stable ydbd-last-stable-name
+ ydb/tests/library/compatibility/binaries/downloader download $YDB_COMPAT_INTER_REF/release/ydbd ydbd-inter $YDB_COMPAT_INTER_REF
+ OUT_NOAUTO ydbd-inter ydbd-inter-name
)
RUN_PROGRAM(
- ydb/tests/library/compatibility/binaries/downloader stable-24-4/release/ydbd ydbd-prelast-stable 24-4
- OUT_NOAUTO ydbd-prelast-stable ydbd-prelast-stable-name
+ ydb/tests/library/compatibility/binaries/downloader download $YDB_COMPAT_INIT_REF/release/ydbd ydbd-init $YDB_COMPAT_INIT_REF
+ OUT_NOAUTO ydbd-init ydbd-init-name
)
+IF(${YDB_COMPAT_TARGET_REF} != "current")
+ RUN_PROGRAM(
+ ydb/tests/library/compatibility/binaries/downloader download $YDB_COMPAT_TARGET_REF/release/ydbd ydbd-target $YDB_COMPAT_TARGET_REF
+ OUT_NOAUTO ydbd-target ydbd-target-name
+ )
+ELSE()
+ INCLUDE(${ARCADIA_ROOT}/ydb/tests/ydbd_dep.inc)
+ BUNDLE(
+ ydb/apps/ydbd NAME ydbd-target
+ )
+ RUN_PROGRAM(
+ ydb/tests/library/compatibility/binaries/downloader append-version ydbd-target-name current
+ OUT_NOAUTO ydbd-target-name
+ )
+ENDIF()
+
END()
diff --git a/ydb/tests/library/compatibility/fixtures.py b/ydb/tests/library/compatibility/fixtures.py
index 0f2d9698f6e..dc15570d7c5 100644
--- a/ydb/tests/library/compatibility/fixtures.py
+++ b/ydb/tests/library/compatibility/fixtures.py
@@ -5,23 +5,17 @@ import yatest
import time
from ydb.tests.library.harness.kikimr_runner import KiKiMR
from ydb.tests.library.harness.kikimr_config import KikimrConfigGenerator
-from ydb.tests.library.harness.param_constants import kikimr_driver_path
from ydb.tests.library.common.types import Erasure
from ydb.tests.oss.ydb_sdk_import import ydb
-current_binary_path = kikimr_driver_path()
-last_stable_binary_path = yatest.common.binary_path("ydb/tests/library/compatibility/binaries/ydbd-last-stable")
-prelast_stable_binary_path = yatest.common.binary_path("ydb/tests/library/compatibility/binaries/ydbd-prelast-stable")
-
-current_binary_version = (float("+inf"), )
-last_stable_version = None
-prelast_stable_version = None
-
-
def string_version_to_tuple(s):
result = []
- for elem in s.split("-"):
+ s = s.replace('.', '-')
+ for idx, elem in enumerate(s.split("-")):
+ # skipping 'stable' in stable-25-1-1 version
+ if idx == 0 and elem == 'stable':
+ continue
try:
result.append(int(elem))
except ValueError:
@@ -29,39 +23,53 @@ def string_version_to_tuple(s):
return tuple(result)
-current_name = "current"
-last_stable_name = "last"
-if last_stable_binary_path is not None: # in import_test yatest.common.binary_path returns None
- last_stable_name = open(yatest.common.binary_path("ydb/tests/library/compatibility/binaries/ydbd-last-stable-name")).read().strip()
- last_stable_version = string_version_to_tuple(last_stable_name)
-prelast_stable_name = "prelast"
-if prelast_stable_binary_path: # in import_test yatest.common.binary_path returns None
- prelast_stable_name = open(yatest.common.binary_path("ydb/tests/library/compatibility/binaries/ydbd-prelast-stable-name")).read().strip()
- prelast_stable_version = string_version_to_tuple(prelast_stable_name)
+current_binary_path = yatest.common.binary_path("ydb/tests/library/compatibility/binaries/ydbd-target")
+current_name = 'current'
+if current_binary_path is not None:
+ with open(yatest.common.binary_path("ydb/tests/library/compatibility/binaries/ydbd-target-name")) as f:
+ current_name = f.read().strip()
+current_binary_version = string_version_to_tuple(current_name)
+
+inter_stable_binary_path = yatest.common.binary_path("ydb/tests/library/compatibility/binaries/ydbd-inter")
+init_stable_binary_path = yatest.common.binary_path("ydb/tests/library/compatibility/binaries/ydbd-init")
+
+inter_stable_version = None
+init_stable_version = None
+
+inter_stable_name = "intermediate"
+if inter_stable_binary_path is not None: # in import_test yatest.common.binary_path returns None
+ with open(yatest.common.binary_path("ydb/tests/library/compatibility/binaries/ydbd-inter-name")) as f:
+ inter_stable_name = f.read().strip()
+ inter_stable_version = string_version_to_tuple(inter_stable_name)
+init_stable_name = "initial"
+if init_stable_binary_path: # in import_test yatest.common.binary_path returns None
+ with open(yatest.common.binary_path("ydb/tests/library/compatibility/binaries/ydbd-init-name")) as f:
+ init_stable_name = f.read().strip()
+ init_stable_version = string_version_to_tuple(init_stable_name)
path_to_version = {
current_binary_path: current_binary_version,
- last_stable_binary_path: last_stable_version,
- prelast_stable_binary_path: prelast_stable_version,
+ inter_stable_binary_path: inter_stable_version,
+ init_stable_binary_path: init_stable_version,
}
all_binary_combinations_restart = [
- [[last_stable_binary_path], [current_binary_path]],
- [[current_binary_path], [last_stable_binary_path]],
+ [[inter_stable_binary_path], [current_binary_path]],
+ [[current_binary_path], [inter_stable_binary_path]],
[[current_binary_path], [current_binary_path]],
- [[prelast_stable_binary_path], [last_stable_binary_path]],
- [[last_stable_binary_path], [prelast_stable_binary_path]],
- [[last_stable_binary_path], [last_stable_binary_path]],
+ [[init_stable_binary_path], [inter_stable_binary_path]],
+ [[inter_stable_binary_path], [init_stable_binary_path]],
+ [[inter_stable_binary_path], [inter_stable_binary_path]],
]
all_binary_combinations_ids_restart = [
- "restart_{}_to_{}".format(last_stable_name, current_name),
- "restart_{}_to_{}".format(current_name, last_stable_name),
+ "restart_{}_to_{}".format(inter_stable_name, current_name),
+ "restart_{}_to_{}".format(current_name, inter_stable_name),
"restart_{}_to_{}".format(current_name, current_name),
- "restart_{}_to_{}".format(prelast_stable_name, last_stable_name),
- "restart_{}_to_{}".format(last_stable_name, prelast_stable_name),
- "restart_{}_to_{}".format(last_stable_name, last_stable_name),
+ "restart_{}_to_{}".format(init_stable_name, inter_stable_name),
+ "restart_{}_to_{}".format(inter_stable_name, init_stable_name),
+ "restart_{}_to_{}".format(inter_stable_name, inter_stable_name),
]
@@ -118,15 +126,15 @@ class RestartToAnotherVersionFixture:
all_binary_combinations_mixed = [
[current_binary_path],
- [last_stable_binary_path],
- [current_binary_path, last_stable_binary_path],
- [last_stable_binary_path, prelast_stable_binary_path],
+ [inter_stable_binary_path],
+ [current_binary_path, inter_stable_binary_path],
+ [inter_stable_binary_path, init_stable_binary_path],
]
all_binary_combinations_ids_mixed = [
"mixed_{}".format(current_name),
- "mixed_{}".format(last_stable_name),
- "mixed_{}".format(current_name + "_and_" + last_stable_name),
- "mixed_{}".format(last_stable_name + "_and_" + prelast_stable_name),
+ "mixed_{}".format(inter_stable_name),
+ "mixed_{}".format(current_name + "_and_" + inter_stable_name),
+ "mixed_{}".format(inter_stable_name + "_and_" + init_stable_name),
]
@@ -159,12 +167,12 @@ class MixedClusterFixture:
all_binary_combinations_rolling = [
- [last_stable_binary_path, current_binary_path],
- [prelast_stable_binary_path, last_stable_binary_path],
+ [inter_stable_binary_path, current_binary_path],
+ [init_stable_binary_path, inter_stable_binary_path],
]
all_binary_combinations_ids_rolling = [
- "rolling_{}_to_{}".format(last_stable_name, current_name),
- "rolling_{}_to_{}".format(prelast_stable_name, last_stable_name),
+ "rolling_{}_to_{}".format(inter_stable_name, current_name),
+ "rolling_{}_to_{}".format(init_stable_name, inter_stable_name),
]