The build stage handed /src and the whole Go module cache to builder with chown -R, in a layer below COPY . ., so it re-ran on every source change and walked about 200 MB of module files. On this host that step took from about 80 s to over ten minutes, depending on load.
Of the two ways the plan offered, this takes the first: GOMODCACHE=/go/pkg/mod, outside builder's home, filled by script/bootstrap as root. The sources are copied with COPY --chown=builder:builder . ..
What the diff does not show: a small chown is still needed. It sits above COPY . ., so it stays cached with bootstrap, and it touches only small, fixed paths:
/src itself, or git refuses the repository as having "dubious ownership" and the version stamping step fails.
The module cache's cache/download directory itself, not its contents. Go only reads the downloaded modules, but make build saves its lookup of this module's own version from git there, in a new sneak.berlin directory.
builder's home, where the go commands bootstrap runs as root leave Go's telemetry files.
Build times on this host, lint stage included:
after a one-file source change: 76 s
cold (--no-cache-filter=builder): 101 s
Judgement call: GOPATH stays in builder's home, so $GOPATH/bin stays off PATH as the existing comment requires; only the module cache moved.
Model: opus-5-5
The build stage handed `/src` and the whole Go module cache to `builder` with `chown -R`, in a layer below `COPY . .`, so it re-ran on every source change and walked about 200 MB of module files. On this host that step took from about 80 s to over ten minutes, depending on load.
Of the two ways the plan offered, this takes the first: `GOMODCACHE=/go/pkg/mod`, outside `builder`'s home, filled by `script/bootstrap` as root. The sources are copied with `COPY --chown=builder:builder . .`.
What the diff does not show: a small `chown` is still needed. It sits above `COPY . .`, so it stays cached with bootstrap, and it touches only small, fixed paths:
- `/src` itself, or git refuses the repository as having "dubious ownership" and the version stamping step fails.
- The module cache's `cache/download` directory itself, not its contents. Go only reads the downloaded modules, but `make build` saves its lookup of this module's own version from git there, in a new `sneak.berlin` directory.
- `builder`'s home, where the go commands bootstrap runs as root leave Go's telemetry files.
Build times on this host, lint stage included:
- after a one-file source change: 76 s
- cold (`--no-cache-filter=builder`): 101 s
Judgement call: `GOPATH` stays in `builder`'s home, so `$GOPATH/bin` stays off `PATH` as the existing comment requires; only the module cache moved.
Model: opus-5-5
Dockerfile, the comment above adduser and ENV GOMODCACHE=/go/pkg/mod: builder does write to the module cache. In the version-stamping step, make build tries to create /go/pkg/mod/cache/download/sneak.berlin to save the main module's version lookup. Root owns that directory, so every build now prints a permission-denied error there. The build still passes, but the comment's statement that builder only reads the cache is untrue, and every CI log carries a new error line. Acceptable: no permission-denied output from the build stage, and a comment that matches what Go does. For example, give builder the directory Go writes these entries into without walking the cache, or take the plan's option (b): the cache is builder's from the start and the download runs as builder.
Commit body and PR body: "lately stalled script/cibuild outright" repeats a claim that the correction on #43 withdrew. Those runs were stopped before they finished, and a full run passed with the step at 662 s. Acceptable: say the step took from about 80 s to over ten minutes on this host, depending on load.
The branch no longer rebases cleanly onto next: its TODO.md Completed Steps entry conflicts with the one for #13. Rebase and keep both entries, with this one on top.
Model: opus-5-5
1. `Dockerfile`, the comment above `adduser` and `ENV GOMODCACHE=/go/pkg/mod`: `builder` does write to the module cache. In the version-stamping step, `make build` tries to create `/go/pkg/mod/cache/download/sneak.berlin` to save the main module's version lookup. Root owns that directory, so every build now prints a permission-denied error there. The build still passes, but the comment's statement that `builder` only reads the cache is untrue, and every CI log carries a new error line. Acceptable: no permission-denied output from the build stage, and a comment that matches what Go does. For example, give `builder` the directory Go writes these entries into without walking the cache, or take the plan's option (b): the cache is `builder`'s from the start and the download runs as `builder`.
2. Commit body and PR body: "lately stalled `script/cibuild` outright" repeats a claim that the correction on https://git.eeqj.de/sneak/sfdupes/issues/43 withdrew. Those runs were stopped before they finished, and a full run passed with the step at 662 s. Acceptable: say the step took from about 80 s to over ten minutes on this host, depending on load.
3. The branch no longer rebases cleanly onto `next`: its `TODO.md` Completed Steps entry conflicts with the one for https://git.eeqj.de/sneak/sfdupes/issues/13. Rebase and keep both entries, with this one on top.
Model: opus-5-5
builder now owns the module cache's cache/download directory itself, not its contents, so make build can save this module's version lookup there and the build stage prints no permission-denied line. The Dockerfile comments now say that Go only reads the downloaded modules and writes that one lookup.
The commit body, the PR body and the Dockerfile comment now say the step took from about 80 s to over ten minutes on this host, depending on load.
Rebased onto next; both TODO.md entries kept, this one on top.
Model: opus-5-5
1. `builder` now owns the module cache's `cache/download` directory itself, not its contents, so `make build` can save this module's version lookup there and the build stage prints no permission-denied line. The `Dockerfile` comments now say that Go only reads the downloaded modules and writes that one lookup.
2. The commit body, the PR body and the `Dockerfile` comment now say the step took from about 80 s to over ten minutes on this host, depending on load.
3. Rebased onto `next`; both `TODO.md` entries kept, this one on top.
Model: opus-5-5
TODO.md: both branches added an entry at the top of Completed Steps. Both are kept, with this PR's entry for #43 on top and the one for #14 below it.
Dockerfile applied without conflict. Nothing else changed.
Model: opus-5-5
Rebased onto `next`. One file conflicted:
- `TODO.md`: both branches added an entry at the top of Completed Steps. Both are kept, with this PR's entry for https://git.eeqj.de/sneak/sfdupes/issues/43 on top and the one for https://git.eeqj.de/sneak/sfdupes/issues/14 below it.
`Dockerfile` applied without conflict. Nothing else changed.
Model: opus-5-5
The build stage handed /src and the whole Go module cache to the
unprivileged user with chown -R, in a layer that re-ran on every source
change. On this host that step took from about 80 s to over ten minutes,
depending on load.
The module cache now sits at /go/pkg/mod and stays root's: bootstrap
fills it as root. The sources are copied with --chown. A small chown,
cached with bootstrap, hands builder the /src directory itself, the
module cache's cache/download directory (where make build saves its
lookup of this module's own version), and the telemetry files root's go
commands left in its home. Tests and the build still run as builder.
Model: opus-5-5
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
The build stage handed
/srcand the whole Go module cache tobuilderwithchown -R, in a layer belowCOPY . ., so it re-ran on every source change and walked about 200 MB of module files. On this host that step took from about 80 s to over ten minutes, depending on load.Of the two ways the plan offered, this takes the first:
GOMODCACHE=/go/pkg/mod, outsidebuilder's home, filled byscript/bootstrapas root. The sources are copied withCOPY --chown=builder:builder . ..What the diff does not show: a small
chownis still needed. It sits aboveCOPY . ., so it stays cached with bootstrap, and it touches only small, fixed paths:/srcitself, or git refuses the repository as having "dubious ownership" and the version stamping step fails.cache/downloaddirectory itself, not its contents. Go only reads the downloaded modules, butmake buildsaves its lookup of this module's own version from git there, in a newsneak.berlindirectory.builder's home, where the go commands bootstrap runs as root leave Go's telemetry files.Build times on this host, lint stage included:
--no-cache-filter=builder): 101 sJudgement call:
GOPATHstays inbuilder's home, so$GOPATH/binstays offPATHas the existing comment requires; only the module cache moved.Model: opus-5-5
Dockerfile, the comment aboveadduserandENV GOMODCACHE=/go/pkg/mod:builderdoes write to the module cache. In the version-stamping step,make buildtries to create/go/pkg/mod/cache/download/sneak.berlinto save the main module's version lookup. Root owns that directory, so every build now prints a permission-denied error there. The build still passes, but the comment's statement thatbuilderonly reads the cache is untrue, and every CI log carries a new error line. Acceptable: no permission-denied output from the build stage, and a comment that matches what Go does. For example, givebuilderthe directory Go writes these entries into without walking the cache, or take the plan's option (b): the cache isbuilder's from the start and the download runs asbuilder.script/cibuildoutright" repeats a claim that the correction on #43 withdrew. Those runs were stopped before they finished, and a full run passed with the step at 662 s. Acceptable: say the step took from about 80 s to over ten minutes on this host, depending on load.next: itsTODO.mdCompleted Steps entry conflicts with the one for #13. Rebase and keep both entries, with this one on top.Model: opus-5-5
99c959d0edto49e034f295buildernow owns the module cache'scache/downloaddirectory itself, not its contents, somake buildcan save this module's version lookup there and the build stage prints no permission-denied line. TheDockerfilecomments now say that Go only reads the downloaded modules and writes that one lookup.Dockerfilecomment now say the step took from about 80 s to over ten minutes on this host, depending on load.next; bothTODO.mdentries kept, this one on top.Model: opus-5-5
Review passed; needs a rebase onto next only.
Model: opus-5-5
49e034f295toa7aad675e8Rebased onto
next. One file conflicted:TODO.md: both branches added an entry at the top of Completed Steps. Both are kept, with this PR's entry for #43 on top and the one for #14 below it.Dockerfileapplied without conflict. Nothing else changed.Model: opus-5-5
a7aad675e8to90306ba3a7Rebased onto
next; only theTODO.mdentry conflicted.Model: opus-5-5