build(deps-dev): bump cryptography from 47.0.0 to 48.0.0 in /pywry #421
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: Test pywry | |
| on: | |
| pull_request: | |
| types: [opened, synchronize, reopened, labeled, unlabeled] | |
| branches: [main, develop] | |
| workflow_dispatch: | |
| permissions: | |
| contents: read | |
| concurrency: | |
| group: ${{ github.workflow }}-${{ github.ref }} | |
| cancel-in-progress: true | |
| defaults: | |
| run: | |
| working-directory: pywry | |
| jobs: | |
| lint: | |
| name: Lint | |
| runs-on: ubuntu-24.04 | |
| permissions: | |
| contents: read | |
| steps: | |
| - uses: actions/checkout@v5 | |
| - name: Set up Python | |
| uses: actions/setup-python@v6 | |
| with: | |
| python-version: '3.12' | |
| cache: 'pip' | |
| cache-dependency-path: pywry/pyproject.toml | |
| - name: Install dependencies | |
| run: | | |
| python -m pip install --upgrade pip | |
| pip install -e ".[notebook,auth,mcp,acp,deepagent,openai,anthropic,magentic]" | |
| pip install ruff ty pytauri-wheel plotly pandas cryptography | |
| - name: Run Ruff linter | |
| run: ruff check pywry/ tests/ | |
| - name: Run Ruff formatter check | |
| run: ruff format --check pywry/ tests/ | |
| - name: Run ty type checker | |
| run: ty check pywry/ | |
| gen-matrix: | |
| name: Resolve test matrix | |
| runs-on: ubuntu-latest | |
| permissions: | |
| contents: read | |
| defaults: | |
| run: | |
| working-directory: ${{ github.workspace }} | |
| outputs: | |
| matrix: ${{ steps.matrix.outputs.matrix }} | |
| pytest-targets: ${{ steps.targets.outputs.targets }} | |
| steps: | |
| - id: matrix | |
| shell: bash | |
| env: | |
| IS_PR: ${{ github.event_name == 'pull_request' }} | |
| HAS_FULL_LABEL: ${{ contains(github.event.pull_request.labels.*.name, 'full-test') }} | |
| run: | | |
| if [[ "$IS_PR" == "true" && "$HAS_FULL_LABEL" != "true" ]]; then | |
| MATRIX='{"include":[{"os":"ubuntu-24.04","python-version":"3.14"},{"os":"windows-2025","python-version":"3.14"},{"os":"macos-15-intel","python-version":"3.14"},{"os":"ubuntu-24.04-arm","python-version":"3.14"},{"os":"windows-11-arm","python-version":"3.14"},{"os":"macos-latest","python-version":"3.14"}]}' | |
| else | |
| MATRIX='{"include":[{"os":"ubuntu-24.04","python-version":"3.11"},{"os":"ubuntu-24.04","python-version":"3.14"},{"os":"windows-2025","python-version":"3.11"},{"os":"windows-2025","python-version":"3.14"},{"os":"macos-15-intel","python-version":"3.11"},{"os":"macos-15-intel","python-version":"3.14"},{"os":"ubuntu-24.04-arm","python-version":"3.11"},{"os":"ubuntu-24.04-arm","python-version":"3.14"},{"os":"windows-11-arm","python-version":"3.12"},{"os":"windows-11-arm","python-version":"3.14"},{"os":"macos-latest","python-version":"3.11"},{"os":"macos-latest","python-version":"3.14"}]}' | |
| fi | |
| echo "matrix=$MATRIX" >> "$GITHUB_OUTPUT" | |
| - name: Checkout for diff | |
| if: github.event_name == 'pull_request' && !contains(github.event.pull_request.labels.*.name, 'full-test') | |
| uses: actions/checkout@v5 | |
| with: | |
| fetch-depth: 0 | |
| ref: ${{ github.event.pull_request.head.sha }} | |
| - id: targets | |
| shell: bash | |
| env: | |
| IS_PR: ${{ github.event_name == 'pull_request' }} | |
| HAS_FULL_LABEL: ${{ contains(github.event.pull_request.labels.*.name, 'full-test') }} | |
| BASE_REF: ${{ github.event.pull_request.base.ref }} | |
| run: | | |
| if [[ "$IS_PR" != "true" || "$HAS_FULL_LABEL" == "true" ]]; then | |
| echo "Full suite (dispatch or full-test label)" | |
| echo "targets=tests/" >> "$GITHUB_OUTPUT" | |
| exit 0 | |
| fi | |
| git fetch --no-tags --prune origin "$BASE_REF" 2>&1 || true | |
| CHANGED=$(git diff --name-only "origin/$BASE_REF"...HEAD) | |
| echo "Changed files in PR:" | |
| echo "$CHANGED" | sed 's/^/ /' | |
| # Source / workflow / shared-test-infra changes force the full suite. | |
| SOURCE_NON_TEST=$(echo "$CHANGED" | grep -E '^pywry/' | grep -vE '^pywry/(tests|docs)/' | grep -vE '^pywry/.*\.md$' || true) | |
| WORKFLOW_SELF=$(echo "$CHANGED" | grep -E '^\.github/workflows/test-pywry\.yml$' || true) | |
| INFRA_TEST=$(echo "$CHANGED" | grep -E '^pywry/tests/(conftest|constants|__init__)\.py$' || true) | |
| TEST_FILES=$(echo "$CHANGED" | grep -E '^pywry/tests/test_.*\.py$' || true) | |
| if [[ -n "$SOURCE_NON_TEST" || -n "$WORKFLOW_SELF" || -n "$INFRA_TEST" ]]; then | |
| echo "Full suite (source/workflow/test-infra changes)" | |
| echo "targets=tests/" >> "$GITHUB_OUTPUT" | |
| elif [[ -n "$TEST_FILES" ]]; then | |
| T=$(echo "$TEST_FILES" | sed 's|^pywry/||' | tr '\n' ' ' | sed 's/ *$//') | |
| echo "Scoped to changed test files: $T" | |
| echo "targets=$T" >> "$GITHUB_OUTPUT" | |
| else | |
| echo "No pywry source/test changes; skipping pytest selection" | |
| echo "targets=__skip__" >> "$GITHUB_OUTPUT" | |
| fi | |
| test: | |
| name: Test - ${{ matrix.os }} - Python ${{ matrix.python-version }} | |
| runs-on: ${{ matrix.os }} | |
| needs: gen-matrix | |
| if: needs.gen-matrix.outputs.pytest-targets != '__skip__' | |
| permissions: | |
| contents: read | |
| strategy: | |
| fail-fast: ${{ github.event_name == 'pull_request' && !contains(github.event.pull_request.labels.*.name, 'full-test') }} | |
| # ``deepagents`` (pulled in by ``.[dev]`` → ``features``) hard- | |
| # requires Python >=3.11 — 3.10 can't resolve the dev extra. | |
| # ``sqlcipher3`` is a source build against the SQLCipher C | |
| # library installed in the ``Build SQLCipher`` step below, so | |
| # any Python ABI works (no binary-wheel coverage gaps). | |
| matrix: ${{ fromJSON(needs.gen-matrix.outputs.matrix) }} | |
| steps: | |
| - uses: actions/checkout@v5 | |
| - name: Set up Python ${{ matrix.python-version }} | |
| uses: actions/setup-python@v6 | |
| with: | |
| python-version: ${{ matrix.python-version }} | |
| allow-prereleases: true | |
| cache: 'pip' | |
| cache-dependency-path: pywry/pyproject.toml | |
| - name: Set up Rust (Linux only) | |
| if: runner.os == 'Linux' | |
| uses: dtolnay/rust-toolchain@stable | |
| - name: Set up Rust (Windows ARM64) | |
| if: runner.os == 'Windows' && runner.arch == 'ARM64' | |
| uses: dtolnay/rust-toolchain@stable | |
| with: | |
| targets: aarch64-pc-windows-msvc | |
| - name: Install Linux dependencies | |
| if: runner.os == 'Linux' | |
| run: | | |
| for i in 1 2 3; do sudo apt-get update && break || sleep 15; done | |
| for i in 1 2 3; do sudo apt-get install -y --fix-missing xvfb dbus-x11 at-spi2-core libxkbcommon-x11-0 libxcb-icccm4 libxcb-image0 libxcb-keysyms1 libxcb-randr0 libxcb-render-util0 libxcb-xinerama0 libxcb-xfixes0 libxcb-shape0 libgl1 libegl1 libwebkit2gtk-4.1-dev libgtk-3-dev build-essential libssl-dev && break || { sleep 30; sudo apt-get update; }; done | |
| - name: Build SQLCipher from source (Linux) | |
| if: runner.os == 'Linux' | |
| shell: bash | |
| run: | | |
| # Build from the upstream source (https://github.com/sqlcipher/sqlcipher) | |
| # so the ``sqlcipher3`` Python package's setup.py links | |
| # against a known-good library on every Python ABI — | |
| # binary wheels stop at Python 3.13. ``--disable-tcl`` | |
| # skips the Tcl extension (not needed by the Python | |
| # binding, and modern Tcl bottles break its compile). | |
| git clone --depth=1 --branch=v4.6.1 https://github.com/sqlcipher/sqlcipher.git /tmp/sqlcipher | |
| cd /tmp/sqlcipher | |
| ./configure \ | |
| --disable-tcl \ | |
| --enable-tempstore=yes \ | |
| CFLAGS="-DSQLITE_HAS_CODEC -DSQLCIPHER_CRYPTO_OPENSSL" \ | |
| LDFLAGS="-lcrypto" | |
| make -j$(nproc) libsqlcipher.la || make -j$(nproc) | |
| sudo make install-libLTLIBRARIES install-includeHEADERS || sudo make install | |
| sudo ldconfig | |
| - name: Build SQLCipher from source (macOS) | |
| if: runner.os == 'macOS' | |
| shell: bash | |
| run: | | |
| # Intentionally NOT installing ``tcl-tk`` from Homebrew: | |
| # the current bottle is Tcl 9.0, whose headers drop the | |
| # ``CONST`` macro and ``TCL_CHANNEL_VERSION_2``, so | |
| # SQLCipher's ``tclsqlite.c`` (still Tcl-8 API) fails to | |
| # compile. SQLCipher's configure auto-disables the Tcl | |
| # extension when no ``tclConfig.sh`` is on the usual | |
| # search paths — we only need the C library anyway; the | |
| # ``sqlcipher3`` Python binding doesn't touch Tcl. | |
| brew install openssl@3 | |
| OPENSSL_PREFIX="$(brew --prefix openssl@3)" | |
| git clone --depth=1 --branch=v4.6.1 https://github.com/sqlcipher/sqlcipher.git /tmp/sqlcipher | |
| cd /tmp/sqlcipher | |
| ./configure \ | |
| --disable-tcl \ | |
| --enable-tempstore=yes \ | |
| CFLAGS="-DSQLITE_HAS_CODEC -DSQLCIPHER_CRYPTO_OPENSSL -I$OPENSSL_PREFIX/include" \ | |
| LDFLAGS="-L$OPENSSL_PREFIX/lib -lcrypto" | |
| # Build only the library target — the default ``make`` tries | |
| # to build the ``sqlcipher`` shell which links against Tcl. | |
| make -j$(sysctl -n hw.logicalcpu) libsqlcipher.la || make -j$(sysctl -n hw.logicalcpu) | |
| sudo make install-libLTLIBRARIES install-includeHEADERS || sudo make install | |
| echo "LDFLAGS=-L/usr/local/lib -L$OPENSSL_PREFIX/lib -lsqlcipher -lcrypto" >> $GITHUB_ENV | |
| echo "CPPFLAGS=-I/usr/local/include -I/usr/local/include/sqlcipher -I$OPENSSL_PREFIX/include" >> $GITHUB_ENV | |
| - name: Install SQLCipher via vcpkg (Windows x64) | |
| if: runner.os == 'Windows' && runner.arch != 'ARM64' | |
| shell: pwsh | |
| run: | | |
| # vcpkg builds SQLCipher from source using the same upstream | |
| # repo (https://github.com/sqlcipher/sqlcipher), just | |
| # packaged as an MSVC-friendly port so we don't have to wire | |
| # nmake + OpenSSL manually. ``SQLCIPHER_PATH`` points | |
| # ``sqlcipher3``'s setup.py at the install root. Skipped on | |
| # arm64-windows: the transitive ``tcl`` port doesn't build | |
| # there even with ``--allow-unsupported``, and the | |
| # ``SqliteStateBackend`` handles the missing binding by | |
| # falling back to plain SQLite. | |
| $env:VCPKG_ROOT = "$env:VCPKG_INSTALLATION_ROOT" | |
| & "$env:VCPKG_ROOT\vcpkg" install "sqlcipher:x64-windows" | |
| $sqlcipherDir = "$env:VCPKG_ROOT\installed\x64-windows" | |
| echo "SQLCIPHER_PATH=$sqlcipherDir" >> $env:GITHUB_ENV | |
| echo "INCLUDE=$sqlcipherDir\include;$sqlcipherDir\include\sqlcipher;$env:INCLUDE" >> $env:GITHUB_ENV | |
| echo "LIB=$sqlcipherDir\lib;$env:LIB" >> $env:GITHUB_ENV | |
| echo "PATH=$sqlcipherDir\bin;$env:PATH" >> $env:GITHUB_ENV | |
| - name: Cache vcpkg packages (Windows ARM) | |
| if: runner.os == 'Windows' && runner.arch == 'ARM64' | |
| uses: actions/cache@v5 | |
| with: | |
| path: C:/vcpkg/installed | |
| key: vcpkg-arm64-windows-openssl-static-md-lua-${{ hashFiles('.github/workflows/test-pywry.yml') }} | |
| restore-keys: | | |
| vcpkg-arm64-windows-openssl-static-md-lua- | |
| - name: Install OpenSSL via vcpkg (Windows ARM) | |
| if: runner.os == 'Windows' && runner.arch == 'ARM64' | |
| shell: pwsh | |
| run: | | |
| $env:VCPKG_ROOT = "$env:VCPKG_INSTALLATION_ROOT" | |
| & "$env:VCPKG_ROOT\vcpkg" install openssl:arm64-windows-static-md | |
| $opensslDir = "$env:VCPKG_ROOT\installed\arm64-windows-static-md" | |
| echo "OPENSSL_DIR=$opensslDir" >> $env:GITHUB_ENV | |
| echo "OPENSSL_LIB_DIR=$opensslDir\lib" >> $env:GITHUB_ENV | |
| echo "OPENSSL_INCLUDE_DIR=$opensslDir\include" >> $env:GITHUB_ENV | |
| - name: Setup build environment (Windows ARM) | |
| if: runner.os == 'Windows' && runner.arch == 'ARM64' | |
| shell: pwsh | |
| run: | | |
| $buildTemp = "C:\buildtmp" | |
| New-Item -ItemType Directory -Force -Path $buildTemp | Out-Null | |
| echo "TMP=$buildTemp" >> $env:GITHUB_ENV | |
| echo "TEMP=$buildTemp" >> $env:GITHUB_ENV | |
| $env:VCPKG_ROOT = "$env:VCPKG_INSTALLATION_ROOT" | |
| & "$env:VCPKG_ROOT\vcpkg" install lua:arm64-windows | |
| $luaDir = "$env:VCPKG_ROOT\installed\arm64-windows" | |
| echo "LUA_DIR=$luaDir" >> $env:GITHUB_ENV | |
| echo "LUA_LIB=$luaDir\lib" >> $env:GITHUB_ENV | |
| echo "LUA_INC=$luaDir\include" >> $env:GITHUB_ENV | |
| - name: Build cryptography from source (Windows ARM) | |
| if: runner.os == 'Windows' && runner.arch == 'ARM64' | |
| shell: pwsh | |
| run: | | |
| pip install --no-cache-dir --no-binary=cryptography cryptography | |
| python -c "from cryptography.hazmat.bindings._rust import openssl; print('cryptography OK')" | |
| - name: Install dependencies | |
| run: | | |
| python -m pip install --upgrade pip | |
| pip install -e ".[dev]" | |
| - name: Verify Docker (Linux) | |
| if: runner.os == 'Linux' | |
| run: docker version | |
| - name: Configure Docker (macOS Intel) | |
| if: runner.os == 'macOS' && runner.arch == 'X64' | |
| shell: bash | |
| run: | | |
| # ``docker/setup-docker-action@v4`` doesn't reliably bring up | |
| # a Docker daemon on ``macos-15-intel`` runners — testcontainers | |
| # then fails with ``FileNotFoundError: /var/run/docker.sock`` | |
| # during the Redis fixture setup. Mirror the resilient | |
| # Docker-Desktop → Colima fallback used in publish-pywry.yml. | |
| set -euo pipefail | |
| if docker info >/dev/null 2>&1; then | |
| echo "Docker daemon already available" | |
| else | |
| if [ -d "/Applications/Docker.app" ]; then | |
| echo "Starting Docker Desktop" | |
| open -a Docker | |
| for _ in {1..30}; do | |
| if docker info >/dev/null 2>&1; then | |
| break | |
| fi | |
| sleep 5 | |
| done | |
| fi | |
| fi | |
| if ! docker info >/dev/null 2>&1; then | |
| echo "Falling back to Colima" | |
| brew install docker colima | |
| colima start --runtime docker --arch x86_64 --cpu 2 --memory 4 --disk 20 | |
| fi | |
| if [ -S "$HOME/.colima/default/docker.sock" ]; then | |
| sudo mkdir -p /var/run | |
| sudo ln -sf "$HOME/.colima/default/docker.sock" /var/run/docker.sock | |
| fi | |
| echo "DOCKER_HOST=unix:///var/run/docker.sock" >> "$GITHUB_ENV" | |
| docker info | |
| - name: Run tests (Linux) | |
| if: runner.os == 'Linux' | |
| env: | |
| PYWRY_HEADLESS: "1" | |
| NO_AT_BRIDGE: "1" | |
| PYTEST_TARGETS: ${{ needs.gen-matrix.outputs.pytest-targets }} | |
| run: | | |
| dbus-run-session -- xvfb-run --auto-servernum --server-args="-screen 0 1920x1080x24" python -m pytest -c pytest.ini $PYTEST_TARGETS -v --tb=short | |
| rc=$? | |
| # Exit 5 = no tests collected after platform filtering on a scoped run; treat as success. | |
| if [[ $rc -eq 5 && "$PYTEST_TARGETS" != "tests/" ]]; then rc=0; fi | |
| exit $rc | |
| - name: Run tests (Windows x64) | |
| if: runner.os == 'Windows' && runner.arch == 'X64' | |
| env: | |
| PYWRY_HEADLESS: "1" | |
| PYWRY_DEPLOY__STATE_BACKEND: "memory" | |
| PYTHONUTF8: "1" | |
| PYTEST_TARGETS: ${{ needs.gen-matrix.outputs.pytest-targets }} | |
| shell: pwsh | |
| run: | | |
| python -m pytest -c pytest.ini $env:PYTEST_TARGETS.Split(' ') -v --tb=short --ignore=tests/test_state_redis_integration.py --ignore=tests/test_auth_rbac_integration.py --ignore=tests/test_deploy_mode_integration.py --ignore=tests/test_e2e_deploy_mode.py --ignore=tests/test_e2e_rbac_widgets.py -m "not redis and not container" | |
| if ($LASTEXITCODE -eq 5 -and $env:PYTEST_TARGETS -ne 'tests/') { exit 0 } | |
| exit $LASTEXITCODE | |
| - name: Run tests (Windows ARM) | |
| if: runner.os == 'Windows' && runner.arch == 'ARM64' | |
| env: | |
| PYWRY_HEADLESS: "1" | |
| PYWRY_DEPLOY__STATE_BACKEND: "memory" | |
| PYTHONUTF8: "1" | |
| PYTEST_TARGETS: ${{ needs.gen-matrix.outputs.pytest-targets }} | |
| shell: pwsh | |
| run: | | |
| python -m pytest -c pytest.ini $env:PYTEST_TARGETS.Split(' ') -v --tb=short --ignore=tests/test_state_redis_integration.py --ignore=tests/test_auth_rbac_integration.py --ignore=tests/test_deploy_mode_integration.py --ignore=tests/test_e2e_deploy_mode.py --ignore=tests/test_e2e_rbac_widgets.py --ignore=tests/test_inline_ssl.py -m "not redis and not container" | |
| if ($LASTEXITCODE -eq 5 -and $env:PYTEST_TARGETS -ne 'tests/') { exit 0 } | |
| exit $LASTEXITCODE | |
| - name: Run tests (macOS Intel) | |
| if: runner.os == 'macOS' && runner.arch == 'X64' | |
| env: | |
| PYWRY_HEADLESS: "1" | |
| PYTEST_TARGETS: ${{ needs.gen-matrix.outputs.pytest-targets }} | |
| run: | | |
| python -m pytest -c pytest.ini $PYTEST_TARGETS -v --tb=short | |
| rc=$? | |
| if [[ $rc -eq 5 && "$PYTEST_TARGETS" != "tests/" ]]; then rc=0; fi | |
| exit $rc | |
| - name: Run tests (macOS ARM) | |
| if: runner.os == 'macOS' && runner.arch == 'ARM64' | |
| env: | |
| PYWRY_HEADLESS: "1" | |
| PYWRY_DEPLOY__STATE_BACKEND: "memory" | |
| PYTEST_TARGETS: ${{ needs.gen-matrix.outputs.pytest-targets }} | |
| run: | | |
| python -m pytest -c pytest.ini $PYTEST_TARGETS -v --tb=short --ignore=tests/test_state_redis_integration.py --ignore=tests/test_auth_rbac_integration.py --ignore=tests/test_deploy_mode_integration.py --ignore=tests/test_e2e_deploy_mode.py --ignore=tests/test_e2e_rbac_widgets.py -m "not redis and not container" | |
| rc=$? | |
| if [[ $rc -eq 5 && "$PYTEST_TARGETS" != "tests/" ]]; then rc=0; fi | |
| exit $rc | |
| ci-required: | |
| name: CI Required | |
| runs-on: ubuntu-latest | |
| if: always() | |
| needs: | |
| - lint | |
| - gen-matrix | |
| - test | |
| permissions: | |
| contents: read | |
| defaults: | |
| run: | |
| working-directory: ${{ github.workspace }} | |
| steps: | |
| - name: Enforce required CI outcomes | |
| shell: bash | |
| env: | |
| LINT_RESULT: ${{ needs.lint.result }} | |
| TEST_RESULT: ${{ needs.test.result }} | |
| PYTEST_TARGETS: ${{ needs.gen-matrix.outputs.pytest-targets }} | |
| run: | | |
| set -euo pipefail | |
| if [[ "$LINT_RESULT" != "success" ]]; then | |
| echo "Lint job failed with result: $LINT_RESULT" | |
| exit 1 | |
| fi | |
| if [[ "$PYTEST_TARGETS" == "__skip__" ]]; then | |
| echo "No pywry source/test changes detected; test matrix intentionally skipped." | |
| exit 0 | |
| fi | |
| if [[ "$TEST_RESULT" != "success" ]]; then | |
| echo "Test matrix did not succeed (result: $TEST_RESULT)" | |
| exit 1 | |
| fi | |
| echo "All required CI checks passed." | |