OLD | NEW |
1 #!/usr/bin/python | 1 #!/usr/bin/python |
2 | 2 |
3 # Copyright (c) 2010 The Chromium OS Authors. All rights reserved. | 3 # Copyright (c) 2010 The Chromium OS Authors. All rights reserved. |
4 # Use of this source code is governed by a BSD-style license that can be | 4 # Use of this source code is governed by a BSD-style license that can be |
5 # found in the LICENSE file. | 5 # found in the LICENSE file. |
6 | 6 |
7 """CBuildbot is wrapper around the build process used by the pre-flight queue""" | 7 """CBuildbot is wrapper around the build process used by the pre-flight queue""" |
8 | 8 |
9 import errno | 9 import errno |
10 import heapq | 10 import heapq |
11 import re | 11 import re |
12 import optparse | 12 import optparse |
13 import os | 13 import os |
14 import shutil | 14 import shutil |
15 import sys | 15 import sys |
16 | 16 |
17 import cbuildbot_comm | 17 import cbuildbot_comm |
18 from cbuildbot_config import config | 18 from cbuildbot_config import config |
19 | 19 |
20 sys.path.append(os.path.join(os.path.dirname(__file__), '../lib')) | 20 sys.path.append(os.path.join(os.path.dirname(__file__), '../lib')) |
21 from cros_build_lib import (Die, Info, ReinterpretPathForChroot, RunCommand, | 21 from cros_build_lib import (Die, Info, ReinterpretPathForChroot, RunCommand, |
22 Warning) | 22 Warning) |
23 | 23 |
24 _DEFAULT_RETRIES = 3 | 24 _DEFAULT_RETRIES = 3 |
25 _PACKAGE_FILE = '%(buildroot)s/src/scripts/cbuildbot_package.list' | 25 _PACKAGE_FILE = '%(buildroot)s/src/scripts/cbuildbot_package.list' |
26 ARCHIVE_BASE = '/var/www/archive' | 26 ARCHIVE_BASE = '/var/www/archive' |
27 ARCHIVE_COUNT = 10 | 27 ARCHIVE_COUNT = 10 |
28 | 28 |
| 29 # Currently, both the full buildbot and the preflight buildbot store their |
| 30 # data in a variable named PORTAGE_BINHOST, but they're in different files. |
| 31 # We're planning on joining the two files soon and renaming the full binhost |
| 32 # to FULL_BINHOST. |
| 33 _FULL_BINHOST = 'PORTAGE_BINHOST' |
| 34 _PREFLIGHT_BINHOST = 'PORTAGE_BINHOST' |
| 35 |
29 # ======================== Utility functions ================================ | 36 # ======================== Utility functions ================================ |
30 | 37 |
31 def MakeDir(path, parents=False): | 38 def MakeDir(path, parents=False): |
32 """Basic wrapper around os.mkdirs. | 39 """Basic wrapper around os.mkdirs. |
33 | 40 |
34 Keyword arguments: | 41 Keyword arguments: |
35 path -- Path to create. | 42 path -- Path to create. |
36 parents -- Follow mkdir -p logic. | 43 parents -- Follow mkdir -p logic. |
37 | 44 |
38 """ | 45 """ |
(...skipping 259 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
298 """Performs a checkout without clobbering previous checkout.""" | 305 """Performs a checkout without clobbering previous checkout.""" |
299 RepoSync(buildroot, retries) | 306 RepoSync(buildroot, retries) |
300 | 307 |
301 | 308 |
302 def _MakeChroot(buildroot): | 309 def _MakeChroot(buildroot): |
303 """Wrapper around make_chroot.""" | 310 """Wrapper around make_chroot.""" |
304 cwd = os.path.join(buildroot, 'src', 'scripts') | 311 cwd = os.path.join(buildroot, 'src', 'scripts') |
305 RunCommand(['./make_chroot', '--fast'], cwd=cwd) | 312 RunCommand(['./make_chroot', '--fast'], cwd=cwd) |
306 | 313 |
307 | 314 |
| 315 def _GetPortageEnvVar(buildroot, board, envvar): |
| 316 """Get a portage environment variable for the specified board, if any. |
| 317 |
| 318 buildroot: The root directory where the build occurs. Must be an absolute |
| 319 path. |
| 320 board: Board type that was built on this machine. E.g. x86-generic. |
| 321 envvar: The environment variable to get. E.g. "PORTAGE_BINHOST". |
| 322 |
| 323 Returns: |
| 324 The value of the environment variable, as a string. If no such variable |
| 325 can be found, return the empty string. |
| 326 """ |
| 327 cwd = os.path.join(buildroot, 'src', 'scripts') |
| 328 binhost = RunCommand(['portageq-%s' % board, 'envvar', envvar], |
| 329 cwd=cwd, redirect_stdout=True, enter_chroot=True, |
| 330 error_ok=True) |
| 331 return binhost.rstrip('\n') |
| 332 |
| 333 |
308 def _SetupBoard(buildroot, board='x86-generic'): | 334 def _SetupBoard(buildroot, board='x86-generic'): |
309 """Wrapper around setup_board.""" | 335 """Wrapper around setup_board.""" |
310 cwd = os.path.join(buildroot, 'src', 'scripts') | 336 cwd = os.path.join(buildroot, 'src', 'scripts') |
311 RunCommand(['./setup_board', '--fast', '--default', '--board=%s' % board], | 337 RunCommand(['./setup_board', '--fast', '--default', '--board=%s' % board], |
312 cwd=cwd, enter_chroot=True) | 338 cwd=cwd, enter_chroot=True) |
313 | 339 |
314 | 340 |
315 def _Build(buildroot): | 341 def _Build(buildroot): |
316 """Wrapper around build_packages.""" | 342 """Wrapper around build_packages.""" |
317 cwd = os.path.join(buildroot, 'src', 'scripts') | 343 cwd = os.path.join(buildroot, 'src', 'scripts') |
(...skipping 182 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
500 paths = [private_overlay] | 526 paths = [private_overlay] |
501 elif overlays == 'public': | 527 elif overlays == 'public': |
502 paths = [public_overlay] | 528 paths = [public_overlay] |
503 elif overlays == 'both': | 529 elif overlays == 'both': |
504 paths = [public_overlay, private_overlay] | 530 paths = [public_overlay, private_overlay] |
505 else: | 531 else: |
506 Die('Incorrect overlay configuration: %s' % overlays) | 532 Die('Incorrect overlay configuration: %s' % overlays) |
507 return paths | 533 return paths |
508 | 534 |
509 | 535 |
| 536 def _UploadPrebuilts(buildroot, board, overlay_config): |
| 537 """Upload prebuilts. |
| 538 |
| 539 Args: |
| 540 buildroot: The root directory where the build occurs. |
| 541 board: Board type that was built on this machine |
| 542 overlay_config: A string describing which overlays you want. |
| 543 'private': Just the private overlay. |
| 544 'public': Just the public overlay. |
| 545 'both': Both the public and private overlays. |
| 546 """ |
| 547 |
| 548 cwd = os.path.join(buildroot, 'src', 'scripts') |
| 549 cmd = [os.path.join(cwd, 'prebuilt.py'), |
| 550 '--sync-binhost-conf', |
| 551 '--build-path', buildroot, |
| 552 '--board', board, |
| 553 '--prepend-version', 'preflight', |
| 554 '--key', _PREFLIGHT_BINHOST] |
| 555 if overlay_config == 'public': |
| 556 cmd.extend(['--upload', 'gs://chromeos-prebuilt']) |
| 557 else: |
| 558 assert overlay_config in ('private', 'both') |
| 559 cmd.extend(['--upload', 'chromeos-images:/var/www/prebuilt/', |
| 560 '--binhost-base-url', 'http://chromeos-prebuilt']) |
| 561 |
| 562 RunCommand(cmd, cwd=cwd) |
| 563 |
| 564 |
510 def main(): | 565 def main(): |
511 # Parse options | 566 # Parse options |
512 usage = "usage: %prog [options] cbuildbot_config" | 567 usage = "usage: %prog [options] cbuildbot_config" |
513 parser = optparse.OptionParser(usage=usage) | 568 parser = optparse.OptionParser(usage=usage) |
514 parser.add_option('-r', '--buildroot', | 569 parser.add_option('-r', '--buildroot', |
515 help='root directory where build occurs', default=".") | 570 help='root directory where build occurs', default=".") |
516 parser.add_option('-n', '--buildnumber', | 571 parser.add_option('-n', '--buildnumber', |
517 help='build number', type='int', default=0) | 572 help='build number', type='int', default=0) |
518 parser.add_option('--chrome_rev', default=None, type='string', | 573 parser.add_option('--chrome_rev', default=None, type='string', |
519 dest='chrome_rev', | 574 dest='chrome_rev', |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
551 tracking_branch = options.tracking_branch | 606 tracking_branch = options.tracking_branch |
552 chrome_atom_to_build = None | 607 chrome_atom_to_build = None |
553 | 608 |
554 if len(args) >= 1: | 609 if len(args) >= 1: |
555 buildconfig = _GetConfig(args[-1]) | 610 buildconfig = _GetConfig(args[-1]) |
556 else: | 611 else: |
557 Warning('Missing configuration description') | 612 Warning('Missing configuration description') |
558 parser.print_usage() | 613 parser.print_usage() |
559 sys.exit(1) | 614 sys.exit(1) |
560 | 615 |
561 # Calculate list of overlay directories. | 616 try: |
562 overlays = _ResolveOverlays(buildroot, buildconfig['overlays']) | 617 # Calculate list of overlay directories. |
| 618 overlays = _ResolveOverlays(buildroot, buildconfig['overlays']) |
| 619 board = buildconfig['board'] |
563 | 620 |
564 try: | |
565 _PreFlightRinse(buildroot, buildconfig['board'], tracking_branch, overlays) | 621 _PreFlightRinse(buildroot, buildconfig['board'], tracking_branch, overlays) |
| 622 chroot_path = os.path.join(buildroot, 'chroot') |
| 623 boardpath = os.path.join(chroot_path, 'build', board) |
566 if options.sync: | 624 if options.sync: |
567 if options.clobber or not os.path.isdir(buildroot): | 625 if options.clobber or not os.path.isdir(buildroot): |
568 _FullCheckout(buildroot, tracking_branch, url=options.url) | 626 _FullCheckout(buildroot, tracking_branch, url=options.url) |
569 else: | 627 else: |
| 628 old_binhost = _GetPortageEnvVar(buildroot, board, _FULL_BINHOST) |
570 _IncrementalCheckout(buildroot) | 629 _IncrementalCheckout(buildroot) |
| 630 new_binhost = _GetPortageEnvVar(buildroot, board, _FULL_BINHOST) |
| 631 if old_binhost != new_binhost: |
| 632 RunCommand(['sudo', 'rm', '-rf', boardpath]) |
571 | 633 |
572 # Check that all overlays can be found. | 634 # Check that all overlays can be found. |
573 for path in overlays: | 635 for path in overlays: |
574 assert ':' not in path, 'Overlay must not contain colons: %s' % path | 636 assert ':' not in path, 'Overlay must not contain colons: %s' % path |
575 if not os.path.isdir(path): | 637 if not os.path.isdir(path): |
576 Die('Missing overlay: %s' % path) | 638 Die('Missing overlay: %s' % path) |
577 | 639 |
578 chroot_path = os.path.join(buildroot, 'chroot') | |
579 if not os.path.isdir(chroot_path): | 640 if not os.path.isdir(chroot_path): |
580 _MakeChroot(buildroot) | 641 _MakeChroot(buildroot) |
581 | 642 |
582 boardpath = os.path.join(chroot_path, 'build', buildconfig['board']) | |
583 if not os.path.isdir(boardpath): | 643 if not os.path.isdir(boardpath): |
584 _SetupBoard(buildroot, board=buildconfig['board']) | 644 _SetupBoard(buildroot, board=buildconfig['board']) |
585 | 645 |
586 # Perform uprev. If chrome_uprev is set, rev Chrome ebuilds. | 646 # Perform uprev. If chrome_uprev is set, rev Chrome ebuilds. |
587 if options.chrome_rev: | 647 if options.chrome_rev: |
588 chrome_atom_to_build = _MarkChromeAsStable(buildroot, tracking_branch, | 648 chrome_atom_to_build = _MarkChromeAsStable(buildroot, tracking_branch, |
589 options.chrome_rev) | 649 options.chrome_rev) |
590 elif buildconfig['uprev']: | 650 elif buildconfig['uprev']: |
591 _UprevPackages(buildroot, tracking_branch, revisionfile, | 651 _UprevPackages(buildroot, tracking_branch, revisionfile, |
592 buildconfig['board'], overlays) | 652 buildconfig['board'], overlays) |
(...skipping 24 matching lines...) Expand all Loading... |
617 test_results_dir=test_results_dir, | 677 test_results_dir=test_results_dir, |
618 gsutil=options.gsutil, | 678 gsutil=options.gsutil, |
619 archive_dir=archive_full_path, | 679 archive_dir=archive_full_path, |
620 acl=options.acl) | 680 acl=options.acl) |
621 | 681 |
622 if buildconfig['uprev']: | 682 if buildconfig['uprev']: |
623 # Don't push changes for developers. | 683 # Don't push changes for developers. |
624 if buildconfig['master']: | 684 if buildconfig['master']: |
625 # Master bot needs to check if the other slaves completed. | 685 # Master bot needs to check if the other slaves completed. |
626 if cbuildbot_comm.HaveSlavesCompleted(config): | 686 if cbuildbot_comm.HaveSlavesCompleted(config): |
| 687 _UploadPrebuilts(buildroot, board, buildconfig['overlays']) |
627 _UprevPush(buildroot, tracking_branch, buildconfig['board'], | 688 _UprevPush(buildroot, tracking_branch, buildconfig['board'], |
628 overlays, options.debug) | 689 overlays, options.debug) |
629 else: | 690 else: |
630 Die('CBUILDBOT - One of the slaves has failed!!!') | 691 Die('CBUILDBOT - One of the slaves has failed!!!') |
631 | 692 |
632 else: | 693 else: |
633 # Publish my status to the master if its expecting it. | 694 # Publish my status to the master if its expecting it. |
634 if buildconfig['important'] and not options.debug: | 695 if buildconfig['important'] and not options.debug: |
635 cbuildbot_comm.PublishStatus(cbuildbot_comm.STATUS_BUILD_COMPLETE) | 696 cbuildbot_comm.PublishStatus(cbuildbot_comm.STATUS_BUILD_COMPLETE) |
636 | 697 |
637 except: | 698 except: |
638 # Send failure to master bot. | 699 # Send failure to master bot. |
639 if not buildconfig['master'] and buildconfig['important']: | 700 if not buildconfig['master'] and buildconfig['important']: |
640 cbuildbot_comm.PublishStatus(cbuildbot_comm.STATUS_BUILD_FAILED) | 701 cbuildbot_comm.PublishStatus(cbuildbot_comm.STATUS_BUILD_FAILED) |
641 | 702 |
642 raise | 703 raise |
643 | 704 |
644 | 705 |
645 if __name__ == '__main__': | 706 if __name__ == '__main__': |
646 main() | 707 main() |
OLD | NEW |