Hola (y una introducción al bot Raku CI)

¡Hola!
Soy Patrick Böker, patrickbkr en GitHub, patrickb en IRC. Soy un desarrollador de software que vive en Alemania, cerca de Stuttgart. He incursionado en muchos lenguajes de programación y pilas de tecnología diferentes. Profesionalmente, trabajo principalmente con Java, VB.net, VBA y Raku. En mi tiempo libre estoy involucrado en el desarrollo del propio lenguaje de programación Raku.

Planeo escribir sobre cualquier tema relacionado con TI que creo que vale la pena compartir, pero como actualmente estoy más involucrado en el idioma Raku, espero escribir principalmente sobre cosas relacionadas con él, pero no se sorprenda si una publicación cubre algunos Otro tema se desliza.

Estuve recientemente concedido una subvención como parte de la Fondo de desarrollo de Raku por la Fundación Perl para trabajar en la tubería de Integración Continua (CI) del compilador Rakudo. Raku * do * es el nombre bastante apropiado del compilador y el tiempo de ejecución que ejecuta Raku y actualmente se desarrolla al unísono con el lenguaje mismo. Intento no confundir los dos, Raku y Rakudo, pero fallaré de vez en cuando, así que no se confunda demasiado cuando los use incorrectamente. Publicaré sobre mi progreso en ese proyecto aquí.

El resto de esta publicación es una introducción a ese proyecto.

Todo empezó con un asunto en nuestro querido repositorio de resolución de problemas. Ese repositorio es la herramienta mediante la cual se discuten, revisan y aprueban cambios más importantes en el lenguaje Raku y temas relacionados. Esto es parecido a PEP en Python o JEP en Java.

Ese problema establece que el proceso de desarrollo de Rakudo tiene un conjunto de deficiencias que más de una vez resultaron en lanzamientos rotos y en nuestro CI fallando en el maestro por períodos de tiempo más largos. Eso duele.

Las deficiencias de nuestro proceso incluyen:

  1. Nuestro CI solo cubre un pequeño conjunto de entornos
  2. El CI no es del todo confiable
  3. Hay flappers en nuestra suite de pruebas
  4. Las personas pueden impulsar cambios directamente para dominar, a veces rompiéndolos

El software que pretendo escribir como parte de la solución se llama RakuCIBot o RCB para abreviar. Así que abordemos los problemas uno por uno.

1. Nuestro CI solo cubre un pequeño conjunto de entornos

La comunidad de Raku no tiene los recursos financieros ni la mano de obra para configurar y encargarse de una solución de CI personalizada en nuestros propios servidores. Por lo tanto, intentamos hacer uso de las ofertas gratuitas que algunos proveedores de CI brindan amablemente a los proyectos de código abierto. No es estrictamente necesario que la solución sea gratuita, es posible que podamos montar un costo mensual moderado para una oferta de CI, pero existen ofertas gratuitas para proyectos de código abierto, por lo que tiene sentido optar por las soluciones gratuitas. Nuestro CI, tal como está actualmente, se basa únicamente en Microsofts Azure CI, ya que ofrecen agentes que ejecutan los tres sistemas operativos principales (Windows, Linux y MacOS) y actualmente no imponen límites de recursos a los proyectos. Anteriormente usamos TravisCI, AppVeyor y CircleCI, pero ninguno de ellos es compatible con los tres sistemas operativos principales y no imponga límites de uso. (Algunas de esas integraciones de CI más antiguas aún no se han cerrado, pero planeamos hacerlo pronto).

Cuando se desarrolla un lenguaje de programación que interactúa directamente con y abstrae las API de bajo nivel del sistema operativo y (en el caso de nuestro compilador JIT) incluso el hardware en sí, uno quiere cobertura de todo el hardware, sistemas operativos y bibliotecas en las que podemos ejecutar. . Nuestro CI actual, que solo se ejecuta en x86-64 y solo en Windows, Linux y MacOS, no es suficiente. Queremos probar, entre otros, y sin ningún orden en particular:

  • OpenBSD
  • AIX
  • SystemZ
  • ARM (especialmente ahora que Apple pasó a ARM)
  • musl (usado en Alpine Linux que es muy popular en contenedores)
  • glibc 2.17 (esa es la versión más antigua en uso en una disto importante: CentOS 7)
  • Algo Debian-y
  • Algo RedHat-y

Actualmente no existe una oferta de CI que brinde soporte para todos estos. Especialmente las plataformas de hardware más raras son difíciles de encontrar. Sin embargo, hay una excepción bastante extraña. los Servicio de compilación abierta, desarrollado y alojado por SUSE, proporciona una infraestructura de compilación de uso gratuito (¡y de código abierto!) que se utilizará para compilar paquetes para una variedad de distribuciones de Linux en una amplia gama de plataformas de hardware. La OBS no es una plataforma de CI, está pensada para ser utilizada para construir (e implementar) paquetes de distribución. Pero técnicamente ejecuta pruebas como parte de su trabajo normal de creación de paquetes y tenemos la aprobación para convertir el servicio OBS en una plataforma CI para Rakudo.

Entonces, el plan es confiar en dos ofertas de CI, AzureCI para MacOS y Windows, y OBS para Linux en todo tipo de diferentes distribuciones de Linux y plataformas de hardware.

Los proyectos centrales de Rakudo utilizan Git y GitHub para la gestión del código fuente. Por lo que es deseable tener el CI integrado en GitHub. Las API de OBS dificultan su uso como CI directamente y no ofrecen ninguna integración en GitHub (recuerde: OBS no se enfoca en ser una plataforma CI actualmente), por lo que necesitamos un software que actúe como intermediario y lo haga. la flexión que es necesaria para usarlo como tal. Esa es una de las tareas que debería realizar el RCB que planeo desarrollar.

Debería ser posible extender RCB para probar también en otras ofertas de CI. SourceHut (es un servicio de pago), por ejemplo, nos daría soporte para varios BSD.

2. El CI no es del todo confiable

Todos los IC que hemos utilizado hasta ahora han fallado ocasionalmente por razones no relacionadas con las pruebas reales. Las razones incluyen que la plataforma de CI está fuera de línea y las API de GitHub no están disponibles temporalmente para el proveedor de CI. Como los proveedores de CI no suelen reintentar una compilación una vez que falla, tales fallas son molestas. Alarman a los autores de un problema en el que no hay ninguno o impiden que se fusione un PR. La única solución que se me ocurre es presentar un intermediario que actúe como un Cola de mensajes. Esa es otra tarea que debería realizar el RCB. Debería poder recibir notificaciones push de las respectivas API de GitHub y los backends de CI para mantener el procesamiento de CI receptivo, pero también para que los cambios sean resistentes a las consecuencias temporales. Debe centrarse en asegurarse de que RCB no pierda o pierda mensajes accidentalmente. De lo contrario, tendremos un sistema tan poco confiable como antes, pero más complejo.

3. Hay flappers en nuestra suite de pruebas

Los Flappers son pruebas en nuestro conjunto de pruebas que no son del todo fiables. Esta prueba es, por alguna razón, a veces falsamente negativa. Cuanto más rara sea la prueba sin éxito, más difícil será reproducirla y corregirla. Preferiblemente queremos arreglar los flappers, pero a veces no es posible hacerlo fácilmente (la falta de mano de obra es la razón habitual). Así que debemos asegurarnos de que los flappers no dañen el IC. La solución simple es volver a ejecutar una ejecución de CI si falla. Eso ayudará con la estabilidad de nuestro CI, pero es contraproducente para arreglar realmente los flappers. Cuando, en el caso de una ejecución de CI fallida, simplemente volvemos a ejecutar las pruebas y no hacemos nada más, básicamente ocultamos un error. Ocultación de errores, también conocido como CATCH { #`[Just ignore.] }, es un famoso anti-patrón debemos esforzarnos por evitar. Entonces, lo que haremos en su lugar es configurar una lista, donde los flappers se guardan manualmente como un libro. RCB lee esa lista y solo se vuelven a ejecutar las fallas de CI que coinciden con uno de los flappers señalados. Además, RCB realizará un seguimiento de las fallas de cada flapper para que podamos tener una idea de la frecuencia con la que chocan los flappers e idealmente obtener una pista para solucionarlos.

4. Las personas pueden impulsar cambios directamente para dominar

Solo permitiremos enviar cambios al maestro que se hayan probado con éxito mediante CI mediante una solicitud de extracción (PR). Un PR es una cosa de GitHubby donde uno propone un cambio para revisión / prueba de CI y que se puede fusionar en un paso separado. Para que este flujo de trabajo funcione, es absolutamente necesario que nuestro CI sea confiable; de ​​lo contrario, los RP pueden y serán bloqueados por resultados de CI falsos negativos, proporcionando una fuente inagotable de molestias para nuestros queridos desarrolladores. No queremos eso. Ya estan atormentado en nombre de nuestros usuarios. Deberíamos evitarles torturas adicionales con la infraestructura.

Para aliviar el dolor de un proceso más complejo de obtener cambios en la rama maestra, quiero que el RCB combine automáticamente los RP cuando se le solicite (a través de una palabra mágica en un comentario del RP) y las pruebas de CI sean exitosas. Entonces, un remitente de relaciones públicas no necesita volver a visitar su relaciones públicas más tarde para fusionarlas.

Para reducir las posibilidades de dificultades imprevistas lo antes posible, traté de abordar primero las partes de este proyecto con el mayor potencial de problemas. En mi experiencia, los componentes externos fuera de mi control son los que causan más problemas. Los componentes externos de RCB son los backends de CI, a saber, AzureCI y OBS y GitHub. Así que comencé por mirar esos primero.

Interfaces: GitHub

Las interfaces de GitHub me dieron el menor problema de las tres. Hay algunos buena documentacion que incluso incluye un tutorial sobre cómo integrar un servidor CI y ya hay un Biblioteca de API Raku GitHub. Empecé a ampliar la funcionalidad de esa biblioteca para admitir también la Cheques y Tira API. Aún no he terminado con ellos, hay más por implementar, por ejemplo, extender el Asunto API para respaldar los comentarios y la implementación de soporte para webhooks.

Interfaces: AzureCI

los Documentación de AzureCI es bastante desordenado. En alguna parte, eso seguramente se debe al enorme alcance que cubren los servicios de Azure. Pero no obstante, me resulta difícil obtener la información que me interesa. El subproyecto relevante de Azure es Azure Pipelines, que es parte de Azure DevOps. Una información específica que casi había pensado que era imposible de obtener son los registros de compilación del individuo trabajos en un escenario. Finalmente descubrí que la única (?) Forma de acceder a esos registros es a través del API de línea de tiempo. Esa API devolverá los bits individuales del registro de un construir (que normalmente se compone de varios trabajos que se ejecutan en paralelo) en orden temporal. Usando las identificaciones principales que contiene cada bit de registro individual (no están documentadas en absoluto) es posible reconstruir los registros de compilación de los trabajos individuales tal como se ven en la interfaz web (ese enlace estará muerto en unas pocas semanas, simplemente ignórelo).

De lo contrario, creo que todos los bits necesarios para controlar las canalizaciones de AzureCI están ahí. Espero que ahora sea un SMOP – en el sentido literal.

Interfaces: OBS

OBS tiene un API. Es bastante sencillo y pequeño. Sin embargo, es necesario comprender cómo funciona OBS para que la API tenga sentido, ya que literalmente se asigna a los flujos de trabajo en OBS. Además, es una API solo XML, JSON no es compatible. Existe una limitación desafortunada en cómo funciona OBS (y por lo tanto su API). En OBS no es posible recuperar el registro de compilación de un paquete aparte del más reciente. Esto tiene la consecuencia de que los trabajos de construcción tendrán que suceder en serie, uno tras otro, en lugar de en paralelo.

Arquitectura del núcleo

Ya desarrollé la arquitectura de la lógica central de la aplicación. Lo explicaré en una próxima publicación.

  1. Configure el marco de la aplicación. Eso incluye configurar una aplicación esqueleto con el material de configuración inicial para obtener una aplicación que no haga nada con algunas pruebas en funcionamiento, una canalización de contenedores y un script de implementación para enviarla a un servidor.
  2. Obtenga suficiente de la integración de GitHub funcionando para que RCB actúe como un backend de CI de GitHub.
  3. Consiga que la integración de OBS funcione.
  4. Desarrolla la lógica central.

Más por venir.