& # 8220; Pretty & # 8221; Integrazione continua per Python
-
03-07-2019 - |
Domanda
Questa è una domanda leggermente .. vana, ma l'output di BuildBot non è particolarmente bello da guardare ..
Ad esempio, rispetto a ..
..e altri, BuildBot sembra piuttosto .. arcaico
Attualmente sto giocando con Hudson, ma è molto incentrato su Java (sebbene con questa guida , ho trovato più facile l'installazione di BuildBot e ho prodotto più informazioni)
Fondamentalmente: esistono sistemi di integrazione continua rivolti a Python, che producono molti grafici brillanti e simili?
Aggiornamento: da allora il progetto Jenkins ha sostituito Hudson come versione della comunità del pacchetto. Anche gli autori originali sono passati a questo progetto. Jenkins è ora un pacchetto standard su Ubuntu / Debian, RedHat / Fedora / CentOS e altri. Il seguente aggiornamento è ancora sostanzialmente corretto. Il punto di partenza per farlo con Jenkins è diverso.
Update: Dopo aver provato alcune alternative, penso che rimarrò fedele a Hudson. Integrità è stata piacevole e semplice, ma piuttosto limitata. Penso che Buildbot sia più adatto ad avere numerosi build-slave, piuttosto che tutto ciò che gira su una singola macchina come stavo usando esso.
Configurare Hudson per un progetto Python è stato piuttosto semplice:
- Scarica Hudson da http://hudson-ci.org/
- Eseguilo con
java -jar hudson.war
- Apri l'interfaccia web sull'indirizzo predefinito di
http://localhost:8080
- Vai a Gestisci Hudson, Plugin, fai clic su " Aggiorna " o simili
- Installa il plug-in Git (ho dovuto impostare il percorso
git
nelle preferenze globali di Hudson) - Crea un nuovo progetto, inserisci il repository, gli intervalli di polling SCM e così via
- Installa
nosetests
tramiteeasy_install
se non è già - Nel passaggio di compilazione, aggiungi
nosetests --with-xunit --verbose
- Controlla " Pubblica rapporto risultati test JUnit " e impostare " XML del rapporto di prova " su
**/nosetests.xml
Questo è tutto ciò che è richiesto. Puoi impostare notifiche e-mail e i plugin meritano una visita. Alcuni attualmente sto usando per progetti Python:
- Plug-in SLOCCount per contare le righe di codice (e rappresentarlo graficamente! ) - devi installare sloccount separatamente
- Violations per analizzare l'output di PyLint (è possibile impostare soglie di avviso, grafico il numero di violazioni per ogni build)
- Cobertura può analizzare l'output coverage.py. Nosetest può raccogliere la copertura durante l'esecuzione dei test, utilizzando
nosetests --with-coverage
(questo scrive l'output in** / coverage.xml
)
Soluzione
Potresti voler dare un'occhiata a Nose e il plug-in di output Xunit . Puoi farlo eseguire i test unitari e i controlli di copertura con questo comando:
nosetests --with-xunit --enable-cover
Ciò sarà utile se si desidera seguire il percorso Jenkins o se si desidera utilizzare un altro server CI che supporti il ??reporting dei test JUnit.
Allo stesso modo puoi catturare l'output di pylint usando il plugin per violazioni per Jenkins
Altri suggerimenti
Non so se lo farebbe: Bitten è realizzato dai ragazzi che scrivono Trac ed è integrato con Trac. Apache Gump è lo strumento CI utilizzato da Apache. È scritto in Python.
Abbiamo avuto un grande successo con TeamCity come nostro server CI e usando nose come nostro runner di test . Plug-in Teamcity per nosetest ti dà il conteggio pass / fail, visualizzazione leggibile per test falliti (che può essere inviato per e-mail). È anche possibile visualizzare i dettagli degli errori di test mentre lo stack è in esecuzione.
Se ovviamente supporta cose come l'esecuzione su più macchine, ed è molto più semplice da configurare e mantenere rispetto a buildbot.
La pagina a cascata di Buildbot può essere notevolmente preimpostata. Ecco un bell'esempio http://build.chromium.org/buildbot/waterfall/waterfall
Anche la Bamboo di Atlassian merita sicuramente una visita. L'intera suite Atlassian (JIRA, Confluence, FishEye, ecc.) È piuttosto dolce.
Immagino che questo thread sia piuttosto vecchio ma ecco la mia opinione su di esso con hudson:
Ho deciso di andare con Pip e impostare un repository (il doloroso per far funzionare ma un bel cestino per le uova dall'aspetto gradevole), su cui hudson si carica automaticamente con test riusciti. Ecco il mio script approssimativo e pronto per l'uso con uno script hudson config esegui script come: /var/lib/hudson/venv/main/bin/hudson_script.py -w $ WORKSPACE -p my.package -v $ BUILD_NUMBER, basta inserire ** / coverage.xml, pylint.txt e nosetests.xml nei bit di configurazione:
#!/var/lib/hudson/venv/main/bin/python
import os
import re
import subprocess
import logging
import optparse
logging.basicConfig(level=logging.INFO,
format='%(asctime)s %(levelname)s %(message)s')
#venvDir = "/var/lib/hudson/venv/main/bin/"
UPLOAD_REPO = "http://ldndev01:3442"
def call_command(command, cwd, ignore_error_code=False):
try:
logging.info("Running: %s" % command)
status = subprocess.call(command, cwd=cwd, shell=True)
if not ignore_error_code and status != 0:
raise Exception("Last command failed")
return status
except:
logging.exception("Could not run command %s" % command)
raise
def main():
usage = "usage: %prog [options]"
parser = optparse.OptionParser(usage)
parser.add_option("-w", "--workspace", dest="workspace",
help="workspace folder for the job")
parser.add_option("-p", "--package", dest="package",
help="the package name i.e., back_office.reconciler")
parser.add_option("-v", "--build_number", dest="build_number",
help="the build number, which will get put at the end of the package version")
options, args = parser.parse_args()
if not options.workspace or not options.package:
raise Exception("Need both args, do --help for info")
venvDir = options.package + "_venv/"
#find out if venv is there
if not os.path.exists(venvDir):
#make it
call_command("virtualenv %s --no-site-packages" % venvDir,
options.workspace)
#install the venv/make sure its there plus install the local package
call_command("%sbin/pip install -e ./ --extra-index %s" % (venvDir, UPLOAD_REPO),
options.workspace)
#make sure pylint, nose and coverage are installed
call_command("%sbin/pip install nose pylint coverage epydoc" % venvDir,
options.workspace)
#make sure we have an __init__.py
#this shouldn't be needed if the packages are set up correctly
#modules = options.package.split(".")
#if len(modules) > 1:
# call_command("touch '%s/__init__.py'" % modules[0],
# options.workspace)
#do the nosetests
test_status = call_command("%sbin/nosetests %s --with-xunit --with-coverage --cover-package %s --cover-erase" % (venvDir,
options.package.replace(".", "/"),
options.package),
options.workspace, True)
#produce coverage report -i for ignore weird missing file errors
call_command("%sbin/coverage xml -i" % venvDir,
options.workspace)
#move it so that the code coverage plugin can find it
call_command("mv coverage.xml %s" % (options.package.replace(".", "/")),
options.workspace)
#run pylint
call_command("%sbin/pylint --rcfile ~/pylint.rc -f parseable %s > pylint.txt" % (venvDir,
options.package),
options.workspace, True)
#remove old dists so we only have the newest at the end
call_command("rm -rfv %s" % (options.workspace + "/dist"),
options.workspace)
#if the build passes upload the result to the egg_basket
if test_status == 0:
logging.info("Success - uploading egg")
upload_bit = "upload -r %s/upload" % UPLOAD_REPO
else:
logging.info("Failure - not uploading egg")
upload_bit = ""
#create egg
call_command("%sbin/python setup.py egg_info --tag-build=.0.%s --tag-svn-revision --tag-date sdist %s" % (venvDir,
options.build_number,
upload_bit),
options.workspace)
call_command("%sbin/epydoc --html --graph all %s" % (venvDir, options.package),
options.workspace)
logging.info("Complete")
if __name__ == "__main__":
main()
Quando si tratta di distribuire elementi, è possibile fare qualcosa del tipo:
pip -E /location/of/my/venv/ install my_package==X.Y.Z --extra-index http://my_repo
E poi le persone possono sviluppare cose usando:
pip -E /location/of/my/venv/ install -e ./ --extra-index http://my_repo
Questa roba presuppone che tu abbia una struttura di repository per pacchetto con un setup.py e dipendenze tutte impostate, quindi puoi semplicemente dare un'occhiata al trunk ed eseguire questa roba su di esso.
Spero che questo aiuti qualcuno.
------ aggiornamento ---------
Ho aggiunto epydoc che si adatta perfettamente a Hudson. Aggiungi javadoc alla tua configurazione con la cartella html
Nota che pip non supporta correttamente il flag -E in questi giorni, quindi devi creare il tuo venv separatamente
un altro: Shining Panda è uno strumento ospitato per Python
Se stai prendendo in considerazione la soluzione CI ospitata e stai facendo open source, dovresti esaminare Travis CI come bene - ha un'ottima integrazione con GitHub. Mentre è iniziato come uno strumento Ruby, hanno aggiunto il supporto Python qualche tempo fa.
Il segnale è un'altra opzione. Puoi saperne di più e guardare un video anche qui .
Vorrei prendere in considerazione CircleCi - ha un ottimo supporto Python e un output molto carino.
binstar di continuum ora è in grado di attivare build da github e compilare per linux, osx e windows (32/64). la cosa bella è che ti permette davvero di accoppiare strettamente la distribuzione e l'integrazione continua. Questo è attraversare le t e punteggiare gli I di integrazione. Il sito, il flusso di lavoro e gli strumenti sono davvero raffinati e AFAIK conda è il modo più robusto e pitonico per distribuire complessi moduli Python, dove è necessario avvolgere e distribuire librerie C / C ++ / Fotran.
Abbiamo usato un po 'morso. È carino e si integra bene con Trac, ma è una seccatura da personalizzare se hai un flusso di lavoro non standard. Inoltre non ci sono tanti plugin quanti sono gli strumenti più popolari. Attualmente stiamo valutando Hudson in sostituzione.
Controlla rultor.com . Come questo articolo spiega, utilizza Docker per ogni build . Grazie a ciò, puoi configurare quello che vuoi nell'immagine Docker, incluso Python.
Poco disclaimer, in realtà ho dovuto creare una soluzione come questa per un client che voleva un modo per testare e distribuire automaticamente qualsiasi codice su un push git e gestire i ticket di emissione tramite note git . Ciò ha portato anche al mio lavoro sul progetto AIMS .
Si potrebbe facilmente impostare un sistema a nodo nudo che ha un utente build e gestirne la build tramite make (1)
, prevedono (1)
, crontab (1)
/ systemd.unit (5)
e incrontab (1)
. Si potrebbe anche fare un passo avanti e utilizzare ansible e sedano per build distribuite con un archivio di file gridfs / nfs.
Anche se non mi aspetterei che nessun altro che un ragazzo UNIX di Barbabianca o un ingegnere / architetto di livello Principio si spinga davvero così lontano. È solo una buona idea e una potenziale esperienza di apprendimento poiché un server di build non è altro che un modo per eseguire arbitrariamente attività di script in modo automatizzato.