Skip to content

feat(environment): add --detach to 'environment new' for background duplication#937

Open
0xnmn wants to merge 1 commit into
masterfrom
0xnmn/environment-new-detach
Open

feat(environment): add --detach to 'environment new' for background duplication#937
0xnmn wants to merge 1 commit into
masterfrom
0xnmn/environment-new-detach

Conversation

@0xnmn

@0xnmn 0xnmn commented Jun 4, 2026

Copy link
Copy Markdown
Contributor

Problem

railway environment new <name> --duplicate <src> is non-atomic. The CLI:

  1. creates an empty environment (EnvironmentCreate with sourceId: null),
  2. client-side fetches the source config,
  3. applies it via EnvironmentPatchCommit,

…all sharing one hardcoded 30s HTTP timeout (src/client.rs). The server-side environmentCreate blocks the HTTP response by long-polling its Temporal workflow until the service + volume copy completes (measured p50 ~13s, p95 ~118s). When the copy exceeds 30s the CLI aborts with operation timed out — but the empty env from step 1 already exists, so a broken orphan ("husk") is left behind, and retries collide on the name. The reporter sees this fail the majority of the time.

Fix

The backend already exposes the right primitives on EnvironmentCreatesourceEnvironmentId (atomic server-side duplicate) and applyChangesInBackground (defer the heavy copy to a background child workflow) — the CLI just never used them.

This adds an opt-in --detach flag to environment new that mirrors the railway up --detach "trigger + return, user polls" idiom:

  • --detach ⇒ a single EnvironmentCreate { sourceId: <dup>, applyChangesInBackground: true }, then returns immediately. The copy runs server-side in the background.
  • Atomic path ⇒ no husk on the detached path.
  • --detach + --service-config/--service-variableerrors with a clear message, since the server-side copy can't apply CLI-side per-service overrides.
  • Long-only flag (-d is already taken by --duplicate), matching --json in this command.

Default behavior is unchanged — without --detach, the existing create→fetch→apply→wait flow runs exactly as before. No breaking change.

Usage

railway environment new pr-843 --duplicate staging --detach --json
# → returns in ~1–3s with {"id","name"}; copy completes in the background.
# Poll with: railway environment   (or the dashboard)

Test plan

  • cargo build clean; cargo fmt
  • railway environment new --help shows --detach
  • --detach --duplicate <src> returns immediately; services/volumes populate shortly after (verify on staging)
  • --detach --service-config … errors clearly, creates nothing
  • default (no --detach) unchanged
  • empty --detach create works

Follow-ups (out of scope)

  • Wire applyChangesInBackground into the MCP create_environment tool (src/commands/mcp/tools/project.rs).
  • backboard: return after StartWorkflowExecution rather than long-polling GetWorkflowExecutionHistory, so even the synchronous prelude doesn't block the request under worker contention.

Closes #923

🤖 Generated with Claude Code

…uplication

`railway environment new --duplicate <src>` is non-atomic today: the CLI
creates an empty env, then client-side fetches the source config and applies
it, all under a hardcoded 30s HTTP timeout. The server-side environmentCreate
blocks the response until the service + volume copy finishes (p95 ~118s), so
duplicates of non-trivial envs routinely exceed 30s, abort, and leave an
orphaned empty environment behind.

Add an opt-in `--detach` flag that uses the backend's atomic path
(sourceEnvironmentId) with applyChangesInBackground:true, so the copy runs in
a background workflow and the call returns immediately. Default behavior is
unchanged. `--detach` errors if combined with --service-config/-variable,
since the server-side copy can't apply CLI-side per-service overrides.

Closes #923
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.

railway environment new --duplicate leaves an orphaned empty environment when duplication exceeds the hardcoded 30s client timeout

1 participant