def get(self, job_id): job = Job.query.options( subqueryload_all(Job.phases), joinedload('project', innerjoin=True), ).get(job_id) if job is None: return '', 404 previous_runs = Job.query.filter( Job.project == job.project, Job.date_created < job.date_created, Job.status == Status.finished, Job.id != job.id, ).order_by(Job.date_created.desc())[:NUM_PREVIOUS_RUNS] # find all parent groups (root trees) test_groups = sorted(TestGroup.query.filter( TestGroup.job_id == job.id, TestGroup.parent_id == None, # NOQA: we have to use == here ), key=lambda x: x.name) test_failures = TestGroup.query.options( joinedload('parent'), ).filter( TestGroup.job_id == job.id, TestGroup.result == Result.failed, TestGroup.num_leaves == 0, ).order_by(TestGroup.name.asc()) num_test_failures = test_failures.count() test_failures = test_failures[:25] if test_failures: failure_origins = find_failure_origins( job, test_failures) for test_failure in test_failures: test_failure.origin = failure_origins.get(test_failure) extended_serializers = { TestGroup: TestGroupWithOriginSerializer(), } log_sources = list(LogSource.query.options( joinedload('step'), ).filter( LogSource.job_id == job.id, ).order_by(LogSource.date_created.asc())) context = self.serialize(job) context.update({ 'phases': job.phases, 'testFailures': { 'total': num_test_failures, 'testGroups': self.serialize(test_failures, extended_serializers), }, 'logs': log_sources, 'testGroups': test_groups, 'previousRuns': previous_runs, }) return self.respond(context)
def get(self, job_id): job = Job.query.options( subqueryload_all(Job.phases), joinedload('project', innerjoin=True), ).get(job_id) if job is None: return '', 404 previous_runs = Job.query.filter( Job.project == job.project, Job.date_created < job.date_created, Job.status == Status.finished, Job.id != job.id, ).order_by(Job.date_created.desc())[:NUM_PREVIOUS_RUNS] test_failures = TestCase.query.filter( TestCase.job_id == job.id, TestCase.result == Result.failed, ).order_by(TestCase.name.asc()) num_test_failures = test_failures.count() test_failures = test_failures[:25] if test_failures: failure_origins = find_failure_origins(job, test_failures) for test_failure in test_failures: test_failure.origin = failure_origins.get(test_failure) extended_serializers = { TestCase: TestCaseWithOriginSerializer(), } log_sources = list( LogSource.query.options(joinedload('step'), ).filter( LogSource.job_id == job.id, ).order_by( LogSource.date_created.asc())) context = self.serialize(job) context.update({ 'phases': job.phases, 'testFailures': { 'total': num_test_failures, 'tests': self.serialize(test_failures, extended_serializers), }, 'logs': log_sources, 'previousRuns': previous_runs, }) return self.respond(context)
def get(self, job_id): job = Job.query.options( joinedload('project', innerjoin=True), ).get(job_id) if job is None: return '', 404 previous_runs = Job.query.filter( Job.project == job.project, Job.date_created < job.date_created, Job.status == Status.finished, Job.id != job.id, ).order_by(Job.date_created.desc())[:NUM_PREVIOUS_RUNS] test_failures = TestCase.query.filter( TestCase.job_id == job.id, TestCase.result == Result.failed, ).order_by(TestCase.name.asc()) num_test_failures = test_failures.count() test_failures = test_failures[:25] if test_failures: failure_origins = find_failure_origins( job.build, test_failures) for test_failure in test_failures: test_failure.origin = failure_origins.get(test_failure) extended_serializers = { TestCase: TestCaseWithOriginSerializer(), } log_sources = list(LogSource.query.options( joinedload('step'), ).filter( LogSource.job_id == job.id, ).order_by(LogSource.date_created.asc())) context = self.serialize(job) context.update({ 'testFailures': { 'total': num_test_failures, 'tests': self.serialize(test_failures, extended_serializers), }, 'logs': log_sources, 'previousRuns': previous_runs, }) return self.respond(context)
def get(self, job_id): job = Job.query.options( joinedload('project', innerjoin=True), ).get(job_id) if job is None: return '', 404 test_failures = TestCase.query.filter( TestCase.job_id == job.id, TestCase.result == Result.failed, ).order_by(TestCase.name.asc()) num_test_failures = test_failures.count() test_failures = test_failures[:25] if test_failures: failure_origins = find_failure_origins( job.build, test_failures) for test_failure in test_failures: test_failure.origin = failure_origins.get(test_failure) extended_serializers = { TestCase: TestCaseWithOriginCrumbler(), } # Restricting to matching JobStep ids when querying LogSources # allows us to use the LogSource.step_id index, which makes # the query significantly faster. jobstep_ids = db.session.query(JobStep.id).filter( JobStep.job_id == job.id ).subquery() log_sources = list(LogSource.query.options( joinedload('step').joinedload('node'), ).filter( LogSource.job_id == job.id, LogSource.project_id == job.project_id, LogSource.step_id.in_(jobstep_ids), ).order_by(LogSource.date_created.asc())) context = self.serialize(job) context.update({ 'testFailures': { 'total': num_test_failures, 'tests': self.serialize(test_failures, extended_serializers), }, 'logs': log_sources, }) return self.respond(context)
def test_simple(self): source = self.create_source(self.project) build_a = self.create_build(project=self.project, result=Result.passed, status=Status.finished, label='build a', date_created=datetime( 2013, 9, 19, 22, 15, 22), source=source) job_a = self.create_job(build=build_a) build_b = self.create_build(project=self.project, result=Result.failed, status=Status.finished, label='build b', date_created=datetime( 2013, 9, 19, 22, 15, 23), source=source) job_b = self.create_job(build=build_b) build_c = self.create_build(project=self.project, result=Result.failed, status=Status.finished, label='build c', date_created=datetime( 2013, 9, 19, 22, 15, 24), source=source) job_c = self.create_job(build=build_c) build_d = self.create_build(project=self.project, result=Result.failed, status=Status.finished, label='build d', date_created=datetime( 2013, 9, 19, 22, 15, 25), source=source) job_d = self.create_job(build=build_d) self.create_test(job_a, name='foo', result=Result.passed) self.create_test(job_a, name='bar', result=Result.passed) self.create_test(job_b, name='foo', result=Result.failed) self.create_test(job_b, name='bar', result=Result.passed) self.create_test(job_c, name='foo', result=Result.failed) self.create_test(job_c, name='bar', result=Result.failed) foo_d = self.create_test(job_d, name='foo', result=Result.failed) bar_d = self.create_test(job_d, name='bar', result=Result.failed) result = find_failure_origins(build_d, [foo_d, bar_d]) assert result == {foo_d: build_b, bar_d: build_c}
def test_simple(self): project = self.create_project() source = self.create_source(project) build_a = self.create_build( project=project, result=Result.passed, status=Status.finished, label='build a', date_created=datetime(2013, 9, 19, 22, 15, 22), source=source) job_a = self.create_job(build=build_a) build_b = self.create_build( project=project, result=Result.failed, status=Status.finished, label='build b', date_created=datetime(2013, 9, 19, 22, 15, 23), source=source) job_b = self.create_job(build=build_b) build_c = self.create_build( project=project, result=Result.failed, status=Status.finished, label='build c', date_created=datetime(2013, 9, 19, 22, 15, 24), source=source) job_c = self.create_job(build=build_c) build_d = self.create_build( project=project, result=Result.failed, status=Status.finished, label='build d', date_created=datetime(2013, 9, 19, 22, 15, 25), source=source) job_d = self.create_job(build=build_d) self.create_test(job_a, name='foo', result=Result.passed) self.create_test(job_a, name='bar', result=Result.passed) self.create_test(job_b, name='foo', result=Result.failed) self.create_test(job_b, name='bar', result=Result.passed) self.create_test(job_c, name='foo', result=Result.failed) self.create_test(job_c, name='bar', result=Result.failed) foo_d = self.create_test(job_d, name='foo', result=Result.failed) bar_d = self.create_test(job_d, name='bar', result=Result.failed) result = find_failure_origins(build_d, [foo_d, bar_d]) assert result == { foo_d: build_b, bar_d: build_c }
def get(self, job_id): job = Job.query.options(joinedload('project', innerjoin=True), ).get(job_id) if job is None: return '', 404 test_failures = TestCase.query.filter( TestCase.job_id == job.id, TestCase.result == Result.failed, ).order_by(TestCase.name.asc()) num_test_failures = test_failures.count() test_failures = test_failures[:25] if test_failures: failure_origins = find_failure_origins(job.build, test_failures) for test_failure in test_failures: test_failure.origin = failure_origins.get(test_failure) extended_serializers = { TestCase: TestCaseWithOriginCrumbler(), } log_sources = list( LogSource.query.options(joinedload('step'), ).filter( LogSource.job_id == job.id, LogSource.project_id == job.project_id, ).order_by(LogSource.date_created.asc())) context = self.serialize(job) context.update({ 'testFailures': { 'total': num_test_failures, 'tests': self.serialize(test_failures, extended_serializers), }, 'logs': log_sources, }) return self.respond(context)
def get(self, job_id): job = Job.query.options(joinedload("project", innerjoin=True)).get(job_id) if job is None: return "", 404 test_failures = TestCase.query.filter(TestCase.job_id == job.id, TestCase.result == Result.failed).order_by( TestCase.name.asc() ) num_test_failures = test_failures.count() test_failures = test_failures[:25] if test_failures: failure_origins = find_failure_origins(job.build, test_failures) for test_failure in test_failures: test_failure.origin = failure_origins.get(test_failure) extended_serializers = {TestCase: TestCaseWithOriginSerializer()} log_sources = list( LogSource.query.options(joinedload("step")) .filter(LogSource.job_id == job.id) .order_by(LogSource.date_created.asc()) ) context = self.serialize(job) context.update( { "testFailures": { "total": num_test_failures, "tests": self.serialize(test_failures, extended_serializers), }, "logs": log_sources, } ) return self.respond(context)
def get(self, build_id): build = Build.query.options( joinedload('project', innerjoin=True), joinedload('author'), joinedload('source').joinedload('revision'), subqueryload_all('stats'), ).get(build_id) if build is None: return '', 404 jobs = list(Job.query.filter( Job.build_id == build.id, )) # identify failures if not jobs: # If we have no jobs, the query to find failures becomes very expensive due to `in_([])` being # handled poorly, but since we know the result, we can just set it. test_failures = [] num_test_failures = 0 else: test_failures = TestCase.query.options( joinedload('job', innerjoin=True), ).filter( TestCase.job_id.in_([j.id for j in jobs]), TestCase.result == Result.failed, ).order_by(TestCase.name.asc()) num_test_failures = test_failures.count() test_failures = test_failures[:25] failures_by_job = defaultdict(list) for failure in test_failures: failures_by_job[failure.job].append(failure) failure_origins = find_failure_origins( build, test_failures) for test_failure in test_failures: test_failure.origin = failure_origins.get(test_failure) seen_by = list(User.query.join( BuildSeen, BuildSeen.user_id == User.id, ).filter( BuildSeen.build_id == build.id, )) extended_serializers = { TestCase: TestCaseWithOriginCrumbler(), } event_list = list(Event.query.filter( Event.item_id == build.id, Event.type.in_(ALL_EVENT_TYPES) ).order_by(Event.date_created.desc())) context = self.serialize(build) context.update({ 'jobs': jobs, 'seenBy': seen_by, 'events': event_list, 'failures': get_failure_reasons(build), 'testFailures': { 'total': num_test_failures, 'tests': self.serialize(test_failures, extended_serializers), }, 'parents': self.serialize(get_parents_last_builds(build)), 'containsAutogeneratedPlan': build_lib.contains_autogenerated_plan(build), }) return self.respond(context)
def get(self, build_id): build = Build.query.options( joinedload("project", innerjoin=True), joinedload("author"), joinedload("source") ).get(build_id) if build is None: return "", 404 previous_runs = ( Build.query.filter( Build.project == build.project, Build.date_created < build.date_created, Build.status == Status.finished, Build.id != build.id, Build.patch == None, # NOQA ) .options(joinedload("source"), joinedload("author")) .order_by(Build.date_created.desc())[:NUM_PREVIOUS_RUNS] ) if previous_runs: most_recent_run = previous_runs[0] else: most_recent_run = None jobs = list(Job.query.filter(Job.build_id == build.id)) # identify failures test_failures = ( TestGroup.query.options(joinedload("parent"), joinedload("job", innerjoin=True)) .filter( TestGroup.job_id.in_([j.id for j in jobs]), TestGroup.result == Result.failed, TestGroup.num_leaves == 0 ) .order_by(TestGroup.name.asc()) ) num_test_failures = test_failures.count() test_failures = test_failures[:25] failures_by_job = defaultdict(list) for failure in test_failures: failures_by_job[failure.job].append(failure) failure_origins = find_failure_origins(build, test_failures) for test_failure in test_failures: test_failure.origin = failure_origins.get(test_failure) # identify added/removed tests if most_recent_run and build.status == Status.finished: changed_tests = find_changed_tests(build, most_recent_run) else: changed_tests = [] seen_by = list(User.query.join(BuildSeen, BuildSeen.user_id == User.id).filter(BuildSeen.build_id == build.id)) extended_serializers = {TestGroup: TestGroupWithOriginSerializer()} context = self.serialize(build) context.update( { "jobs": jobs, "previousRuns": previous_runs, "seenBy": seen_by, "testFailures": { "total": num_test_failures, "testGroups": self.serialize(test_failures, extended_serializers), }, "testChanges": self.serialize(changed_tests, extended_serializers), } ) return self.respond(context)
def get(self, build_id): build = Build.query.options( joinedload('project', innerjoin=True), joinedload('author'), joinedload('source'), ).get(build_id) if build is None: return '', 404 previous_runs = Build.query.filter( Build.project == build.project, Build.date_created < build.date_created, Build.status == Status.finished, Build.id != build.id, Source.patch_id == None, # NOQA ).join( Source, Build.source_id == Source.id, ).options( contains_eager('source'), joinedload('author'), ).order_by(Build.date_created.desc())[:NUM_PREVIOUS_RUNS] if previous_runs: most_recent_run = previous_runs[0] else: most_recent_run = None jobs = list(Job.query.filter( Job.build_id == build.id, )) # identify failures test_failures = TestCase.query.options( joinedload('job', innerjoin=True), ).filter( TestCase.job_id.in_([j.id for j in jobs]), TestCase.result == Result.failed, ).order_by(TestCase.name.asc()) num_test_failures = test_failures.count() test_failures = test_failures[:25] failures_by_job = defaultdict(list) for failure in test_failures: failures_by_job[failure.job].append(failure) failure_origins = find_failure_origins( build, test_failures) for test_failure in test_failures: test_failure.origin = failure_origins.get(test_failure) # identify added/removed tests if most_recent_run and build.status == Status.finished: changed_tests = find_changed_tests(build, most_recent_run) else: changed_tests = [] seen_by = list(User.query.join( BuildSeen, BuildSeen.user_id == User.id, ).filter( BuildSeen.build_id == build.id, )) extended_serializers = { TestCase: TestCaseWithOriginSerializer(), } event_list = list(Event.query.filter( Event.item_id == build.id, ).order_by(Event.date_created.desc())) context = self.serialize(build) context.update({ 'jobs': jobs, 'previousRuns': previous_runs, 'seenBy': seen_by, 'events': event_list, 'testFailures': { 'total': num_test_failures, 'tests': self.serialize(test_failures, extended_serializers), }, 'testChanges': self.serialize(changed_tests, extended_serializers), }) return self.respond(context)
def get(self, build_id): build = Build.query.options( joinedload('project', innerjoin=True), joinedload('author'), joinedload('source').joinedload('revision'), subqueryload_all('stats'), ).get(build_id) if build is None: return '', 404 try: most_recent_run = Build.query.filter( Build.project == build.project, Build.date_created < build.date_created, Build.status == Status.finished, Build.id != build.id, Source.patch_id == None, # NOQA ).join( Source, Build.source_id == Source.id, ).options( contains_eager('source').joinedload('revision'), joinedload('author'), ).order_by(Build.date_created.desc())[0] except IndexError: most_recent_run = None jobs = list(Job.query.filter( Job.build_id == build.id, )) # identify failures test_failures = TestCase.query.options( joinedload('job', innerjoin=True), ).filter( TestCase.job_id.in_([j.id for j in jobs]), TestCase.result == Result.failed, ).order_by(TestCase.name.asc()) num_test_failures = test_failures.count() test_failures = test_failures[:25] failures_by_job = defaultdict(list) for failure in test_failures: failures_by_job[failure.job].append(failure) failure_origins = find_failure_origins( build, test_failures) for test_failure in test_failures: test_failure.origin = failure_origins.get(test_failure) # identify added/removed tests if most_recent_run and build.status == Status.finished: changed_tests = find_changed_tests(build, most_recent_run) else: changed_tests = [] seen_by = list(User.query.join( BuildSeen, BuildSeen.user_id == User.id, ).filter( BuildSeen.build_id == build.id, )) extended_serializers = { TestCase: TestCaseWithOriginCrumbler(), } event_list = list(Event.query.filter( Event.item_id == build.id, ).order_by(Event.date_created.desc())) context = self.serialize(build) context.update({ 'jobs': jobs, 'seenBy': seen_by, 'events': event_list, 'failures': get_failure_reasons(build), 'testFailures': { 'total': num_test_failures, 'tests': self.serialize(test_failures, extended_serializers), }, 'testChanges': self.serialize(changed_tests, extended_serializers), 'parents': self.serialize(get_parents_last_builds(build)), }) return self.respond(context)
def get(self, build_id): build = Build.query.options( joinedload('project', innerjoin=True), joinedload('author'), joinedload('source'), ).get(build_id) if build is None: return '', 404 previous_runs = Build.query.filter( Build.project == build.project, Build.date_created < build.date_created, Build.status == Status.finished, Build.id != build.id, Build.patch == None, # NOQA ).options( joinedload('source'), joinedload('author'), ).order_by(Build.date_created.desc())[:NUM_PREVIOUS_RUNS] if previous_runs: most_recent_run = previous_runs[0] else: most_recent_run = None jobs = list(Job.query.filter( Job.build_id == build.id, )) # identify failures test_failures = TestCase.query.options( joinedload('job', innerjoin=True), ).filter( TestCase.job_id.in_([j.id for j in jobs]), TestCase.result == Result.failed, ).order_by(TestCase.name.asc()) num_test_failures = test_failures.count() test_failures = test_failures[:25] failures_by_job = defaultdict(list) for failure in test_failures: failures_by_job[failure.job].append(failure) failure_origins = find_failure_origins( build, test_failures) for test_failure in test_failures: test_failure.origin = failure_origins.get(test_failure) # identify added/removed tests if most_recent_run and build.status == Status.finished: changed_tests = find_changed_tests(build, most_recent_run) else: changed_tests = [] seen_by = list(User.query.join( BuildSeen, BuildSeen.user_id == User.id, ).filter( BuildSeen.build_id == build.id, )) extended_serializers = { TestCase: TestCaseWithOriginSerializer(), } context = self.serialize(build) context.update({ 'jobs': jobs, 'previousRuns': previous_runs, 'seenBy': seen_by, 'testFailures': { 'total': num_test_failures, 'tests': self.serialize(test_failures, extended_serializers), }, 'testChanges': self.serialize(changed_tests, extended_serializers), }) return self.respond(context)
def get(self, build_id): build = Build.query.options( joinedload('project', innerjoin=True), joinedload('author'), joinedload('source').joinedload('revision'), subqueryload_all('stats'), ).get(build_id) if build is None: return '', 404 try: most_recent_run = Build.query.filter( Build.project == build.project, Build.date_created < build.date_created, Build.status == Status.finished, Build.id != build.id, Source.patch_id == None, # NOQA ).join( Source, Build.source_id == Source.id, ).options( contains_eager('source').joinedload('revision'), joinedload('author'), ).order_by(Build.date_created.desc())[0] except IndexError: most_recent_run = None jobs = list(Job.query.filter( Job.build_id == build.id, )) # identify failures if not jobs: # If we have no jobs, the query to find failures becomes very expensive due to `in_([])` being # handled poorly, but since we know the result, we can just set it. test_failures = [] num_test_failures = 0 else: test_failures = TestCase.query.options( joinedload('job', innerjoin=True), ).filter( TestCase.job_id.in_([j.id for j in jobs]), TestCase.result == Result.failed, ).order_by(TestCase.name.asc()) num_test_failures = test_failures.count() test_failures = test_failures[:25] failures_by_job = defaultdict(list) for failure in test_failures: failures_by_job[failure.job].append(failure) failure_origins = find_failure_origins( build, test_failures) for test_failure in test_failures: test_failure.origin = failure_origins.get(test_failure) # identify added/removed tests if most_recent_run and build.status == Status.finished: changed_tests = find_changed_tests(build, most_recent_run) else: changed_tests = [] seen_by = list(User.query.join( BuildSeen, BuildSeen.user_id == User.id, ).filter( BuildSeen.build_id == build.id, )) extended_serializers = { TestCase: TestCaseWithOriginCrumbler(), } event_list = list(Event.query.filter( Event.item_id == build.id, ).order_by(Event.date_created.desc())) context = self.serialize(build) context.update({ 'jobs': jobs, 'seenBy': seen_by, 'events': event_list, 'failures': get_failure_reasons(build), 'testFailures': { 'total': num_test_failures, 'tests': self.serialize(test_failures, extended_serializers), }, 'testChanges': self.serialize(changed_tests, extended_serializers), 'parents': self.serialize(get_parents_last_builds(build)), }) return self.respond(context)