|
| 1 | +# Development |
| 2 | + |
| 3 | +Building envbuilder currently **requires** a Linux system. |
| 4 | + |
| 5 | +On macOS or Windows systems, we recommend using a VM or the provided |
| 6 | +`.devcontainer` for development. |
| 7 | + |
| 8 | +## Requirements |
| 9 | + |
| 10 | +- Go (see the version in `go.mod`) |
| 11 | +- `make` |
| 12 | +- Docker daemon (for running tests) |
| 13 | + |
| 14 | +## Makefile targets |
| 15 | + |
| 16 | +- `build`: Builds and tags `envbuilder:latest` for your current architecture. |
| 17 | +- `develop`: Runs `envbuilder:latest` against a sample Git repository. |
| 18 | +- `test`: Runs tests. |
| 19 | +- `test-registry`: Stands up a local registry for caching images used in tests. |
| 20 | +- `docs/env-variables.md`: Updates the environment variables documentation. |
| 21 | + |
| 22 | +## Dependency management |
| 23 | + |
| 24 | +Envbuilder has several forked and interrelated dependencies that require care |
| 25 | +when upgrading. This section documents known constraints and pitfalls. |
| 26 | + |
| 27 | +### Kaniko |
| 28 | + |
| 29 | +Envbuilder uses a [fork of Kaniko](https://github.com/coder/kaniko) for |
| 30 | +container image building. The replace directive in `go.mod` points to this fork: |
| 31 | + |
| 32 | +``` |
| 33 | +replace github.com/GoogleContainerTools/kaniko => github.com/coder/kaniko <version> |
| 34 | +``` |
| 35 | + |
| 36 | +The Kaniko fork pins its own versions of `docker/docker`, |
| 37 | +`containerd/containerd`, and related packages. When upgrading deps, be aware |
| 38 | +that the versions resolved by Go's MVS (minimum version selection) may be higher |
| 39 | +than what the Kaniko fork expects if other dependencies (like `coder/coder/v2`) |
| 40 | +require newer versions. |
| 41 | + |
| 42 | +### Tailscale |
| 43 | + |
| 44 | +Envbuilder uses a [Coder fork of Tailscale](https://github.com/coder/tailscale) |
| 45 | +via a replace directive: |
| 46 | + |
| 47 | +``` |
| 48 | +replace tailscale.com => github.com/coder/tailscale <version> |
| 49 | +``` |
| 50 | + |
| 51 | +The `coder/coder/v2` module depends on symbols that only exist in this fork |
| 52 | +(e.g. `netns.SetCoderSoftIsolation`, `tsaddr.CoderServiceIPv6`). When upgrading |
| 53 | +`coder/coder/v2`, you **must** also update the Tailscale replace to match the |
| 54 | +version used in `coder/coder/v2`'s own `go.mod`. You can find it with: |
| 55 | + |
| 56 | +```bash |
| 57 | +grep 'replace tailscale.com' /path/to/coder/coder/go.mod |
| 58 | +``` |
| 59 | + |
| 60 | +### vishvananda/netlink and tailscale/netlink |
| 61 | + |
| 62 | +`tailscale/netlink` is a fork of `vishvananda/netlink` from 2021. Starting from |
| 63 | +`vishvananda/netlink` v1.3.0, the `XfrmAddress.ToIPNet` method gained an |
| 64 | +additional `family uint16` parameter, which breaks `tailscale/netlink`. |
| 65 | + |
| 66 | +If a transitive dependency (e.g. `containerd/containerd/v2`) pulls in |
| 67 | +`vishvananda/netlink` >= v1.3.0, you will see build errors like: |
| 68 | + |
| 69 | +``` |
| 70 | +not enough arguments in call to msg.Sel.Daddr.ToIPNet |
| 71 | + have (uint8) |
| 72 | + want (uint8, uint16) |
| 73 | +``` |
| 74 | + |
| 75 | +The fix is to add `exclude` directives in `go.mod` for the incompatible |
| 76 | +versions, forcing Go to select v1.2.x: |
| 77 | + |
| 78 | +``` |
| 79 | +exclude ( |
| 80 | + github.com/vishvananda/netlink v1.3.0 |
| 81 | + github.com/vishvananda/netlink v1.3.1-0.20250303224720-0e7078ed04c8 |
| 82 | +) |
| 83 | +``` |
| 84 | + |
| 85 | +You may need to add additional exclude directives if new versions are released. |
| 86 | + |
| 87 | +### moby/go-archive |
| 88 | + |
| 89 | +`docker/docker` (the `+incompatible` module) imports `github.com/moby/go-archive` |
| 90 | +and expects certain symbols (`archive.Uncompressed`, `archive.Compression`) at the |
| 91 | +package root. In `moby/go-archive` v0.2.0, these were moved to a `compression` |
| 92 | +subpackage and the top-level aliases were removed. |
| 93 | + |
| 94 | +If you see errors like: |
| 95 | + |
| 96 | +``` |
| 97 | +undefined: archive.Uncompressed |
| 98 | +undefined: archive.Compression |
| 99 | +``` |
| 100 | + |
| 101 | +Pin `moby/go-archive` to v0.1.0 in `go.mod`: |
| 102 | + |
| 103 | +```bash |
| 104 | +go mod edit -require 'github.com/moby/go-archive@v0.1.0' |
| 105 | +go mod tidy |
| 106 | +``` |
| 107 | + |
| 108 | +### General upgrade workflow |
| 109 | + |
| 110 | +When upgrading `coder/coder/v2` or other major dependencies: |
| 111 | + |
| 112 | +1. Update the dependency version in `go.mod`. |
| 113 | +2. Compare replace directives (especially `tailscale.com`) against the |
| 114 | + upstream module's `go.mod` and update to match. |
| 115 | +3. Run `go mod tidy`. |
| 116 | +4. Run `go build ./...` and check for compilation errors. |
| 117 | +5. If you see errors from transitive dependencies, check whether version |
| 118 | + conflicts can be resolved with `exclude` directives or by pinning |
| 119 | + specific versions with `go mod edit -require`. |
| 120 | +6. Run `make test` to verify everything works end-to-end. |
0 commit comments