feat: support ipyvuetify 1 and 3 #2918
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: Test | |
| on: | |
| push: | |
| branches: | |
| - master | |
| tags: | |
| - v* | |
| pull_request: | |
| workflow_dispatch: | |
| schedule: | |
| - cron: "0 6 * * *" # at 06:00 UTC every day | |
| concurrency: | |
| group: ${{ github.workflow }}-${{ github.ref }} | |
| cancel-in-progress: ${{ !(github.ref == 'refs/heads/master') }} | |
| env: | |
| SOLARA_TELEMETRY_SERVER_USER_ID: "install-test" | |
| SOLARA_TELEMETRY_MIXPANEL_TOKEN: adbf863d17cba80db608788e7fce9843 | |
| # without this, buffered output is lost when a process force-exits (e.g. os._exit on windows, | |
| # pytest-timeout kills), which made CI failures undiagnosable | |
| PYTHONUNBUFFERED: "1" | |
| defaults: | |
| run: | |
| shell: bash {0} | |
| jobs: | |
| build: | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@v6 | |
| - name: Set up Python | |
| uses: actions/setup-python@v6 | |
| with: | |
| python-version: "3.10" | |
| - uses: actions/setup-node@v6 | |
| with: | |
| node-version: 20 | |
| - name: Cache JS bundle | |
| id: cache-js-bundle-v2 | |
| uses: actions/cache@v4 | |
| with: | |
| path: | | |
| packages/solara-vuetify-app/dist | |
| packages/solara-vuetify3-app/dist | |
| key: ${{ runner.os }}-js-bundle-${{ hashFiles('packages/solara-vuetify-app/**', 'packages/solara-vuetify3-app/**', 'packages/solara-widget-manager/**', 'packages/solara-widget-manager8/src/**') }} | |
| - name: Build solara widget manager | |
| if: steps.cache-js-bundle-v2.outputs.cache-hit != 'true' | |
| run: | | |
| cd packages/solara-widget-manager | |
| npm install | |
| npm run build | |
| cd ../../ | |
| cd packages/solara-widget-manager8 | |
| npm install | |
| npm run build | |
| cd ../../ | |
| - name: Build solara app package | |
| if: steps.cache-js-bundle-v2.outputs.cache-hit != 'true' | |
| run: | | |
| cd packages/solara-vuetify-app | |
| npm install | |
| npm run build | |
| cd ../../ | |
| cd packages/solara-vuetify3-app | |
| npm install | |
| npm run build | |
| - name: Install build tools | |
| run: pip install hatch | |
| - name: Build solara | |
| run: hatch build | |
| - name: Build solara-assets | |
| run: (cd packages/solara-assets; hatch build) | |
| - name: Build solara-server | |
| run: (cd packages/solara-server; hatch build) | |
| - name: Build pytest-ipywidgets | |
| run: (cd packages/pytest-ipywidgets; hatch build) | |
| - name: Build solara-meta | |
| run: (cd packages/solara-meta; hatch build) | |
| - name: Build solara-enterprise | |
| run: (cd packages/solara-enterprise; hatch build) | |
| - name: Upload Test artifacts | |
| if: always() | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: solara-builds | |
| path: | | |
| dist | |
| packages/solara-assets/dist | |
| packages/solara-server/dist | |
| packages/solara-meta/dist | |
| packages/pytest-ipywidgets/dist | |
| packages/solara-enterprise/dist | |
| packages/solara-vuetify-app/dist | |
| packages/solara-vuetify3-app/dist | |
| code-quality: | |
| runs-on: ubuntu-latest | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| python-version: ["3.9", "3.12"] # 3.9 is the lowest version pre-commit supports | |
| env: | |
| LOCK_FILE_LOCATION: .ci-package-locks/code-quality/python${{ matrix.python-version }}.txt | |
| DIFF_FILE_LOCATION: diff-code-quality-python${{ matrix.python-version }}.txt | |
| steps: | |
| - uses: actions/checkout@v6 | |
| - name: Set up Python ${{ matrix.python-version }} | |
| uses: actions/setup-python@v6 | |
| with: | |
| python-version: ${{ matrix.python-version }} | |
| - name: Prepare | |
| id: prepare | |
| run: | | |
| if [ -f ${{ env.LOCK_FILE_LOCATION }} ]; then | |
| echo "LOCKS_EXIST=true" >> "$GITHUB_OUTPUT" | |
| else | |
| echo "LOCKS_EXIST=false" >> "$GITHUB_OUTPUT" | |
| fi | |
| - name: Install without locking versions | |
| if: github.event_name == 'schedule' || steps.prepare.outputs.LOCKS_EXIST == 'false' | |
| id: install_no_lock | |
| run: | | |
| mkdir -p .ci-package-locks/code-quality | |
| pip install pre-commit | |
| pip freeze --exclude solara --exclude solara-enterprise > ${{ env.LOCK_FILE_LOCATION }} | |
| git diff | tee ${{ env.DIFF_FILE_LOCATION }} | |
| [ -s ${{ env.DIFF_FILE_LOCATION }} ] && echo "HAS_DIFF=true" >> "$GITHUB_OUTPUT" || echo "No dependencies changed" | |
| - name: Install | |
| if: github.event_name != 'schedule' && steps.prepare.outputs.LOCKS_EXIST == 'true' | |
| run: pip install -r ${{ env.LOCK_FILE_LOCATION }} | |
| - name: Install pre-commit | |
| run: pre-commit install | |
| - name: Run pre-commit | |
| run: pre-commit run --all-files | |
| - name: Upload Test artifacts | |
| if: github.event_name == 'schedule' || steps.prepare.outputs.LOCKS_EXIST == 'false' | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: test-results-code-quality-python${{ matrix.python-version }} | |
| path: | | |
| ${{ env.DIFF_FILE_LOCATION }} | |
| ./**/${{ env.LOCK_FILE_LOCATION }} | |
| include-hidden-files: true | |
| - name: Upload CI package locks | |
| if: steps.install_no_lock.outputs.HAS_DIFF == 'true' || steps.prepare.outputs.LOCKS_EXIST == 'false' | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: ci-package-locks-code-quality-python${{ matrix.python-version }} | |
| path: ./**/${{ env.LOCK_FILE_LOCATION }} | |
| include-hidden-files: true | |
| test-install: | |
| needs: [build] | |
| runs-on: ${{ matrix.os }}-latest | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| os: [ubuntu, macos, windows] | |
| python: ["3.8", "3.13"] | |
| steps: | |
| - name: Set up Python | |
| uses: actions/setup-python@v6 | |
| with: | |
| python-version: ${{ matrix.python }} | |
| - uses: actions/checkout@v6 | |
| - uses: actions/download-artifact@v6 | |
| with: | |
| name: solara-builds | |
| - name: Debug | |
| run: ls -R dist | |
| - name: Install solara-ui | |
| run: pip install dist/*.whl | |
| - name: Test import | |
| run: python -c "import solara" | |
| - name: Make sure pytest runs | |
| run: | | |
| pip install pytest | |
| cd /tmp | |
| printf 'import solara\ndef test_dummy(): pass\n' > dummy_test.py | |
| # Add -W ignore flags directly to the command line | |
| pytest dummy_test.py \ | |
| -W error \ | |
| -W "ignore:zmq.eventloop.ioloop is deprecated:DeprecationWarning" | |
| - name: Install solara-server | |
| run: pip install `echo packages/solara-server/dist/*.whl`[starlette] | |
| - name: Run solara create | |
| run: solara create button test.py | |
| - name: Run solara server | |
| run: solara run test.py& | |
| - name: Wait for Solara server to get online | |
| run: | | |
| curl --head --retry 35 --retry-connrefused --retry-delay 5 http://localhost:8765 | |
| - name: Install pytest-ipywidgets | |
| run: pip install packages/pytest-ipywidgets/dist/*.whl | |
| - name: Make sure pytest runs | |
| run: | | |
| # Copy config file again as we are in /tmp | |
| cd /tmp | |
| # Add -W ignore flags directly to the command line | |
| pytest dummy_test.py \ | |
| -W error \ | |
| -W "ignore:zmq.eventloop.ioloop is deprecated:DeprecationWarning" | |
| - name: Install | |
| run: pip install packages/solara-enterprise/dist/*.whl | |
| - name: Test import | |
| run: python -c "import solara_enterprise" | |
| - name: Install solara-meta | |
| run: pip install packages/solara-meta/dist/*.whl | |
| pyinstaller-test: | |
| needs: [build] | |
| timeout-minutes: 15 | |
| runs-on: ${{ matrix.os }}-latest | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| os: [ubuntu, macos, windows] | |
| # just 1 version, it's heavy | |
| python-version: ["3.10"] | |
| env: | |
| LOCK_FILE_LOCATION: .ci-package-locks/pyinstaller/os${{ matrix.os }}-python${{ matrix.python-version }}.txt | |
| steps: | |
| - uses: actions/checkout@v6 | |
| - name: Set up Python ${{ matrix.python-version }} | |
| uses: actions/setup-python@v6 | |
| with: | |
| python-version: ${{ matrix.python-version }} | |
| - uses: actions/download-artifact@v6 | |
| with: | |
| name: solara-builds | |
| - name: Link solara app package | |
| if: matrix.os != 'windows' | |
| run: | | |
| cd packages/solara-vuetify-app | |
| npm run devlink | |
| - name: Copy solara app package | |
| if: matrix.os == 'windows' | |
| run: | | |
| cd packages/solara-vuetify-app | |
| npm run wincopy | |
| - name: Prepare | |
| id: prepare | |
| run: | | |
| mkdir test-results | |
| if [ -f ${{ env.LOCK_FILE_LOCATION }} ]; then | |
| echo "LOCKS_EXIST=true" >> "$GITHUB_OUTPUT" | |
| else | |
| echo "LOCKS_EXIST=false" >> "$GITHUB_OUTPUT" | |
| fi | |
| - name: Install without locking versions | |
| if: github.event_name == 'schedule' || steps.prepare.outputs.LOCKS_EXIST == 'false' | |
| id: install_no_lock | |
| run: | | |
| mkdir -p .ci-package-locks/pyinstaller | |
| command -v uv >/dev/null || pip install uv | |
| # pefile >= 2023.2.7 make pyinstaller incredibly slow https://github.com/erocarrera/pefile/issues/420 | |
| uv pip install --system `echo dist/*.whl`[all] \ | |
| `echo packages/solara-server/dist/*.whl`[all] \ | |
| `echo packages/solara-meta/dist/*.whl`[dev,documentation] \ | |
| "jupyterlab<4" "pydantic<2" "playwright==1.50.0" pyinstaller pefile==2023.2.7 | |
| pip freeze --exclude solara --exclude solara-ui --exclude solara-server > ${{ env.LOCK_FILE_LOCATION }} | |
| git diff --quiet || echo "HAS_DIFF=true" >> "$GITHUB_OUTPUT" | |
| git diff | tee ${{ env.DIFF_FILE_LOCATION }} | |
| [ -s ${{ env.DIFF_FILE_LOCATION }} ] && echo "HAS_DIFF=true" >> "$GITHUB_OUTPUT" || echo "No dependencies changed" | |
| - name: Install | |
| if: github.event_name != 'schedule' && steps.prepare.outputs.LOCKS_EXIST == 'true' | |
| run: | | |
| command -v uv >/dev/null || pip install uv | |
| uv pip install --system -r ${{ env.LOCK_FILE_LOCATION }} \ | |
| `echo dist/*.whl`[all] \ | |
| `echo packages/solara-server/dist/*.whl`[all] \ | |
| `echo packages/solara-meta/dist/*.whl`[dev,documentation] | |
| - name: Build standalone executable | |
| run: (cd pyinstaller/minimal; pyinstaller ./solara.spec --log-level DEBUG) | |
| - name: Install playwright | |
| # only chromium is used in these tests | |
| run: playwright install chromium | |
| - name: Run solara server (pyinstaller) | |
| run: pyinstaller/minimal/dist/solara/solara --port 18765 & | |
| - name: Wait for Solara server to get online | |
| run: | | |
| curl --head --retry 35 --retry-connrefused --retry-delay 5 http://localhost:18765 | |
| - name: Test | |
| if: github.event_name != 'schedule' || steps.install_no_lock.outputs.HAS_DIFF == 'true' | |
| run: pytest tests/pyinstaller --timeout=360 --video=retain-on-failure --output=test-results -vv -s --log-cli-level=warning | |
| - name: Upload Test artifacts | |
| if: always() | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: test-results-pyinstaller-os${{ matrix.os }}-python${{ matrix.python-version }} | |
| path: | | |
| test-results | |
| ${{ env.DIFF_FILE_LOCATION }} | |
| ./**/${{ env.LOCK_FILE_LOCATION }} | |
| include-hidden-files: true | |
| - name: Upload CI package locks | |
| if: steps.install_no_lock.outputs.HAS_DIFF == 'true' || steps.prepare.outputs.LOCKS_EXIST == 'false' | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: ci-package-locks-pyinstaller-os${{ matrix.os }}-python${{ matrix.python-version }} | |
| path: ./**/${{ env.LOCK_FILE_LOCATION }} | |
| include-hidden-files: true | |
| integration-test: | |
| needs: [build] | |
| timeout-minutes: 25 | |
| runs-on: ${{ matrix.os }}-latest | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| # just ubuntu and windows give enough confidence | |
| # osx should work fine (and we test that locally often) | |
| os: [ubuntu, windows] | |
| # just 1 version, it's heavy | |
| python-version: [3.9] | |
| ipywidgets_major: ["7", "8"] | |
| include: | |
| - ipywidgets_major: "7" | |
| ipywidgets: "7.7" | |
| - ipywidgets_major: "8" | |
| ipywidgets: "8.0" | |
| env: | |
| LOCK_FILE_LOCATION: .ci-package-locks/integration/os${{ matrix.os }}-python${{ matrix.python-version }}-ipywidgets${{ matrix.ipywidgets_major }}.txt | |
| DIFF_FILE_LOCATION: diff-integration-os${{ matrix.os }}-python${{ matrix.python-version }}-ipywidgets${{ matrix.ipywidgets_major }}.txt | |
| steps: | |
| - uses: actions/checkout@v6 | |
| - uses: ts-graphviz/setup-graphviz@v2 | |
| - name: Set up Python ${{ matrix.python-version }} | |
| uses: actions/setup-python@v6 | |
| with: | |
| python-version: ${{ matrix.python-version }} | |
| - uses: actions/download-artifact@v6 | |
| with: | |
| name: solara-builds | |
| - name: Link solara app package | |
| if: matrix.os != 'windows' | |
| run: | | |
| cd packages/solara-vuetify-app | |
| npm run devlink | |
| - name: Copy solara app package | |
| if: matrix.os == 'windows' | |
| run: | | |
| cd packages/solara-vuetify-app | |
| npm run wincopy | |
| - name: Prepare | |
| id: prepare | |
| run: | | |
| mkdir test-results | |
| if [ -f ${{ env.LOCK_FILE_LOCATION }} ]; then | |
| echo "LOCKS_EXIST=true" >> "$GITHUB_OUTPUT" | |
| else | |
| echo "LOCKS_EXIST=false" >> "$GITHUB_OUTPUT" | |
| fi | |
| - name: Install without locking versions | |
| if: github.event_name == 'schedule' || steps.prepare.outputs.LOCKS_EXIST == 'false' | |
| id: install_no_lock | |
| run: | | |
| mkdir -p .ci-package-locks/integration | |
| command -v uv >/dev/null || pip install uv | |
| # uv: parallel downloads/installs, much faster than pip (biggest win on windows). | |
| # pip freeze still reads the uv-installed packages fine (standard dist-info). | |
| uv pip install --system `echo dist/*.whl`[all] \ | |
| `echo packages/solara-server/dist/*.whl`[all] \ | |
| `echo packages/pytest-ipywidgets/dist/*.whl`[all,ipywidgets${{ matrix.ipywidgets_major }}] \ | |
| `echo packages/solara-meta/dist/*.whl`[dev,documentation] \ | |
| `echo packages/solara-enterprise/dist/*.whl`[ssg,auth] \ | |
| "jupyterlab<4" "pydantic<2" "playwright==1.50.0" "ipywidgets~=${{ matrix.ipywidgets }}" \ | |
| pytest-retry pytest-xdist | |
| pip freeze --exclude solara --exclude solara-ui --exclude solara-server --exclude pytest-ipywidgets --exclude solara-enterprise > ${{ env.LOCK_FILE_LOCATION }} | |
| git diff | tee ${{ env.DIFF_FILE_LOCATION }} | |
| [ -s ${{ env.DIFF_FILE_LOCATION }} ] && echo "HAS_DIFF=true" >> "$GITHUB_OUTPUT" || echo "No dependencies changed" | |
| - name: Install | |
| if: github.event_name != 'schedule' && steps.prepare.outputs.LOCKS_EXIST == 'true' | |
| run: | | |
| command -v uv >/dev/null || pip install uv | |
| # pytest-xdist explicitly: existing lock files do not have it until the next lock refresh | |
| uv pip install --system -r ${{ env.LOCK_FILE_LOCATION }} \ | |
| `echo dist/*.whl`[all] \ | |
| `echo packages/solara-server/dist/*.whl`[all] \ | |
| `echo packages/pytest-ipywidgets/dist/*.whl`[all,ipywidgets${{ matrix.ipywidgets_major }}] \ | |
| `echo packages/solara-meta/dist/*.whl`[dev,documentation] \ | |
| `echo packages/solara-enterprise/dist/*.whl`[ssg,auth] \ | |
| pytest-xdist | |
| - name: Install playwright | |
| # only chromium is used in these tests | |
| run: playwright install chromium | |
| - name: test | |
| if: github.event_name != 'schedule' || steps.install_no_lock.outputs.HAS_DIFF == 'true' | |
| env: | |
| AUTH0_USERNAME: maartenbreddels+solara-test@gmail.com | |
| AUTH0_PASSWORD: ${{ secrets.AUTH0_PASSWORD }} | |
| FIEF_USERNAME: maartenbreddels+solara-test@gmail.com | |
| FIEF_PASSWORD: ${{ secrets.FIEF_PASSWORD }} | |
| # TODO: we used to also run the (cheap) unittests, to get better coverage report, but that gives errors | |
| # it seems on CI that the default playwright timeout is not (always?) respected, also, if the --timeout argument | |
| # is shorter than the timeout of playwright, we get no good error message, summary: always keep above 30! | |
| # -n 2: keep in sync with the port spacing in tests/integration/conftest.py — more workers | |
| # would put ports outside the valid auth0 callback range (18765-18770) | |
| run: pytest tests/integration -n 2 --timeout=360 --video=retain-on-failure --output=test-results -vv -s --log-cli-level=warning --retries 3 | |
| - name: Upload Test artifacts | |
| if: always() | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: test-results-integration-os${{ matrix.os }}-python${{ matrix.python-version }}-ipywidgets${{ matrix.ipywidgets_major }} | |
| path: | | |
| test-results | |
| ${{ env.DIFF_FILE_LOCATION }} | |
| ./**/${{ env.LOCK_FILE_LOCATION }} | |
| include-hidden-files: true | |
| - name: Upload CI package locks | |
| if: steps.install_no_lock.outputs.HAS_DIFF == 'true' || steps.prepare.outputs.LOCKS_EXIST == 'false' | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: ci-package-locks-integration-os${{ matrix.os }}-python${{ matrix.python-version }}-ipywidgets${{ matrix.ipywidgets_major }} | |
| path: ./**/${{ env.LOCK_FILE_LOCATION }} | |
| include-hidden-files: true | |
| integration-test-vue3: | |
| needs: [build] | |
| timeout-minutes: 15 | |
| runs-on: ubuntu-latest | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| # just ubuntu and windows give enough confidence | |
| # osx should work fine (and we test that locally often) | |
| os: [ubuntu] | |
| # just 1 version, it's heavy | |
| python-version: [3.9] | |
| ipywidgets_major: ["8"] | |
| include: | |
| - ipywidgets_major: "8" | |
| ipywidgets: "8.0" | |
| env: | |
| LOCK_FILE_LOCATION: .ci-package-locks/integration-vue3/os${{ matrix.os }}-ipywidgets${{ matrix.ipywidgets_major }}.txt | |
| DIFF_FILE_LOCATION: diff-integration-vue3-os${{ matrix.os }}-ipywidgets${{ matrix.ipywidgets_major }}.txt | |
| steps: | |
| - uses: actions/checkout@v6 | |
| - name: Set up Python ${{ matrix.python-version }} | |
| uses: actions/setup-python@v6 | |
| with: | |
| python-version: ${{ matrix.python-version }} | |
| - uses: actions/download-artifact@v6 | |
| with: | |
| name: solara-builds | |
| - name: Link solara app package | |
| run: | | |
| (cd packages/solara-vuetify-app; npm run devlink) | |
| (cd packages/solara-vuetify3-app; npm run devlink) | |
| - name: Prepare | |
| id: prepare | |
| run: | | |
| mkdir test-results | |
| if [ -f ${{ env.LOCK_FILE_LOCATION }} ]; then | |
| echo "LOCKS_EXIST=true" >> "$GITHUB_OUTPUT" | |
| else | |
| echo "LOCKS_EXIST=false" >> "$GITHUB_OUTPUT" | |
| fi | |
| - name: Install without locking versions | |
| id: install_no_lock | |
| if: github.event_name == 'schedule' || steps.prepare.outputs.LOCKS_EXIST == 'false' | |
| run: | | |
| mkdir -p .ci-package-locks/integration-vue3 | |
| command -v uv >/dev/null || pip install uv | |
| uv pip install --system `echo dist/*.whl`[all] \ | |
| `echo packages/solara-server/dist/*.whl`[all] \ | |
| `echo packages/pytest-ipywidgets/dist/*.whl`[all,ipywidgets${{ matrix.ipywidgets_major }}] \ | |
| `echo packages/solara-meta/dist/*.whl`[dev,documentation] \ | |
| `echo packages/solara-enterprise/dist/*.whl`[ssg,auth] \ | |
| "jupyterlab<4" "playwright==1.50.0" "pydantic<2" "ipywidgets~=${{ matrix.ipywidgets }}" \ | |
| pytest-retry jupyter_core jupyter-packaging | |
| # separate command: --pre should only apply to ipyvue/ipyvuetify | |
| pip install --pre "ipyvue>=3.0.0a1" "ipyvuetify>=3.0.0a1" | |
| pip freeze --exclude solara --exclude solara-ui --exclude solara-server --exclude pytest-ipywidgets --exclude solara-enterprise > ${{ env.LOCK_FILE_LOCATION }} | |
| git diff | tee ${{ env.DIFF_FILE_LOCATION }} | |
| [ -s ${{ env.DIFF_FILE_LOCATION }} ] && echo "HAS_DIFF=true" >> "$GITHUB_OUTPUT" || echo "No dependencies changed" | |
| - name: Install | |
| if: github.event_name != 'schedule' && steps.prepare.outputs.LOCKS_EXIST == 'true' | |
| run: | | |
| command -v uv >/dev/null || pip install uv | |
| uv pip install --system -r ${{ env.LOCK_FILE_LOCATION }} \ | |
| `echo dist/*.whl`[all] \ | |
| `echo packages/solara-server/dist/*.whl`[all] \ | |
| `echo packages/pytest-ipywidgets/dist/*.whl`[all,ipywidgets${{ matrix.ipywidgets_major }}] \ | |
| `echo packages/solara-meta/dist/*.whl`[dev,documentation] \ | |
| `echo packages/solara-enterprise/dist/*.whl`[ssg,auth] | |
| - name: Install and verify ipyvuetify 3 | |
| run: | | |
| pip install --pre "ipyvue>=3.0.0a1" "ipyvuetify>=3.0.0a1" | |
| python -c "import ipyvuetify, solara.util; print('ipyvuetify', ipyvuetify.__version__); assert solara.util.IPYVUETIFY_V3" | |
| - name: Install playwright | |
| run: playwright install | |
| - name: test | |
| if: github.event_name != 'schedule' || steps.install_no_lock.outputs.HAS_DIFF == 'true' | |
| env: | |
| AUTH0_USERNAME: maartenbreddels+solara-test@gmail.com | |
| AUTH0_PASSWORD: ${{ secrets.AUTH0_PASSWORD }} | |
| FIEF_USERNAME: maartenbreddels+solara-test@gmail.com | |
| FIEF_PASSWORD: ${{ secrets.FIEF_PASSWORD }} | |
| # TODO: we used to also run the (cheap) unittests, to get better coverage report, but that gives errors | |
| # it seems on CI that the default playwright timeout is not (always?) respected, also, if the --timeout argument | |
| # is shorter than the timeout of playwright, we get no good error message, summary: always keep above 30! | |
| # grown one file at a time: everything listed here must stay green on | |
| # ipyvuetify 3, the rest of tests/integration is still vuetify 2 only. | |
| # not included yet: input_date_test (the vuetify 3 date picker ignores | |
| # first_day_of_week/style_ and maps date_picker_type to view_mode) and | |
| # router_test::test_docs_basics | |
| run: pytest tests/integration/widget_test.py tests/integration/error_test.py tests/integration/menu_test.py tests/integration/router_test.py --deselect tests/integration/router_test.py::test_docs_basics --timeout=360 --video=retain-on-failure --output=test-results -vv -s --log-cli-level=warning --retries 3 | |
| - name: Upload Test artifacts | |
| if: always() | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: test-results-integration-vue3-os${{ matrix.os }}-ipywidgets${{ matrix.ipywidgets_major }} | |
| path: | | |
| test-results | |
| ${{ env.DIFF_FILE_LOCATION }} | |
| ./**/${{ env.LOCK_FILE_LOCATION }} | |
| include-hidden-files: true | |
| - name: Upload CI package locks | |
| if: steps.install_no_lock.outputs.HAS_DIFF == 'true' || steps.prepare.outputs.LOCKS_EXIST == 'false' | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: ci-package-locks-integration-vue3-os${{ matrix.os }}-ipywidgets${{ matrix.ipywidgets_major }} | |
| path: ./**/${{ env.LOCK_FILE_LOCATION }} | |
| include-hidden-files: true | |
| unit-test: | |
| needs: [build] | |
| runs-on: ${{ matrix.os }}-latest | |
| timeout-minutes: 15 | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| os: [ubuntu, macos, windows] | |
| python: [3.8, 3.12] | |
| ipywidgets: ["7.7", "8.0"] | |
| env: | |
| LOCK_FILE_LOCATION: .ci-package-locks/unit/os${{ matrix.os }}-python${{ matrix.python }}-ipywidgets${{ matrix.ipywidgets }}.txt | |
| DIFF_FILE_LOCATION: diff-unit-os${{ matrix.os }}-python${{ matrix.python }}-ipywidgets${{ matrix.ipywidgets }}.txt | |
| steps: | |
| - uses: actions/checkout@v6 | |
| - name: Set up Python | |
| uses: actions/setup-python@v6 | |
| with: | |
| python-version: ${{ matrix.python }} | |
| - uses: actions/download-artifact@v6 | |
| with: | |
| name: solara-builds | |
| - name: Prepare | |
| id: prepare | |
| run: | | |
| if [ -f ${{ env.LOCK_FILE_LOCATION }} ]; then | |
| echo "LOCKS_EXIST=true" >> "$GITHUB_OUTPUT" | |
| else | |
| echo "LOCKS_EXIST=false" >> "$GITHUB_OUTPUT" | |
| fi | |
| - name: Install without locking versions | |
| id: install_no_lock | |
| if: github.event_name == 'schedule' || steps.prepare.outputs.LOCKS_EXIST == 'false' | |
| run: | | |
| mkdir -p .ci-package-locks/unit | |
| command -v uv >/dev/null || pip install uv | |
| # uv: parallel downloads/installs, much faster than pip (biggest win on windows). | |
| # pip freeze still reads the uv-installed packages fine (standard dist-info). | |
| # no jupyterlab and no pytest-ipywidgets extras: the unit tests never start | |
| # voila/jupyter servers (integration does), and the jupyterlab<4 chain pins old | |
| # native packages (y-py, pywinpty) that lack wheels on some windows pythons. | |
| # --only-binary pywinpty: ipywidgets 7 still pulls it in via notebook, and its | |
| # latest sdist neither parses nor builds on python 3.8 - resolve to a wheel instead | |
| uv pip install --system --only-binary pywinpty `echo dist/*.whl`[all] \ | |
| `echo packages/solara-server/dist/*.whl`[all] \ | |
| `echo packages/pytest-ipywidgets/dist/*.whl` \ | |
| `echo packages/solara-meta/dist/*.whl`[dev,documentation] \ | |
| `echo packages/solara-enterprise/dist/*.whl`[ssg,auth] \ | |
| diskcache redis "ipywidgets~=${{ matrix.ipywidgets }}" | |
| pip freeze --exclude solara --exclude solara-ui --exclude solara-server --exclude pytest-ipywidgets --exclude solara-enterprise > ${{ env.LOCK_FILE_LOCATION }} | |
| git diff | tee ${{ env.DIFF_FILE_LOCATION }} | |
| [ -s ${{ env.DIFF_FILE_LOCATION }} ] && echo "HAS_DIFF=true" >> "$GITHUB_OUTPUT" || echo "No dependencies changed" | |
| - name: Install | |
| if: github.event_name != 'schedule' && steps.prepare.outputs.LOCKS_EXIST == 'true' | |
| run: | | |
| command -v uv >/dev/null || pip install uv | |
| uv pip install --system --only-binary pywinpty -r ${{ env.LOCK_FILE_LOCATION }} \ | |
| `echo dist/*.whl`[all] \ | |
| `echo packages/solara-server/dist/*.whl`[all] \ | |
| `echo packages/pytest-ipywidgets/dist/*.whl` \ | |
| `echo packages/solara-meta/dist/*.whl`[dev,documentation] \ | |
| `echo packages/solara-enterprise/dist/*.whl`[ssg,auth] | |
| - name: Start Redis | |
| if: ( github.event_name != 'schedule' || steps.install_no_lock.outputs.HAS_DIFF == 'true' ) && matrix.os != 'windows' | |
| uses: shogo82148/actions-setup-redis@v1.51.0 | |
| - name: Run unit tests | |
| if: github.event_name != 'schedule' || steps.install_no_lock.outputs.HAS_DIFF == 'true' | |
| run: | | |
| # otherwise Python's inspect cannot find the source code | |
| mv solara _solara | |
| pytest tests/unit --doctest-modules --timeout=60 --session-timeout=600 -v | |
| - name: Run unit tests as if we are running solara 2.0 | |
| env: | |
| SOLARA_ALLOW_REACTIVE_BOOLEAN: 0 | |
| SOLARA_DEFAULT_CONTAINER: "Fragment" | |
| SOLARA_STORAGE_MUTATION_DETECTION: 1 | |
| if: github.event_name != 'schedule' || steps.install_no_lock.outputs.HAS_DIFF == 'true' | |
| run: | | |
| # otherwise Python's inspect cannot find the source code | |
| mv solara _solara | |
| pytest tests/unit --doctest-modules --timeout=60 --session-timeout=600 -v | |
| - name: upload test artifacts | |
| if: github.event_name == 'schedule' || steps.prepare.outputs.LOCKS_EXIST == 'false' | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: test-results-unit-os${{ matrix.os }}-python${{ matrix.python }}-ipywidgets${{ matrix.ipywidgets }} | |
| path: | | |
| ${{ env.DIFF_FILE_LOCATION }} | |
| ./**/${{ env.LOCK_FILE_LOCATION }} | |
| include-hidden-files: true | |
| - name: Upload CI package locks | |
| if: steps.install_no_lock.outputs.HAS_DIFF == 'true' || steps.prepare.outputs.LOCKS_EXIST == 'false' | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: ci-package-locks-unit-os${{ matrix.os }}-python${{ matrix.python }}-ipywidgets${{ matrix.ipywidgets }} | |
| path: ./**/${{ env.LOCK_FILE_LOCATION }} | |
| include-hidden-files: true | |
| unit-test-vue3: | |
| needs: [build] | |
| runs-on: ubuntu-latest | |
| timeout-minutes: 15 | |
| steps: | |
| - uses: actions/checkout@v6 | |
| - name: Set up Python | |
| uses: actions/setup-python@v6 | |
| with: | |
| python-version: "3.11" | |
| - uses: actions/download-artifact@v6 | |
| with: | |
| name: solara-builds | |
| - name: Install | |
| run: | | |
| command -v uv >/dev/null || pip install uv | |
| uv pip install --system `echo dist/*.whl`[all] \ | |
| `echo packages/solara-server/dist/*.whl`[all] \ | |
| `echo packages/pytest-ipywidgets/dist/*.whl` \ | |
| `echo packages/solara-meta/dist/*.whl`[dev,documentation] \ | |
| `echo packages/solara-enterprise/dist/*.whl`[ssg,auth] \ | |
| diskcache redis "ipywidgets~=8.0" | |
| # ipyvuetify 3 is prerelease only, so it needs an explicit specifier | |
| uv pip install --system --prerelease=allow "ipyvuetify>=3.0.0a1" "ipyvue>=3.0.0a1" | |
| python -c "import ipyvuetify, ipyvue; print('ipyvuetify', ipyvuetify.__version__, 'ipyvue', ipyvue.__version__)" | |
| python -c "from solara.util import IPYVUETIFY_V3; assert IPYVUETIFY_V3, 'expected ipyvuetify 3'" | |
| - name: Start Redis | |
| uses: shogo82148/actions-setup-redis@v1.51.0 | |
| - name: Run unit tests | |
| run: | | |
| # otherwise Python's inspect cannot find the source code | |
| mv solara _solara | |
| # smaller scope than the ipyvuetify 1 matrix on purpose: no doctests and | |
| # no solara 2.0 mode yet, those can be added once this stays green | |
| pytest tests/unit --timeout=60 --session-timeout=600 -v | |
| update-ci-package-locks: | |
| needs: | |
| [build, code-quality, integration-test, integration-test-vue3, unit-test, unit-test-vue3] | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@v6 | |
| with: | |
| fetch-depth: 0 | |
| ref: ${{ github.head_ref || github.ref }} | |
| repository: ${{ github.event.pull_request.head.repo.full_name || github.event.repository.full_name }} | |
| - uses: actions/download-artifact@v6 | |
| with: | |
| pattern: ci-package-locks-* | |
| merge-multiple: true | |
| - name: Prepare | |
| id: prepare | |
| # We check if lock files have changed. This should only be the case if we are either running on a schedule | |
| # or if some lock files did not exist yet. | |
| run: | | |
| git config user.name 'github-actions[bot]' | |
| git config user.email 'github-actions[bot]@users.noreply.github.com' | |
| git add -N .ci-package-locks | |
| git diff --quiet || echo "HAS_DIFF=true" >> "$GITHUB_OUTPUT" | |
| - name: Update CI package locks | |
| if: steps.prepare.outputs.HAS_DIFF == 'true' | |
| run: | | |
| git add .ci-package-locks | |
| git commit -m "Update CI package locks" | |
| git push | |
| release: | |
| needs: | |
| [ | |
| build, | |
| code-quality, | |
| test-install, | |
| integration-test, | |
| integration-test-vue3, | |
| unit-test, | |
| unit-test-vue3, | |
| ] | |
| runs-on: ubuntu-latest | |
| permissions: | |
| id-token: write # this permission is mandatory for trusted publishing | |
| steps: | |
| - uses: actions/checkout@v6 | |
| - name: Set up Python 3.10 | |
| uses: actions/setup-python@v6 | |
| with: | |
| python-version: "3.10" | |
| - uses: actions/download-artifact@v6 | |
| with: | |
| name: solara-builds | |
| - name: Install build tools | |
| run: pip install hatch | |
| - name: Install solara-ui | |
| run: pip install dist/*.whl | |
| - name: Test import solara-ui | |
| run: python -c "import solara" | |
| - name: Install solara-server | |
| run: pip install `echo packages/solara-server/dist/*.whl`[starlette] | |
| - name: Test import of solara-server | |
| run: python -c "import solara; import solara.server.starlette" | |
| - name: Install solara-enterprise | |
| run: pip install packages/solara-enterprise/dist/*.whl | |
| - name: Test import solara-enterprise | |
| run: python -c "import solara_enterprise" | |
| - name: Publish solara-meta to PyPI | |
| if: startsWith(github.event.ref, 'refs/tags/v') | |
| env: | |
| HATCH_INDEX_USER: __token__ | |
| HATCH_INDEX_AUTH: ${{ secrets.pypi_password }} | |
| run: | | |
| cd packages/solara-meta | |
| openssl sha256 dist/* | |
| hatch publish | |
| openssl sha256 dist/* | |
| - name: Publish solara-enterprise to PyPI | |
| if: startsWith(github.event.ref, 'refs/tags/v') | |
| env: | |
| HATCH_INDEX_USER: __token__ | |
| HATCH_INDEX_AUTH: ${{ secrets.pypi_enterprise }} | |
| run: | | |
| cd packages/solara-enterprise | |
| openssl sha256 dist/* | |
| hatch publish | |
| openssl sha256 dist/* | |
| - name: Publish solara-assets to PyPI | |
| if: startsWith(github.event.ref, 'refs/tags/v') | |
| env: | |
| HATCH_INDEX_USER: __token__ | |
| HATCH_INDEX_AUTH: ${{ secrets.pypi_assets }} | |
| run: | | |
| cd packages/solara-assets | |
| openssl sha256 dist/* | |
| hatch publish | |
| openssl sha256 dist/* | |
| - name: Publish solara-ui to PyPI | |
| if: startsWith(github.event.ref, 'refs/tags/v') | |
| env: | |
| HATCH_INDEX_USER: __token__ | |
| HATCH_INDEX_AUTH: ${{ secrets.pypi_ui }} | |
| run: | | |
| openssl sha256 dist/* | |
| hatch publish | |
| openssl sha256 dist/* | |
| - name: Publish solara-server to PyPI | |
| if: startsWith(github.event.ref, 'refs/tags/v') | |
| env: | |
| HATCH_INDEX_USER: __token__ | |
| HATCH_INDEX_AUTH: ${{ secrets.pypi_server }} | |
| run: | | |
| cd packages/solara-server | |
| openssl sha256 dist/* | |
| hatch publish | |
| openssl sha256 dist/* | |
| - name: Publish package distributions to PyPI | |
| if: startsWith(github.event.ref, 'refs/tags/v') | |
| uses: pypa/gh-action-pypi-publish@release/v1 | |
| with: | |
| packages-dir: packages/pytest-ipywidgets/dist | |
| - name: remove assets | |
| run: rm -rf packages/solara-assets/dist | |
| check_pycafe: | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@v6 | |
| - run: | | |
| diff solara/website/pages/documentation/examples/ai/chatbot.py <(curl -s https://py.cafe/files/solara/chatbot/app.py) |