Ejemplo de implementación de Integración Continua con BuildBot

Ejemplo de implementación de Integración Continua con BuildBot
(Imagen por Computerizer from Pixabay)

¡Hola!

Me llamo Evgeny Cherkin, soy programador en el equipo de desarrollo en la empresa minera Polymetal.

Al iniciar cualquier proyecto importante, uno comienza a preguntarse: «¿Qué software es el mejor para su mantenimiento?». Un proyecto de TI pasa por varias etapas antes del lanzamiento de una nueva versión. Es bueno cuando la cadena de estas etapas está automatizada. El propio proceso automatizado de lanzamiento de una nueva versión de un proyecto de TI se llama Integración Continua. BuildBot y se ha convertido en un gran aliado que implementa este proceso.

En este artículo he decidido presentar una revisión de las capacidades BuildBot. ¿Qué puede hacer este software? ¿Cómo acceder a él y cómo establecer relaciones de TRABAJO EFECTIVAS con él? Puedes aplicar nuestra experiencia creando en tu máquina un servicio de construcción y pruebas para tu proyecto.

Contenido

Contenido

1. ¿Por qué BuildBot?
2. Concepto liderado por BuildMaster
3. Instalación
4. Primeros pasos

5. Configuración. Receta paso a paso

5.1 BuildmasterConfig
5.2 workers
5.3 change_source
5.4 shedulers

5.5 BuildFactory
5.6 builders

6. Ejemplo de configuración propia

6.1 En camino a mi master.cfg
6.2 Trabajo con svn
6.3 Has recibido un correo: los reporteros están autorizados para declarar

¡Lo logramos! Mis felicitaciones

1. ¿Por qué BuildBot?

Anteriormente he encontrado artículos en habr-e sobre la implementación Integración Continua utilizando BuildBot. Por ejemplo, este me pareció el más informativo. Hay otro ejemplo — más sencillo. Estos artículos se pueden complementar con un ejemplo del manual, y este además, en inglés. En conjunto resulta un buen punto de partida. Después de leer estos artículos, seguramente querrás hacer algo en BuildBot .

¡Espera! ¿Alguien realmente lo ha utilizado en sus proyectos? Resulta que sí, muchos se ha aplicado en sus tareas. Se puede encontrar ejemplos uso BuildBot también en los archivos de códigos de Google.

Entonces, ¿cuál es la lógica de las personas que utilizan Buildbot? Ведь есть другие инструменты: CruiseControl y Jenkins? Responderé así. Para la mayoría de las tareas Jenkins realmente será suficiente. Por otro lado, BuildBot es más adaptable, mientras que las tareas se resuelven igual de fácilmente que en Jenkins. La decisión es tuya. Pero dado que buscamos una herramienta para un proyecto objetivo en desarrollo, ¿por qué no elegir aquella que permita, partiendo de pasos simples, obtener un sistema de construcción con interactividad y una interfaz única?

Para aquellos cuyo proyecto objetivo está escrito en python, surge la pregunta: "¿Por qué no elegir un sistema de integración que tenga una interfaz clara en términos del lenguaje utilizado en el proyecto?". Y aquí es el momento de presentar las ventajas. BuildBot.

Así que, nuestro "cuarteto de herramientas". He definido un grupo de cuatro características. BuildBot:

  1. Es un framework de código abierto bajo la licencia GPL.
  2. Es el uso de python como herramienta de configuración y descripción de las acciones requeridas.
  3. Es la posibilidad de recibir respuestas de la máquina donde ocurre la compilación.
  4. Finalmente, requiere requisitos mínimos del host. Para su implementación se necesitan python y twisted, y no se requiere una máquina virtual ni la máquina de java.

2. Concepto liderado por BuildMaster

Ejemplo de implementación de Integración Continua con BuildBot

El componente central en la arquitectura de distribución de tareas es BuildMaster. Es un servicio que:

  • supervisa los cambios en el árbol de fuentes del proyecto.
  • envía los comandos que deben ejecutarse en el servicio Worker para compilar y probar el proyecto.
  • notifica a los usuarios sobre los resultados de las acciones realizadas.

BuildMaster se configura a través de un archivo master.cfg. Este archivo se encuentra en la raíz BuildMaster. Más adelante mostraré cómo se crea esta raíz. El archivo en sí master.cfg contiene un script en python que utiliza llamados. BuildBot.

El siguiente objeto más importante BuildBot se llama Worker. Este servicio puede ejecutarse en otro host con otro sistema operativo, o también en el mismo donde BuildMaster. Además, puede existir en un entorno virtual preparado con sus propios paquetes y variables. Estos entornos virtuales pueden ser creados utilizando utilidades de python como virtualenv, venv..

BuildMaster transmite los comandos a cada uno, Workery este, a su vez, los ejecuta. Es decir, el proceso de compilación y prueba del proyecto puede llevarse a cabo en uno Worker-e bajo Windows y en otro Worker bajo linux.

La obtención del código fuente del proyecto ocurre en cada Worker-e.

3. Instalación

Vamos. Usaré Ubuntu 18.04 como host. En él, colocaré uno BuildMaster-a y uno Worker-a. Pero primero necesitamos instalar python3.7:

sudo apt-get update
sudo apt-get install python3.7

Para aquellos que necesitan python3.7.2 en lugar de 3.7.1, se puede hacer lo siguiente:


sudo apt-get update
sudo apt-get install software-properties-common
sudo add-apt-repository ppa:deadsnakes/ppa
sudo apt-get install python3.7
sudo ln -fs /usr/bin/python3.7 /usr/bin/python3
pip3 install --upgrade pip

El siguiente paso es instalar Twisted. y BuildBot, así como los paquetes que permiten utilizar funcionalidad adicional BuildBot-a.


/*Все что под sudo будет установленно для всех пользователей в директорию /usr/local/lib/python3.7/dist-packages*/

#На хосте который производит мониторинг Worker-ов 
sudo pip install twisted #Библиотека twisted
sudo pip install buildbot #BuildMaster
#Дополнительный функционал
pip install pysqlite3 #Устанавливаем базу sqllite в учебных целях
pip install jinja2 #framework наподобие django, для web и для почтовых рассыллок
pip install autobahn #Web cокеты для связи BuildMaster->Worker
pip install sqlalchemy sqlalchemy-migrate #Для отображения схемы базы данных
#Для Web отображения BuildBot-a
pip install buildbot-www buildbot-grid-view buildbot-console-view buildbot-waterfall-view
pip install python-dateutil #Отображение дат в web
#На стороне хоста который непосредственно осуществляет сборку и тестирование 
pip install buildbot-worker #Worker
#Дополнительный функционал
sudo pip install virtualenv #Виртуальная среда 

4. Primeros pasos

Es hora de crear BuildMaster. Estará en nuestra carpeta /home/habr/master.

mkdir master
buildbot create-master master # Aquí es donde realmente lo creamos

Próximo paso. Crearemos Worker. Estará en nuestra carpeta /home/habr/worker.

mkdir worker
buildbot-worker create-worker --umask=0o22 --keepalive=60 worker localhost:4000 yourWorkerName password

Cuando inicies Worker, por defecto creará en /home/habr/worker una carpeta con el nombre del proyecto indicado en master.cfg. Y dentro de la carpeta con el nombre del proyecto, creará un directorio build, y a partir de ahí hará checkout. El directorio de trabajo para Worker-a será el directorio /home/habr/yourProject/build.

La llave "dorada"
Y ahora, lo que escribí en el párrafo anterior: el script que Master pedirá a Worker-a realizar de forma remota en este directorio no se ejecutará porque el script no tiene permisos para ejecutarlo. Para solucionar esto, se necesitará la llave —umask=0o22, que aplica una restricción de escritura en este directorio, pero mantendrá los permisos de ejecución. Y eso es justo lo que necesitamos.

BuildMaster y Worker se conectan entre sí. Ocurre que se interrumpe y Worker espera un tiempo por la respuesta de BuildMaster-a. Si no se recibe respuesta, la conexión se reinicia. La llave —keepalive=60 es necesaria para indicar el tiempo tras el cual connect se reinicia.

5. Configuración. Receta paso a paso

Configuración BuildMaster se lleva a cabo en la máquina donde ejecutamos el comando create-master. En nuestro caso, es el directorio /home/habr/master. El archivo de configuración master.cfg aún no existe, sin embargo, el comando ya ha creado el archivo master.cmg.sample. Es necesario renombrarlo a master.cfg.sample en master.cfg

mv master.cfg.sample master.cfg

Abramos este master.cfg. Y desglosaremos su contenido. Después intentaremos crear nuestro propio archivo de configuración.

master.cfg

c['change_source'] = []
c['change_source'].append(changes.GitPoller(
    'git://github.com/buildbot/hello-world.git',
         workdir='gitpoller-workdir', branch='master',
         pollInterval=300))
                        
c['schedulers'] = []
c['schedulers'].append(schedulers.SingleBranchScheduler(
        name="all",
        change_filter=util.ChangeFilter(branch='master'),
        treeStableTimer=None,
        builderNames=["runtests"]))
c['schedulers'].append(schedulers.ForceScheduler(
        name="force",
        builderNames=["runtests"]))
                        
factory = util.BuildFactory()
                        
factory.addStep(steps.Git(repourl='git://github.com/buildbot/hello-world.git', mode='incremental'))
factory.addStep(steps.ShellCommand(command=["trial", "hello"],
                                   env={"PYTHONPATH": "."}))
                        
c['builders'] = []
c['builders'].append(
    util.BuilderConfig(name="runtests",
    workernames=["example-worker"],
    factory=factory))
                         
c['services'] = []
                        
c['title'] = "Hello World CI"
c['titleURL'] = "https://buildbot.github.io/hello-world/"
                        
                        
c['buildbotURL'] = "http://localhost:8010/"
                        
c['www'] = dict(port=8010,
                plugins=dict(waterfall_view={}, console_view={}, grid_view={}))
                        
c['db'] = {
    'db_url' : "sqlite:////state.sqlite",
}

5.1 BuildmasterConfig

c = BuildmasterConfig = {} 

BuildmasterConfig — diccionario base del archivo de configuración. Debe ser utilizado obligatoriamente en el archivo de configuración. Para facilitar su uso en el código de configuración, se introduce un alias. «c». Nombres de las claves en c[«keyFromDist»] son elementos fijos para la interacción con BuildMaster. Para cada clave se asigna un objeto correspondiente como valor.

5.2 workers

c['workers'] = [worker.Worker("example-worker", "pass")]

Esta vez especificamos BuildMaster- una lista de Worker-s. Nosotros Worker creamos arriba, especificando you-worker-name y password. Ahora también debemos indicarlos en lugar de example-worker y pass .

5.3 change_source

c['change_source'] = []
c['change_source'].append(changes.GitPoller(
                            'git://github.com/buildbot/hello-world.git',
                             workdir='gitpoller-workdir', branch='master',
                             pollInterval=300))                

A través de la clave change_source del diccionario c se accede a la lista donde se debe colocar el objeto que consulta el repositorio con el código fuente del proyecto. En el ejemplo se utiliza un repositorio Git, que se consulta periódicamente.

El primer argumento es la ruta a tu repositorio.

workdir representa la ruta al directorio donde en el lado Worker- se almacenará la versión local del repositorio. /home/habr/worker/yourProject/build git

branch contiene la rama específica en el repositorio que se debe supervisar.

pollInterval contiene el número de segundos después de los cuales BuildMaster se consultará el repositorio en busca de cambios.

Existen varios métodos para rastrear cambios en el repositorio del proyecto.

El método más simple es Polling, que implica que BuildMaster interrogue periódicamente al servidor con el repositorio. En caso de que commit reflejara cambios en el repositorio, entonces BuildMaster creará un objeto interno Change y lo enviará al manejador de eventos Scheduler, que iniciará los pasos para compilar y probar el proyecto en Worker-de. Entre esos pasos se indicará update del repositorio. Justo en Worker-de se creará una copia local del repositorio. Los detalles de este proceso se revelarán a continuación en las siguientes dos secciones (5.4 y 5.5).

Un método aún más elegante para rastrear cambios en el repositorio es el envío directo de mensajes desde el servidor en el que está alojado, hacia BuildMaster-a sobre el cambio en el código fuente del proyecto. En este caso, tan pronto como el desarrollador realice commit, el servidor con el repositorio del proyecto enviará un mensaje a BuildMaster-a. Y este, a su vez, lo interceptará creando un objeto PBChangeSource. Luego, este objeto será pasado a Scheduler, que activará los pasos para compilar y probar el proyecto. Una parte importante de este método es trabajar con hook-scripts del servidor en el repositorio. En el script de hook-a, que se encarga de manejar acciones en el commit-de, se necesita invocar la utilidad sendchange y especificar la dirección de red BuildMaster-a. También se debe especificar el puerto de red que estará escuchando PBChangeSource. PBChangeSource, que, por cierto, es parte de BuildMaster-a. Este método requerirá los derechos de admin-a en el servidor donde está alojado el repositorio del proyecto. Se debe realizar una copia de seguridad del repositorio con anticipación.

5.4 shedulers


c['schedulers'] = []
c['schedulers'].append(schedulers.SingleBranchScheduler(
        name="all",
        change_filter=util.ChangeFilter(branch='master'),
        treeStableTimer=None,
        builderNames=["runtests"]))
c['schedulers'].append(schedulers.ForceScheduler(
        name="force",
        builderNames=["runtests"]))

schedulers – es un elemento que actúa como un disparador, iniciando toda la cadena de compilación y prueba del proyecto.
Ejemplo de implementación de Integración Continua con BuildBot

Los cambios que fueron registrados change_source, se transformaron en el proceso de trabajo BuildBot-a en un objeto Change y ahora cada Sheduler construye solicitudes para iniciar el proceso de compilación del proyecto basándose en ellos. Sin embargo, también determina cuándo pasar estas solicitudes a la cola. El objeto Builder mantiene la cola de solicitudes y rastrea el estado de la compilación actual en un Worker-e. Builder existe tanto en BuildMaster-e como en Worker-e. También envía desde BuildMaster-a a Worker-a ya una serie específica build de pasos que deben ejecutarse.
Vemos que en este ejemplo actual se crean 2 unidades. De hecho, cada una tiene su propio tipo. schedulers SingleBranchScheduler

SingleBranchScheduler – una de las clases de programación más populares. Observa una rama y se activa por un cambio registrado en ella. Cuando ve cambios, puede retrasar el envío de una solicitud de construcción (retrasar por un periodo definido en un parámetro especial treeStableTimer). En name se establece el nombre del cronograma, que se mostrará en BuildBot-la interfaz web. En ChangeFilter se establece un filtro, el cual, al ser pasado, provoca que los cambios en la rama envíen una solicitud de construcción. En builderNames se indica el nombre en Raspberry Pi 3 con núcleos un-def, lts, mp al usar pulseaudio es necesario desconectar una de las tarjetas de audio (auriculares o HDMI), de lo contrario, puede haber un apagado prolongado del equipo y se puede perder el sonido debido a pulseaudio atascado.-a, que definiremos un poco más tarde. En nuestro caso, el nombre será el mismo que el del proyecto: yourProject.

ForceScheduler es bastante simple. Este tipo de programación se activa con un clic del ratón a través de BuildBot-la interfaz web. Los parámetros tienen la misma función que en SingleBranchScheduler.

P.S. №3. Quizás sea útil
Periodic es un cronograma que se activa con una periodicidad fija determinada en el tiempo. La llamada se ve aproximadamente así


from buildbot.plugins import schedulers
nightly = schedulers.Periodic(name="daily",
                              builderNames=["full-solaris"],
                              periodicBuildTimer=24*60*60)
c['schedulers'] = [nightly]                    

5.5 BuildFactory


factory = util.BuildFactory()
                        
factory.addStep(steps.Git(repourl='git://github.com/buildbot/hello-world.git', mode='incremental'))
factory.addStep(steps.ShellCommand(command=["trial", "hello"],
                                   env={"PYTHONPATH": "."}))

periodicBuildTimer define el tiempo de esta periodicidad en segundos.

BuildFactory crea un específico build, que luego en Raspberry Pi 3 con núcleos un-def, lts, mp al usar pulseaudio es necesario desconectar una de las tarjetas de audio (auriculares o HDMI), de lo contrario, puede haber un apagado prolongado del equipo y se puede perder el sonido debido a pulseaudio atascado. envía a Worker. Hay BuildFactory se especifican los pasos a ejecutar Worker-u. Los pasos se añaden utilizando el método addStep

El primer paso añadido en este ejemplo es git clean -d -f -f –x, luego git checkout. Estas acciones están definidas en un parámetro método, que no se muestra claramente, pero implica un valor por defecto fresh. El parámetro mode='incremental' indica que los archivos de la carpeta donde se realiza el checkout, permanecerán intactos si no están en el repositorio.

El segundo paso añadido es la llamada a un script trial con el parámetro hello del lado Worker-a desde el directorio /home/habr/worker/yourProject/build c la variable de entorno PATHONPATH=… Así, puedes escribir tus scripts y ejecutarlos del lado Worker-a a través del paso util.ShellCommand. Estos scripts se pueden colocar directamente en el repositorio. Entonces, en el checkout-e se incluirán en /home/habr/worker/yourProject/build. Sin embargo, hay dos 'peros':

  1. Worker debe ser creado con la clave —umask para que no bloquee los permisos de ejecución después de checkout-a.
  2. Al git push-e, de estos scripts es necesario indicar la propiedad executable, para que luego en checkout-e no se pierdan los permisos de ejecución del script Git.

5.6 builders


c['builders'] = []
c['builders'].append(util.BuilderConfig(name="runtests",
                                        workernames=["example-worker"],
                                        factory=factory))

Sobre qué es Builder se ha hablado aquí. Ahora les contaré más sobre cómo crearlo. BuilderConfig es un constructor en Raspberry Pi 3 con núcleos un-def, lts, mp al usar pulseaudio es necesario desconectar una de las tarjetas de audio (auriculares o HDMI), de lo contrario, puede haber un apagado prolongado del equipo y se puede perder el sonido debido a pulseaudio atascado.. Se pueden definir varios de estos constructores en c[‘builders’] ya que es una lista de objetos en Raspberry Pi 3 con núcleos un-def, lts, mp al usar pulseaudio es necesario desconectar una de las tarjetas de audio (auriculares o HDMI), de lo contrario, puede haber un apagado prolongado del equipo y se puede perder el sonido debido a pulseaudio atascado. del tipo. Ahora reescribiremos un poco el ejemplo BuildBot, acercándolo a nuestra tarea.


c['builders'] = []
c['builders'].append(util.BuilderConfig(name="yourProject",
                                            workernames=["yourWorkerName"],
                                            factory=factory))

Ahora hablaré sobre los parámetros BuilderConfig.

name que define el nombre en Raspberry Pi 3 con núcleos un-def, lts, mp al usar pulseaudio es necesario desconectar una de las tarjetas de audio (auriculares o HDMI), de lo contrario, puede haber un apagado prolongado del equipo y se puede perder el sonido debido a pulseaudio atascado.-a. Aquí lo hemos llamado yourProject. Esto significa que en Worker-e se creará esta misma ruta /home/habr/worker/yourProject/build. Sheduler busca en Raspberry Pi 3 con núcleos un-def, lts, mp al usar pulseaudio es necesario desconectar una de las tarjetas de audio (auriculares o HDMI), de lo contrario, puede haber un apagado prolongado del equipo y se puede perder el sonido debido a pulseaudio atascado. exactamente por este nombre.

workernames contiene una lista Worker-s. Cada uno de los cuales debe ser agregado en c[‘workers’].

factory es el específico build, con el que está asociado en Raspberry Pi 3 con núcleos un-def, lts, mp al usar pulseaudio es necesario desconectar una de las tarjetas de audio (auriculares o HDMI), de lo contrario, puede haber un apagado prolongado del equipo y se puede perder el sonido debido a pulseaudio atascado.. Enviará un objeto build en Worker para ejecutar todos los pasos que forman parte de este build-a.

6. Ejemplo de configuración propia

Aquí está la arquitectura del ejemplo de proyecto que propongo implementar a través de BuildBot
.

Usaremos svn. El repositorio mismo estará en una nube. Aquí está la dirección de esta nube svn.host/svn/yourProject/trunk. En la nube bajo svn hay una cuenta username: usuario, passwd: password. Los scripts que representan los pasos build-a también estarán en la rama svn, en una carpeta separada buildbot/worker_linux. Estos scripts están en el repositorio con la propiedad guardada executable.

BuildMaster y Worker que funcionan en un host project.host .BuildMaster almacena sus archivos en la carpeta /home/habr/master. Worker también guarda en el siguiente camino /home/habr/worker. La conexión entre los procesos BuildMaster-a y Worker-a se realiza a través del puerto 4000 por el protocolo BuildBot-a, es decir, ‘pb’ protocolo.

El proyecto objetivo está completamente escrito en python. La tarea es rastrear sus cambios, crear un archivo ejecutable, generar documentación, realizar pruebas. En caso de fallos, se debe enviar un mensaje a todos los desarrolladores por correo sobre que hay una acción fallida.

La visualización web BuildBot la conectaremos en el puerto 80 para project.host. No es necesario instalar Apatch. La biblioteca twisted ya incluye un servidor web, BuildBot que lo usa.

Para almacenar información de uso interno BuildBot usaremos sqlite.

Para enviar correos electrónicos, se necesita un host smtp.your.domain - en el que se permite el envío de correos desde projectHost@your.domain sin autenticación. Además, en el host ‘smtp el protocolo escucha en el puerto 1025.

En el proceso, hay dos personas involucradas: admin y usuario. El admin se encarga de la administración BuildBot. El usuario es la persona que realiza commit-s.

El archivo ejecutable se genera a través de pyinstaller. La documentación se genera a través de doxygen.

Para esta arquitectura, he escrito lo siguiente master.cfg:

master.cfg


import os, re
from buildbot.plugins import steps, util, schedulers, worker, changes, reporters

c= BuildmasterConfig ={}

c['workers'] = [ worker.Worker('yourWorkerName', 'password') ]
c['protocols'] = {'pb': {'port': 4000}} 


svn_poller = changes.SVNPoller(repourl="https://svn.host/svn/yourProject/trunk",
                                svnuser="user",
                                svnpasswd="password",
                                pollinterval=60,
				split_file=util.svn.split_file_alwaystrunk
                                )

c['change_source'] =  svn_poller

hourlyscheduler = schedulers.SingleBranchScheduler(
                                name="your-project-schedulers",
				change_filter=util.ChangeFilter(branch=None),
                                builderNames=["yourProject"],
				properties = {'owner': 'admin'}
                                )

c['schedulers'] = [hourlyscheduler]

checkout = steps.SVN(repourl='https://svn.host/svn/yourProject/trunk',
                        mode='full',
                        method='fresh',
                        username="user",
                        password="password",
                        haltOnFailure=True)

	
projectHost_build = util.BuildFactory()  


cleanProject = steps.ShellCommand(name="Clean",
                 command=["buildbot/worker_linux/pyinstaller_project", "clean"]
                                )
buildProject = steps.ShellCommand(name="Build",
                 command=["buildbot/worker_linux/pyinstaller_project", "build"]
                                )
doxyProject = steps.ShellCommand(name="Update Docs",
                                command=["buildbot/worker_linux/gendoc", []]
                                )
testProject = steps.ShellCommand(name="Tests",
                                command=["python","tests/utest.py"],
                                env={'PYTHONPATH': '.'}
                                )

projectHost_build.addStep(checkout)
projectHost_build.addStep(cleanProject)
projectHost_build.addStep(buildProject)
projectHost_build.addStep(doxyProject)
projectHost_build.addStep(testProject)


c['builders'] = [
        util.BuilderConfig(name="yourProject", workername='yourWorkerName', factory=projectHost_build)
]


template_html=u'''
<h4>Estado de la versión compilada: {{ summary }}</h4>
<p>Servicio utilizado para la construcción: {{ workername }}</p>
<p>Proyecto: {{ projects }}</p>
<p>Para ver la interfaz de gestión, acceda al enlace: {{ buildbot_url }}</p>
<p>Para ver el resultado de la compilación, acceda al enlace: {{ build_url }}</p>
<p>Utilizando WinSCP, se puede conectar al servidor con ip:xxx.xx.xxx.xx. Al iniciar sesión con habr/password, puede recuperar el archivo ejecutable compilado desde el directorio ~/worker/yourProject/build/dist.</p>
<p><b>La construcción se realizó a través de Buildbot</b></p>
'''

sendMessageToAll = reporters.MailNotifier(fromaddr="projectHost@your.domain",
					sendToInterestedUsers=True,
					lookup="your.domain",
					relayhost="smtp.your.domain",
					smtpPort=1025,
					mode="warnings",
					extraRecipients=['user@your.domain'],
              messageFormatter=reporters.MessageFormatter(
						template=template_html,
						template_type='html',
						wantProperties=True, 
                                                wantSteps=True)
					)
c['services'] = [sendMessageToAll]

c['title'] = "El proceso de construcción"
c['titleURL'] = "http://project.host:80/"

c['buildbotURL'] = "http://project.host"

c['www'] = dict(port=80,
                plugins=dict(waterfall_view={}, console_view={}, grid_view={}))


c['db'] = {
    'db_url' : "sqlite:///state.sqlite"
}

Primero, es necesario crear BuildMaster-a y Worker-a. Luego, insertar este archivo master.cfg en /home/habr/master.

El siguiente paso es iniciar el servicio BuildMaster-a


sudo buildbot start /home/habr/master

Luego, iniciar el servicio Worker-a


buildbot-worker start /home/habr/worker

¡Listo! Ahora Buildbot se rastrearán los cambios y se activará según commit-u en svn, ejecutando pasos de construcción y prueba del proyecto con la arquitectura mencionada anteriormente.

A continuación, detallaré algunas características del mencionado master.cfg.

6.1 En camino a mi master.cfg


Durante la escritura de su master.cfg se cometerán muchos errores, por lo que será necesario leer el archivo de registro. Se guarda tanto en BuildMaster-e c con la ruta absoluta /home/habr/master/twistd.log, como en el lado Worker-a con la ruta absoluta /home/habr/worker/twistd.log. A medida que lea los errores y los corrija, será necesario reiniciar el servicio BuildMaster-a. Así es como se hace:


sudo buildbot stop /home/habr/master
sudo buildbot upgrade-master /home/habr/master
sudo buildbot start /home/habr/master

6.2 Trabajo con svn


svn_poller = changes.SVNPoller(repourl="https://svn.host/svn/yourProject/trunk",
                               svnuser="user",
                               svnpasswd="password",
                               pollinterval=60,
                               split_file=util.svn.split_file_alwaystrunk
                        )

c['change_source'] =  svn_poller

hourlyscheduler = schedulers.SingleBranchScheduler(
                            name="your-project-schedulers",
                            change_filter=util.ChangeFilter(branch=None),
                            builderNames=["yourProject"],
                            properties = {'owner': 'admin'}
                        )

c['schedulers'] = [hourlyscheduler]

checkout = steps.SVN(repourl='https://svn.host/svn/yourProject/trunk',
                     mode='full',
                     method='fresh',
                     username="user",
                     password="password",
                     haltOnFailure=True)

Primero, echemos un vistazo a svn_poller. Esta sigue siendo la misma interfaz, que interroga regularmente el repositorio cada minuto. En este caso, svn_poller se dirige solo a la rama trunk.El parámetro misterioso split_file=util.svn.split_file_alwaystrunk estipula las reglas: cómo dividir la estructura de carpetas svn en ramas. También les ofrece rutas relativas. A su vez, split_file_alwaystrunk facilita el proceso, indicando que en el repositorio solo hay trunk..

En Schedulers se indica ChangeFilter, que ve None y asocia con la rama trunk. según la asociación dada a través de split_file_alwaystrunk. Al reaccionar a los cambios en trunk., inicia en Raspberry Pi 3 con núcleos un-def, lts, mp al usar pulseaudio es necesario desconectar una de las tarjetas de audio (auriculares o HDMI), de lo contrario, puede haber un apagado prolongado del equipo y se puede perder el sonido debido a pulseaudio atascado. c con el nombre yourProject.

properties aquí es necesario para que el administrador reciba notificaciones sobre los resultados de la construcción y prueba como propietario del proceso.

Paso build-a checkout es capaz de realizar la eliminación completa de cualquier archivo que esté en la versión local del repositorio Worker-a. A continuación, hacer un completo svn update.El modo se configura a través del parámetro mode=full, method=fresh. El parámetro haltOnTailure habla de que si svn update. se ejecuta con error, todo el proceso de construcción y prueba debe ser suspendido, ya que las acciones posteriores no tienen sentido.

6.3 Has recibido un correo: los reporteros están autorizados para declarar


reporteros es un servicio de envío de notificaciones por correo electrónico.


template_html=u'''
<h4>Estado de la versión compilada: {{ summary }}</h4>
<p>Servicio utilizado para la construcción: {{ workername }}</p>
<p>Proyecto: {{ projects }}</p>
<p>Para ver la interfaz de gestión, acceda al enlace: {{ buildbot_url }}</p>
<p>Para ver el resultado de la compilación, acceda al enlace: {{ build_url }}</p>
<p>Utilizando WinSCP, se puede conectar al servidor con ip:xxx.xx.xxx.xx. Al iniciar sesión con habr/password, puede recuperar el archivo ejecutable compilado desde el directorio ~/worker/yourProject/build/dist.</p>
<p><b>La construcción se realizó a través de Buildbot</b></p>
'''
                        
sendMessageToAll = reporters.MailNotifier(fromaddr="projectHost@your.domain",
                                          sendToInterestedUsers=True,
                                          lookup="your.domain",
                                          relayhost="smtp.your.domain",
                                          smtpPort=1025,
                                          mode="warnings",
                                          extraRecipients=['user@your.domain'],
                                    messageFormatter=reporters.MessageFormatter(
                                                    template=template_html,
                                                    template_type='html',
                                                    wantProperties=True, 
                                                    wantSteps=True)
                                        )
c['services'] = [sendMessageToAll]

Puede enviar mensajes de varias maneras.

MailNotifier utiliza el correo para enviar notificaciones.

template_html define la plantilla de texto para el envío. Se utiliza html para crear el marcado. Está modificado por el motor jinja2 (que se puede compararse con django). BuildBot tiene un conjunto de variables, cuyos valores se insertan en la plantilla durante la formación del texto del mensaje. Estas variables están escritas en {{ dobles llaves }}. Por ejemplo, resumen muestra el estado de las operaciones realizadas, es decir, éxito o fallo. Y projects mostrará yourProject. Así, mediante comandos de control en jinja2, variables BuildBot-a y herramientas de formateo de cadenas de python se puede crear un mensaje bastante informativo.

MailNotifier contiene los siguientes argumentos.

fromaddr – la dirección desde la que se enviarán las notificaciones a todos.

sendToInterestedUsers=True envía el mensaje al propietario y al usuario que realizó el commit.

lookup – sufijo que debe agregarse a los nombres de usuario que reciben la notificación. Así admin el usuario recibirá el aviso a la dirección admin@your.domain.

relayhost define el nombre del host donde se encuentra el servidor smtp, a smptPort define el número del puerto que escucha smtp servidor.

mode=«warning» indica que las notificaciones deben enviarse solo si al menos un paso build-a que terminó con el estado de fallo o advertencia. En caso de éxito, no es necesario enviar la notificación.

extraRecipients contiene una lista de personas a las que se debe enviar la notificación además del propietario y la persona que realizó el commit.

messageFormatter es un objeto que define el formato del mensaje, su plantilla, y el conjunto de variables disponibles desde jinja2. Parámetros como wantProperties=True y wantSteps=True definen este conjunto de variables disponibles.

s[‘services’]=[sendMessageToAll] proporciona una lista de servicios, entre los cuales estará nuestro reportero.

¡Lo logramos! Mis felicitaciones

Hemos creado nuestra propia configuración y hemos visto la funcionalidad que puede ofrecer. BuildBotEsto, creo, es suficiente para entender si esta herramienta es necesaria para tu proyecto. ¿Te interesa? ¿Te será útil? ¿Es cómodo trabajar con él? Entonces no escribí este artículo en vano.

Y además. Me gustaría que la comunidad profesional que utiliza BuildBot, se ampliara, se tradujeran manuales, y hubiera aún más ejemplos.

Gracias a todos por su atención. Buena suerte.

Fuente: habr.com

Compra un hosting fiable para sitios web con protección contra DDoS, servidores VPS VDS 🔥 Compra un hosting fiable para sitios web con protección contra DDoS, servidores VPS VDS | ProHoster