Skip to content

Comments

sandbox: add CLI for GCE sandbox environments#303

Closed
dashed wants to merge 14 commits intomainfrom
alberto/sandbox-commands
Closed

sandbox: add CLI for GCE sandbox environments#303
dashed wants to merge 14 commits intomainfrom
alberto/sandbox-commands

Conversation

@dashed
Copy link
Member

@dashed dashed commented Feb 17, 2026

Summary

Adds the devservices sandbox command group for managing GCE-based development environments. This provides a complete CLI for creating, managing, and developing on cloud sandbox VMs pre-configured with all Sentry dependencies.

Subcommands (17)

Command Description
sandbox create Create a new sandbox VM
sandbox ssh SSH into sandbox with auto port-forwarding
sandbox ssh-config Generate/manage SSH config for IDE integration
sandbox sync Pull latest branch changes and update dependencies
sandbox logs View devserver/service logs (with --color/--no-color)
sandbox port-forward Background port forwarding with named profiles
sandbox migrate Run database migrations
sandbox restart-devserver Restart the devserver systemd unit
sandbox exec Run arbitrary commands on the sandbox
sandbox hybrid Local devserver + remote services mode
sandbox start Start a stopped sandbox
sandbox stop Stop a sandbox (preserves disk)
sandbox destroy Delete a sandbox and its disk
sandbox list List all sandboxes
sandbox status Show sandbox details
sandbox start-iap-tunnel Start IAP tunnel for port forwarding
sandbox stop-iap-tunnel Stop IAP tunnel

Key Features

SSH Config (ssh-config)

  • Generates ~/.ssh/config entries with IAP ProxyCommand, connection keepalives, and port forwarding
  • --append writes to config, --remove cleans up, default prints to stdout
  • Uses BEGIN/END markers for idempotent upsert/removal
  • Enables VS Code Remote-SSH, JetBrains Gateway, and Mutagen

Convenience Commands (migrate, restart-devserver, exec)

  • Run common operations without SSH sessions
  • exec supports arbitrary commands with proper error handling

Port Profiles

  • Named port profiles: devserver (8000), services (PostgreSQL, Redis, Kafka, Snuba, ClickHouse, Relay, Spotlight), all
  • Used by port-forward, ssh, and hybrid commands

Hybrid Mode (hybrid)

  • Stops remote devserver, forwards all service ports to localhost
  • Local devserver connects to forwarded ports transparently (all sentry services use 127.0.0.1)
  • Socket-based port conflict detection before stopping remote devserver
  • Reversible with --stop (restarts remote devserver, stops port forwarding)

Colored Logs (logs --color/--no-color)

  • Auto-detects terminal (colors when stdout is a TTY, plain when piped)
  • Forced PTY allocation via --ssh-flag=-tt (double -t to force even without local tty)
  • Uses journalctl -o cat when colors enabled to preserve stored ANSI codes (default --short format strips them)
  • ANSI code stripping via remote sed when --no-color or piped
  • --color forces colors through pipes (e.g., | less -R)
  • Works with sandbox packer Part C (--pretty devserver + FORCE_COLOR=1) for rich HTTP status, prefix, and error coloring

Tests

196 tests (107 command + 85 utility + 4 profile) — all passing.

Test plan

  • All existing tests pass
  • Parser tests for all new subcommands and flags
  • Command tests with mocked SSH, gcloud, and state
  • SSH config generation, write, remove, and idempotency tests
  • Port profile parsing tests
  • Hybrid mode port conflict detection tests
  • Color flag auto-detect, force-on, force-off tests
  • PTY allocation tests for ssh_stream
  • Verified on live sandbox: --color shows ANSI-colored output, --no-color strips codes
  • Follow mode (-f) with color streaming tested on live sandbox

Add 6 sandbox subcommands (create, ssh, stop, start, destroy, list) to
manage GCE-based development environments via gcloud CLI. This includes
gcloud wrapper utilities, SQLite state tracking for sandbox instances,
a SandboxError exception hierarchy, and GCE constants.

The Docker precheck is moved after argument parsing so sandbox commands
work without Docker running.
@github-actions
Copy link

github-actions bot commented Feb 17, 2026

Semver Impact of This PR

None (no version bump detected)

📋 Changelog Preview

This is how your changes will appear in the changelog.
Entries from this PR are highlighted with a left border (blockquote style).


Bug Fixes 🐛

  • (state) Gracefully handle stale service entries in state database by vaind in #302

Internal Changes 🔧

Release

  • Fix changelog-preview permissions by BYK in #300
  • Switch from action-prepare-release to Craft by BYK in #299

Other

  • sandbox: add CLI for GCE sandbox environments by dashed in #303

🤖 This preview updates automatically when you update the PR.

Add Phase 3 developer workflow commands:
- sync: pull latest branch changes via maintenance-sync.sh over SSH
- status: show instance details with port-forward state and hints
- port-forward: background SSH tunnels with PID lifecycle tracking
- API validation on create (iap.googleapis.com, compute.googleapis.com)
- Auto-kill port-forward tunnels on stop/destroy
@dashed dashed changed the title sandbox: add CLI commands for GCE sandbox environments sandbox: add CLI for GCE sandbox environments Feb 17, 2026
Forward port 8000 by default when running `sandbox ssh`, eliminating the
need for a separate `port-forward` command. Users can customize with
`--ports 8000,8010` or skip with `--no-forward`.
Replace hardcoded URL strings in test assertions with SANDBOX_REQUIRED_APIS
constant references to fix 3 high-severity "Incomplete URL substring
sanitization" alerts. Add explicit `permissions: contents: read` to build,
lint, and test workflows to fix 5 medium-severity missing permissions alerts.
Adds `devservices sandbox logs [SERVICE]` to view logs from sandbox VM
services. Supports devserver/webpack (default), startup orchestration,
and Docker containers (postgres, redis, kafka, etc.) with partial name
matching. Includes follow mode (-f) for real-time tailing.
Adds LOCAL:REMOTE syntax to --ports flag, e.g. `--ports 8000,15432:5432`
forwards localhost:15432 to sandbox:5432. Plain port numbers (e.g. 8000)
continue to work as before, mapping same port on both sides.
Allows overriding the sentry repo checkout to a specific branch or SHA,
independent of the getsentry/sentry-version pin. Useful when developing
features that span both repos.

Usage:
  devservices sandbox create my-sandbox --branch feat/gs --sentry-ref feat/sentry
  devservices sandbox sync --sentry-ref abc123def
Generates SSH config entries with IAP ProxyCommand, enabling direct SSH,
VS Code Remote-SSH, JetBrains Gateway, and Mutagen file sync without
specifying gcloud flags each time.

Supports --append to write to ~/.ssh/config, --remove to clean up, and
--ports for LocalForward directives. Uses BEGIN/END markers for safe
upsert and removal of config entries.
- migrate: runs make apply-migrations on the sandbox VM
- restart-devserver: restarts sandbox-devserver systemd unit
- exec: runs arbitrary commands on the sandbox via SSH
Add named profiles (devserver, services, all) to --ports flag for quick
port forwarding of service groups. Enables hybrid workflow where
devserver runs locally while connecting to sandbox Docker services.
Single command to toggle hybrid mode: stops the remote devserver,
forwards all service ports, and prints instructions. Reversible
with --stop which restarts the devserver and kills port forwarding.
Check if service ports are already in use locally before entering hybrid
mode. Warns about conflicts and suggests running devservices down. Port
check happens before stopping the remote devserver, so cancelling has
no side effects.
Enable terminal color passthrough for `sandbox logs` by:
- Adding `--color/--no-color` flag with auto-detect (TTY → colors, pipe → plain)
- Adding `tty` parameter to `ssh_stream()` for PTY allocation (`--ssh-flag=-t`)
- Stripping ANSI codes via remote sed when colors are disabled
- Switching non-follow mode to streaming output for direct terminal passthrough
Two fixes discovered during live sandbox testing:

1. SSH PTY: Changed --ssh-flag=-t to --ssh-flag=-tt. The single -t
   requires stdin to be a terminal, but subprocess.Popen doesn't have
   one. Double -tt forces PTY allocation regardless.

2. journalctl output format: The default --short format strips ANSI
   escape codes from stored messages. When colors are enabled, use
   -o cat which outputs raw message content preserving ANSI codes
   written by the --pretty devserver.
@dashed dashed closed this Feb 20, 2026
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