From 4cae0d3e7da61c81f36b44385ddfc41df7c84a93 Mon Sep 17 00:00:00 2001 From: Henry Schreiner Date: Fri, 15 Nov 2024 18:25:57 -0500 Subject: [PATCH] WIP: run on pushes Signed-off-by: Henry Schreiner --- .github/workflows/release_wheel_creation.yml | 124 +-- .github/workflows/test_branches.yml | 870 ------------------ .github/workflows/test_pr_and_main.yml | 915 ------------------- .github/workflows/typos.toml | 74 -- 4 files changed, 2 insertions(+), 1981 deletions(-) delete mode 100644 .github/workflows/test_branches.yml delete mode 100644 .github/workflows/test_pr_and_main.yml delete mode 100644 .github/workflows/typos.toml diff --git a/.github/workflows/release_wheel_creation.yml b/.github/workflows/release_wheel_creation.yml index d439dafaf0a..59d5ed6a527 100644 --- a/.github/workflows/release_wheel_creation.yml +++ b/.github/workflows/release_wheel_creation.yml @@ -2,8 +2,6 @@ name: Pyomo Release Distribution Creation on: push: - tags: - - '*' workflow_dispatch: inputs: git-ref: @@ -20,32 +18,20 @@ jobs: name: Build wheels (${{ matrix.wheel-version }}) on ${{ matrix.os }} for native and cross-compiled architecture runs-on: ${{ matrix.os }} strategy: - fail-fast: true + fail-fast: false matrix: os: [ubuntu-22.04, windows-latest, macos-latest] arch: [all] - wheel-version: ['cp38*', 'cp39*', 'cp310*', 'cp311*', 'cp312*'] - + wheel-version: ['cp39*', 'cp312*'] include: - - wheel-version: 'cp38*' - TARGET: 'py38' - GLOBAL_OPTIONS: "--with-cython --with-distributable-extensions" - wheel-version: 'cp39*' TARGET: 'py39' GLOBAL_OPTIONS: "--with-cython --with-distributable-extensions" - - wheel-version: 'cp310*' - TARGET: 'py310' - GLOBAL_OPTIONS: "--with-cython --with-distributable-extensions" - - wheel-version: 'cp311*' - TARGET: 'py311' - GLOBAL_OPTIONS: "--without-cython --with-distributable-extensions" - wheel-version: 'cp312*' TARGET: 'py312' GLOBAL_OPTIONS: "--without-cython --with-distributable-extensions" exclude: - - wheel-version: 'cp311*' - os: windows-latest - wheel-version: 'cp312*' os: windows-latest @@ -70,109 +56,3 @@ jobs: path: dist/*.whl overwrite: true - alternative_wheels: - name: Build wheels (${{ matrix.wheel-version }}) on ${{ matrix.os }} for aarch64 - runs-on: ${{ matrix.os }} - strategy: - matrix: - os: [ubuntu-22.04] - arch: [all] - wheel-version: ['cp38*', 'cp39*', 'cp310*', 'cp311*', 'cp312*'] - - include: - - wheel-version: 'cp38*' - TARGET: 'py38' - GLOBAL_OPTIONS: "--with-cython --with-distributable-extensions" - - wheel-version: 'cp39*' - TARGET: 'py39' - GLOBAL_OPTIONS: "--with-cython --with-distributable-extensions" - - wheel-version: 'cp310*' - TARGET: 'py310' - GLOBAL_OPTIONS: "--with-cython --with-distributable-extensions" - - wheel-version: 'cp311*' - TARGET: 'py311' - GLOBAL_OPTIONS: "--without-cython --with-distributable-extensions" - - wheel-version: 'cp312*' - TARGET: 'py312' - GLOBAL_OPTIONS: "--without-cython --with-distributable-extensions" - steps: - - uses: actions/checkout@v4 - - name: Set up QEMU - if: runner.os == 'Linux' - uses: docker/setup-qemu-action@v3 - with: - platforms: all - - name: Build wheels - uses: pypa/cibuildwheel@v2.16.5 - with: - output-dir: dist - env: - CIBW_ARCHS_LINUX: "aarch64" - CIBW_BUILD: ${{ matrix.wheel-version }} - CIBW_SKIP: "*-musllinux*" - CIBW_BUILD_VERBOSITY: 1 - CIBW_BEFORE_BUILD: pip install cython pybind11 - CIBW_ENVIRONMENT: PYOMO_SETUP_ARGS="${{ matrix.GLOBAL_OPTIONS }}" - - uses: actions/upload-artifact@v4 - with: - name: alt_wheels-${{ matrix.os }}-${{ matrix.TARGET }} - path: dist/*.whl - overwrite: true - - pure_python: - name: pure_python_wheel - runs-on: ubuntu-latest - strategy: - matrix: - python-version: ['3.11'] - steps: - - uses: actions/checkout@v4 - - name: Set up Python ${{ matrix.python-version }} - uses: actions/setup-python@v5 - with: - python-version: ${{ matrix.python-version }} - - name: Install dependencies - run: | - python -m pip install --upgrade pip - pip install twine wheel setuptools pybind11 - - name: Build pure python wheel - run: | - python setup.py --without-cython sdist --format=gztar bdist_wheel - - name: Upload artifact - uses: actions/upload-artifact@v4 - with: - name: purepythonwheel - path: dist/*.whl - overwrite: true - - generictarball: - name: ${{ matrix.TARGET }} - runs-on: ${{ matrix.os }} - strategy: - fail-fast: false - matrix: - os: [ubuntu-latest] - include: - - os: ubuntu-latest - TARGET: generic_tarball - python-version: [3.8] - steps: - - uses: actions/checkout@v4 - - name: Set up Python ${{ matrix.python-version }} - uses: actions/setup-python@v5 - with: - python-version: ${{ matrix.python-version }} - - name: Install dependencies - run: | - python -m pip install --upgrade pip - pip install twine wheel setuptools pybind11 - - name: Build generic tarball - run: | - python setup.py --without-cython sdist --format=gztar - - name: Upload artifact - uses: actions/upload-artifact@v4 - with: - name: generictarball - path: dist - overwrite: true - diff --git a/.github/workflows/test_branches.yml b/.github/workflows/test_branches.yml deleted file mode 100644 index a4f2f8128e9..00000000000 --- a/.github/workflows/test_branches.yml +++ /dev/null @@ -1,870 +0,0 @@ -name: GitHub Branch CI - -on: - push: - branches-ignore: - - main - workflow_dispatch: - inputs: - git-ref: - description: Git Hash (Optional) - required: false - -concurrency: - group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }} - cancel-in-progress: true - -defaults: - run: - shell: bash -l {0} - -env: - PYTHONWARNINGS: ignore::UserWarning - PYTHON_CORE_PKGS: wheel - PYPI_ONLY: z3-solver linear-tree - PYPY_EXCLUDE: scipy numdifftools seaborn statsmodels linear-tree - CACHE_VER: v221013.1 - NEOS_EMAIL: tests@pyomo.org - SRC_REF: ${{ github.head_ref || github.ref }} - -jobs: - lint: - name: lint/style-and-typos - runs-on: ubuntu-latest - steps: - - name: Checkout Pyomo source - uses: actions/checkout@v4 - - name: Set up Python - uses: actions/setup-python@v5 - with: - python-version: '3.10' - - name: Black Formatting Check - run: | - # Note v24.4.1 fails due to a bug in the parser - pip install 'black!=24.4.1' - black . -S -C --check --diff --exclude examples/pyomobook/python-ch/BadIndent.py - - name: Spell Check - uses: crate-ci/typos@master - with: - config: ./.github/workflows/typos.toml - - name: URL Checker - uses: urlstechie/urlchecker-action@0.0.34 - with: - # A comma-separated list of file types to cover in the URL checks - file_types: .md,.rst,.py - # Choose whether to include file with no URLs in the prints. - print_all: false - # More verbose summary at the end of a run - verbose: true - # How many times to retry a failed request (defaults to 1) - retry_count: 3 - # Exclude Jenkins because it's behind a firewall; ignore RTD because - # a magically-generated string is triggering a failure - exclude_urls: https://pyomo-jenkins.sandia.gov/,https://pyomo.readthedocs.io/en/%s/errors.html - - - build: - name: ${{ matrix.TARGET }}/${{ matrix.python }}${{ matrix.other }} - runs-on: ${{ matrix.os }} - timeout-minutes: 120 - strategy: - fail-fast: false - matrix: - os: [ubuntu-latest] - python: ['3.12'] - other: [""] - category: [""] - - include: - - os: ubuntu-latest - python: '3.12' - TARGET: linux - PYENV: pip - - - os: macos-13 - python: '3.10' - TARGET: osx - PYENV: pip - - - os: windows-latest - python: 3.9 - TARGET: win - PYENV: conda - PACKAGES: glpk pytest-qt filelock - - - os: ubuntu-latest - python: '3.11' - other: /conda - skip_doctest: 1 - TARGET: linux - PYENV: conda - PACKAGES: pytest-qt - - - os: ubuntu-latest - python: '3.10' - other: /mpi - mpi: 3 - skip_doctest: 1 - TARGET: linux - PYENV: conda - PACKAGES: openmpi mpi4py - - - os: ubuntu-latest - python: '3.10' - other: /cython - setup_options: --with-cython - skip_doctest: 1 - TARGET: linux - PYENV: pip - PACKAGES: cython - - - os: windows-latest - python: 3.8 - other: /pip - skip_doctest: 1 - TARGET: win - PYENV: pip - - steps: - - name: Checkout Pyomo source - uses: actions/checkout@v4 - - - name: Configure job parameters - run: | - JOB="${{matrix.TARGET}}/${{matrix.python}}${{matrix.other}}" - echo "GHA_JOBNAME=$JOB" | sed 's|/|_|g' >> $GITHUB_ENV - if test -z "${{matrix.other}}"; then - echo "GHA_JOBGROUP=${{matrix.TARGET}}" >> $GITHUB_ENV - else - echo "GHA_JOBGROUP=other" >> $GITHUB_ENV - fi - # Note: pandas 1.0.3 causes gams 29.1.0 import to fail in python 3.8 - EXTRAS=tests - if test -z "${{matrix.slim}}"; then - EXTRAS="$EXTRAS,docs,optional" - fi - echo "EXTRAS=$EXTRAS" >> $GITHUB_ENV - PYTHON_PACKAGES="${{matrix.PACKAGES}}" - echo "PYTHON_PACKAGES=$PYTHON_PACKAGES" \ - | tr '\n' ' ' | sed 's/ \+/ /g' >> $GITHUB_ENV - - #- name: Pip package cache - # uses: actions/cache@v4 - # if: matrix.PYENV == 'pip' - # id: pip-cache - # with: - # path: cache/pip - # key: pip-${{env.CACHE_VER}}.0-${{runner.os}}-${{matrix.python}} - - #- name: OS package cache - # uses: actions/cache@v4 - # if: matrix.TARGET != 'osx' - # id: os-cache - # with: - # path: cache/os - # key: pkg-${{env.CACHE_VER}}.0-${{runner.os}} - - - name: TPL package download cache - uses: actions/cache@v4 - if: ${{ ! matrix.slim }} - id: download-cache - with: - path: cache/download - key: download-${{env.CACHE_VER}}.0-${{runner.os}} - - - name: Configure curl - run: | - CURLRC="$(cat < ${GITHUB_WORKSPACE}/.curlrc - echo "$CURLRC" > ${GITHUB_WORKSPACE}/_curlrc - echo "CURL_HOME=$GITHUB_WORKSPACE" >> $GITHUB_ENV - - - name: Update OSX - if: matrix.TARGET == 'osx' - run: | - mkdir -p ${GITHUB_WORKSPACE}/cache/os - export HOMEBREW_CACHE=${GITHUB_WORKSPACE}/cache/os - # Be cautious running brew update: it can break - # setup-python on OSX - # brew update - # - # Notes: - # - install glpk - # - pyodbc needs: gcc pkg-config unixodbc freetds - for pkg in bash pkg-config unixodbc freetds glpk ginac; do - brew list $pkg || brew install $pkg - done - - - name: Update Linux - if: matrix.TARGET == 'linux' - run: | - mkdir -p ${GITHUB_WORKSPACE}/cache/os - # Notes: - # - install glpk - # - ipopt needs: libopenblas-dev gfortran liblapack-dev - sudo apt-get -o Dir::Cache=${GITHUB_WORKSPACE}/cache/os \ - install libopenblas-dev gfortran liblapack-dev glpk-utils \ - libginac-dev - sudo chmod -R 777 ${GITHUB_WORKSPACE}/cache/os - - - name: Update Windows - if: matrix.TARGET == 'win' - run: | - echo "SETUPTOOLS_USE_DISTUTILS=local" >> $GITHUB_ENV - - - name: Set up Python ${{ matrix.python }} - if: matrix.PYENV == 'pip' - uses: actions/setup-python@v5 - with: - python-version: ${{ matrix.python }} - - - name: Set up Miniconda Python ${{ matrix.python }} - if: matrix.PYENV == 'conda' - uses: conda-incubator/setup-miniconda@v3 - with: - auto-update-conda: false - python-version: ${{ matrix.python }} - - # This is necessary for qt (UI) tests; the package utilized here does not - # have support for OSX. - - name: Set up UI testing infrastructure - if: ${{ matrix.TARGET != 'osx' }} - uses: pyvista/setup-headless-display-action@v2 - with: - qt: true - pyvista: false - - # GitHub actions is very fragile when it comes to setting up various - # Python interpreters, expecially the setup-miniconda interface. - # Per the setup-miniconda documentation, it is important to always - # invoke bash as a login shell ('shell: bash -l {0}') so that the - # conda environment is properly activated. However, running within - # a login shell appears to foul up the link to python from - # setup-python. Further, we have anecdotal evidence that - # subprocesses invoked through $(python -c ...) and `python -c ...` - # will not pick up the python activated by setup-python on OSX. - # - # Our solution is to define a PYTHON_EXE environment variable that - # can be explicitly called within subprocess calls to reach the - # correct interpreter. Note that we must explicitly run in a *non* - # login shell to set up the environment variable for the - # setup-python environments. - - - name: Install Python Packages (pip) - if: matrix.PYENV == 'pip' - shell: bash # DO NOT REMOVE: see note above - run: | - python -c 'import sys;print(sys.executable)' - python -m pip install --cache-dir cache/pip --upgrade pip - python -m pip install --cache-dir cache/pip setuptools - PYOMO_DEPENDENCIES=`python setup.py dependencies \ - --extras "$EXTRAS" | tail -1` - PACKAGES="${PYTHON_CORE_PKGS} ${PYTHON_PACKAGES} ${PYOMO_DEPENDENCIES} " - if [[ ${{matrix.python}} == pypy* ]]; then - EXCLUDE="$PYPY_EXCLUDE $EXCLUDE" - fi - EXCLUDE=`echo "$EXCLUDE" | xargs` - if test -n "$EXCLUDE"; then - for WORD in $EXCLUDE; do - PACKAGES=${PACKAGES//$WORD / } - done - fi - python -m pip install --cache-dir cache/pip ${PACKAGES} - python -m pip install --cache-dir cache/pip pymysql || \ - python -m pip install --cache-dir cache/pip pymysql - if test -z "${{matrix.slim}}"; then - python -m pip install --cache-dir cache/pip cplex docplex \ - || echo "WARNING: CPLEX Community Edition is not available" - python -m pip install --cache-dir cache/pip gurobipy==10.0.3 \ - || echo "WARNING: Gurobi is not available" - python -m pip install --cache-dir cache/pip xpress \ - || echo "WARNING: Xpress Community Edition is not available" - python -m pip install --cache-dir cache/pip maingopy \ - || echo "WARNING: MAiNGO is not available" - if [[ ${{matrix.python}} == pypy* ]]; then - echo "skipping wntr for pypy" - else - python -m pip install wntr \ - || echo "WARNING: WNTR is not available" - fi - fi - python -c 'import sys; print("PYTHON_EXE=%s" \ - % (sys.executable,))' >> $GITHUB_ENV - echo "" - echo "Final pip environment:" - python -m pip list | sed 's/^/ /' - - - name: Install Python packages (conda) - if: matrix.PYENV == 'conda' - run: | - # Set up environment - conda config --set always_yes yes - conda config --set auto_update_conda false - conda config --remove channels defaults - conda config --append channels nodefaults - conda config --append channels conda-forge - # Try to install mamba - conda install --update-deps -q -y -n base conda-libmamba-solver \ - || MAMBA_FAILED=1 - if test -z "$MAMBA_FAILED"; then - echo "*** Activating the mamba environment solver ***" - conda config --set solver libmamba - fi - # Add the rest of the channels - conda config --append channels gurobi - conda config --append channels ibmdecisionoptimization - conda config --append channels fico-xpress - # Print environment info - echo "*** CONDA environment: ***" - conda info - conda config --show-sources - conda config --show channels - conda list --show-channel-urls - which python - python --version - # Note: some pypi packages are not available through conda - PYOMO_DEPENDENCIES=`python setup.py dependencies \ - --extras "$EXTRAS" | tail -1` - PACKAGES="${PYTHON_CORE_PKGS} ${PYTHON_PACKAGES} ${PYOMO_DEPENDENCIES} " - if [[ ${{matrix.python}} == pypy* ]]; then - EXCLUDE="$PYPY_EXCLUDE $EXCLUDE" - fi - # HACK: Remove problem packages on conda+Linux - if test "${{matrix.TARGET}}" == linux; then - EXCLUDE="casadi numdifftools $EXCLUDE" - fi - EXCLUDE=`echo "$EXCLUDE" | xargs` - if test -n "$EXCLUDE"; then - for WORD in $EXCLUDE; do - PACKAGES=${PACKAGES//$WORD / } - done - fi - for PKG in $PACKAGES; do - if [[ " $PYPI_ONLY " == *" $PKG "* ]]; then - PYPI_DEPENDENCIES="$PYPI_DEPENDENCIES $PKG" - else - CONDA_DEPENDENCIES="$CONDA_DEPENDENCIES $PKG" - fi - done - echo "" - echo "*** Install Pyomo dependencies ***" - # Note: this will fail the build if any installation fails (or - # possibly if it outputs messages to stderr) - conda install --update-deps -q -y $CONDA_DEPENDENCIES - if test -z "${{matrix.slim}}"; then - PYVER=$(echo "py${{matrix.python}}" | sed 's/\.//g') - echo "Installing for $PYVER" - for PKG in 'cplex>=12.10' docplex 'gurobi=10.0.3' xpress cyipopt pymumps scip; do - echo "" - echo "*** Install $PKG ***" - # conda can literally take an hour to determine that a - # package is not available. Perform a quick search to see - # if the package is available for this interpreter before - # attempting an install. - # NOTE: conda search will attempt approximate matches. - _PKGLIST=$(conda search -f "$PKG") || echo "Package $PKG not found" - echo "$_PKGLIST" - _BASE=$(echo "$PKG" | sed 's/[=<>].*//') - _BUILDS=$(echo "$_PKGLIST" | grep "^$_BASE " \ - | sed -r 's/\s+/ /g' | cut -d\ -f3) || echo "" - if test -n "$_BUILDS"; then - _ISPY=$(echo "$_BUILDS" | grep "^py") \ - || echo "INFO: No python build detected." - _PYOK=$(echo "$_BUILDS" | grep -E "^($PYVER|pyh)") \ - || echo "INFO: No python build matching $PYVER detected." - if test -z "$_ISPY" -o -n "$_PYOK"; then - echo "" - echo "... INSTALLING $PKG" - conda install -y "$PKG" || _BUILDS="" - fi - fi - if test -z "$_BUILDS"; then - echo "WARNING: $PKG is not available" - fi - done - fi - # Re-try Pyomo (optional) dependencies with pip - if test -n "$PYPI_DEPENDENCIES"; then - python -m pip install --cache-dir cache/pip $PYPI_DEPENDENCIES - fi - # remember this python interpreter - python -c 'import sys; print("PYTHON_EXE=%s" \ - % (sys.executable,))' >> $GITHUB_ENV - # - # conda activate puts itself first in the PATH, which overrides - # any paths we add through GITHUB_PATH. We will update .profile - # to move the local runner paths back to the front (before conda). - for profile in $HOME/.profile $HOME/.bash_profile; do - if test ! -e $profile; then - continue - fi - echo '' >> $profile - echo 'export PATH=`echo "$PATH" \ - | tr ":" "\\n" | grep runner | tr "\n" ":"`:`echo "$PATH" \ - | tr ":" "\\n" | grep -v runner | tr "\n" ":"`' >> $profile - done - echo "" - echo "Final conda environment:" - conda list | sed 's/^/ /' - - - name: Setup TPL package directories - run: | - TPL_DIR="${GITHUB_WORKSPACE}/cache/tpl" - mkdir -p "$TPL_DIR" - DOWNLOAD_DIR="${GITHUB_WORKSPACE}/cache/download" - mkdir -p "$DOWNLOAD_DIR" - echo "TPL_DIR=$TPL_DIR" >> $GITHUB_ENV - echo "DOWNLOAD_DIR=$DOWNLOAD_DIR" >> $GITHUB_ENV - - - name: Install Ipopt - if: ${{ ! matrix.slim }} - run: | - IPOPT_DIR=$TPL_DIR/ipopt - echo "$IPOPT_DIR" >> $GITHUB_PATH - echo "LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$IPOPT_DIR" >> $GITHUB_ENV - mkdir -p $IPOPT_DIR - IPOPT_TAR=${DOWNLOAD_DIR}/ipopt.tar.gz - if test ! -e $IPOPT_TAR; then - echo "...downloading Ipopt" - if test "${{matrix.TARGET}}" == osx; then - echo "IDAES Ipopt not available on OSX" - exit 0 - fi - URL=https://github.com/IDAES/idaes-ext - RELEASE=$(curl --max-time 150 --retry 8 \ - -L -s -H 'Accept: application/json' ${URL}/releases/latest) - VER=$(echo $RELEASE | sed -e 's/.*"tag_name":"\([^"]*\)".*/\1/') - URL=${URL}/releases/download/$VER - if test "${{matrix.TARGET}}" == linux; then - curl --max-time 150 --retry 8 \ - -L $URL/idaes-solvers-ubuntu2004-x86_64.tar.gz \ - > $IPOPT_TAR - else - curl --max-time 150 --retry 8 \ - -L $URL/idaes-solvers-windows-x86_64.tar.gz \ - $URL/idaes-lib-windows-x86_64.tar.gz > $IPOPT_TAR - fi - fi - cd $IPOPT_DIR - tar -xzi < $IPOPT_TAR - echo "" - echo "$IPOPT_DIR" - ls -l $IPOPT_DIR - - - name: Install GAMS - if: ${{ ! matrix.slim }} - # We install using Powershell because the GAMS installer hangs - # when launched from bash on Windows - shell: pwsh - run: | - $GAMS_DIR = "${env:TPL_DIR}/gams" - echo "$GAMS_DIR" | ` - Out-File -FilePath $env:GITHUB_PATH -Encoding utf8 -Append - echo "LD_LIBRARY_PATH=${env:LD_LIBRARY_PATH}:$GAMS_DIR" ` - Out-File -FilePath $env:GITHUB_ENV -Encoding utf8 -Append - echo "DYLD_LIBRARY_PATH=${env:DYLD_LIBRARY_PATH}:$GAMS_DIR" ` - Out-File -FilePath $env:GITHUB_ENV -Encoding utf8 -Append - $INSTALLER = "${env:DOWNLOAD_DIR}/gams_install.exe" - # We are pinning to 29.1.0 because a license is required for - # versions after this in order to run in demo mode. - $URL = "https://d37drm4t2jghv5.cloudfront.net/distributions/29.1.0" - if ( "${{matrix.TARGET}}" -eq "win" ) { - $URL = "$URL/windows/windows_x64_64.exe" - } elseif ( "${{matrix.TARGET}}" -eq "osx" ) { - $URL = "$URL/macosx/osx_x64_64_sfx.exe" - } else { - $URL = "$URL/linux/linux_x64_64_sfx.exe" - } - if (-not (Test-Path "$INSTALLER" -PathType Leaf)) { - echo "...downloading GAMS" - Invoke-WebRequest -Uri "$URL" -OutFile "$INSTALLER" ` - -RetryIntervalSec 30 -MaximumRetryCount 8 -TimeoutSec 150 - } - echo "...installing GAMS" - if ( "${{matrix.TARGET}}" -eq "win" ) { - Start-Process -FilePath "$INSTALLER" -ArgumentList ` - "/SP- /NORESTART /VERYSILENT /DIR=$GAMS_DIR /NOICONS" ` - -Wait - } else { - chmod 777 $INSTALLER - Start-Process -FilePath "$INSTALLER" -ArgumentList ` - "-q -d $GAMS_DIR" -Wait - mv $GAMS_DIR/*/* $GAMS_DIR/. - } - echo "" - echo "$GAMS_DIR" - ls -l $GAMS_DIR - - - name: Install GAMS Python bindings - if: ${{ ! matrix.slim }} - run: | - GAMS_DIR="${env:TPL_DIR}/gams" - py_ver=$($PYTHON_EXE -c 'import sys;v="_%s%s" % sys.version_info[:2] \ - ;print(v if v != "_27" else "")') - if test -e $GAMS_DIR/apifiles/Python/api$py_ver; then - echo "Installing GAMS Python bindings" - pushd $GAMS_DIR/apifiles/Python/api$py_ver - $PYTHON_EXE setup.py install - popd - fi - - - name: Install BARON - if: ${{ ! matrix.slim }} - shell: pwsh - run: | - $BARON_DIR = "${env:TPL_DIR}/baron" - echo "$BARON_DIR" | ` - Out-File -FilePath $env:GITHUB_PATH -Encoding utf8 -Append - $URL = "https://minlp.com/downloads/xecs/baron/current/" - if ( "${{matrix.TARGET}}" -eq "win" ) { - $INSTALLER = "${env:DOWNLOAD_DIR}/baron_install.exe" - $URL += "baron-win64.exe" - } elseif ( "${{matrix.TARGET}}" -eq "osx" ) { - $INSTALLER = "${env:DOWNLOAD_DIR}/baron_install.zip" - $URL += "baron-osx64.zip" - } else { - $INSTALLER = "${env:DOWNLOAD_DIR}/baron_install.zip" - $URL += "baron-lin64.zip" - } - if (-not (Test-Path "$INSTALLER" -PathType Leaf)) { - echo "...downloading BARON ($URL)" - Invoke-WebRequest -Uri "$URL" -OutFile "$INSTALLER" ` - -RetryIntervalSec 30 -MaximumRetryCount 8 -TimeoutSec 150 - } - echo "...installing BARON" - if ( "${{matrix.TARGET}}" -eq "win" ) { - Start-Process -FilePath "$INSTALLER" -ArgumentList ` - "/SP- /NORESTART /VERYSILENT /DIR=$BARON_DIR /NOICONS" ` - -Wait - } else { - unzip -q $INSTALLER - mv baron-* $BARON_DIR - } - echo "" - echo "$BARON_DIR" - ls -l $BARON_DIR - - - name: Install GJH_ASL_JSON - if: ${{ ! matrix.slim && matrix.TARGET != 'win' }} - run: | - GJH_DIR="$TPL_DIR/gjh" - echo "${GJH_DIR}" >> $GITHUB_PATH - INSTALL_DIR="${DOWNLOAD_DIR}/gjh" - if test ! -e "$INSTALL_DIR/bin"; then - mkdir -p "$INSTALL_DIR" - INSTALLER="$INSTALL_DIR/gjh_asl_json.zip" - URL="https://codeload.github.com/ghackebeil/gjh_asl_json/zip/master" - curl --max-time 150 --retry 8 -L $URL > $INSTALLER - cd $INSTALL_DIR - unzip -q $INSTALLER - cd gjh_asl_json-master/Thirdparty - ./get.ASL - cd .. - make - mv bin "$INSTALL_DIR/bin" - fi - cp -rp "$INSTALL_DIR/bin" "$GJH_DIR" - echo "" - echo "$GJH_DIR" - ls -l $GJH_DIR - - - name: Install Pyomo - run: | - echo "" - echo "Clone Pyomo-model-libraries..." - URL=https://github.com/Pyomo/pyomo-model-libraries.git - git clone -b ${SRC_REF##*/} $URL || git clone -b main $URL - echo "" - echo "Install Pyomo..." - echo "" - $PYTHON_EXE setup.py develop ${{matrix.setup_options}} - echo "" - echo "Set custom PYOMO_CONFIG_DIR" - echo "" - echo "PYOMO_CONFIG_DIR=${GITHUB_WORKSPACE}/config" >> $GITHUB_ENV - - # this has to be done after Pyomo is installed because highspy - # depends on pyomo's find_library function - - name: Install HiGHS - if: ${{ ! matrix.slim }} - shell: bash - run: | - $PYTHON_EXE -m pip install --cache-dir cache/pip highspy \ - || echo "WARNING: highspy is not available" - - - name: Set up coverage tracking - run: | - if test "${{matrix.TARGET}}" == win; then - COVERAGE_BASE=${GITHUB_WORKSPACE}\\.cover - else - COVERAGE_BASE=${GITHUB_WORKSPACE}/.cover - fi - COVERAGE_RC=${COVERAGE_BASE}_rc - echo "COVERAGE_RCFILE=$COVERAGE_RC" >> $GITHUB_ENV - echo "COVERAGE_PROCESS_START=$COVERAGE_RC" >> $GITHUB_ENV - cp ${GITHUB_WORKSPACE}/.coveragerc ${COVERAGE_RC} - echo "data_file=${COVERAGE_BASE}age" >> ${COVERAGE_RC} - SITE_PACKAGES=$($PYTHON_EXE -c \ - "import sysconfig; print(sysconfig.get_path('purelib'))") - echo "Python site-packages: $SITE_PACKAGES" - echo 'import coverage; coverage.process_startup()' \ - > ${SITE_PACKAGES}/run_coverage_at_startup.pth - - - name: Download and install extensions - if: ${{ ! matrix.slim }} - run: | - echo "" - echo "Pyomo download-extensions" - echo "" - pyomo download-extensions || exit 1 - echo "" - echo "Pyomo build-extensions" - echo "" - pyomo build-extensions --parallel 2 - - - name: Report pyomo plugin information - run: | - echo "$PATH" - pyomo help --solvers || exit 1 - pyomo help --transformations || exit 1 - pyomo help --writers || exit 1 - - - name: Run Pyomo tests - if: matrix.mpi == 0 - run: | - $PYTHON_EXE -m pytest -v \ - -W ignore::Warning ${{matrix.category}} \ - pyomo `pwd`/pyomo-model-libraries \ - `pwd`/examples `pwd`/doc --junitxml="TEST-pyomo.xml" - - - name: Run Pyomo MPI tests - if: matrix.mpi != 0 - run: | - # Manually invoke the DAT parser so that parse_table_datacmds.py - # is fully generated by a single process before invoking MPI - $PYTHON_EXE -c "from pyomo.dataportal.parse_datacmds import \ - parse_data_commands; parse_data_commands(data='')" - # Note: if we are testing with openmpi, add '--oversubscribe' - mpirun -np ${{matrix.mpi}} -oversubscribe pytest -v \ - --junit-xml=TEST-pyomo-mpi.xml \ - -m "mpi" -W ignore::Warning \ - pyomo `pwd`/pyomo-model-libraries - - - name: Run documentation tests - if: matrix.skip_doctest == 0 - run: | - make -C doc/OnlineDocs doctest -d - - - name: Process code coverage report - run: | - coverage combine - coverage report -i - coverage xml -i - - - name: Record build artifacts - uses: actions/upload-artifact@v4 - with: - name: ${{github.job}}_${{env.GHA_JOBGROUP}}-${{env.GHA_JOBNAME}} - path: | - .coverage - coverage.xml - # In general, do not record test results as artifacts to - # manage total artifact storage - # TEST-*.xml - - - bare-python-env: - name: linux/3.8/bare-env - runs-on: ubuntu-latest - timeout-minutes: 10 - steps: - - name: Checkout Pyomo source - uses: actions/checkout@v4 - - - name: Set up Python 3.8 - uses: actions/setup-python@v5 - with: - python-version: 3.8 - - - name: Install Pyomo - run: | - echo "" - echo "Install Pyomo..." - echo "" - python setup.py develop - echo "" - echo "Set custom PYOMO_CONFIG_DIR" - echo "" - echo "PYOMO_CONFIG_DIR=${GITHUB_WORKSPACE}/config" >> $GITHUB_ENV - - - name: Report pyomo plugin information - run: | - echo "$PATH" - pyomo help --solvers || exit 1 - pyomo help --transformations || exit 1 - pyomo help --writers || exit 1 - - - name: Run Pyomo standalone test - run: | - echo "" - echo "Running standalone Pyomo test" - echo "" - python `pwd`/pyomo/environ/tests/standalone_minimal_pyomo_driver.py \ - || exit 1 - - - cover: - name: process-coverage-${{ matrix.TARGET }} - needs: build - if: ${{ false }} # turn off for branches - runs-on: ${{ matrix.os }} - timeout-minutes: 10 - strategy: - fail-fast: false - matrix: - os: [ubuntu-latest, macos-13, windows-latest] - - include: - - os: ubuntu-latest - TARGET: linux - - os: macos-13 - TARGET: osx - - os: windows-latest - TARGET: win - - steps: - - name: Checkout Pyomo source - uses: actions/checkout@v4 - # We need the source for .codecov.yml and running "coverage xml" - - #- name: Pip package cache - # uses: actions/cache@v4 - # id: pip-cache - # with: - # path: cache/pip - # key: pip-${{env.CACHE_VER}}.0-${{runner.os}}-3.8 - - - name: Download build artifacts - uses: actions/download-artifact@v4 - with: - path: artifacts - - - name: Set up Python 3.8 - uses: actions/setup-python@v5 - with: - python-version: 3.8 - - - name: Install Python Packages (pip) - shell: bash # DO NOT REMOVE: see note above - run: | - python -c 'import sys;print(sys.executable)' - python -m pip install --cache-dir cache/pip --upgrade pip - PYOMO_DEPENDENCIES=`python setup.py dependencies \ - --extras "tests" | tail -1` - python -m pip install --cache-dir cache/pip \ - ${PYTHON_CORE_PKGS} ${PYOMO_DEPENDENCIES} - python -c 'import sys; print("PYTHON_EXE=%s" \ - % (sys.executable,))' >> $GITHUB_ENV - - - name: Install Pyomo - run: | - echo "" - echo "Clone Pyomo-model-libraries..." - git clone https://github.com/Pyomo/pyomo-model-libraries.git - echo "" - echo "Install Pyomo..." - echo "" - $PYTHON_EXE setup.py develop ${{matrix.setup_options}} - echo "" - echo "Set custom PYOMO_CONFIG_DIR" - echo "" - echo "PYOMO_CONFIG_DIR=${GITHUB_WORKSPACE}/config" >> $GITHUB_ENV - - - name: Generate parse_table_datacmds - run: | - # Manually invoke the DAT parser so that parse_table_datacmds.py - # is generated before running "coverage xml" - $PYTHON_EXE -c "from pyomo.dataportal.parse_datacmds import \ - parse_data_commands; parse_data_commands(data='')" - - - name: Update codecov uploader - run: | - set +e - CODECOV="${GITHUB_WORKSPACE}/codecov.sh" - echo "CODECOV=$CODECOV" >> $GITHUB_ENV - for i in `seq 3`; do - echo "Downloading current codecov script (attempt ${i})" - curl -L https://codecov.io/bash -o $CODECOV - if test $? == 0; then - break - fi - DELAY=$(( RANDOM % 30 + 30)) - echo "Pausing $DELAY seconds before re-attempting download" - sleep $DELAY - done - if test ! -e $CODECOV; then - echo "Failed to download codecov.sh" - exit 1 - fi - - - name: Combine coverage reports - if: github.repository_owner == 'Pyomo' || github.ref != 'refs/heads/main' - run: | - set +e - if [ "$GITHUB_EVENT_NAME" == "pull_request" ]; then - SHA=$(jq --raw-output .pull_request.head.sha "$GITHUB_EVENT_PATH") - else - SHA=$GITHUB_SHA - fi - for ARTIFACT in artifacts/*_*${{matrix.TARGET}}_*; do - NAME=`echo $ARTIFACT | cut -d/ -f2` - cp -v $ARTIFACT/.coverage .coverage-$NAME - done - rm -vf .coverage coverage.xml - echo "Build: ${{ matrix.TARGET }}/other" - echo "" - FILES=.coverage-*_other-* - coverage combine --debug=dataio $FILES - if test ! -e .coverage; then - echo "No coverage to upload." - else - coverage xml || coverage xml -i - mv -v coverage.xml coverage-other.xml - fi - echo "" - echo "Build: ${{ matrix.TARGET }}" - echo "" - FILES=.coverage-*_${{matrix.TARGET}}-* - coverage combine --debug=dataio $FILES - rm -vf artifacts/*/*.xml - if test ! -e .coverage; then - echo "No coverage to upload." - else - coverage xml || coverage xml -i - fi - - - name: Upload codecov reports - if: github.repository_owner == 'Pyomo' || github.ref != 'refs/heads/main' - uses: codecov/codecov-action@v4 - with: - files: coverage.xml - token: ${{ secrets.PYOMO_CODECOV_TOKEN }} - name: ${{ matrix.TARGET }} - flags: ${{ matrix.TARGET }} - fail_ci_if_error: true - - - name: Upload other coverage reports - if: | - hashFiles('coverage-other.xml') != '' && - (github.repository_owner == 'Pyomo' || github.ref != 'refs/heads/main') - uses: codecov/codecov-action@v4 - with: - files: coverage-other.xml - token: ${{ secrets.PYOMO_CODECOV_TOKEN }} - name: ${{ matrix.TARGET }}/other - flags: ${{ matrix.TARGET }},other - fail_ci_if_error: true diff --git a/.github/workflows/test_pr_and_main.yml b/.github/workflows/test_pr_and_main.yml deleted file mode 100644 index 2ca7e166fd8..00000000000 --- a/.github/workflows/test_pr_and_main.yml +++ /dev/null @@ -1,915 +0,0 @@ -name: GitHub CI - -on: - push: - branches: - - main - pull_request: - branches: - - main - types: - - opened - - reopened - - synchronize - - ready_for_review - workflow_dispatch: - inputs: - git-ref: - description: Git Hash (Optional) - required: false - -concurrency: - group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }} - cancel-in-progress: true - -defaults: - run: - shell: bash -l {0} - -env: - PYTHONWARNINGS: ignore::UserWarning - PYTHON_CORE_PKGS: wheel - PYPI_ONLY: z3-solver linear-tree - PYPY_EXCLUDE: scipy numdifftools seaborn statsmodels linear-tree - CACHE_VER: v221013.1 - NEOS_EMAIL: tests@pyomo.org - SRC_REF: ${{ github.head_ref || github.ref }} - -jobs: - lint: - name: lint/style-and-typos - runs-on: ubuntu-latest - if: | - contains(github.event.pull_request.title, '[WIP]') != true && !github.event.pull_request.draft - steps: - - name: Checkout Pyomo source - uses: actions/checkout@v4 - - name: Set up Python - uses: actions/setup-python@v5 - with: - python-version: '3.10' - - name: Black Formatting Check - run: | - # Note v24.4.1 fails due to a bug in the parser - pip install 'black!=24.4.1' - black . -S -C --check --diff --exclude examples/pyomobook/python-ch/BadIndent.py - - name: Spell Check - uses: crate-ci/typos@master - with: - config: ./.github/workflows/typos.toml - - name: URL Checker - uses: urlstechie/urlchecker-action@0.0.34 - with: - # A comma-separated list of file types to cover in the URL checks - file_types: .md,.rst,.py - # Choose whether to include file with no URLs in the prints. - print_all: false - # More verbose summary at the end of a run - verbose: true - # How many times to retry a failed request (defaults to 1) - retry_count: 3 - # Exclude: - # - Jenkins because it's behind a firewall - # - RTD because a magically-generated string triggers failures - exclude_urls: https://pyomo-jenkins.sandia.gov/,https://pyomo.readthedocs.io/en/%s/errors.html - - - build: - name: ${{ matrix.TARGET }}/${{ matrix.python }}${{ matrix.other }} - needs: lint # the linter job is a prerequisite for PRs - runs-on: ${{ matrix.os }} - timeout-minutes: 120 - strategy: - fail-fast: false - matrix: - os: [ubuntu-latest, macos-13, windows-latest] - python: [ 3.8, 3.9, '3.10', '3.11', '3.12' ] - other: [""] - category: [""] - - # win/3.8 conda builds no longer work due to environment not being able - # to resolve. We are skipping it now. - exclude: - - os: windows-latest - python: 3.8 - include: - - os: ubuntu-latest - TARGET: linux - PYENV: pip - - - os: macos-13 - TARGET: osx - PYENV: pip - - - os: windows-latest - TARGET: win - PYENV: conda - PACKAGES: glpk pytest-qt filelock - - - os: ubuntu-latest - python: '3.11' - other: /conda - skip_doctest: 1 - TARGET: linux - PYENV: conda - PACKAGES: pytest-qt - - - os: ubuntu-latest - python: '3.10' - other: /mpi - mpi: 3 - skip_doctest: 1 - TARGET: linux - PYENV: conda - PACKAGES: openmpi mpi4py - - - os: ubuntu-latest - python: '3.11' - other: /singletest - category: "-m 'neos or importtest'" - skip_doctest: 1 - TARGET: linux - PYENV: pip - - - os: ubuntu-latest - python: '3.10' - other: /cython - setup_options: --with-cython - skip_doctest: 1 - TARGET: linux - PYENV: pip - PACKAGES: cython - - - os: windows-latest - python: 3.8 - other: /pip - skip_doctest: 1 - TARGET: win - PYENV: pip - - - os: ubuntu-latest - python: 3.8 - other: /slim - slim: 1 - skip_doctest: 1 - TARGET: linux - PYENV: pip - - - os: ubuntu-latest - python: 3.9 - other: /pyutilib - TARGET: linux - PYENV: pip - PACKAGES: pyutilib - - - os: ubuntu-latest - python: pypy-3.9 - skip_doctest: 1 - TARGET: linux - PYENV: pip - - steps: - - name: Checkout Pyomo source - uses: actions/checkout@v4 - - - name: Configure job parameters - run: | - JOB="${{matrix.TARGET}}/${{matrix.python}}${{matrix.other}}" - echo "GHA_JOBNAME=$JOB" | sed 's|/|_|g' >> $GITHUB_ENV - if test -z "${{matrix.other}}"; then - echo "GHA_JOBGROUP=${{matrix.TARGET}}" >> $GITHUB_ENV - else - echo "GHA_JOBGROUP=other" >> $GITHUB_ENV - fi - # Note: pandas 1.0.3 causes gams 29.1.0 import to fail in python 3.8 - EXTRAS=tests - if test -z "${{matrix.slim}}"; then - EXTRAS="$EXTRAS,docs,optional" - fi - echo "EXTRAS=$EXTRAS" >> $GITHUB_ENV - PYTHON_PACKAGES="${{matrix.PACKAGES}}" - echo "PYTHON_PACKAGES=$PYTHON_PACKAGES" \ - | tr '\n' ' ' | sed 's/ \+/ /g' >> $GITHUB_ENV - - #- name: Pip package cache - # uses: actions/cache@v4 - # if: matrix.PYENV == 'pip' - # id: pip-cache - # with: - # path: cache/pip - # key: pip-${{env.CACHE_VER}}.0-${{runner.os}}-${{matrix.python}} - - #- name: OS package cache - # uses: actions/cache@v4 - # if: matrix.TARGET != 'osx' - # id: os-cache - # with: - # path: cache/os - # key: pkg-${{env.CACHE_VER}}.0-${{runner.os}} - - - name: TPL package download cache - uses: actions/cache@v4 - if: ${{ ! matrix.slim }} - id: download-cache - with: - path: cache/download - key: download-${{env.CACHE_VER}}.0-${{runner.os}} - - - name: Configure curl - run: | - CURLRC="$(cat < ${GITHUB_WORKSPACE}/.curlrc - echo "$CURLRC" > ${GITHUB_WORKSPACE}/_curlrc - echo "CURL_HOME=$GITHUB_WORKSPACE" >> $GITHUB_ENV - - - name: Update OSX - if: matrix.TARGET == 'osx' - run: | - mkdir -p ${GITHUB_WORKSPACE}/cache/os - export HOMEBREW_CACHE=${GITHUB_WORKSPACE}/cache/os - # Be cautious running brew update: it can break - # setup-python on OSX - # brew update - # - # Notes: - # - install glpk - # - pyodbc needs: gcc pkg-config unixodbc freetds - for pkg in bash pkg-config unixodbc freetds glpk ginac; do - brew list $pkg || brew install $pkg - done - - - name: Update Linux - if: matrix.TARGET == 'linux' - run: | - mkdir -p ${GITHUB_WORKSPACE}/cache/os - # Notes: - # - install glpk - # - ipopt needs: libopenblas-dev gfortran liblapack-dev - sudo apt-get -o Dir::Cache=${GITHUB_WORKSPACE}/cache/os \ - install libopenblas-dev gfortran liblapack-dev glpk-utils \ - libginac-dev - sudo chmod -R 777 ${GITHUB_WORKSPACE}/cache/os - - - name: Update Windows - if: matrix.TARGET == 'win' - run: | - echo "SETUPTOOLS_USE_DISTUTILS=local" >> $GITHUB_ENV - - - name: Set up Python ${{ matrix.python }} - if: matrix.PYENV == 'pip' - uses: actions/setup-python@v5 - with: - python-version: ${{ matrix.python }} - - - name: Set up Miniconda Python ${{ matrix.python }} - if: matrix.PYENV == 'conda' - uses: conda-incubator/setup-miniconda@v3 - with: - auto-update-conda: false - python-version: ${{ matrix.python }} - - # This is necessary for qt (UI) tests; the package utilized here does not - # have support for OSX. - - name: Set up UI testing infrastructure - if: ${{ matrix.TARGET != 'osx' }} - uses: pyvista/setup-headless-display-action@v2 - with: - qt: true - pyvista: false - - # GitHub actions is very fragile when it comes to setting up various - # Python interpreters, expecially the setup-miniconda interface. - # Per the setup-miniconda documentation, it is important to always - # invoke bash as a login shell ('shell: bash -l {0}') so that the - # conda environment is properly activated. However, running within - # a login shell appears to foul up the link to python from - # setup-python. Further, we have anecdotal evidence that - # subprocesses invoked through $(python -c ...) and `python -c ...` - # will not pick up the python activated by setup-python on OSX. - # - # Our solution is to define a PYTHON_EXE environment variable that - # can be explicitly called within subprocess calls to reach the - # correct interpreter. Note that we must explicitly run in a *non* - # login shell to set up the environment variable for the - # setup-python environments. - - - name: Install Python Packages (pip) - if: matrix.PYENV == 'pip' - shell: bash # DO NOT REMOVE: see note above - run: | - python -c 'import sys;print(sys.executable)' - python -m pip install --cache-dir cache/pip --upgrade pip - python -m pip install --cache-dir cache/pip setuptools - PYOMO_DEPENDENCIES=`python setup.py dependencies \ - --extras "$EXTRAS" | tail -1` - PACKAGES="${PYTHON_CORE_PKGS} ${PYTHON_PACKAGES} ${PYOMO_DEPENDENCIES} " - if [[ ${{matrix.python}} == pypy* ]]; then - EXCLUDE="$PYPY_EXCLUDE $EXCLUDE" - fi - EXCLUDE=`echo "$EXCLUDE" | xargs` - if test -n "$EXCLUDE"; then - for WORD in $EXCLUDE; do - PACKAGES=${PACKAGES//$WORD / } - done - fi - python -m pip install --cache-dir cache/pip ${PACKAGES} - python -m pip install --cache-dir cache/pip pymysql || \ - python -m pip install --cache-dir cache/pip pymysql - if test -z "${{matrix.slim}}"; then - python -m pip install --cache-dir cache/pip cplex docplex \ - || echo "WARNING: CPLEX Community Edition is not available" - python -m pip install --cache-dir cache/pip gurobipy==10.0.3 \ - || echo "WARNING: Gurobi is not available" - python -m pip install --cache-dir cache/pip xpress \ - || echo "WARNING: Xpress Community Edition is not available" - python -m pip install --cache-dir cache/pip maingopy \ - || echo "WARNING: MAiNGO is not available" - if [[ ${{matrix.python}} == pypy* ]]; then - echo "skipping wntr for pypy" - else - python -m pip install wntr \ - || echo "WARNING: WNTR is not available" - fi - fi - python -c 'import sys; print("PYTHON_EXE=%s" \ - % (sys.executable,))' >> $GITHUB_ENV - echo "" - echo "Final pip environment:" - python -m pip list | sed 's/^/ /' - - - name: Install Python packages (conda) - if: matrix.PYENV == 'conda' - run: | - # Set up environment - conda config --set always_yes yes - conda config --set auto_update_conda false - conda config --remove channels defaults - conda config --append channels nodefaults - conda config --append channels conda-forge - # Try to install mamba - conda install --update-deps -q -y -n base conda-libmamba-solver \ - || MAMBA_FAILED=1 - if test -z "$MAMBA_FAILED"; then - echo "*** Activating the mamba environment solver ***" - conda config --set solver libmamba - fi - # Add the rest of the channels - conda config --append channels gurobi - conda config --append channels ibmdecisionoptimization - conda config --append channels fico-xpress - # Print environment info - echo "*** CONDA environment: ***" - conda info - conda config --show-sources - conda config --show channels - conda list --show-channel-urls - which python - python --version - # Note: some pypi packages are not available through conda - PYOMO_DEPENDENCIES=`python setup.py dependencies \ - --extras "$EXTRAS" | tail -1` - PACKAGES="${PYTHON_CORE_PKGS} ${PYTHON_PACKAGES} ${PYOMO_DEPENDENCIES} " - if [[ ${{matrix.python}} == pypy* ]]; then - EXCLUDE="$PYPY_EXCLUDE $EXCLUDE" - fi - # HACK: Remove problem packages on conda+Linux - if test "${{matrix.TARGET}}" == linux; then - EXCLUDE="casadi numdifftools $EXCLUDE" - fi - EXCLUDE=`echo "$EXCLUDE" | xargs` - if test -n "$EXCLUDE"; then - for WORD in $EXCLUDE; do - PACKAGES=${PACKAGES//$WORD / } - done - fi - for PKG in $PACKAGES; do - if [[ " $PYPI_ONLY " == *" $PKG "* ]]; then - PYPI_DEPENDENCIES="$PYPI_DEPENDENCIES $PKG" - else - CONDA_DEPENDENCIES="$CONDA_DEPENDENCIES $PKG" - fi - done - echo "" - echo "*** Install Pyomo dependencies ***" - # Note: this will fail the build if any installation fails (or - # possibly if it outputs messages to stderr) - conda install --update-deps -q -y $CONDA_DEPENDENCIES - if test -z "${{matrix.slim}}"; then - PYVER=$(echo "py${{matrix.python}}" | sed 's/\.//g') - echo "Installing for $PYVER" - for PKG in 'cplex>=12.10' docplex 'gurobi=10.0.3' xpress cyipopt pymumps scip; do - echo "" - echo "*** Install $PKG ***" - # conda can literally take an hour to determine that a - # package is not available. Perform a quick search to see - # if the package is available for this interpreter before - # attempting an install. - # NOTE: conda search will attempt approximate matches. - _PKGLIST=$(conda search -f "$PKG") || echo "Package $PKG not found" - echo "$_PKGLIST" - _BASE=$(echo "$PKG" | sed 's/[=<>].*//') - _BUILDS=$(echo "$_PKGLIST" | grep "^$_BASE " \ - | sed -r 's/\s+/ /g' | cut -d\ -f3) || echo "" - if test -n "$_BUILDS"; then - _ISPY=$(echo "$_BUILDS" | grep "^py") \ - || echo "INFO: No python build detected." - _PYOK=$(echo "$_BUILDS" | grep -E "^($PYVER|pyh)") \ - || echo "INFO: No python build matching $PYVER detected." - if test -z "$_ISPY" -o -n "$_PYOK"; then - echo "" - echo "... INSTALLING $PKG" - conda install -y "$PKG" || _BUILDS="" - fi - fi - if test -z "$_BUILDS"; then - echo "WARNING: $PKG is not available" - fi - done - fi - # Re-try Pyomo (optional) dependencies with pip - if test -n "$PYPI_DEPENDENCIES"; then - python -m pip install --cache-dir cache/pip $PYPI_DEPENDENCIES - fi - # remember this python interpreter - python -c 'import sys; print("PYTHON_EXE=%s" \ - % (sys.executable,))' >> $GITHUB_ENV - # - # conda activate puts itself first in the PATH, which overrides - # any paths we add through GITHUB_PATH. We will update .profile - # to move the local runner paths back to the front (before conda). - for profile in $HOME/.profile $HOME/.bash_profile; do - if test ! -e $profile; then - continue - fi - echo '' >> $profile - echo 'export PATH=`echo "$PATH" \ - | tr ":" "\\n" | grep runner | tr "\n" ":"`:`echo "$PATH" \ - | tr ":" "\\n" | grep -v runner | tr "\n" ":"`' >> $profile - done - echo "" - echo "Final conda environment:" - conda list | sed 's/^/ /' - - - name: Setup TPL package directories - run: | - TPL_DIR="${GITHUB_WORKSPACE}/cache/tpl" - mkdir -p "$TPL_DIR" - DOWNLOAD_DIR="${GITHUB_WORKSPACE}/cache/download" - mkdir -p "$DOWNLOAD_DIR" - echo "TPL_DIR=$TPL_DIR" >> $GITHUB_ENV - echo "DOWNLOAD_DIR=$DOWNLOAD_DIR" >> $GITHUB_ENV - - - name: Install Ipopt - if: ${{ ! matrix.slim }} - run: | - IPOPT_DIR=$TPL_DIR/ipopt - echo "$IPOPT_DIR" >> $GITHUB_PATH - echo "LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$IPOPT_DIR" >> $GITHUB_ENV - mkdir -p $IPOPT_DIR - IPOPT_TAR=${DOWNLOAD_DIR}/ipopt.tar.gz - if test ! -e $IPOPT_TAR; then - echo "...downloading Ipopt" - if test "${{matrix.TARGET}}" == osx; then - echo "IDAES Ipopt not available on OSX" - exit 0 - fi - URL=https://github.com/IDAES/idaes-ext - RELEASE=$(curl --max-time 150 --retry 8 \ - -L -s -H 'Accept: application/json' ${URL}/releases/latest) - VER=$(echo $RELEASE | sed -e 's/.*"tag_name":"\([^"]*\)".*/\1/') - URL=${URL}/releases/download/$VER - if test "${{matrix.TARGET}}" == linux; then - curl --max-time 150 --retry 8 \ - -L $URL/idaes-solvers-ubuntu2004-x86_64.tar.gz \ - > $IPOPT_TAR - else - curl --max-time 150 --retry 8 \ - -L $URL/idaes-solvers-windows-x86_64.tar.gz \ - $URL/idaes-lib-windows-x86_64.tar.gz > $IPOPT_TAR - fi - fi - cd $IPOPT_DIR - tar -xzi < $IPOPT_TAR - echo "" - echo "$IPOPT_DIR" - ls -l $IPOPT_DIR - - - name: Install GAMS - if: ${{ ! matrix.slim }} - # We install using Powershell because the GAMS installer hangs - # when launched from bash on Windows - shell: pwsh - run: | - $GAMS_DIR = "${env:TPL_DIR}/gams" - echo "$GAMS_DIR" | ` - Out-File -FilePath $env:GITHUB_PATH -Encoding utf8 -Append - echo "LD_LIBRARY_PATH=${env:LD_LIBRARY_PATH}:$GAMS_DIR" ` - Out-File -FilePath $env:GITHUB_ENV -Encoding utf8 -Append - echo "DYLD_LIBRARY_PATH=${env:DYLD_LIBRARY_PATH}:$GAMS_DIR" ` - Out-File -FilePath $env:GITHUB_ENV -Encoding utf8 -Append - $INSTALLER = "${env:DOWNLOAD_DIR}/gams_install.exe" - # We are pinning to 29.1.0 because a license is required for - # versions after this in order to run in demo mode. - $URL = "https://d37drm4t2jghv5.cloudfront.net/distributions/29.1.0" - if ( "${{matrix.TARGET}}" -eq "win" ) { - $URL = "$URL/windows/windows_x64_64.exe" - } elseif ( "${{matrix.TARGET}}" -eq "osx" ) { - $URL = "$URL/macosx/osx_x64_64_sfx.exe" - } else { - $URL = "$URL/linux/linux_x64_64_sfx.exe" - } - if (-not (Test-Path "$INSTALLER" -PathType Leaf)) { - echo "...downloading GAMS" - Invoke-WebRequest -Uri "$URL" -OutFile "$INSTALLER" ` - -RetryIntervalSec 30 -MaximumRetryCount 8 -TimeoutSec 150 - } - echo "...installing GAMS" - if ( "${{matrix.TARGET}}" -eq "win" ) { - Start-Process -FilePath "$INSTALLER" -ArgumentList ` - "/SP- /NORESTART /VERYSILENT /DIR=$GAMS_DIR /NOICONS" ` - -Wait - } else { - chmod 777 $INSTALLER - Start-Process -FilePath "$INSTALLER" -ArgumentList ` - "-q -d $GAMS_DIR" -Wait - mv $GAMS_DIR/*/* $GAMS_DIR/. - } - echo "" - echo "$GAMS_DIR" - ls -l $GAMS_DIR - - - name: Install GAMS Python bindings - if: ${{ ! matrix.slim }} - run: | - GAMS_DIR="${env:TPL_DIR}/gams" - py_ver=$($PYTHON_EXE -c 'import sys;v="_%s%s" % sys.version_info[:2] \ - ;print(v if v != "_27" else "")') - if test -e $GAMS_DIR/apifiles/Python/api$py_ver; then - echo "Installing GAMS Python bindings" - pushd $GAMS_DIR/apifiles/Python/api$py_ver - $PYTHON_EXE setup.py install - popd - fi - - - name: Install BARON - if: ${{ ! matrix.slim }} - shell: pwsh - run: | - $BARON_DIR = "${env:TPL_DIR}/baron" - echo "$BARON_DIR" | ` - Out-File -FilePath $env:GITHUB_PATH -Encoding utf8 -Append - $URL = "https://minlp.com/downloads/xecs/baron/current/" - if ( "${{matrix.TARGET}}" -eq "win" ) { - $INSTALLER = "${env:DOWNLOAD_DIR}/baron_install.exe" - $URL += "baron-win64.exe" - } elseif ( "${{matrix.TARGET}}" -eq "osx" ) { - $INSTALLER = "${env:DOWNLOAD_DIR}/baron_install.zip" - $URL += "baron-osx64.zip" - } else { - $INSTALLER = "${env:DOWNLOAD_DIR}/baron_install.zip" - $URL += "baron-lin64.zip" - } - if (-not (Test-Path "$INSTALLER" -PathType Leaf)) { - echo "...downloading BARON ($URL)" - Invoke-WebRequest -Uri "$URL" -OutFile "$INSTALLER" ` - -RetryIntervalSec 30 -MaximumRetryCount 8 -TimeoutSec 150 - } - echo "...installing BARON" - if ( "${{matrix.TARGET}}" -eq "win" ) { - Start-Process -FilePath "$INSTALLER" -ArgumentList ` - "/SP- /NORESTART /VERYSILENT /DIR=$BARON_DIR /NOICONS" ` - -Wait - } else { - unzip -q $INSTALLER - mv baron-* $BARON_DIR - } - echo "" - echo "$BARON_DIR" - ls -l $BARON_DIR - - - name: Install GJH_ASL_JSON - if: ${{ ! matrix.slim && matrix.TARGET != 'win' }} - run: | - GJH_DIR="$TPL_DIR/gjh" - echo "${GJH_DIR}" >> $GITHUB_PATH - INSTALL_DIR="${DOWNLOAD_DIR}/gjh" - if test ! -e "$INSTALL_DIR/bin"; then - mkdir -p "$INSTALL_DIR" - INSTALLER="$INSTALL_DIR/gjh_asl_json.zip" - URL="https://codeload.github.com/ghackebeil/gjh_asl_json/zip/master" - curl --max-time 150 --retry 8 -L $URL > $INSTALLER - cd $INSTALL_DIR - unzip -q $INSTALLER - cd gjh_asl_json-master/Thirdparty - ./get.ASL - cd .. - make - mv bin "$INSTALL_DIR/bin" - fi - cp -rp "$INSTALL_DIR/bin" "$GJH_DIR" - echo "" - echo "$GJH_DIR" - ls -l $GJH_DIR - - - name: Install Pyomo - run: | - echo "" - echo "Clone Pyomo-model-libraries..." - URL=https://github.com/Pyomo/pyomo-model-libraries.git - git clone -b ${SRC_REF##*/} $URL || git clone -b main $URL - echo "" - echo "Install Pyomo..." - echo "" - $PYTHON_EXE setup.py develop ${{matrix.setup_options}} - echo "" - echo "Set custom PYOMO_CONFIG_DIR" - echo "" - echo "PYOMO_CONFIG_DIR=${GITHUB_WORKSPACE}/config" >> $GITHUB_ENV - - # this has to be done after Pyomo is installed because highspy - # depends on pyomo's find_library function - - name: Install HiGHS - if: ${{ ! matrix.slim }} - shell: bash - run: | - echo "NOTE: temporarily pinning to highspy pre-release for testing" - $PYTHON_EXE -m pip install --cache-dir cache/pip "highspy>=1.7.1.dev1" \ - || echo "WARNING: highspy is not available" - - - name: Set up coverage tracking - run: | - if test "${{matrix.TARGET}}" == win; then - COVERAGE_BASE=${GITHUB_WORKSPACE}\\.cover - else - COVERAGE_BASE=${GITHUB_WORKSPACE}/.cover - fi - COVERAGE_RC=${COVERAGE_BASE}_rc - echo "COVERAGE_RCFILE=$COVERAGE_RC" >> $GITHUB_ENV - echo "COVERAGE_PROCESS_START=$COVERAGE_RC" >> $GITHUB_ENV - cp ${GITHUB_WORKSPACE}/.coveragerc ${COVERAGE_RC} - echo "data_file=${COVERAGE_BASE}age" >> ${COVERAGE_RC} - SITE_PACKAGES=$($PYTHON_EXE -c \ - "import sysconfig; print(sysconfig.get_path('purelib'))") - echo "Python site-packages: $SITE_PACKAGES" - echo 'import coverage; coverage.process_startup()' \ - > ${SITE_PACKAGES}/run_coverage_at_startup.pth - - - name: Download and install extensions - if: ${{ ! matrix.slim }} - run: | - echo "" - echo "Pyomo download-extensions" - echo "" - pyomo download-extensions || exit 1 - echo "" - echo "Pyomo build-extensions" - echo "" - pyomo build-extensions --parallel 2 - - - name: Report pyomo plugin information - run: | - echo "$PATH" - pyomo help --solvers || exit 1 - pyomo help --transformations || exit 1 - pyomo help --writers || exit 1 - - - name: Run Pyomo tests - if: matrix.mpi == 0 - run: | - $PYTHON_EXE -m pytest -v \ - -W ignore::Warning ${{matrix.category}} \ - pyomo `pwd`/pyomo-model-libraries \ - `pwd`/examples `pwd`/doc --junitxml="TEST-pyomo.xml" - - - name: Run Pyomo MPI tests - if: matrix.mpi != 0 - run: | - # Manually invoke the DAT parser so that parse_table_datacmds.py - # is fully generated by a single process before invoking MPI - $PYTHON_EXE -c "from pyomo.dataportal.parse_datacmds import \ - parse_data_commands; parse_data_commands(data='')" - # Note: if we are testing with openmpi, add '--oversubscribe' - mpirun -np ${{matrix.mpi}} -oversubscribe pytest -v \ - --junit-xml=TEST-pyomo-mpi.xml \ - -m "mpi" -W ignore::Warning \ - pyomo `pwd`/pyomo-model-libraries - - - name: Run documentation tests - if: matrix.skip_doctest == 0 - run: | - make -C doc/OnlineDocs doctest -d - - - name: Process code coverage report - run: | - coverage combine - coverage report -i - coverage xml -i - - - name: Record build artifacts - uses: actions/upload-artifact@v4 - with: - name: ${{github.job}}_${{env.GHA_JOBGROUP}}-${{env.GHA_JOBNAME}} - path: | - .coverage - coverage.xml - # In general, do not record test results as artifacts to - # manage total artifact storage - # TEST-*.xml - - - bare-python-env: - name: linux/3.8/bare-env - needs: lint # the linter job is a prerequisite for PRs - runs-on: ubuntu-latest - timeout-minutes: 10 - steps: - - name: Checkout Pyomo source - uses: actions/checkout@v4 - - - name: Set up Python 3.8 - uses: actions/setup-python@v5 - with: - python-version: 3.8 - - - name: Install Pyomo - run: | - echo "" - echo "Install Pyomo..." - echo "" - python setup.py develop - echo "" - echo "Set custom PYOMO_CONFIG_DIR" - echo "" - echo "PYOMO_CONFIG_DIR=${GITHUB_WORKSPACE}/config" >> $GITHUB_ENV - - - name: Report pyomo plugin information - run: | - echo "$PATH" - pyomo help --solvers || exit 1 - pyomo help --transformations || exit 1 - pyomo help --writers || exit 1 - - - name: Run Pyomo standalone test - run: | - echo "" - echo "Running standalone Pyomo test" - echo "" - python `pwd`/pyomo/environ/tests/standalone_minimal_pyomo_driver.py \ - || exit 1 - - - cover: - name: process-coverage-${{ matrix.TARGET }} - needs: build - if: success() || failure() # run even if a build job fails, but not if cancelled - runs-on: ${{ matrix.os }} - timeout-minutes: 10 - strategy: - fail-fast: false - matrix: - os: [ubuntu-latest, macos-13, windows-latest] - - include: - - os: ubuntu-latest - TARGET: linux - - os: macos-13 - TARGET: osx - - os: windows-latest - TARGET: win - - steps: - - name: Checkout Pyomo source - uses: actions/checkout@v4 - # We need the source for .codecov.yml and running "coverage xml" - - #- name: Pip package cache - # uses: actions/cache@v4 - # id: pip-cache - # with: - # path: cache/pip - # key: pip-${{env.CACHE_VER}}.0-${{runner.os}}-3.8 - - - name: Download build artifacts - uses: actions/download-artifact@v4 - with: - path: artifacts - - - name: Set up Python 3.8 - uses: actions/setup-python@v5 - with: - python-version: 3.8 - - - name: Install Python Packages (pip) - shell: bash # DO NOT REMOVE: see note above - run: | - python -c 'import sys;print(sys.executable)' - python -m pip install --cache-dir cache/pip --upgrade pip - PYOMO_DEPENDENCIES=`python setup.py dependencies \ - --extras "tests" | tail -1` - python -m pip install --cache-dir cache/pip \ - ${PYTHON_CORE_PKGS} ${PYOMO_DEPENDENCIES} - python -c 'import sys; print("PYTHON_EXE=%s" \ - % (sys.executable,))' >> $GITHUB_ENV - - - name: Install Pyomo - run: | - echo "" - echo "Clone Pyomo-model-libraries..." - git clone https://github.com/Pyomo/pyomo-model-libraries.git - echo "" - echo "Install Pyomo..." - echo "" - $PYTHON_EXE setup.py develop ${{matrix.setup_options}} - echo "" - echo "Set custom PYOMO_CONFIG_DIR" - echo "" - echo "PYOMO_CONFIG_DIR=${GITHUB_WORKSPACE}/config" >> $GITHUB_ENV - - - name: Generate parse_table_datacmds - run: | - # Manually invoke the DAT parser so that parse_table_datacmds.py - # is generated before running "coverage xml" - $PYTHON_EXE -c "from pyomo.dataportal.parse_datacmds import \ - parse_data_commands; parse_data_commands(data='')" - - - name: Update codecov uploader - run: | - set +e - CODECOV="${GITHUB_WORKSPACE}/codecov.sh" - echo "CODECOV=$CODECOV" >> $GITHUB_ENV - for i in `seq 3`; do - echo "Downloading current codecov script (attempt ${i})" - curl -L https://codecov.io/bash -o $CODECOV - if test $? == 0; then - break - fi - DELAY=$(( RANDOM % 30 + 30)) - echo "Pausing $DELAY seconds before re-attempting download" - sleep $DELAY - done - if test ! -e $CODECOV; then - echo "Failed to download codecov.sh" - exit 1 - fi - - - name: Combine coverage reports - if: github.repository_owner == 'Pyomo' || github.ref != 'refs/heads/main' - run: | - set +e - if [ "$GITHUB_EVENT_NAME" == "pull_request" ]; then - SHA=$(jq --raw-output .pull_request.head.sha "$GITHUB_EVENT_PATH") - else - SHA=$GITHUB_SHA - fi - for ARTIFACT in artifacts/*_*${{matrix.TARGET}}_*; do - NAME=`echo $ARTIFACT | cut -d/ -f2` - cp -v $ARTIFACT/.coverage .coverage-$NAME - done - rm -vf .coverage coverage.xml - echo "Build: ${{ matrix.TARGET }}/other" - echo "" - FILES=.coverage-*_other-* - coverage combine --debug=dataio $FILES - if test ! -e .coverage; then - echo "No coverage to upload." - else - coverage xml || coverage xml -i - mv -v coverage.xml coverage-other.xml - fi - echo "" - echo "Build: ${{ matrix.TARGET }}" - echo "" - FILES=.coverage-*_${{matrix.TARGET}}-* - coverage combine --debug=dataio $FILES - rm -vf artifacts/*/*.xml - if test ! -e .coverage; then - echo "No coverage to upload." - else - coverage xml || coverage xml -i - fi - - - name: Upload codecov reports - if: github.repository_owner == 'Pyomo' || github.ref != 'refs/heads/main' - uses: codecov/codecov-action@v4 - with: - files: coverage.xml - token: ${{ secrets.PYOMO_CODECOV_TOKEN }} - name: ${{ matrix.TARGET }} - flags: ${{ matrix.TARGET }} - fail_ci_if_error: true - - - name: Upload other coverage reports - if: | - hashFiles('coverage-other.xml') != '' && - (github.repository_owner == 'Pyomo' || github.ref != 'refs/heads/main') - uses: codecov/codecov-action@v4 - with: - files: coverage-other.xml - token: ${{ secrets.PYOMO_CODECOV_TOKEN }} - name: ${{ matrix.TARGET }}/other - flags: ${{ matrix.TARGET }},other - fail_ci_if_error: true diff --git a/.github/workflows/typos.toml b/.github/workflows/typos.toml deleted file mode 100644 index 80d50477ca4..00000000000 --- a/.github/workflows/typos.toml +++ /dev/null @@ -1,74 +0,0 @@ -[files] -extend-exclude = ["*.eps"] - -[default.extend-words] -# Ignore IDAES -IDAES = "IDAES" -idaes = "idaes" -# Ignore datas -Datas = "Datas" -datas = "datas" -# Ignore ND -ND = "ND" -nd = "nd" -# Ignore INOUT -inout = "inout" -INOUT= "INOUT" -# Ignore MAYBEE from examples -MAYBEE = "MAYBEE" -# Ignore conext for constraint-external -conext = "conext" -# Ignore AFE (affine expression) from MOSEK vernacular -afe = "afe" -# Ignore Fo from PyNumero tests -Fo = "Fo" -# Ignore ba from contrib -ba = "ba" -# Ignore complimentarity from interior_point -complimentarity = "complimentarity" -# Ignore from "number of inputs" from core -nin = "nin" -# sisser CUTEr instance -sisser = "sisser" -# LAF -LAF = "LAF" -# caf -caf = "caf" -# WRONLY -WRONLY = "WRONLY" -# Ignore the name Hax -Hax = "Hax" -# Ignore dout (short for dual output in SAS solvers) -dout = "dout" -# Big Sur -Sur = "Sur" -# contrib package named mis and the acronym whence the name comes -mis = "mis" -MIS = "MIS" -# Ignore the shorthand ans for answer -ans = "ans" -# Ignore the keyword arange -arange = "arange" -# Ignore IIS -IIS = "IIS" -iis = "iis" -# Ignore PN -PN = "PN" -# Ignore hd -hd = "hd" -# Ignore opf -opf = "opf" -# Ignore FRE -FRE = "FRE" -# Ignore MCH -MCH = "MCH" -# Ignore RO -ro = "ro" -RO = "RO" -# Ignore EOF - end of file -EOF = "EOF" -# Ignore lst as shorthand for list -lst = "lst" -# Abbreviation of gamma (used in stochpdegas1_automatic.py) -gam = "gam" -# AS NEEDED: Add More Words Below