diff --git a/.github/workflows/build_deploy_pages.yml b/.github/workflows/build_deploy_pages.yml index 7c7014a8..0b2f7630 100644 --- a/.github/workflows/build_deploy_pages.yml +++ b/.github/workflows/build_deploy_pages.yml @@ -1,4 +1,4 @@ -name: docs +name: Build and Deploy Documentation on: push: @@ -39,8 +39,8 @@ jobs: if: github.event_name == 'push' permissions: contents: read - pages: write # to deploy to Pages - id-token: write # to verify the deployment originates from an appropriate source + pages: write # to deploy to Pages + id-token: write # to verify the deployment originates from an appropriate source environment: name: github-pages url: ${{ steps.deployment.outputs.page_url }} diff --git a/.github/workflows/build_test_wheels.yml b/.github/workflows/build_test_wheels.yml new file mode 100644 index 00000000..09fdaf3c --- /dev/null +++ b/.github/workflows/build_test_wheels.yml @@ -0,0 +1,126 @@ +# Build wheels, sdist, and full wheel test matrix. +# Runs on: push to main (including merges), publish_pypi.yml (tags), workflow_call, and monthly schedule. +name: Build and Test Wheels + +on: + workflow_call: # For use by publish_pypi.yml + push: + branches: [main] + schedule: + - cron: '0 0 1 * *' + +jobs: + build_wheels: + name: Build wheels + runs-on: ${{ matrix.os }} + strategy: + matrix: + os: [ubuntu-latest, windows-latest, macos-15-intel, macos-latest] + fail-fast: false + steps: + - name: Set env variables to handle macOS-15 + if: ${{ matrix.os == 'macos-15-intel'}} + run: | + echo "MACOSX_DEPLOYMENT_TARGET=15.0" >> $GITHUB_ENV + echo "PLAT=macosx-15.0-universal2" >> $GITHUB_ENV + - name: Checkout repository + uses: actions/checkout@v4 + - name: Install libomp on macos + if: ${{ matrix.os == 'macos-latest' || matrix.os == 'macos-15-intel'}} + run: | + brew reinstall libomp + - name: Ad-hoc codesign for Apple Silicon + if: ${{ matrix.os == 'macos-latest' }} + run: | + dylib_path="wntr/epanet/libepanet/darwin-arm" + if [ -d "$dylib_path" ]; then + for file in "$dylib_path"/*; do + [ -e "$file" ] && codesign -f -s - "$file" + done + fi + - name: Build wheels + uses: pypa/cibuildwheel@v3.1.4 + env: + CIBW_ENVIRONMENT: BUILD_WNTR_EXTENSIONS='true' + CIBW_BUILD: cp310-* cp311-* cp312-* cp313-* + CIBW_SKIP: "*-win32 *-manylinux_i686 pp* *-musllinux*" + CIBW_REPAIR_WHEEL_COMMAND: '' # Skip repair step + - name: Set up Python for twine verification + uses: actions/setup-python@v5 + with: + python-version: '3.11' + - name: Verify wheels with twine + shell: bash + run: | + python -m pip install --upgrade pip twine + for wheel in ./wheelhouse/*.whl; do + twine check "$wheel" + done + - name: Fix linux wheel names # Temporary hack: rename linux -> manylinux2014 so PyPI accepts them without a proper repair step. + if: ${{ matrix.os == 'ubuntu-latest' }} + run: | + for file in ./wheelhouse/*.whl; do + [ -e "$file" ] || continue + new_file="${file/linux/manylinux2014}" + mv "$file" "$new_file" + done + - name: Upload wheels + uses: actions/upload-artifact@v4 + with: + name: cibw-wheels-${{ matrix.os }}-${{ strategy.job-index }} + path: ./wheelhouse/*.whl + + build_sdist: + name: Build SDist + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - uses: actions/setup-python@v5 + with: + python-version: '3.11' + - name: Build SDist + run: pipx run build --sdist + - uses: actions/upload-artifact@v4 + with: + name: sdist + path: dist/*.tar.gz + + test_wheels: + name: Test wheels (${{ matrix.python-version }}, ${{ matrix.os }}) + needs: build_wheels + runs-on: ${{ matrix.os }} + strategy: + matrix: + python-version: ['3.10', '3.11', '3.12', '3.13'] + os: [ubuntu-latest, windows-latest, macos-15-intel, macos-latest] + fail-fast: false + steps: + - name: Set up Python + uses: actions/setup-python@v5 + with: + python-version: ${{ matrix.python-version }} + - name: Download wheels for this OS + uses: actions/download-artifact@v4 + with: + pattern: cibw-wheels-${{ matrix.os }}-* + merge-multiple: true + - name: Checkout test assets + uses: actions/checkout@v4 + with: + sparse-checkout: | + wntr/tests/ + sparse-checkout-cone-mode: false + fetch-depth: 1 + - name: Set mpl backend on windows + if: ${{ matrix.os == 'windows-latest' }} + run: echo "MPLBACKEND=Agg" >> $env:GITHUB_ENV + shell: pwsh + - if: ${{ matrix.os == 'macos-latest' || matrix.os == 'macos-15-intel'}} + run: brew reinstall libomp + - name: Install wntr from wheel + run: | + python -m pip install --upgrade pip + pip install --pre --find-links=. "wntr[optional,test]" + python -c "import wntr; print(wntr.__version__)" + - name: Run tests against wheel + run: pytest wntr/tests/ --ignore=wntr/tests/test_demos.py --ignore=wntr/tests/test_examples.py diff --git a/.github/workflows/build_tests.yml b/.github/workflows/build_tests.yml deleted file mode 100644 index caac8a6c..00000000 --- a/.github/workflows/build_tests.yml +++ /dev/null @@ -1,321 +0,0 @@ -# This workflow will install Python dependencies, run tests and lint with all currently supported python versions on all major plattforms -# For more information see: https://help.github.com/actions/language-and-framework-guides/using-python-with-github-actions - -name: GitHub CI - -on: - push: - branches: [ main, dev, release ] - tags: - - '*' - pull_request: - branches: [ main, dev, release ] - schedule: - - cron: '0 0 1 * *' - -jobs: - build_wheels: - name: Build wheels - runs-on: ${{ matrix.os }} - strategy: - matrix: - os: [ubuntu-latest, windows-latest, macos-15-intel, macos-latest] - fail-fast: false - steps: - - name: Set env variables to handle macOS-15 - if: ${{ matrix.os == 'macos-15-intel'}} - run: | - echo "MACOSX_DEPLOYMENT_TARGET=15.0" >> $GITHUB_ENV - echo "PLAT=macosx-15.0-universal2" >> $GITHUB_ENV - - name: Checkout repository - uses: actions/checkout@v4 - - name: Install libomp on macos - if: ${{ matrix.os == 'macos-latest' || matrix.os == 'macos-15-intel'}} - run: | - brew reinstall libomp # EPANETMSX repo also has this line, maybe include? `brew link --force --overwrite libomp` - - name: Ad-hoc codesign for Apple Silicon - if: ${{ matrix.os == 'macos-latest' }} - run: | - dylib_path="wntr/epanet/libepanet/darwin-arm" - if [ -d "$dylib_path" ]; then - for file in "$dylib_path"/*; do - [ -e "$file" ] && codesign -f -s - "$file" - done - fi - - name: Build wheels - uses: pypa/cibuildwheel@v3.1.4 - env: - CIBW_ENVIRONMENT: BUILD_WNTR_EXTENSIONS='true' - CIBW_BUILD: cp310-* cp311-* cp312-* cp313-* - CIBW_SKIP: "*-win32 *-manylinux_i686 pp* *-musllinux*" - CIBW_REPAIR_WHEEL_COMMAND: '' # Skip repair step - - name: Set up Python for twine verification - uses: actions/setup-python@v5 - with: - python-version: '3.11' - - name: Install twine and verify wheels - shell: bash - run: | - python -m pip install --upgrade pip - pip install twine - for wheel in ./wheelhouse/*.whl; do - echo "Verifying wheel: $wheel" - twine check "$wheel" - done - # - name: Fix macos15 wheel names # For some reason, they come out as macos14 instead of macos15 - # if: ${{ matrix.os == 'macos-15-intel'}} - # run: | - # echo "=== Before renaming ===" - # ls -la ./wheelhouse/ - # for file in ./wheelhouse/*.whl; do - # echo "Original file: $file" - # new_name=$(echo "$file" | sed 's/macosx_14_0/macosx_15_0/') - # echo "New name: $new_name" - # mv "$file" "$new_name" - # done - # echo "=== After renaming ===" - # ls -la ./wheelhouse/ - - name: Fix linux wheel names # This is a bit dishonest, since the wheels are not properly repaired to be manylinux compatible. This is a (hopefully) temporary hack to get our wheels onto pypi. - if: ${{ matrix.os == 'ubuntu-latest' }} - run: | - for file in ./wheelhouse/*.whl; do - [ -e "$file" ] || continue - new_file="${file/linux/manylinux2014}" - mv "$file" "$new_file" - echo "Renamed: $file -> $new_file" - done - - name: Upload wheels - uses: actions/upload-artifact@v4 - with: - name: cibw-wheels-${{ matrix.os }}-${{ strategy.job-index }} - path: ./wheelhouse/*.whl - - test_wheels: - name: Test wheels - needs: build_wheels - runs-on: ${{ matrix.os }} - strategy: - matrix: - python-version: ['3.10', '3.11', '3.12', '3.13'] - os: [ubuntu-latest, windows-latest, macos-15-intel, macos-latest] - fail-fast: false - steps: - - name: Set up Python - uses: actions/setup-python@v5 - with: - python-version: ${{ matrix.python-version }} - - name: Download wheel - uses: actions/download-artifact@v4 - with: - # name: wntr_${{ matrix.python-version }}_${{ matrix.os }}.whl - pattern: "cibw-wheels-*" - merge-multiple: true - - name: Install wntr - run: | - python -m pip install --upgrade pip - pip install wheel "numpy>=2.2.6" scipy networkx pandas matplotlib setuptools - pip install --no-index --pre --find-links=. wntr - - name: Import wntr - run: | - python -c "import wntr" - - name: Checkout requirements.txt - uses: actions/checkout@v4 - with: - sparse-checkout: | - requirements.txt - wntr/tests/ - examples/ - sparse-checkout-cone-mode: false - fetch-depth: 1 - - name: Set mpl backend on windows - if: ${{ matrix.os == 'windows-latest' }} - run: echo "MPLBACKEND=Agg" >> $env:GITHUB_ENV - shell: pwsh - - if: ${{ matrix.os == 'macos-latest' || matrix.os == 'macos-15-intel'}} - run: | - brew reinstall libomp - - name: Test wntr - run: | - pip install --find-links=. --pre "wntr[optional,test]" - pytest wntr/tests/ --ignore=wntr/tests/test_demos.py --ignore=wntr/tests/test_examples.py - - run_coverage: - runs-on: ${{ matrix.os }} - strategy: - matrix: - python-version: ['3.10', '3.11', '3.12', '3.13'] - os: [ubuntu-latest, windows-latest, macos-15-intel, macos-latest] - fail-fast: false - steps: - - uses: actions/checkout@v4 - - name: Set up Python ${{ matrix.python-version }} - uses: actions/setup-python@v5 - with: - python-version: ${{ matrix.python-version }} - - name: Set mpl backend on windows - if: ${{ matrix.os == 'windows-latest' }} - run: echo "MPLBACKEND=Agg" >> $env:GITHUB_ENV - shell: pwsh - - if: ${{ matrix.os == 'macos-latest' || matrix.os == 'macos-15-intel'}} - run: | - brew reinstall libomp - - name: Install dependencies - run: | - python --version - python -m pip install --upgrade pip - python -m pip install -e .[optional,test] - - name: Run Tests - if: ${{ matrix.os != 'macos-latest' }} - env: - OMIT: "'*/tests/*','*/extensions/*','*/sim/network_isolation/network_isolation.py','*/sim/aml/evaluator.py'" - COVERAGE_FILE: .coverage.${{ matrix.python-version }}.${{ matrix.os }} - run: | - coverage erase - coverage run --context=${{ matrix.os }}.py${{ matrix.python-version }} --source=wntr --omit=$OMIT -m pytest -m "not extensions" --ignore=wntr/extensions --doctest-modules --doctest-glob="*.rst" wntr - coverage run --context=${{ matrix.os }}.py${{ matrix.python-version }} --source=wntr --omit=$OMIT --append -m pytest --doctest-glob="*.rst" --ignore-glob="*/extensions/*.rst" documentation - - name: Run Tests (ARM-processor) - if: ${{ matrix.os == 'macos-latest'}} - # doctests are not flexible enough to skip EPANET=v2.0 errors on ARM processor, so do not run doctests on ARM system - run: | - coverage erase - coverage run --context=${{ matrix.os }}.py${{ matrix.python-version }} --source=wntr --omit="*/tests/*","*/sim/network_isolation/network_isolation.py","*/sim/aml/evaluator.py" -m pytest --doctest-modules --doctest-glob="*.rst" wntr - env: - COVERAGE_FILE: .coverage.${{ matrix.python-version }}.${{ matrix.os }} - - name: Save coverage - uses: actions/upload-artifact@v4 - with: - name: .coverage.${{ matrix.python-version }}.${{ matrix.os }} - path: .coverage.${{ matrix.python-version }}.${{ matrix.os }} - include-hidden-files: true - - combine_reports: - needs: [ run_coverage ] - runs-on: ubuntu-latest - steps: - - name: Set up Python - uses: actions/setup-python@v5 - with: - python-version: 3.11 - - uses: actions/checkout@v4 - - name: Install coverage - run: | - python -m pip install --upgrade pip - python -m pip install -e .[optional,test] - pip install coveralls - - name: Download coverage artifacts from test matrix - uses: actions/download-artifact@v4 - with: - pattern: .coverage.*.ubuntu-latest # coverage from other OS cause problems - - name: Setup coverage and combine reports - run: coverage combine .coverage.*.ubuntu-latest - - name: Create coverage report - run: | - echo "[paths]" > .coveragerc - echo "source = " >> .coveragerc - echo " wntr/" >> .coveragerc - echo " wntr\\" >> .coveragerc - echo " D:\\a\\WNTR\\WNTR\\wntr" >> .coveragerc - echo " /home/runner/work/WNTR/WNTR/wntr" >> .coveragerc - echo " /Users/runner/work/WNTR/WNTR/wntr" >> .coveragerc - echo " ${{ github.workspace }}/wntr" >> .coveragerc - coverage report - coverage json --pretty-print - coverage html --show-contexts - - name: Save coverage JSON - uses: actions/upload-artifact@v4 - with: - name: coverage-json - path: coverage.json - - name: Save coverage html - uses: actions/upload-artifact@v4 - with: - name: coverage-html - path: htmlcov - - name: Push to coveralls - run: coveralls --service=github --rcfile=.coveragerc - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - - build_sdist: - name: Build SDist artifact 📦 - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v4 - - uses: actions/setup-python@v5 - with: - python-version: '3.11' - - name: Build SDist - run: pipx run build --sdist - - uses: actions/upload-artifact@v4 - with: - name: sdist - path: dist/*.tar.gz - - publish-to-testpypi: - name: Publish Python 🐍 distribution 📦 to TestPyPI - needs: [build_sdist, test_wheels] - runs-on: ubuntu-latest - environment: - name: testpypi - url: https://test.pypi.org/project/wntr - permissions: - id-token: write - if: github.event_name == 'workflow_dispatch' - steps: - - name: Download wheel artifacts - uses: actions/download-artifact@v4 - with: - pattern: cibw-* - path: dist - merge-multiple: true - - name: Download SDist artifact - uses: actions/download-artifact@v4 - with: - name: sdist - path: dist - - name: Debug wheel files before upload - run: | - echo "=== Wheel files to upload ===" - ls -la dist/ - echo "=== Wheel file details ===" - for wheel in dist/*.whl; do - echo "File: $wheel" - file "$wheel" - unzip -l "$wheel" | head -10 - echo "---" - done - - name: Publish to TestPyPI - uses: pypa/gh-action-pypi-publish@release/v1 - with: - repository-url: https://test.pypi.org/legacy/ - user: __token__ - password: ${{ secrets.TEST_PYPI_API_TOKEN }} - verbose: true - - publish-to-pypi: - name: Publish Python 🐍 distribution 📦 to PyPI - needs: [build_sdist, test_wheels] - runs-on: ubuntu-latest - environment: - name: release - permissions: - id-token: write - if: github.event_name == 'push' && startsWith(github.ref, 'refs/tags') - steps: - - name: Download wheel artifacts - uses: actions/download-artifact@v4 - with: - pattern: cibw-* - path: dist - merge-multiple: true - - name: Download SDist artifact - uses: actions/download-artifact@v4 - with: - name: sdist - path: dist - - - uses: pypa/gh-action-pypi-publish@release/v1 - with: - user: __token__ - password: ${{ secrets.PYPI_WNTR_API_TOKEN }} - diff --git a/.github/workflows/publish_conda.yml b/.github/workflows/publish_conda.yml new file mode 100644 index 00000000..49dea830 --- /dev/null +++ b/.github/workflows/publish_conda.yml @@ -0,0 +1,54 @@ +# Manually triggered: open a conda-forge feedstock PR for a published PyPI release. +# Run this after confirming the version is live on https://pypi.org/project/wntr/. + +name: Publish to conda-forge + +on: + workflow_dispatch: + inputs: + version: + description: 'Version to release (e.g. 1.4.1) — must already be live on PyPI' + required: true + type: string + +jobs: + open-conda-forge-pr: + name: Open conda-forge feedstock PR + runs-on: ubuntu-latest + steps: + - name: Set up Python + uses: actions/setup-python@v5 + with: + python-version: '3.11' + + - name: Install Grayskull + run: pip install grayskull + + - name: Generate recipe with Grayskull + run: grayskull pypi wntr==${{ inputs.version }} + + - name: Clone feedstock fork + run: | + git clone https://x-access-token:${{ secrets.CONDA_FORGE_TOKEN }}@github.com/${{ vars.CONDA_FORGE_FORK_OWNER }}/wntr-feedstock.git + cd wntr-feedstock + git config user.email "github-actions[bot]@users.noreply.github.com" + git config user.name "github-actions[bot]" + git checkout -b release-${{ inputs.version }} + + - name: Patch feedstock recipe + run: python wntr-feedstock/recipe/patch_meta.py wntr/meta.yaml wntr-feedstock/recipe/meta.yaml + + - name: Push branch and open PR + env: + GH_TOKEN: ${{ secrets.CONDA_FORGE_TOKEN }} + run: | + cd wntr-feedstock + git add recipe/meta.yaml + git commit -m "Update WNTR to ${{ inputs.version }}" + git push origin release-${{ inputs.version }} + + gh pr create \ + --repo conda-forge/wntr-feedstock \ + --head ${{ vars.CONDA_FORGE_FORK_OWNER }}:release-${{ inputs.version }} \ + --title "Update WNTR to ${{ inputs.version }}" \ + --body "" diff --git a/.github/workflows/publish_pypi.yml b/.github/workflows/publish_pypi.yml new file mode 100644 index 00000000..c8108b9c --- /dev/null +++ b/.github/workflows/publish_pypi.yml @@ -0,0 +1,37 @@ +# Triggered on version tag push: build wheels, full wheel test matrix, publish to PyPI. +# Tests are expected to have already passed on main before tagging. +name: Publish to PyPI + +on: + push: + tags: + - '*' + +jobs: + wheels: + name: Build and Test Wheels + uses: ./.github/workflows/build_test_wheels.yml + + publish-to-pypi: + name: Publish to PyPI + needs: [wheels] + runs-on: ubuntu-latest + environment: + name: release + url: https://pypi.org/project/wntr/ + permissions: + id-token: write + steps: + - uses: actions/download-artifact@v4 + with: + pattern: cibw-wheels-* + path: dist + merge-multiple: true + - uses: actions/download-artifact@v4 + with: + name: sdist + path: dist + - uses: pypa/gh-action-pypi-publish@release/v1 + with: + user: __token__ + password: ${{ secrets.PYPI_WNTR_API_TOKEN }} diff --git a/.github/workflows/quick_check.yml b/.github/workflows/quick_check.yml deleted file mode 100644 index 7a9ae0ce..00000000 --- a/.github/workflows/quick_check.yml +++ /dev/null @@ -1,39 +0,0 @@ -# This workflow will install Python dependencies, run tests and lint with a single version of Python -# For more information see: https://help.github.com/actions/language-and-framework-guides/using-python-with-github-actions - -name: quick-check - -on: - push: - branches: - - '**' - pull_request: - branches: - - '**' - -jobs: - test: - strategy: - matrix: - python-version: ['3.11', '3.13'] - fail-fast: false - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v2 - - name: Set up Python ${{ matrix.python-version }} - uses: actions/setup-python@v4 - with: - python-version: ${{ matrix.python-version }} - - name: Install packages - run: | - python -m pip install --upgrade pip - pip install -e .[optional,test] - - name: Run tests and coverage (unittests plus doctests) - env: - OMIT: "'*/tests/*','*/extensions/*','*/sim/network_isolation/network_isolation.py','*/sim/aml/evaluator.py'" - run: | - coverage run --source=wntr --omit=$OMIT -m pytest -m "not time_consuming and not extensions" --ignore=wntr/extensions --doctest-modules --doctest-glob="*.rst" wntr - coverage run --source=wntr --omit=$OMIT --append -m pytest --doctest-glob="*.rst" --ignore-glob="*/extensions/*.rst" documentation - coverage report --fail-under=70 - # coverage run --source=wntr --omit="*/tests/*" --append -m pytest --doctest-glob="*.rst" documentation - diff --git a/.github/workflows/extensions.yml b/.github/workflows/test_extensions.yml similarity index 92% rename from .github/workflows/extensions.yml rename to .github/workflows/test_extensions.yml index b7fd98b4..ccc13187 100644 --- a/.github/workflows/extensions.yml +++ b/.github/workflows/test_extensions.yml @@ -1,7 +1,7 @@ # This workflow will install Python dependencies, run tests and lint with a single version of Python # For more information see: https://help.github.com/actions/language-and-framework-guides/using-python-with-github-actions -name: extensions +name: Test Extensions on: push: @@ -12,7 +12,8 @@ on: - '**' jobs: - test: + test: + name: Test Extensions (${{ matrix.python-version }}) strategy: matrix: python-version: ['3.10', '3.11', '3.12', '3.13'] diff --git a/.github/workflows/test_repository.yml b/.github/workflows/test_repository.yml new file mode 100644 index 00000000..8bcc8f7b --- /dev/null +++ b/.github/workflows/test_repository.yml @@ -0,0 +1,111 @@ +# Tests editable install (`pip install -e .`), full OS/Python matrix, coverage, Coveralls. + +name: Test Repository + +on: + push: + branches: [ main ] + pull_request: + branches: [ main ] + schedule: + - cron: '0 0 1 * *' + +jobs: + run_coverage: + name: Run Coverage (${{ matrix.python-version }}, ${{ matrix.os }}) + runs-on: ${{ matrix.os }} + strategy: + matrix: + python-version: ['3.10', '3.11', '3.12', '3.13'] + os: [ubuntu-latest, windows-latest, macos-15-intel, macos-latest] + fail-fast: false + steps: + - uses: actions/checkout@v4 + - name: Set up Python ${{ matrix.python-version }} + uses: actions/setup-python@v5 + with: + python-version: ${{ matrix.python-version }} + - name: Set mpl backend on windows + if: ${{ matrix.os == 'windows-latest' }} + run: echo "MPLBACKEND=Agg" >> $env:GITHUB_ENV + shell: pwsh + - if: ${{ matrix.os == 'macos-latest' || matrix.os == 'macos-15-intel'}} + run: | + brew reinstall libomp + - name: Install dependencies + run: | + python --version + python -m pip install --upgrade pip + python -m pip install -e .[optional,test] + - name: Run Tests + if: ${{ matrix.os != 'macos-latest' }} + env: + OMIT: "'*/tests/*','*/extensions/*','*/sim/network_isolation/network_isolation.py','*/sim/aml/evaluator.py'" + COVERAGE_FILE: .coverage.${{ matrix.python-version }}.${{ matrix.os }} + run: | + coverage erase + coverage run --context=${{ matrix.os }}.py${{ matrix.python-version }} --source=wntr --omit=$OMIT -m pytest -m "not extensions" --ignore=wntr/extensions --doctest-modules --doctest-glob="*.rst" wntr + coverage run --context=${{ matrix.os }}.py${{ matrix.python-version }} --source=wntr --omit=$OMIT --append -m pytest --doctest-glob="*.rst" --ignore-glob="*/extensions/*.rst" documentation + - name: Run Tests (ARM-processor) + if: ${{ matrix.os == 'macos-latest'}} + # doctests are not flexible enough to skip EPANET=v2.0 errors on ARM processor, so do not run doctests on ARM system + run: | + coverage erase + coverage run --context=${{ matrix.os }}.py${{ matrix.python-version }} --source=wntr --omit="*/tests/*","*/sim/network_isolation/network_isolation.py","*/sim/aml/evaluator.py" -m pytest --doctest-modules --doctest-glob="*.rst" wntr + env: + COVERAGE_FILE: .coverage.${{ matrix.python-version }}.${{ matrix.os }} + - name: Save coverage + uses: actions/upload-artifact@v4 + with: + name: .coverage.${{ matrix.python-version }}.${{ matrix.os }} + path: .coverage.${{ matrix.python-version }}.${{ matrix.os }} + include-hidden-files: true + + combine_reports: + name: Combine Coverage and Upload to Coveralls + needs: [ run_coverage ] + runs-on: ubuntu-latest + steps: + - name: Set up Python + uses: actions/setup-python@v5 + with: + python-version: 3.11 + - uses: actions/checkout@v4 + - name: Install coverage + run: | + python -m pip install --upgrade pip + python -m pip install -e .[optional,test] + pip install coveralls + - name: Download coverage artifacts from test matrix + uses: actions/download-artifact@v4 + with: + pattern: .coverage.*.ubuntu-latest # coverage from other OS cause problems + - name: Setup coverage and combine reports + run: coverage combine .coverage.*.ubuntu-latest + - name: Create coverage report + run: | + echo "[paths]" > .coveragerc + echo "source = " >> .coveragerc + echo " wntr/" >> .coveragerc + echo " wntr\\" >> .coveragerc + echo " D:\\a\\WNTR\\WNTR\\wntr" >> .coveragerc + echo " /home/runner/work/WNTR/WNTR/wntr" >> .coveragerc + echo " /Users/runner/work/WNTR/WNTR/wntr" >> .coveragerc + echo " ${{ github.workspace }}/wntr" >> .coveragerc + coverage report + coverage json --pretty-print + coverage html --show-contexts + - name: Save coverage JSON + uses: actions/upload-artifact@v4 + with: + name: coverage-json + path: coverage.json + - name: Save coverage html + uses: actions/upload-artifact@v4 + with: + name: coverage-html + path: htmlcov + - name: Push to coveralls + run: coveralls --service=github --rcfile=.coveragerc + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/README.md b/README.md index 1371a925..86d4705a 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,7 @@
-[![GitHub CI](https://github.com/USEPA/WNTR/actions/workflows/build_tests.yml/badge.svg)](https://github.com/USEPA/WNTR/actions/workflows/build_tests.yml) +[![GitHub CI](https://github.com/USEPA/WNTR/actions/workflows/test_repository.yml/badge.svg)](https://github.com/USEPA/WNTR/actions/workflows/test_repository.yml) [![Coverage Status](https://coveralls.io/repos/github/USEPA/WNTR/badge.svg?branch=main)](https://coveralls.io/github/USEPA/WNTR?branch=main) [![Documentation Status](https://github.com/USEPA/WNTR/actions/workflows/build_deploy_pages.yml/badge.svg)](https://github.com/usepa/wntr/actions/workflows/build_deploy_pages.yml) [![GitHub contributors](https://img.shields.io/github/contributors/USEPA/WNTR.svg)](https://github.com/USEPA/WNTR/graphs/contributors) diff --git a/documentation/developers.rst b/documentation/developers.rst index dad8da7f..4637d08a 100644 --- a/documentation/developers.rst +++ b/documentation/developers.rst @@ -136,7 +136,7 @@ Extensions adhere to the following file structure: 2) a point of contact (developer name and GitHub username), and 3) supporting documentation and examples (using doctest). A link to the documentation should also be added to ``documentation\extensions.rst`` and ``documentation\userguide.rst``. -* **Testing**: Tests are run using the `extensions workflow `_. +* **Testing**: Tests are run using the `test_extensions workflow `_. Tests reside in a file named ``wntr\tests\extensions\test_.py``. Tests should be marked ``@pytest.mark.extensions``. * **Requirements**: If the extension requires packages beyond WNTR's core dependencies, add a corresponding entry to diff --git a/documentation/extensions.rst b/documentation/extensions.rst index 7101f1c6..5aa8b7de 100644 --- a/documentation/extensions.rst +++ b/documentation/extensions.rst @@ -8,8 +8,8 @@ Extensions ========== |extensions| -.. |extensions| image:: https://github.com/USEPA/WNTR/actions/workflows/extensions.yml/badge.svg - :target: https://github.com/USEPA/WNTR/actions/workflows/extensions.yml +.. |extensions| image:: https://github.com/USEPA/WNTR/actions/workflows/test_extensions.yml/badge.svg + :target: https://github.com/USEPA/WNTR/actions/workflows/test_extensions.yml WNTR extensions are intended to house beta and self-contained functionality that adds to WNTR, but is currently not part of core WNTR development. The extensions should be designed for a wide audience. diff --git a/documentation/installation.rst b/documentation/installation.rst index eea8aef8..159f7dc4 100644 --- a/documentation/installation.rst +++ b/documentation/installation.rst @@ -236,7 +236,7 @@ the shared object files can be downloaded from WNTR GitHub Actions using the fol python -m pip install -e . --no-build pip install -r requirements.txt -* Select the latest GitHub Actions build_tests that uses the main branch from https://github.com/USEPA/WNTR/actions/workflows/build_tests.yml +* Select the latest successful run of the wheel workflow on the main branch from https://github.com/USEPA/WNTR/actions/workflows/build_test_wheels.yml * Scroll down to "Artifacts" * Download the wheel that matches the desired operating system and Python version (for example, wntr_3.9_windows-latest.whl) * Unzip the wheel and locate the following files (which are named according to the operating system and Python version)