feat: support bolt+routing #2390
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: Build and Test | |
| env: | |
| MG_VERSION: "3.3.0" | |
| UV_VERSION: "0.11.3" | |
| VM_MAX_MAP_COUNT: "262144" | |
| on: | |
| push: | |
| branches: | |
| - main | |
| pull_request: | |
| types: [opened, synchronize, reopened, review_requested, ready_for_review] | |
| workflow_dispatch: | |
| inputs: | |
| run_linux: | |
| description: "Run Linux tests" | |
| required: false | |
| type: boolean | |
| default: true | |
| run_windows: | |
| description: "Run Windows tests" | |
| required: false | |
| type: boolean | |
| default: false | |
| run_macos: | |
| description: "Run macOS tests" | |
| required: false | |
| type: boolean | |
| default: false | |
| workflow_call: | |
| inputs: | |
| run_linux: | |
| description: "Run Linux tests" | |
| required: false | |
| type: boolean | |
| default: true | |
| run_windows: | |
| description: "Run Windows tests" | |
| required: false | |
| type: boolean | |
| default: false | |
| run_macos: | |
| description: "Run macOS tests" | |
| required: false | |
| type: boolean | |
| default: false | |
| jobs: | |
| build_and_test_ubuntu: | |
| if: ${{ (github.event_name != 'workflow_dispatch' && github.event.pull_request.draft == false) || ( github.event_name == 'workflow_dispatch' && inputs.run_linux == true ) }} | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| python-version: ["3.10", "3.11", "3.12", "3.13", "3.14"] | |
| env: | |
| OS: ubuntu-24.04 | |
| runs-on: ubuntu-24.04 | |
| steps: | |
| - name: Checkout Repository | |
| uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3 | |
| - name: Set up Python ${{ matrix.python-version }} | |
| uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0 | |
| with: | |
| python-version: ${{ matrix.python-version }} | |
| - name: Install uv | |
| uses: astral-sh/setup-uv@fac544c07dec837d0ccb6301d7b5580bf5edae39 # v8.2.0 | |
| with: | |
| version: ${{ env.UV_VERSION }} | |
| - name: Set up pip and install packages | |
| run: | | |
| # these tools installed globally for Memgraph | |
| UV_BIN="$(command -v uv)" | |
| sudo -H "$UV_BIN" pip install --system --python /usr/bin/python3 numpy==1.26.4 scipy==1.13.0 networkx==3.4.2 gensim==4.3.3 xmlsec==1.3.16 --break-system-packages | |
| - name: Install Memgraph | |
| run: | | |
| mkdir /home/runner/memgraph | |
| curl -L https://download.memgraph.com/memgraph/v${{env.MG_VERSION}}/${{ env.OS }}/memgraph_${{env.MG_VERSION}}-1_amd64.deb --output /home/runner/memgraph/memgraph-community.deb | |
| sudo dpkg -i /home/runner/memgraph/memgraph-community.deb | |
| sudo systemctl stop memgraph | |
| sudo runuser -l memgraph -c '/usr/lib/memgraph/memgraph --bolt-port 7687 --data-directory="/var/lib/memgraph/data" --storage-properties-on-edges=true --storage-snapshot-interval-sec=0 --storage-wal-enabled=false --storage-snapshot-on-exit=false --telemetry-enabled=false --log-level=TRACE --also-log-to-stderr=true --log-file=/var/log/memgraph/memgraph-ubuntu-${{ matrix.python-version }}.log' & | |
| - name: Wait for Memgraph to be ready | |
| run: | | |
| echo "Waiting for Memgraph to accept Bolt connections..." | |
| for i in {1..60}; do | |
| if timeout 1 bash -c "echo > /dev/tcp/127.0.0.1/7687" 2>/dev/null; then | |
| echo "Memgraph is ready." | |
| exit 0 | |
| fi | |
| echo "Waiting for Memgraph... ($i/60)" | |
| sleep 1 | |
| done | |
| echo "Memgraph did not become ready in time." | |
| sudo journalctl -u memgraph --no-pager | tail -50 || true | |
| exit 1 | |
| - name: Install Neo4j | |
| run: | | |
| # Using Neo4j 4.4.18 which has cgroupv2 compatibility fixes for Ubuntu 24.04 | |
| docker run --name neo4j-test -p 7474:7474 -p 7688:7687 -d -v $HOME/neo4j/data:/data -v $HOME/neo4j/logs:/logs -v $HOME/neo4j/import:/var/lib/neo4j/import -v $HOME/neo4j/plugins:/plugins --env NEO4J_AUTH=neo4j/test neo4j:4.4.18 | |
| - name: Wait for Neo4j to be ready | |
| run: | | |
| echo "Waiting for Neo4j to be ready..." | |
| for i in {1..60}; do | |
| # Use cypher-shell inside the container to verify Neo4j is accepting connections | |
| if docker exec neo4j-test cypher-shell -u neo4j -p test "RETURN 1" 2>/dev/null; then | |
| echo "Neo4j is ready and accepting queries!" | |
| break | |
| fi | |
| echo "Waiting for Neo4j... ($i/60)" | |
| sleep 2 | |
| done | |
| # Show Neo4j logs for debugging | |
| echo "=== Neo4j logs ===" | |
| docker logs neo4j-test 2>&1 | tail -30 || true | |
| - name: Run Memgraph HA Cluster | |
| env: | |
| MEMGRAPH_ENTERPRISE_LICENSE: ${{ secrets.MEMGRAPH_ENTERPRISE_LICENSE }} | |
| MEMGRAPH_ORGANIZATION_NAME: ${{ secrets.MEMGRAPH_ORGANIZATION_NAME }} | |
| run: | | |
| if [ -z "$MEMGRAPH_ENTERPRISE_LICENSE" ] || [ -z "$MEMGRAPH_ORGANIZATION_NAME" ]; then | |
| echo "::warning::Memgraph enterprise license secrets are not set; skipping the HA cluster and the routing tests." | |
| exit 0 | |
| fi | |
| bash scripts/ha_cluster.sh start | |
| echo "MEMGRAPH_HA_COORDINATOR_HOST=127.0.0.1" >> "$GITHUB_ENV" | |
| echo "MEMGRAPH_HA_COORDINATOR_PORT=7703" >> "$GITHUB_ENV" | |
| - name: Install More Packages (Python <= 3.12) | |
| if: ${{ matrix.python-version == '3.10' || matrix.python-version == '3.11' || matrix.python-version == '3.12' }} | |
| run: | | |
| ps aux | grep memgraph | |
| uv sync --extra arrow --extra dgl --extra docker --extra dot | |
| uv pip install dgl==2.4.0 -f https://data.dgl.ai/wheels/torch-2.4/repo.html --no-build-isolation | |
| uv pip install 'torch>=2.4.0,<=2.5.0' torch-scatter torch-sparse torch-cluster torch-spline-conv torch-geometric -f https://data.pyg.org/whl/torch-2.4.0+cpu.html --no-build-isolation | |
| uv pip install 'tf-keras>=2.16,<3.0' | |
| uv pip install 'tensorflow-gnn>=1.0.0,<2.0.0' | |
| - name: Install More Packages (Python >= 3.13) | |
| if: ${{ matrix.python-version == '3.13' || matrix.python-version == '3.14' }} | |
| run: | | |
| ps aux | grep memgraph | |
| # Keep TensorFlow/TF-GNN stacks off for 3.13+. | |
| uv sync --extra docker --extra dot --extra arrow | |
| - name: Build wheel | |
| run: | | |
| uv build | |
| - name: Run Tests (Python <= 3.12) | |
| if: ${{ matrix.python-version == '3.10' || matrix.python-version == '3.11' || matrix.python-version == '3.12' }} | |
| env: | |
| TF_USE_LEGACY_KERAS: "1" | |
| run: | | |
| uv run --no-sync pytest -vvv -m "not slow and not ubuntu and not docker" | |
| - name: Run Tests (Python >= 3.13) | |
| if: ${{ matrix.python-version == '3.13' || matrix.python-version == '3.14' }} | |
| run: | | |
| uv run --no-sync pytest -vvv -m "not slow and not ubuntu and not docker and not tfgnn" | |
| - name: Install built wheel for distributable test | |
| run: | | |
| # Replace the editable source install in .venv with the built wheel, | |
| # so the suite below exercises the actual distributable against the | |
| # Memgraph/Neo4j already running in this job. | |
| uv pip uninstall gqlalchemy | |
| uv pip install --no-deps dist/*.whl | |
| # Copy tests outside the repo and run from there: this makes imports | |
| # resolve to the INSTALLED package (not the source tree) and skips the | |
| # source-oriented pytest.ini addopts (black/flake8/cov) and testpaths. | |
| rm -rf "${RUNNER_TEMP}/wheel-test" | |
| mkdir -p "${RUNNER_TEMP}/wheel-test" | |
| cp -r tests "${RUNNER_TEMP}/wheel-test/" | |
| # Some tests read query-module files via a path relative to the working | |
| # directory (e.g. gqlalchemy/query_modules/push_streams/kafka.py), so make | |
| # them available there. No __init__.py is created, so this stays a | |
| # namespace dir and imports still resolve to the installed package. | |
| mkdir -p "${RUNNER_TEMP}/wheel-test/gqlalchemy/query_modules/push_streams" | |
| cp gqlalchemy/query_modules/push_streams/* "${RUNNER_TEMP}/wheel-test/gqlalchemy/query_modules/push_streams/" | |
| - name: Test installed wheel (Python <= 3.12) | |
| if: ${{ matrix.python-version == '3.10' || matrix.python-version == '3.11' || matrix.python-version == '3.12' }} | |
| env: | |
| TF_USE_LEGACY_KERAS: "1" | |
| working-directory: ${{ runner.temp }}/wheel-test | |
| run: | | |
| source "${GITHUB_WORKSPACE}/.venv/bin/activate" | |
| # Skip test_packaging.py: it builds/inspects the source repo (reads | |
| # pyproject.toml from the repo root) and is covered by the source run. | |
| pytest tests --ignore=tests/test_packaging.py -o addopts='' -vvv -m "not slow and not ubuntu and not docker" | |
| - name: Test installed wheel (Python >= 3.13) | |
| if: ${{ matrix.python-version == '3.13' || matrix.python-version == '3.14' }} | |
| working-directory: ${{ runner.temp }}/wheel-test | |
| run: | | |
| source "${GITHUB_WORKSPACE}/.venv/bin/activate" | |
| # Skip test_packaging.py: it builds/inspects the source repo (reads | |
| # pyproject.toml from the repo root) and is covered by the source run. | |
| pytest tests --ignore=tests/test_packaging.py -o addopts='' -vvv -m "not slow and not ubuntu and not docker and not tfgnn" | |
| - name: Stop Memgraph HA Cluster | |
| if: always() | |
| run: bash scripts/ha_cluster.sh stop || echo "HA cluster does not exist" | |
| - name: Use the Upload Artifact GitHub Action | |
| uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 | |
| if: always() | |
| with: | |
| name: memgraph-logs-${{ env.OS }}-py${{ matrix.python-version }} | |
| path: /var/log/memgraph | |
| overwrite: true | |
| build_and_test_windows: | |
| if: ${{ (github.event_name != 'workflow_dispatch' && github.event.pull_request.draft == false) || ( github.event_name == 'workflow_dispatch' && inputs.run_windows == true ) }} | |
| continue-on-error: true | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| python-version: ["3.10", "3.11", "3.12", "3.13", "3.14"] | |
| env: | |
| OS: windows-latest | |
| runs-on: windows-latest | |
| steps: | |
| - name: Checkout Repository | |
| uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3 | |
| - name: Set up Python ${{ matrix.python-version }} | |
| uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0 | |
| with: | |
| python-version: ${{ matrix.python-version }} | |
| - name: Install uv | |
| uses: astral-sh/setup-uv@fac544c07dec837d0ccb6301d7b5580bf5edae39 # v8.2.0 | |
| with: | |
| version: ${{ env.UV_VERSION }} | |
| - name: Set default WSL version to 2 | |
| run: wsl --set-default-version 2 | |
| - uses: Vampire/setup-wsl@d1da7f2c0322a5ee4f24975344f67fc0f5baf364 # v7.0.0 | |
| with: | |
| distribution: Ubuntu-24.04 | |
| - name: Update vm.max_map_count | |
| shell: wsl-bash {0} #root shell | |
| run: | | |
| if [ -f /proc/sys/vm/max_map_count ]; then | |
| sudo sysctl -w vm.max_map_count=${{ env.VM_MAX_MAP_COUNT }} | |
| else | |
| echo "Skipping vm.max_map_count update: /proc/sys/vm/max_map_count not available in this WSL environment." | |
| fi | |
| - name: Download, install and run Memgraph under WSL | |
| shell: wsl-bash {0} # root shell | |
| run: | | |
| sudo apt-get update | |
| sudo apt-get -y install python3 python3-pip ipython3 | |
| # uv is not installed in WSL here, so we use pip | |
| pip3 install networkx numpy scipy --break-system-packages | |
| mkdir /memgraph | |
| curl -L https://download.memgraph.com/memgraph/v${{env.MG_VERSION}}/ubuntu-24.04/memgraph_${{env.MG_VERSION}}-1_amd64.deb --output /memgraph/memgraph-community.deb | |
| dpkg -i /memgraph/memgraph-community.deb | |
| systemctl stop memgraph || true | |
| mkdir /mnt/c/memgraph | |
| mkdir -p /var/lib/memgraph/data-windows-${{ matrix.python-version }} | |
| chown -R memgraph:memgraph /var/lib/memgraph/data-windows-${{ matrix.python-version }} | |
| pkill -f '/usr/lib/memgraph/memgraph' || true | |
| runuser -l memgraph -c 'nohup /usr/lib/memgraph/memgraph --bolt-address 0.0.0.0 --bolt-port 7687 --data-directory="/var/lib/memgraph/data-windows-${{ matrix.python-version }}" --storage-properties-on-edges=true --storage-snapshot-interval-sec=0 --storage-wal-enabled=false --storage-snapshot-on-exit=false --telemetry-enabled=false --log-level=TRACE --also-log-to-stderr=true --log-file=/mnt/c/memgraph/memgraph-windows-${{ matrix.python-version }}.log >/mnt/c/memgraph/memgraph-windows-${{ matrix.python-version }}-stdout.log 2>&1 < /dev/null &' | |
| - name: Wait for Memgraph to be ready (WSL) | |
| shell: wsl-bash {0} # root shell | |
| run: | | |
| echo "Waiting for Memgraph to accept Bolt connections..." | |
| for i in {1..60}; do | |
| if timeout 1 bash -c "echo > /dev/tcp/127.0.0.1/7687" 2>/dev/null; then | |
| echo "Memgraph is ready." | |
| exit 0 | |
| fi | |
| echo "Waiting for Memgraph... ($i/60)" | |
| sleep 1 | |
| done | |
| echo "Memgraph did not become ready in time." | |
| exit 1 | |
| - name: Resolve WSL Memgraph host for Windows tests | |
| run: | | |
| $wslIp = (wsl hostname -I).Trim().Split(' ', [System.StringSplitOptions]::RemoveEmptyEntries)[0] | |
| if (-not $wslIp) { | |
| throw "Failed to resolve WSL IP address." | |
| } | |
| "MG_HOST=$wslIp" | Out-File -FilePath $env:GITHUB_ENV -Encoding utf8 -Append | |
| "MG_PORT=7687" | Out-File -FilePath $env:GITHUB_ENV -Encoding utf8 -Append | |
| Write-Host "Resolved MG_HOST=$wslIp" | |
| - name: Wait for Memgraph to be reachable from Windows | |
| run: | | |
| for ($i = 1; $i -le 60; $i++) { | |
| if (Test-NetConnection -ComputerName $env:MG_HOST -Port $env:MG_PORT -InformationLevel Quiet) { | |
| Write-Host "Memgraph reachable at $env:MG_HOST`:$env:MG_PORT" | |
| exit 0 | |
| } | |
| Write-Host "Waiting for Memgraph from Windows... ($i/60)" | |
| Start-Sleep -Seconds 1 | |
| } | |
| throw "Memgraph not reachable at $env:MG_HOST`:$env:MG_PORT" | |
| - name: Download, install and run Neo4j under WSL | |
| shell: wsl-bash {0} # root shell | |
| run: | | |
| curl -fsSL https://debian.neo4j.com/neotechnology.gpg.key | apt-key add - | |
| add-apt-repository "deb https://debian.neo4j.com stable 4.2" | |
| sudo apt-get -y install neo4j=1:4.2.1 | |
| neo4j-admin set-initial-password test | |
| mkdir -p /mnt/c/neo4j/${{ matrix.python-version }} | |
| sed -i 's/#dbms.connector.bolt.listen_address=:7687/dbms.connector.bolt.listen_address=:7688/g' /etc/neo4j/neo4j.conf | |
| sed -i 's/#dbms.connector.bolt.advertised_address=:7687/dbms.connector.bolt.advertised_address=:7688/g' /etc/neo4j/neo4j.conf | |
| sed -i 's/#dbms.default_listen_address=0.0.0.0/dbms.default_listen_address=0.0.0.0/g' /etc/neo4j/neo4j.conf | |
| sed -i 's/dbms.directories.logs=\/var\/log\/neo4j/dbms.directories.logs=\/mnt\/c\/neo4j\/${{ matrix.python-version }}/g' /etc/neo4j/neo4j.conf | |
| cp /etc/neo4j/neo4j.conf /mnt/c/neo4j/${{ matrix.python-version }}/neo4j.conf | |
| sudo service neo4j start | |
| sleep 10 # Wait for Neo4j a bit. | |
| - name: Install packages | |
| run: | | |
| $env:MG_HOST = (wsl hostname -I).Trim().Split(' ', [System.StringSplitOptions]::RemoveEmptyEntries)[0] | |
| if (-not $env:MG_HOST) { | |
| throw "Failed to resolve WSL IP address before tests." | |
| } | |
| $env:MG_PORT = "7687" | |
| Write-Host "Using Memgraph at $env:MG_HOST`:$env:MG_PORT" | |
| if (-not (Test-NetConnection -ComputerName $env:MG_HOST -Port $env:MG_PORT -InformationLevel Quiet)) { | |
| throw "Memgraph is not reachable from Windows at $env:MG_HOST`:$env:MG_PORT" | |
| } | |
| uv sync --extra arrow --extra docker --extra dot | |
| - name: Build wheel | |
| run: | | |
| uv build | |
| - name: Test project | |
| env: | |
| TF_USE_LEGACY_KERAS: "1" | |
| run: | | |
| uv run --no-sync pytest -vvv -m "not slow and not ubuntu and not docker and not extras" | |
| - name: Save Memgraph Logs | |
| uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 | |
| if: always() | |
| with: | |
| name: memgraph-logs-${{ env.OS }}-py${{ matrix.python-version }} | |
| path: C:\memgraph | |
| overwrite: true | |
| - name: Save Neo4j Logs | |
| uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 | |
| if: always() | |
| with: | |
| name: neo4j-logs-${{ env.OS }}-py${{ matrix.python-version }} | |
| path: C:\neo4j | |
| overwrite: true | |
| build_and_test_macos: | |
| if: ${{ (github.event_name != 'workflow_dispatch' && github.event.pull_request.draft == false) || ( github.event_name == 'workflow_dispatch' && inputs.run_macos == true ) }} | |
| runs-on: macos-latest | |
| steps: | |
| - name: Checkout Repository | |
| uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3 | |
| - name: Set up Python 3.14 | |
| uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0 | |
| with: | |
| python-version: "3.14" | |
| - name: Install uv | |
| uses: astral-sh/setup-uv@fac544c07dec837d0ccb6301d7b5580bf5edae39 # v8.2.0 | |
| with: | |
| version: ${{ env.UV_VERSION }} | |
| - name: Install packages | |
| run: | | |
| uv sync | |
| - name: Run macOS smoke tests | |
| run: | | |
| uv run --no-sync pytest -vvv \ | |
| tests/test_utilities.py \ | |
| tests/test_packaging.py::TestUvBuild::test_uv_build_produces_artifacts \ | |
| tests/test_packaging.py::TestUvBuild::test_wheel_metadata \ | |
| tests/test_packaging.py::TestUvBuild::test_wheel_contains_package \ | |
| -m "not slow and not extras and not docker and not ubuntu" |