chore: install dogfood image tooling via mise.toml#25282
Merged
Conversation
Replace the curl-tar-go-install chains across the dogfood Ubuntu 22.04 and 26.04 Dockerfiles with a single `mise install` driven by a new repo-root `mise.toml`. The previous Dockerfiles installed ~25 CLIs across three multi-stage builds with versions hardcoded inline; version bumps were scattered, build-time network failures came from a dozen distinct endpoints, and the mise binary added in The Dockerfiles now COPY `mise.toml` to `/etc/mise/config.toml` and install everything into `/opt/mise/data` (image-owned, outside the persistent home volume, so version bumps reach every workspace on recreate). Build context moves to the repo root so the Dockerfile can reach `mise.toml`; an allowlist `.dockerignore` keeps the transferred context to ~24 kB. The build accepts an optional `--secret id=github_token` so aqua's GitHub API quota goes from 60/hr unauthenticated to 1000/hr with the workflow's `secrets.GITHUB_TOKEN`. The dogfood CI workflow is updated to pass that secret and to point at the new build context + file. Change-Id: Ia8b93019fd34ef89a804e50ec4bb1b10c1efecd6 Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> Signed-off-by: Thomas Kosiewski <tk@coder.com>
`scripts/check_go_versions.sh` and the lint job in `.github/workflows/ci.yaml` previously grepped `ARG GO_VERSION=` and `ARG GOLANGCI_LINT_VERSION=` out of the dogfood Dockerfiles. The migration to `mise.toml` removed those ARGs, so both grep calls returned the empty string and the downstream commands failed (Go version mismatch / `go install ...@v`). Point both readers at `mise.toml`, which is the single source of truth for image tool versions after the migration. Change-Id: I49bb4948303f4c6359eace4e45d57213021bc33f Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> Signed-off-by: Thomas Kosiewski <tk@coder.com>
The previous commit added a 2-line comment above the golangci-lint cache-dir step in ci.yaml, shifting the `actions/cache` line from 188 to 190 and invalidating the line-anchored zizmor suppression. Change-Id: Id41fa6a2c4f9939eb7b594b5b4f75ffbbe08feaa Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> Signed-off-by: Thomas Kosiewski <tk@coder.com>
Aggregated fixes from a code review of the dogfood mise migration:
- Restore `gh` to apt-installed /usr/bin/gh (and remove from mise.toml)
so the `files/usr/local/bin/gh` wrapper continues to bridge
`coder external-auth` into gh authentication. Mise's shim at
${MISE_DATA_DIR}/shims would otherwise win PATH precedence and
bypass the wrapper.
- Replace the line-anchored zizmor `cache-poisoning` suppression
in `.github/zizmor.yml` with an inline `# zizmor: ignore` comment
on the offending step in `ci.yaml`, so the suppression survives
future line shifts.
- Fix the stale `GOLANGCI_LINT_VERSION=` grep in `Makefile:748`'s
`lint/go` target; matches the same `mise.toml` read used in
`.github/workflows/ci.yaml`.
- Replace literal `/opt/mise/data` / `/home/coder:/etc/mise`
occurrences in the dogfood Dockerfiles with the existing
`$MISE_DATA_DIR` and `$MISE_TRUSTED_CONFIG_PATHS` ENV references.
- Drop the pointless `bash -c 'set -euo pipefail; …'` wrapper that
was only protecting a single `mise install` invocation.
- Trim a narrative comment in `mise.toml` and replace an emdash so
`make lint/emdash` stays happy.
Change-Id: Id4358de0710390d39f0e6d8637ac175785435263
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Signed-off-by: Thomas Kosiewski <tk@coder.com>
The inline `# zizmor: ignore[cache-poisoning]` was on the same line as `- name:`, but zizmor anchors the cache-poisoning finding to the `uses: actions/cache@…` line and ignores comments on the step name. Move the comment to its own line directly above the `uses:` line, matching the pattern already used in `.github/workflows/contrib.yaml` for `dangerous-triggers`. Change-Id: I7ca0b1023db2227fb2a8945d1f99614319f0c9be Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> Signed-off-by: Thomas Kosiewski <tk@coder.com>
…risk The single `actions/cache` step ran on every trigger including `pull_request`, so a PR could write content into the cache that subsequent runs (on main or other PRs) would restore from. The previous workaround was a zizmor `cache-poisoning` suppression on that line. Replace it with the standard restore/save split: - `actions/cache/restore` runs unconditionally (PRs may read trusted caches saved by main). - `actions/cache/save` only runs on `refs/heads/main` and only when there was no exact-key hit, so PRs cannot write to the cache. This makes the suppression unnecessary; both have been removed. Change-Id: I1698113632c267b13df1c36b98f75ef4404f3050 Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> Signed-off-by: Thomas Kosiewski <tk@coder.com>
aslilac
reviewed
May 13, 2026
aslilac
left a comment
Member
There was a problem hiding this comment.
I'd love it if we could maintain the ability to use mise while the workspace is running in addition to using it for image prep
Reverts the MISE_DATA_DIR location from /opt/mise/data (image-only) back to ~/.local/share/mise, which sits under /home/coder and is backed by the per-workspace home volume declared in dogfood/coder/main.tf. With this change: - Fresh workspaces still start with every tool pre-installed: Docker's first-mount-copy seeds the empty home volume from /home/coder in the image, so the workspace gets the image-baked mise data dir immediately with no `mise install` downloads. - `mise install`s the user performs at runtime persist across workspace recreates because the home volume is per-workspace and long-lived. - Image tool-version bumps reach *new* workspaces (fresh volumes copy from the image) but not existing workspaces, matching the trade-off Homebrew already accepts on this image — see the /home/linuxbrew volume comment in main.tf. Also tightened the surrounding comment blocks: dropped the running narrative about "why we did this differently" and condensed each block to the minimum needed to understand the invariant at that line. Change-Id: I036bb884480d4cd15406ea0732b968cfbd5aab85 Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> Signed-off-by: Thomas Kosiewski <tk@coder.com>
v4.15.1 transitively requires github.com/mitchellh/osext, whose upstream GitHub repo has been deleted, so `mise install` fails to resolve the module graph. v4.16.0+ drops the dep, and v4.19.0 matches the version already pinned in go.mod. Change-Id: I825e43bf2bc963333a23f28af5382ceb48e827f5 Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> Signed-off-by: Thomas Kosiewski <tk@coder.com>
Change-Id: I37df49e9b1470ed592b4e4063b90b48626cf8dd6 Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> Signed-off-by: Thomas Kosiewski <tk@coder.com>
aslilac
approved these changes
May 13, 2026
aslilac
left a comment
Member
There was a problem hiding this comment.
this just seems like a super nice w. I'm always on board for simplifying a Dockerfile, and this is a huuuuuge simplification. good work!
jdomeracki-coder
left a comment
Contributor
There was a problem hiding this comment.
Note
This review was generated by Coder Agents on behalf of @jdomeracki-coder.
Security review: no critical issues. Two high-severity supply-chain findings, two medium. Net security posture improves (cache-poisoning fix, allowlist .dockerignore, correct BuildKit secret usage, digest-pinned base images).
- mise.toml: pin the five tools previously set to "latest"
(lazygit 0.61.1, doctl 1.158.0, jj 0.41.0, typos 1.46.1,
watchexec 2.5.1) so a compromised upstream release is not
auto-consumed at the next image build.
- mise.toml: re-add `[settings] lockfile = true` and commit
the generated `mise.lock`. Plain `mise lock` populates all
reasonable platforms (linux-{arm64,arm64-musl,x64,x64-musl},
macos-{arm64,x64}, windows-x64), so the repo now carries an
auditable per-tool checksum baseline that replaces the
hand-rolled `sha256sum -c` we used to do for Go.
- ubuntu-22.04 / ubuntu-26.04 Dockerfiles: narrow
`MISE_TRUSTED_CONFIG_PATHS` from `/home/coder` to
`/home/coder/coder` so a malicious mise.toml dropped
anywhere else under the workspace home no longer auto-runs
its [hooks] / [tasks] without a `mise trust` prompt.
- dogfood/coder/Makefile: quote `$(GITHUB_TOKEN_FILE)` in the
build-secret arg so a path with shell metacharacters can't
manipulate the `docker build` command.
Change-Id: I5de42fbe5fe4145342c1f91702c8faefb3f72898
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Signed-off-by: Thomas Kosiewski <tk@coder.com>
Mount mise.lock alongside /etc/mise/config.toml so the dogfood image build verifies download checksums during `mise install` (closes the build-time integrity half of jdomeracki-coder's review). Mechanics: - COPY mise.toml /etc/mise/config.toml + COPY mise.lock /etc/mise/mise.lock. mise reads the lockfile via name-match next to the system config (verified empirically with a deliberately-bad checksum probe). - Pre-create /etc/mise as 0755 before the COPYs. BuildKit's --chmod=0644 on a COPY whose destination dir does not exist apparently propagates the mode to the implicitly-created parent, leaving /etc/mise without the x bit and unreachable for the coder user (which silently produced "0 tools to install"). Use --chmod=0644 explicitly on the file COPYs so a future regen under a tight umask doesn't ship an unreadable lockfile. - MISE_GLOBAL_CONFIG_FILE is NOT overridden — `mise use --global` must continue to write to ~/.config/mise/config.toml on the per-workspace home volume so user-installed tools persist. - Pin helm to "v3.12.0" so the manifest version matches the upstream tarball naming (mise's aqua plugin still drops the `v` from URL templates, so the lockfile URL is patched by scripts/mise_lock.sh after each `mise lock`). Adds scripts/mise_lock.sh to wrap `mise lock` with the helm URL workaround so future regens don't reintroduce 404s. Change-Id: I499605a1231901bc84ffe46532db57cf121f8512 Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> Signed-off-by: Thomas Kosiewski <tk@coder.com>
aqua's helm plugin emits an URL without the `v` prefix (404).
github backend can't resolve a binary (helm only ships .asc files
on GitHub). ubi is deprecated in favor of github. http backend
with `mise.jdx.dev/dev-tools/backends/http.html` templating lets
us point at get.helm.sh directly with a single URL that handles
linux + macos via {{os()}}/{{arch()}} remapping.
Drops scripts/mise_lock.sh — no sed wrapper needed anymore since
the http backend doesn't have the URL-templating bug.
Trade-off: mise.lock doesn't auto-populate per-platform checksums
for http-backend tools (only the version pin is recorded). For
helm specifically, we accept "URL is pinned, checksum is not". The
other ~30 tools still get full URL+checksum verification.
Windows-x64 is omitted from the helm template because helm's
windows release uses .zip and would need a separate platform
override. The dogfood image is linux/amd64-only and nobody on the
team runs helm via mise on Windows.
Change-Id: I2020d8d23b5cad70777dcb7597ea13d0f4357640
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Signed-off-by: Thomas Kosiewski <tk@coder.com>
`make lint/emdash` rejected four emdash characters I introduced in mise-related comments on ubuntu-22.04 and ubuntu-26.04 Dockerfiles during this PR. Replace with semicolons per the lint rule's example. Change-Id: I93c36ee572db212a9e8956288f2c374d0a905f32 Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> Signed-off-by: Thomas Kosiewski <tk@coder.com>
jdomeracki-coder
approved these changes
May 15, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to subscribe to this conversation on GitHub.
Already have an account?
Sign in.
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
This PR replaces the hand-rolled
curl | tar | go install | cargo installchains in the dogfood Ubuntu 22.04 and 26.04 Dockerfiles with a singlemise installdriven by a new repo-rootmise.toml.The previous Dockerfiles installed ~25 CLIs across three multi-stage builds with versions hardcoded inline. Version bumps were scattered across the Dockerfiles, the root
mise.toml(added in #24618 but otherwise unused at runtime), and CI's setup actions; build-time network failures came from a dozen distinct endpoints; andmiseitself sat in the image with no manifest to install from.The new flow:
mise.tomlis the single source of truth for image tool versions. The DockerfilesCOPYit to/etc/mise/config.tomland run a singlemise installas thecoderuser./opt/mise/datarather than the default/home/coder/.local/share/mise, so they live in the image (not on the persistent home volume) and reach every workspace on recreate.COPY mise.toml; an allowlist.dockerignorekeeps the transferred context to ~24 kB.--secret id=github_tokenplumbing through the Makefile and.github/workflows/dogfood.yamllifts aqua's GitHub API quota from 60/hr unauthenticated to 1000/hr withsecrets.GITHUB_TOKEN.MISE_TRUSTED_CONFIG_PATHS=/home/coder:/etc/miseis set as an ENV so users who clone the coder repo into their workspace home aren't prompted tomise trust.Net diff for the two Ubuntu Dockerfiles: -399 / +244 lines (~200 lines shorter each). The
FROM rust-utils,FROM go, andFROM protomulti-stage builds are gone; so are the NVM/Node block, the bulk binary-install block (golangci-lint, helm, kubectx, syft, cosign, bun), the gh.deb/lazygit/doctl tarball installs, the gofmtupdate-alternativesline, and theyq→yq4rename (scripts/lib.sh:267-275already auto-detects either name).Both images were built and smoke-tested with Apple's
containerCLI on macOS — every migrated tool resolves to the expected pinned version including outside the cloned coder repo (e.g.ghfrom/home/coder, matching the workspace startup script indogfood/coder/main.tf),sqlcruns (provingCGO_ENABLED=1was honoured at install),yq --versionreports v4 forscripts/lib.sh's detection, andgofmtresolves via the mise shim.Follow-ups (out of scope here):
mise.locksogh = "latest"and the other floating versions resolve deterministically across rebuilds and dev machines.setup-go/setup-nodeactions to consumemise.tomlso image and CI versions stop being able to drift.