Skip to content

fix(devnet): scope the ha-el reth overrides, and keep .claude out of the build context - #1059

Merged
panos-xyz merged 2 commits into
mainfrom
fix/devnet-scope-ha-el-reth-override
Sep 3, 2026
Merged

fix(devnet): scope the ha-el reth overrides, and keep .claude out of the build context#1059
panos-xyz merged 2 commits into
mainfrom
fix/devnet-scope-ha-el-reth-override

Conversation

@panos-xyz

@panos-xyz panos-xyz commented Sep 2, 2026

Copy link
Copy Markdown
Contributor

Problem

make devnet-up-reth started three containers that immediately died:

docker-ha-el-0-1   Exited (2)
docker-ha-el-1-1   Exited (2)
docker-ha-el-2-1   Exited (2)

error: Invalid value '/genesis.json' for --chain <CHAIN_OR_PATH>: No such file or directory
    [possible values: mainnet,hoodi]

docker-compose-reth.yml carried reth overrides for ha-el-0/1/2 behind this comment:

The ha-el-* overrides below only take effect when docker-compose-cluster.yml is passed as well; otherwise these services do not exist and compose ignores them.

That is not how compose merges files. A service named by any -f file is created, whether or not an earlier file declared it — there is no "override-only" form of a service definition. So in the non-cluster devnet those three ha-el-* entries were not overrides of anything; they were full service definitions consisting of only what the reth file happened to specify: an image, an entrypoint, a command with --chain=/genesis.json, and a single ha-nodekeyN mount. The /genesis.json and /jwt-secret.txt mounts live in docker-compose-cluster.yml, which is not loaded in that mode, so reth had no chain spec to read and exited before doing anything else.

Nothing on the sequencer path breaks as a result — this is why it went unnoticed — but every devnet-up-reth leaves three failed containers and three stray datadir volumes behind, and docker compose up reports the failures.

Fix

Move the three ha-el-* reth overrides into a new docker-compose-cluster-reth.yml, layered only when both --cluster and reth are requested, in Makefile and in devnet.compose_file_args. The plain reth devnet now resolves to exactly the geth devnet's service list; the cluster path is unchanged.

Also corrects the same wrong claim where it is repeated in ops/README.md and in the two code comments that restate it.

Verification

docker compose config --services, all four combinations:

mode services
geth morph-el-0/1, node-0/1, tx-submitter-0, gas-price-oracle, layer1-*
reth identical to geth ✅ (was: + ha-el-0/1/2)
geth + cluster above + ha-el-0/1/2, ha-node-0/1/2
reth + cluster identical to geth + cluster ✅

The cluster override still applies — merged ha-el-* in reth + cluster:

image      = ghcr.io/morph-l2/morph-reth:latest
entrypoint = ['/usr/local/bin/morph-reth']
command    contains --chain=/genesis.json
mounts     = /db, /db/geth/nodekey, /db/geth/static-nodes.json,
             /genesis.json, /jwt-secret.txt, /p2p-secret.key

make -n devnet-down per mode resolves to the intended -f lists, and DEVNET_CLEAN_COMPOSE_FILES covers the new file so devnet-clean-build still reaps cluster leftovers.

python3 -m unittest discover -s ops/devnet-morph/tests — 14 tests, all pass. Three are new or reworked:

  • test_reth_compose_leaves_cluster_services_to_the_cluster_reth_file — regression guard: docker-compose-reth.yml must not name ha-el-* at all.
  • test_cluster_reth_compose_overrides_the_ha_execution_clients — the new file carries all three, with the reth image/entrypoint and one key mount each, and does not redefine morph-el-*.
  • test_reth_compose_configures_deterministic_peering — narrowed to the two morph-el-* that remain in that file.

End-to-end: make devnet-clean-build && make devnet-up-reth on a wiped devnet brings up
morph-el-0/1, node-0/1, tx-submitter-0, gas-price-oracle and the three layer1-*
containers, with no ha-el-* container created and nothing in Exited state (before this
change the same command left three Exited (2)). morph-el-0 produces blocks normally.

Note morph-el-1 sits at height 0 for the first ~10 minutes after startup, until
tx-submitter-0 commits its first batch — node-1 runs with
MORPH_NODE_DERIVATION_VERIFY_MODE=layer1, so L1 derivation is its only source of blocks.
That behaviour is unrelated to this change and is present on main too; it is being looked
at separately.


Second commit: exclude .claude from the docker build context

Rebuilding morph-node:latest while diagnosing an unrelated devnet problem showed the
build context climbing past 20 GB before any build step ran. .dockerignore excludes
.git (1.1 GB) and prover/ (1.2 GB), but not .claude/ — which is 1.0 GB on any
machine that has used a Claude Code worktree (.claude/worktrees):

repo total                     6125 MB
  .git                         1094 MB   (excluded)
  prover                       1205 MB   (excluded)
  .claude                      1010 MB   <- not excluded
  contracts/node_modules        718 MB   (excluded)

Nothing under .claude/ is read by a build. One line in .dockerignore, next to the
other excluded top-level directories, plus the matching assertion in the existing
test_root_dockerignore_excludes_generated_build_outputs. Context after this change
measures 1.74 GB, in line with the ~2.0 GB the repo needs.

(The 20 GB figure itself is not fully explained by this one directory and is not claimed
to be: ops/docker/.devnet holds four 4 GB sparse mdbx files — 16 GB logical, ~1 MB on
disk — but a targeted COPY probe confirms .dockerignore does exclude that path, so
something else contributed. Excluding .claude/ is correct on its own merits either way.)

docker-compose-reth.yml carried reth overrides for ha-el-0/1/2 on the
assumption that compose would ignore them unless
docker-compose-cluster.yml was layered in as well. It does not: compose
creates any service a later -f file names, whether or not an earlier
file declared it. So `make devnet-up-reth` also started three ha-el-*
containers, which only got the -f file's own ha-nodekey mount and none
of the /genesis.json or /jwt-secret.txt mounts that live in the cluster
file. All three died immediately with

    error: Invalid value '/genesis.json' for --chain <CHAIN_OR_PATH>:
    No such file or directory

Move those three service overrides into docker-compose-cluster-reth.yml
and pass it only when both --cluster and reth are asked for, so the
plain reth devnet now resolves to exactly the geth devnet's service
list. The cluster path is unchanged: ha-el-* still come up on the reth
image and entrypoint with the cluster's mounts intact.
@panos-xyz
panos-xyz requested a review from a team as a code owner September 2, 2026 09:46
@panos-xyz
panos-xyz requested review from twcctop and removed request for a team September 2, 2026 09:46
@coderabbitai

coderabbitai Bot commented Sep 2, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Team

Run ID: 6b2a8b01-dbd9-4d24-ac3f-0d1cf14a42fe

📥 Commits

Reviewing files that changed from the base of the PR and between bb68fe1 and 0401a72.

📒 Files selected for processing (6)
  • Makefile
  • ops/README.md
  • ops/devnet-morph/devnet/__init__.py
  • ops/devnet-morph/tests/test_devnet_config.py
  • ops/docker/docker-compose-cluster-reth.yml
  • ops/docker/docker-compose-reth.yml

Included review availability: Your plan provides up to 1 included review per hour; 0 remain after this review.


📝 Walkthrough

Walkthrough

The change moves HA Reth services into a dedicated cluster Compose override. Makefile and Python devnet configuration include this override only for cluster Reth runs. Tests and documentation reflect the new Compose layering.

Changes

Cluster Reth override flow

Layer / File(s) Summary
Separate cluster Reth services
ops/docker/docker-compose-cluster-reth.yml, ops/docker/docker-compose-reth.yml, ops/README.md
The new override defines ha-el-0 through ha-el-2 with cluster mounts, endpoints, and static peers. The shared Reth file retains only non-cluster services. Documentation describes the required layering.
Select cluster overrides
Makefile, ops/devnet-morph/devnet/__init__.py
Cluster Reth runs now append docker-compose-cluster-reth.yml to the Compose files. Cleanup includes the new file.
Validate Compose selection and topology
ops/devnet-morph/tests/test_devnet_config.py
Tests validate service placement, peer counts, secret mounts, Compose file ordering, and cluster-mode selection.

Estimated code review effort: 2 (Simple) | ~10 minutes

Merge Risk: ⚪ Minimal · up to 0401a

The change limits HA execution clients to cluster-enabled Reth devnets while preserving cluster behavior and cleanup. No actionable merge-blocking risk remains after normal checks and review.

Suggested reviewers: tomatoishealthy, segueii

🚥 Pre-merge checks | ✅ 3 | ❌ 2

❌ Failed checks (2 warnings)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 42.86% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 7 functions across 2 files. (4 skipped: 4… Write docstrings for the functions missing them to satisfy the coverage threshold.
Title check ⚠️ Warning The title correctly identifies scoping the HA Reth overrides, but it also claims that .claude is kept out of the build context. The provided changes do not include that change. Remove the unrelated .claude clause, or include the corresponding build-context changes in this pull request.
✅ Passed checks (3 passed)
Check name Status Explanation
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Full details: Docstring Coverage

Explanation

Docstring coverage is 42.86% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 7 functions across 2 files. (4 skipped: 4 unsupported.)

  • Fix all pre-merge checks with AI
✨ Finishing Touches 💡 1
📝 Generate docstrings 💡
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/devnet-scope-ha-el-reth-override

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

Claude Code keeps its git worktrees under .claude/worktrees. On a machine
that has used one, .claude is 1.0 GB -- comparable to .git (1.1 GB) and
prover (1.2 GB), both of which .dockerignore already excludes. Nothing
under it is ever needed by a build, so every image build was shipping it
as build context: ~3.0 GB transferred where ~2.0 GB is required.
@panos-xyz panos-xyz changed the title fix(devnet): keep the ha-el reth overrides out of the plain devnet fix(devnet): scope the ha-el reth overrides, and keep .claude out of the build context Sep 2, 2026
@panos-xyz
panos-xyz merged commit b058227 into main Sep 3, 2026
7 checks passed
@panos-xyz
panos-xyz deleted the fix/devnet-scope-ha-el-reth-override branch September 3, 2026 04:52
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