Skip to content

v0.15.0 Plan

Piotr Hałas edited this page Oct 3, 2026 · 2 revisions

v0.15.0 plan: single-file app (pack) and php-fpm-ng serve

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.

Dependency graph

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"]
Loading

Waves

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.

Decisions needed before the blocked work

  • D1 (blocks #430), from #428: today -c <file> still merges the host PHP_INI_SCAN_DIR, and a missing -c file is silent. Option 1: a packed binary always starts with -n + embedded ini, operator -c/-d are explicit overrides, documented (no fpm_main.c change). 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; matches serve). Option 2: a PHP script on top of build/payload-pack.php (needs a PHP CLI at pack time, declared). Recommendation: option 1.

Out of scope for v0.15.0

Static builds, bundled PHP/extensions, building the user's PHAR, framework automation, file watching in serve, automatic HTTPS in serve.

Clone this wiki locally