Pular para o conteúdo principal
Este documento descreve a política de backport do ClickHouse e o sistema automatizado que a implementa.

Modelo de lançamento

As versões do ClickHouse seguem o formato YY.M.patch.build-type, em que YY é o ano com dois dígitos, M é o mês do lançamento (sem zero à esquerda), patch é o número do patch dentro da branch, build é um número de build que cresce monotonamente, e type é stable ou lts. Exemplo: 25.3.8.23-lts — LTS de março de 2025, patch 8, build 23. Há dois canais de lançamento:
  • As versões Stable são publicadas aproximadamente uma vez por mês. As três versões stable mais recentes recebem patches, o que garante aproximadamente três meses de suporte ativo para cada versão.
  • As versões LTS (Long-Term Support) são publicadas em março e agosto de cada ano. Duas versões LTS têm suporte simultaneamente, cada uma por pelo menos 12 meses.
Recomenda-se que os usuários que executam workloads de produção usem a versão stable mais recente ou uma versão LTS e atualizem rapidamente para novas versões de patch, já que versões de patch não introduzem mudanças incompatíveis.

Política de backport

Nem todas as mudanças passam por backport. O objetivo é manter as branches de release estáveis, por isso o escopo dos backports é intencionalmente limitado:
  • Correções de segurança — sempre passam por backport.
  • Correções de bugs críticos (exceptions (erros lógicos), perda de dados, resultados incorretos, problemas de RBAC) — selecionadas automaticamente para backport de acordo com as regras gerais de backport; identificadas pelo rótulo pr-critical-bugfix, que faz com que pr-must-backport seja adicionado automaticamente.
  • Correções de estabilidade e regressões — passam por backport quando o risco da mudança é baixo em relação ao risco de deixar o bug sem correção; identificadas por pr-must-backport, adicionado manualmente pelos maintainers.
  • Correções de bugs menores com workaround disponível — em geral, não passam por backport para evitar desestabilizar as branches de release.
  • Novos recursos, melhorias e trabalho de performance — não passam por backport.
O rótulo pr-must-backport é a substituição manual usada pelos maintainers para marcar um PR para backport. O rótulo pr-critical-bugfix faz com que pr-must-backport seja adicionado automaticamente pelo hook de CI (consulte pr_labels_and_category.py). Escalonamento de conflitos. Quando o backport automático não consegue resolver conflitos de merge, ainda assim um cherry-pick PR deve ser criado e atribuído ao autor, a quem fez o merge e às pessoas já atribuídas no PR original, para que alguém resolva os conflitos e conclua o backport.

Ferramenta de Backport

A política de backport descrita acima é implementada pela ferramenta automatizada em tests/ci/cherry_pick.py. A ferramenta é executada como um workflow do GitHub Actions na infraestrutura do ClickHouse e cobre todos os requisitos: descobrir branches de release ativas, selecionar PRs qualificadas para backport, executar o procedimento de cherry-pick e backport em duas etapas, gerenciar conflitos, aplicar a política de atraso e manter os rótulos sincronizados. O objetivo de longo prazo é extrair essa implementação para uma ferramenta open-source independente em Python que outros projetos possam adotar. O design pretendido é:
  • Configurável — todos os parâmetros da política (rótulos de qualificação, janela de atraso, limites para PRs desatualizadas, comportamento durante rolling-out etc.) expressos em um arquivo de configuração, para que a ferramenta possa ser adaptada aos requisitos de backport de qualquer projeto sem alterações no código.
  • Distribuível — empacotada como uma wheel Python autocontida, instalável via PyPI, sem dependência da infraestrutura de CI do ClickHouse.
  • Programável — expondo um modelo de objetos claro para pull requests, rótulos e branches de release, para que os usuários possam criar scripts e workflows personalizados sobre o engine principal.

Testes

Uma parte planejada da ferramenta independente é uma suíte de testes dedicada, juntamente com uma infraestrutura de testes leve. A infraestrutura será capaz de criar temporariamente repositórios do GitHub (ou equivalentes locais) já preenchidos com:
  • um conjunto configurável de branches que representam linhas de release,
  • pull requests com várias combinações de rótulos de backport,
  • PRs de release com o rótulo release apontando para as branches de release.
Isso permite que os testes exercitem todo o ciclo de automação — detecção de rótulos, criação de branch de cherry-pick, tratamento de conflitos, criação de PR de backport, lógica de atribuição de responsáveis, omissão durante rolling-out e política de atraso — em um repositório real, mas descartável, sem afetar o estado de produção. A mesma infraestrutura também pode ser reutilizada para testes de regressão de mudanças de política antes da implantação.

Branches de release ativas

Uma branch de release ativa é qualquer branch cujo PR de release correspondente (com o rótulo release) ainda esteja aberto no GitHub. A automação de backport detecta essas branches dinamicamente a cada execução, portanto não é necessário fazer alterações de configuração quando uma nova release é criada ou quando uma antiga chega ao fim de vida. Uma branch de release pode estar no estado rolling-out (seu PR de release tem o rótulo rolling-out) durante o período em que uma nova release está sendo implantada. Os backports gerais são pausados para branches em rolling-out para evitar complicar o rollout. Rótulos específicas de versão (por exemplo, v25.3-must-backport) substituem esse comportamento e forçam o backport mesmo durante um rollout.

Implementação

Visão geral

A automação de backport é executada a cada hora como o workflow CherryPick do GitHub Actions (.github/workflows/cherry_pick.yml), implementado em tests/ci/cherry_pick.py. Ela opera por meio da API do GitHub e de operações locais do git em um runner style-checker-aarch64 self-hosted. O processo ocorre em duas etapas para cada par (PR original, branch de release):
  1. Um PR de cherry-pick é criado para isolar a resolução de conflitos do destino real do merge. Se não houver conflitos, ele será mesclado automaticamente.
  2. Um PR de backport é criado na branch de release real, com as alterações aplicadas via cherry-pick consolidadas em um único commit.

Rótulos

Os rótulos no PR original controlam se e onde o backport será feito.
RótuloEfeito
pr-must-backportBackport para todas as branches de release ativas (ignorando branches marcadas como rolling-out)
pr-must-backport-forceBackport para todas as branches de release ativas, ignorando as restrições de rolling-out
pr-critical-bugfixAciona pr-must-backport automaticamente (via AUTO_BACKPORT em pr_labels_and_category.py)
v{VER}-must-backport (por exemplo, v25.3-must-backport)Backport apenas para essa branch de release específica; sobrescreve o comportamento de ignorar rolling-out para essa branch
pr-backports-createdDefinido pelo bot quando todos os PRs de backport obrigatórios tiverem sido criados; removido se um PR de cherry-pick for reaberto
pr-cherrypickAplicado aos PRs de cherry-pick criados pelo bot
pr-backportAplicado aos PRs de backport criados pelo bot
do not testAplicado aos PRs de cherry-pick para que o CI não seja executado neles
rolling-outDefinido em um PR de release para indicar que sua branch está em rollout no momento; backports gerais a ignoram

Nomenclatura de branches e PRs

Para cada número de PR original N e branch de release release/X.Y:
  • Branch de cherry-pick: cherrypick/release/X.Y/N
  • Branch de backport: backport/release/X.Y/N
  • Título da PR de cherry-pick: Cherry pick #N to release/X.Y: <original title>
  • Título da PR de backport: Backport #N to release/X.Y: <original title>

Processo passo a passo

1. Identifique as releases ativas

BackportPRs.receive_release_prs consulta o GitHub em busca de todos os PRs abertos com o rótulo release. As refs de origem desses PRs correspondem aos nomes dos branches de release (por exemplo, release/25.3). A partir delas, é gerado um conjunto de rótulos de compatibilidade: v25.3-must-backport etc.

2. Encontrar PRs para backport

BackportPRs.receive_prs_for_backport usa a API de busca do GitHub para encontrar PRs mesclados que:
  • tenham pelo menos um rótulo de backport (pr-must-backport, pr-must-backport-force, pr-critical-bugfix ou um rótulo específico da versão), e
  • não já tenham pr-backports-created, e
  • tenham sido mesclados após a data do commit mais antigo encontrada em qualquer release branch, e
  • tenham sido atualizados nos últimos 90 dias (para manter a consulta de busca eficiente).

3. Tratamento de branch em rolling-out

Quando uma PR de release recebe o rótulo rolling-out, os rótulos gerais de backport (pr-must-backport, pr-critical-bugfix) ignoram esse branch. O bot fecha todas as PRs de cherry-pick ou backport criadas anteriormente para esse branch com um comentário explicativo. Um rótulo específico da versão (por exemplo, v25.3-must-backport) sempre prevalece sobre isso. pr-must-backport-force ignora a verificação de rolling-out para todos os branches.

4. Etapa de cherry-pick (ReleaseBranch.create_cherrypick)

Para cada par (PR original, branch de release) em que ainda não exista um PR de cherry-pick:
  1. Faça checkout da branch de release e crie uma branch de backport (backport/release/X.Y/N) a partir dela.
  2. Execute git merge -s ours contra o primeiro parent do commit de merge para criar uma base de merge sintética, sem alterações de conteúdo.
  3. Crie à força uma branch de cherry-pick (cherrypick/release/X.Y/N) apontando diretamente para o commit de merge do PR original.
  4. Tente executar git merge --no-commit --no-ff da branch de cherry-pick na branch de backport:
    • Se já estiver atualizada, a alteração já está presente na branch de release — marque como concluído e pule esta etapa.
    • Caso contrário (com ou sem conflitos), faça reset e envie ambas as branches.
  5. Crie o PR de cherry-pick com destino a backport/release/X.Y/N a partir de cherrypick/release/X.Y/N, com os rótulos pr-cherrypick e do not test.
  6. Propague pr-bugfix ou pr-critical-bugfix do PR original, se aplicável.
  7. Os responsáveis não são definidos neste momento; eles só são adicionados quando forem detectados conflitos.

5. Mesclagem automática de PRs de cherry-pick sem conflitos

Se o PR de cherry-pick puder ser mesclado (sem conflitos), o bot o mescla automaticamente pela API do GitHub e prossegue imediatamente para a etapa de backport.

6. Etapa de backport (ReleaseBranch.create_backport)

Depois que a PR de cherry-pick é mesclada:
  1. Faça checkout da branch de backport e faça pull.
  2. Encontre a merge-base entre a branch de release e a branch de backport.
  3. Execute git reset --soft até a merge-base, consolidando todos os commits de cherry-pick em um só.
  4. Faça um commit usando o título da PR de backport como mensagem.
  5. Faça force-push da branch de backport e abra uma PR de backport voltada para a branch de release real.
  6. Adicione à PR o label pr-backport (e pr-bugfix / pr-critical-bugfix, se aplicável).
  7. Atribua a PR ao autor da PR original, à pessoa que fez o merge e aos responsáveis já atribuídos (excluindo contas de robô).

7. Conclusão

Quando o backport é concluído em todas as branches de release de um determinado PR original, o bot adiciona pr-backports-created ao PR original.

8. Pré-verificação

Antes de iniciar qualquer trabalho em um PR, ReleaseBranch.pre_check executa git merge-base --is-ancestor para verificar se o commit de merge ainda não é alcançável a partir da branch de release. Se for, considera-se que o PR já foi backportado e ele é ignorado.

Tratamento de Cherry-pick PRs Inativos

A classe CherryPickPRs é executada no início de cada execução horária e trata de dois cenários:
  • PRs de cherry-pick órfãos: se a branch de release de um PR de cherry-pick não tiver mais um PR de release aberto (ou seja, o release foi fechado), o PR de cherry-pick será fechado automaticamente.
  • PRs de cherry-pick reabertos: se um PR original já tiver o rótulo pr-backports-created, mas um PR de cherry-pick correspondente ainda estiver aberto, o rótulo pr-backports-created será removido do PR original para que ele possa ser reprocessado.
Para PRs de cherry-pick que aguardam resolução manual de conflitos:
  • Após 3 dias sem atualizações, o bot publica um comentário de ping mencionando os responsáveis atribuídos.
  • Após 7 dias sem atualizações, o bot publica um comentário de encerramento e fecha o PR.

Resolução de conflitos

Quando um cherry-pick gera conflitos, a PR de cherry-pick permanece aberta para resolução manual. O bot a atribui ao autor da PR original, a quem fez o merge e aos responsáveis designados. Depois que os conflitos são resolvidos e a PR de cherry-pick é mesclada, o bot cria a PR de backport na próxima execução horária. Para descartar um backport completamente, feche a PR de cherry-pick. O bot a tratará como intencionalmente ignorada. Para recriar do zero uma PR de cherry-pick com falha:
  1. Remova o rótulo pr-cherrypick da PR de cherry-pick.
  2. Exclua a branch cherrypick/....
  3. Remova pr-backports-created da PR original, se estiver presente.

CI para PRs de backport

Os PRs de backport têm como destino branches de release, por isso usam um workflow de CI dedicado (BackportPR, definido em ci/workflows/backport_branches.py) em vez do workflow padrão de pull request. Esse workflow executa um subconjunto representativo da CI: builds com ASan/UBSan e TSan, builds de release, builds de macOS, testes funcionais com ASan, testes de estresse com TSan e testes de integração. Ele verifica se a branch de backport tem entre 1 e 50 commits e pelo menos um arquivo alterado (conforme validado por check_backport_branch.py).

Autenticação

O workflow usa uma chave SSH (ROBOT_CLICKHOUSE_SSH_KEY) para operações de git push. As chamadas à API do GitHub são autenticadas via get_best_robot_token, que seleciona o token com a maior cota restante de um conjunto armazenado no SSM (/github-tokens). ROBOT_CLICKHOUSE_COMMIT_TOKEN é usado pela etapa de checkout no workflow do Actions, não para chamadas de API. As contas de robô (robot-clickhouse, clickhouse-gh) são excluídas ao atribuir um responsável.

Cache da API do GitHub

GitHubCache (de cache_utils.py) salva o cache de objetos do PyGithub no S3, reduzindo as chamadas à API entre execuções horárias. O cache é baixado no início e enviado ao final de cada execução.

Tratamento de erros

Erros durante o processamento individual de PRs são capturados e registrados em log, mas não interrompem a execução. Depois que todos os PRs forem processados, se tiver ocorrido algum erro, uma BackportException será gerada. No CI, isso dispara uma notificação via CIBuddy para o chat da equipe.
Última modificação em 10 de junho de 2026