From b52837e92ead5ddb1648ba60c46efeb16afe56c7 Mon Sep 17 00:00:00 2001 From: Marco Castelluccio Date: Fri, 17 Mar 2017 01:21:41 +0100 Subject: [PATCH 001/134] First commit --- .travis.yml | 6 ++ code-coverage.py | 171 ++++++++++++++++++++++++++++++++++++++++++ requirements.txt | 1 + test-requirements.txt | 1 + tox.ini | 2 + 5 files changed, 181 insertions(+) create mode 100644 .travis.yml create mode 100644 code-coverage.py create mode 100644 requirements.txt create mode 100644 test-requirements.txt create mode 100644 tox.ini diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 000000000..65f1ad289 --- /dev/null +++ b/.travis.yml @@ -0,0 +1,6 @@ +language: python +install: + - pip install -r requirements.txt + - pip install -r test-requirements.txt +script: + - flake8 . diff --git a/code-coverage.py b/code-coverage.py new file mode 100644 index 000000000..b6fbd4efd --- /dev/null +++ b/code-coverage.py @@ -0,0 +1,171 @@ +import os +import shutil +import subprocess +import time +import argparse +import requests + + +def get_last_task(): + r = requests.get('https://index.taskcluster.net/v1/task/gecko.v2.mozilla-central.latest.firefox.linux64-ccov-opt') + last_task = r.json() + return last_task['taskId'] + + +def get_task(branch, revision): + r = requests.get('https://index.taskcluster.net/v1/task/gecko.v2.%s.revision.%s.firefox.linux64-ccov-opt' % (branch, revision)) + task = r.json() + return task['taskId'] + + +def get_task_details(task_id): + r = requests.get('https://queue.taskcluster.net/v1/task/' + task_id) + return r.json() + + +def get_task_artifacts(task_id): + r = requests.get('https://queue.taskcluster.net/v1/task/' + task_id + '/artifacts') + return r.json()['artifacts'] + + +def get_tasks_in_group(group_id): + r = requests.get('https://queue.taskcluster.net/v1/task-group/' + group_id + '/list', params={ + 'limit': 200 + }) + reply = r.json() + tasks = reply['tasks'] + while 'continuationToken' in reply: + r = requests.get('https://queue.taskcluster.net/v1/task-group/' + group_id + '/list', params={ + 'limit': 200, + 'continuationToken': reply['continuationToken'] + }) + reply = r.json() + tasks += reply['tasks'] + return tasks + + +def download_artifact(task_id, artifact): + r = requests.get('https://queue.taskcluster.net/v1/task/' + task_id + '/artifacts/' + artifact['name'], stream=True) + with open(os.path.join('ccov-artifacts', task_id + '_' + os.path.basename(artifact['name'])), 'wb') as f: + r.raw.decode_content = True + shutil.copyfileobj(r.raw, f) + + +def download_coverage_artifacts(build_task_id): + try: + shutil.rmtree("ccov-artifacts") + except: + pass + + try: + os.mkdir("ccov-artifacts") + except: + pass + + task_data = get_task_details(build_task_id) + + artifacts = get_task_artifacts(build_task_id) + for artifact in artifacts: + if 'target.code-coverage-gcno.zip' in artifact['name']: + download_artifact(build_task_id, artifact) + + test_tasks = [t for t in get_tasks_in_group(task_data['taskGroupId']) if t['task']['metadata']['name'].startswith('test-linux64-ccov')] + for test_task in test_tasks: + artifacts = get_task_artifacts(test_task['status']['taskId']) + for artifact in artifacts: + if 'code-coverage-gcda.zip' in artifact['name']: + download_artifact(test_task['status']['taskId'], artifact) + + +def get_github_commit(mercurial_commit): + r = requests.get("https://api.pub.build.mozilla.org/mapper/gecko-dev/rev/hg/" + mercurial_commit) + + return r.text.split(" ")[0] + + +def generate_info(grcov_path): + files = os.listdir("ccov-artifacts") + ordered_files = [] + for fname in files: + if not fname.endswith('.zip'): + continue + + if 'gcno' in fname: + ordered_files.insert(0, "ccov-artifacts/" + fname) + else: + ordered_files.append("ccov-artifacts/" + fname) + + fout = open("output.info", 'w') + cmd = [grcov_path, '-z', '-t', 'lcov', '-s', '/home/worker/workspace/build/src/'] + cmd.extend(ordered_files[:3]) + proc = subprocess.Popen(cmd, stdout=fout, stderr=subprocess.PIPE) + i = 0 + while proc.poll() is None: + print('Running grcov... ' + str(i)) + i += 1 + time.sleep(1) + + if proc.poll() != 0: + raise Exception("Error while running grcov:\n" + proc.stderr.read()) + + +def generate_report(src_dir, auto_use_gecko_dev, revision): + if auto_use_gecko_dev: + if not os.path.isdir("gecko-dev"): + subprocess.call(["git", "clone", "https://github.com/mozilla/gecko-dev.git"]) + + os.chdir("gecko-dev") + + subprocess.call(["git", "pull"]) + + git_commit = get_github_commit(revision) + + subprocess.call(["git", "checkout", git_commit]) + + os.chdir("..") + + cwd = os.getcwd() + os.chdir(src_dir) + ret = subprocess.call(["genhtml", "-o", os.path.join(cwd, "report"), "--show-details", "--highlight", "--ignore-errors", "source", "--legend", os.path.join(cwd, "output.info"), "--prefix", src_dir]) + if ret != 0: + raise Exception("Error while running genhtml.") + os.chdir(cwd) + + if auto_use_gecko_dev: + os.chdir("gecko-dev") + subprocess.call(["git", "checkout", "master"]) + os.chdir("..") + + +def main(): + parser = argparse.ArgumentParser() + parser.add_argument("src_dir", action="store", help="Path to the source directory") + parser.add_argument("branch", action="store", nargs='?', help="Branch on which jobs ran") + parser.add_argument("commit", action="store", nargs='?', help="Commit hash for push") + parser.add_argument("--grcov", action="store", nargs='?', default="grcov", help="path to grcov") + parser.add_argument('--gecko-dev', dest='gecko_dev', action='store_true') + parser.add_argument('--no-gecko-dev', dest='gecko_dev', action='store_false') + parser.set_defaults(gecko_dev=False) + args = parser.parse_args() + + if (args.branch is None and args.commit is not None) or (args.branch is not None and args.commit is None): + parser.print_help() + return + + if args.branch is None and args.commit is None: + task_id = get_last_task() + task_data = get_task_details(task_id) + revision = task_data["payload"]["env"]["GECKO_HEAD_REV"] + else: + task_id = get_task(args.branch, args.commit) + revision = args.commit + + download_coverage_artifacts(task_id) + + generate_info(args.grcov) + + generate_report(os.path.abspath(args.src_dir), args.gecko_dev, revision) + + +if __name__ == "__main__": + main() diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 000000000..ed84dd33e --- /dev/null +++ b/requirements.txt @@ -0,0 +1 @@ +requests[security]>=2.7.0 diff --git a/test-requirements.txt b/test-requirements.txt new file mode 100644 index 000000000..39304807f --- /dev/null +++ b/test-requirements.txt @@ -0,0 +1 @@ +flake8 diff --git a/tox.ini b/tox.ini new file mode 100644 index 000000000..e44b81084 --- /dev/null +++ b/tox.ini @@ -0,0 +1,2 @@ +[flake8] +ignore = E501 From 60bc7d0d943b6937f2bea354afad3a4bab6a5abc Mon Sep 17 00:00:00 2001 From: Marco Castelluccio Date: Fri, 17 Mar 2017 01:24:44 +0100 Subject: [PATCH 002/134] Add basic README --- README.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 README.md diff --git a/README.md b/README.md new file mode 100644 index 000000000..41889db59 --- /dev/null +++ b/README.md @@ -0,0 +1,5 @@ +# firefox-code-coverage + +[![Build Status](https://travis-ci.org/marco-c/firefox-code-coverage.svg?branch=master)](https://travis-ci.org/marco-c/firefox-code-coverage) + +A description on how to use this tool is available at https://developer.mozilla.org/en-US/docs/Mozilla/Testing/Measuring_Code_Coverage_on_Firefox. From b331d0e23ae39756e0ff290f5bb1fe9880369f4f Mon Sep 17 00:00:00 2001 From: Marco Castelluccio Date: Fri, 17 Mar 2017 01:46:36 +0100 Subject: [PATCH 003/134] Remove now useless code --- code-coverage.py | 39 ++++----------------------------------- 1 file changed, 4 insertions(+), 35 deletions(-) diff --git a/code-coverage.py b/code-coverage.py index b6fbd4efd..2f4c165b0 100644 --- a/code-coverage.py +++ b/code-coverage.py @@ -77,12 +77,6 @@ def download_coverage_artifacts(build_task_id): download_artifact(test_task['status']['taskId'], artifact) -def get_github_commit(mercurial_commit): - r = requests.get("https://api.pub.build.mozilla.org/mapper/gecko-dev/rev/hg/" + mercurial_commit) - - return r.text.split(" ")[0] - - def generate_info(grcov_path): files = os.listdir("ccov-artifacts") ordered_files = [] @@ -97,33 +91,19 @@ def generate_info(grcov_path): fout = open("output.info", 'w') cmd = [grcov_path, '-z', '-t', 'lcov', '-s', '/home/worker/workspace/build/src/'] - cmd.extend(ordered_files[:3]) + cmd.extend(ordered_files) proc = subprocess.Popen(cmd, stdout=fout, stderr=subprocess.PIPE) i = 0 while proc.poll() is None: print('Running grcov... ' + str(i)) i += 1 - time.sleep(1) + time.sleep(60) if proc.poll() != 0: raise Exception("Error while running grcov:\n" + proc.stderr.read()) def generate_report(src_dir, auto_use_gecko_dev, revision): - if auto_use_gecko_dev: - if not os.path.isdir("gecko-dev"): - subprocess.call(["git", "clone", "https://github.com/mozilla/gecko-dev.git"]) - - os.chdir("gecko-dev") - - subprocess.call(["git", "pull"]) - - git_commit = get_github_commit(revision) - - subprocess.call(["git", "checkout", git_commit]) - - os.chdir("..") - cwd = os.getcwd() os.chdir(src_dir) ret = subprocess.call(["genhtml", "-o", os.path.join(cwd, "report"), "--show-details", "--highlight", "--ignore-errors", "source", "--legend", os.path.join(cwd, "output.info"), "--prefix", src_dir]) @@ -131,21 +111,13 @@ def generate_report(src_dir, auto_use_gecko_dev, revision): raise Exception("Error while running genhtml.") os.chdir(cwd) - if auto_use_gecko_dev: - os.chdir("gecko-dev") - subprocess.call(["git", "checkout", "master"]) - os.chdir("..") - def main(): parser = argparse.ArgumentParser() parser.add_argument("src_dir", action="store", help="Path to the source directory") parser.add_argument("branch", action="store", nargs='?', help="Branch on which jobs ran") parser.add_argument("commit", action="store", nargs='?', help="Commit hash for push") - parser.add_argument("--grcov", action="store", nargs='?', default="grcov", help="path to grcov") - parser.add_argument('--gecko-dev', dest='gecko_dev', action='store_true') - parser.add_argument('--no-gecko-dev', dest='gecko_dev', action='store_false') - parser.set_defaults(gecko_dev=False) + parser.add_argument("--grcov", action="store", nargs='?', default="grcov", help="Path to grcov") args = parser.parse_args() if (args.branch is None and args.commit is not None) or (args.branch is not None and args.commit is None): @@ -154,17 +126,14 @@ def main(): if args.branch is None and args.commit is None: task_id = get_last_task() - task_data = get_task_details(task_id) - revision = task_data["payload"]["env"]["GECKO_HEAD_REV"] else: task_id = get_task(args.branch, args.commit) - revision = args.commit download_coverage_artifacts(task_id) generate_info(args.grcov) - generate_report(os.path.abspath(args.src_dir), args.gecko_dev, revision) + generate_report(os.path.abspath(args.src_dir)) if __name__ == "__main__": From 899f7146e6c463623971d1ed13e19a8ac2ff2201 Mon Sep 17 00:00:00 2001 From: James Graham Date: Fri, 17 Mar 2017 14:08:40 +0000 Subject: [PATCH 004/134] Fix the signature of get_report --- code-coverage.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code-coverage.py b/code-coverage.py index 2f4c165b0..2d5fda401 100644 --- a/code-coverage.py +++ b/code-coverage.py @@ -103,7 +103,7 @@ def generate_info(grcov_path): raise Exception("Error while running grcov:\n" + proc.stderr.read()) -def generate_report(src_dir, auto_use_gecko_dev, revision): +def generate_report(src_dir): cwd = os.getcwd() os.chdir(src_dir) ret = subprocess.call(["genhtml", "-o", os.path.join(cwd, "report"), "--show-details", "--highlight", "--ignore-errors", "source", "--legend", os.path.join(cwd, "output.info"), "--prefix", src_dir]) From 02839f81e9fcef2e861ac63a93fe8ad592d10b6b Mon Sep 17 00:00:00 2001 From: James Graham Date: Fri, 17 Mar 2017 14:11:22 +0000 Subject: [PATCH 005/134] Add an option to skip downloading or processing files. Sometimes it happens that you already have the data files and just want to generate a report. Add command line options to skip the download and processing for this scenario. --- code-coverage.py | 21 ++++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) diff --git a/code-coverage.py b/code-coverage.py index 2f4c165b0..0743df293 100644 --- a/code-coverage.py +++ b/code-coverage.py @@ -118,20 +118,27 @@ def main(): parser.add_argument("branch", action="store", nargs='?', help="Branch on which jobs ran") parser.add_argument("commit", action="store", nargs='?', help="Commit hash for push") parser.add_argument("--grcov", action="store", nargs='?', default="grcov", help="Path to grcov") + parser.add_argument("--no-download", action="store_true", help="Use already downloaded coverage files") + parser.add_argument("--no-grcov", action="store_true", help="Use already generated grcov output (implies --no-download)") args = parser.parse_args() - if (args.branch is None and args.commit is not None) or (args.branch is not None and args.commit is None): + if args.no_grcov: + args.no_download = True + + if (args.branch is None) != (args.commit is None) and not args.no_download: parser.print_help() return - if args.branch is None and args.commit is None: - task_id = get_last_task() - else: - task_id = get_task(args.branch, args.commit) + if not args.no_download: + if args.branch is None and args.commit is None: + task_id = get_last_task() + else: + task_id = get_task(args.branch, args.commit) - download_coverage_artifacts(task_id) + download_coverage_artifacts(task_id) - generate_info(args.grcov) + if not args.no_grcov: + generate_info(args.grcov) generate_report(os.path.abspath(args.src_dir)) From d0e07f5aa277217e9ee819ac1157ec863b63a929 Mon Sep 17 00:00:00 2001 From: Marco Castelluccio Date: Thu, 27 Apr 2017 12:01:11 +0200 Subject: [PATCH 006/134] Download code coverage artifacts also if branch and commit are the default values --- code-coverage.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code-coverage.py b/code-coverage.py index 7c26c0047..790d2dd33 100644 --- a/code-coverage.py +++ b/code-coverage.py @@ -135,7 +135,7 @@ def main(): else: task_id = get_task(args.branch, args.commit) - download_coverage_artifacts(task_id) + download_coverage_artifacts(task_id) if not args.no_grcov: generate_info(args.grcov) From 69f3a6129cdd7bdd1cf97cf53e9a471257ffe26c Mon Sep 17 00:00:00 2001 From: Marco Castelluccio Date: Thu, 27 Apr 2017 17:34:06 +0200 Subject: [PATCH 007/134] Add some basic tests --- code-coverage.py => codecoverage.py | 0 tests/__init__.py | 0 tests/test.py | 38 +++++++++++++++++++++++++++++ 3 files changed, 38 insertions(+) rename code-coverage.py => codecoverage.py (100%) create mode 100644 tests/__init__.py create mode 100644 tests/test.py diff --git a/code-coverage.py b/codecoverage.py similarity index 100% rename from code-coverage.py rename to codecoverage.py diff --git a/tests/__init__.py b/tests/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/tests/test.py b/tests/test.py new file mode 100644 index 000000000..4892f8ffa --- /dev/null +++ b/tests/test.py @@ -0,0 +1,38 @@ +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this file, +# You can obtain one at http://mozilla.org/MPL/2.0/. + +import unittest +import os + +import codecoverage + +class Test(unittest.TestCase): + def test(self): + task_id = codecoverage.get_last_task() + self.assertTrue(task_id) + + task_data = codecoverage.get_task_details(task_id) + self.assertEqual(task_data['metadata']['name'], 'build-linux64-ccov/opt') + + revision = task_data['payload']['env']['GECKO_HEAD_REV'] + task_id_2 = codecoverage.get_task('mozilla-central', revision) + self.assertEqual(task_id, task_id_2) + + artifacts = codecoverage.get_task_artifacts(task_id) + chosen_artifact = None + for artifact in artifacts: + if artifact['name'] == 'public/build/target.txt': + chosen_artifact = artifact + self.assertIsNotNone(chosen_artifact) + + tasks = codecoverage.get_tasks_in_group(task_data['taskGroupId']) + self.assertIsInstance(tasks, list) + + codecoverage.download_artifact(task_id, chosen_artifact) + self.assertTrue(os.path.exists('ccov-artifacts/%s_target.txt' % task_id)) + + +if __name__ == '__main__': + unittest.main() + From 856306861c42fc066f2cb6783ffecfc15700e5f4 Mon Sep 17 00:00:00 2001 From: Marco Castelluccio Date: Thu, 27 Apr 2017 17:34:48 +0200 Subject: [PATCH 008/134] Run tests on Travis --- .travis.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.travis.yml b/.travis.yml index 65f1ad289..eaec75bca 100644 --- a/.travis.yml +++ b/.travis.yml @@ -4,3 +4,4 @@ install: - pip install -r test-requirements.txt script: - flake8 . + - python -m unittest discover tests From b173803e80170fc33ce9653b2cc617f8463b96ba Mon Sep 17 00:00:00 2001 From: Marco Castelluccio Date: Thu, 27 Apr 2017 17:35:38 +0200 Subject: [PATCH 009/134] Test both Python 2.7 and 3.5 --- .travis.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.travis.yml b/.travis.yml index eaec75bca..9d970befc 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,4 +1,7 @@ language: python +python: + - "2.7" + - "3.5" install: - pip install -r requirements.txt - pip install -r test-requirements.txt From 9c9d921f01cb38ceb50f9e8089c26a002585a84e Mon Sep 17 00:00:00 2001 From: Marco Castelluccio Date: Thu, 27 Apr 2017 17:38:32 +0200 Subject: [PATCH 010/134] Fix flake8 issues --- tests/test.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/test.py b/tests/test.py index 4892f8ffa..58fa79e29 100644 --- a/tests/test.py +++ b/tests/test.py @@ -7,6 +7,7 @@ import codecoverage + class Test(unittest.TestCase): def test(self): task_id = codecoverage.get_last_task() @@ -35,4 +36,3 @@ def test(self): if __name__ == '__main__': unittest.main() - From ff764b76b4f4c381a1981a19631faa1cfe90f14b Mon Sep 17 00:00:00 2001 From: Marco Castelluccio Date: Thu, 27 Apr 2017 17:40:14 +0200 Subject: [PATCH 011/134] Create ccov-artifacts if it doesn't exist --- tests/test.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/tests/test.py b/tests/test.py index 58fa79e29..0a7e5c307 100644 --- a/tests/test.py +++ b/tests/test.py @@ -30,6 +30,12 @@ def test(self): tasks = codecoverage.get_tasks_in_group(task_data['taskGroupId']) self.assertIsInstance(tasks, list) + try: + os.mkdir('ccov-artifacts') + except OSError as e: + if e.errno != errno.EEXIST: + raise e + codecoverage.download_artifact(task_id, chosen_artifact) self.assertTrue(os.path.exists('ccov-artifacts/%s_target.txt' % task_id)) From 1d604976fbfab6cffa2e4f60d9f02abd79588b92 Mon Sep 17 00:00:00 2001 From: Marco Castelluccio Date: Thu, 27 Apr 2017 17:41:01 +0200 Subject: [PATCH 012/134] Ignore error only if directory already exists --- codecoverage.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/codecoverage.py b/codecoverage.py index 790d2dd33..c850bf1dd 100644 --- a/codecoverage.py +++ b/codecoverage.py @@ -58,9 +58,10 @@ def download_coverage_artifacts(build_task_id): pass try: - os.mkdir("ccov-artifacts") - except: - pass + os.mkdir('ccov-artifacts') + except OSError as e: + if e.errno != errno.EEXIST: + raise e task_data = get_task_details(build_task_id) From 98a87f1d0c2e12a0a3944513b25f228452d3324e Mon Sep 17 00:00:00 2001 From: Marco Castelluccio Date: Thu, 27 Apr 2017 17:44:58 +0200 Subject: [PATCH 013/134] Import errno --- codecoverage.py | 1 + tests/test.py | 1 + 2 files changed, 2 insertions(+) diff --git a/codecoverage.py b/codecoverage.py index c850bf1dd..472ffba6c 100644 --- a/codecoverage.py +++ b/codecoverage.py @@ -1,3 +1,4 @@ +import errno import os import shutil import subprocess diff --git a/tests/test.py b/tests/test.py index 0a7e5c307..0e3643cef 100644 --- a/tests/test.py +++ b/tests/test.py @@ -3,6 +3,7 @@ # You can obtain one at http://mozilla.org/MPL/2.0/. import unittest +import errno import os import codecoverage From 9cc61eb08e2a5629bd87b82b2ac93c7899d3128e Mon Sep 17 00:00:00 2001 From: Marco Castelluccio Date: Thu, 27 Apr 2017 17:47:34 +0200 Subject: [PATCH 014/134] Add .gitignore --- .gitignore | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 .gitignore diff --git a/.gitignore b/.gitignore new file mode 100644 index 000000000..1c5f969be --- /dev/null +++ b/.gitignore @@ -0,0 +1,4 @@ +*~ +*.pyc +*.pyo +ccov-artifacts From cf824d4195fd3ad52a1586ac602393ee0c1c4c5a Mon Sep 17 00:00:00 2001 From: Marco Castelluccio Date: Thu, 27 Apr 2017 17:48:52 +0200 Subject: [PATCH 015/134] Cache pip directory --- .travis.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.travis.yml b/.travis.yml index 9d970befc..153d834ce 100644 --- a/.travis.yml +++ b/.travis.yml @@ -8,3 +8,4 @@ install: script: - flake8 . - python -m unittest discover tests +cache: pip From 90cc3e528d7314b40530cbcfab2eadd94bac7a2d Mon Sep 17 00:00:00 2001 From: Marco Castelluccio Date: Thu, 27 Apr 2017 18:01:20 +0200 Subject: [PATCH 016/134] Use urllib instead of the requests package --- codecoverage.py | 51 +++++++++++++++++++++++++++++-------------------- 1 file changed, 30 insertions(+), 21 deletions(-) diff --git a/codecoverage.py b/codecoverage.py index 472ffba6c..3bd1603f0 100644 --- a/codecoverage.py +++ b/codecoverage.py @@ -1,55 +1,64 @@ +import argparse import errno +import json import os import shutil import subprocess import time -import argparse -import requests +try: + from urllib.parse import urlencode + from urllib.request import urlopen, urlretrieve +except ImportError: + from urllib import urlencode, urlretrieve + from urllib2 import urlopen + + +def get_json(url, params=None): + if params is not None: + url += '?' + urlencode(params) + + r = urlopen(url).read().decode('utf-8') + + return json.loads(r) def get_last_task(): - r = requests.get('https://index.taskcluster.net/v1/task/gecko.v2.mozilla-central.latest.firefox.linux64-ccov-opt') - last_task = r.json() + last_task = get_json('https://index.taskcluster.net/v1/task/gecko.v2.mozilla-central.latest.firefox.linux64-ccov-opt') return last_task['taskId'] def get_task(branch, revision): - r = requests.get('https://index.taskcluster.net/v1/task/gecko.v2.%s.revision.%s.firefox.linux64-ccov-opt' % (branch, revision)) - task = r.json() + task = get_json('https://index.taskcluster.net/v1/task/gecko.v2.%s.revision.%s.firefox.linux64-ccov-opt' % (branch, revision)) return task['taskId'] def get_task_details(task_id): - r = requests.get('https://queue.taskcluster.net/v1/task/' + task_id) - return r.json() + task_details = get_json('https://queue.taskcluster.net/v1/task/' + task_id) + return task_details def get_task_artifacts(task_id): - r = requests.get('https://queue.taskcluster.net/v1/task/' + task_id + '/artifacts') - return r.json()['artifacts'] + artifacts = get_json('https://queue.taskcluster.net/v1/task/' + task_id + '/artifacts') + return artifacts['artifacts'] def get_tasks_in_group(group_id): - r = requests.get('https://queue.taskcluster.net/v1/task-group/' + group_id + '/list', params={ - 'limit': 200 + reply = get_json('https://queue.taskcluster.net/v1/task-group/' + group_id + '/list', { + 'limit': '200', }) - reply = r.json() tasks = reply['tasks'] while 'continuationToken' in reply: - r = requests.get('https://queue.taskcluster.net/v1/task-group/' + group_id + '/list', params={ - 'limit': 200, - 'continuationToken': reply['continuationToken'] + reply = get_json('https://queue.taskcluster.net/v1/task-group/' + group_id + '/list', { + 'limit': '200', + 'continuationToken': reply['continuationToken'], }) - reply = r.json() tasks += reply['tasks'] return tasks def download_artifact(task_id, artifact): - r = requests.get('https://queue.taskcluster.net/v1/task/' + task_id + '/artifacts/' + artifact['name'], stream=True) - with open(os.path.join('ccov-artifacts', task_id + '_' + os.path.basename(artifact['name'])), 'wb') as f: - r.raw.decode_content = True - shutil.copyfileobj(r.raw, f) + fname = os.path.join('ccov-artifacts', task_id + '_' + os.path.basename(artifact['name'])) + urlretrieve('https://queue.taskcluster.net/v1/task/' + task_id + '/artifacts/' + artifact['name'], fname) def download_coverage_artifacts(build_task_id): From e12b2e1bdb6eae95ae8e3d1dacf515ff0efcef76 Mon Sep 17 00:00:00 2001 From: Marco Castelluccio Date: Thu, 27 Apr 2017 18:01:54 +0200 Subject: [PATCH 017/134] Remove 'requests' from requirements. Fixes #6 --- .travis.yml | 1 - requirements.txt | 1 - 2 files changed, 2 deletions(-) delete mode 100644 requirements.txt diff --git a/.travis.yml b/.travis.yml index 153d834ce..aa4763406 100644 --- a/.travis.yml +++ b/.travis.yml @@ -3,7 +3,6 @@ python: - "2.7" - "3.5" install: - - pip install -r requirements.txt - pip install -r test-requirements.txt script: - flake8 . diff --git a/requirements.txt b/requirements.txt deleted file mode 100644 index ed84dd33e..000000000 --- a/requirements.txt +++ /dev/null @@ -1 +0,0 @@ -requests[security]>=2.7.0 From 9be8a5c26e0f7822c5e9ac4016ea95da2f6d8c8b Mon Sep 17 00:00:00 2001 From: Marco Castelluccio Date: Thu, 27 Apr 2017 18:18:50 +0200 Subject: [PATCH 018/134] Use MH_BRANCH and GECKO_HEAD_REV environment variables when they are defined. Fixes #8 --- codecoverage.py | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/codecoverage.py b/codecoverage.py index 472ffba6c..e5fea62a2 100644 --- a/codecoverage.py +++ b/codecoverage.py @@ -132,10 +132,12 @@ def main(): return if not args.no_download: - if args.branch is None and args.commit is None: - task_id = get_last_task() - else: + if args.branch and args.commit: task_id = get_task(args.branch, args.commit) + elif 'MH_BRANCH' in os.environ and 'GECKO_HEAD_REV' in os.environ: + task_id = get_task(os.environ['MH_BRANCH'], os.environ['GECKO_HEAD_REV']) + else: + task_id = get_last_task() download_coverage_artifacts(task_id) From 108e37dc8d0839bde6195975f7a28aa6f9b091ea Mon Sep 17 00:00:00 2001 From: Marco Castelluccio Date: Thu, 27 Apr 2017 18:41:12 +0200 Subject: [PATCH 019/134] Add gcc used during the build to the path when run on a one-click loaner. Fixes #7 --- codecoverage.py | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/codecoverage.py b/codecoverage.py index 472ffba6c..778d25f2a 100644 --- a/codecoverage.py +++ b/codecoverage.py @@ -91,10 +91,15 @@ def generate_info(grcov_path): else: ordered_files.append("ccov-artifacts/" + fname) + # Assume we're on a one-click loaner. + mod_env = os.environ.copy() + if os.path.isdir('/home/worker/workspace/build/src/gcc/bin'): + mod_env['PATH'] = '/home/worker/workspace/build/src/gcc/bin:' + mod_env['PATH'] + fout = open("output.info", 'w') cmd = [grcov_path, '-z', '-t', 'lcov', '-s', '/home/worker/workspace/build/src/'] cmd.extend(ordered_files) - proc = subprocess.Popen(cmd, stdout=fout, stderr=subprocess.PIPE) + proc = subprocess.Popen(cmd, stdout=fout, stderr=subprocess.PIPE, env=mod_env) i = 0 while proc.poll() is None: print('Running grcov... ' + str(i)) From 61b938caad7da9ccea571ed3a81efa47d42a9adf Mon Sep 17 00:00:00 2001 From: Marco Castelluccio Date: Fri, 28 Apr 2017 11:40:17 +0200 Subject: [PATCH 020/134] Support filtering artifacts by test suite. Fixes #1 --- codecoverage.py | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/codecoverage.py b/codecoverage.py index 472ffba6c..89d7fb652 100644 --- a/codecoverage.py +++ b/codecoverage.py @@ -52,7 +52,13 @@ def download_artifact(task_id, artifact): shutil.copyfileobj(r.raw, f) -def download_coverage_artifacts(build_task_id): +def suite_name_from_task_name(name): + name = name[len('test-linux64-ccov/opt-'):] + parts = [p for p in name.split('-') if p != 'e10s' and not p.isdigit()] + return '-'.join(parts) + + +def download_coverage_artifacts(build_task_id, suites): try: shutil.rmtree("ccov-artifacts") except: @@ -71,7 +77,8 @@ def download_coverage_artifacts(build_task_id): if 'target.code-coverage-gcno.zip' in artifact['name']: download_artifact(build_task_id, artifact) - test_tasks = [t for t in get_tasks_in_group(task_data['taskGroupId']) if t['task']['metadata']['name'].startswith('test-linux64-ccov')] + test_tasks = [t for t in get_tasks_in_group(task_data['taskGroupId']) if t['task']['metadata']['name'].startswith('test-linux64-ccov') and (suites is None or suite_name_from_task_name(t['task']['metadata']['name']) in suites)] + for test_task in test_tasks: artifacts = get_task_artifacts(test_task['status']['taskId']) for artifact in artifacts: @@ -122,6 +129,7 @@ def main(): parser.add_argument("--grcov", action="store", nargs='?', default="grcov", help="Path to grcov") parser.add_argument("--no-download", action="store_true", help="Use already downloaded coverage files") parser.add_argument("--no-grcov", action="store_true", help="Use already generated grcov output (implies --no-download)") + parser.add_argument("--suite", action="store", nargs='+', help="List of test suites to include (by default they are all included). E.g. 'mochitest', 'mochitest-chrome', 'gtest', etc.") args = parser.parse_args() if args.no_grcov: @@ -137,7 +145,7 @@ def main(): else: task_id = get_task(args.branch, args.commit) - download_coverage_artifacts(task_id) + download_coverage_artifacts(task_id, args.suite) if not args.no_grcov: generate_info(args.grcov) From e1bc0a4834d489afdd1efd814ea91d75e7710d75 Mon Sep 17 00:00:00 2001 From: Marco Castelluccio Date: Fri, 28 Apr 2017 11:40:51 +0200 Subject: [PATCH 021/134] Add unit test for suite_name_from_task_name --- tests/test.py | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/tests/test.py b/tests/test.py index 0e3643cef..1a86fa70a 100644 --- a/tests/test.py +++ b/tests/test.py @@ -40,6 +40,17 @@ def test(self): codecoverage.download_artifact(task_id, chosen_artifact) self.assertTrue(os.path.exists('ccov-artifacts/%s_target.txt' % task_id)) + def test_suite_name_from_task_name(self): + cases = [ + ('test-linux64-ccov/opt-gtest', 'gtest'), + ('test-linux64-ccov/opt-jsreftest-1', 'jsreftest'), + ('test-linux64-ccov/opt-mochitest-devtools-chrome-e10s-10', 'mochitest-devtools-chrome'), + ('test-linux64-ccov/opt-mochitest-clipboard', 'mochitest-clipboard'), + ('test-linux64-ccov/opt-reftest-no-accel-e10s-5', 'reftest-no-accel'), + ('test-linux64-ccov/opt-mochitest-5', 'mochitest'), + ] + for c in cases: + self.assertEqual(c[0], c[1]) if __name__ == '__main__': unittest.main() From c583d0a12ae35075f8b0ff6f97985b22c887d482 Mon Sep 17 00:00:00 2001 From: Marco Castelluccio Date: Fri, 28 Apr 2017 11:43:14 +0200 Subject: [PATCH 022/134] Fix flake8 issue --- tests/test.py | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/test.py b/tests/test.py index 1a86fa70a..0859161e9 100644 --- a/tests/test.py +++ b/tests/test.py @@ -52,5 +52,6 @@ def test_suite_name_from_task_name(self): for c in cases: self.assertEqual(c[0], c[1]) + if __name__ == '__main__': unittest.main() From 1c5e8508182117e4adffe9b2f5ee5d6f603384ae Mon Sep 17 00:00:00 2001 From: Marco Castelluccio Date: Fri, 28 Apr 2017 11:47:32 +0200 Subject: [PATCH 023/134] Actually call function that has to be tested --- tests/test.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/test.py b/tests/test.py index 0859161e9..d7b3579b1 100644 --- a/tests/test.py +++ b/tests/test.py @@ -50,7 +50,7 @@ def test_suite_name_from_task_name(self): ('test-linux64-ccov/opt-mochitest-5', 'mochitest'), ] for c in cases: - self.assertEqual(c[0], c[1]) + self.assertEqual(codecoverage.suite_name_from_task_name(c[0]), c[1]) if __name__ == '__main__': From 4e545a94c0b900b1116ae0e3011f7845cc43524f Mon Sep 17 00:00:00 2001 From: Marco Castelluccio Date: Fri, 28 Apr 2017 12:30:50 +0200 Subject: [PATCH 024/134] Auomatically download grcov. Fixes #5 --- codecoverage.py | 32 +++++++++++++++++++++++++++++++- 1 file changed, 31 insertions(+), 1 deletion(-) diff --git a/codecoverage.py b/codecoverage.py index 3bd1603f0..1ba8f1c13 100644 --- a/codecoverage.py +++ b/codecoverage.py @@ -4,6 +4,7 @@ import os import shutil import subprocess +import tarfile import time try: from urllib.parse import urlencode @@ -123,6 +124,29 @@ def generate_report(src_dir): os.chdir(cwd) +def download_grcov(): + r = get_json('https://api.github.com/repos/marco-c/grcov/releases/latest') + latest_tag = r['tag_name'] + + if os.path.exists('grcov') and os.path.exists('grcov_ver'): + with open('grcov_ver', 'r') as f: + installed_ver = f.read() + + if installed_ver == latest_tag: + return + + urlretrieve('https://github.com/marco-c/grcov/releases/download/%s/grcov-linux-x86_64.tar.bz2' % latest_tag, 'grcov.tar.bz2') + + tar = tarfile.open('grcov.tar.bz2', 'r:bz2') + tar.extractall() + tar.close() + + os.remove('grcov.tar.bz2') + + with open('grcov_ver', 'w') as f: + f.write(latest_tag) + + def main(): parser = argparse.ArgumentParser() parser.add_argument("src_dir", action="store", help="Path to the source directory") @@ -149,7 +173,13 @@ def main(): download_coverage_artifacts(task_id) if not args.no_grcov: - generate_info(args.grcov) + if args.grcov: + grcov_path = args.grcov + else: + download_grcov() + grcov_path = './grcov' + + generate_info(grcov_path) generate_report(os.path.abspath(args.src_dir)) From 74c36124da178f6e462b3dc265d3d29f03a827ca Mon Sep 17 00:00:00 2001 From: Marco Castelluccio Date: Fri, 28 Apr 2017 12:31:03 +0200 Subject: [PATCH 025/134] Add basic test for grcov downloading --- tests/test.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/tests/test.py b/tests/test.py index 0e3643cef..c2f264367 100644 --- a/tests/test.py +++ b/tests/test.py @@ -40,6 +40,11 @@ def test(self): codecoverage.download_artifact(task_id, chosen_artifact) self.assertTrue(os.path.exists('ccov-artifacts/%s_target.txt' % task_id)) + def test_download_grcov(self): + codecoverage.download_grcov() + self.assertTrue(os.path.exists('grcov')) + self.assertTrue(os.path.exists('grcov_ver')) + if __name__ == '__main__': unittest.main() From de77f2730cc7a91650d96ededce399ded031da77 Mon Sep 17 00:00:00 2001 From: Marco Castelluccio Date: Fri, 28 Apr 2017 18:36:18 +0200 Subject: [PATCH 026/134] Use 'ignore_errors' parameter for ignoring errors in shutil.rmtree --- codecoverage.py | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/codecoverage.py b/codecoverage.py index 89d7fb652..95aba1aee 100644 --- a/codecoverage.py +++ b/codecoverage.py @@ -59,10 +59,7 @@ def suite_name_from_task_name(name): def download_coverage_artifacts(build_task_id, suites): - try: - shutil.rmtree("ccov-artifacts") - except: - pass + shutil.rmtree('ccov-artifacts', ignore_errors=True) try: os.mkdir('ccov-artifacts') From 938c171ed2f4bd96eab8c7bade91461e285eb612 Mon Sep 17 00:00:00 2001 From: Marco Castelluccio Date: Fri, 28 Apr 2017 18:52:06 +0200 Subject: [PATCH 027/134] Simplify code to filter tasks --- codecoverage.py | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/codecoverage.py b/codecoverage.py index 95aba1aee..161802df6 100644 --- a/codecoverage.py +++ b/codecoverage.py @@ -74,7 +74,15 @@ def download_coverage_artifacts(build_task_id, suites): if 'target.code-coverage-gcno.zip' in artifact['name']: download_artifact(build_task_id, artifact) - test_tasks = [t for t in get_tasks_in_group(task_data['taskGroupId']) if t['task']['metadata']['name'].startswith('test-linux64-ccov') and (suites is None or suite_name_from_task_name(t['task']['metadata']['name']) in suites)] + # Returns True if the task is a test-related task. + def _is_test_task(t): + return t['task']['metadata']['name'].startswith('test-linux64-ccov') + + # Returns True if the task is part of one of the suites chosen by the user. + def _is_chosen_task(t): + return suites is None or suite_name_from_task_name(t['task']['metadata']['name']) in suites + + test_tasks = [t for t in get_tasks_in_group(task_data['taskGroupId']) if _is_test_task(t) and _is_chosen_task(t)] for test_task in test_tasks: artifacts = get_task_artifacts(test_task['status']['taskId']) From 6dd48b397e6a08b06a8c0ad365f3bba9fae742c2 Mon Sep 17 00:00:00 2001 From: Marco Castelluccio Date: Fri, 28 Apr 2017 19:01:14 +0200 Subject: [PATCH 028/134] Print warning when a suite couldn't be found --- codecoverage.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/codecoverage.py b/codecoverage.py index bb4d9e5fe..c4a13eb96 100644 --- a/codecoverage.py +++ b/codecoverage.py @@ -11,6 +11,7 @@ except ImportError: from urllib import urlencode, urlretrieve from urllib2 import urlopen +import warnings def get_json(url, params=None): @@ -93,6 +94,10 @@ def _is_chosen_task(t): test_tasks = [t for t in get_tasks_in_group(task_data['taskGroupId']) if _is_test_task(t) and _is_chosen_task(t)] + for suite in suites: + if not any(suite in t['task']['metadata']['name'] for t in test_tasks): + warnings.warn('Suite %s not found' % suite) + for test_task in test_tasks: artifacts = get_task_artifacts(test_task['status']['taskId']) for artifact in artifacts: From 4dc9c8ab4782ed08ac8a1cd0d08572c1cbb337c2 Mon Sep 17 00:00:00 2001 From: Marco Castelluccio Date: Fri, 28 Apr 2017 19:10:11 +0200 Subject: [PATCH 029/134] Download standalone version of grcov, to avoid issues with old libc versions on one-click loaners --- codecoverage.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/codecoverage.py b/codecoverage.py index e0ca723aa..da6e92073 100644 --- a/codecoverage.py +++ b/codecoverage.py @@ -152,7 +152,7 @@ def download_grcov(): if installed_ver == latest_tag: return - urlretrieve('https://github.com/marco-c/grcov/releases/download/%s/grcov-linux-x86_64.tar.bz2' % latest_tag, 'grcov.tar.bz2') + urlretrieve('https://github.com/marco-c/grcov/releases/download/%s/grcov-linux-standalone-x86_64.tar.bz2' % latest_tag, 'grcov.tar.bz2') tar = tarfile.open('grcov.tar.bz2', 'r:bz2') tar.extractall() From 4ae6df8f06ce47c99ee0ac2ccbfc59b693baa254 Mon Sep 17 00:00:00 2001 From: Marco Castelluccio Date: Fri, 28 Apr 2017 19:16:02 +0200 Subject: [PATCH 030/134] Test download_grcov more thoroughly --- tests/test.py | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/tests/test.py b/tests/test.py index e4bc8262e..f6bb25cf9 100644 --- a/tests/test.py +++ b/tests/test.py @@ -57,6 +57,34 @@ def test_download_grcov(self): self.assertTrue(os.path.exists('grcov')) self.assertTrue(os.path.exists('grcov_ver')) + with open('grcov_ver', 'r') as f: + ver = f.read() + + # grcov is downloaded again if the executable doesn't exist. + os.remove('grcov') + codecoverage.download_grcov() + self.assertTrue(os.path.exists('grcov')) + self.assertTrue(os.path.exists('grcov_ver')) + + # grcov isn't downloaded again if the executable exists and the version is the same. + with open('grcov', 'w') as f: + f.write('prova') + + codecoverage.download_grcov() + + with open('grcov', 'r') as f: + self.assertEqual('prova', f.read()) + + # grcov is overwritten if the version changes. + with open('grcov_ver', 'w') as f: + f.write('v0.0.0') + + codecoverage.download_grcov() + + self.assertTrue(os.path.getsize('grcov') > 5) + with open('grcov_ver', 'r') as f: + self.assertEqual(ver, f.read()) + if __name__ == '__main__': unittest.main() From 5d4f800291b283f48c6045469053c359373f878e Mon Sep 17 00:00:00 2001 From: Marco Castelluccio Date: Fri, 28 Apr 2017 20:21:43 +0200 Subject: [PATCH 031/134] Small refactoring using one_click_loaner_gcc variable --- codecoverage.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/codecoverage.py b/codecoverage.py index 66dedcca0..75ce64894 100644 --- a/codecoverage.py +++ b/codecoverage.py @@ -118,10 +118,10 @@ def generate_info(grcov_path): else: ordered_files.append("ccov-artifacts/" + fname) - # Assume we're on a one-click loaner. + one_click_loaner_gcc = '/home/worker/workspace/build/src/gcc/bin' mod_env = os.environ.copy() - if os.path.isdir('/home/worker/workspace/build/src/gcc/bin'): - mod_env['PATH'] = '/home/worker/workspace/build/src/gcc/bin:' + mod_env['PATH'] + if os.path.isdir(one_click_loaner_gcc): + mod_env['PATH'] = one_click_loaner_gcc + ':' + mod_env['PATH'] fout = open("output.info", 'w') cmd = [grcov_path, '-z', '-t', 'lcov', '-s', '/home/worker/workspace/build/src/'] From 39016d32d9c9a0710074571acf87a5bc656c95fd Mon Sep 17 00:00:00 2001 From: Marco Castelluccio Date: Fri, 28 Apr 2017 20:33:49 +0200 Subject: [PATCH 032/134] Also wait if the directory is empty --- codecoverage.py | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/codecoverage.py b/codecoverage.py index 75ce64894..6c9125cbe 100644 --- a/codecoverage.py +++ b/codecoverage.py @@ -118,9 +118,14 @@ def generate_info(grcov_path): else: ordered_files.append("ccov-artifacts/" + fname) - one_click_loaner_gcc = '/home/worker/workspace/build/src/gcc/bin' mod_env = os.environ.copy() - if os.path.isdir(one_click_loaner_gcc): + if 'TASKCLUSTER_INTERACTIVE' in os.environ: # We're on a one-click loaner. + one_click_loaner_gcc = '/home/worker/workspace/build/src/gcc/bin' + i = 0 + while not os.path.isdir(one_click_loaner_gcc) or len(os.listdir(one_click_loaner_gcc)) == 0: + print('Waiting one-click loaner to be ready... ' + str(i)) + i += 1 + time.sleep(60) mod_env['PATH'] = one_click_loaner_gcc + ':' + mod_env['PATH'] fout = open("output.info", 'w') From f133d20ad521260ed1cdca51687b4384a51d7811 Mon Sep 17 00:00:00 2001 From: Marco Castelluccio Date: Fri, 28 Apr 2017 20:37:14 +0200 Subject: [PATCH 033/134] Fix flake8 issues --- codecoverage.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/codecoverage.py b/codecoverage.py index 6c9125cbe..673089a2e 100644 --- a/codecoverage.py +++ b/codecoverage.py @@ -119,7 +119,7 @@ def generate_info(grcov_path): ordered_files.append("ccov-artifacts/" + fname) mod_env = os.environ.copy() - if 'TASKCLUSTER_INTERACTIVE' in os.environ: # We're on a one-click loaner. + if 'TASKCLUSTER_INTERACTIVE' in os.environ: # We're on a one-click loaner. one_click_loaner_gcc = '/home/worker/workspace/build/src/gcc/bin' i = 0 while not os.path.isdir(one_click_loaner_gcc) or len(os.listdir(one_click_loaner_gcc)) == 0: From c920ce713ab0cae1f503f35b1effb3adf9f4d0bd Mon Sep 17 00:00:00 2001 From: Marco Castelluccio Date: Fri, 28 Apr 2017 21:05:20 +0200 Subject: [PATCH 034/134] Don't assume grcov is installed globally --- codecoverage.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/codecoverage.py b/codecoverage.py index 673089a2e..271350a8e 100644 --- a/codecoverage.py +++ b/codecoverage.py @@ -179,7 +179,7 @@ def main(): parser.add_argument("src_dir", action="store", help="Path to the source directory") parser.add_argument("branch", action="store", nargs='?', help="Branch on which jobs ran") parser.add_argument("commit", action="store", nargs='?', help="Commit hash for push") - parser.add_argument("--grcov", action="store", nargs='?', default="grcov", help="Path to grcov") + parser.add_argument("--grcov", action="store", nargs='?', help="Path to grcov") parser.add_argument("--no-download", action="store_true", help="Use already downloaded coverage files") parser.add_argument("--no-grcov", action="store_true", help="Use already generated grcov output (implies --no-download)") parser.add_argument("--suite", action="store", nargs='+', help="List of test suites to include (by default they are all included). E.g. 'mochitest', 'mochitest-chrome', 'gtest', etc.") From e8474d0ddf7bc8a307a608bc34e2879d05ef7adf Mon Sep 17 00:00:00 2001 From: Marco Castelluccio Date: Sat, 29 Apr 2017 00:06:11 +0200 Subject: [PATCH 035/134] Basic tests for other codecoverage.py functions --- tests/test.py | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/tests/test.py b/tests/test.py index f6bb25cf9..6938829c0 100644 --- a/tests/test.py +++ b/tests/test.py @@ -40,6 +40,16 @@ def test(self): codecoverage.download_artifact(task_id, chosen_artifact) self.assertTrue(os.path.exists('ccov-artifacts/%s_target.txt' % task_id)) + codecoverage.download_coverage_artifacts(task_id, 'gtest') + self.assertTrue(len(os.listdir('ccov-artifacts')) == 2) + + codecoverage.download_grcov() + codecoverage.generate_info('./grcov') + self.assertTrue(os.path.exists('output.info')) + + codecoverage.generate_report('gecko-dev') + self.assertTrue(os.path.isdir('report')) + def test_suite_name_from_task_name(self): cases = [ ('test-linux64-ccov/opt-gtest', 'gtest'), From 97b2b186e3d1e775c2c977956b784d79d9e38049 Mon Sep 17 00:00:00 2001 From: Marco Castelluccio Date: Sat, 29 Apr 2017 00:09:09 +0200 Subject: [PATCH 036/134] Install lcov (for genhtml) --- .travis.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.travis.yml b/.travis.yml index aa4763406..10dae1090 100644 --- a/.travis.yml +++ b/.travis.yml @@ -4,7 +4,10 @@ python: - "3.5" install: - pip install -r test-requirements.txt + - mkdir -p symlinks + - git clone https://github.com/linux-test-project/lcov.git && cd lcov && make install DESTDIR=../symlinks && cd .. script: + - export PATH=$HOME/.local/bin:$PWD/symlinks:$PWD/symlinks/usr/local/bin:$PATH - flake8 . - python -m unittest discover tests cache: pip From 694ad7fb0749007d58f5f3ec0920861a110bd4de Mon Sep 17 00:00:00 2001 From: Marco Castelluccio Date: Sat, 29 Apr 2017 00:36:55 +0200 Subject: [PATCH 037/134] Cleanup after tests --- tests/test.py | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/tests/test.py b/tests/test.py index 6938829c0..444400b74 100644 --- a/tests/test.py +++ b/tests/test.py @@ -5,11 +5,23 @@ import unittest import errno import os +import shutil import codecoverage class Test(unittest.TestCase): + @classmethod + def tearDownClass(cls): + shutil.rmtree('report', ignore_errors=True) + shutil.rmtree('ccov-artifacts', ignore_errors=True) + for f in ['grcov', 'grcov_ver', 'output.info']: + try: + os.remove(f) + except OSError as e: + if e.errno != errno.ENOENT: + raise e + def test(self): task_id = codecoverage.get_last_task() self.assertTrue(task_id) @@ -47,7 +59,7 @@ def test(self): codecoverage.generate_info('./grcov') self.assertTrue(os.path.exists('output.info')) - codecoverage.generate_report('gecko-dev') + codecoverage.generate_report('tests') self.assertTrue(os.path.isdir('report')) def test_suite_name_from_task_name(self): From c2a003c7f38a4b41b5852a47dcd7fe9672bbb8f1 Mon Sep 17 00:00:00 2001 From: Marco Castelluccio Date: Sat, 29 Apr 2017 01:15:44 +0200 Subject: [PATCH 038/134] Install and use GCC 6 --- .travis.yml | 8 ++++++++ tests/test.py | 2 +- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 10dae1090..4637ccb0a 100644 --- a/.travis.yml +++ b/.travis.yml @@ -5,9 +5,17 @@ python: install: - pip install -r test-requirements.txt - mkdir -p symlinks + - ln -s /usr/bin/gcc-6 symlinks/gcc + - ln -s /usr/bin/gcov-6 symlinks/gcov - git clone https://github.com/linux-test-project/lcov.git && cd lcov && make install DESTDIR=../symlinks && cd .. script: - export PATH=$HOME/.local/bin:$PWD/symlinks:$PWD/symlinks/usr/local/bin:$PATH - flake8 . - python -m unittest discover tests cache: pip +addons: + apt: + sources: + - ubuntu-toolchain-r-test + packages: + - gcc-6 diff --git a/tests/test.py b/tests/test.py index 444400b74..6aa8b2731 100644 --- a/tests/test.py +++ b/tests/test.py @@ -52,7 +52,7 @@ def test(self): codecoverage.download_artifact(task_id, chosen_artifact) self.assertTrue(os.path.exists('ccov-artifacts/%s_target.txt' % task_id)) - codecoverage.download_coverage_artifacts(task_id, 'gtest') + codecoverage.download_coverage_artifacts(task_id, 'cppunit') self.assertTrue(len(os.listdir('ccov-artifacts')) == 2) codecoverage.download_grcov() From 6d72673cffcaadef6f361914b7e8607d9db3382c Mon Sep 17 00:00:00 2001 From: Marco Castelluccio Date: Sat, 6 May 2017 01:26:16 +0200 Subject: [PATCH 039/134] Don't fail when the suite argument is undefined --- codecoverage.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/codecoverage.py b/codecoverage.py index 271350a8e..7924dd878 100644 --- a/codecoverage.py +++ b/codecoverage.py @@ -95,9 +95,10 @@ def _is_chosen_task(t): test_tasks = [t for t in get_tasks_in_group(task_data['taskGroupId']) if _is_test_task(t) and _is_chosen_task(t)] - for suite in suites: - if not any(suite in t['task']['metadata']['name'] for t in test_tasks): - warnings.warn('Suite %s not found' % suite) + if suites is not None: + for suite in suites: + if not any(suite in t['task']['metadata']['name'] for t in test_tasks): + warnings.warn('Suite %s not found' % suite) for test_task in test_tasks: artifacts = get_task_artifacts(test_task['status']['taskId']) From 4aaa08296ee53611bdc1eb96dbe2d15ed3f6c550 Mon Sep 17 00:00:00 2001 From: Marco Castelluccio Date: Sat, 6 May 2017 01:26:38 +0200 Subject: [PATCH 040/134] No need to add ~/.local/bin to the path --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 4637ccb0a..7814873e9 100644 --- a/.travis.yml +++ b/.travis.yml @@ -9,7 +9,7 @@ install: - ln -s /usr/bin/gcov-6 symlinks/gcov - git clone https://github.com/linux-test-project/lcov.git && cd lcov && make install DESTDIR=../symlinks && cd .. script: - - export PATH=$HOME/.local/bin:$PWD/symlinks:$PWD/symlinks/usr/local/bin:$PATH + - export PATH=$PWD/symlinks:$PWD/symlinks/usr/local/bin:$PATH - flake8 . - python -m unittest discover tests cache: pip From b698934cd209585dcbd388ffcd03b4d582b46c36 Mon Sep 17 00:00:00 2001 From: Marco Castelluccio Date: Sat, 6 May 2017 02:21:53 +0200 Subject: [PATCH 041/134] Set default src_dir when running on a one-click loaner. Fixes #16 --- codecoverage.py | 26 ++++++++++++++++++++------ 1 file changed, 20 insertions(+), 6 deletions(-) diff --git a/codecoverage.py b/codecoverage.py index 7924dd878..cc3680b7d 100644 --- a/codecoverage.py +++ b/codecoverage.py @@ -24,6 +24,10 @@ def get_json(url, params=None): return json.loads(r) +def is_taskcluster_loaner(): + return 'TASKCLUSTER_INTERACTIVE' in os.environ + + def get_last_task(): last_task = get_json('https://index.taskcluster.net/v1/task/gecko.v2.mozilla-central.latest.firefox.linux64-ccov-opt') return last_task['taskId'] @@ -120,7 +124,7 @@ def generate_info(grcov_path): ordered_files.append("ccov-artifacts/" + fname) mod_env = os.environ.copy() - if 'TASKCLUSTER_INTERACTIVE' in os.environ: # We're on a one-click loaner. + if is_taskcluster_loaner(): one_click_loaner_gcc = '/home/worker/workspace/build/src/gcc/bin' i = 0 while not os.path.isdir(one_click_loaner_gcc) or len(os.listdir(one_click_loaner_gcc)) == 0: @@ -177,9 +181,21 @@ def download_grcov(): def main(): parser = argparse.ArgumentParser() - parser.add_argument("src_dir", action="store", help="Path to the source directory") - parser.add_argument("branch", action="store", nargs='?', help="Branch on which jobs ran") - parser.add_argument("commit", action="store", nargs='?', help="Commit hash for push") + + if is_taskcluster_loaner(): + nargs = '?' + default_src_dir = '/home/worker/workspace/build/src/' + default_branch = os.environ['MH_BRANCH'] + default_commit = os.environ['GECKO_HEAD_REV'] + else: + nargs = None + default_src_dir = None + default_branch = None + default_commit = None + + parser.add_argument("src_dir", action="store", nargs=nargs, default=default_src_dir, help="Path to the source directory") + parser.add_argument("branch", action="store", nargs='?', default=default_branch, help="Branch on which jobs ran") + parser.add_argument("commit", action="store", nargs='?', default=default_commit, help="Commit hash for push") parser.add_argument("--grcov", action="store", nargs='?', help="Path to grcov") parser.add_argument("--no-download", action="store_true", help="Use already downloaded coverage files") parser.add_argument("--no-grcov", action="store_true", help="Use already generated grcov output (implies --no-download)") @@ -196,8 +212,6 @@ def main(): if not args.no_download: if args.branch and args.commit: task_id = get_task(args.branch, args.commit) - elif 'MH_BRANCH' in os.environ and 'GECKO_HEAD_REV' in os.environ: - task_id = get_task(os.environ['MH_BRANCH'], os.environ['GECKO_HEAD_REV']) else: task_id = get_last_task() From 19d1e355986f0f68b977fddbba3918b267540a0f Mon Sep 17 00:00:00 2001 From: Marco Castelluccio Date: Sat, 6 May 2017 02:56:27 +0200 Subject: [PATCH 042/134] Install genhtml in a subfolder. Fixes #17 --- codecoverage.py | 22 +++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/codecoverage.py b/codecoverage.py index 7924dd878..647a45756 100644 --- a/codecoverage.py +++ b/codecoverage.py @@ -146,7 +146,7 @@ def generate_info(grcov_path): def generate_report(src_dir): cwd = os.getcwd() os.chdir(src_dir) - ret = subprocess.call(["genhtml", "-o", os.path.join(cwd, "report"), "--show-details", "--highlight", "--ignore-errors", "source", "--legend", os.path.join(cwd, "output.info"), "--prefix", src_dir]) + ret = subprocess.call([os.path.join(cwd, "lcov-bin/usr/local/bin/genhtml"), "-o", os.path.join(cwd, "report"), "--show-details", "--highlight", "--ignore-errors", "source", "--legend", os.path.join(cwd, "output.info"), "--prefix", src_dir]) if ret != 0: raise Exception("Error while running genhtml.") os.chdir(cwd) @@ -175,6 +175,25 @@ def download_grcov(): f.write(latest_tag) +def download_genhtml(): + try: + os.mkdir('lcov-bin') + except OSError as e: + if e.errno != errno.EEXIST: + raise e + + if os.path.isdir('lcov'): + os.chdir('lcov') + subprocess.check_call(['git', 'pull']) + else: + subprocess.check_call(['git', 'clone', 'https://github.com/linux-test-project/lcov.git']) + os.chdir('lcov') + + subprocess.check_call(['make', 'install', 'DESTDIR=../lcov-bin']) + + os.chdir('..') + + def main(): parser = argparse.ArgumentParser() parser.add_argument("src_dir", action="store", help="Path to the source directory") @@ -212,6 +231,7 @@ def main(): generate_info(grcov_path) + download_genhtml() generate_report(os.path.abspath(args.src_dir)) From 955b54c5f3428de7efe129b4f2f36d6533956c22 Mon Sep 17 00:00:00 2001 From: Marco Castelluccio Date: Sat, 6 May 2017 03:03:44 +0200 Subject: [PATCH 043/134] Add basic test for download_genhtml --- tests/test.py | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/tests/test.py b/tests/test.py index 6aa8b2731..5bbc263de 100644 --- a/tests/test.py +++ b/tests/test.py @@ -13,8 +13,9 @@ class Test(unittest.TestCase): @classmethod def tearDownClass(cls): - shutil.rmtree('report', ignore_errors=True) - shutil.rmtree('ccov-artifacts', ignore_errors=True) + for d in ['report', 'ccov-artifacts', 'lcov', 'lcov-bin']: + shutil.rmtree(d, ignore_errors=True) + for f in ['grcov', 'grcov_ver', 'output.info']: try: os.remove(f) @@ -107,6 +108,13 @@ def test_download_grcov(self): with open('grcov_ver', 'r') as f: self.assertEqual(ver, f.read()) + def test_download_genhtml(self): + codecoverage.download_genhtml() + self.assertTrue(os.path.exists('./lcov-bin/usr/local/bin/genhtml')) + + codecoverage.download_genhtml() + self.assertTrue(os.path.exists('./lcov-bin/usr/local/bin/genhtml')) + if __name__ == '__main__': unittest.main() From 2b2b5aec4fe3785fe5fbfd5fd4d9d58ff7a1ea80 Mon Sep 17 00:00:00 2001 From: Marco Castelluccio Date: Sat, 6 May 2017 03:04:21 +0200 Subject: [PATCH 044/134] Don't download and install genhtml manually as part of the Travis build --- .travis.yml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index 7814873e9..f632db188 100644 --- a/.travis.yml +++ b/.travis.yml @@ -7,9 +7,8 @@ install: - mkdir -p symlinks - ln -s /usr/bin/gcc-6 symlinks/gcc - ln -s /usr/bin/gcov-6 symlinks/gcov - - git clone https://github.com/linux-test-project/lcov.git && cd lcov && make install DESTDIR=../symlinks && cd .. script: - - export PATH=$PWD/symlinks:$PWD/symlinks/usr/local/bin:$PATH + - export PATH=$PWD/symlinks:$PATH - flake8 . - python -m unittest discover tests cache: pip From 58c274f42443e74d735c214cd3b71c8d223f2db1 Mon Sep 17 00:00:00 2001 From: Marco Castelluccio Date: Sat, 6 May 2017 03:08:23 +0200 Subject: [PATCH 045/134] Add missing download_genhtml call --- tests/test.py | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/test.py b/tests/test.py index 5bbc263de..4438b1d20 100644 --- a/tests/test.py +++ b/tests/test.py @@ -60,6 +60,7 @@ def test(self): codecoverage.generate_info('./grcov') self.assertTrue(os.path.exists('output.info')) + codecoverage.download_genhtml() codecoverage.generate_report('tests') self.assertTrue(os.path.isdir('report')) From 4a813c8aa8d0f90892a6af8dd7ec98285b64a6f7 Mon Sep 17 00:00:00 2001 From: Marco Castelluccio Date: Wed, 31 May 2017 16:09:53 +0100 Subject: [PATCH 046/134] Fix prefix-dir argument name --- codecoverage.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/codecoverage.py b/codecoverage.py index f2b907e9f..a4ad2ec5f 100644 --- a/codecoverage.py +++ b/codecoverage.py @@ -134,7 +134,7 @@ def generate_info(grcov_path): mod_env['PATH'] = one_click_loaner_gcc + ':' + mod_env['PATH'] fout = open("output.info", 'w') - cmd = [grcov_path, '-z', '-t', 'lcov', '-s', '/home/worker/workspace/build/src/'] + cmd = [grcov_path, '-z', '-t', 'lcov', '-p', '/home/worker/workspace/build/src/'] cmd.extend(ordered_files) proc = subprocess.Popen(cmd, stdout=fout, stderr=subprocess.PIPE, env=mod_env) i = 0 From 5c8bc65ab17aa101183fdae5ed56fddf210a3620 Mon Sep 17 00:00:00 2001 From: Marco Castelluccio Date: Fri, 16 Jun 2017 12:56:45 +0100 Subject: [PATCH 047/134] '-z' grcov parameter is no longer needed --- codecoverage.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/codecoverage.py b/codecoverage.py index a4ad2ec5f..0b0f78968 100644 --- a/codecoverage.py +++ b/codecoverage.py @@ -134,7 +134,7 @@ def generate_info(grcov_path): mod_env['PATH'] = one_click_loaner_gcc + ':' + mod_env['PATH'] fout = open("output.info", 'w') - cmd = [grcov_path, '-z', '-t', 'lcov', '-p', '/home/worker/workspace/build/src/'] + cmd = [grcov_path, '-t', 'lcov', '-p', '/home/worker/workspace/build/src/'] cmd.extend(ordered_files) proc = subprocess.Popen(cmd, stdout=fout, stderr=subprocess.PIPE, env=mod_env) i = 0 From 5a9c01b7b447b6d55d70a45bf46b0e61d21cb97b Mon Sep 17 00:00:00 2001 From: Marco Castelluccio Date: Tue, 22 May 2018 14:19:48 -0700 Subject: [PATCH 048/134] Rename ccov build from opt to debug. Fixes #22 --- codecoverage.py | 6 +++--- tests/test.py | 14 +++++++------- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/codecoverage.py b/codecoverage.py index 0b0f78968..760fa1263 100644 --- a/codecoverage.py +++ b/codecoverage.py @@ -29,12 +29,12 @@ def is_taskcluster_loaner(): def get_last_task(): - last_task = get_json('https://index.taskcluster.net/v1/task/gecko.v2.mozilla-central.latest.firefox.linux64-ccov-opt') + last_task = get_json('https://index.taskcluster.net/v1/task/gecko.v2.mozilla-central.latest.firefox.linux64-ccov-debug') return last_task['taskId'] def get_task(branch, revision): - task = get_json('https://index.taskcluster.net/v1/task/gecko.v2.%s.revision.%s.firefox.linux64-ccov-opt' % (branch, revision)) + task = get_json('https://index.taskcluster.net/v1/task/gecko.v2.%s.revision.%s.firefox.linux64-ccov-debug' % (branch, revision)) return task['taskId'] @@ -68,7 +68,7 @@ def download_artifact(task_id, artifact): def suite_name_from_task_name(name): - name = name[len('test-linux64-ccov/opt-'):] + name = name[len('test-linux64-ccov/debug-'):] parts = [p for p in name.split('-') if p != 'e10s' and not p.isdigit()] return '-'.join(parts) diff --git a/tests/test.py b/tests/test.py index 4438b1d20..c416e4d7e 100644 --- a/tests/test.py +++ b/tests/test.py @@ -28,7 +28,7 @@ def test(self): self.assertTrue(task_id) task_data = codecoverage.get_task_details(task_id) - self.assertEqual(task_data['metadata']['name'], 'build-linux64-ccov/opt') + self.assertEqual(task_data['metadata']['name'], 'build-linux64-ccov/debug') revision = task_data['payload']['env']['GECKO_HEAD_REV'] task_id_2 = codecoverage.get_task('mozilla-central', revision) @@ -66,12 +66,12 @@ def test(self): def test_suite_name_from_task_name(self): cases = [ - ('test-linux64-ccov/opt-gtest', 'gtest'), - ('test-linux64-ccov/opt-jsreftest-1', 'jsreftest'), - ('test-linux64-ccov/opt-mochitest-devtools-chrome-e10s-10', 'mochitest-devtools-chrome'), - ('test-linux64-ccov/opt-mochitest-clipboard', 'mochitest-clipboard'), - ('test-linux64-ccov/opt-reftest-no-accel-e10s-5', 'reftest-no-accel'), - ('test-linux64-ccov/opt-mochitest-5', 'mochitest'), + ('test-linux64-ccov/debug-gtest', 'gtest'), + ('test-linux64-ccov/debug-jsreftest-1', 'jsreftest'), + ('test-linux64-ccov/debug-mochitest-devtools-chrome-e10s-10', 'mochitest-devtools-chrome'), + ('test-linux64-ccov/debug-mochitest-clipboard', 'mochitest-clipboard'), + ('test-linux64-ccov/debug-reftest-no-accel-e10s-5', 'reftest-no-accel'), + ('test-linux64-ccov/debug-mochitest-5', 'mochitest'), ] for c in cases: self.assertEqual(codecoverage.suite_name_from_task_name(c[0]), c[1]) From 9e4c7e5f4d45b9ce943a66b2dba445f350a6d813 Mon Sep 17 00:00:00 2001 From: Marco Castelluccio Date: Tue, 22 May 2018 14:43:04 -0700 Subject: [PATCH 049/134] Update artifact names --- codecoverage.py | 2 +- tests/test.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/codecoverage.py b/codecoverage.py index 760fa1263..ca5fd6734 100644 --- a/codecoverage.py +++ b/codecoverage.py @@ -107,7 +107,7 @@ def _is_chosen_task(t): for test_task in test_tasks: artifacts = get_task_artifacts(test_task['status']['taskId']) for artifact in artifacts: - if 'code-coverage-gcda.zip' in artifact['name']: + if any(a in artifact['name'] for a in ['code-coverage-grcov.zip', 'code-coverage-jsvm.zip']): download_artifact(test_task['status']['taskId'], artifact) diff --git a/tests/test.py b/tests/test.py index c416e4d7e..e2aaa06a0 100644 --- a/tests/test.py +++ b/tests/test.py @@ -54,7 +54,7 @@ def test(self): self.assertTrue(os.path.exists('ccov-artifacts/%s_target.txt' % task_id)) codecoverage.download_coverage_artifacts(task_id, 'cppunit') - self.assertTrue(len(os.listdir('ccov-artifacts')) == 2) + self.assertTrue(len(os.listdir('ccov-artifacts')) == 3) codecoverage.download_grcov() codecoverage.generate_info('./grcov') From 6706212a82b996588ae5be1414286f913c25d7fe Mon Sep 17 00:00:00 2001 From: Marco Castelluccio Date: Tue, 22 May 2018 14:43:51 -0700 Subject: [PATCH 050/134] Download normal Linux grcov build instead of the standalone one (the standalone doesn't exist anymore) --- codecoverage.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/codecoverage.py b/codecoverage.py index ca5fd6734..782984bd5 100644 --- a/codecoverage.py +++ b/codecoverage.py @@ -167,7 +167,7 @@ def download_grcov(): if installed_ver == latest_tag: return - urlretrieve('https://github.com/marco-c/grcov/releases/download/%s/grcov-linux-standalone-x86_64.tar.bz2' % latest_tag, 'grcov.tar.bz2') + urlretrieve('https://github.com/marco-c/grcov/releases/download/%s/grcov-linux-x86_64.tar.bz2' % latest_tag, 'grcov.tar.bz2') tar = tarfile.open('grcov.tar.bz2', 'r:bz2') tar.extractall() From fe56213f0bc7336813aa26011b03056e85b1c7f0 Mon Sep 17 00:00:00 2001 From: Marco Castelluccio Date: Tue, 22 May 2018 15:13:51 -0700 Subject: [PATCH 051/134] Don't download gcno file anymore, as it's not needed --- codecoverage.py | 16 +--------------- tests/test.py | 2 +- 2 files changed, 2 insertions(+), 16 deletions(-) diff --git a/codecoverage.py b/codecoverage.py index 782984bd5..a2cb22282 100644 --- a/codecoverage.py +++ b/codecoverage.py @@ -85,9 +85,6 @@ def download_coverage_artifacts(build_task_id, suites): task_data = get_task_details(build_task_id) artifacts = get_task_artifacts(build_task_id) - for artifact in artifacts: - if 'target.code-coverage-gcno.zip' in artifact['name']: - download_artifact(build_task_id, artifact) # Returns True if the task is a test-related task. def _is_test_task(t): @@ -112,17 +109,6 @@ def _is_chosen_task(t): def generate_info(grcov_path): - files = os.listdir("ccov-artifacts") - ordered_files = [] - for fname in files: - if not fname.endswith('.zip'): - continue - - if 'gcno' in fname: - ordered_files.insert(0, "ccov-artifacts/" + fname) - else: - ordered_files.append("ccov-artifacts/" + fname) - mod_env = os.environ.copy() if is_taskcluster_loaner(): one_click_loaner_gcc = '/home/worker/workspace/build/src/gcc/bin' @@ -135,7 +121,7 @@ def generate_info(grcov_path): fout = open("output.info", 'w') cmd = [grcov_path, '-t', 'lcov', '-p', '/home/worker/workspace/build/src/'] - cmd.extend(ordered_files) + cmd.extend([os.path.join('ccov-artifacts', p) for p in os.listdir('ccov-artifacts')]) proc = subprocess.Popen(cmd, stdout=fout, stderr=subprocess.PIPE, env=mod_env) i = 0 while proc.poll() is None: diff --git a/tests/test.py b/tests/test.py index e2aaa06a0..c416e4d7e 100644 --- a/tests/test.py +++ b/tests/test.py @@ -54,7 +54,7 @@ def test(self): self.assertTrue(os.path.exists('ccov-artifacts/%s_target.txt' % task_id)) codecoverage.download_coverage_artifacts(task_id, 'cppunit') - self.assertTrue(len(os.listdir('ccov-artifacts')) == 3) + self.assertTrue(len(os.listdir('ccov-artifacts')) == 2) codecoverage.download_grcov() codecoverage.generate_info('./grcov') From c116adf5ad986ce75d49808966c920c7af867535 Mon Sep 17 00:00:00 2001 From: Marco Castelluccio Date: Tue, 22 May 2018 15:15:50 -0700 Subject: [PATCH 052/134] Don't wait 60 seconds before checking grcov's return code --- codecoverage.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/codecoverage.py b/codecoverage.py index a2cb22282..8bc7d46e3 100644 --- a/codecoverage.py +++ b/codecoverage.py @@ -125,9 +125,10 @@ def generate_info(grcov_path): proc = subprocess.Popen(cmd, stdout=fout, stderr=subprocess.PIPE, env=mod_env) i = 0 while proc.poll() is None: - print('Running grcov... ' + str(i)) + if i % 60 == 0: + print('Running grcov... ' + str(i)) i += 1 - time.sleep(60) + time.sleep(1) if proc.poll() != 0: raise Exception("Error while running grcov:\n" + proc.stderr.read()) From 9daa3991e94e6b51e4ff0c08f42132d41ae07d8e Mon Sep 17 00:00:00 2001 From: Assiya Khuzyakhmetova Date: Tue, 29 May 2018 22:44:48 +0600 Subject: [PATCH 053/134] Add setup.py (#25) --- setup.py | 8 ++++++++ 1 file changed, 8 insertions(+) create mode 100644 setup.py diff --git a/setup.py b/setup.py new file mode 100644 index 000000000..8588cd2f1 --- /dev/null +++ b/setup.py @@ -0,0 +1,8 @@ +from setuptools import setup, find_packages + +setup( + name='firefox-code-coverage', + version='1.0.0', + description='Code Coverage Report generator for Firefox', + packages=find_packages(exclude=['contrib', 'docs', 'tests']) +) From 11536912bce55629df04c85210a2e5e1e05741d7 Mon Sep 17 00:00:00 2001 From: Assiya Khuzyakhmetova Date: Tue, 29 May 2018 23:33:22 +0600 Subject: [PATCH 054/134] changed name (#26) --- setup.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup.py b/setup.py index 8588cd2f1..c84da89e5 100644 --- a/setup.py +++ b/setup.py @@ -1,7 +1,7 @@ from setuptools import setup, find_packages setup( - name='firefox-code-coverage', + name='firefox_code_coverage', version='1.0.0', description='Code Coverage Report generator for Firefox', packages=find_packages(exclude=['contrib', 'docs', 'tests']) From 5b1edf1ab13439f8d0ba4912f7a38ee3b66b136a Mon Sep 17 00:00:00 2001 From: Assiya Khuzyakhmetova Date: Wed, 30 May 2018 17:37:01 +0600 Subject: [PATCH 055/134] Add test for installing the package (#31) --- .gitignore | 1 + .travis.yml | 2 ++ test-requirements.txt | 2 ++ 3 files changed, 5 insertions(+) diff --git a/.gitignore b/.gitignore index 1c5f969be..81f4c2f03 100644 --- a/.gitignore +++ b/.gitignore @@ -2,3 +2,4 @@ *.pyc *.pyo ccov-artifacts +lcov diff --git a/.travis.yml b/.travis.yml index f632db188..f0cf15ad9 100644 --- a/.travis.yml +++ b/.travis.yml @@ -11,6 +11,8 @@ script: - export PATH=$PWD/symlinks:$PATH - flake8 . - python -m unittest discover tests + - python setup.py sdist bdist_wheel + - pip install dist/firefox_code_coverage-1.0.0.tar.gz cache: pip addons: apt: diff --git a/test-requirements.txt b/test-requirements.txt index 39304807f..86f6aa11d 100644 --- a/test-requirements.txt +++ b/test-requirements.txt @@ -1 +1,3 @@ flake8 +wheel +setuptools From 0eb44a4dbad2858ead822ef2d15c5399c41beb8e Mon Sep 17 00:00:00 2001 From: Assiya Khuzyakhmetova Date: Thu, 31 May 2018 15:34:37 +0600 Subject: [PATCH 056/134] Allow callers to decide the grcov's output format (#32) --- codecoverage.py | 20 +++++++++++--------- tests/test.py | 4 ++-- 2 files changed, 13 insertions(+), 11 deletions(-) diff --git a/codecoverage.py b/codecoverage.py index 8bc7d46e3..9fbaf7841 100644 --- a/codecoverage.py +++ b/codecoverage.py @@ -6,13 +6,14 @@ import subprocess import tarfile import time +import warnings + try: from urllib.parse import urlencode from urllib.request import urlopen, urlretrieve except ImportError: from urllib import urlencode, urlretrieve from urllib2 import urlopen -import warnings def get_json(url, params=None): @@ -108,7 +109,7 @@ def _is_chosen_task(t): download_artifact(test_task['status']['taskId'], artifact) -def generate_info(grcov_path): +def generate_report(grcov_path, output_format, output_path): mod_env = os.environ.copy() if is_taskcluster_loaner(): one_click_loaner_gcc = '/home/worker/workspace/build/src/gcc/bin' @@ -118,9 +119,10 @@ def generate_info(grcov_path): i += 1 time.sleep(60) mod_env['PATH'] = one_click_loaner_gcc + ':' + mod_env['PATH'] - - fout = open("output.info", 'w') - cmd = [grcov_path, '-t', 'lcov', '-p', '/home/worker/workspace/build/src/'] + fout = open(output_path, 'w') + cmd = [grcov_path, '-t', output_format, '-p', '/home/worker/workspace/build/src/'] + if output_format in ['coveralls', 'coveralls+']: + cmd += ['--token', 'UNUSED', '--commit-sha', 'UNUSED'] cmd.extend([os.path.join('ccov-artifacts', p) for p in os.listdir('ccov-artifacts')]) proc = subprocess.Popen(cmd, stdout=fout, stderr=subprocess.PIPE, env=mod_env) i = 0 @@ -134,10 +136,10 @@ def generate_info(grcov_path): raise Exception("Error while running grcov:\n" + proc.stderr.read()) -def generate_report(src_dir): +def generate_html_report(src_dir): cwd = os.getcwd() os.chdir(src_dir) - ret = subprocess.call([os.path.join(cwd, "lcov-bin/usr/local/bin/genhtml"), "-o", os.path.join(cwd, "report"), "--show-details", "--highlight", "--ignore-errors", "source", "--legend", os.path.join(cwd, "output.info"), "--prefix", src_dir]) + ret = subprocess.call([os.path.join(cwd, "lcov-bin/usr/local/bin/genhtml"), "-o", os.path.join(cwd, "report"), "--show-details", "--highlight", "--ignore-errors", "source", "--legend", os.path.join(cwd, 'output.info'), "--prefix", src_dir]) if ret != 0: raise Exception("Error while running genhtml.") os.chdir(cwd) @@ -230,10 +232,10 @@ def main(): download_grcov() grcov_path = './grcov' - generate_info(grcov_path) + generate_report(grcov_path, 'lcov', 'output.info') download_genhtml() - generate_report(os.path.abspath(args.src_dir)) + generate_html_report(os.path.abspath(args.src_dir)) if __name__ == "__main__": diff --git a/tests/test.py b/tests/test.py index c416e4d7e..9cae83dee 100644 --- a/tests/test.py +++ b/tests/test.py @@ -57,11 +57,11 @@ def test(self): self.assertTrue(len(os.listdir('ccov-artifacts')) == 2) codecoverage.download_grcov() - codecoverage.generate_info('./grcov') + codecoverage.generate_report('./grcov', 'lcov', 'output.info') self.assertTrue(os.path.exists('output.info')) codecoverage.download_genhtml() - codecoverage.generate_report('tests') + codecoverage.generate_html_report('tests') self.assertTrue(os.path.isdir('report')) def test_suite_name_from_task_name(self): From 31514e5dd639d769b8c4cdedf697037b7f70b2f3 Mon Sep 17 00:00:00 2001 From: Assiya Khuzyakhmetova Date: Thu, 31 May 2018 19:02:30 +0600 Subject: [PATCH 057/134] Add more flake8 plugins (#34) --- .isort.cfg | 2 ++ codecoverage.py | 24 +++++++++++++----------- setup.py | 5 ++++- test-requirements.txt | 5 +++++ tests/test.py | 4 +++- 5 files changed, 27 insertions(+), 13 deletions(-) create mode 100644 .isort.cfg diff --git a/.isort.cfg b/.isort.cfg new file mode 100644 index 000000000..b110a6bec --- /dev/null +++ b/.isort.cfg @@ -0,0 +1,2 @@ +[settings] +force_single_line=True diff --git a/codecoverage.py b/codecoverage.py index 9fbaf7841..5e1e4f603 100644 --- a/codecoverage.py +++ b/codecoverage.py @@ -1,3 +1,5 @@ +# -*- coding: utf-8 -*- + import argparse import errno import json @@ -133,15 +135,15 @@ def generate_report(grcov_path, output_format, output_path): time.sleep(1) if proc.poll() != 0: - raise Exception("Error while running grcov:\n" + proc.stderr.read()) + raise Exception('Error while running grcov:\n' + proc.stderr.read()) def generate_html_report(src_dir): cwd = os.getcwd() os.chdir(src_dir) - ret = subprocess.call([os.path.join(cwd, "lcov-bin/usr/local/bin/genhtml"), "-o", os.path.join(cwd, "report"), "--show-details", "--highlight", "--ignore-errors", "source", "--legend", os.path.join(cwd, 'output.info'), "--prefix", src_dir]) + ret = subprocess.call([os.path.join(cwd, 'lcov-bin/usr/local/bin/genhtml'), '-o', os.path.join(cwd, 'report'), '--show-details', '--highlight', '--ignore-errors', 'source', '--legend', os.path.join(cwd, 'output.info'), '--prefix', src_dir]) if ret != 0: - raise Exception("Error while running genhtml.") + raise Exception('Error while running genhtml.') os.chdir(cwd) @@ -201,13 +203,13 @@ def main(): default_branch = None default_commit = None - parser.add_argument("src_dir", action="store", nargs=nargs, default=default_src_dir, help="Path to the source directory") - parser.add_argument("branch", action="store", nargs='?', default=default_branch, help="Branch on which jobs ran") - parser.add_argument("commit", action="store", nargs='?', default=default_commit, help="Commit hash for push") - parser.add_argument("--grcov", action="store", nargs='?', help="Path to grcov") - parser.add_argument("--no-download", action="store_true", help="Use already downloaded coverage files") - parser.add_argument("--no-grcov", action="store_true", help="Use already generated grcov output (implies --no-download)") - parser.add_argument("--suite", action="store", nargs='+', help="List of test suites to include (by default they are all included). E.g. 'mochitest', 'mochitest-chrome', 'gtest', etc.") + parser.add_argument('src_dir', action='store', nargs=nargs, default=default_src_dir, help='Path to the source directory') + parser.add_argument('branch', action='store', nargs='?', default=default_branch, help='Branch on which jobs ran') + parser.add_argument('commit', action='store', nargs='?', default=default_commit, help='Commit hash for push') + parser.add_argument('--grcov', action='store', nargs='?', help='Path to grcov') + parser.add_argument('--no-download', action='store_true', help='Use already downloaded coverage files') + parser.add_argument('--no-grcov', action='store_true', help='Use already generated grcov output (implies --no-download)') + parser.add_argument('--suite', action='store', nargs='+', help='List of test suites to include (by default they are all included). E.g. \'mochitest\', \'mochitest-chrome\', \'gtest\', etc.') args = parser.parse_args() if args.no_grcov: @@ -238,5 +240,5 @@ def main(): generate_html_report(os.path.abspath(args.src_dir)) -if __name__ == "__main__": +if __name__ == '__main__': main() diff --git a/setup.py b/setup.py index c84da89e5..731935a29 100644 --- a/setup.py +++ b/setup.py @@ -1,4 +1,7 @@ -from setuptools import setup, find_packages +# -*- coding: utf-8 -*- + +from setuptools import find_packages +from setuptools import setup setup( name='firefox_code_coverage', diff --git a/test-requirements.txt b/test-requirements.txt index 86f6aa11d..1074b0f34 100644 --- a/test-requirements.txt +++ b/test-requirements.txt @@ -1,3 +1,8 @@ flake8 +flake8-isort +flake8-quotes +flake8-coding +flake8-copyright +flake8-debugger wheel setuptools diff --git a/tests/test.py b/tests/test.py index 9cae83dee..df7fa1de0 100644 --- a/tests/test.py +++ b/tests/test.py @@ -1,11 +1,13 @@ +# -*- coding: utf-8 -*- + # This Source Code Form is subject to the terms of the Mozilla Public # License, v. 2.0. If a copy of the MPL was not distributed with this file, # You can obtain one at http://mozilla.org/MPL/2.0/. -import unittest import errno import os import shutil +import unittest import codecoverage From 790eb08b01d13928a1697d52b4dcc31211d1bc48 Mon Sep 17 00:00:00 2001 From: Assiya Khuzyakhmetova Date: Fri, 8 Jun 2018 20:46:18 +0600 Subject: [PATCH 058/134] Add option to ignore suites (#36) --- codecoverage.py | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/codecoverage.py b/codecoverage.py index 5e1e4f603..9cc8e4edd 100644 --- a/codecoverage.py +++ b/codecoverage.py @@ -76,7 +76,7 @@ def suite_name_from_task_name(name): return '-'.join(parts) -def download_coverage_artifacts(build_task_id, suites): +def download_coverage_artifacts(build_task_id, suites, suites_to_ignore=['talos', 'awsy']): shutil.rmtree('ccov-artifacts', ignore_errors=True) try: @@ -95,7 +95,8 @@ def _is_test_task(t): # Returns True if the task is part of one of the suites chosen by the user. def _is_chosen_task(t): - return suites is None or suite_name_from_task_name(t['task']['metadata']['name']) in suites + suite_name = suite_name_from_task_name(t['task']['metadata']['name']) + return suites is None or suite_name in suites and suite_name not in suites_to_ignore test_tasks = [t for t in get_tasks_in_group(task_data['taskGroupId']) if _is_test_task(t) and _is_chosen_task(t)] @@ -210,6 +211,7 @@ def main(): parser.add_argument('--no-download', action='store_true', help='Use already downloaded coverage files') parser.add_argument('--no-grcov', action='store_true', help='Use already generated grcov output (implies --no-download)') parser.add_argument('--suite', action='store', nargs='+', help='List of test suites to include (by default they are all included). E.g. \'mochitest\', \'mochitest-chrome\', \'gtest\', etc.') + parser.add_argument('--ignore', action='store', nargs='+', help='List of test suites to ignore (by default \'talos\' and \'awsy\'). E.g. \'mochitest\', \'mochitest-chrome\', \'gtest\', etc.') args = parser.parse_args() if args.no_grcov: @@ -224,8 +226,10 @@ def main(): task_id = get_task(args.branch, args.commit) else: task_id = get_last_task() - - download_coverage_artifacts(task_id, args.suite) + if args.ignore is None: + download_coverage_artifacts(task_id, args.suite) + else: + download_coverage_artifacts(task_id, args.suite, args.ignore) if not args.no_grcov: if args.grcov: From a720ce65b1a0fe871298eeaf32b8e96235dd74a3 Mon Sep 17 00:00:00 2001 From: Assiya Khuzyakhmetova Date: Fri, 15 Jun 2018 12:41:13 +0600 Subject: [PATCH 059/134] Use --with-artifacts instead of --no-download (#37) --- codecoverage.py | 25 +++++++++++++------------ 1 file changed, 13 insertions(+), 12 deletions(-) diff --git a/codecoverage.py b/codecoverage.py index 9cc8e4edd..656b89d67 100644 --- a/codecoverage.py +++ b/codecoverage.py @@ -112,7 +112,7 @@ def _is_chosen_task(t): download_artifact(test_task['status']['taskId'], artifact) -def generate_report(grcov_path, output_format, output_path): +def generate_report(grcov_path, output_format, output_path, artifacts_path='ccov-artifacts'): mod_env = os.environ.copy() if is_taskcluster_loaner(): one_click_loaner_gcc = '/home/worker/workspace/build/src/gcc/bin' @@ -126,7 +126,7 @@ def generate_report(grcov_path, output_format, output_path): cmd = [grcov_path, '-t', output_format, '-p', '/home/worker/workspace/build/src/'] if output_format in ['coveralls', 'coveralls+']: cmd += ['--token', 'UNUSED', '--commit-sha', 'UNUSED'] - cmd.extend([os.path.join('ccov-artifacts', p) for p in os.listdir('ccov-artifacts')]) + cmd.extend([os.path.join(artifacts_path, p) for p in os.listdir(artifacts_path)]) proc = subprocess.Popen(cmd, stdout=fout, stderr=subprocess.PIPE, env=mod_env) i = 0 while proc.poll() is None: @@ -208,24 +208,22 @@ def main(): parser.add_argument('branch', action='store', nargs='?', default=default_branch, help='Branch on which jobs ran') parser.add_argument('commit', action='store', nargs='?', default=default_commit, help='Commit hash for push') parser.add_argument('--grcov', action='store', nargs='?', help='Path to grcov') - parser.add_argument('--no-download', action='store_true', help='Use already downloaded coverage files') - parser.add_argument('--no-grcov', action='store_true', help='Use already generated grcov output (implies --no-download)') + parser.add_argument('--with-artifacts', action='store', nargs='?', help='Path to already downloaded coverage files') + parser.add_argument('--no-grcov', action='store_true', help='Use already generated grcov output') parser.add_argument('--suite', action='store', nargs='+', help='List of test suites to include (by default they are all included). E.g. \'mochitest\', \'mochitest-chrome\', \'gtest\', etc.') parser.add_argument('--ignore', action='store', nargs='+', help='List of test suites to ignore (by default \'talos\' and \'awsy\'). E.g. \'mochitest\', \'mochitest-chrome\', \'gtest\', etc.') args = parser.parse_args() - if args.no_grcov: - args.no_download = True - - if (args.branch is None) != (args.commit is None) and not args.no_download: - parser.print_help() - return + if not args.with_artifacts and not args.no_grcov: + if (args.branch is None) != (args.commit is None): + parser.print_help() + return - if not args.no_download: if args.branch and args.commit: task_id = get_task(args.branch, args.commit) else: task_id = get_last_task() + if args.ignore is None: download_coverage_artifacts(task_id, args.suite) else: @@ -238,7 +236,10 @@ def main(): download_grcov() grcov_path = './grcov' - generate_report(grcov_path, 'lcov', 'output.info') + if args.with_artifacts: + generate_report(grcov_path, 'lcov', 'output.info', args.with_artifacts) + else: + generate_report(grcov_path, 'lcov', 'output.info') download_genhtml() generate_html_report(os.path.abspath(args.src_dir)) From 5903b6e12f3fa71fe1bb81089b4e877b05b49f47 Mon Sep 17 00:00:00 2001 From: Marco Date: Mon, 18 Jun 2018 13:55:57 +0100 Subject: [PATCH 060/134] Use a GitHub access token for retrieving the list of grcov releases (#38) --- codecoverage.py | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/codecoverage.py b/codecoverage.py index 656b89d67..15db86171 100644 --- a/codecoverage.py +++ b/codecoverage.py @@ -12,17 +12,18 @@ try: from urllib.parse import urlencode - from urllib.request import urlopen, urlretrieve + from urllib.request import Request, urlopen, urlretrieve except ImportError: from urllib import urlencode, urlretrieve - from urllib2 import urlopen + from urllib2 import Request, urlopen -def get_json(url, params=None): +def get_json(url, params=None, headers={}): if params is not None: url += '?' + urlencode(params) - r = urlopen(url).read().decode('utf-8') + request = Request(url, headers=headers) + r = urlopen(request).read().decode('utf-8') return json.loads(r) @@ -149,7 +150,11 @@ def generate_html_report(src_dir): def download_grcov(): - r = get_json('https://api.github.com/repos/marco-c/grcov/releases/latest') + headers = {} + if 'GITHUB_ACCESS_TOKEN' in os.environ: + headers['Authorization'] = 'token {}'.format(os.environ['GITHUB_ACCESS_TOKEN']) + + r = get_json('https://api.github.com/repos/marco-c/grcov/releases/latest', headers=headers) latest_tag = r['tag_name'] if os.path.exists('grcov') and os.path.exists('grcov_ver'): From 71e36c426c8b56b82316bb972652781fd663b123 Mon Sep 17 00:00:00 2001 From: Assiya Khuzyakhmetova Date: Tue, 19 Jun 2018 16:05:37 +0600 Subject: [PATCH 061/134] Add optional output directory to generate_html_report (#40) --- codecoverage.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/codecoverage.py b/codecoverage.py index 15db86171..8e77aa9f0 100644 --- a/codecoverage.py +++ b/codecoverage.py @@ -140,10 +140,10 @@ def generate_report(grcov_path, output_format, output_path, artifacts_path='ccov raise Exception('Error while running grcov:\n' + proc.stderr.read()) -def generate_html_report(src_dir): +def generate_html_report(src_dir, info_file=os.path.join(os.getcwd(), 'output.info'), output_dir=os.path.join(os.getcwd(), 'report')): cwd = os.getcwd() os.chdir(src_dir) - ret = subprocess.call([os.path.join(cwd, 'lcov-bin/usr/local/bin/genhtml'), '-o', os.path.join(cwd, 'report'), '--show-details', '--highlight', '--ignore-errors', 'source', '--legend', os.path.join(cwd, 'output.info'), '--prefix', src_dir]) + ret = subprocess.call([os.path.join(cwd, 'lcov-bin/usr/local/bin/genhtml'), '-o', output_dir, '--show-details', '--highlight', '--ignore-errors', 'source', '--legend', info_file, '--prefix', src_dir]) if ret != 0: raise Exception('Error while running genhtml.') os.chdir(cwd) From 9ff2453ce1e99367cea74c75343fcfe5fd19960d Mon Sep 17 00:00:00 2001 From: Marco Castelluccio Date: Sat, 30 Jun 2018 11:27:34 +0100 Subject: [PATCH 062/134] Don't download an artifact again if it was already downloaded --- codecoverage.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/codecoverage.py b/codecoverage.py index 8e77aa9f0..5d538cedb 100644 --- a/codecoverage.py +++ b/codecoverage.py @@ -68,7 +68,8 @@ def get_tasks_in_group(group_id): def download_artifact(task_id, artifact): fname = os.path.join('ccov-artifacts', task_id + '_' + os.path.basename(artifact['name'])) - urlretrieve('https://queue.taskcluster.net/v1/task/' + task_id + '/artifacts/' + artifact['name'], fname) + if not os.path.exists(fname): + urlretrieve('https://queue.taskcluster.net/v1/task/' + task_id + '/artifacts/' + artifact['name'], fname) def suite_name_from_task_name(name): From 5cb74d7ad7d994ac8f1bcc5da76f0b92c4358208 Mon Sep 17 00:00:00 2001 From: Marco Castelluccio Date: Sat, 30 Jun 2018 11:32:28 +0100 Subject: [PATCH 063/134] Retry when an artifact download fails --- codecoverage.py | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/codecoverage.py b/codecoverage.py index 5d538cedb..825f0a893 100644 --- a/codecoverage.py +++ b/codecoverage.py @@ -69,7 +69,17 @@ def get_tasks_in_group(group_id): def download_artifact(task_id, artifact): fname = os.path.join('ccov-artifacts', task_id + '_' + os.path.basename(artifact['name'])) if not os.path.exists(fname): - urlretrieve('https://queue.taskcluster.net/v1/task/' + task_id + '/artifacts/' + artifact['name'], fname) + while True: + try: + urlretrieve('https://queue.taskcluster.net/v1/task/' + task_id + '/artifacts/' + artifact['name'], fname) + break + except: # noqa: E722 + try: + os.remove(fname) + except OSError: + pass + + time.sleep(7) def suite_name_from_task_name(name): From a15d333fd7d810c8d112ab7c03e170e35e15f6ed Mon Sep 17 00:00:00 2001 From: Marco Castelluccio Date: Sat, 30 Jun 2018 23:40:11 +0100 Subject: [PATCH 064/134] Add an option to generate only high-level stats instead of a full HTML report --- codecoverage.py | 29 ++++++++++++++++++++++++----- 1 file changed, 24 insertions(+), 5 deletions(-) diff --git a/codecoverage.py b/codecoverage.py index 825f0a893..469fb9f7e 100644 --- a/codecoverage.py +++ b/codecoverage.py @@ -228,6 +228,7 @@ def main(): parser.add_argument('--no-grcov', action='store_true', help='Use already generated grcov output') parser.add_argument('--suite', action='store', nargs='+', help='List of test suites to include (by default they are all included). E.g. \'mochitest\', \'mochitest-chrome\', \'gtest\', etc.') parser.add_argument('--ignore', action='store', nargs='+', help='List of test suites to ignore (by default \'talos\' and \'awsy\'). E.g. \'mochitest\', \'mochitest-chrome\', \'gtest\', etc.') + parser.add_argument('--stats', action='store_true', help='Only generate high-level stats, not a full HTML report') args = parser.parse_args() if not args.with_artifacts and not args.no_grcov: @@ -253,12 +254,30 @@ def main(): grcov_path = './grcov' if args.with_artifacts: - generate_report(grcov_path, 'lcov', 'output.info', args.with_artifacts) + generate_report(grcov_path, 'lcov' if not args.stats else 'json', 'output.info', args.with_artifacts) else: - generate_report(grcov_path, 'lcov', 'output.info') - - download_genhtml() - generate_html_report(os.path.abspath(args.src_dir)) + generate_report(grcov_path, 'lcov' if not args.stats else 'json', 'output.info') + + if args.stats: + with open('output.info', 'r') as f: + report = json.load(f) + total_lines = 0 + total_lines_covered = 0 + for sf in report['source_files']: + for c in sf['coverage']: + if c is None: + continue + + total_lines += 1 + if c > 0: + total_lines_covered += 1 + + print('Coverable lines: {}'.format(total_lines)) + print('Covered lines: {}'.format(total_lines_covered)) + print('Coverage percentage: {}'.format(float(total_lines_covered) / float(total_lines))) + else: + download_genhtml() + generate_html_report(os.path.abspath(args.src_dir)) if __name__ == '__main__': From 995b89d3de77acef723da1c593df6c0ede4b8a06 Mon Sep 17 00:00:00 2001 From: Marco Castelluccio Date: Sat, 30 Jun 2018 23:42:01 +0100 Subject: [PATCH 065/134] Remove --no-grcov option --- codecoverage.py | 22 ++++++++++------------ 1 file changed, 10 insertions(+), 12 deletions(-) diff --git a/codecoverage.py b/codecoverage.py index 469fb9f7e..a591d9b37 100644 --- a/codecoverage.py +++ b/codecoverage.py @@ -225,13 +225,12 @@ def main(): parser.add_argument('commit', action='store', nargs='?', default=default_commit, help='Commit hash for push') parser.add_argument('--grcov', action='store', nargs='?', help='Path to grcov') parser.add_argument('--with-artifacts', action='store', nargs='?', help='Path to already downloaded coverage files') - parser.add_argument('--no-grcov', action='store_true', help='Use already generated grcov output') parser.add_argument('--suite', action='store', nargs='+', help='List of test suites to include (by default they are all included). E.g. \'mochitest\', \'mochitest-chrome\', \'gtest\', etc.') parser.add_argument('--ignore', action='store', nargs='+', help='List of test suites to ignore (by default \'talos\' and \'awsy\'). E.g. \'mochitest\', \'mochitest-chrome\', \'gtest\', etc.') parser.add_argument('--stats', action='store_true', help='Only generate high-level stats, not a full HTML report') args = parser.parse_args() - if not args.with_artifacts and not args.no_grcov: + if not args.with_artifacts: if (args.branch is None) != (args.commit is None): parser.print_help() return @@ -246,17 +245,16 @@ def main(): else: download_coverage_artifacts(task_id, args.suite, args.ignore) - if not args.no_grcov: - if args.grcov: - grcov_path = args.grcov - else: - download_grcov() - grcov_path = './grcov' + if args.grcov: + grcov_path = args.grcov + else: + download_grcov() + grcov_path = './grcov' - if args.with_artifacts: - generate_report(grcov_path, 'lcov' if not args.stats else 'json', 'output.info', args.with_artifacts) - else: - generate_report(grcov_path, 'lcov' if not args.stats else 'json', 'output.info') + if args.with_artifacts: + generate_report(grcov_path, 'lcov' if not args.stats else 'json', 'output.info', args.with_artifacts) + else: + generate_report(grcov_path, 'lcov' if not args.stats else 'json', 'output.info') if args.stats: with open('output.info', 'r') as f: From 65c3bdd72f0136e9bd3ab83306326c38a19b5a21 Mon Sep 17 00:00:00 2001 From: Marco Castelluccio Date: Sun, 1 Jul 2018 11:13:46 +0100 Subject: [PATCH 066/134] Always download artifacts, use with_artifacts just as the output directory (and don't redownload if the artifacts are already there) --- codecoverage.py | 51 +++++++++++++++++++++++-------------------------- 1 file changed, 24 insertions(+), 27 deletions(-) diff --git a/codecoverage.py b/codecoverage.py index a591d9b37..027bc451a 100644 --- a/codecoverage.py +++ b/codecoverage.py @@ -66,8 +66,8 @@ def get_tasks_in_group(group_id): return tasks -def download_artifact(task_id, artifact): - fname = os.path.join('ccov-artifacts', task_id + '_' + os.path.basename(artifact['name'])) +def download_artifact(task_id, artifact, artifacts_path): + fname = os.path.join(artifacts_path, task_id + '_' + os.path.basename(artifact['name'])) if not os.path.exists(fname): while True: try: @@ -88,11 +88,9 @@ def suite_name_from_task_name(name): return '-'.join(parts) -def download_coverage_artifacts(build_task_id, suites, suites_to_ignore=['talos', 'awsy']): - shutil.rmtree('ccov-artifacts', ignore_errors=True) - +def download_coverage_artifacts(build_task_id, suites, artifacts_path, suites_to_ignore=['talos', 'awsy']): try: - os.mkdir('ccov-artifacts') + os.mkdir(artifacts_path) except OSError as e: if e.errno != errno.EEXIST: raise e @@ -121,10 +119,10 @@ def _is_chosen_task(t): artifacts = get_task_artifacts(test_task['status']['taskId']) for artifact in artifacts: if any(a in artifact['name'] for a in ['code-coverage-grcov.zip', 'code-coverage-jsvm.zip']): - download_artifact(test_task['status']['taskId'], artifact) + download_artifact(test_task['status']['taskId'], artifact, artifacts_path) -def generate_report(grcov_path, output_format, output_path, artifacts_path='ccov-artifacts'): +def generate_report(grcov_path, output_format, output_path, artifacts_path): mod_env = os.environ.copy() if is_taskcluster_loaner(): one_click_loaner_gcc = '/home/worker/workspace/build/src/gcc/bin' @@ -224,26 +222,25 @@ def main(): parser.add_argument('branch', action='store', nargs='?', default=default_branch, help='Branch on which jobs ran') parser.add_argument('commit', action='store', nargs='?', default=default_commit, help='Commit hash for push') parser.add_argument('--grcov', action='store', nargs='?', help='Path to grcov') - parser.add_argument('--with-artifacts', action='store', nargs='?', help='Path to already downloaded coverage files') + parser.add_argument('--with-artifacts', action='store', nargs='?', default='ccov-artifacts', help='Path to already downloaded coverage files') parser.add_argument('--suite', action='store', nargs='+', help='List of test suites to include (by default they are all included). E.g. \'mochitest\', \'mochitest-chrome\', \'gtest\', etc.') parser.add_argument('--ignore', action='store', nargs='+', help='List of test suites to ignore (by default \'talos\' and \'awsy\'). E.g. \'mochitest\', \'mochitest-chrome\', \'gtest\', etc.') parser.add_argument('--stats', action='store_true', help='Only generate high-level stats, not a full HTML report') args = parser.parse_args() - if not args.with_artifacts: - if (args.branch is None) != (args.commit is None): - parser.print_help() - return + if (args.branch is None) != (args.commit is None): + parser.print_help() + return - if args.branch and args.commit: - task_id = get_task(args.branch, args.commit) - else: - task_id = get_last_task() + if args.branch and args.commit: + task_id = get_task(args.branch, args.commit) + else: + task_id = get_last_task() - if args.ignore is None: - download_coverage_artifacts(task_id, args.suite) - else: - download_coverage_artifacts(task_id, args.suite, args.ignore) + if args.ignore is None: + download_coverage_artifacts(task_id, args.suite, args.with_artifacts) + else: + download_coverage_artifacts(task_id, args.suite, args.with_artifacts, args.ignore) if args.grcov: grcov_path = args.grcov @@ -251,14 +248,12 @@ def main(): download_grcov() grcov_path = './grcov' - if args.with_artifacts: - generate_report(grcov_path, 'lcov' if not args.stats else 'json', 'output.info', args.with_artifacts) - else: - generate_report(grcov_path, 'lcov' if not args.stats else 'json', 'output.info') - if args.stats: - with open('output.info', 'r') as f: + generate_report(grcov_path, 'coveralls', 'output.json', args.with_artifacts) + + with open('output.json', 'r') as f: report = json.load(f) + total_lines = 0 total_lines_covered = 0 for sf in report['source_files']: @@ -274,6 +269,8 @@ def main(): print('Covered lines: {}'.format(total_lines_covered)) print('Coverage percentage: {}'.format(float(total_lines_covered) / float(total_lines))) else: + generate_report(grcov_path, 'lcov', 'output.info', args.with_artifacts) + download_genhtml() generate_html_report(os.path.abspath(args.src_dir)) From 9e82d1e0a50fb2c63a1632c3c2011dfa72bb2aac Mon Sep 17 00:00:00 2001 From: Marco Castelluccio Date: Sun, 1 Jul 2018 11:16:13 +0100 Subject: [PATCH 067/134] No longer need to retrieve artifacts of the build --- codecoverage.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/codecoverage.py b/codecoverage.py index 027bc451a..f3854bb36 100644 --- a/codecoverage.py +++ b/codecoverage.py @@ -97,8 +97,6 @@ def download_coverage_artifacts(build_task_id, suites, artifacts_path, suites_to task_data = get_task_details(build_task_id) - artifacts = get_task_artifacts(build_task_id) - # Returns True if the task is a test-related task. def _is_test_task(t): return t['task']['metadata']['name'].startswith('test-linux64-ccov') From d0d1992c9a45e404f1f8f378c054d0a87d0d0faf Mon Sep 17 00:00:00 2001 From: Marco Castelluccio Date: Sun, 1 Jul 2018 11:16:26 +0100 Subject: [PATCH 068/134] Remove unused module --- codecoverage.py | 1 - 1 file changed, 1 deletion(-) diff --git a/codecoverage.py b/codecoverage.py index f3854bb36..60afe1759 100644 --- a/codecoverage.py +++ b/codecoverage.py @@ -4,7 +4,6 @@ import errno import json import os -import shutil import subprocess import tarfile import time From f23c9e7215fd4fe48a36b4d03d72c6a92c293cad Mon Sep 17 00:00:00 2001 From: Marco Castelluccio Date: Sun, 1 Jul 2018 15:12:41 +0100 Subject: [PATCH 069/134] Support downloading artifacts from Windows ccov build too. Fixes #21 --- codecoverage.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/codecoverage.py b/codecoverage.py index 60afe1759..cd5a39b40 100644 --- a/codecoverage.py +++ b/codecoverage.py @@ -17,6 +17,9 @@ from urllib2 import Request, urlopen +TEST_PLATFORMS = ['test-linux64-ccov/debug', 'test-windows10-64-ccov/debug'] + + def get_json(url, params=None, headers={}): if params is not None: url += '?' + urlencode(params) @@ -98,7 +101,7 @@ def download_coverage_artifacts(build_task_id, suites, artifacts_path, suites_to # Returns True if the task is a test-related task. def _is_test_task(t): - return t['task']['metadata']['name'].startswith('test-linux64-ccov') + return any(t['task']['metadata']['name'].startswith(tp) for tp in TEST_PLATFORMS) # Returns True if the task is part of one of the suites chosen by the user. def _is_chosen_task(t): From c2c26d9fa6459c057a7ac095458ce8d809a26a4d Mon Sep 17 00:00:00 2001 From: Marco Castelluccio Date: Sun, 1 Jul 2018 22:51:08 +0100 Subject: [PATCH 070/134] Print progress while downloading artifacts. Fixes #20 --- codecoverage.py | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/codecoverage.py b/codecoverage.py index cd5a39b40..739f58ba9 100644 --- a/codecoverage.py +++ b/codecoverage.py @@ -5,6 +5,7 @@ import json import os import subprocess +import sys import tarfile import time import warnings @@ -115,11 +116,14 @@ def _is_chosen_task(t): if not any(suite in t['task']['metadata']['name'] for t in test_tasks): warnings.warn('Suite %s not found' % suite) - for test_task in test_tasks: + for i, test_task in enumerate(test_tasks): + sys.stdout.write('\rDownloading artifacts from {}/{} test task...'.format(i, len(test_tasks))) + sys.stdout.flush() artifacts = get_task_artifacts(test_task['status']['taskId']) for artifact in artifacts: if any(a in artifact['name'] for a in ['code-coverage-grcov.zip', 'code-coverage-jsvm.zip']): download_artifact(test_task['status']['taskId'], artifact, artifacts_path) + print('') def generate_report(grcov_path, output_format, output_path, artifacts_path): @@ -141,9 +145,11 @@ def generate_report(grcov_path, output_format, output_path, artifacts_path): i = 0 while proc.poll() is None: if i % 60 == 0: - print('Running grcov... ' + str(i)) + sys.stdout.write('\rRunning grcov... {} seconds'.format(i)) + sys.stdout.flush() i += 1 time.sleep(1) + print('') if proc.poll() != 0: raise Exception('Error while running grcov:\n' + proc.stderr.read()) From d5163d875403de3f43361deac1113599f70bec02 Mon Sep 17 00:00:00 2001 From: Marco Castelluccio Date: Mon, 2 Jul 2018 10:53:30 +0100 Subject: [PATCH 071/134] Fix bug when a suite is selected --- codecoverage.py | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/codecoverage.py b/codecoverage.py index 739f58ba9..482c3c0fc 100644 --- a/codecoverage.py +++ b/codecoverage.py @@ -84,11 +84,16 @@ def download_artifact(task_id, artifact, artifacts_path): time.sleep(7) +def get_chunk(task_name): + for t in TEST_PLATFORMS: + if task_name.startswith(t): + task_name = task_name[len(t) + 1:] + break + return '-'.join([p for p in task_name.split('-') if p != 'e10s']) -def suite_name_from_task_name(name): - name = name[len('test-linux64-ccov/debug-'):] - parts = [p for p in name.split('-') if p != 'e10s' and not p.isdigit()] - return '-'.join(parts) + +def get_suite(task_name): + return '-'.join([p for p in get_chunk(task_name).split('-') if not p.isdigit()]) def download_coverage_artifacts(build_task_id, suites, artifacts_path, suites_to_ignore=['talos', 'awsy']): @@ -106,7 +111,7 @@ def _is_test_task(t): # Returns True if the task is part of one of the suites chosen by the user. def _is_chosen_task(t): - suite_name = suite_name_from_task_name(t['task']['metadata']['name']) + suite_name = get_suite(t['task']['metadata']['name']) return suites is None or suite_name in suites and suite_name not in suites_to_ignore test_tasks = [t for t in get_tasks_in_group(task_data['taskGroupId']) if _is_test_task(t) and _is_chosen_task(t)] From 309fe4a7d28f564f4c7774416cd1f8a994b11f45 Mon Sep 17 00:00:00 2001 From: Marco Castelluccio Date: Mon, 2 Jul 2018 10:53:53 +0100 Subject: [PATCH 072/134] Update tests with the new parameters and with support for Windows --- tests/test.py | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/tests/test.py b/tests/test.py index df7fa1de0..e3a3b13fd 100644 --- a/tests/test.py +++ b/tests/test.py @@ -52,14 +52,16 @@ def test(self): if e.errno != errno.EEXIST: raise e - codecoverage.download_artifact(task_id, chosen_artifact) + codecoverage.download_artifact(task_id, chosen_artifact, 'ccov-artifacts') self.assertTrue(os.path.exists('ccov-artifacts/%s_target.txt' % task_id)) - codecoverage.download_coverage_artifacts(task_id, 'cppunit') - self.assertTrue(len(os.listdir('ccov-artifacts')) == 2) + codecoverage.download_coverage_artifacts(task_id, 'cppunit', 'ccov-artifacts') + self.assertEqual(len([a for a in os.listdir('ccov-artifacts') if 'grcov' in a]), 2) + self.assertEqual(len([a for a in os.listdir('ccov-artifacts') if 'jsvm' in a]), 2) + self.assertEqual(len([a for a in os.listdir('ccov-artifacts') if 'target' in a]), 1) codecoverage.download_grcov() - codecoverage.generate_report('./grcov', 'lcov', 'output.info') + codecoverage.generate_report('./grcov', 'lcov', 'output.info', 'ccov-artifacts') self.assertTrue(os.path.exists('output.info')) codecoverage.download_genhtml() @@ -74,9 +76,11 @@ def test_suite_name_from_task_name(self): ('test-linux64-ccov/debug-mochitest-clipboard', 'mochitest-clipboard'), ('test-linux64-ccov/debug-reftest-no-accel-e10s-5', 'reftest-no-accel'), ('test-linux64-ccov/debug-mochitest-5', 'mochitest'), + ('test-windows10-64-ccov/debug-mochitest-5', 'mochitest'), + ('test-windows10-64-ccov/debug-cppunit', 'cppunit'), ] for c in cases: - self.assertEqual(codecoverage.suite_name_from_task_name(c[0]), c[1]) + self.assertEqual(codecoverage.get_suite(c[0]), c[1]) def test_download_grcov(self): codecoverage.download_grcov() From 3d9efa075456a541ed57c17bd1d15f640c6978c0 Mon Sep 17 00:00:00 2001 From: Marco Castelluccio Date: Mon, 2 Jul 2018 11:31:06 +0100 Subject: [PATCH 073/134] Speed up tests --- tests/test.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/tests/test.py b/tests/test.py index e3a3b13fd..449e1d9e0 100644 --- a/tests/test.py +++ b/tests/test.py @@ -54,16 +54,20 @@ def test(self): codecoverage.download_artifact(task_id, chosen_artifact, 'ccov-artifacts') self.assertTrue(os.path.exists('ccov-artifacts/%s_target.txt' % task_id)) + os.remove('ccov-artifacts/%s_target.txt' % task_id) codecoverage.download_coverage_artifacts(task_id, 'cppunit', 'ccov-artifacts') self.assertEqual(len([a for a in os.listdir('ccov-artifacts') if 'grcov' in a]), 2) self.assertEqual(len([a for a in os.listdir('ccov-artifacts') if 'jsvm' in a]), 2) - self.assertEqual(len([a for a in os.listdir('ccov-artifacts') if 'target' in a]), 1) codecoverage.download_grcov() codecoverage.generate_report('./grcov', 'lcov', 'output.info', 'ccov-artifacts') self.assertTrue(os.path.exists('output.info')) + # Remove all artifacts except one to make the genhtml pass faster for the test. + for a in os.listdir('ccov-artifacts')[:-1]: + os.remove(os.path.join('ccov-artifacts', a)) + codecoverage.download_genhtml() codecoverage.generate_html_report('tests') self.assertTrue(os.path.isdir('report')) From e88d94e320b8b651904ad024f8de4e4c0f176078 Mon Sep 17 00:00:00 2001 From: Marco Castelluccio Date: Mon, 2 Jul 2018 13:00:44 +0100 Subject: [PATCH 074/134] Only use one grcov artifact for the test --- tests/test.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/tests/test.py b/tests/test.py index 449e1d9e0..e354c18e6 100644 --- a/tests/test.py +++ b/tests/test.py @@ -65,8 +65,10 @@ def test(self): self.assertTrue(os.path.exists('output.info')) # Remove all artifacts except one to make the genhtml pass faster for the test. - for a in os.listdir('ccov-artifacts')[:-1]: - os.remove(os.path.join('ccov-artifacts', a)) + for a in os.listdir('ccov-artifacts'): + if 'jsvm' in a: + os.remove(os.path.join('ccov-artifacts', a)) + os.remove(os.path.join('ccov-artifacts', os.listdir('ccov-artifacts')[0])) codecoverage.download_genhtml() codecoverage.generate_html_report('tests') From 5ac08eb014681bb7ae1818a91b1591b8766a755a Mon Sep 17 00:00:00 2001 From: Marco Castelluccio Date: Mon, 2 Jul 2018 14:18:20 +0100 Subject: [PATCH 075/134] Add option to choose platform --- codecoverage.py | 32 +++++++++++++++++++++++++------- tests/test.py | 4 ++-- 2 files changed, 27 insertions(+), 9 deletions(-) diff --git a/codecoverage.py b/codecoverage.py index 482c3c0fc..d27954927 100644 --- a/codecoverage.py +++ b/codecoverage.py @@ -96,7 +96,16 @@ def get_suite(task_name): return '-'.join([p for p in get_chunk(task_name).split('-') if not p.isdigit()]) -def download_coverage_artifacts(build_task_id, suites, artifacts_path, suites_to_ignore=['talos', 'awsy']): +def get_platform(task_name): + if 'linux' in task_name: + return 'linux' + elif 'windows' in task_name: + return 'windows' + else: + raise Exception('Unknown platform') + + +def download_coverage_artifacts(build_task_id, suites, platforms, artifacts_path, suites_to_ignore=['talos', 'awsy']): try: os.mkdir(artifacts_path) except OSError as e: @@ -110,11 +119,15 @@ def _is_test_task(t): return any(t['task']['metadata']['name'].startswith(tp) for tp in TEST_PLATFORMS) # Returns True if the task is part of one of the suites chosen by the user. - def _is_chosen_task(t): + def _is_in_suites_task(t): suite_name = get_suite(t['task']['metadata']['name']) return suites is None or suite_name in suites and suite_name not in suites_to_ignore - test_tasks = [t for t in get_tasks_in_group(task_data['taskGroupId']) if _is_test_task(t) and _is_chosen_task(t)] + def _is_in_platforms_task(t): + platform = get_platform(t['task']['metadata']['name']) + return platforms is None or platform in platforms + + test_tasks = [t for t in get_tasks_in_group(task_data['taskGroupId']) if _is_test_task(t) and _is_in_suites_task(t) and _is_in_platforms_task(t)] if suites is not None: for suite in suites: @@ -160,12 +173,16 @@ def generate_report(grcov_path, output_format, output_path, artifacts_path): raise Exception('Error while running grcov:\n' + proc.stderr.read()) -def generate_html_report(src_dir, info_file=os.path.join(os.getcwd(), 'output.info'), output_dir=os.path.join(os.getcwd(), 'report')): +def generate_html_report(src_dir, info_file=os.path.join(os.getcwd(), 'output.info'), output_dir=os.path.join(os.getcwd(), 'report'), silent=False): cwd = os.getcwd() os.chdir(src_dir) - ret = subprocess.call([os.path.join(cwd, 'lcov-bin/usr/local/bin/genhtml'), '-o', output_dir, '--show-details', '--highlight', '--ignore-errors', 'source', '--legend', info_file, '--prefix', src_dir]) + + with open(os.devnull, 'w') as fnull: + ret = subprocess.call([os.path.join(cwd, 'lcov-bin/usr/local/bin/genhtml'), '-o', output_dir, '--show-details', '--highlight', '--ignore-errors', 'source', '--legend', info_file, '--prefix', src_dir], stdout=fnull if silent else None, stderr=fnull if silent else None) + if ret != 0: raise Exception('Error while running genhtml.') + os.chdir(cwd) @@ -234,6 +251,7 @@ def main(): parser.add_argument('commit', action='store', nargs='?', default=default_commit, help='Commit hash for push') parser.add_argument('--grcov', action='store', nargs='?', help='Path to grcov') parser.add_argument('--with-artifacts', action='store', nargs='?', default='ccov-artifacts', help='Path to already downloaded coverage files') + parser.add_argument('--platform', action='store', nargs='+', help='List of platforms to include (by default they are all included). E.g. \'linux\', \'windows\', etc.') parser.add_argument('--suite', action='store', nargs='+', help='List of test suites to include (by default they are all included). E.g. \'mochitest\', \'mochitest-chrome\', \'gtest\', etc.') parser.add_argument('--ignore', action='store', nargs='+', help='List of test suites to ignore (by default \'talos\' and \'awsy\'). E.g. \'mochitest\', \'mochitest-chrome\', \'gtest\', etc.') parser.add_argument('--stats', action='store_true', help='Only generate high-level stats, not a full HTML report') @@ -249,9 +267,9 @@ def main(): task_id = get_last_task() if args.ignore is None: - download_coverage_artifacts(task_id, args.suite, args.with_artifacts) + download_coverage_artifacts(task_id, args.suite, args.platform, args.with_artifacts) else: - download_coverage_artifacts(task_id, args.suite, args.with_artifacts, args.ignore) + download_coverage_artifacts(task_id, args.suite, args.platform, args.with_artifacts, args.ignore) if args.grcov: grcov_path = args.grcov diff --git a/tests/test.py b/tests/test.py index e354c18e6..14397d7f4 100644 --- a/tests/test.py +++ b/tests/test.py @@ -56,7 +56,7 @@ def test(self): self.assertTrue(os.path.exists('ccov-artifacts/%s_target.txt' % task_id)) os.remove('ccov-artifacts/%s_target.txt' % task_id) - codecoverage.download_coverage_artifacts(task_id, 'cppunit', 'ccov-artifacts') + codecoverage.download_coverage_artifacts(task_id, 'cppunit', None, 'ccov-artifacts') self.assertEqual(len([a for a in os.listdir('ccov-artifacts') if 'grcov' in a]), 2) self.assertEqual(len([a for a in os.listdir('ccov-artifacts') if 'jsvm' in a]), 2) @@ -71,7 +71,7 @@ def test(self): os.remove(os.path.join('ccov-artifacts', os.listdir('ccov-artifacts')[0])) codecoverage.download_genhtml() - codecoverage.generate_html_report('tests') + codecoverage.generate_html_report('tests', silent=True) self.assertTrue(os.path.isdir('report')) def test_suite_name_from_task_name(self): From d3a95ac4a1a3a181339ccd438c712737b8ae1b3d Mon Sep 17 00:00:00 2001 From: Marco Castelluccio Date: Mon, 2 Jul 2018 14:28:41 +0100 Subject: [PATCH 076/134] Add missing newline to please flake8 --- codecoverage.py | 1 + 1 file changed, 1 insertion(+) diff --git a/codecoverage.py b/codecoverage.py index d27954927..b7dde072e 100644 --- a/codecoverage.py +++ b/codecoverage.py @@ -84,6 +84,7 @@ def download_artifact(task_id, artifact, artifacts_path): time.sleep(7) + def get_chunk(task_name): for t in TEST_PLATFORMS: if task_name.startswith(t): From 3433477170fddcb63b692c82315bdded0fced2b5 Mon Sep 17 00:00:00 2001 From: Assiya Khuzyakhmetova Date: Wed, 4 Jul 2018 23:55:12 +0600 Subject: [PATCH 077/134] Add option to use existing CSS style file (#41) --- codecoverage.py | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/codecoverage.py b/codecoverage.py index b7dde072e..f4ebbca3a 100644 --- a/codecoverage.py +++ b/codecoverage.py @@ -174,12 +174,15 @@ def generate_report(grcov_path, output_format, output_path, artifacts_path): raise Exception('Error while running grcov:\n' + proc.stderr.read()) -def generate_html_report(src_dir, info_file=os.path.join(os.getcwd(), 'output.info'), output_dir=os.path.join(os.getcwd(), 'report'), silent=False): +def generate_html_report(src_dir, info_file=os.path.join(os.getcwd(), 'output.info'), output_dir=os.path.join(os.getcwd(), 'report'), silent=False, style_file=None): cwd = os.getcwd() os.chdir(src_dir) with open(os.devnull, 'w') as fnull: - ret = subprocess.call([os.path.join(cwd, 'lcov-bin/usr/local/bin/genhtml'), '-o', output_dir, '--show-details', '--highlight', '--ignore-errors', 'source', '--legend', info_file, '--prefix', src_dir], stdout=fnull if silent else None, stderr=fnull if silent else None) + command = [os.path.join(cwd, 'lcov-bin/usr/local/bin/genhtml'), '-o', output_dir, '--show-details', '--highlight', '--ignore-errors', 'source', '--legend', info_file, '--prefix', src_dir] + if style_file is not None: + command += ['--css-file', style_file] + ret = subprocess.call(command, stdout=fnull if silent else None, stderr=fnull if silent else None) if ret != 0: raise Exception('Error while running genhtml.') From a7c6731950cd46b2a5222b2028c59293e627d7ed Mon Sep 17 00:00:00 2001 From: Assiya Khuzyakhmetova Date: Mon, 9 Jul 2018 22:23:15 +0600 Subject: [PATCH 078/134] Choose the task with the best status if there are retriggers (#43) --- codecoverage.py | 37 ++++++++++++++++++++++++++++++++++++- 1 file changed, 36 insertions(+), 1 deletion(-) diff --git a/codecoverage.py b/codecoverage.py index f4ebbca3a..87422cbc6 100644 --- a/codecoverage.py +++ b/codecoverage.py @@ -19,6 +19,13 @@ TEST_PLATFORMS = ['test-linux64-ccov/debug', 'test-windows10-64-ccov/debug'] +FINISHED_STATUSES = ['completed', 'failed', 'exception'] +ALL_STATUSES = FINISHED_STATUSES + ['unscheduled', 'pending', 'running'] +STATUS_VALUE = { + 'exception': 1, + 'failed': 2, + 'completed': 3, +} def get_json(url, params=None, headers={}): @@ -106,6 +113,11 @@ def get_platform(task_name): raise Exception('Unknown platform') +def get_task_status(task_id): + status = get_json('https://queue.taskcluster.net/v1/task/{}/status'.format(task_id)) + return status['status']['state'] + + def download_coverage_artifacts(build_task_id, suites, platforms, artifacts_path, suites_to_ignore=['talos', 'awsy']): try: os.mkdir(artifacts_path) @@ -135,7 +147,30 @@ def _is_in_platforms_task(t): if not any(suite in t['task']['metadata']['name'] for t in test_tasks): warnings.warn('Suite %s not found' % suite) - for i, test_task in enumerate(test_tasks): + download_tasks = {} + + for test_task in test_tasks: + status = test_task['status']['state'] + assert status in ALL_STATUSES, "State '{}' not recognized".format(status) + + while status not in FINISHED_STATUSES: + sys.stdout.write('\rWaiting for task {} to finish...'.format(test_task['status']['taskId'])) + sys.stdout.flush() + time.sleep(60) + status = get_task_status(test_task['status']['taskId']) + assert status in ALL_STATUSES + + chunk_name = get_chunk(test_task['task']['metadata']['name']) + platform_name = get_platform(test_task['task']['metadata']['name']) + + if (chunk_name, platform_name) not in download_tasks: + download_tasks[(chunk_name, platform_name)] = test_task + else: + prev_task = download_tasks[(chunk_name, platform_name)] + if STATUS_VALUE[status] > STATUS_VALUE[prev_task['status']['state']]: + download_tasks[(chunk_name, platform_name)] = test_task + + for i, test_task in enumerate(download_tasks.values()): sys.stdout.write('\rDownloading artifacts from {}/{} test task...'.format(i, len(test_tasks))) sys.stdout.flush() artifacts = get_task_artifacts(test_task['status']['taskId']) From a85301b198decd90b2fcbbc95cf1c71fbf2d10d3 Mon Sep 17 00:00:00 2001 From: Marco Castelluccio Date: Tue, 10 Jul 2018 21:30:56 +0200 Subject: [PATCH 079/134] Take into account filters (suite and platform) also when the artifacts directory already exists --- codecoverage.py | 17 ++++++++++------- tests/test.py | 12 ++++-------- 2 files changed, 14 insertions(+), 15 deletions(-) diff --git a/codecoverage.py b/codecoverage.py index 87422cbc6..32a9b2d4b 100644 --- a/codecoverage.py +++ b/codecoverage.py @@ -90,6 +90,7 @@ def download_artifact(task_id, artifact, artifacts_path): pass time.sleep(7) + return fname def get_chunk(task_name): @@ -170,17 +171,19 @@ def _is_in_platforms_task(t): if STATUS_VALUE[status] > STATUS_VALUE[prev_task['status']['state']]: download_tasks[(chunk_name, platform_name)] = test_task + artifact_paths = [] for i, test_task in enumerate(download_tasks.values()): sys.stdout.write('\rDownloading artifacts from {}/{} test task...'.format(i, len(test_tasks))) sys.stdout.flush() artifacts = get_task_artifacts(test_task['status']['taskId']) for artifact in artifacts: if any(a in artifact['name'] for a in ['code-coverage-grcov.zip', 'code-coverage-jsvm.zip']): - download_artifact(test_task['status']['taskId'], artifact, artifacts_path) + artifact_paths.append(download_artifact(test_task['status']['taskId'], artifact, artifacts_path)) print('') + return artifact_paths -def generate_report(grcov_path, output_format, output_path, artifacts_path): +def generate_report(grcov_path, output_format, output_path, artifact_paths): mod_env = os.environ.copy() if is_taskcluster_loaner(): one_click_loaner_gcc = '/home/worker/workspace/build/src/gcc/bin' @@ -194,7 +197,7 @@ def generate_report(grcov_path, output_format, output_path, artifacts_path): cmd = [grcov_path, '-t', output_format, '-p', '/home/worker/workspace/build/src/'] if output_format in ['coveralls', 'coveralls+']: cmd += ['--token', 'UNUSED', '--commit-sha', 'UNUSED'] - cmd.extend([os.path.join(artifacts_path, p) for p in os.listdir(artifacts_path)]) + cmd.extend(artifact_paths) proc = subprocess.Popen(cmd, stdout=fout, stderr=subprocess.PIPE, env=mod_env) i = 0 while proc.poll() is None: @@ -306,9 +309,9 @@ def main(): task_id = get_last_task() if args.ignore is None: - download_coverage_artifacts(task_id, args.suite, args.platform, args.with_artifacts) + artifact_paths = download_coverage_artifacts(task_id, args.suite, args.platform, args.with_artifacts) else: - download_coverage_artifacts(task_id, args.suite, args.platform, args.with_artifacts, args.ignore) + artifact_paths = download_coverage_artifacts(task_id, args.suite, args.platform, args.with_artifacts, args.ignore) if args.grcov: grcov_path = args.grcov @@ -317,7 +320,7 @@ def main(): grcov_path = './grcov' if args.stats: - generate_report(grcov_path, 'coveralls', 'output.json', args.with_artifacts) + generate_report(grcov_path, 'coveralls', 'output.json', artifact_paths) with open('output.json', 'r') as f: report = json.load(f) @@ -337,7 +340,7 @@ def main(): print('Covered lines: {}'.format(total_lines_covered)) print('Coverage percentage: {}'.format(float(total_lines_covered) / float(total_lines))) else: - generate_report(grcov_path, 'lcov', 'output.info', args.with_artifacts) + generate_report(grcov_path, 'lcov', 'output.info', artifact_paths) download_genhtml() generate_html_report(os.path.abspath(args.src_dir)) diff --git a/tests/test.py b/tests/test.py index 14397d7f4..254123575 100644 --- a/tests/test.py +++ b/tests/test.py @@ -56,20 +56,16 @@ def test(self): self.assertTrue(os.path.exists('ccov-artifacts/%s_target.txt' % task_id)) os.remove('ccov-artifacts/%s_target.txt' % task_id) - codecoverage.download_coverage_artifacts(task_id, 'cppunit', None, 'ccov-artifacts') + artifact_paths = codecoverage.download_coverage_artifacts(task_id, 'cppunit', None, 'ccov-artifacts') self.assertEqual(len([a for a in os.listdir('ccov-artifacts') if 'grcov' in a]), 2) self.assertEqual(len([a for a in os.listdir('ccov-artifacts') if 'jsvm' in a]), 2) + self.assertEqual(len([a for a in artifact_paths if 'grcov' in a]), 2) + self.assertEqual(len([a for a in artifact_paths if 'jsvm' in a]), 2) codecoverage.download_grcov() - codecoverage.generate_report('./grcov', 'lcov', 'output.info', 'ccov-artifacts') + codecoverage.generate_report('./grcov', 'lcov', 'output.info', artifact_paths) self.assertTrue(os.path.exists('output.info')) - # Remove all artifacts except one to make the genhtml pass faster for the test. - for a in os.listdir('ccov-artifacts'): - if 'jsvm' in a: - os.remove(os.path.join('ccov-artifacts', a)) - os.remove(os.path.join('ccov-artifacts', os.listdir('ccov-artifacts')[0])) - codecoverage.download_genhtml() codecoverage.generate_html_report('tests', silent=True) self.assertTrue(os.path.isdir('report')) From 9ad6c3795fffd1f16b27598f8e6ada7fd427d302 Mon Sep 17 00:00:00 2001 From: Marco Castelluccio Date: Wed, 18 Jul 2018 12:48:28 +0200 Subject: [PATCH 080/134] No need to create lcov-bin directory, it's created automatically by make --- codecoverage.py | 6 ------ 1 file changed, 6 deletions(-) diff --git a/codecoverage.py b/codecoverage.py index 32a9b2d4b..c2a5a3aea 100644 --- a/codecoverage.py +++ b/codecoverage.py @@ -256,12 +256,6 @@ def download_grcov(): def download_genhtml(): - try: - os.mkdir('lcov-bin') - except OSError as e: - if e.errno != errno.EEXIST: - raise e - if os.path.isdir('lcov'): os.chdir('lcov') subprocess.check_call(['git', 'pull']) From e9073166968dd4ac33510a61116f8b8855b933af Mon Sep 17 00:00:00 2001 From: Marco Castelluccio Date: Fri, 27 Jul 2018 23:45:30 +0100 Subject: [PATCH 081/134] Add license to setup.py --- setup.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/setup.py b/setup.py index 731935a29..857ee93aa 100644 --- a/setup.py +++ b/setup.py @@ -7,5 +7,6 @@ name='firefox_code_coverage', version='1.0.0', description='Code Coverage Report generator for Firefox', - packages=find_packages(exclude=['contrib', 'docs', 'tests']) + packages=find_packages(exclude=['contrib', 'docs', 'tests']), + license='MPL2', ) From 3c70be1de846dde18bc5e8d51320e67ec6601e4f Mon Sep 17 00:00:00 2001 From: Marco Date: Tue, 31 Jul 2018 17:24:11 +0100 Subject: [PATCH 082/134] Move module in a canonical location (#45) --- firefox_code_coverage/__init__.py | 1 + codecoverage.py => firefox_code_coverage/codecoverage.py | 0 tests/test.py | 2 +- 3 files changed, 2 insertions(+), 1 deletion(-) create mode 100644 firefox_code_coverage/__init__.py rename codecoverage.py => firefox_code_coverage/codecoverage.py (100%) diff --git a/firefox_code_coverage/__init__.py b/firefox_code_coverage/__init__.py new file mode 100644 index 000000000..40a96afc6 --- /dev/null +++ b/firefox_code_coverage/__init__.py @@ -0,0 +1 @@ +# -*- coding: utf-8 -*- diff --git a/codecoverage.py b/firefox_code_coverage/codecoverage.py similarity index 100% rename from codecoverage.py rename to firefox_code_coverage/codecoverage.py diff --git a/tests/test.py b/tests/test.py index 254123575..d07015cbc 100644 --- a/tests/test.py +++ b/tests/test.py @@ -9,7 +9,7 @@ import shutil import unittest -import codecoverage +from firefox_code_coverage import codecoverage class Test(unittest.TestCase): From cc386da20f389fd5159746d56729e149029de6ae Mon Sep 17 00:00:00 2001 From: Assiya Khuzyakhmetova Date: Mon, 6 Aug 2018 17:16:29 +0600 Subject: [PATCH 083/134] Remove use of prefix in genhtml (#47) --- firefox_code_coverage/codecoverage.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/firefox_code_coverage/codecoverage.py b/firefox_code_coverage/codecoverage.py index c2a5a3aea..5d7f7255f 100644 --- a/firefox_code_coverage/codecoverage.py +++ b/firefox_code_coverage/codecoverage.py @@ -217,7 +217,7 @@ def generate_html_report(src_dir, info_file=os.path.join(os.getcwd(), 'output.in os.chdir(src_dir) with open(os.devnull, 'w') as fnull: - command = [os.path.join(cwd, 'lcov-bin/usr/local/bin/genhtml'), '-o', output_dir, '--show-details', '--highlight', '--ignore-errors', 'source', '--legend', info_file, '--prefix', src_dir] + command = [os.path.join(cwd, 'lcov-bin/usr/local/bin/genhtml'), '-o', output_dir, '--show-details', '--highlight', '--ignore-errors', 'source', '--legend', info_file] if style_file is not None: command += ['--css-file', style_file] ret = subprocess.call(command, stdout=fnull if silent else None, stderr=fnull if silent else None) From 06e2438cf0f1c29b7fae129f8b73231e55f3e14b Mon Sep 17 00:00:00 2001 From: "pyup.io bot" Date: Tue, 28 Aug 2018 03:49:19 -0700 Subject: [PATCH 084/134] Pin all dependencies (#50) * Pin flake8 to latest version 3.5.0 * Pin flake8-isort to latest version 2.5 * Pin flake8-quotes to latest version 1.0.0 * Pin flake8-coding to latest version 1.3.0 * Pin flake8-copyright to latest version 0.2.0 * Pin flake8-debugger to latest version 3.1.0 * Pin wheel to latest version 0.31.1 * Pin setuptools to latest version 40.2.0 --- test-requirements.txt | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/test-requirements.txt b/test-requirements.txt index 1074b0f34..2fafb86b1 100644 --- a/test-requirements.txt +++ b/test-requirements.txt @@ -1,8 +1,8 @@ -flake8 -flake8-isort -flake8-quotes -flake8-coding -flake8-copyright -flake8-debugger -wheel -setuptools +flake8==3.5.0 +flake8-isort==2.5 +flake8-quotes==1.0.0 +flake8-coding==1.3.0 +flake8-copyright==0.2.0 +flake8-debugger==3.1.0 +wheel==0.31.1 +setuptools==40.2.0 From d85c7558ebd5f429d4fb9a533d0ccdf082f63406 Mon Sep 17 00:00:00 2001 From: "pyup.io bot" Date: Sun, 9 Sep 2018 03:47:19 -0700 Subject: [PATCH 085/134] Update flake8-coding from 1.3.0 to 1.3.1 (#51) --- test-requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test-requirements.txt b/test-requirements.txt index 2fafb86b1..3275d942c 100644 --- a/test-requirements.txt +++ b/test-requirements.txt @@ -1,7 +1,7 @@ flake8==3.5.0 flake8-isort==2.5 flake8-quotes==1.0.0 -flake8-coding==1.3.0 +flake8-coding==1.3.1 flake8-copyright==0.2.0 flake8-debugger==3.1.0 wheel==0.31.1 From 177d95371c7b95f338e7be30b3a3431bdfdf7e79 Mon Sep 17 00:00:00 2001 From: Marco Castelluccio Date: Tue, 11 Sep 2018 02:16:51 +0200 Subject: [PATCH 086/134] Fix error message --- firefox_code_coverage/codecoverage.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/firefox_code_coverage/codecoverage.py b/firefox_code_coverage/codecoverage.py index 5d7f7255f..590ecc505 100644 --- a/firefox_code_coverage/codecoverage.py +++ b/firefox_code_coverage/codecoverage.py @@ -209,7 +209,7 @@ def generate_report(grcov_path, output_format, output_path, artifact_paths): print('') if proc.poll() != 0: - raise Exception('Error while running grcov:\n' + proc.stderr.read()) + raise Exception('Error while running grcov: {}\n'.format(proc.stderr.read())) def generate_html_report(src_dir, info_file=os.path.join(os.getcwd(), 'output.info'), output_dir=os.path.join(os.getcwd(), 'report'), silent=False, style_file=None): From 410b6332f059daa31596f70df4c1b876e9e77ce4 Mon Sep 17 00:00:00 2001 From: "pyup.io bot" Date: Sun, 16 Sep 2018 16:52:40 -0700 Subject: [PATCH 087/134] Update setuptools from 40.2.0 to 40.3.0 (#52) --- test-requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test-requirements.txt b/test-requirements.txt index 3275d942c..5813dbfdc 100644 --- a/test-requirements.txt +++ b/test-requirements.txt @@ -5,4 +5,4 @@ flake8-coding==1.3.1 flake8-copyright==0.2.0 flake8-debugger==3.1.0 wheel==0.31.1 -setuptools==40.2.0 +setuptools==40.3.0 From 673b1a245a6d5176fc94ec25ba3881e702ae0eb9 Mon Sep 17 00:00:00 2001 From: "pyup.io bot" Date: Tue, 18 Sep 2018 08:19:43 -0700 Subject: [PATCH 088/134] Update setuptools from 40.3.0 to 40.4.0 (#53) --- test-requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test-requirements.txt b/test-requirements.txt index 5813dbfdc..592da1abe 100644 --- a/test-requirements.txt +++ b/test-requirements.txt @@ -5,4 +5,4 @@ flake8-coding==1.3.1 flake8-copyright==0.2.0 flake8-debugger==3.1.0 wheel==0.31.1 -setuptools==40.3.0 +setuptools==40.4.0 From 3600faedd1c35c7ed25f411e88243bb6cb1f5648 Mon Sep 17 00:00:00 2001 From: "pyup.io bot" Date: Tue, 18 Sep 2018 10:13:02 -0700 Subject: [PATCH 089/134] Update setuptools from 40.4.0 to 40.4.1 (#54) --- test-requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test-requirements.txt b/test-requirements.txt index 592da1abe..84de2ec4d 100644 --- a/test-requirements.txt +++ b/test-requirements.txt @@ -5,4 +5,4 @@ flake8-coding==1.3.1 flake8-copyright==0.2.0 flake8-debugger==3.1.0 wheel==0.31.1 -setuptools==40.4.0 +setuptools==40.4.1 From 4205e971588ed43056bc3a190abc32f9501f209c Mon Sep 17 00:00:00 2001 From: "pyup.io bot" Date: Fri, 21 Sep 2018 16:07:27 -0700 Subject: [PATCH 090/134] Update setuptools from 40.4.1 to 40.4.2 (#55) --- test-requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test-requirements.txt b/test-requirements.txt index 84de2ec4d..e3e62d0a6 100644 --- a/test-requirements.txt +++ b/test-requirements.txt @@ -5,4 +5,4 @@ flake8-coding==1.3.1 flake8-copyright==0.2.0 flake8-debugger==3.1.0 wheel==0.31.1 -setuptools==40.4.1 +setuptools==40.4.2 From 10f64dc3d3f8e465ec695c7319b485abc1b979df Mon Sep 17 00:00:00 2001 From: "pyup.io bot" Date: Sun, 23 Sep 2018 09:56:23 -0700 Subject: [PATCH 091/134] Update setuptools from 40.4.2 to 40.4.3 (#56) --- test-requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test-requirements.txt b/test-requirements.txt index e3e62d0a6..31b139a5e 100644 --- a/test-requirements.txt +++ b/test-requirements.txt @@ -5,4 +5,4 @@ flake8-coding==1.3.1 flake8-copyright==0.2.0 flake8-debugger==3.1.0 wheel==0.31.1 -setuptools==40.4.2 +setuptools==40.4.3 From bd6f0fbc87cfd8b3c67bd6462c9f9082c6a3c218 Mon Sep 17 00:00:00 2001 From: "pyup.io bot" Date: Sun, 30 Sep 2018 02:56:09 -0700 Subject: [PATCH 092/134] Update wheel from 0.31.1 to 0.32.0 (#57) --- test-requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test-requirements.txt b/test-requirements.txt index 31b139a5e..4dc0e9eae 100644 --- a/test-requirements.txt +++ b/test-requirements.txt @@ -4,5 +4,5 @@ flake8-quotes==1.0.0 flake8-coding==1.3.1 flake8-copyright==0.2.0 flake8-debugger==3.1.0 -wheel==0.31.1 +wheel==0.32.0 setuptools==40.4.3 From 24901a7dbf038f24eb1ba6c2d9d6f9444d453cb3 Mon Sep 17 00:00:00 2001 From: "pyup.io bot" Date: Thu, 4 Oct 2018 06:37:27 -0700 Subject: [PATCH 093/134] Update wheel from 0.32.0 to 0.32.1 (#58) --- test-requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test-requirements.txt b/test-requirements.txt index 4dc0e9eae..93ae9c124 100644 --- a/test-requirements.txt +++ b/test-requirements.txt @@ -4,5 +4,5 @@ flake8-quotes==1.0.0 flake8-coding==1.3.1 flake8-copyright==0.2.0 flake8-debugger==3.1.0 -wheel==0.32.0 +wheel==0.32.1 setuptools==40.4.3 From 0ad94dcd970a90ef1cddff771adbc7c13bd52914 Mon Sep 17 00:00:00 2001 From: "pyup.io bot" Date: Wed, 10 Oct 2018 07:45:32 -0700 Subject: [PATCH 094/134] Update flake8-copyright from 0.2.0 to 0.2.2 (#60) --- test-requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test-requirements.txt b/test-requirements.txt index 93ae9c124..df26c8bef 100644 --- a/test-requirements.txt +++ b/test-requirements.txt @@ -2,7 +2,7 @@ flake8==3.5.0 flake8-isort==2.5 flake8-quotes==1.0.0 flake8-coding==1.3.1 -flake8-copyright==0.2.0 +flake8-copyright==0.2.2 flake8-debugger==3.1.0 wheel==0.32.1 setuptools==40.4.3 From 6fe606e4963b910f569ac04a5bdf4e72ef373e58 Mon Sep 17 00:00:00 2001 From: "pyup.io bot" Date: Sun, 21 Oct 2018 06:32:14 -0700 Subject: [PATCH 095/134] Update wheel from 0.32.1 to 0.32.2 (#62) --- test-requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test-requirements.txt b/test-requirements.txt index df26c8bef..ceb50e43a 100644 --- a/test-requirements.txt +++ b/test-requirements.txt @@ -4,5 +4,5 @@ flake8-quotes==1.0.0 flake8-coding==1.3.1 flake8-copyright==0.2.2 flake8-debugger==3.1.0 -wheel==0.32.1 +wheel==0.32.2 setuptools==40.4.3 From 57d190cb9d16021ac9ab7dd575487337148d4dea Mon Sep 17 00:00:00 2001 From: "pyup.io bot" Date: Wed, 24 Oct 2018 09:09:03 -0700 Subject: [PATCH 096/134] Update flake8 from 3.5.0 to 3.6.0 (#63) --- test-requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test-requirements.txt b/test-requirements.txt index ceb50e43a..3fd959402 100644 --- a/test-requirements.txt +++ b/test-requirements.txt @@ -1,4 +1,4 @@ -flake8==3.5.0 +flake8==3.6.0 flake8-isort==2.5 flake8-quotes==1.0.0 flake8-coding==1.3.1 From 8d75b48afa0206be9644ca60fa0657768b86e501 Mon Sep 17 00:00:00 2001 From: "pyup.io bot" Date: Fri, 26 Oct 2018 11:03:53 -0700 Subject: [PATCH 097/134] Update setuptools from 40.4.3 to 40.5.0 (#64) --- test-requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test-requirements.txt b/test-requirements.txt index 3fd959402..42362795a 100644 --- a/test-requirements.txt +++ b/test-requirements.txt @@ -5,4 +5,4 @@ flake8-coding==1.3.1 flake8-copyright==0.2.2 flake8-debugger==3.1.0 wheel==0.32.2 -setuptools==40.4.3 +setuptools==40.5.0 From f230ae329cee969589d642a22f8100742eb75d95 Mon Sep 17 00:00:00 2001 From: "pyup.io bot" Date: Tue, 13 Nov 2018 01:26:38 -0800 Subject: [PATCH 098/134] Update setuptools from 40.5.0 to 40.6.1 (#66) --- test-requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test-requirements.txt b/test-requirements.txt index 42362795a..554833930 100644 --- a/test-requirements.txt +++ b/test-requirements.txt @@ -5,4 +5,4 @@ flake8-coding==1.3.1 flake8-copyright==0.2.2 flake8-debugger==3.1.0 wheel==0.32.2 -setuptools==40.5.0 +setuptools==40.6.1 From 274f8ae7515b8f9a1e28f898e8ae90564235f4e7 Mon Sep 17 00:00:00 2001 From: "pyup.io bot" Date: Tue, 13 Nov 2018 05:40:46 -0800 Subject: [PATCH 099/134] Update setuptools from 40.6.1 to 40.6.2 (#67) --- test-requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test-requirements.txt b/test-requirements.txt index 554833930..80d97d89f 100644 --- a/test-requirements.txt +++ b/test-requirements.txt @@ -5,4 +5,4 @@ flake8-coding==1.3.1 flake8-copyright==0.2.2 flake8-debugger==3.1.0 wheel==0.32.2 -setuptools==40.6.1 +setuptools==40.6.2 From e740e079c5bf5634d024428ee25dfb7e7fedae41 Mon Sep 17 00:00:00 2001 From: "pyup.io bot" Date: Mon, 19 Nov 2018 01:22:08 -0800 Subject: [PATCH 100/134] Update wheel from 0.32.2 to 0.32.3 (#68) --- test-requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test-requirements.txt b/test-requirements.txt index 80d97d89f..73b47a754 100644 --- a/test-requirements.txt +++ b/test-requirements.txt @@ -4,5 +4,5 @@ flake8-quotes==1.0.0 flake8-coding==1.3.1 flake8-copyright==0.2.2 flake8-debugger==3.1.0 -wheel==0.32.2 +wheel==0.32.3 setuptools==40.6.2 From 65d85cecddd5d954d844b3d3f011b022c7a82ba3 Mon Sep 17 00:00:00 2001 From: "pyup.io bot" Date: Mon, 3 Dec 2018 08:31:52 -0800 Subject: [PATCH 101/134] Update flake8-isort from 2.5 to 2.6.0 (#69) --- test-requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test-requirements.txt b/test-requirements.txt index 73b47a754..fbcd18538 100644 --- a/test-requirements.txt +++ b/test-requirements.txt @@ -1,5 +1,5 @@ flake8==3.6.0 -flake8-isort==2.5 +flake8-isort==2.6.0 flake8-quotes==1.0.0 flake8-coding==1.3.1 flake8-copyright==0.2.2 From d378786543cd0d15e7c80c2feec1c3f06aabebe4 Mon Sep 17 00:00:00 2001 From: "pyup.io bot" Date: Tue, 11 Dec 2018 14:27:39 -0800 Subject: [PATCH 102/134] Update setuptools from 40.6.2 to 40.6.3 (#70) --- test-requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test-requirements.txt b/test-requirements.txt index fbcd18538..4c073794f 100644 --- a/test-requirements.txt +++ b/test-requirements.txt @@ -5,4 +5,4 @@ flake8-coding==1.3.1 flake8-copyright==0.2.2 flake8-debugger==3.1.0 wheel==0.32.3 -setuptools==40.6.2 +setuptools==40.6.3 From b664e6cec13c69e262ac57b678e2e6169e3f2de7 Mon Sep 17 00:00:00 2001 From: "pyup.io bot" Date: Sun, 27 Jan 2019 08:46:12 -0800 Subject: [PATCH 103/134] Update setuptools from 40.6.3 to 40.7.0 (#71) --- test-requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test-requirements.txt b/test-requirements.txt index 4c073794f..67f13293d 100644 --- a/test-requirements.txt +++ b/test-requirements.txt @@ -5,4 +5,4 @@ flake8-coding==1.3.1 flake8-copyright==0.2.2 flake8-debugger==3.1.0 wheel==0.32.3 -setuptools==40.6.3 +setuptools==40.7.0 From eda7f581aa9d99d4771505bb7fb4c691e84ccf17 Mon Sep 17 00:00:00 2001 From: "pyup.io bot" Date: Tue, 29 Jan 2019 01:05:56 -0800 Subject: [PATCH 104/134] Update setuptools from 40.7.0 to 40.7.1 (#72) --- test-requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test-requirements.txt b/test-requirements.txt index 67f13293d..154de7747 100644 --- a/test-requirements.txt +++ b/test-requirements.txt @@ -5,4 +5,4 @@ flake8-coding==1.3.1 flake8-copyright==0.2.2 flake8-debugger==3.1.0 wheel==0.32.3 -setuptools==40.7.0 +setuptools==40.7.1 From 833ff5f3de584f25e8bbe2fe89a6f1b032c49034 Mon Sep 17 00:00:00 2001 From: "pyup.io bot" Date: Wed, 30 Jan 2019 10:04:52 -0800 Subject: [PATCH 105/134] Update flake8 from 3.6.0 to 3.7.1 (#73) --- test-requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test-requirements.txt b/test-requirements.txt index 154de7747..35c980c66 100644 --- a/test-requirements.txt +++ b/test-requirements.txt @@ -1,4 +1,4 @@ -flake8==3.6.0 +flake8==3.7.1 flake8-isort==2.6.0 flake8-quotes==1.0.0 flake8-coding==1.3.1 From 637889e1cd9fc6abee3efe622ba70ce5487a45e4 Mon Sep 17 00:00:00 2001 From: "pyup.io bot" Date: Fri, 1 Feb 2019 05:01:21 -0800 Subject: [PATCH 106/134] Update flake8 from 3.7.1 to 3.7.3 (#74) --- test-requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test-requirements.txt b/test-requirements.txt index 35c980c66..c0532f41a 100644 --- a/test-requirements.txt +++ b/test-requirements.txt @@ -1,4 +1,4 @@ -flake8==3.7.1 +flake8==3.7.3 flake8-isort==2.6.0 flake8-quotes==1.0.0 flake8-coding==1.3.1 From cea6db2f688c87cb2782e4ed0ac160b398ccdf80 Mon Sep 17 00:00:00 2001 From: "pyup.io bot" Date: Fri, 1 Feb 2019 05:01:36 -0800 Subject: [PATCH 107/134] Update setuptools from 40.7.1 to 40.7.2 (#75) --- test-requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test-requirements.txt b/test-requirements.txt index c0532f41a..3c97b9c5d 100644 --- a/test-requirements.txt +++ b/test-requirements.txt @@ -5,4 +5,4 @@ flake8-coding==1.3.1 flake8-copyright==0.2.2 flake8-debugger==3.1.0 wheel==0.32.3 -setuptools==40.7.1 +setuptools==40.7.2 From 2b2bafb51adb95ca09c9f0ec5a6ddc1c8ab7bd6c Mon Sep 17 00:00:00 2001 From: "pyup.io bot" Date: Fri, 1 Feb 2019 06:38:54 -0800 Subject: [PATCH 108/134] Update flake8 from 3.7.3 to 3.7.4 (#76) --- test-requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test-requirements.txt b/test-requirements.txt index 3c97b9c5d..c4b98293c 100644 --- a/test-requirements.txt +++ b/test-requirements.txt @@ -1,4 +1,4 @@ -flake8==3.7.3 +flake8==3.7.4 flake8-isort==2.6.0 flake8-quotes==1.0.0 flake8-coding==1.3.1 From 7b36018d68801b2023b0230faa6688a1a2ea122f Mon Sep 17 00:00:00 2001 From: "pyup.io bot" Date: Sun, 3 Feb 2019 15:44:16 -0800 Subject: [PATCH 109/134] Update setuptools from 40.7.2 to 40.7.3 (#77) --- test-requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test-requirements.txt b/test-requirements.txt index c4b98293c..628edab82 100644 --- a/test-requirements.txt +++ b/test-requirements.txt @@ -5,4 +5,4 @@ flake8-coding==1.3.1 flake8-copyright==0.2.2 flake8-debugger==3.1.0 wheel==0.32.3 -setuptools==40.7.2 +setuptools==40.7.3 From aaa035493416f65e10c0f75b4725658d89b8197b Mon Sep 17 00:00:00 2001 From: "pyup.io bot" Date: Tue, 5 Feb 2019 01:45:05 -0800 Subject: [PATCH 110/134] Update flake8 from 3.7.4 to 3.7.5 (#78) --- test-requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test-requirements.txt b/test-requirements.txt index 628edab82..395a8fb7b 100644 --- a/test-requirements.txt +++ b/test-requirements.txt @@ -1,4 +1,4 @@ -flake8==3.7.4 +flake8==3.7.5 flake8-isort==2.6.0 flake8-quotes==1.0.0 flake8-coding==1.3.1 From 8daf4bcbdbba19a13574e2335e49a14b4b69d09f Mon Sep 17 00:00:00 2001 From: "pyup.io bot" Date: Thu, 7 Feb 2019 03:26:08 -0800 Subject: [PATCH 111/134] Update setuptools from 40.7.3 to 40.8.0 (#79) --- test-requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test-requirements.txt b/test-requirements.txt index 395a8fb7b..685f3f335 100644 --- a/test-requirements.txt +++ b/test-requirements.txt @@ -5,4 +5,4 @@ flake8-coding==1.3.1 flake8-copyright==0.2.2 flake8-debugger==3.1.0 wheel==0.32.3 -setuptools==40.7.3 +setuptools==40.8.0 From 99c89912d68f701f23e030ccfb6bcb1a7a19bd04 Mon Sep 17 00:00:00 2001 From: "pyup.io bot" Date: Wed, 13 Feb 2019 02:57:11 -0800 Subject: [PATCH 112/134] Update wheel from 0.32.3 to 0.33.0 (#80) --- test-requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test-requirements.txt b/test-requirements.txt index 685f3f335..02c092d4b 100644 --- a/test-requirements.txt +++ b/test-requirements.txt @@ -4,5 +4,5 @@ flake8-quotes==1.0.0 flake8-coding==1.3.1 flake8-copyright==0.2.2 flake8-debugger==3.1.0 -wheel==0.32.3 +wheel==0.33.0 setuptools==40.8.0 From 34d779c94498521241fe5761f1af135c0ced91bd Mon Sep 17 00:00:00 2001 From: "pyup.io bot" Date: Tue, 19 Feb 2019 11:59:17 +0200 Subject: [PATCH 113/134] Update flake8 from 3.7.5 to 3.7.6 (#81) --- test-requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test-requirements.txt b/test-requirements.txt index 02c092d4b..e94388eac 100644 --- a/test-requirements.txt +++ b/test-requirements.txt @@ -1,4 +1,4 @@ -flake8==3.7.5 +flake8==3.7.6 flake8-isort==2.6.0 flake8-quotes==1.0.0 flake8-coding==1.3.1 From e8596fcc916dffc7b147e4efabf1e5e152c88dc5 Mon Sep 17 00:00:00 2001 From: "pyup.io bot" Date: Wed, 20 Feb 2019 02:03:25 +0200 Subject: [PATCH 114/134] Update wheel from 0.33.0 to 0.33.1 (#82) --- test-requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test-requirements.txt b/test-requirements.txt index e94388eac..affbe3041 100644 --- a/test-requirements.txt +++ b/test-requirements.txt @@ -4,5 +4,5 @@ flake8-quotes==1.0.0 flake8-coding==1.3.1 flake8-copyright==0.2.2 flake8-debugger==3.1.0 -wheel==0.33.0 +wheel==0.33.1 setuptools==40.8.0 From 781a78d5225334772392ad9e7056bcdc76bf805a Mon Sep 17 00:00:00 2001 From: "pyup.io bot" Date: Wed, 20 Mar 2019 02:11:58 +0200 Subject: [PATCH 115/134] Update flake8-isort from 2.6.0 to 2.7.0 (#83) --- test-requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test-requirements.txt b/test-requirements.txt index affbe3041..241fd3789 100644 --- a/test-requirements.txt +++ b/test-requirements.txt @@ -1,5 +1,5 @@ flake8==3.7.6 -flake8-isort==2.6.0 +flake8-isort==2.7.0 flake8-quotes==1.0.0 flake8-coding==1.3.1 flake8-copyright==0.2.2 From 445da82fede6918063c63309f21554204815259e Mon Sep 17 00:00:00 2001 From: "pyup.io bot" Date: Thu, 4 Apr 2019 01:27:14 +0200 Subject: [PATCH 116/134] Update setuptools from 40.8.0 to 40.9.0 (#84) --- test-requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test-requirements.txt b/test-requirements.txt index 241fd3789..ab21828f2 100644 --- a/test-requirements.txt +++ b/test-requirements.txt @@ -5,4 +5,4 @@ flake8-coding==1.3.1 flake8-copyright==0.2.2 flake8-debugger==3.1.0 wheel==0.33.1 -setuptools==40.8.0 +setuptools==40.9.0 From 7f39b7a9c2b4862dd9150624fee5a3b6e7dfce83 Mon Sep 17 00:00:00 2001 From: "pyup.io bot" Date: Fri, 5 Apr 2019 21:45:06 +0200 Subject: [PATCH 117/134] Update setuptools from 40.9.0 to 41.0.0 (#85) --- test-requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test-requirements.txt b/test-requirements.txt index ab21828f2..815278e97 100644 --- a/test-requirements.txt +++ b/test-requirements.txt @@ -5,4 +5,4 @@ flake8-coding==1.3.1 flake8-copyright==0.2.2 flake8-debugger==3.1.0 wheel==0.33.1 -setuptools==40.9.0 +setuptools==41.0.0 From 939268032015bc6c04b51433238713c4bc4e506a Mon Sep 17 00:00:00 2001 From: "pyup.io bot" Date: Tue, 23 Apr 2019 16:50:26 +0200 Subject: [PATCH 118/134] Update setuptools from 41.0.0 to 41.0.1 (#87) --- test-requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test-requirements.txt b/test-requirements.txt index 815278e97..3c2a88baa 100644 --- a/test-requirements.txt +++ b/test-requirements.txt @@ -5,4 +5,4 @@ flake8-coding==1.3.1 flake8-copyright==0.2.2 flake8-debugger==3.1.0 wheel==0.33.1 -setuptools==41.0.0 +setuptools==41.0.1 From da94890a12c82dd9b94a1122cc767c861c5eba61 Mon Sep 17 00:00:00 2001 From: "pyup.io bot" Date: Thu, 9 May 2019 18:00:29 +0200 Subject: [PATCH 119/134] Update wheel from 0.33.1 to 0.33.2 (#89) --- test-requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test-requirements.txt b/test-requirements.txt index 3c2a88baa..eca4f61bf 100644 --- a/test-requirements.txt +++ b/test-requirements.txt @@ -4,5 +4,5 @@ flake8-quotes==1.0.0 flake8-coding==1.3.1 flake8-copyright==0.2.2 flake8-debugger==3.1.0 -wheel==0.33.1 +wheel==0.33.2 setuptools==41.0.1 From b8cf82449464481472079a1ab7ef2e7c32cab574 Mon Sep 17 00:00:00 2001 From: "pyup.io bot" Date: Sun, 12 May 2019 12:19:18 +0200 Subject: [PATCH 120/134] Update wheel from 0.33.2 to 0.33.4 (#91) --- test-requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test-requirements.txt b/test-requirements.txt index eca4f61bf..f59bdaff5 100644 --- a/test-requirements.txt +++ b/test-requirements.txt @@ -4,5 +4,5 @@ flake8-quotes==1.0.0 flake8-coding==1.3.1 flake8-copyright==0.2.2 flake8-debugger==3.1.0 -wheel==0.33.2 +wheel==0.33.4 setuptools==41.0.1 From edc09d25f7b24e3ae42b123167324ee821d2b8b8 Mon Sep 17 00:00:00 2001 From: "pyup.io bot" Date: Mon, 17 Jun 2019 09:53:56 +0200 Subject: [PATCH 121/134] Update flake8-coding from 1.3.1 to 1.3.2 (#92) --- test-requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test-requirements.txt b/test-requirements.txt index f59bdaff5..d4a4694bb 100644 --- a/test-requirements.txt +++ b/test-requirements.txt @@ -1,7 +1,7 @@ flake8==3.7.6 flake8-isort==2.7.0 flake8-quotes==1.0.0 -flake8-coding==1.3.1 +flake8-coding==1.3.2 flake8-copyright==0.2.2 flake8-debugger==3.1.0 wheel==0.33.4 From e069c9719d1594a0ef5225260b88d938e30b4804 Mon Sep 17 00:00:00 2001 From: "pyup.io bot" Date: Mon, 22 Jul 2019 13:45:46 +0200 Subject: [PATCH 122/134] Update flake8 from 3.7.6 to 3.7.8 (#93) --- test-requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test-requirements.txt b/test-requirements.txt index d4a4694bb..8d0c27cdf 100644 --- a/test-requirements.txt +++ b/test-requirements.txt @@ -1,4 +1,4 @@ -flake8==3.7.6 +flake8==3.7.8 flake8-isort==2.7.0 flake8-quotes==1.0.0 flake8-coding==1.3.2 From 10e91e727abcc23cf8ff9ca873f56d8f0988f348 Mon Sep 17 00:00:00 2001 From: "pyup.io bot" Date: Mon, 2 Sep 2019 00:21:10 +0200 Subject: [PATCH 123/134] Update wheel from 0.33.4 to 0.33.6 (#99) --- test-requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test-requirements.txt b/test-requirements.txt index 8d0c27cdf..75d5f251c 100644 --- a/test-requirements.txt +++ b/test-requirements.txt @@ -4,5 +4,5 @@ flake8-quotes==1.0.0 flake8-coding==1.3.2 flake8-copyright==0.2.2 flake8-debugger==3.1.0 -wheel==0.33.4 +wheel==0.33.6 setuptools==41.0.1 From e6e3b85123e9f4df108b9cf4378e8b8945da295a Mon Sep 17 00:00:00 2001 From: "pyup.io bot" Date: Mon, 2 Sep 2019 00:22:25 +0200 Subject: [PATCH 124/134] Update setuptools from 41.0.1 to 41.2.0 (#100) --- test-requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test-requirements.txt b/test-requirements.txt index 75d5f251c..84452e6b5 100644 --- a/test-requirements.txt +++ b/test-requirements.txt @@ -5,4 +5,4 @@ flake8-coding==1.3.2 flake8-copyright==0.2.2 flake8-debugger==3.1.0 wheel==0.33.6 -setuptools==41.0.1 +setuptools==41.2.0 \ No newline at end of file From 723d86345942224d33b11fe9db042e6835825f8d Mon Sep 17 00:00:00 2001 From: Marco Castelluccio Date: Tue, 1 Oct 2019 13:01:25 +0200 Subject: [PATCH 125/134] Use double quotes so we don't have to escape them --- firefox_code_coverage/codecoverage.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/firefox_code_coverage/codecoverage.py b/firefox_code_coverage/codecoverage.py index 590ecc505..1de74d0d7 100644 --- a/firefox_code_coverage/codecoverage.py +++ b/firefox_code_coverage/codecoverage.py @@ -287,9 +287,9 @@ def main(): parser.add_argument('commit', action='store', nargs='?', default=default_commit, help='Commit hash for push') parser.add_argument('--grcov', action='store', nargs='?', help='Path to grcov') parser.add_argument('--with-artifacts', action='store', nargs='?', default='ccov-artifacts', help='Path to already downloaded coverage files') - parser.add_argument('--platform', action='store', nargs='+', help='List of platforms to include (by default they are all included). E.g. \'linux\', \'windows\', etc.') - parser.add_argument('--suite', action='store', nargs='+', help='List of test suites to include (by default they are all included). E.g. \'mochitest\', \'mochitest-chrome\', \'gtest\', etc.') - parser.add_argument('--ignore', action='store', nargs='+', help='List of test suites to ignore (by default \'talos\' and \'awsy\'). E.g. \'mochitest\', \'mochitest-chrome\', \'gtest\', etc.') + parser.add_argument('--platform', action='store', nargs='+', help='List of platforms to include (by default they are all included). E.g. "linux", "windows", etc.') + parser.add_argument('--suite', action='store', nargs='+', help='List of test suites to include (by default they are all included). E.g. "mochitest", "mochitest-chrome", "gtest", etc.') + parser.add_argument('--ignore', action='store', nargs='+', help='List of test suites to ignore (by default "talos" and "awsy"). E.g. "mochitest", "mochitest-chrome", "gtest", etc.') parser.add_argument('--stats', action='store_true', help='Only generate high-level stats, not a full HTML report') args = parser.parse_args() From f0d1291dc6dcd5532cf0afda0f4b49c8ceaac15d Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Tue, 1 Oct 2019 13:10:51 +0200 Subject: [PATCH 126/134] Bump flake8-quotes from 1.0.0 to 2.1.0 (#101) Bumps [flake8-quotes](https://github.com/zheller/flake8-quotes) from 1.0.0 to 2.1.0. - [Release notes](https://github.com/zheller/flake8-quotes/releases) - [Commits](https://github.com/zheller/flake8-quotes/compare/1.0.0...2.1.0) Signed-off-by: dependabot-preview[bot] --- test-requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test-requirements.txt b/test-requirements.txt index 84452e6b5..6cb04d38e 100644 --- a/test-requirements.txt +++ b/test-requirements.txt @@ -1,6 +1,6 @@ flake8==3.7.8 flake8-isort==2.7.0 -flake8-quotes==1.0.0 +flake8-quotes==2.1.0 flake8-coding==1.3.2 flake8-copyright==0.2.2 flake8-debugger==3.1.0 From 6ec781152fb79dbe0b303a0fe189db57438056d0 Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Mon, 7 Oct 2019 23:52:46 +0100 Subject: [PATCH 127/134] Bump setuptools from 41.2.0 to 41.4.0 (#102) Bumps [setuptools](https://github.com/pypa/setuptools) from 41.2.0 to 41.4.0. - [Release notes](https://github.com/pypa/setuptools/releases) - [Changelog](https://github.com/pypa/setuptools/blob/master/CHANGES.rst) - [Commits](https://github.com/pypa/setuptools/compare/v41.2.0...v41.4.0) Signed-off-by: dependabot-preview[bot] --- test-requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test-requirements.txt b/test-requirements.txt index 6cb04d38e..146284f88 100644 --- a/test-requirements.txt +++ b/test-requirements.txt @@ -5,4 +5,4 @@ flake8-coding==1.3.2 flake8-copyright==0.2.2 flake8-debugger==3.1.0 wheel==0.33.6 -setuptools==41.2.0 \ No newline at end of file +setuptools==41.4.0 \ No newline at end of file From 273df07c1d9250cd02472769416a31a67973d11e Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Tue, 15 Oct 2019 09:15:59 +0200 Subject: [PATCH 128/134] Bump flake8-debugger from 3.1.0 to 3.1.1 (#103) Bumps [flake8-debugger](https://github.com/jbkahn/flake8-debugger) from 3.1.0 to 3.1.1. - [Release notes](https://github.com/jbkahn/flake8-debugger/releases) - [Commits](https://github.com/jbkahn/flake8-debugger/compare/3.1.0...3.1.1) Signed-off-by: dependabot-preview[bot] --- test-requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test-requirements.txt b/test-requirements.txt index 146284f88..6e77d8e2b 100644 --- a/test-requirements.txt +++ b/test-requirements.txt @@ -3,6 +3,6 @@ flake8-isort==2.7.0 flake8-quotes==2.1.0 flake8-coding==1.3.2 flake8-copyright==0.2.2 -flake8-debugger==3.1.0 +flake8-debugger==3.1.1 wheel==0.33.6 setuptools==41.4.0 \ No newline at end of file From edf4abadfb3056126a01d25855a7592098ef2010 Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Wed, 16 Oct 2019 11:07:15 +0200 Subject: [PATCH 129/134] Bump flake8-debugger from 3.1.1 to 3.2.0 (#104) Bumps [flake8-debugger](https://github.com/jbkahn/flake8-debugger) from 3.1.1 to 3.2.0. - [Release notes](https://github.com/jbkahn/flake8-debugger/releases) - [Commits](https://github.com/jbkahn/flake8-debugger/compare/3.1.1...3.2.0) Signed-off-by: dependabot-preview[bot] --- test-requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test-requirements.txt b/test-requirements.txt index 6e77d8e2b..8e46860d1 100644 --- a/test-requirements.txt +++ b/test-requirements.txt @@ -3,6 +3,6 @@ flake8-isort==2.7.0 flake8-quotes==2.1.0 flake8-coding==1.3.2 flake8-copyright==0.2.2 -flake8-debugger==3.1.1 +flake8-debugger==3.2.0 wheel==0.33.6 setuptools==41.4.0 \ No newline at end of file From c6e3b3303d362edb984c261872fed9c5ef4cc569 Mon Sep 17 00:00:00 2001 From: Marco Castelluccio Date: Sat, 19 Oct 2019 18:34:40 +0100 Subject: [PATCH 130/134] Drop Python 2.7 testing --- .travis.yml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index f0cf15ad9..53abb2fa4 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,7 +1,6 @@ language: python python: - - "2.7" - - "3.5" + - "3.7" install: - pip install -r test-requirements.txt - mkdir -p symlinks From 8957f960345c3d8adea782cfc9de7d5d4aa1146a Mon Sep 17 00:00:00 2001 From: Marco Castelluccio Date: Sat, 19 Oct 2019 18:39:24 +0100 Subject: [PATCH 131/134] Use pre-commit --- .flake8 | 3 + .isort.cfg | 1 + .pre-commit-config.yaml | 38 +++ .travis.yml | 2 +- MANIFEST.in | 3 + firefox_code_coverage/codecoverage.py | 353 +++++++++++++++++--------- setup.py | 10 +- test-requirements.txt | 9 +- tests/test.py | 101 ++++---- 9 files changed, 343 insertions(+), 177 deletions(-) create mode 100644 .flake8 create mode 100644 .pre-commit-config.yaml create mode 100644 MANIFEST.in diff --git a/.flake8 b/.flake8 new file mode 100644 index 000000000..c6a26c199 --- /dev/null +++ b/.flake8 @@ -0,0 +1,3 @@ +[flake8] +exclude = .git,__pycache__ +ignore = E101, E111, E114, E115, E116, E117, E121, E122, E123, E124, E125, E126, E127, E128, E129, E131, E133, E2, E3, E5, E501, E701, E702, E703, E704, W1, W2, W3, W503, W504 diff --git a/.isort.cfg b/.isort.cfg index b110a6bec..a5ae0bedd 100644 --- a/.isort.cfg +++ b/.isort.cfg @@ -1,2 +1,3 @@ [settings] force_single_line=True +known_third_party = setuptools diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml new file mode 100644 index 000000000..060545c43 --- /dev/null +++ b/.pre-commit-config.yaml @@ -0,0 +1,38 @@ +repos: +- repo: https://github.com/asottile/seed-isort-config + rev: v1.9.2 + hooks: + - id: seed-isort-config +- repo: https://github.com/pre-commit/mirrors-isort + rev: v4.3.21 + hooks: + - id: isort +- repo: https://github.com/ambv/black + rev: stable + hooks: + - id: black +- repo: https://gitlab.com/pycqa/flake8 + rev: 3.7.8 + hooks: + - id: flake8 + additional_dependencies: ['flake8-coding==1.3.1', 'flake8-copyright==0.2.2', 'flake8-debugger==3.1.0', 'flake8-mypy==17.8.0'] +- repo: https://github.com/pre-commit/pre-commit-hooks + rev: v2.3.0 + hooks: + - id: trailing-whitespace + - id: check-yaml + - id: mixed-line-ending + - id: name-tests-test + args: ['--django'] + - id: check-json + - id: requirements-txt-fixer +- repo: https://github.com/codespell-project/codespell + rev: v1.16.0 + hooks: + - id: codespell + exclude_types: [json] +- repo: meta + hooks: + - id: check-useless-excludes +default_language_version: + python: python3.7 diff --git a/.travis.yml b/.travis.yml index 53abb2fa4..93e39f85e 100644 --- a/.travis.yml +++ b/.travis.yml @@ -8,7 +8,7 @@ install: - ln -s /usr/bin/gcov-6 symlinks/gcov script: - export PATH=$PWD/symlinks:$PATH - - flake8 . + - pre-commit run --all-files - python -m unittest discover tests - python setup.py sdist bdist_wheel - pip install dist/firefox_code_coverage-1.0.0.tar.gz diff --git a/MANIFEST.in b/MANIFEST.in new file mode 100644 index 000000000..e0e8ed891 --- /dev/null +++ b/MANIFEST.in @@ -0,0 +1,3 @@ +recursive-exclude * __pycache__ +recursive-exclude * *.py[co] +recursive-exclude tests * diff --git a/firefox_code_coverage/codecoverage.py b/firefox_code_coverage/codecoverage.py index 1de74d0d7..68e8b33e6 100644 --- a/firefox_code_coverage/codecoverage.py +++ b/firefox_code_coverage/codecoverage.py @@ -18,70 +18,82 @@ from urllib2 import Request, urlopen -TEST_PLATFORMS = ['test-linux64-ccov/debug', 'test-windows10-64-ccov/debug'] -FINISHED_STATUSES = ['completed', 'failed', 'exception'] -ALL_STATUSES = FINISHED_STATUSES + ['unscheduled', 'pending', 'running'] -STATUS_VALUE = { - 'exception': 1, - 'failed': 2, - 'completed': 3, -} +TEST_PLATFORMS = ["test-linux64-ccov/debug", "test-windows10-64-ccov/debug"] +FINISHED_STATUSES = ["completed", "failed", "exception"] +ALL_STATUSES = FINISHED_STATUSES + ["unscheduled", "pending", "running"] +STATUS_VALUE = {"exception": 1, "failed": 2, "completed": 3} def get_json(url, params=None, headers={}): if params is not None: - url += '?' + urlencode(params) + url += "?" + urlencode(params) request = Request(url, headers=headers) - r = urlopen(request).read().decode('utf-8') + r = urlopen(request).read().decode("utf-8") return json.loads(r) def is_taskcluster_loaner(): - return 'TASKCLUSTER_INTERACTIVE' in os.environ + return "TASKCLUSTER_INTERACTIVE" in os.environ def get_last_task(): - last_task = get_json('https://index.taskcluster.net/v1/task/gecko.v2.mozilla-central.latest.firefox.linux64-ccov-debug') - return last_task['taskId'] + last_task = get_json( + "https://index.taskcluster.net/v1/task/gecko.v2.mozilla-central.latest.firefox.linux64-ccov-debug" + ) + return last_task["taskId"] def get_task(branch, revision): - task = get_json('https://index.taskcluster.net/v1/task/gecko.v2.%s.revision.%s.firefox.linux64-ccov-debug' % (branch, revision)) - return task['taskId'] + task = get_json( + "https://index.taskcluster.net/v1/task/gecko.v2.%s.revision.%s.firefox.linux64-ccov-debug" + % (branch, revision) + ) + return task["taskId"] def get_task_details(task_id): - task_details = get_json('https://queue.taskcluster.net/v1/task/' + task_id) + task_details = get_json("https://queue.taskcluster.net/v1/task/" + task_id) return task_details def get_task_artifacts(task_id): - artifacts = get_json('https://queue.taskcluster.net/v1/task/' + task_id + '/artifacts') - return artifacts['artifacts'] + artifacts = get_json( + "https://queue.taskcluster.net/v1/task/" + task_id + "/artifacts" + ) + return artifacts["artifacts"] def get_tasks_in_group(group_id): - reply = get_json('https://queue.taskcluster.net/v1/task-group/' + group_id + '/list', { - 'limit': '200', - }) - tasks = reply['tasks'] - while 'continuationToken' in reply: - reply = get_json('https://queue.taskcluster.net/v1/task-group/' + group_id + '/list', { - 'limit': '200', - 'continuationToken': reply['continuationToken'], - }) - tasks += reply['tasks'] + reply = get_json( + "https://queue.taskcluster.net/v1/task-group/" + group_id + "/list", + {"limit": "200"}, + ) + tasks = reply["tasks"] + while "continuationToken" in reply: + reply = get_json( + "https://queue.taskcluster.net/v1/task-group/" + group_id + "/list", + {"limit": "200", "continuationToken": reply["continuationToken"]}, + ) + tasks += reply["tasks"] return tasks def download_artifact(task_id, artifact, artifacts_path): - fname = os.path.join(artifacts_path, task_id + '_' + os.path.basename(artifact['name'])) + fname = os.path.join( + artifacts_path, task_id + "_" + os.path.basename(artifact["name"]) + ) if not os.path.exists(fname): while True: try: - urlretrieve('https://queue.taskcluster.net/v1/task/' + task_id + '/artifacts/' + artifact['name'], fname) + urlretrieve( + "https://queue.taskcluster.net/v1/task/" + + task_id + + "/artifacts/" + + artifact["name"], + fname, + ) break except: # noqa: E722 try: @@ -96,30 +108,32 @@ def download_artifact(task_id, artifact, artifacts_path): def get_chunk(task_name): for t in TEST_PLATFORMS: if task_name.startswith(t): - task_name = task_name[len(t) + 1:] + task_name = task_name[len(t) + 1 :] break - return '-'.join([p for p in task_name.split('-') if p != 'e10s']) + return "-".join([p for p in task_name.split("-") if p != "e10s"]) def get_suite(task_name): - return '-'.join([p for p in get_chunk(task_name).split('-') if not p.isdigit()]) + return "-".join([p for p in get_chunk(task_name).split("-") if not p.isdigit()]) def get_platform(task_name): - if 'linux' in task_name: - return 'linux' - elif 'windows' in task_name: - return 'windows' + if "linux" in task_name: + return "linux" + elif "windows" in task_name: + return "windows" else: - raise Exception('Unknown platform') + raise Exception("Unknown platform") def get_task_status(task_id): - status = get_json('https://queue.taskcluster.net/v1/task/{}/status'.format(task_id)) - return status['status']['state'] + status = get_json("https://queue.taskcluster.net/v1/task/{}/status".format(task_id)) + return status["status"]["state"] -def download_coverage_artifacts(build_task_id, suites, platforms, artifacts_path, suites_to_ignore=['talos', 'awsy']): +def download_coverage_artifacts( + build_task_id, suites, platforms, artifacts_path, suites_to_ignore=["talos", "awsy"] +): try: os.mkdir(artifacts_path) except OSError as e: @@ -130,167 +144,262 @@ def download_coverage_artifacts(build_task_id, suites, platforms, artifacts_path # Returns True if the task is a test-related task. def _is_test_task(t): - return any(t['task']['metadata']['name'].startswith(tp) for tp in TEST_PLATFORMS) + return any( + t["task"]["metadata"]["name"].startswith(tp) for tp in TEST_PLATFORMS + ) # Returns True if the task is part of one of the suites chosen by the user. def _is_in_suites_task(t): - suite_name = get_suite(t['task']['metadata']['name']) - return suites is None or suite_name in suites and suite_name not in suites_to_ignore + suite_name = get_suite(t["task"]["metadata"]["name"]) + return ( + suites is None + or suite_name in suites + and suite_name not in suites_to_ignore + ) def _is_in_platforms_task(t): - platform = get_platform(t['task']['metadata']['name']) + platform = get_platform(t["task"]["metadata"]["name"]) return platforms is None or platform in platforms - test_tasks = [t for t in get_tasks_in_group(task_data['taskGroupId']) if _is_test_task(t) and _is_in_suites_task(t) and _is_in_platforms_task(t)] + test_tasks = [ + t + for t in get_tasks_in_group(task_data["taskGroupId"]) + if _is_test_task(t) and _is_in_suites_task(t) and _is_in_platforms_task(t) + ] if suites is not None: for suite in suites: - if not any(suite in t['task']['metadata']['name'] for t in test_tasks): - warnings.warn('Suite %s not found' % suite) + if not any(suite in t["task"]["metadata"]["name"] for t in test_tasks): + warnings.warn("Suite %s not found" % suite) download_tasks = {} for test_task in test_tasks: - status = test_task['status']['state'] + status = test_task["status"]["state"] assert status in ALL_STATUSES, "State '{}' not recognized".format(status) while status not in FINISHED_STATUSES: - sys.stdout.write('\rWaiting for task {} to finish...'.format(test_task['status']['taskId'])) + sys.stdout.write( + "\rWaiting for task {} to finish...".format( + test_task["status"]["taskId"] + ) + ) sys.stdout.flush() time.sleep(60) - status = get_task_status(test_task['status']['taskId']) + status = get_task_status(test_task["status"]["taskId"]) assert status in ALL_STATUSES - chunk_name = get_chunk(test_task['task']['metadata']['name']) - platform_name = get_platform(test_task['task']['metadata']['name']) + chunk_name = get_chunk(test_task["task"]["metadata"]["name"]) + platform_name = get_platform(test_task["task"]["metadata"]["name"]) if (chunk_name, platform_name) not in download_tasks: download_tasks[(chunk_name, platform_name)] = test_task else: prev_task = download_tasks[(chunk_name, platform_name)] - if STATUS_VALUE[status] > STATUS_VALUE[prev_task['status']['state']]: + if STATUS_VALUE[status] > STATUS_VALUE[prev_task["status"]["state"]]: download_tasks[(chunk_name, platform_name)] = test_task artifact_paths = [] for i, test_task in enumerate(download_tasks.values()): - sys.stdout.write('\rDownloading artifacts from {}/{} test task...'.format(i, len(test_tasks))) + sys.stdout.write( + "\rDownloading artifacts from {}/{} test task...".format(i, len(test_tasks)) + ) sys.stdout.flush() - artifacts = get_task_artifacts(test_task['status']['taskId']) + artifacts = get_task_artifacts(test_task["status"]["taskId"]) for artifact in artifacts: - if any(a in artifact['name'] for a in ['code-coverage-grcov.zip', 'code-coverage-jsvm.zip']): - artifact_paths.append(download_artifact(test_task['status']['taskId'], artifact, artifacts_path)) - print('') + if any( + a in artifact["name"] + for a in ["code-coverage-grcov.zip", "code-coverage-jsvm.zip"] + ): + artifact_paths.append( + download_artifact( + test_task["status"]["taskId"], artifact, artifacts_path + ) + ) + print("") return artifact_paths def generate_report(grcov_path, output_format, output_path, artifact_paths): mod_env = os.environ.copy() if is_taskcluster_loaner(): - one_click_loaner_gcc = '/home/worker/workspace/build/src/gcc/bin' + one_click_loaner_gcc = "/home/worker/workspace/build/src/gcc/bin" i = 0 - while not os.path.isdir(one_click_loaner_gcc) or len(os.listdir(one_click_loaner_gcc)) == 0: - print('Waiting one-click loaner to be ready... ' + str(i)) + while ( + not os.path.isdir(one_click_loaner_gcc) + or len(os.listdir(one_click_loaner_gcc)) == 0 + ): + print("Waiting one-click loaner to be ready... " + str(i)) i += 1 time.sleep(60) - mod_env['PATH'] = one_click_loaner_gcc + ':' + mod_env['PATH'] - fout = open(output_path, 'w') - cmd = [grcov_path, '-t', output_format, '-p', '/home/worker/workspace/build/src/'] - if output_format in ['coveralls', 'coveralls+']: - cmd += ['--token', 'UNUSED', '--commit-sha', 'UNUSED'] + mod_env["PATH"] = one_click_loaner_gcc + ":" + mod_env["PATH"] + fout = open(output_path, "w") + cmd = [grcov_path, "-t", output_format, "-p", "/home/worker/workspace/build/src/"] + if output_format in ["coveralls", "coveralls+"]: + cmd += ["--token", "UNUSED", "--commit-sha", "UNUSED"] cmd.extend(artifact_paths) proc = subprocess.Popen(cmd, stdout=fout, stderr=subprocess.PIPE, env=mod_env) i = 0 while proc.poll() is None: if i % 60 == 0: - sys.stdout.write('\rRunning grcov... {} seconds'.format(i)) + sys.stdout.write("\rRunning grcov... {} seconds".format(i)) sys.stdout.flush() i += 1 time.sleep(1) - print('') + print("") if proc.poll() != 0: - raise Exception('Error while running grcov: {}\n'.format(proc.stderr.read())) + raise Exception("Error while running grcov: {}\n".format(proc.stderr.read())) -def generate_html_report(src_dir, info_file=os.path.join(os.getcwd(), 'output.info'), output_dir=os.path.join(os.getcwd(), 'report'), silent=False, style_file=None): +def generate_html_report( + src_dir, + info_file=os.path.join(os.getcwd(), "output.info"), + output_dir=os.path.join(os.getcwd(), "report"), + silent=False, + style_file=None, +): cwd = os.getcwd() os.chdir(src_dir) - with open(os.devnull, 'w') as fnull: - command = [os.path.join(cwd, 'lcov-bin/usr/local/bin/genhtml'), '-o', output_dir, '--show-details', '--highlight', '--ignore-errors', 'source', '--legend', info_file] + with open(os.devnull, "w") as fnull: + command = [ + os.path.join(cwd, "lcov-bin/usr/local/bin/genhtml"), + "-o", + output_dir, + "--show-details", + "--highlight", + "--ignore-errors", + "source", + "--legend", + info_file, + ] if style_file is not None: - command += ['--css-file', style_file] - ret = subprocess.call(command, stdout=fnull if silent else None, stderr=fnull if silent else None) + command += ["--css-file", style_file] + ret = subprocess.call( + command, stdout=fnull if silent else None, stderr=fnull if silent else None + ) if ret != 0: - raise Exception('Error while running genhtml.') + raise Exception("Error while running genhtml.") os.chdir(cwd) def download_grcov(): headers = {} - if 'GITHUB_ACCESS_TOKEN' in os.environ: - headers['Authorization'] = 'token {}'.format(os.environ['GITHUB_ACCESS_TOKEN']) + if "GITHUB_ACCESS_TOKEN" in os.environ: + headers["Authorization"] = "token {}".format(os.environ["GITHUB_ACCESS_TOKEN"]) - r = get_json('https://api.github.com/repos/marco-c/grcov/releases/latest', headers=headers) - latest_tag = r['tag_name'] + r = get_json( + "https://api.github.com/repos/marco-c/grcov/releases/latest", headers=headers + ) + latest_tag = r["tag_name"] - if os.path.exists('grcov') and os.path.exists('grcov_ver'): - with open('grcov_ver', 'r') as f: + if os.path.exists("grcov") and os.path.exists("grcov_ver"): + with open("grcov_ver", "r") as f: installed_ver = f.read() if installed_ver == latest_tag: return - urlretrieve('https://github.com/marco-c/grcov/releases/download/%s/grcov-linux-x86_64.tar.bz2' % latest_tag, 'grcov.tar.bz2') + urlretrieve( + "https://github.com/marco-c/grcov/releases/download/%s/grcov-linux-x86_64.tar.bz2" + % latest_tag, + "grcov.tar.bz2", + ) - tar = tarfile.open('grcov.tar.bz2', 'r:bz2') + tar = tarfile.open("grcov.tar.bz2", "r:bz2") tar.extractall() tar.close() - os.remove('grcov.tar.bz2') + os.remove("grcov.tar.bz2") - with open('grcov_ver', 'w') as f: + with open("grcov_ver", "w") as f: f.write(latest_tag) def download_genhtml(): - if os.path.isdir('lcov'): - os.chdir('lcov') - subprocess.check_call(['git', 'pull']) + if os.path.isdir("lcov"): + os.chdir("lcov") + subprocess.check_call(["git", "pull"]) else: - subprocess.check_call(['git', 'clone', 'https://github.com/linux-test-project/lcov.git']) - os.chdir('lcov') + subprocess.check_call( + ["git", "clone", "https://github.com/linux-test-project/lcov.git"] + ) + os.chdir("lcov") - subprocess.check_call(['make', 'install', 'DESTDIR=../lcov-bin']) + subprocess.check_call(["make", "install", "DESTDIR=../lcov-bin"]) - os.chdir('..') + os.chdir("..") def main(): parser = argparse.ArgumentParser() if is_taskcluster_loaner(): - nargs = '?' - default_src_dir = '/home/worker/workspace/build/src/' - default_branch = os.environ['MH_BRANCH'] - default_commit = os.environ['GECKO_HEAD_REV'] + nargs = "?" + default_src_dir = "/home/worker/workspace/build/src/" + default_branch = os.environ["MH_BRANCH"] + default_commit = os.environ["GECKO_HEAD_REV"] else: nargs = None default_src_dir = None default_branch = None default_commit = None - parser.add_argument('src_dir', action='store', nargs=nargs, default=default_src_dir, help='Path to the source directory') - parser.add_argument('branch', action='store', nargs='?', default=default_branch, help='Branch on which jobs ran') - parser.add_argument('commit', action='store', nargs='?', default=default_commit, help='Commit hash for push') - parser.add_argument('--grcov', action='store', nargs='?', help='Path to grcov') - parser.add_argument('--with-artifacts', action='store', nargs='?', default='ccov-artifacts', help='Path to already downloaded coverage files') - parser.add_argument('--platform', action='store', nargs='+', help='List of platforms to include (by default they are all included). E.g. "linux", "windows", etc.') - parser.add_argument('--suite', action='store', nargs='+', help='List of test suites to include (by default they are all included). E.g. "mochitest", "mochitest-chrome", "gtest", etc.') - parser.add_argument('--ignore', action='store', nargs='+', help='List of test suites to ignore (by default "talos" and "awsy"). E.g. "mochitest", "mochitest-chrome", "gtest", etc.') - parser.add_argument('--stats', action='store_true', help='Only generate high-level stats, not a full HTML report') + parser.add_argument( + "src_dir", + action="store", + nargs=nargs, + default=default_src_dir, + help="Path to the source directory", + ) + parser.add_argument( + "branch", + action="store", + nargs="?", + default=default_branch, + help="Branch on which jobs ran", + ) + parser.add_argument( + "commit", + action="store", + nargs="?", + default=default_commit, + help="Commit hash for push", + ) + parser.add_argument("--grcov", action="store", nargs="?", help="Path to grcov") + parser.add_argument( + "--with-artifacts", + action="store", + nargs="?", + default="ccov-artifacts", + help="Path to already downloaded coverage files", + ) + parser.add_argument( + "--platform", + action="store", + nargs="+", + help='List of platforms to include (by default they are all included). E.g. "linux", "windows", etc.', + ) + parser.add_argument( + "--suite", + action="store", + nargs="+", + help='List of test suites to include (by default they are all included). E.g. "mochitest", "mochitest-chrome", "gtest", etc.', + ) + parser.add_argument( + "--ignore", + action="store", + nargs="+", + help='List of test suites to ignore (by default "talos" and "awsy"). E.g. "mochitest", "mochitest-chrome", "gtest", etc.', + ) + parser.add_argument( + "--stats", + action="store_true", + help="Only generate high-level stats, not a full HTML report", + ) args = parser.parse_args() if (args.branch is None) != (args.commit is None): @@ -303,26 +412,30 @@ def main(): task_id = get_last_task() if args.ignore is None: - artifact_paths = download_coverage_artifacts(task_id, args.suite, args.platform, args.with_artifacts) + artifact_paths = download_coverage_artifacts( + task_id, args.suite, args.platform, args.with_artifacts + ) else: - artifact_paths = download_coverage_artifacts(task_id, args.suite, args.platform, args.with_artifacts, args.ignore) + artifact_paths = download_coverage_artifacts( + task_id, args.suite, args.platform, args.with_artifacts, args.ignore + ) if args.grcov: grcov_path = args.grcov else: download_grcov() - grcov_path = './grcov' + grcov_path = "./grcov" if args.stats: - generate_report(grcov_path, 'coveralls', 'output.json', artifact_paths) + generate_report(grcov_path, "coveralls", "output.json", artifact_paths) - with open('output.json', 'r') as f: + with open("output.json", "r") as f: report = json.load(f) total_lines = 0 total_lines_covered = 0 - for sf in report['source_files']: - for c in sf['coverage']: + for sf in report["source_files"]: + for c in sf["coverage"]: if c is None: continue @@ -330,15 +443,19 @@ def main(): if c > 0: total_lines_covered += 1 - print('Coverable lines: {}'.format(total_lines)) - print('Covered lines: {}'.format(total_lines_covered)) - print('Coverage percentage: {}'.format(float(total_lines_covered) / float(total_lines))) + print("Coverable lines: {}".format(total_lines)) + print("Covered lines: {}".format(total_lines_covered)) + print( + "Coverage percentage: {}".format( + float(total_lines_covered) / float(total_lines) + ) + ) else: - generate_report(grcov_path, 'lcov', 'output.info', artifact_paths) + generate_report(grcov_path, "lcov", "output.info", artifact_paths) download_genhtml() generate_html_report(os.path.abspath(args.src_dir)) -if __name__ == '__main__': +if __name__ == "__main__": main() diff --git a/setup.py b/setup.py index 857ee93aa..1f1ca0d82 100644 --- a/setup.py +++ b/setup.py @@ -4,9 +4,9 @@ from setuptools import setup setup( - name='firefox_code_coverage', - version='1.0.0', - description='Code Coverage Report generator for Firefox', - packages=find_packages(exclude=['contrib', 'docs', 'tests']), - license='MPL2', + name="firefox_code_coverage", + version="1.0.0", + description="Code Coverage Report generator for Firefox", + packages=find_packages(exclude=["contrib", "docs", "tests"]), + license="MPL2", ) diff --git a/test-requirements.txt b/test-requirements.txt index 8e46860d1..f9ac171ec 100644 --- a/test-requirements.txt +++ b/test-requirements.txt @@ -1,8 +1,3 @@ -flake8==3.7.8 -flake8-isort==2.7.0 -flake8-quotes==2.1.0 -flake8-coding==1.3.2 -flake8-copyright==0.2.2 -flake8-debugger==3.2.0 +pre-commit==1.18.3 +setuptools==41.4.0 wheel==0.33.6 -setuptools==41.4.0 \ No newline at end of file diff --git a/tests/test.py b/tests/test.py index d07015cbc..8f1058fce 100644 --- a/tests/test.py +++ b/tests/test.py @@ -15,10 +15,10 @@ class Test(unittest.TestCase): @classmethod def tearDownClass(cls): - for d in ['report', 'ccov-artifacts', 'lcov', 'lcov-bin']: + for d in ["report", "ccov-artifacts", "lcov", "lcov-bin"]: shutil.rmtree(d, ignore_errors=True) - for f in ['grcov', 'grcov_ver', 'output.info']: + for f in ["grcov", "grcov_ver", "output.info"]: try: os.remove(f) except OSError as e: @@ -30,100 +30,109 @@ def test(self): self.assertTrue(task_id) task_data = codecoverage.get_task_details(task_id) - self.assertEqual(task_data['metadata']['name'], 'build-linux64-ccov/debug') + self.assertEqual(task_data["metadata"]["name"], "build-linux64-ccov/debug") - revision = task_data['payload']['env']['GECKO_HEAD_REV'] - task_id_2 = codecoverage.get_task('mozilla-central', revision) + revision = task_data["payload"]["env"]["GECKO_HEAD_REV"] + task_id_2 = codecoverage.get_task("mozilla-central", revision) self.assertEqual(task_id, task_id_2) artifacts = codecoverage.get_task_artifacts(task_id) chosen_artifact = None for artifact in artifacts: - if artifact['name'] == 'public/build/target.txt': + if artifact["name"] == "public/build/target.txt": chosen_artifact = artifact self.assertIsNotNone(chosen_artifact) - tasks = codecoverage.get_tasks_in_group(task_data['taskGroupId']) + tasks = codecoverage.get_tasks_in_group(task_data["taskGroupId"]) self.assertIsInstance(tasks, list) try: - os.mkdir('ccov-artifacts') + os.mkdir("ccov-artifacts") except OSError as e: if e.errno != errno.EEXIST: raise e - codecoverage.download_artifact(task_id, chosen_artifact, 'ccov-artifacts') - self.assertTrue(os.path.exists('ccov-artifacts/%s_target.txt' % task_id)) - os.remove('ccov-artifacts/%s_target.txt' % task_id) - - artifact_paths = codecoverage.download_coverage_artifacts(task_id, 'cppunit', None, 'ccov-artifacts') - self.assertEqual(len([a for a in os.listdir('ccov-artifacts') if 'grcov' in a]), 2) - self.assertEqual(len([a for a in os.listdir('ccov-artifacts') if 'jsvm' in a]), 2) - self.assertEqual(len([a for a in artifact_paths if 'grcov' in a]), 2) - self.assertEqual(len([a for a in artifact_paths if 'jsvm' in a]), 2) + codecoverage.download_artifact(task_id, chosen_artifact, "ccov-artifacts") + self.assertTrue(os.path.exists("ccov-artifacts/%s_target.txt" % task_id)) + os.remove("ccov-artifacts/%s_target.txt" % task_id) + + artifact_paths = codecoverage.download_coverage_artifacts( + task_id, "cppunit", None, "ccov-artifacts" + ) + self.assertEqual( + len([a for a in os.listdir("ccov-artifacts") if "grcov" in a]), 2 + ) + self.assertEqual( + len([a for a in os.listdir("ccov-artifacts") if "jsvm" in a]), 2 + ) + self.assertEqual(len([a for a in artifact_paths if "grcov" in a]), 2) + self.assertEqual(len([a for a in artifact_paths if "jsvm" in a]), 2) codecoverage.download_grcov() - codecoverage.generate_report('./grcov', 'lcov', 'output.info', artifact_paths) - self.assertTrue(os.path.exists('output.info')) + codecoverage.generate_report("./grcov", "lcov", "output.info", artifact_paths) + self.assertTrue(os.path.exists("output.info")) codecoverage.download_genhtml() - codecoverage.generate_html_report('tests', silent=True) - self.assertTrue(os.path.isdir('report')) + codecoverage.generate_html_report("tests", silent=True) + self.assertTrue(os.path.isdir("report")) def test_suite_name_from_task_name(self): cases = [ - ('test-linux64-ccov/debug-gtest', 'gtest'), - ('test-linux64-ccov/debug-jsreftest-1', 'jsreftest'), - ('test-linux64-ccov/debug-mochitest-devtools-chrome-e10s-10', 'mochitest-devtools-chrome'), - ('test-linux64-ccov/debug-mochitest-clipboard', 'mochitest-clipboard'), - ('test-linux64-ccov/debug-reftest-no-accel-e10s-5', 'reftest-no-accel'), - ('test-linux64-ccov/debug-mochitest-5', 'mochitest'), - ('test-windows10-64-ccov/debug-mochitest-5', 'mochitest'), - ('test-windows10-64-ccov/debug-cppunit', 'cppunit'), + ("test-linux64-ccov/debug-gtest", "gtest"), + ("test-linux64-ccov/debug-jsreftest-1", "jsreftest"), + ( + "test-linux64-ccov/debug-mochitest-devtools-chrome-e10s-10", + "mochitest-devtools-chrome", + ), + ("test-linux64-ccov/debug-mochitest-clipboard", "mochitest-clipboard"), + ("test-linux64-ccov/debug-reftest-no-accel-e10s-5", "reftest-no-accel"), + ("test-linux64-ccov/debug-mochitest-5", "mochitest"), + ("test-windows10-64-ccov/debug-mochitest-5", "mochitest"), + ("test-windows10-64-ccov/debug-cppunit", "cppunit"), ] for c in cases: self.assertEqual(codecoverage.get_suite(c[0]), c[1]) def test_download_grcov(self): codecoverage.download_grcov() - self.assertTrue(os.path.exists('grcov')) - self.assertTrue(os.path.exists('grcov_ver')) + self.assertTrue(os.path.exists("grcov")) + self.assertTrue(os.path.exists("grcov_ver")) - with open('grcov_ver', 'r') as f: + with open("grcov_ver", "r") as f: ver = f.read() # grcov is downloaded again if the executable doesn't exist. - os.remove('grcov') + os.remove("grcov") codecoverage.download_grcov() - self.assertTrue(os.path.exists('grcov')) - self.assertTrue(os.path.exists('grcov_ver')) + self.assertTrue(os.path.exists("grcov")) + self.assertTrue(os.path.exists("grcov_ver")) # grcov isn't downloaded again if the executable exists and the version is the same. - with open('grcov', 'w') as f: - f.write('prova') + with open("grcov", "w") as f: + f.write("prova") codecoverage.download_grcov() - with open('grcov', 'r') as f: - self.assertEqual('prova', f.read()) + with open("grcov", "r") as f: + self.assertEqual("prova", f.read()) # grcov is overwritten if the version changes. - with open('grcov_ver', 'w') as f: - f.write('v0.0.0') + with open("grcov_ver", "w") as f: + f.write("v0.0.0") codecoverage.download_grcov() - self.assertTrue(os.path.getsize('grcov') > 5) - with open('grcov_ver', 'r') as f: + self.assertTrue(os.path.getsize("grcov") > 5) + with open("grcov_ver", "r") as f: self.assertEqual(ver, f.read()) def test_download_genhtml(self): codecoverage.download_genhtml() - self.assertTrue(os.path.exists('./lcov-bin/usr/local/bin/genhtml')) + self.assertTrue(os.path.exists("./lcov-bin/usr/local/bin/genhtml")) codecoverage.download_genhtml() - self.assertTrue(os.path.exists('./lcov-bin/usr/local/bin/genhtml')) + self.assertTrue(os.path.exists("./lcov-bin/usr/local/bin/genhtml")) -if __name__ == '__main__': +if __name__ == "__main__": unittest.main() From bbfedb1ddc96acbbed11ed2be843f3cec3fad2ca Mon Sep 17 00:00:00 2001 From: Marco Castelluccio Date: Sat, 19 Oct 2019 18:40:54 +0100 Subject: [PATCH 132/134] Add .gitignore --- .gitignore | 27 +++++++++++++++++++++++---- 1 file changed, 23 insertions(+), 4 deletions(-) diff --git a/.gitignore b/.gitignore index 81f4c2f03..cf29fbaea 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,24 @@ -*~ +.pytest_cache/ *.pyc -*.pyo -ccov-artifacts -lcov + +# Distribution / packaging +.Python +build/ +develop-eggs/ +dist/ +downloads/ +eggs/ +.eggs/ +lib/ +lib64/ +parts/ +sdist/ +var/ +wheels/ +pip-wheel-metadata/ +share/python-wheels/ +*.egg-info/ +.installed.cfg +*.egg +MANIFEST +cache/ From 36d00cfd1e8dd29649dc9696e97a0f28d52c6a0f Mon Sep 17 00:00:00 2001 From: Marco Castelluccio Date: Sat, 19 Oct 2019 19:19:46 +0100 Subject: [PATCH 133/134] Update suite name --- tests/test.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/test.py b/tests/test.py index 8f1058fce..994fc7e5e 100644 --- a/tests/test.py +++ b/tests/test.py @@ -57,7 +57,7 @@ def test(self): os.remove("ccov-artifacts/%s_target.txt" % task_id) artifact_paths = codecoverage.download_coverage_artifacts( - task_id, "cppunit", None, "ccov-artifacts" + task_id, "cppunit-1proc", None, "ccov-artifacts" ) self.assertEqual( len([a for a in os.listdir("ccov-artifacts") if "grcov" in a]), 2 From a1178393ddd4a5618dbea1472f111d35ff58c2c7 Mon Sep 17 00:00:00 2001 From: Bastien Abadie Date: Wed, 23 Oct 2019 10:10:12 +0200 Subject: [PATCH 134/134] Patch marco-c/firefox-code-coverage to work in mozilla/code-coverage, fixes #232 --- .isort.cfg | 2 +- .taskcluster.yml | 19 +++++++++++++++++ report/.flake8 | 3 --- report/.gitignore | 11 ++++++---- report/.isort.cfg | 3 --- report/.pre-commit-config.yaml | 38 ---------------------------------- report/.travis.yml | 21 ------------------- report/README.md | 2 -- report/ci-test.sh | 7 +++++++ report/test-requirements.txt | 1 - report/tox.ini | 2 -- 11 files changed, 34 insertions(+), 75 deletions(-) delete mode 100644 report/.flake8 delete mode 100644 report/.isort.cfg delete mode 100644 report/.pre-commit-config.yaml delete mode 100644 report/.travis.yml create mode 100755 report/ci-test.sh delete mode 100644 report/tox.ini diff --git a/.isort.cfg b/.isort.cfg index 7561560b1..5f64710da 100644 --- a/.isort.cfg +++ b/.isort.cfg @@ -1,5 +1,5 @@ [settings] -known_first_party = code_coverage_backend,code_coverage_bot,code_coverage_events,code_coverage_tools,conftest +known_first_party = code_coverage_backend,code_coverage_bot,code_coverage_events,code_coverage_tools,conftest,firefox_code_coverage known_third_party = connexion,datadog,dateutil,fakeredis,flask,flask_cors,flask_talisman,google,hglib,jsone,jsonschema,libmozdata,libmozevent,logbook,pytest,pytz,raven,redis,requests,responses,setuptools,structlog,taskcluster,werkzeug,zstandard force_single_line = True default_section=FIRSTPARTY diff --git a/.taskcluster.yml b/.taskcluster.yml index 51b9b4d9a..ca81313b4 100644 --- a/.taskcluster.yml +++ b/.taskcluster.yml @@ -137,6 +137,25 @@ tasks: owner: bastien@mozilla.com source: https://github.com/mozilla/code-coverage + - taskId: {$eval: as_slugid("report_check_tests")} + provisionerId: aws-provisioner-v1 + workerType: github-worker + created: {$fromNow: ''} + deadline: {$fromNow: '1 hour'} + payload: + maxRunTime: 3600 + image: python:3.7 + command: + - sh + - -lxce + - "git clone --quiet ${repository} /src && cd /src && git checkout ${head_rev} -b checks && + cd /src/report && ./ci-test.sh" + metadata: + name: "Code Coverage Report checks: unit tests" + description: Check python code with unittest + owner: bastien@mozilla.com + source: https://github.com/mozilla/code-coverage + - taskId: {$eval: as_slugid("backend_build")} created: {$fromNow: ''} deadline: {$fromNow: '1 hour'} diff --git a/report/.flake8 b/report/.flake8 deleted file mode 100644 index c6a26c199..000000000 --- a/report/.flake8 +++ /dev/null @@ -1,3 +0,0 @@ -[flake8] -exclude = .git,__pycache__ -ignore = E101, E111, E114, E115, E116, E117, E121, E122, E123, E124, E125, E126, E127, E128, E129, E131, E133, E2, E3, E5, E501, E701, E702, E703, E704, W1, W2, W3, W503, W504 diff --git a/report/.gitignore b/report/.gitignore index cf29fbaea..c70ba33fb 100644 --- a/report/.gitignore +++ b/report/.gitignore @@ -1,7 +1,3 @@ -.pytest_cache/ -*.pyc - -# Distribution / packaging .Python build/ develop-eggs/ @@ -22,3 +18,10 @@ share/python-wheels/ *.egg MANIFEST cache/ +ccov-artifacts/ +grcov +grcov_ver +lcov-bin/ +lcov/ +output.info +report/ diff --git a/report/.isort.cfg b/report/.isort.cfg deleted file mode 100644 index a5ae0bedd..000000000 --- a/report/.isort.cfg +++ /dev/null @@ -1,3 +0,0 @@ -[settings] -force_single_line=True -known_third_party = setuptools diff --git a/report/.pre-commit-config.yaml b/report/.pre-commit-config.yaml deleted file mode 100644 index 060545c43..000000000 --- a/report/.pre-commit-config.yaml +++ /dev/null @@ -1,38 +0,0 @@ -repos: -- repo: https://github.com/asottile/seed-isort-config - rev: v1.9.2 - hooks: - - id: seed-isort-config -- repo: https://github.com/pre-commit/mirrors-isort - rev: v4.3.21 - hooks: - - id: isort -- repo: https://github.com/ambv/black - rev: stable - hooks: - - id: black -- repo: https://gitlab.com/pycqa/flake8 - rev: 3.7.8 - hooks: - - id: flake8 - additional_dependencies: ['flake8-coding==1.3.1', 'flake8-copyright==0.2.2', 'flake8-debugger==3.1.0', 'flake8-mypy==17.8.0'] -- repo: https://github.com/pre-commit/pre-commit-hooks - rev: v2.3.0 - hooks: - - id: trailing-whitespace - - id: check-yaml - - id: mixed-line-ending - - id: name-tests-test - args: ['--django'] - - id: check-json - - id: requirements-txt-fixer -- repo: https://github.com/codespell-project/codespell - rev: v1.16.0 - hooks: - - id: codespell - exclude_types: [json] -- repo: meta - hooks: - - id: check-useless-excludes -default_language_version: - python: python3.7 diff --git a/report/.travis.yml b/report/.travis.yml deleted file mode 100644 index 93e39f85e..000000000 --- a/report/.travis.yml +++ /dev/null @@ -1,21 +0,0 @@ -language: python -python: - - "3.7" -install: - - pip install -r test-requirements.txt - - mkdir -p symlinks - - ln -s /usr/bin/gcc-6 symlinks/gcc - - ln -s /usr/bin/gcov-6 symlinks/gcov -script: - - export PATH=$PWD/symlinks:$PATH - - pre-commit run --all-files - - python -m unittest discover tests - - python setup.py sdist bdist_wheel - - pip install dist/firefox_code_coverage-1.0.0.tar.gz -cache: pip -addons: - apt: - sources: - - ubuntu-toolchain-r-test - packages: - - gcc-6 diff --git a/report/README.md b/report/README.md index 41889db59..4130f471d 100644 --- a/report/README.md +++ b/report/README.md @@ -1,5 +1,3 @@ # firefox-code-coverage -[![Build Status](https://travis-ci.org/marco-c/firefox-code-coverage.svg?branch=master)](https://travis-ci.org/marco-c/firefox-code-coverage) - A description on how to use this tool is available at https://developer.mozilla.org/en-US/docs/Mozilla/Testing/Measuring_Code_Coverage_on_Firefox. diff --git a/report/ci-test.sh b/report/ci-test.sh new file mode 100755 index 000000000..ab05ba22d --- /dev/null +++ b/report/ci-test.sh @@ -0,0 +1,7 @@ +#!/bin/bash -e + +pip install --disable-pip-version-check --no-cache-dir --quiet -r test-requirements.txt + +python -m unittest discover tests +python setup.py sdist bdist_wheel +pip install dist/firefox_code_coverage-1.0.0.tar.gz diff --git a/report/test-requirements.txt b/report/test-requirements.txt index f9ac171ec..b72fce9ec 100644 --- a/report/test-requirements.txt +++ b/report/test-requirements.txt @@ -1,3 +1,2 @@ -pre-commit==1.18.3 setuptools==41.4.0 wheel==0.33.6 diff --git a/report/tox.ini b/report/tox.ini deleted file mode 100644 index e44b81084..000000000 --- a/report/tox.ini +++ /dev/null @@ -1,2 +0,0 @@ -[flake8] -ignore = E501