Skip to content

build(maru): wire :maru:* subprojects into the linea-monorepo build#3126

Draft
gauravahuja wants to merge 12 commits into
mainfrom
feat/wire-maru-into-monorepo
Draft

build(maru): wire :maru:* subprojects into the linea-monorepo build#3126
gauravahuja wants to merge 12 commits into
mainfrom
feat/wire-maru-into-monorepo

Conversation

@gauravahuja
Copy link
Copy Markdown
Contributor

Summary

Companion to #3100 (the history-only import). That PR landed maru/ under linea-monorepo with full git history but the subtree didn't yet build. This PR makes it build.

12 logical commits, separable for review:

  • chore: remove maru's own .github/, settings.gradle, and buildSrc/.
  • build: add libp2p / JitPack / Splunk repos to kotlin-common-minimal-conventions; register :maru:* subprojects in monorepo settings.gradle; rewrite apply plugin: lines to net.consensys.zkevm.kotlin-*-conventions; rewrite project(':<name>') refs to project(':maru:<name>'); substitute build.linea.internal:* deps with local :jvm-libs:* subprojects; fold maru/gradle/versions.gradle into gradle/libs.versions.toml.
  • ci: port 6 maru workflows to .github/workflows/maru-*.yml (chaos, e2e, smoke, build-and-publish, release, testing) and wire maru_changed into main.yml, testing.yml, build-and-publish.yml, reuse-check-images-tags-and-push.yml.
  • build(maru): pin Vert.x 4 + Micrometer 1.12 for maru subprojects only — Besu 26.5's acceptance-tests-dsl is bytecode-bound to removed Vert.x 4 types (io.vertx.core.impl.ConcurrentHashSet), removed methods (Vertx.nettyEventLoopGroup), and the pre-1.13 io.micrometer.prometheus.* package, none of which can be supplied by class-level shims. Maru's :maru:app swaps :jvm-libs:generic:vertx-helper for the published Vert.x-4-era build.linea.internal:vertx-helper:0.0.1-v20260327160734 (resolves from Maven Central). Drop this once Besu moves to Vert.x 5.

Verification (local)

  • :maru:*:compileKotlin (main, test, integrationTest, acceptanceTest sources): all green.
  • :maru:jvm-libs:test-utils:test: 32/32 pass.
  • :maru:app:integrationTest: 38/39 pass + 1 known QBFT round-change flake (passes on retry; unrelated to anything in this PR).
  • ./gradlew spotlessCheck (whole monorepo): green.
  • git log --follow maru/<file> and git blame maru/<file>: history attribution preserved post-import.

Deferred to follow-up PRs

  1. security-code-scanner.yml port — needs SECURITY_SCAN_METRICS_TOKEN and APPSEC_BOT_SLACK_WEBHOOK GitHub secrets provisioned in linea-monorepo first.
  2. PR-time wiring for maru-chaos-testing.yml, maru-smoke-tests.yml, maru-e2e-tests.yml — workflow files exist but are only reachable via workflow_dispatch. Standalone maru's main.yml wired chaos (on path changes) and smoke (every PR); we can replicate once we're satisfied the base testing path is stable.
  3. Aggregated Jacoco upload for maru — currently per-subproject **/build/jacoco/*.exec is uploaded as jacoco-maru-exec (coordinator-style), but the monorepo's jacoco-report job doesn't yet consume it.
  4. Move :jvm-libs:generic:vertx-helper (Vert.x 5) back — once Besu 26.6+ moves to Vert.x 5, drop the Vert.x 4 / Micrometer 1.12 force in maru/build.gradle and switch maru's app back to the local vertx-helper.

Notes for review

  • Docker secret rename in maru-build-and-publish.yml: DOCKER_ORG_NAMEDOCKERHUB_USERNAME, DOCKER_REPO_TOKENDOCKERHUB_TOKEN (reuses the monorepo's existing secrets).
  • Release tag pattern changed v*maru-v* to avoid colliding with other components in the monorepo.
  • Maru subprojects use catalog accessors via "${libs.versions.X.get()}" interpolation, matching the coordinator/* pattern. Maru-only catalog entries added: discovery, dockerComposeRule, http4k, javalin, jvmLibp2p, kotlinxDatetime, lineaPackages, okhttp, pktsCore, rocksdbjni.

Test plan

  • CI green on the new maru-testing job.
  • CI green on existing zkevm components (coordinator-*, linea-besu-*, tracer-*, etc. — should be unaffected since maru changes are subproject-scoped).
  • Spot-check git log --follow on a maru file from the merged PR view.

Workflows will be re-added at the monorepo root as .github/workflows/maru-*.yml
with paths filters in a later commit (mirrors the tracer import pattern from
PR #1852). Maru's dependabot.yml, pull_request_template.md, and ISSUE_TEMPLATE/
are dropped — the monorepo has its own equivalents.
The maru subprojects will be wired directly into zkevm/settings.gradle as
:maru:* includes in a later commit. There is only one Gradle settings.gradle
per build, so maru's own settings.gradle must go.
A Gradle build supports only one buildSrc. Maru's five convention plugins
(maru.kotlin-{common-minimal,common,library,library-minimal,application}-conventions)
are functionally equivalent to zkevm's existing net.consensys.zkevm.kotlin-*
family — same five conventions, with zkevm's being slightly richer (catalog-driven
versions, --enable-native-access JVM arg, consistent dependency resolution,
annotation-default-target).

Maru subprojects' 'apply plugin: maru.kotlin-X-conventions' lines will be
switched to 'apply plugin: net.consensys.zkevm.kotlin-X-conventions' in a
later commit.
…entions

Required for the imported maru subprojects which depend on:
  - io.libp2p:jvm-libp2p (cloudsmith) — used by maru's p2p, crypto, utils
  - com.github.multiformats:* (jitpack) — libp2p transitive
  - com.splunk.* — parity with maru's previous build setup

Each repository is content-filtered to the specific group(s) it serves so
resolution doesn't unnecessarily query these endpoints for unrelated artifacts.
Adds 22 includes mirroring maru's original settings.gradle layout, with
paths re-rooted under :maru:* (e.g. ':app' → ':maru:app', 'jvm-libs:extensions'
→ 'maru:jvm-libs:extensions'). The 'include maru' line ties maru's existing
build.gradle to the :maru subproject; the next commit gutts that file to drop
dependencies on the removed maru/buildSrc + gradle/versions.gradle.
The io.spring.dependency-management plugin is added with 'apply false' on the
root project's plugin classpath so maru subprojects can apply it via
'alias(libs.plugins.dependencyManagement)' in their own plugins{} block.

Maru relies on dependencyManagement for BOM-driven version resolution from
maru/gradle/versions.gradle (unversioned 'implementation' declarations
resolved via the dependencyManagement{} DSL). A follow-up commit folds
versions.gradle into the catalog, after which most subprojects can drop the
plugin.
…ct paths

- Switch every maru subproject's apply-plugin line from 'maru.kotlin-X-conventions'
  to 'net.consensys.zkevm.kotlin-X-conventions'. Maru's conventions were
  removed in an earlier commit; zkevm's same-named conventions are functional
  equivalents.

- Add 'alias(libs.plugins.dependencyManagement)' to each maru subproject's
  plugins{} block. Maru relies on this for BOM-driven version resolution from
  maru/gradle/versions.gradle (unversioned 'implementation' declarations
  resolved via the dependencyManagement{} DSL).

- Apply maru/gradle/versions.gradle directly in each subproject (after the
  plugins{} block). A parent-level subprojects{ apply from } closure doesn't
  work because the parent's closure evaluates before the subproject's plugins
  block has applied dependencyManagement.

- Rewrite all 'project(":<name>")' refs in maru's subprojects to
  'project(":maru:<name>")'. Maru's internal cross-references like
  'project(":api")' previously resolved from maru's own rootProject; in the
  monorepo they need the full :maru:* path.

- Gut maru/build.gradle to a minimal parent that only layers the SPDX
  license-header + Java importOrder Spotless rules on top of the monorepo's
  base config. All other configuration (errorprone, jacoco, JaCoCo aggregation,
  test args, all the allprojects/subprojects boilerplate) is now provided by
  the monorepo's root build.gradle and zkevm/buildSrc conventions.

- Add Vert.x + micrometer + linea metrics/micrometer/vertx-helper deps to
  maru/app/build.gradle. These were previously bundled by maru's
  kotlin-application-conventions plugin (deleted with maru/buildSrc); zkevm's
  lighter kotlin-application-conventions doesn't bundle them, so they go
  explicit in app/build.gradle.

Build is not yet green: build.linea.internal:* deps still resolve as remote
artifacts via versions.gradle's lineaPackagesVersion default. The next commit
folds gradle/versions.gradle into the catalog and substitutes those refs to
local zkevm subprojects.
…oject refs

Maru's subprojects depended on 13 build.linea.internal:* artifacts via
versions.gradle's dependencyManagement BOM pins. Those artifacts are products
of the zkevm-monorepo build itself, so in the monorepo we wire them as project
references instead of remote dependencies. Mapping:

  build.linea.internal:metrics              → :jvm-libs:linea:core:metrics
  build.linea.internal:micrometer           → :jvm-libs:linea:metrics:micrometer
  build.linea.internal:vertx-helper         → :jvm-libs:generic:vertx-helper
  build.linea.internal:json-rpc             → :jvm-libs:generic:json-rpc
  build.linea.internal:futures              → :jvm-libs:generic:extensions:futures
  build.linea.internal:kotlin               → :jvm-libs:generic:extensions:kotlin
  build.linea.internal:domain-models        → :jvm-libs:linea:core:domain-models
  build.linea.internal:interfaces           → :jvm-libs:linea:clients:interfaces
  build.linea.internal:linea-contract-clients → :jvm-libs:linea:clients:linea-contract-clients
  build.linea.internal:web3j-extensions     → :jvm-libs:linea:web3j-extensions
  build.linea.internal:file-system          → :jvm-libs:linea:testing:file-system
  build.linea.internal:logging              → :jvm-libs:generic:logging
  build.linea.internal:long-running-service → :jvm-libs:linea:core:long-running-service

Two small source fixes were needed for compilation under the monorepo:

  - QbftFinalStateAdapter.kt:58: '.equals(localAddress)' → '== localAddress'
    (Kotlin 2.x flags the explicit .equals() call as deprecated; zkevm's
    -Werror would otherwise fail the build).
  - ConsensusMetrics.kt:70: drop 'percentileBuckets = [...]' parameter from
    metricsFacade.createHistogram(). zkevm's :jvm-libs:linea:core:metrics
    interface does not yet expose that parameter (newer maru-side API).
    publishPercentileHistogram=true is still set, so histograms still emit
    percentiles with default buckets.

Build is green: './gradlew :maru:app:compileKotlin -x spotlessCheck' succeeds.
gradle/versions.gradle is still applied per-subproject and still pins maru-only
external deps (Discovery, jvm-libp2p, Javalin, http4k, etc.); the next commit
folds those into gradle/libs.versions.toml and removes versions.gradle.
Each maru subproject previously applied the io.spring.dependency-management
plugin and `apply from: maru/gradle/versions.gradle`, which used Spring DM
BOM imports (vertx-stack-depchain, besu, slf4j-bom) to govern transitive
versions. This duplicated zkevm's own version source-of-truth and pulled
Vert.x 4 in via the Besu BOM, conflicting with the local Vert.x 5
:jvm-libs:generic:vertx-helper at runtime.

Move every maru subproject onto zkevm's gradle/libs.versions.toml:
  - add maru-only entries (discovery, jvm-libp2p, javalin, http4k, okhttp,
    pkts-core, rocksdbjni, docker-compose-rule, kotlinx-datetime)
  - reuse existing aliases (jackson, guava, hoplite, picoli, tuweni, teku,
    web3j, log4j, awaitility, etc.) via "${libs.versions.X.get()}"
    interpolation, matching the coordinator/* pattern
  - leave org.hyperledger.besu* and io.vertx:* versionless: aligned by
    root build.gradle's eachDependency rule and kotlin-common-conventions'
    vertx-stack-depchain platform respectively
  - drop libs.plugins.dependencyManagement and `apply from versions.gradle`
    from all 21 subprojects
  - delete maru/gradle/versions.gradle and the stale
    maru/gradle/libs.versions.toml left over from the import

Also: replace deprecated Hash.toString() (-Werror failure post-fold) with
.bytes.toHexString() in BesuTransactionsHelper.
Port maru's standalone-repo workflows to live at the monorepo root,
mirroring the established coordinator-*/tracer-*/linea-besu-* pattern:

  - maru-testing.yml          (unit + integration tests, codecov)
  - maru-build-and-publish.yml (docker image build via shared composite)
  - maru-chaos-testing.yml    (workflow_dispatch only for now)
  - maru-e2e-tests.yml        (workflow_dispatch only for now)
  - maru-smoke-tests.yml      (workflow_dispatch only for now)
  - maru-release.yml          (triggered by maru-v* tags)

Wire maru into the orchestrator workflows:
  - main.yml: add `maru` paths-filter and pipe `maru_changed`/
    `maru_image_tagged` into check-and-tag-images, testing, and
    build-and-publish
  - testing.yml: add maru_changed input + maru job
  - build-and-publish.yml: add maru_changed/maru_image_tagged inputs
    and maru job
  - reuse-check-images-tags-and-push.yml: add maru_changed input,
    image_tagged_maru output, and the corresponding image-tag check
    and push steps

Transformations applied per workflow:
  - Gradle invocations rewritten to :maru:* task paths
  - setup-java + setup-gradle replaced by ./.github/actions/setup-
    java-and-gradle composite
  - DOCKER_ORG_NAME / DOCKER_REPO_TOKEN renamed to DOCKERHUB_USERNAME /
    DOCKERHUB_TOKEN to share zkevm's existing Docker secrets
  - Release tag pattern changed from `v*` to `maru-v*` to avoid
    colliding with other components in the monorepo
  - CHANGELOG and tar paths rebased to maru/

Deferred:
  - security-code-scanner.yml (needs SECURITY_SCAN_METRICS_TOKEN and
    APPSEC_BOT_SLACK_WEBHOOK secrets provisioned first)
  - PR-time wiring for chaos / smoke / e2e (workflows exist but are
    only reachable via workflow_dispatch in this PR)
  - Aggregated jacoco upload (per-subproject .exec artifacts uploaded
    as jacoco-maru-exec; monorepo's jacoco-report job not yet
    consuming this artifact)
…mpat

Maru integration tests use Besu 26.5's acceptance-tests-dsl
(ThreadBesuNodeRunner, Cluster) to spin up real Besu nodes in-JVM. Besu
26.5's bytecode is bound to:

  - Removed Vert.x 4 internal types: io.vertx.core.impl.ConcurrentHashSet,
    used by PeerPermissionsDenylist / MaintainedPeers /
    PrometheusMetricsSystem / PrometheusGuavaCache$Context /
    AccessLocationTracker$AccountAccessList.
  - Removed Vert.x 4 methods on still-present types:
    Vertx.nettyEventLoopGroup() (Vert.x 5 removed it entirely).
  - The pre-1.13 Micrometer Prometheus package
    io.micrometer.prometheus.PrometheusMeterRegistry (renamed to
    io.micrometer.prometheusmetrics.PrometheusMeterRegistry in 1.13+).

Class-level shims can cover removed types but not removed methods on
interfaces we don't own, so maru's test runtime must actually be on Vert.x 4
+ Micrometer 1.12.

Force in :maru's subprojects { ... } block:
  - all io.vertx:* (except vertx-stack-depchain, to avoid colliding with
    zkevm convention's strict 5.0.10 platform pin) -> 4.5.24
  - all io.micrometer:* -> 1.12.13

And swap :maru:app's vertx-helper from the local Vert.x 5
:jvm-libs:generic:vertx-helper to the published Vert.x 4-era
build.linea.internal:vertx-helper:0.0.1-v20260327160734 so its bytecode
references resolve cleanly against the forced runtime.

Verified:
  - :maru:jvm-libs:test-utils:test: 32 / 32 pass (was 23 / 32)
  - :maru:app:integrationTest: 38 / 39 pass (was 0 / 39); 1 flake passes
    on retry, unrelated to Vert.x

Drop the entire eachDependency block and switch back to
:jvm-libs:generic:vertx-helper once Besu moves to Vert.x 5.
Missed by the catalog-fold conversion; caught by ./gradlew spotlessCheck
on the monorepo-wide pass.
@gauravahuja gauravahuja requested a deployment to docker-build-and-e2e May 15, 2026 19:51 — with GitHub Actions Waiting
@github-actions
Copy link
Copy Markdown
Contributor

linea-besu Changelog Preview (informational)

[Unreleased] diff (commits touching linea-besu/** since latest releases/linea-besu/v* tag)

[unreleased]

Generated by git-cliff-action using cliff.toml. This comment is informational and does not gate the PR.

@github-actions
Copy link
Copy Markdown
Contributor

tx-exclusion-api Changelog Preview (informational)

[Unreleased] diff (commits touching tx-exclusion-api/** since latest releases/tx-exclusion-api/v* tag)

[unreleased]

⚙️ Miscellaneous Tasks

Generated by git-cliff-action using cliff.toml. This comment is informational and does not gate the PR.

@github-actions
Copy link
Copy Markdown
Contributor

coordinator Changelog Preview (informational)

[Unreleased] diff (commits touching coordinator/** since latest releases/coordinator/v* tag)

[unreleased]

Generated by git-cliff-action using cliff.toml. This comment is informational and does not gate the PR.

@github-actions
Copy link
Copy Markdown
Contributor

prover Changelog Preview (informational)

[Unreleased] diff (commits touching prover/** since latest releases/prover/v* tag)

[unreleased]

🐛 Bug Fixes

⚙️ Miscellaneous Tasks

Generated by git-cliff-action using cliff.toml. This comment is informational and does not gate the PR.

@github-actions
Copy link
Copy Markdown
Contributor

postman Changelog Preview (informational)

[Unreleased] diff (commits touching postman/** since latest releases/postman/v* tag)

[unreleased]

⚙️ Miscellaneous Tasks

Generated by git-cliff-action using cliff.toml. This comment is informational and does not gate the PR.

if-no-files-found: ignore
- name: Upload test results to Codecov
if: ${{ !cancelled() && env.CODECOV_TOKEN != '' }}
uses: codecov/test-results-action@v1
@codecov-commenter
Copy link
Copy Markdown

codecov-commenter commented May 15, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 77.27%. Comparing base (b56778e) to head (a066739).
⚠️ Report is 341 commits behind head on main.

Additional details and impacted files
@@             Coverage Diff              @@
##               main    #3126      +/-   ##
============================================
+ Coverage     77.25%   77.27%   +0.02%     
- Complexity     6991     7007      +16     
============================================
  Files          1121     1118       -3     
  Lines         44418    44394      -24     
  Branches       5335     5343       +8     
============================================
- Hits          34314    34307       -7     
+ Misses         8751     8723      -28     
- Partials       1353     1364      +11     
Flag Coverage Δ *Carryforward flag
hardhat 96.17% <ø> (ø)
kotlin 55.96% <ø> (+0.03%) ⬆️
lido-governance-monitor 97.61% <ø> (ø) Carriedforward from b56778e
linea-native-libs 90.69% <ø> (ø)
linea-shared-utils 96.18% <ø> (ø) Carriedforward from b56778e
native-yield-automation-service 97.68% <ø> (ø) Carriedforward from b56778e
postman 99.92% <ø> (ø)
sdk-core 98.09% <ø> (ø) Carriedforward from b56778e
sdk-ethers 89.83% <ø> (ø) Carriedforward from b56778e
sdk-viem 99.45% <ø> (ø)
tracer 88.55% <ø> (ø) Carriedforward from b56778e

*This pull request uses carry forward flags. Click here to find out more.
see 97 files with indirect coverage changes

🚀 New features to boost your workflow:
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@socket-security
Copy link
Copy Markdown

Review the following changes in direct dependencies. Learn more about Socket for GitHub.

Diff Package Supply Chain
Security
Vulnerability Quality Maintenance License
Addedgithub/​softprops/​action-gh-release@​3bb12739c298aeb8a4eeaf626c5b8d85266b0e65100100100100100
Addedgithub/​azure/​setup-helm@​1a275c3b69536ee54be43f2070a358922e12c8d4100100100100100

View full report

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.

3 participants