diff --git a/.github/ISSUE_TEMPLATE/release_checklist.md b/.github/ISSUE_TEMPLATE/release_checklist.md index 6107962..5be9636 100644 --- a/.github/ISSUE_TEMPLATE/release_checklist.md +++ b/.github/ISSUE_TEMPLATE/release_checklist.md @@ -6,6 +6,10 @@ labels: "release" assignees: "" --- +### Run diffpy.cmi example scripts + +- [ ] Manually trigger the `validate-examples.yml` workflow to run all example scripts. + ### PyPI/GitHub rc-release preparation checklist: - [ ] All PRs/issues attached to the release are merged. diff --git a/.github/workflows/validate-examples.yml b/.github/workflows/validate-examples.yml new file mode 100644 index 0000000..2ccf311 --- /dev/null +++ b/.github/workflows/validate-examples.yml @@ -0,0 +1,52 @@ +name: Validate Examples + +on: + workflow_dispatch: + +jobs: + validate-examples: + defaults: + run: + shell: bash -l {0} + + runs-on: ubuntu-latest + + steps: + - name: Check out repository + uses: actions/checkout@v4 + + - name: Initialize miniconda + uses: conda-incubator/setup-miniconda@v3 + with: + activate-environment: test + channels: conda-forge + auto-update-conda: true + auto-activate-base: false + python-version: 3.13 + + - name: Conda config + run: >- + conda config --set always_yes yes + --set changeps1 no + + - name: Install dependencies + run: | + conda install --file requirements/conda.txt + conda install --file requirements/tests.txt + + if [ -d requirements/packs ]; then + for f in requirements/packs/*.txt; do + if [ -f "$f" ]; then + echo "Installing dependencies from $f" + conda install --file "$f" + fi + done + fi + + python -m pip install . --no-deps + + - name: Run example scripts + run: | + set -Eeuo pipefail + echo "Running example scripts" + pytest validators/validate_examples.py --cov diff --git a/news/run-ex-on-releases.rst b/news/run-ex-on-releases.rst new file mode 100644 index 0000000..20c2924 --- /dev/null +++ b/news/run-ex-on-releases.rst @@ -0,0 +1,23 @@ +**Added:** + +* Add workflow to run ``examples/validate_examples.py`` manually. + +**Changed:** + +* Changed workflow so that ``validate_examples.py`` is ran only on manual triggers. + +**Deprecated:** + +* + +**Removed:** + +* + +**Fixed:** + +* + +**Security:** + +* diff --git a/tests/conftest.py b/tests/conftest.py index 5a4edca..658294d 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -1,26 +1,9 @@ import json -import shutil from pathlib import Path import matplotlib import pytest -PROJECT_ROOT = Path(__file__).resolve().parents[1] -EXAMPLES_ROOT = PROJECT_ROOT / "docs" / "examples" - - -@pytest.fixture(scope="session") -def tmp_examples(tmp_path_factory): - """Copy the entire examples/ tree into a temp directory once per - test session. - - Returns the path to that copy. - """ - tmpdir = tmp_path_factory.mktemp("examples") - tmp_examples = tmpdir / "examples" - shutil.copytree(EXAMPLES_ROOT, tmp_examples) - yield tmp_examples - @pytest.fixture(scope="session") def example_cases(tmp_path_factory): diff --git a/tests/test_examples.py b/tests/test_examples.py deleted file mode 100644 index fafbfab..0000000 --- a/tests/test_examples.py +++ /dev/null @@ -1,12 +0,0 @@ -import runpy - - -def test_all_examples(tmp_examples): - """Run all example scripts to ensure they execute without error.""" - scripts = list(tmp_examples.rglob("**/solutions/diffpy-cmi/*.py")) - # sort list so that fitBulkNi.py runs first - scripts.sort(key=lambda s: 0 if s.name == "fitBulkNi.py" else 1) - for script in scripts: - script_relative_path = script.relative_to(tmp_examples) - print(f"Testing {script_relative_path}") - runpy.run_path(str(script), run_name="__main__") diff --git a/validators/validate_examples.py b/validators/validate_examples.py new file mode 100644 index 0000000..3fd2cde --- /dev/null +++ b/validators/validate_examples.py @@ -0,0 +1,32 @@ +import runpy +import shutil +from pathlib import Path + +import pytest + +PROJECT_ROOT = Path(__file__).resolve().parents[1] +EXAMPLES_ROOT = PROJECT_ROOT / "docs" / "examples" + + +@pytest.fixture(scope="session") +def tmp_examples(tmp_path_factory): + """Copy the entire examples/ tree into a temp directory once per + test session. + + Returns the path to that copy. + """ + tmpdir = tmp_path_factory.mktemp("examples") + tmp_examples = tmpdir / "examples" + shutil.copytree(EXAMPLES_ROOT, tmp_examples) + yield tmp_examples + + +def test_all_examples(tmp_examples): + """Run all example scripts to ensure they execute without error.""" + scripts = list(tmp_examples.rglob("**/solutions/diffpy-cmi/*.py")) + # sort list so that fitBulkNi.py runs first + scripts.sort(key=lambda s: 0 if s.name == "fitBulkNi.py" else 1) + for script in scripts: + script_relative_path = script.relative_to(tmp_examples) + print(f"Testing {script_relative_path}") + runpy.run_path(str(script), run_name="__main__")