Repository navigation
v0.15.0 Plan
Drafted 2026-10-04. Milestone: v0.15.0. Theme: run an app with one command.
Tracked in the org project php-fpm-ng, Roadmap view: field Wave (iterations v0.15 wave 1-3, v0.15 release), GitHub blocked by links (#430 <- #429, #431 <- #430, #679 <- #669) and sub-issues of #425 (#426-#431). Iteration dates are rough targets, not commitments.
graph LR
D1{{"decision: -c / host ini on a packed binary"}} --> I430
D2{{"decision: pack command spelling"}} --> I429
I427["#427 contract (done)"] --> I429["#429 pack command"]
I428["#428 config from buffer (done)"] --> I430
I428 --> S1
I429 --> I430["#430 run packed app + lifecycle"]
I430 --> I431["#431 CI gate + user docs"]
I431 --> E425["#425 epic closes"]
S1["#728 serve, part 1: default gateway->fastcgi"] --> S2["#728 serve, part 2: --direct, --worker, --print-config, docs"]
S1 -. "shared in-memory config path" .-> I430
I743["#743 flaky test"]
I669["#669 gate artifacts"] --> I679["#679 release retention"]
| Wave | Lane | Issue | Depends on | Notes |
|---|---|---|---|---|
| 1 | A | #743 flaky two-gateways test | - | Small. Also hits async fiber-phpt; reaches async by sync. |
| 1 | B | #669, then #679 | - | Both touch workflows; one lane, in order. Check with a release.yml rehearsal on GitHub, never the local package gate. |
| 1 | C | #429 pack command | #427 (done), decision D2 | Build side only: three mandatory inputs, byte-identical recoverable payload, no app code run during pack (sentinel stub test). |
| 1 | D | #728 serve, part 1 | #428 (done) | Generate the config in memory, feed it through fpm_conf_load_ini_buffer (#428). Default gateway -> fastcgi on a private unix socket, foreground, logs to stdout/stderr, refuses an explicit -y. |
| 2 | D | #728 serve, part 2 | part 1 |
--direct, --worker, --print-config (output passes -t), phpts for all three modes, getting-started page leads with serve. |
| 2 | C | #430 run a packed app | #429, #428, decision D1 | Materialize the PHAR to a real file (#426/#427 verdict), embedded php.ini via -n + ini_entries, embedded fpm.conf via the buffer parser. Reload, stop, log reopen, upgrade/repack, OPcache identity of two apps. Reuse serve's in-memory config path. |
| 3 | C | #431 end-to-end gate + docs | #429, #430 | Deb (Ubuntu) and apk (Alpine) cells via release rehearsal; user chapter: prepare, pack, run, reload, repack. Then close #425. |
| 4 | - | Release v0.15.0 | all | CHANGELOG PR, rehearsal, tag after owner OK. |
Lanes C and D both touch startup and config loading (fpm_main.c, fpm_conf.c). They can run in parallel in wave 1 (different code: pack vs config generation), but #430 should start after serve part 1 is merged, so it can reuse the in-memory config path instead of writing a second one.
-
D1 (blocks #430), from #428: today
-c <file>still merges the hostPHP_INI_SCAN_DIR, and a missing-cfile is silent. Option 1: a packed binary always starts with-n+ embedded ini, operator-c/-dare explicit overrides, documented (nofpm_main.cchange). Option 2: also harden-c(fail on a missing file, ignore the scan dir). Recommendation: option 1 now, option 2 as a separate issue. -
D2 (blocks #429): how the user packs. Option 1: a subcommand of the binary,
php-fpm-ng pack --phar app.phar --ini php.ini --conf fpm.conf -o app(no PHP CLI needed; matchesserve). Option 2: a PHP script on top ofbuild/payload-pack.php(needs a PHP CLI at pack time, declared). Recommendation: option 1.
Static builds, bundled PHP/extensions, building the user's PHAR, framework automation, file watching in serve, automatic HTTPS in serve.