Skip to content

test(memgraph): run the shared suite against Memgraph via a memgraph: false tag #811

test(memgraph): run the shared suite against Memgraph via a memgraph: false tag

test(memgraph): run the shared suite against Memgraph via a memgraph: false tag #811

Workflow file for this run

name: Testkit (stub)
on:
push:
branches: [main]
# Housekeeping-only changes (docs, changelog, version bump) can't affect
# tests — skip the heavy CI on them. A mixed change still runs (paths-ignore
# skips only when EVERY changed file matches).
paths-ignore: ['**/*.md', 'lib/shared/neo4j/driver/version.rb']
pull_request:
paths-ignore: ['**/*.md', 'lib/shared/neo4j/driver/version.rb']
jobs:
testkit-stub:
name: testkit-stub (${{ matrix.flavor }})
runs-on: ubuntu-latest
# All flavors are gated: the require-green postprocess step must pass
# for every flavor for the PR to merge.
strategy:
fail-fast: false
matrix:
include:
# Pure MRI: ruby:4.0-slim base, runs lib/mri/.
- flavor: mri
base_image: ruby:4.0-slim
force_mri: ''
# Native JRuby: jruby:10.1.0.0-jdk21 base, runs lib/jruby/.
- flavor: jruby
base_image: jruby:10.1.0.0-jdk21
force_mri: ''
# MRI-on-JRuby forward-compat: jruby image as the runtime but
# NEO4J_DRIVER_FORCE_MRI=1 flips the Gemfile to the MRI gemspec
# so we exercise lib/mri/ under JRuby. Uses the mri baseline
# because it runs MRI code.
- flavor: mri-on-jruby
base_image: jruby:10.1.0.0-jdk21
force_mri: '1'
env:
# testkit.main.py contract: TEST_DRIVER_REPO points at the driver
# source it should mount as /driver in the container; TEST_DRIVER_NAME
# selects the artifact namespace and docker image name. See
# testkit/driver.py:_get_glue and :_ensure_image.
TEST_DRIVER_NAME: ruby
TEST_DRIVER_REPO: ${{ github.workspace }}
# Switch the driver image between MRI and JRuby via the BASE_IMAGE
# build arg honoured by testkit/Dockerfile. testkit forwards env vars
# prefixed with TESTKIT_DRIVER_BUILD_ARG_ as --build-arg.
TESTKIT_DRIVER_BUILD_ARG_BASE_IMAGE: ${{ matrix.base_image }}
# MRI-on-JRuby row passes '1', the others pass '' (no-op). Baked
# into the image as ENV so Gemfile sees it at bundle/run time.
TESTKIT_DRIVER_BUILD_ARG_NEO4J_DRIVER_FORCE_MRI: ${{ matrix.force_mri }}
# Use the Rust boltstub baked into testkit's runner image
# (testkit/runner_image/Dockerfile installs /usr/local/bin/boltstub).
# tests/stub/shared.py reads this env var; when truthy it spawns the
# binary on PATH instead of `python -m boltstub`. Authors quote a
# 2-3× speedup on stub tests.
TEST_RUSTY_STUB: 'true'
# Without this, testkit's run_fail_wrapper re-raises on the first
# failing suite and short-circuits the rest. We want the full run so
# the require-green postprocess step sees every suite's result (a
# green run has 0 failures anyway; this matters when diagnosing a red).
TEST_RUN_ALL_TESTS: 'true'
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
with:
python-version: '3.11'
# testkit.json carries the pinned testkit ref this driver was tested
# against — same source of truth used by testkit's own tooling. The
# workflow no longer hardcodes it.
- name: Clone pinned testkit
run: |
URI=$(python3 -c "import json; print(json.load(open('testkit/testkit.json'))['testkit']['uri'])")
REF=$(python3 -c "import json; print(json.load(open('testkit/testkit.json'))['testkit']['ref'])")
mkdir -p "$RUNNER_TEMP/testkit"
git -C "$RUNNER_TEMP/testkit" init
git -C "$RUNNER_TEMP/testkit" remote add origin "$URI"
git -C "$RUNNER_TEMP/testkit" fetch --depth 1 origin "$REF"
git -C "$RUNNER_TEMP/testkit" checkout FETCH_HEAD
echo "TESTKIT_PATH=$RUNNER_TEMP/testkit" >> "$GITHUB_ENV"
- name: Install testkit Python deps
run: pip install -Ur "$TESTKIT_PATH/requirements.txt" teamcity-messages
# testkit.main.py orchestrates the whole flow: builds the driver
# image from testkit/Dockerfile (BASE_IMAGE supplied above), starts
# the driver container with our backend, builds the runner image
# (which already includes the Rust boltstub), then runs the stub
# suite against the backend. `--tests STUB_TESTS` keeps it scoped
# to stubs only (no Neo4j needed). Stdout is tee'd so the
# regression gate can parse it.
- name: Run testkit stub suite
id: testkit
continue-on-error: true
run: |
set -o pipefail
cd "$TESTKIT_PATH"
python3 main.py --tests STUB_TESTS 2>&1 | tee "$RUNNER_TEMP/run.log"
- uses: ./.github/actions/testkit-postprocess
id: postprocess
if: always()
with:
target_label: stub
log_path: ${{ runner.temp }}/run.log
run_outcome: ${{ steps.testkit.outcome }}
- name: Upload run log
if: always()
uses: actions/upload-artifact@v4
with:
# Per-matrix-row name; upload-artifact@v4 errors on duplicates.
name: testkit-stub-run-log-${{ matrix.flavor }}
path: ${{ steps.postprocess.outputs.log }}
if-no-files-found: ignore
# testkit dumps backend / docker / build logs under
# $TESTKIT_PATH/artifacts at run time; bundle them all so a failing
# job is debuggable without re-running locally.
- name: Upload testkit artifacts
if: always()
uses: actions/upload-artifact@v4
with:
name: testkit-stub-artifacts-${{ matrix.flavor }}
path: ${{ env.TESTKIT_PATH }}/artifacts/
if-no-files-found: ignore
# Stable, version-free gate for branch protection (see specs.yml). Require
# `testkit-stub-success` in the ruleset rather than the per-flavor matrix legs.
testkit-stub-success:
name: testkit-stub-success
needs: [testkit-stub]
if: ${{ !cancelled() }}
runs-on: ubuntu-latest
steps:
- name: Require the testkit-stub matrix to pass
# Bracket notation: a hyphen in the job id is parsed as subtraction
# under dot access (needs.testkit-stub → needs.testkit - stub).
if: ${{ needs['testkit-stub'].result != 'success' }}
run: |
echo "testkit-stub matrix result: ${{ needs['testkit-stub'].result }}"
exit 1