Skip to content

fix: stops a project-root storage path deleting project files - #34

Merged
Soviann merged 1 commit into
mainfrom
test/kill-gitkeep-label-mutants
Jul 20, 2026
Merged

fix: stops a project-root storage path deleting project files#34
Soviann merged 1 commit into
mainfrom
test/kill-gitkeep-label-mutants

Conversation

@Soviann

@Soviann Soviann commented Jul 20, 2026

Copy link
Copy Markdown
Owner

What

Release-0.4.0 pre-flight found make mutation failing the 90% MSI floor (89.78%) — and, far worse, deleting composer.json from the real checkout, twice.

The data-loss guard (the headline)

composer.json / package.json match RECORD_NAME_PATTERN (<identifier>.json), so a storage.filesystem.path misconfigured to the project root lets deploytasks:reset/rollup list them as stale records and delete them. This is exactly what happened locally: a killed ConcatOperandRemoval mutant on the default path ('%kernel.project_dir%/var/deploy-tasks''%kernel.project_dir%') pointed storage at the checkout root, and the test teardown's reset() ate composer.json before the mutant died.

FilesystemStorage::assertDedicatedStorageDir() now refuses (with an actionable StorageException) any storage directory containing a composer.json — on both the listing path (records()all/reset/removeAll) and the targeted path (filePath()has/get/save/remove). TDD'd (both tests red first). CHANGELOG → Security; docs/storage.md documents the dedicated-directory requirement.

MSI back over the floor

8 escaped mutants killed in DeployTasksInstallHostCommand (from #32's new code):

  • exact-relative-label assertions (no leading slash / no absolute remnant) kill the substr() off-by-one and unwrap mutants in gitkeepLabel();
  • a {projectDir}-adjacent sibling-prefix test pins the trailing-slash boundary in str_starts_with();
  • a 0o755 permission pin kills the mkdir mode mutants.

Test-pollution fix

RelativePathConfigTest now cleans its /tmp-side scratch dirs in setUp: a killed path-anchoring mutant writes /tmp/var/rel-deploy-state against the CWD before dying, which failed the next honest run's assertFileDoesNotExist (bit us twice today).

Verification

Full local make mutation after the change: Covered MSI 90%+, exit 0, and composer.json intact (previous two runs deleted it). Suite at 1120 tests, CS Fixer + PHPStan clean.

composer.json/package.json match the record-name pattern, so a
storage.filesystem.path misconfigured to the project root let reset and
rollup delete them as stale records — found when killed Infection
mutants of the default path did exactly that to the real checkout,
twice. Storage now refuses any directory containing a composer.json.
Also hardens the gitkeep-label and mkdir-mode tests (8 escaped mutants,
MSI back over the 90% floor) and makes RelativePathConfigTest clean the
/tmp-side leftovers a killed path mutant writes.
@Soviann
Soviann enabled auto-merge (squash) July 20, 2026 09:52
@Soviann
Soviann merged commit a5b1d4b into main Jul 20, 2026
20 checks passed
@Soviann
Soviann deleted the test/kill-gitkeep-label-mutants branch July 20, 2026 09:53
@codecov

codecov Bot commented Jul 20, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.

📢 Thoughts on this report? Let us know!

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant