Merge lp:~christophe-lyon/cbuild/tools-fix-svn-name into lp:cbuild
- tools-fix-svn-name
- Merge into trunk
Proposed by
Christophe Lyon
Status: | Needs review |
---|---|
Proposed branch: | lp:~christophe-lyon/cbuild/tools-fix-svn-name |
Merge into: | lp:cbuild |
Diff against target: |
3321 lines (+3126/-0) 39 files modified
MAINTAIN.txt (+92/-0) aarch64-merger.sh (+172/-0) addtestdiffs.py (+133/-0) cache-builds.py (+131/-0) chain.sh (+75/-0) check-leaks.sh (+14/-0) closest.py (+63/-0) cron-often.sh (+56/-0) ctimes.py (+100/-0) difftests.sh (+45/-0) ec2-pull.sh (+28/-0) ec2-spawn.sh (+36/-0) ec2new.sh (+23/-0) ec2slave-init-cbuild.sh (+36/-0) ec2slave-init.sh (+105/-0) ec2slave.sh (+65/-0) ec2watch.sh (+18/-0) enrich-gcc-linaro-repo (+45/-0) export-bzr.sh (+85/-0) export-git.sh (+75/-0) export-hg.sh (+61/-0) findancestor.py (+204/-0) findlogs.py (+113/-0) gcc-release.sh (+168/-0) getbody.py (+26/-0) lab-pull.sh (+22/-0) latestami.sh (+17/-0) launcher.sh (+146/-0) libec2.sh (+78/-0) pull_branch.sh (+21/-0) s3-diet.py (+91/-0) spawn.sh (+36/-0) stamp_branch.sh (+70/-0) tabulate.sh (+36/-0) taker.json (+82/-0) taker.py (+396/-0) track-tree.sh (+16/-0) up_branch.sh (+53/-0) utilisation.py (+93/-0) |
To merge this branch: | bzr merge lp:~christophe-lyon/cbuild/tools-fix-svn-name |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Linaro Toolchain Builder | Pending | ||
Review via email: mp+216447@code.launchpad.net |
Commit message
Description of the change
Attempt to avoid generation of ~/var/snapshots
To post a comment you must log in.
- 108. By Christophe Lyon
-
Fix previous commit.
Unmerged revisions
- 108. By Christophe Lyon
-
Fix previous commit.
- 107. By Christophe Lyon
-
Do not generate tarball and delta if no name parameter is provided.
- 106. By Renato Golin
-
Adding Clang/Extra/RT to LLVM update
- 105. By Yvan Roux
-
Add gcc-linaro-4.8 branch in cron-often polling task.
- 104. By Linaro Toolchain Builder
-
Add support for toolchain64 host and GCC Linaro 4.8 branch
- 103. By Linaro Toolchain Builder
-
Update find to take gcc-4.8 branches into account.
- 102. By Christophe Lyon
-
Fix bug #1156536
- 101. By Michael Hope
-
Fix taker stuff
- 100. By Michael Hope
-
Make tabulate work on all GCC results.
- 99. By Michael Hope
-
Update to use gcc-google-4.7 and not gcc-google-4.6
Preview Diff
[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1 | === added file 'MAINTAIN.txt' | |||
2 | --- MAINTAIN.txt 1970-01-01 00:00:00 +0000 | |||
3 | +++ MAINTAIN.txt 2014-07-01 15:58:40 +0000 | |||
4 | @@ -0,0 +1,92 @@ | |||
5 | 1 | cbuild maintenance tasks | ||
6 | 2 | ======================== | ||
7 | 3 | |||
8 | 4 | Users | ||
9 | 5 | ----- | ||
10 | 6 | * cbuild - pulls keys from http://launchpad.net/~cbuild | ||
11 | 7 | |||
12 | 8 | Things to watch | ||
13 | 9 | --------------- | ||
14 | 10 | |||
15 | 11 | Disks: | ||
16 | 12 | |||
17 | 13 | * / for free space | ||
18 | 14 | * /space for free space | ||
19 | 15 | |||
20 | 16 | `~/var/snapshots/gcc-4.8?svn*`: | ||
21 | 17 | |||
22 | 18 | * Youngest is no more than 3 days old | ||
23 | 19 | * Check cbuild-tools/launcher.sh on fault | ||
24 | 20 | |||
25 | 21 | `~/var/tcwg-web/*.pickle`: | ||
26 | 22 | |||
27 | 23 | * No more than four hours old | ||
28 | 24 | * Check lib/tcwg-web/update.sh on fault | ||
29 | 25 | |||
30 | 26 | Common tasks | ||
31 | 27 | ------------ | ||
32 | 28 | |||
33 | 29 | Where have all my directories gone? | ||
34 | 30 | |||
35 | 31 | * ~/lib/cbuild | ||
36 | 32 | * ~/var/snapshots | ||
37 | 33 | * ~/public_html/build | ||
38 | 34 | |||
39 | 35 | How do I spawn a release build via the shell? | ||
40 | 36 | |||
41 | 37 | * Use gcc-release-process.sh! else: | ||
42 | 38 | * scp gcc-linaro-4.7-2012.12.tar.bz2 cbuild@toolchain64.lab:~/var/snapshots | ||
43 | 39 | * ssh cbuild@toolchain64.lab | ||
44 | 40 | * ~/lib/cbuild-tools/spawn.sh ~/var/snapshots/gcc-linaro-4.7-2012.tar.bz2 | ||
45 | 41 | |||
46 | 42 | A fault with frequent tasks like merge reqeusts, tip builds or data | ||
47 | 43 | being out of date? | ||
48 | 44 | |||
49 | 45 | * Check ~/lib/cbuild-tools/cron-often.sh | ||
50 | 46 | |||
51 | 47 | A fault with daily tasks like upstream builds? | ||
52 | 48 | |||
53 | 49 | * Check ~/lib/cbuild-tools/launcher.sh | ||
54 | 50 | |||
55 | 51 | A fault with one of the helpers? | ||
56 | 52 | |||
57 | 53 | * sudo service tcwg-web stop | ||
58 | 54 | * cd lib/tcwg-web | ||
59 | 55 | * Uncommet 'development = True' in twg-web.ini | ||
60 | 56 | * python index.py | ||
61 | 57 | * Run the request, see the backtrace | ||
62 | 58 | |||
63 | 59 | Version out of date on one of the upstream builds? | ||
64 | 60 | |||
65 | 61 | * Edit launcher.sh | ||
66 | 62 | |||
67 | 63 | Want to build/track a new upstream? | ||
68 | 64 | |||
69 | 65 | * git clone upstream-url ~/repos/decent-name | ||
70 | 66 | * Add a new dow line to launcher.sh | ||
71 | 67 | |||
72 | 68 | Want to track a new Linaro series? | ||
73 | 69 | |||
74 | 70 | * cd ~/repos/gcc-linaro | ||
75 | 71 | * bzr branch lp:gcc-linaro/4.8 | ||
76 | 72 | * Add a new line to cron-often.sh | ||
77 | 73 | * Consider pushing a new gcc-linaro-4.8+bzr12345.{tar,tar.xz} to ~/var/snapshots/base | ||
78 | 74 | |||
79 | 75 | Want to propogate a cbuild update to the slaves? | ||
80 | 76 | |||
81 | 77 | * cd ~/lib/cbuild | ||
82 | 78 | * bzr pull | ||
83 | 79 | |||
84 | 80 | Want to add a new build queue? | ||
85 | 81 | |||
86 | 82 | * cd ~/var/scheduler/queue | ||
87 | 83 | * mkdir queue-name | ||
88 | 84 | * echo host1 host2 host3 > queue-name/hosts.txt | ||
89 | 85 | * echo config-fragments-if-any > queue-name/template.txt | ||
90 | 86 | * cd ../spawn/default | ||
91 | 87 | * ln -s ../../queue/queue-name | ||
92 | 88 | |||
93 | 89 | Want to delete a job from the queue? | ||
94 | 90 | |||
95 | 91 | * cd ~/var/scheduler/queue | ||
96 | 92 | * `rm */job-name.job` | ||
97 | 0 | 93 | ||
98 | === added file 'aarch64-merger.sh' | |||
99 | --- aarch64-merger.sh 1970-01-01 00:00:00 +0000 | |||
100 | +++ aarch64-merger.sh 2014-07-01 15:58:40 +0000 | |||
101 | @@ -0,0 +1,172 @@ | |||
102 | 1 | #!/bin/bash | ||
103 | 2 | # | ||
104 | 3 | # Automatically merge and create a merge request for any new aarch64 | ||
105 | 4 | # commits. | ||
106 | 5 | # | ||
107 | 6 | # | ||
108 | 7 | |||
109 | 8 | set -e | ||
110 | 9 | |||
111 | 10 | # Path to Linaro GCC 4.7 | ||
112 | 11 | tip=4.7 | ||
113 | 12 | # Path to the ARM bzr branch | ||
114 | 13 | from=arm-aarch64-4.7 | ||
115 | 14 | # Fill this in with the last merged bzr revno | ||
116 | 15 | # Example: bzr log 4.7 shows r193293..r193328. bzr log arm-* --show-ids shows that | ||
117 | 16 | # r193328 is bzr116407. | ||
118 | 17 | current=116423 | ||
119 | 18 | |||
120 | 19 | get_revision() { | ||
121 | 20 | echo $(bzr log -c $1 --show-ids --short $2 | awk -F: '/revision-id:/ {print $NF}') | ||
122 | 21 | } | ||
123 | 22 | |||
124 | 23 | is_fsf_merge() { | ||
125 | 24 | (bzr log -c $1 -p $2 | grep -qF "+++ gcc/DATESTAMP") && echo y | ||
126 | 25 | } | ||
127 | 26 | |||
128 | 27 | all_revnos() { | ||
129 | 28 | bzr log -r $stop.. --log-format=line $1 | awk -F: '{print $1;}' | ||
130 | 29 | } | ||
131 | 30 | |||
132 | 31 | extract_changelog() { | ||
133 | 32 | # Pull the ChangeLog out | ||
134 | 33 | inside= | ||
135 | 34 | |||
136 | 35 | while read i; do | ||
137 | 36 | if [[ "$i" =~ ^=== ]]; then inside=; fi | ||
138 | 37 | |||
139 | 38 | if [ -n "$inside" ] && [[ "$i" =~ ^\+(.+) ]]; then | ||
140 | 39 | echo "${BASH_REMATCH[1]}" | ||
141 | 40 | fi | ||
142 | 41 | |||
143 | 42 | if [[ "$i" =~ ^\+\+\+\ .+/ChangeLog\.aarch64 ]]; then inside=y; fi | ||
144 | 43 | |||
145 | 44 | done < /tmp/bzr$revno.diff > /tmp/bzr$revno.changes | ||
146 | 45 | } | ||
147 | 46 | |||
148 | 47 | search_back() { | ||
149 | 48 | # Search back to the first non-merge | ||
150 | 49 | for i in $all; do | ||
151 | 50 | if [ -z "$(is_fsf_merge $i $from)" ]; then | ||
152 | 51 | last=$i | ||
153 | 52 | break | ||
154 | 53 | fi | ||
155 | 54 | done | ||
156 | 55 | } | ||
157 | 56 | |||
158 | 57 | search_forward() { | ||
159 | 58 | # Search forward to the first non-merge | ||
160 | 59 | for i in $(seq $((current+1)) 1 $last); do | ||
161 | 60 | if [ -z "$(is_fsf_merge $i $from)" ]; then | ||
162 | 61 | first=$i | ||
163 | 62 | break | ||
164 | 63 | fi | ||
165 | 64 | done | ||
166 | 65 | } | ||
167 | 66 | |||
168 | 67 | dir=`mktemp -td merger.XXXXXXXXXX` | ||
169 | 68 | trap "rm -rf $dir" EXIT | ||
170 | 69 | |||
171 | 70 | # End point for any scans | ||
172 | 71 | stop=116380 | ||
173 | 72 | |||
174 | 73 | all=$(all_revnos $from) | ||
175 | 74 | |||
176 | 75 | search_back | ||
177 | 76 | search_forward | ||
178 | 77 | |||
179 | 78 | sfirst=$(get_revision $first $from) | ||
180 | 79 | slast=$(get_revision $last $from) | ||
181 | 80 | |||
182 | 81 | name="merge-from-aarch64-4.7-r$sfirst-r$slast" | ||
183 | 82 | |||
184 | 83 | # See if the merge request already exists | ||
185 | 84 | if false && wget -q -O- https://code.launchpad.net/gcc-linaro | grep -q -F $name; then | ||
186 | 85 | echo "Branch $name already exists, nothing to do." | ||
187 | 86 | exit 0 | ||
188 | 87 | fi | ||
189 | 88 | |||
190 | 89 | rm -rf $name | ||
191 | 90 | bzr branch -q --hardlink $tip $name | ||
192 | 91 | |||
193 | 92 | realname="Michael Hope" | ||
194 | 93 | email="michael.hope@linaro.org" | ||
195 | 94 | login=$(bzr lp-login) | ||
196 | 95 | |||
197 | 96 | short="Merge from FSF arm/aarch64-4.7-branch r$sfirst..r$slast." | ||
198 | 97 | |||
199 | 98 | echo -e "$(date +%Y-%m-%d) $realname <$email>\n" > $dir/log | ||
200 | 99 | echo -e "\t$short\n" >> $dir/log | ||
201 | 100 | |||
202 | 101 | # Go through and merge each revision | ||
203 | 102 | for revno in $(seq $first 1 $last); do | ||
204 | 103 | if [ -n "$(is_fsf_merge $revno $from)" ]; then | ||
205 | 104 | echo "Skipping the FSF merge at $revno" | ||
206 | 105 | continue | ||
207 | 106 | fi | ||
208 | 107 | |||
209 | 108 | svn=$(get_revision $revno $from) | ||
210 | 109 | stem=$dir/bzr$revno | ||
211 | 110 | |||
212 | 111 | echo "Merging $svn (bzr$revno)" | ||
213 | 112 | # bzr diff returns 1 on changed... | ||
214 | 113 | (cd $from && bzr diff -c $revno || true) > $stem.diff | ||
215 | 114 | |||
216 | 115 | if ! (cd $name && bzr patch $stem.diff); then | ||
217 | 116 | read -p "Conflicts found. Fix in $name then press enter > " | ||
218 | 117 | fi | ||
219 | 118 | |||
220 | 119 | # Nuke any patch reminants | ||
221 | 120 | find $name -name *.orig -exec rm {} \; | ||
222 | 121 | find $name -name *.rej -exec rm {} \; | ||
223 | 122 | |||
224 | 123 | # Add any missing files. bzr patch should have done this already | ||
225 | 124 | # but doesn't on conflict. | ||
226 | 125 | (cd $name && bzr add) | ||
227 | 126 | |||
228 | 127 | # Pull out the commit message | ||
229 | 128 | (cd $from && bzr log -c $revno) > $stem.log | ||
230 | 129 | |||
231 | 130 | inside= | ||
232 | 131 | while read i; do | ||
233 | 132 | if [ -n "$inside" ]; then | ||
234 | 133 | trimmed=$(echo "$i") | ||
235 | 134 | echo "$trimmed" | ||
236 | 135 | fi | ||
237 | 136 | |||
238 | 137 | if [[ "$i" =~ ^message: ]]; then inside=y; fi | ||
239 | 138 | done < $stem.log > $stem.message | ||
240 | 139 | |||
241 | 140 | # Commit each as a revision to make future tracking easier. The | ||
242 | 141 | # merge will roll this up into one. | ||
243 | 142 | echo -e "Backport $from r$svn.\n" > $stem.commit | ||
244 | 143 | cat $stem.message >> $stem.commit | ||
245 | 144 | |||
246 | 145 | (cd $name && bzr commit -F $stem.commit) | ||
247 | 146 | |||
248 | 147 | echo -e "\tBackport $from r$svn:" >> $dir/log | ||
249 | 148 | while read i; do | ||
250 | 149 | echo -e "\t$i" | ||
251 | 150 | done < $stem.message >> $dir/log | ||
252 | 151 | |||
253 | 152 | echo >> $dir/log | ||
254 | 153 | done | ||
255 | 154 | |||
256 | 155 | # Upate the ChangeLog and commit | ||
257 | 156 | cat $dir/log $name/ChangeLog.linaro > $dir/new | ||
258 | 157 | mv $dir/new $name/ChangeLog.linaro | ||
259 | 158 | |||
260 | 159 | cd $name | ||
261 | 160 | bzr commit -m"$short" | ||
262 | 161 | bzr push "lp:~$login/gcc-linaro/$name" | ||
263 | 162 | |||
264 | 163 | # propose-merge always runs an editor for the message. Make a fake | ||
265 | 164 | # editor that sets the text. | ||
266 | 165 | cat > $dir/editor <<EOF | ||
267 | 166 | #!/bin/bash | ||
268 | 167 | cp $dir/log \$1 | ||
269 | 168 | EOF | ||
270 | 169 | |||
271 | 170 | chmod +x $dir/editor | ||
272 | 171 | |||
273 | 172 | VISUAL=$dir/editor bzr lp-propose-merge -m"$short" | ||
274 | 0 | 173 | ||
275 | === added file 'addtestdiffs.py' | |||
276 | --- addtestdiffs.py 1970-01-01 00:00:00 +0000 | |||
277 | +++ addtestdiffs.py 2014-07-01 15:58:40 +0000 | |||
278 | @@ -0,0 +1,133 @@ | |||
279 | 1 | #!/usr/bin/python | ||
280 | 2 | """Record the difference between the test results of this build and | ||
281 | 3 | it's ancestor or predecessor. | ||
282 | 4 | """ | ||
283 | 5 | |||
284 | 6 | import sys | ||
285 | 7 | import re | ||
286 | 8 | import os | ||
287 | 9 | import pprint | ||
288 | 10 | import subprocess | ||
289 | 11 | import logging | ||
290 | 12 | import time | ||
291 | 13 | |||
292 | 14 | import findancestor | ||
293 | 15 | import findlogs | ||
294 | 16 | |||
295 | 17 | TEMPLATE = """Difference in testsuite results between: | ||
296 | 18 | %(current)s build %(buildid)s | ||
297 | 19 | and the one before it: | ||
298 | 20 | %(other)s build %(otherbuildid)s | ||
299 | 21 | |||
300 | 22 | ------ | ||
301 | 23 | %(diff)s""" | ||
302 | 24 | |||
303 | 25 | def make_testsuite_diff(left, right): | ||
304 | 26 | # PENDING: This is bad | ||
305 | 27 | return subprocess.check_output(['./difftests.sh', left, right]) | ||
306 | 28 | |||
307 | 29 | def make_benchmarks_diff(left, right, suffix): | ||
308 | 30 | return subprocess.check_output(['../linaro-toolchain-benchmarks/scripts/diffbench.py', | ||
309 | 31 | '%s/benchmarks-%s.txt' % (left, suffix), | ||
310 | 32 | '%s/benchmarks-%s.txt' % (right, suffix) | ||
311 | 33 | ]) | ||
312 | 34 | |||
313 | 35 | def run(allfiles, snapshots, builds, check, final, make_diff): | ||
314 | 36 | now = time.time() | ||
315 | 37 | |||
316 | 38 | # Make the search a bit easier by only keeping the .txt files | ||
317 | 39 | filtered = [x for x in allfiles if '.txt' in x[-1] or check in x[-1]] | ||
318 | 40 | |||
319 | 41 | # And cache by directory | ||
320 | 42 | directories = {} | ||
321 | 43 | |||
322 | 44 | for f in filtered: | ||
323 | 45 | directory = '/'.join(f[:-1]) | ||
324 | 46 | directories.setdefault(directory, []).append(f) | ||
325 | 47 | |||
326 | 48 | prefiltered = findlogs.prefilter(allfiles, check) | ||
327 | 49 | |||
328 | 50 | # Find all builds that have finished | ||
329 | 51 | for build in [x for x in filtered if x[-1] == 'finished.txt']: | ||
330 | 52 | match = '/'.join(build[:-1]) | ||
331 | 53 | |||
332 | 54 | # Skip if the build is too old. Either we have a result or | ||
333 | 55 | # it's never coming in | ||
334 | 56 | try: | ||
335 | 57 | age = (now - os.path.getmtime('%s/%s/finished.txt' % (builds, match))) / (60*60*24) | ||
336 | 58 | |||
337 | 59 | if age >= 30: | ||
338 | 60 | continue | ||
339 | 61 | except OSError: | ||
340 | 62 | continue | ||
341 | 63 | |||
342 | 64 | # Find all of the files in the same directory | ||
343 | 65 | siblings = directories[match] | ||
344 | 66 | |||
345 | 67 | all = ' '.join(x[-1] for x in siblings) | ||
346 | 68 | |||
347 | 69 | # Are there any .sum style results? | ||
348 | 70 | if check not in all: | ||
349 | 71 | continue | ||
350 | 72 | |||
351 | 73 | # See if the diff already exists | ||
352 | 74 | if ' %s' % final in all: | ||
353 | 75 | continue | ||
354 | 76 | |||
355 | 77 | # Find the ancestor or predecessor | ||
356 | 78 | current = build[1] | ||
357 | 79 | other = findancestor.find(allfiles, current, snapshots) | ||
358 | 80 | |||
359 | 81 | if not other: | ||
360 | 82 | logging.info('No known ancestor to %s' % current) | ||
361 | 83 | continue | ||
362 | 84 | |||
363 | 85 | # Find the corresponding build | ||
364 | 86 | logs = ['/'.join(x) for x in siblings if check in x[-1]] | ||
365 | 87 | assert logs | ||
366 | 88 | log = logs[-1] | ||
367 | 89 | |||
368 | 90 | try: | ||
369 | 91 | otherlogs = findlogs.find(prefiltered, log, other) | ||
370 | 92 | except Exception, ex: | ||
371 | 93 | logging.info('Error %s while finding logs on %s vs %s' % (ex, log, other)) | ||
372 | 94 | otherlogs = None | ||
373 | 95 | |||
374 | 96 | if not otherlogs: | ||
375 | 97 | logging.debug("Can't find %s of %s" % (log, other)) | ||
376 | 98 | continue | ||
377 | 99 | |||
378 | 100 | other, otherbuildid = otherlogs | ||
379 | 101 | buildid = build[-2] | ||
380 | 102 | diff = None | ||
381 | 103 | |||
382 | 104 | try: | ||
383 | 105 | logging.debug('Generating a diff between predecessor %s/%s and %s' % (other, otherbuildid, os.path.dirname(log))) | ||
384 | 106 | |||
385 | 107 | left = '%s/%s/logs/%s' % (builds, other, otherbuildid) | ||
386 | 108 | right = os.path.join(builds, os.path.dirname(log)) | ||
387 | 109 | diff = make_diff(left, right) | ||
388 | 110 | |||
389 | 111 | except Exception, ex: | ||
390 | 112 | logging.error(ex) | ||
391 | 113 | |||
392 | 114 | if diff == None: | ||
393 | 115 | continue | ||
394 | 116 | |||
395 | 117 | with open('%s/%s/%s' % (builds, match, final), 'w') as f: | ||
396 | 118 | print >> f, TEMPLATE % locals() | ||
397 | 119 | |||
398 | 120 | def main(): | ||
399 | 121 | # logging.basicConfig(level=logging.DEBUG) | ||
400 | 122 | allfiles, snapshots, builds = sys.argv[1:] | ||
401 | 123 | |||
402 | 124 | with open(allfiles) as f: | ||
403 | 125 | allf = [x.strip().split(os.sep) for x in f.readlines()] | ||
404 | 126 | |||
405 | 127 | run(allf, snapshots, builds, '.sum', 'testsuite-diff.txt', make_testsuite_diff) | ||
406 | 128 | |||
407 | 129 | for suffix in 'spec2000 eembc eembc_office'.split(): | ||
408 | 130 | run(allf, snapshots, builds, 'benchmarks-%s.txt' % suffix, 'benchmarks-%s-diff.txt' % suffix, lambda x, y: make_benchmarks_diff(x, y, suffix)) | ||
409 | 131 | |||
410 | 132 | if __name__ == '__main__': | ||
411 | 133 | main() | ||
412 | 0 | 134 | ||
413 | === added file 'cache-builds.py' | |||
414 | --- cache-builds.py 1970-01-01 00:00:00 +0000 | |||
415 | +++ cache-builds.py 2014-07-01 15:58:40 +0000 | |||
416 | @@ -0,0 +1,131 @@ | |||
417 | 1 | #!/usr/bin/python | ||
418 | 2 | |||
419 | 3 | """Scan a directory tree and cache the results of each version and | ||
420 | 4 | build. | ||
421 | 5 | """ | ||
422 | 6 | |||
423 | 7 | import sys | ||
424 | 8 | import os | ||
425 | 9 | import pprint | ||
426 | 10 | import cPickle | ||
427 | 11 | import json | ||
428 | 12 | |||
429 | 13 | def list(path): | ||
430 | 14 | try: | ||
431 | 15 | return os.walk(path).next() | ||
432 | 16 | except StopIteration: | ||
433 | 17 | return None, [], [] | ||
434 | 18 | |||
435 | 19 | def get_date(root, name): | ||
436 | 20 | return os.path.getmtime('%s/%s' % (root, name)) | ||
437 | 21 | |||
438 | 22 | def intern_all(values): | ||
439 | 23 | return tuple(intern(x) for x in values) | ||
440 | 24 | |||
441 | 25 | def make_path(top, path): | ||
442 | 26 | root = top['root'] | ||
443 | 27 | |||
444 | 28 | assert path.startswith(root) | ||
445 | 29 | return path[len(root)+1:] | ||
446 | 30 | |||
447 | 31 | def add_build(top, name, aroot): | ||
448 | 32 | parts = intern_all(name.split('-') + ['']) | ||
449 | 33 | arch, distro, cbuild, host, config = parts[:5] | ||
450 | 34 | |||
451 | 35 | root, dirs, files = list(aroot) | ||
452 | 36 | files = intern_all(files) | ||
453 | 37 | |||
454 | 38 | top['hosts'][host] = arch | ||
455 | 39 | top['arches'].setdefault(arch, {}) | ||
456 | 40 | top['configs'].setdefault(config, {}) | ||
457 | 41 | |||
458 | 42 | build = { | ||
459 | 43 | 'name': name, | ||
460 | 44 | 'arch': arch, | ||
461 | 45 | 'distro': distro, | ||
462 | 46 | 'cbuild': cbuild, | ||
463 | 47 | 'host': host, | ||
464 | 48 | 'config': config, | ||
465 | 49 | 'abspath': aroot, | ||
466 | 50 | 'path': make_path(top, aroot), | ||
467 | 51 | 'files': files, | ||
468 | 52 | 'failed': [], | ||
469 | 53 | 'subfailures': [], | ||
470 | 54 | 'testlog': None, | ||
471 | 55 | 'started': None, | ||
472 | 56 | 'finished': None, | ||
473 | 57 | 'languages': [], | ||
474 | 58 | 'binary': None, | ||
475 | 59 | } | ||
476 | 60 | |||
477 | 61 | for name in files: | ||
478 | 62 | if 'failed' in name: | ||
479 | 63 | build['failed'].append(name) | ||
480 | 64 | |||
481 | 65 | if '-failed' in name: | ||
482 | 66 | build['subfailures'].append(name.replace('-failed', ' ').split()[0]) | ||
483 | 67 | |||
484 | 68 | elif name == 'started.txt': | ||
485 | 69 | build['started'] = get_date(root, name) | ||
486 | 70 | elif name == 'finished.txt': | ||
487 | 71 | build['finished'] = get_date(root, name) | ||
488 | 72 | elif name == 'gcc-configure.txt': | ||
489 | 73 | with open('%s/%s' % (root, name)) as f: | ||
490 | 74 | for line in f: | ||
491 | 75 | if line.startswith('The following'): | ||
492 | 76 | end = line.split(': ')[-1] | ||
493 | 77 | build['languages'] = intern_all(end.strip().split(',')) | ||
494 | 78 | break | ||
495 | 79 | |||
496 | 80 | if name.endswith('-testsuite.txt'): | ||
497 | 81 | build['testlog'] = make_path(top, '%s/%s' % (root, name)) | ||
498 | 82 | |||
499 | 83 | return build | ||
500 | 84 | |||
501 | 85 | def add_version(top, name, path): | ||
502 | 86 | version = { | ||
503 | 87 | 'name': name, | ||
504 | 88 | 'abspath': path, | ||
505 | 89 | 'builds': {} | ||
506 | 90 | } | ||
507 | 91 | |||
508 | 92 | root, dirs, files = list('%s/logs' % path) | ||
509 | 93 | |||
510 | 94 | for dir in dirs: | ||
511 | 95 | version['builds'][dir] = add_build(top, dir, '%s/%s' % (root, dir)) | ||
512 | 96 | |||
513 | 97 | return version | ||
514 | 98 | |||
515 | 99 | def add_versions(top, aroot, adirs): | ||
516 | 100 | for dir in adirs: | ||
517 | 101 | path = '%s/%s' % (aroot, dir) | ||
518 | 102 | |||
519 | 103 | root, dirs, files = list(path) | ||
520 | 104 | |||
521 | 105 | if 'logs' in dirs: | ||
522 | 106 | version = add_version(top, dir, path) | ||
523 | 107 | top['versions'][dir] = version | ||
524 | 108 | |||
525 | 109 | def main(): | ||
526 | 110 | top = { | ||
527 | 111 | 'root': None, | ||
528 | 112 | 'all': [], | ||
529 | 113 | 'versions': {}, | ||
530 | 114 | 'arches': {}, | ||
531 | 115 | 'configs': {}, | ||
532 | 116 | 'hosts': {}, | ||
533 | 117 | } | ||
534 | 118 | |||
535 | 119 | for path in sys.argv[1:]: | ||
536 | 120 | root, dirs, files = os.walk(path).next() | ||
537 | 121 | top['root'] = root | ||
538 | 122 | add_versions(top, root, dirs) | ||
539 | 123 | |||
540 | 124 | with open('builds.pickle', 'w') as f: | ||
541 | 125 | cPickle.dump(top, f, cPickle.HIGHEST_PROTOCOL) | ||
542 | 126 | |||
543 | 127 | with open('builds.json', 'w') as f: | ||
544 | 128 | json.dump(top, f, indent=2) | ||
545 | 129 | |||
546 | 130 | if __name__ == '__main__': | ||
547 | 131 | main() | ||
548 | 0 | 132 | ||
549 | === added file 'chain.sh' | |||
550 | --- chain.sh 1970-01-01 00:00:00 +0000 | |||
551 | +++ chain.sh 2014-07-01 15:58:40 +0000 | |||
552 | @@ -0,0 +1,75 @@ | |||
553 | 1 | #!/bin/bash | ||
554 | 2 | # | ||
555 | 3 | # Chain a job on following another. Generally works on the latest. | ||
556 | 4 | # | ||
557 | 5 | |||
558 | 6 | set -e | ||
559 | 7 | # If the pattern fails then propogate the error | ||
560 | 8 | set -o pipefail | ||
561 | 9 | |||
562 | 10 | . ~/.config/cbuild/toolsrc | ||
563 | 11 | |||
564 | 12 | config=cortexa9hf | ||
565 | 13 | |||
566 | 14 | type=$1 | ||
567 | 15 | shift | ||
568 | 16 | pattern=$1 | ||
569 | 17 | shift | ||
570 | 18 | |||
571 | 19 | # Set to run=echo for testing | ||
572 | 20 | run= | ||
573 | 21 | |||
574 | 22 | function get_latest { | ||
575 | 23 | case $type in | ||
576 | 24 | benchmarks | ubutest) | ||
577 | 25 | # See what binaries we have locally that match | ||
578 | 26 | version=$( ls -t $binaries/*${config}r?.tar* | head -n1 ) | ||
579 | 27 | version=$( basename $( dirname $version )) | ||
580 | 28 | ;; | ||
581 | 29 | trunk | oecore) | ||
582 | 30 | # Pick the latest snapshot | ||
583 | 31 | version=$( ls -t $snapshots/$pattern | head -n1 ) | ||
584 | 32 | version=$( basename $version ) | ||
585 | 33 | version=$( echo $version | sed -r "s/(.+)\.tar.+/\1/" ) | ||
586 | 34 | ;; | ||
587 | 35 | *) | ||
588 | 36 | exit -1 | ||
589 | 37 | ;; | ||
590 | 38 | esac | ||
591 | 39 | |||
592 | 40 | [ -n $version ] | ||
593 | 41 | } | ||
594 | 42 | |||
595 | 43 | function spawn { | ||
596 | 44 | target=$queue/$2/$1.job | ||
597 | 45 | |||
598 | 46 | if [ ! -f $target ]; then | ||
599 | 47 | PYTHONPATH=$lib/tcwg-web python -m schedulejob $2 $1 | ||
600 | 48 | echo Spawned $1 into $2 | ||
601 | 49 | fi | ||
602 | 50 | } | ||
603 | 51 | |||
604 | 52 | function chain { | ||
605 | 53 | # Now do something | ||
606 | 54 | case $type in | ||
607 | 55 | benchmarks) | ||
608 | 56 | spawn benchmarks-$version a9hf-ref | ||
609 | 57 | spawn benchmarks-spec2000-$version a9hf-ref | ||
610 | 58 | ;; | ||
611 | 59 | ubutest) | ||
612 | 60 | spawn ubutest-$version a9hf-ref | ||
613 | 61 | ;; | ||
614 | 62 | trunk) | ||
615 | 63 | spawn $version a9hf-builder | ||
616 | 64 | ;; | ||
617 | 65 | oecore) | ||
618 | 66 | spawn test-oecore-$version x86_64-heavy | ||
619 | 67 | ;; | ||
620 | 68 | *) | ||
621 | 69 | exit -1 | ||
622 | 70 | ;; | ||
623 | 71 | esac | ||
624 | 72 | } | ||
625 | 73 | |||
626 | 74 | get_latest | ||
627 | 75 | chain | ||
628 | 0 | 76 | ||
629 | === added file 'check-leaks.sh' | |||
630 | --- check-leaks.sh 1970-01-01 00:00:00 +0000 | |||
631 | +++ check-leaks.sh 2014-07-01 15:58:40 +0000 | |||
632 | @@ -0,0 +1,14 @@ | |||
633 | 1 | #!/bin/sh | ||
634 | 2 | # | ||
635 | 3 | # Watch the build directory for any results that shouldn't be there | ||
636 | 4 | # | ||
637 | 5 | |||
638 | 6 | . ~/.config/cbuild/toolsrc | ||
639 | 7 | |||
640 | 8 | benchmarks="coremark eembc denbench spec" | ||
641 | 9 | |||
642 | 10 | check=$www/build/ | ||
643 | 11 | |||
644 | 12 | for i in $benchmarks; do | ||
645 | 13 | find $check -name "$i*run.txt" | sed "s#$check##" | head -n 10 | ||
646 | 14 | done | ||
647 | 0 | 15 | ||
648 | === added file 'closest.py' | |||
649 | --- closest.py 1970-01-01 00:00:00 +0000 | |||
650 | +++ closest.py 2014-07-01 15:58:40 +0000 | |||
651 | @@ -0,0 +1,63 @@ | |||
652 | 1 | #!/usr/bin/env python | ||
653 | 2 | # Find the closest base filename. Finds the one with the longest | ||
654 | 3 | # common prefix | ||
655 | 4 | # | ||
656 | 5 | |||
657 | 6 | import sys | ||
658 | 7 | import os.path | ||
659 | 8 | import re | ||
660 | 9 | |||
661 | 10 | def match(find, path): | ||
662 | 11 | """Check a build against a queue, returning the common prefix if | ||
663 | 12 | the needle starts with the queue name. | ||
664 | 13 | |||
665 | 14 | The longest match is the closest. | ||
666 | 15 | |||
667 | 16 | >>> match('foo', 'baz') | ||
668 | 17 | >>> match('gcc-foo-bar', 'gcc') | ||
669 | 18 | 'gcc' | ||
670 | 19 | >>> match('gcc-foo-bar', 'gcc-foo') | ||
671 | 20 | 'gcc-foo' | ||
672 | 21 | >>> match('gcc-foo-bar', 'default') | ||
673 | 22 | '' | ||
674 | 23 | """ | ||
675 | 24 | base = os.path.basename(path) | ||
676 | 25 | |||
677 | 26 | if find.startswith(base): | ||
678 | 27 | return base | ||
679 | 28 | elif base == 'default': | ||
680 | 29 | return '' | ||
681 | 30 | else: | ||
682 | 31 | return None | ||
683 | 32 | |||
684 | 33 | def match2(find, path): | ||
685 | 34 | base = os.path.basename(path) | ||
686 | 35 | return os.path.commonprefix([find, base]) | ||
687 | 36 | |||
688 | 37 | def main(): | ||
689 | 38 | against = os.path.basename(sys.argv[1]) | ||
690 | 39 | |||
691 | 40 | prefixes = [] | ||
692 | 41 | |||
693 | 42 | for full in sys.argv[2:]: | ||
694 | 43 | key = match(against, full) | ||
695 | 44 | |||
696 | 45 | if key != None: | ||
697 | 46 | prefixes.append((full, key)) | ||
698 | 47 | |||
699 | 48 | if not prefixes: | ||
700 | 49 | for full in sys.argv[2:]: | ||
701 | 50 | key = match2(against, full) | ||
702 | 51 | |||
703 | 52 | if key != None: | ||
704 | 53 | prefixes.append((full, key)) | ||
705 | 54 | |||
706 | 55 | prefixes.sort(key=lambda x: -len(x[-1])) | ||
707 | 56 | print prefixes[0][0] | ||
708 | 57 | |||
709 | 58 | def test(): | ||
710 | 59 | import doctest | ||
711 | 60 | doctest.testmod() | ||
712 | 61 | |||
713 | 62 | if __name__ == '__main__': | ||
714 | 63 | main() | ||
715 | 0 | 64 | ||
716 | === added file 'cron-often.sh' | |||
717 | --- cron-often.sh 1970-01-01 00:00:00 +0000 | |||
718 | +++ cron-often.sh 2014-07-01 15:58:40 +0000 | |||
719 | @@ -0,0 +1,56 @@ | |||
720 | 1 | #!/bin/bash | ||
721 | 2 | # | ||
722 | 3 | # Job that runs often, polling builds, branches, and others. | ||
723 | 4 | # | ||
724 | 5 | |||
725 | 6 | # Root of the www directory | ||
726 | 7 | . ~/.config/cbuild/toolsrc | ||
727 | 8 | |||
728 | 9 | timeout="timeout 3600" | ||
729 | 10 | #timeout= | ||
730 | 11 | |||
731 | 12 | cd $ctools | ||
732 | 13 | |||
733 | 14 | # Update the list of all files and other caches | ||
734 | 15 | function allfiles { | ||
735 | 16 | pushd $1 > /dev/null | ||
736 | 17 | find . | sort > /tmp/all-files.txt | ||
737 | 18 | |||
738 | 19 | # Only update if changed | ||
739 | 20 | ! cmp -s all-files.txt /tmp/all-files.txt \ | ||
740 | 21 | && python ~/lib/cbuild-tools/cache-builds.py . \ | ||
741 | 22 | && mv -f /tmp/all-files.txt . \ | ||
742 | 23 | && gzip -9fc --rsyncable all-files.txt > all-files.txt.gz \ | ||
743 | 24 | && gzip -9fc --rsyncable builds.json > builds.json.gz | ||
744 | 25 | |||
745 | 26 | popd > /dev/null | ||
746 | 27 | } | ||
747 | 28 | |||
748 | 29 | # Tabulate any new benchmarks | ||
749 | 30 | ./tabulate.sh | ||
750 | 31 | |||
751 | 32 | # Update the file list cache | ||
752 | 33 | allfiles $build | ||
753 | 34 | allfiles $benchmarks | ||
754 | 35 | |||
755 | 36 | # Pull any new merge requests | ||
756 | 37 | timeout 14400 python taker.py -f prompt=false | ||
757 | 38 | |||
758 | 39 | # Add the testsuite diffs to anything new | ||
759 | 40 | python2.7 addtestdiffs.py $build/all-files.txt $snapshots $build | ||
760 | 41 | python2.7 addtestdiffs.py $benchmarks/all-files.txt $snapshots $benchmarks | ||
761 | 42 | |||
762 | 43 | # Rebuild all files after the diffs are added | ||
763 | 44 | allfiles $build | ||
764 | 45 | allfiles $benchmarks | ||
765 | 46 | |||
766 | 47 | # Poll all interesting Linaro branches | ||
767 | 48 | $timeout ./export-git.sh $repos/meta-linaro meta-linaro-0~ | ||
768 | 49 | $timeout ./pull_branch.sh $repos/gcc-linaro-4.8/4.8 gcc-linaro-4.8 | ||
769 | 50 | $timeout ./pull_branch.sh $repos/gcc-linaro/4.7 gcc-linaro-4.7 | ||
770 | 51 | $timeout ./pull_branch.sh $repos/gcc-linaro/4.6 gcc-linaro-4.6 | ||
771 | 52 | $timeout ./pull_branch.sh $repos/crosstool-ng/linaro crosstool-ng-linaro-1.13.1 | ||
772 | 53 | $timeout ./pull_branch.sh $repos/gdb-linaro/7.5 gdb-linaro-7.5 | ||
773 | 54 | $timeout ./pull_branch.sh $repos/cortex-strings cortex-strings-1.0 | ||
774 | 55 | $timeout ./export-git.sh $repos/qemu-linaro qemu-linaro-1.0~ | ||
775 | 56 | $timeout ./export-git.sh $repos/boot-wrapper boot-wrapper-0~ | ||
776 | 0 | 57 | ||
777 | === added file 'ctimes.py' | |||
778 | --- ctimes.py 1970-01-01 00:00:00 +0000 | |||
779 | +++ ctimes.py 2014-07-01 15:58:40 +0000 | |||
780 | @@ -0,0 +1,100 @@ | |||
781 | 1 | """Parse the scheduler log and print the time spent transitioning from | ||
782 | 2 | state to state for each host. | ||
783 | 3 | """ | ||
784 | 4 | import sys | ||
785 | 5 | import fileinput | ||
786 | 6 | import collections | ||
787 | 7 | import pprint | ||
788 | 8 | |||
789 | 9 | Edge = collections.namedtuple('Edge', 'a b took time') | ||
790 | 10 | |||
791 | 11 | def parse(): | ||
792 | 12 | hosts = {} | ||
793 | 13 | lasts = {} | ||
794 | 14 | first = None | ||
795 | 15 | |||
796 | 16 | for line in fileinput.input(): | ||
797 | 17 | parts = line.split() | ||
798 | 18 | stamp, host, state, arg = (parts + ['']*4)[:4] | ||
799 | 19 | stamp = float(stamp) | ||
800 | 20 | |||
801 | 21 | if first == None: | ||
802 | 22 | first = stamp | ||
803 | 23 | |||
804 | 24 | if arg: | ||
805 | 25 | state = arg | ||
806 | 26 | |||
807 | 27 | last = lasts.get(host, None) | ||
808 | 28 | lasts[host] = (stamp, state) | ||
809 | 29 | |||
810 | 30 | if last: | ||
811 | 31 | elapsed = stamp - last[0] | ||
812 | 32 | hosts.setdefault(host, []).append(Edge(last[1], state, elapsed, stamp - first)) | ||
813 | 33 | |||
814 | 34 | return hosts | ||
815 | 35 | |||
816 | 36 | def cost(): | ||
817 | 37 | hosts = parse() | ||
818 | 38 | |||
819 | 39 | print('\t'.join('day host job took'.split())) | ||
820 | 40 | |||
821 | 41 | for host in hosts: | ||
822 | 42 | doing = None | ||
823 | 43 | start = None | ||
824 | 44 | |||
825 | 45 | for edge in hosts[host]: | ||
826 | 46 | if edge.b == 'idle': | ||
827 | 47 | if doing and start: | ||
828 | 48 | pretty = doing.replace('-extract-top', '') | ||
829 | 49 | print('%.1f\t%s\t\t%s\t%.1f' % (edge.time/3600/24, host, pretty, (edge.time - start)/3600)) | ||
830 | 50 | doing = None | ||
831 | 51 | |||
832 | 52 | if edge.b in ['lurking', 'idle']: | ||
833 | 53 | start = edge.time | ||
834 | 54 | doing = None | ||
835 | 55 | |||
836 | 56 | if edge.b in ['starting', 'idle', 'updating', 'running', 'lurking']: | ||
837 | 57 | # Skip | ||
838 | 58 | pass | ||
839 | 59 | elif 'fetch-binary' in edge.b: | ||
840 | 60 | # Skip | ||
841 | 61 | pass | ||
842 | 62 | else: | ||
843 | 63 | if doing == None: | ||
844 | 64 | doing = edge.b | ||
845 | 65 | |||
846 | 66 | def main(): | ||
847 | 67 | hosts = parse() | ||
848 | 68 | |||
849 | 69 | # Go through and bin them | ||
850 | 70 | bins = {} | ||
851 | 71 | |||
852 | 72 | for host, edges in hosts.items(): | ||
853 | 73 | bins[host] = {} | ||
854 | 74 | |||
855 | 75 | for edge in edges: | ||
856 | 76 | key = '%s -> %s' % (edge.a, edge.b) | ||
857 | 77 | |||
858 | 78 | if edge.a in ['lurking', 'running', 'idle']: | ||
859 | 79 | continue | ||
860 | 80 | |||
861 | 81 | if key in ['idle -> updating', 'running -> idle', 'updating -> running']: | ||
862 | 82 | continue | ||
863 | 83 | |||
864 | 84 | bins[host].setdefault(key, []).append(edge.took) | ||
865 | 85 | |||
866 | 86 | for host in sorted(bins): | ||
867 | 87 | keys = bins[host] | ||
868 | 88 | print('%s:' % host) | ||
869 | 89 | |||
870 | 90 | for key in sorted(keys): | ||
871 | 91 | values = keys[key] | ||
872 | 92 | print(' %s: %.1f' % (key, sum(values)/len(values)), end=' ') | ||
873 | 93 | |||
874 | 94 | for value in values: | ||
875 | 95 | print('%.0f' % value, end=' ') | ||
876 | 96 | |||
877 | 97 | print() | ||
878 | 98 | |||
879 | 99 | if __name__ == '__main__': | ||
880 | 100 | cost() | ||
881 | 0 | 101 | ||
882 | === added file 'difftests.sh' | |||
883 | --- difftests.sh 1970-01-01 00:00:00 +0000 | |||
884 | +++ difftests.sh 2014-07-01 15:58:40 +0000 | |||
885 | @@ -0,0 +1,45 @@ | |||
886 | 1 | #!/bin/bash | ||
887 | 2 | # | ||
888 | 3 | # Take all of the .sum files from two directories and generate the differences | ||
889 | 4 | # | ||
890 | 5 | # Example: | ||
891 | 6 | # difftests.sh \ | ||
892 | 7 | # build/gcc-4.6+svn173209/logs/armv7l-maverick-cbuild113-ursa3-cortexa9r1 \ | ||
893 | 8 | # build/gcc-4.6+svn173722/logs/armv7l-maverick-cbuild114-ursa4-cortexa9r1 | ||
894 | 9 | # | ||
895 | 10 | |||
896 | 11 | set -e | ||
897 | 12 | |||
898 | 13 | base=$1 | ||
899 | 14 | next=$2 | ||
900 | 15 | |||
901 | 16 | dir=`mktemp -d difftests.XXXXXXXXXX` | ||
902 | 17 | trap "rm -rf $dir" EXIT | ||
903 | 18 | |||
904 | 19 | mkdir -p $dir/base | ||
905 | 20 | mkdir -p $dir/next | ||
906 | 21 | |||
907 | 22 | # Copy across all logs | ||
908 | 23 | cp $base/*.sum* $dir/base | ||
909 | 24 | cp $next/*.sum* $dir/next | ||
910 | 25 | unxz -f $dir/base/*.xz $dir/next/*.xz | ||
911 | 26 | |||
912 | 27 | # Pull out jus the PASS/FAIL/etc lines and sort by test name | ||
913 | 28 | # * Change absolute path names to .../ | ||
914 | 29 | # * Drop all limits tests | ||
915 | 30 | # | ||
916 | 31 | for i in `find $dir -name "*.sum"`; do | ||
917 | 32 | grep -E '^[A-Z]+:' $i \ | ||
918 | 33 | | grep -Ev limits- \ | ||
919 | 34 | | grep -Ev /guality/ \ | ||
920 | 35 | | sed -r 's#/scratch/\w+/\w+/\w+/\w+/[^/]+#...#g' \ | ||
921 | 36 | | sed -r "s#UNSUPPORTED: .+/testsuite/#UNSUPPORTED: #" \ | ||
922 | 37 | | sort -k 2 > $i.tmp | ||
923 | 38 | mv $i.tmp $i | ||
924 | 39 | done | ||
925 | 40 | |||
926 | 41 | # diff returns non-zero if there is a difference | ||
927 | 42 | set +e | ||
928 | 43 | (cd $dir && diff -U 0 -r base next) > $dir/diff.txt | ||
929 | 44 | # Drop anything but changes in test lines | ||
930 | 45 | grep -E '^[+-][A-Z]' $dir/diff.txt || true | ||
931 | 0 | 46 | ||
932 | === added file 'ec2-pull.sh' | |||
933 | --- ec2-pull.sh 1970-01-01 00:00:00 +0000 | |||
934 | +++ ec2-pull.sh 2014-07-01 15:58:40 +0000 | |||
935 | @@ -0,0 +1,28 @@ | |||
936 | 1 | #!/bin/bash | ||
937 | 2 | # | ||
938 | 3 | # Pull the results from the cloud to the build server | ||
939 | 4 | # | ||
940 | 5 | |||
941 | 6 | set -e | ||
942 | 7 | |||
943 | 8 | . ~/.config/cbuild/toolsrc | ||
944 | 9 | |||
945 | 10 | s3=linaro-toolchain-builds | ||
946 | 11 | |||
947 | 12 | dir=`mktemp -d` | ||
948 | 13 | trap "rm -rf $dir" EXIT | ||
949 | 14 | |||
950 | 15 | mkdir -p $dir/build | ||
951 | 16 | cd $dir | ||
952 | 17 | |||
953 | 18 | # Check what's there and fetch, aborting if it takes too long | ||
954 | 19 | candidates=$( timeout 600 s3cmd ls s3://$s3 | awk '{print $4;}' | grep 'logs.tar.xz$' ) | ||
955 | 20 | |||
956 | 21 | for i in $candidates; do | ||
957 | 22 | base=$( basename $i ) | ||
958 | 23 | # Get, extract, push, and remove | ||
959 | 24 | timeout 600 s3cmd get --skip-existing --no-progress $i && \ | ||
960 | 25 | tar xaf $base && \ | ||
961 | 26 | rsync -rtC build $www && \ | ||
962 | 27 | s3cmd del $i | ||
963 | 28 | done | ||
964 | 0 | 29 | ||
965 | === added file 'ec2-spawn.sh' | |||
966 | --- ec2-spawn.sh 1970-01-01 00:00:00 +0000 | |||
967 | +++ ec2-spawn.sh 2014-07-01 15:58:40 +0000 | |||
968 | @@ -0,0 +1,36 @@ | |||
969 | 1 | #!/bin/bash | ||
970 | 2 | |||
971 | 3 | function spawn { | ||
972 | 4 | host=$1 | ||
973 | 5 | ami=$2 | ||
974 | 6 | type=$3 | ||
975 | 7 | |||
976 | 8 | dir=/tmp/ec2slave/$host | ||
977 | 9 | mkdir -p $dir | ||
978 | 10 | cd $dir | ||
979 | 11 | |||
980 | 12 | ls /var/run/screen/S-cbuild/*.$host > /dev/null 2>&1 || \ | ||
981 | 13 | screen -S $host -L -d -m bash -c "cd $HOME/lib/cbuild-tools && exec ./ec2slave.sh $host $ami $type" | ||
982 | 14 | } | ||
983 | 15 | |||
984 | 16 | # us-east1 x86_64 EBS Natty | ||
985 | 17 | #spawn oort1 ami-fd589594 c1.xlarge | ||
986 | 18 | # Precise | ||
987 | 19 | spawn oort1 ami-a29943cb c1.xlarge | ||
988 | 20 | #spawn oort3 ami-fd589594 c1.xlarge | ||
989 | 21 | # us-east1 i686 EBS Natty | ||
990 | 22 | #spawn oort2 ami-81c31ae8 c1.medium | ||
991 | 23 | # Precise | ||
992 | 24 | spawn oort2 ami-ac9943c5 c1.medium | ||
993 | 25 | #spawn oort4 ami-ac9943c5 c1.medium | ||
994 | 26 | spawn oort6 ami-ac9943c5 c1.medium | ||
995 | 27 | #spawn oort8 ami-ac9943c5 c1.medium | ||
996 | 28 | #spawn oort4 ami-e358958a c1.medium | ||
997 | 29 | #spawn oort6 ami-e358958a c1.medium | ||
998 | 30 | #spawn oort8 ami-e358958a c1.medium | ||
999 | 31 | #spawn oort6 ami-e358958a c1.medium | ||
1000 | 32 | #spawn oort8 ami-06ad526f c1.medium | ||
1001 | 33 | #spawn oort11 ami-d5e54dbc c1.xlarge | ||
1002 | 34 | spawn oort12 ami-dfe54db6 c1.medium | ||
1003 | 35 | #spawn oort14 ami-37af765e c1.medium | ||
1004 | 36 | #spawn oort14 ami-87dd03ee c1.medium | ||
1005 | 0 | 37 | ||
1006 | === added file 'ec2new.sh' | |||
1007 | --- ec2new.sh 1970-01-01 00:00:00 +0000 | |||
1008 | +++ ec2new.sh 2014-07-01 15:58:40 +0000 | |||
1009 | @@ -0,0 +1,23 @@ | |||
1010 | 1 | #!/bin/bash | ||
1011 | 2 | # | ||
1012 | 3 | # Runs a EC2 slave for local use | ||
1013 | 4 | # | ||
1014 | 5 | # Usage: ec2new.sh [hostname [ami [type]]] | ||
1015 | 6 | # | ||
1016 | 7 | # such as: | ||
1017 | 8 | # ec2new.sh oort51 ami-1aad5273 c1.xlarge | ||
1018 | 9 | # ec2new.sh oort52 ami-06ad526f c1.medium | ||
1019 | 10 | # | ||
1020 | 11 | |||
1021 | 12 | set -e | ||
1022 | 13 | |||
1023 | 14 | # Don't kill on exit... | ||
1024 | 15 | kill=false | ||
1025 | 16 | . `dirname $0`/libec2.sh | ||
1026 | 17 | |||
1027 | 18 | echo Starting an instance | ||
1028 | 19 | start_instance | ||
1029 | 20 | init_instance | ||
1030 | 21 | |||
1031 | 22 | echo instance: $instance | ||
1032 | 23 | echo ip: $ip | ||
1033 | 0 | 24 | ||
1034 | === added file 'ec2slave-init-cbuild.sh' | |||
1035 | --- ec2slave-init-cbuild.sh 1970-01-01 00:00:00 +0000 | |||
1036 | +++ ec2slave-init-cbuild.sh 2014-07-01 15:58:40 +0000 | |||
1037 | @@ -0,0 +1,36 @@ | |||
1038 | 1 | #!/bin/sh | ||
1039 | 2 | # | ||
1040 | 3 | # Second stage where the cbuild user sets up | ||
1041 | 4 | # | ||
1042 | 5 | # Most configuration is in files shipped with this script | ||
1043 | 6 | |||
1044 | 7 | touch ~/.in-cloud | ||
1045 | 8 | |||
1046 | 9 | # Setup the SSH config | ||
1047 | 10 | cat > ~/.ssh/config <<EOF | ||
1048 | 11 | # Easier to set the port here then everywhere | ||
1049 | 12 | Host cbuild-master | ||
1050 | 13 | ProxyCommand ssh cbuild.validation.linaro.org nc -q0 toolchain64 %p | ||
1051 | 14 | EOF | ||
1052 | 15 | |||
1053 | 16 | # Set up the cbuild global config | ||
1054 | 17 | cat > ~/.config/cbuild/cbuildrc <<EOF | ||
1055 | 18 | # Nothing | ||
1056 | 19 | EOF | ||
1057 | 20 | |||
1058 | 21 | # Seed the known hosts with keys | ||
1059 | 22 | for i in linaro-gateway bazaar.launchpad.net validation.linaro.org cbuild.validation.linaro.org $(hostname) localhost cbuild-master; do | ||
1060 | 23 | ssh -o StrictHostKeyChecking=no -o BatchMode=yes $i true || true | ||
1061 | 24 | done | ||
1062 | 25 | |||
1063 | 26 | # Checkout the cbuild scripts | ||
1064 | 27 | if [ ! -d /cbuild/.bzr ]; then | ||
1065 | 28 | bzr lp-login cbuild | ||
1066 | 29 | bzr branch --use-existing-dir lp:cbuild /cbuild | ||
1067 | 30 | fi | ||
1068 | 31 | |||
1069 | 32 | cd /cbuild | ||
1070 | 33 | bzr pull | ||
1071 | 34 | |||
1072 | 35 | # Seed files from the nice-and-close S3 | ||
1073 | 36 | s3cmd sync s3://linaro-toolchain-files files | ||
1074 | 0 | 37 | ||
1075 | === added file 'ec2slave-init.sh' | |||
1076 | --- ec2slave-init.sh 1970-01-01 00:00:00 +0000 | |||
1077 | +++ ec2slave-init.sh 2014-07-01 15:58:40 +0000 | |||
1078 | @@ -0,0 +1,105 @@ | |||
1079 | 1 | #!/bin/sh | ||
1080 | 2 | |||
1081 | 3 | # Fail on any error | ||
1082 | 4 | set -e | ||
1083 | 5 | |||
1084 | 6 | # Automatically kill the slave if it runs for too long | ||
1085 | 7 | echo /sbin/poweroff | at now + 72 hours | ||
1086 | 8 | |||
1087 | 9 | # Set the hostname | ||
1088 | 10 | hostname=${1:-oort99} | ||
1089 | 11 | |||
1090 | 12 | echo $hostname > /etc/hostname | ||
1091 | 13 | hostname $hostname | ||
1092 | 14 | echo 127.0.0.1 $hostname proxy >> /etc/hosts | ||
1093 | 15 | |||
1094 | 16 | # Bind mount /cbuild | ||
1095 | 17 | mkdir -p /cbuild /mnt/cbuild | ||
1096 | 18 | mount -o bind /mnt/cbuild /cbuild | ||
1097 | 19 | chmod a+w /cbuild | ||
1098 | 20 | |||
1099 | 21 | # Use the S3 backed archive | ||
1100 | 22 | sed -i.dist 's,archive.ubuntu.com,archive.ubuntu.com.s3.amazonaws.com,g' /etc/apt/sources.list | ||
1101 | 23 | # without pipelining to make it more reliable | ||
1102 | 24 | echo "Acquire::http::Pipeline-Depth 0;" > /etc/apt/apt.conf.d/99no-pipelining | ||
1103 | 25 | |||
1104 | 26 | flags="-yq --force-yes" | ||
1105 | 27 | |||
1106 | 28 | # Install the basic packages | ||
1107 | 29 | apt-get update || true | ||
1108 | 30 | apt-get install $flags puppet jed python-software-properties | ||
1109 | 31 | |||
1110 | 32 | # Add in the PPA | ||
1111 | 33 | #add-apt-repository ppa:linaro-toolchain-dev/build-deps | ||
1112 | 34 | #apt-get update || true | ||
1113 | 35 | |||
1114 | 36 | # Basics | ||
1115 | 37 | apt-get build-dep $flags gcc binutils gdb | ||
1116 | 38 | apt-get build-dep $flags gcc gdb eglibc ffmpeg llvm python libvorbis | ||
1117 | 39 | apt-get build-dep $flags gcc-4.6 || \ | ||
1118 | 40 | apt-get build-dep $flags gcc-4.5 || \ | ||
1119 | 41 | apt-get build-dep $flags gcc-snapshot \ | ||
1120 | 42 | |||
1121 | 43 | # For llvm | ||
1122 | 44 | apt-get install $flags python-sphinx || true | ||
1123 | 45 | |||
1124 | 46 | # For cross test. Missing on lucid | ||
1125 | 47 | apt-get install $flags qemu-kvm qemu-user qemu-system || true | ||
1126 | 48 | |||
1127 | 49 | # Needed for baremetal and graphite | ||
1128 | 50 | apt-get install $flags binutils-arm-none-eabi libcloog-ppl-dev || true | ||
1129 | 51 | |||
1130 | 52 | # Needed for cbuild | ||
1131 | 53 | apt-get install $flags time python-irclib wget gnupg ccrypt rsync coreutils \ | ||
1132 | 54 | sendemail bzr xdelta3 xz-utils unzip openssh-client gdb libio-socket-ssl-perl libnet-ssleay-perl | ||
1133 | 55 | |||
1134 | 56 | # Needed for ubutest | ||
1135 | 57 | apt-get build-dep $flags eglibc base-files base-passwd bash coreutils dash \ | ||
1136 | 58 | debianutils diffutils dpkg e2fsprogs findutils grep gzip hostname ncurses \ | ||
1137 | 59 | perl python-defaults sed shadow tar util-linux | ||
1138 | 60 | |||
1139 | 61 | # Needed for qemu | ||
1140 | 62 | apt-get install $flags libpixman-1-dev | ||
1141 | 63 | |||
1142 | 64 | apt-get build-dep $flags python2.7 || true | ||
1143 | 65 | # devscripts asks a question... | ||
1144 | 66 | echo 1 | apt-get install $flags devscripts || true | ||
1145 | 67 | |||
1146 | 68 | # Needed for crosstool-NG LSB based builds | ||
1147 | 69 | apt-get install $flags lsb lsb-build-cc3 lsb-appchk3 ccache gcc-mingw32 flip tk tofrodos | ||
1148 | 70 | apt-get install $flags gcc-4.1 g++-4.1 || true | ||
1149 | 71 | apt-get install $flags gcc-4.1-multilib g++-4.1-multilib || true | ||
1150 | 72 | |||
1151 | 73 | # Needed for cloud builds | ||
1152 | 74 | apt-get install $flags polipo s3cmd | ||
1153 | 75 | |||
1154 | 76 | # Use Bash as /bin/sh. Michael's fault... | ||
1155 | 77 | echo n | dpkg-reconfigure -f teletype dash | ||
1156 | 78 | |||
1157 | 79 | # Set up the cbuild user | ||
1158 | 80 | cb=/home/cbuild | ||
1159 | 81 | |||
1160 | 82 | adduser --disabled-password --gecos cbuild cbuild | ||
1161 | 83 | tar xaf *seed*.tar* -C /home/cbuild --strip-components=1 | ||
1162 | 84 | |||
1163 | 85 | chown -R cbuild.cbuild $cb | ||
1164 | 86 | chmod -R go-rwx $cb/.ssh | ||
1165 | 87 | |||
1166 | 88 | # Finally put /tmp in RAM for faster builds | ||
1167 | 89 | mount -t tmpfs tmfs /tmp | ||
1168 | 90 | |||
1169 | 91 | # Break multiarch | ||
1170 | 92 | multi=`dpkg-architecture -qDEB_BUILD_MULTIARCH || true` | ||
1171 | 93 | |||
1172 | 94 | if [ ! -z "$multi" ]; then | ||
1173 | 95 | pushd /usr/lib | ||
1174 | 96 | cd /usr/lib && ls $multi/*crt*.o | xargs -L 1 ln -sf | ||
1175 | 97 | cd /usr/include | ||
1176 | 98 | |||
1177 | 99 | for i in asm gnu bits sys; do | ||
1178 | 100 | if [ -d $multi/$i ]; then | ||
1179 | 101 | rm -rf $i | ||
1180 | 102 | ln -sf $multi/$i | ||
1181 | 103 | fi | ||
1182 | 104 | done | ||
1183 | 105 | fi | ||
1184 | 0 | 106 | ||
1185 | === added file 'ec2slave.sh' | |||
1186 | --- ec2slave.sh 1970-01-01 00:00:00 +0000 | |||
1187 | +++ ec2slave.sh 2014-07-01 15:58:40 +0000 | |||
1188 | @@ -0,0 +1,65 @@ | |||
1189 | 1 | #!/bin/bash | ||
1190 | 2 | # | ||
1191 | 3 | # Runs a EC2 slave that builds cbuild jobs | ||
1192 | 4 | # | ||
1193 | 5 | # Usage: ec2slave.sh [hostname [ami [type]]] | ||
1194 | 6 | # | ||
1195 | 7 | # such as: | ||
1196 | 8 | # ec2slave.sh oort2 ami-689c6701 c1.medium | ||
1197 | 9 | # ec2slave.sh oort1 ami-40926929 c1.xlarge | ||
1198 | 10 | # | ||
1199 | 11 | |||
1200 | 12 | set -e | ||
1201 | 13 | |||
1202 | 14 | . `dirname $0`/libec2.sh | ||
1203 | 15 | |||
1204 | 16 | function kill_old { | ||
1205 | 17 | if [ "$instance" != "" ]; then | ||
1206 | 18 | now=`date +%s` | ||
1207 | 19 | elapsed=$(($now-$used)) | ||
1208 | 20 | |||
1209 | 21 | if [ "$elapsed" -gt "600" ]; then | ||
1210 | 22 | echo Killing $instance due to inactivity | ||
1211 | 23 | $lock ec2kill $instance | ||
1212 | 24 | instance= | ||
1213 | 25 | fi | ||
1214 | 26 | fi | ||
1215 | 27 | } | ||
1216 | 28 | |||
1217 | 29 | function update_status { | ||
1218 | 30 | if [ "$instance" == "" ]; then | ||
1219 | 31 | $wget -O - $SCHEDULER_API/update/$hostname/lurking | ||
1220 | 32 | else | ||
1221 | 33 | $wget -O - $SCHEDULER_API/update/$hostname/idle | ||
1222 | 34 | fi | ||
1223 | 35 | } | ||
1224 | 36 | |||
1225 | 37 | DRIFT=$(($RANDOM % 30)) | ||
1226 | 38 | |||
1227 | 39 | while true; do | ||
1228 | 40 | echo $hostname $instance `date` | ||
1229 | 41 | |||
1230 | 42 | sleep $((180 + $DRIFT)) | ||
1231 | 43 | |||
1232 | 44 | kill_old | ||
1233 | 45 | update_status | ||
1234 | 46 | |||
1235 | 47 | # See if there's a job waiting | ||
1236 | 48 | next=`$wget -O - $SCHEDULER_API/peek/$hostname` | ||
1237 | 49 | |||
1238 | 50 | case "$next" in | ||
1239 | 51 | False) continue ;; | ||
1240 | 52 | esac | ||
1241 | 53 | |||
1242 | 54 | echo Running a job | ||
1243 | 55 | |||
1244 | 56 | if [ "$instance" == "" ]; then | ||
1245 | 57 | echo Starting an instance | ||
1246 | 58 | start_instance | ||
1247 | 59 | init_instance | ||
1248 | 60 | used=`date +%s` | ||
1249 | 61 | fi | ||
1250 | 62 | |||
1251 | 63 | ssh -o StrictHostKeyChecking=no -o BatchMode=yes -t cbuild@$ip 'cd /cbuild && ./run.sh' | ||
1252 | 64 | used=`date +%s` | ||
1253 | 65 | done | ||
1254 | 0 | 66 | ||
1255 | === added file 'ec2watch.sh' | |||
1256 | --- ec2watch.sh 1970-01-01 00:00:00 +0000 | |||
1257 | +++ ec2watch.sh 2014-07-01 15:58:40 +0000 | |||
1258 | @@ -0,0 +1,18 @@ | |||
1259 | 1 | #!/bin/bash | ||
1260 | 2 | # | ||
1261 | 3 | # Watch the EC2 instances so we can see where the money goes | ||
1262 | 4 | # | ||
1263 | 5 | # Terribly ugly hack. Add this as a cronjob that runs once a half | ||
1264 | 6 | # hour. Spits the results of ec2din into a timestamped file under | ||
1265 | 7 | # $HOME/var. | ||
1266 | 8 | # | ||
1267 | 9 | |||
1268 | 10 | # Pull in the local configuration | ||
1269 | 11 | . ~/.private/ec2slave.rc | ||
1270 | 12 | |||
1271 | 13 | dir=$HOME/var/log/ec2watch | ||
1272 | 14 | month=$(date +%Y-%m) | ||
1273 | 15 | now=$(date +%F-%H-%M) | ||
1274 | 16 | |||
1275 | 17 | mkdir -p $dir/$month | ||
1276 | 18 | ec2din --show-empty-fields | gzip > $dir/$month/$now.txt.gz | ||
1277 | 0 | 19 | ||
1278 | === added file 'enrich-gcc-linaro-repo' | |||
1279 | --- enrich-gcc-linaro-repo 1970-01-01 00:00:00 +0000 | |||
1280 | +++ enrich-gcc-linaro-repo 2014-07-01 15:58:40 +0000 | |||
1281 | @@ -0,0 +1,45 @@ | |||
1282 | 1 | #!/usr/bin/python | ||
1283 | 2 | # -*- coding: utf-8 -*- | ||
1284 | 3 | # | ||
1285 | 4 | # Copies revisions from branches into the dev focus branch as it's | ||
1286 | 5 | # also the stacked branch. This speeds up branching when using a | ||
1287 | 6 | # shared repo. | ||
1288 | 7 | # | ||
1289 | 8 | # Runs as a cron job | ||
1290 | 9 | # | ||
1291 | 10 | # Author: Loïc Minier <loic.minier@linaro.org> | ||
1292 | 11 | # | ||
1293 | 12 | |||
1294 | 13 | # took 6mn41s on the first run | ||
1295 | 14 | # 18s on the second run | ||
1296 | 15 | # | ||
1297 | 16 | |||
1298 | 17 | import sys | ||
1299 | 18 | |||
1300 | 19 | import bzrlib.repository | ||
1301 | 20 | import bzrlib.plugin | ||
1302 | 21 | |||
1303 | 22 | #bzrlib.initialize() | ||
1304 | 23 | bzrlib.plugin.load_plugins() | ||
1305 | 24 | |||
1306 | 25 | r_4_7 = bzrlib.repository.Repository.open('lp:gcc-linaro/4.7') | ||
1307 | 26 | r_4_6 = bzrlib.repository.Repository.open('lp:gcc-linaro/4.6') | ||
1308 | 27 | #r_4_5 = bzrlib.repository.Repository.open('lp:gcc-linaro/4.5') | ||
1309 | 28 | #r_4_4 = bzrlib.repository.Repository.open('lp:gcc-linaro/4.4') | ||
1310 | 29 | # copy revisions from 4.6 branches into 4.7 which is the devfocus | ||
1311 | 30 | # branch because it's used as a stacked branch | ||
1312 | 31 | # 4.4 and 4.5 aren't updated anymore | ||
1313 | 32 | r_4_7.fetch(r_4_6) | ||
1314 | 33 | #r_4_6.fetch(r_4_5) | ||
1315 | 34 | #r_4_6.fetch(r_4_4) | ||
1316 | 35 | # copy revisions from 4.6 into 4.4 and 4.5 once to workaround LP #388269; only | ||
1317 | 36 | # needed once ever | ||
1318 | 37 | # copying 4.5 into 4.4 took 52mn55s on the first run and 51s on second run | ||
1319 | 38 | # (with three up-to-date enriching branches enabled) | ||
1320 | 39 | # copying 4.5 into 4.6 took 1h45mn13s on the first run and 48s on second run | ||
1321 | 40 | # (with three maybe not fully up-to-date enriching branches enabled) | ||
1322 | 41 | #r_4_4.fetch(r_4_6) | ||
1323 | 42 | #r_4_5.fetch(r_4_6) | ||
1324 | 43 | r_4_6.fetch(r_4_7) | ||
1325 | 44 | |||
1326 | 45 | print sys.argv[0], 'done' | ||
1327 | 0 | \ No newline at end of file | 46 | \ No newline at end of file |
1328 | 1 | 47 | ||
1329 | === added file 'export-bzr.sh' | |||
1330 | --- export-bzr.sh 1970-01-01 00:00:00 +0000 | |||
1331 | +++ export-bzr.sh 2014-07-01 15:58:40 +0000 | |||
1332 | @@ -0,0 +1,85 @@ | |||
1333 | 1 | #!/bin/sh | ||
1334 | 2 | # Update a branch and snapshot the latest revision | ||
1335 | 3 | # Can also snapshot past revisions and add a per-user | ||
1336 | 4 | # suffix | ||
1337 | 5 | # | ||
1338 | 6 | # Example: export-bzr.sh ~/repos/gcc-linaro/4.6 gcc-linaro-4.6 [revno [suffix [basedir]]] | ||
1339 | 7 | # | ||
1340 | 8 | set -e | ||
1341 | 9 | |||
1342 | 10 | . ~/.config/cbuild/toolsrc | ||
1343 | 11 | |||
1344 | 12 | dir=`mktemp -d` | ||
1345 | 13 | trap "rm -rf $dir" EXIT | ||
1346 | 14 | |||
1347 | 15 | # Directory this script runs from | ||
1348 | 16 | here=`dirname $0` | ||
1349 | 17 | |||
1350 | 18 | # Suffix for manual pulls | ||
1351 | 19 | SUFFIX=${4:-} | ||
1352 | 20 | |||
1353 | 21 | # Pull a branch and tarball it up | ||
1354 | 22 | branch=$1 | ||
1355 | 23 | head=$2 | ||
1356 | 24 | |||
1357 | 25 | latest=`bzr revno $branch` | ||
1358 | 26 | revno=${3:-$latest} | ||
1359 | 27 | |||
1360 | 28 | base=${5:-$branch} | ||
1361 | 29 | |||
1362 | 30 | stem="$head+bzr$revno$SUFFIX" | ||
1363 | 31 | tar="/tmp/$stem.tar" | ||
1364 | 32 | meta="/tmp/$stem.txt" | ||
1365 | 33 | diff="/tmp/$stem.diff" | ||
1366 | 34 | xdelta="$tar.xdelta3.xz" | ||
1367 | 35 | |||
1368 | 36 | if [ -f $snapshots/`basename $xdelta` ]; then | ||
1369 | 37 | exit 0 | ||
1370 | 38 | fi | ||
1371 | 39 | |||
1372 | 40 | closest=`$here/closest.py $tar $snapshots/base/*.tar` | ||
1373 | 41 | |||
1374 | 42 | mkdir -p $snapshots | ||
1375 | 43 | |||
1376 | 44 | ancestor=`bzr revision-info -d $branch -r ancestor:$base` | ||
1377 | 45 | |||
1378 | 46 | # Record some meta data about the branch | ||
1379 | 47 | echo \# Branch summary > $meta | ||
1380 | 48 | echo name: $stem >> $meta | ||
1381 | 49 | echo snapshot-date: `date --rfc-3339=seconds` >> $meta | ||
1382 | 50 | bzr log -l1 $branch | grep -E '^(committer|timestamp):' >> $meta | ||
1383 | 51 | echo directory: $branch >> $meta | ||
1384 | 52 | echo branch: `bzr info $branch | grep parent | awk '{print $3;}'` >> $meta | ||
1385 | 53 | echo mainline-branch: $base >> $meta | ||
1386 | 54 | echo revno: $revno >> $meta | ||
1387 | 55 | echo revision: `bzr revision-info -d $branch -r $revno` >> $meta | ||
1388 | 56 | echo tip: `bzr revision-info -d $branch` >> $meta | ||
1389 | 57 | echo ancestor: $ancestor >> $meta | ||
1390 | 58 | echo closest: `basename $closest` >> $meta | ||
1391 | 59 | echo xdelta3: `basename $xdelta` >> $meta | ||
1392 | 60 | |||
1393 | 61 | id=`echo $ancestor | awk '{ print $2; }'` | ||
1394 | 62 | |||
1395 | 63 | # Create the diff | ||
1396 | 64 | if [ "$id" != "$revno" ]; then | ||
1397 | 65 | bzr diff -r $id $branch > $diff || true | ||
1398 | 66 | fi | ||
1399 | 67 | |||
1400 | 68 | echo Exporting and stamping $revno | ||
1401 | 69 | bzr export -r $revno $dir/$stem $branch | ||
1402 | 70 | REVNO=$revno $here/stamp_branch.sh $branch $dir/$stem | ||
1403 | 71 | |||
1404 | 72 | # Create the tarball | ||
1405 | 73 | echo Creating $tar | ||
1406 | 74 | (cd $dir && find $stem -print0 | sort -z) | tar caf $tar -C $dir --no-recursion --null -T - | ||
1407 | 75 | |||
1408 | 76 | # Create the delta | ||
1409 | 77 | echo Making the delta relative to $closest | ||
1410 | 78 | xdelta3 -fe -s $closest $tar $tar.xdelta3 | ||
1411 | 79 | rm -f $tar | ||
1412 | 80 | xz -f $tar.xdelta3 | ||
1413 | 81 | |||
1414 | 82 | mv -f $tar*.xz $diff $meta $snapshots | ||
1415 | 83 | |||
1416 | 84 | echo New snapshot `basename $tar` created | ||
1417 | 85 | echo stem: $stem | ||
1418 | 0 | 86 | ||
1419 | === added file 'export-git.sh' | |||
1420 | --- export-git.sh 1970-01-01 00:00:00 +0000 | |||
1421 | +++ export-git.sh 2014-07-01 15:58:40 +0000 | |||
1422 | @@ -0,0 +1,75 @@ | |||
1423 | 1 | #!/bin/sh | ||
1424 | 2 | # | ||
1425 | 3 | # Update a git branch and snapshot the latest revision | ||
1426 | 4 | # | ||
1427 | 5 | |||
1428 | 6 | set -e | ||
1429 | 7 | |||
1430 | 8 | . ~/.config/cbuild/toolsrc | ||
1431 | 9 | |||
1432 | 10 | dir=`mktemp -d` | ||
1433 | 11 | trap "rm -rf $dir" EXIT | ||
1434 | 12 | |||
1435 | 13 | # Directory this script runs from | ||
1436 | 14 | here=`dirname $0` | ||
1437 | 15 | |||
1438 | 16 | # Suffix for manual pulls | ||
1439 | 17 | SUFFIX=${4:-} | ||
1440 | 18 | |||
1441 | 19 | # Subdirectory to archive. Needed for Android GCC | ||
1442 | 20 | #SUBDIR= | ||
1443 | 21 | |||
1444 | 22 | # Pull a branch and tarball it up | ||
1445 | 23 | branch=$1 | ||
1446 | 24 | head=${2:-`basename $branch`} | ||
1447 | 25 | id=${3:-HEAD} | ||
1448 | 26 | |||
1449 | 27 | export GIT_DIR=$branch/.git | ||
1450 | 28 | export GIT_WORK_TREE=$branch | ||
1451 | 29 | |||
1452 | 30 | (cd $branch && git reset --hard -q && git pull -q) | ||
1453 | 31 | latest=`git rev-parse $id` | ||
1454 | 32 | short=`echo $latest | cut -c -7` | ||
1455 | 33 | now=`date +%Y%m%d` | ||
1456 | 34 | |||
1457 | 35 | name=$head$now+git$short$SUFFIX | ||
1458 | 36 | tar=/tmp/$name.tar | ||
1459 | 37 | xdelta=$tar.xdelta3.xz | ||
1460 | 38 | |||
1461 | 39 | if ls $snapshots/$head*git$short*xz > /dev/null 2>&1; then | ||
1462 | 40 | exit 0 | ||
1463 | 41 | fi | ||
1464 | 42 | |||
1465 | 43 | mkdir -p $snapshots | ||
1466 | 44 | echo Exporting $short | ||
1467 | 45 | git archive --format=tar --prefix=$name/ $id $SUBDIR | tar xf - -C $dir | ||
1468 | 46 | |||
1469 | 47 | if [ -n "$SUBDIR" ]; then | ||
1470 | 48 | # We've ended up with $dir/$head/$SUBDIR. Shuffle them about | ||
1471 | 49 | mv $dir/$head/$SUBDIR $dir | ||
1472 | 50 | rm -r $dir/$head | ||
1473 | 51 | mv $dir/$SUBDIR $dir/$head | ||
1474 | 52 | fi | ||
1475 | 53 | |||
1476 | 54 | # Create the tarball | ||
1477 | 55 | echo Creating $tar | ||
1478 | 56 | (cd $dir && find $name -print0 | sort -z) | tar caf $tar -C $dir --no-recursion --null -T - | ||
1479 | 57 | |||
1480 | 58 | # Use gzip as an approximation to how well it will compress | ||
1481 | 59 | size=$( gzip < $tar | wc -c ) | ||
1482 | 60 | |||
1483 | 61 | if [ "$size" -lt "10000000000" ]; then | ||
1484 | 62 | # Small enough to just tar | ||
1485 | 63 | xz -9f $tar | ||
1486 | 64 | else | ||
1487 | 65 | # Create the delta | ||
1488 | 66 | closest=`$here/closest.py $tar $snapshots/base/*.tar` | ||
1489 | 67 | echo Making the delta relative to $closest | ||
1490 | 68 | xdelta3 -fe -s $closest $tar $tar.xdelta3 | ||
1491 | 69 | rm -f $tar | ||
1492 | 70 | xz -9f $tar.xdelta3 | ||
1493 | 71 | fi | ||
1494 | 72 | |||
1495 | 73 | mv $tar*.xz $snapshots | ||
1496 | 74 | echo New snapshot `basename $tar` created | ||
1497 | 75 | $here/spawn.sh $tar | ||
1498 | 0 | 76 | ||
1499 | === added file 'export-hg.sh' | |||
1500 | --- export-hg.sh 1970-01-01 00:00:00 +0000 | |||
1501 | +++ export-hg.sh 2014-07-01 15:58:40 +0000 | |||
1502 | @@ -0,0 +1,61 @@ | |||
1503 | 1 | #!/bin/sh | ||
1504 | 2 | # Update a branch and snapshot the latest revision | ||
1505 | 3 | # Can also snapshot past revisions and add a per-user | ||
1506 | 4 | # suffix | ||
1507 | 5 | # | ||
1508 | 6 | # Example: export-bzr.sh ~/repos/gcc-linaro/4.6 gcc-linaro-4.6 [revno [suffix [basedir]]] | ||
1509 | 7 | # | ||
1510 | 8 | set -e | ||
1511 | 9 | |||
1512 | 10 | dir=`mktemp -d` | ||
1513 | 11 | trap "rm -rf $dir" EXIT | ||
1514 | 12 | |||
1515 | 13 | # Directory this script runs from | ||
1516 | 14 | here=`dirname $0` | ||
1517 | 15 | |||
1518 | 16 | # Suffix for manual pulls | ||
1519 | 17 | SUFFIX=${4:-} | ||
1520 | 18 | |||
1521 | 19 | # Pull a branch and tarball it up | ||
1522 | 20 | branch=$1 | ||
1523 | 21 | head=$2 | ||
1524 | 22 | hgflags="-R $branch -y -q" | ||
1525 | 23 | |||
1526 | 24 | hg $hgflags pull | ||
1527 | 25 | latest=`hg $hgflags -q tip | awk -F: '{print $1;}'` | ||
1528 | 26 | |||
1529 | 27 | revno=${3:-$latest} | ||
1530 | 28 | |||
1531 | 29 | base=${5:-$branch} | ||
1532 | 30 | |||
1533 | 31 | snapshots=$HOME/snapshots | ||
1534 | 32 | stem=$head+hg$revno$SUFFIX | ||
1535 | 33 | tar=/tmp/$stem.tar | ||
1536 | 34 | xdelta=$tar.xdelta3.xz | ||
1537 | 35 | |||
1538 | 36 | if [ -f $snapshots/`basename $xdelta` ]; then | ||
1539 | 37 | exit 0 | ||
1540 | 38 | fi | ||
1541 | 39 | |||
1542 | 40 | closest=`$here/closest.py $tar $snapshots/base/*.tar` | ||
1543 | 41 | |||
1544 | 42 | mkdir -p $snapshots | ||
1545 | 43 | |||
1546 | 44 | echo Exporting and stamping $revno | ||
1547 | 45 | hg $hgflags archive -r $revno $dir/$head | ||
1548 | 46 | REVNO=$revno $here/stamp_branch.sh $branch $dir/$head | ||
1549 | 47 | |||
1550 | 48 | # Create the tarball | ||
1551 | 49 | echo Creating $tar | ||
1552 | 50 | (cd $dir && find $head -print0 | sort -z) | tar caf $tar -C $dir --no-recursion --null -T - | ||
1553 | 51 | |||
1554 | 52 | # Create the delta | ||
1555 | 53 | echo Making the delta relative to $closest | ||
1556 | 54 | xdelta3 -fe -s $closest $tar $tar.xdelta3 | ||
1557 | 55 | rm -f $tar | ||
1558 | 56 | xz -f $tar.xdelta3 | ||
1559 | 57 | |||
1560 | 58 | mv -f $tar.xdelta3.xz $snapshots | ||
1561 | 59 | |||
1562 | 60 | echo New snapshot `basename $tar` created | ||
1563 | 61 | echo stem: $stem | ||
1564 | 0 | 62 | ||
1565 | === added file 'findancestor.py' | |||
1566 | --- findancestor.py 1970-01-01 00:00:00 +0000 | |||
1567 | +++ findancestor.py 2014-07-01 15:58:40 +0000 | |||
1568 | @@ -0,0 +1,204 @@ | |||
1569 | 1 | #!/usr/bin/python | ||
1570 | 2 | """Given a build name, find the ancestor or the last working build of | ||
1571 | 3 | that series. | ||
1572 | 4 | |||
1573 | 5 | Examples: | ||
1574 | 6 | findancestor gcc-linaro-4.5+bzr99502~ams~merge-20110413 -> the ancestor | ||
1575 | 7 | findancestor gcc-linaro-4.5+bzr99510 -> probably gcc-linaro-4.5+bzr99509 | ||
1576 | 8 | findancestor gcc-4.6+svn174684 -> the build from last week | ||
1577 | 9 | """ | ||
1578 | 10 | |||
1579 | 11 | import sys | ||
1580 | 12 | import os.path | ||
1581 | 13 | import pprint | ||
1582 | 14 | import re | ||
1583 | 15 | import pdb | ||
1584 | 16 | import collections | ||
1585 | 17 | |||
1586 | 18 | def parse(name): | ||
1587 | 19 | """Parse the meta data file which is a series of name: value pairs""" | ||
1588 | 20 | values = {} | ||
1589 | 21 | |||
1590 | 22 | with open(name) as f: | ||
1591 | 23 | lines = [x.strip() for x in f.readlines()] | ||
1592 | 24 | |||
1593 | 25 | for line in lines: | ||
1594 | 26 | if not line: | ||
1595 | 27 | continue | ||
1596 | 28 | |||
1597 | 29 | if line.startswith('#'): | ||
1598 | 30 | continue | ||
1599 | 31 | |||
1600 | 32 | name, value = [x.strip() for x in line.split(':', 1)] | ||
1601 | 33 | values[name] = value | ||
1602 | 34 | |||
1603 | 35 | return values | ||
1604 | 36 | |||
1605 | 37 | def revkey(record): | ||
1606 | 38 | try: | ||
1607 | 39 | if record.date: | ||
1608 | 40 | return int(record.date.replace('~', '')) | ||
1609 | 41 | else: | ||
1610 | 42 | return int(record.revision) | ||
1611 | 43 | except ValueError: | ||
1612 | 44 | return record.revision | ||
1613 | 45 | |||
1614 | 46 | def make_splitter(): | ||
1615 | 47 | """Splits a build name like gcc-4.5+svn1234, | ||
1616 | 48 | gcc-linaro-4.6+bzr1234, and gdb-7.3~20110606+gitabcdef into the | ||
1617 | 49 | product, series, optional date, version control system, and | ||
1618 | 50 | revision. | ||
1619 | 51 | |||
1620 | 52 | >>> make_splitter().match('gcc-4.5~svn12345').groups() | ||
1621 | 53 | ('gcc-', '4.5', None, '~svn', '12345') | ||
1622 | 54 | >>> make_splitter().match('gcc-linaro-4.6+bzr4567').groups() | ||
1623 | 55 | ('gcc-linaro-', '4.6', None, '+bzr', '4567') | ||
1624 | 56 | >>> make_splitter().match('gdb-7.3~20110606+git057a947').groups() | ||
1625 | 57 | ('gdb-', '7.3', '~20110606', '+git', '057a947') | ||
1626 | 58 | """ | ||
1627 | 59 | return re.compile('([\D\-]+)([\d\.]+)([+~]\d+)?([+~][a-z]{3})(\w+)$') | ||
1628 | 60 | |||
1629 | 61 | def make_release_splitter(): | ||
1630 | 62 | """Splits a release name like gcc-linaro-4.5-2011.03-0 into | ||
1631 | 63 | product, series, and release. | ||
1632 | 64 | |||
1633 | 65 | >>> make_release_splitter().match('gcc-linaro-4.5-2011.03-0').groups() | ||
1634 | 66 | ('gcc-linaro-', '4.5', '-2011.03-0') | ||
1635 | 67 | >>> make_release_splitter().match('gcc-linaro-4.6-2012.03').groups() | ||
1636 | 68 | ('gcc-linaro-', '4.6', '-2012.03') | ||
1637 | 69 | """ | ||
1638 | 70 | return re.compile('([\D\-]+)([\d\.]+)(-[\d.\-]+)$') | ||
1639 | 71 | |||
1640 | 72 | def find_via_meta(name, snapshots): | ||
1641 | 73 | # See if we can find the meta data and extract the ancestor | ||
1642 | 74 | metaname = os.path.join(snapshots, '%s.txt' % name) | ||
1643 | 75 | |||
1644 | 76 | try: | ||
1645 | 77 | meta = parse(metaname) | ||
1646 | 78 | revision, prev, mainline = meta['revision'], meta['ancestor'], meta['mainline-branch'] | ||
1647 | 79 | |||
1648 | 80 | if revision != prev: | ||
1649 | 81 | return '%s+bzr%s' % (mainline, prev.split()[0]) | ||
1650 | 82 | except Exception, ex: | ||
1651 | 83 | pass | ||
1652 | 84 | |||
1653 | 85 | return '' | ||
1654 | 86 | |||
1655 | 87 | def find_via_build(allfiles, name): | ||
1656 | 88 | # Don't know the ancestor. Find the previous build | ||
1657 | 89 | Record = collections.namedtuple('Record', 'product series date vcs revision') | ||
1658 | 90 | |||
1659 | 91 | splitter = make_splitter() | ||
1660 | 92 | builds = set([x[1] for x in allfiles if x[-1] == 'finished.txt']) | ||
1661 | 93 | builds = [splitter.match(x) for x in sorted(builds)] | ||
1662 | 94 | builds = [Record(*x.groups()) for x in builds if x] | ||
1663 | 95 | |||
1664 | 96 | match = splitter.match(name) | ||
1665 | 97 | |||
1666 | 98 | if match: | ||
1667 | 99 | this = Record(*match.groups()) | ||
1668 | 100 | |||
1669 | 101 | # Grab the builds that match | ||
1670 | 102 | matches = [x for x in builds | ||
1671 | 103 | if x.product == this.product | ||
1672 | 104 | and x.series == this.series | ||
1673 | 105 | and x.vcs == this.vcs] | ||
1674 | 106 | |||
1675 | 107 | # Sort them by revno | ||
1676 | 108 | matches.sort(key=revkey) | ||
1677 | 109 | |||
1678 | 110 | # Find this build and the one before | ||
1679 | 111 | revnos = [x.revision for x in matches] | ||
1680 | 112 | |||
1681 | 113 | if this.revision in revnos: | ||
1682 | 114 | idx = revnos.index(this.revision) | ||
1683 | 115 | |||
1684 | 116 | if idx > 0: | ||
1685 | 117 | return ''.join(x for x in matches[idx-1] if x) | ||
1686 | 118 | |||
1687 | 119 | return '' | ||
1688 | 120 | |||
1689 | 121 | def find_via_variant(allfiles, name): | ||
1690 | 122 | # Don't know the ancestor. Find the same build without the variant. | ||
1691 | 123 | if '^' not in name: | ||
1692 | 124 | return None | ||
1693 | 125 | |||
1694 | 126 | root, variant = name.split('^') | ||
1695 | 127 | |||
1696 | 128 | builds = [x for x in allfiles if x[-1] == 'finished.txt' and x[-4] == root] | ||
1697 | 129 | |||
1698 | 130 | if builds: | ||
1699 | 131 | return root | ||
1700 | 132 | |||
1701 | 133 | return '' | ||
1702 | 134 | |||
1703 | 135 | def find_via_release(allfiles, name): | ||
1704 | 136 | Record = collections.namedtuple('Record', 'product series release') | ||
1705 | 137 | |||
1706 | 138 | # Don't know the ancestor. Find the previous release | ||
1707 | 139 | splitter = make_release_splitter() | ||
1708 | 140 | builds = set([x[1] for x in allfiles if x[-1] == 'finished.txt']) | ||
1709 | 141 | builds = [splitter.match(x) for x in sorted(builds)] | ||
1710 | 142 | builds = [Record(*x.groups()) for x in builds if x] | ||
1711 | 143 | |||
1712 | 144 | match = splitter.match(name) | ||
1713 | 145 | |||
1714 | 146 | if match: | ||
1715 | 147 | this = Record(*match.groups()) | ||
1716 | 148 | |||
1717 | 149 | # Grab the builds that match | ||
1718 | 150 | matches = [x for x in builds | ||
1719 | 151 | if x.product == this.product | ||
1720 | 152 | and x.series == this.series] | ||
1721 | 153 | |||
1722 | 154 | # Sort them by release | ||
1723 | 155 | matches.sort(key=lambda x: x.release) | ||
1724 | 156 | |||
1725 | 157 | # Find this build and the one before | ||
1726 | 158 | releases = [x.release for x in matches] | ||
1727 | 159 | |||
1728 | 160 | if this.release in releases: | ||
1729 | 161 | idx = releases.index(this.release) | ||
1730 | 162 | |||
1731 | 163 | if idx > 0: | ||
1732 | 164 | return ''.join(x for x in matches[idx-1] if x) | ||
1733 | 165 | |||
1734 | 166 | return '' | ||
1735 | 167 | |||
1736 | 168 | def find(allfiles, name, snapshots): | ||
1737 | 169 | ancestor = find_via_meta(name, snapshots) | ||
1738 | 170 | |||
1739 | 171 | if ancestor: | ||
1740 | 172 | return ancestor | ||
1741 | 173 | |||
1742 | 174 | ancestor = find_via_variant(allfiles, name) | ||
1743 | 175 | |||
1744 | 176 | if ancestor: | ||
1745 | 177 | return ancestor | ||
1746 | 178 | |||
1747 | 179 | ancestor = find_via_build(allfiles, name) | ||
1748 | 180 | |||
1749 | 181 | if ancestor: | ||
1750 | 182 | return ancestor | ||
1751 | 183 | |||
1752 | 184 | ancestor = find_via_release(allfiles, name) | ||
1753 | 185 | |||
1754 | 186 | if ancestor: | ||
1755 | 187 | return ancestor | ||
1756 | 188 | |||
1757 | 189 | return '' | ||
1758 | 190 | |||
1759 | 191 | def main(): | ||
1760 | 192 | allfiles, name = sys.argv[1:] | ||
1761 | 193 | |||
1762 | 194 | with open(allfiles) as f: | ||
1763 | 195 | allf = [x.strip().split(os.sep) for x in f.readlines()] | ||
1764 | 196 | |||
1765 | 197 | print find(allf, name, '') | ||
1766 | 198 | |||
1767 | 199 | def test(): | ||
1768 | 200 | import doctest | ||
1769 | 201 | doctest.testmod() | ||
1770 | 202 | |||
1771 | 203 | if __name__ == '__main__': | ||
1772 | 204 | main() | ||
1773 | 0 | 205 | ||
1774 | === added file 'findlogs.py' | |||
1775 | --- findlogs.py 1970-01-01 00:00:00 +0000 | |||
1776 | +++ findlogs.py 2014-07-01 15:58:40 +0000 | |||
1777 | @@ -0,0 +1,113 @@ | |||
1778 | 1 | #!/usr/bin/python | ||
1779 | 2 | """Given a log file from a build and the build's ancestor, find the | ||
1780 | 3 | corresponding log file for the ancestor. | ||
1781 | 4 | |||
1782 | 5 | Used to find the GCC testsuite results from the ancestor so that they | ||
1783 | 6 | can be compared. | ||
1784 | 7 | |||
1785 | 8 | Example: | ||
1786 | 9 | findlogs.py build/all-files.txt build/gcc-4.6+svn173722/logs/armv7l-maverick-cbuild114-ursa4-cortexa9r1/gcc.sum.xz gcc-4.6+svn173209 | ||
1787 | 10 | "gcc-4.6+svn173209 armv7l-maverick-cbuild113-ursa3-cortexa9r1" | ||
1788 | 11 | |||
1789 | 12 | """ | ||
1790 | 13 | |||
1791 | 14 | import sys | ||
1792 | 15 | import os.path | ||
1793 | 16 | import pprint | ||
1794 | 17 | import re | ||
1795 | 18 | import pdb | ||
1796 | 19 | import logging | ||
1797 | 20 | |||
1798 | 21 | def prefilter(files, contains): | ||
1799 | 22 | # Select those that could be a log | ||
1800 | 23 | files = [x[-4:] for x in files if len(x) >= 4] | ||
1801 | 24 | # ...and those that match the build log | ||
1802 | 25 | files = [x for x in files if contains in x[-1]] | ||
1803 | 26 | |||
1804 | 27 | return files | ||
1805 | 28 | |||
1806 | 29 | def find(allfiles, log, ancestor): | ||
1807 | 30 | logging.debug("FIND: input log %s" % (log)) | ||
1808 | 31 | logging.debug("FIND: input ancestor %s" % (ancestor)) | ||
1809 | 32 | log = log.split('/') | ||
1810 | 33 | arch, osname, cbuild, host, config = log[-2].split('-') | ||
1811 | 34 | |||
1812 | 35 | # Tidy up the ancestor | ||
1813 | 36 | match = re.match('lp\:([^/]+)(/.+)?([+~]\w+\d+)', ancestor) | ||
1814 | 37 | |||
1815 | 38 | if match: | ||
1816 | 39 | branch, series, revision = match.groups() | ||
1817 | 40 | |||
1818 | 41 | if series: | ||
1819 | 42 | series = series[1:] | ||
1820 | 43 | elif branch == 'gcc-linaro': | ||
1821 | 44 | # gcc-linaro has been different series at different | ||
1822 | 45 | # times. Patch. | ||
1823 | 46 | match = re.match('\+bzr(\d+)', revision) | ||
1824 | 47 | |||
1825 | 48 | if match: | ||
1826 | 49 | revno = int(match.group(1)) | ||
1827 | 50 | if revno < 100000: | ||
1828 | 51 | series = '4.5' | ||
1829 | 52 | elif revno < 110000: | ||
1830 | 53 | series = '4.6' | ||
1831 | 54 | elif revno < 121996: | ||
1832 | 55 | series = '4.7' | ||
1833 | 56 | else: | ||
1834 | 57 | series = '4.8' | ||
1835 | 58 | |||
1836 | 59 | logging.debug("FIND: ancestor has branch %s series %s" % (branch, series)) | ||
1837 | 60 | |||
1838 | 61 | elif branch == 'gcc': | ||
1839 | 62 | # gcc is the same as gcc/4.8 | ||
1840 | 63 | match = re.match('\+bzr(\d+)', revision) | ||
1841 | 64 | |||
1842 | 65 | if match: | ||
1843 | 66 | revno = int(match.group(1)) | ||
1844 | 67 | if revno < 120000: | ||
1845 | 68 | series = '4.7' | ||
1846 | 69 | else: | ||
1847 | 70 | series = '4.8' | ||
1848 | 71 | else: | ||
1849 | 72 | assert False, 'Unrecognised development focus for %s' % branch | ||
1850 | 73 | |||
1851 | 74 | ancestor = '%s-%s%s' % (branch, series, revision) | ||
1852 | 75 | logging.debug("FIND: updated ancestor to %s" % (ancestor)) | ||
1853 | 76 | |||
1854 | 77 | # Select those that could be a log | ||
1855 | 78 | files = [x[-4:] for x in allfiles if len(x) >= 4] | ||
1856 | 79 | |||
1857 | 80 | # Select results from the ancestor | ||
1858 | 81 | files = [x for x in files if x[-4] == ancestor] | ||
1859 | 82 | # ...and those that match the build log | ||
1860 | 83 | files = [x for x in files if x[-1] == log[-1]] | ||
1861 | 84 | |||
1862 | 85 | # Split out the build ID | ||
1863 | 86 | for f in files: | ||
1864 | 87 | f[-2] = (f[-2].split('-') + ['']*5)[:5] | ||
1865 | 88 | |||
1866 | 89 | # ...and that have the same architecture, config, and os | ||
1867 | 90 | files = [x for x in files if x[-2][0] == arch and x[-2][-1] == config and x[-2][1] == osname] | ||
1868 | 91 | |||
1869 | 92 | # Sort by cbuild number | ||
1870 | 93 | files.sort(key=lambda x: int(x[-2][2].replace('cbuild', ''))) | ||
1871 | 94 | |||
1872 | 95 | if files: | ||
1873 | 96 | best = files[-1] | ||
1874 | 97 | return (best[0], '-'.join(best[2])) | ||
1875 | 98 | else: | ||
1876 | 99 | return None | ||
1877 | 100 | |||
1878 | 101 | def main(): | ||
1879 | 102 | allfiles, log, ancestor = sys.argv[1:] | ||
1880 | 103 | |||
1881 | 104 | with open(allfiles) as f: | ||
1882 | 105 | allf = [x.strip().split(os.sep) for x in f.readlines()] | ||
1883 | 106 | |||
1884 | 107 | best = find(allf, log, ancestor) | ||
1885 | 108 | |||
1886 | 109 | if best: | ||
1887 | 110 | print ' '.join(best) | ||
1888 | 111 | |||
1889 | 112 | if __name__ == '__main__': | ||
1890 | 113 | main() | ||
1891 | 0 | 114 | ||
1892 | === added file 'gcc-release.sh' | |||
1893 | --- gcc-release.sh 1970-01-01 00:00:00 +0000 | |||
1894 | +++ gcc-release.sh 2014-07-01 15:58:40 +0000 | |||
1895 | @@ -0,0 +1,168 @@ | |||
1896 | 1 | #!/bin/bash | ||
1897 | 2 | # | ||
1898 | 3 | # Run the steps in the GCC release process | ||
1899 | 4 | # | ||
1900 | 5 | # gcc-release.sh lp:gcc-linaro/4.7 [respin] | ||
1901 | 6 | # | ||
1902 | 7 | |||
1903 | 8 | set -e | ||
1904 | 9 | |||
1905 | 10 | branch=$1 | ||
1906 | 11 | [ -z "$branch" ] && echo 'Missing branch name' && exit -1 | ||
1907 | 12 | |||
1908 | 13 | if [ -n "$2" ]; then | ||
1909 | 14 | respin=-$2 | ||
1910 | 15 | nextspin=$(($2 + 1)) | ||
1911 | 16 | else | ||
1912 | 17 | respin= | ||
1913 | 18 | nextspin=1 | ||
1914 | 19 | fi | ||
1915 | 20 | |||
1916 | 21 | # Pull the author and email from bzr whoami | ||
1917 | 22 | me=$( bzr whoami ) | ||
1918 | 23 | fullname=$( echo "$me" | awk -F\< '{print $1;}' | sed 's# *$##' ) | ||
1919 | 24 | email=$( echo "$me" | awk -F\< '{print $2;}' | tr -d \> ) | ||
1920 | 25 | |||
1921 | 26 | year=$( date +%Y ) | ||
1922 | 27 | month=$( date +%m ) | ||
1923 | 28 | day=$( date +%d ) | ||
1924 | 29 | |||
1925 | 30 | series=$( echo $branch | sed -r "s#.+/(.+)#\1#" ) | ||
1926 | 31 | # Die if the series can't be found in the branch name | ||
1927 | 32 | [ -n "$series" ] | ||
1928 | 33 | |||
1929 | 34 | # For testing: | ||
1930 | 35 | # Stack on top of a local branch to cut the branch time | ||
1931 | 36 | #stacked=--stacked | ||
1932 | 37 | # Override the month | ||
1933 | 38 | #month=07 | ||
1934 | 39 | |||
1935 | 40 | # Use ~/.ssh/config to set up the validation lab bounce host | ||
1936 | 41 | host=cbuild@toolchain64.lab | ||
1937 | 42 | snapshots="~/var/snapshots" | ||
1938 | 43 | |||
1939 | 44 | release=$year.$month$respin | ||
1940 | 45 | |||
1941 | 46 | mkdir -p release/$series-$release | ||
1942 | 47 | cd release/$series-$release | ||
1943 | 48 | ln -sf ~/linaro/gcc/.bzr | ||
1944 | 49 | |||
1945 | 50 | # Create a new branch if needed | ||
1946 | 51 | if [ ! -d tree/.bzr ]; then | ||
1947 | 52 | echo "Branching $branch" | ||
1948 | 53 | bzr branch $stacked $branch tree | ||
1949 | 54 | fi | ||
1950 | 55 | |||
1951 | 56 | # Add the release ChangeLog entry and bump the version | ||
1952 | 57 | if ! head -n 50 tree/ChangeLog.linaro | grep -q "GCC Linaro $series-$release released"; then | ||
1953 | 58 | echo "Adding release entry to the ChangeLog" | ||
1954 | 59 | cat > message <<EOF | ||
1955 | 60 | $year-$month-$day $fullname <$email> | ||
1956 | 61 | |||
1957 | 62 | GCC Linaro $series-$release released. | ||
1958 | 63 | |||
1959 | 64 | gcc/ | ||
1960 | 65 | * LINARO-VERSION: Update. | ||
1961 | 66 | |||
1962 | 67 | EOF | ||
1963 | 68 | cat message tree/ChangeLog.linaro > tmp | ||
1964 | 69 | mv tmp tree/ChangeLog.linaro | ||
1965 | 70 | |||
1966 | 71 | echo $series-$release > tree/gcc/LINARO-VERSION | ||
1967 | 72 | |||
1968 | 73 | echo "Tagging and committing" | ||
1969 | 74 | bzr commit -m "Make $series-$release release." tree | ||
1970 | 75 | bzr tag -d tree gcc-linaro-$series-$release | ||
1971 | 76 | fi | ||
1972 | 77 | |||
1973 | 78 | work=gcc-linaro-$series-$release | ||
1974 | 79 | |||
1975 | 80 | if [ ! -d $work ]; then | ||
1976 | 81 | echo "Exporting" | ||
1977 | 82 | bzr export $work.tmp tree | ||
1978 | 83 | mv $work.tmp $work | ||
1979 | 84 | fi | ||
1980 | 85 | |||
1981 | 86 | cd $work | ||
1982 | 87 | |||
1983 | 88 | # Update the manuals | ||
1984 | 89 | env SOURCEDIR=`pwd`/gcc/doc DESTDIR=`pwd`/INSTALL ./gcc/doc/install.texi2html | ||
1985 | 90 | |||
1986 | 91 | # Build the tree and translations | ||
1987 | 92 | if [ ! -d ../objdir/gcc/po ]; then | ||
1988 | 93 | echo "Building" | ||
1989 | 94 | ./contrib/gcc_build -d `pwd` -o ../objdir -c "--enable-generated-files-in-srcdir --disable-multilib" -m \-sj4 build > ../build.txt 2>&1 | ||
1990 | 95 | fi | ||
1991 | 96 | |||
1992 | 97 | # Copy the translations across | ||
1993 | 98 | cp -uv ../objdir/gcc/po/*.gmo gcc/po/ | ||
1994 | 99 | |||
1995 | 100 | # Make the md5sums | ||
1996 | 101 | if [ ! -f MD5SUMS ]; then | ||
1997 | 102 | echo "Making MD5SUMS" | ||
1998 | 103 | cat > MD5SUMS <<EOF | ||
1999 | 104 | # This file contains the MD5 checksums of the files in the | ||
2000 | 105 | # $work.tar.bz2 tarball. | ||
2001 | 106 | # | ||
2002 | 107 | # Besides verifying that all files in the tarball were correctly expanded, | ||
2003 | 108 | # it also can be used to determine if any files have changed since the | ||
2004 | 109 | # tarball was expanded or to verify that a patchfile was correctly applied. | ||
2005 | 110 | # | ||
2006 | 111 | # Suggested usage: | ||
2007 | 112 | # md5sum -c MD5SUMS | grep -v "OK\$" | ||
2008 | 113 | EOF | ||
2009 | 114 | find . -type f | sed -e 's:^\./::' -e '/MD5SUMS/d' | sort | xargs md5sum >> MD5SUMS | ||
2010 | 115 | fi | ||
2011 | 116 | |||
2012 | 117 | cd .. | ||
2013 | 118 | |||
2014 | 119 | next=$series-$release-$nextspin~dev | ||
2015 | 120 | |||
2016 | 121 | # Bump the version | ||
2017 | 122 | if ! grep -q $next tree/gcc/LINARO-VERSION; then | ||
2018 | 123 | cat > message <<EOF | ||
2019 | 124 | $year-$month-$day $fullname <$email> | ||
2020 | 125 | |||
2021 | 126 | gcc/ | ||
2022 | 127 | * LINARO-VERSION: Bump version. | ||
2023 | 128 | |||
2024 | 129 | EOF | ||
2025 | 130 | cat message tree/ChangeLog.linaro > tmp | ||
2026 | 131 | mv tmp tree/ChangeLog.linaro | ||
2027 | 132 | |||
2028 | 133 | echo $next > tree/gcc/LINARO-VERSION | ||
2029 | 134 | bzr commit -m "Bump version number, post release." tree | ||
2030 | 135 | fi | ||
2031 | 136 | |||
2032 | 137 | # Tar it up | ||
2033 | 138 | if [ ! -f $work.tar.bz2 ]; then | ||
2034 | 139 | # Check for bad files | ||
2035 | 140 | for ext in .orig .rej "~" .svn .bzr; do | ||
2036 | 141 | if [ -n "$(find $work -name *$ext)" ]; then | ||
2037 | 142 | echo "Found $ext files in the tarball" | ||
2038 | 143 | exit -2 | ||
2039 | 144 | fi | ||
2040 | 145 | done | ||
2041 | 146 | |||
2042 | 147 | echo "Making tarball" | ||
2043 | 148 | tar cf $work.tar $work | ||
2044 | 149 | bzip2 -9 $work.tar | ||
2045 | 150 | fi | ||
2046 | 151 | |||
2047 | 152 | # Only sign on the build infrastructure | ||
2048 | 153 | if [ ! -f $work.tar.bz2.asc ]; then | ||
2049 | 154 | read -p "Upload the tarball to snapshots and sign (y/n)? " | ||
2050 | 155 | |||
2051 | 156 | if [ "$REPLY" = "y" ]; then | ||
2052 | 157 | echo "Pushing to snapshots" | ||
2053 | 158 | rsync --progress -a $work.tar.bz2 "$host:$snapshots" | ||
2054 | 159 | # Password is the EEMBC password on https://wiki.linaro.org/Internal/ToolChain | ||
2055 | 160 | ssh -t $host gpg --no-use-agent -q --yes --passphrase-file /home/cbuild/.config/cbuild/password --armor --sign --detach-sig --default-key cbuild "$snapshots/$work.tar.bz2" | ||
2056 | 161 | # Pull the signature back down and check | ||
2057 | 162 | rsync -a "$host:$snapshots/$work*asc" . | ||
2058 | 163 | gpg -q --verify $work.tar.bz2.asc | ||
2059 | 164 | fi | ||
2060 | 165 | fi | ||
2061 | 166 | |||
2062 | 167 | echo "Done. Results are in $(pwd). Spawn at http://ex.seabright.co.nz/helpers/scheduler/spawn." | ||
2063 | 168 | echo "Don't forget to push!" | ||
2064 | 0 | 169 | ||
2065 | === added file 'getbody.py' | |||
2066 | --- getbody.py 1970-01-01 00:00:00 +0000 | |||
2067 | +++ getbody.py 2014-07-01 15:58:40 +0000 | |||
2068 | @@ -0,0 +1,26 @@ | |||
2069 | 1 | #!/usr/bin/python | ||
2070 | 2 | """Extracts the body of a GCC contrib/test_summary email by extracting | ||
2071 | 3 | the lines between a cat <<'EOF' and the EOF. | ||
2072 | 4 | """ | ||
2073 | 5 | |||
2074 | 6 | import fileinput | ||
2075 | 7 | import re | ||
2076 | 8 | |||
2077 | 9 | def main(): | ||
2078 | 10 | lines = iter([x.rstrip() for x in fileinput.input()]) | ||
2079 | 11 | |||
2080 | 12 | while True: | ||
2081 | 13 | line = lines.next() | ||
2082 | 14 | if re.match('cat\s*<<', line): | ||
2083 | 15 | break | ||
2084 | 16 | |||
2085 | 17 | while True: | ||
2086 | 18 | line = lines.next() | ||
2087 | 19 | |||
2088 | 20 | if re.match('EOF', line): | ||
2089 | 21 | break | ||
2090 | 22 | else: | ||
2091 | 23 | print line | ||
2092 | 24 | |||
2093 | 25 | if __name__ == '__main__': | ||
2094 | 26 | main() | ||
2095 | 0 | 27 | ||
2096 | === added file 'lab-pull.sh' | |||
2097 | --- lab-pull.sh 1970-01-01 00:00:00 +0000 | |||
2098 | +++ lab-pull.sh 2014-07-01 15:58:40 +0000 | |||
2099 | @@ -0,0 +1,22 @@ | |||
2100 | 1 | #!/bin/bash | ||
2101 | 2 | # | ||
2102 | 3 | # Pull results from the lab into this server | ||
2103 | 4 | # | ||
2104 | 5 | |||
2105 | 6 | dir=$HOME/incoming/validation | ||
2106 | 7 | www=/var/www/ex.seabright.co.nz | ||
2107 | 8 | |||
2108 | 9 | mkdir -p $dir | ||
2109 | 10 | |||
2110 | 11 | for j in build benchmarks; do | ||
2111 | 12 | # Fetch everything | ||
2112 | 13 | timeout 600 rsync -e "ssh -C" -itr "control.v:~/cbuild/$j/*/*-logs.*" $dir/$j | ||
2113 | 14 | |||
2114 | 15 | # Extract those that are new | ||
2115 | 16 | cd $www | ||
2116 | 17 | |||
2117 | 18 | for i in $dir/$j/*-logs*.xz; do | ||
2118 | 19 | if [ $i.done -nt $i ]; then continue; fi | ||
2119 | 20 | tar xaf $i && touch $i.done | ||
2120 | 21 | done | ||
2121 | 22 | done | ||
2122 | 0 | 23 | ||
2123 | === added file 'latestami.sh' | |||
2124 | --- latestami.sh 1970-01-01 00:00:00 +0000 | |||
2125 | +++ latestami.sh 2014-07-01 15:58:40 +0000 | |||
2126 | @@ -0,0 +1,17 @@ | |||
2127 | 1 | #!/bin/bash | ||
2128 | 2 | # | ||
2129 | 3 | # Get the AMI of the latest release of a series | ||
2130 | 4 | # | ||
2131 | 5 | |||
2132 | 6 | distro=${1:-precise} | ||
2133 | 7 | arch=${2:-amd64} | ||
2134 | 8 | region=us-east-1 | ||
2135 | 9 | storage=ebs | ||
2136 | 10 | |||
2137 | 11 | wget -q -O - https://cloud-images.ubuntu.com/query/$distro/server/released.current.txt \ | ||
2138 | 12 | | grep $region \ | ||
2139 | 13 | | grep $arch \ | ||
2140 | 14 | | grep $storage \ | ||
2141 | 15 | | grep -v hvm \ | ||
2142 | 16 | | awk '{ print $8; }' | ||
2143 | 17 | |||
2144 | 0 | 18 | ||
2145 | === added file 'launcher.sh' | |||
2146 | --- launcher.sh 1970-01-01 00:00:00 +0000 | |||
2147 | +++ launcher.sh 2014-07-01 15:58:40 +0000 | |||
2148 | @@ -0,0 +1,146 @@ | |||
2149 | 1 | #!/bin/bash | ||
2150 | 2 | # | ||
2151 | 3 | # Takes all incoming events and launches them. Done as one large | ||
2152 | 4 | # script to keep everything together and remove contention and locking | ||
2153 | 5 | # issues. | ||
2154 | 6 | # | ||
2155 | 7 | |||
2156 | 8 | . ~/.config/cbuild/toolsrc | ||
2157 | 9 | |||
2158 | 10 | # Use run=echo to test | ||
2159 | 11 | run= | ||
2160 | 12 | |||
2161 | 13 | #set -e | ||
2162 | 14 | |||
2163 | 15 | # Pull in the local configuration | ||
2164 | 16 | hostrc=$( dirname $0 )/launcher-$( hostname ).rc | ||
2165 | 17 | [ -f $hostrc ] && . $hostrc | ||
2166 | 18 | |||
2167 | 19 | function remove_old_jobs { | ||
2168 | 20 | # Nuke any daily jobs early | ||
2169 | 21 | $run find $scheduler -name "gcc-4.*svn*.job" -mtime +5 -exec rm -f {} \; | ||
2170 | 22 | # Nuke any old jobs | ||
2171 | 23 | $run find $scheduler -name "*.job" -mtime +14 -exec rm -f {} \; | ||
2172 | 24 | # Nuke any old locks | ||
2173 | 25 | $run find $scheduler -name "*.job.*" -mtime +20 -exec rm -f {} \; | ||
2174 | 26 | } | ||
2175 | 27 | |||
2176 | 28 | function daily { | ||
2177 | 29 | remove_old_jobs | ||
2178 | 30 | # Pull the active trunk branches once a day | ||
2179 | 31 | PRIORITY=daily $run $ctools/up_branch.sh $repos/gcc-trunk gcc-4.8~ | ||
2180 | 32 | PRIORITY=daily $run $ctools/up_branch.sh $repos/gcc-4.7 gcc-4.7+ | ||
2181 | 33 | # Update the md5sums on all snapshots | ||
2182 | 34 | (cd $snapshots && $run rm -f md5sums && $run md5sum *z* > md5sums) | ||
2183 | 35 | # Remove older files from S3 | ||
2184 | 36 | $run python $ctools/s3-diet.py linaro-toolchain-builds | ||
2185 | 37 | # Check for leaking benchmark results | ||
2186 | 38 | $run $ctools/check-leaks.sh | ||
2187 | 39 | # Update the benchmarks graph | ||
2188 | 40 | local pattern="logs/arm*precise*ursa1?-*a9hf*/benchmarks.txt" | ||
2189 | 41 | local diffplot="python $lib/linaro-toolchain-benchmarks/scripts/diffplot.py" | ||
2190 | 42 | (cd $benchmarks \ | ||
2191 | 43 | && $run $diffplot gcc-4.8~svn.png gcc-4.7.0/$pattern gcc-4.8~svn??????/$pattern \ | ||
2192 | 44 | && $run $diffplot gcc-linaro-4.7.png gcc-4.7.0/$pattern gcc-linaro-4.7-201?.??/$pattern \ | ||
2193 | 45 | && $run $diffplot gcc-linaro-4.7+bzr.png gcc-linaro-4.7+bzr??????/$pattern \ | ||
2194 | 46 | ) | ||
2195 | 47 | } | ||
2196 | 48 | |||
2197 | 49 | function build_many { | ||
2198 | 50 | # Build a range of branches | ||
2199 | 51 | local dow=$1 | ||
2200 | 52 | |||
2201 | 53 | case $dow in | ||
2202 | 54 | 1) | ||
2203 | 55 | # Benchmark the latest tip build | ||
2204 | 56 | $run $ctools/chain.sh benchmarks "gcc-linaro-4.7+bzr??????" | ||
2205 | 57 | $run $ctools/chain.sh oecore "gcc-linaro-4.7+bzr??????.*" | ||
2206 | 58 | ;; | ||
2207 | 59 | 2) | ||
2208 | 60 | $run $ctools/export-git.sh $repos/newlib newlib-1.21~ | ||
2209 | 61 | $run $ctools/export-git.sh $repos/qemu-git qemu-1.4~ | ||
2210 | 62 | $run $ctools/up_branch.sh $repos/gcc-arm-embedded-4.6 gcc-arm-embedded-4.6+ | ||
2211 | 63 | $run $ctools/chain.sh ubutest "gcc-4.6+*" | ||
2212 | 64 | ;; | ||
2213 | 65 | 3) | ||
2214 | 66 | # Ensure we get at least one build of trunk a week | ||
2215 | 67 | $run $ctools/chain.sh trunk "gcc-4.8~*" | ||
2216 | 68 | $run $ctools/export-git.sh $repos/openembedded-core openembedded-core-1.4~ | ||
2217 | 69 | $run $ctools/export-git.sh $repos/bitbake bitbake-1.15+ | ||
2218 | 70 | ;; | ||
2219 | 71 | 4) | ||
2220 | 72 | $run $ctools/chain.sh trunk "gcc-4.7+*" | ||
2221 | 73 | $run $ctools/up_branch.sh $repos/gcc-arm-aarch64-4.7 gcc-arm-aaarch64-4.7+ | ||
2222 | 74 | # Many updates for LLVM, only one tarball (no version number) at the end | ||
2223 | 75 | $run $ctools/up_branch.sh $repos/llvm/tools/clang | ||
2224 | 76 | $run $ctools/up_branch.sh $repos/llvm/tools/clang/tools/extra | ||
2225 | 77 | $run $ctools/up_branch.sh $repos/llvm/projects/compiler-rt | ||
2226 | 78 | $run $ctools/up_branch.sh $repos/llvm llvm-svn~ | ||
2227 | 79 | ;; | ||
2228 | 80 | 5) | ||
2229 | 81 | # Benchmark the latest trunk build | ||
2230 | 82 | $run $ctools/chain.sh benchmarks "gcc-4.8~*" | ||
2231 | 83 | # Make sure 4.6 is built once a week | ||
2232 | 84 | $run $ctools/up_branch.sh $repos/gcc-4.6 gcc-4.6+ | ||
2233 | 85 | $run $ctools/up_branch.sh $repos/eglibc/libc eglibc-2.18~ | ||
2234 | 86 | $run $ctools/export-git.sh $repos/libffi libffi-3.1~ | ||
2235 | 87 | ;; | ||
2236 | 88 | 6) | ||
2237 | 89 | $run $ctools/chain.sh ubutest "gcc-4.8~*" | ||
2238 | 90 | # Make sure 4.7 is built once a week | ||
2239 | 91 | $run $ctools/up_branch.sh $repos/gcc-4.7 gcc-4.7+ | ||
2240 | 92 | $run $ctools/export-git.sh $repos/gdb gdb-7.6~ | ||
2241 | 93 | $run $ctools/up_branch.sh $repos/gcc-google-4.7 gcc-google-4.7+ | ||
2242 | 94 | ;; | ||
2243 | 95 | 7) | ||
2244 | 96 | $run $ctools/chain.sh ubutest "gcc-4.7+*" | ||
2245 | 97 | $run $ctools/export-git.sh $repos/binutils binutils-2.24~ | ||
2246 | 98 | ;; | ||
2247 | 99 | esac | ||
2248 | 100 | } | ||
2249 | 101 | |||
2250 | 102 | function dow { | ||
2251 | 103 | local dow=$1 | ||
2252 | 104 | |||
2253 | 105 | build_many $dow | ||
2254 | 106 | |||
2255 | 107 | case $dow in | ||
2256 | 108 | 4) | ||
2257 | 109 | launch weekly | ||
2258 | 110 | ;; | ||
2259 | 111 | esac | ||
2260 | 112 | } | ||
2261 | 113 | |||
2262 | 114 | function weekly { | ||
2263 | 115 | true | ||
2264 | 116 | } | ||
2265 | 117 | |||
2266 | 118 | function often { | ||
2267 | 119 | true | ||
2268 | 120 | } | ||
2269 | 121 | |||
2270 | 122 | function launch { | ||
2271 | 123 | local event=$1 | ||
2272 | 124 | local arg=$2 | ||
2273 | 125 | |||
2274 | 126 | case $event in | ||
2275 | 127 | daily) | ||
2276 | 128 | launch dow $( date +%u ) | ||
2277 | 129 | daily $arg | ||
2278 | 130 | ;; | ||
2279 | 131 | dow) | ||
2280 | 132 | dow $arg | ||
2281 | 133 | ;; | ||
2282 | 134 | weekly) | ||
2283 | 135 | weekly | ||
2284 | 136 | ;; | ||
2285 | 137 | often) | ||
2286 | 138 | often | ||
2287 | 139 | ;; | ||
2288 | 140 | esac | ||
2289 | 141 | } | ||
2290 | 142 | |||
2291 | 143 | event=$1; shift | ||
2292 | 144 | |||
2293 | 145 | echo launcher: running $event on $( date +%u ) | ||
2294 | 146 | launch $event $1 | ||
2295 | 0 | 147 | ||
2296 | === added file 'libec2.sh' | |||
2297 | --- libec2.sh 1970-01-01 00:00:00 +0000 | |||
2298 | +++ libec2.sh 2014-07-01 15:58:40 +0000 | |||
2299 | @@ -0,0 +1,78 @@ | |||
2300 | 1 | # Common functions for spawning and initialising an EC2 instace | ||
2301 | 2 | # | ||
2302 | 3 | |||
2303 | 4 | . ~/.config/cbuild/toolsrc | ||
2304 | 5 | . $lib/cbuild/siterc | ||
2305 | 6 | |||
2306 | 7 | wget="wget --no-proxy -q" | ||
2307 | 8 | this=ec2slave | ||
2308 | 9 | |||
2309 | 10 | hostname=${1:-oort99} | ||
2310 | 11 | ami=${2:-missing-ami} | ||
2311 | 12 | # 64 bit high-CPU | ||
2312 | 13 | type=${3:-c1.xlarge} | ||
2313 | 14 | kill=${kill:-true} | ||
2314 | 15 | |||
2315 | 16 | region=us-east-1 | ||
2316 | 17 | |||
2317 | 18 | lock="flock /tmp/heavy.lock" | ||
2318 | 19 | |||
2319 | 20 | # Bring in any local configuration | ||
2320 | 21 | [ -f ~/.private/$this.rc ] && . ~/.private/$this.rc | ||
2321 | 22 | |||
2322 | 23 | dir=/tmp/$this/$hostname | ||
2323 | 24 | |||
2324 | 25 | function get_state { | ||
2325 | 26 | $lock ec2din --show-empty-fields $instance > $dir/din | ||
2326 | 27 | line=`grep ^INSTANCE $dir/din` | ||
2327 | 28 | state=`echo $line | awk '{ print $6; }'` | ||
2328 | 29 | if [ -f ~/.in-cloud ]; then | ||
2329 | 30 | # Use the local IP | ||
2330 | 31 | ip=`echo $line | awk '{ print $5; }'` | ||
2331 | 32 | else | ||
2332 | 33 | # Use the public IP | ||
2333 | 34 | ip=`echo $line | awk '{ print $4; }'` | ||
2334 | 35 | fi | ||
2335 | 36 | |||
2336 | 37 | echo get_state on $instance: $state $ip | ||
2337 | 38 | } | ||
2338 | 39 | |||
2339 | 40 | function start_instance { | ||
2340 | 41 | $wget -O - $SCHEDULER_API/update/$hostname/starting || true | ||
2341 | 42 | mkdir -p $dir | ||
2342 | 43 | |||
2343 | 44 | $lock ec2run $ami -t $type --region $region -k $key \ | ||
2344 | 45 | --instance-initiated-shutdown-behavior terminate > $dir/run | ||
2345 | 46 | instance=`grep ^INSTANCE $dir/run | awk '{ print $2; }'` | ||
2346 | 47 | |||
2347 | 48 | if [ "$kill" = "true" ]; then trap "$lock ec2kill $instance" EXIT; fi | ||
2348 | 49 | |||
2349 | 50 | get_state | ||
2350 | 51 | |||
2351 | 52 | while [ "$state" != "running" ]; do | ||
2352 | 53 | sleep 5 | ||
2353 | 54 | get_state | ||
2354 | 55 | done | ||
2355 | 56 | |||
2356 | 57 | # Wait for Ubuntu to boot | ||
2357 | 58 | for i in {1..10}; do | ||
2358 | 59 | if ssh -o StrictHostKeyChecking=no ubuntu@$ip true; then break; fi | ||
2359 | 60 | sleep 10 | ||
2360 | 61 | done | ||
2361 | 62 | |||
2362 | 63 | # Test the connection | ||
2363 | 64 | ssh ubuntu@$ip uname -a | ||
2364 | 65 | |||
2365 | 66 | echo Instance $instance started | ||
2366 | 67 | } | ||
2367 | 68 | |||
2368 | 69 | function init_instance { | ||
2369 | 70 | # Do the system wide setup | ||
2370 | 71 | scp $this-init.sh ~/.private/$this-*seed* ubuntu@$ip:~ | ||
2371 | 72 | ssh ubuntu@$ip sudo bash $this-init.sh $hostname | ||
2372 | 73 | # And the user specific | ||
2373 | 74 | scp $this-init-cbuild.sh cbuild@$ip:~ | ||
2374 | 75 | ssh -t cbuild@$ip bash $this-init-cbuild.sh | ||
2375 | 76 | # Copy the site configuration across | ||
2376 | 77 | scp $lib/cbuild/siterc cbuild@$ip:/cbuild | ||
2377 | 78 | } | ||
2378 | 0 | 79 | ||
2379 | === added file 'pull_branch.sh' | |||
2380 | --- pull_branch.sh 1970-01-01 00:00:00 +0000 | |||
2381 | +++ pull_branch.sh 2014-07-01 15:58:40 +0000 | |||
2382 | @@ -0,0 +1,21 @@ | |||
2383 | 1 | #!/bin/sh | ||
2384 | 2 | # Update a branch, snapshot the latest revision, and spawn the jobs | ||
2385 | 3 | |||
2386 | 4 | set -e | ||
2387 | 5 | |||
2388 | 6 | # Directory this script runs from | ||
2389 | 7 | here=`dirname $0` | ||
2390 | 8 | |||
2391 | 9 | # Pull a branch and tarball it up | ||
2392 | 10 | branch=$1 | ||
2393 | 11 | head=$2 | ||
2394 | 12 | |||
2395 | 13 | # Silly bzr... | ||
2396 | 14 | rm -rf $branch/.bzr/checkout/limbo $branch/.bzr/checkout/pending-deletion | ||
2397 | 15 | bzr pull -q --overwrite -d $branch | ||
2398 | 16 | |||
2399 | 17 | stem=`$here/export-bzr.sh $branch $head $3 $4 $5 $6 $7 | grep ^stem: | awk '{print $2;}'` | ||
2400 | 18 | |||
2401 | 19 | if [ "$stem" != "" ]; then | ||
2402 | 20 | $here/spawn.sh $stem | ||
2403 | 21 | fi | ||
2404 | 0 | 22 | ||
2405 | === added file 's3-diet.py' | |||
2406 | --- s3-diet.py 1970-01-01 00:00:00 +0000 | |||
2407 | +++ s3-diet.py 2014-07-01 15:58:40 +0000 | |||
2408 | @@ -0,0 +1,91 @@ | |||
2409 | 1 | #!/usr/bin/env python | ||
2410 | 2 | |||
2411 | 3 | """Put a S3 bucket on a diet by removing old files. Used to delete | ||
2412 | 4 | old builds from the cbuild archive. | ||
2413 | 5 | """ | ||
2414 | 6 | |||
2415 | 7 | import collections | ||
2416 | 8 | import sys | ||
2417 | 9 | import datetime | ||
2418 | 10 | import re | ||
2419 | 11 | import os.path | ||
2420 | 12 | import ConfigParser | ||
2421 | 13 | import logging | ||
2422 | 14 | |||
2423 | 15 | import simples3 | ||
2424 | 16 | import hurry.filesize | ||
2425 | 17 | |||
2426 | 18 | |||
2427 | 19 | Entry = collections.namedtuple('Entry', 'key timestamp etag size basename') | ||
2428 | 20 | |||
2429 | 21 | |||
2430 | 22 | def main(): | ||
2431 | 23 | dry_run = False | ||
2432 | 24 | |||
2433 | 25 | logging.basicConfig(level=logging.INFO) | ||
2434 | 26 | |||
2435 | 27 | config = ConfigParser.SafeConfigParser() | ||
2436 | 28 | config.read(os.path.expanduser('~/.s3cfg')) | ||
2437 | 29 | |||
2438 | 30 | bucket = simples3.S3Bucket(sys.argv[1], | ||
2439 | 31 | access_key=config.get('default', 'access_key'), | ||
2440 | 32 | secret_key=config.get('default', 'secret_key')) | ||
2441 | 33 | |||
2442 | 34 | |||
2443 | 35 | by_key = {} | ||
2444 | 36 | entries = [] | ||
2445 | 37 | |||
2446 | 38 | for v in bucket.listdir(): | ||
2447 | 39 | entry = Entry(*(v + (os.path.basename(v[0]), ))) | ||
2448 | 40 | by_key[entry.key] = entry | ||
2449 | 41 | entries.append(entry) | ||
2450 | 42 | |||
2451 | 43 | # Do some linting | ||
2452 | 44 | to_delete = [] | ||
2453 | 45 | |||
2454 | 46 | # Delete the signature if the original file is gone | ||
2455 | 47 | for entry in entries: | ||
2456 | 48 | if entry.key.endswith('.asc'): | ||
2457 | 49 | original = entry.key.replace('.asc', '') | ||
2458 | 50 | |||
2459 | 51 | if original not in by_key: | ||
2460 | 52 | logging.debug('Deleting orphan signature %s' % entry.basename) | ||
2461 | 53 | to_delete.append(entry) | ||
2462 | 54 | |||
2463 | 55 | # Delete anything that's too old | ||
2464 | 56 | now = datetime.datetime.utcnow() | ||
2465 | 57 | |||
2466 | 58 | for entry in entries: | ||
2467 | 59 | age = now - entry.timestamp | ||
2468 | 60 | |||
2469 | 61 | is_merge = '+bzr' in entry.basename and len(entry.basename.split('~')) == 3 | ||
2470 | 62 | |||
2471 | 63 | if re.search(r'-201.\.\d\d', entry.basename) and '+bzr' not in entry.basename: | ||
2472 | 64 | logging.debug("Not deleting %s as it's special" % entry.basename) | ||
2473 | 65 | elif is_merge and age.days >= 30: | ||
2474 | 66 | logging.debug('Deleting %d day old merge %s' % (age.days, entry.basename)) | ||
2475 | 67 | to_delete.append(entry) | ||
2476 | 68 | elif age.days >= 45: | ||
2477 | 69 | logging.debug('Deleting %d day old %s' % (age.days, entry.basename)) | ||
2478 | 70 | to_delete.append(entry) | ||
2479 | 71 | else: | ||
2480 | 72 | pass | ||
2481 | 73 | |||
2482 | 74 | # Nuke any duplicates | ||
2483 | 75 | to_delete = sorted(set(to_delete)) | ||
2484 | 76 | |||
2485 | 77 | total = sum(x.size for x in entries) | ||
2486 | 78 | deleting = sum(x.size for x in to_delete) | ||
2487 | 79 | |||
2488 | 80 | logging.info('Total stored: %s in %d entries' % (hurry.filesize.size(total), len(entries))) | ||
2489 | 81 | logging.info('To delete: %s in %d entries' % (hurry.filesize.size(deleting), len(to_delete))) | ||
2490 | 82 | |||
2491 | 83 | for entry in sorted(to_delete, key=lambda x: -x.size): | ||
2492 | 84 | logging.info('Deleting %s' % entry.basename) | ||
2493 | 85 | |||
2494 | 86 | if not dry_run: | ||
2495 | 87 | del bucket[entry.key] | ||
2496 | 88 | |||
2497 | 89 | if __name__ == '__main__': | ||
2498 | 90 | main() | ||
2499 | 91 | |||
2500 | 0 | 92 | ||
2501 | === added file 'spawn.sh' | |||
2502 | --- spawn.sh 1970-01-01 00:00:00 +0000 | |||
2503 | +++ spawn.sh 2014-07-01 15:58:40 +0000 | |||
2504 | @@ -0,0 +1,36 @@ | |||
2505 | 1 | #/bin/bash | ||
2506 | 2 | # | ||
2507 | 3 | # Spawn a job based on the queues | ||
2508 | 4 | # | ||
2509 | 5 | # Examples: | ||
2510 | 6 | # spawn gcc-4.5+svn12345 | ||
2511 | 7 | # spawn.sh ~/path/to/thing-to-build.tar.xz | ||
2512 | 8 | # spawn.sh ~/path/to/thing-to-build.tar.xz queue-name | ||
2513 | 9 | # | ||
2514 | 10 | |||
2515 | 11 | set -e | ||
2516 | 12 | |||
2517 | 13 | . ~/.config/cbuild/toolsrc | ||
2518 | 14 | |||
2519 | 15 | # Directory this script runs from | ||
2520 | 16 | here=`dirname $0` | ||
2521 | 17 | |||
2522 | 18 | job=$1 | ||
2523 | 19 | |||
2524 | 20 | priority=${PRIORITY:-.} | ||
2525 | 21 | |||
2526 | 22 | # Tidy up job so that you can also supply a path | ||
2527 | 23 | job=`basename $job` | ||
2528 | 24 | job=`echo $job | sed -r 's/(.+)\.tar.*/\1/'` | ||
2529 | 25 | |||
2530 | 26 | queue=${2:-$job} | ||
2531 | 27 | closest=$($here/closest.py $queue $scheduler/spawn/$priority/*) | ||
2532 | 28 | |||
2533 | 29 | echo Spawning $job into the queue `basename $closest` | ||
2534 | 30 | |||
2535 | 31 | # "Demux" via spawn queue into real job queues, use tcwg-web's schedulejob.py | ||
2536 | 32 | # script for scheduling jobs with LAVA support, etc. | ||
2537 | 33 | for i in $closest/*; do | ||
2538 | 34 | PYTHONPATH=$lib/tcwg-web python -m schedulejob `basename $i` $job | ||
2539 | 35 | echo Spawned into `basename $i` | ||
2540 | 36 | done | ||
2541 | 0 | 37 | ||
2542 | === added file 'stamp_branch.sh' | |||
2543 | --- stamp_branch.sh 1970-01-01 00:00:00 +0000 | |||
2544 | +++ stamp_branch.sh 2014-07-01 15:58:40 +0000 | |||
2545 | @@ -0,0 +1,70 @@ | |||
2546 | 1 | #!/bin/bash | ||
2547 | 2 | repo=$1 | ||
2548 | 3 | into=$2 | ||
2549 | 4 | |||
2550 | 5 | # Check for known version control systems. | ||
2551 | 6 | if [ -d $repo/.bzr ]; then | ||
2552 | 7 | GCC_GIT=${GCC_BZR-${BZR-bzr}} | ||
2553 | 8 | vcs_type="bzr" | ||
2554 | 9 | elif [ -d $repo/.svn ]; then | ||
2555 | 10 | GCC_SVN=${GCC_SVN-${SVN-svn}} | ||
2556 | 11 | vcs_type="svn" | ||
2557 | 12 | else | ||
2558 | 13 | echo "This does not seem to be a GCC GIT/Bzr tree!" | ||
2559 | 14 | exit | ||
2560 | 15 | fi | ||
2561 | 16 | |||
2562 | 17 | rm -f $into/LAST_UPDATED $into/gcc/REVISION | ||
2563 | 18 | |||
2564 | 19 | case $vcs_type in | ||
2565 | 20 | svn) | ||
2566 | 21 | revision=${REVNO:-`svn info $1 | awk '/Revision:/ { print $2 }'`} | ||
2567 | 22 | branch=`svn info $1 | sed -ne "/URL:/ { | ||
2568 | 23 | s,.*/trunk,trunk, | ||
2569 | 24 | s,.*/branches/,, | ||
2570 | 25 | s,.*/tags/,, | ||
2571 | 26 | p | ||
2572 | 27 | }"` | ||
2573 | 28 | ;; | ||
2574 | 29 | |||
2575 | 30 | bzr) | ||
2576 | 31 | revision=${REVNO:-`bzr revno $repo`} | ||
2577 | 32 | parent=`bzr info $repo | gawk '/parent branch/ { print $3; }'` | ||
2578 | 33 | |||
2579 | 34 | # Keep the branch name out of the version to prevent spurious | ||
2580 | 35 | # test failures. | ||
2581 | 36 | # | ||
2582 | 37 | # ...net/%2Bbranch/gcc-linaro/4.7/ becomes gcc-linaro/4.7 | ||
2583 | 38 | # ...net/~michaelh1/gcc-linaro/better-longlong/ becomes gcc-linaro/~michaelh1 | ||
2584 | 39 | # | ||
2585 | 40 | parts=( $(echo $parent | tr '/' '\n' | tac) ) | ||
2586 | 41 | echo ${parts[@]} | ||
2587 | 42 | n3=${parts[0]} | ||
2588 | 43 | n2=${parts[1]} | ||
2589 | 44 | n1=${parts[2]} | ||
2590 | 45 | |||
2591 | 46 | case $n1,$n2,$n3 in | ||
2592 | 47 | *branch,*,*) branch="$n2/$n3" ;; | ||
2593 | 48 | \~*,*,*) branch="$n2/dev" ;; | ||
2594 | 49 | *) branch="$n2" ;; | ||
2595 | 50 | esac | ||
2596 | 51 | ;; | ||
2597 | 52 | esac | ||
2598 | 53 | |||
2599 | 54 | { | ||
2600 | 55 | date | ||
2601 | 56 | echo "`TZ=UTC date` (revision $revision)" | ||
2602 | 57 | } > $into/LAST_UPDATED | ||
2603 | 58 | |||
2604 | 59 | # And the product specific parts | ||
2605 | 60 | |||
2606 | 61 | # GCC | ||
2607 | 62 | if [ -f $into/gcc/version.c ]; then | ||
2608 | 63 | echo "[$branch revision $revision]" > $into/gcc/REVISION | ||
2609 | 64 | fi | ||
2610 | 65 | |||
2611 | 66 | # crosstool-NG | ||
2612 | 67 | if [ -f $into/ct-ng.in ]; then | ||
2613 | 68 | sed -i -r "s#bzr.+#bzr$revision#" $into/version.sh | ||
2614 | 69 | sed -i -r "s#^REVISION\s*=.*#REVISION = +bzr$revision#" $into/contrib/linaro/build.mk | ||
2615 | 70 | fi | ||
2616 | 0 | 71 | ||
2617 | === added file 'tabulate.sh' | |||
2618 | --- tabulate.sh 1970-01-01 00:00:00 +0000 | |||
2619 | +++ tabulate.sh 2014-07-01 15:58:40 +0000 | |||
2620 | @@ -0,0 +1,36 @@ | |||
2621 | 1 | #!/bin/bash | ||
2622 | 2 | # | ||
2623 | 3 | # Tabulate any new benchmark results | ||
2624 | 4 | # | ||
2625 | 5 | |||
2626 | 6 | . ~/.config/cbuild/toolsrc | ||
2627 | 7 | |||
2628 | 8 | tmp=`mktemp -td tabulate.XXXXXXXXXX` | ||
2629 | 9 | trap "rm -rf $tmp" EXIT | ||
2630 | 10 | |||
2631 | 11 | base=${1:-$benchmarks} | ||
2632 | 12 | scripts=${2:-$HOME/lib/linaro-toolchain-benchmarks/scripts} | ||
2633 | 13 | |||
2634 | 14 | tabulate() { | ||
2635 | 15 | filter=$1 | ||
2636 | 16 | suffix=$2 | ||
2637 | 17 | |||
2638 | 18 | name=benchmarks$suffix.txt | ||
2639 | 19 | |||
2640 | 20 | for i in $base/gcc*/logs/*/$filter.txt; do | ||
2641 | 21 | dir=$(dirname $i) | ||
2642 | 22 | |||
2643 | 23 | # Skip if the tabulated version is newer | ||
2644 | 24 | [ ! $i -nt $dir/$name ] && continue | ||
2645 | 25 | |||
2646 | 26 | echo $dir... | ||
2647 | 27 | python $scripts/tabulate.py $dir/$filter.txt > $tmp/$name \ | ||
2648 | 28 | && touch -r $i $tmp/$name \ | ||
2649 | 29 | && mv $tmp/$name $dir | ||
2650 | 30 | done | ||
2651 | 31 | } | ||
2652 | 32 | |||
2653 | 33 | tabulate "*run" "" | ||
2654 | 34 | tabulate "spec2000-*run" "-spec2000" | ||
2655 | 35 | tabulate "eembc-*run" "-eembc" | ||
2656 | 36 | tabulate "eembc_office-*run" "-eembc_office" | ||
2657 | 0 | 37 | ||
2658 | === added file 'taker.json' | |||
2659 | --- taker.json 1970-01-01 00:00:00 +0000 | |||
2660 | +++ taker.json 2014-07-01 15:58:40 +0000 | |||
2661 | @@ -0,0 +1,82 @@ | |||
2662 | 1 | {"build": "http://ex.seabright.co.nz/build/", | ||
2663 | 2 | "instance": "production", | ||
2664 | 3 | "projects": ["gcc-linaro", "gcc", "crosstool-ng", "gdb-linaro"], | ||
2665 | 4 | "prompt": true, | ||
2666 | 5 | |||
2667 | 6 | "hosts": { | ||
2668 | 7 | "crucis": { | ||
2669 | 8 | "dry-run": true, | ||
2670 | 9 | "repos": "/home/michaelh/linaro", | ||
2671 | 10 | "all-files": "build/all-files.txt", | ||
2672 | 11 | "tools": ".", | ||
2673 | 12 | "build": "build" | ||
2674 | 13 | }, | ||
2675 | 14 | "orion": { | ||
2676 | 15 | "repos": "/home/cbuild/repos", | ||
2677 | 16 | "all-files": "/var/www/ex.seabright.co.nz/build/all-files.txt", | ||
2678 | 17 | "tools": "/home/cbuild/lib/cbuild-tools", | ||
2679 | 18 | "build": "/var/www/ex.seabright.co.nz/build" | ||
2680 | 19 | }, | ||
2681 | 20 | "cbuild-master": { | ||
2682 | 21 | "repos": "/home/cbuild/var/repos", | ||
2683 | 22 | "all-files": "/home/cbuild/public_html/build/all-files.txt", | ||
2684 | 23 | "tools": "/home/cbuild/lib/cbuild-tools", | ||
2685 | 24 | "build": "/home/cbuild/public_html/build" | ||
2686 | 25 | }, | ||
2687 | 26 | "toolchain64": { | ||
2688 | 27 | "repos": "/home/cbuild/var/repos", | ||
2689 | 28 | "all-files": "/home/cbuild/public_html/build/all-files.txt", | ||
2690 | 29 | "tools": "/home/cbuild/lib/cbuild-tools", | ||
2691 | 30 | "build": "/home/cbuild/public_html/build" | ||
2692 | 31 | } | ||
2693 | 32 | }, | ||
2694 | 33 | "filters": { | ||
2695 | 34 | "xinclude": ["lp663939"] | ||
2696 | 35 | }, | ||
2697 | 36 | "branches": { | ||
2698 | 37 | "lp:gcc-linaro": { | ||
2699 | 38 | "prefix": "gcc-linaro-4.8", | ||
2700 | 39 | "reporoot": "gcc-linaro-4.8" | ||
2701 | 40 | }, | ||
2702 | 41 | "lp:gcc-linaro/4.5": { | ||
2703 | 42 | "prefix": "gcc-linaro-4.5", | ||
2704 | 43 | "reporoot": "gcc-linaro" | ||
2705 | 44 | }, | ||
2706 | 45 | "lp:gcc-linaro/4.6": { | ||
2707 | 46 | "prefix": "gcc-linaro-4.6", | ||
2708 | 47 | "reporoot": "gcc-linaro" | ||
2709 | 48 | }, | ||
2710 | 49 | "lp:gcc-linaro/4.7": { | ||
2711 | 50 | "prefix": "gcc-linaro-4.7", | ||
2712 | 51 | "reporoot": "gcc-linaro" | ||
2713 | 52 | }, | ||
2714 | 53 | "lp:gcc-linaro/4.8": { | ||
2715 | 54 | "prefix": "gcc-linaro-4.8", | ||
2716 | 55 | "reporoot": "gcc-linaro-4.8" | ||
2717 | 56 | }, | ||
2718 | 57 | "lp:gcc-linaro/4.6-2011.07-stable": { | ||
2719 | 58 | "prefix": "gcc-linaro-4.6-2011.07-stable", | ||
2720 | 59 | "reporoot": "gcc-linaro" | ||
2721 | 60 | }, | ||
2722 | 61 | "lp:gcc-linaro/4.4": { | ||
2723 | 62 | "prefix": "gcc-linaro-4.4", | ||
2724 | 63 | "reporoot": "gcc-linaro" | ||
2725 | 64 | }, | ||
2726 | 65 | "lp:gcc/4.6": { | ||
2727 | 66 | "prefix": "gcc-4.6", | ||
2728 | 67 | "reporoot": "gcc-linaro" | ||
2729 | 68 | }, | ||
2730 | 69 | "lp:gcc": { | ||
2731 | 70 | "prefix": "gcc-4.8", | ||
2732 | 71 | "reporoot": "gcc-bzr" | ||
2733 | 72 | }, | ||
2734 | 73 | "lp:gdb-linaro": { | ||
2735 | 74 | "prefix": "gdb-linaro-7.5", | ||
2736 | 75 | "reporoot": "gdb-linaro" | ||
2737 | 76 | }, | ||
2738 | 77 | "lp:~linaro-toolchain-dev/crosstool-ng/linaro": { | ||
2739 | 78 | "prefix": "crosstool-ng-linaro-1.13.1", | ||
2740 | 79 | "reporoot": "crosstool-ng" | ||
2741 | 80 | } | ||
2742 | 81 | } | ||
2743 | 82 | } | ||
2744 | 0 | 83 | ||
2745 | === added file 'taker.py' | |||
2746 | --- taker.py 1970-01-01 00:00:00 +0000 | |||
2747 | +++ taker.py 2014-07-01 15:58:40 +0000 | |||
2748 | @@ -0,0 +1,396 @@ | |||
2749 | 1 | """Script that monitors merge requests, branches unseen ones, and sets | ||
2750 | 2 | up a build. | ||
2751 | 3 | """ | ||
2752 | 4 | |||
2753 | 5 | import os | ||
2754 | 6 | import os.path | ||
2755 | 7 | import re | ||
2756 | 8 | import subprocess | ||
2757 | 9 | import json | ||
2758 | 10 | import socket | ||
2759 | 11 | import datetime | ||
2760 | 12 | import logging | ||
2761 | 13 | import getopt | ||
2762 | 14 | import sys | ||
2763 | 15 | import pprint | ||
2764 | 16 | import pdb | ||
2765 | 17 | import StringIO | ||
2766 | 18 | import findlogs | ||
2767 | 19 | |||
2768 | 20 | import launchpadlib.launchpad | ||
2769 | 21 | |||
2770 | 22 | # Message sent when a merge request is snapshotted and queued for build | ||
2771 | 23 | QUEUED = { | ||
2772 | 24 | 'subject': "[cbuild] Queued %(snapshot)s for build", | ||
2773 | 25 | 'body': """ | ||
2774 | 26 | cbuild has taken a snapshot of this branch at r%(revno)s and queued it for build. | ||
2775 | 27 | |||
2776 | 28 | The diff against the ancestor r%(ancestor)s is available at: | ||
2777 | 29 | http://cbuild.validation.linaro.org/snapshots/%(snapshot)s.diff | ||
2778 | 30 | |||
2779 | 31 | and will be built on the following builders: | ||
2780 | 32 | %(builders)s | ||
2781 | 33 | |||
2782 | 34 | You can track the build queue at: | ||
2783 | 35 | http://cbuild.validation.linaro.org/helpers/scheduler | ||
2784 | 36 | |||
2785 | 37 | cbuild-snapshot: %(snapshot)s | ||
2786 | 38 | cbuild-ancestor: %(target)s+bzr%(ancestor)s | ||
2787 | 39 | cbuild-state: check | ||
2788 | 40 | """ | ||
2789 | 41 | } | ||
2790 | 42 | |||
2791 | 43 | # Message sent when a individual build completes | ||
2792 | 44 | CHECK_OK = { | ||
2793 | 45 | 'subject': "[cbuild] Build OK for %(snapshot)s on %(build)s", | ||
2794 | 46 | 'body': """ | ||
2795 | 47 | cbuild successfully built this on %(build)s. | ||
2796 | 48 | |||
2797 | 49 | The build results are available at: | ||
2798 | 50 | http://cbuild.validation.linaro.org/build/%(snapshot)s/logs/%(build)s | ||
2799 | 51 | |||
2800 | 52 | %(diff)s | ||
2801 | 53 | |||
2802 | 54 | The full testsuite results are at: | ||
2803 | 55 | http://cbuild.validation.linaro.org/build/%(snapshot)s/logs/%(build)s/gcc-testsuite.txt | ||
2804 | 56 | |||
2805 | 57 | cbuild-checked: %(build)s | ||
2806 | 58 | """ | ||
2807 | 59 | } | ||
2808 | 60 | |||
2809 | 61 | # Message sent when a individual build fails | ||
2810 | 62 | CHECK_FAILED = { | ||
2811 | 63 | 'subject': "[cbuild] Build failed for %(snapshot)s on %(build)s", | ||
2812 | 64 | 'body': """ | ||
2813 | 65 | cbuild had trouble building this on %(build)s. | ||
2814 | 66 | See the following failure logs: | ||
2815 | 67 | %(logs)s | ||
2816 | 68 | |||
2817 | 69 | under the build results at: | ||
2818 | 70 | http://cbuild.validation.linaro.org/build/%(snapshot)s/logs/%(build)s | ||
2819 | 71 | |||
2820 | 72 | %(diff)s | ||
2821 | 73 | |||
2822 | 74 | cbuild-checked: %(build)s | ||
2823 | 75 | """, | ||
2824 | 76 | 'vote': 'Needs Fixing', | ||
2825 | 77 | 'nice': False | ||
2826 | 78 | } | ||
2827 | 79 | |||
2828 | 80 | CONFIG = json.load(open('taker.json')) | ||
2829 | 81 | |||
2830 | 82 | def run(cmd, cwd=None, const=False): | ||
2831 | 83 | logging.debug('Executing "%s" (cwd=%s)' % (' '.join(cmd), cwd)) | ||
2832 | 84 | |||
2833 | 85 | if const or not get_config2(False, 'dry-run'): | ||
2834 | 86 | child = subprocess.Popen(cmd, cwd=cwd, stdout=subprocess.PIPE) | ||
2835 | 87 | stdout, stderr = child.communicate() | ||
2836 | 88 | retcode = child.wait() | ||
2837 | 89 | |||
2838 | 90 | if retcode: | ||
2839 | 91 | raise Exception('Child process returned %s' % retcode) | ||
2840 | 92 | |||
2841 | 93 | lines = [x.rstrip() for x in StringIO.StringIO(stdout).readlines()] | ||
2842 | 94 | logging.debug('Stdout: %r' % lines[:20]) | ||
2843 | 95 | |||
2844 | 96 | return lines | ||
2845 | 97 | else: | ||
2846 | 98 | return [] | ||
2847 | 99 | |||
2848 | 100 | def tidy_branch(v): | ||
2849 | 101 | """Tidy up a branch name from one of the staging servers to the | ||
2850 | 102 | top level server. | ||
2851 | 103 | """ | ||
2852 | 104 | return v.replace('lp://qastaging/', 'lp:') | ||
2853 | 105 | |||
2854 | 106 | def get_config_raw(v): | ||
2855 | 107 | at = CONFIG | ||
2856 | 108 | |||
2857 | 109 | for name in v.split('!'): | ||
2858 | 110 | at = at[name] | ||
2859 | 111 | |||
2860 | 112 | return at | ||
2861 | 113 | |||
2862 | 114 | def get_config(*args): | ||
2863 | 115 | v = '!'.join(args) | ||
2864 | 116 | |||
2865 | 117 | # See if the value exists in the hosts override first | ||
2866 | 118 | try: | ||
2867 | 119 | return get_config_raw('hosts!%s!%s' % (socket.gethostname(), v)) | ||
2868 | 120 | except KeyError: | ||
2869 | 121 | return get_config_raw(v) | ||
2870 | 122 | |||
2871 | 123 | def get_config2(default, *args): | ||
2872 | 124 | """Get a configuration value, falling back to the default if not set.""" | ||
2873 | 125 | try: | ||
2874 | 126 | return get_config(*args) | ||
2875 | 127 | except KeyError: | ||
2876 | 128 | return default | ||
2877 | 129 | |||
2878 | 130 | class Proposal: | ||
2879 | 131 | def __init__(self, proposal): | ||
2880 | 132 | self.proposal = proposal | ||
2881 | 133 | self.parse(proposal) | ||
2882 | 134 | |||
2883 | 135 | def parse(self, proposal): | ||
2884 | 136 | """Parse the proposal by scanning all comments for | ||
2885 | 137 | 'cbuild-foo: bar' tokens. Pull these into member variables. | ||
2886 | 138 | """ | ||
2887 | 139 | self.state = None | ||
2888 | 140 | self.ancestor = None | ||
2889 | 141 | self.checked = [] | ||
2890 | 142 | |||
2891 | 143 | for comment in proposal.all_comments: | ||
2892 | 144 | lines = [x.strip() for x in comment.message_body.split('\n')] | ||
2893 | 145 | |||
2894 | 146 | for line in lines: | ||
2895 | 147 | match = re.match('cbuild-(\w+):\s+(\S+)', line) | ||
2896 | 148 | |||
2897 | 149 | if match: | ||
2898 | 150 | name, value = match.groups() | ||
2899 | 151 | |||
2900 | 152 | if name in ['checked']: | ||
2901 | 153 | getattr(self, name).append(value) | ||
2902 | 154 | else: | ||
2903 | 155 | setattr(self, name, value) | ||
2904 | 156 | |||
2905 | 157 | def add_comment(proposal, template, **kwargs): | ||
2906 | 158 | """Add a comment using the given template for the subject and | ||
2907 | 159 | body text. | ||
2908 | 160 | """ | ||
2909 | 161 | vote = template.get('vote', None) | ||
2910 | 162 | # True if this is a 'happy' result. Used in debugging to | ||
2911 | 163 | # prevent unreversable results from going up to Launchpad. | ||
2912 | 164 | nice = template.get('nice', True) | ||
2913 | 165 | |||
2914 | 166 | subject = (template['subject'] % kwargs).rstrip() | ||
2915 | 167 | body = (template['body'] % kwargs).rstrip() | ||
2916 | 168 | |||
2917 | 169 | just_print = get_config2(False, 'dry-run') | ||
2918 | 170 | |||
2919 | 171 | if not nice and get_config2(True, 'cautious'): | ||
2920 | 172 | # Running in a debug/test mode. Don't push unreversable | ||
2921 | 173 | # results. | ||
2922 | 174 | just_print = True | ||
2923 | 175 | |||
2924 | 176 | if get_config2(False, 'prompt'): | ||
2925 | 177 | logging.info("Want to add this comment: %s\n%s\n\nVote: %s\n" % (subject, body, vote)) | ||
2926 | 178 | |||
2927 | 179 | if just_print: | ||
2928 | 180 | got = raw_input('Add it anyway? > ') | ||
2929 | 181 | else: | ||
2930 | 182 | got = raw_input('OK to add? > ') | ||
2931 | 183 | |||
2932 | 184 | just_print = got.strip() not in ['Y', 'y'] | ||
2933 | 185 | |||
2934 | 186 | if just_print: | ||
2935 | 187 | logging.info("Would have added this comment: %s\n%s\n\nVote: %s\n" % (subject, body, vote)) | ||
2936 | 188 | else: | ||
2937 | 189 | if vote: | ||
2938 | 190 | proposal.proposal.createComment(subject=subject, content=body, vote=vote) | ||
2939 | 191 | else: | ||
2940 | 192 | proposal.proposal.createComment(subject=subject, content=body) | ||
2941 | 193 | |||
2942 | 194 | def queue(proposal): | ||
2943 | 195 | """Run the queue step by snapshoting and queuing the build.""" | ||
2944 | 196 | lp = proposal.proposal | ||
2945 | 197 | |||
2946 | 198 | source = lp.source_branch | ||
2947 | 199 | owner = source.owner.name | ||
2948 | 200 | branch = tidy_branch(source.bzr_identity) | ||
2949 | 201 | revno = source.revision_count | ||
2950 | 202 | |||
2951 | 203 | # We might have hit this before Launchpad has scanned it | ||
2952 | 204 | if not revno: | ||
2953 | 205 | # Work around Launchpad being broken on 2011-09-07 by assuming | ||
2954 | 206 | # the merge was against the latest revno | ||
2955 | 207 | # Work around bzr revno bug with ghost ancestry | ||
2956 | 208 | # (https://launchpad.net/bugs/1161018) | ||
2957 | 209 | revno = run(['bzr', 'revno', 'nosmart+%s' % branch], const=True) | ||
2958 | 210 | revno = int(revno[0]) | ||
2959 | 211 | assert revno | ||
2960 | 212 | |||
2961 | 213 | target = tidy_branch(lp.target_branch.bzr_identity) | ||
2962 | 214 | |||
2963 | 215 | # Find where to check it out | ||
2964 | 216 | prefix = get_config('branches', target, 'prefix') | ||
2965 | 217 | reporoot = get_config('branches', target, 'reporoot') | ||
2966 | 218 | |||
2967 | 219 | # Give it an archive name | ||
2968 | 220 | suffix = '~%s~%s' % (owner, os.path.basename(branch)) | ||
2969 | 221 | |||
2970 | 222 | snapshot = '%s+bzr%s%s' % (prefix, revno, suffix) | ||
2971 | 223 | path = '%s/%s/%s' % (get_config('repos'), reporoot, snapshot) | ||
2972 | 224 | |||
2973 | 225 | # Remove the old directory | ||
2974 | 226 | run(['rm', '-rf', path]) | ||
2975 | 227 | # Branch it | ||
2976 | 228 | run(['bzr', 'branch', '--no-tree', branch, path], cwd=os.path.dirname(path)) | ||
2977 | 229 | # Find the common ancestor | ||
2978 | 230 | lines = run(['bzr', 'revision-info', '-d', path, '-r', 'ancestor:%s' % target]) | ||
2979 | 231 | |||
2980 | 232 | ancestor = lines[0].split()[0] if lines else 'unknown' | ||
2981 | 233 | |||
2982 | 234 | # Make the snapshot | ||
2983 | 235 | lines = run(['%s/pull_branch.sh' % get_config('tools'), path, prefix, '%s' % revno, suffix, target]) | ||
2984 | 236 | |||
2985 | 237 | # Scan the tool results to see which queues the build was | ||
2986 | 238 | # pushed into | ||
2987 | 239 | builders = [] | ||
2988 | 240 | |||
2989 | 241 | for line in lines: | ||
2990 | 242 | match = re.match('Spawned into (\S+)', line) | ||
2991 | 243 | |||
2992 | 244 | if match: | ||
2993 | 245 | builders.append(match.group(1)) | ||
2994 | 246 | |||
2995 | 247 | add_comment(proposal, QUEUED, snapshot=snapshot, revno=revno, builders=' '.join(builders), ancestor=ancestor, target=target) | ||
2996 | 248 | |||
2997 | 249 | def make_diff(proposal, all_files, check): | ||
2998 | 250 | """Check if there are any DejaGNU summary files and diff them.""" | ||
2999 | 251 | sums = [x for x in check if '.sum' in x[-1]] | ||
3000 | 252 | |||
3001 | 253 | if not proposal.ancestor: | ||
3002 | 254 | lines = ['The test suite was not checked as the branch point was not recorded.'] | ||
3003 | 255 | elif not sums: | ||
3004 | 256 | lines = ['The test suite was not checked as this build has no .sum style test results'] | ||
3005 | 257 | else: | ||
3006 | 258 | # Have some test results. See if there's a corresponding | ||
3007 | 259 | # version in the branch point build. | ||
3008 | 260 | first = '/'.join(sums[0]) | ||
3009 | 261 | ref = findlogs.find(all_files, first, proposal.ancestor) | ||
3010 | 262 | |||
3011 | 263 | if not ref: | ||
3012 | 264 | lines = ['The test suite was not checked as the branch point %s has nothing to compare against.' % proposal.ancestor] | ||
3013 | 265 | else: | ||
3014 | 266 | revision, build = ref | ||
3015 | 267 | |||
3016 | 268 | # Generate a unified diff between the two sets of results | ||
3017 | 269 | diff = run(['%s/difftests.sh' % get_config('tools'), | ||
3018 | 270 | '%s/%s/logs/%s' % (get_config('build'), revision, build), | ||
3019 | 271 | '%s/%s' % (get_config('build'), os.path.dirname(first))], | ||
3020 | 272 | const=True) | ||
3021 | 273 | |||
3022 | 274 | if diff: | ||
3023 | 275 | lines = ['The test suite results changed compared to the branch point %s:' % proposal.ancestor] | ||
3024 | 276 | lines.extend([' %s' % x for x in diff]) | ||
3025 | 277 | else: | ||
3026 | 278 | lines = ['The test suite results were unchanged compared to the branch point %s.' % proposal.ancestor] | ||
3027 | 279 | |||
3028 | 280 | if len(lines) > 40: | ||
3029 | 281 | total = len(lines) | ||
3030 | 282 | lines = lines[:40] | ||
3031 | 283 | lines.append(' ...and %d more' % (total - len(lines))) | ||
3032 | 284 | |||
3033 | 285 | return '\n'.join(lines) | ||
3034 | 286 | |||
3035 | 287 | def check_build(proposal, all_files, build, matches): | ||
3036 | 288 | """Check a single build to see how the results went.""" | ||
3037 | 289 | |||
3038 | 290 | if build in proposal.checked: | ||
3039 | 291 | logging.debug('Already posted a comment on %s' % build) | ||
3040 | 292 | else: | ||
3041 | 293 | check = [x for x in matches if len(x) >= 4 and x[2] == build] | ||
3042 | 294 | failures = [x for x in check if 'failed' in x[-1]] | ||
3043 | 295 | finished = 'finished.txt' in [x[-1] for x in check] | ||
3044 | 296 | |||
3045 | 297 | logging.info('Checking %s (finished=%s, failures=%r)' % (build, finished, failures)) | ||
3046 | 298 | |||
3047 | 299 | if finished: | ||
3048 | 300 | logs = ' '.join(x[-1] for x in failures) | ||
3049 | 301 | |||
3050 | 302 | diff = make_diff(proposal, all_files, check) | ||
3051 | 303 | |||
3052 | 304 | if failures: | ||
3053 | 305 | add_comment(proposal, CHECK_FAILED, build=build, snapshot=proposal.snapshot, logs=logs, diff=diff) | ||
3054 | 306 | else: | ||
3055 | 307 | add_comment(proposal, CHECK_OK, build=build, snapshot=proposal.snapshot, logs=logs, diff=diff) | ||
3056 | 308 | |||
3057 | 309 | def check(proposal, all_files): | ||
3058 | 310 | """Check an already queued build for build results.""" | ||
3059 | 311 | # Find all log files for this snapshot | ||
3060 | 312 | matches = [x for x in all_files if x[0] == proposal.snapshot] | ||
3061 | 313 | matches = [x for x in matches if len(x) >= 3 and x[1] == 'logs'] | ||
3062 | 314 | |||
3063 | 315 | if not matches: | ||
3064 | 316 | logging.debug('No log files yet') | ||
3065 | 317 | return | ||
3066 | 318 | |||
3067 | 319 | # Build a list of builds | ||
3068 | 320 | builds = [x[2] for x in matches if len(x) == 3] | ||
3069 | 321 | |||
3070 | 322 | for build in builds: | ||
3071 | 323 | check_build(proposal, all_files, build, matches) | ||
3072 | 324 | |||
3073 | 325 | def run_proposal(proposal, all_files, allowed): | ||
3074 | 326 | when = proposal.date_review_requested | ||
3075 | 327 | |||
3076 | 328 | # Only run recent proposals that have had review requested | ||
3077 | 329 | if when: | ||
3078 | 330 | now = datetime.datetime.now(when.tzinfo) | ||
3079 | 331 | elapsed = (now - when).days | ||
3080 | 332 | |||
3081 | 333 | logging.info('Checking proposal %s which is %d days old' % (proposal, elapsed)) | ||
3082 | 334 | |||
3083 | 335 | if elapsed <= get_config2(14, 'age-limit'): | ||
3084 | 336 | p = Proposal(proposal) | ||
3085 | 337 | |||
3086 | 338 | state = p.state if p.state else 'queue' | ||
3087 | 339 | |||
3088 | 340 | if state in allowed: | ||
3089 | 341 | # Could use a dodgy getattr()... | ||
3090 | 342 | if state == 'queue': | ||
3091 | 343 | queue(p) | ||
3092 | 344 | elif state == 'check': | ||
3093 | 345 | check(p, all_files) | ||
3094 | 346 | else: | ||
3095 | 347 | assert False, 'Proposal %s is in the invalid state "%s"' % (proposal, p.state) | ||
3096 | 348 | else: | ||
3097 | 349 | logging.info("Skipping %s" % state) | ||
3098 | 350 | |||
3099 | 351 | def main(): | ||
3100 | 352 | opts, args = getopt.getopt(sys.argv[1:], 'f:vs:') | ||
3101 | 353 | verbose = int(get_config2(0, 'verbose')) | ||
3102 | 354 | steps = get_config2('queue', 'steps').split(',') | ||
3103 | 355 | |||
3104 | 356 | for opt, arg in opts: | ||
3105 | 357 | if opt == '-f': | ||
3106 | 358 | name, value = arg.split('=') | ||
3107 | 359 | option = json.loads('{ "%s": %s }' % (name, value)) | ||
3108 | 360 | CONFIG.update(option) | ||
3109 | 361 | elif opt == '-v': | ||
3110 | 362 | verbose += 1 | ||
3111 | 363 | elif opt == '-s': | ||
3112 | 364 | steps = arg.split(',') | ||
3113 | 365 | |||
3114 | 366 | if verbose >= 2: | ||
3115 | 367 | logging.basicConfig(level=logging.DEBUG) | ||
3116 | 368 | elif verbose >= 1: | ||
3117 | 369 | logging.basicConfig(level=logging.INFO) | ||
3118 | 370 | |||
3119 | 371 | # Parse all-files into a list of already split paths | ||
3120 | 372 | with open(get_config('all-files')) as f: | ||
3121 | 373 | all_files = f.readlines() | ||
3122 | 374 | |||
3123 | 375 | all_files = [x.rstrip().split('/') for x in all_files] | ||
3124 | 376 | all_files = [x[1:] for x in all_files if len(x) >= 2] | ||
3125 | 377 | |||
3126 | 378 | # Login to Launchpad | ||
3127 | 379 | launchpad = launchpadlib.launchpad.Launchpad.login_with('taker', get_config('instance'), credentials_file=os.path.expanduser('~/.launchpadlib/credentials')) | ||
3128 | 380 | |||
3129 | 381 | # Scan all projects... | ||
3130 | 382 | for name in get_config('projects'): | ||
3131 | 383 | logging.info('Checking project %s' % name) | ||
3132 | 384 | project = launchpad.projects[name] | ||
3133 | 385 | |||
3134 | 386 | # Scan all proposals in the project... | ||
3135 | 387 | proposals = project.getMergeProposals() | ||
3136 | 388 | |||
3137 | 389 | for p in proposals: | ||
3138 | 390 | try: | ||
3139 | 391 | run_proposal(p, all_files, steps) | ||
3140 | 392 | except Exception, ex: | ||
3141 | 393 | logging.error('Error while processing %s: %s' % (p, ex)) | ||
3142 | 394 | |||
3143 | 395 | if __name__ == '__main__': | ||
3144 | 396 | main() | ||
3145 | 0 | 397 | ||
3146 | === added file 'track-tree.sh' | |||
3147 | --- track-tree.sh 1970-01-01 00:00:00 +0000 | |||
3148 | +++ track-tree.sh 2014-07-01 15:58:40 +0000 | |||
3149 | @@ -0,0 +1,16 @@ | |||
3150 | 1 | #!/bin/sh | ||
3151 | 2 | |||
3152 | 3 | set -e | ||
3153 | 4 | |||
3154 | 5 | dir=`mktemp -d` | ||
3155 | 6 | trap "rm -rf $dir" EXIT | ||
3156 | 7 | |||
3157 | 8 | find $@ -type f | sort > $dir/all-files.txt | ||
3158 | 9 | cp -a changes/all-files.txt $dir/previous.txt | ||
3159 | 10 | |||
3160 | 11 | cmp -s $dir/previous.txt $dir/all-files.txt && exit | ||
3161 | 12 | |||
3162 | 13 | stamp=`date +%Y-%m-%d-%H%M%S` | ||
3163 | 14 | |||
3164 | 15 | (cd $dir && diff -U 0 previous.txt all-files.txt) | tee $dir/$stamp.diff | ||
3165 | 16 | mv $dir/$stamp.diff $dir/all-files.txt changes | ||
3166 | 0 | 17 | ||
3167 | === added file 'up_branch.sh' | |||
3168 | --- up_branch.sh 1970-01-01 00:00:00 +0000 | |||
3169 | +++ up_branch.sh 2014-07-01 15:58:40 +0000 | |||
3170 | @@ -0,0 +1,53 @@ | |||
3171 | 1 | #!/bin/bash | ||
3172 | 2 | # Update a SVN branch and snapshot the latest revision | ||
3173 | 3 | # Can also snapshot past revisions and add a per-user | ||
3174 | 4 | # suffix | ||
3175 | 5 | |||
3176 | 6 | set -e | ||
3177 | 7 | |||
3178 | 8 | . ~/.config/cbuild/toolsrc | ||
3179 | 9 | |||
3180 | 10 | # Directory this script runs from | ||
3181 | 11 | here=`dirname $0` | ||
3182 | 12 | |||
3183 | 13 | # Suffix for manual pulls | ||
3184 | 14 | SUFFIX=${SUFFIX:-} | ||
3185 | 15 | |||
3186 | 16 | # Pull a branch and tarball it up | ||
3187 | 17 | branch=$1 | ||
3188 | 18 | head=$2 | ||
3189 | 19 | |||
3190 | 20 | svn up -q $branch | ||
3191 | 21 | # Recent SVN adds a last changed revision field. Delete spaces to | ||
3192 | 22 | # strip the space from the revno and, coincidentally, make the field | ||
3193 | 23 | # easier to match. | ||
3194 | 24 | latest=$(svn info $branch | tr -d ' ' | awk -F: '/LastChangedRev/ { print $2 }') | ||
3195 | 25 | revno=${REVNO:-$latest} | ||
3196 | 26 | |||
3197 | 27 | if [ "x${head}" != "x" ]; then | ||
3198 | 28 | name=${head}svn$revno$SUFFIX | ||
3199 | 29 | tar=/tmp/$name.tar | ||
3200 | 30 | xdelta=$snapshots/$name.tar.xdelta3.xz | ||
3201 | 31 | |||
3202 | 32 | if [ ! -f $xdelta ]; then | ||
3203 | 33 | echo Exporting and stamping $revno | ||
3204 | 34 | tmp=`mktemp -d` | ||
3205 | 35 | rm -rf $tmp/$name | ||
3206 | 36 | svn export $branch $tmp/$name | ||
3207 | 37 | REVNO=$revno $here/stamp_branch.sh $branch $tmp/$name | ||
3208 | 38 | |||
3209 | 39 | # Create the tarball | ||
3210 | 40 | echo Creating $tar | ||
3211 | 41 | (cd $tmp && find "$name" -print0 | sort -z) | tar caf $tar -C $tmp --no-recursion --null -T - | ||
3212 | 42 | rm -rf $tmp | ||
3213 | 43 | # Create the delta | ||
3214 | 44 | closest=`$here/closest.py $tar $snapshots/base/*.tar` | ||
3215 | 45 | echo Making the delta relative to $closest | ||
3216 | 46 | xdelta3 -fe -s $closest $tar $tar.xdelta3 | ||
3217 | 47 | rm -f $tar | ||
3218 | 48 | xz -f $tar.xdelta3 | ||
3219 | 49 | mv $tar.xdelta3.xz $snapshots | ||
3220 | 50 | echo New snapshot $head $revno created | ||
3221 | 51 | $here/spawn.sh $tar | ||
3222 | 52 | fi | ||
3223 | 53 | fi | ||
3224 | 0 | 54 | ||
3225 | === added file 'utilisation.py' | |||
3226 | --- utilisation.py 1970-01-01 00:00:00 +0000 | |||
3227 | +++ utilisation.py 2014-07-01 15:58:40 +0000 | |||
3228 | @@ -0,0 +1,93 @@ | |||
3229 | 1 | """Plots the backlog and utilisation level of a class of build | ||
3230 | 2 | machines. | ||
3231 | 3 | """ | ||
3232 | 4 | |||
3233 | 5 | import fileinput | ||
3234 | 6 | |||
3235 | 7 | import matplotlib | ||
3236 | 8 | matplotlib.use('agg') | ||
3237 | 9 | |||
3238 | 10 | from pylab import * | ||
3239 | 11 | |||
3240 | 12 | def process(lines, name, matcher): | ||
3241 | 13 | start = float(lines[0][0]) | ||
3242 | 14 | backlog = [] | ||
3243 | 15 | running = [] | ||
3244 | 16 | states = [] | ||
3245 | 17 | hosts = {} | ||
3246 | 18 | |||
3247 | 19 | for line in lines: | ||
3248 | 20 | time, type, host, arg = line[:4] | ||
3249 | 21 | |||
3250 | 22 | if not matcher(host): | ||
3251 | 23 | continue | ||
3252 | 24 | |||
3253 | 25 | offset = float(time) - start | ||
3254 | 26 | days = offset / (60*60*24) | ||
3255 | 27 | |||
3256 | 28 | if type == 'backlog': | ||
3257 | 29 | if hosts[host] == 'reserved': | ||
3258 | 30 | # Reserved machines report as a zero backlog | ||
3259 | 31 | pass | ||
3260 | 32 | else: | ||
3261 | 33 | backlog.append((days, int(arg))) | ||
3262 | 34 | elif type == 'state': | ||
3263 | 35 | if arg != 'updating': | ||
3264 | 36 | states.append((host, arg, days)) | ||
3265 | 37 | hosts[host] = arg | ||
3266 | 38 | |||
3267 | 39 | # Scan through the states and remove the glitches | ||
3268 | 40 | merged = [] | ||
3269 | 41 | |||
3270 | 42 | for host in hosts: | ||
3271 | 43 | just = [x for x in states if x[0] == host] | ||
3272 | 44 | |||
3273 | 45 | for i in range(len(just) - 1): | ||
3274 | 46 | this = just[i] | ||
3275 | 47 | next = just[i+1] | ||
3276 | 48 | elapsed = next[-1] - this[-1] | ||
3277 | 49 | |||
3278 | 50 | if this[1] == 'running' and next[1] == 'idle' and elapsed < 5.0/60/60/24: | ||
3279 | 51 | # Drop this record | ||
3280 | 52 | pass | ||
3281 | 53 | else: | ||
3282 | 54 | merged.append(this) | ||
3283 | 55 | |||
3284 | 56 | merged.sort(key=lambda x: x[-1]) | ||
3285 | 57 | |||
3286 | 58 | # Scan through and figure out the number of hosts running at any one time | ||
3287 | 59 | states = {} | ||
3288 | 60 | |||
3289 | 61 | for row in merged: | ||
3290 | 62 | states[row[0]] = row[1] | ||
3291 | 63 | |||
3292 | 64 | running.append((row[-1], sum(1 if x == 'running' else 0 for x in states.values()))) | ||
3293 | 65 | |||
3294 | 66 | backlog = array(backlog) | ||
3295 | 67 | running = array(running) | ||
3296 | 68 | |||
3297 | 69 | clf() | ||
3298 | 70 | plot(backlog[:,0], backlog[:,1]) | ||
3299 | 71 | scatter(backlog[:,0], backlog[:,1], label='backlog') | ||
3300 | 72 | |||
3301 | 73 | plot(running[:,0], running[:,1], c='g', label='running') | ||
3302 | 74 | |||
3303 | 75 | ylim(0, ylim()[1]+1) | ||
3304 | 76 | xlim(0, xlim()[1]) | ||
3305 | 77 | xlabel('Time (days)') | ||
3306 | 78 | ylabel('Utilisation (#boards) & backlog (# jobs)') | ||
3307 | 79 | title('%s utilisation' % name) | ||
3308 | 80 | legend() | ||
3309 | 81 | grid() | ||
3310 | 82 | savefig('%s.png' % name) | ||
3311 | 83 | show() | ||
3312 | 84 | |||
3313 | 85 | def main(): | ||
3314 | 86 | lines = list(fileinput.input()) | ||
3315 | 87 | lines = [x.rstrip().split() for x in lines] | ||
3316 | 88 | |||
3317 | 89 | process(lines, 'ursas', lambda x: x.startswith('ursa')) | ||
3318 | 90 | # process(lines, 'cloud', lambda x: x.startswith('oort')) | ||
3319 | 91 | |||
3320 | 92 | if __name__ == '__main__': | ||
3321 | 93 | main() |