Skip to content

Commit 5b5fd0c

Browse files
classabbyampthe-maldridge
authored andcommitted
services/nomad/build: add buildbot nomad job
1 parent d76434d commit 5b5fd0c

File tree

2 files changed

+532
-0
lines changed

2 files changed

+532
-0
lines changed

services/nomad/build/buildbot.cfg

Lines changed: 368 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,368 @@
1+
# vim: set ft=python:
2+
3+
# {{ $allocID := env "NOMAD_ALLOC_ID" }}
4+
5+
import configparser
6+
import json
7+
import shlex
8+
from pathlib import Path
9+
10+
from twisted.internet import defer
11+
12+
from buildbot.process.results import SUCCESS, SKIPPED
13+
from buildbot.plugins import util, secrets, reporters, worker, schedulers
14+
from buildbot.plugins import steps
15+
16+
ini = configparser.ConfigParser()
17+
ini.read('/local/config.ini')
18+
19+
with open(ini['buildbot'].get('workers', '/local/workers.json')) as f:
20+
js = json.load(f)
21+
workers = js.get("workers", [])
22+
builders = js.get("builders", [])
23+
24+
netauth = util.BuildbotNetAuth(conf=Path("/etc/netauth/config.toml"))
25+
26+
authz = util.Authz(
27+
allowRules=[
28+
util.AnyEndpointMatcher(role="ops", defaultDeny=False),
29+
util.AnyControlEndpointMatcher(role="ops"),
30+
],
31+
roleMatchers=[
32+
util.RolesFromGroups(groupPrefix="build-"),
33+
]
34+
)
35+
36+
c = BuildmasterConfig = {
37+
'buildbotNetUsageData': None,
38+
'protocols': {'pb': {'port': ini['buildbot'].getint('worker-port', 9989)}},
39+
'secretsProviders': [secrets.SecretInAFile(dirname="/secrets/buildbot")],
40+
'workers': [],
41+
'change_source': [],
42+
'collapseRequests': True,
43+
'schedulers': [],
44+
'builders': [],
45+
'services': [reporters.Prometheus(port=9100)],
46+
'title': ini['buildbot'].get('title', 'Void Linux'),
47+
'titleURL': ini['buildbot'].get('title-url', 'https://voidlinux.org/'),
48+
'buildbotURL': ini['buildbot'].get('url', 'http://localhost:8010/'),
49+
'www': {
50+
'port': ini['buildbot'].getint('www-port', 8010),
51+
'plugins': {'waterfall_view': {}, 'console_view': {}, 'grid_view': {}, 'void_view': {}},
52+
'change_hook_dialects': {
53+
'github': {
54+
'secret': util.Secret('github-webhook'),
55+
'strict': True,
56+
},
57+
},
58+
'avatar_methods': [
59+
netauth, util.AvatarGitHub(), util.AvatarGravatar(),
60+
],
61+
'authz': authz,
62+
'auth': netauth,
63+
'ui_default_config': {
64+
'Links.build_link_template': "%(build_number)",
65+
'Waterfall.number_background_waterfall': True,
66+
'Waterfall.show_builders_without_builds': True,
67+
'Builders.show_workers_name': True,
68+
'Grid.fullChanges': True,
69+
},
70+
},
71+
'db': {
72+
'db_url': ini['buildbot'].get('db-url', 'sqlite:////db/state.sqlite'),
73+
},
74+
}
75+
76+
if 'irc' in ini:
77+
c['services'].append(reporters.IRC(
78+
host=ini['irc']['host'],
79+
port=ini['irc'].getint('port', 6697),
80+
nick=ini['irc']['nick'],
81+
password=util.Secret('irc-password'),
82+
channels=[ini['irc']['channel']],
83+
authz={'!': ini['irc'].get('authz-users', '').split(' ')},
84+
notify_events=ini['irc'].get(
85+
'notify-events', 'failure exception cancelled worker'
86+
).split(),
87+
noticeOnChannel=ini['irc'].getboolean('notice', True),
88+
# useRevisions and showBlameList are not implemented and will cause
89+
# the irc notifier to error out, do NOT enable them
90+
useRevisions=ini['irc'].getboolean('use-revisions', False),
91+
showBlameList=ini['irc'].getboolean('show-blame', False),
92+
useSSL=ini['irc'].getboolean('use-ssl', True),
93+
useColors=ini['irc'].getboolean('use-colors', True),
94+
))
95+
96+
# ###### WORKERS
97+
98+
for w in workers:
99+
name = 'worker-' + w['name']
100+
passwd = util.Secret('worker-password')
101+
max_builds = w.get('max-builds', 1)
102+
c['workers'].append(worker.Worker(name, passwd, max_builds=max_builds))
103+
104+
105+
# ###### SCHEDULERS
106+
107+
builder_names = []
108+
for b in builders:
109+
builder_names.append(b['name'])
110+
111+
c['schedulers'].append(schedulers.SingleBranchScheduler(
112+
name="all",
113+
change_filter=util.ChangeFilter(branch='master'),
114+
treeStableTimer=None,
115+
builderNames=builder_names))
116+
117+
c['schedulers'].append(schedulers.ForceScheduler(
118+
name="force",
119+
builderNames=builder_names))
120+
121+
122+
# ###### BUILDERS
123+
124+
distdir = 'void-packages'
125+
bulkdir = 'xbps-bulk'
126+
hostdir = '/hostdir'
127+
buildroot = 'buildroot'
128+
builddir = lambda: util.Interpolate('builddir-%(prop:buildnumber)s')
129+
do_sync = lambda: util.Interpolate('%(prop:sync)s') == "True"
130+
hide_skipped = lambda results, _: results == SKIPPED
131+
132+
133+
factory = util.BuildFactory()
134+
135+
136+
@util.renderer
137+
def make_xbps_src_cmd(props, cmd):
138+
command = [
139+
f'{distdir}/xbps-src',
140+
'-H', hostdir,
141+
'-m', buildroot,
142+
'-A', props.getProperty('host'),
143+
]
144+
145+
if cmd == 'binary-bootstrap':
146+
command += shlex.split(str(props.getProperty('bootstrap_args')))
147+
elif props.getProperty('cross') == 'True':
148+
command += ['-a', props.getProperty('target')]
149+
150+
command += [cmd]
151+
152+
return command
153+
154+
155+
@util.renderer
156+
def make_xbps_bulk_cmd(props):
157+
command = [
158+
f'../{bulkdir}/configure',
159+
'-h', hostdir,
160+
'-d', f'../{distdir}',
161+
'-m', f'../{buildroot}',
162+
'-t',
163+
]
164+
if props.getProperty('cross') == 'True':
165+
command += ['-a', props.getProperty('target')]
166+
else:
167+
command += ['-a', 'native-', props.getProperty('host')]
168+
169+
return command
170+
171+
172+
class ShellCommandWithChanges(steps.ShellCommand):
173+
@defer.inlineCallbacks
174+
def run(self):
175+
cmd = yield self.makeRemoteShellCommand()
176+
pkgs = [f.split("/")[-2] for f in self.build.allFiles()
177+
if f.startswith("srcpkgs/") and f.endswith("/template")]
178+
cmd.command += pkgs
179+
yield self.runCommand(cmd)
180+
return cmd.results()
181+
182+
183+
@util.renderer
184+
def build_packages(props):
185+
# if a better solver is written
186+
# cmds = []
187+
# for p in str(props.getProperty('packages')).strip().split():
188+
# cmds.append(util.ShellArg(
189+
# command=['make', f'built/{p}'],
190+
# logname=f'pkg:{p}',
191+
# haltOnFailure=True,
192+
# ))
193+
cmds = [util.ShellArg(
194+
command=['make', 'all'],
195+
logname='build',
196+
haltOnFailure=True,
197+
)]
198+
if cmds:
199+
cmds.append(util.ShellArg(
200+
command=['make', 'clean'],
201+
logname='cleanup',
202+
haltOnFailure=True,
203+
))
204+
return cmds
205+
206+
207+
@util.renderer
208+
def make_prune_cmd(props):
209+
return ['bash', '-c',
210+
util.Interpolate(f"""
211+
export XBPS_TARGET_ARCH="%(prop:target)s"
212+
for repo in / /debug /nonfree /bootstrap; do
213+
xbps-rindex -r "{hostdir}/binpkgs/$repo"
214+
done
215+
if [ "$XBPS_TARGET_ARCH" = i686 ]; then
216+
for repo in /multilib /multilib/nonfree /multilib/bootstrap; do
217+
XBPS_TARGET_ARCH=x86_64 xbps-rindex -r "{hostdir}/binpkgs/$repo"
218+
done
219+
fi
220+
""")]
221+
222+
@util.renderer
223+
def make_rsync_cmd(props):
224+
return ['bash', '-c',
225+
util.Interpolate("""
226+
rsync -vurk --delete-after --delay-updates \
227+
--filter='+ */ + %(prop:target)s-repodata + %(prop:target)s-stagedata + *.%(prop:target)s.xbps + otime - .* - *' \
228+
--password-file=/secrets/rsync/password /hostdir/binpkgs/ \
229+
{{ range nomadService 1 $allocID "build-rsyncd" -}}
230+
rsync://buildsync-%(prop:worker)s@{{ .Address }}:{{ .Port }}/%(prop:worker)s
231+
{{ end -}}""")]
232+
233+
234+
factory.addStep(steps.Git(
235+
repourl='https://github.com/void-linux/void-packages.git',
236+
mode='incremental',
237+
workdir=distdir,
238+
progress=True,
239+
alwaysUseLatest=True,
240+
name='update_void_packages',
241+
description='updating void-packages from git',
242+
descriptionDone='void-packages updated',
243+
haltOnFailure=True,
244+
logEnviron=False,
245+
))
246+
247+
factory.addStep(steps.Git(
248+
repourl='https://github.com/void-linux/xbps-bulk.git',
249+
mode='incremental',
250+
workdir=bulkdir,
251+
progress=True,
252+
alwaysUseLatest=True,
253+
name='update_xbps_bulk',
254+
description='updating xbps-bulk from git',
255+
descriptionDone='xbps-bulk updated',
256+
haltOnFailure=True,
257+
logEnviron=False,
258+
))
259+
260+
factory.addStep(steps.ShellCommand(
261+
command=make_xbps_src_cmd.withArgs('binary-bootstrap'),
262+
name='bootstrap',
263+
description='running xbps-src binary-bootstrap',
264+
descriptionDone='xbps-src binary-bootstrap done',
265+
haltOnFailure=True,
266+
logEnviron=False,
267+
usePTY=True,
268+
workdir='.',
269+
))
270+
271+
factory.addStep(steps.ShellCommand(
272+
command=make_xbps_src_cmd.withArgs('bootstrap-update'),
273+
name='bootstrap_update',
274+
description='updating xbps-src bootstrap packages',
275+
descriptionDone='xbps-src bootstrap-update done',
276+
haltOnFailure=True,
277+
logEnviron=False,
278+
usePTY=True,
279+
workdir='.',
280+
))
281+
282+
factory.addStep(ShellCommandWithChanges(
283+
command=make_xbps_bulk_cmd,
284+
name='find_packages',
285+
description='finding packages to build',
286+
descriptionDone='found packages',
287+
haltOnFailure=True,
288+
logEnviron=False,
289+
usePTY=True,
290+
workdir=builddir(),
291+
))
292+
293+
factory.addStep(steps.SetPropertyFromCommand(
294+
command=['make', 'print_pkgs'],
295+
property='packages',
296+
name='get_packages',
297+
description='collecting packages to build',
298+
descriptionDone='collected packages',
299+
haltOnFailure=True,
300+
logEnviron=False,
301+
workdir=builddir(),
302+
))
303+
304+
factory.addStep(steps.ShellSequence(
305+
commands=build_packages,
306+
name='build_packages',
307+
description='building packages',
308+
descriptionDone='built packages',
309+
haltOnFailure=True,
310+
logEnviron=False,
311+
usePTY=True,
312+
workdir=builddir(),
313+
timeout=14400,
314+
))
315+
316+
factory.addStep(steps.ShellCommand(
317+
command=make_prune_cmd,
318+
name='prune_packages',
319+
description='removing obsolete packages',
320+
descriptionDone='removed obsolete packages',
321+
haltOnFailure=True,
322+
logEnviron=False,
323+
usePTY=True,
324+
workdir='.',
325+
timeout=14400,
326+
))
327+
328+
factory.addStep(steps.ShellCommand(
329+
command=make_rsync_cmd,
330+
name='sync_packages',
331+
description='syncing packages to the shadow repository',
332+
descriptionDone='synced packages to the shadow repository',
333+
alwaysRun=True,
334+
logEnviron=False,
335+
usePTY=True,
336+
workdir='.',
337+
doStepIf=do_sync(),
338+
hideStepIf=hide_skipped,
339+
timeout=14400,
340+
decodeRC={
341+
0: SUCCESS,
342+
23: SUCCESS,
343+
24: SUCCESS,
344+
},
345+
))
346+
347+
for b in builders:
348+
workernames = ["worker-" + b['worker']]
349+
350+
name = b['name']
351+
hostarch = b['host']
352+
targetarch = b.get('target', hostarch)
353+
props = {
354+
'name': name,
355+
'host': hostarch,
356+
'target': targetarch,
357+
'cross': str(hostarch != targetarch),
358+
'worker': b['worker'],
359+
'sync': str(b['sync']),
360+
'bootstrap_args': b.get('bootstrap_args', '-N'),
361+
}
362+
363+
c['builders'].append(util.BuilderConfig(
364+
name=name,
365+
workernames=workernames,
366+
factory=factory,
367+
properties=props,
368+
))

0 commit comments

Comments
 (0)