Skip to content

docker: freshly-built cli test image silently drops Livewire form fields (103 false failures) — root cause not found #689

Description

@nielsdrost7

Summary

While eliminating the project's SQLite testing fallback (routing local tests through the db compose service — real MariaDB, matching CI), a freshly-built cli image was found to produce false test failures at scale: 103 failures on a full-suite run that pass cleanly under the existing, proven ip2-test-php:8.4 local image against the exact same database. Root cause not found despite extensive isolation — documenting the investigation so it isn't lost, and so nobody re-trusts a freshly-built cli image without re-verifying first.

Symptom

Modules\Clients\Tests\Feature\ContactsTest::it_creates_a_contact_through_a_modal (and ~100 others, mostly Livewire fillForm()/mountAction()/callMountedAction() flows):

Component has errors: "mountedActions.0.data.relation_id" => ["The customer field is required."], ...
Failed asserting that false is true.

The form's fillForm($payload) call appears to have no effect by the time callMountedAction() validates — as if the filled values never reached component state. Confirmed via DB::listen() on a simpler case (UserProfileTest::it_saves_the_user_data_form): the resulting UPDATE statement is missing the field that was supposedly filled.

What was ruled out (all confirmed NOT the cause)

  • Docker Compose networking/env injection — reproduces identically via plain docker run bypassing compose entirely.
  • .env.testing file contents — reproduces with the file held constant (same file used against both the broken and working image).
  • HOME env var — explicitly setting HOME=/tmp to match the working invocation made no difference.
  • Stale compiled views / config cache — cleared storage/framework/views/*.php and bootstrap/cache/*.php; no change.
  • Alpine vs Debian base — rebuilt the image on php:8.4-cli (Debian trixie, matching the proven image); bug persisted.
  • Extension setphp -m diffed to a single extra module (pcntl) against ip2-test-php:8.4; removing it (rebuilding with the exact minimal extension list intl gd pdo_mysql bcmath zip exif — the one documented as producing the known-good image) made no difference.
  • Stale test data from manual tinker sessions during the investigation — ran php artisan migrate:fresh for a clean database; identical 103 failures on the clean DB.
  • Full php -i diff — apart from memory_limit, pcntl, and container hostname/HOME/PWD, output is identical between the two images.
  • PHP version — both report PHP 8.4.23 (cli), built via the same docker-library/php recipe (confirmed via docker history --no-trunc on the working image).

The one confirmed difference: the two php binaries have different SHA-256 hashes (built ~12 days apart per their respective Build Date), suggesting upstream Debian trixie package drift (glibc/openssl/etc.) between builds — plausible but unconfirmed as the actual mechanism. A concrete but unverified hypothesis: Livewire's component-snapshot checksum validation (HMAC'd with APP_KEY) silently rejecting/no-op'ing an update if something in the crypto/hash chain behaves subtly differently, rather than throwing — worth checking Livewire\Mechanisms\HandleComponents\ComponentContext/checksum verification path first.

Current state

  • docker-resources/php-cli/Dockerfile was reduced to the minimal, documented-working extension set as the best available mitigation, but this issue was not resolved by that change — it's flagged here specifically because the minimal-extension rebuild still reproduces the bug.
  • Docs and docker-compose.yml currently tell developers to verify docker compose run --rm cli php artisan test against a small known test (e.g. --filter=ContactsTest) before trusting a full local run, pending this investigation.
  • The underlying db (MariaDB) service + invoiceplane_v1_import-style init-script provisioning is unaffected and confirmed working — this is specifically about the cli PHP image's behavior under Livewire form-testing at scale.

Suggested next steps

  • Bisect: pull the exact php:8.4-cli digest matching ip2-test-php:8.4's build date and rebuild against that pinned digest instead of latest — if the bug disappears, that confirms upstream package drift as the mechanism.
  • Trace Livewire's checksum/snapshot validation path directly (add temporary logging in HandleComponents) during a failing fillForm() call to see if it's rejecting the update silently.
  • If confirmed as a base-image drift issue, pin the Dockerfile's FROM php:8.4-cli to a specific digest rather than floating latest, and document why.

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't workingtesting

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions