Merge pull request #161 from Grid2op/claude/security-audit-review-jghnx0 #880
Workflow file for this run
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: CI | |
| on: | |
| push: | |
| branches: | |
| - '*' | |
| tags: | |
| - 'v*.*.*' | |
| env: | |
| # ── Wheel count guard ───────────────────────────────────────────────────── | |
| # Must be updated in sync with the build matrix whenever a Python version | |
| # is added or removed. A mismatch blocks the lightsim2grid-wheels artifact | |
| # from being created, which in turn prevents the PyPI release workflow | |
| # (publish.yml) from running at all. | |
| # | |
| # manylinux x86_64 (cp39–cp314 × 1 container) → 6 | |
| # windows x64 (cp39–cp314 × AMD64) → 6 | |
| # macos x86_64 (cp39–cp314, native on macos-15-intel) → 6 | |
| # macos arm64 (cp310–cp314, native on macos-14) → 5 | |
| # exotic macos arm64 via cibuildwheel (cp39) → 1 | |
| # exotic windows ARM64 via cibuildwheel (cp39–cp314) → 6 | |
| # total: 30 | |
| EXPECTED_WHEELS: 30 | |
| EXPECTED_SDIST: 1 | |
| jobs: | |
| manylinux_build: | |
| # build wheels for some linux | |
| name: Build linux ${{ matrix.python.name }} wheel on ${{ matrix.cont.name}} | |
| runs-on: ${{matrix.cont.runner}} | |
| env: | |
| ACTIONS_ALLOW_USE_UNSECURE_NODE_VERSION: true | |
| strategy: | |
| matrix: | |
| python: | |
| # - { | |
| # name: cp37, | |
| # abi: cp37m, | |
| # version: '3.7', | |
| # } | |
| # - { | |
| # name: cp38, | |
| # abi: cp38, | |
| # version: '3.8', | |
| # } | |
| - { | |
| name: cp39, | |
| abi: cp39, | |
| version: '3.9', | |
| } | |
| - { | |
| name: cp310, | |
| abi: cp310, | |
| version: '3.10', | |
| } | |
| - { | |
| name: cp311, | |
| abi: cp311, | |
| version: '3.11', | |
| } | |
| - { | |
| name: cp312, | |
| abi: cp312, | |
| version: '3.12', | |
| } | |
| - { | |
| name: cp313, | |
| abi: cp313, | |
| version: '3.13', | |
| } | |
| - { | |
| name: cp314, | |
| abi: cp314, | |
| version: '3.14', | |
| } | |
| cont: | |
| - { | |
| name: manylinux_2_28_x86_64, | |
| val: quay.io/pypa/manylinux_2_28_x86_64, | |
| arch: amd64, | |
| runner: ubuntu-latest | |
| } | |
| # - { | |
| # name: manylinux_2_28_aarch64, | |
| # val: quay.io/pypa/manylinux_2_28_aarch64, | |
| # arch: arm64, | |
| # runner: ubuntu-24.04-arm | |
| # } | |
| container: | |
| image: ${{matrix.cont.val}} | |
| # does not work if not manylinux2014_x86_64... | |
| # does not work if not manylinux_2_28_x86_64... | |
| steps: | |
| # - name: Set up QEMU | |
| # if: matrix.cont.name == 'manylinux_2_28_aarch64' | |
| # uses: docker/setup-qemu-action@v2 | |
| # with: | |
| # platforms: arm64 | |
| - name: Checkout sources | |
| uses: actions/checkout@v4 | |
| with: | |
| submodules: true | |
| - name: Setup path | |
| run: echo "/opt/python/${{ matrix.python.name }}-${{ matrix.python.abi }}/bin/" >> $GITHUB_PATH | |
| - name: get python version | |
| run: | | |
| python3 --version | |
| - name: Install Python dependencies | |
| run: | | |
| python3 -m pip install --upgrade pip | |
| python3 -m pip install -r requirements_compile_ci.txt | |
| python3 -m pip freeze | |
| - name: Build lightsim2grid wheel | |
| run: | | |
| python3 -m pip wheel --verbose . --no-deps -w dist | |
| auditwheel repair dist/*.whl | |
| - name: Build source archive | |
| if: matrix.python.name == 'cp312' | |
| run: | | |
| python3 -m pip install build | |
| python3 -m build --sdist | |
| - name: Install lightsim2grid wheel | |
| run: | | |
| python3 -m pip install wheelhouse/*.whl --user | |
| python3 -m pip freeze | |
| - name: Check package can be imported (bare install, default numpy) | |
| run: | | |
| mkdir tmp_for_import_checking | |
| cd tmp_for_import_checking | |
| python3 -c "import lightsim2grid" | |
| python3 -c "from lightsim2grid import *" | |
| python3 -c "from lightsim2grid.newtonpf import newtonpf" | |
| python3 -c "from lightsim2grid.timeSerie import TimeSeriesCPP" | |
| python3 -c "from lightsim2grid.contingencyAnalysis import ContingencyAnalysisCPP" | |
| python3 -c "from lightsim2grid.securityAnalysis import SecurityAnalysisCPP" | |
| python3 -c "from lightsim2grid.network import LSGrid" | |
| - name: Check package can be imported (bare install, numpy < 2) | |
| if: matrix.python.name != 'cp37' && matrix.python.name != 'cp38' && matrix.python.name != 'cp313' && matrix.python.name != 'cp314' | |
| run: | | |
| python3 -m pip install "numpy<2" scipy | |
| cd tmp_for_import_checking | |
| python3 -c "import lightsim2grid" | |
| python3 -c "from lightsim2grid import *" | |
| python3 -c "from lightsim2grid.newtonpf import newtonpf" | |
| python3 -c "from lightsim2grid.timeSerie import TimeSeriesCPP" | |
| python3 -c "from lightsim2grid.contingencyAnalysis import ContingencyAnalysisCPP" | |
| python3 -c "from lightsim2grid.securityAnalysis import SecurityAnalysisCPP" | |
| python3 -c "from lightsim2grid.network import LSGrid" | |
| - name: Fix urllib3 (python 3.7) | |
| if: matrix.python.name == 'cp37' | |
| run: | |
| pip install urllib3==1.26.6 | |
| # otherwise urllib3 v2.0 only supports OpenSSL 1.1.1+, currently the 'ssl' module is compiled with 'OpenSSL 1.0.2k-fips 26 Jan 2017' | |
| - name: Install grid2op | |
| if: matrix.python.name != 'cp313' # pandapower does not support 3.13, so grid2op does not so I cannot test that for 3.13 | |
| run: | | |
| python3 -m pip install grid2op pandapower lxml # lxml missing import see https://github.com/e2nIEE/pandapower/issues/2752 | |
| python3 -m pip freeze | |
| - name: Check extra can be imported can be imported (with grid2op) | |
| if: matrix.python.name != 'cp313' # pandapower does not support 3.13, so grid2op does not so I cannot test that for 3.13 | |
| run: | | |
| cd tmp_for_import_checking | |
| python3 -v -c "from lightsim2grid import LightSimBackend" | |
| python3 -c "from lightsim2grid.timeSerie import TimeSerie" | |
| python3 -c "from lightsim2grid.contingencyAnalysis import ContingencyAnalysis" | |
| python3 -c "from lightsim2grid.physical_law_checker import PhysicalLawChecker" | |
| python3 -c "from lightsim2grid.securityAnalysis import SecurityAnalysis" | |
| python3 -c "from lightsim2grid.network import init_from_pandapower" | |
| - name: Check LightSimBackend can be used to create env | |
| if: matrix.python.name != 'cp313' # pandapower does not support 3.13, so grid2op does not so I cannot test that for 3.13 | |
| run: | | |
| cd tmp_for_import_checking | |
| python3 -v -c "from lightsim2grid import LightSimBackend; import grid2op; env = grid2op.make('l2rpn_case14_sandbox', test=True, backend=LightSimBackend())" | |
| - name: Upload wheel | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: lightsim2grid-wheel-linux-${{ matrix.python.name }}-${{ matrix.cont.name }} | |
| path: wheelhouse/*.whl | |
| - name: Upload source archive | |
| uses: actions/upload-artifact@v4 | |
| if: matrix.python.name == 'cp312' | |
| with: | |
| name: lightsim2grid-sources | |
| path: dist/*.tar.gz | |
| windows_build: | |
| # build wheels for windows | |
| name: Build windows ${{ matrix.python.name }} wheel for ${{ matrix.win_arch.msvc}} | |
| runs-on: windows-2022 | |
| strategy: | |
| matrix: | |
| python: | |
| # - { | |
| # name: cp37, | |
| # version: '3.7', | |
| # } | |
| # - { | |
| # name: cp38, | |
| # version: '3.8', | |
| # } | |
| - { | |
| name: cp39, | |
| version: '3.9', | |
| } | |
| - { | |
| name: cp310, | |
| version: '3.10', | |
| } | |
| - { | |
| name: cp311, | |
| version: '3.11', | |
| } | |
| - { | |
| name: cp312, | |
| version: '3.12', | |
| } | |
| - { | |
| name: cp313, | |
| version: '3.13', | |
| } | |
| - { | |
| name: cp314, | |
| version: '3.14', | |
| } | |
| win_arch: | |
| - { | |
| name: "AMD64", | |
| msvc: x64 | |
| } | |
| # - { | |
| # name: "x86", | |
| # msvc: x86 | |
| # } | |
| env: | |
| RUNNER_OS: windows-2022 | |
| PYTHON_VERSION: ${{ matrix.python.version }} | |
| steps: | |
| - name: Checkout sources | |
| uses: actions/checkout@v4 | |
| with: | |
| submodules: true | |
| - name: Setup Python ${{ matrix.python.version }} ${{ matrix.win_arch.msvc}} | |
| uses: actions/setup-python@v5 | |
| with: | |
| python-version: ${{ matrix.python.version }} | |
| architecture: ${{ matrix.win_arch.msvc}} | |
| - name: Setup MSVC ${{ matrix.win_arch.msvc}} | |
| uses: bus1/cabuild/action/msdevshell@e22aba57d6e74891d059d66501b6b5aed8123c4d # v1 | |
| with: | |
| architecture: ${{ matrix.win_arch.msvc}} | |
| - name: Install Python dependencies | |
| run: | | |
| python3 -m pip install --upgrade pip | |
| python3 -m pip install -r requirements_compile_ci.txt | |
| python3 -m pip freeze | |
| - name: Build wheel | |
| run: python -m pip wheel --verbose . --no-deps -w dist | |
| - name: Install wheel | |
| shell: bash | |
| run: python -m pip install dist/*.whl --user | |
| - name: Check package can be imported (bare install, default numpy) | |
| run: | | |
| mkdir tmp_for_import_checking | |
| cd tmp_for_import_checking | |
| python3 -c "import lightsim2grid" | |
| python3 -c "from lightsim2grid import *" | |
| python3 -c "from lightsim2grid.newtonpf import newtonpf" | |
| python3 -c "from lightsim2grid.timeSerie import TimeSeriesCPP" | |
| python3 -c "from lightsim2grid.contingencyAnalysis import ContingencyAnalysisCPP" | |
| python3 -c "from lightsim2grid.securityAnalysis import SecurityAnalysisCPP" | |
| python3 -c "from lightsim2grid.network import LSGrid" | |
| - name: Check package can be imported (bare install, numpy < 2) | |
| if: matrix.python.name != 'cp37' && matrix.python.name != 'cp38' && matrix.python.name != 'cp313' && matrix.python.name != 'cp314' | |
| run: | | |
| python3 -m pip install "numpy<2" scipy | |
| cd tmp_for_import_checking | |
| python3 -c "import lightsim2grid" | |
| python3 -c "from lightsim2grid import *" | |
| python3 -c "from lightsim2grid.newtonpf import newtonpf" | |
| python3 -c "from lightsim2grid.timeSerie import TimeSeriesCPP" | |
| python3 -c "from lightsim2grid.contingencyAnalysis import ContingencyAnalysisCPP" | |
| python3 -c "from lightsim2grid.securityAnalysis import SecurityAnalysisCPP" | |
| python3 -c "from lightsim2grid.network import LSGrid" | |
| python3 -m pip install --upgrade numpy | |
| - name: Check LightSimBackend can be imported (with grid2op) | |
| if: matrix.python.name != 'cp314' # pandapower does not support 3.14, so grid2op does not so I cannot test that for 3.14 | |
| run: | | |
| python -m pip install grid2op lxml # lxml missing import see https://github.com/e2nIEE/pandapower/issues/2752 | |
| cd tmp_for_import_checking | |
| python -c "from lightsim2grid import LightSimBackend" | |
| python -c "from lightsim2grid import LightSimBackend; import grid2op; env = grid2op.make('l2rpn_case14_sandbox', test=True, backend=LightSimBackend())" | |
| python -c "from lightsim2grid.timeSerie import TimeSerie" | |
| python -c "from lightsim2grid.contingencyAnalysis import ContingencyAnalysis" | |
| python -c "from lightsim2grid.physical_law_checker import PhysicalLawChecker" | |
| python -c "from lightsim2grid.securityAnalysis import SecurityAnalysis" | |
| python -c "from lightsim2grid.network import init_from_pandapower" | |
| - name: Check LightSimBackend can be used to create env | |
| if: matrix.python.name != 'cp314' # pandapower does not support 3.14, so grid2op does not so I cannot test that for 3.14 | |
| run: | | |
| cd tmp_for_import_checking | |
| python3 -v -c "from lightsim2grid import LightSimBackend; import grid2op; env = grid2op.make('l2rpn_case14_sandbox', test=True, backend=LightSimBackend())" | |
| # - name: Debug windows CI | |
| # run: | | |
| # python -m unittest lightsim2grid.tests.test_n1contingencyrewards.TestN1ContingencyReward_Base.test_do_nothing | |
| - name: Upload wheel | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: lightsim2grid-wheel-win-${{ matrix.python.name }}-${{ matrix.win_arch.msvc}} | |
| path: dist/*.whl | |
| macos_build_37_: | |
| ## build wheel for python 3.7 and above for macos (only >= 3.10 for arm64 ) | |
| name: Build darwin ${{ matrix.python.name }} wheel on ${{ matrix.runner.arch}} | |
| runs-on: ${{ matrix.runner.name }} | |
| strategy: | |
| matrix: | |
| python: | |
| # - { | |
| # name: cp37, | |
| # version: '3.7', | |
| # } | |
| # - { | |
| # name: cp38, | |
| # version: '3.8', | |
| # } | |
| - { | |
| name: cp39, | |
| version: '3.9', | |
| } | |
| - { | |
| name: cp310, | |
| version: '3.10', | |
| } | |
| - { | |
| name: cp311, | |
| version: '3.11', | |
| } | |
| - { | |
| name: cp312, | |
| version: '3.12', | |
| } | |
| - { | |
| name: cp313, | |
| version: '3.13', | |
| } | |
| - { | |
| name: cp314, | |
| version: '3.14', | |
| } | |
| runner: | |
| - { | |
| name: macos-15-intel, | |
| arch: x86_64 | |
| } | |
| - { | |
| name: macos-14, | |
| arch: arm64 | |
| } | |
| exclude: | |
| - python: # does not work | |
| name: cp37 | |
| runner: | |
| arch: arm64 | |
| - python: # does not work | |
| name: cp38 | |
| runner: | |
| arch: arm64 | |
| - python: # does not work | |
| name: cp39 | |
| runner: | |
| arch: arm64 | |
| env: | |
| RUNNER_OS: ${{ matrix.runner.name }} | |
| PYTHON_VERSION: ${{ matrix.python.version }} | |
| steps: | |
| - name: Checkout sources | |
| uses: actions/checkout@v4 | |
| with: | |
| submodules: true | |
| - name: Setup Python | |
| uses: actions/setup-python@v5 | |
| with: | |
| python-version: ${{ matrix.python.version }} | |
| - name: Install Python dependencies | |
| run: | | |
| python -m pip install --upgrade pip | |
| python -m pip install -r requirements_compile_ci.txt | |
| python -m pip freeze | |
| - name: Build wheel | |
| run: python -m pip wheel --verbose . --no-deps -w dist | |
| - name: Install wheel | |
| shell: bash | |
| run: | | |
| python -m pip install dist/*.whl --user | |
| python -m pip freeze | |
| - name: Install packaging (python 3.8) | |
| if: matrix.python.name == 'cp38' | |
| run: python -m pip install packaging | |
| - name: Check package can be imported (bare install, default numpy) | |
| run: | | |
| mkdir tmp_for_import_checking | |
| cd tmp_for_import_checking | |
| python -c "import lightsim2grid" | |
| python -c "from lightsim2grid import *" | |
| python -c "from lightsim2grid.newtonpf import newtonpf" | |
| python -c "from lightsim2grid.timeSerie import TimeSeriesCPP" | |
| python -c "from lightsim2grid.contingencyAnalysis import ContingencyAnalysisCPP" | |
| python -c "from lightsim2grid.securityAnalysis import SecurityAnalysisCPP" | |
| python -c "from lightsim2grid.network import LSGrid" | |
| - name: Check package can be imported (bare install) | |
| if: matrix.python.name != 'cp37' && matrix.python.name != 'cp38' | |
| run: | | |
| cd tmp_for_import_checking | |
| python3 -c "import lightsim2grid" | |
| python3 -c "from lightsim2grid import *" | |
| python3 -c "from lightsim2grid.newtonpf import newtonpf" | |
| python3 -c "from lightsim2grid.timeSerie import TimeSeriesCPP" | |
| python3 -c "from lightsim2grid.contingencyAnalysis import ContingencyAnalysisCPP" | |
| python3 -c "from lightsim2grid.securityAnalysis import SecurityAnalysisCPP" | |
| python3 -c "from lightsim2grid.network import LSGrid" | |
| - name: Fix urllib3 (python 3.7) | |
| if: matrix.python.name == 'cp37' | |
| run: | |
| pip install urllib3==1.26.6 | |
| # otherwise urllib3 v2.0 only supports OpenSSL 1.1.1+, currently the 'ssl' module is compiled with 'OpenSSL 1.0.2k-fips 26 Jan 2017' | |
| - name: Install grid2op | |
| if: matrix.python.name != 'cp314' || matrix.runner.arch != 'x86_64' | |
| # grid2op does not work on darwin cp34 wheel on macos on x86_64 | |
| # probably because of pandapower | |
| run: | | |
| python -m pip install grid2op lxml # lxml missing import see https://github.com/e2nIEE/pandapower/issues/2752 | |
| python -m pip freeze | |
| - name: Check extra can be imported can be imported (with grid2op) | |
| if: matrix.python.name != 'cp314' || matrix.runner.arch != 'x86_64' | |
| # grid2op does not work on darwin cp34 wheel on macos on x86_64 | |
| # probably because of pandapower | |
| run: | | |
| cd tmp_for_import_checking | |
| python -v -c "from lightsim2grid import LightSimBackend" | |
| python -c "from lightsim2grid.timeSerie import TimeSerie" | |
| python -c "from lightsim2grid.contingencyAnalysis import ContingencyAnalysis" | |
| python -c "from lightsim2grid.physical_law_checker import PhysicalLawChecker" | |
| python -c "from lightsim2grid.securityAnalysis import SecurityAnalysis" | |
| python -c "from lightsim2grid.network import init_from_pandapower" | |
| - name: Check LightSimBackend can be used to create env | |
| if: matrix.python.name != 'cp314' || matrix.runner.arch != 'x86_64' | |
| # grid2op does not work on darwin cp34 wheel on macos on x86_64 | |
| # probably because of pandapower | |
| run: | | |
| cd tmp_for_import_checking | |
| python -v -c "from lightsim2grid import LightSimBackend; import grid2op; env = grid2op.make('l2rpn_case14_sandbox', test=True, backend=LightSimBackend())" | |
| - name: Upload wheel | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: lightsim2grid-wheel-darwin-${{ matrix.python.name }}-${{ matrix.runner.arch}} | |
| path: dist/*.whl | |
| exotic_build: | |
| # build wheel using emulation for "exotic"things | |
| # see https://github.com/cvxpy/cvxpy/blob/master/.github/workflows/build.yml | |
| name: Build ${{ matrix.runner.name }} ${{ matrix.python.name }} wheel with cibuildwheel | |
| runs-on: ${{ matrix.runner.name }} | |
| strategy: | |
| matrix: | |
| runner: | |
| - { | |
| name: macos-14, # host on arm64 | |
| whl_nm: macos_arm64, | |
| cibuildwheel: macos | |
| } | |
| - { | |
| name: windows-2022, # host on x86_64 | |
| whl_nm: windows_arm64, | |
| cibuildwheel: windows | |
| } | |
| # - { | |
| # name: ubuntu-latest, # host on x86_64 # takes forever, like 20 mins x 2 at least | |
| # whl_nm: linux_arm64, | |
| # cibuildwheel: linux | |
| # } | |
| python: | |
| # - { | |
| # name: cp38, | |
| # version: '3.8', | |
| # } | |
| - { | |
| name: cp39, | |
| version: '3.9', | |
| } | |
| - { | |
| name: cp310, | |
| version: '3.10', | |
| } | |
| - { | |
| name: cp311, | |
| version: '3.11', | |
| } | |
| - { | |
| name: cp312, | |
| version: '3.12', | |
| } | |
| - { | |
| name: cp313, | |
| version: '3.13', | |
| } | |
| - { | |
| name: cp314, | |
| version: '3.14', | |
| } | |
| exclude: | |
| - python: | |
| name: cp310 # because already done natively above | |
| runner: | |
| name: macos-14 | |
| - python: | |
| name: cp311 # because already done natively above | |
| runner: | |
| name: macos-14 | |
| - python: | |
| name: cp312 # because already done natively above | |
| runner: | |
| name: macos-14 | |
| - python: | |
| name: cp313 # because already done natively above | |
| runner: | |
| name: macos-14 | |
| - python: | |
| name: cp314 # because already done natively above | |
| runner: | |
| name: macos-14 | |
| - python: | |
| name: cp38 # does not work | |
| runner: | |
| name: windows-2022 | |
| env: | |
| RUNNER_OS: ${{ matrix.runner.name }} | |
| PYTHON_VERSION: ${{ matrix.python.version }} | |
| steps: | |
| - name: Checkout sources | |
| uses: actions/checkout@v4 | |
| with: | |
| submodules: true | |
| - name: Set up QEMU | |
| if: runner.os == 'Linux' | |
| uses: docker/setup-qemu-action@c7c53464625b32c7a7e944ae62b3e17d2b600130 # v3.7.0 | |
| with: | |
| platforms: all | |
| - name: Compile with cibuildwheel | |
| uses: pypa/cibuildwheel@63fd63b352a9a8bdcc24791c9dbee952ee9a8abc # v3.3.0 | |
| env: | |
| CIBW_PLATFORM: "${{ matrix.runner.cibuildwheel}}" | |
| CIBW_BUILD: "${{ matrix.python.name}}-*" | |
| CIBW_ARCHS_LINUX: aarch64 | |
| CIBW_ARCHS_MACOS: arm64 | |
| CIBW_ARCHS_WINDOWS: ARM64 | |
| CIBW_ENVIRONMENT: __O3_OPTIM=1 | |
| CIBW_TEST_REQUIRES: grid2op pandapower | |
| CIBW_TEST_SKIP: "*-macosx_arm64 *-win_arm64" # to silence warning "While arm64 wheels can be built on x86_64, they cannot be tested." | |
| CIBW_TEST_COMMAND: > | |
| python -c "import lightsim2grid" && | |
| python -c "from lightsim2grid import *" && | |
| python -c "from lightsim2grid.newtonpf import newtonpf" && | |
| python -c "from lightsim2grid.timeSerie import TimeSeriesCPP, TimeSerie" && | |
| python -c "from lightsim2grid.contingencyAnalysis import ContingencyAnalysisCPP, ContingencyAnalysis" && | |
| python -c "from lightsim2grid.securityAnalysis import SecurityAnalysisCPP, SecurityAnalysis" && | |
| python -c "from lightsim2grid.network import LSGrid, init_from_pandapower" && | |
| python -c "from lightsim2grid import LightSimBackend" && | |
| python -c "from lightsim2grid.physical_law_checker import PhysicalLawChecker" | |
| - name: Upload wheel | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: lightsim2grid-wheel-exotic-${{ matrix.runner.whl_nm}}-${{ matrix.python.name }} | |
| path: ./wheelhouse/*.whl | |
| test_cmake_standalone: | |
| name: Test standalone cmake build — ${{ matrix.os }} | |
| runs-on: ${{ matrix.os }} | |
| strategy: | |
| matrix: | |
| os: [ubuntu-latest, windows-2022, macos-14] | |
| steps: | |
| - uses: actions/checkout@v4 | |
| with: | |
| submodules: true | |
| - name: Setup MSVC (windows) | |
| if: runner.os == 'Windows' | |
| uses: bus1/cabuild/action/msdevshell@e22aba57d6e74891d059d66501b6b5aed8123c4d | |
| with: | |
| architecture: x64 | |
| - name: Configure + build lightsim2grid_core | |
| run: | | |
| cmake -S src/core -B _build_core -DCMAKE_BUILD_TYPE=Release | |
| cmake --build _build_core --config Release | |
| - name: Install | |
| run: cmake --install _build_core --prefix _install --config Release | |
| - name: Verify installed layout (unix) | |
| if: runner.os != 'Windows' | |
| run: | | |
| ls _install/lib/*lightsim2grid_core* || ls _install/lib64/*lightsim2grid_core* | |
| ls _install/include/lightsim2grid/LSGrid.hpp | |
| ls _install/lib/cmake/lightsim2grid_core/lightsim2grid_coreConfig.cmake | |
| - name: Verify installed layout (windows) | |
| if: runner.os == 'Windows' | |
| shell: bash | |
| run: | | |
| ls _install/lib/lightsim2grid_core* || ls _install/bin/lightsim2grid_core* | |
| ls _install/include/lightsim2grid/LSGrid.hpp | |
| ls _install/lib/cmake/lightsim2grid_core/lightsim2grid_coreConfig.cmake | |
| - name: Build minimal consumer via find_package | |
| shell: bash | |
| run: | | |
| mkdir -p _test_consumer | |
| cat > _test_consumer/CMakeLists.txt << 'EOF' | |
| cmake_minimum_required(VERSION 3.15) | |
| project(consumer CXX) | |
| set(CMAKE_CXX_STANDARD 14) | |
| find_package(lightsim2grid_core CONFIG REQUIRED) | |
| add_executable(consumer consumer.cpp) | |
| target_link_libraries(consumer PRIVATE lightsim2grid::core) | |
| EOF | |
| cat > _test_consumer/consumer.cpp << 'EOF' | |
| #include <AlgorithmRegistry.hpp> | |
| int main() { auto& r = ls2g::AlgorithmRegistry::instance(); return r.available_algorithm_names().empty() ? 1 : 0; } | |
| EOF | |
| cmake -S _test_consumer -B _build_consumer \ | |
| -DCMAKE_PREFIX_PATH="$(pwd)/_install" \ | |
| -DCMAKE_BUILD_TYPE=Release | |
| cmake --build _build_consumer --config Release | |
| test_plugin_against_installed: | |
| name: Test plugin against pip-installed — ${{ matrix.os }} | |
| runs-on: ${{ matrix.os }} | |
| strategy: | |
| matrix: | |
| os: [ubuntu-latest, windows-2022, macos-14] | |
| steps: | |
| - uses: actions/checkout@v4 | |
| with: | |
| submodules: true | |
| - uses: actions/setup-python@v5 | |
| with: | |
| python-version: '3.12' | |
| - name: Setup MSVC (windows) | |
| if: runner.os == 'Windows' | |
| uses: bus1/cabuild/action/msdevshell@e22aba57d6e74891d059d66501b6b5aed8123c4d | |
| with: | |
| architecture: x64 | |
| - name: Install lightsim2grid | |
| run: | | |
| python -m pip install --upgrade pip | |
| python -m pip install -r requirements_compile_ci.txt | |
| python -m pip install -v . --no-build-isolation | |
| - name: Build plugin via get_cmake_dir() | |
| shell: bash | |
| run: | | |
| mkdir -p _tmp_cmake_dir | |
| LS2G_CMAKE=$(cd _tmp_cmake_dir && python -c "import lightsim2grid; print(lightsim2grid.get_cmake_dir())") | |
| cmake -S examples/external_algorithm -B examples/external_algorithm/build \ | |
| -DLIGHTSIM2GRID_CMAKE_DIR="$LS2G_CMAKE" \ | |
| -DCMAKE_BUILD_TYPE=Release | |
| cmake --build examples/external_algorithm/build --config Release | |
| - name: Run plugin test | |
| run: python examples/external_algorithm/test_plugin.py | |
| - name: Run plugin registration unittests (against the installed package) | |
| shell: bash | |
| # Run from the scratch dir so `import lightsim2grid` resolves to the | |
| # pip-installed package, not the source tree (which has no built | |
| # extension). LS2G_TEST_PLUGIN_DIR points the tests at the plugin built | |
| # above; the finders pick the right per-platform file name themselves. | |
| working-directory: _tmp_cmake_dir | |
| env: | |
| LS2G_TEST_PLUGIN_DIR: ${{ github.workspace }}/examples/external_algorithm/build | |
| run: | | |
| python -m unittest -v \ | |
| lightsim2grid.tests.test_solver_registry \ | |
| lightsim2grid.tests.test_plugin_registration | |
| test_klu_strategies: | |
| name: Test KLU detection strategies (Ubuntu) | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@v4 | |
| with: | |
| submodules: true | |
| - uses: actions/setup-python@v5 | |
| with: | |
| python-version: '3.12' | |
| - name: Install Python build dependencies | |
| run: | | |
| python -m pip install --upgrade pip | |
| python -m pip install -r requirements_compile_ci.txt | |
| # ── Strategy 4: build KLU from SuiteSparse submodule CMakeLists ──────── | |
| # Submodule present but no pre-built .a files → CMake strategy 4 triggers | |
| - name: "[Strategy 4] Install lightsim2grid" | |
| run: python -m pip install -v . --no-build-isolation | |
| - name: "[Strategy 4] Assert KLU solver is available" | |
| run: | | |
| mkdir -p _klu_check | |
| cd _klu_check | |
| python -c " | |
| from lightsim2grid.lightsim2grid_cpp import klu_solver_available | |
| assert klu_solver_available, 'KLU solver not available (strategy 4 failed)' | |
| print('Strategy 4 OK: KLU available') | |
| " | |
| - name: "[Strategy 4] Uninstall lightsim2grid" | |
| run: pip uninstall lightsim2grid -y | |
| # ── Strategy 3: pre-built .a files in SuiteSparse submodule ──────────── | |
| # `make` compiles KLU static libs; CMake finds them via strategy 3 | |
| - name: "[Strategy 3] Compile KLU static libraries" | |
| run: make | |
| - name: "[Strategy 3] Install lightsim2grid" | |
| run: python -m pip install -v . --no-build-isolation | |
| - name: "[Strategy 3] Assert KLU solver is available" | |
| run: | | |
| cd _klu_check | |
| python -c " | |
| from lightsim2grid.lightsim2grid_cpp import klu_solver_available | |
| assert klu_solver_available, 'KLU solver not available (strategy 3 failed)' | |
| print('Strategy 3 OK: KLU available') | |
| " | |
| - name: "[Strategy 3] Uninstall lightsim2grid" | |
| run: pip uninstall lightsim2grid -y | |
| - name: "[Strategy 3] Clean compiled KLU static libraries" | |
| run: make distclean | |
| # ── Strategy 1: system-wide KLU via apt ──────────────────────────────── | |
| # libsuitesparse-dev on Ubuntu 24.04 ships CMake config files → strategy 1 | |
| # SuiteSparse submodule removed so strategies 3 & 4 cannot interfere | |
| - name: "[Strategy 1] Install libsuitesparse-dev" | |
| run: sudo apt-get install -y libsuitesparse-dev | |
| - name: "[Strategy 1] Remove SuiteSparse submodule" | |
| run: rm -rf SuiteSparse | |
| - name: "[Strategy 1] Install lightsim2grid" | |
| run: python -m pip install -v . --no-build-isolation | |
| - name: "[Strategy 1] Assert KLU solver is available" | |
| run: | | |
| cd _klu_check | |
| python -c " | |
| from lightsim2grid.lightsim2grid_cpp import klu_solver_available | |
| assert klu_solver_available, 'KLU solver not available (strategy 1 failed)' | |
| print('Strategy 1 OK: KLU available') | |
| " | |
| test_march_native: | |
| # -march=native is a supported opt-in build flag (see benchmarks/env_compile_all.sh) | |
| # that release wheels do not use, so plain CI builds never exercise it. It changes | |
| # which SIMD ISA Eigen sees enabled (__AVX__, __AVX2__, ...) in each translation | |
| # unit; lightsim2grid_core and lightsim2grid_cpp (the pybind11 bindings) are two | |
| # separate shared libraries, so both must see the identical flag -- otherwise an | |
| # Eigen object allocated in one and freed in the other computes a different | |
| # alignment offset, corrupting the heap ("double free or corruption") the first | |
| # time a function's return value crosses the module boundary (e.g. any pandapower | |
| # -> LightSimBackend conversion, or a forecast-backend copy). Regression test for | |
| # that class of bug: env creation reliably crashed within seconds before the fix. | |
| name: Test -march=native build (Ubuntu) | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@v4 | |
| with: | |
| submodules: true | |
| - uses: actions/setup-python@v5 | |
| with: | |
| python-version: '3.12' | |
| - name: Install Python dependencies | |
| run: | | |
| python -m pip install --upgrade pip | |
| python -m pip install -r requirements_compile_ci.txt | |
| python -m pip install grid2op pandapower lxml | |
| - name: Build lightsim2grid with -march=native | |
| run: __COMPILE_MARCHNATIVE=1 __O3_OPTIM=1 python -m pip install -v . --no-build-isolation | |
| - name: Create + reset a LightSimBackend env (exercises the core<->bindings Eigen boundary) | |
| run: | | |
| mkdir -p _march_native_check | |
| cd _march_native_check | |
| python -c " | |
| import warnings | |
| from grid2op import make | |
| from grid2op.Parameters import Parameters | |
| from lightsim2grid import LightSimBackend | |
| param = Parameters() | |
| param.init_from_dict({'NO_OVERFLOW_DISCONNECTION': True, 'ENV_DC': True, 'FORECAST_DC': True}) | |
| with warnings.catch_warnings(): | |
| warnings.filterwarnings('ignore') | |
| env = make('l2rpn_case14_sandbox', backend=LightSimBackend(), param=param, test=True) | |
| env.reset() | |
| print('OK: env created and reset under -march=native without crashing') | |
| " | |
| package: | |
| name: Package wheels | |
| runs-on: ubuntu-latest | |
| needs: [exotic_build, macos_build_37_, windows_build, manylinux_build] | |
| steps: | |
| - name: Download wheels | |
| uses: actions/download-artifact@v4 | |
| with: | |
| path: download | |
| - name: Verify wheel and sdist count | |
| run: | | |
| WHEEL_COUNT=$(find download/ -name "*.whl" | wc -l | tr -d ' ') | |
| SDIST_COUNT=$(find download/ -name "*.tar.gz" | wc -l | tr -d ' ') | |
| echo "Found ${WHEEL_COUNT} wheel(s), expected ${{ env.EXPECTED_WHEELS }}." | |
| echo "Found ${SDIST_COUNT} sdist(s), expected ${{ env.EXPECTED_SDIST }}." | |
| if [ "${WHEEL_COUNT}" -ne "${{ env.EXPECTED_WHEELS }}" ] || \ | |
| [ "${SDIST_COUNT}" -ne "${{ env.EXPECTED_SDIST }}" ]; then | |
| echo "::error::Wheel count mismatch: found ${WHEEL_COUNT} wheels \ | |
| and ${SDIST_COUNT} sdist(s), expected ${{ env.EXPECTED_WHEELS }} wheels \ | |
| and ${{ env.EXPECTED_SDIST }} sdist(s). A Python version was probably \ | |
| added or removed from the build matrix without updating EXPECTED_WHEELS, \ | |
| or one of the build jobs silently failed and produced no wheel. \ | |
| Fix the matrix and the EXPECTED_WHEELS constant together — this mismatch \ | |
| will prevent the PyPI release workflow (publish.yml) from running." | |
| echo "" | |
| echo "--- Wheels found ---" | |
| find download/ -name "*.whl" | sort | |
| echo "--- Sdists found ---" | |
| find download/ -name "*.tar.gz" | sort | |
| exit 1 | |
| fi | |
| echo "✓ All ${{ env.EXPECTED_WHEELS }} wheels and ${{ env.EXPECTED_SDIST }} sdist accounted for." | |
| - name: Upload wheels | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: lightsim2grid-wheels | |
| retention-days: 90 | |
| path: | | |
| download/**/*.whl | |
| download/**/*.tar.gz |