Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
47 changes: 47 additions & 0 deletions .devcontainer/README.md
Original file line number Diff line number Diff line change
@@ -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 ./...
```
34 changes: 34 additions & 0 deletions .devcontainer/devcontainer.json
Original file line number Diff line number Diff line change
@@ -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" }
}
}
12 changes: 12 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down