Skip to content

Isolate Composer under ~/.pv/composer#12

Merged
munezaclovis merged 2 commits intomainfrom
worktree-rustling-growing-spark
Mar 5, 2026
Merged

Isolate Composer under ~/.pv/composer#12
munezaclovis merged 2 commits intomainfrom
worktree-rustling-growing-spark

Conversation

@munezaclovis
Copy link
Copy Markdown
Contributor

Summary

  • Composer is now fully contained under ~/.pv/composer/ — it never touches ~/.composer
  • ~/.pv/bin/composer is a shim script (like the PHP shim) that sets COMPOSER_HOME and COMPOSER_CACHE_DIR, resolves the correct PHP version per-project, then execs the phar
  • composer global require laravel/installer installs to ~/.pv/composer/vendor/bin/, which is now included in the PATH instructions
  • FrankenPHP worker processes inherit COMPOSER_HOME/COMPOSER_CACHE_DIR via CaddyEnv() so runtime Composer calls (Statamic, Nova) are also isolated
  • Selftest verifies composer config --global home returns the pv-managed directory
  • Existing ~/.composer/auth.json and config.json are automatically migrated during pv install

What changed

File Change
config/paths.go Add ComposerDir, ComposerCacheDir, ComposerBinDir, ComposerPharPath; create dirs in EnsureDirs; add env vars to CaddyEnv
binaries/install.go Save composer.phar to ~/.pv/data/ instead of ~/.pv/bin/
phpenv/shim.go Add composerShimScript; WriteShims() now writes both php and composer shims
setup/shell.go PATH instructions include ~/.pv/composer/vendor/bin
setup/selftest.go Add checkComposerIsolation() to verify COMPOSER_HOME
setup/composer.go New — MigrateComposerConfig() copies auth/config from ~/.composer
cmd/install.go Call migration helper after writing shims

Test plan

  • All existing tests pass (go test ./...)
  • 13 new e2e tests in composer_e2e_test.go that invoke the real shim with a fake PHP binary:
    • COMPOSER_HOME and COMPOSER_CACHE_DIR are set correctly
    • composer.phar path is passed as first arg to PHP
    • All CLI args are forwarded (global require laravel/installer --dev)
    • PHP version resolves from global default, .pv-php, and composer.json
    • ~/.composer is never touched
    • External COMPOSER_HOME env is overridden by the shim
    • Graceful errors when no PHP version configured or binary missing
  • 3 shim unit tests (both shims created, executable, contain expected paths)
  • 5 migration tests (copies auth.json, config.json, skips if absent, doesn't overwrite, preserves 0600 perms)
  • Updated path/env tests for new composer directories and CaddyEnv entries

- Add ComposerDir, ComposerCacheDir, ComposerBinDir, ComposerPharPath helpers
- Save composer.phar to ~/.pv/data/ instead of ~/.pv/bin/
- Replace ~/.pv/bin/composer binary with a shim that sets COMPOSER_HOME
  and COMPOSER_CACHE_DIR, resolves PHP version per-project, then execs
  the phar through the resolved PHP binary
- Include ~/.pv/composer/vendor/bin in PATH instructions so composer
  global require binaries are immediately available
- Pass COMPOSER_HOME and COMPOSER_CACHE_DIR in CaddyEnv so FrankenPHP
  worker processes inherit them (Statamic, Nova, etc.)
- Add composer isolation check to selftest (composer config --global home)
- Add migration helper that copies auth.json and config.json from
  ~/.composer if they exist
- Add 13 e2e tests covering env isolation, arg forwarding, version
  resolution (.pv-php, composer.json, global), error cases, and
  override of external COMPOSER_HOME
- Add scripts/e2e/composer.sh: real composer global require/remove cycle
  that verifies packages land in ~/.pv/composer/vendor/bin and
  ~/.composer is never created
- Update verify-install.sh to check composer shim, phar, and directories
- Update diagnostics.sh to dump composer dir/shim on failure
- Wire Phase 12 (Composer Containment) into e2e.yml workflow
@munezaclovis munezaclovis merged commit 4ca139b into main Mar 5, 2026
2 checks passed
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