@@ -3,6 +3,7 @@ package main
33import (
44 "context"
55 "fmt"
6+ "os"
67 "path"
78 "strings"
89
@@ -126,6 +127,12 @@ func (s *Runtime) CreateRunnerEnvironment(ctx context.Context) error {
126127 return s .Wool .Wrapf (err , "cannot create docker runner" )
127128 }
128129 dockerEnv .WithPause ()
130+ // Run as the invoking host user. uv sync writes uv.lock into the
131+ // bind-mounted source and populates the venv; as root those files
132+ // become root-owned on the host, and a later Init that hashes uv.lock
133+ // for its dependency cache then fails with "permission denied" on any
134+ // host where the user isn't root (e.g. Linux CI).
135+ dockerEnv .WithUser (fmt .Sprintf ("%d:%d" , os .Getuid (), os .Getgid ()))
129136
130137 instance , err := resources .FindNetworkInstanceInNetworkMappings (ctx , s .NetworkMappings , s .FastAPI .RestEndpoint , resources .NewNativeNetworkAccess ())
131138 if err != nil {
@@ -147,6 +154,14 @@ func (s *Runtime) CreateRunnerEnvironment(ctx context.Context) error {
147154 if err != nil {
148155 return s .Wool .Wrapf (err , "cannot create cache location" )
149156 }
157+ // uv's download cache defaults to $HOME/.cache/uv; the host user has no
158+ // home inside the image, so give uv a writable, host-owned cache mount.
159+ uvCache , err := s .LocalDirCreate (ctx , ".cache/container/uv" )
160+ if err != nil {
161+ return s .Wool .Wrapf (err , "cannot create uv cache location" )
162+ }
163+ dockerEnv .WithMount (uvCache , "/uv-cache" )
164+ dockerEnv .WithEnvironmentVariables (ctx , resources .Env ("UV_CACHE_DIR" , "/uv-cache" ))
150165 s .runnerEnvironment = dockerEnv
151166
152167 case s .Base .Runtime .IsNixRuntime ():
0 commit comments