From 0f3ec98fcea35ac1b04f8d1d7cc9c536be8f44f3 Mon Sep 17 00:00:00 2001 From: Benjamin Wohlwend Date: Mon, 3 Oct 2022 19:19:48 +0200 Subject: [PATCH 1/7] fix starlette 0.21 tests (#1653) Starlette 0.21 moved to httpx as base for the TestClient --- .ci/.jenkins_framework.yml | 2 +- tests/contrib/asyncio/starlette_tests.py | 10 ++++++++-- tests/requirements/reqs-starlette-newest.txt | 2 +- 3 files changed, 10 insertions(+), 4 deletions(-) diff --git a/.ci/.jenkins_framework.yml b/.ci/.jenkins_framework.yml index fa3200967..cde2eba22 100644 --- a/.ci/.jenkins_framework.yml +++ b/.ci/.jenkins_framework.yml @@ -43,7 +43,7 @@ FRAMEWORK: - aiopg-newest - asyncpg-newest - tornado-newest - # - starlette-newest # disabled for now, see https://github.com/elastic/apm-agent-python/issues/1172 + - starlette-newest - pymemcache-newest - graphene-2 - httpx-newest diff --git a/tests/contrib/asyncio/starlette_tests.py b/tests/contrib/asyncio/starlette_tests.py index 9ce63e11d..552fe6fda 100644 --- a/tests/contrib/asyncio/starlette_tests.py +++ b/tests/contrib/asyncio/starlette_tests.py @@ -250,11 +250,17 @@ def test_capture_headers_body_is_dynamic(app, elasticapm_client): for i, val in enumerate((True, False)): elasticapm_client.config.update(str(i), capture_body="transaction" if val else "none", capture_headers=val) - client.post("/", "somedata", headers={"foo": "bar"}) + try: + client.post("/", content="somedata", headers={"foo": "bar"}) + except TypeError: # starlette < 0.21.0 used requests as base for TestClient, with a different API + client.post("/", "somedata", headers={"foo": "bar"}) elasticapm_client.config.update(str(i) + str(i), capture_body="error" if val else "none", capture_headers=val) with pytest.raises(ValueError): - client.post("/raise-exception", "somedata", headers={"foo": "bar"}) + try: + client.post("/raise-exception", content="somedata", headers={"foo": "bar"}) + except TypeError: + client.post("/raise-exception", "somedata", headers={"foo": "bar"}) assert "headers" in elasticapm_client.events[constants.TRANSACTION][0]["context"]["request"] assert "headers" in elasticapm_client.events[constants.TRANSACTION][0]["context"]["response"] diff --git a/tests/requirements/reqs-starlette-newest.txt b/tests/requirements/reqs-starlette-newest.txt index 831c0209b..1d359f184 100644 --- a/tests/requirements/reqs-starlette-newest.txt +++ b/tests/requirements/reqs-starlette-newest.txt @@ -1,5 +1,5 @@ starlette>=0.15 aiofiles -requests +httpx flask -r reqs-base.txt From 21980d8de2dc7419b1fbf1b8bfd838ae615f32c3 Mon Sep 17 00:00:00 2001 From: Benjamin Wohlwend Date: Mon, 3 Oct 2022 19:21:10 +0200 Subject: [PATCH 2/7] only use content-type and content-encoding headers for POSTing events (#1651) * only use content-type and content-encoding headers for POSTing events closes #1634 * fix test --- elasticapm/base.py | 2 -- elasticapm/transport/http.py | 9 +++++++-- tests/transports/test_urllib3.py | 21 ++++++++++++++++++--- 3 files changed, 25 insertions(+), 7 deletions(-) diff --git a/elasticapm/base.py b/elasticapm/base.py index 6ccc86216..6a57d2f7c 100644 --- a/elasticapm/base.py +++ b/elasticapm/base.py @@ -140,8 +140,6 @@ def __init__(self, config=None, **inline): logging.setLogRecordFactory(new_factory) headers = { - "Content-Type": "application/x-ndjson", - "Content-Encoding": "gzip", "User-Agent": self.get_user_agent(), } diff --git a/elasticapm/transport/http.py b/elasticapm/transport/http.py index 45ef99cb1..aca627efc 100644 --- a/elasticapm/transport/http.py +++ b/elasticapm/transport/http.py @@ -75,6 +75,12 @@ def send(self, data, forced_flush=False): headers = self._headers.copy() if self._headers else {} headers.update(self.auth_headers) + headers.update( + { + b"Content-Type": b"application/x-ndjson", + b"Content-Encoding": b"gzip", + } + ) url = self._url if forced_flush: @@ -146,7 +152,6 @@ def get_config(self, current_version=None, keys=None): data = json_encoder.dumps(keys).encode("utf-8") headers = self._headers.copy() headers[b"Content-Type"] = "application/json" - headers.pop(b"Content-Encoding", None) # remove gzip content-encoding header headers.update(self.auth_headers) max_age = 300 if current_version: @@ -190,7 +195,7 @@ def _process_queue(self): def fetch_server_info(self): headers = self._headers.copy() if self._headers else {} headers.update(self.auth_headers) - headers["accept"] = "text/plain" + headers[b"accept"] = b"text/plain" try: response = self.http.urlopen("GET", self._server_info_url, headers=headers, timeout=self._timeout) body = response.data diff --git a/tests/transports/test_urllib3.py b/tests/transports/test_urllib3.py index c37e21fff..9c76d5453 100644 --- a/tests/transports/test_urllib3.py +++ b/tests/transports/test_urllib3.py @@ -50,12 +50,20 @@ @pytest.mark.flaky(reruns=3) # test is flaky on Windows def test_send(waiting_httpserver, elasticapm_client): + elasticapm_client.server_version = (8, 0) # avoid making server_info request waiting_httpserver.serve_content(code=202, content="", headers={"Location": "http://example.com/foo"}) - transport = Transport(waiting_httpserver.url, client=elasticapm_client) + transport = Transport( + waiting_httpserver.url, client=elasticapm_client, headers=elasticapm_client._transport._headers + ) transport.start_thread() try: url = transport.send("x".encode("latin-1")) assert url == "http://example.com/foo" + request_headers = waiting_httpserver.requests[0].headers + assert request_headers["User-Agent"].startswith("apm-agent-python/") + assert request_headers["Authorization"] == "Bearer test_key" + assert request_headers["Content-Type"] == "application/x-ndjson" + assert request_headers["Content-Encoding"] == "gzip" finally: transport.close() @@ -277,7 +285,7 @@ def test_get_config(waiting_httpserver, elasticapm_client): transport = Transport( url + "/" + constants.EVENTS_API_PATH, client=elasticapm_client, - headers={"Content-Type": "application/x-ndjson", "Content-Encoding": "gzip"}, + headers=elasticapm_client._transport._headers, ) version, data, max_age = transport.get_config("1", {}) assert version == "2" @@ -380,9 +388,16 @@ def test_fetch_server_info(waiting_httpserver, elasticapm_client): content=b'{"version": "8.0.0-alpha1"}', ) url = waiting_httpserver.url - transport = Transport(url + "/" + constants.EVENTS_API_PATH, client=elasticapm_client) + transport = Transport( + url + "/" + constants.EVENTS_API_PATH, client=elasticapm_client, headers=elasticapm_client._transport._headers + ) transport.fetch_server_info() assert elasticapm_client.server_version == (8, 0, 0, "alpha1") + request_headers = waiting_httpserver.requests[0].headers + assert request_headers["User-Agent"].startswith("apm-agent-python/") + assert "Authorization" in request_headers + assert "Content-Type" not in request_headers + assert "Content-Encoding" not in request_headers def test_fetch_server_info_no_json(waiting_httpserver, caplog, elasticapm_client): From 5447d49e69581282f2ec3a7c8866d883699b1c23 Mon Sep 17 00:00:00 2001 From: Benjamin Wohlwend Date: Mon, 3 Oct 2022 19:21:33 +0200 Subject: [PATCH 3/7] fix errors in pymongo tests introduced in #1639 (#1648) * fix errors in pymongo tests introduced in #1639 * fix cursor refresh destination tracking --- elasticapm/instrumentation/packages/pymongo.py | 3 ++- tests/instrumentation/pymongo_tests.py | 4 ++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/elasticapm/instrumentation/packages/pymongo.py b/elasticapm/instrumentation/packages/pymongo.py index d19036b6a..c7ca3faa9 100644 --- a/elasticapm/instrumentation/packages/pymongo.py +++ b/elasticapm/instrumentation/packages/pymongo.py @@ -132,7 +132,8 @@ def call(self, module, method, wrapped, instance, args, kwargs): span_type="db", span_subtype="mongodb", span_action="query", - extra={"destination": {}}, + extra=context, + leaf=True, ) as span: response = wrapped(*args, **kwargs) if span.context and instance.address: diff --git a/tests/instrumentation/pymongo_tests.py b/tests/instrumentation/pymongo_tests.py index 10d68628e..d93b3401d 100644 --- a/tests/instrumentation/pymongo_tests.py +++ b/tests/instrumentation/pymongo_tests.py @@ -99,7 +99,7 @@ def test_collection_count(instrument, elasticapm_client, mongo_database): assert span["context"]["destination"] == { "address": os.environ.get("MONGODB_HOST", "localhost"), "port": int(os.environ.get("MONGODB_PORT", 27017)), - "service": {"name": "", "resource": "mongodb", "type": ""}, + "service": {"name": "", "resource": "mongodb/elasticapm_test", "type": ""}, } @@ -258,7 +258,7 @@ def test_collection_find(instrument, elasticapm_client, mongo_database): assert span["context"]["destination"] == { "address": os.environ.get("MONGODB_HOST", "localhost"), "port": int(os.environ.get("MONGODB_PORT", 27017)), - "service": {"name": "", "resource/elasticapm_test": "mongodb", "type": ""}, + "service": {"name": "", "resource": "mongodb/elasticapm_test", "type": ""}, } From 5b804327b8b21b1abe54d2fa551f750185d22977 Mon Sep 17 00:00:00 2001 From: Benjamin Wohlwend Date: Mon, 3 Oct 2022 19:59:50 +0200 Subject: [PATCH 4/7] Use minimum of 5 seconds for interval between central config calls (#1652) * Use minimum of 5 seconds for interval between central config calls Handling of negative values is not implemented, as this is not allowed per RFC: https://www.rfc-editor.org/rfc/rfc7234#section-5.2.2.8 closes #1645 * add test for negative values Co-authored-by: Colton Myers --- elasticapm/transport/http.py | 24 ++++++++++++++++++----- tests/transports/test_urllib3.py | 33 ++++++++++++++++++++++++++++++++ 2 files changed, 52 insertions(+), 5 deletions(-) diff --git a/elasticapm/transport/http.py b/elasticapm/transport/http.py index aca627efc..b45563c9a 100644 --- a/elasticapm/transport/http.py +++ b/elasticapm/transport/http.py @@ -164,11 +164,9 @@ def get_config(self, current_version=None, keys=None): logger.debug("HTTP error while fetching remote config: %s", str(e)) return current_version, None, max_age body = response.read() - if "Cache-Control" in response.headers: - try: - max_age = int(next(re.finditer(r"max-age=(\d+)", response.headers["Cache-Control"])).groups()[0]) - except StopIteration: - logger.debug("Could not parse Cache-Control header: %s", response.headers["Cache-Control"]) + + max_age = self._get_cache_control_max_age(response.headers) or max_age + if response.status == 304: # config is unchanged, return logger.debug("Configuration unchanged") @@ -187,6 +185,22 @@ def get_config(self, current_version=None, keys=None): logger.warning("Failed decoding APM Server response as JSON: %s", body) return current_version, None, max_age + def _get_cache_control_max_age(self, response_headers): + max_age = None + if "Cache-Control" in response_headers: + try: + cc_max_age = int(next(re.finditer(r"max-age=(\d+)", response_headers["Cache-Control"])).groups()[0]) + if cc_max_age <= 0: + # max_age remains at default value + pass + elif cc_max_age < 5: + max_age = 5 + else: + max_age = cc_max_age + except StopIteration: + logger.debug("Could not parse Cache-Control header: %s", response_headers["Cache-Control"]) + return max_age + def _process_queue(self): if not self.client.server_version: self.fetch_server_info() diff --git a/tests/transports/test_urllib3.py b/tests/transports/test_urllib3.py index 9c76d5453..61def0130 100644 --- a/tests/transports/test_urllib3.py +++ b/tests/transports/test_urllib3.py @@ -337,6 +337,39 @@ def test_get_config_bad_cache_control_header(waiting_httpserver, caplog, elastic assert record.message == "Could not parse Cache-Control header: max-age=fifty" +def test_get_config_cache_control_zero(waiting_httpserver, caplog, elasticapm_client): + waiting_httpserver.serve_content( + code=200, content=b'{"x": "y"}', headers={"Cache-Control": "max-age=0", "Etag": "2"} + ) + url = waiting_httpserver.url + transport = Transport(url + "/" + constants.EVENTS_API_PATH, client=elasticapm_client) + max_age = transport.get_config("1", {})[2] + assert max_age == 300 # if max-age is 0, we use the default + + +def test_get_config_cache_control_negative(waiting_httpserver, caplog, elasticapm_client): + waiting_httpserver.serve_content( + code=200, content=b'{"x": "y"}', headers={"Cache-Control": "max-age=-1", "Etag": "2"} + ) + url = waiting_httpserver.url + transport = Transport(url + "/" + constants.EVENTS_API_PATH, client=elasticapm_client) + with caplog.at_level("DEBUG", "elasticapm.transport.http"): + max_age = transport.get_config("1", {})[2] + assert max_age == 300 # if max-age is negative, we use the default + record = caplog.records[-1] + assert record.message == "Could not parse Cache-Control header: max-age=-1" + + +def test_get_config_cache_control_less_than_minimum(waiting_httpserver, caplog, elasticapm_client): + waiting_httpserver.serve_content( + code=200, content=b'{"x": "y"}', headers={"Cache-Control": "max-age=3", "Etag": "2"} + ) + url = waiting_httpserver.url + transport = Transport(url + "/" + constants.EVENTS_API_PATH, client=elasticapm_client) + max_age = transport.get_config("1", {})[2] + assert max_age == 5 # if max-age is less than 5, we use 5 + + def test_get_config_empty_response(waiting_httpserver, caplog, elasticapm_client): waiting_httpserver.serve_content(code=200, content=b"", headers={"Cache-Control": "max-age=5"}) url = waiting_httpserver.url From c86c5e837adab2c78f7b2857df1d7480883ff0c4 Mon Sep 17 00:00:00 2001 From: Marco <9968523+marcoffee@users.noreply.github.com> Date: Tue, 4 Oct 2022 06:25:45 -0300 Subject: [PATCH 5/7] Use typing.TypeVar on decorators' type hints (#1655) * Fixes issue #1654 Co-authored-by: Colton Myers --- elasticapm/contrib/asyncio/traces.py | 6 ++++-- elasticapm/contrib/serverless/aws.py | 6 ++++-- elasticapm/traces.py | 5 +++-- elasticapm/utils/compat.py | 5 ++++- elasticapm/utils/deprecation.py | 5 ++++- 5 files changed, 19 insertions(+), 8 deletions(-) diff --git a/elasticapm/contrib/asyncio/traces.py b/elasticapm/contrib/asyncio/traces.py index 1ab07aa97..34b18eabd 100644 --- a/elasticapm/contrib/asyncio/traces.py +++ b/elasticapm/contrib/asyncio/traces.py @@ -30,15 +30,17 @@ import functools from types import TracebackType -from typing import Optional, Type +from typing import Optional, Type, TypeVar from elasticapm.conf.constants import LABEL_RE from elasticapm.traces import SpanType, capture_span, execution_context from elasticapm.utils import get_name_from_func +_AnnotatedFunctionT = TypeVar("_AnnotatedFunctionT") + class async_capture_span(capture_span): - def __call__(self, func): + def __call__(self, func: _AnnotatedFunctionT) -> _AnnotatedFunctionT: self.name = self.name or get_name_from_func(func) @functools.wraps(func) diff --git a/elasticapm/contrib/serverless/aws.py b/elasticapm/contrib/serverless/aws.py index 4bd2ae2f1..67d6f7211 100644 --- a/elasticapm/contrib/serverless/aws.py +++ b/elasticapm/contrib/serverless/aws.py @@ -35,7 +35,7 @@ import os import platform import time -from typing import Optional +from typing import Optional, TypeVar from urllib.parse import urlencode import elasticapm @@ -51,6 +51,8 @@ COLD_START = True +_AnnotatedFunctionT = TypeVar("_AnnotatedFunctionT") + class capture_serverless(object): """ @@ -89,7 +91,7 @@ def __init__(self, name: Optional[str] = None, elasticapm_client: Optional[Clien self.client_kwargs = kwargs - def __call__(self, func): + def __call__(self, func: _AnnotatedFunctionT) -> _AnnotatedFunctionT: self.name = self.name or get_name_from_func(func) @functools.wraps(func) diff --git a/elasticapm/traces.py b/elasticapm/traces.py index 1a7ade1d5..b20868df6 100644 --- a/elasticapm/traces.py +++ b/elasticapm/traces.py @@ -39,7 +39,7 @@ from collections import defaultdict from datetime import timedelta from types import TracebackType -from typing import Any, Callable, Dict, List, Optional, Sequence, Tuple, Type, Union +from typing import Any, Dict, List, Optional, Sequence, Tuple, Type, TypeVar, Union import elasticapm from elasticapm.conf import constants @@ -62,6 +62,7 @@ execution_context = init_execution_context() SpanType = Union["Span", "DroppedSpan"] +_AnnotatedFunctionT = TypeVar("_AnnotatedFunctionT") class ChildDuration(object): @@ -1056,7 +1057,7 @@ def __init__( self.sync = sync self.links = links - def __call__(self, func: Callable) -> Callable: + def __call__(self, func: _AnnotatedFunctionT) -> _AnnotatedFunctionT: self.name = self.name or get_name_from_func(func) @functools.wraps(func) diff --git a/elasticapm/utils/compat.py b/elasticapm/utils/compat.py index f29326c6d..b0ee9876a 100644 --- a/elasticapm/utils/compat.py +++ b/elasticapm/utils/compat.py @@ -33,9 +33,12 @@ import atexit import functools import platform +from typing import TypeVar +_AnnotatedFunctionT = TypeVar("_AnnotatedFunctionT") -def noop_decorator(func): + +def noop_decorator(func: _AnnotatedFunctionT) -> _AnnotatedFunctionT: @functools.wraps(func) def wrapped(*args, **kwargs): return func(*args, **kwargs) diff --git a/elasticapm/utils/deprecation.py b/elasticapm/utils/deprecation.py index 3849bd394..5c53e265f 100644 --- a/elasticapm/utils/deprecation.py +++ b/elasticapm/utils/deprecation.py @@ -30,6 +30,9 @@ import functools import warnings +from typing import TypeVar + +_AnnotatedFunctionT = TypeVar("_AnnotatedFunctionT") # https://wiki.python.org/moin/PythonDecoratorLibrary#Smart_deprecation_warnings_.28with_valid_filenames.2C_line_numbers.2C_etc..29 @@ -39,7 +42,7 @@ def deprecated(alternative=None): as deprecated. It will result in a warning being emitted when the function is used.""" - def real_decorator(func): + def real_decorator(func: _AnnotatedFunctionT) -> _AnnotatedFunctionT: @functools.wraps(func) def new_func(*args, **kwargs): msg = "Call to deprecated function {0}.".format(func.__name__) From 74db326b55d400af74972e172bcfe02b75d94de8 Mon Sep 17 00:00:00 2001 From: Benjamin Wohlwend Date: Wed, 5 Oct 2022 18:30:34 +0200 Subject: [PATCH 6/7] use github actions for pre-commit checks (#1658) * use github actions for pre-commit checks * remove pre-commit run from Jenkins * remove linting CI job * use correct repo and newest version of flake8 thanks @basepi for the heads-up --- .ci/jobs/apm-agent-python-linting-mbp.yml | 44 ------------------ .ci/linting.groovy | 55 ----------------------- .github/workflows/pre-commit.yml | 14 ++++++ .pre-commit-config.yaml | 9 ++-- Jenkinsfile | 29 ------------ 5 files changed, 19 insertions(+), 132 deletions(-) delete mode 100644 .ci/jobs/apm-agent-python-linting-mbp.yml delete mode 100644 .ci/linting.groovy create mode 100644 .github/workflows/pre-commit.yml diff --git a/.ci/jobs/apm-agent-python-linting-mbp.yml b/.ci/jobs/apm-agent-python-linting-mbp.yml deleted file mode 100644 index 731512b0e..000000000 --- a/.ci/jobs/apm-agent-python-linting-mbp.yml +++ /dev/null @@ -1,44 +0,0 @@ ---- -- job: - name: apm-agent-python/apm-agent-python-linting-mbp - display-name: APM Agent Python Linting - description: APM Agent Python Linting - view: APM-CI - project-type: multibranch - concurrent: true - node: linux - script-path: .ci/linting.groovy - scm: - - github: - branch-discovery: no-pr - discover-pr-forks-strategy: merge-current - discover-pr-forks-trust: permission - discover-pr-origin: merge-current - discover-tags: false - notification-context: 'apm-ci/linting' - head-filter-regex: '^PR-.*$' - repo: apm-agent-python - repo-owner: elastic - credentials-id: 2a9602aa-ab9f-4e52-baf3-b71ca88469c7-UserAndToken - ssh-checkout: - credentials: f6c7695a-671e-4f4f-a331-acdce44ff9ba - build-strategies: - - change-request: - ignore-target-only-changes: false - clean: - after: true - before: true - prune: true - shallow-clone: true - depth: 3 - do-not-fetch-tags: true - submodule: - disable: false - recursive: true - parent-credentials: true - timeout: 100 - reference-repo: /var/lib/jenkins/.git-references/apm-agent-python.git - timeout: '15' - use-author: true - wipe-workspace: 'True' - prune-dead-branches: true diff --git a/.ci/linting.groovy b/.ci/linting.groovy deleted file mode 100644 index fd4d0aa7e..000000000 --- a/.ci/linting.groovy +++ /dev/null @@ -1,55 +0,0 @@ -#!/usr/bin/env groovy -@Library('apm@current') _ - -pipeline { - agent { label 'linux && immutable' } - environment { - BASE_DIR = "src" - HOME = "${env.WORKSPACE}/${env.BASE_DIR}" - } - options { - buildDiscarder(logRotator(numToKeepStr: '20', artifactNumToKeepStr: '20', daysToKeepStr: '30')) - timestamps() - ansiColor('xterm') - disableResume() - durabilityHint('PERFORMANCE_OPTIMIZED') - rateLimitBuilds(throttle: [count: 60, durationName: 'hour', userBoost: true]) - quietPeriod(10) - } - triggers { - issueCommentTrigger('(?i)(/test).linters.*') - } - stages { - stage('Checkout') { - options { skipDefaultCheckout() } - steps { - runCheckout() - } - } - stage('Sanity checks') { - options { skipDefaultCheckout() } - steps { - dir("${BASE_DIR}") { - runPreCommit() - } - } - } - } -} - -def runCheckout() { - // Use gitCheckout to prepare the context - try { - gitCheckout(basedir: "${BASE_DIR}", githubNotifyFirstTimeContributor: false) - } catch (err) { - // NOOP: avoid failing if non-elasticians, this will avoid issues when PRs comming - // from non elasticians since the validation will not fail - } -} - -def runPreCommit() { - docker.image('python:3.7-stretch').inside(){ - // registry: '' will help to disable the docker login - preCommit(commit: "${GIT_BASE_COMMIT}", junit: true, registry: '') - } -} diff --git a/.github/workflows/pre-commit.yml b/.github/workflows/pre-commit.yml new file mode 100644 index 000000000..c2f7e71fc --- /dev/null +++ b/.github/workflows/pre-commit.yml @@ -0,0 +1,14 @@ +name: pre-commit + +on: + pull_request: + push: + branches: [main] + +jobs: + pre-commit: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + - uses: actions/setup-python@v3 + - uses: pre-commit/action@v3.0.0 diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index dec850ab6..13e03cc57 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -1,15 +1,16 @@ repos: - repo: https://github.com/pycqa/isort - rev: 5.7.0 + rev: 5.10.1 hooks: - id: isort - repo: https://github.com/ambv/black - rev: 22.3.0 + rev: 22.8.0 hooks: - id: black language_version: python3 -- repo: https://gitlab.com/pycqa/flake8 - rev: 3.8.4 + exclude: elasticapm\/utils\/wrapt +- repo: https://github.com/PyCQA/flake8 + rev: 5.0.4 hooks: - id: flake8 exclude: elasticapm\/utils\/wrapt|build|src|tests|dist|conftest.py|setup.py diff --git a/Jenkinsfile b/Jenkinsfile index 6e7e3820a..76088b991 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -67,35 +67,6 @@ pipeline { } } } - stage('Sanity checks') { - when { - beforeAgent true - allOf { - expression { return env.ONLY_DOCS == "false" } - anyOf { - not { changeRequest() } - expression { return params.Run_As_Main_Branch } - } - } - } - environment { - PATH = "${env.WORKSPACE}/.local/bin:${env.WORKSPACE}/bin:${env.PATH}" - } - steps { - withGithubNotify(context: 'Sanity checks', tab: 'tests') { - deleteDir() - unstash 'source' - script { - docker.image('python:3.7-stretch').inside(){ - dir("${BASE_DIR}"){ - // registry: '' will help to disable the docker login - preCommit(commit: "${GIT_BASE_COMMIT}", junit: true, registry: '') - } - } - } - } - } - } /** Execute unit tests. */ From 30783da43064245f74666f481ceaaa47db5529b2 Mon Sep 17 00:00:00 2001 From: Victor Martinez Date: Tue, 11 Oct 2022 09:28:47 +0100 Subject: [PATCH 7/7] bump python versions and use docker slim versions (#1661) --- tests/Dockerfile | 11 ++++++++--- tests/scripts/docker/black.sh | 2 +- tests/scripts/docker/flake8.sh | 2 +- tests/scripts/docker/isort.sh | 2 +- 4 files changed, 11 insertions(+), 6 deletions(-) diff --git a/tests/Dockerfile b/tests/Dockerfile index fdc207d67..785c50229 100644 --- a/tests/Dockerfile +++ b/tests/Dockerfile @@ -1,15 +1,20 @@ ARG PYTHON_IMAGE -FROM ${PYTHON_IMAGE} +FROM ${PYTHON_IMAGE}-slim RUN apt-get -qq update && apt-get -qq -y --no-install-recommends install \ + build-essential \ ca-certificates \ curl \ + gnupg2 \ + libmariadb-dev \ + libpq-dev \ + make \ netcat \ odbc-postgresql \ unixodbc-dev \ freetds-dev \ - libmemcached-dev &&\ - rm -rf /var/lib/apt/lists/* + libmemcached-dev \ + && rm -rf /var/lib/apt/lists/* # connection to ha.pool.sks-keyservers.net fails sometimes, so let's retry with couple different servers RUN for server in $(shuf -e ha.pool.sks-keyservers.net \ diff --git a/tests/scripts/docker/black.sh b/tests/scripts/docker/black.sh index 71bceeebf..3eba8e233 100755 --- a/tests/scripts/docker/black.sh +++ b/tests/scripts/docker/black.sh @@ -7,7 +7,7 @@ docker_pip_cache="/tmp/cache/pip" cd tests -docker build --build-arg PYTHON_IMAGE=python:3.6 -t python-linters . +docker build --build-arg PYTHON_IMAGE=python:3.8 -t python-linters . docker run \ -e LOCAL_USER_ID=$UID \ -e PIP_CACHE=${docker_pip_cache} \ diff --git a/tests/scripts/docker/flake8.sh b/tests/scripts/docker/flake8.sh index 05382df33..a60ee0491 100755 --- a/tests/scripts/docker/flake8.sh +++ b/tests/scripts/docker/flake8.sh @@ -7,7 +7,7 @@ docker_pip_cache="/tmp/cache/pip" cd tests -docker build --build-arg PYTHON_IMAGE=python:3.6 -t lint_flake8 . +docker build --build-arg PYTHON_IMAGE=python:3.8 -t lint_flake8 . docker run \ -e LOCAL_USER_ID=$UID \ -e PIP_CACHE=${docker_pip_cache} \ diff --git a/tests/scripts/docker/isort.sh b/tests/scripts/docker/isort.sh index b7eec13dc..84e62832e 100755 --- a/tests/scripts/docker/isort.sh +++ b/tests/scripts/docker/isort.sh @@ -7,7 +7,7 @@ docker_pip_cache="/tmp/cache/pip" cd tests -docker build --build-arg PYTHON_IMAGE=python:3.6 -t python-linters . +docker build --build-arg PYTHON_IMAGE=python:3.8 -t python-linters . docker run \ -e LOCAL_USER_ID=$UID \ -e PIP_CACHE=${docker_pip_cache} \