15
15
import click
16
16
import glob
17
17
import json
18
+ import logging
18
19
import os
19
20
import re
20
21
import requests
24
25
from fireci import ci_command
25
26
from fireci import gradle
26
27
28
+ _logger = logging .getLogger ('fireci.coverage' )
29
+
30
+
31
+ def prow_job_log_link ():
32
+ job_name = os .getenv ('JOB_NAME' )
33
+ job_type = os .getenv ('JOB_TYPE' )
34
+ build_id = os .getenv ('BUILD_ID' )
35
+ repo_owner = os .getenv ('REPO_OWNER' )
36
+ repo_name = os .getenv ('REPO_NAME' )
37
+ pull_number = os .getenv ('PULL_NUMBER' )
38
+
39
+ domain = "android-ci.firebaseopensource.com"
40
+ bucket = "android-ci"
41
+
42
+ dir_pre_submit = f'pr-logs/pull/{ repo_owner } _{ repo_name } /{ pull_number } '
43
+ dir_post_submit = "logs"
44
+ directory = dir_pre_submit if job_type == 'presubmit' else dir_post_submit
45
+ path = f'{ job_name } /{ build_id } '
46
+
47
+ return f'https://{ domain } /view/gcs/{ bucket } /{ directory } /{ path } '
48
+
49
+
50
+ def gcloud_identity_token ():
51
+ result = subprocess .run (['gcloud' , 'auth' , 'print-identity-token' ], stdout = subprocess .PIPE , check = True )
52
+ return result .stdout .decode ('utf-8' ).strip ()
53
+
27
54
28
55
@click .option (
29
56
'--gradle-task' ,
30
- type = click .Choice (['checkCoverage' , 'checkCoverageChanged' ]),
31
57
default = 'checkCoverage' ,
32
- help = 'Run coverage tasks for affected products only in pre-submit and all products in post-submit'
58
+ help = 'The gradle task, which collects coverage for affected or all products.'
59
+ )
60
+ @click .option (
61
+ '--log' ,
62
+ default = prow_job_log_link ,
63
+ help = 'The link to the log of the prow job, which runs this coverage check.'
64
+ )
65
+ @click .option (
66
+ '--metrics-service-url' ,
67
+ envvar = 'METRICS_SERVICE_URL' ,
68
+ help = 'The URL to the metrics service, which persists data and calculates diff.'
69
+ )
70
+ @click .option (
71
+ '--access-token' ,
72
+ default = gcloud_identity_token ,
73
+ help = 'The access token, used to authorize http requests to the metrics service.'
33
74
)
34
75
@ci_command ()
35
- def coverage_check (gradle_task ):
76
+ def coverage (gradle_task , log , metrics_service_url , access_token ):
77
+ """Produces and uploads code coverage reports."""
78
+
36
79
gradle .run (gradle_task , '--continue' )
37
80
38
- test_report = parse_xml_reports ()
39
- post_request (test_report )
81
+ test_results = parse_xml_reports ()
82
+ test_report = {'metric' : 'Coverage' , 'results' : test_results , 'log' : log }
83
+
84
+ post_report (metrics_service_url , access_token , test_report )
40
85
41
86
42
87
def parse_xml_reports ():
43
88
test_results = []
44
89
45
90
xml_reports = glob .glob ('./**/reports/jacoco/*.xml' , recursive = True )
91
+ _logger .info (f'Found { len (xml_reports )} coverage reports: { xml_reports } ' )
92
+
46
93
for xml_report in xml_reports :
47
94
sdk = re .search (r'([^/]*)\.xml' , xml_report ).group (1 )
48
95
report = ElementTree .parse (xml_report ).getroot ()
@@ -54,9 +101,7 @@ def parse_xml_reports():
54
101
file_coverage = calculate_coverage (source_file )
55
102
test_results .append ({'sdk' : sdk , 'type' : file_name , 'value' : file_coverage })
56
103
57
- test_report = {'metric' : 'Coverage' , 'results' : test_results , 'log' : find_prow_job_link ()}
58
-
59
- return json .dumps (test_report )
104
+ return test_results
60
105
61
106
62
107
def calculate_coverage (element ):
@@ -68,41 +113,19 @@ def calculate_coverage(element):
68
113
return 0
69
114
70
115
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' )
116
+ def post_report (metrics_service_url , access_token , test_report ):
92
117
endpoint = construct_request_endpoint ()
93
- headers = construct_request_header ()
118
+ headers = {'Authorization' : f'Bearer { access_token } ' , 'Content-Type' : 'application/json' }
119
+ data = json .dumps (test_report )
94
120
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 } ' )
121
+ _logger .info ('Posting to the metrics service ...' )
122
+ _logger .info (f'Request endpoint: { endpoint } ' )
123
+ _logger .info (f'Request data: { data } ' )
100
124
125
+ request_url = f'{ metrics_service_url } { endpoint } '
126
+ result = requests .post (request_url , data = data , headers = headers )
101
127
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' }
128
+ _logger .info (f'Response: { result .text } ' )
106
129
107
130
108
131
def construct_request_endpoint ():
0 commit comments