Skip to content

Commit e110151

Browse files
authored
tests: Move sanic under toxgen & add option to control how many releases to pick (#4767)
- Move sanic under toxgen - This gets rid of the `-latest` group for Web 2 as all Web 2 test suites are now governed by toxgen - Add `num_versions` as a new option to optionally slim down the number of tested versions (useful for sanic as it has a lot of "majors" due to calver) - When a package had multiple majors, we used to always pick the lowest as well as the highest release in the last major -- removed the lowest now to not over-test. All majors will still be tested by default, we just won't be testing two releases in the last major. Ref #4506
1 parent 7ae6866 commit e110151

File tree

6 files changed

+82
-177
lines changed

6 files changed

+82
-177
lines changed

.github/workflows/test-integrations-web-2.yml

Lines changed: 0 additions & 95 deletions
Original file line numberDiff line numberDiff line change
@@ -22,101 +22,6 @@ env:
2222
CACHED_BUILD_PATHS: |
2323
${{ github.workspace }}/dist-serverless
2424
jobs:
25-
test-web_2-latest:
26-
name: Web 2 (latest)
27-
timeout-minutes: 30
28-
runs-on: ${{ matrix.os }}
29-
strategy:
30-
fail-fast: false
31-
matrix:
32-
python-version: ["3.9","3.12","3.13"]
33-
# python3.6 reached EOL and is no longer being supported on
34-
# new versions of hosted runners on Github Actions
35-
# ubuntu-20.04 is the last version that supported python3.6
36-
# see https://github.com/actions/setup-python/issues/544#issuecomment-1332535877
37-
os: [ubuntu-22.04]
38-
# Use Docker container only for Python 3.6
39-
container: ${{ matrix.python-version == '3.6' && 'python:3.6' || null }}
40-
steps:
41-
- uses: actions/[email protected]
42-
- uses: actions/setup-python@v6
43-
if: ${{ matrix.python-version != '3.6' }}
44-
with:
45-
python-version: ${{ matrix.python-version }}
46-
allow-prereleases: true
47-
- name: Setup Test Env
48-
run: |
49-
pip install "coverage[toml]" tox
50-
- name: Erase coverage
51-
run: |
52-
coverage erase
53-
- name: Test aiohttp latest
54-
run: |
55-
set -x # print commands that are executed
56-
./scripts/runtox.sh "py${{ matrix.python-version }}-aiohttp-latest"
57-
- name: Test asgi latest
58-
run: |
59-
set -x # print commands that are executed
60-
./scripts/runtox.sh "py${{ matrix.python-version }}-asgi-latest"
61-
- name: Test bottle latest
62-
run: |
63-
set -x # print commands that are executed
64-
./scripts/runtox.sh "py${{ matrix.python-version }}-bottle-latest"
65-
- name: Test falcon latest
66-
run: |
67-
set -x # print commands that are executed
68-
./scripts/runtox.sh "py${{ matrix.python-version }}-falcon-latest"
69-
- name: Test litestar latest
70-
run: |
71-
set -x # print commands that are executed
72-
./scripts/runtox.sh "py${{ matrix.python-version }}-litestar-latest"
73-
- name: Test pyramid latest
74-
run: |
75-
set -x # print commands that are executed
76-
./scripts/runtox.sh "py${{ matrix.python-version }}-pyramid-latest"
77-
- name: Test quart latest
78-
run: |
79-
set -x # print commands that are executed
80-
./scripts/runtox.sh "py${{ matrix.python-version }}-quart-latest"
81-
- name: Test sanic latest
82-
run: |
83-
set -x # print commands that are executed
84-
./scripts/runtox.sh "py${{ matrix.python-version }}-sanic-latest"
85-
- name: Test starlite latest
86-
run: |
87-
set -x # print commands that are executed
88-
./scripts/runtox.sh "py${{ matrix.python-version }}-starlite-latest"
89-
- name: Test tornado latest
90-
run: |
91-
set -x # print commands that are executed
92-
./scripts/runtox.sh "py${{ matrix.python-version }}-tornado-latest"
93-
- name: Generate coverage XML (Python 3.6)
94-
if: ${{ !cancelled() && matrix.python-version == '3.6' }}
95-
run: |
96-
export COVERAGE_RCFILE=.coveragerc36
97-
coverage combine .coverage-sentry-*
98-
coverage xml --ignore-errors
99-
- name: Generate coverage XML
100-
if: ${{ !cancelled() && matrix.python-version != '3.6' }}
101-
run: |
102-
coverage combine .coverage-sentry-*
103-
coverage xml
104-
- name: Upload coverage to Codecov
105-
if: ${{ !cancelled() }}
106-
uses: codecov/[email protected]
107-
with:
108-
token: ${{ secrets.CODECOV_TOKEN }}
109-
files: coverage.xml
110-
# make sure no plugins alter our coverage reports
111-
plugins: noop
112-
verbose: true
113-
- name: Upload test results to Codecov
114-
if: ${{ !cancelled() }}
115-
uses: codecov/test-results-action@v1
116-
with:
117-
token: ${{ secrets.CODECOV_TOKEN }}
118-
files: .junitxml
119-
verbose: true
12025
test-web_2-pinned:
12126
name: Web 2 (pinned)
12227
timeout-minutes: 30

scripts/populate_tox/README.md

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,7 @@ then determining which versions make sense to test to get good coverage.
1818

1919
The lowest supported and latest version of a framework are always tested, with
2020
a number of releases in between:
21-
- If the package has majors, we pick the highest version of each major. For the
22-
latest major, we also pick the lowest version in that major.
21+
- If the package has majors, we pick the highest version of each major.
2322
- If the package doesn't have multiple majors, we pick two versions in between
2423
lowest and highest.
2524

@@ -46,6 +45,8 @@ integration_name: {
4645
},
4746
"python": python_version_specifier,
4847
"include": package_version_specifier,
48+
"integration_name": integration_name,
49+
"num_versions": int,
4950
}
5051
```
5152

@@ -161,6 +162,10 @@ of which are actually testing the `openai` integration. If this is the case, you
161162

162163
Linking an integration to a test suite allows the script to access integration configuration like for example the minimum version defined in `sentry_sdk/integrations/__init__.py`.
163164

165+
### `num_versions`
166+
167+
With this option you can tweak the default version picking behavior by specifying how many package versions should be tested. It accepts an integer equal to or greater than 2, as the oldest and latest supported versions will always be picked. Additionally, if there is a recent prerelease, it'll also always be picked (this doesn't count towards `num_versions`).
168+
164169

165170
## How-Tos
166171

scripts/populate_tox/config.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -259,6 +259,16 @@
259259
"requests": {
260260
"package": "requests",
261261
},
262+
"sanic": {
263+
"package": "sanic",
264+
"deps": {
265+
"*": ["websockets<11.0", "aiohttp"],
266+
">=22": ["sanic-testing"],
267+
"py3.6": ["aiocontextvars==0.2.1"],
268+
"py3.8": ["tracerite<1.1.2"],
269+
},
270+
"num_versions": 4,
271+
},
262272
"spark": {
263273
"package": "pyspark",
264274
"python": ">=3.8",

scripts/populate_tox/populate_tox.py

Lines changed: 48 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,6 @@
7474
"redis",
7575
"requests",
7676
"rq",
77-
"sanic",
7877
}
7978

8079

@@ -258,47 +257,48 @@ def _supports_lowest(release: Version) -> bool:
258257

259258

260259
def pick_releases_to_test(
261-
releases: list[Version], last_prerelease: Optional[Version]
260+
integration: str, releases: list[Version], last_prerelease: Optional[Version]
262261
) -> list[Version]:
263262
"""Pick a handful of releases to test from a sorted list of supported releases."""
264263
# If the package has majors (or major-like releases, even if they don't do
265-
# semver), we want to make sure we're testing them all. If not, we just pick
266-
# the oldest, the newest, and a couple in between.
264+
# semver), we want to make sure we're testing them all (unless there's too
265+
# many). If not, we just pick the oldest, the newest, and a couple
266+
# in between.
267267
#
268268
# If there is a relevant prerelease, also test that in addition to the above.
269-
has_majors = len(set([v.major for v in releases])) > 1
269+
num_versions = TEST_SUITE_CONFIG[integration].get("num_versions")
270+
if num_versions is not None and (
271+
not isinstance(num_versions, int) or num_versions < 2
272+
):
273+
print(" Integration has invalid `num_versions`: must be an int >= 2")
274+
num_versions = None
275+
276+
has_majors = len({v.major for v in releases}) > 1
270277
filtered_releases = set()
271278

272279
if has_majors:
273280
# Always check the very first supported release
274281
filtered_releases.add(releases[0])
275282

276-
# Find out the min and max release by each major
283+
# Find out the max release by each major
277284
releases_by_major = {}
278285
for release in releases:
279-
if release.major not in releases_by_major:
280-
releases_by_major[release.major] = [release, release]
281-
if release < releases_by_major[release.major][0]:
282-
releases_by_major[release.major][0] = release
283-
if release > releases_by_major[release.major][1]:
284-
releases_by_major[release.major][1] = release
285-
286-
for i, (min_version, max_version) in enumerate(releases_by_major.values()):
286+
if (
287+
release.major not in releases_by_major
288+
or release > releases_by_major[release.major]
289+
):
290+
releases_by_major[release.major] = release
291+
292+
# Add the highest release in each major
293+
for max_version in releases_by_major.values():
287294
filtered_releases.add(max_version)
288-
if i == len(releases_by_major) - 1:
289-
# If this is the latest major release, also check the lowest
290-
# version of this version
291-
filtered_releases.add(min_version)
295+
296+
# If num_versions was provided, slim down the selection
297+
if num_versions is not None:
298+
filtered_releases = _pick_releases(sorted(filtered_releases), num_versions)
292299

293300
else:
294-
filtered_releases = {
295-
releases[0], # oldest version supported
296-
releases[len(releases) // 3],
297-
releases[
298-
len(releases) // 3 * 2
299-
], # two releases in between, roughly evenly spaced
300-
releases[-1], # latest
301-
}
301+
filtered_releases = _pick_releases(releases, num_versions)
302302

303303
filtered_releases = sorted(filtered_releases)
304304
if last_prerelease is not None:
@@ -307,6 +307,25 @@ def pick_releases_to_test(
307307
return filtered_releases
308308

309309

310+
def _pick_releases(
311+
releases: list[Version], num_versions: Optional[int]
312+
) -> set[Version]:
313+
num_versions = num_versions or 4
314+
315+
versions = {
316+
releases[0], # oldest version supported
317+
releases[-1], # latest
318+
}
319+
320+
for i in range(1, num_versions - 1):
321+
try:
322+
versions.add(releases[len(releases) // (num_versions - 1) * i])
323+
except IndexError:
324+
pass
325+
326+
return versions
327+
328+
310329
def supported_python_versions(
311330
package_python_versions: Union[SpecifierSet, list[Version]],
312331
custom_supported_versions: Optional[SpecifierSet] = None,
@@ -631,7 +650,9 @@ def main(fail_on_changes: bool = False) -> None:
631650
# Pick a handful of the supported releases to actually test against
632651
# and fetch the PyPI data for each to determine which Python versions
633652
# to test it on
634-
test_releases = pick_releases_to_test(releases, latest_prerelease)
653+
test_releases = pick_releases_to_test(
654+
integration, releases, latest_prerelease
655+
)
635656

636657
for release in test_releases:
637658
_add_python_versions_to_release(integration, package, release)

scripts/populate_tox/tox.jinja

Lines changed: 0 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -81,12 +81,6 @@ envlist =
8181
{py3.7,py3.11,py3.12}-rq-v{1.15,1.16}
8282
{py3.7,py3.12,py3.13}-rq-latest
8383

84-
# Sanic
85-
{py3.6,py3.7}-sanic-v{0.8}
86-
{py3.6,py3.8}-sanic-v{20}
87-
{py3.8,py3.11,py3.12}-sanic-v{24.6}
88-
{py3.9,py3.12,py3.13}-sanic-latest
89-
9084
# === Integrations - Auto-generated ===
9185
# These come from the populate_tox.py script. Eventually we should move all
9286
# integration tests there.
@@ -210,18 +204,6 @@ deps =
210204
rq-v1.16: rq~=1.16.0
211205
rq-latest: rq
212206
213-
# Sanic
214-
sanic: websockets<11.0
215-
sanic: aiohttp
216-
sanic-v{24.6}: sanic_testing
217-
sanic-latest: sanic_testing
218-
{py3.6}-sanic: aiocontextvars==0.2.1
219-
{py3.8}-sanic: tracerite<1.1.2
220-
sanic-v0.8: sanic~=0.8.0
221-
sanic-v20: sanic~=20.0
222-
sanic-v24.6: sanic~=24.6.0
223-
sanic-latest: sanic
224-
225207
# === Integrations - Auto-generated ===
226208
# These come from the populate_tox.py script. Eventually we should move all
227209
# integration tests there.

0 commit comments

Comments
 (0)