Skip to content

build(native): migrate GraalVM metadata to reachability-metadata.json - #723

Merged
stefanoboriero merged 3 commits into
masterfrom
chore/migrate-native-config-to-reachability-metadata
Oct 19, 2026
Merged

stefanoboriero merged 3 commits into
masterfrom
chore/migrate-native-config-to-reachability-metadata

Conversation

@stefanoboriero

@stefanoboriero stefanoboriero commented Oct 19, 2026 •

Copy link
Copy Markdown
Contributor

Fixes master CI (COMP-2861): https://seqera.atlassian.net/browse/COMP-2861

Supersedes #718 (closed): the SDK reflection entries it added by hand are now generated, and its Jersey entry is now captured by the tracing agent.

Root cause

Master's native binary tests (Linux, MAC, MAC-arm64, Windows) failed with 790 of 898 tests red. Two things were wrong:

  1. Metadata format / toolchain mismatch. CI and the Gradle toolchain use GraalVM 25, but .sdkmanrc still pinned GraalVM 21. Regenerating on Java 21 produced no changes (the task was also cached by Gradle, so clean is needed to force it). The GraalVM 25 native-image-agent writes the unified reachability-metadata.json instead of the legacy reflect-config.json / resource-config.json, so the new Tower SDK entries never reached the legacy files.
  2. Missing Jersey/HK2 entry. Jersey 2.48 made JerseyClassAnalyzer public with a (ServiceLocator) constructor that HK2 instantiates reflectively. With no reflection entry, every API call in the native binary logged HK2 service reification failed for [...JerseyClassAnalyzer] to stderr, failing the tests that assert empty stderr. The tracing agent could not capture it because conf/access-filter-file.json filters by the accessed class and only admitted io.seqera.tower.*.

Changes

  • Replace conf/{reflect,resource,jni,proxy,serialization,predefined-classes}-config.json with a single conf/reachability-metadata.json. The proxy, serialization and predefined-classes files were empty.
  • The new file is agent output (generator plus test -Dtracing-agent=true) merged with the previous reflection, JNI and resource entries. There is no legacy-to-unified converter, so the merge was a one-off script. Agent output alone had 1079 reflection types and missed the CLI's own classes and Jersey.
  • access-filter-file.json: include org.glassfish.jersey.inject.hk2.** so the JerseyClassAnalyzer entry is recorded by the agent instead of added by hand.
  • .sdkmanrc now targets GraalVM 25 (25.4.4+1-graal), matching CI.
  • build.gradle: log full stack traces of failing tests.
  • README and ReflectionConfigGenerator javadoc updated.

Notes

  • Regenerating on top of the committed file keeps all entries (rerun gives identical counts). Do not clear conf/ first, because config-merge-dir only merges into what is already there.
  • The merge only adds, so stale entries for removed SDK classes are not pruned.

Testing

  • Built the native image locally with Oracle GraalVM 25.4.4 and ran the suite against it (TOWER_CLI=build/native/nativeCompile/tw ./gradlew cleanTest test): 898 tests, 896 pass. The 2 failures (TaskCmdTest.testTaskDetail*) are a local locale artifact ($0,000000 vs $0.000000), the same as reported in build(native): fix native binary tests after Jersey 2.48 and SDK 1.236.0 bumps #718.
  • Verified that a traced InfoCmdTest run with the new access-filter rule captures JerseyClassAnalyzer with no manual entry and no other changes.
  • CI on this PR is the real confirmation.

🤖 Generated with Claude Code

… [COMP-2861]

CI builds with GraalVM 25, whose native-image-agent emits the unified
reachability-metadata.json format instead of the legacy per-category
files. Regenerating on the new toolchain therefore left reflect-config.json
untouched and master without the new Tower SDK entries.

Replace the legacy conf/*-config.json files (proxy, serialization and
predefined-classes were empty) with a single reachability-metadata.json:
agent output merged with the previous reflection, JNI and resource entries.
Point .sdkmanrc at GraalVM 25 to match CI and the Gradle toolchain.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
stefanoboriero and others added 2 commits October 19, 2026 14:45
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
…MP-2861]

Jersey 2.48 made JerseyClassAnalyzer public with a (ServiceLocator)
constructor that HK2 instantiates reflectively. Without a reflection
entry every API call in the native binary logged an HK2 reification
failure to stderr, failing 790 binary tests on CI.

access-filter-file.json filters by the accessed class and only admitted
io.seqera.tower.*, so the tracing agent never recorded Jersey/HK2
reflection and the entry had to be added by hand. Include
org.glassfish.jersey.inject.hk2.** so regenerating the metadata captures
it automatically, and add the captured entry.

Verified against a GraalVM 25 native build: 898 binary tests run, 896
pass; the 2 failures (TaskCmdTest.testTaskDetail*) are a local-locale
artifact ($0,000000 vs $0.000000).

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
@stefanoboriero
stefanoboriero requested a review from a team October 19, 2026 13:34
@stefanoboriero
stefanoboriero merged commit 4c66156 into master Oct 19, 2026
12 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants