| OLD | NEW |
| 1 # Copyright 2015 The Chromium Authors. All rights reserved. | 1 # Copyright 2015 The Chromium Authors. All rights reserved. |
| 2 # Use of this source code is governed by a BSD-style license that can be | 2 # Use of this source code is governed by a BSD-style license that can be |
| 3 # found in the LICENSE file. | 3 # found in the LICENSE file. |
| 4 | 4 |
| 5 from collections import defaultdict | 5 from collections import defaultdict |
| 6 import datetime | 6 import datetime |
| 7 import json | 7 import json |
| 8 | 8 |
| 9 from apiclient import discovery | 9 from apiclient import discovery |
| 10 from apiclient.errors import HttpError | 10 from apiclient.errors import HttpError |
| 11 import httplib2 | 11 import httplib2 |
| 12 from oauth2client import client | 12 from oauth2client import client |
| 13 | 13 |
| 14 from infra_libs import ts_mon | 14 from infra_libs import ts_mon |
| 15 | 15 |
| 16 | 16 |
| 17 # Dictionary mapping whitelisted lower-case labels to corresponding tree names. | 17 # Dictionary mapping whitelisted lower-case labels to corresponding tree names. |
| 18 WHITELISTED_LABELS = {'sheriff-chromium': 'chromium', | 18 WHITELISTED_LABELS = {'sheriff-chromium': 'chromium', |
| 19 'sheriff-blink': 'blink', | 19 'sheriff-blink': 'blink', |
| 20 'infra-troopers': 'trooper'} | 20 'infra-troopers': 'trooper'} |
| 21 BATCH_SIZE = 10 | 21 BATCH_SIZE = 10 |
| 22 | 22 |
| 23 | 23 |
| 24 issue_tracker_requests = ts_mon.CounterMetric( |
| 25 'flakiness_pipeline/issue_tracker_requests', |
| 26 description='Number of requests to the issue tracker') |
| 27 |
| 28 |
| 24 def _build_crbug_service(crbug_service_account): # pragma: no cover | 29 def _build_crbug_service(crbug_service_account): # pragma: no cover |
| 25 with open(crbug_service_account) as crbug_sa_file: | 30 with open(crbug_service_account) as crbug_sa_file: |
| 26 service_account = json.load(crbug_sa_file) | 31 service_account = json.load(crbug_sa_file) |
| 27 | 32 |
| 28 creds = client.SignedJwtAssertionCredentials( | 33 creds = client.SignedJwtAssertionCredentials( |
| 29 service_account['client_email'], service_account['private_key'], | 34 service_account['client_email'], service_account['private_key'], |
| 30 'https://www.googleapis.com/auth/userinfo.email') | 35 'https://www.googleapis.com/auth/userinfo.email') |
| 31 http = creds.authorize(httplib2.Http()) | 36 http = creds.authorize(httplib2.Http()) |
| 32 return discovery.build( | 37 return discovery.build( |
| 33 'monorail', 'v1', discoveryServiceUrl='https://monorail-prod.appspot.com/' | 38 'monorail', 'v1', discoveryServiceUrl='https://monorail-prod.appspot.com/' |
| 34 '_ah/api/discovery/v1/apis/{api}/{apiVersion}/rest', http=http) | 39 '_ah/api/discovery/v1/apis/{api}/{apiVersion}/rest', http=http) |
| 35 | 40 |
| 36 | 41 |
| 37 def _list_issues(crbug_service_account): | 42 def _list_issues(crbug_service_account): |
| 38 service = _build_crbug_service(crbug_service_account) | 43 service = _build_crbug_service(crbug_service_account) |
| 39 issues = [] | 44 issues = [] |
| 40 seen_issue_ids = set() | 45 seen_issue_ids = set() |
| 41 for whitelisted_label in WHITELISTED_LABELS: | 46 for whitelisted_label in WHITELISTED_LABELS: |
| 42 start_index = 0 | 47 start_index = 0 |
| 43 while True: | 48 while True: |
| 44 request = service.issues().list( | 49 request = service.issues().list( |
| 45 projectId='chromium', label=whitelisted_label, | 50 projectId='chromium', label=whitelisted_label, |
| 46 startIndex=start_index, maxResults=BATCH_SIZE, can='open') | 51 startIndex=start_index, maxResults=BATCH_SIZE, can='open') |
| 47 response = request.execute(num_retries=5) | 52 response = request.execute(num_retries=5) |
| 53 issue_tracker_requests.increment( |
| 54 {'source': 'builder_alerts', 'operation': 'issues_list'}) |
| 48 | 55 |
| 49 # Issue Tracker may omit certain issues occasionally, so counting whether | 56 # Issue Tracker may omit certain issues occasionally, so counting whether |
| 50 # they add up to 'totalResults' in response is not relaible. However, we | 57 # they add up to 'totalResults' in response is not relaible. However, we |
| 51 # can use the fact that 'items' is not present in response if we try to | 58 # can use the fact that 'items' is not present in response if we try to |
| 52 # list issues starting from an index beyond totalResults. | 59 # list issues starting from an index beyond totalResults. |
| 53 if not response.get('items'): | 60 if not response.get('items'): |
| 54 break | 61 break |
| 55 | 62 |
| 56 # Here we increment start_index by BATCH_SIZE rather then by the actual | 63 # Here we increment start_index by BATCH_SIZE rather then by the actual |
| 57 # number of returned issues in 'items' because as described above, issue | 64 # number of returned issues in 'items' because as described above, issue |
| (...skipping 106 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 164 | 171 |
| 165 sheriff_issue['tags'] = sorted(tags) # converts back to list | 172 sheriff_issue['tags'] = sorted(tags) # converts back to list |
| 166 if severity is not None: | 173 if severity is not None: |
| 167 sheriff_issue['severity'] = severity | 174 sheriff_issue['severity'] = severity |
| 168 | 175 |
| 169 # We assume that a tags have 1:1 mapping to trees here. | 176 # We assume that a tags have 1:1 mapping to trees here. |
| 170 for tree_name in sheriff_issue['tags']: | 177 for tree_name in sheriff_issue['tags']: |
| 171 sheriff_issues[tree_name].append(sheriff_issue) | 178 sheriff_issues[tree_name].append(sheriff_issue) |
| 172 | 179 |
| 173 return sheriff_issues | 180 return sheriff_issues |
| OLD | NEW |