ฉันจำเป็นต้องตั้งค่ากระบวนการประกอบและจัดส่งแพ็คเกจซอฟต์แวร์จากพื้นที่เก็บข้อมูล Git ไปยังไซต์ และเมื่อฉันเห็นบทความเกี่ยวกับ buildbot เมื่อไม่นานมานี้ในHabré (ลิงก์ท้ายสุด) ฉันจึงตัดสินใจลองใช้และนำไปใช้
เนื่องจาก buildbot เป็นระบบแบบกระจาย จึงสมเหตุสมผลที่จะสร้างโฮสต์ build แยกต่างหากสำหรับแต่ละสถาปัตยกรรมและระบบปฏิบัติการ ในกรณีของเรา สิ่งเหล่านี้จะเป็นคอนเทนเนอร์ LXC (ในกรณีของ Linux) และ qemu (ในกรณีของ Windows):
- vm-srv-build1 - centos 7 จะมี buildbot master และหนึ่งในคนงาน
- vm-srv-build2 - debian 10 สำหรับการสร้างแพ็คเกจ DEB
- vm-srv-build3 - windows 10 สำหรับการประกอบคุณรู้เพื่ออะไร
เราจะรวบรวม
การติดตั้ง
GNU / Linux
มีเอกสารเพียงพอบนอินเทอร์เน็ตสำหรับการติดตั้ง
สำหรับอาจารย์:
pip3 install buildbot
pip3 install twisted
pip3 install autobahn
pip3 install pysqlite3
pip3 install sqlalchemy sqlalchemy-migrate
pip3 install buildbot-www buildbot-grid-view buildbot-console-view buildbot-waterfall-view
pip3 install python-dateutil
สำหรับ “คนงาน” แค่นี้ก็เพียงพอแล้ว:
pip3 install buildbot-worker
แน่นอนว่าการรวบรวมแพ็คเกจสำหรับแต่ละระบบปฏิบัติการจะเหมาะสมกว่า แต่นี่อยู่นอกเหนือขอบเขตของบทความ นอกจากนี้เรายังจะละเว้นคำอธิบายการตั้งค่าคอนเทนเนอร์สำหรับงาน ฉันจะทราบเพียงว่าฉันใช้ ProxMox VE เท่านั้น และคุณจะต้องติดตั้งแพ็คเกจสำหรับแต่ละแกนที่จำเป็นสำหรับการประกอบ (centos: rpmdevtools ฯลฯ ; debian: build-essential, dh-make, pbuilder ฯลฯ )
โปรเจ็กต์บิวด์และบริการ buildbot จะเปิดตัวในฐานะผู้ใช้ที่ไม่มีสิทธิ์ ดังนั้นคุณต้องสร้างโปรเจ็กต์หนึ่งรายการบนโฮสต์ทั้งหมดที่เข้าร่วมในกระบวนการ:
adduser buildbot
ต่อไป เราจะกำหนดค่าการเปิดตัวบริการโดยอัตโนมัติตามลำดับในแต่ละโฮสต์ (คอนเทนเนอร์):
หน่วย Systemd เพื่อรันวิซาร์ด:
touch /etc/systemd/buildbot-master.service
[Unit]
Description=BuildBot master service
After=network.target
[Service]
User=buildbot
Group=buildbot
WorkingDirectory=/home/buildbot/master
ExecStart=/usr/local/bin/buildbot start --nodaemon
ExecReload=/bin/kill -HUP $MAINPID
[Install]
WantedBy=multi-user.target
และ "คนงาน"
touch /etc/systemd/buildbot-worker.service
[Unit]
Description=BuildBot worker service
After=network.target
[Service]master
User=buildbot
Group=buildbot
WorkingDirectory=/home/buildbot/worker
ExecStart=/usr/local/bin/buildbot-worker start --nodaemon
[Install]
WantedBy=buildbot-master.service
เนื่องจากสคริปต์ทั้งหมด (ในกรณีของเรา) อยู่ใน /usr/local/ คุณควรกำหนดเส้นทางไปยังสคริปต์เหล่านั้นในตัวแปรสภาพแวดล้อม:
nano /root/.bash_profile
PATH=$PATH:$HOME/.local/bin:$HOME/bin:/usr/local/bin
หลังจากนี้ คุณสามารถสร้างโครงสร้างพื้นฐานไดเร็กทอรีสำหรับ "ผู้ปฏิบัติงาน" (บนโฮสต์ทั้งหมด) โดยทำการลงทะเบียนภายใต้ผู้ใช้ buildbot และรันคำสั่งต่อไปนี้:
บนโฮสต์แรก 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
บนโฮสต์ที่สอง 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
บนโฮสต์ของผู้ปฏิบัติงาน สามารถเริ่มบริการ buildbot-ผู้ปฏิบัติงานได้
systemctl start buildbot-worker
MS Windows
ในฐานะ "ผู้ปฏิบัติงาน" สำหรับการประกอบภายใต้ Windows จะใช้เครื่องเสมือนที่มี Win10 รุ่นล่าสุด
ในการทำงานคุณจะต้อง:
หลาม ไพวิน ไป - หากต้องการติดตั้งสิ่งต่าง ๆ ทุกประเภทใน Python คุณต้องดาวน์โหลด
สร้างเครื่องมือสำหรับ Visual Studio 2019 - 7Zip
หลังจากติดตั้งทั้งหมดที่กล่าวมาข้างต้นแล้ว คุณสามารถติดตั้ง buildbot ได้เอง:
pip install buildbot-worker
มาสร้างไดเร็กทอรีการทำงานกันเถอะ
md c:worker
และมาเปิดตัวกัน
buildbot-worker start c:worker
หากทุกอย่างใช้งานได้ (ดูบันทึก c:workertwistd.log) คุณสามารถลงทะเบียน "ผู้ปฏิบัติงาน" ของเราเป็นบริการได้โดยการเพิ่มรายการที่มีไดเร็กทอรีการทำงานลงในรีจิสทรี (คำสั่งจะดำเนินการใน PowerShell ที่ทำงานในฐานะผู้ดูแลระบบ):
buildbot_worker_windows_service.exe --user VM-SRV-BUILD3buildbot --password 123456 --startup auto install
New-ItemProperty -path Registry::HKEY_LOCAL_MACHINESYSTEMCurrentControlSetservicesBuildBotParameters -Name directories -PropertyType String -Value c:worker
และคุณสามารถเริ่มใช้บริการได้
Start-Service buildbot
นั่นคือทั้งหมดสำหรับ "คนงาน" คุณไม่จำเป็นต้องแตะต้องพวกเขาอีกต่อไป การควบคุมทั้งหมดมาจากผู้เชี่ยวชาญ
การตั้งค่าตัวช่วยสร้าง
ขั้นแรก เรามาสร้างโครงสร้างพื้นฐานสำหรับต้นแบบ (บนโฮสต์หลัก) เพื่อดำเนินการนี้ โดยลงทะเบียนภายใต้ผู้ใช้ buildbot และรันคำสั่งต่อไปนี้:
su - buildbot
mkdir /home/buildbot/master
cd ~
buildbot create-master master
สำหรับแพ็คเกจสำเร็จรูป ให้สร้างไดเร็กทอรี builds
mkdir /home/buildbot/builds
ไฟล์ master.cfg ถูกสร้างขึ้นในไดเร็กทอรี /home/buildbot/master/ ไฟล์นี้เป็นโค้ด Python และมีคำอธิบายกลไกทั้งหมดของระบบ เราจะทำงานร่วมกับมันในอนาคต
nano /home/buildbot/master/master.cfg
import os, re
from buildbot.plugins import steps, util, schedulers, worker, changes, reporters
c= BuildmasterConfig ={}
# Описание наших рабочих.
c['workers'] = [ worker.Worker('CentOS', '123456'), worker.Worker('Debian-10', '123456'), worker.Worker('Windows-10', '123456')]
c['protocols'] = {'pb': {'port': 4000}}
# Указание мастеру какой репозиторий отслеживать
c['change_source'] = []
c['change_source'].append(changes.GitPoller(
repourl = 'https://bitbucket.org/svk28/rac-gui.git',
project = 'Rac-GUI',
branches = True,
pollInterval = 60
)
)
# служба запуска сборки
c['schedulers'] = []
c['schedulers'].append(schedulers.SingleBranchScheduler(
name="Rac-GUI-schedulers",
change_filter=util.ChangeFilter(branch='master'),
builderNames=["Rac-GUI-RPM-builder", "Rac-GUI-DEB-builder", "Rac-GUI-WIN-builder"],
properties = {'owner': 'admin'}
)
)
@util.renderer
######################################3
# Сборка RPM-пакета
rac_gui_build_RPM = util.BuildFactory()
rac_gui_build_RPM.addStep(steps.Git(
repourl = 'https://bitbucket.org/svk28/rac-gui.git',
workdir = 'rac-gui',
haltOnFailure = True,
submodules = True,
mode='full',
progress = True)
)
ในการทำให้การประกอบแพ็คเกจของเวอร์ชันต่าง ๆ เป็นแบบอัตโนมัติ เพื่อที่จะไม่ต้องเจาะลึกโค้ดของไฟล์ master.cfg ในสคริปต์หลักของโปรแกรม rac_gui.tcl บรรทัดที่มีเวอร์ชันปัจจุบันและรีลีสจะถูกเพิ่มในส่วนหัว : :
######################################################
# Rac GUI
...
# version: 1.0.3
# release: 1
และตามบรรทัดเหล่านี้ buildbot จะกำหนดหมายเลขแพ็คเกจ หากต้องการแยกข้อมูล ให้ใช้การเรียก grep ของคอนโซล ใน buildbot คุณไม่สามารถกำหนดตัวแปรสำหรับ "คนงาน" ได้ (อย่างน้อยฉันก็ยังไม่พบวิธีการ) นี่คือคุณสมบัติที่ใช้สำหรับ เหล่านั้น. ในกระบวนการประกอบ เราได้เพิ่มขั้นตอนในการกำหนดเวอร์ชันและการเผยแพร่ และตั้งค่าคุณสมบัติเวอร์ชันและการเผยแพร่ตามลำดับ คุณสมบัติสามารถตั้งค่าได้หลายวิธี ในกรณีนี้ โดยการเรียกคำสั่งคอนโซล:
# Добавим определение версии из основного файла
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"
)
)
คุณสามารถแทนที่ค่าผลลัพธ์ได้ด้วยการเรียก util.Interpolate()
# Запакуем исходники
rac_gui_build_RPM.addStep(
steps.ShellCommand(
command=["tar", "czf", util.Interpolate("/home/buildbot/rpmbuild/SOURCES/rac-gui-%(prop:version)s-%(prop:release)s.tar.gz"), "../rac-gui"]
)
)
ควรสังเกตว่าเนื่องจากโฮสต์ยังใช้สำหรับการประกอบบรรจุภัณฑ์ด้วยตนเอง การประกอบจึงเกิดขึ้นตามเส้นทางมาตรฐาน
# Копируем spec
rac_gui_build_RPM.addStep(steps.ShellCommand(
command=["cp", "../rac-gui/rac_gui.spec", "/home/buildbot/rpmbuild/SPECS/rac_gui.spec"]))
หากต้องการตั้งค่าหมายเลขรุ่นและเวอร์ชันที่ถูกต้อง ให้ใช้การเรียก sed มาตรฐาน เช่น คำสั่งจะแทนที่ค่าภายในไฟล์ spec ด้วยค่าที่ต้องการ
# меняем версию
rac_gui_build_RPM.addStep(steps.ShellCommand(
command=["sed", "-i", util.Interpolate("s/.*Version:.*/Version:t%(prop:version)s/"), "/home/buildbot/rpmbuild/SPECS/rac_gui.spec"]))
# меняем релиз
rac_gui_build_RPM.addStep(steps.ShellCommand(
command=["sed", "-i", util.Interpolate("s/.*Release:.*/Release:t%(prop:release)s/"), "/home/buildbot/rpmbuild/SPECS/rac_gui.spec"]))
# запускаем процесс сборки
rac_gui_build_RPM.addStep(steps.RpmBuild(
specfile="/home/buildbot/rpmbuild/SPECS/rac_gui.spec",
dist='.el5',
topdir='/home/buildbot/rpmbuild',
builddir='/home/buildbot/rpmbuild/build',
rpmdir='/home/buildbot/rpmbuild/RPMS',
sourcedir='/home/buildbot/rpmbuild/SOURCES'
)
)
เราคัดลอกแพ็คเกจที่ประกอบเสร็จแล้วและไฟล์เก็บถาวรพร้อมแหล่งที่มาไปยังต้นแบบ แต่คุณสามารถคัดลอกไฟล์จากไฟล์งานของคุณไปยังพื้นที่เก็บข้อมูลหรือเว็บไซต์ของคุณได้ทันที
# Скопируем файл на мастер
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")
)
)
มาเริ่มกระบวนการคัดลอกแพ็คเกจที่รวบรวมไปยังโฮสต์ผ่าน FTP บนต้นแบบกันดีกว่า เพื่อจุดประสงค์นี้จึงถูกนำมาใช้
rac_gui_build_RPM.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.noarch.rpm"),
util.Interpolate("--remote-file=uploads/rac-gui/rac-gui-%(prop:version)s-%(prop:release)s.noarch.rpm")]
)
)
rac_gui_build_RPM.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.tar.gz"),
util.Interpolate("--remote-file=uploads/rac-gui/rac-gui-%(prop:version)s-%(prop:release)s.tar.gz")]
)
)
แค่นั้นแหละกับ RPM ตอนนี้เรามาเริ่มอธิบายอัลกอริทึมสำหรับการสร้างแพ็คเกจ DEB กันดีกว่า เนื่องจากกระบวนการสร้างแพ็คเกจสำหรับระบบที่แตกต่างกันมีความเป็นอิสระจากกัน หลายขั้นตอนจึงต้องทำซ้ำ
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"]))
สำหรับแพ็คเกจ RPM ขั้นตอนต่อไปนี้บางส่วนจะทำโดย rpm เองระหว่างการประกอบและอธิบายไว้ภายในข้อมูลจำเพาะ สำหรับ Debian คุณต้องทำที่นี่:
# Поменяем пути к библиотекам
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")]
)
)
และทำกับ DEB เสร็จแล้ว ตอนนี้ windows!
rac_gui_build_WIN = util.BuildFactory()
rac_gui_build_WIN.addStep(steps.Git(
repourl = 'https://bitbucket.org/svk28/rac-gui.git',
haltOnFailure = True,
submodules = True,
mode='full',
workdir='build',
progress = True)
)
เนื่องจาก grep และ sed ไม่ใช่มาตรฐานใน Windows (หรือมีหรือไม่) เราจะใช้ PowerShell
# Добавим определение версии из основного файла
rac_gui_build_WIN.addStep(
steps.SetPropertyFromCommand(
command="powershell -command "((Get-Content .rac_gui.tcl | Select-String -Pattern 'version:') -split 's')[2]",
property="version"
)
)
# Добавим определение релиза из основного файла
rac_gui_build_WIN.addStep(
steps.SetPropertyFromCommand(
command="powershell -command "((Get-Content .rac_gui.tcl | Select-String -Pattern 'release:') -split 's')[2]",
property="release"
)
)
# Создадим запускаемый файл
rac_gui_build_WIN.addStep(steps.ShellCommand(
command=["c:binfreewrap.exe", "rac_gui.tcl"]))
# запакуем то, что получилось
rac_gui_build_WIN.addStep(steps.ShellCommand(
command=["c:Program Files7-zip7z.exe", "a", "-r", util.Interpolate("..rac-gui_%(prop:version)s-%(prop:release)s.win.zip"), "..build"]))
# скопируем на мастер
rac_gui_build_WIN.addStep(
steps.FileUpload(
workersrc=util.Interpolate("..rac-gui_%(prop:version)s-%(prop:release)s.win.zip"),
masterdest=util.Interpolate("/home/buildbot/builds/rac-gui_%(prop:version)s-%(prop:release)s.win.zip")
)
)
# Скопируем файл на хостинг
rac_gui_build_WIN.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.win.zip"),
util.Interpolate("--remote-file=uploads/rac-gui/rac-gui_%(prop:version)s-%(prop:release)s.win.zip")]
)
)
# Тут определяем какие сборщики у нас есть
c['builders'] = [
util.BuilderConfig(name="Rac-GUI-RPM-builder", workername='CentOS', factory=rac_gui_build_RPM),
util.BuilderConfig(name="Rac-GUI-DEB-builder", workername='Debian-10', factory=rac_gui_build_DEB),
util.BuilderConfig(name="Rac-GUI-WIN-builder", workername='Windows-10', factory=rac_gui_build_WIN),
]
เราจะใช้อีเมลเพื่อแจ้งให้คุณทราบเกี่ยวกับสถานะของกระบวนการสร้าง
c['services'] = []
template=u'''
<h4>Build status: {{ summary }}</h4>
<p> Worker used: {{ workername }}</p>
{% for step in build['steps'] %}
<p> {{ step['name'] }}: {{ step['result'] }}</p>
{% endfor %}
<p><b> -- The Buildbot</b></p>
'''
mailNotifier = reporters.MailNotifier(fromaddr="[email protected]",
sendToInterestedUsers=False,
mode=('all'),
extraRecipients=["[email protected]"],
relayhost="mail.domain.ru",
smtpPort=587,
smtpUser="[email protected]",
smtpPassword="******",
messageFormatter=reporters.MessageFormatter(
template=template, template_type='html',
wantProperties=True, wantSteps=True))
c['services'].append(mailNotifier)
# Основные настройки мастера
c['title'] = "The process of bulding"
c['titleURL'] = "http://vm-srv-build1:80/"
c['buildbotURL'] = "http://vm-srv-build1/"
c['www'] = dict(port=80,
plugins=dict(waterfall_view={}, console_view={}, grid_view={}))
c['db'] = {
'db_url' : "sqlite:///state.sqlite"
}
บันทึกไฟล์และคุณสามารถลองเริ่มบริการตัวช่วยสร้างได้:
systemctl restart buildbot-master
ในบันทึก เราจะตรวจสอบว่าทุกอย่างเป็นไปตามการกำหนดค่าและทุกอย่างทำงานได้ตามปกติ ตอนนี้พนักงานของเราทุกคนควรเชื่อมต่อกัน ซึ่งจะถูกรายงานอย่างมีความสุขในบันทึก »»'/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
เสร็จสิ้นกระบวนการตั้งค่า คุณสามารถดูสถานะปัจจุบันผ่านทางเว็บอินเตอร์เฟส ที่ซึ่งคุณสามารถดูข้อผิดพลาดของบิลด์ เตะกระบวนการที่ค้างหากมีข้อผิดพลาดเกิดขึ้น ฯลฯ
ทันทีหลังจากการเปิดตัว คุณสามารถดูผู้ทำงานหนักของเราได้ผ่านเมนู "สร้าง" -> "ผู้ปฏิบัติงาน"
หลังจากกระบวนการสร้างครั้งแรกเสร็จสิ้น (เช่น การเปลี่ยนแปลงพื้นที่เก็บข้อมูล Git) สถานะของกระบวนการจะปรากฏในหน้าแรก
หากคุณคลิกเมาส์บนบรรทัดที่ต้องการ หน้าเว็บจะเปิดขึ้นพร้อมสถานะปัจจุบันของกระบวนการนี้ ซึ่งคุณสามารถดูได้ว่าเกิดอะไรขึ้น ข้อผิดพลาดใด ฯลฯ
สามารถดูการกำหนดค่าวิซาร์ดทั้งหมดได้ที่นี่
import os, re
from buildbot.plugins import steps, util, schedulers, worker, changes, reporters
c= BuildmasterConfig ={}
c['workers'] = [ worker.Worker('CentOS', '123456'), worker.Worker('Debian-10', '123456'), worker.Worker('Windows-10', '123456')]
c['protocols'] = {'pb': {'port': 4000}}
c['change_source'] = []
c['change_source'].append(changes.GitPoller(
repourl = 'https://bitbucket.org/svk28/rac-gui.git',
project = 'Rac-GUI',
branches = True,
pollInterval = 600
))
# служба запуска сборки
c['schedulers'] = []
c['schedulers'].append(schedulers.SingleBranchScheduler(
name="Rac-GUI-schedulers",
change_filter=util.ChangeFilter(branch='master'),
builderNames=["Rac-GUI-RPM-builder", "Rac-GUI-DEB-builder", "Rac-GUI-WIN-builder"],
properties = {'owner': 'admin'}
))
@util.renderer
def get_name_version_release(props):
prog_name = "rac-gui"
prog_version = "1.0.3"
prog_release = "3"
return {
"prog_name": prog_name
#"prog_version": prog_version,
#"prog_release": prog_release
}
rac_gui_build_RPM = util.BuildFactory()
rac_gui_build_RPM.addStep(steps.Git(
repourl = 'https://bitbucket.org/svk28/rac-gui.git',
workdir = 'rac-gui',
haltOnFailure = True,
submodules = True,
mode='full',
progress = True)
)
# Добавим определение версии из основного файла
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"
)
)
rac_gui_build_RPM.addStep(steps.ShellCommand(
command=["tar", "czf", util.Interpolate("/home/buildbot/rpmbuild/SOURCES/rac-gui-%(prop:version)s-%(prop:release)s.tar.gz"), "../rac-gui"]))
rac_gui_build_RPM.addStep(steps.ShellCommand(
command=["cp", "../rac-gui/rac_gui.spec", "/home/buildbot/rpmbuild/SPECS/rac_gui.spec"]))
rac_gui_build_RPM.addStep(steps.ShellCommand(
command=["sed", "-i", util.Interpolate("s/.*Version:.*/Version:t%(prop:version)s/"), "/home/buildbot/rpmbuild/SPECS/rac_gui.spec"]))
rac_gui_build_RPM.addStep(steps.ShellCommand(
command=["sed", "-i", util.Interpolate("s/.*Release:.*/Release:t%(prop:release)s/"), "/home/buildbot/rpmbuild/SPECS/rac_gui.spec"]))
rac_gui_build_RPM.addStep(steps.RpmBuild(
specfile="/home/buildbot/rpmbuild/SPECS/rac_gui.spec",
dist='.el5',
topdir='/home/buildbot/rpmbuild',
builddir='/home/buildbot/rpmbuild/build',
rpmdir='/home/buildbot/rpmbuild/RPMS',
sourcedir='/home/buildbot/rpmbuild/SOURCES'
))
# Скопируем файл на мастер
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")
)
)
rac_gui_build_RPM.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.noarch.rpm"),
util.Interpolate("--remote-file=uploads/rac-gui/rac-gui-%(prop:version)s-%(prop:release)s.noarch.rpm")]
)
)
rac_gui_build_RPM.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.tar.gz"),
util.Interpolate("--remote-file=uploads/rac-gui/rac-gui-%(prop:version)s-%(prop:release)s.tar.gz")]
)
)
####################################
## DEB
####################################
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"]))
# Поменяем пути к библиотекам
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")]
)
)
############################################
# WIN
############################################
rac_gui_build_WIN = util.BuildFactory()
rac_gui_build_WIN.addStep(steps.Git(
repourl = 'https://bitbucket.org/svk28/rac-gui.git',
haltOnFailure = True,
submodules = True,
mode='full',
workdir='build',
progress = True)
)
# Добавим определение версии из основного файла
rac_gui_build_WIN.addStep(
steps.SetPropertyFromCommand(
command="powershell -command "((Get-Content .rac_gui.tcl | Select-String -Pattern 'version:') -split 's')[2]",
property="version"
)
)
# Добавим определение релиза из основного файла
rac_gui_build_WIN.addStep(
steps.SetPropertyFromCommand(
command="powershell -command "((Get-Content .rac_gui.tcl | Select-String -Pattern 'release:') -split 's')[2]",
property="release"
)
)
# Создадим запускаемый файл
rac_gui_build_WIN.addStep(steps.ShellCommand(
command=["c:binfreewrap.exe", "rac_gui.tcl"]))
# запакуем то, что получилось
rac_gui_build_WIN.addStep(steps.ShellCommand(
command=["c:Program Files7-zip7z.exe", "a", "-r", util.Interpolate("..rac-gui_%(prop:version)s-%(prop:release)s.win.zip"), "..build"]))
# скопируем на мастер
rac_gui_build_WIN.addStep(
steps.FileUpload(
workersrc=util.Interpolate("..rac-gui_%(prop:version)s-%(prop:release)s.win.zip"),
masterdest=util.Interpolate("/home/buildbot/builds/rac-gui_%(prop:version)s-%(prop:release)s.win.zip")
)
)
# Скопируем файл на хостинг
rac_gui_build_WIN.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.win.zip"),
util.Interpolate("--remote-file=uploads/rac-gui/rac-gui_%(prop:version)s-%(prop:release)s.win.zip")]
)
)
c['builders'] = [
util.BuilderConfig(name="Rac-GUI-RPM-builder", workername='CentOS', factory=rac_gui_build_RPM),
util.BuilderConfig(name="Rac-GUI-DEB-builder", workername='Debian-10', factory=rac_gui_build_DEB),
util.BuilderConfig(name="Rac-GUI-WIN-builder", workername='Windows-10', factory=rac_gui_build_WIN),
]
c['services'] = []
template=u'''
<h4>Build status: {{ summary }}</h4>
<p> Worker used: {{ workername }}</p>
{% for step in build['steps'] %}
<p> {{ step['name'] }}: {{ step['result'] }}</p>
{% endfor %}
<p><b> -- The Buildbot</b></p>
'''
mailNotifier = reporters.MailNotifier(fromaddr="[email protected]",
sendToInterestedUsers=False,
mode=('all'),
extraRecipients=["[email protected]"],
relayhost="mail.domain.local",
smtpPort=587,
smtpUser="[email protected]",
smtpPassword="**********",
messageFormatter=reporters.MessageFormatter(
template=template, template_type='html',
wantProperties=True, wantSteps=True))
c['services'].append(mailNotifier)
c['title'] = "The process of bulding"
c['titleURL'] = "http://vm-srv-build1:80/"
c['buildbotURL'] = "http://vm-srv-build1/"
c['www'] = dict(port=80,
plugins=dict(waterfall_view={}, console_view={}, grid_view={}))
c['db'] = {
'db_url' : "sqlite:///state.sqlite"
}
วัสดุ
มีการใช้สื่อต่อไปนี้ในการเตรียมบทความ:
ตัวอย่างการใช้งานการบูรณาการอย่างต่อเนื่องโดยใช้ BuildBot Buildbot: เรื่องราวพร้อมตัวอย่างเกี่ยวกับระบบบูรณาการที่ต่อเนื่องอีกระบบหนึ่ง การตั้งค่าการรวมอย่างต่อเนื่องใน Buildbot บน Ubuntu 16.04 - เอกสารประกอบผลิตภัณฑ์
บทช่วยสอน Buildbot
ที่มา: will.com