RFC: Una nueva estrategia de versionado para Discourse

Estamos planeando introducir un nuevo sistema de versionado para Discourse. Nuestro objetivo es proporcionar más opciones y previsibilidad para los administradores de la comunidad, manteniendo nuestra velocidad de desarrollo. También estamos ajustando parte de la terminología para que se alinee mejor con otro software.

Este documento evolucionará a medida que recibamos comentarios, comencemos a implementar el sistema y luego ampliemos el uso de los nuevos flujos de lanzamiento.

Si tiene algún comentario/sugerencia en esta etapa, ¡háganoslo saber respondiendo a este tema!


Objetivos

  1. Introducir ‘lanzamientos’ más regulares para Discourse, que proporcionen un equilibrio entre la velocidad de desarrollo y la estabilidad.

  2. Continuar proporcionando aproximadamente lanzamientos cada 6 meses, que se admitan durante un período prolongado.

  3. Proporcionar soporte superpuesto para lanzamientos regulares y de soporte extendido, de modo que los administradores tengan más flexibilidad sobre el momento de las actualizaciones, mientras continúan recibiendo actualizaciones críticas de seguridad.

  4. Mantener la ceremonia en torno a los ‘lanzamientos’ al mínimo. En la medida de lo posible, se automatizará y no ralentizará la experiencia del desarrollador principal. Los lanzamientos ESR son iguales que cualquier otro lanzamiento.

  5. El nombre y el procedimiento deben coincidir con los estándares de la industria, de modo que sea más fácil de explicar a los desarrolladores y usuarios finales.

Descripción general de alto nivel

  • Realizar aproximadamente un lanzamiento por mes. La versión ‘principal’ es el año actual y la versión ‘secundaria’ se incrementa con cada lanzamiento. El número de versión de parche se incrementará para cualquier corrección retroportada.

    por ejemplo, el primer lanzamiento de 2026 sería v2026.0, el siguiente sería v2026.1, etc.

    Los lanzamientos recibirán correcciones críticas durante dos ciclos de lanzamiento completos. por ejemplo, el soporte para 2026.0 continuará hasta que se lance 2026.2.

  • Aproximadamente cada 6 meses, declarar uno de esos lanzamientos como Lanzamiento de Soporte Extendido (ESR). Las versiones ESR permanecen admitidas durante 2 lanzamientos después de que se declara el siguiente ESR.

    por ejemplo, si v2026.0 es ESR, y v2026.6 es el siguiente ESR, entonces el soporte de v2026.0 finalizará cuando se lance v2026.8. Suponiendo una cadencia mensual, eso sería una superposición de 2 meses en el soporte ESR.

  • Proporcionar correcciones críticas para latest, el lanzamiento más reciente, el lanzamiento anterior y cualquier versión ESR activa.

  • Renombrar la rama tests-passed a latest.

Ejemplo de gráfico de períodos de soporte durante un año:

gantt
    title Lanzamientos y Períodos de Soporte de Discourse (enero de 2026 - enero de 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

Implementación

  • Cada lanzamiento tendrá una rama creada a partir de latest. Estas estarán en un espacio de nombres y se conservarán indefinidamente. Por ejemplo, v2026.1 tendría una rama llamada release/2026.1.

  • Cada lanzamiento de parche se etiquetará. por ejemplo, v2026.1.0, v2026.1.1, etc.

  • El último lanzamiento se etiquetará como release. El último ESR se etiquetará como esr.

  • El lanzamiento anterior se etiquetará como release-previous. El ESR activo anterior (si lo hay) se etiquetará como esr-previous.

  • Para compatibilidad con versiones anteriores, las etiquetas que coincidan con los flujos de lanzamiento existentes se enlazarán a su equivalente nuevo más cercano. stableesr. betarelease. tests-passedlatest.

    Estas se considerarán obsoletas y nuestro objetivo será eliminarlas en el futuro. En particular, ‘beta’ es problemático porque da la impresión de que Discourse no está listo para producción.

  • En latest, el número de versión será la versión en desarrollo actual, con el sufijo -latest. por ejemplo, 2026.3.0-latest.

Proceso de lanzamiento automatizado

Cada mes, una acción de GitHub abrirá una nueva PR que contendrá un solo commit que incrementará version.rb en main a la siguiente versión -latest.

Una vez que un humano fusione la PR, otra acción de GitHub detectará que main se mueve a la siguiente versión -latest y creará una rama para el lanzamiento completado. Esencialmente, esta rama se convierte en un ‘candidato a lanzamiento’. Se abrirá otra PR automatizada contra la rama de lanzamiento con una actualización para eliminar el sufijo -latest de version.rb, y así ‘lanzarla’.

Por lo general, fusionaremos estas dos PR rápidamente. Pero tener PR separadas para crear y finalizar el lanzamiento nos da la opción de abordar cualquier problema en la rama 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'

Por separado, otro flujo de trabajo de acciones de GitHub observará cualquier commit retroportado a las ramas de lanzamiento. Cuando se encuentren, se generará una nueva PR para incrementar la versión de parche en esa rama. Un humano puede decidir cuándo fusionar esas PR.

Todas estas automatizaciones mantendrán automáticamente actualizadas varias etiquetas (release, release-previous, esr, esr-previous, además de los alias de compatibilidad con versiones anteriores).

Correcciones de seguridad

El flujo de trabajo de corrección de seguridad sigue siendo en gran medida el mismo, excepto que ahora necesitamos hacer las correcciones en dos de estos tres lugares nuevos:

  • latest

  • esr

  • esr-previous :new_button:

  • release :new_button:

  • release-previous :new_button:

(Recuerde, según la ilustración anterior, son solo dos de los tres porque esr-previous está admitido, el nuevo esr es el mismo que release o release-previous, y eliminamos el soporte para esr-previous cuando eso ya no sea cierto).

Al introducir una corrección de seguridad en latest, se moverá automáticamente una etiqueta latest-security-fix a ese commit. docker_manager se actualizará para monitorear esa etiqueta y solicitar a los administradores que actualicen. Esto nos permite lanzar y notificar sobre correcciones de seguridad sin necesidad de acelerar un incremento de versión.

Traducciones

En este momento, las ramas stable y tests-passed se pueden traducir en CrowdIn, y los resultados se integran regularmente. En el nuevo sistema, inicialmente planeamos que latest y release sean traducibles en CrowdIn.

Idealmente, para cuando release se convierta en release-previous o esr, las traducciones se habrán asentado. Si hay demanda de traducciones continuas de esas versiones, entonces eso es algo que podría considerarse en el futuro.

Compatibilidad de plugins/temas

El aumento del uso de flujos que no sean latest de Discourse aumentará nuestra dependencia del sistema discourse-compatibility. Por lo tanto, necesitamos algunas mejoras en el sistema de compatibilidad.

En lugar de usar un archivo .discourse-compatibility en main, podríamos admitir la compatibilidad implícita basada en ramas/etiquetas con nombres especiales. Esto debería ser mucho más fácil que hacer malabares con hashes de commit manualmente. Por ejemplo, un plugin podría tener ramas como:

  • d-compat/v2026.1
  • d-compat/v2026.2
  • d-compat/v2026.3
  • main (utilizado para cualquier versión de Discourse que no tenga su propia rama)

Al instalar un plugin, Discourse puede buscar una rama que coincida con la versión actual. Si existe, la extrae. De lo contrario, consulta el archivo .discourse-compatibility. De lo contrario, extrae la rama predeterminada.

Podemos crear una acción pública de GitHub que se ejecute diariamente en cada tema/plugin, verifique nuevos lanzamientos de Discourse y cree automáticamente estas ramas. Cada tema/plugin podría optar por usar esta acción de fijación automática, o podrían optar por una estrategia más ‘flotante’.

Alojamiento de discourse.org

Inicialmente, nuestra oferta alojada continuará ejecutando la versión latest de Discourse. En el futuro, exploraremos opciones para que nuestros clientes de nivel empresarial seleccionen una versión de ‘lanzamiento’.

Valores predeterminados de instalación estándar

Inicialmente, el valor predeterminado seguirá siendo latest. Los administradores podrán optar por el nuevo flujo de lanzamiento de la misma manera que optan por stable en este momento. Es posible que exploremos cambios más fáciles entre los flujos de lanzamiento en el futuro, una vez que el sistema sea más maduro.

38 Me gusta

Estoy un poco confundido. Entonces, ¿tests-passed alias latest (que supongo que es el predeterminado) será el más actualizado (recibiendo las actualizaciones más frecuentes; sin cambios allí), pero la rama beta actual, ahora la rama release, seguirá comportándose como hasta ahora, es decir, un “grupo” de commits/actualizaciones, y luego la rama ESR (alias stable) será un “grupo” más grande de actualizaciones beta/release?

¿Significa esto que release se convierte ahora en la opción predeterminada, o cuando dices ‘última versión’ te refieres a ‘última actualización en la rama release’? ¿Habría entonces una diferencia entre esa y latest?

¡Gracias!

1 me gusta

beta es actualmente una etiqueta y no recibe correcciones retroactivas.

Con esta propuesta, cada versión publicada tendrá su propia rama y recibirá correcciones de seguridad mientras esté “soportada”. Las personas podrían elegir apuntar su instalación al número de versión específico y seguir usándola después de que se publique otra versión. Eso no es posible con las actuales beta o stable.

release será una etiqueta que seguirá la última versión publicada (incluidas las correcciones menores) para correcciones de seguridad.

No:

‘última versión publicada’ (o simplemente ‘release’) = el commit más reciente en la rama de versión más reciente

‘latest’ = el nuevo nombre para tests-passed

3 Me gusta

¡Gracias, eso lo aclara!

2 Me gusta

¡Esto parece un avance positivo!

¿Habrá alguna prueba específica de las actualizaciones de esr-previous a esr en el momento en que se etiquete esr? Argumentaría que dichas actualizaciones deberían organizarse para que sean actualizaciones fluidas o para tener buenas descripciones de cómo realizarlas de la manera más fluida posible.

4 Me gusta

Sí, las actualizaciones entre versiones ESR (o de hecho, cualquier versión compatible) seguirán siendo fluidas.

2 Me gusta

Solo una pequeña petición por conveniencia, ¿podría el puntero (por ejemplo, 2026.0) estar más bien ligado al mes en que se publica una versión? (Es decir, 2026.01 para enero, 2026.02 para febrero, etc.)

4 Me gusta

El problema de vincular explícitamente las cosas a un mes es que no podremos omitir un mes o lanzar dos versiones en un mes. Por eso, planeamos mantenerlo como un número incremental simple.

3 Me gusta

Un proyecto que uso mucho (mailcow) omite el mes cuando no hay cambios significativos en el núcleo.

Y contar desde 0 sería muy extraño. Tiene perfecto sentido para los programadores, pero no mucho sentido para las personas no técnicas.

2 Me gusta

Me preguntaba sobre la versión x.0 mencionada. Me gusta mucho vincularla al mes para poder saber de inmediato cuándo se lanzó una versión. Pero tal vez no importe si xx.8 se lanzó en septiembre, diciembre o junio. Sin embargo, apenas recuerdo en qué versión estamos ahora, así que sería muy útil poder saber de inmediato si alguien está hablando de un error de la semana pasada o de hace algunos meses sin tener que ir a buscar el commit como lo hago ahora.

Ubuntu tiene YY.04 y YY.10. Ha funcionado durante veinte años. Saltar meses no parece difícil.

Eso parece ser más un problema, aunque podrías hacer algo como 22.1a o 22.01a si tuvieras que tener dos lanzamientos en un mes.

6 Me gusta

Hace algún tiempo también empezamos a usar esta estrategia para nuestra plataforma. Exactamente lo mismo, incluyendo el branching y el patching. Puedo recomendarlo.

Usamos lanzamientos mensuales. Así que hay 1–12. El ritmo ayuda a todos. Siempre hay algo que lanzar (hola, dependabot) y nadie quiere cortar la rama dos veces al mes de todos modos. Además, cuando digo “uso 2025.6”, todo el mundo sabe que es el de antes de las vacaciones de verano.

7 Me gusta

En primer lugar, :rocket: ¡este es un gran paso!

Después de reflexionar un poco, tengo dos observaciones menores.

  1. git branch y muchas otras herramientas no entienden el versionado y ordenarán alfabética o numéricamente. En ambos casos, 2026.10 terminará entre 2026.1 y 2026.2. Inspirado por Ubuntu, propongo introducir un cero inicial para las versiones y subversiones cuando solo tengan un dígito, de modo que tendríamos v2026.01, v2026.02 y v2026.10 y entonces el universo estará feliz de nuevo.

  2. El nuevo método de compatibilidad de plugins parece excesivamente complejo y muy frágil.

Así que si creo una nueva función en mi plugin que necesita v2026.3, creo una rama y pongo mi nueva funcionalidad allí. Ahora que la función ha sido creada y mi cliente está contento, puedo descansar y disfrutar de mis vacaciones :palm_tree: :wine_glass:. Sin embargo, después de mi tercera copa de vino, decides lanzar v2026.4 y mi cliente decide actualizar. Y ¡puf!, no hay una rama v2026.4 en mi plugin y la funcionalidad desaparece :sob:

Así que nunca usaría esto y preferiría seguir usando .discourse-compatibility en su lugar.

9 Me gusta

La intención es la inversa. Las ramas de compatibilidad son solo para ramas ‘lanzadas’ de Discourse. Discourse latest siempre usará main de tu plugin. Ahí es donde desarrollarás nuevas funcionalidades.

Así que la historia sería:

Discourse lanza v2026.2. Las acciones de GitHub en tu plugin lo detectan automáticamente y crean una rama d-compat/v2026.2. Ahora, cualquiera que use Discourse v2026.2 usará la versión d-compat/v2026.2 de tu plugin.

Lanzas una nueva funcionalidad en main de tu plugin. No necesitas pensar en la compatibilidad hacia atrás, porque la rama main solo la usan las personas que ejecutan Discourse latest.

Luego, mientras te tomas tu tercera copa de vino :wine_glass:, Discourse lanza v2026.3. Inicialmente no hay una rama de plugin para esta versión, por lo que se usará main. Las cosas seguirán funcionando como lo hicieron para las personas en latest.

En cuestión de horas, tu acción de GitHub detecta la nueva versión y congela d-compat/v2026.3, lista para que tu próxima funcionalidad de plugin llegue a main sin preocupaciones de compatibilidad hacia atrás.

Este es esencialmente el flujo de trabajo que usamos en CDCK para manejar la compatibilidad estable de temas/plugins. Después de cada lanzamiento estable, tenemos un script para revisar nuestros cientos de temas/plugins y congelarlos a través de .discourse-compatibility. Esta propuesta basada en ramas tiene como objetivo ser una versión más ligera de ese flujo de trabajo.

16 Me gusta

Eso es increíble, gracias por la explicación detallada.

Parece que puedo tomar una cuarta copa de vino :wink:

15 Me gusta

Secundando lo que otros han dicho, me gusta la dirección de los cambios propuestos. Y creo que los nombres de rama propuestos son mucho más intuitivos que los antiguos :+1:

Lo que aún no me queda del todo claro es cómo funcionará el proceso de actualización para las ramas release y esr (la latest parece sencilla). Ustedes mencionan que, en cada momento, se admitirán tanto la versión actual (n) como la anterior (n-1), y que, como administrador, tendré la opción de cuándo actualizar.

Ahora, basándome en mi experiencia con otro software, cuando llega una nueva versión (n+1), se me notifica de la disponibilidad de la versión n+1. Y que entonces podría decidir hacer una actualización mayor (equivalente a, por ejemplo, apt dist-upgrade en Linux) o hacer una actualización menor/estándar (equivalente a, por ejemplo, apt upgrade en Linux) y permanecer en la versión n. ¿Es algo que se incorporará al script del lanzador de Discourse?

Además, entiendo el deseo de mantener la ceremonia/proceso de lanzamiento al mínimo, pero mi intuición sería que tanto las versiones normales como las esr reciban al menos un poco de pruebas adicionales, antes de ser lanzadas. Eso podría deberse a haber trabajado demasiado tiempo en TI empresarial, sin embargo :smile:

Por último, me pregunto si los lanzamientos mensuales son en realidad “demasiado rápidos”. Ahora, eso es admitidamente subjetivo, pero a juzgar por mi propia experiencia en la gestión de cosas de TI de forma paralela como voluntario, es posible que no tenga tiempo para actualizaciones importantes cada mes. Y partiendo de eso, me preguntaba si podrían también facilitarles un poco la vida a ustedes como desarrolladores de Discourse simplemente lanzando trimestralmente, y no tener ramas esr separadas, sino solo ramas release.

4 Me gusta

Eso dificultará la vida de los desarrolladores de temas y complementos, porque en esa (esta) situación tendrás presión de tiempo para actualizar tus temas y complementos, y de lo contrario no tendrás ninguna actualización de seguridad. Una versión ESR eliminará esa presión.

4 Me gusta

No estoy seguro de seguir completamente. Mi entendimiento basado en las publicaciones anteriores era que la creación de una rama de versión de lanzamiento activaría automáticamente la creación de una rama de plugin para esa versión. Por lo tanto, mi suposición sería que fusionar release y esr en una sola también reduciría el esfuerzo para los constructores de plugins y temas, porque cada vez que necesites aplicar una corrección, tendría que aplicarse a menos ramas (tres en lugar de cinco). ¿Pero tal vez me estoy perdiendo algo?

2 Me gusta

No se trata de cuándo el autor del tema/plugin publica una solución, sino de cuándo el núcleo de Discourse tiene una solución de seguridad.

Según

la única diferencia entre release y esr es que esr recibe correcciones de seguridad durante 6 + 2 = 8 meses.

1 me gusta

Con las herramientas actuales del lanzador y esta nueva estructura de ramas, podrías tener control sobre el momento de la actualización haciendo algo como:

  1. Se lanza v2026.02
  2. Estableces version: release/v2026.02 en tu archivo app.yml
  3. Se lanza v2026.03
  4. Ejecutas una reconstrucción. Todavía obtienes 2026.02, con las correcciones de seguridad recientes.
  5. Cuando estés listo, cambias a version: release/v2026.03 en app.yml

Pero editar manualmente ese app.yml cada mes no es ideal, así que esperamos poder diseñar un sistema que haga el proceso más fácil de usar.

El proceso en el OP nos permite tratar las ramas como “candidatos a lanzamiento” antes de marcarlos realmente como un lanzamiento. No estoy seguro de si/cómo usaremos esa capacidad en esta etapa; creo que es algo que evolucionará a medida que nos acostumbremos al nuevo sistema.

Estamos tratando de encontrar un equilibrio entre la velocidad de desarrollo de Discourse y la estabilidad para las personas con personalizaciones extensas. Tener un retraso de más de 3 meses para que las funciones lleguen a nuestros clientes no es una opción. En todo caso, el lanzamiento mensual es un poco lento para nosotros. En este momento, todavía tenemos la intención de usar latest para la mayoría de nuestros alojamientos.

Pero, por supuesto, para las personas que alojan Discourse por sí mismas, entiendo el deseo de tener cambios menos frecuentes. Ahí es donde entran los lanzamientos ESR.

5 Me gusta

Depende del autor del plugin/tema. O pueden continuar con la estrategia actual, donde la rama main del plugin debe funcionar con todas las versiones ‘lanzadas’ de Discourse. O pueden usar la estrategia de ramificación automática, que facilita la compatibilidad, pero también significa que es posible que necesites hacer mucho ‘backporting’ en tu plugin en caso de correcciones críticas de errores/seguridad.

En cualquier momento dado, hay tres versiones “soportadas” de Discourse, más latest. Por lo tanto, las correcciones críticas deberán aplicarse en hasta 4 ramas.

3 Me gusta