Skip to content

1.23.0

Choose a tag to compare

@koriym koriym released this 16 Aug 18:08
· 36 commits to 1.x since this release

An application can be packed into one phar and booted read-only. Compiler::phar() packs what a compile
just produced, and the archive writes only under the directory named at the build and at the boot.

Added

  • Compiler::phar() — pack the compiled tree into var/build/{context}.phar, on both the new Compiler(...) and Compiler::fromInjector(...) shapes (#426)
  • The compile marker is a readable record (.bear-compile.json: app, context, tmpDir, writeDir), and the pack reads the write directory from it instead of taking it again (#426)
  • The pack reads imports from the compiled ImportAppConfig and stops the build when any application was never compiled, writes into the archive, or writes outside the write directory the host was compiled for (#426)
  • A boot that cannot rewrite its scripts - an archive, an immutable image - throws CompiledForAnotherWriteDirException naming both write directories, instead of failing on the write (#426)
  • No file directly under the application root ships in an archive - composer.json, autoload.php, preload.php, env.json, .env and the rest are the project's, not the artifact's - and no .env* file ships wherever it sits (#426)
  • The pack refuses an entry the archive does not carry, and refuses an output it could not remove first (#426)
  • Injector::getOverrideInstance() takes a $writeDir, like getInstance(): an override injector in a read-only tree needs one too (#426)

Changed

  • ImportApp::appDir() replaces the $appDir property: the compiled container holds the object, and the build-time path is not the runtime one (#426)
  • The compile marker filename is .bear-compile.json; a 1.22 marker reads as absent, so recompile after upgrading (#426)
  • Requires ray/compiler ^1.16, whose CompiledInjector accepts a phar:// script directory (#426)
  • Requires bear/app-meta ^1.12, which owns the write-directory layout: Meta::create() places an application and the Meta carries the base it was placed under (#426)

Removed

  • Injector\AppDirs (1.22): Injector\CompiledScripts::dir() answers where compiled scripts live, Meta::create() places an application, and $meta->writeDir carries the base it was placed under (#426)
  • InvalidWriteDirException (1.22): a relative write directory is refused by BEAR\AppMeta\Exception\WriteDirNotAbsoluteException (#426)

Fixed

  • A stream-URI appDir such as phar://app.phar without a write directory throws WriteDirRequiredException, instead of reporting the tmp directory it cannot create inside the artifact (#426)

Additional Notes

This section was added later (2026-08-17). Everything in this release is #426.

Upgrading from 1.22

⚠️ Recompile before deploying. The marker is now .bear-compile.json, so a 1.22 .compile-marker reads as absent. A writable tree recompiles itself on the first boot; a read-only one cannot, and throws CompiledForAnotherWriteDirException.

composer update bear/package
php bin/compile.php prod-app

The names that went with it are in Removed above; all four were added in 1.22. Injector::getInstance() and Compiler are unchanged, so an application that never named them is unaffected.

Packing an archive

// bin/compile.php
$compiler = new Compiler('MyVendor\MyProject', $context, dirname(__DIR__), getenv('APP_WRITE_DIR') ?: null);
$code = $compiler();

exit($code === 0 ? $compiler->phar() : $code);
APP_WRITE_DIR=/var/run/myapp php bin/compile.php
# Phar: /app/var/build/prod-cli-hal-app.phar (31.8MB, 7678 files)
# Writes: /var/run/myapp

APP_WRITE_DIR=/var/run/myapp php var/build/prod-cli-hal-app.phar get /index
# 200 OK

The archive can be moved, renamed, and its build tree deleted. The write directory is the one thing that must be the same absolute path at the build and at the boot - when they differ, the boot names both.