Run notebooks in Jupyter Lite as part of ci (Emscripten xeus-cpp automated testing) #2541
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: | |
| workflow_dispatch: | |
| pull_request: | |
| branches: | |
| - main | |
| push: | |
| branches: | |
| - main | |
| schedule: | |
| - cron: '30 20 * * *' # Warning: Timezone dep - 20:00 is 1:00 | |
| concurrency: | |
| group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.run_id }} | |
| cancel-in-progress: true | |
| jobs: | |
| build: | |
| runs-on: ${{ matrix.os }} | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| include: | |
| - name: ubu24 | |
| os: ubuntu-24.04 | |
| micromamba_shell_init: bash | |
| - name: ubu24-arm | |
| os: ubuntu-24.04-arm | |
| micromamba_shell_init: bash | |
| - name: ubu24-analyzers | |
| os: ubuntu-24.04 | |
| coverage: true | |
| debug: on | |
| micromamba_shell_init: bash | |
| - name: ubu22 | |
| os: ubuntu-22.04 | |
| micromamba_shell_init: bash | |
| - name: ubu22-arm | |
| os: ubuntu-22.04-arm | |
| micromamba_shell_init: bash | |
| - name: osx15-x86 | |
| os: macos-15-intel | |
| micromamba_shell_init: bash | |
| - name: osx14-arm | |
| os: macos-14 | |
| micromamba_shell_init: bash | |
| - name: osx15-arm | |
| os: macos-15 | |
| micromamba_shell_init: bash | |
| - name: osx26-arm | |
| os: macos-26 | |
| micromamba_shell_init: bash | |
| - name: Windows22 | |
| os: windows-2022 | |
| micromamba_shell_init: cmd.exe | |
| - name: Windows25 | |
| os: windows-2025 | |
| micromamba_shell_init: cmd.exe | |
| steps: | |
| - uses: actions/checkout@v5 | |
| with: | |
| fetch-depth: 0 | |
| - name: install mamba | |
| uses: mamba-org/setup-micromamba@main | |
| with: | |
| environment-file: environment-dev.yml | |
| init-shell: >- | |
| ${{ matrix.micromamba_shell_init }} | |
| environment-name: xeus-cpp | |
| - name: Setup default Build Type on *nux | |
| if: ${{ runner.os != 'windows' }} | |
| run: | | |
| os="${{ matrix.os }}" | |
| if [[ "${{ matrix.debug }}" == "on" ]]; then | |
| echo "BUILD_TYPE=Debug" >> $GITHUB_ENV | |
| fi | |
| if [[ "${os}" == "macos"* ]]; then | |
| echo "ncpus=$(sysctl -n hw.ncpu)" >> $GITHUB_ENV | |
| else | |
| echo "ncpus=$(nproc --all)" >> $GITHUB_ENV | |
| fi | |
| - name: Setup default Build Type on Windows | |
| if: ${{ runner.os == 'windows' }} | |
| run: | | |
| $env:ncpus=$([Environment]::ProcessorCount) | |
| echo "ncpus=$env:ncpus" >> $env:GITHUB_ENV | |
| - name: micromamba shell hook | |
| if: ${{ runner.os == 'windows' }} | |
| shell: powershell | |
| run: | | |
| micromamba shell hook -s cmd.exe --root-prefix C:\Users\runneradmin\micromamba-root | |
| - name: cmake configure | |
| if: ${{ runner.os == 'windows' }} | |
| shell: cmd /C call {0} | |
| run: | | |
| call C:\Users\runneradmin\micromamba-root\condabin\micromamba.bat activate xeus-cpp | |
| mkdir -p build | |
| cd build | |
| cmake .. -G "NMake Makefiles" -DCMAKE_BUILD_TYPE=Release -DXEUS_BUILD_TESTS=ON -DDEPENDENCY_SEARCH_PREFIX="%CONDA_PREFIX%\Library" -DCMAKE_PREFIX_PATH="%CONDA_PREFIX%\Library" -DCMAKE_INSTALL_PREFIX="%CONDA_PREFIX%" | |
| - name: cmake configure | |
| if: ${{ runner.os != 'windows' }} | |
| shell: bash -l {0} | |
| run: | | |
| mkdir -p build | |
| cd build | |
| cmake .. \ | |
| -DCMAKE_PREFIX_PATH=$CONDA_PREFIX \ | |
| -DCMAKE_INSTALL_PREFIX=$CONDA_PREFIX \ | |
| -DXEUS_CPP_ENABLE_CODE_COVERAGE=${{ matrix.coverage }} \ | |
| -DCMAKE_COMPILE_WARNING_AS_ERROR=ON \ | |
| -DCMAKE_BUILD_TYPE=${{ env.BUILD_TYPE }} | |
| - name: build, run C++ tests & install | |
| if: ${{ runner.os == 'windows' }} | |
| shell: cmd /C call {0} | |
| run: | | |
| call C:\Users\runneradmin\micromamba-root\condabin\micromamba.bat activate xeus-cpp | |
| cd build | |
| set CL=/MP | |
| nmake check-xeus-cpp | |
| nmake install | |
| - name: build, run C++ tests & install | |
| if: ${{ runner.os != 'windows' }} | |
| shell: bash -l {0} | |
| run: | | |
| cd build | |
| make install -j ${{ env.ncpus }} | |
| make -j ${{ env.ncpus }} check-xeus-cpp | |
| if [[ "${{ matrix.os }}" != "macos"* && "${{ matrix.debug }}" == "on" ]]; then | |
| sudo apt update | |
| sudo apt install libc6-dbg | |
| micromamba install -c conda-forge valgrind | |
| valgrind --show-error-list=yes --track-origins=yes --error-exitcode=1 \ | |
| --show-leak-kinds=definite,possible \ | |
| --gen-suppressions=all \ | |
| --suppressions="../etc/xeus-cpp-valgrind_x86.supp" \ | |
| test/test_xeus_cpp | |
| fi | |
| - name: Python tests Unix Systems | |
| if: ${{ runner.os != 'windows' }} | |
| shell: bash -l {0} | |
| run: | | |
| cd test | |
| pytest -sv . | |
| - name: Python tests Windows Systems | |
| if: ${{ runner.os == 'windows' }} | |
| shell: cmd /C call {0} | |
| run: | | |
| call C:\Users\runneradmin\micromamba-root\condabin\micromamba.bat activate xeus-cpp | |
| cd test | |
| pytest -sv test_xcpp_kernel.py | |
| - name: Prepare code coverage report | |
| if: ${{ success() && (matrix.coverage == true) }} | |
| shell: bash -l {0} | |
| run: | | |
| # Create lcov report | |
| # Find the current compiler version. | |
| CC=$(realpath `which c++`) | |
| vers="${CC##*-}" | |
| sudo apt install lcov | |
| # capture coverage info | |
| lcov --directory build/ --capture --output-file coverage.info --gcov-tool $CONDA_PREFIX/bin/gcov | |
| lcov --remove coverage.info '/usr/*' "${HOME}"'/.cache/*' ${{ github.workspace }}'/test/*' --output-file coverage.info | |
| # output coverage data for debugging (optional) | |
| lcov --list coverage.info | |
| - name: Upload to codecov.io | |
| if: ${{ success() && (matrix.coverage == true) }} | |
| uses: codecov/codecov-action@v5 | |
| with: | |
| files: ./coverage.info | |
| fail_ci_if_error: true | |
| verbose: true | |
| token: ${{ secrets.CODECOV_TOKEN }} | |
| - name: Setup tmate session | |
| if: ${{ failure() && runner.debug }} | |
| uses: mxschmitt/action-tmate@v3 | |
| # When debugging increase to a suitable value! | |
| timeout-minutes: 30 | |
| emscripten_wasm: | |
| runs-on: ${{ matrix.os }} | |
| name: ${{ matrix.os}}-${{ matrix.notebook }}-${{ matrix.kernel }} | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| os: [ubuntu-24.04, macos-15] | |
| notebook: [smallpt.ipynb, xeus-cpp-lite-demo.ipynb] | |
| kernel: [C++17,C++20,C++23] | |
| steps: | |
| - uses: actions/checkout@v5 | |
| with: | |
| fetch-depth: 0 | |
| - name: install mamba | |
| uses: mamba-org/setup-micromamba@main | |
| with: | |
| environment-file: environment-wasm-build.yml | |
| init-shell: bash | |
| environment-name: xeus-cpp-wasm-build | |
| - name: Setup default Build Type on *nux | |
| if: ${{ runner.os != 'windows' }} | |
| run: | | |
| os="${{ matrix.os }}" | |
| if [[ "${os}" == "macos"* ]]; then | |
| echo "ncpus=$(sysctl -n hw.ncpu)" >> $GITHUB_ENV | |
| else | |
| echo "ncpus=$(nproc --all)" >> $GITHUB_ENV | |
| fi | |
| - name: Build and test xeus-cpp in node, then install | |
| shell: bash -l {0} | |
| run: | | |
| micromamba create -f environment-wasm-host.yml --platform=emscripten-wasm32 | |
| mkdir build | |
| pushd build | |
| export BUILD_PREFIX=$MAMBA_ROOT_PREFIX/envs/xeus-cpp-wasm-build | |
| echo "BUILD_PREFIX=$BUILD_PREFIX" >> $GITHUB_ENV | |
| export PREFIX=$MAMBA_ROOT_PREFIX/envs/xeus-cpp-wasm-host | |
| echo "PREFIX=$PREFIX" >> $GITHUB_ENV | |
| export SYSROOT_PATH=$BUILD_PREFIX/opt/emsdk/upstream/emscripten/cache/sysroot | |
| micromamba create -n node-env -c conda-forge nodejs=22 | |
| export PATH="$MAMBA_ROOT_PREFIX/envs/node-env/bin:$PATH" | |
| emcmake cmake \ | |
| -DCMAKE_BUILD_TYPE=Release \ | |
| -DCMAKE_INSTALL_PREFIX=$PREFIX \ | |
| -DXEUS_CPP_EMSCRIPTEN_WASM_BUILD=ON \ | |
| -DCMAKE_FIND_ROOT_PATH=$PREFIX \ | |
| -DSYSROOT_PATH=$SYSROOT_PATH \ | |
| -DCMAKE_COMPILE_WARNING_AS_ERROR=ON \ | |
| .. | |
| emmake make check-xeus-cpp -j ${{ env.ncpus }} | |
| emmake make -j ${{ env.ncpus }} install | |
| - name: Test Emscripten xeus-cpp in browser | |
| shell: bash -l {0} | |
| run: | | |
| set -e | |
| cd build/test | |
| # Fresh install browsers, and run Emscripten tests in them | |
| # This is to match the Emscripten build instructions, where | |
| # we run in a fresh browser, to stop any extra installed | |
| # stuff interferring with the running of the tests | |
| # Explaination of options for emrun | |
| # --browser (name of browser on path) | |
| # --kill_exit makes it so that when emrun finishes, | |
| # that the headless browser we create is killed along with it | |
| # --timeout 60 is such that emrun is killed after 60 seconds if | |
| # still running. emrun should have finished long before then, | |
| # so if it is still running, something went wrong (such as a test | |
| # which crashed the html file). This will cause the ci to fail, | |
| # as a non 0 value of will be returned. | |
| # In the case of Chrome we have the extra --no-sandbox flag, as on | |
| # Ubuntu Chrome will refuse to run otherwise, as it expects to have | |
| # been installed with admin privileges. This flag allows it to run | |
| # in userspace. | |
| os="${{ matrix.os }}" | |
| if [[ "${os}" == "macos"* ]]; then | |
| # Install Firefox | |
| wget "https://download.mozilla.org/?product=firefox-latest&os=osx&lang=en-US" -O Firefox-latest.dmg | |
| hdiutil attach Firefox-latest.dmg | |
| cp -r /Volumes/Firefox/Firefox.app $PWD | |
| hdiutil detach /Volumes/Firefox | |
| cd ./Firefox.app/Contents/MacOS/ | |
| export PATH="$PWD:$PATH" | |
| cd - | |
| # Install Google Chrome | |
| wget https://dl.google.com/chrome/mac/stable/accept_tos%3Dhttps%253A%252F%252Fwww.google.com%252Fintl%252Fen_ph%252Fchrome%252Fterms%252F%26_and_accept_tos%3Dhttps%253A%252F%252Fpolicies.google.com%252Fterms/googlechrome.pkg | |
| pkgutil --expand-full googlechrome.pkg google-chrome | |
| cd ./google-chrome/GoogleChrome.pkg/Payload/Google\ Chrome.app/Contents/MacOS/ | |
| export PATH="$PWD:$PATH" | |
| cd - | |
| # Run tests in browsers | |
| echo "Running test_xeus_cpp in Firefox" | |
| python ${{ env.BUILD_PREFIX }}/bin/emrun.py --browser="firefox" --kill_exit --timeout 60 --browser-args="--headless" test_xeus_cpp.html | |
| echo "Running test_xeus_cpp in Google Chrome" | |
| python ${{ env.BUILD_PREFIX }}/bin/emrun.py --browser="Google Chrome" --kill_exit --timeout 60 --browser-args="--headless --no-sandbox" test_xeus_cpp.html | |
| sudo safaridriver --enable | |
| python -m pip install selenium | |
| echo "Running test_xeus_cpp in Safari" | |
| python ${{ env.BUILD_PREFIX }}/bin/emrun.py --no_browser --kill_exit --timeout 60 --browser-args="--headless --no-sandbox" test_xeus_cpp.html & | |
| python ../../scripts/browser_tests_safari.py test_xeus_cpp.html | |
| else | |
| # Install Google Chrome | |
| wget https://dl.google.com/linux/direct/google-chrome-stable_current_amd64.deb | |
| dpkg-deb -x google-chrome-stable_current_amd64.deb $PWD/chrome | |
| cd ./chrome/opt/google/chrome/ | |
| export PATH="$PWD:$PATH" | |
| cd - | |
| # Install Firefox | |
| wget https://ftp.mozilla.org/pub/firefox/releases/138.0.1/linux-x86_64/en-GB/firefox-138.0.1.tar.xz | |
| tar -xJf firefox-138.0.1.tar.xz | |
| cd ./firefox | |
| export PATH="$PWD:$PATH" | |
| cd - | |
| # Run tests in browsers | |
| echo "Running test_xeus_cpp in Firefox" | |
| python ${{ env.BUILD_PREFIX }}/bin/emrun.py --browser="firefox" --kill_exit --timeout 60 --browser-args="--headless" test_xeus_cpp.html | |
| echo "Running test_xeus_cpp in Google Chrome" | |
| python ${{ env.BUILD_PREFIX }}/bin/emrun.py --browser="google-chrome" --kill_exit --timeout 60 --browser-args="--headless --no-sandbox" test_xeus_cpp.html | |
| fi | |
| timeout-minutes: 4 | |
| - name: Jupyter Lite integration test | |
| shell: bash -l {0} | |
| run: | | |
| set -e | |
| micromamba create -n xeus-lite-host jupyterlite-core=0.6 jupyterlite-xeus -c conda-forge | |
| micromamba activate xeus-lite-host | |
| if [[ "${{ matrix.os }}" == "macos"* ]]; then | |
| brew install coreutils | |
| export PATH="$HOMEBREW_PREFIX/opt/coreutils/libexec/gnubin:$PATH" | |
| fi | |
| export INPUT_TEXT="" | |
| if [[ "${{ matrix.notebook }}" == "xeus-cpp-lite-demo.ipynb"* ]]; then | |
| export INPUT_TEXT="--stdin Test_Name" | |
| fi | |
| timeout 900 jupyter lite serve --settings-overrides=overrides.json --XeusAddon.prefix=${{ env.PREFIX }} \ | |
| --XeusAddon.mounts="${{ env.PREFIX }}/share/xeus-cpp/tagfiles:/share/xeus-cpp/tagfiles" \ | |
| --XeusAddon.mounts="${{ env.PREFIX }}/etc/xeus-cpp/tags.d:/etc/xeus-cpp/tags.d" \ | |
| --contents README.md \ | |
| --contents notebooks/xeus-cpp-lite-demo.ipynb \ | |
| --contents notebooks/smallpt.ipynb \ | |
| --contents notebooks/images/marie.png \ | |
| --contents notebooks/audio/audio.wav & | |
| # There is a bug in nbdime after 3.2.0 where it will show the filenames as if there was a diff | |
| # but there is no diff with the options chosen below (the latest doesn't show a diff, just the filenames with +++ | |
| # and --- as if it was planning to show a diff. This only happens for xeus-cpp-lite-demo.ipynb. | |
| python -m pip install nbdime==3.2.0 | |
| python -m pip install selenium | |
| # This sleep is to force enough time for the jupyter site to build before trying | |
| # to run notebooks in it. If you try to run the notebooks before the website is | |
| # ready the ci python script will crash saying ti cannot access the url | |
| sleep 10 | |
| echo "Running xeus-cpp in Jupter Lite in Chrome" | |
| python -u scripts/automated-notebook-run-script.py --driver chrome --notebook ${{ matrix.notebook }} --kernel ${{ matrix.kernel }} $INPUT_TEXT | |
| nbdiff notebooks/${{ matrix.notebook }} $HOME/Downloads/${{ matrix.notebook }} --ignore-id --ignore-metadata >> chrome_diff.txt | |
| export CHROME_TESTS_RETURN_VALUE=$( [ -s chrome_diff.txt ] && echo 1 || echo 0 ) | |
| echo "Running xeus-cpp in Jupter Lite in Firefox" | |
| python -u scripts/automated-notebook-run-script.py --driver firefox --notebook ${{ matrix.notebook }} --kernel ${{ matrix.kernel }} $INPUT_TEXT | |
| nbdiff notebooks/${{ matrix.notebook }} $HOME/Downloads/${{ matrix.notebook }} --ignore-id --ignore-metadata >> firefox_diff.txt | |
| export FIREFOX_TESTS_RETURN_VALUE=$( [ -s firefox_diff.txt ] && echo 1 || echo 0 ) | |
| rm $HOME/Downloads/${{ matrix.notebook }} | |
| export SAFARI_TESTS_RETURN_VALUE=0 | |
| touch safari_diff.txt | |
| if [[ "${{ matrix.os }}" == "macos"* ]]; then | |
| python -m pip install PyAutoGUI | |
| python scripts/enable-downloads-safari-github-ci.py | |
| echo "Running xeus-cpp in Jupter Lite in Safari" | |
| python -u scripts/automated-notebook-run-script.py --driver safari --notebook ${{ matrix.notebook }} --kernel ${{ matrix.kernel }} $INPUT_TEXT | |
| nbdiff notebooks/${{ matrix.notebook }} $HOME/Downloads/${{ matrix.notebook }} --ignore-id --ignore-metadata >> safari_diff.txt | |
| export SAFARI_TESTS_RETURN_VALUE=$( [ -s safari_diff.txt ] && echo 1 || echo 0 ) | |
| rm $HOME/Downloads/${{ matrix.notebook }} | |
| fi | |
| if [[ $SAFARI_TESTS_RETURN_VALUE -ne 0 || $FIREFOX_TESTS_RETURN_VALUE -ne 0 || $CHROME_TESTS_RETURN_VALUE -ne 0 ]]; then | |
| if [[ "${{ matrix.os }}" == "macos"* ]]; then | |
| echo "Diff Safari (blank means no diff)" | |
| cat safari_diff.txt | |
| fi | |
| echo "Diff Firefox (blank means no diff)" | |
| cat firefox_diff.txt | |
| echo "Diff Chrome (blank means no diff)" | |
| cat chrome_diff.txt | |
| exit 1 | |
| fi | |
| timeout-minutes: 15 | |
| - name: Setup tmate session | |
| if: ${{ failure() && runner.debug }} | |
| uses: mxschmitt/action-tmate@v3 | |
| # When debugging increase to a suitable value! | |
| timeout-minutes: 30 |