Skip to content

Commit 1366c0c

Browse files
committed
Coverage parsing and uploading in fireci.
1 parent 63c88cf commit 1366c0c

File tree

2 files changed

+124
-1
lines changed

2 files changed

+124
-1
lines changed

ci/fireci/fireciplugins/coverage.py

Lines changed: 122 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,122 @@
1+
# Copyright 2020 Google LLC
2+
#
3+
# Licensed under the Apache License, Version 2.0 (the "License");
4+
# you may not use this file except in compliance with the License.
5+
# You may obtain a copy of the License at
6+
#
7+
# http://www.apache.org/licenses/LICENSE-2.0
8+
#
9+
# Unless required by applicable law or agreed to in writing, software
10+
# distributed under the License is distributed on an "AS IS" BASIS,
11+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
# See the License for the specific language governing permissions and
13+
# limitations under the License.
14+
15+
import click
16+
import glob
17+
import json
18+
import os
19+
import re
20+
import requests
21+
import subprocess
22+
import xml.etree.ElementTree as ElementTree
23+
24+
from fireci import ci_command
25+
from fireci import gradle
26+
27+
28+
@click.option(
29+
'--gradle-task',
30+
type=click.Choice(['checkCoverage', 'checkCoverageChanged']),
31+
default='checkCoverage',
32+
help='Run coverage tasks for affected products only in pre-submit and all products in post-submit'
33+
)
34+
@ci_command()
35+
def coverage_check(gradle_task):
36+
gradle.run(gradle_task)
37+
38+
test_report = parse_xml_reports()
39+
post_request(test_report)
40+
41+
42+
def parse_xml_reports():
43+
test_results = []
44+
45+
xml_reports = glob.glob('./**/reports/jacoco/*.xml', recursive=True)
46+
for xml_report in xml_reports:
47+
sdk = re.search(r'([^/]*)\.xml', xml_report).group(1)
48+
report = ElementTree.parse(xml_report).getroot()
49+
sdk_coverage = calculate_coverage(report)
50+
test_results.append({'sdk': sdk, 'type': '', 'value': sdk_coverage})
51+
52+
for source_file in report.findall('.//sourcefile'):
53+
file_name = source_file.attrib['name']
54+
file_coverage = calculate_coverage(source_file)
55+
test_results.append({'sdk': sdk, 'type': file_name, 'value': file_coverage})
56+
57+
test_report = {'metric': 'Coverage', 'results': test_results, 'log': find_prow_job_link()}
58+
59+
return json.dumps(test_report)
60+
61+
62+
def calculate_coverage(element):
63+
counter = element.find('counter[@type="LINE"]')
64+
if counter is not None:
65+
covered = int(counter.attrib['covered'])
66+
missed = int(counter.attrib['missed'])
67+
return covered / (covered + missed)
68+
return 0
69+
70+
71+
def find_prow_job_link():
72+
job_name = os.getenv('JOB_NAME')
73+
job_type = os.getenv('JOB_TYPE')
74+
build_id = os.getenv('BUILD_ID')
75+
repo_owner = os.getenv('REPO_OWNER')
76+
repo_name = os.getenv('REPO_NAME')
77+
pull_number = os.getenv('PULL_NUMBER')
78+
79+
domain = "android-ci.firebaseopensource.com"
80+
bucket = "android-ci"
81+
82+
dir_pre_submit = f'pr-logs/pull/{repo_owner}_{repo_name}/{pull_number}'
83+
dir_post_submit = "logs"
84+
directory = dir_pre_submit if job_type == 'presubmit' else dir_post_submit
85+
path = f'{job_name}/{build_id}'
86+
87+
return f'https://{domain}/view/gcs/{bucket}/{directory}/{path}'
88+
89+
90+
def post_request(data):
91+
metrics_service_url = os.getenv('METRICS_SERVICE_URL')
92+
endpoint = construct_request_endpoint()
93+
headers = construct_request_header()
94+
95+
print('Posting to the metrics service ...')
96+
print(f'Request endpoint: {endpoint}')
97+
print(f'Request data: {data}')
98+
result = requests.post(f'{metrics_service_url}{endpoint}', data=data, headers=headers)
99+
print(f'Response: {result.text}')
100+
101+
102+
def construct_request_header():
103+
result = subprocess.run(['gcloud', 'auth', 'print-identity-token'], stdout=subprocess.PIPE)
104+
access_token = result.stdout.decode('utf-8').strip()
105+
return {'Authorization': f'Bearer {access_token}', 'Content-Type': 'application/json'}
106+
107+
108+
def construct_request_endpoint():
109+
repo_owner = os.getenv('REPO_OWNER')
110+
repo_name = os.getenv('REPO_NAME')
111+
branch = os.getenv('PULL_BASE_REF')
112+
base_commit = os.getenv('PULL_BASE_SHA')
113+
head_commit = os.getenv('PULL_PULL_SHA')
114+
pull_request = os.getenv('PULL_NUMBER')
115+
116+
commit = head_commit if head_commit else base_commit
117+
118+
endpoint = f'/repos/{repo_owner}/{repo_name}/commits/{commit}/reports?branch={branch}'
119+
if pull_request:
120+
endpoint += f'&pull_request={pull_request}&base_commit={base_commit}'
121+
122+
return endpoint

ci/fireci/setup.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,8 @@
2828
'click==7.0',
2929
'opencensus==0.2.0',
3030
'google-cloud-monitoring==0.31.1',
31-
'PyGithub==1.43.8'
31+
'PyGithub==1.43.8',
32+
'requests==2.23.0'
3233
],
3334
packages=find_packages(exclude=['tests']),
3435
entry_points={

0 commit comments

Comments
 (0)