Skip to content

Fix non-root permission errors and uv usage#14765

Open
SisypheOvO wants to merge 1 commit into
ppy:masterfrom
SisypheOvO:uv-access
Open

Fix non-root permission errors and uv usage#14765
SisypheOvO wants to merge 1 commit into
ppy:masterfrom
SisypheOvO:uv-access

Conversation

@SisypheOvO

Copy link
Copy Markdown
Contributor

This PR addresses two independent issues affecting run-checks.sh.

Part 1: Permission errors (bug fix)

Problem

When running run-checks.sh on Windows or macOS (and any Linux setup where the host user's UID does not exist in the image), the container falls through to the useradd/gosu branch in meta/docker-entrypoint.sh and switches to a freshly-created osu-wiki-docker user. Two issues then surface:

1. uv fails to initialize its cache

error: Failed to initialize cache at /home/osu-wiki-docker/.cache/uv
Caused by: failed to create directory /home/osu-wiki-docker/.cache/uv: Permission denied (os error 13)

useradd is invoked without -m, so the new user's $HOME(/home/osu-wiki-docker) is never created on disk. uv expected a writable $HOME and failed.

2. uv cannot reach the Python interpreter

error: Failed to query Python interpreter
Caused by: failed to canonicalize path /osu-wiki/.venv/bin/python3: Permission denied (os error 13)

uv sync runs as root during image build, so the managed Python interpreter ends up under /root/.local/share/uv/python/.... /root has mode 700 by default, so the non-root user cannot traverse into it, and any symlink chain that ends up inside /root is unreachable.

Changes

  • meta/docker-entrypoint.sh: add -m to useradd so the new user gets
    a home directory.
  • Dockerfile: add RUN chmod o+rx /root so non-root users can traverse
    /root and reach the Python interpreter installed by uv. This only opens
    the directory for traversal — files inside /root keep their own modes.

Part 2. Use uv run instead of uv tool run

osu-wiki-tools==2.5.1 is already declared in pyproject.toml, and uv sync installs it into /osu-wiki/.venv during image build. However, all use of uv invoke the tool via uv tool run, which ignores the project venv and installs the tool into an ephemeral uv tool environment under ~/.cache/uv/tools/... instead.

This means:

  1. The version is not actually pinned at runtime. uv tool run resolves the latest compatible release from PyPI rather than honoring the ==2.5.1 constraint in pyproject.toml.
  2. The tool is downloaded and installed twice.
  3. The container relies on the network at runtime to fetch the tool into its ephemeral environment, even though everything needed is already in the image.

Changes

  • replace them
  • run-checks.sh: add --volume /osu-wiki/.venv/ so the image's prebuilt venv is preserved when the bind mount is applied. Without this, uv run would not find .venv inside the container, would download Python 3.14 (~34 MiB) and rebuild the venv on every run, **writing the resulting .venv directory into the host's repo.
  • Remove the .venv folder left after running the test (same as removing node_modules)

Testing

docker image rm osu-wiki && bash run-checks.sh --show-build

@github-actions github-actions Bot added the area:meta non-article files label May 23, 2026
@TicClick TicClick self-requested a review May 29, 2026 20:14
Comment thread run-checks.sh

exit_code=$?

# FIXME: The above command leaves behind an empty node_modules directory if it

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why did you remove the comment? it doesn't seem to be fixed, no?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

because this is not actually a bug. The empty directory left behind when deleting an anonymous volume is due to its underlying Linux mounting mechanism. a volume must be mounted at a specified location inside the container. If the directory does not exist, Docker automatically creates an empty directory as the mount point, and this empty directory remains in the container's file system even if the volume is subsequently deleted.

Anonymous volumes must create this directory to overwrite the original directory within the container -- and they are designed to be independent of the container's lifecycle; therefore, by default anonymous volumes do not automatically remove the directories they created when the container is deleted.

manually removing the folders in later steps is the final solution.

Comment thread Dockerfile
# Install osu-wiki tool dependencies
COPY package.json package-lock.json pyproject.toml uv.lock ./
RUN npm install && npm install -g osu-wiki && uv sync
RUN chmod o+rx /root

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I feel like this is not needed and can be resolved with:

UV_CACHE_DIR=/tmp/uv-cache
UV_PYTHON_INSTALL_DIR=/opt/uv/python

ref: https://docs.astral.sh/uv/reference/environment/#uv_python_install_dir

if you don't want to get into this I can look it up later

@SisypheOvO SisypheOvO May 31, 2026

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yes UV_CACHE_DIR should work. I'm just hoping all tool cache can be fixed in one line instead of trying to fix for each everytime. I can switch to this if you want

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area:meta non-article files size/S

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants