From 48642f9e96a4f1f4b6a361e228c1d764933c1403 Mon Sep 17 00:00:00 2001 From: Anderson Bravalheri Date: Thu, 3 Jun 2021 15:06:41 +0100 Subject: [PATCH 1/3] feat(api): support generic CI env vars (#299) The official docs for Coveralls define a set of generic environment variables that once defined should support any CI environment: https://docs.coveralls.io/supported-ci-services (bottom of the page). The changes implemented in this PR attempt to read those variables but allows the values to be overwritten by any CI-specific configuration currently supported. They were also inspired by the official client (coveralls-ruby - lib/coveralls/configuration.rb - set_standard_service_params_for_generic_ci). --- coveralls/api.py | 30 ++++++++++++++++++++++++++++- docs/usage/configuration.rst | 24 +++++++++++++++++++++++ tests/api/configuration_test.py | 34 +++++++++++++++++++++++++++++++++ 3 files changed, 87 insertions(+), 1 deletion(-) diff --git a/coveralls/api.py b/coveralls/api.py index cb9db7fd..d5b1b589 100644 --- a/coveralls/api.py +++ b/coveralls/api.py @@ -16,6 +16,8 @@ log = logging.getLogger('coveralls.api') +NUMBER_REGEX = re.compile(r'(\d+)$', re.IGNORECASE) + class Coveralls: # pylint: disable=too-many-public-methods @@ -144,7 +146,33 @@ def load_config_from_semaphore(): def load_config_from_unknown(): return 'coveralls-python', None, None, None + def load_config_from_generic_ci_environment(self): + # Inspired by the official client: + # coveralls-ruby in lib/coveralls/configuration.rb + # (set_standard_service_params_for_generic_ci) + + config = { + 'service_name': os.environ.get('CI_NAME'), + 'service_number': os.environ.get('CI_BUILD_NUMBER'), + 'service_build_url': os.environ.get('CI_BUILD_URL'), + 'service_job_id': os.environ.get('CI_JOB_ID'), + 'service_branch': os.environ.get('CI_BRANCH'), + } + + pr_match = NUMBER_REGEX.findall(os.environ.get('CI_PULL_REQUEST', '')) + if pr_match: + config['service_pull_request'] = pr_match[-1] + + non_empty = {key: value for key, value in config.items() if value} + self.config.update(non_empty) + def load_config_from_ci_environment(self): + # As defined at the bottom of + # https://docs.coveralls.io/supported-ci-services + # there are a few env vars that should support any arbitrary CI. + # We load them first and allow more specific vars to overwrite + self.load_config_from_generic_ci_environment() + if os.environ.get('APPVEYOR'): name, job, number, pr = self.load_config_from_appveyor() elif os.environ.get('BUILDKITE'): @@ -166,7 +194,7 @@ def load_config_from_ci_environment(self): else: name, job, number, pr = self.load_config_from_unknown() - self.config['service_name'] = name + self.config.setdefault('service_name', name) if job: self.config['service_job_id'] = job if number: diff --git a/docs/usage/configuration.rst b/docs/usage/configuration.rst index 6441306d..94c12b4e 100644 --- a/docs/usage/configuration.rst +++ b/docs/usage/configuration.rst @@ -156,3 +156,27 @@ you can copy from the coveralls.io website). As per `#245 `_, our users suggest leaving "keep this value secret" unchecked -- this may be secure enough as-is, in that a user making a PR cannot access this variable. + +Other CI systems +---------------- + +As specified in the Coveralls `official docs +` +other CI systems can be supported if the following environment variables are +defined:: + + CI_NAME + # Name of the CI service being used + CI_BUILD_NUMBER + # Number (counter) relative to the current build + CI_BUILD_URL + # URL to a webpage showing the build information/output + CI_BRANCH + # For pull requests this is the name of the branch targeted by the PR, + # otherwise it corresponds to the name of the current branch or tag + CI_JOB_ID (optional) + # Unique identifier of the job in the CI service. + # When missing, CI_BUILD_NUMBER is used + CI_PULL_REQUEST (optional) + # If given, corresponds to the number of the pull request, as specified + # in the supported repository hosting service (GitHub, GitLab, etc) diff --git a/tests/api/configuration_test.py b/tests/api/configuration_test.py index fe0c43fe..c0f7e7da 100644 --- a/tests/api/configuration_test.py +++ b/tests/api/configuration_test.py @@ -198,6 +198,40 @@ def test_semaphore_20_no_config(self): assert cover.config['service_number'] == 'b86b3adf' assert cover.config['service_pull_request'] == '9999' + @mock.patch.dict( + os.environ, + {'CI_NAME': 'generic-ci', + 'CI_PULL_REQUEST': 'pull/1234', + 'CI_JOB_ID': 'bb0e00166', + 'CI_BUILD_NUMBER': '3', + 'CI_BUILD_URL': 'https://generic-ci.local/build/123456789', + 'CI_BRANCH': 'fixup-branch', + 'COVERALLS_REPO_TOKEN': 'xxx'}, + clear=True) + def test_generic_no_config(self): + cover = Coveralls() + assert cover.config['service_name'] == 'generic-ci' + assert cover.config['service_job_id'] == 'bb0e00166' + assert cover.config['service_branch'] == 'fixup-branch' + assert cover.config['service_pull_request'] == '1234' + + @mock.patch.dict( + os.environ, + {'CI_NAME': 'generic-ci', + 'CI_PULL_REQUEST': '', + 'CI_JOB_ID': 'bb0e00166', + 'CI_BUILD_NUMBER': '3', + 'CI_BUILD_URL': 'https://generic-ci.local/build/123456789', + 'CI_BRANCH': 'fixup-branch', + 'COVERALLS_REPO_TOKEN': 'xxx'}, + clear=True) + def test_generic_no_config_no_pr(self): + cover = Coveralls() + assert cover.config['service_name'] == 'generic-ci' + assert cover.config['service_job_id'] == 'bb0e00166' + assert cover.config['service_branch'] == 'fixup-branch' + assert 'service_pull_request' not in cover.config + @mock.patch.dict(os.environ, {'COVERALLS_SERVICE_NAME': 'xxx'}, clear=True) def test_service_name_from_env(self): cover = Coveralls(repo_token='yyy') From 70bf17d84be3a35a953cd5222e31ed500224384f Mon Sep 17 00:00:00 2001 From: Anderson Bravalheri Date: Sat, 5 Jun 2021 00:37:52 +0100 Subject: [PATCH 2/3] docs(api): update CI_* env var descriptions --- coveralls/api.py | 3 +++ docs/usage/configuration.rst | 11 ++++++----- 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/coveralls/api.py b/coveralls/api.py index d5b1b589..f3487167 100644 --- a/coveralls/api.py +++ b/coveralls/api.py @@ -151,6 +151,9 @@ def load_config_from_generic_ci_environment(self): # coveralls-ruby in lib/coveralls/configuration.rb # (set_standard_service_params_for_generic_ci) + # The meaning of each env var is clarified in: + # https://github.com/lemurheavy/coveralls-public/issues/1558 + config = { 'service_name': os.environ.get('CI_NAME'), 'service_number': os.environ.get('CI_BUILD_NUMBER'), diff --git a/docs/usage/configuration.rst b/docs/usage/configuration.rst index 94c12b4e..dd1c82cd 100644 --- a/docs/usage/configuration.rst +++ b/docs/usage/configuration.rst @@ -168,15 +168,16 @@ defined:: CI_NAME # Name of the CI service being used CI_BUILD_NUMBER - # Number (counter) relative to the current build + # The number assigned to the build by your CI service. CI_BUILD_URL - # URL to a webpage showing the build information/output + # URL to a webpage showing the build information/logs CI_BRANCH - # For pull requests this is the name of the branch targeted by the PR, + # For pull requests this is the name of the branch being targeted, # otherwise it corresponds to the name of the current branch or tag CI_JOB_ID (optional) - # Unique identifier of the job in the CI service. - # When missing, CI_BUILD_NUMBER is used + # For parallel builds, the number assigned to each job comprising the build. + # When missing, Coveralls will assign an incrementing integer (1, 2, 3 ...). + # This value should not change between multiple runs of the build. CI_PULL_REQUEST (optional) # If given, corresponds to the number of the pull request, as specified # in the supported repository hosting service (GitHub, GitLab, etc) From e4486d671a2b006488995bfe0224947666bcb040 Mon Sep 17 00:00:00 2001 From: Anderson Bravalheri Date: Tue, 20 Jul 2021 21:01:39 +0100 Subject: [PATCH 3/3] docs(api): specify format for CI_PULL_REQUEST --- docs/usage/configuration.rst | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/docs/usage/configuration.rst b/docs/usage/configuration.rst index dd1c82cd..c023495e 100644 --- a/docs/usage/configuration.rst +++ b/docs/usage/configuration.rst @@ -166,18 +166,25 @@ other CI systems can be supported if the following environment variables are defined:: CI_NAME - # Name of the CI service being used + # Name of the CI service being used. CI_BUILD_NUMBER # The number assigned to the build by your CI service. CI_BUILD_URL - # URL to a webpage showing the build information/logs + # URL to a webpage showing the build information/logs. CI_BRANCH # For pull requests this is the name of the branch being targeted, - # otherwise it corresponds to the name of the current branch or tag + # otherwise it corresponds to the name of the current branch or tag. CI_JOB_ID (optional) # For parallel builds, the number assigned to each job comprising the build. # When missing, Coveralls will assign an incrementing integer (1, 2, 3 ...). # This value should not change between multiple runs of the build. CI_PULL_REQUEST (optional) # If given, corresponds to the number of the pull request, as specified - # in the supported repository hosting service (GitHub, GitLab, etc) + # in the supported repository hosting service (GitHub, GitLab, etc). + # This variable expects a value defined as an integer, e.g.: + # CI_PULL_REQUEST=42 (recommended) + # However, for flexibility, any single line string ending with the same + # integer value can also be used (such as the pull request URL or + # relative path), e.g.: + # CI_PULL_REQUEST='myuser/myrepo/pull/42' + # CI_PULL_REQUEST='https://github.com/myuser/myrepo/pull/42'