Repository navigation
feat: localdev MODE=init|load with graceful-shutdown state dump - #16
Merged
Merged
Conversation
Rewrites the localdev container's entrypoint around two explicit modes so external orchestrators (storacha/smelt's snapshot feature) can drive post-deploy, post-registration state capture. Modes: - MODE=init: starts anvil with --dump-state, deploys contracts via deploy-local.sh, launches the mockrpc Filecoin proxy, and stays alive. On SIGTERM, a trap tears down mockrpc then anvil (in that order — mockrpc first so no late-arriving txs land in the snapshot), waits briefly for fs sync, then atomically copies anvil-state.json and deployed-addresses.json into $OUTPUT_DIR (default /output). The previous behavior killed anvil immediately after deploy — no window for external services to register before the dump. - MODE=load: loads a pre-deployed state file, starts mockrpc, stays alive. Also runs anvil with --dump-state so graceful shutdown captures the current (possibly post-registration) state. When /output is mounted writable, the trap copies the dump there too; otherwise it's a silent no-op. Lets an orchestrator snapshot a running chain by issuing docker stop. - MODE unset: autodetects (load if /app/anvil-state.json exists, else init). Keeps zero-config behavior working. Other changes: - Healthcheck in docker-compose.yml switched to `test -f /tmp/ready`. The sentinel is touched only after contracts are deployed (init) or state is loaded (load) AND mockrpc is accepting requests — more accurate than the previous eth_blockNumber port probe, which succeeded before contracts were available in init mode. - OUTPUT_DIR is configurable (default /output). - SIGTERM during deploy refuses to dump (DEPLOY_IN_PROGRESS guard + deploy-as-background-subprocess pattern so bash's trap fires promptly on signals rather than waiting for forge/cast children). Exits non-zero with a clear message rather than snapshotting a partially-deployed chain. - Breaking change: the old DUMP_STATE=true env var is removed. Replaced by MODE=init. README documents both modes and the opt-in dump-on-shutdown semantics of load mode. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
alanshaw
approved these changes
Apr 21, 2026
| > Use `MODE=init` instead. The critical behavioral difference is that init mode | ||
| > now stays alive after deploying contracts (so external services can register | ||
| > against the chain) and dumps state on graceful shutdown (SIGTERM), rather than | ||
| > dumping immediately after deploy. |
remove breaking changes section
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Rewrites the localdev container's entrypoint around two explicit modes so external orchestrators (storacha/smelt's snapshot feature) can drive post-deploy, post-registration state capture.
Modes:
MODE=init: starts anvil with --dump-state, deploys contracts via deploy-local.sh, launches the mockrpc Filecoin proxy, and stays alive. On SIGTERM, a trap tears down mockrpc then anvil (in that order — mockrpc first so no late-arriving txs land in the snapshot), waits briefly for fs sync, then atomically copies anvil-state.json and deployed-addresses.json into $OUTPUT_DIR (default /output). The previous behavior killed anvil immediately after deploy — no window for external services to register before the dump.
MODE=load: loads a pre-deployed state file, starts mockrpc, stays alive. Also runs anvil with --dump-state so graceful shutdown captures the current (possibly post-registration) state. When /output is mounted writable, the trap copies the dump there too; otherwise it's a silent no-op. Lets an orchestrator snapshot a running chain by issuing docker stop.
MODE unset: autodetects (load if /app/anvil-state.json exists, else init). Keeps zero-config behavior working.
Other changes:
test -f /tmp/ready. The sentinel is touched only after contracts are deployed (init) or state is loaded (load) AND mockrpc is accepting requests — more accurate than the previous eth_blockNumber port probe, which succeeded before contracts were available in init mode.README documents both modes and the opt-in dump-on-shutdown semantics of load mode.