From f71e79ba5964bf88654ac94392ff24018ee25d5a Mon Sep 17 00:00:00 2001 From: "Frederic G. MARAND" Date: Thu, 2 Jul 2026 10:05:02 +0200 Subject: [PATCH] Add optional dev container (documentation branch, not for merge) Explored a Dev Container for envrun; verified working (CLI + GoLand) but it is a net minus here: envrun is a single Go binary depending only on the toolchain, so the container adds complexity that benefits no one, and native dev is simpler and faster. Kept on this branch as a worked reference - prebuilt-image vs Feature / Netskope-CA rationale, editor-agnostic customizations, dogfooding postCreateCommand - and deliberately left unmerged. See .devcontainer/README.md. --- .devcontainer/README.md | 47 +++++++++++++++++++++++++++++++++ .devcontainer/devcontainer.json | 34 ++++++++++++++++++++++++ README.md | 12 +++++++++ 3 files changed, 93 insertions(+) create mode 100644 .devcontainer/README.md create mode 100644 .devcontainer/devcontainer.json diff --git a/.devcontainer/README.md b/.devcontainer/README.md new file mode 100644 index 0000000..3c884a0 --- /dev/null +++ b/.devcontainer/README.md @@ -0,0 +1,47 @@ +# Dev container for envrun + +This folder adds an optional [Dev Container](https://containers.dev) so envrun +can be developed inside a reproducible, editor-agnostic environment. It is +purely additive: the repo remains a plain Go project, and `go`/`make`/your +native IDE keep working unchanged whether or not you use this. + +## What it sets up + +- A **single container** (no Docker Compose, no extra services): envrun is a + CLI with no runtime dependencies, so the environment is one container. +- A **prebuilt Go image** (`mcr.microsoft.com/devcontainers/go`) with the Go + toolchain baked in via the registry pull. We deliberately use this rather than + the base image plus the Go *Feature*: a Feature fetches the toolchain from + `go.googlesource.com` at build time, which can fail behind a TLS-inspecting + corporate proxy when the container's trust store lacks the proxy CA. A + prebuilt image needs no such fetch, so it builds reliably in both plain and + proxied environments. +- A **lifecycle hook** (`postCreateCommand`) that runs `go mod download` and + then `make demo` - which dogfoods envrun by running it on this repo's own + `.env.demo`. Creating the container demonstrates the tool working. + +`make lint` (`go tool staticcheck ./...`), `make test`, and `make build` all +work in-container with no extra configuration. + +## Opening it (three interchangeable ways) + +Any tool that implements the Dev Container spec can drive this same file: + +- **VS Code** (Dev Containers extension): open the repo, then "Reopen in + Container". +- **JetBrains / GoLand** (Gateway or the Dev Containers action): open the + `devcontainer.json`; the IDE backend runs *inside* the container and a thin + client attaches. The container can be local or remote - "remote" just means a + separate environment, not necessarily a separate machine. +- **CLI**: `devcontainer up --workspace-folder .` (from `@devcontainers/cli`), + then `devcontainer exec --workspace-folder . make test`. + +## Try the dogfood by hand + +Inside the container (or natively): + +```sh +make demo # envrun injects .env.demo into `env`, sorted +make lint # go tool staticcheck ./... +make test # go test -race ./... +``` diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json new file mode 100644 index 0000000..934a9e1 --- /dev/null +++ b/.devcontainer/devcontainer.json @@ -0,0 +1,34 @@ +{ + // envrun dev container: an editor-agnostic Go dev environment that also + // dogfoods envrun itself. See ./README.md for what each part demonstrates. + "name": "envrun", + + // Prebuilt Go dev-container image: the Go toolchain arrives baked in via the + // registry pull. We deliberately do NOT use the base image + Go *feature* + // here: the feature fetches the toolchain from go.googlesource.com at build + // time, which fails behind a TLS-inspecting corporate proxy (e.g. Netskope) + // when the container's trust store lacks the proxy CA. A prebuilt image needs + // no such fetch, so it works both in plain and proxied environments. + // Tag tracks Go 1.25.x (>= go.mod's `go 1.25.8`); GOTOOLCHAIN handles the rest. + "image": "mcr.microsoft.com/devcontainers/go:1.25-bookworm", + + // Lifecycle hook: runs once after the container is created, with the source + // tree mounted. It fetches deps and then runs envrun on itself via the repo's + // own `make demo` target (LOCAL=demo go run . -f .env.demo env | sort), so the + // act of creating the container demonstrates the tool working (visible in the + // create log). `make lint` (go tool staticcheck) and `make test` also work + // in-container with no extra setup. + "postCreateCommand": "go mod download && make demo", + + // Editor setup the workspace declares for whatever client attaches. + // `customizations` is namespaced per tool: each editor reads ONLY its own + // block and ignores the others, so a single spec configures every client. + "customizations": { + // VS Code: install the Go extension into the in-container editor server. + "vscode": { "extensions": ["golang.go"] }, + // JetBrains (GoLand / Gateway): `backend` selects which JetBrains IDE + // backend runs inside the container - GoLand for a Go repo. `plugins` + // (marketplace IDs) and `settings` could also go here. VS Code ignores this. + "jetbrains": { "backend": "GoLand" } + } +} diff --git a/README.md b/README.md index 77b18f3..4a5007d 100644 --- a/README.md +++ b/README.md @@ -132,6 +132,18 @@ Why the parsing lives in an importable package, what shape that package has, and what was declined on the way: [ADR-002](docs/adr/002-splitting-the-command-from-the-library.md). +## Developing + +Standard Go tooling works directly: `make test`, `make lint` +(`go tool staticcheck ./...`), and `make build`. +Run `make demo` to watch `envrun` inject `.env.demo` into the `env` command. + +A [Dev Container](https://containers.dev) is also provided under +[`.devcontainer/`](.devcontainer/README.md) for a reproducible, +editor-agnostic environment (open it with VS Code, JetBrains/Gateway, or the +`devcontainer` CLI). It is purely additive: native development is unaffected. + + ## Support - Non-security questions: use [Github issues](https://github.com/fgm/envrun/issues)