test(memgraph): run the shared suite against Memgraph via a memgraph: false tag #1865
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: Driver specs | |
| 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: | |
| rspec: | |
| name: rspec (ruby ${{ matrix.ruby }}${{ matrix.force_mri && ' [mri flavor]' || '' }} / neo4j ${{ matrix.neo4j }}) | |
| runs-on: ubuntu-latest | |
| # JRuby rows are continue-on-error for now: native JRuby flavor has | |
| # no code yet (lib/jruby/ empty), and the MRI-on-JRuby include row | |
| # below is exercised here for the first time. | |
| continue-on-error: ${{ startsWith(matrix.ruby, 'jruby') }} | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| ruby: | |
| - "3.4" | |
| - "4.0" | |
| - "jruby-10.1.0.0" | |
| neo4j: | |
| - "4.4.48" | |
| - "5.26.28" | |
| - "2026.06.0" | |
| # Default value so the `include` below adds a new row rather | |
| # than merging into existing combinations (GH Actions semantics). | |
| force_mri: [false] | |
| include: | |
| # MRI flavor on JRuby — exercises the cross-flavor path via | |
| # NEO4J_DRIVER_FORCE_MRI=1 (the Gemfile's `gemspec name:` flip). | |
| # Single Neo4j version to keep CI minutes reasonable. | |
| - ruby: "jruby-10.1.0.0" | |
| neo4j: "2026.06.0" | |
| force_mri: true | |
| services: | |
| neo4j: | |
| image: neo4j:${{ matrix.neo4j }}-enterprise | |
| env: | |
| NEO4J_AUTH: neo4j/password | |
| NEO4J_ACCEPT_LICENSE_AGREEMENT: "yes" | |
| # Allow the LoadCsv spec's `file://` import. The default import dir | |
| # (/var/lib/neo4j/import) is the same across the 4.4/5.x/2026 matrix, | |
| # so we mount a shared host dir there instead of reconfiguring the | |
| # import path (whose config key differs between 4.4 and 5.x). | |
| NEO4J_dbms_security_allow__csv__import__from__file__urls: "true" | |
| ports: | |
| - 7687:7687 | |
| - 7474:7474 | |
| # The host path is created by Docker at service start (before checkout); | |
| # the "Prepare import dir" step below makes it writable by the runner. | |
| options: >- | |
| --health-cmd "cypher-shell -u neo4j -p password 'RETURN 1'" | |
| --health-interval 10s | |
| --health-timeout 5s | |
| --health-retries 20 | |
| --health-start-period 30s | |
| --volume /tmp/neo4j-import:/var/lib/neo4j/import | |
| env: | |
| TEST_NEO4J_URL: bolt://localhost:7687 | |
| TEST_NEO4J_USER: neo4j | |
| TEST_NEO4J_PASS: password | |
| # Shared host dir mounted into the neo4j service's import directory; the | |
| # LoadCsv spec writes its file here and the server reads it via file://. | |
| # Its presence is also what un-skips the csv-tagged example (see spec_helper). | |
| TEST_NEO4J_IMPORT_DIR: /tmp/neo4j-import | |
| # Empty string when force_mri is false; '1' on the include row. | |
| # The Gemfile checks this and pins to the MRI gemspec when set. | |
| NEO4J_DRIVER_FORCE_MRI: ${{ matrix.force_mri && '1' || '' }} | |
| # Serialise gem installs. setup-ruby's `bundler-cache: true` runs | |
| # `bundle install --jobs 4` by default; on JRuby the parallel | |
| # workers race on the jar-dependencies post_install hook for the | |
| # path-source gem (the hook calls back into ruby-maven before | |
| # ruby-maven has finished extracting deps.lst / polyglot.jar). | |
| # No-op on MRI (no hook); a few seconds slower than parallel but | |
| # correct everywhere — matches testkit/build.py for the same | |
| # reason. Cf. PR #303 commit 670dec3 fix in testkit/build.py. | |
| BUNDLE_JOBS: '1' | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - uses: ruby/setup-ruby@v1 | |
| with: | |
| ruby-version: ${{ matrix.ruby }} | |
| bundler-cache: true | |
| # The bind-mounted import dir is root-owned (and the neo4j entrypoint may | |
| # chown it to the in-container neo4j user); make it writable by the runner | |
| # so the LoadCsv spec can drop its file there. The spec chmods the file | |
| # itself world-readable so the neo4j process can read it back. | |
| - name: Prepare Neo4j import dir (LOAD CSV file:// tests) | |
| run: sudo mkdir -p /tmp/neo4j-import && sudo chmod 1777 /tmp/neo4j-import | |
| - name: Run RSpec | |
| run: bundle exec rspec --format progress | |
| # Memgraph compatibility: the SAME shared suite, run against Memgraph instead | |
| # of Neo4j. Neo4j-only specs are tagged `memgraph: false` and skipped via | |
| # TEST_MEMGRAPH (see spec_helper); everything else runs unchanged. Runs on both | |
| # flavors — latest CRuby (pure-Ruby Bolt) and latest JRuby (Java driver, which | |
| # Memgraph officially supports). See docs/memgraph.md. | |
| rspec-memgraph: | |
| name: rspec (memgraph / ruby ${{ matrix.ruby }}${{ matrix.force_mri && ' [mri flavor]' || '' }}) | |
| runs-on: ubuntu-latest | |
| # Only the CRuby leg gates. Both JRuby legs (Java-driver flavor, and the | |
| # MRI-flavor-on-JVM cross-flavor row) are non-blocking, matching the repo-wide | |
| # JRuby policy. The mri-flavor-on-JVM row isolates whether a JRuby-only red is | |
| # the Java driver's behavior (MRI-on-JVM passes) or a JVM/Linux environment | |
| # effect (MRI-on-JVM fails too) — the same three-cell layout as the Neo4j job. | |
| continue-on-error: ${{ startsWith(matrix.ruby, 'jruby') }} | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| ruby: | |
| - "4.0" # latest CRuby — MRI pure-Ruby Bolt flavor | |
| - "jruby-10.1.0.0" # latest JRuby — Java-driver flavor | |
| force_mri: [false] | |
| include: | |
| # MRI flavor on JRuby — same env/platform as the Java-driver row but the | |
| # pure-Ruby impl, via NEO4J_DRIVER_FORCE_MRI=1 (the Gemfile's flip). | |
| - ruby: "jruby-10.1.0.0" | |
| force_mri: true | |
| services: | |
| memgraph: | |
| image: memgraph/memgraph:3.12.0 # pinned to the validated version | |
| ports: | |
| - 7687:7687 | |
| # MEMGRAPH_USER/PASSWORD create the user at startup, which turns auth on | |
| # (Memgraph has no auth flag — the first user is the switch). The suite | |
| # then authenticates with basic neo4j/password (the driver_helper default), | |
| # exercising the auth path the same way as against Neo4j. Memgraph has no | |
| # built-in Docker healthcheck; the query-ready step below waits. | |
| env: | |
| MEMGRAPH_USER: neo4j | |
| MEMGRAPH_PASSWORD: password | |
| env: | |
| TEST_NEO4J_URL: bolt://localhost:7687 | |
| TEST_MEMGRAPH: "1" # activates the `memgraph: false` exclusion | |
| TEST_NEO4J_DATABASE: memgraph # Memgraph's default database (no `neo4j` db) | |
| # Memgraph advertises Neo4j/v5.11.0 compatibility; feeds version-gated specs. | |
| NEO4J_VERSION: 5.11.0 | |
| # '1' on the mri-flavor-on-JVM row; empty otherwise. The Gemfile pins to the | |
| # MRI gemspec when set (same as the rspec job's cross-flavor row). | |
| NEO4J_DRIVER_FORCE_MRI: ${{ matrix.force_mri && '1' || '' }} | |
| BUNDLE_JOBS: '1' | |
| steps: | |
| - uses: actions/checkout@v4 | |
| with: | |
| persist-credentials: false # no authenticated git ops here; don't leak the token to bundle | |
| - uses: ruby/setup-ruby@v1 | |
| with: | |
| ruby-version: ${{ matrix.ruby }} | |
| bundler-cache: true | |
| - name: Wait for Memgraph (query-ready) | |
| # A listening TCP port doesn't mean Memgraph accepts queries yet (and the | |
| # startup user may not exist yet); retry a real authenticated query until | |
| # it responds. | |
| run: | | |
| for i in $(seq 1 30); do | |
| bundle exec ruby -e "require 'neo4j/driver'; Neo4j::Driver::GraphDatabase.driver('bolt://localhost:7687', Neo4j::Driver::AuthTokens.basic('neo4j', 'password')) { |d| d.session { |s| s.run('RETURN 1').consume } }" >/dev/null 2>&1 && exit 0 | |
| sleep 2 | |
| done | |
| echo "::error::Memgraph never became query-ready"; exit 1 | |
| - name: Run RSpec (Memgraph) | |
| run: bundle exec rspec --format progress | |
| # Stable, version-free gate for branch protection. Requiring the matrix | |
| # legs directly would embed the Ruby/Neo4j versions in the required-check | |
| # names, so bumping the matrix would silently strip the requirement. This | |
| # gate's name never changes; require `rspec-success` in the ruleset instead. | |
| rspec-success: | |
| name: rspec-success | |
| needs: [rspec] | |
| if: ${{ !cancelled() }} | |
| runs-on: ubuntu-latest | |
| steps: | |
| - name: Require the rspec matrix to pass | |
| if: ${{ needs.rspec.result != 'success' }} | |
| run: | | |
| echo "rspec matrix result: ${{ needs.rspec.result }}" | |
| exit 1 | |
| # Version-free gate for the Memgraph leg. Not yet added to the branch-protection | |
| # ruleset (Memgraph is community-verified, not gating) — promote by requiring | |
| # `memgraph-success` once it has been stable for a while. | |
| memgraph-success: | |
| name: memgraph-success | |
| needs: [rspec-memgraph] | |
| if: ${{ !cancelled() }} | |
| runs-on: ubuntu-latest | |
| steps: | |
| - name: Require the Memgraph suite to pass | |
| if: ${{ needs.rspec-memgraph.result != 'success' }} | |
| run: | | |
| echo "rspec-memgraph result: ${{ needs.rspec-memgraph.result }}" | |
| exit 1 |