RFC: Uma nova estratégia de versionamento para Discourse

Estamos planejando introduzir um novo sistema de versionamento para o Discourse. Nosso objetivo é fornecer mais opções e previsibilidade para os administradores da comunidade, mantendo nossa velocidade de desenvolvimento. Também estamos ajustando alguma terminologia para melhor alinhar com outros softwares.

Este documento evoluirá à medida que recebermos comentários, começarmos a implementar o sistema e, em seguida, expandirmos o uso dos novos fluxos de lançamento.

Se você tiver algum comentário/sugestão nesta fase, por favor, nos informe respondendo a este tópico!


Objetivos

  1. Introduzir ‘lançamentos’ mais regulares para o Discourse, que forneçam um equilíbrio entre velocidade de desenvolvimento e estabilidade
  2. Continuar a fornecer aproximadamente 6 lançamentos mensais que são suportados por um período estendido
  3. Fornecer suporte sobreposto para lançamentos regulares e de suporte estendido, para que os administradores tenham mais flexibilidade sobre o tempo de atualização, enquanto continuam a receber atualizações críticas de segurança
  4. Manter a cerimônia em torno dos ‘lançamentos’ ao mínimo. O máximo possível deve ser automatizado e não deve diminuir a experiência do desenvolvedor principal. Lançamentos ESR são iguais a qualquer outro lançamento.
  5. A nomenclatura e o procedimento devem corresponder aos padrões da indústria, para que seja mais fácil explicar aos desenvolvedores e usuários finais.

Visão Geral de Alto Nível

  • Cortar aproximadamente um lançamento por mês. A versão ‘principal’ é o ano atual, e a versão ‘secundária’ incrementa a cada lançamento. O número da versão de patch será incrementado para quaisquer correções retroativas.

    ex: o primeiro lançamento de 2026 seria v2026.0, o próximo seria v2026.1, etc.

    Os lançamentos receberão correções críticas por dois ciclos de lançamento completos. ex: o suporte para 2026.0 continuará até que 2026.2 seja lançado.

  • Aproximadamente a cada 6 meses, declarar um desses lançamentos como um Lançamento de Suporte Estendido (ESR). As versões ESR permanecem suportadas por 2 lançamentos após o próximo ESR ser declarado.

    ex: se v2026.0 for ESR, e v2026.6 for o próximo ESR, então o suporte para v2026.0 terminará quando v2026.8 for lançado. Assumindo uma cadência mensal, isso seria uma sobreposição de 2 meses no suporte ESR.

  • Fornecer correções críticas para latest, o lançamento mais recente, o lançamento anterior e quaisquer versões ESR ativas.

  • Renomear o branch tests-passed para latest

Exemplo de gráfico de períodos de suporte ao longo de um ano:

gantt
    title Lançamentos e Períodos de Suporte do Discourse (Jan 2026 – Jan 2027)
    dateFormat  YYYY-MM-DD
    axisFormat  %b %Y

    2026.0 (ESR) :active, 2026-01-27, 2026-09-29
    2026.1 :done, 2026-02-24, 2026-04-28
    2026.2 :done, 2026-03-31, 2026-05-26
    2026.3 :done, 2026-04-28, 2026-06-30
    2026.4 :done, 2026-05-26, 2026-07-28
    2026.5 :done, 2026-06-30, 2026-08-25
    2026.6 (ESR) :active, 2026-07-28, 2027-01-26
    2026.7 :done, 2026-08-25, 2026-10-27
    2026.8 :done, 2026-09-29, 2026-11-24
    2026.9 :done, 2026-10-27, 2026-12-29
    2026.10 :done, 2026-11-24, 2027-01-26
    2026.11 :done, 2026-12-29, 2027-01-26

Implementação

  • Cada lançamento terá um branch cortado de latest. Estes serão nomeados e preservados indefinidamente. Por exemplo, v2026.1 teria um branch chamado release/2026.1

  • Cada lançamento de patch será marcado. ex: v2026.1.0, v2026.1.1, etc.

  • O último lançamento será marcado como release. O último ESR será marcado como esr.

  • O lançamento anterior será marcado como release-previous. O ESR ativo anterior (se houver) será marcado como esr-previous.

  • Para compatibilidade retroativa, tags que correspondem aos fluxos de lançamento existentes serão alias para o equivalente novo mais próximo. stableesr. betarelease. tests-passedlatest.

    Estes serão considerados obsoletos, e pretendemos descontinuar alguns ou todos eles no futuro. Em particular, ‘beta’ é problemático porque dá a impressão de que o Discourse não está pronto para produção.

  • Em latest, o número da versão será a versão em desenvolvimento, com o sufixo -latest. ex: 2026.3.0-latest

Processo de Lançamento Automatizado

Todo mês, uma ação do GitHub abrirá um novo PR contendo um único commit que incrementa o version.rb em main para a próxima versão -latest.

Uma vez que um humano mescle o PR, outra ação do GitHub detectará main movendo-se para a próxima -latest e cortará um branch para o lançamento concluído. Essencialmente, este branch se torna um ‘candidato a lançamento’. Outro PR automatizado será aberto contra o branch de lançamento com uma atualização para remover o sufixo -latest de version.rb, e assim ‘lançá-lo’.

Geralmente, mesclaremos esses dois PRs em rápida sucessão. Mas ter PRs separados para criar e finalizar o lançamento nos dá a opção de abordar quaisquer problemas no branch antes de finalizar.

    %%{init: { 'logLevel': 'debug', 'gitGraph': {'showBranches': true, 'showCommitLabel':true,'mainBranchOrder': 2}} }%%
    gitGraph
       checkout main
       commit id:'version v2026.1-latest'
       commit id:'...'
       commit id:'....'
       branch 'release/2026.1'
       commit id:'version 2026.1'
       checkout 'main'
       commit id:'version v2026.2-latest'

Separadamente, outro fluxo de trabalho de ações do GitHub observará quaisquer commits retroativos para branches de lançamento. Quando algum for encontrado, um novo PR será gerado para incrementar a versão de patch nesse branch. Um humano pode decidir quando mesclar esses PRs.

Todas essas automações manterão automaticamente várias tags (release, release-previous, esr, esr-previous, além de aliases de compatibilidade retroativa) atualizadas.

Correções de Segurança

O fluxo de trabalho de correção de segurança permanece em grande parte o mesmo, exceto que agora precisamos fazer as correções em dois desses três novos locais:

  • latest

  • esr

  • esr-previous :new_button:

  • release :new_button:

  • release-previous :new_button:

(Lembre-se, de acordo com a ilustração anterior, são apenas dois dos três porque esr-previous é suportado, o novo esr é o mesmo que release ou release-previous, e descontinuamos o suporte para esr-previous quando isso não for mais verdade).

Ao introduzir uma correção de segurança em latest, uma tag latest-security-fix será automaticamente movida para esse commit. O docker_manager será atualizado para monitorar essa tag e solicitar aos administradores que atualizem. Isso nos permite lançar e notificar sobre correções de segurança sem precisar acelerar um aumento de versão.

Traduções

No momento, os branches stable e tests-passed podem ser traduzidos no CrowdIn, e os resultados são integrados regularmente. No novo sistema, inicialmente planejamos que latest e release sejam traduzíveis no CrowdIn.

Idealmente, quando release se tornar release-previous ou esr, as traduções terão se estabilizado. Se houver demanda por traduções contínuas dessas versões, isso poderá ser considerado no futuro.

Compatibilidade de Plugins/Temas

Aumentar o uso de fluxos que não sejam latest do Discourse aumentará nossa dependência do sistema discourse-compatibility. Portanto, precisamos de algumas melhorias no sistema de compatibilidade.

Em vez de usar um arquivo .discourse-compatibility em main, poderíamos, em vez disso, suportar compatibilidade implícita com base em branches/tags nomeadas especialmente. Isso deve ser muito mais fácil do que gerenciar hashes de commit manualmente. Por exemplo, um plugin poderia ter branches como

  • d-compat/v2026.1
  • d-compat/v2026.2
  • d-compat/v2026.3
  • main (usado para qualquer versão do Discourse que não tenha seu próprio branch)

Ao instalar um plugin, o Discourse pode verificar um branch que corresponda à versão atual. Se existir, faça o checkout dele. Caso contrário, verifique o arquivo .discourse-compatibility. Caso contrário, faça o checkout do branch padrão.

Podemos criar uma ação pública do GitHub que roda diariamente em cada tema/plugin, verifica novos lançamentos do Discourse e cria automaticamente esses branches. Cada tema/plugin pode optar por usar essa ação de fixação automática, ou pode ir para uma estratégia mais ‘flutuante’.

Hospedagem discourse.org

Inicialmente, nossa oferta hospedada continuará executando a versão latest do Discourse. No futuro, exploraremos opções para que nossos clientes de nível empresarial selecionem uma versão de ‘lançamento’.

Padrões de Instalação Padrão

Inicialmente, o padrão permanecerá latest. Os administradores poderão optar pelos novos fluxos de lançamento da mesma forma que optam pelo estável no momento. Podemos explorar trocas mais fáceis entre os fluxos de lançamento no futuro, uma vez que o sistema esteja mais maduro.

38 curtidas

Estou um pouco confuso. Então o tests-passed também conhecido como latest (que presumo ser o padrão) será o mais atualizado (recebendo as atualizações mais frequentes; nenhuma mudança aí), mas o branch beta atual, agora o branch release, ainda se comportará como está agora, ou seja, um “grupo” de commits/atualizações, e então o branch ESR (também conhecido como stable) será um “grupo” maior de atualizações beta/release?

Isso significa que release agora se torna a opção padrão, ou quando você diz ‘última versão’ você está se referindo a ‘última atualização no branch release’? Haveria então uma diferença entre isso e latest?

Obrigado!

1 curtida

beta é atualmente uma tag e não recebe correções retroativas.

Com esta proposta, cada release versionada terá seu próprio branch e receberá correções de segurança enquanto for “suportada”. As pessoas poderiam apontar sua instalação para o número de versão específico e continuar a usá-lo após outra release ser feita. Isso não é possível com o beta ou stable atual.

release será uma tag que segue a última release (incluindo releases de patch) para correções de segurança.

Não:

‘última release’ (ou apenas ‘release’) = o commit mais recente no branch de release mais recente

‘latest’ = o novo nome para tests-passed

3 curtidas

Obrigado, isso esclarece!

2 curtidas

Isso parece um desenvolvimento positivo!

Haverá algum teste específico de atualizações de esr-previous para esr no momento em que esr for rotulado? Tais atualizações, argumentaria eu, devem ser organizadas para serem atualizações suaves, ou para ter boas descrições de como realizá-las da forma mais suave possível.

4 curtidas

Sim, as atualizações entre versões ESR (ou qualquer versão suportada) continuarão a ser transparentes.

2 curtidas

Apenas um pequeno pedido por uma questão de conveniência, o ponteiro (por exemplo, 2026.0) poderia estar mais ligado ao mês em que um lançamento é enviado? (Ou seja, 2026.01 para janeiro, 2026.02 para fevereiro, etc.)

4 curtidas

O problema de vincular explicitamente as coisas a um mês é que não poderemos pular um mês ou lançar duas versões em um mês. É por isso que planejamos mantê-lo como um número incremental simples.

3 curtidas

Um projeto que uso bastante (mailcow) pula o mês quando não há alterações significativas no núcleo.

E contar a partir de 0 seria muito estranho. Faz todo o sentido para programadores, mas não muito sentido para pessoas não técnicas.

2 curtidas

Eu estava pensando sobre o lançamento x.0 mencionado. Eu realmente gosto de vinculá-lo ao mês para que você possa saber imediatamente quando um lançamento foi lançado. Mas talvez não importe se xx.8 foi lançado em setembro, dezembro ou junho. Mal consigo me lembrar em qual versão estamos agora, então poder saber imediatamente se alguém está falando sobre um bug da semana passada ou de alguns meses atrás sem ter que olhar o commit como faço agora, seria muito bom.

O Ubuntu tem YY.04 e YY.10. Funciona há vinte anos. Pular meses não parece difícil.

Isso parece ser mais um problema, embora você possa fazer algo como 22.1a ou 22.01a se tivesse que ter dois lançamentos em um mês.

6 curtidas

Há algum tempo também começamos a usar essa estratégia para nossa plataforma. Exatamente a mesma, incluindo branching e patching. Posso recomendar.

Usamos lançamentos mensais. Então, há 1–12. O ritmo ajuda a todos. Sempre há algo para lançar e ninguém quer cortar o branch duas vezes por mês de qualquer maneira. Além disso, quando digo “Eu uso 2025.6”, todos sabem que é o de antes das férias de verão.

7 curtidas

Em primeiro lugar, :rocket: este é um ótimo passo!

Após pensar um pouco, tenho duas observações menores.

  1. git branch e muitas outras ferramentas não entendem versionamento e ordenarão alfabética ou numericamente. Em ambos os casos, 2026.10 acabará entre 2026.1 e 2026.2. Inspirado pelo Ubuntu, proponho introduzir um zero à esquerda para releases e patch releases quando eles tiverem apenas um dígito, então teríamos v2026.01, v2026.02 e v2026.10 e então o universo ficará feliz novamente.

  2. o novo método de compatibilidade de plugins parece excessivamente complexo e muito frágil

Então, se eu construir um novo recurso no meu plugin que precise de v2026.3, eu crio um branch e coloco minha nova funcionalidade nele. Agora que o recurso foi construído e meu cliente está feliz, posso descansar e aproveitar minhas férias :palm_tree: :wine_glass:. No entanto, depois da minha terceira taça de vinho, você decide lançar v2026.4 e meu cliente decide atualizar. E puff, não há branch v2026.4 no meu plugin e a funcionalidade desaparece :sob:

Portanto, eu nunca usaria isso e manteria o uso de .discourse-compatibility em vez disso.

9 curtidas

A intenção é o inverso. Os branches de compatibilidade são apenas para branches ‘lançados’ do Discourse. O latest do Discourse sempre usará o main do seu plugin. É lá que você desenvolverá novos recursos.

Então, a história seria:

O Discourse lança o v2026.2. As ações do GitHub no seu plugin detectam isso automaticamente e criam um branch d-compat/v2026.2. Agora, qualquer pessoa que use o Discourse v2026.2 usará a versão d-compat/v2026.2 do seu plugin.

Você lança um novo recurso no main do seu plugin. Você não precisa se preocupar com compatibilidade retroativa, porque o branch main é usado apenas por pessoas que executam o Discourse latest.

Então, enquanto você bebe sua terceira taça de vinho :wine_glass:, o Discourse lança o v2026.3. Inicialmente, não há branch de plugin para esta versão, então o main será usado. As coisas continuam funcionando como antes para as pessoas no latest.

Em poucas horas, sua ação do GitHub detecta a nova versão e congela o d-compat/v2026.3, pronto para que seu próximo recurso de plugin chegue ao main sem preocupações de compatibilidade retroativa.

Este é essencialmente o fluxo de trabalho que usamos na CDCK para lidar com a compatibilidade estável de temas/plugins. Após cada lançamento estável, temos um script para percorrer nossas centenas de temas/plugins e congelá-los via .discourse-compatibility. Esta proposta baseada em branches visa ser uma versão mais leve desse fluxo de trabalho.

16 curtidas

Isso é incrível, obrigado pela explicação detalhada.

Parece que posso tomar uma quarta taça de vinho :wink:

15 curtidas

Concordando com o que outros disseram, gosto da direção das mudanças propostas. E acho que os nomes de branch propostos são muito mais intuitivos do que os antigos :+1:

O que ainda não está muito claro para mim é como funcionará o processo de atualização para os branches release e esr (o latest parece direto). Você menciona que, em cada ponto no tempo, tanto a release atual (vamos chamá-la de n) quanto a release anterior (n-1) serão suportadas, e que, como administrador, terei a opção de quando atualizar.

Agora, com base na minha experiência com outros softwares, quando uma nova versão de release (n+1) chega, eu seria notificado sobre a disponibilidade da versão n+1. E que eu poderia então decidir fazer uma atualização maior (equivalente a, por exemplo, apt dist-upgrade no Linux) ou fazer uma atualização menor/padrão (equivalente a, por exemplo, apt upgrade no Linux) e permanecer na versão n. Isso é algo que será incorporado ao script do lançador do Discourse?

Além disso, entendo o desejo de manter a cerimônia/processo de release no mínimo, mas minha intuição seria que tanto as releases normais quanto as esr recebessem pelo menos um pouco de teste extra, antes de serem lançadas. Isso pode ser influenciado por trabalhar muito tempo em TI corporativa, no entanto :smile:

Por último, estou me perguntando se as releases mensais são realmente “muito rápidas”. Isso é admitidamente subjetivo, mas, julgando pela minha própria experiência em gerenciar coisas de TI por conta própria como voluntário, eu posso não ter tempo para atualizações maiores a cada mês. E partindo disso, eu estava me perguntando se você poderia potencialmente também tornar suas vidas como desenvolvedores do Discourse um pouco mais fáceis, simplesmente lançando trimestralmente, e não tendo branches esr separados, mas apenas branches release.

4 curtidas

Isso tornará a vida dos desenvolvedores de temas e plugins mais difícil, porque nessa (esta) situação você tem uma pressão de tempo para atualizar seus temas e plugins, e caso contrário, você não terá nenhuma atualização de segurança. Uma versão ESR aliviará essa pressão.

4 curtidas

Não tenho certeza se entendi completamente. Minha compreensão com base nas postagens anteriores era que a criação de um branch de versão de lançamento acionaria automaticamente a criação de um branch de plugin para essa versão. Portanto, minha suposição seria que mesclar release e esr em um também reduziria o esforço para construtores de plugins e temas, porque sempre que você precisar enviar uma correção, ela precisaria ser enviada para menos branches (três em vez de cinco). Mas talvez eu esteja perdendo alguma coisa?

2 curtidas

Não se trata de quando o autor do tema/plugin lança uma correção, mas sim de quando o core do Discourse tem uma correção de segurança.

De acordo com

a única diferença entre release e esr é que esr recebe correções de segurança por 6 + 2 = 8 meses.

1 curtida

Com as ferramentas de launcher atuais e essa nova estrutura de branches, você poderia ter controle sobre o tempo de atualização fazendo algo como:

  1. v2026.02 lançado
  2. Você define version: release/v2026.02 no seu arquivo app.yml
  3. v2026.03 lançado
  4. Você executa uma reconstrução. Você ainda obtém 2026.02, com quaisquer correções de segurança recentes
  5. Quando estiver pronto, você muda para version: release/v2026.03 em app.yml

Mas editar manualmente esse app.yml todo mês realmente não é o ideal, então esperamos poder projetar um sistema que torne o processo mais amigável ao usuário.

O processo na OP nos permite tratar os branches como ‘candidatos a lançamento’ antes de realmente marcá-los como um lançamento. Não tenho certeza exatamente se/como usaremos essa capacidade neste estágio - acho que é algo que evoluirá à medida que nos acostumarmos com o novo sistema.

Estamos tentando encontrar um equilíbrio aqui entre a velocidade de desenvolvimento do Discourse e a estabilidade para pessoas com personalizações extensas. Ter um atraso de mais de 3 meses para que os recursos cheguem aos nossos clientes não é uma opção. Na verdade, o mensal está no lado lento para nós. No momento, ainda pretendemos usar latest para a maioria de nossos hospedagens.

Mas, é claro, para pessoas que hospedam o Discourse, entendo o desejo de ter mudanças menos frequentes. É aí que entram os lançamentos ESR.

5 curtidas

Depende do autor do plugin/tema. Ou eles podem continuar com a estratégia atual, onde o branch main do plugin precisa funcionar com todas as versões ‘lançadas’ do Discourse. Ou eles podem usar a estratégia de branching automático, que facilita a compatibilidade, mas também significa que você pode precisar fazer muito ‘backporting’ em seu plugin em caso de correções críticas de bugs/segurança.

A qualquer momento, existem três versões “suportadas” do Discourse, mais latest. Portanto, correções críticas precisarão ser aplicadas em até 4 branches.

3 curtidas