Exemplo n.º 1
0
 def __enter__(self):
     self._saved = os.dup(sys.stdout.fileno()), os.dup(sys.stderr.fileno())
     self.tee = subprocess.Popen(["tee", self.filepath], stdin=subprocess.PIPE)
     os.dup2(self.tee.stdin.fileno(), sys.stdout.fileno())
     os.dup2(self.tee.stdin.fileno(), sys.stderr.fileno())
     if self.time:
         print datetime()
         self.start_time = time.time()
Exemplo n.º 2
0
    def report_ticket(self, ticket, status, log, plugins=(), dry_run=False, pending_status=None):
        report = {
            'status': status,
            'patches': ticket['patches'],
            'deps': ticket['depends_on'],
            'spkgs': ticket['spkgs'],
            'base': self.base,
            'user': self.config['user'],
            'machine': self.config['machine'],
            'time': datetime(),
            'plugins': plugins,
            'patchbot_version': patchbot_version.get_version(),
        }
        if pending_status:
            report['pending_status'] = pending_status
        try:
            report['base'] = ticket_base = sorted([
                describe_branch('patchbot/base', tag_only=True),
                describe_branch('patchbot/ticket_upstream', tag_only=True)], compare_version)[-1]
            report['git_base'] = self.git_commit('patchbot/base')
            report['git_base_human'] = describe_branch('patchbot/base')
            if ticket['id'] != 0:
                report['git_branch'] = ticket.get('git_branch', None)
                report['git_log'] = subprocess.check_output(['git', 'log', '--oneline', '%s..patchbot/ticket_upstream' % ticket_base]).strip().split('\n')
                # If apply failed, we don't want to be stuck in an infinite loop.
                report['git_commit'] = self.git_commit('patchbot/ticket_upstream')
                report['git_commit_human'] = describe_branch('patchbot/ticket_upstream')
                report['git_merge'] = self.git_commit('patchbot/ticket_merged')
                report['git_merge_human'] = describe_branch('patchbot/ticket_merged')
            else:
                report['git_branch'] = self.config['base_branch']
                report['git_log'] = []
                report['git_commit'] = report['git_merge'] = report['git_base']
        except Exception:
            traceback.print_exc()

        if status != 'Pending':
            history = open("%s/history.txt" % self.log_dir, "a")
            history.write("%s %s %s%s\n" % (
                    datetime(),
                    ticket['id'],
                    status,
                    " dry_run" if dry_run else ""))
            history.close()

        print "REPORT"
        import pprint
        pprint.pprint(report)
        print ticket['id'], status
        fields = {'report': json.dumps(report)}
        if os.path.exists(log):
            files = [('log', 'log', bz2.compress(open(log).read()))]
        else:
            files = []
        if not dry_run or status == 'Pending':
            print post_multipart("%s/report/%s" % (self.server, ticket['id']), fields, files)
Exemplo n.º 3
0
 def __exit__(self, exc_type, exc_val, exc_tb):
     if exc_type is not None:
         traceback.print_exc()
     if self.time:
         print datetime()
         print int(time.time() - self.start_time), "seconds"
     self.tee.stdin.close()
     time.sleep(1)
     os.dup2(self._saved[0], sys.stdout.fileno())
     os.dup2(self._saved[1], sys.stderr.fileno())
     time.sleep(1)
     try:
         signal.signal(signal.SIGALRM, alarm_handler)
         signal.alarm(self.timeout)
         self.tee.wait()
         signal.alarm(0)
     except TimeOut:
         traceback.print_exc()
         raise
     return False
Exemplo n.º 4
0
def report_ticket(server, ticket, status, base, machine, user, log, plugins=[]):
    print ticket['id'], status
    report = {
        'status': status,
        'patches': ticket['patches'],
        'deps': ticket['depends_on'],
        'spkgs': ticket['spkgs'],
        'base': base,
        'user': user,
        'machine': machine,
        'time': datetime(),
        'plugins': plugins,
    }
    fields = {'report': json.dumps(report)}
    if status != 'Pending':
        files = [('log', 'log', bz2.compress(open(log).read()))]
    else:
        files = []
    print post_multipart("%s/report/%s" % (server, ticket['id']), fields, files)
Exemplo n.º 5
0
    def test_a_ticket(self, ticket=None):

        self.reload_config()

        if ticket is None:
            ticket = self.get_ticket()
        else:
            ticket = None, scrape(int(ticket))
        if not ticket:
            print "No more tickets."
            time.sleep(self.config['idle'])
            return

        rating, ticket = ticket
        print "\n" * 2
        print "=" * 30, ticket['id'], "=" * 30
        print ticket['title']
        print "score", rating
        print "\n" * 2
        self.log_dir = self.sage_root + "/logs/patchbot"
        if not os.path.exists(self.log_dir):
            os.makedirs(self.log_dir)
        log = '%s/%s-log.txt' % (self.log_dir, ticket['id'])
        history = open("%s/history.txt" % self.log_dir, "a")
        history.write("%s %s\n" % (datetime(), ticket['id']))
        history.close()
        if not self.plugin_only:
            self.report_ticket(ticket, status='Pending', log=log)
        plugins_results = []
        try:
            t = Timer()
            with Tee(log, time=True, timeout=self.config['timeout'], timer=t):
                print "Sage Patchbot", patchbot_version.get_version()

                if ticket['spkgs']:
                    state = 'spkg'
                    print "\n".join(ticket['spkgs'])
                    print
                    for spkg in ticket['spkgs']:
                        print
                        print '+' * 10, spkg, '+' * 10
                        print
                        try:
                            self.check_spkg(spkg)
                        except Exception:
                            traceback.print_exc()
                        t.finish(spkg)

                if not ticket['spkgs']:
                    state = 'started'
                    os.environ['MAKE'] = "make -j%s" % self.config['parallelism']
                    os.environ['SAGE_ROOT'] = self.sage_root
                    os.environ['GIT_AUTHOR_NAME'] = os.environ['GIT_COMMITTER_NAME'] = 'patchbot'
                    os.environ['GIT_AUTHOR_EMAIL'] = os.environ['GIT_COMMITTER_EMAIL'] = 'patchbot@localhost'
                    os.environ['GIT_AUTHOR_DATE'] = os.environ['GIT_COMMITTER_DATE'] = '1970-01-01T00:00:00'
                    pull_from_trac(self.sage_root, ticket['id'], force=True, use_ccache=self.config['use_ccache'])
                    t.finish("Apply")
                    state = 'applied'
                    if not self.plugin_only:
                        self.report_ticket(ticket, status='Pending', log=log, pending_status=state)

                    do_or_die("$MAKE")
                    t.finish("Build")
                    state = 'built'
                    if not self.plugin_only:
                        self.report_ticket(ticket, status='Pending', log=log, pending_status=state)

                    # TODO: Exclude dependencies.
                    patch_dir = tempfile.mkdtemp()
                    if ticket['id'] != 0:
                        do_or_die("git format-patch -o '%s' patchbot/base..patchbot/ticket_merged" % patch_dir)

                    kwds = {
                        "original_dir": self.sage_root,
                        "patched_dir": os.getcwd(),
                        "patches": [os.path.join(patch_dir, p) for p in os.listdir(patch_dir)],
                        "sage_binary": os.path.join(os.getcwd(), 'sage'),
                        "dry_run": self.dry_run,
                    }

                    for name, plugin in self.config['plugins']:
                        try:
                            if ticket['id'] != 0 and os.path.exists(os.path.join(self.log_dir, '0', name)):
                                baseline = pickle.load(open(os.path.join(self.log_dir, '0', name)))
                            else:
                                baseline = None
                            print plugin_boundary(name)
                            do_or_die("git checkout patchbot/ticket_merged")
                            res = plugin(ticket, is_git=True, baseline=baseline, **kwds)
                            passed = True
                        except Exception:
                            traceback.print_exc()
                            passed = False
                            res = None
                        finally:
                            if isinstance(res, PluginResult):
                                if res.baseline is not None:
                                    plugin_dir = os.path.join(self.log_dir, str(ticket['id']))
                                    if not os.path.exists(plugin_dir):
                                        os.mkdir(plugin_dir)
                                    pickle.dump(res.baseline, open(os.path.join(plugin_dir, name), 'w'))
                                    passed = res.status == PluginResult.Passed
                                    print name, res.status
                                    plugins_results.append((name, passed, res.data))
                            else:
                                plugins_results.append((name, passed, None))
                            t.finish(name)
                            print plugin_boundary(name, end=True)
                    plugins_passed = all(passed for (name, passed, data) in plugins_results)
                    self.report_ticket(ticket, status='Pending', log=log, pending_status='plugins_passed' if plugins_passed else 'plugins_failed')

                    if self.plugin_only:
                        state = 'plugins' if plugins_passed else 'plugins_failed'
                    else:
                        if self.dry_run:
                            test_target = "$SAGE_ROOT/src/sage/misc/a*.py"
                            # TODO: Remove
                            test_target = "$SAGE_ROOT/src/sage/doctest/*.py"
                        else:
                            test_target = "--all --long"
                        if self.config['parallelism'] > 1:
                            test_cmd = "-tp %s" % self.config['parallelism']
                        else:
                            test_cmd = "-t"
                        do_or_die("$SAGE_ROOT/sage %s %s" % (test_cmd, test_target))
                        t.finish("Tests")
                        state = 'tested'

                        if not plugins_passed:
                            state = 'tests_passed_plugins_failed'

        except (urllib2.HTTPError, socket.error):
            # Don't report failure because the network/trac died...
            print
            t.print_all()
            traceback.print_exc()
            state = 'network_error'
        except Exception:
            traceback.print_exc()

        for _ in range(5):
            try:
                print "Reporting", ticket['id'], status[state]
                self.report_ticket(ticket, status=status[state], log=log, plugins=plugins_results, dry_run=self.dry_run)
                print "Done reporting", ticket['id']
                break
            except IOError:
                traceback.print_exc()
                time.sleep(self.config['idle'])
        else:
            print "Error reporting", ticket['id']
        maybe_temp_root = os.environ['SAGE_ROOT']
        if maybe_temp_root.endswith("-sage-git-temp-%s" % ticket['id']):
            shutil.rmtree(maybe_temp_root)
        return status[state]