Tag: CI

Cómo revisar y probar un Pull Request (PR) en GitHub, GitLab o Gogs

Hay gente que a día de hoy sigue sin entender la diferencia entre Git (herramienta de versionado) y GitHub (plataforma para alojar proyectos Git, ahora propiedad de Microsoft). Y mucho menos entiende el valor que aportan plataformas web como son GitHub, GitLab o Gogs, que añaden todo el valor social y de discusión sobre los cambios propuestos por otros desarrolladores o usuarios, permitiendo así el Desarrollo Colaborativo y auge que hoy en día presenta la filosofía de software Open Source.

Siendo así, vamos a aclarar que Git es una estupenda herramienta de versionado y sincronización de código, o cualquier fichero que no sea binario, permitiendo establecer la sucesión cronológica y relacionar los cambios entre sí para una control y revisión del avance de un proyecto.

Pero por otro lado Git solo, es bastante «cojo» por así decirlo. Las personas no nos relacionamos y trabajamos mediante protocolos o herramientas que llevamos instaladas y que nos permitan trabajar en equipo de manera eficaz 🤣. Es aquí donde entran las plataformas web que dan esa capa social que permiten a los desarrolladores y contribuidores al proyecto comunicarse, establecer criterios, marcar pautas, organizarse, revisar secciones de código… En este artículo nos vamos a centrar en el proceso de revisión de aportes de código Pull Request, abreviados y conocidos como PR.

Esquema básico del proceso de revisión:

Antes de empezar vamos a aclarar una serie de términos que creo que es conveniente definir. Lo primero explicar lo que es un Fork, que no es más que un clon de un proyecto cuya propiedad (en términos de administración) es de otro usuario u otra organización, pero permanece relacionado con su proyecto originario del que se hizo fork (normalmente se denomina al proyecto origen upstream). Y luego lo que es un Pull Request (de ahora en adelante PR), que es una petición que se hace al proyecto originario (upstream) para que incluya los cambios que tenemos en una de las ramas de nuestro repositorio «forkeado».

Entre el PR y la aceptación del mismo está lo que se conoce como discusión y revisión de los cambios propuestos. Los procesos de revisión son importantes porque permiten afinar los cambios, corregir metodologías de trabajo, realizar pruebas de integración con plataformas como AppVeyor o TravisCI… Podríamos decir que es el punto en el que se comunican las personas involucradas en la propuesta de PR.

Entrando en el terrenos práctico la discusión se genera en la sección de PR y es donde se produce toda la conversación. Aquí podéis ver un ejemplo:

https://github.com/RDCH106/pycoinmon/pull/5

Creo bastante evidente como se debate, ya que es como un foro en el que dependiendo de la plataforma (GitHub, GitLab o Gogs…) será más completo o menos.

La pregunta del millón es cómo probamos el código que está en el PR. No se encuentra en una rama del repositorio el PR, realmente se encuentra en la rama del que nos hace el PR (a donde podemos ir para probar los cambios). De hecho lo interesante es que el PR puede ir cambiando, si el autor del PR en su fork, en la rama que usó para el PR, realiza cambios. Es decir, un PR no es un elemento estático sujeto a un commit concreto, sino que es la referencia a una rama del proyecto fork que contiene cambios que el upstream no tiene. El truco reside en que comparten la misma base de código y los cambios del PR son la diferencia entre la rama del proyecto upstream al que se le propone el PR y la rama del proyecto fork que contiene los cambios.

Pero esto es una verdad a medias… y digo a medias porque un PR sí es una rama, realmente es una referencia en el repositorio remoto (donde hacemos pull y push). Y eso es bueno 😁. La referencia entre un fork y su upstream nunca se rompe de manera oficial (existen por ejemplo mecanismos en GitHub para solicitar que un fork de un proyecto deje de estar relacionado con su upstream), por lo que asumiremos que un fork es como un padre y un hijo, pueden no llevarse bien pero eso nunca hará que desaparezca la relación parental padre-hijo. Cada vez que la rama del fork desde la que se hace PR se actualiza, la del proyecto upstream también queda actualizada. Por eso resulta conveniente usar ramas para hacer PR de diferentes features (características) que vamos a desarrollar, ya que así podremos mantener de manera independiente ambos paquetes de trabajo sin que haya interferencias entre ellos, y pudiendo dejar la rama el tiempo que haga falta hasta que finalmente se incluyan los cambios al proyecto upstream.

A causa de lo comentado antes podemos revisar desde la consola las referencias remotas con las que cuenta un proyecto git con el comando «git ls-remote«. Voy a usar el proyecto pyCOINMON como ejemplo totalmente práctico:

rdch106@RDCH106 MINGW64 /d/GIT/pycoinmon (develop)
$ git ls-remote
From https://github.com/RDCH106/pycoinmon.git
be75cbb0e449383fd42c9033a8b76c844fcfef17        HEAD
d01ecf133c342f490030b56066ed8ff18b36f124        refs/heads/develop
be75cbb0e449383fd42c9033a8b76c844fcfef17        refs/heads/master
ec9c10b6d88274a1a006ae139856de478876572c        refs/pull/1/head
c0cb91e1776632494a23cf181584c1903516a758        refs/pull/11/head
46f2e6db3d22a4a48dcf3680157c95641123095d        refs/pull/2/head
035e64652c533a569c6b236f54e12aff35ad82b1        refs/pull/3/head
0f08bd644912e7de4a3bc53e3a8d0dbd64d6fc34        refs/pull/4/head
87ef8ca9af3eb5a523d3ef532fccee91aeedcd44        refs/pull/5/head
896d697e846649c7f23b9af3430067451ab5c089        refs/pull/7/head
d57455a8acf719cd3acea623f0759c6e11baada1        refs/pull/7/merge
d6f4c5a4b3e2b0025d74e9feed2609ba50835950        refs/tags/v0.1.0
be413f410cfa23e1f0f2715f2714874a22757b0d        refs/tags/v0.1.0^{}
cdc5e356b6d7f829e83a1b0a25e2a7304844223b        refs/tags/v0.1.4
4b69c059196f1f41bafc4f5970afb8a34817b509        refs/tags/v0.1.4^{}
b5649af39db2738481751f07b6ad59585144dbd0        refs/tags/v0.2.4
c3506ed1289f3dbcddb2db68201a114a9d1cf8b3        refs/tags/v0.2.4^{}
f0c564d2617d42c0fcb3cb842122a214a6021d37        refs/tags/v0.2.6
a3fe8f8b788311c1d4f5ee906cf2a4c70ffac8db        refs/tags/v0.2.6^{}
cea535e4e663531454b437ee8d7976a06e1ae415        refs/tags/v0.2.8
080192d1d7eb33feed6b92df2b389b39592545a6        refs/tags/v0.2.8^{}
9c374d2031a9da655be44e0c79944166cbf99e8a        refs/tags/v0.3.2
f76f78252863d372fde5d6ff197ba7519f7da50b        refs/tags/v0.3.2^{}
cc248bbd64f177a9b6041cad7c269b880c21b355        refs/tags/v0.3.5
fd50d344575e54def4b841221b2b5c2e8a0a74e3        refs/tags/v0.3.5^{}
7727986a93ce65c2deb905fcd92718c43f3e61ca        refs/tags/v0.4.0
aa2df260dc9c1ae9c1aa88ddd7d2498b451bf0fc        refs/tags/v0.4.0^{}
a620d5e379d495c69926d97a33803e91b3c07783        refs/tags/v0.4.4
d0b3fa9ae73a15ff17a47804fbbac80245c028c1        refs/tags/v0.4.4^{}
f12102dfacc530f90600082a97a0533ba862bd2c        refs/tags/v0.4.7
4329b9f5a9782071fe661376225df6d8d6dfa47e        refs/tags/v0.4.7^{}
1d3dbf367ab319f0d9a515c007ff07b90de6ca1c        refs/tags/v0.4.8
d01ecf133c342f490030b56066ed8ff18b36f124        refs/tags/v0.4.8^{}

Nos vamos a centrar por ejemplo en el PR #7 que es uno de los que tenemos abiertos y cuyos cambios supongamos que queremos probar:

Lo que vamos a hacer es traernos los cambios del PR basándonos en su ID (en nuestro caso #7), creando una nueva rama (PR_7) para poder probarlo por separado:

rdch106@RDCH106 MINGW64 /d/GIT/pycoinmon (develop)
$ git fetch origin pull/7/head:PR_7
remote: Enumerating objects: 7, done.
remote: Counting objects: 100% (7/7), done.
remote: Total 10 (delta 7), reused 7 (delta 7), pack-reused 3
Unpacking objects: 100% (10/10), done.
From https://github.com/RDCH106/pycoinmon
 * [new ref]         refs/pull/7/head -> PR_7

Ahora sólo resta hacer un checkout a PR_7:

rdch106@RDCH106 MINGW64 /d/GIT/pycoinmon (develop)
$ git checkout PR_7
Switched to branch 'PR_7'

O hacerlo desde el maravilloso SourceTree el cual os recomiendo como herramienta profesional para la gestión de vuestros repositorios Git locales y remotos (si eres usuario GNU/Linux no me olvido de ti, te recomiendo GitKraken).

A partir de aquí ya es hacer lo que quieras. Puedes probar los cambios, hacer algunas pruebas, hacer un «merge» para incluir los cambios en otra rama o incluso en la propia rama master.

En lo que a mí respecta, recomiendo simplemente probar los cambios y en la zona de discusión que comentaba antes, realizar todas las apreciaciones necesarias y dejar las cosas lo más claras posible, siendo responsabilidad del desarrollador que hizo el PR realizar los cambios para evitar conflictos. Una vez esté todo correcto, también recomiendo realizar el merge desde GitHub, GitLab o Gogs

Además todo este proceso forma parte del aprendizaje y democratización de los conocimientos, haciendo de cada PR un sitio al que se puede volver para aprender y revisar lo ocurrido gracias a la trazabilidad en la discusión de los cambios.

Personalmente los procesos de revisión es una base estupenda junto al Planning Poker (prueba https://scrumpoker.online), para igualar las habilidades y competencias que permiten acortar divergencias entre las estimaciones de un grupo de desarrollo ante la planificación de las cargas de trabajo. Yo personalmente soy partidario de que el que lanzó la estimación más alta en la partida de poker realice el paquete de trabajo para que baje su estimación y aumenten sus habilidades, gracias a la supervisión (revisión) de quien dio la cifra más baja, que se asume que dio una estimación más ajustada por unas habilidades mayores.

Integración Continua en GitHub con AppVeyor (parte 2)

En esta segunda parte, Jorge nos amplía y completa un poco más la anterior entrada sobre la Integración Continua con AppVeyor, para mostrarnos cómo generar y publicar una release automáticamente.


 

Generación del artefacto

Lo primero que será necesario es configurar un «artifact», que sera lo que se haga «push» hacia GitHub, para ello, en la pestaña «SETTINGS» en el menú «Build», haremos que los resultados que nos interesen se añadan a un .zip, creando un «After build script», en el cual meteremos los binarios que nos interese. Previamente a eso, vamos a indicarle en la parte superior, que queremos que la compilación utilice «debug» y «release».

El script:

7z a PostAppVeyor_%configuration%.zip %APPVEYOR_BUILD_FOLDER%\%APPVEYOR_PROJECT_NAME%\bin\%configuration%\*.exe

Añadirá todos los .exe que haya en la carpeta al fichero que indicamos, en caso de necesitar añadir otros ficheros o librerías, se podría indicar cambiando el patrón de búsqueda o poniendo rutas absolutas.

Con esto, AppVeyor va a generar el .zip, ahora sólo queda hacer que sea público como resultado de la compilación. Para eso, en la pestaña «SETTINGS», en el menú «Artifacts», lo creamos mediante el botón «Add artifact».

Seleccionando el .zip que se ha generado mediante el script, se le pone un nombre con el cual publicarlo en AppVeyor (hay que tener en cuenta que AppVeyor borra todos estos archivos a los 6 meses).

 

Publicación del artefacto

Después de todo lo anterior, sólo nos queda publicar los binarios en el apartado de «Release» de GitHub cuando nos interese. Para ello, lo primero de todo, necesitamos generar un token en GitHub para AppVeyor. Esto se hace desde el perfil , en el apartado «Settings/Developer Settings/Personal Access Tokens» pulsando en «Generate new token».

Tras darle un nombre, los permisos que necesitamos asignarles son simplemente «public_repo» y pulsar en «Generate token».

Esto nos genera un código alfanumérico, que debemos copiar, ya que lo necesitaremos en AppVeyor para configurarlo.

Una vez tenemos el token, nos vamos a AppVeyor y en la pestaña «SETTINGS» en el menú «Deployment», seleccionamos «Add deployment».

En el desplegable, hay que seleccionar «GitHub Releases». Cabe destacar que vamos a configurarlo para que sólo se publiquen como release los «Tags» del repositorio en la rama master. Para eso, vamos a configurar los parámetros de publicación que se ofrecen, teniendo especial cuidado en añadir una condición que sera «APPVEYOR_REPO_TAG» = true, para que sólo las etiquetas se suban a GitHub Release. Un ejemplo de como configurarlo seria el siguiente:

Una vez todo listo, solo nos queda crear un tag en nuestro proyecto, y pushear el tag a Github, esto iniciará el proceso, y cuando acabe, se podrá ver el resultado en el apartado «releases» del repositorio de GitHub.

 

Con esto queda cerrado el ciclo de despligue que junto a la entrada anterior sobre integración y testeo continuo, nos permite llevar nuestro código a cotas de calidad de desarrollo muy altas, preparando a su vez el proyecto sofware para poder gestionarlo cómodamente y de manera segura ante eventuales contribuyentes.

 

Integración Continua en GitHub con AppVeyor (parte 1)

En esta ocasión tengo el gusto de presentar a Jorge, un excelente compañero de trabajo y un grandísimo profesional. En su día a día siempre anda buscando la mejor forma de hacer las cosas y en esta ocasión nos trae un detallado tutorial de Integración Continua, ámbito en el que recientemente se ha sumergido, y del que hoy nos presenta unas pildoritas de sabiduría y buen hacer.


GitHub, con todo el revuelo que ha provocado la compra por parte de Microsoft, es uno de los mayores repositorios de código que existen, y el mayor de código libre. Dispone de múltiples herramientas que ayudan al desarrollo de aplicaciones y testeo de aplicaciones que en muchos casos no son explotadas, lo cual es una lástima ya que son gratuitas (siempre que tu repositorio sea público) y aportan una gran ayuda.

En esta entrada vamos a hablar sobre una de esas herramientas llamada AppVeyor, ¿y que es AppVeyor? Es una herramienta de integración continua que permite realizar compilaciones, ejecutar teses, y publicar binarios, todo ello con unos pocos clicks gracias a su alta integración en GitHub (y encima gratuito si tu repositorio es público).

Llegados a este punto, se puede pensar, ¿qué me puede aportar a mi todo eso? La respuesta es sencilla, si tienes algún repositorio en el que colaboras con más gente, siempre sabréis que los cambios van a compilar, y en el caso de que tengáis test unitarios, que los ha pasado, y además de todo eso, publicar las «release» si así lo queréis. Vale, ahora pensarás, yo soy un desarrollador independiente, que no comparte repositorios, y tampoco me preocupo en sacar ninguna «release», ¿en qué puede ayudarme a mi? Fácil, puedes configurar diferentes «build» para diferentes entornos, y probar que tu código es perfectamente funcional en varias plataformas y versiones sin necesitar disponer de esas máquinas para compilar en ellas.

 

Compilación

¿Te he convencido? Pues vamos a ver como podemos configurar esta herramienta para nuestro repositorio. Lo primero es registrarnos en su web (algo muy fácil usando nuestra cuenta de GitHub).

Con sólo eso, ya estamos registrados, y llegamos a nuestro «dashboard», que por el momento estará vacío, pero vamos a solucionarlo pulsando en «NEW PROJECT» .

Para este ejemplo, he creado un repositorio en mi perfil llamado PostAppVeyor, el cual aparece automáticamente, y simplemente hay que pulsar en «ADD».

Ya tenemos nuestra integración lista, aunque de momento no haya hecho nada, veamos qué pasa si pulsamos en «NEW BUILD».

Pulsando esto, se lanzará una compilación que se puede seguir desde «LATEST BUILD».

Un detalle importante, es que al haber añadido AppVeyor al repositorio, se establecen automáticamente los WebHooks para notificar a GitHub los resultados, y si miramos el historial de commits del repositorio, se puede ver el resultado.

Esto también se aplica automáticamente para los «Pull Request», de modo que siempre se comprobarán las modificaciones que haya sobre el repositorio.

 

Test unitarios

Vale, el repositorio compila, ¿cómo añado los teses? Otra respuesta fácil, AppVeyor es capaz de detectarlos automáticamente. Añadamos un test al proyecto y veamos que pasa al «pushearlo» a GitHub. Automáticamente se inicia una compilación pero… ha fallado, ¿por qué?, si en Visual Studio pasaba el test sin problemas…

Vale, esto es debido a que los teses unitarios de Visual Studio, necesitan descargar paquetes NuGet. Vamos a solucionar esto yendo a la pestaña «SETTINGS» y al menu «Build». Hay que buscar «Before build script» para añadir un evento previo a la compilación, que haga un «nuget restore», tras esto, basta con pulsar en «Save» y ya estaría listo.

Ahora que tenemos todo lo necesario, vamos a volver a probar (Mediante el botón «RE-BUILD» del resultado que ha fallado) y ¡sopresa!, ya funciona correctamente.

Pero espera… a mi no me dice eso. Mis teses no se ejecutan, ¿qué pasa? Bueno, es posible que tu proyecto este hecho en un Visual Studio superior al que usa por defecto (2015), y el descubrimiento de teses unitarios no haya funcionado del todo bien, esto podemos solucionarlo rápidamente seleccionando la versión de Visual Studio que vamos a utilizar (en mi caso 2017). Volviendo a la pestaña «SETTINGS», pero esta vez en el menú «Environment», seleccionando Visual Studio 2017 y damos a «Save».

Veamos el resultado ahora pulsando en «RE-BUILD»…. ¡¡¡Premio, nuestros teses ya se ejecutan!!!

Con todo lo que hemos hecho hasta ahora, tenemos un repositorio que comprueba automáticamente si el código compila correctamente, y ademas ejecuta los teses unitarios para comprobar que sigue cumpliendo con el funcionamiento esperado.

En la próxima entrada veremos cómo generar y publicar las «releases» a partir de nuestro código compilado y testeado.