diff --git a/.github/actions/build-distribution/action.yml b/.github/actions/build-distribution/action.yml new file mode 100644 index 000000000..bc0d55c29 --- /dev/null +++ b/.github/actions/build-distribution/action.yml @@ -0,0 +1,21 @@ +--- + +name: common build distribution tasks +description: Run the build distribution + +runs: + using: "composite" + steps: + - uses: actions/setup-python@v5 + with: + python-version: "3.10" + + - name: Build lambda layer zip + run: ./dev-utils/make-distribution.sh + shell: bash + + - uses: actions/upload-artifact@v4 + with: + name: build-distribution + path: ./build/ + if-no-files-found: error diff --git a/.github/actions/packages/action.yml b/.github/actions/packages/action.yml new file mode 100644 index 000000000..871f49c32 --- /dev/null +++ b/.github/actions/packages/action.yml @@ -0,0 +1,27 @@ +--- + +name: common package tasks +description: Run the packages + +runs: + using: "composite" + steps: + - uses: actions/setup-python@v5 + with: + python-version: "3.10" + - name: Override the version if there is no tag release. + run: | + if [[ "${GITHUB_REF}" != refs/tags/* ]]; then + echo "ELASTIC_CI_POST_VERSION=${{ github.run_id }}" >> "${GITHUB_ENV}" + fi + shell: bash + - name: Build packages + run: ./dev-utils/make-packages.sh + shell: bash + - name: Upload Packages + uses: actions/upload-artifact@v4 + with: + name: packages + path: | + dist/*.whl + dist/*tar.gz diff --git a/.github/dependabot.yml b/.github/dependabot.yml index eb1cff95b..afb941790 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -29,3 +29,30 @@ updates: github-actions: patterns: - "*" + + # GitHub composite actions + - package-ecosystem: "github-actions" + directory: "/.github/actions/packages" + reviewers: + - "elastic/observablt-ci" + schedule: + interval: "weekly" + day: "sunday" + time: "22:00" + groups: + github-actions: + patterns: + - "*" + + - package-ecosystem: "github-actions" + directory: "/.github/actions/build-distribution" + reviewers: + - "elastic/observablt-ci" + schedule: + interval: "weekly" + day: "sunday" + time: "22:00" + groups: + github-actions: + patterns: + - "*" diff --git a/.github/workflows/build-distribution.yml b/.github/workflows/build-distribution.yml deleted file mode 100644 index ba8497e0c..000000000 --- a/.github/workflows/build-distribution.yml +++ /dev/null @@ -1,23 +0,0 @@ -name: build-distribution - -on: - workflow_call: ~ - -permissions: - contents: read - -jobs: - build: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v4 - - uses: actions/setup-python@v5 - with: - python-version: "3.10" - - name: Build lambda layer zip - run: ./dev-utils/make-distribution.sh - - uses: actions/upload-artifact@v3 - with: - name: build-distribution - path: ./build/ - if-no-files-found: error diff --git a/.github/workflows/opentelemetry.yml b/.github/workflows/opentelemetry.yml deleted file mode 100644 index 84a6209ff..000000000 --- a/.github/workflows/opentelemetry.yml +++ /dev/null @@ -1,22 +0,0 @@ ---- -# Look up results at https://ela.st/oblt-ci-cd-stats. -# There will be one service per GitHub repository, including the org name, and one Transaction per Workflow. -name: OpenTelemetry Export Trace - -on: - workflow_run: - workflows: [ "*" ] - types: [completed] - -permissions: - contents: read - -jobs: - otel-export-trace: - runs-on: ubuntu-latest - steps: - - uses: elastic/apm-pipeline-library/.github/actions/opentelemetry@current - with: - vaultUrl: ${{ secrets.VAULT_ADDR }} - vaultRoleId: ${{ secrets.VAULT_ROLE_ID }} - vaultSecretId: ${{ secrets.VAULT_SECRET_ID }} diff --git a/.github/workflows/packages.yml b/.github/workflows/packages.yml index 4f04d78a4..496107508 100644 --- a/.github/workflows/packages.yml +++ b/.github/workflows/packages.yml @@ -21,24 +21,4 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - - uses: actions/setup-python@v5 - with: - python-version: "3.10" - - name: Override the version if there is no tag release. - run: | - if [[ "${GITHUB_REF}" != refs/tags/* ]]; then - echo "ELASTIC_CI_POST_VERSION=${{ github.run_id }}" >> "${GITHUB_ENV}" - fi - - name: Install wheel - run: pip install --user wheel - - name: Building universal wheel - run: python setup.py bdist_wheel - - name: Building source distribution - run: python setup.py sdist - - name: Upload Packages - uses: actions/upload-artifact@v4 - with: - name: packages - path: | - dist/*.whl - dist/*tar.gz + - uses: ./.github/actions/packages diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 5f91014b4..cc0de40a2 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -18,7 +18,18 @@ jobs: enabled: ${{ startsWith(github.ref, 'refs/tags') }} packages: - uses: ./.github/workflows/packages.yml + permissions: + attestations: write + id-token: write + contents: write + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - uses: ./.github/actions/packages + - name: generate build provenance + uses: actions/attest-build-provenance@951c0c5f8e375ad4efad33405ab77f7ded2358e4 # v1.1.1 + with: + subject-path: "${{ github.workspace }}/dist/*" publish-pypi: needs: @@ -46,7 +57,18 @@ jobs: repository-url: https://test.pypi.org/legacy/ build-distribution: - uses: ./.github/workflows/build-distribution.yml + permissions: + attestations: write + id-token: write + contents: write + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - uses: ./.github/actions/build-distribution + - name: generate build provenance + uses: actions/attest-build-provenance@951c0c5f8e375ad4efad33405ab77f7ded2358e4 # v1.1.1 + with: + subject-path: "${{ github.workspace }}/build/dist/elastic-apm-python-lambda-layer.zip" publish-lambda-layers: needs: @@ -63,7 +85,7 @@ jobs: secrets: | secret/observability-team/ci/service-account/apm-agent-python access_key_id | AWS_ACCESS_KEY_ID ; secret/observability-team/ci/service-account/apm-agent-python secret_access_key | AWS_SECRET_ACCESS_KEY - - uses: actions/download-artifact@v3 + - uses: actions/download-artifact@v4 with: name: build-distribution path: ./build @@ -86,6 +108,14 @@ jobs: needs: - build-distribution runs-on: ubuntu-latest + permissions: + attestations: write + id-token: write + contents: write + strategy: + fail-fast: false + matrix: + dockerfile: [ 'Dockerfile', 'Dockerfile.wolfi' ] env: DOCKER_IMAGE_NAME: docker.elastic.co/observability/apm-agent-python steps: @@ -97,35 +127,41 @@ jobs: url: ${{ secrets.VAULT_ADDR }} roleId: ${{ secrets.VAULT_ROLE_ID }} secretId: ${{ secrets.VAULT_SECRET_ID }} - - uses: actions/download-artifact@v3 + + - uses: actions/download-artifact@v4 with: name: build-distribution path: ./build - - id: setup-docker - name: Set up docker variables - run: |- - if [ "${{ startsWith(github.ref, 'refs/tags') }}" == "false" ] ; then - # for testing purposes - echo "tag=test" >> "${GITHUB_OUTPUT}" - else - # version without v prefix (e.g. 1.2.3) - echo "tag=${GITHUB_REF_NAME/v/}" >> "${GITHUB_OUTPUT}" - fi - - name: Docker build - run: >- - docker build - -t ${{ env.DOCKER_IMAGE_NAME }}:${{ steps.setup-docker.outputs.tag }} - --build-arg AGENT_DIR=./build/dist/package/python - . - - name: Docker retag - run: >- - docker tag - ${{ env.DOCKER_IMAGE_NAME }}:${{ steps.setup-docker.outputs.tag }} - ${{ env.DOCKER_IMAGE_NAME }}:latest - - name: Docker push - if: startsWith(github.ref, 'refs/tags') - run: |- - docker push --all-tags ${{ env.DOCKER_IMAGE_NAME }} + + - name: Extract metadata (tags, labels) + id: docker-meta + uses: docker/metadata-action@8e5442c4ef9f78752691e2d8f8d19755c6f78e81 # v5.5.1 + with: + images: ${{ env.DOCKER_IMAGE_NAME }} + tags: | + type=raw,value=latest,prefix=test-,enable={{is_default_branch}} + type=semver,pattern={{version}} + flavor: | + suffix=${{ contains(matrix.dockerfile, 'wolfi') && '-wolfi' || '' }} + + - name: Build and push image + id: push + uses: docker/build-push-action@2cdde995de11925a030ce8070c3d77a52ffcf1c0 # v5.3.0 + with: + context: . + push: true + file: ${{ matrix.dockerfile }} + tags: ${{ steps.docker-meta.outputs.tags }} + labels: ${{ steps.docker-meta.outputs.labels }} + build-args: | + AGENT_DIR=./build/dist/package/python + + - name: generate build provenance (containers) + uses: actions/attest-build-provenance@951c0c5f8e375ad4efad33405ab77f7ded2358e4 # v1.1.1 + with: + subject-name: "${{ env.DOCKER_IMAGE_NAME }}" + subject-digest: ${{ steps.push.outputs.digest }} + push-to-registry: true github-draft: permissions: diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 381c317b0..967378697 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -35,7 +35,11 @@ permissions: jobs: build-distribution: - uses: ./.github/workflows/build-distribution.yml + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - uses: ./.github/actions/build-distribution + create-matrix: runs-on: ubuntu-latest diff --git a/CHANGELOG.asciidoc b/CHANGELOG.asciidoc index 03f4e048f..cf6a99a7c 100644 --- a/CHANGELOG.asciidoc +++ b/CHANGELOG.asciidoc @@ -32,6 +32,14 @@ endif::[] [[release-notes-6.x]] === Python Agent version 6.x +[[release-notes-6.22.1]] +==== 6.22.1 - 2024-05-17 + +[float] +===== Features + +* Relax wrapt dependency to only exclude 1.15.0 {pull}2005[#2005] + [[release-notes-6.22.0]] ==== 6.22.0 - 2024-04-03 diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 21180e9f1..c58fbb7c6 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -192,7 +192,8 @@ If you have commit access, the process is as follows: 1. Tag the commit with `git tag -s vX.Y.Z`, for example `git tag -s v1.2.3`. Copy the changelog for the release to the tag message, removing any leading `#`. 1. Push tag upstream with `git push upstream --tags` (and optionally to your own fork as well) -1. Open a PR from `main` to the major branch, e.g. `1.x` to update it. In order to keep history you may want to +1. Open a PR from `main` to the major branch, e.g. `1.x` to update it. In order to keep history create a + branch from the `main` branch, rebase it on top of the major branch to drop duplicated commits and then merge with the `rebase` strategy. It is crucial that `main` and the major branch have the same content. 1. After tests pass, Github Actions will automatically build and push the new release to PyPI. 1. Edit and publish the [draft Github release](https://github.com/elastic/apm-agent-python/releases) diff --git a/Dockerfile.wolfi b/Dockerfile.wolfi new file mode 100644 index 000000000..1ed923ce5 --- /dev/null +++ b/Dockerfile.wolfi @@ -0,0 +1,3 @@ +FROM docker.elastic.co/wolfi/chainguard-base@sha256:9f940409f96296ef56140bcc4665c204dd499af4c32c96cc00e792558097c3f1 +ARG AGENT_DIR +COPY ${AGENT_DIR} /opt/python \ No newline at end of file diff --git a/dev-utils/make-packages.sh b/dev-utils/make-packages.sh new file mode 100755 index 000000000..91b2a7bd1 --- /dev/null +++ b/dev-utils/make-packages.sh @@ -0,0 +1,16 @@ +#!/bin/bash +# +# Make a Python APM agent distribution +# + +echo "::group::Install wheel" +pip install --user wheel +echo "::endgroup::" + +echo "::group::Building universal wheel" +python setup.py bdist_wheel +echo "::endgroup::" + +echo "::group::Building source distribution" +python setup.py sdist +echo "::endgroup::" diff --git a/elasticapm/base.py b/elasticapm/base.py index ff2fd6e25..2c82f0d88 100644 --- a/elasticapm/base.py +++ b/elasticapm/base.py @@ -374,7 +374,7 @@ def get_service_info(self): def get_process_info(self): result = { "pid": os.getpid(), - "ppid": os.getppid() if hasattr(os, "getppid") else None, + "ppid": os.getppid(), "title": None, # Note: if we implement this, the value needs to be wrapped with keyword_field } if self.config.include_process_args: diff --git a/elasticapm/contrib/serverless/azure.py b/elasticapm/contrib/serverless/azure.py index ed2444d60..c5df4882a 100644 --- a/elasticapm/contrib/serverless/azure.py +++ b/elasticapm/contrib/serverless/azure.py @@ -43,8 +43,6 @@ from elasticapm.utils.disttracing import TraceParent from elasticapm.utils.logging import get_logger -SERVERLESS_HTTP_REQUEST = ("api", "elb") - logger = get_logger("elasticapm.serverless") _AnnotatedFunctionT = TypeVar("_AnnotatedFunctionT") diff --git a/elasticapm/version.py b/elasticapm/version.py index c8799817e..e778fc5b2 100644 --- a/elasticapm/version.py +++ b/elasticapm/version.py @@ -28,5 +28,5 @@ # OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -__version__ = (6, 22, 0) +__version__ = (6, 22, 1) VERSION = ".".join(map(str, __version__)) diff --git a/setup.cfg b/setup.cfg index ce33450a6..2dca4283e 100644 --- a/setup.cfg +++ b/setup.cfg @@ -39,7 +39,7 @@ zip_safe = false install_requires = urllib3!=2.0.0,<3.0.0 certifi - wrapt>=1.14.1,<1.15.0 # https://github.com/elastic/apm-agent-python/issues/1894 + wrapt>=1.14.1,!=1.15.0 # https://github.com/elastic/apm-agent-python/issues/1894 ecs_logging test_suite=tests diff --git a/tests/docker-compose.yml b/tests/docker-compose.yml index 48b43cda2..62a05c83f 100644 --- a/tests/docker-compose.yml +++ b/tests/docker-compose.yml @@ -130,7 +130,7 @@ services: - pymssqldata:/var/opt/mssql mysql: - image: mysql + image: mysql:8.0 command: --default-authentication-plugin=mysql_native_password --log_error_verbosity=3 environment: - MYSQL_DATABASE=eapm_tests diff --git a/tests/requirements/reqs-asgi-2.txt b/tests/requirements/reqs-asgi-2.txt index eecc89d9a..97ff3022d 100644 --- a/tests/requirements/reqs-asgi-2.txt +++ b/tests/requirements/reqs-asgi-2.txt @@ -1,6 +1,6 @@ quart==0.6.13 MarkupSafe<2.1 -jinja2==3.0.3 +jinja2==3.1.4 async-asgi-testclient asgiref -r reqs-base.txt diff --git a/tests/requirements/reqs-base.txt b/tests/requirements/reqs-base.txt index 747e42631..4f79a5929 100644 --- a/tests/requirements/reqs-base.txt +++ b/tests/requirements/reqs-base.txt @@ -8,7 +8,7 @@ coverage[toml]==6.3 ; python_version == '3.7' coverage==7.3.1 ; python_version > '3.7' pytest-cov==4.0.0 ; python_version < '3.8' pytest-cov==4.1.0 ; python_version > '3.7' -jinja2==3.1.2 ; python_version == '3.7' +jinja2==3.1.4 ; python_version == '3.7' pytest-localserver==0.5.0 pytest-mock==3.6.1 ; python_version == '3.6' pytest-mock==3.10.0 ; python_version > '3.6' @@ -29,7 +29,7 @@ mock pytz ecs_logging structlog -wrapt>=1.14.1,<1.15.0 +wrapt>=1.14.1,!=1.15.0 simplejson pytest-asyncio==0.21.0 ; python_version >= '3.7' diff --git a/tests/requirements/reqs-flask-1.1.txt b/tests/requirements/reqs-flask-1.1.txt index 107d375d5..cd32a4696 100644 --- a/tests/requirements/reqs-flask-1.1.txt +++ b/tests/requirements/reqs-flask-1.1.txt @@ -1,4 +1,4 @@ -jinja2<3.1.0 +jinja2<3.2.0 Werkzeug<2.1.0 Flask>=1.1,<1.2 MarkupSafe<2.1 diff --git a/tests/upstream/json-specs/metadata.json b/tests/upstream/json-specs/metadata.json index 7103bbeb5..1122ed68c 100644 --- a/tests/upstream/json-specs/metadata.json +++ b/tests/upstream/json-specs/metadata.json @@ -441,6 +441,14 @@ ], "maxLength": 1024 }, + "host_id": { + "description": "The OpenTelemetry semantic conventions compliant \"host.id\" attribute, if available.", + "type": [ + "null", + "string" + ], + "maxLength": 1024 + }, "hostname": { "description": "Deprecated: Use ConfiguredHostname and DetectedHostname instead. DeprecatedHostname is the host name of the system the service is running on. It does not distinguish between configured and detected hostname and therefore is deprecated and only used if no other hostname information is available.", "type": [