Skip to content

Commit f24186a

Browse files
delucchi-cmuhombit
andauthored
Add testing stage for trying against lowest pinned versions. (#515)
* Add testing stage for trying against lowest pinned versions. * Update copier.yml Co-authored-by: Konstantin Malanchev <[email protected]> --------- Co-authored-by: Konstantin Malanchev <[email protected]>
1 parent eead79a commit f24186a

File tree

4 files changed

+88
-6
lines changed

4 files changed

+88
-6
lines changed

copier.yml

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@ project_license:
6464

6565
python_versions:
6666
help: What versions of python are you targeting? We will add automated testing for these versions.
67-
default: ["3.9", "3.10", "3.11"]
67+
default: ["3.9", "3.10", "3.11", "3.12", "3.13"]
6868
type: str
6969
multiselect: true
7070
choices:
@@ -145,6 +145,15 @@ include_benchmarks:
145145
no: false
146146
when: "{{ custom_install }}"
147147

148+
test_lowest_version:
149+
help: Run pull request tests with the lowest versions of python and dependencies? Recommended if you are developing a library
150+
default: direct
151+
choices:
152+
Do not test with lowest versions of dependencies: none
153+
Test with lowest versions of direct dependencies only (those listed in pyproject.toml): direct
154+
Test with lowest versions of all dependencies: all
155+
when: "{{ custom_install }}"
156+
148157
_message_after_copy: |
149158
Your project "{{ project_name }}" has been created successfully!
150159

docs/source/template_options.rst

Lines changed: 32 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -125,11 +125,14 @@ The license type you want to use for this project.
125125
8. Versions of Python
126126
---------------------
127127

128-
+------------+-----------------------------------------------------------------+
129-
| Question | What versions of Python will your project support? |
130-
+------------+-----------------------------------------------------------------+
131-
| Options | 3.7 (end-of-life), 3.8, **✱ 3.9**, **✱ 3.10**, **✱ 3.11**, 3.12 |
132-
+------------+-----------------------------------------------------------------+
128+
+------------+----------------------------------------------------+
129+
| Question | What versions of Python will your project support? |
130+
+------------+----------------------------------------------------+
131+
| Options | 3.8 (end-of-life), **✱ 3.9**, |
132+
| | **✱ 3.9**, **✱ 3.10**, |
133+
| | **✱ 3.11**, **✱ 3.12**, |
134+
| | 3.13 |
135+
+------------+----------------------------------------------------+
133136

134137
Select all versions of python that you are targeting for execution.
135138

@@ -271,3 +274,27 @@ It will also create a sample benchmarking suite under ``benchmarks/``::
271274
├─ ...
272275

273276
Read more at :doc:`../practices/ci_benchmarking`.
277+
278+
16. Test against lowest versions
279+
------------------------------------------------
280+
281+
+------------+-----------------------------------------------------------+
282+
| Question | Run pull request tests with the lowest versions of python |
283+
| | and dependencies? |
284+
+------------+-----------------------------------------------------------+
285+
| Options | | (none) Do not test with lowest versions of dependencies |
286+
| | | **(direct)** Test with lowest versions of direct |
287+
| | dependencies only (those listed in pyproject.toml) |
288+
| | | (all) Test with lowest versions of all dependencies |
289+
+------------+-----------------------------------------------------------+
290+
291+
Adds an optional stage to the end of the testing and coverage github CI workflow
292+
using the oldest version of python you've selected above, and will determine
293+
the oldest versions of dependencies indicated in the pyproject file.
294+
295+
A new environment has these dependencies installed, and we try to run the pytest
296+
unit tests against these versions.
297+
298+
This can be useful if your project is a library, and folks may want to depend on
299+
you and your dependencies. Understanding the true range of versions you support
300+
in your application can make dependency resolution much easier for your users!

python-project-template/.github/workflows/testing-and-coverage.yml.jinja

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
{%- import 'python-versions.jinja' as py %}
12
# This workflow will install Python dependencies, run tests and report code coverage with a variety of Python versions
23
# For more information see: https://help.github.com/actions/language-and-framework-guides/using-python-with-github-actions
34

@@ -36,3 +37,29 @@ jobs:
3637
uses: codecov/codecov-action@v5
3738
with:
3839
token: {% raw %}${{ secrets.CODECOV_TOKEN }}{% endraw %}
40+
{%- if test_lowest_version != 'none' %}
41+
test-lowest-versions:
42+
runs-on: ubuntu-latest
43+
steps:
44+
- uses: actions/checkout@v4
45+
- name: Set up Python {{ py.min(python_versions) }}
46+
uses: actions/setup-python@v5
47+
with:
48+
python-version: '{{ py.min(python_versions) }}'
49+
- name: Install dependencies
50+
run: |
51+
sudo apt-get update
52+
python -m pip install --upgrade uv
53+
uv venv venv
54+
source venv/bin/activate
55+
{%- if test_lowest_version == 'direct' %}
56+
uv pip compile --resolution=lowest-direct -o requirements_lowest.txt pyproject.toml
57+
{%- elif test_lowest_version == 'all' %}
58+
uv pip compile --resolution=lowest -o requirements_lowest.txt pyproject.toml
59+
{%- endif %}
60+
uv pip install --constraint=requirements_lowest.txt -e .[dev]
61+
- name: Run unit tests with pytest
62+
run: |
63+
source venv/bin/activate
64+
python -m pytest
65+
{%- endif %}

tests/test_package_creation.py

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -288,6 +288,25 @@ def test_doc_combinations_no_docs(copie, doc_answers):
288288
assert not (result.project_dir / "docs").is_dir()
289289

290290

291+
@pytest.mark.parametrize("test_lowest_version", ["none", "direct", "all"])
292+
def test_test_lowest_version(copie, test_lowest_version):
293+
"""Confirm we can generate a "testing_and_coverage.yaml" file, with all
294+
test_lowest_version mechanisms selected."""
295+
296+
# provide a dictionary of the non-default answers to use
297+
extra_answers = {
298+
"test_lowest_version": test_lowest_version,
299+
}
300+
301+
# run copier to hydrate a temporary project
302+
result = copie.copy(extra_answers=extra_answers)
303+
304+
assert successfully_created_project(result)
305+
assert directory_structure_is_correct(result)
306+
assert black_runs_successfully(result)
307+
assert contains_required_files(result)
308+
309+
291310
def test_github_workflows_schema(copie):
292311
"""Confirm the current GitHub workflows have valid schemas."""
293312
extra_answers = {

0 commit comments

Comments
 (0)