From ef4d7664acf9a11ef54b7d5a37d4e2b9217f42ae Mon Sep 17 00:00:00 2001 From: t8y2 <1156263951@qq.com> Date: Fri, 7 Aug 2026 02:23:57 +0800 Subject: [PATCH] fix(agents): include Neo4j in native release packaging Closes #5489 --- .github/scripts/bump-agent-versions.mjs | 11 +++++++++- .github/scripts/bump-agent-versions.test.mjs | 21 +++++++++++++++++++ .../scripts/reuse-agent-release-assets.mjs | 2 +- .../reuse-agent-release-assets.test.mjs | 18 ++++++++++++++++ .../scripts/driver_release_packages_test.py | 18 +++++++++++++++- agents/scripts/version_agent_artifacts.py | 2 +- 6 files changed, 68 insertions(+), 4 deletions(-) diff --git a/.github/scripts/bump-agent-versions.mjs b/.github/scripts/bump-agent-versions.mjs index e2a582d3c..b1e273cd6 100644 --- a/.github/scripts/bump-agent-versions.mjs +++ b/.github/scripts/bump-agent-versions.mjs @@ -5,6 +5,10 @@ import { appendFileSync, existsSync, readFileSync, writeFileSync } from "node:fs const VERSIONS_PATH = "agents/versions.json"; const VERSION_SYNC_SUBJECT = "chore: bump module versions [skip ci]"; const JRE_BUILD_PATHS = new Set([".github/workflows/agents-release.yml"]); +const NATIVE_RELEASE_PACKAGING_PATHS = new Set([ + ".github/scripts/reuse-agent-release-assets.mjs", + "agents/scripts/version_agent_artifacts.py", +]); function bumpPatchVersion(version) { const match = /^(\d+)\.(\d+)\.(\d+)(.*)$/.exec(version); @@ -126,16 +130,21 @@ export function evaluateAgentVersionBump({ if (commonChanged) { logs.push("Common agent runtime changes detected; common-triggered bumps are limited to modules that package agents/common."); } + const nativeReleasePackagingChanged = changedFiles.some((file) => NATIVE_RELEASE_PACKAGING_PATHS.has(file)); + if (nativeReleasePackagingChanged) { + logs.push("Shared native release packaging changes detected; all native modules will be rebuilt."); + } for (const { moduleName, module } of resolvedModules) { const moduleChanged = pathChanged(changedFiles, module.modulePath); // Only modules that package agents/common need installer-visible updates // for shared Java runtime changes; native and standalone agents do not. const commonAffectsModule = commonChanged && module.commonDependent; + const nativePackagingAffectsModule = nativeReleasePackagingChanged && module.nativeBuild; const oldVersion = nextVersions[moduleName] ?? "0.1.0"; const prevVersion = prevVersions[moduleName] ?? ""; const manuallyVersioned = manualVersionsChanged && (!prevVersion || prevVersion !== oldVersion); - const moduleNeedsBuild = moduleChanged || commonAffectsModule || manuallyVersioned; + const moduleNeedsBuild = moduleChanged || commonAffectsModule || nativePackagingAffectsModule || manuallyVersioned; if (!moduleNeedsBuild) { logs.push(` ${moduleName}: no changes`); diff --git a/.github/scripts/bump-agent-versions.test.mjs b/.github/scripts/bump-agent-versions.test.mjs index ea133dd71..dba4b308d 100644 --- a/.github/scripts/bump-agent-versions.test.mjs +++ b/.github/scripts/bump-agent-versions.test.mjs @@ -96,6 +96,27 @@ test("bumps Neo4j from its native Go source directory", () => { assert.deepEqual(result.nativeModules, ["neo4j"]); }); +test("rebuilds native modules when shared native packaging changes", () => { + const existing = new Set([ + "agents/drivers/access", + "agents/drivers/access/build.gradle", + "agents/drivers/duckdb", + "agents/drivers/neo4j-go", + ]); + const result = evaluateAgentVersionBump({ + versions: { access: "0.1.37", duckdb: "0.1.3", neo4j: "0.1.40" }, + changedFiles: ["agents/scripts/version_agent_artifacts.py"], + moduleExists: (path) => existing.has(path), + readModuleFile: () => "implementation project(':common')", + }); + + assert.equal(result.versions.access, "0.1.37"); + assert.equal(result.versions.duckdb, "0.1.4"); + assert.equal(result.versions.neo4j, "0.1.41"); + assert.deepEqual(result.nativeModules, ["duckdb", "neo4j"]); + assert.deepEqual(result.reusedModules, ["access"]); +}); + test("builds a manually versioned module even without runtime file changes", () => { const result = evaluateAgentVersionBump({ versions: { duckdb: "0.1.1" }, diff --git a/.github/scripts/reuse-agent-release-assets.mjs b/.github/scripts/reuse-agent-release-assets.mjs index bbf2a1a57..5499bba22 100644 --- a/.github/scripts/reuse-agent-release-assets.mjs +++ b/.github/scripts/reuse-agent-release-assets.mjs @@ -15,7 +15,7 @@ import { basename, join } from "node:path"; import { tmpdir } from "node:os"; const REGISTRY_ASSET = "agent-registry.json"; -const NATIVE_MODULES = new Set(["duckdb", "oracle", "xugu", "kingbase", "vastbase", "rabbitmq", "tdengine"]); +const NATIVE_MODULES = new Set(["duckdb", "oracle", "xugu", "kingbase", "neo4j", "vastbase", "rabbitmq", "tdengine"]); const PLATFORMS = [ "macos-aarch64", "macos-x64", diff --git a/.github/scripts/reuse-agent-release-assets.test.mjs b/.github/scripts/reuse-agent-release-assets.test.mjs index dda1aec36..9a57ec0ca 100644 --- a/.github/scripts/reuse-agent-release-assets.test.mjs +++ b/.github/scripts/reuse-agent-release-assets.test.mjs @@ -78,6 +78,24 @@ test("requires all TDengine native platforms when reusing a release", () => { ); }); +test("requires all Neo4j native platforms when reusing a release", () => { + const native = Object.fromEntries( + platforms.slice(0, -1).map((platform, index) => [platform, artifact(`dbx-agent-neo4j-0.1.40-${platform}.tar.zst`, String(index + 1))]), + ); + const registry = { drivers: { neo4j: { version: "0.1.40", native } }, jres: {} }; + + assert.throws( + () => collectReusableAssetPlan({ + registry, + release: releaseFor(Object.values(native)), + versions: { neo4j: "0.1.40" }, + modules: ["neo4j"], + reuseJre: false, + }), + /missing=windows-x64/, + ); +}); + test("ignores zero-size legacy JAR placeholders for native-only modules", () => { const native = Object.fromEntries( platforms.map((platform, index) => [platform, artifact(`dbx-agent-duckdb-0.1.2-${platform}.tar.zst`, String(index + 1))]), diff --git a/agents/scripts/driver_release_packages_test.py b/agents/scripts/driver_release_packages_test.py index dd95f48e9..1de27a3a3 100644 --- a/agents/scripts/driver_release_packages_test.py +++ b/agents/scripts/driver_release_packages_test.py @@ -9,7 +9,7 @@ import zipfile from pathlib import Path from build_driver_zips import build_driver_zips, remove_raw_driver_artifacts -from version_agent_artifacts import version_agent_artifacts +from version_agent_artifacts import NATIVE_DRIVERS, version_agent_artifacts class DriverReleasePackagesTest(unittest.TestCase): @@ -35,6 +35,7 @@ class DriverReleasePackagesTest(unittest.TestCase): "oracle": "0.1.10", "xugu": "0.1.20", "kingbase": "0.1.34", + "neo4j": "0.1.40", "vastbase": "0.1.37", "duckdb": "0.1.0", "rabbitmq": "0.1.0", @@ -229,6 +230,21 @@ class DriverReleasePackagesTest(unittest.TestCase): ) self.assertTrue(all(output.is_file() for output in outputs)) + def test_versions_neo4j_native_artifacts(self) -> None: + with tempfile.TemporaryDirectory() as temp_dir: + release_dir = Path(temp_dir) + source = release_dir / "dbx-agent-neo4j-macos-aarch64" + source.write_bytes(b"\xcf\xfa\xed\xfetest-neo4j-agent") + versions = {driver: "0.1.0" for driver in NATIVE_DRIVERS} + versions["neo4j"] = "0.1.40" + + renamed = version_agent_artifacts(release_dir, versions) + versioned = release_dir / "dbx-agent-neo4j-0.1.40-macos-aarch64" + + self.assertEqual(renamed, [versioned]) + self.assertFalse(source.exists()) + self.assertEqual(versioned.read_bytes(), b"\xcf\xfa\xed\xfetest-neo4j-agent") + def test_full_offline_bundle_includes_supported_windows_artifacts(self) -> None: with tempfile.TemporaryDirectory() as temp_dir: release_dir = Path(temp_dir) diff --git a/agents/scripts/version_agent_artifacts.py b/agents/scripts/version_agent_artifacts.py index b15e45470..8e767c03b 100644 --- a/agents/scripts/version_agent_artifacts.py +++ b/agents/scripts/version_agent_artifacts.py @@ -4,7 +4,7 @@ import json from pathlib import Path -NATIVE_DRIVERS = ("cassandra", "oracle", "xugu", "kingbase", "vastbase", "duckdb", "rabbitmq", "tdengine") +NATIVE_DRIVERS = ("cassandra", "oracle", "xugu", "kingbase", "neo4j", "vastbase", "duckdb", "rabbitmq", "tdengine") PLATFORMS = ( "macos-aarch64", "macos-x64",