Skip to content

Commit aadfbc2

Browse files
committed
Merge branch 'main' into remove_CAT
2 parents ed8f4f8 + 59633ac commit aadfbc2

File tree

93 files changed

+3554
-968
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

93 files changed

+3554
-968
lines changed

.devcontainer/Dockerfile

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,13 +20,13 @@ FROM ghcr.io/newrelic/newrelic-python-agent-ci:${IMAGE_TAG}
2020
USER root
2121
ARG UID=1001
2222
ARG GID=${UID}
23-
ENV HOME=/home/vscode
23+
ENV HOME=/root
2424
RUN mkdir -p ${HOME} && \
2525
groupadd --gid ${GID} vscode && \
2626
useradd --uid ${UID} --gid ${GID} --home ${HOME} vscode && \
27-
chown -R ${UID}:${GID} /home/vscode
27+
chown -R ${UID}:${GID} ${HOME}/
2828

29-
# Allow uv to download Python versions manually
29+
# Restrict uv to only download Python versions manually
3030
ENV UV_PYTHON_DOWNLOADS=manual
3131

3232
# Set user

.github/actionlint.yml

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
# Copyright 2010 New Relic, Inc.
2+
#
3+
# Licensed under the Apache License, Version 2.0 (the "License");
4+
# you may not use this file except in compliance with the License.
5+
# You may obtain a copy of the License at
6+
#
7+
# http://www.apache.org/licenses/LICENSE-2.0
8+
#
9+
# Unless required by applicable law or agreed to in writing, software
10+
# distributed under the License is distributed on an "AS IS" BASIS,
11+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
# See the License for the specific language governing permissions and
13+
# limitations under the License.
14+
15+
paths:
16+
.github/workflows/**/*.{yml,yaml}:
17+
ignore:
18+
# This runner exists, but is in beta and not known to actionlint.
19+
- 'label "windows-11-arm" is unknown\. .+'
20+
- 'property "check_run_id" is not defined.+'

.github/containers/Dockerfile

Lines changed: 31 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -23,15 +23,33 @@ RUN export DEBIAN_FRONTEND=noninteractive && \
2323
bash \
2424
build-essential \
2525
curl \
26+
default-libmysqlclient-dev \
27+
expat \
2628
fish \
2729
fontconfig \
30+
freetds-common \
31+
freetds-dev \
2832
gcc \
2933
git \
34+
libbz2-dev \
35+
libcurl4-openssl-dev \
36+
libffi-dev \
37+
libgmp-dev \
38+
libkrb5-dev \
39+
liblzma-dev \
40+
libmpfr-dev \
41+
libncurses-dev \
42+
libpq-dev \
43+
libreadline-dev \
44+
libsqlite3-dev \
45+
libssl-dev \
3046
locales \
3147
make \
3248
odbc-postgresql \
3349
openssl \
3450
pkg-config \
51+
python3-dev \
52+
python3-pip \
3553
rustc \
3654
sudo \
3755
tzdata \
@@ -40,6 +58,8 @@ RUN export DEBIAN_FRONTEND=noninteractive && \
4058
vim \
4159
wget \
4260
zip \
61+
zlib1g \
62+
zlib1g-dev \
4363
zsh && \
4464
rm -rf /var/lib/apt/lists/*
4565

@@ -87,18 +107,20 @@ WORKDIR "${HOME}"
87107
RUN curl -LsSf https://astral.sh/uv/install.sh | sh
88108
ENV PATH="${HOME}/.local/bin:${PATH}"
89109
ENV UV_PYTHON_PREFERENCE="only-managed"
110+
ENV UV_LINK_MODE="copy"
90111

91-
# Install Python
92-
ARG PYTHON_VERSIONS="3.13 3.12 3.11 3.10 3.9 3.8 pypy3.10"
93-
RUN bash -c "uv python install ${PYTHON_VERSIONS}" && \
94-
uv python pin --global 3.13
112+
# Install PyPy versions and rename shims
113+
RUN uv python install -f pp3.11 pp3.10
114+
RUN mv "${HOME}/.local/bin/python3.11" "${HOME}/.local/bin/pypy3.11" && \
115+
mv "${HOME}/.local/bin/python3.10" "${HOME}/.local/bin/pypy3.10"
95116

96-
# Add shims for python and pip
97-
COPY --chmod=775 <<EOF "${HOME}/.local/bin/python"
98-
#!/bin/bash
99-
exec uv run --no-project python \$@
100-
EOF
117+
# Install CPython versions
118+
RUN uv python install -f cp3.14 cp3.13 cp3.12 cp3.11 cp3.10 cp3.9 cp3.8
119+
120+
# Set default Python version to CPython 3.13
121+
RUN uv python install -f --default cp3.13
101122

123+
# Add shim for pip to use 'uv pip'
102124
COPY --chmod=775 <<EOF "${HOME}/.local/bin/pip"
103125
#!/bin/bash
104126
exec uv pip \$@

.github/scripts/get-envs.py

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
#!/usr/bin/env python
2+
# Copyright 2010 New Relic, Inc.
3+
#
4+
# Licensed under the Apache License, Version 2.0 (the "License");
5+
# you may not use this file except in compliance with the License.
6+
# You may obtain a copy of the License at
7+
#
8+
# http://www.apache.org/licenses/LICENSE-2.0
9+
#
10+
# Unless required by applicable law or agreed to in writing, software
11+
# distributed under the License is distributed on an "AS IS" BASIS,
12+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
# See the License for the specific language governing permissions and
14+
# limitations under the License.
15+
16+
import fileinput
17+
import os
18+
from pathlib import Path
19+
from textwrap import dedent
20+
21+
GROUP_NUMBER = int(os.environ["GROUP_NUMBER"]) - 1
22+
TOTAL_GROUPS = int(os.environ["TOTAL_GROUPS"])
23+
GITHUB_JOB = os.environ["GITHUB_JOB"]
24+
GITHUB_OUTPUT = os.environ.get("GITHUB_OUTPUT", None)
25+
26+
27+
def main(stdin):
28+
environments = [env.rstrip() for env in stdin]
29+
filtered_envs = [env for env in environments if env.startswith(GITHUB_JOB + "-")]
30+
grouped_envs = filtered_envs[GROUP_NUMBER::TOTAL_GROUPS]
31+
32+
# If not environments are found, raise an error with helpful information.
33+
if not grouped_envs:
34+
error_msg = dedent(f"""
35+
No matching environments found.
36+
GITHUB_JOB = {GITHUB_JOB}
37+
GROUP_NUMBER = {GROUP_NUMBER + 1}
38+
TOTAL_GROUPS = {TOTAL_GROUPS}
39+
40+
environments = {environments}
41+
filtered_envs = {filtered_envs}
42+
grouped_envs = {grouped_envs}
43+
""")
44+
raise RuntimeError(error_msg(environments))
45+
46+
# Output results to GITHUB_OUTPUT for use in later steps.
47+
if GITHUB_OUTPUT:
48+
with Path(GITHUB_OUTPUT).open("a") as output_fh:
49+
print(f"envs={','.join(grouped_envs)}", file=output_fh)
50+
51+
# Output human readable results to stdout for visibility in logs.
52+
print("\n".join(grouped_envs))
53+
54+
55+
if __name__ == "__main__":
56+
with fileinput.input() as stdin:
57+
main(stdin)

.github/scripts/tox-summary.py

Lines changed: 114 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,114 @@
1+
#!/usr/bin/env python
2+
# Copyright 2010 New Relic, Inc.
3+
#
4+
# Licensed under the Apache License, Version 2.0 (the "License");
5+
# you may not use this file except in compliance with the License.
6+
# You may obtain a copy of the License at
7+
#
8+
# http://www.apache.org/licenses/LICENSE-2.0
9+
#
10+
# Unless required by applicable law or agreed to in writing, software
11+
# distributed under the License is distributed on an "AS IS" BASIS,
12+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
# See the License for the specific language governing permissions and
14+
# limitations under the License.
15+
16+
import json
17+
import os
18+
import re
19+
from pathlib import Path
20+
from textwrap import dedent
21+
22+
REPO_DIR = Path(__file__).parent.parent.parent
23+
TOX_DIR = REPO_DIR / ".tox"
24+
GITHUB_SUMMARY = Path(os.environ.get("GITHUB_STEP_SUMMARY", TOX_DIR / "summary.md"))
25+
RESULTS_FILE_RE = re.compile(
26+
r"(?P<job_name>[a-zA-Z0-9_-]+)-(?P<job_num>\d+)-(?P<run_id>[a-zA-Z0-9]+)-(?P<job_id>[a-zA-Z0-9_-]+)-results.json"
27+
)
28+
29+
GITHUB_SERVER_URL = os.environ.get("GITHUB_SERVER_URL", "https://github.com")
30+
GITHUB_REPOSITORY = os.environ.get("GITHUB_REPOSITORY", "newrelic/newrelic-python-agent")
31+
32+
TABLE_HEADER = """
33+
# Tox Results Summary
34+
35+
| Environment | Status | Duration (s) | Setup Duration (s) | Test Duration (s) | Runner |
36+
|-------------|--------|--------------|--------------------|-------------------|--------|
37+
"""
38+
TABLE_HEADER = dedent(TABLE_HEADER).strip()
39+
40+
41+
def main():
42+
results = {}
43+
# Search both repo and .tox dirs
44+
filepaths = list(REPO_DIR.glob("*-results.json")) + list(TOX_DIR.glob("*-results.json"))
45+
for filepath in filepaths:
46+
with filepath.open() as f:
47+
# Load the JSON data
48+
data = json.load(f)
49+
envs = data.get("testenvs", ())
50+
51+
# Extract GitHub info from filename
52+
match = RESULTS_FILE_RE.match(filepath.name)
53+
if match:
54+
runner_link = f"{GITHUB_SERVER_URL}/{GITHUB_REPOSITORY}/actions/runs/{match.group('run_id')}/job/{match.group('job_id')}"
55+
runner = f"[{match.group('job_name')} ({match.group('job_num')})]({runner_link})"
56+
else:
57+
runner = "N/A"
58+
59+
# Aggregate any non-empty results
60+
sub_results = {k: v for k, v in envs.items() if v and k != ".pkg"}
61+
for result in sub_results.values():
62+
result["runner"] = runner
63+
results.update(sub_results)
64+
65+
if not results:
66+
raise RuntimeError("No tox results found.")
67+
68+
with GITHUB_SUMMARY.open("w") as output_fp:
69+
summary = summarize_results(results)
70+
# Print table header
71+
print(TABLE_HEADER, file=output_fp)
72+
73+
for result in summary:
74+
line = "| {env_name} | {status} | {duration} | {setup_duration} | {test_duration} | {runner} |".format(
75+
**result
76+
)
77+
print(line, file=output_fp)
78+
79+
80+
def summarize_results(results):
81+
summary = []
82+
for env, result in results.items():
83+
duration = result["result"].get("duration", 0)
84+
duration = f"{duration:.2f}" if duration >= 0 else "N/A"
85+
status = "OK ✅" if result["result"]["success"] else "FAIL ❌"
86+
runner = result.get("runner", "N/A")
87+
88+
# Sum up setup and test durations from individual commands
89+
setup_duration = 0
90+
for cmd in result.get("setup", ()):
91+
setup_duration += cmd.get("elapsed", 0)
92+
setup_duration = f"{setup_duration:.2f}" if setup_duration >= 0 else "N/A"
93+
94+
test_duration = 0
95+
for cmd in result.get("test", ()):
96+
test_duration += cmd.get("elapsed", 0)
97+
test_duration = f"{test_duration:.2f}" if test_duration >= 0 else "N/A"
98+
99+
summary.append(
100+
{
101+
"env_name": env,
102+
"status": status,
103+
"duration": duration,
104+
"setup_duration": setup_duration,
105+
"test_duration": test_duration,
106+
"runner": runner,
107+
}
108+
)
109+
110+
return sorted(summary, key=lambda result: (1 if "OK" in result["status"] else 0, result["env_name"]))
111+
112+
113+
if __name__ == "__main__":
114+
main()

.github/workflows/benchmarks.yml

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
# Copyright 2010 New Relic, Inc.
2+
#
3+
# Licensed under the Apache License, Version 2.0 (the "License");
4+
# you may not use this file except in compliance with the License.
5+
# You may obtain a copy of the License at
6+
#
7+
# http://www.apache.org/licenses/LICENSE-2.0
8+
#
9+
# Unless required by applicable law or agreed to in writing, software
10+
# distributed under the License is distributed on an "AS IS" BASIS,
11+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
# See the License for the specific language governing permissions and
13+
# limitations under the License.
14+
---
15+
name: Benchmarks
16+
17+
on:
18+
pull_request:
19+
20+
permissions:
21+
contents: read
22+
23+
concurrency:
24+
group: ${{ github.ref || github.run_id }}-${{ github.workflow }}
25+
cancel-in-progress: true
26+
27+
jobs:
28+
# Benchmarks
29+
benchmark:
30+
runs-on: ubuntu-24.04
31+
timeout-minutes: 30
32+
strategy:
33+
matrix:
34+
python: ["3.8", "3.9", "3.10", "3.11", "3.12", "3.13", "3.14"]
35+
36+
env:
37+
ASV_FACTOR: "1.1"
38+
BASE_SHA: ${{ github.event.pull_request.base.sha }}
39+
40+
steps:
41+
- uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # 5.0.0
42+
with:
43+
fetch-depth: 0
44+
45+
- uses: actions/setup-python@e797f83bcb11b83ae66e0230d6156d7c80228e7c # 6.0.0
46+
with:
47+
python-version: "${{ matrix.python }}"
48+
49+
- name: Fetch git tags
50+
run: |
51+
git config --global --add safe.directory "$GITHUB_WORKSPACE"
52+
git fetch --tags origin
53+
54+
- name: Install Dependencies
55+
run: |
56+
pip install --upgrade pip
57+
pip install asv virtualenv
58+
59+
- name: Configure Machine Information
60+
run: |
61+
asv machine --yes
62+
63+
- name: Run Benchmark
64+
run: |
65+
asv continuous \
66+
--show-stderr \
67+
--split \
68+
--factor "${ASV_FACTOR}" \
69+
--python=${{ matrix.python }} \
70+
"${BASE_SHA}" "${GITHUB_SHA}"

.github/workflows/build-ci-image.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,7 @@ jobs:
7575
7676
- name: Login to GitHub Container Registry
7777
if: github.event_name != 'pull_request'
78-
uses: docker/login-action@184bdaa0721073962dff0199f1fb9940f07167d1 # 3.5.0
78+
uses: docker/login-action@5e57cd118135c172c3672efd75eb46360885c0ef # 3.6.0
7979
with:
8080
registry: ghcr.io
8181
username: ${{ github.repository_owner }}
@@ -122,7 +122,7 @@ jobs:
122122

123123
- name: Login to GitHub Container Registry
124124
if: github.event_name != 'pull_request'
125-
uses: docker/login-action@184bdaa0721073962dff0199f1fb9940f07167d1 # 3.5.0
125+
uses: docker/login-action@5e57cd118135c172c3672efd75eb46360885c0ef # 3.6.0
126126
with:
127127
registry: ghcr.io
128128
username: ${{ github.repository_owner }}

0 commit comments

Comments
 (0)