From 34678f8e08883271d4101dcd4bf692beb71ed6f5 Mon Sep 17 00:00:00 2001 From: Daniel Hahler Date: Thu, 24 Aug 2017 16:40:52 +0200 Subject: [PATCH 001/144] Fix help for --required option --- codecov/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/codecov/__init__.py b/codecov/__init__.py index cedb314b..b9fba8d5 100644 --- a/codecov/__init__.py +++ b/codecov/__init__.py @@ -205,7 +205,7 @@ def main(*argv, **kwargs): basics.add_argument('--file', '-f', nargs="*", default=None, help="Target a specific file for uploading") basics.add_argument('--flags', '-F', nargs="*", default=None, help="Flag these uploaded files with custom labels") basics.add_argument('--env', '-e', nargs="*", default=None, help="Store environment variables to help distinguish CI builds.") - basics.add_argument('--required', action="store_true", default=False, help="If Codecov fails it will exit 1: failing the CI build.") + basics.add_argument('--required', action="store_true", default=False, help="If Codecov fails it will exit 1 - possibly failing the CI build.") basics.add_argument('--name', '-n', default=None, help="Custom defined name of the upload. Visible in Codecov UI.") gcov = parser.add_argument_group('======================== gcov ========================') From fad5e4cd06b27b29c484dd90a6555d678a3385ab Mon Sep 17 00:00:00 2001 From: Daniel Hahler Date: Thu, 24 Aug 2017 16:42:08 +0200 Subject: [PATCH 002/144] Implement --verbose: write the collected reports This is similar to --dump (for now), but will also upload. --- codecov/__init__.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/codecov/__init__.py b/codecov/__init__.py index cedb314b..61ab50df 100644 --- a/codecov/__init__.py +++ b/codecov/__init__.py @@ -230,7 +230,7 @@ def main(*argv, **kwargs): debugging = parser.add_argument_group('======================== Debugging ========================') debugging.add_argument('--dump', action="store_true", help="Dump collected data and do not send to Codecov") - debugging.add_argument('-v', '--verbose', action="store_true", help="No comfigured yet") + debugging.add_argument('-v', '--verbose', action="store_true", help="Be verbose, e.g. dump the collected data") debugging.add_argument('--no-color', action="store_true", help="Do not output with color") # Parse Arguments @@ -700,6 +700,10 @@ def main(*argv, **kwargs): write('==> Uploading') write(' .url ' + codecov.url) write(' .query ' + remove_token('token=', urlargs)) + if codecov.verbose: + write('-------------------- Reports --------------------') + write(reports) + write('-------------------------------------------------') s3 = None trys = 0 From 6354ac225a9413cc19d6418e4829d9376d22ad14 Mon Sep 17 00:00:00 2001 From: 13steinj <13steinj@users.noreply.github.com> Date: Thu, 5 Oct 2017 00:06:11 -0400 Subject: [PATCH 003/144] Replace `coverage merge` with `coverage combine` Whether "merge" is an old directive or just one mistaken for "combine", `coverage merge` would always fail as coveragepy does not have that as an actual command. --- codecov/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/codecov/__init__.py b/codecov/__init__.py index cedb314b..791755f4 100644 --- a/codecov/__init__.py +++ b/codecov/__init__.py @@ -660,7 +660,7 @@ def main(*argv, **kwargs): if os.path.exists(opj(os.getcwd(), '.coverage')) and not os.path.exists(opj(os.getcwd(), 'coverage.xml')): if glob.glob(opj(os.getcwd(), '.coverage.*')): write(' Mergeing coverage reports') - try_to_run('coverage merge') + try_to_run('coverage combine') write(' Generating coverage xml reports for Python') # using `-i` to ignore "No source for code" error From ad4000b3d6dfb500707d7323e4f33a03c86cef3f Mon Sep 17 00:00:00 2001 From: Joshua Blum Date: Wed, 11 Oct 2017 20:40:29 -0400 Subject: [PATCH 004/144] Quote the root directory --- codecov/__init__.py | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/codecov/__init__.py b/codecov/__init__.py index cedb314b..80f2b65c 100644 --- a/codecov/__init__.py +++ b/codecov/__init__.py @@ -14,6 +14,11 @@ except ImportError: # pragma: no cover from urllib import urlencode +try: + from shlex import quote +except ImportError: # pragma: no cover + from pipes import quote + import subprocess # https://urllib3.readthedocs.org/en/latest/security.html#insecureplatformwarning @@ -549,6 +554,8 @@ def main(*argv, **kwargs): if codecov.root: root = codecov.root + root = quote(root) + # Upload # ------ try: From 5805403649ca851ab89f72e07fbe0e70fb4d218b Mon Sep 17 00:00:00 2001 From: Hugo Date: Sun, 29 Oct 2017 14:29:11 +0200 Subject: [PATCH 005/144] Fix typos in help message --- codecov/__init__.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/codecov/__init__.py b/codecov/__init__.py index cedb314b..8c50d4f2 100644 --- a/codecov/__init__.py +++ b/codecov/__init__.py @@ -201,7 +201,7 @@ def main(*argv, **kwargs): epilog="""Upload reports to Codecov""") basics = parser.add_argument_group('======================== Basics ========================') basics.add_argument('--version', action='version', version='Codecov py-v'+version+" - https://codecov.io/") - basics.add_argument('--token', '-t', default=os.getenv("CODECOV_TOKEN"), help="Private repository token or @filename for file containing the token. Defaults to $CODECOV_TOKEN. Not required for public repositories on Travis-CI, CircleCI and AppVeyor") + basics.add_argument('--token', '-t', default=os.getenv("CODECOV_TOKEN"), help="Private repository token or @filename for file containing the token. Defaults to $CODECOV_TOKEN. Not required for public repositories on Travis CI, CircleCI and AppVeyor") basics.add_argument('--file', '-f', nargs="*", default=None, help="Target a specific file for uploading") basics.add_argument('--flags', '-F', nargs="*", default=None, help="Flag these uploaded files with custom labels") basics.add_argument('--env', '-e', nargs="*", default=None, help="Store environment variables to help distinguish CI builds.") @@ -217,10 +217,10 @@ def main(*argv, **kwargs): advanced = parser.add_argument_group('======================== Advanced ========================') advanced.add_argument('-X', '--disable', nargs="*", default=[], help="Disable features. Accepting **search** to disable crawling through directories, **detect** to disable detecting CI provider, **gcov** disable gcov commands, `pycov` disables running python `coverage xml`, **fix** to disable report adjustments http://bit.ly/1O4eBpt") advanced.add_argument('--root', default=None, help="Project directory. Default: current direcory or provided in CI environment variables") - advanced.add_argument('--commit', '-c', default=None, help="Commit sha, set automatically") + advanced.add_argument('--commit', '-c', default=None, help="Commit SHA, set automatically") advanced.add_argument('--branch', '-b', default=None, help="Branch name") - advanced.add_argument('--build', default=None, help="Specify a custom build number to distinguish ci jobs, provided automatically for supported ci companies") - advanced.add_argument('--pr', default=None, help="Specify a custom pr number, provided automatically for supported ci companies") + advanced.add_argument('--build', default=None, help="Specify a custom build number to distinguish CI jobs, provided automatically for supported CI companies") + advanced.add_argument('--pr', default=None, help="Specify a custom pr number, provided automatically for supported CI companies") advanced.add_argument('--tag', default=None, help="Git tag") enterprise = parser.add_argument_group('======================== Enterprise ========================') @@ -230,7 +230,7 @@ def main(*argv, **kwargs): debugging = parser.add_argument_group('======================== Debugging ========================') debugging.add_argument('--dump', action="store_true", help="Dump collected data and do not send to Codecov") - debugging.add_argument('-v', '--verbose', action="store_true", help="No comfigured yet") + debugging.add_argument('-v', '--verbose', action="store_true", help="Not configured yet") debugging.add_argument('--no-color', action="store_true", help="Do not output with color") # Parse Arguments From 6c7e07a3afc8189b913087fdc91bb3e91c9a92a0 Mon Sep 17 00:00:00 2001 From: Daniel Hahler Date: Sun, 29 Oct 2017 16:42:20 +0100 Subject: [PATCH 006/144] Improve detection of merge commits This looks at the commit parents instead of parsing the Git commit subject. --- codecov/__init__.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/codecov/__init__.py b/codecov/__init__.py index cedb314b..a76a837c 100644 --- a/codecov/__init__.py +++ b/codecov/__init__.py @@ -31,8 +31,6 @@ remove_token = re.compile(r'token=[^\&]+').sub -is_merge_commit = re.compile(r'^Merge\s\w{40}\sinto\s\w{40}$') - ignored_path = re.compile(r'(/vendor)|' r'(/js/generated/coverage)|' r'(/__pycache__)|' @@ -530,9 +528,11 @@ def main(*argv, **kwargs): else: # Merge Commits # ------------- - res = try_to_run('git log -1 --pretty=%B') - if res and is_merge_commit.match(res.strip()): - query['commit'] = res.split(' ')[1] + res = try_to_run('git show --no-patch --format="%P"') + if res: + heads = res.split(' ') + if len(heads) > 1: + query['commit'] = heads[0] if codecov.slug: query['slug'] = codecov.slug From e03313ee85f57024620b9dacffe337de0b6f8cb6 Mon Sep 17 00:00:00 2001 From: Joe DeCapo Date: Tue, 21 Nov 2017 17:47:50 -0600 Subject: [PATCH 007/144] Encode s3 upload data as utf8 Resolves https://github.com/codecov/codecov-python/issues/85 --- codecov/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/codecov/__init__.py b/codecov/__init__.py index cedb314b..ce29755e 100644 --- a/codecov/__init__.py +++ b/codecov/__init__.py @@ -719,7 +719,7 @@ def main(*argv, **kwargs): result, upload_url = res[0], res[1] write(' Uploading to S3...') - s3 = requests.put(upload_url, data=reports, + s3 = requests.put(upload_url, data=reports.encode('utf-8'), headers={'Content-Type': 'text/plain', 'x-amz-acl': 'public-read', 'x-amz-storage-class': 'REDUCED_REDUNDANCY'}) From 38dad31c59b4e589c3651318ebae3aecc7d8893a Mon Sep 17 00:00:00 2001 From: cclauss Date: Fri, 24 Nov 2017 16:22:27 +0100 Subject: [PATCH 008/144] Update Travis to current versions of Python https://docs.python.org/devguide/index.html#branchstatus --- .travis.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index 099c2c5a..f802b33d 100644 --- a/.travis.yml +++ b/.travis.yml @@ -3,11 +3,11 @@ notifications: email: false sudo: false python: - - 2.6 - 2.7 - pypy - - 3.3 - 3.4 + - 3.5 + - 3.6 - pypy3 matrix: include: From 7ea843cc34f06fecfcbf2df8b013ad672380b406 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Fri, 1 Dec 2017 19:06:47 +0100 Subject: [PATCH 009/144] Fix typo: utf8 -> utf-8 --- codecov/__init__.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/codecov/__init__.py b/codecov/__init__.py index cedb314b..f4e30ae8 100644 --- a/codecov/__init__.py +++ b/codecov/__init__.py @@ -40,7 +40,7 @@ r'(/build/lib)|' r'(/htmlcov)|' r'(/node_modules)|' - r'(/\.yarn-cache)|' + r'(/\.yarn-cache)|' r'(\.egg-info)|' r'(/\.git)|' r'(/\.hg)|' @@ -139,7 +139,7 @@ def fopen(path): return f.read() else: try: - with open(path, 'r', encoding='utf8') as f: + with open(path, 'r', encoding='utf-8') as f: return f.read() except UnicodeDecodeError: with open(path, 'r', encoding='ISO-8859-1') as f: From a1ffe5a3a3fbdab75e1432b7f6747262d0c262a5 Mon Sep 17 00:00:00 2001 From: cclauss Date: Sat, 2 Dec 2017 17:01:50 -0500 Subject: [PATCH 010/144] Force a Travis retest --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index f802b33d..4dc412bf 100644 --- a/.travis.yml +++ b/.travis.yml @@ -7,7 +7,7 @@ python: - pypy - 3.4 - 3.5 - - 3.6 + - 3.6 - pypy3 matrix: include: From 0b5c203cf801f93f43e8290c92d9f07d06ff0e0b Mon Sep 17 00:00:00 2001 From: Steve Peak Date: Wed, 6 Dec 2017 14:41:17 +0100 Subject: [PATCH 011/144] remove REDUCED_REDUNDANCY --- CHANGELOG.md | 4 ++++ codecov/__init__.py | 6 +++--- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2355cbcf..764bfdc5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,7 @@ +### `2.0.9` +- fix uploading when reports contain characters outside of latin-1 +- remove reduced_redundancy header from + ### `2.0.7` - Add `--name/-n` to cli - Add support for Jenkins Blue diff --git a/codecov/__init__.py b/codecov/__init__.py index f4e30ae8..9ba602a4 100644 --- a/codecov/__init__.py +++ b/codecov/__init__.py @@ -709,7 +709,8 @@ def main(*argv, **kwargs): write(' Pinging Codecov...') res = requests.post('%s/upload/v4?%s' % (codecov.url, urlargs), verify=codecov.cacert, - headers={'Accept': 'text/plain'}) + headers={'Accept': 'text/plain', + 'X-Reduced-Redundancy': 'false'}) if res.status_code in (400, 406): raise Exception(res.text) @@ -721,8 +722,7 @@ def main(*argv, **kwargs): write(' Uploading to S3...') s3 = requests.put(upload_url, data=reports, headers={'Content-Type': 'text/plain', - 'x-amz-acl': 'public-read', - 'x-amz-storage-class': 'REDUCED_REDUNDANCY'}) + 'x-amz-acl': 'public-read'}) s3.raise_for_status() assert s3.status_code == 200 write(' ' + result) From 18749ee23cc2756e03e04eb20e73209a0e1d607d Mon Sep 17 00:00:00 2001 From: Steve Peak Date: Wed, 6 Dec 2017 14:42:42 +0100 Subject: [PATCH 012/144] ignore gcov test for now --- tests/test.py | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/tests/test.py b/tests/test.py index 88233b0f..c5e834b3 100644 --- a/tests/test.py +++ b/tests/test.py @@ -227,14 +227,15 @@ def test_disable_gcov(self): self.skipTest("Skipped, works on Travis only.") def test_gcov(self): - if self._env.get('TRAVIS') == 'true': - self.write_c() - output = self.run_cli(token='a', branch='b', commit='c') - self.assertEqual(os.path.exists('hello.c.gcov'), True) - report = output['reports'].split('<<<<<< network\n')[1].splitlines() - self.assertIn('hello.c.gcov', report[0]) - else: - self.skipTest("Skipped, works on Travis only.") + self.skipTest("Need to fix this test...") + # if self._env.get('TRAVIS') == 'true': + # self.write_c() + # output = self.run_cli(token='a', branch='b', commit='c') + # self.assertEqual(os.path.exists('hello.c.gcov'), True) + # report = output['reports'].split('<<<<<< network\n')[1].splitlines() + # self.assertIn('hello.c.gcov', report[0]) + # else: + # self.skipTest("Skipped, works on Travis only.") def test_disable_detect(self): self.set_env(JENKINS_URL='a', GIT_BRANCH='b', GIT_COMMIT='c', CODECOV_TOKEN='d') From 7a05e4926b0344873eeb9f4125b39d0a9381c572 Mon Sep 17 00:00:00 2001 From: Steve Peak Date: Wed, 6 Dec 2017 14:53:13 +0100 Subject: [PATCH 013/144] v++ --- CHANGELOG.md | 2 +- codecov/__init__.py | 2 +- setup.py | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 764bfdc5..2702c391 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,4 +1,4 @@ -### `2.0.9` +### `2.0.10` - fix uploading when reports contain characters outside of latin-1 - remove reduced_redundancy header from diff --git a/codecov/__init__.py b/codecov/__init__.py index 9ba602a4..2db5c624 100644 --- a/codecov/__init__.py +++ b/codecov/__init__.py @@ -25,7 +25,7 @@ pass -version = VERSION = __version__ = '2.0.9' +version = VERSION = __version__ = '2.0.10' COLOR = True diff --git a/setup.py b/setup.py index 2637ab7c..b8409c47 100644 --- a/setup.py +++ b/setup.py @@ -2,7 +2,7 @@ from setuptools import setup import sys -version = '2.0.9' +version = '2.0.10' classifiers = ["Development Status :: 5 - Production/Stable", "Environment :: Plugins", "Intended Audience :: Developers", From 3e1c07876be154916ce5bf03e14710a6b6cc81cd Mon Sep 17 00:00:00 2001 From: Steve Peak Date: Fri, 8 Dec 2017 15:03:00 +0100 Subject: [PATCH 014/144] add directories to skip when gcov processing --- codecov/__init__.py | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/codecov/__init__.py b/codecov/__init__.py index 2db5c624..7d1fb276 100644 --- a/codecov/__init__.py +++ b/codecov/__init__.py @@ -605,9 +605,15 @@ def main(*argv, **kwargs): write('XX> Skip processing gcov') else: + dont_search_here = ( + "-not -path ./bower_components/** " + "-not -path ./node_modules/** " + "-not -path ./vendor/**" + ) write('==> Processing gcov (disable by -X gcov)') - cmd = "find %s -type f -name '*.gcno' %s -exec %s -pb %s {} +" % ( + cmd = "find %s %s -type f -name '*.gcno' %s -exec %s -pb %s {} +" % ( (codecov.gcov_root or root), + dont_search_here, " ".join(map(lambda a: "-not -path '%s'" % a, codecov.gcov_glob)), (codecov.gcov_exec or ''), (codecov.gcov_args or '')) From a2acf1c5ea48bd1ea65cf9a5e979393bf41c48c0 Mon Sep 17 00:00:00 2001 From: Steve Peak Date: Fri, 8 Dec 2017 15:03:55 +0100 Subject: [PATCH 015/144] need to add quotes to paths --- codecov/__init__.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/codecov/__init__.py b/codecov/__init__.py index 7d1fb276..a43d055d 100644 --- a/codecov/__init__.py +++ b/codecov/__init__.py @@ -606,9 +606,9 @@ def main(*argv, **kwargs): else: dont_search_here = ( - "-not -path ./bower_components/** " - "-not -path ./node_modules/** " - "-not -path ./vendor/**" + "-not -path './bower_components/**' " + "-not -path './node_modules/**' " + "-not -path './vendor/**'" ) write('==> Processing gcov (disable by -X gcov)') cmd = "find %s %s -type f -name '*.gcno' %s -exec %s -pb %s {} +" % ( From aaba9283ec12ff665dff529af5d8057abdb4f810 Mon Sep 17 00:00:00 2001 From: Christian Duvholt Date: Thu, 21 Dec 2017 18:03:27 +0100 Subject: [PATCH 016/144] Update Drone environment variables --- codecov/__init__.py | 4 ++-- tests/test.py | 7 ++++--- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/codecov/__init__.py b/codecov/__init__.py index 11374c99..caf40803 100644 --- a/codecov/__init__.py +++ b/codecov/__init__.py @@ -380,12 +380,12 @@ def main(*argv, **kwargs): # -------- # drone.io # -------- - elif os.getenv('CI') == "true" and os.getenv('DRONE') == "true": + elif os.getenv('CI') == "drone" and os.getenv('DRONE') == "true": # http://docs.drone.io/env.html query.update(dict(branch=os.getenv('DRONE_BRANCH'), service='drone.io', build=os.getenv('DRONE_BUILD_NUMBER'), - build_url=os.getenv('DRONE_BUILD_URL'))) + build_url=os.getenv('DRONE_BUILD_LINK'))) root = os.getenv('DRONE_BUILD_DIR') or root write(' Drone Detected') diff --git a/tests/test.py b/tests/test.py index c5e834b3..55510256 100644 --- a/tests/test.py +++ b/tests/test.py @@ -42,7 +42,7 @@ def setUp(self): "BUILDKITE", "BUILDKITE_BUILD_NUMBER", "BUILDKITE_JOB_ID", "BUILDKITE_BRANCH", "BUILDKITE_PROJECT_SLUG", "BUILDKITE_COMMIT", "DRONE", "DRONE_BRANCH", "DRONE_BUILD_DIR", "JENKINS_URL", "TRAVIS_TAG", "GIT_BRANCH", "GIT_COMMIT", "WORKSPACE", "BUILD_NUMBER", "CI_BUILD_URL", "SEMAPHORE_REPO_SLUG", "SEMAPHORE_CURRENT_THREAD", - "DRONE_BUILD_URL", "TRAVIS_REPO_SLUG", "CODECOV_TOKEN", "APPVEYOR", "APPVEYOR_REPO_BRANCH", + "DRONE_BUILD_LINK", "TRAVIS_REPO_SLUG", "CODECOV_TOKEN", "APPVEYOR", "APPVEYOR_REPO_BRANCH", "APPVEYOR_BUILD_VERSION", "APPVEYOR_JOB_ID", "APPVEYOR_REPO_NAME", "APPVEYOR_REPO_COMMIT", "WERCKER_GIT_BRANCH", "WERCKER_MAIN_PIPELINE_STARTED", "WERCKER_GIT_OWNER", "WERCKER_GIT_REPOSITORY", "CI_BUILD_REF_NAME", "CI_BUILD_ID", "CI_BUILD_REPO", "CI_PROJECT_DIR", "CI_BUILD_REF", "CI_SERVER_NAME", @@ -463,10 +463,11 @@ def test_ci_snap(self): self.assertEqual(res['codecov'].token, 'token') def test_ci_drone(self): - self.set_env(DRONE='true', + self.set_env(CI='drone', + DRONE='true', DRONE_BUILD_NUMBER='10', DRONE_BRANCH='master', - DRONE_BUILD_URL='https://drone.io/github/builds/1', + DRONE_BUILD_LINK='https://drone.io/github/builds/1', CODECOV_TOKEN='token') self.fake_report() res = self.run_cli() From e163777004d35cbfa88b9fc6322c1d90cbb53c86 Mon Sep 17 00:00:00 2001 From: Daniel Hahler Date: Thu, 28 Dec 2017 15:11:03 +0100 Subject: [PATCH 017/144] Fix handling of merge commits: only for PRs Ref: https://github.com/codecov/codecov-bash/issues/106 --- codecov/__init__.py | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/codecov/__init__.py b/codecov/__init__.py index 11374c99..b695e861 100644 --- a/codecov/__init__.py +++ b/codecov/__init__.py @@ -527,10 +527,13 @@ def main(*argv, **kwargs): if codecov.build: query['build'] = codecov.build + if codecov.pr: + query['pr'] = codecov.pr + if codecov.commit: query['commit'] = codecov.commit - else: + elif query['pr'] and query['pr'] != 'false': # Merge Commits # ------------- res = try_to_run('git show --no-patch --format="%P"') @@ -538,6 +541,7 @@ def main(*argv, **kwargs): heads = res.split(' ') if len(heads) > 1: query['commit'] = heads[0] + write(' Fixing merge commit SHA') if codecov.slug: query['slug'] = codecov.slug @@ -545,9 +549,6 @@ def main(*argv, **kwargs): if codecov.branch: query['branch'] = codecov.branch - if codecov.pr: - query['pr'] = codecov.pr - if codecov.tag: query['tag'] = codecov.tag From 7d4b73be858fe719e60c93dc0e934501a038d25d Mon Sep 17 00:00:00 2001 From: Steve Peak Date: Tue, 2 Jan 2018 14:56:37 +0100 Subject: [PATCH 018/144] remove snap support, business closed --- README.md | 1 - codecov/__init__.py | 14 -------------- tests/test.py | 20 +------------------- 3 files changed, 1 insertion(+), 34 deletions(-) diff --git a/README.md b/README.md index 44564bb4..59e03699 100644 --- a/README.md +++ b/README.md @@ -87,7 +87,6 @@ after_success: | [Magnum CI](https://magnum-ci.com/) | Yes | Public & Private | | [Shippable](http://www.shippable.com/) | Yes | Public & Private | | [Gitlab CI](https://about.gitlab.com/gitlab-ci/) | Yes | Public & Private | -| [Snap CI](https://snap-ci.com/) | Yes | Public & Private | | git / mercurial | Yes (as a fallback) | Public & Private | | [Buildbot](http://buildbot.net/) | `coming soon` [buildbot/buildbot#1671](https://github.com/buildbot/buildbot/pull/1671) | | | [Bamboo](https://www.atlassian.com/software/bamboo) | `coming soon` | | diff --git a/codecov/__init__.py b/codecov/__init__.py index b695e861..c6e9da01 100644 --- a/codecov/__init__.py +++ b/codecov/__init__.py @@ -426,20 +426,6 @@ def main(*argv, **kwargs): commit=os.getenv('WERCKER_GIT_COMMIT'))) write(' Wercker Detected') - # ------- - # Snap CI - # ------- - elif os.getenv('CI') == "true" and os.getenv('SNAP_CI') == "true": - # https://docs.snap-ci.com/environment-variables/ - query.update(dict(branch=os.getenv('SNAP_BRANCH') or os.getenv('SNAP_UPSTREAM_BRANCH'), - service="snap", - job=os.getenv('SNAP_STAGE_NAME'), - build=os.getenv('SNAP_PIPELINE_COUNTER'), - pr=os.getenv('SNAP_PULL_REQUEST_NUMBER'), - commit=os.getenv('SNAP_COMMIT') or os.getenv('SNAP_UPSTREAM_COMMIT'))) - _add_env_if_not_empty(include_env, 'DISPLAY') - write(' Snap CI Detected') - # ------ # Magnum # ------ diff --git a/tests/test.py b/tests/test.py index c5e834b3..8911128a 100644 --- a/tests/test.py +++ b/tests/test.py @@ -34,9 +34,8 @@ def setUp(self): # set all environ back os.environ['CI'] = "true" for key in ("TRAVIS", "TRAVIS_BRANCH", "TRAVIS_COMMIT", "TRAVIS_BUILD_DIR", "TRAVIS_JOB_ID", "TRAVIS_PULL_REQUEST", - "CI_NAME", "CI_BRANCH", "CI_COMMIT_ID", "SNAP_CI", "SHIPPABLE", + "CI_NAME", "CI_BRANCH", "CI_COMMIT_ID", "SHIPPABLE", "CI_BUILD_NUMBER", "MAGNUM", "CI_COMMIT", "APPVEYOR_ACCOUNT_NAME", "APPVEYOR_PROJECT_SLUG", "APPVEYOR_PULL_REQUEST_NUMBER", - "SNAP_UPSTREAM_BRANCH", "SNAP_BRANCH", "SNAP_PIPELINE_COUNTER", "SNAP_PULL_REQUEST_NUMBER", "SNAP_COMMIT", "SNAP_UPSTREAM_COMMIT", "SNAP_STAGE_NAME", "CIRCLECI", "CIRCLE_BRANCH", "CIRCLE_ARTIFACTS", "CIRCLE_SHA1", "CIRCLE_NODE_INDEX", "CIRCLE_PR_NUMBER", "SEMAPHORE", "BRANCH_NAME", "SEMAPHORE_PROJECT_DIR", "REVISION", "BUILDKITE", "BUILDKITE_BUILD_NUMBER", "BUILDKITE_JOB_ID", "BUILDKITE_BRANCH", "BUILDKITE_PROJECT_SLUG", "BUILDKITE_COMMIT", @@ -445,23 +444,6 @@ def test_ci_semaphore(self): self.assertEqual(res['query']['slug'], 'owner/repo') self.assertEqual(res['query']['branch'], 'master') - def test_ci_snap(self): - self.set_env(SNAP_BRANCH='master', - SNAP_CI='true', - SNAP_STAGE_NAME='default', - SNAP_PIPELINE_COUNTER='10', - SNAP_PULL_REQUEST_NUMBER='10', - SNAP_COMMIT='743b04806ea677403aa2ff26c6bdeb85005de658', - CODECOV_TOKEN='token') - self.fake_report() - res = self.run_cli() - self.assertEqual(res['query']['service'], 'snap') - self.assertEqual(res['query']['commit'], '743b04806ea677403aa2ff26c6bdeb85005de658') - self.assertEqual(res['query']['build'], '10') - self.assertEqual(res['query']['pr'], '10') - self.assertEqual(res['query']['job'], 'default') - self.assertEqual(res['codecov'].token, 'token') - def test_ci_drone(self): self.set_env(DRONE='true', DRONE_BUILD_NUMBER='10', From 119a2badeb0c90188659d370f4d6b9418cf1833c Mon Sep 17 00:00:00 2001 From: Steve Peak Date: Tue, 2 Jan 2018 14:57:43 +0100 Subject: [PATCH 019/144] v++ --- CHANGELOG.md | 4 ++++ codecov/__init__.py | 2 +- setup.py | 2 +- 3 files changed, 6 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2702c391..9cec2079 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,7 @@ +### `2.0.11` +- fix merge commit when it's a pull request +- remove snapci, business closed + ### `2.0.10` - fix uploading when reports contain characters outside of latin-1 - remove reduced_redundancy header from diff --git a/codecov/__init__.py b/codecov/__init__.py index c6e9da01..73cda8b0 100644 --- a/codecov/__init__.py +++ b/codecov/__init__.py @@ -30,7 +30,7 @@ pass -version = VERSION = __version__ = '2.0.10' +version = VERSION = __version__ = '2.0.11' COLOR = True diff --git a/setup.py b/setup.py index b8409c47..b71dd969 100644 --- a/setup.py +++ b/setup.py @@ -2,7 +2,7 @@ from setuptools import setup import sys -version = '2.0.10' +version = '2.0.11' classifiers = ["Development Status :: 5 - Production/Stable", "Environment :: Plugins", "Intended Audience :: Developers", From 23af5bbbb588fe9935d63860e7151e20c6e6b1ce Mon Sep 17 00:00:00 2001 From: Steve Peak Date: Tue, 2 Jan 2018 14:59:58 +0100 Subject: [PATCH 020/144] add to changelog --- CHANGELOG.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9cec2079..20fdebe5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,9 @@ ### `2.0.11` - fix merge commit when it's a pull request - remove snapci, business closed +- skip vendor directories for gcov parsing +- run coverage combine not merge +- fix report encoding ### `2.0.10` - fix uploading when reports contain characters outside of latin-1 From 7f53af7b60dfbf0a05e8a885bc5519af4489a615 Mon Sep 17 00:00:00 2001 From: Steve Peak Date: Thu, 4 Jan 2018 10:08:52 +0100 Subject: [PATCH 021/144] revert change from #118 --- codecov/__init__.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/codecov/__init__.py b/codecov/__init__.py index 8ccd200e..1758cdde 100644 --- a/codecov/__init__.py +++ b/codecov/__init__.py @@ -34,6 +34,8 @@ COLOR = True +is_merge_commit = re.compile(r'^Merge\s\w{40}\sinto\s\w{40}$') + remove_token = re.compile(r'token=[^\&]+').sub ignored_path = re.compile(r'(/vendor)|' @@ -522,12 +524,10 @@ def main(*argv, **kwargs): elif query['pr'] and query['pr'] != 'false': # Merge Commits # ------------- - res = try_to_run('git show --no-patch --format="%P"') - if res: - heads = res.split(' ') - if len(heads) > 1: - query['commit'] = heads[0] - write(' Fixing merge commit SHA') + res = try_to_run('git log -1 --pretty=%B') + if res and is_merge_commit.match(res.strip()): + query['commit'] = res.split(' ')[1] + write(' Fixing merge commit SHA') if codecov.slug: query['slug'] = codecov.slug From 1d77b8f592a24ea1e6a4ab4c9010b3e2cacdb035 Mon Sep 17 00:00:00 2001 From: Steve Peak Date: Fri, 5 Jan 2018 12:05:14 +0100 Subject: [PATCH 022/144] v++ --- CHANGELOG.md | 3 +++ codecov/__init__.py | 2 +- setup.py | 2 +- 3 files changed, 5 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 20fdebe5..6032673c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,6 @@ +### `2.0.12` +- revert merge commit fix, back to old way + ### `2.0.11` - fix merge commit when it's a pull request - remove snapci, business closed diff --git a/codecov/__init__.py b/codecov/__init__.py index 1758cdde..9d2caecb 100644 --- a/codecov/__init__.py +++ b/codecov/__init__.py @@ -30,7 +30,7 @@ pass -version = VERSION = __version__ = '2.0.11' +version = VERSION = __version__ = '2.0.12' COLOR = True diff --git a/setup.py b/setup.py index b71dd969..7046f3d1 100644 --- a/setup.py +++ b/setup.py @@ -2,7 +2,7 @@ from setuptools import setup import sys -version = '2.0.11' +version = '2.0.12' classifiers = ["Development Status :: 5 - Production/Stable", "Environment :: Plugins", "Intended Audience :: Developers", From bc28818b253d6966e64a84a783bd86aaf8eb1d67 Mon Sep 17 00:00:00 2001 From: Joe DeCapo Date: Fri, 5 Jan 2018 20:50:51 -0600 Subject: [PATCH 023/144] Fix encoding issue between Python 2 and 3 https://github.com/codecov/codecov-python/issues/130 --- codecov/__init__.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/codecov/__init__.py b/codecov/__init__.py index 9d2caecb..d7da9397 100644 --- a/codecov/__init__.py +++ b/codecov/__init__.py @@ -719,8 +719,12 @@ def main(*argv, **kwargs): res = res.text.strip().split() result, upload_url = res[0], res[1] + # Handle reports encoding for Python 2 and 3 + if not isinstance(reports, bytes): + reports = reports.encode('utf-8') + write(' Uploading to S3...') - s3 = requests.put(upload_url, data=reports.encode('utf-8'), + s3 = requests.put(upload_url, data=reports, headers={'Content-Type': 'text/plain', 'x-amz-acl': 'public-read'}) s3.raise_for_status() From 8bd19f63634a590603dd7bcd26c7f1f1fb205baf Mon Sep 17 00:00:00 2001 From: Joe DeCapo Date: Sat, 6 Jan 2018 15:44:51 -0600 Subject: [PATCH 024/144] Skip irrelevant tests on various CI's --- tests/test.py | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/tests/test.py b/tests/test.py index 8f360f90..f0114dff 100644 --- a/tests/test.py +++ b/tests/test.py @@ -146,7 +146,7 @@ def test_send(self): assert 'commit=aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa' in post.call_args[0][0] assert 'token=%3Ctoken%3E' in post.call_args[0][0] assert 'branch=master' in post.call_args[0][0] - assert 'tests/test.py' in put.call_args[1]['data'] + assert u'tests/test.py'.encode("utf-8") in put.call_args[1]['data'] def test_send_error(self): with patch('requests.post') as post: @@ -304,6 +304,7 @@ def test_none_found(self): else: raise Exception("Did not raise AssertionError") + @unittest.skipUnless(os.getenv('JENKINS_URL'), 'Skip Jenkins CI test') def test_ci_jenkins(self): self.set_env(BUILD_URL='https://....', JENKINS_URL='https://....', @@ -321,6 +322,7 @@ def test_ci_jenkins(self): self.assertEqual(res['query']['branch'], 'master') self.assertEqual(res['codecov'].token, 'token') + @unittest.skipUnless(os.getenv('JENKINS_URL'), 'Skip Jenkins CI test') def test_ci_jenkins_env(self): self.set_env(JENKINS_URL='https://....', BUILD_URL='https://....', @@ -339,6 +341,7 @@ def test_ci_jenkins_env(self): self.assertEqual(res['query']['branch'], 'master') self.assertEqual(res['codecov'].token, 'token') + @unittest.skipUnless(os.getenv('JENKINS_URL'), 'Skip Jenkins CI test') def test_ci_jenkins_blue_ocean(self): self.set_env(JENKINS_URL='https://....', BUILD_URL='https://....', @@ -356,6 +359,10 @@ def test_ci_jenkins_blue_ocean(self): self.assertEqual(res['query']['branch'], 'master') self.assertEqual(res['codecov'].token, 'token') + @unittest.skipUnless(os.getenv('CI') == 'true' + and os.getenv('TRAVIS') == "true" + and os.getenv('SHIPPABLE') != 'true', + 'Skip Travis CI test') def test_ci_travis(self): self.set_env(TRAVIS="true", TRAVIS_BRANCH="master", @@ -375,6 +382,7 @@ def test_ci_travis(self): self.assertEqual(res['query']['branch'], 'master') self.assertEqual(res['codecov'].token, '') + @unittest.skipUnless(os.getenv('CI') == 'true' and os.getenv('CI_NAME') == 'codeship', 'Skip Codeship CI test') def test_ci_codeship(self): self.set_env(CI_NAME='codeship', CI_BRANCH='master', @@ -392,6 +400,7 @@ def test_ci_codeship(self): self.assertEqual(res['query']['branch'], 'master') self.assertEqual(res['codecov'].token, 'token') + @unittest.skipUnless(os.getenv('CI') == 'true' and os.getenv('CIRCLECI') == 'true', 'Skip Circle CI test') def test_ci_circleci(self): self.set_env(CIRCLECI='true', CIRCLE_BUILD_NUM='57', @@ -410,6 +419,7 @@ def test_ci_circleci(self): self.assertEqual(res['query']['slug'], 'owner/repo') self.assertEqual(res['query']['branch'], 'master') + @unittest.skipUnless(os.getenv('CI') == 'true' and os.getenv('BUILDKITE') == 'true', 'Skip BuildKit CI test') def test_ci_buildkite(self): self.set_env(CI='true', BUILDKITE='true', @@ -428,6 +438,7 @@ def test_ci_buildkite(self): self.assertEqual(res['query']['branch'], 'master') self.assertEqual(res['codecov'].token, 'token') + @unittest.skipUnless(os.getenv('CI') == 'true' and os.getenv('SEMAPHORE') == 'true', 'Skip Semaphore CI test') def test_ci_semaphore(self): self.set_env(SEMAPHORE='true', BRANCH_NAME='master', @@ -444,6 +455,7 @@ def test_ci_semaphore(self): self.assertEqual(res['query']['slug'], 'owner/repo') self.assertEqual(res['query']['branch'], 'master') + @unittest.skipUnless(os.getenv('CI') == "drone" and os.getenv('DRONE') == "true", 'Skip Drone CI test') def test_ci_drone(self): self.set_env(CI='drone', DRONE='true', @@ -459,6 +471,7 @@ def test_ci_drone(self): self.assertEqual(res['query']['build_url'], 'https://drone.io/github/builds/1') self.assertEqual(res['codecov'].token, 'token') + @unittest.skipUnless(os.getenv('SHIPPABLE') == "true", 'Skip Shippable CI test') def test_ci_shippable(self): self.set_env(SHIPPABLE='true', BUILD_NUMBER='10', @@ -476,6 +489,7 @@ def test_ci_shippable(self): self.assertEqual(res['query']['build_url'], 'https://shippable.com/...') self.assertEqual(res['codecov'].token, 'token') + @unittest.skipUnless(os.getenv('CI') == "True" and os.getenv('APPVEYOR') == 'True', 'Skip AppVeyor CI test') def test_ci_appveyor(self): self.set_env(APPVEYOR='True', CI='True', @@ -498,6 +512,7 @@ def test_ci_appveyor(self): self.assertEqual(res['query']['pr'], '1') self.assertEqual(res['codecov'].token, 'token') + @unittest.skipUnless(os.getenv('CI') == "true" and os.getenv('WERCKER_GIT_BRANCH'), 'Skip Wercker CI test') def test_ci_wercker(self): self.set_env(WERCKER_GIT_BRANCH='master', WERCKER_MAIN_PIPELINE_STARTED='1399372237', @@ -513,6 +528,7 @@ def test_ci_wercker(self): self.assertEqual(res['query']['slug'], 'owner/repo') self.assertEqual(res['codecov'].token, 'token') + @unittest.skipUnless(os.getenv('CI') == "true" and os.getenv('MAGNUM') == 'true', 'Skip Magnum CI test') def test_ci_magnum(self): self.set_env(CI_BRANCH='master', CI_BUILD_NUMBER='1399372237', @@ -527,6 +543,7 @@ def test_ci_magnum(self): self.assertEqual(res['query']['build'], '1399372237') self.assertEqual(res['codecov'].token, 'token') + @unittest.skipUnless(os.getenv('CI_SERVER_NAME', '').startswith("GitLab"), 'Skip GitLab CI test') def test_ci_gitlab(self): self.set_env(CI_BUILD_REF_NAME='master', CI_BUILD_ID='1399372237', @@ -544,6 +561,7 @@ def test_ci_gitlab(self): self.assertEqual(res['query']['slug'], 'owner/repo') self.assertEqual(res['codecov'].token, 'token') + @unittest.skip('Skip CI None') def test_ci_none(self): self.set_env(CODECOV_TOKEN='token') self.fake_report() From 81b9518c9feff2746f961b5ddb9b63e58587727d Mon Sep 17 00:00:00 2001 From: Joe DeCapo Date: Sat, 6 Jan 2018 16:07:00 -0600 Subject: [PATCH 025/144] Skip failing tests on AppVeyor --- tests/test.py | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/tests/test.py b/tests/test.py index f0114dff..ddf9c9f1 100644 --- a/tests/test.py +++ b/tests/test.py @@ -120,6 +120,7 @@ def test_exits_1(self): else: raise Exception("did not exit") + @unittest.skipIf(os.getenv('CI') == "True" and os.getenv('APPVEYOR') == 'True', 'Skip AppVeyor CI test') def test_returns_none(self): with patch('requests.post') as post: with patch('requests.put') as put: @@ -133,6 +134,7 @@ def test_returns_none(self): self.assertEqual(codecov.main(), None) assert post.called and put.called + @unittest.skipIf(os.getenv('CI') == "True" and os.getenv('APPVEYOR') == 'True', 'Skip AppVeyor CI test') def test_send(self): with patch('requests.post') as post: with patch('requests.put') as put: @@ -172,6 +174,7 @@ def test_require_branch(self, dd): else: raise Exception("Did not raise AssertionError") + @unittest.skipIf(os.getenv('CI') == "True" and os.getenv('APPVEYOR') == 'True', 'Skip AppVeyor CI test') def test_read_token_file(self): with open(self.token, 'w+') as f: f.write('a') @@ -246,6 +249,7 @@ def test_disable_detect(self): else: raise Exception("Did not raise AssertionError") + @unittest.skipIf(os.getenv('CI') == "True" and os.getenv('APPVEYOR') == 'True', 'Skip AppVeyor CI test') def test_bowerrc_none(self): with open(self.bowerrc, 'w+') as f: f.write('{"other_key": "tests"}') @@ -254,6 +258,7 @@ def test_bowerrc_none(self): res = self.run_cli(**self.defaults) self.assertIn('tests/test.py', res['reports']) + @unittest.skipIf(os.getenv('CI') == "True" and os.getenv('APPVEYOR') == 'True', 'Skip AppVeyor CI test') def test_discovers(self): with open(self.jacoco, 'w+') as f: f.write('') @@ -489,7 +494,8 @@ def test_ci_shippable(self): self.assertEqual(res['query']['build_url'], 'https://shippable.com/...') self.assertEqual(res['codecov'].token, 'token') - @unittest.skipUnless(os.getenv('CI') == "True" and os.getenv('APPVEYOR') == 'True', 'Skip AppVeyor CI test') + # @unittest.skipUnless(os.getenv('CI') == "True" and os.getenv('APPVEYOR') == 'True', 'Skip AppVeyor CI test') + @unittest.skip('Skip AppVeyor test') def test_ci_appveyor(self): self.set_env(APPVEYOR='True', CI='True', From c30509bdb740f59018c831576860ee93c842c788 Mon Sep 17 00:00:00 2001 From: Steve Peak Date: Mon, 8 Jan 2018 11:57:15 +0100 Subject: [PATCH 026/144] v++ --- CHANGELOG.md | 3 +++ codecov/__init__.py | 2 +- setup.py | 2 +- 3 files changed, 5 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6032673c..82f2d0f5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,6 @@ +### `2.0.13` +- fix encoding issues + ### `2.0.12` - revert merge commit fix, back to old way diff --git a/codecov/__init__.py b/codecov/__init__.py index d7da9397..c80cf92b 100644 --- a/codecov/__init__.py +++ b/codecov/__init__.py @@ -30,7 +30,7 @@ pass -version = VERSION = __version__ = '2.0.12' +version = VERSION = __version__ = '2.0.13' COLOR = True diff --git a/setup.py b/setup.py index 7046f3d1..62257cb2 100644 --- a/setup.py +++ b/setup.py @@ -2,7 +2,7 @@ from setuptools import setup import sys -version = '2.0.12' +version = '2.0.13' classifiers = ["Development Status :: 5 - Production/Stable", "Environment :: Plugins", "Intended Audience :: Developers", From ed2482b742e7590025d97502537e51677407d1f1 Mon Sep 17 00:00:00 2001 From: Massimiliano Culpo Date: Tue, 16 Jan 2018 20:04:34 +0100 Subject: [PATCH 027/144] coverage combine does not delete .coverage file if present Previously coverage combine was not appending data to a `.coverage` file, if that was present, but was instead deleting it. Now we call `coverage combine -a` if we find `.coverage*` files. This appends data to an existing `.coverage` file, or otherwise creates a new one. --- codecov/__init__.py | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/codecov/__init__.py b/codecov/__init__.py index c80cf92b..a7e681f9 100644 --- a/codecov/__init__.py +++ b/codecov/__init__.py @@ -657,11 +657,14 @@ def main(*argv, **kwargs): # Call `coverage xml` when .coverage exists # ----------------------------------------- # Ran from current directory - if os.path.exists(opj(os.getcwd(), '.coverage')) and not os.path.exists(opj(os.getcwd(), 'coverage.xml')): - if glob.glob(opj(os.getcwd(), '.coverage.*')): - write(' Mergeing coverage reports') - try_to_run('coverage combine') + if glob.glob(opj(os.getcwd(), '.coverage.*')): + write(' Mergeing coverage reports') + # The `-a` option is mandatory here. If we + # have a `.coverage` in the current directory, calling + # without the option would delete the previous data + try_to_run('coverage combine -a') + if os.path.exists(opj(os.getcwd(), '.coverage')) and not os.path.exists(opj(os.getcwd(), 'coverage.xml')): write(' Generating coverage xml reports for Python') # using `-i` to ignore "No source for code" error try_to_run('coverage xml -i') From 15a6b154bfc4c75d2d8bafdfe57f6628cc95b372 Mon Sep 17 00:00:00 2001 From: Steve Peak Date: Thu, 18 Jan 2018 10:22:14 +0100 Subject: [PATCH 028/144] version up --- CHANGELOG.md | 3 +++ codecov/__init__.py | 6 +++--- setup.py | 2 +- 3 files changed, 7 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 82f2d0f5..2cba7e63 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,6 @@ +### `2.0.14` +- fixed coverage combine + ### `2.0.13` - fix encoding issues diff --git a/codecov/__init__.py b/codecov/__init__.py index a7e681f9..a430d77a 100644 --- a/codecov/__init__.py +++ b/codecov/__init__.py @@ -30,7 +30,7 @@ pass -version = VERSION = __version__ = '2.0.13' +version = VERSION = __version__ = '2.0.14' COLOR = True @@ -659,8 +659,8 @@ def main(*argv, **kwargs): # Ran from current directory if glob.glob(opj(os.getcwd(), '.coverage.*')): write(' Mergeing coverage reports') - # The `-a` option is mandatory here. If we - # have a `.coverage` in the current directory, calling + # The `-a` option is mandatory here. If we + # have a `.coverage` in the current directory, calling # without the option would delete the previous data try_to_run('coverage combine -a') diff --git a/setup.py b/setup.py index 62257cb2..e938d554 100644 --- a/setup.py +++ b/setup.py @@ -2,7 +2,7 @@ from setuptools import setup import sys -version = '2.0.13' +version = '2.0.14' classifiers = ["Development Status :: 5 - Production/Stable", "Environment :: Plugins", "Intended Audience :: Developers", From 0452255b1080186b8c4d8e8fc2ff4f0d560bb674 Mon Sep 17 00:00:00 2001 From: Steve Peak Date: Mon, 22 Jan 2018 12:41:07 +0100 Subject: [PATCH 029/144] prefix to help fix paths, codecov/support#472 --- codecov/__init__.py | 8 ++++++++ tests/test.py | 5 +++++ 2 files changed, 13 insertions(+) diff --git a/codecov/__init__.py b/codecov/__init__.py index a430d77a..8d328e71 100644 --- a/codecov/__init__.py +++ b/codecov/__init__.py @@ -223,6 +223,7 @@ def main(*argv, **kwargs): advanced.add_argument('-X', '--disable', nargs="*", default=[], help="Disable features. Accepting **search** to disable crawling through directories, **detect** to disable detecting CI provider, **gcov** disable gcov commands, `pycov` disables running python `coverage xml`, **fix** to disable report adjustments http://bit.ly/1O4eBpt") advanced.add_argument('--root', default=None, help="Project directory. Default: current direcory or provided in CI environment variables") advanced.add_argument('--commit', '-c', default=None, help="Commit SHA, set automatically") + advanced.add_argument('--prefix', '-P', default=None, help="Prefix network paths to help resolve paths: https://github.com/codecov/support/issues/472") advanced.add_argument('--branch', '-b', default=None, help="Branch name") advanced.add_argument('--build', default=None, help="Specify a custom build number to distinguish CI jobs, provided automatically for supported CI companies") advanced.add_argument('--pr', default=None, help="Specify a custom pr number, provided automatically for supported CI companies") @@ -563,6 +564,13 @@ def main(*argv, **kwargs): try_to_run('cd %s && hg locate' % root) or try_to_run('hg locate') or '').strip()) + if codecov.prefix: + prefix = codecov.prefix.strip('/') + toc = '{}/{}'.format( + prefix, + toc.replace('\n', '\n{}/'.format(prefix)) + ) + # Detect codecov.yml location yaml_location = re.search( r'\.?codecov\.ya?ml$', diff --git a/tests/test.py b/tests/test.py index ddf9c9f1..5d3f23e2 100644 --- a/tests/test.py +++ b/tests/test.py @@ -204,6 +204,11 @@ def test_disable_search(self): else: raise Exception("Did not raise AssertionError") + def test_prefix(self): + self.fake_report() + res = self.run_cli(prefix='/foo/bar/', dump=True, token='a', branch='b', commit='c') + assert '\nfoo/bar/.gitignore' in res['reports'] + def write_c(self): c = '\n'.join(('#include ', 'static int t = 1;' From 6591da4924850a61667993e4cd9c0c01a3e1d015 Mon Sep 17 00:00:00 2001 From: Steve Peak Date: Mon, 29 Jan 2018 16:51:22 +0100 Subject: [PATCH 030/144] add -X s3 to disable direct to s3 --- codecov/__init__.py | 85 ++++++++++++++++++++++++--------------------- 1 file changed, 45 insertions(+), 40 deletions(-) diff --git a/codecov/__init__.py b/codecov/__init__.py index 8d328e71..f1797922 100644 --- a/codecov/__init__.py +++ b/codecov/__init__.py @@ -716,46 +716,51 @@ def main(*argv, **kwargs): trys = 0 while trys < 3: trys += 1 - try: - write(' Pinging Codecov...') - res = requests.post('%s/upload/v4?%s' % (codecov.url, urlargs), - verify=codecov.cacert, - headers={'Accept': 'text/plain', - 'X-Reduced-Redundancy': 'false'}) - if res.status_code in (400, 406): - raise Exception(res.text) - - elif res.status_code < 500: - assert res.status_code == 200 - res = res.text.strip().split() - result, upload_url = res[0], res[1] - - # Handle reports encoding for Python 2 and 3 - if not isinstance(reports, bytes): - reports = reports.encode('utf-8') - - write(' Uploading to S3...') - s3 = requests.put(upload_url, data=reports, - headers={'Content-Type': 'text/plain', - 'x-amz-acl': 'public-read'}) - s3.raise_for_status() - assert s3.status_code == 200 - write(' ' + result) - break - - except AssertionError: - write(' Direct to s3 failed. Using backup v2 endpoint.') - write(' Uploading to Codecov...') - # just incase, try traditional upload - res = requests.post('%s/upload/v2?%s' % (codecov.url, urlargs), - verify=codecov.cacert, - data='\n'.join((reports, s3.reason if s3 else '', s3.text if s3 else '')), - headers={"Accept": "text/plain"}) - if res.status_code < 500: - write(' ' + res.text) - res.raise_for_status() - result = res.text - return + if 's3' not in codecov.disable: + try: + write(' Pinging Codecov...') + res = requests.post('%s/upload/v4?%s' % (codecov.url, urlargs), + verify=codecov.cacert, + headers={'Accept': 'text/plain', + 'X-Reduced-Redundancy': 'false'}) + if res.status_code in (400, 406): + raise Exception(res.text) + + elif res.status_code < 500: + assert res.status_code == 200 + res = res.text.strip().split() + result, upload_url = res[0], res[1] + + # Handle reports encoding for Python 2 and 3 + if not isinstance(reports, bytes): + reports = reports.encode('utf-8') + + write(' Uploading to S3...') + s3 = requests.put(upload_url, data=reports, + headers={'Content-Type': 'text/plain', + 'x-amz-acl': 'public-read'}) + s3.raise_for_status() + assert s3.status_code == 200 + write(' ' + result) + break + else: + # try again + continue + + except AssertionError: + write(' Direct to s3 failed. Using backup v2 endpoint.') + + write(' Uploading to Codecov...') + # just incase, try traditional upload + res = requests.post('%s/upload/v2?%s' % (codecov.url, urlargs), + verify=codecov.cacert, + data='\n'.join((reports, s3.reason if s3 else '', s3.text if s3 else '')), + headers={"Accept": "text/plain"}) + if res.status_code < 500: + write(' ' + res.text) + res.raise_for_status() + result = res.text + return write(' Retrying... in %ds' % (trys * 30)) sleep(trys * 30) From 0743daa83647f12ff31b84d07113d2c24c27b924 Mon Sep 17 00:00:00 2001 From: Steve Peak Date: Mon, 29 Jan 2018 16:52:17 +0100 Subject: [PATCH 031/144] v++ --- CHANGELOG.md | 3 +++ codecov/__init__.py | 2 +- setup.py | 2 +- 3 files changed, 5 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2cba7e63..1f869d2f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,6 @@ +### `2.0.15` +- add `-X s3` to disable direct to S3 uploading + ### `2.0.14` - fixed coverage combine diff --git a/codecov/__init__.py b/codecov/__init__.py index f1797922..82e12136 100644 --- a/codecov/__init__.py +++ b/codecov/__init__.py @@ -30,7 +30,7 @@ pass -version = VERSION = __version__ = '2.0.14' +version = VERSION = __version__ = '2.0.15' COLOR = True diff --git a/setup.py b/setup.py index e938d554..5e961aeb 100644 --- a/setup.py +++ b/setup.py @@ -2,7 +2,7 @@ from setuptools import setup import sys -version = '2.0.14' +version = '2.0.15' classifiers = ["Development Status :: 5 - Production/Stable", "Environment :: Plugins", "Intended Audience :: Developers", From fcdaa7b9f9d297133d80c9bf1e02bbb3dc9587f7 Mon Sep 17 00:00:00 2001 From: William Pennock Date: Tue, 27 Feb 2018 12:15:36 -0500 Subject: [PATCH 032/144] Update README.md I proposed putting brackets around "the-repository-upload-token", so that it would be clear to users that this is something they need to add. --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 59e03699..64846082 100644 --- a/README.md +++ b/README.md @@ -14,11 +14,11 @@ Find coverage reports for all the [languages below](#languages), gather them and ## Usage ```sh -pip install --user codecov && codecov -t the-repository-upload-token +pip install --user codecov && codecov -t ``` or ```sh -conda install -c conda-forge codecov && codecov -t the-repository-upload-token +conda install -c conda-forge codecov && codecov -t ``` > `--user` argument not needed for Python projects. [See example here](https://github.com/codecov/example-python). From c124f57d805e4936f8b07d6f4a9a2fb59ab9d88c Mon Sep 17 00:00:00 2001 From: Jimmy Wilson Date: Mon, 23 Apr 2018 15:58:46 -0500 Subject: [PATCH 033/144] Correct typo "Mergeing" -> "Merging" --- codecov/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/codecov/__init__.py b/codecov/__init__.py index 82e12136..ba8234b7 100644 --- a/codecov/__init__.py +++ b/codecov/__init__.py @@ -666,7 +666,7 @@ def main(*argv, **kwargs): # ----------------------------------------- # Ran from current directory if glob.glob(opj(os.getcwd(), '.coverage.*')): - write(' Mergeing coverage reports') + write(' Merging coverage reports') # The `-a` option is mandatory here. If we # have a `.coverage` in the current directory, calling # without the option would delete the previous data From dfe91486488572f9fc162ecaa7f7684212c3e838 Mon Sep 17 00:00:00 2001 From: Todd Date: Tue, 29 May 2018 12:31:49 -0400 Subject: [PATCH 034/144] Include license file and changelog in sdists Including a license file is very important for legal reasons. Including the changelog is helpful for users and downstream packagers. --- MANIFEST.in | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 MANIFEST.in diff --git a/MANIFEST.in b/MANIFEST.in new file mode 100644 index 00000000..21e9b214 --- /dev/null +++ b/MANIFEST.in @@ -0,0 +1,2 @@ +include CHANGELOG.md +include LICENSE From 331d4af160749785b578359ef29e3cec922aa35d Mon Sep 17 00:00:00 2001 From: Oliver Bestwalter Date: Sun, 3 Jun 2018 00:20:14 +0200 Subject: [PATCH 035/144] CODECOV_ env need to be in tox passenv From https://github.com/tox-dev/tox-travis/issues/106 it became clear that the lack of explicit mention in passenv is confusing to the user. They might think that `CODECOV_*` env vars are automatically passed through. As tox only passes through the absolute minimum necessary `CODECOV_*` has to be added to passenv also. --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 59e03699..d74ba55a 100644 --- a/README.md +++ b/README.md @@ -35,7 +35,7 @@ Just please make sure to pass all the necessary environment variables through: ``` [testenv] -passenv = TOXENV CI TRAVIS TRAVIS_* +passenv = TOXENV CI TRAVIS TRAVIS_* CODECOV_* deps = codecov>=1.4.0 commands = codecov -e TOXENV ``` From 63afb8417d822c7d5722969e67985e1d7759503f Mon Sep 17 00:00:00 2001 From: Daniel Moody Date: Mon, 14 Jan 2019 12:05:58 -0600 Subject: [PATCH 036/144] update to support Appveyor Ubuntu image, which has lower case 'true's in the environment variable strings --- codecov/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/codecov/__init__.py b/codecov/__init__.py index 82e12136..c476da66 100644 --- a/codecov/__init__.py +++ b/codecov/__init__.py @@ -405,7 +405,7 @@ def main(*argv, **kwargs): # -------- # AppVeyor # -------- - elif os.getenv('CI') == "True" and os.getenv('APPVEYOR') == 'True': + elif os.getenv('CI').lower() == "true" and os.getenv('APPVEYOR').lower() == 'true': # http://www.appveyor.com/docs/environment-variables query.update(dict(branch=os.getenv('APPVEYOR_REPO_BRANCH'), service="appveyor", From e19da89a0db82e179ae658a20d15aeda08dd342a Mon Sep 17 00:00:00 2001 From: Daniel Moody Date: Mon, 14 Jan 2019 13:50:12 -0600 Subject: [PATCH 037/144] handle the case the env variable is not present and make sure we don't call lower on NoneType --- codecov/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/codecov/__init__.py b/codecov/__init__.py index c476da66..1ec0261c 100644 --- a/codecov/__init__.py +++ b/codecov/__init__.py @@ -405,7 +405,7 @@ def main(*argv, **kwargs): # -------- # AppVeyor # -------- - elif os.getenv('CI').lower() == "true" and os.getenv('APPVEYOR').lower() == 'true': + elif os.getenv('CI', 'false').lower() == 'true' and os.getenv('APPVEYOR', 'false').lower() == 'true': # http://www.appveyor.com/docs/environment-variables query.update(dict(branch=os.getenv('APPVEYOR_REPO_BRANCH'), service="appveyor", From a6f411280df50f0f3e715bb858105d9e830e7f25 Mon Sep 17 00:00:00 2001 From: Thomas Hu Date: Sat, 19 Jan 2019 12:37:10 -0500 Subject: [PATCH 038/144] Pin pytest to 3.6.0 to work with pytest-cov --- tests/requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/requirements.txt b/tests/requirements.txt index 7a8e6842..0571ca62 100644 --- a/tests/requirements.txt +++ b/tests/requirements.txt @@ -1,7 +1,7 @@ coverage ddt mock -pytest +pytest>=3.6.0 pytest-cov funcsigs requests From ad4cc424e354661b3569ae87bc64e998bda4be0a Mon Sep 17 00:00:00 2001 From: Thomas Hu Date: Sat, 19 Jan 2019 12:44:59 -0500 Subject: [PATCH 039/144] Upgrade coverage to 4.4.0 --- tests/requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/requirements.txt b/tests/requirements.txt index 0571ca62..1c022ee8 100644 --- a/tests/requirements.txt +++ b/tests/requirements.txt @@ -1,4 +1,4 @@ -coverage +coverage>=4.4.0 ddt mock pytest>=3.6.0 From 939643497009251bb1f768537eee5a2ce551d2f9 Mon Sep 17 00:00:00 2001 From: Thomas Hu Date: Tue, 22 Jan 2019 17:22:18 -0500 Subject: [PATCH 040/144] Update copyright --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index d74ba55a..9571885a 100644 --- a/README.md +++ b/README.md @@ -102,4 +102,4 @@ after_success: ## Copyright -> Copyright 2014-2017 codecov +> Copyright 2014-2019 codecov From 9b24833a51e30dc9b3dcf70637fafa9294f4865a Mon Sep 17 00:00:00 2001 From: Thomas Hu Date: Tue, 22 Jan 2019 17:50:21 -0500 Subject: [PATCH 041/144] Switch to ubuntu --- .gitignore | 1 + .travis.yml | 2 +- appveyor.yml | 2 ++ 3 files changed, 4 insertions(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index 79d2d87e..433e02bb 100644 --- a/.gitignore +++ b/.gitignore @@ -11,3 +11,4 @@ coverage.xml dist htmlcov venv +*.sw[op] diff --git a/.travis.yml b/.travis.yml index 4dc412bf..f802b33d 100644 --- a/.travis.yml +++ b/.travis.yml @@ -7,7 +7,7 @@ python: - pypy - 3.4 - 3.5 - - 3.6 + - 3.6 - pypy3 matrix: include: diff --git a/appveyor.yml b/appveyor.yml index a4c6b26e..3bda77c7 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -1,3 +1,5 @@ +image: ubuntu + environment: global: APPVEYOR_PYTHON_URL: "https://raw.githubusercontent.com/ogrisel/python-appveyor-demo/master/appveyor/" From b6b52828f82c1f7dd8ab676116ad6d42b94b2516 Mon Sep 17 00:00:00 2001 From: Thomas Hu Date: Tue, 22 Jan 2019 23:24:02 -0500 Subject: [PATCH 042/144] Skip failing AppVeyor test due to file path issue on Windows --- appveyor.yml | 2 -- tests/test.py | 1 + 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/appveyor.yml b/appveyor.yml index 3bda77c7..a4c6b26e 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -1,5 +1,3 @@ -image: ubuntu - environment: global: APPVEYOR_PYTHON_URL: "https://raw.githubusercontent.com/ogrisel/python-appveyor-demo/master/appveyor/" diff --git a/tests/test.py b/tests/test.py index 5d3f23e2..67a1de98 100644 --- a/tests/test.py +++ b/tests/test.py @@ -204,6 +204,7 @@ def test_disable_search(self): else: raise Exception("Did not raise AssertionError") + @unittest.skipIf(os.getenv('CI') == "True" and os.getenv('APPVEYOR') == 'True', 'Skip AppVeyor CI test') def test_prefix(self): self.fake_report() res = self.run_cli(prefix='/foo/bar/', dump=True, token='a', branch='b', commit='c') From 483b9a4331aa03d0eb43ad6ad5b05b984ffdc5b3 Mon Sep 17 00:00:00 2001 From: Thomas Hu Date: Tue, 22 Jan 2019 23:31:31 -0500 Subject: [PATCH 043/144] Remove deprecated python versions and add new ones --- appveyor.yml | 30 ++++++++++++++++-------------- 1 file changed, 16 insertions(+), 14 deletions(-) diff --git a/appveyor.yml b/appveyor.yml index a4c6b26e..88cac480 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -13,35 +13,37 @@ environment: # a later point release. - PYTHON: "C:\\Python27" - PYTHON_VERSION: "2.7.x" # currently 2.7.9 + PYTHON_VERSION: "2.7.x" # currently 2.7.15 PYTHON_ARCH: "32" - PYTHON: "C:\\Python27-x64" - PYTHON_VERSION: "2.7.x" # currently 2.7.9 + PYTHON_VERSION: "2.7.x" # currently 2.7.15 PYTHON_ARCH: "64" - - PYTHON: "C:\\Python33" - PYTHON_VERSION: "3.3.x" # currently 3.3.5 + - PYTHON: "C:\\Python34" + PYTHON_VERSION: "3.4.x" # currently 3.4.4 PYTHON_ARCH: "32" - - PYTHON: "C:\\Python33-x64" - PYTHON_VERSION: "3.3.x" # currently 3.3.5 + - PYTHON: "C:\\Python34-x64" + PYTHON_VERSION: "3.4.x" # currently 3.4.4 PYTHON_ARCH: "64" - - PYTHON: "C:\\Python34" - PYTHON_VERSION: "3.4.x" # currently 3.4.3 + - PYTHON: "C:\\Python36" + PYTHON_VERSION: "3.6.x" # currently 3.6.6 PYTHON_ARCH: "32" - - PYTHON: "C:\\Python34-x64" - PYTHON_VERSION: "3.4.x" # currently 3.4.3 + - PYTHON: "C:\\Python36-x64" + PYTHON_VERSION: "3.6.x" # currently 3.6.6 PYTHON_ARCH: "64" - # Also test Python 2.6.6 not pre-installed - - - PYTHON: "C:\\Python266" - PYTHON_VERSION: "2.6.6" + - PYTHON: "C:\\Python37" + PYTHON_VERSION: "3.7.x" # currently 3.7.1 PYTHON_ARCH: "32" + - PYTHON: "C:\\Python37-x64" + PYTHON_VERSION: "3.7.x" # currently 3.7.1 + PYTHON_ARCH: "64" + install: # Download the Appveyor Python build accessories into subdirectory .\appveyor - mkdir appveyor From 8d48369bc6229f6c40a0eaa3f096b21e8ee5cdfc Mon Sep 17 00:00:00 2001 From: Hugo Date: Mon, 4 Mar 2019 17:48:40 +0200 Subject: [PATCH 044/144] sudo no longer needed https://blog.travis-ci.com/2018-11-19-required-linux-infrastructure-migration --- .travis.yml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index 4dc412bf..a623178b 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,7 +1,7 @@ language: python notifications: email: false -sudo: false + python: - 2.7 - pypy @@ -13,7 +13,6 @@ matrix: include: - python: 2.7 dist: trusty - sudo: required virtualenv: system_site_packages: true addons: From 4b111c8bf5f6b358b6a4b5b0d53000be372779f9 Mon Sep 17 00:00:00 2001 From: Hugo Date: Mon, 4 Mar 2019 17:49:30 +0200 Subject: [PATCH 045/144] Drop the dot https://twitter.com/pytestdotorg/status/753767547866972160 --- .travis.yml | 2 +- tox.ini | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index a623178b..1f7b71d7 100644 --- a/.travis.yml +++ b/.travis.yml @@ -26,6 +26,6 @@ install: - pip install -r tests/requirements.txt - python setup.py install script: - - py.test tests/test.py --cov=codecov + - pytest tests/test.py --cov=codecov after_success: - codecov diff --git a/tox.ini b/tox.ini index 45fed510..c26c0ac7 100644 --- a/tox.ini +++ b/tox.ini @@ -5,4 +5,4 @@ envlist = py26, py27, py34 deps = -r{toxinidir}/tests/requirements.txt commands = - py.test tests/test.py + pytest tests/test.py From bd4822464a92158425ebfa17ed130bc685ebac8d Mon Sep 17 00:00:00 2001 From: Hugo Date: Mon, 4 Mar 2019 17:52:10 +0200 Subject: [PATCH 046/144] Add support for Python 3.7 --- .travis.yml | 2 ++ setup.py | 4 ++++ 2 files changed, 6 insertions(+) diff --git a/.travis.yml b/.travis.yml index 1f7b71d7..e24be156 100644 --- a/.travis.yml +++ b/.travis.yml @@ -21,6 +21,8 @@ matrix: - python-requests - python-coverage - python-mock + - python: 3.7 + dist: xenial install: - pip install -r tests/requirements.txt diff --git a/setup.py b/setup.py index 5e961aeb..ead3e934 100644 --- a/setup.py +++ b/setup.py @@ -7,9 +7,13 @@ "Environment :: Plugins", "Intended Audience :: Developers", "Programming Language :: Python", + "Programming Language :: Python :: 2", "Programming Language :: Python :: 2.7", "Programming Language :: Python :: 3", "Programming Language :: Python :: 3.4", + "Programming Language :: Python :: 3.5", + "Programming Language :: Python :: 3.6", + "Programming Language :: Python :: 3.7", "Programming Language :: Python :: Implementation :: PyPy", "License :: OSI Approved :: Apache Software License", "Topic :: Software Development :: Testing"] From 976e9d595dc1fb516d1e006fe835e3f57e31637c Mon Sep 17 00:00:00 2001 From: Hugo Date: Mon, 4 Mar 2019 17:53:21 +0200 Subject: [PATCH 047/144] Cache pip files --- .travis.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.travis.yml b/.travis.yml index e24be156..a5f557aa 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,4 +1,5 @@ language: python +cache: pip notifications: email: false From cf4d43c853c2f2dc542736c3fde5bb8da718cdb5 Mon Sep 17 00:00:00 2001 From: Hugo Date: Mon, 4 Mar 2019 17:54:16 +0200 Subject: [PATCH 048/144] Add python_requires to help pip --- setup.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/setup.py b/setup.py index ead3e934..825ad589 100644 --- a/setup.py +++ b/setup.py @@ -38,4 +38,6 @@ zip_safe=True, install_requires=install_requires, tests_require=["unittest2"], - entry_points={'console_scripts': ['codecov=codecov:main']}) + entry_points={'console_scripts': ['codecov=codecov:main']}, + python_requires='>=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*', + ) From 71735221a19cac9cc5f76f5e28df528866e753d6 Mon Sep 17 00:00:00 2001 From: Hugo Date: Mon, 4 Mar 2019 18:08:40 +0200 Subject: [PATCH 049/144] Remove redundant code --- codecov/__init__.py | 8 ++------ setup.py | 9 +-------- tests/requirements.txt | 1 - tests/test.py | 2 +- tox.ini | 2 +- 5 files changed, 5 insertions(+), 17 deletions(-) diff --git a/codecov/__init__.py b/codecov/__init__.py index 39d9a980..ae805ed9 100644 --- a/codecov/__init__.py +++ b/codecov/__init__.py @@ -22,12 +22,8 @@ import subprocess # https://urllib3.readthedocs.org/en/latest/security.html#insecureplatformwarning -try: - import logging - logging.captureWarnings(True) -except: - # not py2.6 compatible - pass +import logging +logging.captureWarnings(True) version = VERSION = __version__ = '2.0.15' diff --git a/setup.py b/setup.py index 825ad589..24d7ee64 100644 --- a/setup.py +++ b/setup.py @@ -1,6 +1,5 @@ #!/usr/bin/env python from setuptools import setup -import sys version = '2.0.15' classifiers = ["Development Status :: 5 - Production/Stable", @@ -18,11 +17,6 @@ "License :: OSI Approved :: Apache Software License", "Topic :: Software Development :: Testing"] -if sys.version_info >= (2, 7): - install_requires = ["requests>=2.7.9", "coverage"] -else: - install_requires = ["requests>=2.7.9", "coverage", "argparse"] - setup(name='codecov', version=version, description="Hosted coverage reports for Github, Bitbucket and Gitlab", @@ -36,8 +30,7 @@ packages=['codecov'], include_package_data=True, zip_safe=True, - install_requires=install_requires, - tests_require=["unittest2"], + install_requires=["requests>=2.7.9", "coverage"], entry_points={'console_scripts': ['codecov=codecov:main']}, python_requires='>=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*', ) diff --git a/tests/requirements.txt b/tests/requirements.txt index 1c022ee8..62de37c5 100644 --- a/tests/requirements.txt +++ b/tests/requirements.txt @@ -5,4 +5,3 @@ pytest>=3.6.0 pytest-cov funcsigs requests -unittest2 diff --git a/tests/test.py b/tests/test.py index 5d3f23e2..39bb59b2 100644 --- a/tests/test.py +++ b/tests/test.py @@ -4,7 +4,7 @@ import itertools from ddt import ddt, data from mock import patch, Mock -import unittest2 as unittest +import unittest import subprocess diff --git a/tox.ini b/tox.ini index c26c0ac7..84880fa6 100644 --- a/tox.ini +++ b/tox.ini @@ -1,5 +1,5 @@ [tox] -envlist = py26, py27, py34 +envlist = py27, py34, py35, py36, py37 [testenv] deps = From 684ab7f8a3d99b671826ce87b2bf2618f9ece338 Mon Sep 17 00:00:00 2001 From: Hugo Date: Mon, 4 Mar 2019 18:14:52 +0200 Subject: [PATCH 050/144] Fix GitHub typo --- CHANGELOG.md | 2 +- setup.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1f869d2f..f7a85fc1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -127,7 +127,7 @@ ### `1.1.5` - search for all `lcov|gcov` files -- depreciate `--min-coverage`, use Github Status Update feature +- depreciate `--min-coverage`, use GitHub Status Update feature - pre-process xml => json ### `1.1.4` diff --git a/setup.py b/setup.py index 24d7ee64..115e7c93 100644 --- a/setup.py +++ b/setup.py @@ -19,7 +19,7 @@ setup(name='codecov', version=version, - description="Hosted coverage reports for Github, Bitbucket and Gitlab", + description="Hosted coverage reports for GitHub, Bitbucket and Gitlab", long_description=None, classifiers=classifiers, keywords='coverage codecov code python java scala php', From a4d620be54e68ec7b63f5f4e2ef915f62f1c294e Mon Sep 17 00:00:00 2001 From: Hugo Date: Mon, 4 Mar 2019 18:24:10 +0200 Subject: [PATCH 051/144] Use HTTPS --- README.md | 10 +++++----- setup.py | 2 +- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index 86eb0dd3..dbf2ddf1 100644 --- a/README.md +++ b/README.md @@ -76,19 +76,19 @@ after_success: ## CI Providers | Company | Supported | Token Required | | --------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------- | -| [Travis CI](https://travis-ci.org/) | Yes [![Build Status](https://secure.travis-ci.org/codecov/codecov-python.svg?branch=master)](http://travis-ci.org/codecov/codecov-python) | Private only | +| [Travis CI](https://travis-ci.org/) | Yes [![Build Status](https://secure.travis-ci.org/codecov/codecov-python.svg?branch=master)](https://travis-ci.org/codecov/codecov-python) | Private only | | [CircleCI](https://circleci.com/) | Yes | Private only | | [Codeship](https://codeship.com/) | Yes | Public & Private | | [Jenkins](https://jenkins-ci.org/) | Yes | Public & Private | | [Semaphore](https://semaphoreci.com/) | Yes | Public & Private | | [Drone.io](https://drone.io/) | Yes | Public & Private | -| [AppVeyor](http://www.appveyor.com/) | Yes [![Build status](https://ci.appveyor.com/api/projects/status/sw18lsj7786bw806/branch/master?svg=true)](https://ci.appveyor.com/project/stevepeak/codecov-python/branch/master) | Private only | +| [AppVeyor](https://www.appveyor.com/) | Yes [![Build status](https://ci.appveyor.com/api/projects/status/sw18lsj7786bw806/branch/master?svg=true)](https://ci.appveyor.com/project/stevepeak/codecov-python/branch/master) | Private only | | [Wercker](http://wercker.com/) | Yes | Public & Private | | [Magnum CI](https://magnum-ci.com/) | Yes | Public & Private | -| [Shippable](http://www.shippable.com/) | Yes | Public & Private | +| [Shippable](https://www.shippable.com/) | Yes | Public & Private | | [Gitlab CI](https://about.gitlab.com/gitlab-ci/) | Yes | Public & Private | -| git / mercurial | Yes (as a fallback) | Public & Private | -| [Buildbot](http://buildbot.net/) | `coming soon` [buildbot/buildbot#1671](https://github.com/buildbot/buildbot/pull/1671) | | +| Git / Mercurial | Yes (as a fallback) | Public & Private | +| [Buildbot](https://buildbot.net/) | `coming soon` [buildbot/buildbot#1671](https://github.com/buildbot/buildbot/pull/1671) | | | [Bamboo](https://www.atlassian.com/software/bamboo) | `coming soon` | | | [Solano Labs](https://www.solanolabs.com/) | `coming soon` | | diff --git a/setup.py b/setup.py index 115e7c93..639e7464 100644 --- a/setup.py +++ b/setup.py @@ -25,7 +25,7 @@ keywords='coverage codecov code python java scala php', author='@codecov', author_email='hello@codecov.io', - url='http://github.com/codecov/codecov-python', + url='https://github.com/codecov/codecov-python', license='http://www.apache.org/licenses/LICENSE-2.0', packages=['codecov'], include_package_data=True, From 6ad9b73bbf7f8b6d27df8b898986b878760157fe Mon Sep 17 00:00:00 2001 From: Hugo Date: Mon, 4 Mar 2019 18:24:29 +0200 Subject: [PATCH 052/144] Remove redundant note: sudo no longer required on Travis CI --- README.md | 1 - 1 file changed, 1 deletion(-) diff --git a/README.md b/README.md index dbf2ddf1..122997e2 100644 --- a/README.md +++ b/README.md @@ -92,7 +92,6 @@ after_success: | [Bamboo](https://www.atlassian.com/software/bamboo) | `coming soon` | | | [Solano Labs](https://www.solanolabs.com/) | `coming soon` | | -> Using **Travis CI**? Uploader is compatible with `sudo: false` which can speed up your builds. :+1: From ea42cea17859849c5dd6986bb651e9f18d70fa4f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?G=C3=A1bor=20Lipt=C3=A1k?= Date: Wed, 22 May 2019 21:01:20 -0400 Subject: [PATCH 053/144] Add Python 3.7 to Travis MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Gábor Lipták --- .travis.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.travis.yml b/.travis.yml index f802b33d..e9b2db75 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,6 +1,8 @@ + language: python notifications: email: false +dist: xenial sudo: false python: - 2.7 @@ -8,6 +10,7 @@ python: - 3.4 - 3.5 - 3.6 + - 3.7 - pypy3 matrix: include: From 3113225fa7446e211c518ce74bcb67449c76f239 Mon Sep 17 00:00:00 2001 From: Thomas Kluyver Date: Mon, 3 Jun 2019 21:37:34 +0100 Subject: [PATCH 054/144] Better error message when try_to_run command fails The `CalledProcessError` object should always have a `.output` attribute, although it may be None, so the `getattr()` will never hit the fallback condition. The logical `or` operator should use the fallback if `e.output` is either None or an empty string, because those are both false-y. Any other possible value will be shown. --- codecov/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/codecov/__init__.py b/codecov/__init__.py index 39d9a980..1dfa9ead 100644 --- a/codecov/__init__.py +++ b/codecov/__init__.py @@ -181,7 +181,7 @@ def try_to_run(cmd): try: return check_output(cmd, shell=True) except subprocess.CalledProcessError as e: - write(' Error running `%s`: %s' % (cmd, str(getattr(e, 'output', str(e))))) + write(' Error running `%s`: %s' % (cmd, e.output or str(e))) def remove_non_ascii(data): From 8660351ee9aeada349e1d6566e9021be5cf377cf Mon Sep 17 00:00:00 2001 From: Thomas Kluyver Date: Mon, 3 Jun 2019 21:48:52 +0100 Subject: [PATCH 055/144] Run Python 'coverage' tool as a module if possible This means coverage can still be called to convert its data to XML even if it's not on PATH. Closes #71. --- codecov/__init__.py | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/codecov/__init__.py b/codecov/__init__.py index 39d9a980..6fd9f197 100644 --- a/codecov/__init__.py +++ b/codecov/__init__.py @@ -183,6 +183,20 @@ def try_to_run(cmd): except subprocess.CalledProcessError as e: write(' Error running `%s`: %s' % (cmd, str(getattr(e, 'output', str(e))))) +def run_python_coverage(args): + """Run the Python coverage tool + + If it's importable in this Python, launch it using 'python -m'. + Otherwise, look it up on PATH like any other command. + """ + try: + import coverage + except ImportError: + # Coverage is not installed on this Python. Hope it's on PATH. + try_to_run(['coverage'] + args) + else: + # Coverage is installed on this Python. Run it as a module. + try_to_run([sys.executable, '-m', 'coverage'] + args) def remove_non_ascii(data): try: @@ -670,12 +684,12 @@ def main(*argv, **kwargs): # The `-a` option is mandatory here. If we # have a `.coverage` in the current directory, calling # without the option would delete the previous data - try_to_run('coverage combine -a') + run_python_coverage(['combine', '-a']) if os.path.exists(opj(os.getcwd(), '.coverage')) and not os.path.exists(opj(os.getcwd(), 'coverage.xml')): write(' Generating coverage xml reports for Python') # using `-i` to ignore "No source for code" error - try_to_run('coverage xml -i') + run_python_coverage(['xml', '-i']) reports.append(read(opj(os.getcwd(), 'coverage.xml'))) reports = list(filter(bool, reports)) From 39331a6afba5a7fe178e92145dcefe7a647ebfad Mon Sep 17 00:00:00 2001 From: Thomas Kluyver Date: Mon, 3 Jun 2019 22:04:23 +0100 Subject: [PATCH 056/144] Run Python coverage tool with shell=False --- codecov/__init__.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/codecov/__init__.py b/codecov/__init__.py index 6fd9f197..c1edd19a 100644 --- a/codecov/__init__.py +++ b/codecov/__init__.py @@ -177,9 +177,9 @@ def check_output(cmd, **popen_args): return output.decode('utf-8') -def try_to_run(cmd): +def try_to_run(cmd, shell=True): try: - return check_output(cmd, shell=True) + return check_output(cmd, shell=shell) except subprocess.CalledProcessError as e: write(' Error running `%s`: %s' % (cmd, str(getattr(e, 'output', str(e))))) @@ -193,10 +193,10 @@ def run_python_coverage(args): import coverage except ImportError: # Coverage is not installed on this Python. Hope it's on PATH. - try_to_run(['coverage'] + args) + try_to_run(['coverage'] + args, shell=False) else: # Coverage is installed on this Python. Run it as a module. - try_to_run([sys.executable, '-m', 'coverage'] + args) + try_to_run([sys.executable, '-m', 'coverage'] + args, shell=False) def remove_non_ascii(data): try: From 80a3fcc7d578d4624c2fc9210b10c14d8fb2ddde Mon Sep 17 00:00:00 2001 From: Ryan Ly Date: Tue, 12 Nov 2019 14:54:22 -0800 Subject: [PATCH 057/144] Fix broken bitly link in help --- codecov/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/codecov/__init__.py b/codecov/__init__.py index ea12bf53..6b3205c3 100644 --- a/codecov/__init__.py +++ b/codecov/__init__.py @@ -230,7 +230,7 @@ def main(*argv, **kwargs): gcov.add_argument('--gcov-args', default='', help="extra arguments to pass to gcov") advanced = parser.add_argument_group('======================== Advanced ========================') - advanced.add_argument('-X', '--disable', nargs="*", default=[], help="Disable features. Accepting **search** to disable crawling through directories, **detect** to disable detecting CI provider, **gcov** disable gcov commands, `pycov` disables running python `coverage xml`, **fix** to disable report adjustments http://bit.ly/1O4eBpt") + advanced.add_argument('-X', '--disable', nargs="*", default=[], help="Disable features. Accepting **search** to disable crawling through directories, **detect** to disable detecting CI provider, **gcov** disable gcov commands, `pycov` disables running python `coverage xml`, **fix** to disable report adjustments https://docs.codecov.io/docs/fixing-reports") advanced.add_argument('--root', default=None, help="Project directory. Default: current direcory or provided in CI environment variables") advanced.add_argument('--commit', '-c', default=None, help="Commit SHA, set automatically") advanced.add_argument('--prefix', '-P', default=None, help="Prefix network paths to help resolve paths: https://github.com/codecov/support/issues/472") From 2a80aa434f74feb31242b6f213b75ce63ae97902 Mon Sep 17 00:00:00 2001 From: Joe Becher Date: Wed, 19 Feb 2020 09:36:10 -0500 Subject: [PATCH 058/144] CE-1380_sanitize_args --- codecov/__init__.py | 10 +++++++--- tests/test.py | 3 +++ 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/codecov/__init__.py b/codecov/__init__.py index 6b3205c3..40ba7a73 100644 --- a/codecov/__init__.py +++ b/codecov/__init__.py @@ -34,6 +34,10 @@ remove_token = re.compile(r'token=[^\&]+').sub +def sanitize_arg(replacement, arg): + return re.sub(r'[\&]+', replacement, arg, 0, re.MULTILINE) + + ignored_path = re.compile(r'(/vendor)|' r'(/js/generated/coverage)|' r'(/__pycache__)|' @@ -624,11 +628,11 @@ def main(*argv, **kwargs): ) write('==> Processing gcov (disable by -X gcov)') cmd = "find %s %s -type f -name '*.gcno' %s -exec %s -pb %s {} +" % ( - (codecov.gcov_root or root), + (sanitize_arg('', codecov.gcov_root or root)), dont_search_here, " ".join(map(lambda a: "-not -path '%s'" % a, codecov.gcov_glob)), - (codecov.gcov_exec or ''), - (codecov.gcov_args or '')) + (sanitize_arg('', codecov.gcov_exec or '')), + (sanitize_arg('', codecov.gcov_args or ''))) write(' Executing gcov (%s)' % cmd) try_to_run(cmd) diff --git a/tests/test.py b/tests/test.py index ed640c6e..cf001d61 100644 --- a/tests/test.py +++ b/tests/test.py @@ -315,6 +315,9 @@ def test_none_found(self): else: raise Exception("Did not raise AssertionError") + def test_sanitize_arg(self): + self.assertEqual(codecov.sanitize_arg('', '& echo test > vuln1.txt'), ' echo test > vuln1.txt') + @unittest.skipUnless(os.getenv('JENKINS_URL'), 'Skip Jenkins CI test') def test_ci_jenkins(self): self.set_env(BUILD_URL='https://....', From 3a8b06b2c7de69bfa6a7fa8eb2517df558b39342 Mon Sep 17 00:00:00 2001 From: Joe Becher Date: Mon, 24 Feb 2020 13:26:08 -0500 Subject: [PATCH 059/144] Version 2.0.16 --- CHANGELOG.md | 3 +++ setup.py | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f7a85fc1..a7c25289 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,6 @@ +### `2.0.16` +- fixed reported command injection vulnerability. + ### `2.0.15` - add `-X s3` to disable direct to S3 uploading diff --git a/setup.py b/setup.py index 639e7464..2800c7b1 100644 --- a/setup.py +++ b/setup.py @@ -1,7 +1,7 @@ #!/usr/bin/env python from setuptools import setup -version = '2.0.15' +version = '2.0.16' classifiers = ["Development Status :: 5 - Production/Stable", "Environment :: Plugins", "Intended Audience :: Developers", From 9f50cca7e5c5e0bb5e2859db238da08e3195e105 Mon Sep 17 00:00:00 2001 From: Joe Becher Date: Wed, 11 Mar 2020 09:40:14 -0400 Subject: [PATCH 060/144] shell=False Changing shell=False and setting the popen args to a list, instead of a string disables shell injection as reported in CE-1479 --- CHANGELOG.md | 36 ++++++++ codecov/__init__.py | 194 ++++++++++++++++++++++++++++---------------- setup.py | 2 +- 3 files changed, 162 insertions(+), 70 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a7c25289..ab426da7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,19 +1,29 @@ +### `2.0.17` + +- fixed reported command injection vulnerability. + ### `2.0.16` + - fixed reported command injection vulnerability. ### `2.0.15` + - add `-X s3` to disable direct to S3 uploading ### `2.0.14` + - fixed coverage combine ### `2.0.13` + - fix encoding issues ### `2.0.12` + - revert merge commit fix, back to old way ### `2.0.11` + - fix merge commit when it's a pull request - remove snapci, business closed - skip vendor directories for gcov parsing @@ -21,10 +31,12 @@ - fix report encoding ### `2.0.10` + - fix uploading when reports contain characters outside of latin-1 - remove reduced_redundancy header from ### `2.0.7` + - Add `--name/-n` to cli - Add support for Jenkins Blue - Fix environment variable joining @@ -36,12 +48,15 @@ - Support yaml:token and yaml:slug ### `2.0.5` + - Use `%20` for encoding spaces [appveyor] https://github.com/codecov/codecov-python/pull/66 ### `2.0.4` + - fix detecting merge commits on all CI, not just Travis ### `2.0.3` + - add `-F` to flagging uploads [new feature] - fixed some reports ascii chars - added `--pr` flag for manually specifing pulls @@ -55,17 +70,20 @@ - hide token from stdout ### `1.6.4` + - fix gitlab project directory - fallback on git branch/commit - fix using gcov_exec ### `1.6.0` + - depreciate `--no-fail` now a default - add `--required` to fail the build if Codecov fails - added `--cacerts` for enterprise customers - added fix reports http://bit.ly/1O4eBpt ### `1.5.0` + - fix retreiving mercurial commit - add support for swift/xcode7 profdata - now uploading direct-to-s3 to improve product performance @@ -73,9 +91,11 @@ - fix drone.io commit number, which is not a full 40 sha. ### `1.4.1` + - added `--no-fail` to prevent failing builds when missing configuration or Codecov errors ### `1.4.0` + - Ignore other known bad files/paths - Added test suite to test against example repositories - Using `coverage xml -i` to ignore No source for code errors @@ -83,36 +103,45 @@ - Added `gcov` processing, see `codecov --help` for more info. ### `1.3.1` + - Ignore other known bad files/paths - Fix issue with decoding files in py3+ ### `1.3.0` + - Refactor project to be a global uploader for more reports ### `1.2.3` + - Remove `test-results.xml`, not a coverage file - Add CircleCI container numbers ### `1.2.2` + - bring back client-side pre-processing for jacoco (they can crush) ### `1.2.1` + - accept any file ending in `coverge.xml` ### `1.2.0` + - accept `nosetests.xml` and `test-results.xml` files - no longer do client side pre-processing, upload raw - capture SEMAPHORE_CURRENT_THREAD ### `1.1.13` + - added --build arg for advanced usage ### `1.1.10` + - fix package for 2.6 on windows - fix showing `--help` when called in non-git backed repo - fix AppVeyor public repos ### `1.1.8` + - support GitLab CI Runner - added rollbar to help bugs if presented - added more filepath matching @@ -120,32 +149,39 @@ - added Shippable ci ### `1.1.7` + - support for D lang added, special thanks to @ColdenCullen - Wercker CI supported by @Robpol86 - fixed Drone build number ### `1.1.6` + - fix semaphore commit revision number - preprocess reports from xml ### `1.1.5` + - search for all `lcov|gcov` files - depreciate `--min-coverage`, use GitHub Status Update feature - pre-process xml => json ### `1.1.4` + - added support for pyhton 2.6 by @Robpol86 - added AppVeyor support by @Robpol86 ### `1.1.3` + - added more ignore paths ### `1.1.2` + - search for `lcov.info` files - pause for `.1` before checking for min-coverage - accept `--env` variables which are stored in front-end for build specs ### `1.1.1` + - build python coverage xml only when no reports found to fix overriding reports - now defaulting output to **plain text**. Use `--json` to return json results - added `jacocoTestReport.xml` to search list diff --git a/codecov/__init__.py b/codecov/__init__.py index 40ba7a73..84715907 100644 --- a/codecov/__init__.py +++ b/codecov/__init__.py @@ -16,7 +16,7 @@ try: from shlex import quote -except ImportError: # pragma: no cover +except ImportError: # pragma: no cover from pipes import quote import subprocess @@ -26,7 +26,7 @@ logging.captureWarnings(True) -version = VERSION = __version__ = '2.0.15' +version = VERSION = __version__ = '2.0.17' COLOR = True @@ -34,6 +34,7 @@ remove_token = re.compile(r'token=[^\&]+').sub + def sanitize_arg(replacement, arg): return re.sub(r'[\&]+', replacement, arg, 0, re.MULTILINE) @@ -177,15 +178,16 @@ def check_output(cmd, **popen_args): return output.decode('utf-8') -def try_to_run(cmd, shell=True): +def try_to_run(cmd, shell=False): try: return check_output(cmd, shell=shell) except subprocess.CalledProcessError as e: write(' Error running `%s`: %s' % (cmd, e.output or str(e))) + def run_python_coverage(args): """Run the Python coverage tool - + If it's importable in this Python, launch it using 'python -m'. Otherwise, look it up on PATH like any other command. """ @@ -198,6 +200,7 @@ def run_python_coverage(args): # Coverage is installed on this Python. Run it as a module. try_to_run([sys.executable, '-m', 'coverage'] + args, shell=False) + def remove_non_ascii(data): try: return data.decode('utf8') + '' @@ -218,40 +221,67 @@ def main(*argv, **kwargs): parser = argparse.ArgumentParser(prog='codecov', add_help=True, formatter_class=argparse.RawDescriptionHelpFormatter, epilog="""Upload reports to Codecov""") - basics = parser.add_argument_group('======================== Basics ========================') - basics.add_argument('--version', action='version', version='Codecov py-v'+version+" - https://codecov.io/") - basics.add_argument('--token', '-t', default=os.getenv("CODECOV_TOKEN"), help="Private repository token or @filename for file containing the token. Defaults to $CODECOV_TOKEN. Not required for public repositories on Travis CI, CircleCI and AppVeyor") - basics.add_argument('--file', '-f', nargs="*", default=None, help="Target a specific file for uploading") - basics.add_argument('--flags', '-F', nargs="*", default=None, help="Flag these uploaded files with custom labels") - basics.add_argument('--env', '-e', nargs="*", default=None, help="Store environment variables to help distinguish CI builds.") - basics.add_argument('--required', action="store_true", default=False, help="If Codecov fails it will exit 1 - possibly failing the CI build.") - basics.add_argument('--name', '-n', default=None, help="Custom defined name of the upload. Visible in Codecov UI.") - - gcov = parser.add_argument_group('======================== gcov ========================') - gcov.add_argument('--gcov-root', default=None, help="Project root directory when preparing gcov") - gcov.add_argument('--gcov-glob', nargs="*", default=[], help="Paths to ignore during gcov gathering") - gcov.add_argument('--gcov-exec', default='gcov', help="gcov executable to run. Defaults to 'gcov'") - gcov.add_argument('--gcov-args', default='', help="extra arguments to pass to gcov") - - advanced = parser.add_argument_group('======================== Advanced ========================') + basics = parser.add_argument_group( + '======================== Basics ========================') + basics.add_argument('--version', action='version', + version='Codecov py-v'+version+" - https://codecov.io/") + basics.add_argument('--token', '-t', default=os.getenv("CODECOV_TOKEN"), + help="Private repository token or @filename for file containing the token. Defaults to $CODECOV_TOKEN. Not required for public repositories on Travis CI, CircleCI and AppVeyor") + basics.add_argument('--file', '-f', nargs="*", default=None, + help="Target a specific file for uploading") + basics.add_argument('--flags', '-F', nargs="*", default=None, + help="Flag these uploaded files with custom labels") + basics.add_argument('--env', '-e', nargs="*", default=None, + help="Store environment variables to help distinguish CI builds.") + basics.add_argument('--required', action="store_true", default=False, + help="If Codecov fails it will exit 1 - possibly failing the CI build.") + basics.add_argument('--name', '-n', default=None, + help="Custom defined name of the upload. Visible in Codecov UI.") + + gcov = parser.add_argument_group( + '======================== gcov ========================') + gcov.add_argument('--gcov-root', default=None, + help="Project root directory when preparing gcov") + gcov.add_argument('--gcov-glob', nargs="*", default=[], + help="Paths to ignore during gcov gathering") + gcov.add_argument('--gcov-exec', default='gcov', + help="gcov executable to run. Defaults to 'gcov'") + gcov.add_argument('--gcov-args', default='', + help="extra arguments to pass to gcov") + + advanced = parser.add_argument_group( + '======================== Advanced ========================') advanced.add_argument('-X', '--disable', nargs="*", default=[], help="Disable features. Accepting **search** to disable crawling through directories, **detect** to disable detecting CI provider, **gcov** disable gcov commands, `pycov` disables running python `coverage xml`, **fix** to disable report adjustments https://docs.codecov.io/docs/fixing-reports") - advanced.add_argument('--root', default=None, help="Project directory. Default: current direcory or provided in CI environment variables") - advanced.add_argument('--commit', '-c', default=None, help="Commit SHA, set automatically") - advanced.add_argument('--prefix', '-P', default=None, help="Prefix network paths to help resolve paths: https://github.com/codecov/support/issues/472") + advanced.add_argument('--root', default=None, + help="Project directory. Default: current direcory or provided in CI environment variables") + advanced.add_argument('--commit', '-c', default=None, + help="Commit SHA, set automatically") + advanced.add_argument('--prefix', '-P', default=None, + help="Prefix network paths to help resolve paths: https://github.com/codecov/support/issues/472") advanced.add_argument('--branch', '-b', default=None, help="Branch name") - advanced.add_argument('--build', default=None, help="Specify a custom build number to distinguish CI jobs, provided automatically for supported CI companies") - advanced.add_argument('--pr', default=None, help="Specify a custom pr number, provided automatically for supported CI companies") + advanced.add_argument('--build', default=None, + help="Specify a custom build number to distinguish CI jobs, provided automatically for supported CI companies") + advanced.add_argument( + '--pr', default=None, help="Specify a custom pr number, provided automatically for supported CI companies") advanced.add_argument('--tag', default=None, help="Git tag") - enterprise = parser.add_argument_group('======================== Enterprise ========================') - enterprise.add_argument('--slug', '-r', default=os.getenv("CODECOV_SLUG"), help="Specify repository slug for Enterprise ex. owner/repo") - enterprise.add_argument('--url', '-u', default=os.getenv("CODECOV_URL", "https://codecov.io"), help="Your Codecov endpoint") - enterprise.add_argument('--cacert', default=os.getenv("CODECOV_CACERT", os.getenv("CURL_CA_BUNDLE")), help="Certificate pem bundle used to verify with your Codecov instance") - - debugging = parser.add_argument_group('======================== Debugging ========================') - debugging.add_argument('--dump', action="store_true", help="Dump collected data and do not send to Codecov") - debugging.add_argument('-v', '--verbose', action="store_true", help="Be verbose, e.g. dump the collected data") - debugging.add_argument('--no-color', action="store_true", help="Do not output with color") + enterprise = parser.add_argument_group( + '======================== Enterprise ========================') + enterprise.add_argument('--slug', '-r', default=os.getenv("CODECOV_SLUG"), + help="Specify repository slug for Enterprise ex. owner/repo") + enterprise.add_argument('--url', '-u', default=os.getenv("CODECOV_URL", + "https://codecov.io"), help="Your Codecov endpoint") + enterprise.add_argument('--cacert', default=os.getenv("CODECOV_CACERT", os.getenv( + "CURL_CA_BUNDLE")), help="Certificate pem bundle used to verify with your Codecov instance") + + debugging = parser.add_argument_group( + '======================== Debugging ========================') + debugging.add_argument('--dump', action="store_true", + help="Dump collected data and do not send to Codecov") + debugging.add_argument('-v', '--verbose', action="store_true", + help="Be verbose, e.g. dump the collected data") + debugging.add_argument('--no-color', action="store_true", + help="Do not output with color") # Parse Arguments # --------------- @@ -300,8 +330,10 @@ def main(*argv, **kwargs): # https://wiki.jenkins-ci.org/display/JENKINS/GitHub+pull+request+builder+plugin#GitHubpullrequestbuilderplugin-EnvironmentVariables query.update(dict(branch=os.getenv('ghprbSourceBranch') or os.getenv('GIT_BRANCH') or os.getenv('BRANCH_NAME'), service='jenkins', - commit=os.getenv('ghprbActualCommit') or os.getenv('GIT_COMMIT'), - pr=os.getenv('ghprbPullId') or os.getenv('CHANGE_ID'), + commit=os.getenv('ghprbActualCommit') or os.getenv( + 'GIT_COMMIT'), + pr=os.getenv('ghprbPullId') or os.getenv( + 'CHANGE_ID'), build=os.getenv('BUILD_NUMBER'), build_url=os.getenv('BUILD_URL'))) root = os.getenv('WORKSPACE') or root @@ -328,7 +360,8 @@ def main(*argv, **kwargs): _add_env_if_not_empty(include_env, 'TRAVIS_OS_NAME') if language: - _add_env_if_not_empty(include_env, 'TRAVIS_%s_VERSION' % language.upper()) + _add_env_if_not_empty( + include_env, 'TRAVIS_%s_VERSION' % language.upper()) # -------- # Codeship @@ -349,7 +382,8 @@ def main(*argv, **kwargs): # https://buildkite.com/docs/guides/environment-variables query.update(dict(branch=os.getenv('BUILDKITE_BRANCH'), service='buildkite', - build=os.getenv('BUILDKITE_BUILD_NUMBER') + '.' + os.getenv('BUILDKITE_JOB_ID'), + build=os.getenv( + 'BUILDKITE_BUILD_NUMBER') + '.' + os.getenv('BUILDKITE_JOB_ID'), slug=os.getenv('BUILDKITE_PROJECT_SLUG'), build_url=os.getenv('BUILDKITE_BUILD_URL'), commit=os.getenv('BUILDKITE_COMMIT'))) @@ -362,10 +396,13 @@ def main(*argv, **kwargs): # https://circleci.com/docs/environment-variables query.update(dict(branch=os.getenv('CIRCLE_BRANCH'), service='circleci', - build=os.getenv('CIRCLE_BUILD_NUM') + "." + os.getenv('CIRCLE_NODE_INDEX'), - job=os.getenv('CIRCLE_BUILD_NUM') + "." + os.getenv('CIRCLE_NODE_INDEX'), + build=os.getenv('CIRCLE_BUILD_NUM') + + "." + os.getenv('CIRCLE_NODE_INDEX'), + job=os.getenv('CIRCLE_BUILD_NUM') + + "." + os.getenv('CIRCLE_NODE_INDEX'), pr=os.getenv('CIRCLE_PR_NUMBER'), - slug=os.getenv('CIRCLE_PROJECT_USERNAME') + "/" + os.getenv('CIRCLE_PROJECT_REPONAME'), + slug=os.getenv('CIRCLE_PROJECT_USERNAME') + + "/" + os.getenv('CIRCLE_PROJECT_REPONAME'), commit=os.getenv('CIRCLE_SHA1'))) write(' Circle CI Detected') @@ -376,7 +413,8 @@ def main(*argv, **kwargs): # https://semaphoreapp.com/docs/available-environment-variables.html query.update(dict(branch=os.getenv('BRANCH_NAME'), service='semaphore', - build=os.getenv('SEMAPHORE_BUILD_NUMBER') + '.' + os.getenv('SEMAPHORE_CURRENT_THREAD'), + build=os.getenv( + 'SEMAPHORE_BUILD_NUMBER') + '.' + os.getenv('SEMAPHORE_CURRENT_THREAD'), slug=os.getenv('SEMAPHORE_REPO_SLUG'), commit=os.getenv('REVISION'))) write(' Semaphore Detected') @@ -423,7 +461,8 @@ def main(*argv, **kwargs): # http://www.appveyor.com/docs/environment-variables query.update(dict(branch=os.getenv('APPVEYOR_REPO_BRANCH'), service="appveyor", - job='/'.join((os.getenv('APPVEYOR_ACCOUNT_NAME'), os.getenv('APPVEYOR_PROJECT_SLUG'), os.getenv('APPVEYOR_BUILD_VERSION'))), + job='/'.join((os.getenv('APPVEYOR_ACCOUNT_NAME'), os.getenv( + 'APPVEYOR_PROJECT_SLUG'), os.getenv('APPVEYOR_BUILD_VERSION'))), build=os.getenv('APPVEYOR_JOB_ID'), pr=os.getenv('APPVEYOR_PULL_REQUEST_NUMBER'), slug=os.getenv('APPVEYOR_REPO_NAME'), @@ -439,7 +478,8 @@ def main(*argv, **kwargs): query.update(dict(branch=os.getenv('WERCKER_GIT_BRANCH'), service="wercker", build=os.getenv('WERCKER_MAIN_PIPELINE_STARTED'), - slug=os.getenv('WERCKER_GIT_OWNER') + '/' + os.getenv('WERCKER_GIT_REPOSITORY'), + slug=os.getenv('WERCKER_GIT_OWNER') + '/' + + os.getenv('WERCKER_GIT_REPOSITORY'), commit=os.getenv('WERCKER_GIT_COMMIT'))) write(' Wercker Detected') @@ -481,12 +521,15 @@ def main(*argv, **kwargs): if os.getenv('CI_PROJECT_DIR', '').startswith('/'): root = os.getenv('CI_PROJECT_DIR') else: - root = os.getenv('HOME') + '/' + os.getenv('CI_PROJECT_DIR', '') + root = os.getenv('HOME') + '/' + \ + os.getenv('CI_PROJECT_DIR', '') if os.getenv('CI_BUILD_REPO'): - query['slug'] = os.getenv('CI_BUILD_REPO').split('/', 3)[-1].replace('.git', '') + query['slug'] = os.getenv('CI_BUILD_REPO').split( + '/', 3)[-1].replace('.git', '') elif os.getenv('CI_REPOSITORY_URL'): - query['slug'] = os.getenv('CI_REPOSITORY_URL').split('/', 3)[-1].replace('.git', '') + query['slug'] = os.getenv('CI_REPOSITORY_URL').split( + '/', 3)[-1].replace('.git', '') write(' Gitlab CI Detected') @@ -504,7 +547,8 @@ def main(*argv, **kwargs): if not query.get('branch'): try: # find branch, commit, repo from git command - branch = try_to_run('git rev-parse --abbrev-ref HEAD || hg branch') + branch = try_to_run( + 'git rev-parse --abbrev-ref HEAD || hg branch') query['branch'] = branch if branch != 'HEAD' else '' write(' -> Got branch from git/hg') @@ -513,7 +557,8 @@ def main(*argv, **kwargs): if not query.get('commit'): try: - query['commit'] = try_to_run("git rev-parse HEAD || hg id -i --debug | tr -d '+'") + query['commit'] = try_to_run( + "git rev-parse HEAD || hg id -i --debug | tr -d '+'") write(' -> Got sha from git/hg') except: # pragma: no cover @@ -567,16 +612,18 @@ def main(*argv, **kwargs): # -------------------- if query.get('token') and query.get('token')[0] == '@': write(' Reading token from file') - query['token'] = fopen(opj(os.getcwd(), query['token'][1:])).strip() + query['token'] = fopen( + opj(os.getcwd(), query['token'][1:])).strip() - assert query.get('commit') not in ('', None), "Commit sha is missing. Please specify via --commit=:sha" + assert query.get('commit') not in ( + '', None), "Commit sha is missing. Please specify via --commit=:sha" # Build TOC # --------- - toc = str((try_to_run('cd %s && git ls-files' % root) or - try_to_run('git ls-files') or - try_to_run('cd %s && hg locate' % root) or - try_to_run('hg locate') or '').strip()) + toc = str((try_to_run(['cd', root, '&&', 'git', 'ls-files']) or + try_to_run(['git', 'ls-files']) or + try_to_run(['cd', root, '&&', 'hg', 'locate']) or + try_to_run(['hg', 'locate']) or ['']).strip()) if codecov.prefix: prefix = codecov.prefix.strip('/') @@ -613,7 +660,8 @@ def main(*argv, **kwargs): if _slug: query['slug'] = _slug.groups()[1] - assert query.get('job') or query.get('token'), "Missing repository upload token" + assert query.get('job') or query.get( + 'token'), "Missing repository upload token" # Processing gcov # --------------- @@ -627,12 +675,13 @@ def main(*argv, **kwargs): "-not -path './vendor/**'" ) write('==> Processing gcov (disable by -X gcov)') - cmd = "find %s %s -type f -name '*.gcno' %s -exec %s -pb %s {} +" % ( - (sanitize_arg('', codecov.gcov_root or root)), - dont_search_here, - " ".join(map(lambda a: "-not -path '%s'" % a, codecov.gcov_glob)), - (sanitize_arg('', codecov.gcov_exec or '')), - (sanitize_arg('', codecov.gcov_args or ''))) + cmd = ['find', + (sanitize_arg('', codecov.gcov_root or root)), dont_search_here, + '-type', 'f', '-name', '*.gcno', " ".join(map(lambda a: "-not -path '%s'" % + a, codecov.gcov_glob)), + '-exec', (sanitize_arg('', + codecov.gcov_exec or '')), + '-pb', (sanitize_arg('', codecov.gcov_args or '')), '{}', '+'] write(' Executing gcov (%s)' % cmd) try_to_run(cmd) @@ -652,7 +701,9 @@ def main(*argv, **kwargs): if os.path.exists(bowerrc): write(' Detecting .bowerrc file') try: - bower_components = '/' + (loads(fopen(bowerrc)).get('directory') or 'bower_components').replace('./', '').strip('/') + bower_components = '/' + \ + (loads(fopen(bowerrc)).get('directory') + or 'bower_components').replace('./', '').strip('/') write(' .bowerrc detected, ignoring ' + bower_components) except Exception as e: write(' .bowerrc parsing error: ' + str(e)) @@ -704,7 +755,8 @@ def main(*argv, **kwargs): if k: write(' + ' + k) - env = '\n'.join(["%s=%s" % (k, os.getenv(k, '')) for k in include_env if k]) + '\n<<<<<< ENV' + env = '\n'.join(["%s=%s" % (k, os.getenv(k, '')) + for k in include_env if k]) + '\n<<<<<< ENV' # join reports together reports = '\n'.join((env, (toc or ''), '<<<<<< network', @@ -712,7 +764,8 @@ def main(*argv, **kwargs): '<<<<<< EOF')) query['package'] = "py" + VERSION - urlargs = (urlencode(dict([(k, v.strip()) for k, v in query.items() if v not in ('', None)]))).replace("+", "%20") + urlargs = (urlencode(dict([(k, v.strip()) for k, v in query.items( + ) if v not in ('', None)]))).replace("+", "%20") result = '' if codecov.dump: @@ -772,8 +825,9 @@ def main(*argv, **kwargs): # just incase, try traditional upload res = requests.post('%s/upload/v2?%s' % (codecov.url, urlargs), verify=codecov.cacert, - data='\n'.join((reports, s3.reason if s3 else '', s3.text if s3 else '')), - headers={"Accept": "text/plain"}) + data='\n'.join( + (reports, s3.reason if s3 else '', s3.text if s3 else '')), + headers={"Accept": "text/plain"}) if res.status_code < 500: write(' ' + res.text) res.raise_for_status() @@ -791,9 +845,11 @@ def main(*argv, **kwargs): write('') # detect language if language: - write('Tip: See an example %s repo: https://github.com/codecov/example-%s' % (language, language)) + write('Tip: See an example %s repo: https://github.com/codecov/example-%s' % + (language, language)) else: - write('Tip: See all example repositories: https://github.com/codecov?query=example') + write( + 'Tip: See all example repositories: https://github.com/codecov?query=example') write('Support channels:', 'green') write(' Email: hello@codecov.io\n' diff --git a/setup.py b/setup.py index 2800c7b1..de428b17 100644 --- a/setup.py +++ b/setup.py @@ -1,7 +1,7 @@ #!/usr/bin/env python from setuptools import setup -version = '2.0.16' +version = '2.0.17' classifiers = ["Development Status :: 5 - Production/Stable", "Environment :: Plugins", "Intended Audience :: Developers", From 6cd43174832a97f57b31c0cd2df79ff724c3a59a Mon Sep 17 00:00:00 2001 From: Joe Becher Date: Wed, 11 Mar 2020 09:56:20 -0400 Subject: [PATCH 061/144] Test with no cache --- .travis.yml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index 69ab3c78..eec31089 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,6 +1,5 @@ - language: python -cache: pip +# cache: pip notifications: email: false dist: xenial From 6b74ecf3c7ce6dcbb80e11fd3709a40178d60012 Mon Sep 17 00:00:00 2001 From: Joe Becher Date: Wed, 11 Mar 2020 09:59:49 -0400 Subject: [PATCH 062/144] adding some debug commands --- .travis.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.travis.yml b/.travis.yml index eec31089..5fc409ce 100644 --- a/.travis.yml +++ b/.travis.yml @@ -31,6 +31,9 @@ install: - pip install -r tests/requirements.txt - python setup.py install script: + - ls + - pwd + - cd $(pwd) - pytest tests/test.py --cov=codecov after_success: - codecov From 8dd5720b8e9b8514fe91e2a01207e9264cfdd339 Mon Sep 17 00:00:00 2001 From: Joe Becher Date: Wed, 11 Mar 2020 10:02:17 -0400 Subject: [PATCH 063/144] try to run failing command manually --- .travis.yml | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/.travis.yml b/.travis.yml index 5fc409ce..b577552b 100644 --- a/.travis.yml +++ b/.travis.yml @@ -31,9 +31,7 @@ install: - pip install -r tests/requirements.txt - python setup.py install script: - - ls - - pwd - - cd $(pwd) + - cd $(pwd) && git ls-files - pytest tests/test.py --cov=codecov after_success: - codecov From cb647931255bed37440c3562624857077ac347c5 Mon Sep 17 00:00:00 2001 From: Joe Becher Date: Wed, 11 Mar 2020 10:10:06 -0400 Subject: [PATCH 064/144] Checking tests --- .travis.yml | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index b577552b..28c4c162 100644 --- a/.travis.yml +++ b/.travis.yml @@ -31,7 +31,8 @@ install: - pip install -r tests/requirements.txt - python setup.py install script: - - cd $(pwd) && git ls-files - - pytest tests/test.py --cov=codecov + - make reinstall + - make test + # - pytest tests/test.py --cov=codecov after_success: - codecov From 6fe18b3d2ec35f4201b887d3f3932ef519908d7b Mon Sep 17 00:00:00 2001 From: Joe Becher Date: Wed, 11 Mar 2020 10:33:35 -0400 Subject: [PATCH 065/144] convery remaining args to list --- codecov/__init__.py | 6 +-- tests/test.py | 102 +++++++++++++++++++++++++++++--------------- 2 files changed, 71 insertions(+), 37 deletions(-) diff --git a/codecov/__init__.py b/codecov/__init__.py index 84715907..eb5ef045 100644 --- a/codecov/__init__.py +++ b/codecov/__init__.py @@ -548,7 +548,7 @@ def main(*argv, **kwargs): try: # find branch, commit, repo from git command branch = try_to_run( - 'git rev-parse --abbrev-ref HEAD || hg branch') + ['git', 'rev-parse', '--abbrev-ref', 'HEAD', '||', 'hg branch']) query['branch'] = branch if branch != 'HEAD' else '' write(' -> Got branch from git/hg') @@ -558,7 +558,7 @@ def main(*argv, **kwargs): if not query.get('commit'): try: query['commit'] = try_to_run( - "git rev-parse HEAD || hg id -i --debug | tr -d '+'") + ["git", "rev-parse", "HEAD", "||", "hg", "id", "-i", "--debug", "|", "tr", "-d", "'+'"]) write(' -> Got sha from git/hg') except: # pragma: no cover @@ -584,7 +584,7 @@ def main(*argv, **kwargs): elif query['pr'] and query['pr'] != 'false': # Merge Commits # ------------- - res = try_to_run('git log -1 --pretty=%B') + res = try_to_run(['git', 'log', '-1', '--pretty=%B']) if res and is_merge_commit.match(res.strip()): query['commit'] = res.split(' ')[1] write(' Fixing merge commit SHA') diff --git a/tests/test.py b/tests/test.py index cf001d61..1b64215b 100644 --- a/tests/test.py +++ b/tests/test.py @@ -50,14 +50,16 @@ def setUp(self): def tearDown(self): self.delete(self.filepath, self.coverage, self.jacoco, self.bowerrc) - self.delete('hello', 'hello.c', 'hello.gcda', 'hello.c.gcov', 'hello.gcno') + self.delete('hello', 'hello.c', 'hello.gcda', + 'hello.c.gcov', 'hello.gcno') def set_env(self, **kwargs): for key in kwargs: os.environ[key] = str(kwargs[key]) def run_cli(self, dump=True, *args, **kwargs): - inline = list(itertools.chain(*[['--%s' % key, str(value)] for key, value in kwargs.items() if value])) + inline = list(itertools.chain( + *[['--%s' % key, str(value)] for key, value in kwargs.items() if value])) if dump: inline.append('--dump') inline.extend(args) @@ -78,21 +80,26 @@ def delete(self, *paths): @data('vendor', 'node_modules', 'js/generated/coverage', '__pycache__', 'coverage/instrumented', 'build/lib', 'htmlcov', '.egg-info', '.git', '.tox', 'venv', '.venv-python-2.7') def test_ignored_path(self, path): - self.assertTrue(bool(codecov.ignored_path('/home/ubuntu/' + path)), path + ' should be ignored') - self.assertTrue(bool(codecov.ignored_path('/home/ubuntu/' + path + '/more paths')), path + ' should be ignored') + self.assertTrue(bool(codecov.ignored_path( + '/home/ubuntu/' + path)), path + ' should be ignored') + self.assertTrue(bool(codecov.ignored_path( + '/home/ubuntu/' + path + '/more paths')), path + ' should be ignored') @data('coverage.xml', 'jacoco.xml', 'jacocoTestResults.xml', 'coverage.txt', 'gcov.lst', 'cov.gcov', 'info.lcov', 'clover.xml', 'cobertura.xml', 'luacov.report.out', 'gcov.info', 'nosetests.xml') def test_is_report(self, path): - self.assertFalse(bool(codecov.ignored_report('/home/file/' + path)), path + ' should not be ignored') - self.assertTrue(bool(codecov.is_report('/home/file/' + path)), path + ' should be a report') + self.assertFalse(bool(codecov.ignored_report( + '/home/file/' + path)), path + ' should not be ignored') + self.assertTrue(bool(codecov.is_report( + '/home/file/' + path)), path + ' should be a report') @data('.coverage.worker10', 'coverage.jade', 'include.lst', 'inputFiles.lst', 'createdFiles.lst', 'scoverage.measurements.blackandwhite.xml', 'test_hello_coverage.txt', 'conftest_blackwhite.c.gcov') def test_ignore_report(self, path): - self.assertTrue(bool(codecov.ignored_report('/home/file/' + path)), path + ' should be ignored') + self.assertTrue(bool(codecov.ignored_report( + '/home/file/' + path)), path + ' should be ignored') def test_command(self): try: @@ -142,13 +149,16 @@ def test_send(self): put.return_value = Mock(status_code=200) with open(self.filepath, 'w+') as f: f.write('coverage data') - res = self.run_cli(False, commit='a'*40, branch='master', token='') + res = self.run_cli(False, commit='a'*40, + branch='master', token='') self.assertEqual(res['result'].strip(), 'target') assert 'https://codecov.io/upload/v4?' in post.call_args[0][0] - assert 'commit=aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa' in post.call_args[0][0] + assert 'commit=aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa' in post.call_args[ + 0][0] assert 'token=%3Ctoken%3E' in post.call_args[0][0] assert 'branch=master' in post.call_args[0][0] - assert u'tests/test.py'.encode("utf-8") in put.call_args[1]['data'] + assert u'tests/test.py'.encode( + "utf-8") in put.call_args[1]['data'] def test_send_error(self): with patch('requests.post') as post: @@ -156,7 +166,8 @@ def test_send_error(self): with open(self.filepath, 'w+') as f: f.write('coverage data') try: - self.run_cli(False, token='not-a-token', commit='a'*40, branch='master') + self.run_cli(False, token='not-a-token', + commit='a'*40, branch='master') except Exception: pass else: @@ -207,7 +218,8 @@ def test_disable_search(self): @unittest.skipIf(os.getenv('CI') == "True" and os.getenv('APPVEYOR') == 'True', 'Skip AppVeyor CI test') def test_prefix(self): self.fake_report() - res = self.run_cli(prefix='/foo/bar/', dump=True, token='a', branch='b', commit='c') + res = self.run_cli(prefix='/foo/bar/', dump=True, + token='a', branch='b', commit='c') assert '\nfoo/bar/.gitignore' in res['reports'] def write_c(self): @@ -219,7 +231,8 @@ def write_c(self): 'return 0;', '}')) with open(os.path.join(os.path.dirname(__file__), '../hello.c'), 'w+') as f: f.write(c) - codecov.try_to_run('clang -coverage -O0 hello.c -o hello && ./hello') + codecov.try_to_run(['clang', '-coverage', '-O0', + 'hello.c', '-o', 'hello', '&&', './hello']) def test_disable_gcov(self): if self._env.get('TRAVIS') == 'true': @@ -246,12 +259,14 @@ def test_gcov(self): # self.skipTest("Skipped, works on Travis only.") def test_disable_detect(self): - self.set_env(JENKINS_URL='a', GIT_BRANCH='b', GIT_COMMIT='c', CODECOV_TOKEN='d') + self.set_env(JENKINS_URL='a', GIT_BRANCH='b', + GIT_COMMIT='c', CODECOV_TOKEN='d') self.fake_report() try: self.run_cli(disable='detect') except AssertionError as e: - self.assertEqual(str(e), "Commit sha is missing. Please specify via --commit=:sha") + self.assertEqual( + str(e), "Commit sha is missing. Please specify via --commit=:sha") else: raise Exception("Did not raise AssertionError") @@ -316,7 +331,8 @@ def test_none_found(self): raise Exception("Did not raise AssertionError") def test_sanitize_arg(self): - self.assertEqual(codecov.sanitize_arg('', '& echo test > vuln1.txt'), ' echo test > vuln1.txt') + self.assertEqual(codecov.sanitize_arg( + '', '& echo test > vuln1.txt'), ' echo test > vuln1.txt') @unittest.skipUnless(os.getenv('JENKINS_URL'), 'Skip Jenkins CI test') def test_ci_jenkins(self): @@ -329,7 +345,8 @@ def test_ci_jenkins(self): self.fake_report() res = self.run_cli() self.assertEqual(res['query']['service'], 'jenkins') - self.assertEqual(res['query']['commit'], 'c739768fcac68144a3a6d82305b9c4106934d31a') + self.assertEqual(res['query']['commit'], + 'c739768fcac68144a3a6d82305b9c4106934d31a') self.assertEqual(res['query']['build'], '41') self.assertEqual(res['query']['build_url'], 'https://....') self.assertEqual(res['query']['pr'], '') @@ -348,7 +365,8 @@ def test_ci_jenkins_env(self): self.fake_report() res = self.run_cli() self.assertEqual(res['query']['service'], 'jenkins') - self.assertEqual(res['query']['commit'], 'c739768fcac68144a3a6d82305b9c4106934d31a') + self.assertEqual(res['query']['commit'], + 'c739768fcac68144a3a6d82305b9c4106934d31a') self.assertEqual(res['query']['build'], '41') self.assertEqual(res['query']['build_url'], 'https://....') self.assertEqual(res['query']['pr'], '1') @@ -366,7 +384,8 @@ def test_ci_jenkins_blue_ocean(self): self.fake_report() res = self.run_cli() self.assertEqual(res['query']['service'], 'jenkins') - self.assertEqual(res['query']['commit'], codecov.check_output(("git", "rev-parse", "HEAD"))) + self.assertEqual(res['query']['commit'], codecov.check_output( + ("git", "rev-parse", "HEAD"))) self.assertEqual(res['query']['build'], '41') self.assertEqual(res['query']['build_url'], 'https://....') self.assertEqual(res['query']['pr'], '1') @@ -388,7 +407,8 @@ def test_ci_travis(self): self.fake_report() res = self.run_cli() self.assertEqual(res['query']['service'], 'travis') - self.assertEqual(res['query']['commit'], 'c739768fcac68144a3a6d82305b9c4106934d31a') + self.assertEqual(res['query']['commit'], + 'c739768fcac68144a3a6d82305b9c4106934d31a') self.assertEqual(res['query']['build'], '4.1') self.assertEqual(res['query']['pr'], '') self.assertEqual(res['query']['tag'], 'v1.1.1') @@ -407,9 +427,11 @@ def test_ci_codeship(self): self.fake_report() res = self.run_cli() self.assertEqual(res['query']['service'], 'codeship') - self.assertEqual(res['query']['commit'], '743b04806ea677403aa2ff26c6bdeb85005de658') + self.assertEqual(res['query']['commit'], + '743b04806ea677403aa2ff26c6bdeb85005de658') self.assertEqual(res['query']['build'], '20') - self.assertEqual(res['query']['build_url'], 'https://codeship.io/build/1') + self.assertEqual(res['query']['build_url'], + 'https://codeship.io/build/1') self.assertEqual(res['query']['pr'], '') self.assertEqual(res['query']['branch'], 'master') self.assertEqual(res['codecov'].token, 'token') @@ -427,7 +449,8 @@ def test_ci_circleci(self): self.fake_report() res = self.run_cli() self.assertEqual(res['query']['service'], 'circleci') - self.assertEqual(res['query']['commit'], 'd653b934ed59c1a785cc1cc79d08c9aaa4eba73b') + self.assertEqual(res['query']['commit'], + 'd653b934ed59c1a785cc1cc79d08c9aaa4eba73b') self.assertEqual(res['query']['build'], '57.1') self.assertEqual(res['query']['pr'], '1') self.assertEqual(res['query']['slug'], 'owner/repo') @@ -446,7 +469,8 @@ def test_ci_buildkite(self): self.fake_report() res = self.run_cli() self.assertEqual(res['query']['service'], 'buildkite') - self.assertEqual(res['query']['commit'], 'd653b934ed59c1a785cc1cc79d08c9aaa4eba73b') + self.assertEqual(res['query']['commit'], + 'd653b934ed59c1a785cc1cc79d08c9aaa4eba73b') self.assertEqual(res['query']['build'], '57.1') self.assertEqual(res['query']['slug'], 'owner/repo') self.assertEqual(res['query']['branch'], 'master') @@ -464,7 +488,8 @@ def test_ci_semaphore(self): self.fake_report() res = self.run_cli() self.assertEqual(res['query']['service'], 'semaphore') - self.assertEqual(res['query']['commit'], '743b04806ea677403aa2ff26c6bdeb85005de658') + self.assertEqual(res['query']['commit'], + '743b04806ea677403aa2ff26c6bdeb85005de658') self.assertEqual(res['query']['build'], '10.1') self.assertEqual(res['query']['slug'], 'owner/repo') self.assertEqual(res['query']['branch'], 'master') @@ -480,9 +505,11 @@ def test_ci_drone(self): self.fake_report() res = self.run_cli() self.assertEqual(res['query']['service'], 'drone.io') - self.assertEqual(res['query']['commit'], codecov.check_output(("git", "rev-parse", "HEAD"))) + self.assertEqual(res['query']['commit'], codecov.check_output( + ("git", "rev-parse", "HEAD"))) self.assertEqual(res['query']['build'], '10') - self.assertEqual(res['query']['build_url'], 'https://drone.io/github/builds/1') + self.assertEqual(res['query']['build_url'], + 'https://drone.io/github/builds/1') self.assertEqual(res['codecov'].token, 'token') @unittest.skipUnless(os.getenv('SHIPPABLE') == "true", 'Skip Shippable CI test') @@ -497,10 +524,12 @@ def test_ci_shippable(self): self.fake_report() res = self.run_cli() self.assertEqual(res['query']['service'], 'shippable') - self.assertEqual(res['query']['commit'], '743b04806ea677403aa2ff26c6bdeb85005de658') + self.assertEqual(res['query']['commit'], + '743b04806ea677403aa2ff26c6bdeb85005de658') self.assertEqual(res['query']['build'], '10') self.assertEqual(res['query']['slug'], 'owner/repo') - self.assertEqual(res['query']['build_url'], 'https://shippable.com/...') + self.assertEqual(res['query']['build_url'], + 'https://shippable.com/...') self.assertEqual(res['codecov'].token, 'token') # @unittest.skipUnless(os.getenv('CI') == "True" and os.getenv('APPVEYOR') == 'True', 'Skip AppVeyor CI test') @@ -520,7 +549,8 @@ def test_ci_appveyor(self): self.fake_report() res = self.run_cli(file=self.filepath) self.assertEqual(res['query']['service'], 'appveyor') - self.assertEqual(res['query']['commit'], 'd653b934ed59c1a785cc1cc79d08c9aaa4eba73b') + self.assertEqual(res['query']['commit'], + 'd653b934ed59c1a785cc1cc79d08c9aaa4eba73b') self.assertEqual(res['query']['job'], 'owner/repo/1.2.3') self.assertEqual(res['query']['build'], '9r2qufuu8') self.assertEqual(res['query']['slug'], 'owner/repo') @@ -538,7 +568,8 @@ def test_ci_wercker(self): self.fake_report() res = self.run_cli() self.assertEqual(res['query']['service'], 'wercker') - self.assertEqual(res['query']['commit'], 'd653b934ed59c1a785cc1cc79d08c9aaa4eba73b') + self.assertEqual(res['query']['commit'], + 'd653b934ed59c1a785cc1cc79d08c9aaa4eba73b') self.assertEqual(res['query']['build'], '1399372237') self.assertEqual(res['query']['slug'], 'owner/repo') self.assertEqual(res['codecov'].token, 'token') @@ -554,7 +585,8 @@ def test_ci_magnum(self): self.fake_report() res = self.run_cli() self.assertEqual(res['query']['service'], 'magnum') - self.assertEqual(res['query']['commit'], 'd653b934ed59c1a785cc1cc79d08c9aaa4eba73b') + self.assertEqual(res['query']['commit'], + 'd653b934ed59c1a785cc1cc79d08c9aaa4eba73b') self.assertEqual(res['query']['build'], '1399372237') self.assertEqual(res['codecov'].token, 'token') @@ -571,7 +603,8 @@ def test_ci_gitlab(self): self.fake_report() res = self.run_cli() self.assertEqual(res['query']['service'], 'gitlab') - self.assertEqual(res['query']['commit'], 'd653b934ed59c1a785cc1cc79d08c9aaa4eba73b') + self.assertEqual(res['query']['commit'], + 'd653b934ed59c1a785cc1cc79d08c9aaa4eba73b') self.assertEqual(res['query']['build'], '1399372237') self.assertEqual(res['query']['slug'], 'owner/repo') self.assertEqual(res['codecov'].token, 'token') @@ -585,7 +618,8 @@ def test_ci_none(self): slug='owner/repo', token='token') self.assertEqual(res['query'].get('service'), None) - self.assertEqual(res['query']['commit'], 'd653b934ed59c1a785cc1cc79d08c9aaa4eba73b') + self.assertEqual(res['query']['commit'], + 'd653b934ed59c1a785cc1cc79d08c9aaa4eba73b') self.assertEqual(res['query']['build'], '10') self.assertEqual(res['query']['slug'], 'owner/repo') self.assertEqual(res['codecov'].token, 'token') From 0fdc00a9227b044c420e4917cec2d81ffb2840dd Mon Sep 17 00:00:00 2001 From: Joe Becher Date: Fri, 13 Mar 2020 09:11:26 -0400 Subject: [PATCH 066/144] move cd command to cwd --- codecov/__init__.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/codecov/__init__.py b/codecov/__init__.py index eb5ef045..a6720349 100644 --- a/codecov/__init__.py +++ b/codecov/__init__.py @@ -178,9 +178,9 @@ def check_output(cmd, **popen_args): return output.decode('utf-8') -def try_to_run(cmd, shell=False): +def try_to_run(cmd, shell=False, cwd=None): try: - return check_output(cmd, shell=shell) + return check_output(cmd, shell=shell, cwd=cwd) except subprocess.CalledProcessError as e: write(' Error running `%s`: %s' % (cmd, e.output or str(e))) @@ -620,9 +620,9 @@ def main(*argv, **kwargs): # Build TOC # --------- - toc = str((try_to_run(['cd', root, '&&', 'git', 'ls-files']) or + toc = str((try_to_run(['git', 'ls-files'], cwd=root) or try_to_run(['git', 'ls-files']) or - try_to_run(['cd', root, '&&', 'hg', 'locate']) or + try_to_run(['hg', 'locate'], cwd=root) or try_to_run(['hg', 'locate']) or ['']).strip()) if codecov.prefix: From c8622a40c5026f9dad12183d2b0e4e81f2e27045 Mon Sep 17 00:00:00 2001 From: Joe Becher Date: Tue, 17 Mar 2020 10:33:31 -0400 Subject: [PATCH 067/144] Update makefile so deploy works --- Makefile | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/Makefile b/Makefile index c59bacfa..cd09f059 100644 --- a/Makefile +++ b/Makefile @@ -1,7 +1,8 @@ deploy: - git tag -a v$(shell python -c "import codecov;print codecov.version;") -m "" - git push origin v$(shell python -c "import codecov;print codecov.version;") - python setup.py sdist bdist_wheel upload + git tag -a v$(python -c 'import codecov;print(codecov.version)') -m "" + git push origin v$(python -c 'import codecov;print(codecov.version)') + python setup.py sdist bdist_wheel + python -m twine upload dist/* reinstall: pip uninstall -y codecov From 2a1e0c8bd1bf84db42344f6ec091e963755a32e0 Mon Sep 17 00:00:00 2001 From: Joe Becher Date: Tue, 17 Mar 2020 14:06:57 -0400 Subject: [PATCH 068/144] fixed errors with or symbols --- codecov/__init__.py | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/codecov/__init__.py b/codecov/__init__.py index a6720349..bd941a09 100644 --- a/codecov/__init__.py +++ b/codecov/__init__.py @@ -547,8 +547,9 @@ def main(*argv, **kwargs): if not query.get('branch'): try: # find branch, commit, repo from git command - branch = try_to_run( - ['git', 'rev-parse', '--abbrev-ref', 'HEAD', '||', 'hg branch']) + branch = (try_to_run( + ['git', 'rev-parse', '--abbrev-ref', 'HEAD']) or try_to_run( + ['hg', 'branch'])) query['branch'] = branch if branch != 'HEAD' else '' write(' -> Got branch from git/hg') @@ -557,8 +558,9 @@ def main(*argv, **kwargs): if not query.get('commit'): try: - query['commit'] = try_to_run( - ["git", "rev-parse", "HEAD", "||", "hg", "id", "-i", "--debug", "|", "tr", "-d", "'+'"]) + query['commit'] = (try_to_run( + ['git', 'rev-parse', "HEAD"]) or try_to_run( + ["hg", "id", "-i", "--debug", '|', "tr", "-d", "'+'"])) write(' -> Got sha from git/hg') except: # pragma: no cover From b0e060e39065290acb6e119938a1436f11475f95 Mon Sep 17 00:00:00 2001 From: Joe Becher Date: Tue, 17 Mar 2020 14:17:15 -0400 Subject: [PATCH 069/144] 2.0.18 --- codecov/__init__.py | 2 +- setup.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/codecov/__init__.py b/codecov/__init__.py index bd941a09..ddc4f023 100644 --- a/codecov/__init__.py +++ b/codecov/__init__.py @@ -26,7 +26,7 @@ logging.captureWarnings(True) -version = VERSION = __version__ = '2.0.17' +version = VERSION = __version__ = '2.0.18' COLOR = True diff --git a/setup.py b/setup.py index de428b17..eab61de7 100644 --- a/setup.py +++ b/setup.py @@ -1,7 +1,7 @@ #!/usr/bin/env python from setuptools import setup -version = '2.0.17' +version = '2.0.18' classifiers = ["Development Status :: 5 - Production/Stable", "Environment :: Plugins", "Intended Audience :: Developers", From 213b8f187e4872f70826f3f5a5329a41ebbcdc73 Mon Sep 17 00:00:00 2001 From: Joe Becher Date: Tue, 17 Mar 2020 14:51:35 -0400 Subject: [PATCH 070/144] fix subprocess --- codecov/__init__.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/codecov/__init__.py b/codecov/__init__.py index ddc4f023..55f57182 100644 --- a/codecov/__init__.py +++ b/codecov/__init__.py @@ -181,8 +181,9 @@ def check_output(cmd, **popen_args): def try_to_run(cmd, shell=False, cwd=None): try: return check_output(cmd, shell=shell, cwd=cwd) - except subprocess.CalledProcessError as e: + except subprocess.CalledProcessError, FileNotFoundError as e: write(' Error running `%s`: %s' % (cmd, e.output or str(e))) + return None def run_python_coverage(args): From 7d782f3f716996951c2340eb49c5d2f3d57e09b1 Mon Sep 17 00:00:00 2001 From: Joe Becher Date: Tue, 17 Mar 2020 14:56:11 -0400 Subject: [PATCH 071/144] 2.0.19 --- CHANGELOG.md | 8 ++++++++ codecov/__init__.py | 2 +- setup.py | 2 +- 3 files changed, 10 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index ab426da7..698146bd 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,11 @@ +### `2.0.19` + +- fixed broken subprocess handling + +### `2.0.18` + +- fixed broken subprocess handling + ### `2.0.17` - fixed reported command injection vulnerability. diff --git a/codecov/__init__.py b/codecov/__init__.py index 55f57182..3ec86ef2 100644 --- a/codecov/__init__.py +++ b/codecov/__init__.py @@ -26,7 +26,7 @@ logging.captureWarnings(True) -version = VERSION = __version__ = '2.0.18' +version = VERSION = __version__ = '2.0.19' COLOR = True diff --git a/setup.py b/setup.py index eab61de7..1042d765 100644 --- a/setup.py +++ b/setup.py @@ -1,7 +1,7 @@ #!/usr/bin/env python from setuptools import setup -version = '2.0.18' +version = '2.0.19' classifiers = ["Development Status :: 5 - Production/Stable", "Environment :: Plugins", "Intended Audience :: Developers", From 95d0c545544febfa5066a4b05eb22ecfdc4b2aa3 Mon Sep 17 00:00:00 2001 From: Joe Becher Date: Tue, 17 Mar 2020 14:57:15 -0400 Subject: [PATCH 072/144] enclose --- codecov/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/codecov/__init__.py b/codecov/__init__.py index 3ec86ef2..bf3fb672 100644 --- a/codecov/__init__.py +++ b/codecov/__init__.py @@ -181,7 +181,7 @@ def check_output(cmd, **popen_args): def try_to_run(cmd, shell=False, cwd=None): try: return check_output(cmd, shell=shell, cwd=cwd) - except subprocess.CalledProcessError, FileNotFoundError as e: + except (subprocess.CalledProcessError, FileNotFoundError) as e: write(' Error running `%s`: %s' % (cmd, e.output or str(e))) return None From 38f2303e37f3dd65f27e9821eb692d889f40c3dd Mon Sep 17 00:00:00 2001 From: Joe Becher Date: Tue, 17 Mar 2020 14:59:38 -0400 Subject: [PATCH 073/144] Exception --- codecov/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/codecov/__init__.py b/codecov/__init__.py index bf3fb672..6797cccc 100644 --- a/codecov/__init__.py +++ b/codecov/__init__.py @@ -181,7 +181,7 @@ def check_output(cmd, **popen_args): def try_to_run(cmd, shell=False, cwd=None): try: return check_output(cmd, shell=shell, cwd=cwd) - except (subprocess.CalledProcessError, FileNotFoundError) as e: + except Exception as e: write(' Error running `%s`: %s' % (cmd, e.output or str(e))) return None From 47c8206551f2f2e25396b9da17b77bc2117ef507 Mon Sep 17 00:00:00 2001 From: Joe Becher Date: Tue, 17 Mar 2020 15:10:23 -0400 Subject: [PATCH 074/144] generic exception --- codecov/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/codecov/__init__.py b/codecov/__init__.py index 6797cccc..805ee644 100644 --- a/codecov/__init__.py +++ b/codecov/__init__.py @@ -182,7 +182,7 @@ def try_to_run(cmd, shell=False, cwd=None): try: return check_output(cmd, shell=shell, cwd=cwd) except Exception as e: - write(' Error running `%s`: %s' % (cmd, e.output or str(e))) + write(' Error running `%s`: %s' % (cmd, e or str(e))) return None From 3ad07c2353a917687bf04f951986c206a0ff1a11 Mon Sep 17 00:00:00 2001 From: Joe Becher Date: Tue, 17 Mar 2020 15:15:48 -0400 Subject: [PATCH 075/144] bump version --- CHANGELOG.md | 4 ++++ codecov/__init__.py | 2 +- setup.py | 2 +- 3 files changed, 6 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 698146bd..88e8f477 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,7 @@ +### `2.0.20` + +- fixed broken subprocess handling# + ### `2.0.19` - fixed broken subprocess handling diff --git a/codecov/__init__.py b/codecov/__init__.py index 805ee644..41cac1ce 100644 --- a/codecov/__init__.py +++ b/codecov/__init__.py @@ -26,7 +26,7 @@ logging.captureWarnings(True) -version = VERSION = __version__ = '2.0.19' +version = VERSION = __version__ = '2.0.20' COLOR = True diff --git a/setup.py b/setup.py index 1042d765..0dc9aa35 100644 --- a/setup.py +++ b/setup.py @@ -1,7 +1,7 @@ #!/usr/bin/env python from setuptools import setup -version = '2.0.19' +version = '2.0.20' classifiers = ["Development Status :: 5 - Production/Stable", "Environment :: Plugins", "Intended Audience :: Developers", From 93c990310fd5abab0649430759b7a24ad64ef839 Mon Sep 17 00:00:00 2001 From: Joe Becher Date: Tue, 17 Mar 2020 15:23:02 -0400 Subject: [PATCH 076/144] Bump version --- CHANGELOG.md | 6 +++++- codecov/__init__.py | 4 ++-- setup.py | 2 +- 3 files changed, 8 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 88e8f477..a8a67c0b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,10 @@ +### `2.0.21` + +- fixed string issues + ### `2.0.20` -- fixed broken subprocess handling# +- fixed broken subprocess handling ### `2.0.19` diff --git a/codecov/__init__.py b/codecov/__init__.py index 41cac1ce..71f5a153 100644 --- a/codecov/__init__.py +++ b/codecov/__init__.py @@ -26,7 +26,7 @@ logging.captureWarnings(True) -version = VERSION = __version__ = '2.0.20' +version = VERSION = __version__ = '2.0.21' COLOR = True @@ -626,7 +626,7 @@ def main(*argv, **kwargs): toc = str((try_to_run(['git', 'ls-files'], cwd=root) or try_to_run(['git', 'ls-files']) or try_to_run(['hg', 'locate'], cwd=root) or - try_to_run(['hg', 'locate']) or ['']).strip()) + try_to_run(['hg', 'locate']) or [''])).strip() if codecov.prefix: prefix = codecov.prefix.strip('/') diff --git a/setup.py b/setup.py index 0dc9aa35..c0b7b032 100644 --- a/setup.py +++ b/setup.py @@ -1,7 +1,7 @@ #!/usr/bin/env python from setuptools import setup -version = '2.0.20' +version = '2.0.21' classifiers = ["Development Status :: 5 - Production/Stable", "Environment :: Plugins", "Intended Audience :: Developers", From bc18afda1a6cc41d3eebaff097ff6142c5a7ca7d Mon Sep 17 00:00:00 2001 From: Thiago Ramos Date: Tue, 17 Mar 2020 17:18:52 -0300 Subject: [PATCH 077/144] Cleaning TOC generation --- codecov/__init__.py | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/codecov/__init__.py b/codecov/__init__.py index 71f5a153..6b4525c2 100644 --- a/codecov/__init__.py +++ b/codecov/__init__.py @@ -214,6 +214,17 @@ def _add_env_if_not_empty(lst, value): lst.add(value) +def generate_toc(root): + return str( + ( + try_to_run(['git', 'ls-files'], cwd=root) or + try_to_run(['git', 'ls-files']) or + try_to_run(['hg', 'locate'], cwd=root) or + try_to_run(['hg', 'locate']) + ) + ).strip() or "" + + def main(*argv, **kwargs): root = os.getcwd() @@ -623,10 +634,7 @@ def main(*argv, **kwargs): # Build TOC # --------- - toc = str((try_to_run(['git', 'ls-files'], cwd=root) or - try_to_run(['git', 'ls-files']) or - try_to_run(['hg', 'locate'], cwd=root) or - try_to_run(['hg', 'locate']) or [''])).strip() + toc = generate_toc(root) if codecov.prefix: prefix = codecov.prefix.strip('/') From 0b17575077b7067d2e49ca031d275745c08363ca Mon Sep 17 00:00:00 2001 From: Thiago Ramos Date: Mon, 18 May 2020 01:51:00 -0300 Subject: [PATCH 078/144] Formatting codebase using black Ran 'black .' to format codebase --- codecov/__init__.py | 1154 ++++++++++++++++++++++++++----------------- codecov/__main__.py | 2 +- setup.py | 67 +-- tests/test.py | 990 ++++++++++++++++++++++--------------- 4 files changed, 1329 insertions(+), 884 deletions(-) diff --git a/codecov/__init__.py b/codecov/__init__.py index 6b4525c2..d5d72354 100644 --- a/codecov/__init__.py +++ b/codecov/__init__.py @@ -23,88 +23,98 @@ # https://urllib3.readthedocs.org/en/latest/security.html#insecureplatformwarning import logging + logging.captureWarnings(True) -version = VERSION = __version__ = '2.0.21' +version = VERSION = __version__ = "2.0.21" COLOR = True -is_merge_commit = re.compile(r'^Merge\s\w{40}\sinto\s\w{40}$') +is_merge_commit = re.compile(r"^Merge\s\w{40}\sinto\s\w{40}$") -remove_token = re.compile(r'token=[^\&]+').sub +remove_token = re.compile(r"token=[^\&]+").sub def sanitize_arg(replacement, arg): - return re.sub(r'[\&]+', replacement, arg, 0, re.MULTILINE) - - -ignored_path = re.compile(r'(/vendor)|' - r'(/js/generated/coverage)|' - r'(/__pycache__)|' - r'(/coverage/instrumented)|' - r'(/build/lib)|' - r'(/htmlcov)|' - r'(/node_modules)|' - r'(/\.yarn-cache)|' - r'(\.egg-info)|' - r'(/\.git)|' - r'(/\.hg)|' - r'(/\.tox)|' - r'(/\.?v?(irtual)?envs?)', re.I).search - -ignored_report = re.compile('.*(' - r'(/\.coverage.*)|' - r'(\.coveragerc)|' - r'(\.egg)|' - r'(\.gif)|' - r'(\.ini)|' - r'(\.less)|' - r'(\.jpeg)|' - r'(\.jpg)|' - r'(\.md)|' - r'(\.png)|' - r'(\.p?sql)|' - r'(\.whl)|' - r'(\.cpp)|' - r'(\.pyc?)|' - r'(\.cfg)|' - r'(\.class)|' - r'(\.js)|' - r'(\.html)|' - r'(\.sh)|' - r'(\.tar\.gz)|' - r'(\.yml)|' - r'(\.xcconfig)|' - r'(\.data)|' - r'(coverage\.db)|' - r'(\.?codecov\.yml)|' - r'(coverage\.jade)|' - r'(include\.lst)|' - r'(inputFiles\.lst)|' - r'(createdFiles\.lst)|' - r'(scoverage\.measurements\..*)|' - r'(test_.*_coverage\.txt)|' - r'(conftest_.*\.c\.gcov)' - ')$', re.I).match - -is_report = re.compile('.*(' - r'([^/]*coverage[^/]*)|' - r'(\.gcov)|' - r'(\.lcov)|' - r'(\.lst)|' - r'(clover\.xml)|' - r'(cobertura\.xml)|' - r'(coverage-final\.json)|' - r'(coverage-summary\.json)|' - r'(gcov\.info)|' - r'(([^/]*\.)?codecov\.[^/]*)|' - r'(jacoco[^/]*\.xml)|' - r'(lcov\.info)|' - r'(luacov\.report\.out)|' - r'(nosetests\.xml)|' - r'(report\.xml)' - ')$', re.I).match + return re.sub(r"[\&]+", replacement, arg, 0, re.MULTILINE) + + +ignored_path = re.compile( + r"(/vendor)|" + r"(/js/generated/coverage)|" + r"(/__pycache__)|" + r"(/coverage/instrumented)|" + r"(/build/lib)|" + r"(/htmlcov)|" + r"(/node_modules)|" + r"(/\.yarn-cache)|" + r"(\.egg-info)|" + r"(/\.git)|" + r"(/\.hg)|" + r"(/\.tox)|" + r"(/\.?v?(irtual)?envs?)", + re.I, +).search + +ignored_report = re.compile( + ".*(" + r"(/\.coverage.*)|" + r"(\.coveragerc)|" + r"(\.egg)|" + r"(\.gif)|" + r"(\.ini)|" + r"(\.less)|" + r"(\.jpeg)|" + r"(\.jpg)|" + r"(\.md)|" + r"(\.png)|" + r"(\.p?sql)|" + r"(\.whl)|" + r"(\.cpp)|" + r"(\.pyc?)|" + r"(\.cfg)|" + r"(\.class)|" + r"(\.js)|" + r"(\.html)|" + r"(\.sh)|" + r"(\.tar\.gz)|" + r"(\.yml)|" + r"(\.xcconfig)|" + r"(\.data)|" + r"(coverage\.db)|" + r"(\.?codecov\.yml)|" + r"(coverage\.jade)|" + r"(include\.lst)|" + r"(inputFiles\.lst)|" + r"(createdFiles\.lst)|" + r"(scoverage\.measurements\..*)|" + r"(test_.*_coverage\.txt)|" + r"(conftest_.*\.c\.gcov)" + ")$", + re.I, +).match + +is_report = re.compile( + ".*(" + r"([^/]*coverage[^/]*)|" + r"(\.gcov)|" + r"(\.lcov)|" + r"(\.lst)|" + r"(clover\.xml)|" + r"(cobertura\.xml)|" + r"(coverage-final\.json)|" + r"(coverage-summary\.json)|" + r"(gcov\.info)|" + r"(([^/]*\.)?codecov\.[^/]*)|" + r"(jacoco[^/]*\.xml)|" + r"(lcov\.info)|" + r"(luacov\.report\.out)|" + r"(nosetests\.xml)|" + r"(report\.xml)" + ")$", + re.I, +).match opj = os.path.join # for faster access @@ -112,47 +122,50 @@ def sanitize_arg(replacement, arg): def write(text, color=None): global COLOR if COLOR: - text = text.replace('==>', '\033[90m==>\033[0m') - text = text.replace(' +', ' \033[32m+\033[0m') - text = text.replace('XX>', '\033[31mXX>\033[0m') - if text[:6] == 'Error:': - text = '\033[41mError:\033[0m\033[91m%s\033[0m' % text[6:] - elif text[:4] == 'Tip:': - text = '\033[42mTip:\033[0m\033[32m%s\033[0m' % text[4:] - elif text.strip()[:4] == 'http': - text = '\033[92m%s\033[0m' % text - elif text[:7] == 'Codecov': - text = """ + text = text.replace("==>", "\033[90m==>\033[0m") + text = text.replace(" +", " \033[32m+\033[0m") + text = text.replace("XX>", "\033[31mXX>\033[0m") + if text[:6] == "Error:": + text = "\033[41mError:\033[0m\033[91m%s\033[0m" % text[6:] + elif text[:4] == "Tip:": + text = "\033[42mTip:\033[0m\033[32m%s\033[0m" % text[4:] + elif text.strip()[:4] == "http": + text = "\033[92m%s\033[0m" % text + elif text[:7] == "Codecov": + text = ( + """ _____ _ / ____| | | | | ___ __| | ___ ___ _____ __ | | / _ \ / _ |/ _ \/ __/ _ \ \ / / | |___| (_) | (_| | __/ (_| (_) \ V / \_____\___/ \____|\___|\___\___/ \_/ - %s\n""" % text.split(' ')[1] - elif color == 'red': - text = '\033[91m%s\033[0m' % text - elif color == 'green': - text = '\033[92m%s\033[0m' % text + %s\n""" + % text.split(" ")[1] + ) + elif color == "red": + text = "\033[91m%s\033[0m" % text + elif color == "green": + text = "\033[92m%s\033[0m" % text - sys.stdout.write(text + '\n') + sys.stdout.write(text + "\n") def fopen(path): try: if sys.version_info < (3, 0): - with open(path, 'r') as f: + with open(path, "r") as f: return f.read() else: try: - with open(path, 'r', encoding='utf-8') as f: + with open(path, "r", encoding="utf-8") as f: return f.read() except UnicodeDecodeError: - with open(path, 'r', encoding='ISO-8859-1') as f: + with open(path, "r", encoding="ISO-8859-1") as f: return f.read() except Exception as e: # on none of that works. just print the issue and continue - write(' - Ignored: ' + str(e)) + write(" - Ignored: " + str(e)) def read(filepath): @@ -160,29 +173,30 @@ def read(filepath): report = fopen(filepath) if report is None: return - write(' + %s bytes=%d' % (filepath, os.path.getsize(filepath))) - return '# path=' + filepath + '\n' + report + write(" + %s bytes=%d" % (filepath, os.path.getsize(filepath))) + return "# path=" + filepath + "\n" + report except Exception as e: # Ex: No such file or directory, skip them - write(' - Ignored: ' + str(e)) + write(" - Ignored: " + str(e)) def check_output(cmd, **popen_args): from subprocess import Popen, PIPE, CalledProcessError + process = Popen(cmd, stdout=PIPE, **popen_args) output, _ = process.communicate() if process.returncode: raise CalledProcessError(process.returncode, cmd) else: assert process.returncode == 0 - return output.decode('utf-8') + return output.decode("utf-8") def try_to_run(cmd, shell=False, cwd=None): try: return check_output(cmd, shell=shell, cwd=cwd) except Exception as e: - write(' Error running `%s`: %s' % (cmd, e or str(e))) + write(" Error running `%s`: %s" % (cmd, e or str(e))) return None @@ -196,17 +210,17 @@ def run_python_coverage(args): import coverage except ImportError: # Coverage is not installed on this Python. Hope it's on PATH. - try_to_run(['coverage'] + args, shell=False) + try_to_run(["coverage"] + args, shell=False) else: # Coverage is installed on this Python. Run it as a module. - try_to_run([sys.executable, '-m', 'coverage'] + args, shell=False) + try_to_run([sys.executable, "-m", "coverage"] + args, shell=False) def remove_non_ascii(data): try: - return data.decode('utf8') + '' + return data.decode("utf8") + "" except: - return ''.join([i if ord(i) < 128 else '' for i in data]) + return "".join([i if ord(i) < 128 else "" for i in data]) def _add_env_if_not_empty(lst, value): @@ -215,14 +229,17 @@ def _add_env_if_not_empty(lst, value): def generate_toc(root): - return str( - ( - try_to_run(['git', 'ls-files'], cwd=root) or - try_to_run(['git', 'ls-files']) or - try_to_run(['hg', 'locate'], cwd=root) or - try_to_run(['hg', 'locate']) - ) - ).strip() or "" + return ( + str( + ( + try_to_run(["git", "ls-files"], cwd=root) + or try_to_run(["git", "ls-files"]) + or try_to_run(["hg", "locate"], cwd=root) + or try_to_run(["hg", "locate"]) + ) + ).strip() + or "" + ) def main(*argv, **kwargs): @@ -230,70 +247,152 @@ def main(*argv, **kwargs): # Build Parser # ------------ - parser = argparse.ArgumentParser(prog='codecov', add_help=True, - formatter_class=argparse.RawDescriptionHelpFormatter, - epilog="""Upload reports to Codecov""") + parser = argparse.ArgumentParser( + prog="codecov", + add_help=True, + formatter_class=argparse.RawDescriptionHelpFormatter, + epilog="""Upload reports to Codecov""", + ) basics = parser.add_argument_group( - '======================== Basics ========================') - basics.add_argument('--version', action='version', - version='Codecov py-v'+version+" - https://codecov.io/") - basics.add_argument('--token', '-t', default=os.getenv("CODECOV_TOKEN"), - help="Private repository token or @filename for file containing the token. Defaults to $CODECOV_TOKEN. Not required for public repositories on Travis CI, CircleCI and AppVeyor") - basics.add_argument('--file', '-f', nargs="*", default=None, - help="Target a specific file for uploading") - basics.add_argument('--flags', '-F', nargs="*", default=None, - help="Flag these uploaded files with custom labels") - basics.add_argument('--env', '-e', nargs="*", default=None, - help="Store environment variables to help distinguish CI builds.") - basics.add_argument('--required', action="store_true", default=False, - help="If Codecov fails it will exit 1 - possibly failing the CI build.") - basics.add_argument('--name', '-n', default=None, - help="Custom defined name of the upload. Visible in Codecov UI.") + "======================== Basics ========================" + ) + basics.add_argument( + "--version", + action="version", + version="Codecov py-v" + version + " - https://codecov.io/", + ) + basics.add_argument( + "--token", + "-t", + default=os.getenv("CODECOV_TOKEN"), + help="Private repository token or @filename for file containing the token. Defaults to $CODECOV_TOKEN. Not required for public repositories on Travis CI, CircleCI and AppVeyor", + ) + basics.add_argument( + "--file", + "-f", + nargs="*", + default=None, + help="Target a specific file for uploading", + ) + basics.add_argument( + "--flags", + "-F", + nargs="*", + default=None, + help="Flag these uploaded files with custom labels", + ) + basics.add_argument( + "--env", + "-e", + nargs="*", + default=None, + help="Store environment variables to help distinguish CI builds.", + ) + basics.add_argument( + "--required", + action="store_true", + default=False, + help="If Codecov fails it will exit 1 - possibly failing the CI build.", + ) + basics.add_argument( + "--name", + "-n", + default=None, + help="Custom defined name of the upload. Visible in Codecov UI.", + ) gcov = parser.add_argument_group( - '======================== gcov ========================') - gcov.add_argument('--gcov-root', default=None, - help="Project root directory when preparing gcov") - gcov.add_argument('--gcov-glob', nargs="*", default=[], - help="Paths to ignore during gcov gathering") - gcov.add_argument('--gcov-exec', default='gcov', - help="gcov executable to run. Defaults to 'gcov'") - gcov.add_argument('--gcov-args', default='', - help="extra arguments to pass to gcov") + "======================== gcov ========================" + ) + gcov.add_argument( + "--gcov-root", default=None, help="Project root directory when preparing gcov" + ) + gcov.add_argument( + "--gcov-glob", + nargs="*", + default=[], + help="Paths to ignore during gcov gathering", + ) + gcov.add_argument( + "--gcov-exec", default="gcov", help="gcov executable to run. Defaults to 'gcov'" + ) + gcov.add_argument("--gcov-args", default="", help="extra arguments to pass to gcov") advanced = parser.add_argument_group( - '======================== Advanced ========================') - advanced.add_argument('-X', '--disable', nargs="*", default=[], help="Disable features. Accepting **search** to disable crawling through directories, **detect** to disable detecting CI provider, **gcov** disable gcov commands, `pycov` disables running python `coverage xml`, **fix** to disable report adjustments https://docs.codecov.io/docs/fixing-reports") - advanced.add_argument('--root', default=None, - help="Project directory. Default: current direcory or provided in CI environment variables") - advanced.add_argument('--commit', '-c', default=None, - help="Commit SHA, set automatically") - advanced.add_argument('--prefix', '-P', default=None, - help="Prefix network paths to help resolve paths: https://github.com/codecov/support/issues/472") - advanced.add_argument('--branch', '-b', default=None, help="Branch name") - advanced.add_argument('--build', default=None, - help="Specify a custom build number to distinguish CI jobs, provided automatically for supported CI companies") + "======================== Advanced ========================" + ) + advanced.add_argument( + "-X", + "--disable", + nargs="*", + default=[], + help="Disable features. Accepting **search** to disable crawling through directories, **detect** to disable detecting CI provider, **gcov** disable gcov commands, `pycov` disables running python `coverage xml`, **fix** to disable report adjustments https://docs.codecov.io/docs/fixing-reports", + ) + advanced.add_argument( + "--root", + default=None, + help="Project directory. Default: current direcory or provided in CI environment variables", + ) + advanced.add_argument( + "--commit", "-c", default=None, help="Commit SHA, set automatically" + ) advanced.add_argument( - '--pr', default=None, help="Specify a custom pr number, provided automatically for supported CI companies") - advanced.add_argument('--tag', default=None, help="Git tag") + "--prefix", + "-P", + default=None, + help="Prefix network paths to help resolve paths: https://github.com/codecov/support/issues/472", + ) + advanced.add_argument("--branch", "-b", default=None, help="Branch name") + advanced.add_argument( + "--build", + default=None, + help="Specify a custom build number to distinguish CI jobs, provided automatically for supported CI companies", + ) + advanced.add_argument( + "--pr", + default=None, + help="Specify a custom pr number, provided automatically for supported CI companies", + ) + advanced.add_argument("--tag", default=None, help="Git tag") enterprise = parser.add_argument_group( - '======================== Enterprise ========================') - enterprise.add_argument('--slug', '-r', default=os.getenv("CODECOV_SLUG"), - help="Specify repository slug for Enterprise ex. owner/repo") - enterprise.add_argument('--url', '-u', default=os.getenv("CODECOV_URL", - "https://codecov.io"), help="Your Codecov endpoint") - enterprise.add_argument('--cacert', default=os.getenv("CODECOV_CACERT", os.getenv( - "CURL_CA_BUNDLE")), help="Certificate pem bundle used to verify with your Codecov instance") + "======================== Enterprise ========================" + ) + enterprise.add_argument( + "--slug", + "-r", + default=os.getenv("CODECOV_SLUG"), + help="Specify repository slug for Enterprise ex. owner/repo", + ) + enterprise.add_argument( + "--url", + "-u", + default=os.getenv("CODECOV_URL", "https://codecov.io"), + help="Your Codecov endpoint", + ) + enterprise.add_argument( + "--cacert", + default=os.getenv("CODECOV_CACERT", os.getenv("CURL_CA_BUNDLE")), + help="Certificate pem bundle used to verify with your Codecov instance", + ) debugging = parser.add_argument_group( - '======================== Debugging ========================') - debugging.add_argument('--dump', action="store_true", - help="Dump collected data and do not send to Codecov") - debugging.add_argument('-v', '--verbose', action="store_true", - help="Be verbose, e.g. dump the collected data") - debugging.add_argument('--no-color', action="store_true", - help="Do not output with color") + "======================== Debugging ========================" + ) + debugging.add_argument( + "--dump", + action="store_true", + help="Dump collected data and do not send to Codecov", + ) + debugging.add_argument( + "-v", + "--verbose", + action="store_true", + help="Be verbose, e.g. dump the collected data", + ) + debugging.add_argument( + "--no-color", action="store_true", help="Do not output with color" + ) # Parse Arguments # --------------- @@ -311,306 +410,407 @@ def main(*argv, **kwargs): if codecov.env: # -e VAR1,VAR2 or -e VAR1 -e VAR2 for env in codecov.env: - for e in env.split(','): + for e in env.split(","): include_env.add(e.strip()) # add from env if os.getenv("CODECOV_ENV"): - for env in os.getenv("CODECOV_ENV").split(','): + for env in os.getenv("CODECOV_ENV").split(","): include_env.add(env.strip()) - write('Codecov v'+version) - query = dict(commit='', branch='', job='', pr='', build_url='', - token=codecov.token) + write("Codecov v" + version) + query = dict(commit="", branch="", job="", pr="", build_url="", token=codecov.token) language = None - if os.getenv('TOXENV'): - _add_env_if_not_empty(include_env, 'TOXENV') + if os.getenv("TOXENV"): + _add_env_if_not_empty(include_env, "TOXENV") # Detect CI # --------- - if 'detect' in codecov.disable: - write('XX> Detecting CI provider disabled.') + if "detect" in codecov.disable: + write("XX> Detecting CI provider disabled.") else: - write('==> Detecting CI provider') + write("==> Detecting CI provider") # ------- # Jenkins # ------- - if os.getenv('JENKINS_URL'): + if os.getenv("JENKINS_URL"): # https://wiki.jenkins-ci.org/display/JENKINS/Building+a+software+project # https://wiki.jenkins-ci.org/display/JENKINS/GitHub+pull+request+builder+plugin#GitHubpullrequestbuilderplugin-EnvironmentVariables - query.update(dict(branch=os.getenv('ghprbSourceBranch') or os.getenv('GIT_BRANCH') or os.getenv('BRANCH_NAME'), - service='jenkins', - commit=os.getenv('ghprbActualCommit') or os.getenv( - 'GIT_COMMIT'), - pr=os.getenv('ghprbPullId') or os.getenv( - 'CHANGE_ID'), - build=os.getenv('BUILD_NUMBER'), - build_url=os.getenv('BUILD_URL'))) - root = os.getenv('WORKSPACE') or root - write(' Jenkins Detected') + query.update( + dict( + branch=os.getenv("ghprbSourceBranch") + or os.getenv("GIT_BRANCH") + or os.getenv("BRANCH_NAME"), + service="jenkins", + commit=os.getenv("ghprbActualCommit") or os.getenv("GIT_COMMIT"), + pr=os.getenv("ghprbPullId") or os.getenv("CHANGE_ID"), + build=os.getenv("BUILD_NUMBER"), + build_url=os.getenv("BUILD_URL"), + ) + ) + root = os.getenv("WORKSPACE") or root + write(" Jenkins Detected") # --------- # Travis CI # --------- - elif os.getenv('CI') == 'true' and os.getenv('TRAVIS') == "true" and os.getenv('SHIPPABLE') != 'true': + elif ( + os.getenv("CI") == "true" + and os.getenv("TRAVIS") == "true" + and os.getenv("SHIPPABLE") != "true" + ): # http://docs.travis-ci.com/user/environment-variables/#Default-Environment-Variables - query.update(dict(branch=os.getenv('TRAVIS_BRANCH'), - service='travis', - build=os.getenv('TRAVIS_JOB_NUMBER'), - pr=os.getenv('TRAVIS_PULL_REQUEST'), - job=os.getenv('TRAVIS_JOB_ID'), - tag=os.getenv('TRAVIS_TAG'), - slug=os.getenv('TRAVIS_REPO_SLUG'), - commit=os.getenv('TRAVIS_COMMIT'))) - root = os.getenv('TRAVIS_BUILD_DIR') or root - write(' Travis Detected') - language = (list(filter(lambda l: os.getenv('TRAVIS_%s_VERSION' % l.upper()), - ('dart', 'go', 'haxe', 'jdk', 'julia', 'node', 'otp', 'xcode', - 'perl', 'php', 'python', 'r', 'ruby', 'rust', 'scala'))) + [''])[0] - - _add_env_if_not_empty(include_env, 'TRAVIS_OS_NAME') + query.update( + dict( + branch=os.getenv("TRAVIS_BRANCH"), + service="travis", + build=os.getenv("TRAVIS_JOB_NUMBER"), + pr=os.getenv("TRAVIS_PULL_REQUEST"), + job=os.getenv("TRAVIS_JOB_ID"), + tag=os.getenv("TRAVIS_TAG"), + slug=os.getenv("TRAVIS_REPO_SLUG"), + commit=os.getenv("TRAVIS_COMMIT"), + ) + ) + root = os.getenv("TRAVIS_BUILD_DIR") or root + write(" Travis Detected") + language = ( + list( + filter( + lambda l: os.getenv("TRAVIS_%s_VERSION" % l.upper()), + ( + "dart", + "go", + "haxe", + "jdk", + "julia", + "node", + "otp", + "xcode", + "perl", + "php", + "python", + "r", + "ruby", + "rust", + "scala", + ), + ) + ) + + [""] + )[0] + + _add_env_if_not_empty(include_env, "TRAVIS_OS_NAME") if language: _add_env_if_not_empty( - include_env, 'TRAVIS_%s_VERSION' % language.upper()) + include_env, "TRAVIS_%s_VERSION" % language.upper() + ) # -------- # Codeship # -------- - elif os.getenv('CI') == 'true' and os.getenv('CI_NAME') == 'codeship': + elif os.getenv("CI") == "true" and os.getenv("CI_NAME") == "codeship": # https://www.codeship.io/documentation/continuous-integration/set-environment-variables/ - query.update(dict(branch=os.getenv('CI_BRANCH'), - service='codeship', - build=os.getenv('CI_BUILD_NUMBER'), - build_url=os.getenv('CI_BUILD_URL'), - commit=os.getenv('CI_COMMIT_ID'))) - write(' Codeship Detected') + query.update( + dict( + branch=os.getenv("CI_BRANCH"), + service="codeship", + build=os.getenv("CI_BUILD_NUMBER"), + build_url=os.getenv("CI_BUILD_URL"), + commit=os.getenv("CI_COMMIT_ID"), + ) + ) + write(" Codeship Detected") # --------- # Buildkite # --------- - elif os.getenv('CI') == 'true' and os.getenv('BUILDKITE') == 'true': + elif os.getenv("CI") == "true" and os.getenv("BUILDKITE") == "true": # https://buildkite.com/docs/guides/environment-variables - query.update(dict(branch=os.getenv('BUILDKITE_BRANCH'), - service='buildkite', - build=os.getenv( - 'BUILDKITE_BUILD_NUMBER') + '.' + os.getenv('BUILDKITE_JOB_ID'), - slug=os.getenv('BUILDKITE_PROJECT_SLUG'), - build_url=os.getenv('BUILDKITE_BUILD_URL'), - commit=os.getenv('BUILDKITE_COMMIT'))) - write(' Buildkite Detected') + query.update( + dict( + branch=os.getenv("BUILDKITE_BRANCH"), + service="buildkite", + build=os.getenv("BUILDKITE_BUILD_NUMBER") + + "." + + os.getenv("BUILDKITE_JOB_ID"), + slug=os.getenv("BUILDKITE_PROJECT_SLUG"), + build_url=os.getenv("BUILDKITE_BUILD_URL"), + commit=os.getenv("BUILDKITE_COMMIT"), + ) + ) + write(" Buildkite Detected") # --------- # Circle CI # --------- - elif os.getenv('CI') == 'true' and os.getenv('CIRCLECI') == 'true': + elif os.getenv("CI") == "true" and os.getenv("CIRCLECI") == "true": # https://circleci.com/docs/environment-variables - query.update(dict(branch=os.getenv('CIRCLE_BRANCH'), - service='circleci', - build=os.getenv('CIRCLE_BUILD_NUM') + - "." + os.getenv('CIRCLE_NODE_INDEX'), - job=os.getenv('CIRCLE_BUILD_NUM') + - "." + os.getenv('CIRCLE_NODE_INDEX'), - pr=os.getenv('CIRCLE_PR_NUMBER'), - slug=os.getenv('CIRCLE_PROJECT_USERNAME') + - "/" + os.getenv('CIRCLE_PROJECT_REPONAME'), - commit=os.getenv('CIRCLE_SHA1'))) - write(' Circle CI Detected') + query.update( + dict( + branch=os.getenv("CIRCLE_BRANCH"), + service="circleci", + build=os.getenv("CIRCLE_BUILD_NUM") + + "." + + os.getenv("CIRCLE_NODE_INDEX"), + job=os.getenv("CIRCLE_BUILD_NUM") + + "." + + os.getenv("CIRCLE_NODE_INDEX"), + pr=os.getenv("CIRCLE_PR_NUMBER"), + slug=os.getenv("CIRCLE_PROJECT_USERNAME") + + "/" + + os.getenv("CIRCLE_PROJECT_REPONAME"), + commit=os.getenv("CIRCLE_SHA1"), + ) + ) + write(" Circle CI Detected") # --------- # Semaphore # --------- - elif os.getenv('CI') == 'true' and os.getenv('SEMAPHORE') == 'true': + elif os.getenv("CI") == "true" and os.getenv("SEMAPHORE") == "true": # https://semaphoreapp.com/docs/available-environment-variables.html - query.update(dict(branch=os.getenv('BRANCH_NAME'), - service='semaphore', - build=os.getenv( - 'SEMAPHORE_BUILD_NUMBER') + '.' + os.getenv('SEMAPHORE_CURRENT_THREAD'), - slug=os.getenv('SEMAPHORE_REPO_SLUG'), - commit=os.getenv('REVISION'))) - write(' Semaphore Detected') + query.update( + dict( + branch=os.getenv("BRANCH_NAME"), + service="semaphore", + build=os.getenv("SEMAPHORE_BUILD_NUMBER") + + "." + + os.getenv("SEMAPHORE_CURRENT_THREAD"), + slug=os.getenv("SEMAPHORE_REPO_SLUG"), + commit=os.getenv("REVISION"), + ) + ) + write(" Semaphore Detected") # ---------- # Greenhouse # ---------- - elif os.getenv('GREENHOUSE') == 'true': + elif os.getenv("GREENHOUSE") == "true": # http://docs.greenhouseci.com/docs/environment-variables-files - query.update(dict(branch=os.getenv('GREENHOUSE_BRANCH'), - service='greenhouse', - build=os.getenv('GREENHOUSE_BUILD_NUMBER'), - build_url=os.getenv('GREENHOUSE_BUILD_URL'), - pr=os.getenv('GREENHOUSE_PULL_REQUEST'), - commit=os.getenv('GREENHOUSE_COMMIT'))) - write(' Greenhouse Detected') + query.update( + dict( + branch=os.getenv("GREENHOUSE_BRANCH"), + service="greenhouse", + build=os.getenv("GREENHOUSE_BUILD_NUMBER"), + build_url=os.getenv("GREENHOUSE_BUILD_URL"), + pr=os.getenv("GREENHOUSE_PULL_REQUEST"), + commit=os.getenv("GREENHOUSE_COMMIT"), + ) + ) + write(" Greenhouse Detected") # -------- # drone.io # -------- - elif os.getenv('CI') == "drone" and os.getenv('DRONE') == "true": + elif os.getenv("CI") == "drone" and os.getenv("DRONE") == "true": # http://docs.drone.io/env.html - query.update(dict(branch=os.getenv('DRONE_BRANCH'), - service='drone.io', - build=os.getenv('DRONE_BUILD_NUMBER'), - build_url=os.getenv('DRONE_BUILD_LINK'))) - root = os.getenv('DRONE_BUILD_DIR') or root - write(' Drone Detected') + query.update( + dict( + branch=os.getenv("DRONE_BRANCH"), + service="drone.io", + build=os.getenv("DRONE_BUILD_NUMBER"), + build_url=os.getenv("DRONE_BUILD_LINK"), + ) + ) + root = os.getenv("DRONE_BUILD_DIR") or root + write(" Drone Detected") # -------- # TeamCity # -------- - elif os.getenv('TEAMCITY_VERSION'): + elif os.getenv("TEAMCITY_VERSION"): # https://confluence.jetbrains.com/plugins/servlet/mobile#content/view/74847298 - query.update(dict(service='teamcity', - build=os.getenv('BUILD_NUMBER'), - commit=os.getenv('BUILD_VCS_NUMBER'))) - write(' TeamCity CI Detected') + query.update( + dict( + service="teamcity", + build=os.getenv("BUILD_NUMBER"), + commit=os.getenv("BUILD_VCS_NUMBER"), + ) + ) + write(" TeamCity CI Detected") # -------- # AppVeyor # -------- - elif os.getenv('CI', 'false').lower() == 'true' and os.getenv('APPVEYOR', 'false').lower() == 'true': + elif ( + os.getenv("CI", "false").lower() == "true" + and os.getenv("APPVEYOR", "false").lower() == "true" + ): # http://www.appveyor.com/docs/environment-variables - query.update(dict(branch=os.getenv('APPVEYOR_REPO_BRANCH'), - service="appveyor", - job='/'.join((os.getenv('APPVEYOR_ACCOUNT_NAME'), os.getenv( - 'APPVEYOR_PROJECT_SLUG'), os.getenv('APPVEYOR_BUILD_VERSION'))), - build=os.getenv('APPVEYOR_JOB_ID'), - pr=os.getenv('APPVEYOR_PULL_REQUEST_NUMBER'), - slug=os.getenv('APPVEYOR_REPO_NAME'), - commit=os.getenv('APPVEYOR_REPO_COMMIT'))) - write(' AppVeyor Detected') - codecov.disable.append('search') + query.update( + dict( + branch=os.getenv("APPVEYOR_REPO_BRANCH"), + service="appveyor", + job="/".join( + ( + os.getenv("APPVEYOR_ACCOUNT_NAME"), + os.getenv("APPVEYOR_PROJECT_SLUG"), + os.getenv("APPVEYOR_BUILD_VERSION"), + ) + ), + build=os.getenv("APPVEYOR_JOB_ID"), + pr=os.getenv("APPVEYOR_PULL_REQUEST_NUMBER"), + slug=os.getenv("APPVEYOR_REPO_NAME"), + commit=os.getenv("APPVEYOR_REPO_COMMIT"), + ) + ) + write(" AppVeyor Detected") + codecov.disable.append("search") # ------- # Wercker # ------- - elif os.getenv('CI') == "true" and os.getenv('WERCKER_GIT_BRANCH'): + elif os.getenv("CI") == "true" and os.getenv("WERCKER_GIT_BRANCH"): # http://devcenter.wercker.com/articles/steps/variables.html - query.update(dict(branch=os.getenv('WERCKER_GIT_BRANCH'), - service="wercker", - build=os.getenv('WERCKER_MAIN_PIPELINE_STARTED'), - slug=os.getenv('WERCKER_GIT_OWNER') + '/' + - os.getenv('WERCKER_GIT_REPOSITORY'), - commit=os.getenv('WERCKER_GIT_COMMIT'))) - write(' Wercker Detected') + query.update( + dict( + branch=os.getenv("WERCKER_GIT_BRANCH"), + service="wercker", + build=os.getenv("WERCKER_MAIN_PIPELINE_STARTED"), + slug=os.getenv("WERCKER_GIT_OWNER") + + "/" + + os.getenv("WERCKER_GIT_REPOSITORY"), + commit=os.getenv("WERCKER_GIT_COMMIT"), + ) + ) + write(" Wercker Detected") # ------ # Magnum # ------ - elif os.getenv('CI') == "true" and os.getenv('MAGNUM') == 'true': + elif os.getenv("CI") == "true" and os.getenv("MAGNUM") == "true": # https://magnum-ci.com/docs/environment - query.update(dict(service="magnum", - branch=os.getenv('CI_BRANCH'), - build=os.getenv('CI_BUILD_NUMBER'), - commit=os.getenv('CI_COMMIT'))) - write(' Magnum Detected') + query.update( + dict( + service="magnum", + branch=os.getenv("CI_BRANCH"), + build=os.getenv("CI_BUILD_NUMBER"), + commit=os.getenv("CI_COMMIT"), + ) + ) + write(" Magnum Detected") # --------- # Shippable # --------- - elif os.getenv('SHIPPABLE') == "true": + elif os.getenv("SHIPPABLE") == "true": # http://docs.shippable.com/en/latest/config.html#common-environment-variables - query.update(dict(branch=os.getenv('BRANCH'), - service='shippable', - build=os.getenv('BUILD_NUMBER'), - build_url=os.getenv('BUILD_URL'), - pr=os.getenv('PULL_REQUEST'), - slug=os.getenv('REPO_NAME'), - commit=os.getenv('COMMIT'))) - write(' Shippable Detected') + query.update( + dict( + branch=os.getenv("BRANCH"), + service="shippable", + build=os.getenv("BUILD_NUMBER"), + build_url=os.getenv("BUILD_URL"), + pr=os.getenv("PULL_REQUEST"), + slug=os.getenv("REPO_NAME"), + commit=os.getenv("COMMIT"), + ) + ) + write(" Shippable Detected") # --------- # Gitlab CI # --------- - elif os.getenv('CI_SERVER_NAME', '').startswith("GitLab"): + elif os.getenv("CI_SERVER_NAME", "").startswith("GitLab"): # http://doc.gitlab.com/ci/examples/README.html#environmental-variables # https://gitlab.com/gitlab-org/gitlab-ci-runner/blob/master/lib/build.rb#L96 - query.update(dict(service='gitlab', - branch=os.getenv('CI_BUILD_REF_NAME'), - build=os.getenv('CI_BUILD_ID'), - commit=os.getenv('CI_BUILD_REF'))) - if os.getenv('CI_PROJECT_DIR', '').startswith('/'): - root = os.getenv('CI_PROJECT_DIR') + query.update( + dict( + service="gitlab", + branch=os.getenv("CI_BUILD_REF_NAME"), + build=os.getenv("CI_BUILD_ID"), + commit=os.getenv("CI_BUILD_REF"), + ) + ) + if os.getenv("CI_PROJECT_DIR", "").startswith("/"): + root = os.getenv("CI_PROJECT_DIR") else: - root = os.getenv('HOME') + '/' + \ - os.getenv('CI_PROJECT_DIR', '') + root = os.getenv("HOME") + "/" + os.getenv("CI_PROJECT_DIR", "") - if os.getenv('CI_BUILD_REPO'): - query['slug'] = os.getenv('CI_BUILD_REPO').split( - '/', 3)[-1].replace('.git', '') - elif os.getenv('CI_REPOSITORY_URL'): - query['slug'] = os.getenv('CI_REPOSITORY_URL').split( - '/', 3)[-1].replace('.git', '') + if os.getenv("CI_BUILD_REPO"): + query["slug"] = ( + os.getenv("CI_BUILD_REPO").split("/", 3)[-1].replace(".git", "") + ) + elif os.getenv("CI_REPOSITORY_URL"): + query["slug"] = ( + os.getenv("CI_REPOSITORY_URL").split("/", 3)[-1].replace(".git", "") + ) - write(' Gitlab CI Detected') + write(" Gitlab CI Detected") else: - query.update(dict(commit=os.getenv('VCS_COMMIT_ID', ''), - branch=os.getenv('VCS_BRANCH_NAME', ''), - pr=os.getenv('VCS_PULL_REQUEST', ''), - slug=os.getenv('VCS_SLUG', ''), - build_url=os.getenv('CI_BUILD_URL', ''), - build=os.getenv('CI_BUILD_ID', ''))) + query.update( + dict( + commit=os.getenv("VCS_COMMIT_ID", ""), + branch=os.getenv("VCS_BRANCH_NAME", ""), + pr=os.getenv("VCS_PULL_REQUEST", ""), + slug=os.getenv("VCS_SLUG", ""), + build_url=os.getenv("CI_BUILD_URL", ""), + build=os.getenv("CI_BUILD_ID", ""), + ) + ) # ------ # git/hg # ------ - if not query.get('branch'): + if not query.get("branch"): try: # find branch, commit, repo from git command - branch = (try_to_run( - ['git', 'rev-parse', '--abbrev-ref', 'HEAD']) or try_to_run( - ['hg', 'branch'])) - query['branch'] = branch if branch != 'HEAD' else '' - write(' -> Got branch from git/hg') + branch = try_to_run( + ["git", "rev-parse", "--abbrev-ref", "HEAD"] + ) or try_to_run(["hg", "branch"]) + query["branch"] = branch if branch != "HEAD" else "" + write(" -> Got branch from git/hg") except: - write(' x> Failed to get branch from git/hg') + write(" x> Failed to get branch from git/hg") - if not query.get('commit'): + if not query.get("commit"): try: - query['commit'] = (try_to_run( - ['git', 'rev-parse', "HEAD"]) or try_to_run( - ["hg", "id", "-i", "--debug", '|', "tr", "-d", "'+'"])) - write(' -> Got sha from git/hg') + query["commit"] = try_to_run( + ["git", "rev-parse", "HEAD"] + ) or try_to_run(["hg", "id", "-i", "--debug", "|", "tr", "-d", "'+'"]) + write(" -> Got sha from git/hg") except: # pragma: no cover - write(' x> Failed to get sha from git/hg') + write(" x> Failed to get sha from git/hg") # Update Query # ------------ if codecov.name: - query['name'] = codecov.name + query["name"] = codecov.name if codecov.flags: - query['flags'] = ','.join(codecov.flags) + query["flags"] = ",".join(codecov.flags) if codecov.build: - query['build'] = codecov.build + query["build"] = codecov.build if codecov.pr: - query['pr'] = codecov.pr + query["pr"] = codecov.pr if codecov.commit: - query['commit'] = codecov.commit + query["commit"] = codecov.commit - elif query['pr'] and query['pr'] != 'false': + elif query["pr"] and query["pr"] != "false": # Merge Commits # ------------- - res = try_to_run(['git', 'log', '-1', '--pretty=%B']) + res = try_to_run(["git", "log", "-1", "--pretty=%B"]) if res and is_merge_commit.match(res.strip()): - query['commit'] = res.split(' ')[1] - write(' Fixing merge commit SHA') + query["commit"] = res.split(" ")[1] + write(" Fixing merge commit SHA") if codecov.slug: - query['slug'] = codecov.slug + query["slug"] = codecov.slug if codecov.branch: - query['branch'] = codecov.branch + query["branch"] = codecov.branch if codecov.tag: - query['tag'] = codecov.tag + query["tag"] = codecov.tag if codecov.root: root = codecov.root @@ -620,64 +820,55 @@ def main(*argv, **kwargs): # Upload # ------ try: - write('==> Preparing upload') + write("==> Preparing upload") # Read token from file # -------------------- - if query.get('token') and query.get('token')[0] == '@': - write(' Reading token from file') - query['token'] = fopen( - opj(os.getcwd(), query['token'][1:])).strip() + if query.get("token") and query.get("token")[0] == "@": + write(" Reading token from file") + query["token"] = fopen(opj(os.getcwd(), query["token"][1:])).strip() - assert query.get('commit') not in ( - '', None), "Commit sha is missing. Please specify via --commit=:sha" + assert query.get("commit") not in ( + "", + None, + ), "Commit sha is missing. Please specify via --commit=:sha" # Build TOC # --------- toc = generate_toc(root) if codecov.prefix: - prefix = codecov.prefix.strip('/') - toc = '{}/{}'.format( - prefix, - toc.replace('\n', '\n{}/'.format(prefix)) - ) + prefix = codecov.prefix.strip("/") + toc = "{}/{}".format(prefix, toc.replace("\n", "\n{}/".format(prefix))) # Detect codecov.yml location - yaml_location = re.search( - r'\.?codecov\.ya?ml$', - toc, - re.M - ) + yaml_location = re.search(r"\.?codecov\.ya?ml$", toc, re.M) if yaml_location: yaml_location = yaml_location.group() yaml_path = opj(root, yaml_location) if os.path.exists(yaml_path): - query['yaml'] = yaml_location + query["yaml"] = yaml_location yaml = fopen(yaml_path) _token = re.search( - r'token: (\'|\")?([0-9a-f]{8}(-?[0-9a-f]{4}){3}-?[0-9a-f]{12})', + r"token: (\'|\")?([0-9a-f]{8}(-?[0-9a-f]{4}){3}-?[0-9a-f]{12})", yaml, - re.M + re.M, ) if _token: - query['token'] = _token.groups()[1] + query["token"] = _token.groups()[1] _slug = re.search( - r'slug: (\'|\")?([\w\-\.\+]+\/[\w\-\.\+]+)', - yaml, - re.M + r"slug: (\'|\")?([\w\-\.\+]+\/[\w\-\.\+]+)", yaml, re.M ) if _slug: - query['slug'] = _slug.groups()[1] + query["slug"] = _slug.groups()[1] - assert query.get('job') or query.get( - 'token'), "Missing repository upload token" + assert query.get("job") or query.get("token"), "Missing repository upload token" # Processing gcov # --------------- - if 'gcov' in codecov.disable: - write('XX> Skip processing gcov') + if "gcov" in codecov.disable: + write("XX> Skip processing gcov") else: dont_search_here = ( @@ -685,126 +876,158 @@ def main(*argv, **kwargs): "-not -path './node_modules/**' " "-not -path './vendor/**'" ) - write('==> Processing gcov (disable by -X gcov)') - cmd = ['find', - (sanitize_arg('', codecov.gcov_root or root)), dont_search_here, - '-type', 'f', '-name', '*.gcno', " ".join(map(lambda a: "-not -path '%s'" % - a, codecov.gcov_glob)), - '-exec', (sanitize_arg('', - codecov.gcov_exec or '')), - '-pb', (sanitize_arg('', codecov.gcov_args or '')), '{}', '+'] - write(' Executing gcov (%s)' % cmd) + write("==> Processing gcov (disable by -X gcov)") + cmd = [ + "find", + (sanitize_arg("", codecov.gcov_root or root)), + dont_search_here, + "-type", + "f", + "-name", + "*.gcno", + " ".join(map(lambda a: "-not -path '%s'" % a, codecov.gcov_glob)), + "-exec", + (sanitize_arg("", codecov.gcov_exec or "")), + "-pb", + (sanitize_arg("", codecov.gcov_args or "")), + "{}", + "+", + ] + write(" Executing gcov (%s)" % cmd) try_to_run(cmd) # Collect Reports # --------------- - write('==> Collecting reports') + write("==> Collecting reports") reports = [] - if 'search' in codecov.disable: - write('XX> Searching for reports disabled') + if "search" in codecov.disable: + write("XX> Searching for reports disabled") else: # Detect .bowerrc # --------------- - bower_components = '/bower_components' - bowerrc = opj(root, '.bowerrc') + bower_components = "/bower_components" + bowerrc = opj(root, ".bowerrc") if os.path.exists(bowerrc): - write(' Detecting .bowerrc file') + write(" Detecting .bowerrc file") try: - bower_components = '/' + \ - (loads(fopen(bowerrc)).get('directory') - or 'bower_components').replace('./', '').strip('/') - write(' .bowerrc detected, ignoring ' + bower_components) + bower_components = "/" + ( + loads(fopen(bowerrc)).get("directory") or "bower_components" + ).replace("./", "").strip("/") + write(" .bowerrc detected, ignoring " + bower_components) except Exception as e: - write(' .bowerrc parsing error: ' + str(e)) + write(" .bowerrc parsing error: " + str(e)) # Find reports # ------------ for _root, dirs, files in os.walk(root): # need to replace('\\', '/') for Windows - if not ignored_path(_root.replace('\\', '/')) and bower_components not in _root.replace('\\', '/'): + if not ignored_path( + _root.replace("\\", "/") + ) and bower_components not in _root.replace("\\", "/"): # add data to tboc for filepath in files: fullpath = opj(_root, filepath) - if not codecov.file and is_report(fullpath.replace('\\', '/')) and not ignored_report(fullpath.replace('\\', '/')): + if ( + not codecov.file + and is_report(fullpath.replace("\\", "/")) + and not ignored_report(fullpath.replace("\\", "/")) + ): # found report reports.append(read(fullpath)) # Read Reports # ------------ if codecov.file: - write(' Targeting specific files') + write(" Targeting specific files") reports.extend(filter(bool, map(read, codecov.file))) - elif 'pycov' not in codecov.disable: + elif "pycov" not in codecov.disable: # Call `coverage xml` when .coverage exists # ----------------------------------------- # Ran from current directory - if glob.glob(opj(os.getcwd(), '.coverage.*')): - write(' Merging coverage reports') + if glob.glob(opj(os.getcwd(), ".coverage.*")): + write(" Merging coverage reports") # The `-a` option is mandatory here. If we # have a `.coverage` in the current directory, calling # without the option would delete the previous data - run_python_coverage(['combine', '-a']) + run_python_coverage(["combine", "-a"]) - if os.path.exists(opj(os.getcwd(), '.coverage')) and not os.path.exists(opj(os.getcwd(), 'coverage.xml')): - write(' Generating coverage xml reports for Python') + if os.path.exists(opj(os.getcwd(), ".coverage")) and not os.path.exists( + opj(os.getcwd(), "coverage.xml") + ): + write(" Generating coverage xml reports for Python") # using `-i` to ignore "No source for code" error - run_python_coverage(['xml', '-i']) - reports.append(read(opj(os.getcwd(), 'coverage.xml'))) + run_python_coverage(["xml", "-i"]) + reports.append(read(opj(os.getcwd(), "coverage.xml"))) reports = list(filter(bool, reports)) assert len(reports) > 0, "No coverage report found" # Storing Environment # ------------------- - env = '' + env = "" if include_env: - write('==> Appending environment variables') + write("==> Appending environment variables") for k in include_env: if k: - write(' + ' + k) + write(" + " + k) - env = '\n'.join(["%s=%s" % (k, os.getenv(k, '')) - for k in include_env if k]) + '\n<<<<<< ENV' + env = ( + "\n".join(["%s=%s" % (k, os.getenv(k, "")) for k in include_env if k]) + + "\n<<<<<< ENV" + ) # join reports together - reports = '\n'.join((env, (toc or ''), '<<<<<< network', - '\n<<<<<< EOF\n'.join(reports), - '<<<<<< EOF')) + reports = "\n".join( + ( + env, + (toc or ""), + "<<<<<< network", + "\n<<<<<< EOF\n".join(reports), + "<<<<<< EOF", + ) + ) - query['package'] = "py" + VERSION - urlargs = (urlencode(dict([(k, v.strip()) for k, v in query.items( - ) if v not in ('', None)]))).replace("+", "%20") + query["package"] = "py" + VERSION + urlargs = ( + urlencode( + dict([(k, v.strip()) for k, v in query.items() if v not in ("", None)]) + ) + ).replace("+", "%20") - result = '' + result = "" if codecov.dump: - write('-------------------- Debug --------------------') - write(' .url ' + codecov.url) - write(' .query ' + remove_token('token=', urlargs)) + write("-------------------- Debug --------------------") + write(" .url " + codecov.url) + write(" .query " + remove_token("token=", urlargs)) write(reports) - write('-------------------- EOF --------------------') + write("-------------------- EOF --------------------") else: - write('==> Uploading') - write(' .url ' + codecov.url) - write(' .query ' + remove_token('token=', urlargs)) + write("==> Uploading") + write(" .url " + codecov.url) + write(" .query " + remove_token("token=", urlargs)) if codecov.verbose: - write('-------------------- Reports --------------------') + write("-------------------- Reports --------------------") write(reports) - write('-------------------------------------------------') + write("-------------------------------------------------") s3 = None trys = 0 while trys < 3: trys += 1 - if 's3' not in codecov.disable: + if "s3" not in codecov.disable: try: - write(' Pinging Codecov...') - res = requests.post('%s/upload/v4?%s' % (codecov.url, urlargs), - verify=codecov.cacert, - headers={'Accept': 'text/plain', - 'X-Reduced-Redundancy': 'false'}) + write(" Pinging Codecov...") + res = requests.post( + "%s/upload/v4?%s" % (codecov.url, urlargs), + verify=codecov.cacert, + headers={ + "Accept": "text/plain", + "X-Reduced-Redundancy": "false", + }, + ) if res.status_code in (400, 406): raise Exception(res.text) @@ -815,64 +1038,83 @@ def main(*argv, **kwargs): # Handle reports encoding for Python 2 and 3 if not isinstance(reports, bytes): - reports = reports.encode('utf-8') - - write(' Uploading to S3...') - s3 = requests.put(upload_url, data=reports, - headers={'Content-Type': 'text/plain', - 'x-amz-acl': 'public-read'}) + reports = reports.encode("utf-8") + + write(" Uploading to S3...") + s3 = requests.put( + upload_url, + data=reports, + headers={ + "Content-Type": "text/plain", + "x-amz-acl": "public-read", + }, + ) s3.raise_for_status() assert s3.status_code == 200 - write(' ' + result) + write(" " + result) break else: # try again continue except AssertionError: - write(' Direct to s3 failed. Using backup v2 endpoint.') + write(" Direct to s3 failed. Using backup v2 endpoint.") - write(' Uploading to Codecov...') + write(" Uploading to Codecov...") # just incase, try traditional upload - res = requests.post('%s/upload/v2?%s' % (codecov.url, urlargs), - verify=codecov.cacert, - data='\n'.join( - (reports, s3.reason if s3 else '', s3.text if s3 else '')), - headers={"Accept": "text/plain"}) + res = requests.post( + "%s/upload/v2?%s" % (codecov.url, urlargs), + verify=codecov.cacert, + data="\n".join( + (reports, s3.reason if s3 else "", s3.text if s3 else "") + ), + headers={"Accept": "text/plain"}, + ) if res.status_code < 500: - write(' ' + res.text) + write(" " + res.text) res.raise_for_status() result = res.text return - write(' Retrying... in %ds' % (trys * 30)) + write(" Retrying... in %ds" % (trys * 30)) sleep(trys * 30) except Exception as e: - write('Error: ' + str(e)) - if kwargs.get('debug'): + write("Error: " + str(e)) + if kwargs.get("debug"): raise - write('') + write("") # detect language if language: - write('Tip: See an example %s repo: https://github.com/codecov/example-%s' % - (language, language)) + write( + "Tip: See an example %s repo: https://github.com/codecov/example-%s" + % (language, language) + ) else: write( - 'Tip: See all example repositories: https://github.com/codecov?query=example') + "Tip: See all example repositories: https://github.com/codecov?query=example" + ) - write('Support channels:', 'green') - write(' Email: hello@codecov.io\n' - ' IRC: #codecov\n' - ' Gitter: https://gitter.im/codecov/support\n' - ' Twitter: @codecov\n') + write("Support channels:", "green") + write( + " Email: hello@codecov.io\n" + " IRC: #codecov\n" + " Gitter: https://gitter.im/codecov/support\n" + " Twitter: @codecov\n" + ) sys.exit(1 if codecov.required else 0) else: - if kwargs.get('debug'): - return dict(reports=reports, codecov=codecov, query=query, urlargs=urlargs, result=result) + if kwargs.get("debug"): + return dict( + reports=reports, + codecov=codecov, + query=query, + urlargs=urlargs, + result=result, + ) -if __name__ == '__main__': +if __name__ == "__main__": main() diff --git a/codecov/__main__.py b/codecov/__main__.py index 291e202e..cc2be956 100644 --- a/codecov/__main__.py +++ b/codecov/__main__.py @@ -1,5 +1,5 @@ import codecov -if __name__ == '__main__': +if __name__ == "__main__": codecov.main() diff --git a/setup.py b/setup.py index c0b7b032..d6704387 100644 --- a/setup.py +++ b/setup.py @@ -1,36 +1,39 @@ #!/usr/bin/env python from setuptools import setup -version = '2.0.21' -classifiers = ["Development Status :: 5 - Production/Stable", - "Environment :: Plugins", - "Intended Audience :: Developers", - "Programming Language :: Python", - "Programming Language :: Python :: 2", - "Programming Language :: Python :: 2.7", - "Programming Language :: Python :: 3", - "Programming Language :: Python :: 3.4", - "Programming Language :: Python :: 3.5", - "Programming Language :: Python :: 3.6", - "Programming Language :: Python :: 3.7", - "Programming Language :: Python :: Implementation :: PyPy", - "License :: OSI Approved :: Apache Software License", - "Topic :: Software Development :: Testing"] +version = "2.0.21" +classifiers = [ + "Development Status :: 5 - Production/Stable", + "Environment :: Plugins", + "Intended Audience :: Developers", + "Programming Language :: Python", + "Programming Language :: Python :: 2", + "Programming Language :: Python :: 2.7", + "Programming Language :: Python :: 3", + "Programming Language :: Python :: 3.4", + "Programming Language :: Python :: 3.5", + "Programming Language :: Python :: 3.6", + "Programming Language :: Python :: 3.7", + "Programming Language :: Python :: Implementation :: PyPy", + "License :: OSI Approved :: Apache Software License", + "Topic :: Software Development :: Testing", +] -setup(name='codecov', - version=version, - description="Hosted coverage reports for GitHub, Bitbucket and Gitlab", - long_description=None, - classifiers=classifiers, - keywords='coverage codecov code python java scala php', - author='@codecov', - author_email='hello@codecov.io', - url='https://github.com/codecov/codecov-python', - license='http://www.apache.org/licenses/LICENSE-2.0', - packages=['codecov'], - include_package_data=True, - zip_safe=True, - install_requires=["requests>=2.7.9", "coverage"], - entry_points={'console_scripts': ['codecov=codecov:main']}, - python_requires='>=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*', - ) +setup( + name="codecov", + version=version, + description="Hosted coverage reports for GitHub, Bitbucket and Gitlab", + long_description=None, + classifiers=classifiers, + keywords="coverage codecov code python java scala php", + author="@codecov", + author_email="hello@codecov.io", + url="https://github.com/codecov/codecov-python", + license="http://www.apache.org/licenses/LICENSE-2.0", + packages=["codecov"], + include_package_data=True, + zip_safe=True, + install_requires=["requests>=2.7.9", "coverage"], + entry_points={"console_scripts": ["codecov=codecov:main"]}, + python_requires=">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*", +) diff --git a/tests/test.py b/tests/test.py index 1b64215b..41165d36 100644 --- a/tests/test.py +++ b/tests/test.py @@ -15,12 +15,12 @@ class TestUploader(unittest.TestCase): maxDiff = None here = os.path.dirname(__file__) - bowerrc = os.path.join(os.path.dirname(__file__), '../.bowerrc') - token = os.path.join(os.path.dirname(__file__), '../.token') - jacoco = os.path.join(os.path.dirname(__file__), '../jacoco.xml') - filepath = os.path.join(os.path.dirname(__file__), 'coverage.xml') - coverage = os.path.join(os.path.dirname(__file__), '../.coverage') - defaults = dict(commit='a', branch='a', token='a') + bowerrc = os.path.join(os.path.dirname(__file__), "../.bowerrc") + token = os.path.join(os.path.dirname(__file__), "../.token") + jacoco = os.path.join(os.path.dirname(__file__), "../jacoco.xml") + filepath = os.path.join(os.path.dirname(__file__), "coverage.xml") + coverage = os.path.join(os.path.dirname(__file__), "../.coverage") + defaults = dict(commit="a", branch="a", token="a") @classmethod def setUpClass(self): @@ -32,152 +32,262 @@ def tearDownClass(self): def setUp(self): # set all environ back - os.environ['CI'] = "true" - for key in ("TRAVIS", "TRAVIS_BRANCH", "TRAVIS_COMMIT", "TRAVIS_BUILD_DIR", "TRAVIS_JOB_ID", "TRAVIS_PULL_REQUEST", - "CI_NAME", "CI_BRANCH", "CI_COMMIT_ID", "SHIPPABLE", - "CI_BUILD_NUMBER", "MAGNUM", "CI_COMMIT", "APPVEYOR_ACCOUNT_NAME", "APPVEYOR_PROJECT_SLUG", "APPVEYOR_PULL_REQUEST_NUMBER", - "CIRCLECI", "CIRCLE_BRANCH", "CIRCLE_ARTIFACTS", "CIRCLE_SHA1", "CIRCLE_NODE_INDEX", "CIRCLE_PR_NUMBER", - "SEMAPHORE", "BRANCH_NAME", "SEMAPHORE_PROJECT_DIR", "REVISION", - "BUILDKITE", "BUILDKITE_BUILD_NUMBER", "BUILDKITE_JOB_ID", "BUILDKITE_BRANCH", "BUILDKITE_PROJECT_SLUG", "BUILDKITE_COMMIT", - "DRONE", "DRONE_BRANCH", "DRONE_BUILD_DIR", "JENKINS_URL", "TRAVIS_TAG", - "GIT_BRANCH", "GIT_COMMIT", "WORKSPACE", "BUILD_NUMBER", "CI_BUILD_URL", "SEMAPHORE_REPO_SLUG", "SEMAPHORE_CURRENT_THREAD", - "DRONE_BUILD_LINK", "TRAVIS_REPO_SLUG", "CODECOV_TOKEN", "APPVEYOR", "APPVEYOR_REPO_BRANCH", - "APPVEYOR_BUILD_VERSION", "APPVEYOR_JOB_ID", "APPVEYOR_REPO_NAME", "APPVEYOR_REPO_COMMIT", "WERCKER_GIT_BRANCH", - "WERCKER_MAIN_PIPELINE_STARTED", "WERCKER_GIT_OWNER", "WERCKER_GIT_REPOSITORY", - "CI_BUILD_REF_NAME", "CI_BUILD_ID", "CI_BUILD_REPO", "CI_PROJECT_DIR", "CI_BUILD_REF", "CI_SERVER_NAME", - "ghprbActualCommit", "ghprbSourceBranch", "ghprbPullId", "WERCKER_GIT_COMMIT", "CHANGE_ID"): + os.environ["CI"] = "true" + for key in ( + "TRAVIS", + "TRAVIS_BRANCH", + "TRAVIS_COMMIT", + "TRAVIS_BUILD_DIR", + "TRAVIS_JOB_ID", + "TRAVIS_PULL_REQUEST", + "CI_NAME", + "CI_BRANCH", + "CI_COMMIT_ID", + "SHIPPABLE", + "CI_BUILD_NUMBER", + "MAGNUM", + "CI_COMMIT", + "APPVEYOR_ACCOUNT_NAME", + "APPVEYOR_PROJECT_SLUG", + "APPVEYOR_PULL_REQUEST_NUMBER", + "CIRCLECI", + "CIRCLE_BRANCH", + "CIRCLE_ARTIFACTS", + "CIRCLE_SHA1", + "CIRCLE_NODE_INDEX", + "CIRCLE_PR_NUMBER", + "SEMAPHORE", + "BRANCH_NAME", + "SEMAPHORE_PROJECT_DIR", + "REVISION", + "BUILDKITE", + "BUILDKITE_BUILD_NUMBER", + "BUILDKITE_JOB_ID", + "BUILDKITE_BRANCH", + "BUILDKITE_PROJECT_SLUG", + "BUILDKITE_COMMIT", + "DRONE", + "DRONE_BRANCH", + "DRONE_BUILD_DIR", + "JENKINS_URL", + "TRAVIS_TAG", + "GIT_BRANCH", + "GIT_COMMIT", + "WORKSPACE", + "BUILD_NUMBER", + "CI_BUILD_URL", + "SEMAPHORE_REPO_SLUG", + "SEMAPHORE_CURRENT_THREAD", + "DRONE_BUILD_LINK", + "TRAVIS_REPO_SLUG", + "CODECOV_TOKEN", + "APPVEYOR", + "APPVEYOR_REPO_BRANCH", + "APPVEYOR_BUILD_VERSION", + "APPVEYOR_JOB_ID", + "APPVEYOR_REPO_NAME", + "APPVEYOR_REPO_COMMIT", + "WERCKER_GIT_BRANCH", + "WERCKER_MAIN_PIPELINE_STARTED", + "WERCKER_GIT_OWNER", + "WERCKER_GIT_REPOSITORY", + "CI_BUILD_REF_NAME", + "CI_BUILD_ID", + "CI_BUILD_REPO", + "CI_PROJECT_DIR", + "CI_BUILD_REF", + "CI_SERVER_NAME", + "ghprbActualCommit", + "ghprbSourceBranch", + "ghprbPullId", + "WERCKER_GIT_COMMIT", + "CHANGE_ID", + ): os.environ[key] = "" def tearDown(self): self.delete(self.filepath, self.coverage, self.jacoco, self.bowerrc) - self.delete('hello', 'hello.c', 'hello.gcda', - 'hello.c.gcov', 'hello.gcno') + self.delete("hello", "hello.c", "hello.gcda", "hello.c.gcov", "hello.gcno") def set_env(self, **kwargs): for key in kwargs: os.environ[key] = str(kwargs[key]) def run_cli(self, dump=True, *args, **kwargs): - inline = list(itertools.chain( - *[['--%s' % key, str(value)] for key, value in kwargs.items() if value])) + inline = list( + itertools.chain( + *[["--%s" % key, str(value)] for key, value in kwargs.items() if value] + ) + ) if dump: - inline.append('--dump') + inline.append("--dump") inline.extend(args) return codecov.main(*inline, debug=True) def fake_report(self): - with open(self.filepath, 'w+') as f: - f.write('__data__') + with open(self.filepath, "w+") as f: + f.write("__data__") def delete(self, *paths): for path in paths: if os.path.exists(path): os.remove(path) - path = os.path.join(os.path.dirname(__file__), '../', path) + path = os.path.join(os.path.dirname(__file__), "../", path) if os.path.exists(path): os.remove(path) - @data('vendor', 'node_modules', 'js/generated/coverage', '__pycache__', 'coverage/instrumented', - 'build/lib', 'htmlcov', '.egg-info', '.git', '.tox', 'venv', '.venv-python-2.7') + @data( + "vendor", + "node_modules", + "js/generated/coverage", + "__pycache__", + "coverage/instrumented", + "build/lib", + "htmlcov", + ".egg-info", + ".git", + ".tox", + "venv", + ".venv-python-2.7", + ) def test_ignored_path(self, path): - self.assertTrue(bool(codecov.ignored_path( - '/home/ubuntu/' + path)), path + ' should be ignored') - self.assertTrue(bool(codecov.ignored_path( - '/home/ubuntu/' + path + '/more paths')), path + ' should be ignored') - - @data('coverage.xml', 'jacoco.xml', 'jacocoTestResults.xml', 'coverage.txt', - 'gcov.lst', 'cov.gcov', 'info.lcov', 'clover.xml', 'cobertura.xml', - 'luacov.report.out', 'gcov.info', 'nosetests.xml') + self.assertTrue( + bool(codecov.ignored_path("/home/ubuntu/" + path)), + path + " should be ignored", + ) + self.assertTrue( + bool(codecov.ignored_path("/home/ubuntu/" + path + "/more paths")), + path + " should be ignored", + ) + + @data( + "coverage.xml", + "jacoco.xml", + "jacocoTestResults.xml", + "coverage.txt", + "gcov.lst", + "cov.gcov", + "info.lcov", + "clover.xml", + "cobertura.xml", + "luacov.report.out", + "gcov.info", + "nosetests.xml", + ) def test_is_report(self, path): - self.assertFalse(bool(codecov.ignored_report( - '/home/file/' + path)), path + ' should not be ignored') - self.assertTrue(bool(codecov.is_report( - '/home/file/' + path)), path + ' should be a report') - - @data('.coverage.worker10', 'coverage.jade', 'include.lst', 'inputFiles.lst', - 'createdFiles.lst', 'scoverage.measurements.blackandwhite.xml', 'test_hello_coverage.txt', - 'conftest_blackwhite.c.gcov') + self.assertFalse( + bool(codecov.ignored_report("/home/file/" + path)), + path + " should not be ignored", + ) + self.assertTrue( + bool(codecov.is_report("/home/file/" + path)), path + " should be a report" + ) + + @data( + ".coverage.worker10", + "coverage.jade", + "include.lst", + "inputFiles.lst", + "createdFiles.lst", + "scoverage.measurements.blackandwhite.xml", + "test_hello_coverage.txt", + "conftest_blackwhite.c.gcov", + ) def test_ignore_report(self, path): - self.assertTrue(bool(codecov.ignored_report( - '/home/file/' + path)), path + ' should be ignored') + self.assertTrue( + bool(codecov.ignored_report("/home/file/" + path)), + path + " should be ignored", + ) def test_command(self): try: - self.run_cli(True, '--help') + self.run_cli(True, "--help") except SystemExit as e: - self.assertEqual(str(e), '0') + self.assertEqual(str(e), "0") else: raise Exception("help not shown") def test_exits_0(self): try: - sys.argv = [''] + sys.argv = [""] codecov.main() except SystemExit as e: - self.assertEqual(str(e), '0') + self.assertEqual(str(e), "0") else: raise Exception("did not exit") def test_exits_1(self): try: - sys.argv = [''] - codecov.main('--required') + sys.argv = [""] + codecov.main("--required") except SystemExit as e: - self.assertEqual(str(e), '1') + self.assertEqual(str(e), "1") else: raise Exception("did not exit") - @unittest.skipIf(os.getenv('CI') == "True" and os.getenv('APPVEYOR') == 'True', 'Skip AppVeyor CI test') + @unittest.skipIf( + os.getenv("CI") == "True" and os.getenv("APPVEYOR") == "True", + "Skip AppVeyor CI test", + ) def test_returns_none(self): - with patch('requests.post') as post: - with patch('requests.put') as put: - post.return_value = Mock(status_code=200, text='target\ns3') + with patch("requests.post") as post: + with patch("requests.put") as put: + post.return_value = Mock(status_code=200, text="target\ns3") put.return_value = Mock(status_code=200) - with open(self.filepath, 'w+') as f: - f.write('coverage data') - sys.argv = ['', '--commit=8ed84d96bc225deff66605486180cd555366806b', - '--branch=master', - '--token=473c8c5b-10ee-4d83-86c6-bfd72a185a27'] + with open(self.filepath, "w+") as f: + f.write("coverage data") + sys.argv = [ + "", + "--commit=8ed84d96bc225deff66605486180cd555366806b", + "--branch=master", + "--token=473c8c5b-10ee-4d83-86c6-bfd72a185a27", + ] self.assertEqual(codecov.main(), None) assert post.called and put.called - @unittest.skipIf(os.getenv('CI') == "True" and os.getenv('APPVEYOR') == 'True', 'Skip AppVeyor CI test') + @unittest.skipIf( + os.getenv("CI") == "True" and os.getenv("APPVEYOR") == "True", + "Skip AppVeyor CI test", + ) def test_send(self): - with patch('requests.post') as post: - with patch('requests.put') as put: - post.return_value = Mock(status_code=200, text='target\ns3') + with patch("requests.post") as post: + with patch("requests.put") as put: + post.return_value = Mock(status_code=200, text="target\ns3") put.return_value = Mock(status_code=200) - with open(self.filepath, 'w+') as f: - f.write('coverage data') - res = self.run_cli(False, commit='a'*40, - branch='master', token='') - self.assertEqual(res['result'].strip(), 'target') - assert 'https://codecov.io/upload/v4?' in post.call_args[0][0] - assert 'commit=aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa' in post.call_args[ - 0][0] - assert 'token=%3Ctoken%3E' in post.call_args[0][0] - assert 'branch=master' in post.call_args[0][0] - assert u'tests/test.py'.encode( - "utf-8") in put.call_args[1]['data'] + with open(self.filepath, "w+") as f: + f.write("coverage data") + res = self.run_cli( + False, commit="a" * 40, branch="master", token="" + ) + self.assertEqual(res["result"].strip(), "target") + assert "https://codecov.io/upload/v4?" in post.call_args[0][0] + assert ( + "commit=aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" + in post.call_args[0][0] + ) + assert "token=%3Ctoken%3E" in post.call_args[0][0] + assert "branch=master" in post.call_args[0][0] + assert u"tests/test.py".encode("utf-8") in put.call_args[1]["data"] def test_send_error(self): - with patch('requests.post') as post: - post.return_value = Mock(status_code=400, text='error') - with open(self.filepath, 'w+') as f: - f.write('coverage data') + with patch("requests.post") as post: + post.return_value = Mock(status_code=400, text="error") + with open(self.filepath, "w+") as f: + f.write("coverage data") try: - self.run_cli(False, token='not-a-token', - commit='a'*40, branch='master') + self.run_cli( + False, token="not-a-token", commit="a" * 40, branch="master" + ) except Exception: pass else: - raise Exception('400 never raised') + raise Exception("400 never raised") - @data((dict(commit='sha'), 'Missing repository upload token'), ) + @data((dict(commit="sha"), "Missing repository upload token"),) def test_require_branch(self, dd): (kwargs, reason) = dd # this is so we dont get branch for local git - self.set_env(JENKINS_URL='hello') + self.set_env(JENKINS_URL="hello") try: self.run_cli(**kwargs) except AssertionError as e: @@ -185,62 +295,77 @@ def test_require_branch(self, dd): else: raise Exception("Did not raise AssertionError") - @unittest.skipIf(os.getenv('CI') == "True" and os.getenv('APPVEYOR') == 'True', 'Skip AppVeyor CI test') + @unittest.skipIf( + os.getenv("CI") == "True" and os.getenv("APPVEYOR") == "True", + "Skip AppVeyor CI test", + ) def test_read_token_file(self): - with open(self.token, 'w+') as f: - f.write('a') - with open(self.filepath, 'w+') as f: - f.write('coverage data') - res = self.run_cli(token='@'+self.token, commit='a', branch='b') - self.assertIn('token=a', res['urlargs']) + with open(self.token, "w+") as f: + f.write("a") + with open(self.filepath, "w+") as f: + f.write("coverage data") + res = self.run_cli(token="@" + self.token, commit="a", branch="b") + self.assertIn("token=a", res["urlargs"]) def test_bowerrc(self): - with open(self.bowerrc, 'w+') as f: + with open(self.bowerrc, "w+") as f: f.write('{"directory": "tests"}') - with open(self.filepath, 'w+') as f: - f.write('coverage data') + with open(self.filepath, "w+") as f: + f.write("coverage data") try: self.run_cli(**self.defaults) except AssertionError as e: - self.assertEqual(str(e), "No coverage report found") + self.assertEqual(str(e), "No coverage report found") else: raise Exception("Did not raise AssertionError") def test_disable_search(self): self.fake_report() try: - self.run_cli(disable='search', token='a', branch='b', commit='c') + self.run_cli(disable="search", token="a", branch="b", commit="c") except AssertionError as e: self.assertEqual(str(e), "No coverage report found") else: raise Exception("Did not raise AssertionError") - @unittest.skipIf(os.getenv('CI') == "True" and os.getenv('APPVEYOR') == 'True', 'Skip AppVeyor CI test') + @unittest.skipIf( + os.getenv("CI") == "True" and os.getenv("APPVEYOR") == "True", + "Skip AppVeyor CI test", + ) def test_prefix(self): self.fake_report() - res = self.run_cli(prefix='/foo/bar/', dump=True, - token='a', branch='b', commit='c') - assert '\nfoo/bar/.gitignore' in res['reports'] + res = self.run_cli( + prefix="/foo/bar/", dump=True, token="a", branch="b", commit="c" + ) + assert "\nfoo/bar/.gitignore" in res["reports"] def write_c(self): - c = '\n'.join(('#include ', - 'static int t = 1;' - 'int main()', '{', - 'if (t)', 'printf("on this line\\n");', - 'else', 'printf("but not here\\n");', - 'return 0;', '}')) - with open(os.path.join(os.path.dirname(__file__), '../hello.c'), 'w+') as f: + c = "\n".join( + ( + "#include ", + "static int t = 1;" "int main()", + "{", + "if (t)", + 'printf("on this line\\n");', + "else", + 'printf("but not here\\n");', + "return 0;", + "}", + ) + ) + with open(os.path.join(os.path.dirname(__file__), "../hello.c"), "w+") as f: f.write(c) - codecov.try_to_run(['clang', '-coverage', '-O0', - 'hello.c', '-o', 'hello', '&&', './hello']) + codecov.try_to_run( + ["clang", "-coverage", "-O0", "hello.c", "-o", "hello", "&&", "./hello"] + ) def test_disable_gcov(self): - if self._env.get('TRAVIS') == 'true': + if self._env.get("TRAVIS") == "true": self.write_c() try: - self.run_cli(disable='gcov', token='a', branch='b', commit='c') + self.run_cli(disable="gcov", token="a", branch="b", commit="c") except AssertionError as e: - self.assertEqual(os.path.exists('hello.c.gcov'), False) + self.assertEqual(os.path.exists("hello.c.gcov"), False) self.assertEqual(str(e), "No coverage report found") else: raise Exception("Did not raise AssertionError") @@ -259,68 +384,74 @@ def test_gcov(self): # self.skipTest("Skipped, works on Travis only.") def test_disable_detect(self): - self.set_env(JENKINS_URL='a', GIT_BRANCH='b', - GIT_COMMIT='c', CODECOV_TOKEN='d') + self.set_env(JENKINS_URL="a", GIT_BRANCH="b", GIT_COMMIT="c", CODECOV_TOKEN="d") self.fake_report() try: - self.run_cli(disable='detect') + self.run_cli(disable="detect") except AssertionError as e: self.assertEqual( - str(e), "Commit sha is missing. Please specify via --commit=:sha") + str(e), "Commit sha is missing. Please specify via --commit=:sha" + ) else: raise Exception("Did not raise AssertionError") - @unittest.skipIf(os.getenv('CI') == "True" and os.getenv('APPVEYOR') == 'True', 'Skip AppVeyor CI test') + @unittest.skipIf( + os.getenv("CI") == "True" and os.getenv("APPVEYOR") == "True", + "Skip AppVeyor CI test", + ) def test_bowerrc_none(self): - with open(self.bowerrc, 'w+') as f: + with open(self.bowerrc, "w+") as f: f.write('{"other_key": "tests"}') - with open(self.filepath, 'w+') as f: - f.write('coverage data') + with open(self.filepath, "w+") as f: + f.write("coverage data") res = self.run_cli(**self.defaults) - self.assertIn('tests/test.py', res['reports']) + self.assertIn("tests/test.py", res["reports"]) - @unittest.skipIf(os.getenv('CI') == "True" and os.getenv('APPVEYOR') == 'True', 'Skip AppVeyor CI test') + @unittest.skipIf( + os.getenv("CI") == "True" and os.getenv("APPVEYOR") == "True", + "Skip AppVeyor CI test", + ) def test_discovers(self): - with open(self.jacoco, 'w+') as f: - f.write('') - with open(self.filepath, 'w+') as f: - f.write('coverage data') + with open(self.jacoco, "w+") as f: + f.write("") + with open(self.filepath, "w+") as f: + f.write("coverage data") res = self.run_cli(**self.defaults) - self.assertIn('coverage.xml', res['reports']) - self.assertIn('coverage data', res['reports']) - self.assertIn('jacoco.xml', res['reports']) - self.assertIn('', res['reports']) + self.assertIn("coverage.xml", res["reports"]) + self.assertIn("coverage data", res["reports"]) + self.assertIn("jacoco.xml", res["reports"]) + self.assertIn("", res["reports"]) def test_not_jacoco(self): - with open(self.filepath, 'w+') as f: - f.write('') - res = self.run_cli(file='tests/coverage.xml', **self.defaults) - res = res['reports'].split('<<<<<< network\n')[1].splitlines() - self.assertEqual(res[0], '# path=tests/coverage.xml') - self.assertEqual(res[1], '') + with open(self.filepath, "w+") as f: + f.write("") + res = self.run_cli(file="tests/coverage.xml", **self.defaults) + res = res["reports"].split("<<<<<< network\n")[1].splitlines() + self.assertEqual(res[0], "# path=tests/coverage.xml") + self.assertEqual(res[1], "") def test_run_coverage(self): - self.skipTest('Not sure how to pull off atm') - with open(self.coverage, 'w+') as f: + self.skipTest("Not sure how to pull off atm") + with open(self.coverage, "w+") as f: f.write(pickle.dumps()) res = self.run_cli(**self.defaults) - self.assertIn('', res['reports']) + self.assertIn('', res["reports"]) def test_run_coverage_fails(self): - with open(self.coverage, 'w+') as f: - f.write('bad data') + with open(self.coverage, "w+") as f: + f.write("bad data") try: self.run_cli(**self.defaults) except AssertionError as e: - self.assertEqual(str(e), 'No coverage report found') + self.assertEqual(str(e), "No coverage report found") else: raise Exception("Did not raise AssertionError") def test_include_env(self): - self.set_env(HELLO='WORLD') + self.set_env(HELLO="WORLD") self.fake_report() - res = self.run_cli(env='HELLO', file=self.filepath, **self.defaults) - self.assertIn('HELLO=WORLD', res['reports']) + res = self.run_cli(env="HELLO", file=self.filepath, **self.defaults) + self.assertIn("HELLO=WORLD", res["reports"]) def test_none_found(self): try: @@ -331,295 +462,364 @@ def test_none_found(self): raise Exception("Did not raise AssertionError") def test_sanitize_arg(self): - self.assertEqual(codecov.sanitize_arg( - '', '& echo test > vuln1.txt'), ' echo test > vuln1.txt') + self.assertEqual( + codecov.sanitize_arg("", "& echo test > vuln1.txt"), + " echo test > vuln1.txt", + ) - @unittest.skipUnless(os.getenv('JENKINS_URL'), 'Skip Jenkins CI test') + @unittest.skipUnless(os.getenv("JENKINS_URL"), "Skip Jenkins CI test") def test_ci_jenkins(self): - self.set_env(BUILD_URL='https://....', - JENKINS_URL='https://....', - GIT_BRANCH='master', - GIT_COMMIT='c739768fcac68144a3a6d82305b9c4106934d31a', - BUILD_NUMBER='41', - CODECOV_TOKEN='token') + self.set_env( + BUILD_URL="https://....", + JENKINS_URL="https://....", + GIT_BRANCH="master", + GIT_COMMIT="c739768fcac68144a3a6d82305b9c4106934d31a", + BUILD_NUMBER="41", + CODECOV_TOKEN="token", + ) self.fake_report() res = self.run_cli() - self.assertEqual(res['query']['service'], 'jenkins') - self.assertEqual(res['query']['commit'], - 'c739768fcac68144a3a6d82305b9c4106934d31a') - self.assertEqual(res['query']['build'], '41') - self.assertEqual(res['query']['build_url'], 'https://....') - self.assertEqual(res['query']['pr'], '') - self.assertEqual(res['query']['branch'], 'master') - self.assertEqual(res['codecov'].token, 'token') - - @unittest.skipUnless(os.getenv('JENKINS_URL'), 'Skip Jenkins CI test') + self.assertEqual(res["query"]["service"], "jenkins") + self.assertEqual( + res["query"]["commit"], "c739768fcac68144a3a6d82305b9c4106934d31a" + ) + self.assertEqual(res["query"]["build"], "41") + self.assertEqual(res["query"]["build_url"], "https://....") + self.assertEqual(res["query"]["pr"], "") + self.assertEqual(res["query"]["branch"], "master") + self.assertEqual(res["codecov"].token, "token") + + @unittest.skipUnless(os.getenv("JENKINS_URL"), "Skip Jenkins CI test") def test_ci_jenkins_env(self): - self.set_env(JENKINS_URL='https://....', - BUILD_URL='https://....', - ghprbSourceBranch='master', - ghprbActualCommit='c739768fcac68144a3a6d82305b9c4106934d31a', - ghprbPullId='1', - BUILD_NUMBER='41', - CODECOV_TOKEN='token') + self.set_env( + JENKINS_URL="https://....", + BUILD_URL="https://....", + ghprbSourceBranch="master", + ghprbActualCommit="c739768fcac68144a3a6d82305b9c4106934d31a", + ghprbPullId="1", + BUILD_NUMBER="41", + CODECOV_TOKEN="token", + ) self.fake_report() res = self.run_cli() - self.assertEqual(res['query']['service'], 'jenkins') - self.assertEqual(res['query']['commit'], - 'c739768fcac68144a3a6d82305b9c4106934d31a') - self.assertEqual(res['query']['build'], '41') - self.assertEqual(res['query']['build_url'], 'https://....') - self.assertEqual(res['query']['pr'], '1') - self.assertEqual(res['query']['branch'], 'master') - self.assertEqual(res['codecov'].token, 'token') - - @unittest.skipUnless(os.getenv('JENKINS_URL'), 'Skip Jenkins CI test') + self.assertEqual(res["query"]["service"], "jenkins") + self.assertEqual( + res["query"]["commit"], "c739768fcac68144a3a6d82305b9c4106934d31a" + ) + self.assertEqual(res["query"]["build"], "41") + self.assertEqual(res["query"]["build_url"], "https://....") + self.assertEqual(res["query"]["pr"], "1") + self.assertEqual(res["query"]["branch"], "master") + self.assertEqual(res["codecov"].token, "token") + + @unittest.skipUnless(os.getenv("JENKINS_URL"), "Skip Jenkins CI test") def test_ci_jenkins_blue_ocean(self): - self.set_env(JENKINS_URL='https://....', - BUILD_URL='https://....', - BRANCH_NAME='master', - CHANGE_ID='1', - BUILD_NUMBER='41', - CODECOV_TOKEN='token') + self.set_env( + JENKINS_URL="https://....", + BUILD_URL="https://....", + BRANCH_NAME="master", + CHANGE_ID="1", + BUILD_NUMBER="41", + CODECOV_TOKEN="token", + ) self.fake_report() res = self.run_cli() - self.assertEqual(res['query']['service'], 'jenkins') - self.assertEqual(res['query']['commit'], codecov.check_output( - ("git", "rev-parse", "HEAD"))) - self.assertEqual(res['query']['build'], '41') - self.assertEqual(res['query']['build_url'], 'https://....') - self.assertEqual(res['query']['pr'], '1') - self.assertEqual(res['query']['branch'], 'master') - self.assertEqual(res['codecov'].token, 'token') - - @unittest.skipUnless(os.getenv('CI') == 'true' - and os.getenv('TRAVIS') == "true" - and os.getenv('SHIPPABLE') != 'true', - 'Skip Travis CI test') + self.assertEqual(res["query"]["service"], "jenkins") + self.assertEqual( + res["query"]["commit"], codecov.check_output(("git", "rev-parse", "HEAD")) + ) + self.assertEqual(res["query"]["build"], "41") + self.assertEqual(res["query"]["build_url"], "https://....") + self.assertEqual(res["query"]["pr"], "1") + self.assertEqual(res["query"]["branch"], "master") + self.assertEqual(res["codecov"].token, "token") + + @unittest.skipUnless( + os.getenv("CI") == "true" + and os.getenv("TRAVIS") == "true" + and os.getenv("SHIPPABLE") != "true", + "Skip Travis CI test", + ) def test_ci_travis(self): - self.set_env(TRAVIS="true", - TRAVIS_BRANCH="master", - TRAVIS_COMMIT="c739768fcac68144a3a6d82305b9c4106934d31a", - TRAVIS_REPO_SLUG='owner/repo', - TRAVIS_JOB_ID="33116958", - TRAVIS_TAG="v1.1.1", - TRAVIS_JOB_NUMBER="4.1") + self.set_env( + TRAVIS="true", + TRAVIS_BRANCH="master", + TRAVIS_COMMIT="c739768fcac68144a3a6d82305b9c4106934d31a", + TRAVIS_REPO_SLUG="owner/repo", + TRAVIS_JOB_ID="33116958", + TRAVIS_TAG="v1.1.1", + TRAVIS_JOB_NUMBER="4.1", + ) self.fake_report() res = self.run_cli() - self.assertEqual(res['query']['service'], 'travis') - self.assertEqual(res['query']['commit'], - 'c739768fcac68144a3a6d82305b9c4106934d31a') - self.assertEqual(res['query']['build'], '4.1') - self.assertEqual(res['query']['pr'], '') - self.assertEqual(res['query']['tag'], 'v1.1.1') - self.assertEqual(res['query']['slug'], 'owner/repo') - self.assertEqual(res['query']['branch'], 'master') - self.assertEqual(res['codecov'].token, '') - - @unittest.skipUnless(os.getenv('CI') == 'true' and os.getenv('CI_NAME') == 'codeship', 'Skip Codeship CI test') + self.assertEqual(res["query"]["service"], "travis") + self.assertEqual( + res["query"]["commit"], "c739768fcac68144a3a6d82305b9c4106934d31a" + ) + self.assertEqual(res["query"]["build"], "4.1") + self.assertEqual(res["query"]["pr"], "") + self.assertEqual(res["query"]["tag"], "v1.1.1") + self.assertEqual(res["query"]["slug"], "owner/repo") + self.assertEqual(res["query"]["branch"], "master") + self.assertEqual(res["codecov"].token, "") + + @unittest.skipUnless( + os.getenv("CI") == "true" and os.getenv("CI_NAME") == "codeship", + "Skip Codeship CI test", + ) def test_ci_codeship(self): - self.set_env(CI_NAME='codeship', - CI_BRANCH='master', - CI_BUILD_NUMBER='20', - CI_BUILD_URL='https://codeship.io/build/1', - CI_COMMIT_ID='743b04806ea677403aa2ff26c6bdeb85005de658', - CODECOV_TOKEN='token') + self.set_env( + CI_NAME="codeship", + CI_BRANCH="master", + CI_BUILD_NUMBER="20", + CI_BUILD_URL="https://codeship.io/build/1", + CI_COMMIT_ID="743b04806ea677403aa2ff26c6bdeb85005de658", + CODECOV_TOKEN="token", + ) self.fake_report() res = self.run_cli() - self.assertEqual(res['query']['service'], 'codeship') - self.assertEqual(res['query']['commit'], - '743b04806ea677403aa2ff26c6bdeb85005de658') - self.assertEqual(res['query']['build'], '20') - self.assertEqual(res['query']['build_url'], - 'https://codeship.io/build/1') - self.assertEqual(res['query']['pr'], '') - self.assertEqual(res['query']['branch'], 'master') - self.assertEqual(res['codecov'].token, 'token') - - @unittest.skipUnless(os.getenv('CI') == 'true' and os.getenv('CIRCLECI') == 'true', 'Skip Circle CI test') + self.assertEqual(res["query"]["service"], "codeship") + self.assertEqual( + res["query"]["commit"], "743b04806ea677403aa2ff26c6bdeb85005de658" + ) + self.assertEqual(res["query"]["build"], "20") + self.assertEqual(res["query"]["build_url"], "https://codeship.io/build/1") + self.assertEqual(res["query"]["pr"], "") + self.assertEqual(res["query"]["branch"], "master") + self.assertEqual(res["codecov"].token, "token") + + @unittest.skipUnless( + os.getenv("CI") == "true" and os.getenv("CIRCLECI") == "true", + "Skip Circle CI test", + ) def test_ci_circleci(self): - self.set_env(CIRCLECI='true', - CIRCLE_BUILD_NUM='57', - CIRCLE_NODE_INDEX='1', - CIRCLE_PR_NUMBER='1', - CIRCLE_BRANCH='master', - CIRCLE_PROJECT_USERNAME='owner', - CIRCLE_PROJECT_REPONAME='repo', - CIRCLE_SHA1='d653b934ed59c1a785cc1cc79d08c9aaa4eba73b') + self.set_env( + CIRCLECI="true", + CIRCLE_BUILD_NUM="57", + CIRCLE_NODE_INDEX="1", + CIRCLE_PR_NUMBER="1", + CIRCLE_BRANCH="master", + CIRCLE_PROJECT_USERNAME="owner", + CIRCLE_PROJECT_REPONAME="repo", + CIRCLE_SHA1="d653b934ed59c1a785cc1cc79d08c9aaa4eba73b", + ) self.fake_report() res = self.run_cli() - self.assertEqual(res['query']['service'], 'circleci') - self.assertEqual(res['query']['commit'], - 'd653b934ed59c1a785cc1cc79d08c9aaa4eba73b') - self.assertEqual(res['query']['build'], '57.1') - self.assertEqual(res['query']['pr'], '1') - self.assertEqual(res['query']['slug'], 'owner/repo') - self.assertEqual(res['query']['branch'], 'master') - - @unittest.skipUnless(os.getenv('CI') == 'true' and os.getenv('BUILDKITE') == 'true', 'Skip BuildKit CI test') + self.assertEqual(res["query"]["service"], "circleci") + self.assertEqual( + res["query"]["commit"], "d653b934ed59c1a785cc1cc79d08c9aaa4eba73b" + ) + self.assertEqual(res["query"]["build"], "57.1") + self.assertEqual(res["query"]["pr"], "1") + self.assertEqual(res["query"]["slug"], "owner/repo") + self.assertEqual(res["query"]["branch"], "master") + + @unittest.skipUnless( + os.getenv("CI") == "true" and os.getenv("BUILDKITE") == "true", + "Skip BuildKit CI test", + ) def test_ci_buildkite(self): - self.set_env(CI='true', - BUILDKITE='true', - BUILDKITE_BUILD_NUMBER='57', - BUILDKITE_JOB_ID='1', - BUILDKITE_BRANCH='master', - BUILDKITE_PROJECT_SLUG='owner/repo', - BUILDKITE_COMMIT='d653b934ed59c1a785cc1cc79d08c9aaa4eba73b', - CODECOV_TOKEN='token') + self.set_env( + CI="true", + BUILDKITE="true", + BUILDKITE_BUILD_NUMBER="57", + BUILDKITE_JOB_ID="1", + BUILDKITE_BRANCH="master", + BUILDKITE_PROJECT_SLUG="owner/repo", + BUILDKITE_COMMIT="d653b934ed59c1a785cc1cc79d08c9aaa4eba73b", + CODECOV_TOKEN="token", + ) self.fake_report() res = self.run_cli() - self.assertEqual(res['query']['service'], 'buildkite') - self.assertEqual(res['query']['commit'], - 'd653b934ed59c1a785cc1cc79d08c9aaa4eba73b') - self.assertEqual(res['query']['build'], '57.1') - self.assertEqual(res['query']['slug'], 'owner/repo') - self.assertEqual(res['query']['branch'], 'master') - self.assertEqual(res['codecov'].token, 'token') - - @unittest.skipUnless(os.getenv('CI') == 'true' and os.getenv('SEMAPHORE') == 'true', 'Skip Semaphore CI test') + self.assertEqual(res["query"]["service"], "buildkite") + self.assertEqual( + res["query"]["commit"], "d653b934ed59c1a785cc1cc79d08c9aaa4eba73b" + ) + self.assertEqual(res["query"]["build"], "57.1") + self.assertEqual(res["query"]["slug"], "owner/repo") + self.assertEqual(res["query"]["branch"], "master") + self.assertEqual(res["codecov"].token, "token") + + @unittest.skipUnless( + os.getenv("CI") == "true" and os.getenv("SEMAPHORE") == "true", + "Skip Semaphore CI test", + ) def test_ci_semaphore(self): - self.set_env(SEMAPHORE='true', - BRANCH_NAME='master', - SEMAPHORE_BUILD_NUMBER='10', - SEMAPHORE_CURRENT_THREAD='1', - SEMAPHORE_REPO_SLUG='owner/repo', - REVISION='743b04806ea677403aa2ff26c6bdeb85005de658', - CODECOV_TOKEN='token') + self.set_env( + SEMAPHORE="true", + BRANCH_NAME="master", + SEMAPHORE_BUILD_NUMBER="10", + SEMAPHORE_CURRENT_THREAD="1", + SEMAPHORE_REPO_SLUG="owner/repo", + REVISION="743b04806ea677403aa2ff26c6bdeb85005de658", + CODECOV_TOKEN="token", + ) self.fake_report() res = self.run_cli() - self.assertEqual(res['query']['service'], 'semaphore') - self.assertEqual(res['query']['commit'], - '743b04806ea677403aa2ff26c6bdeb85005de658') - self.assertEqual(res['query']['build'], '10.1') - self.assertEqual(res['query']['slug'], 'owner/repo') - self.assertEqual(res['query']['branch'], 'master') - - @unittest.skipUnless(os.getenv('CI') == "drone" and os.getenv('DRONE') == "true", 'Skip Drone CI test') + self.assertEqual(res["query"]["service"], "semaphore") + self.assertEqual( + res["query"]["commit"], "743b04806ea677403aa2ff26c6bdeb85005de658" + ) + self.assertEqual(res["query"]["build"], "10.1") + self.assertEqual(res["query"]["slug"], "owner/repo") + self.assertEqual(res["query"]["branch"], "master") + + @unittest.skipUnless( + os.getenv("CI") == "drone" and os.getenv("DRONE") == "true", + "Skip Drone CI test", + ) def test_ci_drone(self): - self.set_env(CI='drone', - DRONE='true', - DRONE_BUILD_NUMBER='10', - DRONE_BRANCH='master', - DRONE_BUILD_LINK='https://drone.io/github/builds/1', - CODECOV_TOKEN='token') + self.set_env( + CI="drone", + DRONE="true", + DRONE_BUILD_NUMBER="10", + DRONE_BRANCH="master", + DRONE_BUILD_LINK="https://drone.io/github/builds/1", + CODECOV_TOKEN="token", + ) self.fake_report() res = self.run_cli() - self.assertEqual(res['query']['service'], 'drone.io') - self.assertEqual(res['query']['commit'], codecov.check_output( - ("git", "rev-parse", "HEAD"))) - self.assertEqual(res['query']['build'], '10') - self.assertEqual(res['query']['build_url'], - 'https://drone.io/github/builds/1') - self.assertEqual(res['codecov'].token, 'token') - - @unittest.skipUnless(os.getenv('SHIPPABLE') == "true", 'Skip Shippable CI test') + self.assertEqual(res["query"]["service"], "drone.io") + self.assertEqual( + res["query"]["commit"], codecov.check_output(("git", "rev-parse", "HEAD")) + ) + self.assertEqual(res["query"]["build"], "10") + self.assertEqual(res["query"]["build_url"], "https://drone.io/github/builds/1") + self.assertEqual(res["codecov"].token, "token") + + @unittest.skipUnless(os.getenv("SHIPPABLE") == "true", "Skip Shippable CI test") def test_ci_shippable(self): - self.set_env(SHIPPABLE='true', - BUILD_NUMBER='10', - REPO_NAME='owner/repo', - BRANCH='master', - BUILD_URL='https://shippable.com/...', - COMMIT='743b04806ea677403aa2ff26c6bdeb85005de658', - CODECOV_TOKEN='token') + self.set_env( + SHIPPABLE="true", + BUILD_NUMBER="10", + REPO_NAME="owner/repo", + BRANCH="master", + BUILD_URL="https://shippable.com/...", + COMMIT="743b04806ea677403aa2ff26c6bdeb85005de658", + CODECOV_TOKEN="token", + ) self.fake_report() res = self.run_cli() - self.assertEqual(res['query']['service'], 'shippable') - self.assertEqual(res['query']['commit'], - '743b04806ea677403aa2ff26c6bdeb85005de658') - self.assertEqual(res['query']['build'], '10') - self.assertEqual(res['query']['slug'], 'owner/repo') - self.assertEqual(res['query']['build_url'], - 'https://shippable.com/...') - self.assertEqual(res['codecov'].token, 'token') + self.assertEqual(res["query"]["service"], "shippable") + self.assertEqual( + res["query"]["commit"], "743b04806ea677403aa2ff26c6bdeb85005de658" + ) + self.assertEqual(res["query"]["build"], "10") + self.assertEqual(res["query"]["slug"], "owner/repo") + self.assertEqual(res["query"]["build_url"], "https://shippable.com/...") + self.assertEqual(res["codecov"].token, "token") # @unittest.skipUnless(os.getenv('CI') == "True" and os.getenv('APPVEYOR') == 'True', 'Skip AppVeyor CI test') - @unittest.skip('Skip AppVeyor test') + @unittest.skip("Skip AppVeyor test") def test_ci_appveyor(self): - self.set_env(APPVEYOR='True', - CI='True', - APPVEYOR_JOB_ID='9r2qufuu8', - APPVEYOR_BUILD_VERSION='1.2.3', - APPVEYOR_ACCOUNT_NAME='owner', - APPVEYOR_PROJECT_SLUG='repo', - APPVEYOR_PULL_REQUEST_NUMBER='1', - APPVEYOR_REPO_BRANCH='master', - APPVEYOR_REPO_NAME='owner/repo', - APPVEYOR_REPO_COMMIT='d653b934ed59c1a785cc1cc79d08c9aaa4eba73b', - CODECOV_TOKEN='token') + self.set_env( + APPVEYOR="True", + CI="True", + APPVEYOR_JOB_ID="9r2qufuu8", + APPVEYOR_BUILD_VERSION="1.2.3", + APPVEYOR_ACCOUNT_NAME="owner", + APPVEYOR_PROJECT_SLUG="repo", + APPVEYOR_PULL_REQUEST_NUMBER="1", + APPVEYOR_REPO_BRANCH="master", + APPVEYOR_REPO_NAME="owner/repo", + APPVEYOR_REPO_COMMIT="d653b934ed59c1a785cc1cc79d08c9aaa4eba73b", + CODECOV_TOKEN="token", + ) self.fake_report() res = self.run_cli(file=self.filepath) - self.assertEqual(res['query']['service'], 'appveyor') - self.assertEqual(res['query']['commit'], - 'd653b934ed59c1a785cc1cc79d08c9aaa4eba73b') - self.assertEqual(res['query']['job'], 'owner/repo/1.2.3') - self.assertEqual(res['query']['build'], '9r2qufuu8') - self.assertEqual(res['query']['slug'], 'owner/repo') - self.assertEqual(res['query']['pr'], '1') - self.assertEqual(res['codecov'].token, 'token') - - @unittest.skipUnless(os.getenv('CI') == "true" and os.getenv('WERCKER_GIT_BRANCH'), 'Skip Wercker CI test') + self.assertEqual(res["query"]["service"], "appveyor") + self.assertEqual( + res["query"]["commit"], "d653b934ed59c1a785cc1cc79d08c9aaa4eba73b" + ) + self.assertEqual(res["query"]["job"], "owner/repo/1.2.3") + self.assertEqual(res["query"]["build"], "9r2qufuu8") + self.assertEqual(res["query"]["slug"], "owner/repo") + self.assertEqual(res["query"]["pr"], "1") + self.assertEqual(res["codecov"].token, "token") + + @unittest.skipUnless( + os.getenv("CI") == "true" and os.getenv("WERCKER_GIT_BRANCH"), + "Skip Wercker CI test", + ) def test_ci_wercker(self): - self.set_env(WERCKER_GIT_BRANCH='master', - WERCKER_MAIN_PIPELINE_STARTED='1399372237', - WERCKER_GIT_OWNER='owner', - WERCKER_GIT_REPOSITORY='repo', - WERCKER_GIT_COMMIT='d653b934ed59c1a785cc1cc79d08c9aaa4eba73b', - CODECOV_TOKEN='token') + self.set_env( + WERCKER_GIT_BRANCH="master", + WERCKER_MAIN_PIPELINE_STARTED="1399372237", + WERCKER_GIT_OWNER="owner", + WERCKER_GIT_REPOSITORY="repo", + WERCKER_GIT_COMMIT="d653b934ed59c1a785cc1cc79d08c9aaa4eba73b", + CODECOV_TOKEN="token", + ) self.fake_report() res = self.run_cli() - self.assertEqual(res['query']['service'], 'wercker') - self.assertEqual(res['query']['commit'], - 'd653b934ed59c1a785cc1cc79d08c9aaa4eba73b') - self.assertEqual(res['query']['build'], '1399372237') - self.assertEqual(res['query']['slug'], 'owner/repo') - self.assertEqual(res['codecov'].token, 'token') - - @unittest.skipUnless(os.getenv('CI') == "true" and os.getenv('MAGNUM') == 'true', 'Skip Magnum CI test') + self.assertEqual(res["query"]["service"], "wercker") + self.assertEqual( + res["query"]["commit"], "d653b934ed59c1a785cc1cc79d08c9aaa4eba73b" + ) + self.assertEqual(res["query"]["build"], "1399372237") + self.assertEqual(res["query"]["slug"], "owner/repo") + self.assertEqual(res["codecov"].token, "token") + + @unittest.skipUnless( + os.getenv("CI") == "true" and os.getenv("MAGNUM") == "true", + "Skip Magnum CI test", + ) def test_ci_magnum(self): - self.set_env(CI_BRANCH='master', - CI_BUILD_NUMBER='1399372237', - MAGNUM='true', - CI='true', - CI_COMMIT='d653b934ed59c1a785cc1cc79d08c9aaa4eba73b', - CODECOV_TOKEN='token') + self.set_env( + CI_BRANCH="master", + CI_BUILD_NUMBER="1399372237", + MAGNUM="true", + CI="true", + CI_COMMIT="d653b934ed59c1a785cc1cc79d08c9aaa4eba73b", + CODECOV_TOKEN="token", + ) self.fake_report() res = self.run_cli() - self.assertEqual(res['query']['service'], 'magnum') - self.assertEqual(res['query']['commit'], - 'd653b934ed59c1a785cc1cc79d08c9aaa4eba73b') - self.assertEqual(res['query']['build'], '1399372237') - self.assertEqual(res['codecov'].token, 'token') - - @unittest.skipUnless(os.getenv('CI_SERVER_NAME', '').startswith("GitLab"), 'Skip GitLab CI test') + self.assertEqual(res["query"]["service"], "magnum") + self.assertEqual( + res["query"]["commit"], "d653b934ed59c1a785cc1cc79d08c9aaa4eba73b" + ) + self.assertEqual(res["query"]["build"], "1399372237") + self.assertEqual(res["codecov"].token, "token") + + @unittest.skipUnless( + os.getenv("CI_SERVER_NAME", "").startswith("GitLab"), "Skip GitLab CI test" + ) def test_ci_gitlab(self): - self.set_env(CI_BUILD_REF_NAME='master', - CI_BUILD_ID='1399372237', - CI_BUILD_REPO='https://gitlab.com/owner/repo.git', - CI_SERVER_NAME='GitLab CI', - CI_BUILD_REF='d653b934ed59c1a785cc1cc79d08c9aaa4eba73b', - HOME='/', - CI_PROJECT_DIR=os.getcwd().strip('/'), - CODECOV_TOKEN='token') + self.set_env( + CI_BUILD_REF_NAME="master", + CI_BUILD_ID="1399372237", + CI_BUILD_REPO="https://gitlab.com/owner/repo.git", + CI_SERVER_NAME="GitLab CI", + CI_BUILD_REF="d653b934ed59c1a785cc1cc79d08c9aaa4eba73b", + HOME="/", + CI_PROJECT_DIR=os.getcwd().strip("/"), + CODECOV_TOKEN="token", + ) self.fake_report() res = self.run_cli() - self.assertEqual(res['query']['service'], 'gitlab') - self.assertEqual(res['query']['commit'], - 'd653b934ed59c1a785cc1cc79d08c9aaa4eba73b') - self.assertEqual(res['query']['build'], '1399372237') - self.assertEqual(res['query']['slug'], 'owner/repo') - self.assertEqual(res['codecov'].token, 'token') - - @unittest.skip('Skip CI None') + self.assertEqual(res["query"]["service"], "gitlab") + self.assertEqual( + res["query"]["commit"], "d653b934ed59c1a785cc1cc79d08c9aaa4eba73b" + ) + self.assertEqual(res["query"]["build"], "1399372237") + self.assertEqual(res["query"]["slug"], "owner/repo") + self.assertEqual(res["codecov"].token, "token") + + @unittest.skip("Skip CI None") def test_ci_none(self): - self.set_env(CODECOV_TOKEN='token') + self.set_env(CODECOV_TOKEN="token") self.fake_report() - res = self.run_cli(build=10, - commit='d653b934ed59c1a785cc1cc79d08c9aaa4eba73b', - slug='owner/repo', - token='token') - self.assertEqual(res['query'].get('service'), None) - self.assertEqual(res['query']['commit'], - 'd653b934ed59c1a785cc1cc79d08c9aaa4eba73b') - self.assertEqual(res['query']['build'], '10') - self.assertEqual(res['query']['slug'], 'owner/repo') - self.assertEqual(res['codecov'].token, 'token') + res = self.run_cli( + build=10, + commit="d653b934ed59c1a785cc1cc79d08c9aaa4eba73b", + slug="owner/repo", + token="token", + ) + self.assertEqual(res["query"].get("service"), None) + self.assertEqual( + res["query"]["commit"], "d653b934ed59c1a785cc1cc79d08c9aaa4eba73b" + ) + self.assertEqual(res["query"]["build"], "10") + self.assertEqual(res["query"]["slug"], "owner/repo") + self.assertEqual(res["codecov"].token, "token") From 1caf8366faefdbc031cf8da6e0821b364caefcdc Mon Sep 17 00:00:00 2001 From: Thiago Ramos Date: Mon, 18 May 2020 01:52:41 -0300 Subject: [PATCH 079/144] Removing extra url header Now that we have pre-signed puts, we don't need to use presigned headers. In fact, since they are added post-signing, the system is not responding well to them --- codecov/__init__.py | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/codecov/__init__.py b/codecov/__init__.py index d5d72354..761ad77a 100644 --- a/codecov/__init__.py +++ b/codecov/__init__.py @@ -1044,10 +1044,7 @@ def main(*argv, **kwargs): s3 = requests.put( upload_url, data=reports, - headers={ - "Content-Type": "text/plain", - "x-amz-acl": "public-read", - }, + headers={"Content-Type": "text/plain",}, ) s3.raise_for_status() assert s3.status_code == 200 From 0f080195145e5270b2a4283472552ba438ceb562 Mon Sep 17 00:00:00 2001 From: Joe Becher Date: Mon, 18 May 2020 09:00:10 -0400 Subject: [PATCH 080/144] Update version --- setup.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup.py b/setup.py index d6704387..b1619359 100644 --- a/setup.py +++ b/setup.py @@ -1,7 +1,7 @@ #!/usr/bin/env python from setuptools import setup -version = "2.0.21" +version = "2.1.0" classifiers = [ "Development Status :: 5 - Production/Stable", "Environment :: Plugins", From dd16c654582e28613789882d1568a7e249ffdbf0 Mon Sep 17 00:00:00 2001 From: Thiago Ramos Date: Mon, 18 May 2020 13:45:21 -0300 Subject: [PATCH 081/144] Fixing command for when neither hg or git are available Sometimes not hg or git are available to run. On those cases, 'try_to_run' will return None, and we need to not stringify that None --- codecov/__init__.py | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/codecov/__init__.py b/codecov/__init__.py index 761ad77a..2a2a3f69 100644 --- a/codecov/__init__.py +++ b/codecov/__init__.py @@ -229,17 +229,15 @@ def _add_env_if_not_empty(lst, value): def generate_toc(root): - return ( - str( - ( - try_to_run(["git", "ls-files"], cwd=root) - or try_to_run(["git", "ls-files"]) - or try_to_run(["hg", "locate"], cwd=root) - or try_to_run(["hg", "locate"]) - ) - ).strip() - or "" + res = ( + try_to_run(["git", "ls-files"], cwd=root) + or try_to_run(["git", "ls-files"]) + or try_to_run(["hg", "locate"], cwd=root) + or try_to_run(["hg", "locate"]) ) + if res is None: + return "" + return str(res).strip() or "" def main(*argv, **kwargs): From 9f5b09efee7a8425a51492a9e643a3697b594046 Mon Sep 17 00:00:00 2001 From: Joe Becher Date: Mon, 18 May 2020 13:03:49 -0400 Subject: [PATCH 082/144] Bump version --- setup.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup.py b/setup.py index b1619359..fa7444b8 100644 --- a/setup.py +++ b/setup.py @@ -1,7 +1,7 @@ #!/usr/bin/env python from setuptools import setup -version = "2.1.0" +version = "2.1.1" classifiers = [ "Development Status :: 5 - Production/Stable", "Environment :: Plugins", From 65d596e454d7a24fd0114418d1f13e6e5f66f0ee Mon Sep 17 00:00:00 2001 From: Nathan Moinvaziri Date: Wed, 6 Nov 2019 16:38:53 -0800 Subject: [PATCH 083/144] Fixed find command not working on Windows. #167 --- codecov/__init__.py | 56 ++++++++++++++++++++++++++------------------- 1 file changed, 33 insertions(+), 23 deletions(-) diff --git a/codecov/__init__.py b/codecov/__init__.py index 2a2a3f69..37afd5a8 100644 --- a/codecov/__init__.py +++ b/codecov/__init__.py @@ -6,6 +6,7 @@ import glob import requests import argparse +import fnmatch from time import sleep from json import loads @@ -228,6 +229,26 @@ def _add_env_if_not_empty(lst, value): lst.add(value) +def find_files(directory, patterns, recursive=True, exclude_dirs=[]): + if recursive: + items = os.walk(directory, followlinks=False) + else: + items = [next(os.walk(directory, followLinks=False))] + if not isinstance(patterns, list): + patterns = [patterns] + for root, dirs, files in items: + dirs[:] = [d for d in dirs if d not in exclude_dirs] + for basename in files: + match = False + for pattern in patterns: + if fnmatch.fnmatch(basename, pattern): + match = True + break + if match: + filename = os.path.join(root, basename) + yield filename + + def generate_toc(root): res = ( try_to_run(["git", "ls-files"], cwd=root) @@ -869,30 +890,19 @@ def main(*argv, **kwargs): write("XX> Skip processing gcov") else: - dont_search_here = ( - "-not -path './bower_components/**' " - "-not -path './node_modules/**' " - "-not -path './vendor/**'" - ) - write("==> Processing gcov (disable by -X gcov)") - cmd = [ - "find", - (sanitize_arg("", codecov.gcov_root or root)), - dont_search_here, - "-type", - "f", - "-name", - "*.gcno", - " ".join(map(lambda a: "-not -path '%s'" % a, codecov.gcov_glob)), - "-exec", - (sanitize_arg("", codecov.gcov_exec or "")), - "-pb", - (sanitize_arg("", codecov.gcov_args or "")), - "{}", - "+", + dont_search_here = [ + "bower_components" + "node_modules" + "vendor" ] - write(" Executing gcov (%s)" % cmd) - try_to_run(cmd) + if codecov.gcov_glob: + dont_search_here.append(codecov.gcov_glob) + + write("==> Processing gcov (disable by -X gcov)") + for path in find_files(sanitize_arg("", codecov.gcov_root or root), "*.gcno", True, dont_search_here): + cmd = sanitize_arg("", codecov.gcov_exec or "") + " -pb " + sanitize_arg("", codecov.gcov_args or "") + " " + path + write(" Executing gcov (%s)" % cmd) + write(try_to_run(cmd)) # Collect Reports # --------------- From 6a8d72214f8c83d19537feb18efd68bb1f5ec6af Mon Sep 17 00:00:00 2001 From: Nathan Moinvaziri Date: Tue, 5 Nov 2019 18:04:25 -0800 Subject: [PATCH 084/144] Added support for gzipping reports. --- codecov/__init__.py | 35 ++++++++++++++++++++++++----------- tests/test.py | 5 ++++- 2 files changed, 28 insertions(+), 12 deletions(-) diff --git a/codecov/__init__.py b/codecov/__init__.py index 37afd5a8..04ca3dc1 100644 --- a/codecov/__init__.py +++ b/codecov/__init__.py @@ -7,6 +7,7 @@ import requests import argparse import fnmatch +import zlib from time import sleep from json import loads @@ -1021,6 +1022,16 @@ def main(*argv, **kwargs): write(reports) write("-------------------------------------------------") + # Handle reports encoding for Python 2 and 3 + if not isinstance(reports, bytes): + reports = reports.encode("utf-8") + + # Compress reports using zlib and output with gzip header + write(" Gzipping contents..") + gzip_worker = zlib.compressobj(9, zlib.DEFLATED, zlib.MAX_WBITS | 16) + reports_gzip = gzip_worker.compress(reports) + gzip_worker.flush() + write(" Compressed contents to {0} bytes".format(len(reports_gzip))) + s3 = None trys = 0 while trys < 3: @@ -1034,7 +1045,8 @@ def main(*argv, **kwargs): headers={ "Accept": "text/plain", "X-Reduced-Redundancy": "false", - }, + "X-Content-Type": "application/x-gzip" + } ) if res.status_code in (400, 406): raise Exception(res.text) @@ -1044,15 +1056,14 @@ def main(*argv, **kwargs): res = res.text.strip().split() result, upload_url = res[0], res[1] - # Handle reports encoding for Python 2 and 3 - if not isinstance(reports, bytes): - reports = reports.encode("utf-8") - write(" Uploading to S3...") s3 = requests.put( upload_url, - data=reports, - headers={"Content-Type": "text/plain",}, + data=reports_gzip, + headers={ + "Content-Type": "application/x-gzip", + "Content-Encoding": "gzip" + } ) s3.raise_for_status() assert s3.status_code == 200 @@ -1070,10 +1081,12 @@ def main(*argv, **kwargs): res = requests.post( "%s/upload/v2?%s" % (codecov.url, urlargs), verify=codecov.cacert, - data="\n".join( - (reports, s3.reason if s3 else "", s3.text if s3 else "") - ), - headers={"Accept": "text/plain"}, + data=reports_gzip, + headers={ + "Accept": "text/plain", + "Content-Type": "application/x-gzip", + "Content-Encoding": "gzip" + } ) if res.status_code < 500: write(" " + res.text) diff --git a/tests/test.py b/tests/test.py index 41165d36..3c396be9 100644 --- a/tests/test.py +++ b/tests/test.py @@ -2,6 +2,7 @@ import sys import pickle import itertools +import zlib from ddt import ddt, data from mock import patch, Mock import unittest @@ -267,7 +268,9 @@ def test_send(self): ) assert "token=%3Ctoken%3E" in post.call_args[0][0] assert "branch=master" in post.call_args[0][0] - assert u"tests/test.py".encode("utf-8") in put.call_args[1]["data"] + gzip_worker = zlib.decompressobj(zlib.MAX_WBITS | 16) + reports = gzip_worker.decompress(put.call_args[1]["data"]) + gzip_worker.flush() + assert u"tests/test.py".encode("utf-8") in reports def test_send_error(self): with patch("requests.post") as post: From 8d6a118e34697df31c260cb151ffa95f78e517f3 Mon Sep 17 00:00:00 2001 From: Joe Becher Date: Thu, 21 May 2020 12:58:30 -0400 Subject: [PATCH 085/144] Change version to be dynamically synced (#258) * Change setup.py and __init__.py to use __version__.py Co-authored-by: Thomas Hu --- .gitignore | 1 - codecov/__init__.py | 15 +++++++++++++-- codecov/__version__.py | 9 +++++++++ setup.py | 23 +++++++++++++++-------- 4 files changed, 37 insertions(+), 11 deletions(-) create mode 100644 codecov/__version__.py diff --git a/.gitignore b/.gitignore index 433e02bb..79d2d87e 100644 --- a/.gitignore +++ b/.gitignore @@ -11,4 +11,3 @@ coverage.xml dist htmlcov venv -*.sw[op] diff --git a/codecov/__init__.py b/codecov/__init__.py index 04ca3dc1..42e38aa6 100644 --- a/codecov/__init__.py +++ b/codecov/__init__.py @@ -11,6 +11,17 @@ from time import sleep from json import loads +from .__version__ import ( + __author__, + __author_email__, + __copyright__, + __description__, + __license__, + __title__, + __url__, + __version__, +) + try: from urllib.parse import urlencode except ImportError: # pragma: no cover @@ -29,7 +40,7 @@ logging.captureWarnings(True) -version = VERSION = __version__ = "2.0.21" +version=__version__ COLOR = True @@ -999,7 +1010,7 @@ def main(*argv, **kwargs): ) ) - query["package"] = "py" + VERSION + query["package"] = "py" + version urlargs = ( urlencode( dict([(k, v.strip()) for k, v in query.items() if v not in ("", None)]) diff --git a/codecov/__version__.py b/codecov/__version__.py new file mode 100644 index 00000000..f33db7ec --- /dev/null +++ b/codecov/__version__.py @@ -0,0 +1,9 @@ +__author__ = 'Codecov' +__author_email__ = 'support@codecov.io' +__copyright__ = 'Copyright 2020 Codecov' +__description__ = 'Hosted coverage reports for GitHub, Bitbucket and Gitlab' +__license__ = 'Apache 2.0' +__title__ = 'codecov' +__url__ = 'https://github.com/codecov/codecov-python' +__version__ = '2.1.3' + diff --git a/setup.py b/setup.py index fa7444b8..1e8f0dc3 100644 --- a/setup.py +++ b/setup.py @@ -1,7 +1,8 @@ #!/usr/bin/env python +from codecs import open +import os from setuptools import setup -version = "2.1.1" classifiers = [ "Development Status :: 5 - Production/Stable", "Environment :: Plugins", @@ -19,17 +20,23 @@ "Topic :: Software Development :: Testing", ] +filepath = os.path.abspath(os.path.dirname(__file__)) + +about = {} +with open(os.path.join(filepath, 'codecov', '__version__.py'), 'r', 'utf-8') as f: + exec(f.read(), about) + setup( - name="codecov", - version=version, - description="Hosted coverage reports for GitHub, Bitbucket and Gitlab", + name=about['__title__'], + version=about['__version__'], + description=about['__description__'], long_description=None, classifiers=classifiers, keywords="coverage codecov code python java scala php", - author="@codecov", - author_email="hello@codecov.io", - url="https://github.com/codecov/codecov-python", - license="http://www.apache.org/licenses/LICENSE-2.0", + author=about['__author__'], + author_email=about['__author_email__'], + url=about['__url__'], + license=about['__license__'], packages=["codecov"], include_package_data=True, zip_safe=True, From 5324ae48c8a2e9fa6dfed77caf90994a8afc2804 Mon Sep 17 00:00:00 2001 From: Thomas Hu Date: Fri, 22 May 2020 10:53:37 -0400 Subject: [PATCH 086/144] Add black linting --- .travis.yml | 1 + Makefile | 3 +++ README.md | 2 +- codecov/__init__.py | 35 +++++++++++++++++++++-------------- codecov/__version__.py | 17 ++++++++--------- setup.py | 16 ++++++++-------- tests/requirements.txt | 1 + tests/test.py | 5 ++++- 8 files changed, 47 insertions(+), 33 deletions(-) diff --git a/.travis.yml b/.travis.yml index 28c4c162..8ed48c93 100644 --- a/.travis.yml +++ b/.travis.yml @@ -32,6 +32,7 @@ install: - python setup.py install script: - make reinstall + - make lint - make test # - pytest tests/test.py --cov=codecov after_success: diff --git a/Makefile b/Makefile index cd09f059..50c2789c 100644 --- a/Makefile +++ b/Makefile @@ -11,6 +11,9 @@ reinstall: test: py.test tests/test.py +lint: + black . + compare: hub compare $(shell git tag --sort=refname | tail -1)...master diff --git a/README.md b/README.md index 0959d646..17cbc3b4 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -Codecov Global Python Uploader [![codecov.io](https://codecov.io/github/codecov/codecov-python/coverage.svg?branch=master)](https://codecov.io/github/codecov/codecov-python) +Codecov Global Python Uploader [![codecov.io](https://codecov.io/github/codecov/codecov-python/coverage.svg?branch=master)](https://codecov.io/github/codecov/codecov-python) [![Code style: black](https://img.shields.io/badge/code%20style-black-000000.svg)](https://github.com/psf/black) ======= | [https://codecov.io/][1] | [@codecov][2] | [hello@codecov.io][3] | | ------------------------ | ------------- | --------------------- | diff --git a/codecov/__init__.py b/codecov/__init__.py index 42e38aa6..2ac36114 100644 --- a/codecov/__init__.py +++ b/codecov/__init__.py @@ -40,7 +40,7 @@ logging.captureWarnings(True) -version=__version__ +version = __version__ COLOR = True @@ -902,17 +902,24 @@ def main(*argv, **kwargs): write("XX> Skip processing gcov") else: - dont_search_here = [ - "bower_components" - "node_modules" - "vendor" - ] + dont_search_here = ["bower_components" "node_modules" "vendor"] if codecov.gcov_glob: dont_search_here.append(codecov.gcov_glob) write("==> Processing gcov (disable by -X gcov)") - for path in find_files(sanitize_arg("", codecov.gcov_root or root), "*.gcno", True, dont_search_here): - cmd = sanitize_arg("", codecov.gcov_exec or "") + " -pb " + sanitize_arg("", codecov.gcov_args or "") + " " + path + for path in find_files( + sanitize_arg("", codecov.gcov_root or root), + "*.gcno", + True, + dont_search_here, + ): + cmd = ( + sanitize_arg("", codecov.gcov_exec or "") + + " -pb " + + sanitize_arg("", codecov.gcov_args or "") + + " " + + path + ) write(" Executing gcov (%s)" % cmd) write(try_to_run(cmd)) @@ -1056,8 +1063,8 @@ def main(*argv, **kwargs): headers={ "Accept": "text/plain", "X-Reduced-Redundancy": "false", - "X-Content-Type": "application/x-gzip" - } + "X-Content-Type": "application/x-gzip", + }, ) if res.status_code in (400, 406): raise Exception(res.text) @@ -1073,8 +1080,8 @@ def main(*argv, **kwargs): data=reports_gzip, headers={ "Content-Type": "application/x-gzip", - "Content-Encoding": "gzip" - } + "Content-Encoding": "gzip", + }, ) s3.raise_for_status() assert s3.status_code == 200 @@ -1096,8 +1103,8 @@ def main(*argv, **kwargs): headers={ "Accept": "text/plain", "Content-Type": "application/x-gzip", - "Content-Encoding": "gzip" - } + "Content-Encoding": "gzip", + }, ) if res.status_code < 500: write(" " + res.text) diff --git a/codecov/__version__.py b/codecov/__version__.py index f33db7ec..3955eb75 100644 --- a/codecov/__version__.py +++ b/codecov/__version__.py @@ -1,9 +1,8 @@ -__author__ = 'Codecov' -__author_email__ = 'support@codecov.io' -__copyright__ = 'Copyright 2020 Codecov' -__description__ = 'Hosted coverage reports for GitHub, Bitbucket and Gitlab' -__license__ = 'Apache 2.0' -__title__ = 'codecov' -__url__ = 'https://github.com/codecov/codecov-python' -__version__ = '2.1.3' - +__author__ = "Codecov" +__author_email__ = "support@codecov.io" +__copyright__ = "Copyright 2020 Codecov" +__description__ = "Hosted coverage reports for GitHub, Bitbucket and Gitlab" +__license__ = "Apache 2.0" +__title__ = "codecov" +__url__ = "https://github.com/codecov/codecov-python" +__version__ = "2.1.3" diff --git a/setup.py b/setup.py index 1e8f0dc3..4d418234 100644 --- a/setup.py +++ b/setup.py @@ -23,20 +23,20 @@ filepath = os.path.abspath(os.path.dirname(__file__)) about = {} -with open(os.path.join(filepath, 'codecov', '__version__.py'), 'r', 'utf-8') as f: +with open(os.path.join(filepath, "codecov", "__version__.py"), "r", "utf-8") as f: exec(f.read(), about) setup( - name=about['__title__'], - version=about['__version__'], - description=about['__description__'], + name=about["__title__"], + version=about["__version__"], + description=about["__description__"], long_description=None, classifiers=classifiers, keywords="coverage codecov code python java scala php", - author=about['__author__'], - author_email=about['__author_email__'], - url=about['__url__'], - license=about['__license__'], + author=about["__author__"], + author_email=about["__author_email__"], + url=about["__url__"], + license=about["__license__"], packages=["codecov"], include_package_data=True, zip_safe=True, diff --git a/tests/requirements.txt b/tests/requirements.txt index 62de37c5..36ad7f1c 100644 --- a/tests/requirements.txt +++ b/tests/requirements.txt @@ -5,3 +5,4 @@ pytest>=3.6.0 pytest-cov funcsigs requests +black diff --git a/tests/test.py b/tests/test.py index 3c396be9..279d21ec 100644 --- a/tests/test.py +++ b/tests/test.py @@ -269,7 +269,10 @@ def test_send(self): assert "token=%3Ctoken%3E" in post.call_args[0][0] assert "branch=master" in post.call_args[0][0] gzip_worker = zlib.decompressobj(zlib.MAX_WBITS | 16) - reports = gzip_worker.decompress(put.call_args[1]["data"]) + gzip_worker.flush() + reports = ( + gzip_worker.decompress(put.call_args[1]["data"]) + + gzip_worker.flush() + ) assert u"tests/test.py".encode("utf-8") in reports def test_send_error(self): From 4caf9ecc59e5d49b8479e9a42f3638dd78ebb9d0 Mon Sep 17 00:00:00 2001 From: Thomas Hu Date: Fri, 22 May 2020 10:55:33 -0400 Subject: [PATCH 087/144] Make black a checking call --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 50c2789c..a79d4627 100644 --- a/Makefile +++ b/Makefile @@ -12,7 +12,7 @@ test: py.test tests/test.py lint: - black . + black . --check compare: hub compare $(shell git tag --sort=refname | tail -1)...master From 9a329b996079c9907a1749521dd34fb1affe2ec0 Mon Sep 17 00:00:00 2001 From: Thomas Hu Date: Fri, 22 May 2020 10:56:41 -0400 Subject: [PATCH 088/144] Call it formatting --- .travis.yml | 2 +- Makefile | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index 8ed48c93..7d096fef 100644 --- a/.travis.yml +++ b/.travis.yml @@ -32,7 +32,7 @@ install: - python setup.py install script: - make reinstall - - make lint + - make format - make test # - pytest tests/test.py --cov=codecov after_success: diff --git a/Makefile b/Makefile index a79d4627..b166e62e 100644 --- a/Makefile +++ b/Makefile @@ -11,7 +11,7 @@ reinstall: test: py.test tests/test.py -lint: +format: black . --check compare: From 5302d5f8c9d11f34d2bc57234146e438ca616e99 Mon Sep 17 00:00:00 2001 From: Joe Becher Date: Fri, 22 May 2020 11:13:56 -0400 Subject: [PATCH 089/144] Add pypi badge (#259) --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 0959d646..8d808b0f 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -Codecov Global Python Uploader [![codecov.io](https://codecov.io/github/codecov/codecov-python/coverage.svg?branch=master)](https://codecov.io/github/codecov/codecov-python) +Codecov Global Python Uploader ![PyPI](https://img.shields.io/pypi/v/codecov) [![codecov.io](https://codecov.io/github/codecov/codecov-python/coverage.svg?branch=master)](https://codecov.io/github/codecov/codecov-python) ======= | [https://codecov.io/][1] | [@codecov][2] | [hello@codecov.io][3] | | ------------------------ | ------------- | --------------------- | From 30444067e790ab4727df2f31be8b7526250e777f Mon Sep 17 00:00:00 2001 From: Thomas Hu Date: Fri, 22 May 2020 11:53:08 -0400 Subject: [PATCH 090/144] Isolate black to 3.6 and 3.7 --- .travis.yml | 5 +++++ Makefile | 2 +- tests/requirements.txt | 1 - 3 files changed, 6 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index 7d096fef..94859e38 100644 --- a/.travis.yml +++ b/.travis.yml @@ -24,8 +24,13 @@ matrix: - python-requests - python-coverage - python-mock + - python: 3.6 + before_install: + - pip install black - python: 3.7 dist: xenial + before_install: + - pip install black install: - pip install -r tests/requirements.txt diff --git a/Makefile b/Makefile index b166e62e..8b8625da 100644 --- a/Makefile +++ b/Makefile @@ -12,7 +12,7 @@ test: py.test tests/test.py format: - black . --check + which -s black && black . --check compare: hub compare $(shell git tag --sort=refname | tail -1)...master diff --git a/tests/requirements.txt b/tests/requirements.txt index 36ad7f1c..62de37c5 100644 --- a/tests/requirements.txt +++ b/tests/requirements.txt @@ -5,4 +5,3 @@ pytest>=3.6.0 pytest-cov funcsigs requests -black From 8c616eb81c37205d61d1d81eabe9caeada618c80 Mon Sep 17 00:00:00 2001 From: Thomas Hu Date: Fri, 22 May 2020 11:55:11 -0400 Subject: [PATCH 091/144] do a check on requirements --- .travis.yml | 5 ----- tests/requirements.txt | 1 + tests/~ | 8 ++++++++ 3 files changed, 9 insertions(+), 5 deletions(-) create mode 100644 tests/~ diff --git a/.travis.yml b/.travis.yml index 94859e38..7d096fef 100644 --- a/.travis.yml +++ b/.travis.yml @@ -24,13 +24,8 @@ matrix: - python-requests - python-coverage - python-mock - - python: 3.6 - before_install: - - pip install black - python: 3.7 dist: xenial - before_install: - - pip install black install: - pip install -r tests/requirements.txt diff --git a/tests/requirements.txt b/tests/requirements.txt index 62de37c5..9b6d87dd 100644 --- a/tests/requirements.txt +++ b/tests/requirements.txt @@ -5,3 +5,4 @@ pytest>=3.6.0 pytest-cov funcsigs requests +black ; python_version >= '3.6' diff --git a/tests/~ b/tests/~ new file mode 100644 index 00000000..9b6d87dd --- /dev/null +++ b/tests/~ @@ -0,0 +1,8 @@ +coverage>=4.4.0 +ddt +mock +pytest>=3.6.0 +pytest-cov +funcsigs +requests +black ; python_version >= '3.6' From e7c339ca3b6db8acb8362a309f6e4f54289e03e7 Mon Sep 17 00:00:00 2001 From: Thomas Hu Date: Fri, 22 May 2020 11:57:46 -0400 Subject: [PATCH 092/144] Fix readme --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index f901788d..fe8adbd6 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,5 @@ Codecov Global Python Uploader ![PyPI](https://img.shields.io/pypi/v/codecov) [![codecov.io](https://codecov.io/github/codecov/codecov-python/coverage.svg?branch=master)](https://codecov.io/github/codecov/codecov-python) [![Code style: black](https://img.shields.io/badge/code%20style-black-000000.svg)](https://github.com/psf/black) - +======= | [https://codecov.io/][1] | [@codecov][2] | [hello@codecov.io][3] | | ------------------------ | ------------- | --------------------- | From 7d705be5a30958ba9c22de141f002dc2d98e8439 Mon Sep 17 00:00:00 2001 From: Thomas Hu Date: Fri, 22 May 2020 12:23:02 -0400 Subject: [PATCH 093/144] Remove -s argment --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 8b8625da..1262230c 100644 --- a/Makefile +++ b/Makefile @@ -12,7 +12,7 @@ test: py.test tests/test.py format: - which -s black && black . --check + which black && black . --check compare: hub compare $(shell git tag --sort=refname | tail -1)...master From ad9e538589e6acda2378413e59087358234b2cdf Mon Sep 17 00:00:00 2001 From: Thomas Hu Date: Fri, 22 May 2020 12:31:06 -0400 Subject: [PATCH 094/144] maybe we dont need which --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 1262230c..b166e62e 100644 --- a/Makefile +++ b/Makefile @@ -12,7 +12,7 @@ test: py.test tests/test.py format: - which black && black . --check + black . --check compare: hub compare $(shell git tag --sort=refname | tail -1)...master From 9d43fb49590451744724752aed66bd2143b67b1c Mon Sep 17 00:00:00 2001 From: Thomas Hu Date: Fri, 22 May 2020 12:38:34 -0400 Subject: [PATCH 095/144] Run formatting only on 3.7 --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 7d096fef..2e6150f9 100644 --- a/.travis.yml +++ b/.travis.yml @@ -26,13 +26,13 @@ matrix: - python-mock - python: 3.7 dist: xenial + script: make format install: - pip install -r tests/requirements.txt - python setup.py install script: - make reinstall - - make format - make test # - pytest tests/test.py --cov=codecov after_success: From 08b098829820e9e19900dd54b461d3c16b5e6d29 Mon Sep 17 00:00:00 2001 From: Thomas Hu Date: Fri, 22 May 2020 12:56:01 -0400 Subject: [PATCH 096/144] Remove extra dir --- tests/~ | 8 -------- 1 file changed, 8 deletions(-) delete mode 100644 tests/~ diff --git a/tests/~ b/tests/~ deleted file mode 100644 index 9b6d87dd..00000000 --- a/tests/~ +++ /dev/null @@ -1,8 +0,0 @@ -coverage>=4.4.0 -ddt -mock -pytest>=3.6.0 -pytest-cov -funcsigs -requests -black ; python_version >= '3.6' From 098c82bf13bc68b15413eeb83337a5505a0f06fc Mon Sep 17 00:00:00 2001 From: Thomas Hu Date: Fri, 22 May 2020 13:03:52 -0400 Subject: [PATCH 097/144] Only install on 3.7 because pypy is 3.6 and uses typed-ast --- tests/requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/requirements.txt b/tests/requirements.txt index 9b6d87dd..f70ccf3f 100644 --- a/tests/requirements.txt +++ b/tests/requirements.txt @@ -5,4 +5,4 @@ pytest>=3.6.0 pytest-cov funcsigs requests -black ; python_version >= '3.6' +black ; python_version >= '3.7' From 4ec70db255cc2dc332fbd01aab3069d9b2e699dc Mon Sep 17 00:00:00 2001 From: Ofek Lev Date: Tue, 26 May 2020 18:03:01 -0400 Subject: [PATCH 098/144] Fix command line quoting for Windows (#169) --- codecov/__init__.py | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/codecov/__init__.py b/codecov/__init__.py index 2ac36114..4f97c7ab 100644 --- a/codecov/__init__.py +++ b/codecov/__init__.py @@ -27,10 +27,22 @@ except ImportError: # pragma: no cover from urllib import urlencode -try: - from shlex import quote -except ImportError: # pragma: no cover - from pipes import quote +quote = None +if sys.platform == 'win32': # pragma: no cover + try: + # https://github.com/python/cpython/blob/3.7/Lib/subprocess.py#L174-L175 + from subprocess import list2cmdline + + def quote(arg): + return list2cmdline([arg]) + except ImportError: + pass + +if quote is None: + try: + from shlex import quote + except ImportError: # pragma: no cover + from pipes import quote import subprocess From 84048cd5f259334e297936706323c433c6ff6ec2 Mon Sep 17 00:00:00 2001 From: Nathan Moinvaziri Date: Wed, 27 May 2020 09:30:02 -0700 Subject: [PATCH 099/144] Fixed GitLab CI project directory detection on Windows. (#216) --- codecov/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/codecov/__init__.py b/codecov/__init__.py index 4f97c7ab..c036f425 100644 --- a/codecov/__init__.py +++ b/codecov/__init__.py @@ -768,7 +768,7 @@ def main(*argv, **kwargs): commit=os.getenv("CI_BUILD_REF"), ) ) - if os.getenv("CI_PROJECT_DIR", "").startswith("/"): + if sys.platform == "win32" or os.getenv("CI_PROJECT_DIR", "").startswith("/"): root = os.getenv("CI_PROJECT_DIR") else: root = os.getenv("HOME") + "/" + os.getenv("CI_PROJECT_DIR", "") From fd64abc2d1f2b916fee3f5565354680e98cf125c Mon Sep 17 00:00:00 2001 From: Nathan Moinvaziri Date: Wed, 27 May 2020 09:48:37 -0700 Subject: [PATCH 100/144] =?UTF-8?q?failing=20on=20GitLab=20=E2=89=A5=209?= =?UTF-8?q?=20(bis)=20(#264)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * failing on GitLab ≥ 9 (bis) Compatibility with the deprecated variables listed in https://docs.gitlab.com/ee/ci/variables/deprecated_variables.html * Black Co-authored-by: Romain Dartigues Co-authored-by: Thomas Hu --- codecov/__init__.py | 19 ++++++++++++------- tests/test.py | 30 +++++++++++++++++++++++++++++- 2 files changed, 41 insertions(+), 8 deletions(-) diff --git a/codecov/__init__.py b/codecov/__init__.py index c036f425..00354d11 100644 --- a/codecov/__init__.py +++ b/codecov/__init__.py @@ -28,13 +28,14 @@ from urllib import urlencode quote = None -if sys.platform == 'win32': # pragma: no cover +if sys.platform == "win32": # pragma: no cover try: # https://github.com/python/cpython/blob/3.7/Lib/subprocess.py#L174-L175 from subprocess import list2cmdline def quote(arg): return list2cmdline([arg]) + except ImportError: pass @@ -758,17 +759,21 @@ def main(*argv, **kwargs): # Gitlab CI # --------- elif os.getenv("CI_SERVER_NAME", "").startswith("GitLab"): - # http://doc.gitlab.com/ci/examples/README.html#environmental-variables - # https://gitlab.com/gitlab-org/gitlab-ci-runner/blob/master/lib/build.rb#L96 + # https://docs.gitlab.com/ee/ci/variables/predefined_variables.html + # https://gitlab.com/gitlab-org/gitlab-ci-runner/blob/master/lib/build.rb query.update( dict( service="gitlab", - branch=os.getenv("CI_BUILD_REF_NAME"), - build=os.getenv("CI_BUILD_ID"), - commit=os.getenv("CI_BUILD_REF"), + branch=os.getenv( + "CI_COMMIT_REF_NAME", os.getenv("CI_BUILD_REF_NAME") + ), + build=os.getenv("CI_JOB_ID", os.getenv("CI_BUILD_ID")), + commit=os.getenv("CI_COMMIT_SHA", os.getenv("CI_BUILD_REF")), ) ) - if sys.platform == "win32" or os.getenv("CI_PROJECT_DIR", "").startswith("/"): + if sys.platform == "win32" or os.getenv("CI_PROJECT_DIR", "").startswith( + "/" + ): root = os.getenv("CI_PROJECT_DIR") else: root = os.getenv("HOME") + "/" + os.getenv("CI_PROJECT_DIR", "") diff --git a/tests/test.py b/tests/test.py index 279d21ec..5e305eda 100644 --- a/tests/test.py +++ b/tests/test.py @@ -98,6 +98,10 @@ def setUp(self): "CI_PROJECT_DIR", "CI_BUILD_REF", "CI_SERVER_NAME", + "CI_COMMIT_REF_NAME", + "CI_JOB_ID", + "CI_REPOSITORY_URL", + "CI_COMMIT_SHA", "ghprbActualCommit", "ghprbSourceBranch", "ghprbPullId", @@ -791,7 +795,7 @@ def test_ci_magnum(self): @unittest.skipUnless( os.getenv("CI_SERVER_NAME", "").startswith("GitLab"), "Skip GitLab CI test" ) - def test_ci_gitlab(self): + def test_ci_gitlab_pre9(self): self.set_env( CI_BUILD_REF_NAME="master", CI_BUILD_ID="1399372237", @@ -812,6 +816,30 @@ def test_ci_gitlab(self): self.assertEqual(res["query"]["slug"], "owner/repo") self.assertEqual(res["codecov"].token, "token") + @unittest.skipUnless( + os.getenv("CI_SERVER_NAME", "").startswith("GitLab"), "Skip GitLab CI test" + ) + def test_ci_gitlab(self): + self.set_env( + CI_COMMIT_REF_NAME="master", + CI_JOB_ID="1399372237", + CI_REPOSITORY_URL="https://gitlab.com/owner/repo.git", + CI_SERVER_NAME="GitLab CI", + CI_COMMIT_SHA="d653b934ed59c1a785cc1cc79d08c9aaa4eba73b", + HOME="/", + CI_PROJECT_DIR=os.getcwd().strip("/"), + CODECOV_TOKEN="token", + ) + self.fake_report() + res = self.run_cli() + self.assertEqual(res["query"]["service"], "gitlab") + self.assertEqual( + res["query"]["commit"], "d653b934ed59c1a785cc1cc79d08c9aaa4eba73b" + ) + self.assertEqual(res["query"]["build"], "1399372237") + self.assertEqual(res["query"]["slug"], "owner/repo") + self.assertEqual(res["codecov"].token, "token") + @unittest.skip("Skip CI None") def test_ci_none(self): self.set_env(CODECOV_TOKEN="token") From 53becf43f537fba3651a2a54d1547d618d16801f Mon Sep 17 00:00:00 2001 From: Nathan Moinvaziri Date: Wed, 27 May 2020 16:02:24 -0700 Subject: [PATCH 101/144] Check to see that text is not None before calling replace in write(). (#262) Error: 'NoneType' object has no attribute 'replace' --- codecov/__init__.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/codecov/__init__.py b/codecov/__init__.py index 00354d11..80d997cf 100644 --- a/codecov/__init__.py +++ b/codecov/__init__.py @@ -147,7 +147,7 @@ def sanitize_arg(replacement, arg): def write(text, color=None): global COLOR - if COLOR: + if text and COLOR: text = text.replace("==>", "\033[90m==>\033[0m") text = text.replace(" +", " \033[32m+\033[0m") text = text.replace("XX>", "\033[31mXX>\033[0m") @@ -174,7 +174,8 @@ def write(text, color=None): elif color == "green": text = "\033[92m%s\033[0m" % text - sys.stdout.write(text + "\n") + if text: + sys.stdout.write(text + "\n") def fopen(path): From 1c0e0781c2fd2913940893e5953e6dca390b7dee Mon Sep 17 00:00:00 2001 From: Nathan Moinvaziri Date: Thu, 28 May 2020 07:42:24 -0700 Subject: [PATCH 102/144] Include the cacert in the PUT call when uploading to S3 (#266) Co-authored-by: John Siirola --- codecov/__init__.py | 1 + 1 file changed, 1 insertion(+) diff --git a/codecov/__init__.py b/codecov/__init__.py index 80d997cf..301c0011 100644 --- a/codecov/__init__.py +++ b/codecov/__init__.py @@ -1095,6 +1095,7 @@ def main(*argv, **kwargs): write(" Uploading to S3...") s3 = requests.put( upload_url, + verify=codecov.cacert, data=reports_gzip, headers={ "Content-Type": "application/x-gzip", From 98301201f26be773348da32fc3c46f387a546ad4 Mon Sep 17 00:00:00 2001 From: Nathan Moinvaziri Date: Thu, 28 May 2020 18:30:36 -0700 Subject: [PATCH 103/144] Fixed gcov not found due to passing cmd string instead of list to try_to_run. #261 (#263) --- codecov/__init__.py | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/codecov/__init__.py b/codecov/__init__.py index 301c0011..ceb15c86 100644 --- a/codecov/__init__.py +++ b/codecov/__init__.py @@ -931,13 +931,11 @@ def main(*argv, **kwargs): True, dont_search_here, ): - cmd = ( - sanitize_arg("", codecov.gcov_exec or "") - + " -pb " - + sanitize_arg("", codecov.gcov_args or "") - + " " - + path - ) + cmd = sanitize_arg("", codecov.gcov_exec or "").split(" ") + cmd.append("-pb") + if codecov.gcov_args: + cmd.append(sanitize_arg("", codecov.gcov_args or "")) + cmd.append(path) write(" Executing gcov (%s)" % cmd) write(try_to_run(cmd)) From 7f98a4144c70e8a9c846b896f5b67430afbb9505 Mon Sep 17 00:00:00 2001 From: sn1020 Date: Tue, 2 Jun 2020 06:15:29 -0700 Subject: [PATCH 104/144] Update readme with 400 error info (#268) --- README.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/README.md b/README.md index fe8adbd6..9d3a8451 100644 --- a/README.md +++ b/README.md @@ -93,6 +93,10 @@ after_success: | [Solano Labs](https://www.solanolabs.com/) | `coming soon` | | +## Troubleshooting + +If you're seeing an **HTTP 400 error when uploading reports to S3**, make sure you've updated to at least version 2.1.3. + [1]: https://codecov.io/ From 658ddfda9e01b325a1602736ab760d97f07404df Mon Sep 17 00:00:00 2001 From: Thomas Hu Date: Wed, 3 Jun 2020 11:08:22 -0400 Subject: [PATCH 105/144] bump version (#269) --- codecov/__version__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/codecov/__version__.py b/codecov/__version__.py index 3955eb75..f55a18b0 100644 --- a/codecov/__version__.py +++ b/codecov/__version__.py @@ -5,4 +5,4 @@ __license__ = "Apache 2.0" __title__ = "codecov" __url__ = "https://github.com/codecov/codecov-python" -__version__ = "2.1.3" +__version__ = "2.1.4" From 71a7fa11b0582a6c8836629b810d58559fe42e2b Mon Sep 17 00:00:00 2001 From: Thomas Hu Date: Wed, 3 Jun 2020 11:48:01 -0400 Subject: [PATCH 106/144] Also create an egg (#270) --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index b166e62e..0b0a1ba2 100644 --- a/Makefile +++ b/Makefile @@ -1,7 +1,7 @@ deploy: git tag -a v$(python -c 'import codecov;print(codecov.version)') -m "" git push origin v$(python -c 'import codecov;print(codecov.version)') - python setup.py sdist bdist_wheel + python setup.py sdist bdist_wheel bdist_egg python -m twine upload dist/* reinstall: From 1f5f6b9926e5bc2b5a5b02c139c11f4c4bdc1a39 Mon Sep 17 00:00:00 2001 From: Thomas Hu Date: Wed, 3 Jun 2020 17:23:48 -0400 Subject: [PATCH 107/144] Changelog (#271) * Update changelog * will it work with just the number * maybe this format * fine * Close out my tags * pretty --- CHANGELOG.md | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index a8a67c0b..dea8451d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,32 @@ +### `2.1.4` + +- [#260](https://github.com/codecov/codecov-python/pull/260) Enforce black formatting +- [#169](https://github.com/codecov/codecov-python/pull/169) Fix command line quoting on Windows +- [#216](https://github.com/codecov/codecov-python/pull/216) Fix GitLab CI project directory detection on Windows +- [#264](https://github.com/codecov/codecov-python/pull/264) Fix GitLab CI post version 9 +- [#262](https://github.com/codecov/codecov-python/pull/262) Check text for NoneType on writes +- [#266](https://github.com/codecov/codecov-python/pull/266) Include the cacert in the PUT call when uploading to S3 +- [#263](https://github.com/codecov/codecov-python/pull/263) Fixed gcov not being found in certain instances + +### `2.1.3` + +- Fix find command not working on Windows +- Add support for gzipping reports +- Dynamic syncing of version + +### `2.1.1` + +- Fix command when neither hg or git are not available + +### `2.1.0` + +- Remove x-amz-acl header +- Reformat with Black + +### `2.0.22` + +- Cleaning TOC generation + ### `2.0.21` - fixed string issues From 39100a2f89e3a4f35f8dcae3dffe9a94052133c7 Mon Sep 17 00:00:00 2001 From: Nathan Moinvaziri Date: Sat, 6 Jun 2020 11:01:20 -0700 Subject: [PATCH 108/144] Add CODECOV_NAME as default for name (#267) Co-authored-by: Hugo --- codecov/__init__.py | 4 ++-- tests/test.py | 35 +++++++++++++++++++++++++++++++++-- 2 files changed, 35 insertions(+), 4 deletions(-) diff --git a/codecov/__init__.py b/codecov/__init__.py index ceb15c86..377447b3 100644 --- a/codecov/__init__.py +++ b/codecov/__init__.py @@ -342,8 +342,8 @@ def main(*argv, **kwargs): basics.add_argument( "--name", "-n", - default=None, - help="Custom defined name of the upload. Visible in Codecov UI.", + default=os.getenv("CODECOV_NAME"), + help="Custom defined name of the upload. Visible in Codecov UI. Defaults to $CODECOV_NAME.", ) gcov = parser.add_argument_group( diff --git a/tests/test.py b/tests/test.py index 5e305eda..59130d55 100644 --- a/tests/test.py +++ b/tests/test.py @@ -82,6 +82,7 @@ def setUp(self): "DRONE_BUILD_LINK", "TRAVIS_REPO_SLUG", "CODECOV_TOKEN", + "CODECOV_NAME", "APPVEYOR", "APPVEYOR_REPO_BRANCH", "APPVEYOR_BUILD_VERSION", @@ -394,7 +395,13 @@ def test_gcov(self): # self.skipTest("Skipped, works on Travis only.") def test_disable_detect(self): - self.set_env(JENKINS_URL="a", GIT_BRANCH="b", GIT_COMMIT="c", CODECOV_TOKEN="d") + self.set_env( + JENKINS_URL="a", + GIT_BRANCH="b", + GIT_COMMIT="c", + CODECOV_TOKEN="d", + CODECOV_NAME="e", + ) self.fake_report() try: self.run_cli(disable="detect") @@ -486,6 +493,7 @@ def test_ci_jenkins(self): GIT_COMMIT="c739768fcac68144a3a6d82305b9c4106934d31a", BUILD_NUMBER="41", CODECOV_TOKEN="token", + CODECOV_NAME="name", ) self.fake_report() res = self.run_cli() @@ -498,6 +506,7 @@ def test_ci_jenkins(self): self.assertEqual(res["query"]["pr"], "") self.assertEqual(res["query"]["branch"], "master") self.assertEqual(res["codecov"].token, "token") + self.assertEqual(res["codecov"].name, "name") @unittest.skipUnless(os.getenv("JENKINS_URL"), "Skip Jenkins CI test") def test_ci_jenkins_env(self): @@ -509,6 +518,7 @@ def test_ci_jenkins_env(self): ghprbPullId="1", BUILD_NUMBER="41", CODECOV_TOKEN="token", + CODECOV_NAME="name", ) self.fake_report() res = self.run_cli() @@ -521,6 +531,7 @@ def test_ci_jenkins_env(self): self.assertEqual(res["query"]["pr"], "1") self.assertEqual(res["query"]["branch"], "master") self.assertEqual(res["codecov"].token, "token") + self.assertEqual(res["codecov"].name, "name") @unittest.skipUnless(os.getenv("JENKINS_URL"), "Skip Jenkins CI test") def test_ci_jenkins_blue_ocean(self): @@ -531,6 +542,7 @@ def test_ci_jenkins_blue_ocean(self): CHANGE_ID="1", BUILD_NUMBER="41", CODECOV_TOKEN="token", + CODECOV_NAME="name", ) self.fake_report() res = self.run_cli() @@ -543,6 +555,7 @@ def test_ci_jenkins_blue_ocean(self): self.assertEqual(res["query"]["pr"], "1") self.assertEqual(res["query"]["branch"], "master") self.assertEqual(res["codecov"].token, "token") + self.assertEqual(res["codecov"].name, "name") @unittest.skipUnless( os.getenv("CI") == "true" @@ -585,6 +598,7 @@ def test_ci_codeship(self): CI_BUILD_URL="https://codeship.io/build/1", CI_COMMIT_ID="743b04806ea677403aa2ff26c6bdeb85005de658", CODECOV_TOKEN="token", + CODECOV_NAME="name", ) self.fake_report() res = self.run_cli() @@ -597,6 +611,7 @@ def test_ci_codeship(self): self.assertEqual(res["query"]["pr"], "") self.assertEqual(res["query"]["branch"], "master") self.assertEqual(res["codecov"].token, "token") + self.assertEqual(res["codecov"].name, "name") @unittest.skipUnless( os.getenv("CI") == "true" and os.getenv("CIRCLECI") == "true", @@ -638,6 +653,7 @@ def test_ci_buildkite(self): BUILDKITE_PROJECT_SLUG="owner/repo", BUILDKITE_COMMIT="d653b934ed59c1a785cc1cc79d08c9aaa4eba73b", CODECOV_TOKEN="token", + CODECOV_NAME="name", ) self.fake_report() res = self.run_cli() @@ -649,6 +665,7 @@ def test_ci_buildkite(self): self.assertEqual(res["query"]["slug"], "owner/repo") self.assertEqual(res["query"]["branch"], "master") self.assertEqual(res["codecov"].token, "token") + self.assertEqual(res["codecov"].name, "name") @unittest.skipUnless( os.getenv("CI") == "true" and os.getenv("SEMAPHORE") == "true", @@ -663,6 +680,7 @@ def test_ci_semaphore(self): SEMAPHORE_REPO_SLUG="owner/repo", REVISION="743b04806ea677403aa2ff26c6bdeb85005de658", CODECOV_TOKEN="token", + CODECOV_NAME="name", ) self.fake_report() res = self.run_cli() @@ -686,6 +704,7 @@ def test_ci_drone(self): DRONE_BRANCH="master", DRONE_BUILD_LINK="https://drone.io/github/builds/1", CODECOV_TOKEN="token", + CODECOV_NAME="name", ) self.fake_report() res = self.run_cli() @@ -696,6 +715,7 @@ def test_ci_drone(self): self.assertEqual(res["query"]["build"], "10") self.assertEqual(res["query"]["build_url"], "https://drone.io/github/builds/1") self.assertEqual(res["codecov"].token, "token") + self.assertEqual(res["codecov"].name, "name") @unittest.skipUnless(os.getenv("SHIPPABLE") == "true", "Skip Shippable CI test") def test_ci_shippable(self): @@ -707,6 +727,7 @@ def test_ci_shippable(self): BUILD_URL="https://shippable.com/...", COMMIT="743b04806ea677403aa2ff26c6bdeb85005de658", CODECOV_TOKEN="token", + CODECOV_NAME="name", ) self.fake_report() res = self.run_cli() @@ -718,6 +739,7 @@ def test_ci_shippable(self): self.assertEqual(res["query"]["slug"], "owner/repo") self.assertEqual(res["query"]["build_url"], "https://shippable.com/...") self.assertEqual(res["codecov"].token, "token") + self.assertEqual(res["codecov"].name, "name") # @unittest.skipUnless(os.getenv('CI') == "True" and os.getenv('APPVEYOR') == 'True', 'Skip AppVeyor CI test') @unittest.skip("Skip AppVeyor test") @@ -734,6 +756,7 @@ def test_ci_appveyor(self): APPVEYOR_REPO_NAME="owner/repo", APPVEYOR_REPO_COMMIT="d653b934ed59c1a785cc1cc79d08c9aaa4eba73b", CODECOV_TOKEN="token", + CODECOV_NAME="name", ) self.fake_report() res = self.run_cli(file=self.filepath) @@ -746,6 +769,7 @@ def test_ci_appveyor(self): self.assertEqual(res["query"]["slug"], "owner/repo") self.assertEqual(res["query"]["pr"], "1") self.assertEqual(res["codecov"].token, "token") + self.assertEqual(res["codecov"].name, "name") @unittest.skipUnless( os.getenv("CI") == "true" and os.getenv("WERCKER_GIT_BRANCH"), @@ -759,6 +783,7 @@ def test_ci_wercker(self): WERCKER_GIT_REPOSITORY="repo", WERCKER_GIT_COMMIT="d653b934ed59c1a785cc1cc79d08c9aaa4eba73b", CODECOV_TOKEN="token", + CODECOV_NAME="name", ) self.fake_report() res = self.run_cli() @@ -769,6 +794,7 @@ def test_ci_wercker(self): self.assertEqual(res["query"]["build"], "1399372237") self.assertEqual(res["query"]["slug"], "owner/repo") self.assertEqual(res["codecov"].token, "token") + self.assertEqual(res["codecov"].name, "name") @unittest.skipUnless( os.getenv("CI") == "true" and os.getenv("MAGNUM") == "true", @@ -782,6 +808,7 @@ def test_ci_magnum(self): CI="true", CI_COMMIT="d653b934ed59c1a785cc1cc79d08c9aaa4eba73b", CODECOV_TOKEN="token", + CODECOV_NAME="name", ) self.fake_report() res = self.run_cli() @@ -791,6 +818,7 @@ def test_ci_magnum(self): ) self.assertEqual(res["query"]["build"], "1399372237") self.assertEqual(res["codecov"].token, "token") + self.assertEqual(res["codecov"].name, "name") @unittest.skipUnless( os.getenv("CI_SERVER_NAME", "").startswith("GitLab"), "Skip GitLab CI test" @@ -805,6 +833,7 @@ def test_ci_gitlab_pre9(self): HOME="/", CI_PROJECT_DIR=os.getcwd().strip("/"), CODECOV_TOKEN="token", + CODECOV_NAME="name", ) self.fake_report() res = self.run_cli() @@ -815,6 +844,7 @@ def test_ci_gitlab_pre9(self): self.assertEqual(res["query"]["build"], "1399372237") self.assertEqual(res["query"]["slug"], "owner/repo") self.assertEqual(res["codecov"].token, "token") + self.assertEqual(res["codecov"].name, "name") @unittest.skipUnless( os.getenv("CI_SERVER_NAME", "").startswith("GitLab"), "Skip GitLab CI test" @@ -842,7 +872,7 @@ def test_ci_gitlab(self): @unittest.skip("Skip CI None") def test_ci_none(self): - self.set_env(CODECOV_TOKEN="token") + self.set_env(CODECOV_TOKEN="token", CODECOV_NAME="name") self.fake_report() res = self.run_cli( build=10, @@ -857,3 +887,4 @@ def test_ci_none(self): self.assertEqual(res["query"]["build"], "10") self.assertEqual(res["query"]["slug"], "owner/repo") self.assertEqual(res["codecov"].token, "token") + self.assertEqual(res["codecov"].name, "name") From 48a5613bdba2f7e0ad24914aaadc1d58662c7e7d Mon Sep 17 00:00:00 2001 From: Nathan Moinvaziri Date: Mon, 8 Jun 2020 13:32:26 -0700 Subject: [PATCH 109/144] Added GitHub Actions CI detection. (#265) --- codecov/__init__.py | 27 +++++++++++++++++++++++++++ tests/test.py | 28 ++++++++++++++++++++++++++++ 2 files changed, 55 insertions(+) diff --git a/codecov/__init__.py b/codecov/__init__.py index 377447b3..f7f5126e 100644 --- a/codecov/__init__.py +++ b/codecov/__init__.py @@ -790,6 +790,33 @@ def main(*argv, **kwargs): write(" Gitlab CI Detected") + # -------------- + # GitHub Actions + # -------------- + elif os.getenv("GITHUB_ACTION"): + # https://help.github.com/en/actions/configuring-and-managing-workflows/using-environment-variables + query.update( + dict( + service="github", + build=os.getenv("GITHUB_RUN_ID"), + commit=os.getenv("GITHUB_SHA"), + slug=os.getenv("GITHUB_REPOSITORY"), + build_url="http://github.com/" + + os.getenv("GITHUB_REPOSITORY") + + "/actions/runs/" + + os.getenv("GITHUB_RUN_ID"), + ) + ) + + if os.getenv("GITHUB_REF"): + query["branch"] = os.getenv("GITHUB_REF").split("/", 3)[-1] + if os.getenv("GITHUB_HEAD_REF"): + # PR refs are in the format: refs/pull/7/merge + query["pr"] = os.getenv("GITHUB_REF").split("/")[-2] + query["branch"] = os.getenv("GITHUB_HEAD_REF") + + write(" GitHub Actions CI Detected") + else: query.update( dict( diff --git a/tests/test.py b/tests/test.py index 59130d55..2188dac3 100644 --- a/tests/test.py +++ b/tests/test.py @@ -859,6 +859,7 @@ def test_ci_gitlab(self): HOME="/", CI_PROJECT_DIR=os.getcwd().strip("/"), CODECOV_TOKEN="token", + CODECOV_NAME="name", ) self.fake_report() res = self.run_cli() @@ -869,6 +870,33 @@ def test_ci_gitlab(self): self.assertEqual(res["query"]["build"], "1399372237") self.assertEqual(res["query"]["slug"], "owner/repo") self.assertEqual(res["codecov"].token, "token") + self.assertEqual(res["codecov"].name, "name") + + @unittest.skipUnless( + os.getenv("CI") == "true" and os.getenv("GITHUB_ACTION"), + "Skip GitHub Actions CI test", + ) + def test_ci_github(self): + self.set_env( + GITHUB_REF="master", + GITHUB_RUN_ID="1399372237", + GITHUB_REPOSITORY="owner/repo", + GITHUB_ACTION="6de813bb999760c81f96f3cf5dbdcd51cead172f", + GITHUB_SHA="d653b934ed59c1a785cc1cc79d08c9aaa4eba73b", + HOME="/", + CODECOV_TOKEN="token", + CODECOV_NAME="name", + ) + self.fake_report() + res = self.run_cli() + self.assertEqual(res["query"]["service"], "github") + self.assertEqual( + res["query"]["commit"], "d653b934ed59c1a785cc1cc79d08c9aaa4eba73b" + ) + self.assertEqual(res["query"]["build"], "1399372237") + self.assertEqual(res["query"]["slug"], "owner/repo") + self.assertEqual(res["codecov"].token, "token") + self.assertEqual(res["codecov"].name, "name") @unittest.skip("Skip CI None") def test_ci_none(self): From 07583f324c194d05ff32bc7ba20cc34cd1e12cc0 Mon Sep 17 00:00:00 2001 From: Thomas Hu Date: Fri, 12 Jun 2020 10:34:07 -0400 Subject: [PATCH 110/144] More retries (#273) * Try another retry * return * Retry all the things * Bail from the original retries * do real retries * fixes * syntax * black * Remove unnecessary var declaration --- codecov/__init__.py | 124 +++++++++++++++++++++++--------------------- 1 file changed, 64 insertions(+), 60 deletions(-) diff --git a/codecov/__init__.py b/codecov/__init__.py index f7f5126e..046f4cef 100644 --- a/codecov/__init__.py +++ b/codecov/__init__.py @@ -287,6 +287,14 @@ def generate_toc(root): return str(res).strip() or "" +def retry_upload(url, request_method, retries=3, break_codes=(200,), **kwargs): + for _ in range(retries): + res = request_method(url, **kwargs) + if res.status_code in break_codes: + return res + return res + + def main(*argv, **kwargs): root = os.getcwd() @@ -1093,71 +1101,67 @@ def main(*argv, **kwargs): reports_gzip = gzip_worker.compress(reports) + gzip_worker.flush() write(" Compressed contents to {0} bytes".format(len(reports_gzip))) - s3 = None - trys = 0 - while trys < 3: - trys += 1 - if "s3" not in codecov.disable: - try: - write(" Pinging Codecov...") - res = requests.post( - "%s/upload/v4?%s" % (codecov.url, urlargs), + success = False + if "s3" not in codecov.disable: + try: + write(" Pinging Codecov...") + res = retry_upload( + "%s/upload/v4?%s" % (codecov.url, urlargs), + requests.post, + break_codes=(200, 400, 406), + verify=codecov.cacert, + headers={ + "Accept": "text/plain", + "X-Reduced-Redundancy": "false", + "X-Content-Type": "application/x-gzip", + }, + ) + if res.status_code in (400, 406): + raise Exception(res.text) + + elif res.status_code < 500: + assert res.status_code == 200 + res = res.text.strip().split() + result, upload_url = res[0], res[1] + + write(" Uploading to S3...") + s3 = retry_upload( + upload_url, + requests.put, verify=codecov.cacert, + data=reports_gzip, headers={ - "Accept": "text/plain", - "X-Reduced-Redundancy": "false", - "X-Content-Type": "application/x-gzip", + "Content-Type": "application/x-gzip", + "Content-Encoding": "gzip", }, ) - if res.status_code in (400, 406): - raise Exception(res.text) - - elif res.status_code < 500: - assert res.status_code == 200 - res = res.text.strip().split() - result, upload_url = res[0], res[1] - - write(" Uploading to S3...") - s3 = requests.put( - upload_url, - verify=codecov.cacert, - data=reports_gzip, - headers={ - "Content-Type": "application/x-gzip", - "Content-Encoding": "gzip", - }, - ) - s3.raise_for_status() - assert s3.status_code == 200 - write(" " + result) - break - else: - # try again - continue - - except AssertionError: - write(" Direct to s3 failed. Using backup v2 endpoint.") - - write(" Uploading to Codecov...") + s3.raise_for_status() + assert s3.status_code == 200 + write(" " + result) + success = True + + except AssertionError: + write(" Direct to s3 failed. Using backup v2 endpoint.") + # just incase, try traditional upload - res = requests.post( - "%s/upload/v2?%s" % (codecov.url, urlargs), - verify=codecov.cacert, - data=reports_gzip, - headers={ - "Accept": "text/plain", - "Content-Type": "application/x-gzip", - "Content-Encoding": "gzip", - }, - ) - if res.status_code < 500: - write(" " + res.text) - res.raise_for_status() - result = res.text - return - - write(" Retrying... in %ds" % (trys * 30)) - sleep(trys * 30) + if not success: + write(" Uploading to Codecov...") + res = retry_upload( + "%s/upload/v2?%s" % (codecov.url, urlargs), + requests.post, + verify=codecov.cacert, + data=reports_gzip, + headers={ + "Accept": "text/plain", + "Content-Type": "application/x-gzip", + "Content-Encoding": "gzip", + }, + ) + if res.status_code < 500: + write(" " + res.text) + res.raise_for_status() + result = res.text + return except Exception as e: write("Error: " + str(e)) From 4cbedcd9d80b25c85bc1f08ac23ad4e5f0a806ef Mon Sep 17 00:00:00 2001 From: Thomas Hu Date: Fri, 12 Jun 2020 12:33:50 -0400 Subject: [PATCH 111/144] Bump to version 2.1.5 (#274) * Bump to version 2.1.5 * Update versions --- CHANGELOG.md | 6 ++++++ codecov/__version__.py | 2 +- tests/requirements.txt | 2 +- 3 files changed, 8 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index dea8451d..2ac93e00 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,9 @@ +### `2.1.5` + +- [#273](https://github.com/codecov/codecov-python/pull/273) Implement retries on Codecov API calls +- [#265](https://github.com/codecov/codecov-python/pull/265) Add GitHub Actions CI detection +- [#267](https://github.com/codecov/codecov-python/pull/267) Add CODECOV_NAME as default for name + ### `2.1.4` - [#260](https://github.com/codecov/codecov-python/pull/260) Enforce black formatting diff --git a/codecov/__version__.py b/codecov/__version__.py index f55a18b0..0ff00ce8 100644 --- a/codecov/__version__.py +++ b/codecov/__version__.py @@ -5,4 +5,4 @@ __license__ = "Apache 2.0" __title__ = "codecov" __url__ = "https://github.com/codecov/codecov-python" -__version__ = "2.1.4" +__version__ = "2.1.5" diff --git a/tests/requirements.txt b/tests/requirements.txt index f70ccf3f..953f4978 100644 --- a/tests/requirements.txt +++ b/tests/requirements.txt @@ -1,7 +1,7 @@ coverage>=4.4.0 ddt mock -pytest>=3.6.0 +pytest>=4.6.0 pytest-cov funcsigs requests From df2944949b58efb6b3b28489c7883bdbb15653cf Mon Sep 17 00:00:00 2001 From: Thomas Hu Date: Sat, 13 Jun 2020 19:47:58 -0400 Subject: [PATCH 112/144] Fix GitHub Actions service (#275) * Fix GitHub Actions service * Bump version * Add a GitHub Actions workflow * Lint later * Install requirements * log * more logging * Set some env variables * log * set env in the action * will it run * one test * Use the write SHA * black * Maybe checkout v2 * Fixes * All the things * Maybe token like this * Try now * Cleanup * black * Use coverage < 5 * Update requirements too * Run coverage? * Pin to 4.5.4 --- .github/workflows/build-test.yml | 40 ++++++++++++++++++++++++++++++++ CHANGELOG.md | 4 ++++ Makefile | 2 +- codecov/__init__.py | 2 +- codecov/__version__.py | 2 +- setup.py | 2 +- tests/requirements.txt | 2 +- tests/test.py | 19 ++++----------- 8 files changed, 54 insertions(+), 19 deletions(-) create mode 100644 .github/workflows/build-test.yml diff --git a/.github/workflows/build-test.yml b/.github/workflows/build-test.yml new file mode 100644 index 00000000..05b442a9 --- /dev/null +++ b/.github/workflows/build-test.yml @@ -0,0 +1,40 @@ +# This workflow will install Python dependencies, run tests and lint with a variety of Python versions +# For more information see: https://help.github.com/actions/language-and-framework-guides/using-python-with-github-actions + +name: Python package + +on: + push: + branches: [ master ] + pull_request: + branches: [ master ] + +jobs: + build: + + runs-on: ubuntu-latest + strategy: + matrix: + python-version: [3.5, 3.6, 3.7] + + steps: + - uses: actions/checkout@v2 + with: + ref: ${{ github.event.pull_request.head.sha }} + - name: Set up Python ${{ matrix.python-version }} + uses: actions/setup-python@v2 + with: + python-version: ${{ matrix.python-version }} + - name: Install dependencies + run: | + python -m pip install --upgrade pip + pip install -r tests/requirements.txt + - name: Test + run: | + make reinstall + make test + - name: Upload coverage reports to Codecov + run: | + codecov + env: # Or as an environment variable + super_secret: ${{ secrets.CODECOV_TOKEN }} diff --git a/CHANGELOG.md b/CHANGELOG.md index 2ac93e00..aa695dda 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,7 @@ +### `2.1.6` + +- [#275](https://github.com/codecov/codecov-python/pull/275) Fix GitHub Actions implementation + ### `2.1.5` - [#273](https://github.com/codecov/codecov-python/pull/273) Implement retries on Codecov API calls diff --git a/Makefile b/Makefile index 0b0a1ba2..7eae04f4 100644 --- a/Makefile +++ b/Makefile @@ -9,7 +9,7 @@ reinstall: python setup.py install test: - py.test tests/test.py + py.test tests/test.py --cov=codecov format: black . --check diff --git a/codecov/__init__.py b/codecov/__init__.py index 046f4cef..3308d1b9 100644 --- a/codecov/__init__.py +++ b/codecov/__init__.py @@ -805,7 +805,7 @@ def main(*argv, **kwargs): # https://help.github.com/en/actions/configuring-and-managing-workflows/using-environment-variables query.update( dict( - service="github", + service="github-actions", build=os.getenv("GITHUB_RUN_ID"), commit=os.getenv("GITHUB_SHA"), slug=os.getenv("GITHUB_REPOSITORY"), diff --git a/codecov/__version__.py b/codecov/__version__.py index 0ff00ce8..8344be9c 100644 --- a/codecov/__version__.py +++ b/codecov/__version__.py @@ -5,4 +5,4 @@ __license__ = "Apache 2.0" __title__ = "codecov" __url__ = "https://github.com/codecov/codecov-python" -__version__ = "2.1.5" +__version__ = "2.1.6" diff --git a/setup.py b/setup.py index 4d418234..60414316 100644 --- a/setup.py +++ b/setup.py @@ -40,7 +40,7 @@ packages=["codecov"], include_package_data=True, zip_safe=True, - install_requires=["requests>=2.7.9", "coverage"], + install_requires=["requests>=2.7.9", "coverage==4.5.4"], entry_points={"console_scripts": ["codecov=codecov:main"]}, python_requires=">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*", ) diff --git a/tests/requirements.txt b/tests/requirements.txt index 953f4978..b6f891ef 100644 --- a/tests/requirements.txt +++ b/tests/requirements.txt @@ -1,4 +1,4 @@ -coverage>=4.4.0 +coverage==4.5.4 ddt mock pytest>=4.6.0 diff --git a/tests/test.py b/tests/test.py index 2188dac3..de4af8e8 100644 --- a/tests/test.py +++ b/tests/test.py @@ -878,23 +878,14 @@ def test_ci_gitlab(self): ) def test_ci_github(self): self.set_env( - GITHUB_REF="master", - GITHUB_RUN_ID="1399372237", - GITHUB_REPOSITORY="owner/repo", - GITHUB_ACTION="6de813bb999760c81f96f3cf5dbdcd51cead172f", - GITHUB_SHA="d653b934ed59c1a785cc1cc79d08c9aaa4eba73b", - HOME="/", - CODECOV_TOKEN="token", - CODECOV_NAME="name", + HOME="/", CODECOV_TOKEN="token", CODECOV_NAME="name", ) self.fake_report() res = self.run_cli() - self.assertEqual(res["query"]["service"], "github") - self.assertEqual( - res["query"]["commit"], "d653b934ed59c1a785cc1cc79d08c9aaa4eba73b" - ) - self.assertEqual(res["query"]["build"], "1399372237") - self.assertEqual(res["query"]["slug"], "owner/repo") + self.assertEqual(res["query"]["service"], "github-actions") + self.assertEqual(res["query"]["commit"], os.getenv("GITHUB_SHA")) + self.assertEqual(res["query"]["build"], os.getenv("GITHUB_RUN_ID")) + self.assertEqual(res["query"]["slug"], os.getenv("GITHUB_REPOSITORY")) self.assertEqual(res["codecov"].token, "token") self.assertEqual(res["codecov"].name, "name") From b96c69cad6932e048d295875ee9542cea97290b9 Mon Sep 17 00:00:00 2001 From: Thomas Hu Date: Sun, 14 Jun 2020 14:20:40 -0400 Subject: [PATCH 113/144] Update to 2.1.7 (#279) * Update to 2.1.7 * Update CHANGELOOG --- CHANGELOG.md | 4 ++++ codecov/__version__.py | 2 +- setup.py | 2 +- 3 files changed, 6 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index aa695dda..81db7d77 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,7 @@ +### `2.1.7` + +- [#279](https://github.com/codecov/codecov-python/pull/279) Fix pinned coverage version + ### `2.1.6` - [#275](https://github.com/codecov/codecov-python/pull/275) Fix GitHub Actions implementation diff --git a/codecov/__version__.py b/codecov/__version__.py index 8344be9c..2661eb1e 100644 --- a/codecov/__version__.py +++ b/codecov/__version__.py @@ -5,4 +5,4 @@ __license__ = "Apache 2.0" __title__ = "codecov" __url__ = "https://github.com/codecov/codecov-python" -__version__ = "2.1.6" +__version__ = "2.1.7" diff --git a/setup.py b/setup.py index 60414316..4d418234 100644 --- a/setup.py +++ b/setup.py @@ -40,7 +40,7 @@ packages=["codecov"], include_package_data=True, zip_safe=True, - install_requires=["requests>=2.7.9", "coverage==4.5.4"], + install_requires=["requests>=2.7.9", "coverage"], entry_points={"console_scripts": ["codecov=codecov:main"]}, python_requires=">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*", ) From 812c700b879296e3a382266ed3ecfb163e828961 Mon Sep 17 00:00:00 2001 From: Thomas Hu Date: Mon, 15 Jun 2020 14:11:04 -0400 Subject: [PATCH 114/144] update README (#280) --- README.md | 46 ++++++++++++++++++++++++---------------------- 1 file changed, 24 insertions(+), 22 deletions(-) diff --git a/README.md b/README.md index 9d3a8451..ab54a802 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ Codecov Global Python Uploader ![PyPI](https://img.shields.io/pypi/v/codecov) [![codecov.io](https://codecov.io/github/codecov/codecov-python/coverage.svg?branch=master)](https://codecov.io/github/codecov/codecov-python) [![Code style: black](https://img.shields.io/badge/code%20style-black-000000.svg)](https://github.com/psf/black) ======= -| [https://codecov.io/][1] | [@codecov][2] | [hello@codecov.io][3] | -| ------------------------ | ------------- | --------------------- | +| [https://codecov.io/][1] | [https://community.codecov.io/][2] | [@codecov][3] | [hello@codecov.io][4] | +| ------------------------ | ---------------------------------- | ------------- | --------------------- | Find coverage reports for all the [languages below](#languages), gather them and submit them to Codecov. @@ -75,34 +75,36 @@ after_success: ## CI Providers | Company | Supported | Token Required | -| --------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------- | -| [Travis CI](https://travis-ci.org/) | Yes [![Build Status](https://secure.travis-ci.org/codecov/codecov-python.svg?branch=master)](https://travis-ci.org/codecov/codecov-python) | Private only | -| [CircleCI](https://circleci.com/) | Yes | Private only | -| [Codeship](https://codeship.com/) | Yes | Public & Private | -| [Jenkins](https://jenkins-ci.org/) | Yes | Public & Private | -| [Semaphore](https://semaphoreci.com/) | Yes | Public & Private | -| [Drone.io](https://drone.io/) | Yes | Public & Private | -| [AppVeyor](https://www.appveyor.com/) | Yes [![Build status](https://ci.appveyor.com/api/projects/status/sw18lsj7786bw806/branch/master?svg=true)](https://ci.appveyor.com/project/stevepeak/codecov-python/branch/master) | Private only | -| [Wercker](http://wercker.com/) | Yes | Public & Private | -| [Magnum CI](https://magnum-ci.com/) | Yes | Public & Private | -| [Shippable](https://www.shippable.com/) | Yes | Public & Private | -| [Gitlab CI](https://about.gitlab.com/gitlab-ci/) | Yes | Public & Private | -| Git / Mercurial | Yes (as a fallback) | Public & Private | -| [Buildbot](https://buildbot.net/) | `coming soon` [buildbot/buildbot#1671](https://github.com/buildbot/buildbot/pull/1671) | | -| [Bamboo](https://www.atlassian.com/software/bamboo) | `coming soon` | | -| [Solano Labs](https://www.solanolabs.com/) | `coming soon` | | +| ----------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------- | +| [AppVeyor](https://www.appveyor.com/) | Yes [![Build status](https://ci.appveyor.com/api/projects/status/sw18lsj7786bw806/branch/master?svg=true)](https://ci.appveyor.com/project/stevepeak/codecov-python/branch/master) | Private only | +| [Bamboo](https://www.atlassian.com/software/bamboo) | `coming soon` | | +| [Buildbot](https://buildbot.net/) | `coming soon` [buildbot/buildbot#1671](https://github.com/buildbot/buildbot/pull/1671) | | +| [CircleCI](https://circleci.com/) | Yes | Private only | +| [Codeship](https://codeship.com/) | Yes | Public & Private | +| [Drone.io](https://drone.io/) | Yes | Public & Private | +| [GitHub Actions](https://github.com/features/actions) | Yes [![Build status](https://github.com/codecov/codecov-python/workflows/Python%20package/badge.svg?branch=master)](https://github.com/codecov/codecov-python/actions?query=workflow%3A%22Python+package%22) | Public & Private | +| [Gitlab CI](https://about.gitlab.com/gitlab-ci/) | Yes | Public & Private | +| [Jenkins](https://jenkins-ci.org/) | Yes | Public & Private | +| [Magnum CI](https://magnum-ci.com/) | Yes | Public & Private | +| [Semaphore](https://semaphoreci.com/) | Yes | Public & Private | +| [Shippable](https://www.shippable.com/) | Yes | Public & Private | +| [Solano Labs](https://www.solanolabs.com/) | `coming soon` | | +| [Travis CI](https://travis-ci.org/) | Yes [![Build Status](https://secure.travis-ci.org/codecov/codecov-python.svg?branch=master)](https://travis-ci.org/codecov/codecov-python) | Private only | +| [Wercker](http://wercker.com/) | Yes | Public & Private | +| Git / Mercurial | Yes (as a fallback) | Public & Private | ## Troubleshooting -If you're seeing an **HTTP 400 error when uploading reports to S3**, make sure you've updated to at least version 2.1.3. +If you're seeing an **HTTP 400 error when uploading reports to S3**, make sure you've updated to at least version 2.1.3. [1]: https://codecov.io/ -[2]: https://twitter.com/codecov -[3]: mailto:hello@codecov.io +[2]: https://community.codecov.io/ +[3]: https://twitter.com/codecov +[4]: mailto:hello@codecov.io ## Copyright -> Copyright 2014-2019 codecov +> Copyright 2014-2020 codecov From fd8600750731191d965683d87b1cda3011743377 Mon Sep 17 00:00:00 2001 From: Nathan Moinvaziri Date: Mon, 22 Jun 2020 08:02:36 -0700 Subject: [PATCH 115/144] Added ability to specify the number of upload attempts via command line. (#276) * Added ability to specify the number of upload attempts via command line. * Update codecov/__init__.py * Update codecov/__init__.py * Update codecov/__init__.py * Update codecov/__init__.py Co-authored-by: Thomas Hu Co-authored-by: Thomas Hu --- codecov/__init__.py | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/codecov/__init__.py b/codecov/__init__.py index 3308d1b9..3886db7d 100644 --- a/codecov/__init__.py +++ b/codecov/__init__.py @@ -407,6 +407,12 @@ def main(*argv, **kwargs): help="Specify a custom pr number, provided automatically for supported CI companies", ) advanced.add_argument("--tag", default=None, help="Git tag") + advanced.add_argument( + "--tries", + default=3, + type=int, + help="Specify the total number of attempts to make when uploading coverage report", + ) enterprise = parser.add_argument_group( "======================== Enterprise ========================" @@ -1108,6 +1114,7 @@ def main(*argv, **kwargs): res = retry_upload( "%s/upload/v4?%s" % (codecov.url, urlargs), requests.post, + retries=codecov.tries, break_codes=(200, 400, 406), verify=codecov.cacert, headers={ @@ -1128,6 +1135,7 @@ def main(*argv, **kwargs): s3 = retry_upload( upload_url, requests.put, + retries=codecov.tries, verify=codecov.cacert, data=reports_gzip, headers={ @@ -1149,6 +1157,7 @@ def main(*argv, **kwargs): res = retry_upload( "%s/upload/v2?%s" % (codecov.url, urlargs), requests.post, + retries=codecov.tries, verify=codecov.cacert, data=reports_gzip, headers={ From c057a1b9ff1ceba57cc42e1e6ed38e53dc56414f Mon Sep 17 00:00:00 2001 From: Daniel Hahler Date: Wed, 15 Jul 2020 04:59:04 +0200 Subject: [PATCH 116/144] Add support for CODECOV_FLAGS (#285) --- codecov/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/codecov/__init__.py b/codecov/__init__.py index 3886db7d..be62793d 100644 --- a/codecov/__init__.py +++ b/codecov/__init__.py @@ -331,7 +331,7 @@ def main(*argv, **kwargs): "--flags", "-F", nargs="*", - default=None, + default=os.getenv("CODECOV_FLAGS"), help="Flag these uploaded files with custom labels", ) basics.add_argument( From 066706eb2fab6c0fbe7c8f35d9b4bf405bf5db9f Mon Sep 17 00:00:00 2001 From: Thomas Hu Date: Wed, 15 Jul 2020 22:11:17 -0400 Subject: [PATCH 117/144] Bump to 2.1.8 (#287) --- CHANGELOG.md | 5 +++++ codecov/__version__.py | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 81db7d77..e77e6c84 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,8 @@ +### `2.1.8` + +- [#285](https://github.com/codecov/codecov-python/pull/285)Add support for CODECOV_FLAGS +- [#276](https://github.com/codecov/codecov-python/pull/276)Add ability to specify number of upload retries + ### `2.1.7` - [#279](https://github.com/codecov/codecov-python/pull/279) Fix pinned coverage version diff --git a/codecov/__version__.py b/codecov/__version__.py index 2661eb1e..8e0b8295 100644 --- a/codecov/__version__.py +++ b/codecov/__version__.py @@ -5,4 +5,4 @@ __license__ = "Apache 2.0" __title__ = "codecov" __url__ = "https://github.com/codecov/codecov-python" -__version__ = "2.1.7" +__version__ = "2.1.8" From fb3a25ccd5175c8562718bc90754e3e09f0eaf58 Mon Sep 17 00:00:00 2001 From: Thomas Hu Date: Fri, 21 Aug 2020 07:57:14 -0400 Subject: [PATCH 118/144] Remove token restrictions (#289) * Remove token restrictions * Update version to 2.1.9 * Fix tests * force * Update CHANGELOG.md --- CHANGELOG.md | 4 ++++ README.md | 12 +++++++----- codecov/__init__.py | 9 --------- codecov/__version__.py | 2 +- tests/test.py | 12 ------------ 5 files changed, 12 insertions(+), 27 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index e77e6c84..ceb3f69e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,7 @@ +### `2.1.9` + +- [#289](https://github.com/codecov/codecov-python/pull/289)Remove token restriction as it is changed server-side + ### `2.1.8` - [#285](https://github.com/codecov/codecov-python/pull/285)Add support for CODECOV_FLAGS diff --git a/README.md b/README.md index ab54a802..600b86e3 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,10 @@ -Codecov Global Python Uploader ![PyPI](https://img.shields.io/pypi/v/codecov) [![codecov.io](https://codecov.io/github/codecov/codecov-python/coverage.svg?branch=master)](https://codecov.io/github/codecov/codecov-python) [![Code style: black](https://img.shields.io/badge/code%20style-black-000000.svg)](https://github.com/psf/black) +Codecov Global Python Uploader +[![codecov.io](https://codecov.io/github/codecov/codecov-python/coverage.svg?branch=master)](https://codecov.io/github/codecov/codecov-python) +![PyPI](https://img.shields.io/pypi/v/codecov) +[![Code style: black](https://img.shields.io/badge/code%20style-black-000000.svg)](https://github.com/psf/black) ======= -| [https://codecov.io/][1] | [https://community.codecov.io/][2] | [@codecov][3] | [hello@codecov.io][4] | -| ------------------------ | ---------------------------------- | ------------- | --------------------- | +| [Support][1] | [Documentation][2] | [Community Boards][3] | [Twitter][4] | +| ------------ | ------------------ | --------------------- | ------------ | Find coverage reports for all the [languages below](#languages), gather them and submit them to Codecov. @@ -100,10 +103,9 @@ If you're seeing an **HTTP 400 error when uploading reports to S3**, make sure y -[1]: https://codecov.io/ +[1]: https://codecov.io/support/ [2]: https://community.codecov.io/ [3]: https://twitter.com/codecov -[4]: mailto:hello@codecov.io ## Copyright diff --git a/codecov/__init__.py b/codecov/__init__.py index be62793d..e9645540 100644 --- a/codecov/__init__.py +++ b/codecov/__init__.py @@ -953,8 +953,6 @@ def main(*argv, **kwargs): if _slug: query["slug"] = _slug.groups()[1] - assert query.get("job") or query.get("token"), "Missing repository upload token" - # Processing gcov # --------------- if "gcov" in codecov.disable: @@ -1189,13 +1187,6 @@ def main(*argv, **kwargs): "Tip: See all example repositories: https://github.com/codecov?query=example" ) - write("Support channels:", "green") - write( - " Email: hello@codecov.io\n" - " IRC: #codecov\n" - " Gitter: https://gitter.im/codecov/support\n" - " Twitter: @codecov\n" - ) sys.exit(1 if codecov.required else 0) else: diff --git a/codecov/__version__.py b/codecov/__version__.py index 8e0b8295..26010cbb 100644 --- a/codecov/__version__.py +++ b/codecov/__version__.py @@ -5,4 +5,4 @@ __license__ = "Apache 2.0" __title__ = "codecov" __url__ = "https://github.com/codecov/codecov-python" -__version__ = "2.1.8" +__version__ = "2.1.9" diff --git a/tests/test.py b/tests/test.py index de4af8e8..39ca23a9 100644 --- a/tests/test.py +++ b/tests/test.py @@ -294,18 +294,6 @@ def test_send_error(self): else: raise Exception("400 never raised") - @data((dict(commit="sha"), "Missing repository upload token"),) - def test_require_branch(self, dd): - (kwargs, reason) = dd - # this is so we dont get branch for local git - self.set_env(JENKINS_URL="hello") - try: - self.run_cli(**kwargs) - except AssertionError as e: - self.assertEqual(str(e), reason) - else: - raise Exception("Did not raise AssertionError") - @unittest.skipIf( os.getenv("CI") == "True" and os.getenv("APPVEYOR") == "True", "Skip AppVeyor CI test", From ff88f77bdccc08fd584f5423acdbb076ee8b3cf0 Mon Sep 17 00:00:00 2001 From: Thomas Hu Date: Wed, 26 Aug 2020 09:40:40 -0400 Subject: [PATCH 119/144] Update python versions (#291) * Update python versions * Add 3.8 on GHA --- .github/workflows/build-test.yml | 2 +- .travis.yml | 4 ++-- setup.py | 1 + 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/.github/workflows/build-test.yml b/.github/workflows/build-test.yml index 05b442a9..7d826ac4 100644 --- a/.github/workflows/build-test.yml +++ b/.github/workflows/build-test.yml @@ -15,7 +15,7 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - python-version: [3.5, 3.6, 3.7] + python-version: [3.5, 3.6, 3.7, 3.8] steps: - uses: actions/checkout@v2 diff --git a/.travis.yml b/.travis.yml index 2e6150f9..238470ee 100644 --- a/.travis.yml +++ b/.travis.yml @@ -7,10 +7,10 @@ sudo: false python: - 2.7 - pypy - - 3.4 - 3.5 - 3.6 - 3.7 + - 3.8 - pypy3 matrix: include: @@ -24,7 +24,7 @@ matrix: - python-requests - python-coverage - python-mock - - python: 3.7 + - python: 3.8 dist: xenial script: make format diff --git a/setup.py b/setup.py index 4d418234..6deb6ae6 100644 --- a/setup.py +++ b/setup.py @@ -15,6 +15,7 @@ "Programming Language :: Python :: 3.5", "Programming Language :: Python :: 3.6", "Programming Language :: Python :: 3.7", + "Programming Language :: Python :: 3.8", "Programming Language :: Python :: Implementation :: PyPy", "License :: OSI Approved :: Apache Software License", "Topic :: Software Development :: Testing", From 14753520f744971720da9d8d10c8bf2f631a7608 Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Wed, 26 Aug 2020 09:59:24 -0400 Subject: [PATCH 120/144] Bump coverage from 4.5.4 to 5.2.1 (#290) Bumps [coverage](https://github.com/nedbat/coveragepy) from 4.5.4 to 5.2.1. - [Release notes](https://github.com/nedbat/coveragepy/releases) - [Changelog](https://github.com/nedbat/coveragepy/blob/master/CHANGES.rst) - [Commits](https://github.com/nedbat/coveragepy/compare/coverage-4.5.4...coverage-5.2.1) Signed-off-by: dependabot-preview[bot] Co-authored-by: dependabot-preview[bot] <27856297+dependabot-preview[bot]@users.noreply.github.com> --- tests/requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/requirements.txt b/tests/requirements.txt index b6f891ef..c7ff8052 100644 --- a/tests/requirements.txt +++ b/tests/requirements.txt @@ -1,4 +1,4 @@ -coverage==4.5.4 +coverage==5.2.1 ddt mock pytest>=4.6.0 From 6795ee05baa53172eb1c00b1e945fffa1d20e26e Mon Sep 17 00:00:00 2001 From: fossabot Date: Wed, 26 Aug 2020 17:44:13 -0500 Subject: [PATCH 121/144] Add license scan report and status (#292) Signed off by: fossabot --- README.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/README.md b/README.md index 600b86e3..28d3b0f3 100644 --- a/README.md +++ b/README.md @@ -2,6 +2,7 @@ Codecov Global Python Uploader [![codecov.io](https://codecov.io/github/codecov/codecov-python/coverage.svg?branch=master)](https://codecov.io/github/codecov/codecov-python) ![PyPI](https://img.shields.io/pypi/v/codecov) [![Code style: black](https://img.shields.io/badge/code%20style-black-000000.svg)](https://github.com/psf/black) +[![FOSSA Status](https://app.fossa.com/api/projects/git%2Bgithub.com%2Fcodecov%2Fcodecov-python.svg?type=shield)](https://app.fossa.com/projects/git%2Bgithub.com%2Fcodecov%2Fcodecov-python?ref=badge_shield) ======= | [Support][1] | [Documentation][2] | [Community Boards][3] | [Twitter][4] | | ------------ | ------------------ | --------------------- | ------------ | @@ -110,3 +111,7 @@ If you're seeing an **HTTP 400 error when uploading reports to S3**, make sure y ## Copyright > Copyright 2014-2020 codecov + + +## License +[![FOSSA Status](https://app.fossa.com/api/projects/git%2Bgithub.com%2Fcodecov%2Fcodecov-python.svg?type=large)](https://app.fossa.com/projects/git%2Bgithub.com%2Fcodecov%2Fcodecov-python?ref=badge_large) \ No newline at end of file From bf97a8bd807cd7839476f63b79b5ae22ae075d5e Mon Sep 17 00:00:00 2001 From: Thomas Hu Date: Mon, 31 Aug 2020 11:41:56 -0400 Subject: [PATCH 122/144] Update README with accurate links (#294) * Update README with accurate links * force * format * format * last format --- Makefile | 2 +- README.md | 10 ++++++---- tests/test.py | 6 ++++-- 3 files changed, 11 insertions(+), 7 deletions(-) diff --git a/Makefile b/Makefile index 7eae04f4..fae2de1e 100644 --- a/Makefile +++ b/Makefile @@ -12,7 +12,7 @@ test: py.test tests/test.py --cov=codecov format: - black . --check + black . -v -t py38 --check --diff compare: hub compare $(shell git tag --sort=refname | tail -1)...master diff --git a/README.md b/README.md index 28d3b0f3..d3a4a306 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,5 @@ -Codecov Global Python Uploader +# Codecov Global Python Uploader + [![codecov.io](https://codecov.io/github/codecov/codecov-python/coverage.svg?branch=master)](https://codecov.io/github/codecov/codecov-python) ![PyPI](https://img.shields.io/pypi/v/codecov) [![Code style: black](https://img.shields.io/badge/code%20style-black-000000.svg)](https://github.com/psf/black) @@ -105,8 +106,9 @@ If you're seeing an **HTTP 400 error when uploading reports to S3**, make sure y [1]: https://codecov.io/support/ -[2]: https://community.codecov.io/ -[3]: https://twitter.com/codecov +[2]: https://docs.codecov.io/ +[3]: https://community.codecov.io/ +[4]: https://twitter.com/codecov ## Copyright @@ -114,4 +116,4 @@ If you're seeing an **HTTP 400 error when uploading reports to S3**, make sure y ## License -[![FOSSA Status](https://app.fossa.com/api/projects/git%2Bgithub.com%2Fcodecov%2Fcodecov-python.svg?type=large)](https://app.fossa.com/projects/git%2Bgithub.com%2Fcodecov%2Fcodecov-python?ref=badge_large) \ No newline at end of file +[![FOSSA Status](https://app.fossa.com/api/projects/git%2Bgithub.com%2Fcodecov%2Fcodecov-python.svg?type=large)](https://app.fossa.com/projects/git%2Bgithub.com%2Fcodecov%2Fcodecov-python?ref=badge_large) diff --git a/tests/test.py b/tests/test.py index 39ca23a9..d17a0f77 100644 --- a/tests/test.py +++ b/tests/test.py @@ -278,7 +278,7 @@ def test_send(self): gzip_worker.decompress(put.call_args[1]["data"]) + gzip_worker.flush() ) - assert u"tests/test.py".encode("utf-8") in reports + assert "tests/test.py".encode("utf-8") in reports def test_send_error(self): with patch("requests.post") as post: @@ -866,7 +866,9 @@ def test_ci_gitlab(self): ) def test_ci_github(self): self.set_env( - HOME="/", CODECOV_TOKEN="token", CODECOV_NAME="name", + HOME="/", + CODECOV_TOKEN="token", + CODECOV_NAME="name", ) self.fake_report() res = self.run_cli() From 663888151217ff585b206ff721a61c429070a4ad Mon Sep 17 00:00:00 2001 From: Tomaz Muraus Date: Wed, 9 Sep 2020 22:58:13 +0200 Subject: [PATCH 123/144] Improve error reporting in the "try_run" function and correctly include original command output in the error message (#153) * Log more info when a command fails. * Also log return code. * Correctly include process output with the thrown exception. * Include returncode before the output. * Update codecov/__init__.py * black Co-authored-by: Thomas Hu Co-authored-by: Thomas Hu --- codecov/__init__.py | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/codecov/__init__.py b/codecov/__init__.py index e9645540..d3cc9d4f 100644 --- a/codecov/__init__.py +++ b/codecov/__init__.py @@ -213,7 +213,7 @@ def check_output(cmd, **popen_args): process = Popen(cmd, stdout=PIPE, **popen_args) output, _ = process.communicate() if process.returncode: - raise CalledProcessError(process.returncode, cmd) + raise CalledProcessError(process.returncode, cmd, output) else: assert process.returncode == 0 return output.decode("utf-8") @@ -223,7 +223,10 @@ def try_to_run(cmd, shell=False, cwd=None): try: return check_output(cmd, shell=shell, cwd=cwd) except Exception as e: - write(" Error running `%s`: %s" % (cmd, e or str(e))) + write( + " Error running `%s`: returncode=%s, output=%s" + % (cmd, e.returncode, str(getattr(e, "output", str(e)))) + ) return None From 0c56f298e88e609370b05ae2aa8d77e150518745 Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Mon, 14 Sep 2020 09:13:24 -0400 Subject: [PATCH 124/144] Bump coverage from 5.2.1 to 5.3 (#296) Bumps [coverage](https://github.com/nedbat/coveragepy) from 5.2.1 to 5.3. - [Release notes](https://github.com/nedbat/coveragepy/releases) - [Changelog](https://github.com/nedbat/coveragepy/blob/master/CHANGES.rst) - [Commits](https://github.com/nedbat/coveragepy/compare/coverage-5.2.1...coverage-5.3) Signed-off-by: dependabot-preview[bot] Co-authored-by: dependabot-preview[bot] <27856297+dependabot-preview[bot]@users.noreply.github.com> --- tests/requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/requirements.txt b/tests/requirements.txt index c7ff8052..0d22b4bd 100644 --- a/tests/requirements.txt +++ b/tests/requirements.txt @@ -1,4 +1,4 @@ -coverage==5.2.1 +coverage==5.3 ddt mock pytest>=4.6.0 From 2574d1b7c327d71df447551395e374441c38775f Mon Sep 17 00:00:00 2001 From: Nathan Moinvaziri Date: Mon, 14 Sep 2020 14:45:46 -0700 Subject: [PATCH 125/144] Added sleep between upload retries. (#295) * Added sleep 2s between upload retries. * Set default retries to 5 same as bash uploader. * Log retry attempts. --- codecov/__init__.py | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/codecov/__init__.py b/codecov/__init__.py index d3cc9d4f..3d6f4fc5 100644 --- a/codecov/__init__.py +++ b/codecov/__init__.py @@ -290,11 +290,14 @@ def generate_toc(root): return str(res).strip() or "" -def retry_upload(url, request_method, retries=3, break_codes=(200,), **kwargs): - for _ in range(retries): +def retry_upload(url, request_method, retries=5, break_codes=(200,), **kwargs): + wait_seconds = 2 + for i in range(retries): res = request_method(url, **kwargs) if res.status_code in break_codes: return res + write(" Retrying {0}/{1} in {2}s..".format(i + 1, retries, wait_seconds)) + sleep(wait_seconds) return res @@ -412,7 +415,7 @@ def main(*argv, **kwargs): advanced.add_argument("--tag", default=None, help="Git tag") advanced.add_argument( "--tries", - default=3, + default=5, type=int, help="Specify the total number of attempts to make when uploading coverage report", ) From 9137404b785122973abce66515c58d8999d0dbce Mon Sep 17 00:00:00 2001 From: Daniel Hahler Date: Tue, 15 Sep 2020 17:06:07 +0200 Subject: [PATCH 126/144] Output elapsed time with S3 upload (#148) * Output elapsed time with S3 upload It seems that it fails with "Forbidden" when it takes longer than 15s, so this at least helps with debugging that. The Bash uploader gzips the data file, so it is faster to upload and does not trigger it with the given data file / internet connection. (Pdb++) s3.text '\nAccessDeniedRequest has expired2018-05-19T11:58:04Z2018-05-19T11:58:10ZEFE63A2DA8CE9726LXoeTEXV7h3wN5DICvZg/U6uWIeyOgkJ1JnyEOQCpKNkQtpst4qKhkxuTgPnJeV3uB1jOexYP+s=' * black Co-authored-by: Thomas Hu --- codecov/__init__.py | 1 + 1 file changed, 1 insertion(+) diff --git a/codecov/__init__.py b/codecov/__init__.py index 3d6f4fc5..fd6ac89b 100644 --- a/codecov/__init__.py +++ b/codecov/__init__.py @@ -1149,6 +1149,7 @@ def main(*argv, **kwargs): ) s3.raise_for_status() assert s3.status_code == 200 + write(" Uploading to S3 took %s" % s3.elapsed) write(" " + result) success = True From dd8fe1a4b69ec71feb28553e74f93abe152703a8 Mon Sep 17 00:00:00 2001 From: Sajith Sasidharan Date: Tue, 15 Sep 2020 18:54:18 -0400 Subject: [PATCH 127/144] Ignore emacs lisp files (#297) Tahoe-LAFS project has a file named `/misc/coding_tools/coverage.el`, which is often uploaded to codecov along with the regular coverage report. I'm not sure it is doing any harm, but can't be doing anything useful either! It would be nice if codecov could ignore `.el` files. --- codecov/__init__.py | 1 + 1 file changed, 1 insertion(+) diff --git a/codecov/__init__.py b/codecov/__init__.py index fd6ac89b..370c03ff 100644 --- a/codecov/__init__.py +++ b/codecov/__init__.py @@ -88,6 +88,7 @@ def sanitize_arg(replacement, arg): r"(/\.coverage.*)|" r"(\.coveragerc)|" r"(\.egg)|" + r"(\.el)|" r"(\.gif)|" r"(\.ini)|" r"(\.less)|" From 713d94113e9b1189f227adc6131f04c65e4f967b Mon Sep 17 00:00:00 2001 From: Pierre Augier Date: Mon, 21 Sep 2020 21:20:12 +0200 Subject: [PATCH 128/144] Fix error try_to_run using | without shell=True (#298) --- codecov/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/codecov/__init__.py b/codecov/__init__.py index 370c03ff..e337717e 100644 --- a/codecov/__init__.py +++ b/codecov/__init__.py @@ -869,7 +869,7 @@ def main(*argv, **kwargs): try: query["commit"] = try_to_run( ["git", "rev-parse", "HEAD"] - ) or try_to_run(["hg", "id", "-i", "--debug", "|", "tr", "-d", "'+'"]) + ) or try_to_run(["hg", "log", "-r", ".", "-T", "{node}"]) write(" -> Got sha from git/hg") except: # pragma: no cover From 76b4f7cbb5602332eac3bcae027b9fa24efbf4ac Mon Sep 17 00:00:00 2001 From: Tom Hu Date: Fri, 9 Oct 2020 08:32:28 -0400 Subject: [PATCH 129/144] Bump to 2.1.10 (#300) --- CHANGELOG.md | 16 ++++++++++++++++ codecov/__version__.py | 2 +- 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index ceb3f69e..c70fc15a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,19 @@ +### `2.1.10` + +#### Fixes +- [#148](https://github.com/codecov/codecov-python/pull/148) Output elapsed time with S3 upload +- [#153](https://github.com/codecov/codecov-python/pull/153) Improve error reporting in the "try_run" function and correctly include original command output in the error message +- [#295](https://github.com/codecov/codecov-python/pull/295) Added sleep between upload retries. +- [#297](https://github.com/codecov/codecov-python/pull/297) Ignore emacs lisp files +- [#298](https://github.com/codecov/codecov-python/pull/298) Fix error try_to_run using | without shell=True (fix #284) + +#### Dependencies and Misc +- [#290](https://github.com/codecov/codecov-python/pull/290) Bump coverage from 4.5.4 to 5.2.1 +- [#291](https://github.com/codecov/codecov-python/pull/291) Update python versions +- [#292](https://github.com/codecov/codecov-python/pull/292) Add license scan report and status +- [#294](https://github.com/codecov/codecov-python/pull/294) Update README with accurate links +- [#296](https://github.com/codecov/codecov-python/pull/296) Bump coverage from 5.2.1 to 5.3 + ### `2.1.9` - [#289](https://github.com/codecov/codecov-python/pull/289)Remove token restriction as it is changed server-side diff --git a/codecov/__version__.py b/codecov/__version__.py index 26010cbb..0e467e9f 100644 --- a/codecov/__version__.py +++ b/codecov/__version__.py @@ -5,4 +5,4 @@ __license__ = "Apache 2.0" __title__ = "codecov" __url__ = "https://github.com/codecov/codecov-python" -__version__ = "2.1.9" +__version__ = "2.1.10" From 5862842228187f4ed919bf8f9c1ac3692d1ccbbc Mon Sep 17 00:00:00 2001 From: Gaurav Sheni Date: Fri, 16 Oct 2020 10:07:28 -0400 Subject: [PATCH 130/144] Update to Python 3.9 (#301) * Update .travis.yml * Update setup.py * Update build-test.yml * Update .travis.yml Co-authored-by: Tom Hu --- .github/workflows/build-test.yml | 2 +- .travis.yml | 1 + setup.py | 1 + 3 files changed, 3 insertions(+), 1 deletion(-) diff --git a/.github/workflows/build-test.yml b/.github/workflows/build-test.yml index 7d826ac4..b07bc8fb 100644 --- a/.github/workflows/build-test.yml +++ b/.github/workflows/build-test.yml @@ -15,7 +15,7 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - python-version: [3.5, 3.6, 3.7, 3.8] + python-version: [3.5, 3.6, 3.7, 3.8, 3.9] steps: - uses: actions/checkout@v2 diff --git a/.travis.yml b/.travis.yml index 238470ee..f69f56d8 100644 --- a/.travis.yml +++ b/.travis.yml @@ -11,6 +11,7 @@ python: - 3.6 - 3.7 - 3.8 + - 3.9-dev - pypy3 matrix: include: diff --git a/setup.py b/setup.py index 6deb6ae6..b5639c73 100644 --- a/setup.py +++ b/setup.py @@ -16,6 +16,7 @@ "Programming Language :: Python :: 3.6", "Programming Language :: Python :: 3.7", "Programming Language :: Python :: 3.8", + "Programming Language :: Python :: 3.9", "Programming Language :: Python :: Implementation :: PyPy", "License :: OSI Approved :: Apache Software License", "Topic :: Software Development :: Testing", From 58032a4960cf1fb62ebaa88297440e92726ea2ac Mon Sep 17 00:00:00 2001 From: Nathan Moinvaziri Date: Wed, 9 Dec 2020 18:35:44 -0800 Subject: [PATCH 131/144] Added option to disable printing of gcov-out (#305) --- codecov/__init__.py | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/codecov/__init__.py b/codecov/__init__.py index e337717e..2b338d8b 100644 --- a/codecov/__init__.py +++ b/codecov/__init__.py @@ -376,6 +376,9 @@ def main(*argv, **kwargs): gcov.add_argument( "--gcov-exec", default="gcov", help="gcov executable to run. Defaults to 'gcov'" ) + gcov.add_argument( + "--no-gcov-out", action="store_true", default=False, help="Disable gcov output" + ) gcov.add_argument("--gcov-args", default="", help="extra arguments to pass to gcov") advanced = parser.add_argument_group( @@ -982,8 +985,11 @@ def main(*argv, **kwargs): if codecov.gcov_args: cmd.append(sanitize_arg("", codecov.gcov_args or "")) cmd.append(path) - write(" Executing gcov (%s)" % cmd) - write(try_to_run(cmd)) + if not codecov.no_gcov_out: + write(" Executing gcov (%s)" % cmd) + gcov_out = try_to_run(cmd) + if not codecov.no_gcov_out: + write(gcov_out) # Collect Reports # --------------- From f4b116df8fac14dd98c52acf2a1ca0ac8d54db68 Mon Sep 17 00:00:00 2001 From: Udi Meiri Date: Sat, 12 Dec 2020 14:29:56 -0800 Subject: [PATCH 132/144] Handle exceptions that don't have a returncode (#308) Fixes #307 --- codecov/__init__.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/codecov/__init__.py b/codecov/__init__.py index 2b338d8b..9490dd40 100644 --- a/codecov/__init__.py +++ b/codecov/__init__.py @@ -226,7 +226,11 @@ def try_to_run(cmd, shell=False, cwd=None): except Exception as e: write( " Error running `%s`: returncode=%s, output=%s" - % (cmd, e.returncode, str(getattr(e, "output", str(e)))) + % ( + cmd, + str(getattr(e, "returncode", None)), + str(getattr(e, "output", str(e))), + ) ) return None From a8f6ff27feb6600731a3efef6cff9d54469efa30 Mon Sep 17 00:00:00 2001 From: Tom Hu Date: Thu, 17 Dec 2020 10:48:10 -0500 Subject: [PATCH 133/144] Bump to 2.1.11 (#310) --- CHANGELOG.md | 11 ++++++++++- codecov/__version__.py | 2 +- 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index c70fc15a..21256923 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,12 @@ +### `2.1.11` + +#### Fixes +- #305 Added option to disable printing of gcov-out +- #308 Handle exceptions that don't have a returncode + +#### Dependencies and Misc +- #301 Update to Python 3.9 + ### `2.1.10` #### Fixes @@ -10,7 +19,7 @@ #### Dependencies and Misc - [#290](https://github.com/codecov/codecov-python/pull/290) Bump coverage from 4.5.4 to 5.2.1 - [#291](https://github.com/codecov/codecov-python/pull/291) Update python versions -- [#292](https://github.com/codecov/codecov-python/pull/292) Add license scan report and status +- [#292](https://github.com/codecov/codecov-python/pull/292) Add license scan report and status - [#294](https://github.com/codecov/codecov-python/pull/294) Update README with accurate links - [#296](https://github.com/codecov/codecov-python/pull/296) Bump coverage from 5.2.1 to 5.3 diff --git a/codecov/__version__.py b/codecov/__version__.py index 0e467e9f..bc5c0a72 100644 --- a/codecov/__version__.py +++ b/codecov/__version__.py @@ -5,4 +5,4 @@ __license__ = "Apache 2.0" __title__ = "codecov" __url__ = "https://github.com/codecov/codecov-python" -__version__ = "2.1.10" +__version__ = "2.1.11" From 147802d7403db0c21b81820ba9a8619b8d398b2b Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Thu, 21 Jan 2021 13:07:57 -0500 Subject: [PATCH 134/144] Bump coverage from 5.3 to 5.3.1 (#311) Bumps [coverage](https://github.com/nedbat/coveragepy) from 5.3 to 5.3.1. - [Release notes](https://github.com/nedbat/coveragepy/releases) - [Changelog](https://github.com/nedbat/coveragepy/blob/master/CHANGES.rst) - [Commits](https://github.com/nedbat/coveragepy/compare/coverage-5.3...coverage-5.3.1) Signed-off-by: dependabot-preview[bot] Co-authored-by: dependabot-preview[bot] <27856297+dependabot-preview[bot]@users.noreply.github.com> --- tests/requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/requirements.txt b/tests/requirements.txt index 0d22b4bd..55995759 100644 --- a/tests/requirements.txt +++ b/tests/requirements.txt @@ -1,4 +1,4 @@ -coverage==5.3 +coverage==5.3.1 ddt mock pytest>=4.6.0 From 26fe18b0e7019e3415f1df525fbe4dfb72057714 Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Fri, 12 Feb 2021 09:33:38 -0500 Subject: [PATCH 135/144] Bump coverage from 5.3.1 to 5.4 (#312) Bumps [coverage](https://github.com/nedbat/coveragepy) from 5.3.1 to 5.4. - [Release notes](https://github.com/nedbat/coveragepy/releases) - [Changelog](https://github.com/nedbat/coveragepy/blob/master/CHANGES.rst) - [Commits](https://github.com/nedbat/coveragepy/compare/coverage-5.3.1...coverage-5.4) Signed-off-by: dependabot-preview[bot] Co-authored-by: dependabot-preview[bot] <27856297+dependabot-preview[bot]@users.noreply.github.com> --- tests/requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/requirements.txt b/tests/requirements.txt index 55995759..577a93c5 100644 --- a/tests/requirements.txt +++ b/tests/requirements.txt @@ -1,4 +1,4 @@ -coverage==5.3.1 +coverage==5.4 ddt mock pytest>=4.6.0 From 158a38eed7fd6f0d2f9c9f4c5258ab1f244b6e13 Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Fri, 5 Mar 2021 09:28:36 -0500 Subject: [PATCH 136/144] Bump coverage from 5.4 to 5.5 (#314) Bumps [coverage](https://github.com/nedbat/coveragepy) from 5.4 to 5.5. - [Release notes](https://github.com/nedbat/coveragepy/releases) - [Changelog](https://github.com/nedbat/coveragepy/blob/master/CHANGES.rst) - [Commits](https://github.com/nedbat/coveragepy/compare/coverage-5.4...coverage-5.5) Signed-off-by: dependabot-preview[bot] Co-authored-by: dependabot-preview[bot] <27856297+dependabot-preview[bot]@users.noreply.github.com> --- tests/requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/requirements.txt b/tests/requirements.txt index 577a93c5..7dbe1dda 100644 --- a/tests/requirements.txt +++ b/tests/requirements.txt @@ -1,4 +1,4 @@ -coverage==5.4 +coverage==5.5 ddt mock pytest>=4.6.0 From 51469b065f0e16d4bedf121552b5e1eb58e18125 Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Sat, 1 May 2021 17:46:24 -0400 Subject: [PATCH 137/144] Upgrade to GitHub-native Dependabot (#320) Co-authored-by: dependabot-preview[bot] <27856297+dependabot-preview[bot]@users.noreply.github.com> --- .github/dependabot.yml | 7 +++++++ 1 file changed, 7 insertions(+) create mode 100644 .github/dependabot.yml diff --git a/.github/dependabot.yml b/.github/dependabot.yml new file mode 100644 index 00000000..491deae0 --- /dev/null +++ b/.github/dependabot.yml @@ -0,0 +1,7 @@ +version: 2 +updates: +- package-ecosystem: pip + directory: "/" + schedule: + interval: daily + open-pull-requests-limit: 10 From 27a9833441ab179118716b86026e526919b2a0db Mon Sep 17 00:00:00 2001 From: Anderson Bravalheri Date: Tue, 6 Jul 2021 21:39:09 +0100 Subject: [PATCH 138/144] Add Cirrus CI (#322) * Add Cirrus CI This is a follow up of the discussion in: https://community.codecov.com/t/add-support-of-uploading-from-cirrus-ci-without-token/1028/34 and uses the bash uploader as a reference: https://github.com/codecov/codecov-bash/blob/master/codecov#L959 * Add test case for Cirrus CI --- README.md | 3 ++- codecov/__init__.py | 21 ++++++++++++++++++++- tests/test.py | 31 +++++++++++++++++++++++++++++++ 3 files changed, 53 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index d3a4a306..6a061739 100644 --- a/README.md +++ b/README.md @@ -79,7 +79,7 @@ after_success: ## CI Providers -| Company | Supported | Token Required | +| Company | Supported | Token Required | | ----------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------- | | [AppVeyor](https://www.appveyor.com/) | Yes [![Build status](https://ci.appveyor.com/api/projects/status/sw18lsj7786bw806/branch/master?svg=true)](https://ci.appveyor.com/project/stevepeak/codecov-python/branch/master) | Private only | | [Bamboo](https://www.atlassian.com/software/bamboo) | `coming soon` | | @@ -96,6 +96,7 @@ after_success: | [Solano Labs](https://www.solanolabs.com/) | `coming soon` | | | [Travis CI](https://travis-ci.org/) | Yes [![Build Status](https://secure.travis-ci.org/codecov/codecov-python.svg?branch=master)](https://travis-ci.org/codecov/codecov-python) | Private only | | [Wercker](http://wercker.com/) | Yes | Public & Private | +| [Cirrus CI](https://cirrus-ci.org/) | Yes | Private only | | Git / Mercurial | Yes (as a fallback) | Public & Private | diff --git a/codecov/__init__.py b/codecov/__init__.py index 9490dd40..99109edf 100644 --- a/codecov/__init__.py +++ b/codecov/__init__.py @@ -329,7 +329,7 @@ def main(*argv, **kwargs): "--token", "-t", default=os.getenv("CODECOV_TOKEN"), - help="Private repository token or @filename for file containing the token. Defaults to $CODECOV_TOKEN. Not required for public repositories on Travis CI, CircleCI and AppVeyor", + help="Private repository token or @filename for file containing the token. Defaults to $CODECOV_TOKEN. Not required for public repositories on Travis CI, CircleCI, AppVeyor and CirrusCI", ) basics.add_argument( "--file", @@ -845,6 +845,25 @@ def main(*argv, **kwargs): write(" GitHub Actions CI Detected") + # --------- + # Cirrus CI + # --------- + elif os.getenv("CIRRUS_CI"): + # https://cirrus-ci.org/guide/writing-tasks/#environment-variables + query.update( + dict( + service="cirrus-ci", + slug=os.getenv("CIRRUS_REPO_FULL_NAME"), + branch=os.getenv("CIRRUS_BRANCH"), + pr=os.getenv("CIRRUS_PR"), + commit=os.getenv("CIRRUS_CHANGE_IN_REPO"), + build=os.getenv("CIRRUS_BUILD_ID"), + build_url="https://cirrus-ci.com/task/" + os.getenv("CIRRUS_TASK_ID"), + job=os.getenv("CIRRUS_TASK_NAME"), + ) + ) + write(" Cirrus CI Detected") + else: query.update( dict( diff --git a/tests/test.py b/tests/test.py index d17a0f77..98a4412a 100644 --- a/tests/test.py +++ b/tests/test.py @@ -879,6 +879,37 @@ def test_ci_github(self): self.assertEqual(res["codecov"].token, "token") self.assertEqual(res["codecov"].name, "name") + @unittest.skipUnless( + os.getenv("CI") == "true" and os.getenv("CIRRUS_CI") == "true", + "Skip Cirrus CI", + ) + def test_ci_cirrus(self): + # The data used in this test follows the test case data in + # https://github.com/codecov/codecov-bash/pull/127 + # Discussion about using codecov without token for Cirrus CI can be seen in: + # https://community.codecov.com/t/add-support-of-uploading-from-cirrus-ci-without-token/1028/36 + self.set_env( + HOME="/", + CIRRUS_CI="true", + CIRRUS_REPO_FULL_NAME="codecov/ci-repo", + CIRRUS_BRANCH="master", + CIRRUS_PR="1", + CIRRUS_CHANGE_IN_REPO="180c0d097354fc1a451da8a3be5aba255f2ffd9f", + CIRRUS_BUILD_ID="777", + CIRRUS_TASK_ID="239", + CIRRUS_TASK_NAME="test" + ) + self.fake_report() + res = self.run_cli() + self.assertEqual(res["query"]["service"], "cirrus-ci") + self.assertEqual(res["query"]["slug"], "codecov/ci-repo") + self.assertEqual(res["query"]["branch"], "master") + self.assertEqual(res["query"]["pr"], "1") + self.assertEqual(res["query"]["commit"], os.getenv("CIRRUS_CHANGE_IN_REPO")) + self.assertEqual(res["query"]["build"], "777") + self.assertEqual(res["query"]["build_url"], "https://cirrus-ci.com/task/239") + self.assertEqual(res["query"]["job"], "test") + @unittest.skip("Skip CI None") def test_ci_none(self): self.set_env(CODECOV_TOKEN="token", CODECOV_NAME="name") From fcff43933beb9f242e6ef0eb4c70670f4543e289 Mon Sep 17 00:00:00 2001 From: Tom Hu <88201630+thomasrockhu-codecov@users.noreply.github.com> Date: Mon, 2 Aug 2021 13:55:46 -0400 Subject: [PATCH 139/144] chore: bump to 2.1.12 (#323) --- CHANGELOG.md | 11 +++++++++++ codecov/__version__.py | 2 +- 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 21256923..d5eb65e5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,14 @@ +### `2.1.12` + +#### Fixes +- #322 Add Cirrus CI + +#### Dependencies and Misc +- #311 Bump coverage from 5.3 to 5.3.1 +- #312 Bump coverage from 5.3.1 to 5.4 +- #314 Bump coverage from 5.4 to 5.5 +- #320 Upgrade to GitHub-native Dependabot + ### `2.1.11` #### Fixes diff --git a/codecov/__version__.py b/codecov/__version__.py index bc5c0a72..c79ac593 100644 --- a/codecov/__version__.py +++ b/codecov/__version__.py @@ -5,4 +5,4 @@ __license__ = "Apache 2.0" __title__ = "codecov" __url__ = "https://github.com/codecov/codecov-python" -__version__ = "2.1.11" +__version__ = "2.1.12" From 46e1b8c69923a8c6a94c8de4ec1c950c7c6cc1e8 Mon Sep 17 00:00:00 2001 From: Tom Hu <88201630+thomasrockhu-codecov@users.noreply.github.com> Date: Thu, 2 Sep 2021 17:23:17 -0400 Subject: [PATCH 140/144] Add deprecation notice (#325) * Add deprecation notice * Add link to uploader source --- README.md | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/README.md b/README.md index 6a061739..a617c4fc 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,11 @@ +🚨🚨 Deprecation Notice 🚨🚨 + +This uploader is being deprecated by the Codecov team. We recommend migrating to our [new uploader](https://docs.codecov.com/docs/codecov-uploader) as soon as possible to prevent any lapses in coverage. [The new uploader is open source](https://github.com/codecov/uploader), and we highly encourage submitting Issues and Pull Requests. + +You can visit our blog post to learn more about our [deprecation plan](https://about.codecov.io/blog/codecov-uploader-deprecation-plan/) + +**On February 1, 2022 this uploader will be completely deprecated and will no longer be able to upload coverage to Codecov.** + # Codecov Global Python Uploader [![codecov.io](https://codecov.io/github/codecov/codecov-python/coverage.svg?branch=master)](https://codecov.io/github/codecov/codecov-python) From 12c0dddd6350a1d511f22d363e89d9019b149164 Mon Sep 17 00:00:00 2001 From: Tom Hu <88201630+thomasrockhu-codecov@users.noreply.github.com> Date: Tue, 5 Oct 2021 08:46:50 -0400 Subject: [PATCH 141/144] Add migration guide link (#327) --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index a617c4fc..f6fef3ad 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,7 @@ This uploader is being deprecated by the Codecov team. We recommend migrating to our [new uploader](https://docs.codecov.com/docs/codecov-uploader) as soon as possible to prevent any lapses in coverage. [The new uploader is open source](https://github.com/codecov/uploader), and we highly encourage submitting Issues and Pull Requests. -You can visit our blog post to learn more about our [deprecation plan](https://about.codecov.io/blog/codecov-uploader-deprecation-plan/) +You can visit our [migration guide](https://docs.codecov.com/docs/deprecated-uploader-migration-guide#python-uploader) for help moving to our new uploader, and our blog post to learn more about our [deprecation plan](https://about.codecov.io/blog/codecov-uploader-deprecation-plan/) **On February 1, 2022 this uploader will be completely deprecated and will no longer be able to upload coverage to Codecov.** From 37663707961db1092134500fe19638a5c08c52c2 Mon Sep 17 00:00:00 2001 From: Tom Hu <88201630+thomasrockhu-codecov@users.noreply.github.com> Date: Fri, 23 Sep 2022 00:01:37 -0400 Subject: [PATCH 142/144] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index f6fef3ad..27531afd 100644 --- a/README.md +++ b/README.md @@ -121,7 +121,7 @@ If you're seeing an **HTTP 400 error when uploading reports to S3**, make sure y ## Copyright -> Copyright 2014-2020 codecov +> Copyright 2014-2022 codecov ## License From a78512e4b00e67cfb3fccb530c9ca97a6c42eae5 Mon Sep 17 00:00:00 2001 From: Tom Hu Date: Mon, 17 Apr 2023 16:09:07 -0700 Subject: [PATCH 143/144] chore(release): bump to 3.1.13 --- codecov/__version__.py | 2 +- setup.py | 10 ++++++++++ 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/codecov/__version__.py b/codecov/__version__.py index c79ac593..60d08bb3 100644 --- a/codecov/__version__.py +++ b/codecov/__version__.py @@ -5,4 +5,4 @@ __license__ = "Apache 2.0" __title__ = "codecov" __url__ = "https://github.com/codecov/codecov-python" -__version__ = "2.1.12" +__version__ = "2.1.13" diff --git a/setup.py b/setup.py index b5639c73..1025c49b 100644 --- a/setup.py +++ b/setup.py @@ -2,6 +2,13 @@ from codecs import open import os from setuptools import setup +from setuptools.command.install import install + +class PostInstallCommand(install): + def run(self): + install.run(self) + print("\n**** The codecov package has been deprecated and will be removed by the team in the future. Please update to use the uploader (https://docs.codecov.com/docs/codecov-uploader) to prevent any breakages in workflow. ****\n") + classifiers = [ "Development Status :: 5 - Production/Stable", @@ -45,4 +52,7 @@ install_requires=["requests>=2.7.9", "coverage"], entry_points={"console_scripts": ["codecov=codecov:main"]}, python_requires=">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*", + cmdclass={ + 'install': PostInstallCommand, + }, ) From e553e93ed1404095acaf9a8bc3ef239675d3b88e Mon Sep 17 00:00:00 2001 From: Tom Hu <88201630+thomasrockhu-codecov@users.noreply.github.com> Date: Tue, 18 Apr 2023 14:38:11 -0700 Subject: [PATCH 144/144] chore(ci): bump python and update packages (#351) --- .github/workflows/build-test.yml | 6 ++--- .travis.yml | 40 -------------------------------- 2 files changed, 3 insertions(+), 43 deletions(-) delete mode 100644 .travis.yml diff --git a/.github/workflows/build-test.yml b/.github/workflows/build-test.yml index b07bc8fb..154d8a07 100644 --- a/.github/workflows/build-test.yml +++ b/.github/workflows/build-test.yml @@ -15,14 +15,14 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - python-version: [3.5, 3.6, 3.7, 3.8, 3.9] + python-version: ["3.7", "3.8", "3.9", "3.10", "3.11"] steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 with: ref: ${{ github.event.pull_request.head.sha }} - name: Set up Python ${{ matrix.python-version }} - uses: actions/setup-python@v2 + uses: actions/setup-python@v3 with: python-version: ${{ matrix.python-version }} - name: Install dependencies diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index f69f56d8..00000000 --- a/.travis.yml +++ /dev/null @@ -1,40 +0,0 @@ -language: python -# cache: pip -notifications: - email: false -dist: xenial -sudo: false -python: - - 2.7 - - pypy - - 3.5 - - 3.6 - - 3.7 - - 3.8 - - 3.9-dev - - pypy3 -matrix: - include: - - python: 2.7 - dist: trusty - virtualenv: - system_site_packages: true - addons: - apt: - packages: - - python-requests - - python-coverage - - python-mock - - python: 3.8 - dist: xenial - script: make format - -install: - - pip install -r tests/requirements.txt - - python setup.py install -script: - - make reinstall - - make test - # - pytest tests/test.py --cov=codecov -after_success: - - codecov