Skip to content

Reconcile final-stage apt state before perl-dependent postinsts run - #2

Merged
k0d3r1s merged 2 commits into
masterfrom
worktree-fix-perl-skew-dist-upgrade
Aug 9, 2026
Merged

Reconcile final-stage apt state before perl-dependent postinsts run#2
k0d3r1s merged 2 commits into
masterfrom
worktree-fix-perl-skew-dist-upgrade

Conversation

@k0d3r1s

@k0d3r1s k0d3r1s commented Aug 8, 2026

Copy link
Copy Markdown
Member

Why

Run 31266620318 failed at build php-zts-base-master with:

Perl API version v5.40.0 of Cwd does not match v5.42.0 at /usr/lib/aarch64-linux-gnu/perl-base/XSLoader.pm line 112

Debian sid transitioned perl 5.40 → 5.42. The zts-base builder stage rebuilt fresh (new php/source/ content invalidated its cache) and pulled perl 5.42, while curl:latest's apt layers were cache hits (no working cache-buster exists — ARG CACHE_BUSTER is never referenced in any RUN nor passed by the build actions), leaving its perl-base modules at 5.40. COPY --from=builder /usr/bin/ /usr/bin/ then overwrote /usr/bin/perl with the 5.42 binary, and the final-stage apt-get install's perl-based maintainer scripts (deb-systemd-helper, update-rc.d) failed on the module mismatch → dpkg exit 100.

What

Add apt-get dist-upgrade -y after apt-get update in the five final stages that lack an upgrade, so the base converges to current sid before perl-dependent postinsts run:

  • php/zts-base/Dockerfile
  • php/base/Dockerfile
  • php/testing/Dockerfile / php/zts-testing/Dockerfile (before autoremove — no install line there)
  • php/franken-testing/Dockerfile (parity with php/franken, which already upgrades)

php/fpm and php/zts already run upgrade -y and are untouched. dist-upgrade rather than upgrade because a mid-transition perl-base upgrade can require new packages, which plain upgrade silently holds back (exit 0).

How to verify

  1. The curl → php-franken-testing-master chain re-dispatched with no_cache=true (immediate unblock, independent of this PR).
  2. After merge, a php-fpm-base-master → php-fpm-socket-master chain exercises the php/base change — the zts chain never builds it.
  3. Logs should show dist-upgrade upgrading perl-base and no Perl API version … does not match lines.

What to watch for

  • This layer only re-runs when cache is invalidated upstream (new PHP source). A quiet-window sid transition can still reproduce the failure — durable protection needs a real cache-buster (referencing $CACHE_BUSTER in the apt RUNs and passing github.run_id from the build actions) or a scheduled no_cache=true rebuild.
  • Follow-up worth a separate task: COPY --from=builder /usr/bin/ /usr/bin/ ships the build toolchain (gcc, git, gdb, valgrind…) into runtime images and is the generic trigger for this skew class.

🤖 Generated with Claude Code

https://claude.ai/code/session_015tYeFcz7Z3Faz4hVMvvayk

The final stages of the php images never upgrade the base packages, so
when the builder stage rebuilds fresh (new PHP source invalidates its
cache) while curl:latest's apt layers are cache hits, the wholesale
COPY --from=builder /usr/bin/ overwrites /usr/bin/perl with a newer
interpreter than the base image's XS modules. Debian sid's perl
5.40->5.42 transition turned that skew into dpkg postinst failures
(Perl API version v5.40.0 of Cwd does not match v5.42.0) in the
build php-zts-base-master step.

Add apt-get dist-upgrade -y to the five final stages that lack an
upgrade (zts-base, base, testing, zts-testing, franken-testing);
fpm, zts, and franken already have one. dist-upgrade rather than
upgrade because a mid-transition perl-base upgrade can require new
packages, which plain upgrade silently holds back.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_015tYeFcz7Z3Faz4hVMvvayk
@coderabbitai

coderabbitai Bot commented Aug 8, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Summary by CodeRabbit

  • Bug Fixes
    • Improved package upgrade handling across PHP container images.
    • Better supports rolling-release package transitions and keeps related dependencies consistent.
    • Preserved minimal package installation settings to help maintain lean runtime images.

Walkthrough

The PHP Dockerfiles now use apt-get dist-upgrade for runtime package updates. The commands retain non-recommending options, and comments document Sid package transition and Perl dependency requirements.

Changes

PHP runtime package upgrades

Layer / File(s) Summary
Runtime package upgrade commands
php/base/Dockerfile, php/fpm/Dockerfile, php/franken-testing/Dockerfile, php/franken/Dockerfile, php/testing/Dockerfile, php/zts-base/Dockerfile, php/zts-testing/Dockerfile, php/zts/Dockerfile
Runtime package setup now uses apt-get dist-upgrade -y --no-install-recommends. Comments document Sid transitions and Perl dependencies where applicable.

Estimated code review effort: 1 (Trivial) | ~5 minutes

Poem

A rabbit hops through Sid tonight,
With packages aligned just right.
Dist-upgrade clears the way,
Perl dependencies safely stay.
Docker builds bloom in light.

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly summarizes the main change: reconciling final-stage APT state before Perl-dependent maintainer scripts run.
Description check ✅ Passed The description directly explains the Perl mismatch, the dist-upgrade fix, affected Dockerfiles, verification, and follow-up considerations.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches 💡 1
🛠️ Fix failing CI checks 💡
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch worktree-fix-perl-skew-dist-upgrade

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

Add --no-install-recommends to the dist-upgrade lines so replacement
packages pulled mid-transition do not drag in Recommends, and a comment
explaining why dist-upgrade is used instead of upgrade, so a future
harmonizing pass does not revert it. Convert the fpm, zts, and franken
final stages from upgrade to the same dist-upgrade line: they share the
wholesale /usr/bin copy pattern, and plain upgrade silently holds back
perl-base when the transition needs package adds or removals.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_015tYeFcz7Z3Faz4hVMvvayk
@k0d3r1s

k0d3r1s commented Aug 8, 2026

Copy link
Copy Markdown
Member Author

Verification update: the no-cache re-run of master (31271329533) failed with the same Perl mismatch, which upgrades this PR from nice-to-have to required. The log shows why: even on a fully fresh build, apt-get upgrade -y prints "The following packages have been kept back" and leaves perl-base at 5.40 (both in curl's final stage and the zts-base builder), while the builder's toolchain install pulls perl 5.42.2-3 in as a new dependency. The /usr/bin copy then plants the 5.42 interpreter next to 5.40 modules regardless of cache state — so stale cache made it likelier, but plain upgrade's kept-back behavior reproduces the skew even with no_cache=true. dist-upgrade is the fix, not just a hardening.

Now verifying with a chain dispatched on this branch: 31272663046.

@k0d3r1s

k0d3r1s commented Aug 8, 2026

Copy link
Copy Markdown
Member Author

Branch verification run 31272663046: the Perl fix is confirmedbuild php-zts-base-master, php-zts-master, and php-zts-testing-master all pass (the first of these failed in both master runs).

The run then failed at build php-franken-master with an unrelated upstream incompatibility: php-src master commit e0221be8 (2026-07-30) converted PG(output_handler) from char* to zend_string*, and FrankenPHP — v1.12.7 and current main — still does PG(output_handler) && PG(output_handler)[0] / ZVAL_STRING(&oh, PG(output_handler)) in frankenphp.c:589, which no longer compiles. No upstream fix PR exists yet. php-franken-master/php-franken-testing-master are blocked until php/frankenphp adapts (last successful franken-master build here was 2026-07-04, predating the API change).

Separate observation from the same log: xcaddy downloads github.com/dunglas/frankenphp v1.12.7 from the module proxy — the COPY php/frankenphp/ clone + go mod download in php/franken/Dockerfile is never actually compiled. Pointing xcaddy at the local clone (--with github.com/dunglas/frankenphp=/go/src/app) would make the franken build track the cloned source as apparently intended — worth a follow-up.

fpm-side verification (exercises php/base, php/fpm, php/testing — no frankenphp involved): 31276236043.

@k0d3r1s

k0d3r1s commented Aug 8, 2026

Copy link
Copy Markdown
Member Author

Verification complete ✅ — fpm chain 31276236043 succeeded end-to-end: php-fpm-base-master, php-fpm-master, php-fpm-testing-master, php-fpm-socket-master all built and pushed. Combined with the earlier zts run, every Dockerfile touched by this PR is now exercised in CI.

The log shows the fix working exactly as designed in php-fpm-base-master's final stage:

+ apt-get dist-upgrade -y --no-install-recommends
debconf: Perl may be unconfigured (Perl API version v5.40.0 of Cwd does not match v5.42.0 ...)   <- transient, non-fatal
Setting up perl-base (5.42.2-3) ...                                                             <- skew reconciled

No Perl API version errors in any later stage.

Remaining known issue (independent of this PR): php-franken-master/php-franken-testing-master stay red until php/frankenphp adapts to php-src's 2026-07-30 PG(output_handler)zend_string* change (details in the previous comment).

@k0d3r1s
k0d3r1s marked this pull request as ready for review August 8, 2026 21:17

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@php/base/Dockerfile`:
- Around line 203-204: Add and vary a cache-busting build argument before the
package-refresh RUN instruction in php/base/Dockerfile lines 203-204 and
php/zts-base/Dockerfile lines 191-192, ensuring both base stages invalidate
their APT upgrade layers. Also verify CI varies the existing CACHE_BUSTER
argument for derived images.
🪄 Autofix

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 96920c9c-3a66-4b95-a84a-cf2f5a357385

📥 Commits

Reviewing files that changed from the base of the PR and between e691b25 and 2530a65.

📒 Files selected for processing (8)
  • php/base/Dockerfile
  • php/fpm/Dockerfile
  • php/franken-testing/Dockerfile
  • php/franken/Dockerfile
  • php/testing/Dockerfile
  • php/zts-base/Dockerfile
  • php/zts-testing/Dockerfile
  • php/zts/Dockerfile
📜 Review details
🧰 Additional context used
🔍 Remote MCP Context7, DeepWiki

Additional review context

  • Debian APT documents that apt-get upgrade holds back packages when dependency changes require installing or removing packages.

  • apt-get dist-upgrade resolves changing dependencies and may install or remove packages. This supports the PR’s rationale for Perl transitions, but reviewers should verify the resulting package plan does not remove required runtime packages.

  • APT recommends running apt-get update before either upgrade command, so the command ordering is correct.

Repository-specific DeepWiki context was unavailable because the public endpoint required authentication.

🔇 Additional comments (1)
php/base/Dockerfile (1)

203-204: 🩺 Stability & Availability

Verify the dist-upgrade removal plan across all final images.

apt-get dist-upgrade may install or remove packages during dependency resolution. (manpages.debian.org) Each stage upgrades the image after its runtime state is assembled and then runs apt-get autoremove. Capture the simulated or real APT plan for every stage. Fail or alert when a runtime-critical package is removed.

  • php/base/Dockerfile#L203-L204: verify the copied PHP runtime and explicit library set.
  • php/fpm/Dockerfile#L150-L151: verify the PHP-FPM runtime and explicit library set.
  • php/franken-testing/Dockerfile#L126-L127: verify FrankenPHP and its watcher library.
  • php/franken/Dockerfile#L126-L127: verify FrankenPHP and its watcher library.
  • php/testing/Dockerfile#L115-L116: verify inherited PHP-FPM dependencies.
  • php/zts-base/Dockerfile#L191-L192: verify the copied PHP ZTS runtime and explicit library set.
  • php/zts-testing/Dockerfile#L113-L114: verify inherited PHP ZTS dependencies.
  • php/zts/Dockerfile#L148-L149: verify the PHP ZTS runtime and explicit library set.

Source: MCP tools

Comment thread php/base/Dockerfile
Comment on lines +203 to +204
# dist-upgrade, not upgrade: sid transitions can need package adds/removals to move perl-base; plain upgrade holds it back and perl postinsts break on the skew
&& apt-get dist-upgrade -y --no-install-recommends \

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🩺 Stability & Availability | 🔵 Trivial

Add a recurring cache trigger to both base stages.

If the base and builder layers remain cache hits, Docker can reuse the package-upgrade RUN layer without checking current APT state. (docs.docker.com) Add and vary a cache argument for both base images, or schedule no-cache rebuilds. Also verify that CI varies the existing CACHE_BUSTER argument in the derived images.

  • php/base/Dockerfile#L203-L204: add the cache trigger for the PHP base refresh.
  • php/zts-base/Dockerfile#L191-L192: add the cache trigger for the PHP ZTS base refresh.
📍 Affects 2 files
  • php/base/Dockerfile#L203-L204 (this comment)
  • php/zts-base/Dockerfile#L191-L192
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@php/base/Dockerfile` around lines 203 - 204, Add and vary a cache-busting
build argument before the package-refresh RUN instruction in php/base/Dockerfile
lines 203-204 and php/zts-base/Dockerfile lines 191-192, ensuring both base
stages invalidate their APT upgrade layers. Also verify CI varies the existing
CACHE_BUSTER argument for derived images.

@k0d3r1s
k0d3r1s merged commit 2530a65 into master Aug 9, 2026
20 of 21 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