J'avais besoin de mettre en place le processus d'assemblage et de livraison de progiciels depuis un référentiel Git vers le site. Et quand j'ai vu, il n'y a pas si longtemps, ici sur Habré un article sur buildbot (lien à la fin), j'ai décidé de l'essayer et de l'appliquer.
Étant donné que buildbot est un système distribué, il serait logique de créer un hôte de build distinct pour chaque architecture et système d'exploitation. Dans notre cas, il s'agira de conteneurs LXC (dans le cas de Linux) et qemu (dans le cas de Windows) :
vm-srv-build1 - centos 7, il y aura un maître buildbot et l'un des travailleurs
vm-srv-build2 - debian 10, pour créer des packages DEB
vm-srv-build3 - Windows 10, pour l'assemblage, vous savez à quoi ça sert
Nous collecterons Interface graphique Rac — une interface graphique pour 1C rac pour la gestion d'un cluster de serveurs. Pour Linux, des outils standards pour chaque système d'exploitation seront utilisés ; pour créer un fichier exe pour Windows à partir d'un script tcl, utilisez enveloppement libre.
Installation
GNU / Linux
Il existe suffisamment de documentation sur Internet pour l'installation 1,2. Oui, et cela ne pose pas de problèmes particuliers :
Pour le maître :
Bien sûr, il serait plus correct de collecter des packages pour chaque système d'exploitation, mais cela dépasse le cadre de l'article. Nous omettrons également la description de la mise en place des conteneurs pour le travail, je noterai seulement que j'utilise ProxMox VE. Et vous devrez également installer des packages pour chaque axe requis pour l'assemblage (centos : rpmdevtools, etc. ; debian : build-essential, dh-make, pbuilder, etc.)
Les projets de build et les services buildbot seront lancés en tant qu'utilisateur non privilégié, vous devez donc en créer un sur tous les hôtes participant au processus :
adduser buildbot
Ensuite, nous configurerons le lancement automatique des services, respectivement, sur chacun des hôtes (conteneurs) :
Après cela, vous pouvez créer une infrastructure de répertoires pour les « travailleurs » (sur tous les hôtes), pour ce faire, inscrivez-vous sous l'utilisateur buildbot et exécutez les commandes suivantes :
Sur le premier hôte vm-srv-build1 :
su - buildbot
mkdir /home/buildbot/worker
cd ~
buildbot-worker create-worker --umask=0o22 --keepalive=60 worker vm-srv-build1:4000 CentOS 123456
Sur le deuxième hôte vm-srv-build2 :
su - buildbot
mkdir /home/buildbot/worker
cd ~
buildbot-worker create-worker --umask=0o22 --keepalive=60 worker vm-srv-build1:4000 Debian-10 123456
Sur les hôtes de travail, le service buildbot-worker peut être démarré
systemctl start buildbot-worker
MS Windows
En tant que « travailleur » pour l'assemblage sous Windows, une machine virtuelle avec la dernière version de Win10 sera utilisée.
Pour travailler besoin:
Une fois tout ce qui précède installé, vous pouvez installer le buildbot lui-même :
pip install buildbot-worker
Créons un répertoire de travail
md c:worker
Et lançons
buildbot-worker start c:worker
Si tout fonctionne (voir log c:workertwistd.log), alors vous pouvez enregistrer notre « travailleur » en tant que service en ajoutant un élément avec le répertoire de travail au registre (les commandes sont exécutées dans PowerShell exécuté en tant qu'administrateur) :
C'est tout avec les "ouvriers", vous n'avez pas besoin d'y toucher davantage, tout le contrôle vient du maître.
Configuration de l'assistant
Pour commencer, créons l'infrastructure pour le maître (sur l'hôte principal), pour ce faire, inscrivez-vous sous l'utilisateur buildbot et exécutez les commandes suivantes :
su - buildbot
mkdir /home/buildbot/master
cd ~
buildbot create-master master
Pour les packages prêts à l'emploi, créez un répertoire builds
mkdir /home/buildbot/builds
Un fichier master.cfg a été créé dans le répertoire /home/buildbot/master/. Ce fichier est un code python et contient une description de tous les mécanismes du système ; nous travaillerons avec lui à l'avenir.
Pour automatiser l'assemblage de packages de différentes versions, afin de ne pas avoir à se plonger dans le code du fichier master.cfg, dans le script principal du programme rac_gui.tcl, des lignes avec la version et la release actuelles ont été ajoutées dans l'en-tête :
Et sur la base de ces lignes, buildbot numérotera les packages. Pour extraire des données, utilisez l'appel grep de la console. Dans buildbot, vous ne pouvez tout simplement pas définir de variables pour les « travailleurs » (du moins, je n'ai pas trouvé comment). C'est à cela que servent les propriétés. Ceux. Dans le processus d'assemblage, nous ajoutons des étapes pour déterminer la version et la version et, en conséquence, définissons les propriétés de la version et de la version. Les propriétés peuvent être définies de différentes manières, dans ce cas en appelant la commande console :
# Добавим определение версии из основного файла
rac_gui_build_RPM.addStep(
steps.SetPropertyFromCommand(
command="grep version ../rac-gui/rac_gui.tcl | grep -oE 'b[0-9]{1,2}.[0-9]{1,2}.[0-9]{1,2}b'", property="version"
)
)
# Добавим определение релиза из основного файла
rac_gui_build_RPM.addStep(
steps.SetPropertyFromCommand(
command="grep release ../rac-gui/rac_gui.tcl | grep -oE 'b[0-9]{1,3}b'", property="release"
)
)
Vous pouvez remplacer les valeurs résultantes en appelant util.Interpolate().
Il convient de noter ici que puisque l'hôte est également utilisé pour l'assemblage manuel des packages, l'assemblage s'effectuera selon des chemins standards.
Pour définir les numéros de version et de version corrects, utilisez un appel sed standard, c'est-à-dire la commande remplace les valeurs à l'intérieur du fichier de spécifications par celles requises
Nous copions le package assemblé fini et l'archive avec les sources vers le maître. Mais vous pouvez immédiatement copier des fichiers de votre fichier de travail vers votre référentiel ou votre site Web.
# Скопируем файл на мастер
rac_gui_build_RPM.addStep(
steps.FileUpload(
workersrc=util.Interpolate("/home/buildbot/rpmbuild/RPMS/noarch/rac-gui-%(prop:version)s-%(prop:release)s.noarch.rpm"),
masterdest=util.Interpolate("/home/buildbot/builds/rac-gui-%(prop:version)s-%(prop:release)s.noarch.rpm")
)
)
rac_gui_build_RPM.addStep(
steps.FileUpload(
workersrc=util.Interpolate("/home/buildbot/rpmbuild/SOURCES/rac-gui-%(prop:version)s-%(prop:release)s.tar.gz"),
masterdest=util.Interpolate("/home/buildbot/builds/rac-gui-%(prop:version)s-%(prop:release)s.tar.gz")
)
)
Commençons le processus de copie des packages collectés vers l'hébergement via FTP sur le maître. A cet effet, il est utilisé scénario sur tcl.
C'est tout avec RPM. Commençons maintenant à décrire l'algorithme de création d'un package DEB. Étant donné que les processus de création de packages pour différents systèmes sont indépendants les uns des autres, de nombreuses étapes seront répétées.
rac_gui_build_DEB = util.BuildFactory()
rac_gui_build_DEB.addStep(steps.Git(
repourl = 'https://bitbucket.org/svk28/rac-gui.git',
haltOnFailure = True,
submodules = True,
mode='full',
workdir='build',
progress = True)
)
# Добавим определение версии из основного файла
rac_gui_build_DEB.addStep(
steps.SetPropertyFromCommand(
command="grep version rac_gui.tcl | grep -oE 'b[0-9]{1,2}.[0-9]{1,2}.[0-9]{1,2}b'", property="version"
)
)
# Добавим определение релиза из основного файла
rac_gui_build_DEB.addStep(
steps.SetPropertyFromCommand(
command="grep release rac_gui.tcl | grep -oE 'b[0-9]{1,3}b'", property="release"
)
)
# Переименуем запускаемый файл
rac_gui_build_DEB.addStep(steps.ShellCommand(
command=["mv", "rac_gui.tcl", "racgui"]))
Pour un paquet RPM, certaines des procédures suivantes sont effectuées par le RPM lui-même lors de l'assemblage et sont décrites dans la spécification ; pour Debian, vous devez le faire ici :
# Поменяем пути к библиотекам
rac_gui_build_DEB.addStep(steps.ShellCommand(
command=["sed", "-i", "s+^set dir(lib)+set dir(lib) /usr/share/rac-gui/lib ;#+g", "racgui"]))
# Поменяем пути к файлам
rac_gui_build_DEB.addStep(steps.ShellCommand(
command=["sed", "-i", "s+[pwd]+/usr/share/rac-gui+g", "racgui"]))
# заархивируем исходники
rac_gui_build_DEB.addStep(steps.ShellCommand(
command=["tar", "czf", util.Interpolate("../rac-gui_%(prop:version)s.orig.tar.gz"), "."]))
# Соберём пакет
rac_gui_build_DEB.addStep(steps.ShellCommand(
command=["dpkg-buildpackage"]))
# Скопируем файл на мастер
rac_gui_build_DEB.addStep(
steps.FileUpload(
workersrc=util.Interpolate("../rac-gui_%(prop:version)s-%(prop:release)s_amd64.deb"),
masterdest=util.Interpolate("/home/buildbot/builds/rac-gui_%(prop:version)s-%(prop:release)s_amd64.deb")
)
)
rac_gui_build_DEB.addStep(
steps.MasterShellCommand(
command=["/usr/local/bin/deploy-ftp.tcl",
util.Interpolate("--local-file=/home/buildbot/builds/rac-gui_%(prop:version)s-%(prop:release)s_amd64.deb"),
util.Interpolate("--remote-file=uploads/rac-gui/rac-gui_%(prop:version)s-%(prop:release)s_amd64.deb")]
)
)
Enregistrez le fichier et vous pouvez essayer de démarrer le service assistant :
systemctl restart buildbot-master
Dans le journal, nous vérifierons que tout est en ordre avec la configuration et que tout fonctionne normalement. Tous nos travailleurs devraient maintenant se connecter, ce qui sera volontiers signalé dans le journal »»'/home/buildbot/master/twistd.log»»' :
2019-07-24 16:50:35+0300 [-] Loading buildbot.tac...
2019-07-24 16:50:35+0300 [-] Loaded.
2019-07-24 16:50:35+0300 [-] twistd 19.2.1 (/usr/bin/python3.6 3.6.8) starting up.
2019-07-24 16:50:35+0300 [-] reactor class: twisted.internet.epollreactor.EPollReactor.
2019-07-24 16:50:35+0300 [-] Starting BuildMaster -- buildbot.version: 2.3.1
2019-07-24 16:50:35+0300 [-] Loading configuration from '/home/buildbot/master/master.cfg'
2019-07-24 16:50:36+0300 [-] /usr/local/lib/python3.6/site-packages/buildbot/config.py:90: buildbot.config.ConfigWarning: [0.9.0 and later] `buildbotNetUsageData` is not configured and defaults to basic.
This parameter helps the buildbot development team to understand the installation base.
No personal information is collected.
Only installation software version info and plugin usage is sent.
You can `opt-out` by setting this variable to None.
Or `opt-in` for more information by setting it to "full".
2019-07-24 16:50:36+0300 [-] Setting up database with URL 'sqlite:/state.sqlite'
2019-07-24 16:50:36+0300 [-] setting database journal mode to 'wal'
2019-07-24 16:50:36+0300 [-] adding 1 new services, removing 0
2019-07-24 16:50:36+0300 [-] adding 1 new change_sources, removing 0
2019-07-24 16:50:36+0300 [-] gitpoller: using workdir '/home/buildbot/master/gitpoller-work'
2019-07-24 16:50:36+0300 [-] adding 3 new builders, removing 0
2019-07-24 16:50:36+0300 [-] adding 1 new schedulers, removing 0
2019-07-24 16:50:36+0300 [-] initializing www plugin 'waterfall_view'
2019-07-24 16:50:36+0300 [-] initializing www plugin 'console_view'
2019-07-24 16:50:36+0300 [-] initializing www plugin 'grid_view'
2019-07-24 16:50:36+0300 [-] NOTE: www plugin 'sitenav' is installed but not configured
2019-07-24 16:50:36+0300 [-] initializing www plugin 'waterfall_view'
2019-07-24 16:50:36+0300 [-] initializing www plugin 'console_view'
2019-07-24 16:50:36+0300 [-] initializing www plugin 'grid_view'
2019-07-24 16:50:36+0300 [-] NOTE: www plugin 'sitenav' is installed but not configured
2019-07-24 16:50:36+0300 [-] BuildbotSite starting on 80
2019-07-24 16:50:36+0300 [-] Starting factory <buildbot.www.service.BuildbotSite object at 0x7fe31c2657b8>
2019-07-24 16:50:36+0300 [-] adding 3 new workers, removing 0
2019-07-24 16:50:36+0300 [-] PBServerFactory starting on 4000
2019-07-24 16:50:36+0300 [-] Starting factory <twisted.spread.pb.PBServerFactory object at 0x7fe31c147470>
2019-07-24 16:50:37+0300 [-] BuildMaster is running
2019-07-24 16:50:37+0300 [-] buildbotNetUsageData: sending {'installid': 'b6193b126b96689351d2fe95787c5a03fc0879f9', 'versions': {'Python': '3.6.8', 'Buildbot': '2.3.1', 'Twisted': '19.2.1'}, 'platform': {'platform': 'Linux-4.15.18-10- pve-x86_64-with-centos-7.6.1810-Core', 'system': 'Linux', 'machine': 'x86_64', 'processor': 'x86_64', 'python_implementation': 'CPython', 'version': '#1 SMP PVE 4.15.18-32', 'distro': 'centos:7'}, 'plugins': {'buildbot/worker/base/Worker': 3, 'buildbot/config/BuilderConfig': 3, 'buildbot/schedulers/basic/SingleBranchScheduler': 1, 'buildbot/reporters/mail/MailNotifier': 1, 'buildbot/changes/gitpoller/GitPoller': 1, 'buildbot/steps/worker/MakeDirectory': 1, 'buildbot/steps/source/git/Git': 3, 'buildbot/steps/shell/ShellCommand': 9, 'buildbot/steps/package/rpm/rpmbuild/RpmBuild': 1}, 'db': 'sqlite', 'mq': 'simple', 'www_plugins': ['waterfall_view', 'console_view', 'grid_view']}
2019-07-24 16:50:37+0300 [Broker,0,127.0.0.1] worker 'CentOS' attaching from IPv4Address(type='TCP', host='127.0.0.1', port=37332)
2019-07-24 16:50:37+0300 [Broker,0,127.0.0.1] Got workerinfo from 'CentOS'
2019-07-24 16:50:37+0300 [-] bot attached
2019-07-24 16:50:37+0300 [Broker,0,127.0.0.1] Worker CentOS attached to Rac-GUI-RPM-builder
2019-07-24 16:50:37+0300 [-] buildbotNetUsageData: buildbot.net said: ok
2019-07-24 16:50:39+0300 [Broker,1,192.168.55.15] worker 'Windows-10' attaching from IPv4Address(type='TCP', host='192.168.5.145', port=49831)
2019-07-24 16:50:39+0300 [Broker,1,192.168.55.15] Got workerinfo from 'Windows-10'
2019-07-24 16:50:40+0300 [-] bot attached
2019-07-24 16:50:40+0300 [Broker,1,192.168.55.15] Worker Windows-10 attached to Rac-GUI-WIN-builder
2019-07-24 16:50:41+0300 [Broker,2,192.168.55.99] worker 'Debian-10' attaching from IPv4Address(type='TCP', host='192.168.5.9', port=44430)
2019-07-24 16:50:41+0300 [Broker,2,192.168.55.99] Got workerinfo from 'Debian-10'
2019-07-24 16:50:41+0300 [-] bot attached
2019-07-24 16:50:41+0300 [Broker,2,192.168.55.99] Worker Debian-10 attached to Rac-GUI-DEB-builder
Ceci termine le processus de configuration. Vous pouvez consulter l'état actuel via l'interface Web. Où vous pouvez également voir les erreurs de construction, lancer un processus gelé en cas de problème, etc.
Immédiatement après le lancement, nos travailleurs acharnés peuvent être consultés via le menu « Builds » -> « Workers »
Une fois le premier processus de construction terminé (c'est-à-dire les modifications apportées au référentiel Git), l'état des processus apparaîtra sur la première page.
Si vous cliquez sur la ligne souhaitée avec la souris, une page s'ouvrira avec l'état actuel de ce processus, où vous pourrez voir ce qui se passe, quelles erreurs, etc.
La configuration complète de l'assistant peut être trouvée ici