Changelog - Version 7.0
Status: in development. This document tracks changes landing on the
7.0branch. Nothing here is released yet, and the contents may still change.
Breaking Changes
-
symfony/consoleis now^7.4 || ^8.0, up from^5.4|^6.2|^7.0.Console 8.0 removed
Application::add(). Its replacement,addCommand(), only exists from 7.4 on, so spanning both would mean picking the method at runtime. Raising the floor to 7.4 keeps the console bootstrap a plain call.The lower bounds this drops were already unusable on this branch: console 5.4 conflicts with
psr/log >= 3, whichbyjg/restserver ^7.0requires, and 6.x through 7.3 conflict with thesymfony/yaml8.x the toolchain pulls in.
New
-
Runner::showDocs()accepts an optional$usagePrefix. When given, the usage line is that prefix followed by the parameters as positional values, without--arg(./app user:cleanup <days> [table]), so a launcher that maps its own command names to Scriptify targets can print help in its own syntax. Without it the output is unchanged. See docs/showdocs.md. -
LauncherandCommandProvider: a command line for an application's own commands (./app payment:sweep 42). ACommandProviderclass names them with class references, a class standing for all its public methods (payment:charge,payment:refund, ...).Launcherruns them, lists them with their PHPDoc summary (list), checks each one without running it (list --check), prints<command> --help, and runs a command again and again with--daemon. A host with built-in commands extends it, and protects their names withisReserved(). See docs/launcher.md. -
Classes can be resolved through a PSR-11 container, so a class with constructor dependencies can be run without being changed. The container is optional.
scriptify runandinstalltake it from the--bootstrapfile: if the file returns aContainerInterface, Scriptify asks it for the class. An application passes its own toLauncher(orRunner). See docs/container.md.Nothing changes without opting in: the default bootstrap,
vendor/autoload.php, returns Composer'sClassLoader, which is not a container. -
Resolution is strict once a container is given: a class the container does not hold is refused, not built with
new. Falling back would be a guess, and a class whose dependencies are all optional would run without the collaborators the container holds -- working, wrong and silent. Without a container nothing changed:new, as always. -
Scriptify::installCommand()installs a service for a command line, as given, in a working directory: whatinstallnow uses forscriptify run, and what an application uses to install one of its own commands. The service templates take the full command, and set the working directory (systemdWorkingDirectory, upstartchdir, initd--chdir, crondcd). -
When
newis the path and the constructor takes arguments, the failure is now aScriptifyExceptionnaming the class, instead of anArgumentCountErrorthrown from insideRunnerwith a stack trace pointing at the wrong place. -
installno longer instantiates the class it is checking. The check asks whether the class and the method exist, whichmethod_exists()answers from the class name; building the object pulled in its whole dependency graph -- database connections included -- to install a service that had not run yet. -
A class can be named with forward slashes --
Some/Name/Space/MyClass::method-- as well as with backslashes. A backslash is the shell's escape character, so the documented form has to be quoted, and doubled again whenever the command passes through another layer: inside acomposer.jsonscript a single separator becomes four characters, which is a fine place for a typo to hide. A forward slash is not valid in a PHP identifier, so the conversion cannot destroy a legitimate name.--showdocsnow prints the slash form, so the usage line it emits can be pasted anywhere without adjusting the quoting. -
psr/containeris now a declared dependency. It was already in the tree throughsymfony/service-contracts, butRunnernames the interface in its public signature now, so relying on a transitive dependency would be luck.
Fixed
-
A service installed with arguments did not start: the command line used
--args, whichrundoes not know (The "--args" option does not exist). It is--argnow, each value shell-quoted. -
An initd service did not start: its command line added
--daemonize,--pidfileand--log, whichrundoes not have.start-stop-daemonalready runs it in the background with a pid file, so they are gone. -
ServiceWriterwith an override path (used by the tests) wrote the file there but applied the initdchmodto the original/etc/init.dpath. -
--showdocsno longer leaves a stray/in front of the text of a single-line docblock (/** Like this. */). The opening and closing markers are now removed completely before the leading*of each line.
Requirements
- PHP 8.3, 8.4, 8.5 and 8.6 are now supported:
"php": ">=8.3 <8.7". The previous<8.6upper bound excluded PHP 8.6, since<8.6is exclusive.
ByJG dependencies
byjg/jinja-phpis now^7.0.byjg/restserveris now^7.0.
While 7.0 is unreleased these resolve to 7.0.x-dev from each component's
7.0 branch, via minimum-stability: dev with prefer-stable: true.
Toolchain
-
PHPUnit updated to
^12.5. -
Psalm is installed as
psalm/pharinstead ofvimeo/psalm.vimeo/psalmlists the PHP versions it supports and no published release includes 8.6, so as a dev dependency it madecomposer installfail on the 8.6 build job before any test ran.psalm/pharrequires onlyphp ^8.2and bundles its own dependencies, so it installs on every PHP version in the matrix and cannot conflict with the project's. Psalm itself still refuses to run on 8.6, which is why the Psalm job uses 8.5.composer psalmruns it. -
PHPUnit 13 is deliberately not used. It requires PHP
>=8.4.1, breaking the 8.3 floor.
Continuous Integration
- The build matrix now includes PHP 8.6.
- The Psalm job runs on PHP 8.5.
Housekeeping
phpunit.xml.distrenamed tophpunit.xml.