Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
48 commits
Select commit Hold shift + click to select a range
375e2a6
Rename the JVM distribution to arcadedb-jvm
tae898 Oct 25, 2026
d6022ca
Add arcadedb.__backend__ and refuse to import next to the other distr…
tae898 Oct 25, 2026
7189d6a
Port the native build: Java glue, native wheel builder, Python native…
tae898 Oct 25, 2026
dd0eea8
CI: a native workflow with a selective matrix, and a gated release of…
tae898 Oct 25, 2026
9d28df9
Docs: which package? The choice on every page a user lands on
tae898 Oct 25, 2026
a7c0f1e
Native tests: find the Java glue in native/, skip the docs site test …
tae898 Oct 25, 2026
9ae92b3
Native: positional-count refusal, RID value surface, run_in_transacti…
tae898 Oct 25, 2026
5cfc2ef
Native tests: skips come from explicit markers and NotOnNativeYet, ne…
tae898 Oct 25, 2026
99a9dc2
Native glue: graph batches go through db.batch() (P-04), parallel ins…
tae898 Oct 25, 2026
0e266d7
Native parity: PQ settings, float vector bulk, XML limits, example 29…
tae898 Oct 25, 2026
a28fc0f
CI: the native dev-release job publishes through the environment pypi…
tae898 Oct 25, 2026
b55e7c4
CI: one test and one release workflow per build (test-jvm, release-jv…
tae898 Oct 25, 2026
56aab39
Tests: put the degree query of the graph batch test in a variable so …
tae898 Oct 25, 2026
1871c1e
Native: write the engine log to the per-user log directory, never the…
tae898 Oct 25, 2026
7bf78db
Native: Python functions in SQL and openCypher, record events, Ctrl-C…
tae898 Oct 25, 2026
bab9817
Native: a callback reply lives in library memory that Java frees
tae898 Oct 25, 2026
bae8dfc
Native: a vetoed save is not an error; an after_delete event of an un…
tae898 Oct 25, 2026
fbd8664
Native: the reply of a callback goes through an out slot, never a ret…
tae898 Oct 25, 2026
a561129
Native parity: install setuptools in the parity env, pass SYSTEMROOT …
tae898 Oct 25, 2026
702e49c
Native: restore the schema property; the SIGINT subprocess test insta…
tae898 Oct 25, 2026
7f88779
Native CI: a cheap Python-version job on the built linux-x86_64 wheel…
tae898 Oct 25, 2026
648c62b
Tests: nosec markers for the fresh-process SIGINT test's subprocess
tae898 Oct 25, 2026
a815a57
Native: get_stats, get_metadata and PQ search work, AsyncExecutor.tra…
tae898 Oct 25, 2026
0af1225
Native: AsyncExecutor.transaction releases its callbacks once the exe…
tae898 Oct 25, 2026
ae9cf58
Native get_metadata: rerank_oversample and fused_pq follow the engine…
tae898 Oct 25, 2026
3f783a2
CI: match auditwheel's wrapped report on one line; the wheel-check te…
tae898 Oct 25, 2026
5e0b043
Merge native-two-dist (CI fixes: auditwheel wrap, arcadedb_jvm wheel …
tae898 Oct 25, 2026
7b6712c
Merge native-two-dist (CI fixes: auditwheel wrap, arcadedb_jvm wheel …
tae898 Oct 25, 2026
9663b8e
Merge native-two-dist (CI fixes: auditwheel wrap, arcadedb_jvm wheel …
tae898 Oct 25, 2026
a7813c3
Native glue: apply the P-04 and P-01b hunks 99a9dc2 dropped (graph ba…
tae898 Oct 25, 2026
6fd1624
Native: columnar bulk insert by address for strings, nulls and vector…
tae898 Oct 25, 2026
60c3626
Merge pull request #71 from ArcadeData/p04-port-fix
tae898 Oct 25, 2026
48c03df
Merge pull request #67 from ArcadeData/native-callbacks
tae898 Oct 25, 2026
c79a1e3
Merge pull request #69 from ArcadeData/native-not-yet-gaps
tae898 Oct 25, 2026
1f5245a
Merge pull request #70 from ArcadeData/native-log-dir
tae898 Oct 25, 2026
7ec6790
Merge native-two-dist (the stack: #71, #67, #69, #70 and the CI fixes…
tae898 Oct 25, 2026
032122d
Merge native-two-dist (the stack: #71, #67, #69, #70) into native-col…
tae898 Oct 25, 2026
67ed7da
Native tests: no NOTYET left, every JVM-only test is NA-JVM or reads …
tae898 Oct 25, 2026
95e1350
Product quantization test: read fused_pq through get_metadata(), blac…
tae898 Oct 25, 2026
5f35d83
Merge pull request #72 from ArcadeData/native-columnar-port
tae898 Oct 25, 2026
20e7a01
Restore the black import style in _native/database.py
tae898 Oct 25, 2026
a077b95
Merge native-two-dist (#72 columnar) into nyet-to-na-jvm
tae898 Oct 25, 2026
42b0b64
Merge pull request #68 from ArcadeData/native-ci-python-versions
tae898 Oct 25, 2026
0f78c3b
Merge pull request #73 from ArcadeData/nyet-to-na-jvm
tae898 Oct 25, 2026
2a1ebad
Native: start the isolate with -XX:MaximumHeapSizePercent=50 by default
tae898 Oct 25, 2026
38e8aae
Merge pull request #74 from ArcadeData/native-heap-50
tae898 Oct 25, 2026
a215349
Native build: commit every 1000 rows by default in insert_many, graph…
tae898 Oct 25, 2026
a2dfd0c
Merge pull request #75 from ArcadeData/native-ingest-commit-defaults
tae898 Oct 25, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/actionlint.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
# ArcadeData/arcadedb, scoped to the exact file and rule. They are style findings in `run:` scripts, not
# schema errors, and the list is meant to shrink: fix the script and delete its entry.
paths:
.github/workflows/test-python-bindings.yml:
.github/workflows/test-jvm.yml:
ignore:
- 'shellcheck reported issue in this script: SC(2001|2010|2012|2086|2129):'
.github/workflows/test-python-examples.yml:
Expand Down
27 changes: 12 additions & 15 deletions .github/workflows/release.yml → .github/workflows/release-jvm.yml
Original file line number Diff line number Diff line change
@@ -1,27 +1,24 @@
name: Release to PyPI
name: Release JVM (arcadedb-jvm)

# Pushing a tag that is the bare version (26.11.1, 26.11.1.post1, 26.11.1.dev0; no "v", same as
# ArcadeData/arcadedb) builds the wheels, tests them, checks them and publishes them to PyPI.
# Versions run A.B.C.devN -> A.B.C -> A.B.C.postN; never aN, bN or rcN. devN starts at 0 and
# restarts at 0 on a new base A.B.C, postN starts at 1; scripts/check_version.py enforces the
# counting in the first job (a later native job passes --tag-prefix native-v for its own tags).
# counting in the first job. The same tag also starts release-native.yml; each workflow checks the tag against its own PyPI project.
#
# PyPI keys a trusted publisher on this FILENAME and on the job's environment, so do not rename
# either without changing the publisher on PyPI at the same time:
# project arcadedb <- ArcadeData/arcadedb-python, workflow release.yml, environment pypi
# project arcadedb-native <- same repository and workflow, environment pypi-native (not used yet)
# project arcadedb-jvm <- ArcadeData/arcadedb-python, workflow release-jvm.yml, environment pypi-jvm
# project arcadedb <- ArcadeData/arcadedb-python, workflow release-native.yml, environment pypi (the native build)
# Both GitHub environments only accept deployments from tags that match [0-9]*.
#
# Nothing here stores a token: the publish job authenticates with PyPI trusted publishing (OIDC),
# and only that job has the id-token permission.
#
# pyproject.toml names the distribution arcadedb (tracker #19).
# The guard in the publish job refuses to publish anything that is not `arcadedb`, so this workflow
# cannot publish another distribution from here by accident.
#
# TODO (native-wheel port, tracker #19): a second publish job for arcadedb-native, in environment
# pypi-native with its own id-token permission and the same kind of guard (distribution name must
# be arcadedb-native). There is no native job yet.
# pyproject.toml names the distribution arcadedb-jvm (tracker #19). The wheel file is arcadedb_jvm-<version>-...
# (PEP 427 turns the dash into an underscore). The guard in the publish job refuses to publish anything
# that is not `arcadedb-jvm`, so this workflow cannot publish the native `arcadedb` by accident; the
# native build has its own workflow, release-native.yml, with the same kind of guard.

on:
push:
Expand All @@ -38,7 +35,7 @@ concurrency:

env:
# The only distribution this workflow may publish. See the guard in the publish job.
DIST_NAME: arcadedb
DIST_NAME: arcadedb-jvm

jobs:
# The tag must be a bare PEP 440 version of the allowed kinds, and the next number of its base.
Expand Down Expand Up @@ -100,7 +97,7 @@ jobs:
test:
name: Unit tests and wheels
needs: validate-version
uses: ./.github/workflows/test-python-bindings.yml
uses: ./.github/workflows/test-jvm.yml
with:
arcadedb-tag: ${{ needs.validate-version.outputs.arcadedb-tag }}
build-version: ${{ needs.validate-version.outputs.version }}
Expand Down Expand Up @@ -250,7 +247,7 @@ jobs:
needs: [validate-version, verify-wheels]
runs-on: ubuntu-24.04
timeout-minutes: 30
environment: pypi
environment: pypi-jvm
permissions:
id-token: write
steps:
Expand All @@ -260,7 +257,7 @@ jobs:
name: release-dist
path: dist/

# GUARD: this workflow publishes the distribution `arcadedb` and nothing else. A wheel with
# GUARD: this workflow publishes the distribution `arcadedb-jvm` and nothing else. A wheel with
# another name stops the job here, before anything reaches PyPI. Two checks, so neither can drift alone:
# the wheel file name and the Name field of its METADATA, both must be DIST_NAME.
- name: Refuse unless every wheel is the distribution ${{ env.DIST_NAME }}
Expand Down
218 changes: 218 additions & 0 deletions .github/workflows/release-native.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,218 @@
name: Release native (arcadedb)

# Pushing a tag that is the bare version (26.11.1.dev0, 26.11.1, 26.11.1.post1; no "v", never aN/bN/rcN) builds the native wheels, runs
# the parity suite against them on every platform and Python, checks them and publishes them to PyPI as `arcadedb`. The same tag also
# starts release-jvm.yml, which publishes `arcadedb-jvm`; the two workflows do not wait for each other.
#
# The build and the tests are test-native.yml, called with `release: true` (the full matrix: linux-x86_64, linux-aarch64,
# macos-arm64 and windows-x64, each on Python 3.11 to 3.14). A native image build takes about 1 to 2.5 hours per platform; this workflow adds
# no build of its own. The way the JVM release calls test-jvm.yml is the model.
#
# PyPI keys a trusted publisher on this FILENAME and on the job's environment, so do not rename either without changing the publisher
# on PyPI at the same time:
# project arcadedb <- ArcadeData/arcadedb-python, workflow release-native.yml, environment pypi
# project arcadedb-jvm <- ArcadeData/arcadedb-python, workflow release-jvm.yml, environment pypi-jvm
# The GitHub environment `pypi` only accepts deployments from tags that match [0-9]*. There is one environment and one publish job for
# dev, final and post releases.
#
# What is published (the `verify` job decides, the `publish` job uploads):
# A.B.C.devN the parity run of linux-x86_64, linux-aarch64 and macos-arm64 passed on every Python. windows-x64 is published too when it
# passed on every Python, and is informational otherwise.
# A.B.C, A.B.C.postN ONLY when the readiness bar is met: the repository variable ARCADEDB_NATIVE_READINESS_BAR_MET is `true` (a maintainer
# sets it after checking the correctness fixes and the fault and concurrency probes), the parity run of ALL four platforms
# on ALL four Pythons passed, and no test is a NOTYET skip (test-native.yml passes --max-notyet 0 for a final version).
# Speed parity is not part of the bar. The bar is written down in docs/modules/ROOT/pages/development/release.adoc.
#
# Nothing here stores a token: the publish job authenticates with PyPI trusted publishing (OIDC), and only that job has the id-token
# permission. The guard in the publish job refuses to publish anything that is not `arcadedb`, so this workflow cannot publish the
# JVM `arcadedb-jvm` by accident.

on:
push:
tags:
- "[0-9]+.[0-9]+.[0-9]+*" # 26.11.1.dev0, 26.11.1, 26.11.1.post1; validate-version rejects the rest

permissions:
contents: read

# One release per tag at a time. A running release is never cancelled half way through an upload. The group differs from the one of
# test-native.yml (test-native-...), which this workflow calls.
concurrency:
group: release-native-${{ github.ref_name }}
cancel-in-progress: false

env:
# The only distribution this workflow may publish. See the guard in the publish job.
DIST_NAME: arcadedb

jobs:
# The tag must be a bare PEP 440 version of the allowed kinds, and the next number of its base.
validate-version:
name: Validate tag
runs-on: ubuntu-24.04
timeout-minutes: 10
outputs:
version: ${{ steps.validate.outputs.version }}
final: ${{ steps.validate.outputs.final }}
steps:
- name: Validate tag
id: validate
env:
TAG: ${{ github.ref_name }}
run: |
if ! [[ "$TAG" =~ ^[0-9]+\.[0-9]+\.[0-9]+(\.(dev|post)[0-9]+)?$ ]]; then
echo "::error::Tag '$TAG' is not A.B.C, A.B.C.devN or A.B.C.postN (bare version, no v, no aN/bN/rcN)"
exit 1
fi
# a .devN wheel is a pre-release; an A.B.C or A.B.C.postN wheel is final and needs the readiness bar
if [[ "$TAG" == *.dev* ]]; then final=false; else final=true; fi
{ echo "version=$TAG"; echo "final=$final"; } >> "$GITHUB_OUTPUT"
echo "Release $TAG (final=$final)"

- name: Checkout code
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false

# The counting rule is on the docs page development/release.adoc. The script only checks and fails closed: exit 1 is a tag that
# breaks the rule, exit 2 is a source (git tags, PyPI) it could not read, and either stops the release before anything is built.
# The tag being released is left out of the git tags; running the whole workflow again for a version that is already on PyPI
# fails here, so re-run only the publish job instead. Its tests are in tests/test_check_version.py.
- name: Tag must be the next version
env:
TAG: ${{ github.ref_name }}
run: python3 -I scripts/check_version.py "$TAG" --git-remote origin --pypi "$DIST_NAME"

# Builds a wheel per platform, runs the parity suite on every Python and uploads the wheels (native-wheel-<platform>) and one marker per
# passed leg (native-passed-<platform>-py<version>).
test:
name: Native build and parity
needs: validate-version
uses: ./.github/workflows/test-native.yml
with:
version: ${{ needs.validate-version.outputs.version }}
release: true

# What may be published, decided once: the wheels whose platform passed on every required Python, and the readiness bar for a final
# release. Runs when `test` failed too, because a platform that is only informational may fail; the markers say which legs passed.
verify:
name: Verify what may be published
needs: [validate-version, test]
if: ${{ !cancelled() && needs.validate-version.result == 'success' }}
runs-on: ubuntu-24.04
timeout-minutes: 15
outputs:
ok: ${{ steps.verify.outputs.ok }}
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false

- uses: actions/download-artifact@9000827ccba6bdab643e8b6fd33ac0654aef8333 # v8.0.2
with:
pattern: native-passed-*
path: passed
merge-multiple: true

- uses: actions/download-artifact@9000827ccba6bdab643e8b6fd33ac0654aef8333 # v8.0.2
with:
pattern: native-wheel-*
path: wheels
merge-multiple: true

- name: Every required platform passed on every Python, and the wheels are the ones that were tested
id: verify
env:
VERSION: ${{ needs.validate-version.outputs.version }}
FINAL: ${{ needs.validate-version.outputs.final }}
BAR: ${{ vars.ARCADEDB_NATIVE_READINESS_BAR_MET }}
run: |
set -euo pipefail
mkdir -p passed dist
ls -l passed wheels
pythons="3.11 3.12 3.13 3.14"
if [ "$FINAL" = true ]; then
required="linux-x86_64 linux-aarch64 macos-arm64 windows-x64"
if [ "$BAR" != true ]; then
echo "::error::$VERSION is a final release of arcadedb (native), and the readiness bar is not marked as met (repository variable ARCADEDB_NATIVE_READINESS_BAR_MET): nothing is published. See docs/modules/ROOT/pages/development/release.adoc" >&2
exit 1
fi
else
required="linux-x86_64 linux-aarch64 macos-arm64"
fi
for key in $required; do
for py in $pythons; do
[ -f "passed/$key-py$py.ok" ] || { echo "::error::required leg $key on Python $py did not pass its parity run: nothing is published" >&2; exit 1; }
done
done
# every platform that passed on every Python is published (Windows is informational for a pre-release)
for key in linux-x86_64 linux-aarch64 macos-arm64 windows-x64; do
all=true
for py in $pythons; do [ -f "passed/$key-py$py.ok" ] || all=false; done
[ "$all" = true ] || continue
w="$(cat "passed/$key-py3.12.ok")"
case "$w" in
"arcadedb-${VERSION}-py3-none-"*.whl) ;;
*) echo "::error::unexpected wheel $w for version $VERSION" >&2; exit 1 ;;
esac
[ -f "wheels/$w" ] || { echo "::error::wheel $w is missing" >&2; exit 1; }
cp "wheels/$w" dist/
done
ls -l dist
echo "ok=true" >> "$GITHUB_OUTPUT"

- uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7.0.2
with:
name: native-release-dist
path: dist/*.whl
if-no-files-found: error
retention-days: 7

# One job for A.B.C.devN, A.B.C and A.B.C.postN. `verify` already refused a final version unless ARCADEDB_NATIVE_READINESS_BAR_MET is true.
publish:
name: Publish to PyPI
needs: [validate-version, verify]
if: ${{ !cancelled() && needs.verify.result == 'success' }}
runs-on: ubuntu-24.04
timeout-minutes: 15
environment:
name: pypi
url: https://pypi.org/project/arcadedb/
permissions:
id-token: write # PyPI trusted publishing (OIDC); no API token anywhere
steps:
- uses: actions/download-artifact@9000827ccba6bdab643e8b6fd33ac0654aef8333 # v8.0.2
with:
name: native-release-dist
path: dist

# GUARD: this workflow publishes the distribution `arcadedb` and nothing else. A wheel with another name stops the job here,
# before anything reaches PyPI. Two checks, so neither can drift alone: the wheel file name and the Name field of its METADATA,
# both must be DIST_NAME.
- name: Refuse unless every wheel is the distribution ${{ env.DIST_NAME }}
run: |
python3 -I - <<'PY'
import os, pathlib, re, sys, zipfile

want = os.environ["DIST_NAME"]
norm = lambda s: re.sub(r"[-_.]+", "-", s).lower()
wheels = sorted(pathlib.Path("dist").glob("*.whl"))
if not wheels:
sys.exit("no wheels in dist/")
bad = []
for w in wheels:
file_dist = w.name.split("-")[0]
with zipfile.ZipFile(w) as zf:
meta = next(n for n in zf.namelist() if n.endswith(".dist-info/METADATA"))
meta_dist = re.search(r"^Name: (.+)$", zf.read(meta).decode(), re.M).group(1)
if norm(file_dist) != want or norm(meta_dist) != want:
bad.append(f"{w.name}: file name says {file_dist}, METADATA says {meta_dist}")
if bad:
print("\n".join(f"::error::{b}" for b in bad))
sys.exit(f"Refusing to publish: this workflow publishes only the distribution '{want}'.")
print(f"OK: {len(wheels)} wheels, all distribution '{want}'")
PY

- uses: pypa/gh-action-pypi-publish@dc37677b2e1c63e2034f94d8a5b11f265b73ba33 # v1.14.2
with:
packages-dir: dist
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
name: Test Python Bindings
# The JVM build: the `arcadedb-jvm` distribution. release-jvm.yml calls this workflow on a version tag and publishes the wheels it builds.
# The native build, `arcadedb`, is test-native.yml / release-native.yml.
name: Test JVM (arcadedb-jvm)

on:
push:
Expand All @@ -16,6 +18,10 @@ on:
- "CLAUDE.md"
- "examples/README.md"
- "LICENSE*"
# the native build has its own workflows; nothing under native/ is in the JVM wheel
- "native/**"
- ".github/workflows/test-native.yml"
- ".github/workflows/release-native.yml"
pull_request:
# ready_for_review: draft PRs skip the platform matrices (see the job conditions),
# so marking one ready is what starts them.
Expand All @@ -27,6 +33,10 @@ on:
- "CLAUDE.md"
- "examples/README.md"
- "LICENSE*"
# the native build has its own workflows; nothing under native/ is in the JVM wheel
- "native/**"
- ".github/workflows/test-native.yml"
- ".github/workflows/release-native.yml"

# A new upstream snapshot is published as arcadedata/arcadedb:latest without
# any change here, so build and test against it every night as well. The tag
Expand All @@ -36,7 +46,7 @@ on:
schedule:
- cron: "0 3 * * *"

# Allow being called by other workflows (e.g., release workflow)
# Allow being called by other workflows (release-jvm.yml)
workflow_call:
inputs:
arcadedb-tag:
Expand Down Expand Up @@ -69,7 +79,7 @@ on:
# the workflow literally: github.workflow is the CALLER's name in a
# workflow_call, which would put this workflow and its sibling in one group.
concurrency:
group: test-python-bindings-${{ github.event.pull_request.number || github.run_id }}
group: test-jvm-${{ github.event.pull_request.number || github.run_id }}
cancel-in-progress: ${{ github.event_name == 'pull_request' }}

env:
Expand Down Expand Up @@ -204,7 +214,7 @@ jobs:
env:
EVENT_NAME: ${{ github.event_name }}
run: |
matrix="$(python3 scripts/select_matrix.py bindings --event "$EVENT_NAME")"
matrix="$(python3 scripts/select_matrix.py jvm --event "$EVENT_NAME")"
echo "$matrix"
echo "matrix=$matrix" >> "$GITHUB_OUTPUT"

Expand Down
Loading
Loading