¿Cómo mantener un control de versiones escalable del código en WordPress?
En WordPress, el control de versiones es la gestión de los cambios realizados en el código relacionado con plugins, páginas y otros componentes de tu sitio web.
Mantener un sistema de gestión de control de versiones bien estructurado y ser capaz de seguir el progreso y la evolución del código a lo largo del tiempo es una de las principales diferencias entre los expertos en WordPress y los aficionados.
De hecho, en White Canvas creemos que un gran y escalable control de versiones es la piedra angular de nuestra eficiencia. Sin un sistema de control de versiones sólido, no podríamos entregar nuestros proyectos tan confiablemente y consistentemente como lo hacemos.
En este artículo, vamos a explorar los fundamentos de nuestras metodologías de control de versiones y proporcionar algunas buenas prácticas que los desarrolladores de WordPress pueden aprovechar.
Aviso: el resto del artículo asume que estás familiarizado con Git, por lo que no dedicaremos mucho tiempo a profundizar en sus fundamentos. Si querés desarrollar buenas prácticas de control de versiones, Git es el sistema líder mundial de control de versiones y probablemente la mejor alternativa para que explores dada su amplia difusión.
Dado que esta es una guía para usar Git, “Git” y “sistema de control de versiones” se usarán indistintamente.
Los beneficios del control de versiones
Como recordatorio, estos son los principales beneficios de mantener un sólido sistema de gestión de control de versiones.
Seguimiento del progreso
Con Git, podés hacer cambios en los archivos mientras retenés todo el progreso realizado hasta ese punto en la versión anterior.
Los desarrolladores individuales pueden avanzar en aislamiento sin afectar el trabajo de otros.
Cuando los desarrolladores suben sus commits, otros desarrolladores del equipo tendrán acceso a su código dentro de Git.
Gestión de ramas
Git te permite gestionar copias del código principal (ramas) para editarlas en aislamiento y luego fusionarlas con el código principal para incorporar los cambios. Muchos desarrolladores WordPress (como nuestro equipo) utilizan GitFlow, un modelo alternativo de ramas de Git, como una solución universal de ramificación.
Revisión de código
Revisar el código es esencial para el aseguramiento de calidad, y Git ofrece integración con soluciones de revisión de código. Gerrit es una de las más populares, aplicando estándares y calidad de código para grandes equipos de manera descentralizada. Algunas soluciones de alojamiento en la nube como GitLab tienen soluciones de revisión de código integradas.
Integración continua
La integración continua es la práctica automatizada de fusionar ramas de características en la rama principal y probarlas de inmediato. Al utilizar CI, los desarrolladores pueden determinar rápidamente si los cambios realizados fallaron o tuvieron éxito y actuar en consecuencia.
Los pilares del control de versiones
Para dominar las estrategias de control de versiones de tu equipo, debés familiarizarte con los fundamentos y aprender buenas prácticas para su implementación. Para nosotros, los 3 pilares del control de versiones son los repositorios en la nube, las estrategias de ramificación y las estrategias de CI/CD.
Vamos a explorar cómo optimizar cada uno de ellos.
Repositorios en la nube
Hay varias alternativas de alojamiento en la nube para tu código WordPress, como GitLab, GitHub y Bitbucket. Además de albergar versiones de nuestro código, estos sistemas de alojamiento ofrecen múltiples funciones adicionales. Para determinar cuál es la mejor para tu equipo, debés comparar las características con tus necesidades específicas.
Por ejemplo, si tu equipo o tu cliente tienen contratado Jira para la gestión de proyectos, tiene más sentido usar Bitbucket debido a su integración directa para gestionar problemas, ramas, pull requests, etc. Si tu equipo usa Jira, Bitbucket es prácticamente la opción ideal.
Si la integración con Jira no es una preocupación y el proyecto requerirá integraciones complicadas de pipelines CI/CD, GitHub y sus acciones comunitarias pueden ser convenientes para tu equipo. Las acciones comunitarias permiten a tu equipo ahorrar recursos utilizando el trabajo previo probado y comprobado de otros para realizar procesos complejos como la creación de instancias de AWS y mucho más.
Finalmente, si tu proyecto requiere flexibilidad, integraciones, pipelines, gestión de problemas, proyectos dentro del mismo servidor de control de versiones y, en resumen, la navaja suiza del control de versiones, GitLab es la solución.
La siguiente tabla desglosa algunos de los beneficios principales de cada plataforma en la nube.
Plataformas de Git en la nube | Beneficios |
GitHub | • El repositorio más popular, con una comunidad en auge. • El historial de commits del equipo es visible. • Pull requests. • Seguimiento de problemas. • Notificaciones por correo electrónico para pull requests, fallas de pipelines, menciones, y más. • APIs ricas con excelente documentación. • Plan gratuito para equipos con repositorios privados ilimitados y colaboradores. • GitHub Actions ofrece varias opciones de automatización de flujos de trabajo y herramientas CI/CD. • Genial para documentación y comúnmente usado para colaboración. • GitHub puede ser un buen punto de partida para un equipo de desarrolladores eligiendo su repositorio. |
GitLab | • Historial de commits visible. • Pull requests. • Seguimiento de problemas. • Interfaz amigable. • Notificaciones por correo electrónico. • Pipelines CI/CD robustos y automatización de flujos de trabajo. • Ideal para equipos técnicos que no planean colaborar fuera de su organización. |
Bitbucket | • Plan gratuito para repositorios privados, con un límite de 5 colaboradores. • Incluye una REST API para construir aplicaciones de terceros. • Notificaciones por correo electrónico. • Historial de commits. • Pull requests. • Seguimiento de problemas. • Más características orientadas a gerentes y análisis. • Potencialmente la mejor opción para equipos usando JIRA u otros productos de Atlassian. |
Estrategias de ramificación
Una vez que hayas elegido una solución de alojamiento en la nube para Git, debés determinar la estrategia de ramas.
Si tenés algo de experiencia con el control de versiones y escuchás “estrategia de ramas”, probablemente te venga a la mente la imagen de abajo, que corresponde a una estrategia de ramas que Vincent Driessen creó hace más de 10 años en su publicación “A successful Git branching model“.
Este modelo se ha vuelto extremadamente popular en la última década, al punto que algunos equipos lo consideran el estándar de facto para estrategias de ramas modernas. La realidad es que, para algunos proyectos, su estrategia de ramas puede verse así, mientras que para otros, no. Sin embargo, recordemos que esta estrategia no fue construida para soluciones modernas o ágiles.
Git se utiliza principalmente para aplicaciones web, que se entregan continuamente y no se revierten. Los desarrolladores no tienen que soportar múltiples versiones de sus aplicaciones web, lo cual es contrario a la estrategia ideada por Driessen. Esta estrategia funciona de maravillas para algunos equipos; para otros, no.
Todo esto es para decir: al elegir una estrategia de ramas, debés considerar las necesidades de tu equipo para evitar caer en la trampa de buscar estrategias que sirvan para todo. Pensá en las necesidades del equipo en términos de ramas, estrategias de fusión, pull requests y cómo manejarás las implementaciones.
Con el tiempo, los miembros del equipo deberán emplear una combinación de teoría y experiencia para crear la solución perfecta para el proyecto.
Aquí hay 3 buenas prácticas que utilizamos para optimizar nuestra estrategia de ramas.
Mantener solo una rama principal.
Tener múltiples ramas “principales” (DEV, STG, PROD, main) crea problemas de mantenimiento a largo plazo. Eventualmente sufrirán desfasajes y conflictos, y será difícil saber qué características son parte de cada rama sin dedicar tiempo y esfuerzo a documentarlas. En resumen, un lío.
Lo que hacemos es mantener una sola rama principal y múltiples ramas de características, que contienen una sola tarea o función cada una.
Minimizar el tiempo que las ramas están activas.
Mantener las ramas vivas por demasiado tiempo también causa problemas de mantenimiento. Ramas más pequeñas con fusiones más pequeñas son más fáciles de gestionar. Acostumbrate a hacer commits y fusiones frecuentes en lugar de dejar que las ramas crezcan demasiado durante mucho tiempo. Hacé progresos atómicos.
Para nosotros, la mayoría de las ramas permanecen activas menos de una semana.
Fusionar e implementar desde pull requests.
Siempre fusioná desde pull requests, no localmente. De esta manera, todos pueden seguir el origen de la fusión. Lo mismo ocurre con las implementaciones: implementá desde pull requests o ramas de características.
Cuando hayas confirmado que todo funciona correctamente, entonces fusioná. De lo contrario, corrés el riesgo de introducir errores en la rama principal.
Estrategias de CI/CD
Definir cómo tu equipo subirá su código a los entornos PROD, STG y DEV es esencial. Lo que hacemos es configurar pipelines de integración continua y entrega continua (CI/CD). Podrás configurar estos pipelines desde cualquiera de las plataformas en la nube que mencionamos antes.
Estas son 5 de las buenas prácticas que usamos para optimizar nuestros pipelines de CI/CD:
Usar comandos específicos para el pipeline.
La mayoría de los equipos utilizan dependencias instalables a través de npm o Yarn. Muchos de ellos emitirán npm install en el pipeline, ignorando el comando npm ci mucho más eficiente. npm ci utiliza “package-lock.json” para instalar dependencias, lo que lo hace aproximadamente un tercio más rápido y no intentará actualizar ninguna dependencia en el proceso.
Configurar la caché y los artefactos.
Es una excelente manera de reducir los tiempos de cómputo del pipeline y mantener copias en caché de los artefactos que produce cada pipeline.
Siempre que sea posible, implementar mediante Git.
Dar prioridad a la implementación mediante Git. Podés, por ejemplo, conectarte a través de SSH al servidor y actualizar la rama. O podés hacer checkout del commit que quieras implementar a través de Git. A toda costa, evitá implementar con los comandos SCP o RSYNC, ya que carecen de la funcionalidad para informar a los miembros del equipo qué se modificó y qué permaneció igual.
Acostumbrarse a rebase, revert y cherry-pick.
Estos son los tres comandos más útiles para mantener las ramas. Si los usás a diario, sin embargo, algo anda mal con la estrategia de CI/CD del equipo.
Al manejar conflictos de fusión, ser práctico.
Los conflictos de fusión ocurren, pero cómo los manejás es crucial para la eficiencia del pipeline de CI/CD. Como regla general, elegí código ya productivo sobre código en desarrollo y código más antiguo sobre código más nuevo. Siempre podés volver atrás y resolver errores, pero romper algo que ya está funcionando causa todo tipo de problemas que querés evitar.
Además, recomendamos automatizar las dependencias del pipeline y las compilaciones de recursos para la optimización de pull requests y requerir una confirmación manual para implementar en los diversos entornos.
Git orientado a WordPress
Para WordPress en particular, podemos seguir dos caminos principales: versionar toda la instalación de WordPress y versionar solo el tema. Vamos a explorar ambos.
Versionar toda la instalación de WordPress
Con esta estrategia, usarás un archivo .gitignore muy permisivo para versionar toda la instalación de WordPress, como plugins, archivos centrales (wp-includes, wp-admin, etc.), y el resto de los archivos del proyecto necesarios, mientras ignorás todo lo demás.
Ignorarás directorios innecesarios, como uploads y otras carpetas que no deberían incluirse en la versión, como node_modules o la carpeta vendor generada por PHP Composer.
Para una idea de cómo estructurar este archivo, usá este archivo .gitignore recomendado por WPEngine.
Este método no requiere mucha explicación. Es el método más utilizado y solo requiere que ignores uploads y las dependencias de desarrollo.
Versionar solo el tema
La segunda estrategia implica versionar solo los archivos esenciales del tema mientras se ignora la instalación general de WordPress. Además de los archivos centrales, ignoraremos directorios como wp-content/uploads, node_modules, y vendor.
Para ideas sobre estructuras, revisá este archivo recomendado, también por WPEngine.
Si planeás usar esta estrategia, probablemente ya hayas versionado tu proyecto. En este punto, necesitás comenzar a ignorar archivos y directorios específicos.
Primero, creá tu archivo .gitignore o modificá el existente según tus necesidades. Luego, emití este comando en el directorio raíz de tu proyecto:
$ git rm -rf --cached
Esto dejará una copia local lista para un commit. Y eso es todo.
Para la próxima versión, necesitamos comenzar a honrar las limitaciones de nuestro nuevo .gitignore. A partir de ahora, solo vamos a commitear estos cambios, dejándonos con un commit en el que solo hay un archivo modificado (.gitignore) y varios archivos eliminados (los que ignoramos).
$ git add .; git commit -m “Updated .gitignore”;
Para esta estrategia, recordá tener los archivos centrales de WordPress en su lugar antes de aplicar el tema que guardamos. Podés descargar el archivo central de WordPress aquí y descargar por separado tu repositorio.
Ahora creá un enlace simbólico que conduzca desde el directorio donde estarán los archivos centrales hasta el directorio wp-content dentro de tu repositorio, reemplazando el wp-content original de WordPress.
En resumen
Git es la solución líder mundial en control de versiones, y todos los desarrolladores de WordPress deberían familiarizarse con él. Combinado con una excelente solución de alojamiento de código remota, conforman el dúo perfecto que tu equipo necesita para maximizar la eficiencia y hacer los proyectos.
La clave para usar Git en combinación con alojamiento en la nube es entender su funcionamiento interno y tener un plan sólido. Usarlo sin pautas adecuadas sobre quién puede commitear o sin estrategias claras de ramificación o gestión de CI/CD es una receta para el desastre.
Con esta guía, esperamos haber proporcionado una buena introducción al proceso continuo de desarrollar un excelente sistema de gestión de control de versiones que apoye las necesidades del equipo y garantice que el proyecto siempre esté avanzando.