sam-one: --tunnel codespaces, and a mesh of your own in a GitHub codespace - #522
Conversation
`--tunnel codespaces` advertises the https URL GitHub Codespaces assigns to the forwarded port, https://<CODESPACE_NAME>-<port>.<forwarding domain>, read from the environment GitHub sets. Nothing is started: GitHub runs the forwarder, and the provider is the same Tunnel shape cloudflare uses, so the banner, the QR code and the router advertisement work unchanged. A forwarded port is private to the codespace owner until they make it public, and no API inside the codespace can do that. The provider probes its own public URL in the background: GitHub's login redirect earns one warning with the exact click (and the gh command), and the first 200 through the proxy is confirmed in the log, so flipping the port is visible.
Two dev container configurations and one make target. `testnet` (and `testnet-latest`) copy the released sam-one and sam-node out of the published `stable` (or `latest`) images onto a plain base image, so a practitioner never compiles; `develop` is the Go, Node, Python and Docker toolchain with `make build` on create. In either, `make testnet` runs sam-one on port 8080 with `--tunnel codespaces`, keeps its state in the checkout's ignored .sam-one, and passes extra flags through ARGS; outside a codespace the same target is a local sam-one. The Codespaces guide states the contract: what GitHub provides (URL, idle stop, retention, private ports), what a public port exposes (the Cloud Run stance), what persists, and that the command is the one you take to Cloud Run or Kubernetes. README badges point at the testnet and develop configurations; Dependabot follows the features and the pinned base images.
There was a problem hiding this comment.
Code Review
This pull request introduces support for running and developing SAM inside GitHub Codespaces. It adds dev container configurations for both development (with Go, Node, Python, and Docker toolchains) and testnet environments (using stable or latest pre-built binaries). A new codespaces tunnel provider is implemented in internal/tunnel/codespaces.go (along with unit tests) to automatically detect the Codespace environment, derive the public HTTPS URL, and probe the forwarded port's visibility, providing actionable warnings if the port is private. Additionally, the Makefile is updated with a testnet target, and extensive documentation and README badges are added to guide users. I have no feedback to provide as there are no review comments.
The devcontainers go and base images ship without sshd, so gh codespace ssh cannot reach a codespace built from them. The sshd feature is what GitHub's own documentation prescribes for that case.
A control plane of your own in a GitHub codespace, for two audiences: a practitioner who wants a public testnet without installing anything or holding a cloud account, and a contributor who wants to build and test in the browser and point external clients (SDK programs, a phone) at their branch.
What is in it
sam-one --tunnel codespaces(internal/tunnel/codespaces.go). A tunnel provider for the forwarder GitHub already runs: it deriveshttps://<CODESPACE_NAME>-<port>.<GITHUB_CODESPACES_PORT_FORWARDING_DOMAIN>from the environment GitHub sets, starts nothing, and plugs into the sameTunnelshape as cloudflare, so the banner, the QR code and the router advertisement work unchanged. A forwarded port is private to the codespace owner until they make it public, which no API inside the codespace can do; the provider probes its own public URL in the background, warns once with the exact click (and theghcommand) when GitHub's login gate answers, and confirms the first200through the proxy. Unit tests cover URL derivation, the environment check and the probe state machine (gateway errors, login gate, public, deadline, cancel).Dev containers. Three configurations:
.devcontainer/testnet/copies the releasedsam-oneandsam-nodeout ofghcr.io/google/sam-one:stable/sam-node:stableonto a plain base image: no toolchain, nothing compiled..devcontainer/testnet-latest/is the same from:latest(main). Together they mirror hub and bananas..devcontainer/devcontainer.jsonis the Go 1.27 image plus Node, Python and Docker-in-Docker features, withmake buildon create.make testnetrunssam-one --data-dir ./.sam-one --port 8080 --tunnel codespaces(the tunnel flag only whenCODESPACE_NAMEis set, so on a laptop it is a localsam-one), prefers./bin/sam-oneover the one onPATH, and passes extra flags throughARGS. The state directory is ignored by git and, in a codespace, survives rebuilds.Docs. A Codespaces guide that states the contract: what GitHub provides (URL, idle stop, retention, private ports), what a public port exposes (the same stance as Cloud Run
--allow-unauthenticated), what persists, and that the command line is the one you take to Cloud Run or Kubernetes. The reference documents the provider; the getting-started tables and the contributing page gain the option; README gets two badges. Dependabot follows the dev container features and the digest-pinned base images.Validation
go build ./...,go vet, golangci-lint and the dead-code check are clean; provider tests pass with-race.302to the login page while private, transparent once public,HostandX-Forwarded-Protoset):make testnetprinted the documented command and the public URL in the banner, the provider warned while private and confirmed after the flip,/infoadvertised/dns4/<host>/tcp/443/wss, and asam-nodeenrolled over the public URL and authenticated with the router overwssthrough the proxy.make buildon create takes about three minutes on 2 cores;make testnetused the branch's own./bin/sam-onein the develop container and the image binary in the testnet one.Rollout note
The
testnetconfigurations run the published images, which do not have--tunnel codespacesuntil this merges (latest) and is tagged (stable); until then they fail with a clearunknown tunnel provider "codespaces". Thedevelopconfiguration works from this branch. Still to confirm in a real codespace: WebSocket through GitHub's public port, whether the proxy sendsX-Forwarded-Proto, and whether port visibility survives stop/start.