Skip to content

The e2e suite can delete a developer's real devpod workspaces #103

Description

@blooop

Question

Running the e2e suite on a host deletes that host's real devpod workspaces. Make
it impossible.

Graduated from the conflict-scoping ticket,
which found this while enumerating collisions. Three facts compose into a footgun:

  • dl --purge deletes every workspace devpod list returns
    (devlaunch/dl.py:335-339) — it has no notion of "only mine".
  • An e2e test exercises exactly that, for real, at
    test/e2e/test_full_workflow.py:266.
  • devpod list reads ~/.devpod, not anything under XDG_*. So the scratch
    XDG_CACHE_HOME/XDG_CONFIG_HOME dance that CLAUDE.md prescribes does not
    protect you here. devlaunch never sets DEVPOD_HOME (grep -rn DEVPOD_HOME .
    is empty).

So pytest -m e2e run on a developer's machine — by habit, by a misconfigured
editor, by an agent that did not read the marker config — destroys their whole
workspace list. The addopts = "-m 'not e2e'" default in pyproject.toml:126 is
the only thing standing between a developer and that, and a default is not a
safeguard.

The same ticket found a second, milder instance: the suite's workspace ids are
hardcoded constants — e2e-test-{create,lifecycle,git,purge} at
test/e2e/test_full_workflow.py:52,86,136,235 — and teardown devpod delete --forces them, so two concurrent e2e runs delete each other's workspaces.

This is a wayfinder:build ticket: go through /tdd.

Test-first, and note the shape of the red test. The failing test cannot be
"run --purge and see what dies" — the red state of that test is the damage.
Write it at a seam instead: the thing under test is that the suite refuses to
touch state it did not create. Candidate seams, pick and justify one — a fixture
that refuses to run destructive e2e unless pointed at a scoped DEVPOD_HOME; a
guard asserting devpod list is empty or contains only this run's ids before any
--force delete; per-run unique ids so the constants stop being shared at all.

Prefer the smallest thing that makes the bad outcome unrepresentable rather than
merely unlikely (principles 2 and 3) — a guard that can be forgotten at the next
new test is weaker than a scoping that applies to the whole suite at once.

Scope note. Whether dl --purge itself should learn a narrower blast radius
in production is a separate question and is not this ticket — this ticket makes
the test suite safe to run. If the work suggests the production behaviour is
also wrong, say so on the ticket and let the map graduate it.

Relation to the daemon. Inside a dind devcontainer each run gets its own
~/.devpod and its own daemon, so the nested daemon fixes this incidentally.
That is not a reason to skip it: the suite must be safe when someone runs it
outside a container, which is precisely the case nobody is protected from today.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions