Esempio di implementazione della Continuous Integration con BuildBot.

Esempio di implementazione della Continuous Integration con BuildBot.
(Immagine di Computerizer da Pixabay)

Ciao!

Mi chiamo Evgeny Cherkin, sono un programmatore nel team di sviluppatori di una compagnia mineraria Polymetal.

Iniziando qualsiasi grande progetto, ti viene da pensare: «Quale software è meglio utilizzare per il suo supporto?». Un progetto IT prima del rilascio di una nuova versione passa attraverso una serie di fasi. È positivo quando la catena di queste fasi è automatizzata. Il processo automatizzato di rilascio di una nuova versione di un progetto IT si chiama Integrazione Continua. BuildBot e si è rivelato un buon aiutante per realizzare questo processo.

In questo articolo ho deciso di presentare una panoramica delle funzionalità BuildBot. Cosa può fare questo software? Come avvicinarsi e come stabilire con esso normali RELAZIONI DI LAVORO EFFICACI? La nostra esperienza puoi applicarla anche a te, creando sulla tua macchina un servizio di build e test per il tuo progetto.

Contenuto

Contenuto

1. Perché BuildBot?
2. La concezione sotto la direzione di BuildMaster
3. Installazione
4. Primi passi

5. Configurazione. Ricetta passo dopo passo

5.1 BuildmasterConfig
5.2 workers
5.3 change_source
5.4 shedulers

5.5 BuildFactory
5.6 builders

6. Esempio della propria configurazione

6.1 Sul cammino verso il proprio master.cfg
6.2 Lavorare con svn
6.3 Hai una lettera: reporters è autorizzato a dichiarare

Ce l'abbiamo fatta! Le mie congratulazioni

1. Perché BuildBot?

In precedenza su habr-e ho incontrato articoli sull'implementazione Integrazione Continua utilizzando BuildBot. Per esempio, questo mi è sembrato il più informativo. C'è un altro esempio — più semplice. Questi articoli possono essere conditi con un esempio dal manuale, ma ClusterFirst in aggiunta, in lingua inglese. Insieme formano un buon punto di partenza. Dopo aver letto questi articoli, vorrai sicuramente fare qualcosa di BuildBot .

Fermati! Qualcuno lo ha mai utilizzato nei suoi progetti? A quanto pare sì, molti lo hanno applicato nei loro compiti. È possibile trovarlo casi d'uso utilizzo BuildBot anche negli archivi di codici di Google.

Qual è quindi la logica delle persone che utilizzano Buildbot? Ведь есть другие инструменты: CruiseControl e Jenkins. Risponderò così. Per la maggior parte dei compiti Jenkins sarà davvero sufficiente. A sua volta, BuildBot è più adattabile, e nel contempo i compiti vengono risolti semplicemente, proprio come in Jenkins. Sta a te scegliere. Ma poiché stiamo cercando uno strumento per un progetto target in fase di sviluppato, perché non scegliere quello che, partendo da semplici passi, permette di ottenere un sistema di build con interattività e un'interfaccia unica.

Coloro che hanno un progetto mirato scritto in Python si pongono la domanda: «Perché non scegliere un sistema di integrazione che abbia un'interfaccia comprensibile dal punto di vista del linguaggio utilizzato nel progetto?» E qui è il momento giusto per presentare i vantaggi BuildBot.

Quindi, il nostro «quartetto degli strumenti». Ho definito per me stesso un gruppo di quattro caratteristiche BuildBot:

  1. Questo è un framework open-source con licenza GPL
  2. Questo è l'uso di Python come strumento per la configurazione e la descrizione delle azioni richieste
  3. Questa è la possibilità di ricevere risposte dalla macchina su cui avviene la compilazione
  4. Infine, ci sono requisiti minimi per l'host. Per il deployment sono necessari Python e Twisted, e non è richiesta una macchina virtuale o una macchina Java.

2. La concezione sotto la direzione di BuildMaster

Esempio di implementazione della Continuous Integration con BuildBot.

Al centro dell'architettura di distribuzione delle attività c'è BuildMaster. Esso rappresenta un servizio che:

  • monitora le modifiche nell'albero del codice sorgente del progetto
  • invio comandi che devono essere eseguiti dal servizio Worker per costruire e testare il progetto
  • notifica gli utenti sui risultati delle azioni eseguite

BuildMaster si configura tramite un file master.cfg. Questo file si trova nella radice BuildMaster. Più avanti mostrerò come viene creata questa radice. Il file stesso master.cfg contiene uno script Python che utilizza chiamate BuildBot.

Il prossimo oggetto più importante BuildBot si chiama Worker. Questo servizio può essere avviato su un altro host con un altro OS, oppure anche su quello dove BuildMaster. Inoltre, può esistere in un ambiente virtuale preparato con i propri pacchetti e variabili. Questi ambienti virtuali possono essere creati utilizzando utilità Python come virtualenv, venv.

BuildMaster trasmette i comandi a ciascuno Worker, il quale, a sua volta, li esegue. Quindi, il processo di costruzione e test del progetto può avvenire su Worker-e sotto Windows e su un altro Worker sotto Linux.

Il checkout del codice sorgente del progetto avviene su ciascuno Worker-e.

3. Installazione

Quindi, iniziamo. Come host utilizzerò Ubuntu 18.04. Su di esso ospiterò un BuildMaster-a e un Worker-a. Ma prima è necessario installare Python 3.7:

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

Per chi ha bisogno di Python 3.7.2 invece di 3.7.1, può fare quanto segue:


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

Il passo successivo è installare Twisted e BuildBot, e anche pacchetti che consentono di utilizzare funzionalità aggiuntive 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. Primi passi

È tempo di creare BuildMaster. Lo troveremo nella nostra cartella /home/habr/master.

mkdir master
buildbot create-master master # Qui creiamo effettivamente

Il passo successivo. Creeremo Worker. Lo troveremo nella nostra cartella /home/habr/worker.

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

Quando lo avvierai Worker, per impostazione predefinita creerà in /home/habr/worker una cartella con il nome del progetto specificato in master.cfg. E nella cartella con il nome del progetto creerà una directory build, e poi eseguirà checkout. La directory di lavoro per Worker-a sarà la directory /home/habr/yourProject/build.

La chiave "d'oro"
E ora, per cui ho scritto il paragrafo precedente: lo script che Master richiederà a Worker-a di fare in remoto in questa directory non verrà eseguito, poiché lo script non ha i diritti per l'esecuzione. Per risolvere la situazione, avremo bisogno della chiave —umask=0o22, che vieta la scrittura in questa directory, ma lascia i diritti di esecuzione. Ed è esattamente ciò di cui abbiamo bisogno.

BuildMaster e Worker stabilisce una connessione tra di loro. A volte, questa si interrompe e Worker aspetta una risposta da BuildMaster-a. Se non ci sarà risposta, la connessione verrà ripristinata. La chiave —keepalive=60 è necessaria per specificare il tempo dopo il quale connect viene riavviato.

5. Configurazione. Ricetta passo dopo passo

Configurazione BuildMaster viene eseguito dal lato della macchina in cui abbiamo eseguito il comando create-master. Nel nostro caso, si tratta della directory /home/habr/master. Il file di configurazione master.cfg non esiste ancora, tuttavia il comando ha già creato il file master.cmg.sample. È necessario rinominarlo in master.cfg.sample in master.cfg

mv master.cfg.sample master.cfg

Apriremo questo master.cfg. E analizzeremo da cosa è composto. Dopodiché, proveremo a creare il nostro file di configurazione.

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 — dizionario di base del file di configurazione. Deve essere necessariamente utilizzato nel file di configurazione. Per comodità d'uso nel codice di configurazione viene introdotto il suo alias «c». Nominal chiavi in c[«keyFromDist»] sono elementi fissi per interagire con BuildMaster. Per ogni chiave, viene fornito un oggetto corrispondente come valore.

5.2 workers

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

Questa volta indichiamo BuildMaster- una lista di Worker-e. Noi stessi Worker l'abbiamo creata sopra, specificando your-worker-name e password. Ora dobbiamo indicare gli stessi al posto di example-worker e 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))                

Per la chiave change_source del dizionario c, accediamo alla lista in cui deve essere inserito l'oggetto che interroga il repository con il codice sorgente del progetto. Nell'esempio viene utilizzato un repository Git, interrogato a intervalli di tempo regolari.

Il primo argomento è il percorso del tuo repository.

workdir rappresenta il percorso della cartella in cui, sul lato Worker-o rispetto al percorso /home/habr/worker/yourProject/build verrà conservata una versione locale del repository.

branch contiene un ramo specifico nel repository da monitorare.

pollInterval contiene il numero di secondi dopo i quali BuildMaster verrà interrogato il repository per eventuali modifiche.

Esistono diversi metodi per monitorare le modifiche nel repository del progetto.

Il metodo più semplice è il polling, che implica che BuildMaster interrogando periodicamente il server con il repository. Nel caso in cui commit ha riflesso le modifiche nel repository, allora BuildMaster dopo un certo ritardo verrà creato un oggetto interno Change e sarà inviato al gestore eventi Scheduler, il quale avvierà i passaggi per la compilazione e il test del progetto su Worker-e. Tra questi passaggi verrà indicato aggiornamento del repository. Proprio su Worker-e verrà creata una copia locale del repository. I dettagli di questo processo saranno svelati nei prossimi due paragrafi (5.4 e 5.5).

Un metodo ancora più elegante per monitorare le modifiche nel repository è l'invio diretto di messaggi dal server su cui è ospitato a BuildMaster-e riguardanti la modifica del codice sorgente del progetto. In questo caso, non appena il sviluppatore effettua commit, il server con il repository del progetto invierà un messaggio BuildMaster-e. Quest'ultimo, a sua volta, lo catturerà creando un oggetto PBChangeSource. Successivamente, questo oggetto sarà passato a Scheduler, il quale attiverà i passaggi per la compilazione del progetto e il suo testing. Una parte importante di questo metodo è il lavoro con hook-script del server nel repository. Nel script hook-e, responsabile della gestione delle azioni su commit-e, è necessario invocare l'utilità sendchange e specificare l'indirizzo di rete BuildMaster-e. Dobbiamo anche specificare la porta di rete che ascolterà PBChangeSource. PBChangeSource, che è parte di BuildMaster-e. Questo metodo richiederà i diritti admin-a sul server dove risiede il repository del progetto. Prima di tutto sarà necessario fare un backup del repository.

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 – è un elemento che funge da grilletto, avviando tutta la catena di compilazione e test del progetto.
Esempio di implementazione della Continuous Integration con BuildBot.

Le modifiche che sono state registrate change_source, si sono trasformate nel processo di lavoro BuildBot-a in un oggetto Change e ora ogni Scheduler sulla base di esse costruisce richieste per avviare il processo di compilazione del progetto. Tuttavia, determina anche quando queste richieste devono essere passate ulteriormente in coda. L'oggetto Builder mantiene una coda di richieste e tiene traccia dello stato dell'attuale compilazione su un Worker-e. Builder esiste sia su BuildMaster-e che su Worker-e. Esso invia da BuildMaster-e a Worker-e già un specifico build — una serie di passaggi che devono essere eseguiti.
Vediamo che nell'esempio attuale vengono create 2 unità. Inoltre, ognuna ha il proprio tipo. schedulers SingleBranchScheduler

SingleBranchScheduler – una delle classi di pianificazione più popolari. Osserva un ramo e si attiva con un cambiamento fisso in esso. Quando rileva modifiche, può ritardare l'invio della richiesta di costruzione (ritardare per un periodo specificato nel parametro speciale treeStableTimer). Nel name si assegna il nome della pianificazione, che verrà visualizzato nel BuildBot-interfaccia web. Nel ChangeFilter si imposta un filtro, superato il quale le modifiche nel ramo spingono la pianificazione a inviare una richiesta di costruzione. Nel builderNames si specifica il nome builder-a, che imposteremo poco dopo. Il nome nel nostro caso sarà lo stesso del nome del progetto: yourProject.

ForceScheduler è piuttosto semplice. Questo tipo di pianificazione si attiva con un clic del mouse tramite BuildBot-interfaccia web. I parametri hanno lo stesso significato che in SingleBranchScheduler.

P.S. n. 3. Potrebbe tornare utile
Periodic — è una pianificazione che si attiva con una periodicità fissa nel tempo. L'invocazione di esso appare più o meno così


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 indica il tempo di questa periodicità in secondi.

BuildFactory crea un concreto build, che poi builder invia a Worker. In BuildFactory si specificano i passaggi da eseguire Worker-a. I passaggi vengono aggiunti tramite la chiamata del metodo addStep

Il primo passaggio aggiunto in questo esempio è git clean -d -f -f –x, quindi git checkout. Queste azioni sono incluse nel parametro method, che non è esplicitamente indicato, ma подразумевает un valore predefinito fresh. Il parametro mode='incremental' indica che i file nella directory in cui viene eseguito il checkout, nel frattempo quelli assenti nel repository rimangono intatti.

Il secondo passaggio aggiunto è la chiamata a uno script trial con il parametro hello dal lato Worker-a dalla directory /home/habr/worker/yourProject/build c con la variabile d'ambiente PATHONPATH=… In questo modo, puoi scrivere i tuoi script ed eseguirli dal lato Worker-a tramite il passaggio util.ShellCommand. Questi script possono essere inseriti direttamente nel repository. Allora durante il checkout-e saranno inclusi in /home/habr/worker/yourProject/build. Tuttavia, ci sono due "ma":

  1. Worker deve essere creato con la chiave —umask per non bloccare i diritti di esecuzione dopo checkout-a.
  2. Durante git push-e di questi script è necessario specificare la proprietà executable, affinché poi al momento checkout-e non ha perso i diritti di esecuzione dello script Git.

5.6 builders


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

Di cosa si tratta Builder è stato raccontato qui. Ora ti spiego più nel dettaglio come crearlo. BuilderConfig è un costruttore builder. Possono essere definiti più di questi costruttori in c[‘builders’] poiché è una lista di oggetti di tipo. builder Ora riscriveremo un esempio da BuildBot, avvicinandolo al nostro compito.


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

Adesso parlerò dei parametri BuilderConfig.

name definisce il nome builder-a. Qui lo abbiamo chiamato yourProject. Questo significa che su Worker-e sarà creato questo stesso percorso /home/habr/worker/yourProject/build. Scheduler cerca builder proprio con questo nome.

workernames contiene una lista Worker-di. Ognuno di essi deve essere aggiunto a c[‘workers’].

factory è specifico build, con cui è associato builder. Lo invierà un oggetto build in Worker per eseguire tutti i passaggi che fanno parte di questo build-a.

6. Esempio della propria configurazione

Ecco l'architettura dell'esempio di progetto che propongo di realizzare tramite BuildBot
.

Come sistema di controllo delle versioni useremo svn. Il repository stesso si troverà in un certo cloud. Ecco l'indirizzo di questo cloud svn.host/svn/yourProject/trunk. Nel cloud sotto svn c'è un account username: user, passwd: password. Gli script, che rappresentano i passaggi build-a si troveranno anch'essi nel ramo svn, in una cartella separata buildbot/worker_linux. Questi script si trovano nel repository con la proprietà salvata executable.

BuildMaster e Worker funzionano su un unico host project.host .BuildMaster salva i suoi file nella cartella /home/habr/master. Worker sà salvare anche al seguente percorso /home/habr/worker. La connessione tra i processi BuildMaster-a e Worker-a avviene tramite la porta 4000 utilizzando il protocollo BuildBot-a, vale a dire ‘pb’ protocollo.

Il progetto target è interamente scritto in python. L'obiettivo è tracciare le sue modifiche, creare un file eseguibile, generare documentazione, effettuare test. In caso di failure, è necessario inviare un messaggio via email a tutti gli sviluppatori che informa che c'è stata un'azione non riuscita.

L'interfaccia web BuildBot la collegheremo sulla porta 80 per project.host. Apatch non è obbligatorio. Nella libreria twisted è già presente un server web, BuildBot che lo utilizza.

Per la conservazione delle informazioni interne per BuildBot utilizzeremo sqlite.

Per le email è necessario un host smtp.your.domain — è consentito inviare mail da projectHost@your.domain senza autenticazione. Inoltre, sull'host ‘smtp ‘ il protocollo ascolta sulla porta 1025.

Le persone coinvolte nel processo sono due: admin e user. admin amministra BuildBot. user è un soggetto che compie commit-.

Il file Exacutable viene generato tramite pyinstaller. La documentazione viene generata tramite doxygen.

Per questa architettura ho scritto quanto segue 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="Pulisci",
                 command=["buildbot/worker_linux/pyinstaller_project", "clean"]
                                )
buildProject = steps.ShellCommand(name="Costruisci",
                 command=["buildbot/worker_linux/pyinstaller_project", "build"]
                                )
doxyProject = steps.ShellCommand(name="Aggiorna Documenti",
                                command=["buildbot/worker_linux/gendoc", []]
                                )
testProject = steps.ShellCommand(name="Test",
                                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>Stato del rilascio costruito: {{ summary }}</h4>
<p>Servizio utilizzato per la costruzione: {{ workername }}</p>
<p>Progetto: {{ projects }}</p>
<p>Per visualizzare l'interfaccia di gestione, segui il link: {{ buildbot_url }}</p>
<p>Per visualizzare il risultato della costruzione, segui il link: {{ build_url }}</p>
<p>Utilizzando WinSCP puoi connetterti al server con l'IP: xxx.xx.xxx.xx. Accedi con habr/password per scaricare il file eseguibile dalla directory ~/worker/yourProject/build/dist.</p>
<p><b>La costruzione è stata effettuata tramite 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'] = "Il processo di costruzione"
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"
}

Per cominciare, è necessario creare BuildMaster-a e Worker-a. Quindi inserire questo file master.cfg in /home/habr/master.

Il passo successivo richiede di avviare il servizio BuildMaster-a


sudo buildbot start /home/habr/master

Poi avviare il servizio Worker-a


buildbot-worker start /home/habr/worker

Fatto! Ora Buildbot seguirà le modifiche e agirà in base commit-u in svn, eseguendo le fasi di build e test del progetto con l'architettura sopra menzionata.

Di seguito, descriverò alcune caratteristiche del suddetto master.cfg.

6.1 Sul cammino verso il proprio master.cfg


Durante la scrittura del proprio master.cfg verranno commessi numerosi errori, quindi sarà necessario leggere il file di log. Questo si trova sia su BuildMaster-e con il percorso assoluto /home/habr/master/twistd.log, sia sul lato Worker-a con il percorso assoluto /home/habr/worker/twistd.log. Man mano che si leggono errori e si correggono, sarà necessario riavviare il servizio BuildMaster-a. Ecco come si fa:


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

6.2 Lavorare 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)

Per cominciare, diamo un'occhiata a svn_poller. Questo è lo stesso interfaccia che interroga regolarmente il repository una volta al minuto. In questo caso svn_poller si riferisce solo al ramo trunk. Il misterioso parametro split_file=util.svn.split_file_alwaystrunk stabilisce le regole: come suddividere la struttura delle cartelle svn in rami. Questo offre loro percorsi relativi. A sua volta split_file_alwaystrunk semplifica il processo, specificando che nel repository ci sono solo trunk.

In Schedulers viene specificato ChangeFilter, che vede Nessuno e associa ad esso il ramo trunk secondo l'associazione specificata tramite split_file_alwaystrunk. Rispondendo alle modifiche in trunk, avvia builder c di nome yourProject.

properties qui è necessario affinché l'amministratore riceva una notifica sui risultati della build e del test come proprietario del processo.

Passaggio build-a checkout è in grado di effettuare una completa rimozione di tutti i file presenti nella versione locale del repository Worker-a. E poi effettuare un completo svn update. La modalità è impostata tramite il parametro modalità=full, metodo=fresh. Il parametro haltOnTailure indica che se svn update si verifica un errore, l'intero processo di compilazione e test deve essere sospeso, poiché le azioni successive non hanno senso.

6.3 Hai una lettera: reporters è autorizzato a dichiarare


reporters è un servizio di invio di notifiche via email.


template_html=u'''
<h4>Stato del rilascio costruito: {{ summary }}</h4>
<p>Servizio utilizzato per la costruzione: {{ workername }}</p>
<p>Progetto: {{ projects }}</p>
<p>Per visualizzare l'interfaccia di gestione, segui il link: {{ buildbot_url }}</p>
<p>Per visualizzare il risultato della costruzione, segui il link: {{ build_url }}</p>
<p>Utilizzando WinSCP puoi connetterti al server con l'IP: xxx.xx.xxx.xx. Accedi con habr/password per scaricare il file eseguibile dalla directory ~/worker/yourProject/build/dist.</p>
<p><b>La costruzione è stata effettuata tramite 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]

Può inviare messaggi in vari modi.

MailNotifier usa la posta per l'invio di notifiche.

template_html definisce il modello di testo per l'invio. Per la creazione del layout viene utilizzato html. È modificato dal motore jinja2 (può essere paragonato a django). BuildBot ha un insieme di variabili, i cui valori vengono inseriti nel modello durante la generazione del testo del messaggio. Queste variabili sono racchiuse tra {{ doppie parentesi graffe }}. Ad esempio, summary stampa lo stato delle operazioni completate, cioè success o failure. E projects stampe yourProject. Così, attraverso comandi di controllo in jinja2, variabili BuildBot-a e strumenti di formattazione delle stringhe python si può creare un messaggio piuttosto informativo.

MailNotifier contiene i seguenti argomenti.

fromaddr – l'indirizzo da cui verrà inviata la comunicazione a tutti.

sendToInterestedUsers=True invia il messaggio al proprietario e all'utente che ha effettuato commit.

lookup è un suffisso che deve essere aggiunto ai nomi degli utenti che ricevono l'invio. Così admin l'utente riceverà la comunicazione all'indirizzo admin@your.domain.

relayhost definisce il nome dell'host dove è aperto il server smtp, a smptPort definisce il numero di porta che ascolta smtp il server.

modalità=«warning» indica che l'invio deve essere fatto solo se c'è almeno un passo build-a che si è concluso con lo stato di failure o warning. In caso di success non è necessario l'invio.

extraRecipients contiene un elenco di persone a cui deve essere inviata la comunicazione oltre al proprietario e alla persona che ha effettuato commit.

messageFormatter è un oggetto che definisce il formato del messaggio, il suo modello e l'insieme di variabili disponibili da jinja2. Parametri come wantProperties=True e wantSteps=True definiscono questo insieme di variabili disponibili.

s[‘services’]=[sendMessageToAll] fornisce un elenco di servizi, tra cui il nostro reporter.

Ce l'abbiamo fatta! Le mie congratulazioni

Abbiamo creato una nostra configurazione e visto le funzionalità che può offrire BuildBot. Penso che questo sia sufficiente per capire se questo strumento è utile per il tuo progetto. Ti interessa? Ti sarà utile? È facile da usare? Allora non ho scritto questo articolo invano.

E in aggiunta. Vorrei che la comunità professionale che utilizza BuildBot, è diventato più ampio, i manuali venivano tradotti e aumentavano anche gli esempi.

Grazie a tutti per l'attenzione. Buona fortuna.

Fonte: habr.com

Acquista hosting affidabile per siti web con protezione DDoS, VPS VDS server 🔥 Acquista hosting affidabile per siti web con protezione DDoS, VPS VDS server | ProHoster