Перейти к основному содержанию
В этом документе описаны политика бэкпорта ClickHouse и автоматизированная система, которая её реализует.

Модель релизов

Версии ClickHouse следуют схеме YY.M.patch.build-type, где YY — двузначный год, M — месяц релиза (без ведущего нуля), patch — номер патча в ветке, build — монотонно возрастающий номер сборки, а type — либо stable, либо lts. Пример: 25.3.8.23-lts — LTS-релиз за март 2025 года, патч 8, сборка 23. Существует два трека релизов:
  • Стабильные релизы публикуются примерно раз в месяц. Патчи выпускаются для трёх последних стабильных релизов, что даёт каждому релизу около трёх месяцев активной поддержки.
  • Релизы LTS (Long-Term Support) публикуются в марте и августе каждого года. Одновременно поддерживаются две версии LTS, каждая — не менее 12 месяцев.
Пользователям, запускающим рабочие нагрузки в продакшене, рекомендуется использовать либо последний стабильный релиз, либо LTS-релиз и своевременно обновляться до новых патч-версий, поскольку патч-релизы не вносят несовместимых изменений.

Политика бэкпортов

Бэкпортируются не все изменения. Цель — поддерживать ветки релиза в стабильном состоянии, поэтому объём бэкпортов намеренно ограничен:
  • Исправления уязвимостей — бэкпортируются всегда.
  • Исправления критических ошибок (исключения (логические ошибки), потеря данных, некорректные результаты, проблемы с RBAC) — автоматически отбираются для бэкпорта по общим правилам бэкпортирования; определяются по метке pr-critical-bugfix, из-за которой автоматически добавляется pr-must-backport.
  • Исправления, связанные со стабильностью и регрессиями — бэкпортируются, если риск изменения невелик по сравнению с риском оставить ошибку без исправления; определяются по pr-must-backport, которую мейнтейнеры добавляют вручную.
  • Незначительные исправления ошибок при наличии обходного пути — как правило, не бэкпортируются, чтобы не дестабилизировать ветки релиза.
  • Новые возможности, улучшения, оптимизации производительности — не бэкпортируются.
Метка pr-must-backport — это ручное переопределение, которое мейнтейнеры используют, чтобы пометить PR для бэкпортирования. Метка pr-critical-bugfix приводит к тому, что pr-must-backport автоматически добавляется хуком CI (см. pr_labels_and_category.py). Эскалация конфликтов. Если при автоматическом бэкпортировании не удаётся разрешить конфликты слияния, PR cherry-pick всё равно должен быть создан и назначен автору, тому, кто выполнил слияние, и текущим назначенным исполнителям исходного PR, чтобы человек мог разрешить конфликты и завершить бэкпорт.

Инструмент бэкпорта

Описанная выше политика бэкпорта реализована в автоматизированном инструменте tests/ci/cherry_pick.py. Инструмент запускается как workflow GitHub Actions в инфраструктуре ClickHouse и охватывает все требования: обнаружение активных веток релиза, выбор PR, подходящих для бэкпорта, выполнение двухэтапной процедуры cherry-pick и бэкпорта, разрешение конфликтов, соблюдение политики задержки и поддержание синхронизации меток. Долгосрочная цель — выделить эту реализацию в автономный open-source инструмент на Python, который смогут использовать и другие проекты. Целевая архитектура выглядит так:
  • Настраиваемый — все параметры политики (подходящие метки, окно задержки, пороги устаревания PR, поведение во время раскатки и т. д.) задаются в виде файла конфигурации, чтобы инструмент можно было адаптировать под требования бэкпорта любого проекта без изменений в коде.
  • Распространяемый — упакован как самодостаточный Python wheel, устанавливаемый из PyPI, без зависимости от CI-инфраструктуры ClickHouse.
  • Программируемый — предоставляет понятную объектную модель для pull request, меток и веток релиза, чтобы пользователи могли строить собственные workflow поверх базового движка.

Тестирование

Планируемой частью автономного инструмента является отдельный набор тестов вместе с облегчённой тестовой инфраструктурой. Эта инфраструктура сможет поднимать временные GitHub-репозитории (или их локальные эквиваленты), заранее заполненные:
  • настраиваемым набором веток, представляющих линии релизов,
  • pull request’ами с различными комбинациями меток бэкпорта,
  • релизными PR с меткой release, указывающими на ветки релизов.
Это позволит тестам проходить полный цикл автоматизации — обнаружение меток, создание веток для cherry-pick, обработку конфликтов, создание PR бэкпорта, логику назначения назначенных исполнителей, пропуск во время раскатки и политику задержек — на реальном, но временном репозитории, не затрагивая production-среду. Эту же инфраструктуру можно повторно использовать для регрессионного тестирования изменений политик перед их развёртыванием.

Активные ветки релиза

Активной считается любая ветка релиза, для которой соответствующий релизный PR (с меткой release) всё ещё открыт на GitHub. Автоматизация бэкпорта определяет такие ветки динамически при каждом запуске, поэтому при выходе нового релиза или завершении жизненного цикла старого никаких изменений в конфигурации не требуется. Ветка релиза может находиться в состоянии раскатки (если её релизный PR помечен меткой rolling-out) в период развёртывания нового релиза. Обычные бэкпорты для веток в состоянии раскатки приостанавливаются, чтобы не усложнять этот процесс. Метки, привязанные к конкретной версии (например, v25.3-must-backport), переопределяют это поведение и принудительно запускают бэкпорт даже во время раскатки.

Реализация

Обзор

Автоматизация бэкпортов запускается каждый час в виде workflow CherryPick в GitHub Actions (.github/workflows/cherry_pick.yml), реализованного в tests/ci/cherry_pick.py. Она работает через GitHub API и локальные операции git на самоуправляемом раннере style-checker-aarch64. Процесс состоит из двух этапов для каждой пары (original PR, ветка релиза):
  1. Создается PR cherry-pick, чтобы отделить разрешение конфликтов от фактического слияния в целевую ветку. Если конфликтов нет, он сливается автоматически.
  2. Создается бэкпорт PR в реальную ветку релиза, при этом изменения после cherry-pick объединяются в один коммит.

Метки

Метки в исходном PR определяют, будет ли выполняться бэкпорт и в какие ветки.
МеткаЭффект
pr-must-backportБэкпорт во все активные ветки релиза (кроме веток, помеченных rolling-out)
pr-must-backport-forceБэкпорт во все активные ветки релиза без учёта ограничений rolling-out
pr-critical-bugfixАвтоматически включает pr-must-backport (через AUTO_BACKPORT в pr_labels_and_category.py)
v{VER}-must-backport (например, v25.3-must-backport)Бэкпорт только в указанную ветку релиза; для этой ветки отменяет пропуск из-за rolling-out
pr-backports-createdУстанавливается ботом, когда созданы все необходимые PR для бэкпорта; снимается, если PR cherry-pick переоткрыт
pr-cherrypickПрименяется к PR cherry-pick, созданным ботом
pr-backportПрименяется к PR бэкпорта, созданным ботом
do not testПрименяется к PR cherry-pick, чтобы CI не запускался для них
rolling-outУстанавливается в release PR, чтобы показать, что его ветка сейчас находится в процессе раскатки; обычные бэкпорты её пропускают

Именование веток и PR

Для каждого номера исходного PR N и ветки релиза release/X.Y:
  • Ветка для cherry-pick: cherrypick/release/X.Y/N
  • Ветка бэкпорта: backport/release/X.Y/N
  • Заголовок PR cherry-pick: Cherry pick #N to release/X.Y: <original title>
  • Заголовок PR бэкпорта: Backport #N to release/X.Y: <original title>

Пошаговая инструкция

1. Поиск активных релизов

BackportPRs.receive_release_prs запрашивает в GitHub все открытые PR с меткой release. Head ref этих PR — это имена веток релиза (например, release/25.3). На их основе формируется набор меток совместимости: v25.3-must-backport и т. д.

2. Найдите PR для бэкпорта

BackportPRs.receive_prs_for_backport использует API поиска GitHub, чтобы найти слитые PR, которые:
  • имеют как минимум одну метку для бэкпорта (pr-must-backport, pr-must-backport-force, pr-critical-bugfix или метку для конкретной версии), и
  • не имеют pr-backports-created, и
  • были слиты после самой ранней даты коммита, найденной в любой release branch, и
  • обновлялись в течение последних 90 дней (чтобы поисковый запрос оставался эффективным).

3. Обработка ветки в процессе раскатки

Если релизный PR помечен меткой rolling-out, общие метки бэкпорта (pr-must-backport, pr-critical-bugfix) не применяются к этой ветке. Бот закрывает все ранее созданные PR с cherry-pick или бэкпортом для этой ветки, добавляя поясняющий комментарий. Метка для конкретной версии (например, v25.3-must-backport) всегда имеет приоритет над этим правилом. pr-must-backport-force отключает проверку rolling-out для всех веток.

4. Этап cherry-pick (ReleaseBranch.create_cherrypick)

Для каждой пары (исходный PR, ветка релиза), для которой PR cherry-pick ещё не существует:
  1. Переключитесь на ветку релиза и создайте от неё ветку бэкпорта (backport/release/X.Y/N).
  2. Выполните git merge -s ours относительно первого родителя коммита слияния, чтобы создать синтетическую базу слияния без изменений содержимого.
  3. Принудительно создайте ветку cherry-pick (cherrypick/release/X.Y/N), указывающую непосредственно на коммит слияния исходного PR.
  4. Попробуйте выполнить git merge --no-commit --no-ff ветки cherry-pick в ветку бэкпорта:
    • Если ветка уже в актуальном состоянии, изменение уже присутствует в ветке релиза — пометьте как выполненное и пропустите.
    • В противном случае (с конфликтами или без них) выполните reset и отправьте обе ветки.
  5. Создайте PR cherry-pick из cherrypick/release/X.Y/N в backport/release/X.Y/N, добавив метки pr-cherrypick и do not test.
  6. Перенесите pr-bugfix или pr-critical-bugfix из исходного PR, если применимо.
  7. Назначенные исполнители на этом этапе не задаются; их добавляют только при обнаружении конфликтов.

5. Автоматическое слияние PR cherry-pick без конфликтов

Если PR cherry-pick можно слить без конфликтов, бот автоматически выполняет слияние через GitHub API и сразу переходит к этапу бэкпорта.

6. Этап бэкпорта (ReleaseBranch.create_backport)

После слияния PR cherry-pick:
  1. Переключитесь на ветку бэкпорта и выполните pull.
  2. Найдите merge-base между веткой релиза и веткой бэкпорта.
  3. Выполните git reset --soft до merge-base, объединив все cherry-pick-коммиты в один.
  4. Создайте коммит, используя в качестве сообщения заголовок PR бэкпорта.
  5. Выполните принудительный push ветки бэкпорта и откройте PR бэкпорта в целевую ветку релиза.
  6. Добавьте к PR метку pr-backport (а также pr-bugfix / pr-critical-bugfix, если применимо).
  7. Назначьте PR автору исходного PR, пользователю, выполнившему слияние, и уже назначенным исполнителям (исключая учётные записи роботов).

7. Завершение

Когда бэкпорт выполнен во все ветки релиза для данного исходного PR, бот добавляет к исходному PR метку pr-backports-created.

8. Предварительная проверка

Перед началом любой работы с PR ReleaseBranch.pre_check запускает git merge-base --is-ancestor, чтобы убедиться, что коммит слияния ещё не достижим из релизной ветки. Если достижим, PR считается уже бэкпортированным и пропускается.

Обработка устаревших PR cherry-pick

Класс CherryPickPRs запускается в начале каждого ежечасного выполнения и обрабатывает два сценария:
  • Осиротевшие PR cherry-pick: если для ветки релиза, связанной с PR cherry-pick, больше нет открытого релизного PR (то есть релиз закрыт), PR cherry-pick закрывается автоматически.
  • Повторно открытые PR cherry-pick: если у исходного PR уже есть метка pr-backports-created, но PR cherry-pick для него всё ещё открыт, метка pr-backports-created удаляется из исходного PR, чтобы его можно было обработать повторно.
Для PR cherry-pick, ожидающих ручного разрешения конфликтов:
  • Через 3 дня без обновлений бот публикует комментарий с Ping и упоминанием назначенных исполнителей.
  • Через 7 дней без обновлений бот публикует комментарий о закрытии и закрывает PR.

Разрешение конфликтов

Если при cherry-pick возникают конфликты, PR cherry-pick остаётся открытым, чтобы их мог разрешить человек. Бот назначает его автору исходного PR, тому, кто его слил, и назначенным исполнителям. После разрешения конфликтов и слияния PR cherry-pick бот создаёт PR бэкпорта при следующем запуске, который выполняется раз в час. Чтобы полностью отказаться от бэкпорта, закройте PR cherry-pick. Бот воспримет это как намеренный пропуск. Чтобы заново создать повреждённый PR cherry-pick с нуля:
  1. Удалите метку pr-cherrypick из PR cherry-pick.
  2. Удалите ветку cherrypick/....
  3. Удалите pr-backports-created из исходного PR, если он есть.

CI для PR бэкпорта

PR бэкпорта нацелены на ветки релиза, поэтому для них используется отдельный CI workflow (BackportPR, определённый в ci/workflows/backport_branches.py), а не стандартный workflow для pull request. Этот workflow запускает репрезентативное подмножество CI: сборки ASan/UBSan и TSan, релизные сборки, сборки для macOS, функциональные тесты под ASan, стресс-тесты под TSan и интеграционные тесты. Он проверяет, что ветка бэкпорта содержит от 1 до 50 коммитов и как минимум один изменённый файл (это проверяется скриптом check_backport_branch.py).

Аутентификация

В этом рабочем процессе для операций git push используется SSH-ключ (ROBOT_CLICKHOUSE_SSH_KEY). Вызовы GitHub API аутентифицируются через get_best_robot_token, который выбирает токен с наибольшей оставшейся квотой из пула, хранящегося в SSM (/github-tokens). ROBOT_CLICKHOUSE_COMMIT_TOKEN используется на шаге checkout в workflow Actions, а не для вызовов API. Аккаунты роботов (robot-clickhouse, clickhouse-gh) исключаются при назначении ответственного.

Кэш API GitHub

GitHubCache (из cache_utils.py) сохраняет кэш объектов PyGithub в S3, сокращая количество вызовов API при ежечасных запусках. Кэш загружается в начале и выгружается в конце каждого запуска.

Обработка ошибок

Ошибки при обработке отдельных PR перехватываются и записываются в журнал, но не прерывают выполнение. После обработки всех PR, если возникли какие-либо ошибки, выбрасывается BackportException. В CI это приводит к отправке уведомления в командный чат через CIBuddy.
Последнее изменение 10 июня 2026 г.