Skip to content

feat: support bolt+routing #2390

feat: support bolt+routing

feat: support bolt+routing #2390

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"