Skip to content

fix(env): a snapshot reload edits the deployed compose file and restarts every service, the browser included - #404

Merged
earakely-scale merged 2 commits into
mainfrom
edgararakelyan/fd-4655-snapshot-reload-browser
Oct 30, 2026
Merged

earakely-scale merged 2 commits into
mainfrom
edgararakelyan/fd-4655-snapshot-reload-browser

Conversation

@earakely-scale

@earakely-scale earakely-scale commented Oct 30, 2026 •

Copy link
Copy Markdown
Collaborator

What and why

Loading a universe from a snapshot swaps a multi env's database for the snapshot's. Until now the reload:

  • Re-rendered the whole compose file from the current config. A reload after the default browser changes, as it will when FD-4648 moves the stages from website-browser to playwright-mcp, would write a gateway and browser that don't match the running deploy.
  • Restarted only the MCP servers, the gateway, pgweb and db-mcp. The website backends and frontends and the browser kept running across the database swap.

Now the reload reads the compose file the deploy wrote and points its servicedb at the snapshot image. It also drops the schema init script, which a snapshot doesn't need, and changes nothing else in the file. Then it recreates every service in the file except servicedb.

  • snapshot_compose(compose, db_image) makes the edit. It refuses a file that doesn't name the servicedb's image exactly once, and an image reference that isn't valid.
  • The reload no longer reads the gateway, browser or service-db envs for their images. It reads the service-db env only for the state store that the changelog triggers use.

Fixes FD-4655.

How it was tested

  • Unit:
    • The reload tests were rewritten. They check that every service but servicedb is kept byte for byte, for browsers named website-browser or browseruse-mcp, whatever the config's default, and that every service but servicedb is recreated, the browser included.
    • They also check that the file is written as data, that a second reload swaps the image again, and the refusals.
    • Full unit tier: 10,947 passed. The one failure, test_the_event_pipe_is_not_left_open_in_the_server, reads /proc/self/fd, which macOS doesn't have.
  • End to end, on Modal VM against AgentEnvHub's dev store, main and this branch:
Case main this branch
multi-slack-email loading test-universe v198 from its stored snapshot (env-snapshot-multi-slack-email v48) Restored; 6 of 6 services recreated Same
psi-stayncook-multi (an MCP server, a website, the browser), reloaded from a snapshot of its own database 5 of 8 recreated. stayncook-website-backend, stayncook-website-frontend and website-browser kept their old containers 8 of 8 recreated, all running

Main and this branch agree on everything else:

  • After the reload, the compose file differed from the deployed one only in the servicedb's image line and its init-script mount, and every other service kept the image it was deployed with.
  • The data came back from the snapshot:
    • multi-slack-email had 100 email and 120 slack rows, and list_emails returned the universe's mail.
    • In the psi-stayncook-multi runs, a marker table was made before the snapshot was taken and dropped from the live database afterwards. It came back after the reload.
  • The MCP tools returned the snapshot's data. The browser loaded the site ("Eathnbn"), and its page grew from 1,265 characters before the data to 16,980.

The psi-stayncook-multi snapshot was never stored. The run builds the image on the VM the way a snapshot bake does, without the upload, and hands it to _load_from_snapshot, so the store got only the deploys' own records. All deploys were torn down.

🤖 Generated with Claude Code

RetriggerView in GreptileConfidence Score: 5/5

The PR appears safe to merge; the service-name failure is fixed and no new actionable issues were found.

Summary

Snapshot reloads keep the deployed compose file, replace the database image, and recreate every other service, including the browser.

  • Snapshot reloads keep deployed services and restart them against the restored database.

Diagram

%%{init: {'theme': 'neutral'}}%%
flowchart LR
    A[Read deployed compose file] --> B[Replace database image and remove init mount]
    B --> C[Recreate database and wait for health]
    C --> D[Read service names as strings]
    D --> E[Recreate every other service]
    E --> F[Wait for gateway and restore change tracking]
Loading

Reviews (2) · Last reviewed commit: "fix(env): read the reload's service name..." · Reviewed by Greptile

…rts every service, the browser included

The reload re-rendered the compose file from the current config, so a change of default browser between deploy and
reload would rename the running browser, and it recreated only the MCP servers, gateway, pgweb and db-mcp, leaving the
websites and the browser on containers from before the database swap. It now changes only the servicedb's image and
init-script mount in the file the deploy wrote, and recreates every service but servicedb.

Fixes FD-4655.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
@earakely-scale
earakely-scale requested a review from a team as a code owner October 30, 2026 04:24
Comment thread src/agent_env/env/envs/multi_env.py Resolved
safe_load follows YAML 1.1, so a service named on, 123 or null came back as True, an int or None: shlex.quote raised,
or quoted None as an empty name, after the database had already been swapped.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
@earakely-scale

Copy link
Copy Markdown
Collaborator Author

🤖 Automated Claude routine — Env Pod PR Context Review. This is a bot, not Edgar Arakelyan; not a human review.

Context from outside this diff: another open PR rewrites the same block this one deletes.

_load_from_snapshot here (src/agent_env/env/envs/multi_env.py:601) drops the create_docker_compose re-render, and with it the website_configs = [WebsiteConfig(backend_image=…, frontend_image=env.frontend_docker_image_artifact.image_name, …)] list. #391 edits that same list instead, to website_configs = [website_config(env) for env in self.website_envs] (src/agent_env/env/envs/multi_env.py:616 on its head wloo/web-apps-deploy) — needed because #390 makes frontend_docker_image_artifact optional (src/agent_env/env/envs/website.py:55), so .image_name on it is a None dereference for a one-image site.

So the two changes overlap and only one survives the merge. Worth noting for whoever lands second: reading the deployed compose in place already covers the one-image case (website services are never re-rendered), so the website_config(env) hunk can simply drop out — the thing to avoid in a conflict resolution is bringing back the old frontend_docker_image_artifact.image_name line, which the website stack makes unsafe.


Generated by Claude Code

@earakely-scale
earakely-scale merged commit 5e2310e into main Oct 30, 2026
25 checks passed
@earakely-scale
earakely-scale deleted the edgararakelyan/fd-4655-snapshot-reload-browser branch October 30, 2026 14:58
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.

1 participant