246ef92e6e5a2401e1f41ce9c4e1319ebd5e8053
[buildbot.git] / phase2 / master.cfg
1 # -*- python -*-
2 # ex: set syntax=python:
3
4 import os
5 import re
6 import subprocess
7 import ConfigParser
8
9 from buildbot import locks
10
11 ini = ConfigParser.ConfigParser()
12 ini.read("./config.ini")
13
14 # This is a sample buildmaster config file. It must be installed as
15 # 'master.cfg' in your buildmaster's base directory.
16
17 # This is the dictionary that the buildmaster pays attention to. We also use
18 # a shorter alias to save typing.
19 c = BuildmasterConfig = {}
20
21 ####### BUILDSLAVES
22
23 # The 'slaves' list defines the set of recognized buildslaves. Each element is
24 # a BuildSlave object, specifying a unique slave name and password. The same
25 # slave name and password must be configured on the slave.
26 from buildbot.buildslave import BuildSlave
27
28 c['slaves'] = []
29
30 for section in ini.sections():
31 if section.startswith("slave "):
32 if ini.has_option(section, "name") and ini.has_option(section, "password"):
33 name = ini.get(section, "name")
34 password = ini.get(section, "password")
35 max_builds = 1
36 if ini.has_option(section, "builds"):
37 max_builds = ini.getint(section, "builds")
38 c['slaves'].append(BuildSlave(name, password, max_builds = max_builds))
39
40 # 'slavePortnum' defines the TCP port to listen on for connections from slaves.
41 # This must match the value configured into the buildslaves (with their
42 # --master option)
43 c['slavePortnum'] = 9990
44
45 # coalesce builds
46 c['mergeRequests'] = True
47
48 ####### CHANGESOURCES
49
50 home_dir = ini.get("general", "homedir")
51
52 repo_url = ini.get("repo", "url")
53
54 rsync_url = ini.get("rsync", "url")
55 rsync_key = ini.get("rsync", "password")
56
57 # find arches
58 arches = [ ]
59 archnames = [ ]
60
61 findarches = subprocess.Popen([home_dir+'/dumpinfo.pl', 'architectures'],
62 stdout = subprocess.PIPE, cwd = home_dir+'/source.git')
63
64 while True:
65 line = findarches.stdout.readline()
66 if not line:
67 break
68 at = line.strip().split()
69 arches.append(at)
70 archnames.append(at[0])
71
72
73 # find feeds
74 feeds = []
75
76 from buildbot.changes.gitpoller import GitPoller
77 c['change_source'] = []
78
79 with open(home_dir+'/source.git/feeds.conf.default', 'r') as f:
80 for line in f:
81 parts = line.strip().split()
82 if parts[0] == "src-git":
83 feeds.append(parts)
84 c['change_source'].append(GitPoller(parts[2], workdir='%s/%s.git' %(os.getcwd(), parts[1]), branch='master', pollinterval=300))
85
86
87 ####### SCHEDULERS
88
89 # Configure the Schedulers, which decide how to react to incoming changes. In this
90 # case, just kick off a 'basebuild' build
91
92 from buildbot.schedulers.basic import SingleBranchScheduler
93 from buildbot.schedulers.forcesched import ForceScheduler
94 from buildbot.changes import filter
95 c['schedulers'] = []
96 c['schedulers'].append(SingleBranchScheduler(
97 name="all",
98 change_filter=filter.ChangeFilter(branch='master'),
99 treeStableTimer=60,
100 builderNames=archnames))
101
102 c['schedulers'].append(ForceScheduler(
103 name="force",
104 builderNames=archnames))
105
106 ####### BUILDERS
107
108 # The 'builders' list defines the Builders, which tell Buildbot how to perform a build:
109 # what steps, and which slaves can execute them. Note that any particular build will
110 # only take place on one slave.
111
112 from buildbot.process.factory import BuildFactory
113 from buildbot.steps.source import Git
114 from buildbot.steps.shell import ShellCommand
115 from buildbot.steps.transfer import FileDownload
116 from buildbot.process.properties import WithProperties
117
118 c['builders'] = []
119
120 dlLock = locks.SlaveLock("slave_dl")
121
122 slaveNames = [ ]
123
124 for slave in c['slaves']:
125 slaveNames.append(slave.slavename)
126
127 for arch in arches:
128 ts = arch[1].split('/')
129
130 factory = BuildFactory()
131
132 # prepare workspace
133 factory.addStep(FileDownload(mastersrc="cleanup.sh", slavedest="cleanup.sh", mode=0755))
134
135 factory.addStep(ShellCommand(
136 name = "cleanold",
137 description = "Cleaning previous builds",
138 command = ["./cleanup.sh", WithProperties("%(slavename)s"), WithProperties("%(buildername)s"), "full"],
139 haltOnFailure = True,
140 timeout = 2400))
141
142 factory.addStep(ShellCommand(
143 name = "cleanup",
144 description = "Cleaning work area",
145 command = ["./cleanup.sh", WithProperties("%(slavename)s"), WithProperties("%(buildername)s"), "single"],
146 haltOnFailure = True,
147 timeout = 2400))
148
149 factory.addStep(ShellCommand(
150 name = "mksdkdir",
151 description = "Preparing SDK directory",
152 command = ["mkdir", "sdk"],
153 haltOnFailure = True))
154
155 factory.addStep(ShellCommand(
156 name = "downloadsdk",
157 description = "Downloading SDK archive",
158 command = ["rsync", "-va", "downloads.lede-project.org::downloads/snapshots/targets/%s/%s/LEDE-SDK-*.tar.bz2" %(ts[0], ts[1]), "sdk.tar.bz2"],
159 haltOnFailure = True))
160
161 factory.addStep(ShellCommand(
162 name = "unpacksdk",
163 description = "Unpacking SDK archive",
164 command = ["tar", "--strip-components=1", "-C", "sdk/", "-vxjf", "sdk.tar.bz2"],
165 haltOnFailure = True))
166
167 factory.addStep(FileDownload(mastersrc=home_dir+'/key-build', slavedest="sdk/key-build", mode=0400))
168
169 factory.addStep(ShellCommand(
170 name = "mkdldir",
171 description = "Preparing download directory",
172 command = ["sh", "-c", "mkdir -p $HOME/dl && rmdir ./sdk/dl && ln -sf $HOME/dl ./sdk/dl"]))
173
174 factory.addStep(ShellCommand(
175 name = "updatefeeds",
176 description = "Updating feeds",
177 workdir = "build/sdk",
178 command = ["./scripts/feeds", "update"]))
179
180 factory.addStep(ShellCommand(
181 name = "installfeeds",
182 description = "Installing feeds",
183 workdir = "build/sdk",
184 command = ["./scripts/feeds", "install", "-a"]))
185
186 factory.addStep(ShellCommand(
187 name = "compile",
188 description = "Building packages",
189 workdir = "build/sdk",
190 command = ["make", "-j4", "V=s", "IGNORE_ERRORS=n m y", "BUILD_LOG=1", "CONFIG_SIGNED_PACKAGES=y"]))
191
192 factory.addStep(ShellCommand(
193 name = "uploadprepare",
194 description = "Preparing package directory",
195 workdir = "build/sdk",
196 command = ["rsync", "-av", "--include", "/%s/" %(arch[0]), "--exclude", "/*", "--exclude", "/%s/*" %(arch[0]), "bin/packages/", "%s/packages/" %(rsync_url)],
197 env={'RSYNC_PASSWORD': rsync_key},
198 haltOnFailure = True,
199 logEnviron = False
200 ))
201
202 factory.addStep(ShellCommand(
203 name = "packageupload",
204 description = "Uploading package files",
205 workdir = "build/sdk",
206 command = ["rsync", "--delete", "-avz", "bin/packages/%s/" %(arch[0]), "%s/packages/%s/" %(rsync_url, arch[0])],
207 env={'RSYNC_PASSWORD': rsync_key},
208 haltOnFailure = True,
209 logEnviron = False
210 ))
211
212 factory.addStep(ShellCommand(
213 name = "logprepare",
214 description = "Preparing log directory",
215 workdir = "build/sdk",
216 command = ["rsync", "-av", "--include", "/%s/" %(arch[0]), "--exclude", "/*", "--exclude", "/%s/*" %(arch[0]), "bin/packages/", "%s/faillogs/" %(rsync_url)],
217 env={'RSYNC_PASSWORD': rsync_key},
218 haltOnFailure = True,
219 logEnviron = False
220 ))
221
222 factory.addStep(ShellCommand(
223 name = "logfind",
224 description = "Finding failure logs",
225 workdir = "build/sdk/logs/package/feeds",
226 command = ["sh", "-c", "sed -ne 's!^ *ERROR: package/feeds/\\([^ ]*\\) .*$!\\1!p' ../error.txt | sort -u | xargs -r find > ../../../logs.txt"],
227 haltOnFailure = False
228 ))
229
230 factory.addStep(ShellCommand(
231 name = "logcollect",
232 description = "Collecting failure logs",
233 workdir = "build/sdk",
234 command = ["rsync", "-av", "--files-from=logs.txt", "logs/package/feeds/", "faillogs/"],
235 haltOnFailure = False
236 ))
237
238 factory.addStep(ShellCommand(
239 name = "logupload",
240 description = "Uploading failure logs",
241 workdir = "build/sdk",
242 command = ["rsync", "--delete", "-avz", "faillogs/", "%s/faillogs/%s/" %(rsync_url, arch[0])],
243 env={'RSYNC_PASSWORD': rsync_key},
244 haltOnFailure = False,
245 logEnviron = False
246 ))
247
248 from buildbot.config import BuilderConfig
249
250 c['builders'].append(BuilderConfig(name=arch[0], slavenames=slaveNames, factory=factory))
251
252
253 ####### STATUS arches
254
255 # 'status' is a list of Status arches. The results of each build will be
256 # pushed to these arches. buildbot/status/*.py has a variety to choose from,
257 # including web pages, email senders, and IRC bots.
258
259 c['status'] = []
260
261 from buildbot.status import html
262 from buildbot.status.web import authz, auth
263
264 if ini.has_option("status", "bind"):
265 if ini.has_option("status", "user") and ini.has_option("status", "password"):
266 authz_cfg=authz.Authz(
267 # change any of these to True to enable; see the manual for more
268 # options
269 auth=auth.BasicAuth([(ini.get("status", "user"), ini.get("status", "password"))]),
270 gracefulShutdown = False,
271 forceBuild = 'auth', # use this to test your slave once it is set up
272 forceAllBuilds = 'auth',
273 pingBuilder = False,
274 stopBuild = 'auth',
275 stopAllBuilds = 'auth',
276 cancelPendingBuild = 'auth',
277 )
278 c['status'].append(html.WebStatus(http_port=ini.get("status", "bind"), authz=authz_cfg))
279 else:
280 c['status'].append(html.WebStatus(http_port=ini.get("status", "bind")))
281
282 ####### PROJECT IDENTITY
283
284 # the 'title' string will appear at the top of this buildbot
285 # installation's html.WebStatus home page (linked to the
286 # 'titleURL') and is embedded in the title of the waterfall HTML page.
287
288 c['title'] = ini.get("general", "title")
289 c['titleURL'] = ini.get("general", "title_url")
290
291 # the 'buildbotURL' string should point to the location where the buildbot's
292 # internal web server (usually the html.WebStatus page) is visible. This
293 # typically uses the port number set in the Waterfall 'status' entry, but
294 # with an externally-visible host name which the buildbot cannot figure out
295 # without some help.
296
297 c['buildbotURL'] = ini.get("general", "buildbot_url")
298
299 ####### DB URL
300
301 c['db'] = {
302 # This specifies what database buildbot uses to store its state. You can leave
303 # this at its default for all but the largest installations.
304 'db_url' : "sqlite:///state.sqlite",
305 }
306