Skip to content

Silence git dubious ownership error in the wp-env test environment - #2652

Merged
westonruter merged 1 commit into
trunkfrom
fix/wp-env-git-safe-directory
Aug 31, 2026
Merged

Silence git dubious ownership error in the wp-env test environment#2652
westonruter merged 1 commit into
trunkfrom
fix/wp-env-git-safe-directory

Conversation

@westonruter

Copy link
Copy Markdown
Member

Summary

No separate issue was filed for this.

Every npm run test-php:* command currently prints a scary-looking block before the tests run:

The repository at "/var/www/html/wp-content/plugins/performance" does not have the correct ownership and git refuses to use it:

fatal: detected dubious ownership in repository at '/var/www/html/wp-content/plugins/performance'
To add an exception for this directory, call:

	git config --global --add safe.directory /var/www/html/wp-content/plugins/performance

Composer could not detect the root package (wordpress/performance) version, defaulting to '1.0.0'.

Nothing actually fails — PHPUnit runs fine immediately afterwards — but it says fatal and is easy to mistake for a broken environment.

Relevant technical choices

The cause is specific to Docker Desktop on macOS. Inside the container, the bind-mount point itself reports as root-owned while its contents carry the host user's UID:

0:0     directory .        ← /var/www/html/wp-content/plugins/performance (the mountpoint)
501:20  directory .git     ← contents, correctly mapped

Git checks the ownership of the repository directory, sees 0:0 against a process running as 501, and refuses (the safe.directory protection added in Git 2.35.2 for CVE-2022-24765). Composer shells out to git to determine the root package version — composer.json has no version key — so the error surfaces on every Composer invocation in that container.

This adds an afterStart lifecycle script registering the mount path in the container's global git config:

  • --replace-all rather than --add, so repeated starts do not append duplicate entries.
  • The --config=.wp-env.test.json flag is repeated because lifecycle scripts run on the host and inherit process.env but not the CLI flags. Locally overridden settings are still honored: wp-env derives .wp-env.test.override.json from the custom config path and merges it last, so the nested wp-env run targets the same containers.
  • Only .wp-env.test.json needs this. .wp-env.json has no mappings entry for the repo root, so no git repository is mounted at a path where Composer runs in the development environment.
  • Linux bind mounts report real ownership and never hit this, where the command is a harmless no-op.

Verified by removing the config from the container, confirming the error returned, then running npm run wp-env-test -- start and confirming both that the entry was restored and that Composer no longer emits the warning at all — it now detects the version from git as intended. npm run lint-json confirms the file still validates against https://schemas.wp.org/trunk/wp-env.json.

Use of AI Tools

This change was written by Claude Opus 5 via Claude Code, working from a real failure observed locally. The diagnosis was verified empirically inside the running container rather than assumed — including the ownership mismatch shown above, wp-env's use of docker compose exec (which is why a --global write persists), and the override-merge behavior — by reading the @wordpress/env source. The change and its reasoning were reviewed before submitting.

Docker Desktop on macOS presents the bind-mount point for
wp-content/plugins/performance as owned by 0:0, while everything beneath
it correctly carries the host user's UID. Git checks the ownership of the
repository directory itself, so it sees a mismatch and refuses to operate:

    fatal: detected dubious ownership in repository at
    '/var/www/html/wp-content/plugins/performance'

Composer shells out to git to determine the root package version, so every
`composer` invocation in the test container prints that error along with
"Composer could not detect the root package (wordpress/performance)
version, defaulting to '1.0.0'". Nothing actually fails, but the noise
appears above the output of every `npm run test-php:*` command and reads
like a fatal error.

Add an `afterStart` lifecycle script that registers the mount path in the
container's global git config. `--replace-all` keeps the entry unique
across repeated starts. Linux bind mounts report real ownership and never
hit this, where the command is simply a harmless no-op.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@github-actions

github-actions Bot commented Aug 29, 2026

Copy link
Copy Markdown

The following accounts have interacted with this PR and/or linked issues. I will continue to update these lists as activity occurs. You can also manually ask me to refresh this list by adding the props-bot label.

If you're merging code through a pull request on GitHub, copy and paste the following into the bottom of the merge commit message.

Co-authored-by: westonruter <westonruter@git.wordpress.org>
Co-authored-by: adamsilverstein <adamsilverstein@git.wordpress.org>

To understand the WordPress project's expectations around crediting contributors, please review the Contributor Attribution page in the Core Handbook.

@westonruter westonruter added [Type] Bug An existing feature is broken Infrastructure Issues for the overall performance plugin infrastructure no milestone PRs that do not have a defined milestone for release labels Aug 29, 2026

@adamsilverstein adamsilverstein left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Gold star!

@westonruter
westonruter merged commit c8e1a4e into trunk Aug 31, 2026
16 of 18 checks passed
@westonruter
westonruter deleted the fix/wp-env-git-safe-directory branch August 31, 2026 17:18
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Infrastructure Issues for the overall performance plugin infrastructure no milestone PRs that do not have a defined milestone for release [Type] Bug An existing feature is broken

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants