Modelo de lançamento
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.
Política de backport
- 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 quepr-must-backportseja 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.
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
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
- 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
releaseapontando para as branches de release.
Branches de release ativas
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
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):
- 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.
- 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
Nomenclatura de branches e PRs
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-bugfixou 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
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)
- Faça checkout da branch de release e crie uma branch de backport (
backport/release/X.Y/N) a partir dela. - Execute
git merge -s ourscontra o primeiro parent do commit de merge para criar uma base de merge sintética, sem alterações de conteúdo. - Crie à força uma branch de cherry-pick (
cherrypick/release/X.Y/N) apontando diretamente para o commit de merge do PR original. - Tente executar
git merge --no-commit --no-ffda 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.
- Crie o PR de cherry-pick com destino a
backport/release/X.Y/Na partir decherrypick/release/X.Y/N, com os rótulospr-cherrypickedo not test. - Propague
pr-bugfixoupr-critical-bugfixdo PR original, se aplicável. - 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
6. Etapa de backport (ReleaseBranch.create_backport)
- Faça checkout da branch de backport e faça pull.
- Encontre a
merge-baseentre a branch de release e a branch de backport. - Execute
git reset --softaté amerge-base, consolidando todos os commits de cherry-pick em um só. - Faça um commit usando o título da PR de backport como mensagem.
- Faça force-push da branch de backport e abra uma PR de backport voltada para a branch de release real.
- Adicione à PR o label
pr-backport(epr-bugfix/pr-critical-bugfix, se aplicável). - 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
pr-backports-created ao PR original.
8. Pré-verificação
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
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ótulopr-backports-createdserá removido do PR original para que ele possa ser reprocessado.
- 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
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:
- Remova o rótulo
pr-cherrypickda PR decherry-pick. - Exclua a branch
cherrypick/.... - Remova
pr-backports-createdda PR original, se estiver presente.
CI para PRs de backport
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
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
BackportException será gerada. No CI, isso dispara uma notificação via CIBuddy para o chat da equipe.