Skip to content

Allow PHP 8.6 as max version and run CI on it - #6403

Open
SanderMuller wants to merge 4 commits into
phpstan:2.2.xfrom
SanderMuller:allow-php-86
Open

Allow PHP 8.6 as max version and run CI on it#6403
SanderMuller wants to merge 4 commits into
phpstan:2.2.xfrom
SanderMuller:allow-php-86

Conversation

@SanderMuller

@SanderMuller SanderMuller commented Sep 9, 2026

Copy link
Copy Markdown
Contributor

Point 3 of your plan. Re-targeted to 2.2.x, where #4192 and both 8.5 deprecation patches went, and where
the php-8-stubs update is going.

The cap. MAX_PHP_VERSION goes to 80699, mirroring #4192. phpVersion: 80600 through 80699 are
accepted, 80700 is still rejected, and a composer constraint of 8.7 now clamps to 8.6.99 instead of
8.5.99. Without this there is no phpVersion value to gate 8.6 behaviour on, and self-analysis on 8.6
cannot start, because build/ignore-by-php-version.neon.php feeds it PHP_VERSION_ID.

The matrices. I went through every workflow. 14 version lists contain 8.5. I appended 8.6 to the six
that only decide which PHP runs the job:

  • lint.yml, tests.yml, reflection-golden-test.yml, static-analysis.yml (twice)
  • phar.yml, the 7.4 to 8.5 list that runs the built phar on every supported version

setup-php installs 8.6 as a nightly of 8.6.0-dev from master, so these legs work today.

The eight I left alone, because appending there is not free:

  • turbo-build-image.yml, twice. It publishes ghcr.io/phpstan/turbo-build:gnu-php{version} on manual
    dispatch, and the turbo-compile legs in phar.yml pull those images. A gnu-php8.6 image has to exist
    before anything can reference it, and the extension has to build against 8.6 first.
  • the five turbo-compile lists in phar.yml, for the same reason.
  • bench.yml. Its list is 7.4, 8.5 and the baselines are pinned per version, so a new leg has nothing to
    compare against.

Say the word and I will add any of them, but they looked like separate decisions rather than an oversight.

Verified

  • Full suite OK (21376 tests, 96547 assertions), make phpstan clean, phpcs clean on the touched files.
  • phpVersion: 80600 and 80699 are accepted, 80700 reports expects to be 70100..80699|array|null.
  • Self-analysis under 8.6.0beta2 reports No errors. It could not start before this.
  • All nine e2e/composer-*version* projects pass with a real composer install in each.
  • Reverting only PhpVersionFactory.php and parametersSchema.neon fails 6 of the updated assertions.

The Hoa deprecation you expected is already merged as a6144e213. Nothing else in vendor/ deprecates on
8.6: the autoload emits 24 notices before that commit and 0 after.

@phpstan-bot

Copy link
Copy Markdown
Collaborator

You've opened the pull request against the latest branch 2.3.x. PHPStan 2.3 is not going to be released for months. If your code is relevant on 2.2.x and you want it to be released sooner, please rebase your pull request and change its target to 2.2.x.

@staabm

staabm commented Sep 9, 2026

Copy link
Copy Markdown
Contributor

I am pretty sure, ondrej has a greater plan on 8.6 support and it needs a lot more to be accepted than this :-)

@SanderMuller

Copy link
Copy Markdown
Contributor Author

You were right, and Ondřej has since posted the plan. This PR is one half of his point 3.

The other half of that point, the Hoa deprecation, is merged as a6144e213. Point 1 is
phpstan/php-8-stubs#163, which is in review.

Two things to settle before this is useful:

Branch. The 8.5 equivalent, #4192, went to 2.1.x, the oldest maintained branch at the time, and merged
up. Both 8.5 deprecation patches did the same, and Ondřej is sending the php-8-stubs update to 2.2.x. By
that convention this belongs on 2.2.x, not 2.3.x. Happy to re-target.

Workflows. Point 3 also asks for 8.6 in the Actions matrices. On 2.2.x there are 14 version lists that
contain 8.5: phar.yml six times, static-analysis.yml and turbo-build-image.yml twice each, then
lint.yml, tests.yml, reflection-golden-test.yml and bench.yml. I would leave bench.yml alone,
since its list is 7.4,8.5 and the baselines are pinned per version. I can add those here, or keep this to
the cap and send them separately.

Either way this waits on the stubs, so no rush. Close it if you would rather carry the whole thing
yourself.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@SanderMuller SanderMuller changed the title Allow PHP 8.6 as max version Allow PHP 8.6 as max version and run CI on it Sep 9, 2026
@SanderMuller
SanderMuller changed the base branch from 2.3.x to 2.2.x September 9, 2026 20:39
@SanderMuller

Copy link
Copy Markdown
Contributor Author

Re-targeted to 2.2.x and extended to the rest of point 3, so the description above is rewritten.

It now adds 8.6 to the six workflow lists that only pick which PHP runs the job. The eight I left alone are
the turbo ones, which need a gnu-php8.6 image published first, and bench.yml, which has no baseline for
a new version. Reasons for each are in the description.

Curious what the new legs turn up, which is the point of adding them.

@SanderMuller SanderMuller reopened this Sep 9, 2026
@ondrejmirtes

Copy link
Copy Markdown
Member

The places where 8.6 was added to the workflows are incomplete, for one I'm sure you didn't add it to the turbo compilation, testing etc.

@ondrejmirtes

Copy link
Copy Markdown
Member

Also, some deprecations when running PHPUnit:


PHP Deprecated:  Returning a value from a constructor is deprecated in /home/runner/work/phpstan-src/phpstan-src/tests/PHPStan/Rules/Methods/data/returnTypes.php on line 552

PHP Deprecated:  Returning a value from a destructor is deprecated in /home/runner/work/phpstan-src/phpstan-src/tests/PHPStan/Rules/Methods/data/returnTypes.php on line 732
PHP Deprecated:  Returning from a finally block is deprecated in /home/runner/work/phpstan-src/phpstan-src/tests/PHPStan/Rules/Methods/data/returnTypes.php on line 1253
Deprecated: Returning a value from a constructor is deprecated in /home/runner/work/phpstan-src/phpstan-src/tests/PHPStan/Rules/Methods/data/returnTypes.php on line 552

Deprecated: Returning a value from a destructor is deprecated in /home/runner/work/phpstan-src/phpstan-src/tests/PHPStan/Rules/Methods/data/returnTypes.php on line 732

Deprecated: Returning from a finally block is deprecated in /home/runner/work/phpstan-src/phpstan-src/tests/PHPStan/Rules/Methods/data/returnTypes.php on line 1253

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@SanderMuller

Copy link
Copy Markdown
Contributor Author

Added them, 001996146. All 14 lists that contain 8.5 now contain 8.6, and I re-scanned to confirm none is
left.

The previous run answers the first question. All eight new 8.6 legs passed:

  • Lint (8.6)
  • PHPStan (8.6, ubuntu-latest) and PHPStan (8.6, windows-latest)
  • PHPStan with result cache (8.6)
  • Reflection golden test (8.6)
  • Run PHAR on PHP 8.6
  • Tests PHPUnit 12.x (8.6) on both runners

So PHPStan itself runs clean on 8.6 once the hoa patch is in.

The turbo legs are red, and none of it is our code. Three separate upstream gaps:

  • gnu, both arches: Docker pull failed. ghcr.io/phpstan/turbo-build:gnu-php8.6 does not exist yet, so
    turbo-build-image.yml has to publish it first. Build image (php8.6, arm64) is red in the same run.
  • musl: ERROR: unable to select packages: php86 (no such package). Alpine has no php86 packages.
  • Windows: curl: (22) ... 404. There is no 8.6 build at the download URL.

So the turbo matrices cannot go green until Alpine and the Windows builds ship 8.6 and our own image is
published. Nothing there says the extension itself is unhappy on 8.6, it never gets as far as compiling.

The PHPUnit deprecations

Reproduced on 8.6.0beta2, all three from that one file.

They surface because tests/phpstan-bootstrap.php does
class_alias(Foo::class, FooAlias::class, true). The third argument autoloads ReturnTypes\Foo, Composer's
classmap includes tests/PHPStan, so the whole data file is compiled and PHP reports the three constructs.

I tried the obvious fix and it does not work. Adding the file to exclude-from-classmap silences all
three, and then ReturnTypeRuleTest fails. Without the alias, returnAlias() and returnAnotherAlias()
produce two errors the test does not expect. So the file has to stay loadable.

That leaves moving the three constructs into a data file that nothing autoloads, since PHPStan reads them
statically anyway. That shifts every expected line number after 552 in ReturnTypeRuleTest. I would rather
ask first than send you a large diff you did not want.

The other reds belong to the base. The two macos-15-intel Turbo legs, PHPStan (8.1, windows-latest),
Mutation Testing and Test (PHP 8.5) are red on #6392 and #6404 as well.

@ondrejmirtes

Copy link
Copy Markdown
Member

The 8.6 turbo builds need to be fixed. One of them will take care of itself after pushing (our ghcr.io/phpstan/turbo-build:gnu-php8.6). Maybe it should be a separate PR so we get a green one after rebase here.

Alpine HAS 8.6 images: https://hub.docker.com/_/php/tags?name=8.6

Windows also will definitely have some 8.6 beta builds.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@SanderMuller

Copy link
Copy Markdown
Contributor Author

You are right about Windows, and Alpine is more specific than either of us said. 6b3c472e3 fixes what can
be fixed from here.

Windows. The 8.6 devel packs exist, under downloads/qa, which the step never tried:
php-devel-pack-8.6.0beta3-Win32-vs18-x64.zip and the -nts twin. I added that as a third fallback after
releases and releases/archives.

There were two more problems in that leg, both visible in the failing log. It asked for
php-devel-pack-8.6.0-dev-Win32--x64.zip:

  • Win32--x64, with the empty segment, because the include block maps vs per version and stops at 8.5.
    8.6 needs vs18, which the qa file names confirm. Added.
  • 8.6.0-dev, because setup-php installs a nightly for 8.6. No devel pack is published for a nightly, so
    even with both fixes the exact name will not resolve until 8.6 has releases. Matching a beta pack against
    a -dev runtime is a call I did not want to make for you.

Alpine. The php:8.6 images on Docker Hub are the official PHP images, and the musl leg does not use
those. It runs alpine:3.24 and installs Alpine's own packages with apk add php86 php86-dev .... Those
packages are in edge only, not in 3.24, which is why the log says php86 (no such package). I checked
each branch on pkgs.alpinelinux.org. So the leg now uses alpine:edge for 8.6 and stays on 3.24
everywhere else. Switching to the official php:8.6-alpine3.24 image would work too, and is a bigger
change than I would make unasked.

gnu. Nothing to do here, as you say. turbo-build-image.yml already carries 8.6 in this branch, so once
that is merged and dispatched, the gnu-php8.6 image exists and these legs stop failing.

Happy to split the turbo matrices into their own PR so this one can go green on the ten legs that already
pass. Say which you prefer and I will move them.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@SanderMuller

Copy link
Copy Markdown
Contributor Author

Results from 6b3c472e3, and one correction to what I said about Alpine. a73dadc32 follows up.

musl. The container switch worked, the log shows docker pull alpine:edge, but the job name still reads
alpine:3.24 because that comes from matrix.target.container. It still failed, and my earlier claim was
imprecise. php86 is not in edge main or community, it is in edge/testing, as
php86 8.6.0_beta3-r0. I checked each repository separately this time. So a73dadc32 points the apk call
at edge/testing for 8.6 only, and leaves 8.3 to 8.5 on the stable repositories.

gnu. This one will not take care of itself after pushing. Build image (php8.6, amd64) fails while
building the image, not while pulling it:

add-apt-repository -y ppa:ondrej/php
&& apt_install "php$PHP_MINOR-cli" "php$PHP_MINOR-dev" ...
did not complete successfully: exit code: 1

The PPA has no 8.6 packages yet, so the image cannot be built until it does.

Windows. Still failing, for the reason I mentioned rather than the URL. setup-php installs
8.6.0-dev, and the devel packs are published for 8.6.0beta3.

There is a pattern worth noting: Alpine testing has 8.6.0_beta3, and windows.php.net has 8.6.0beta3.
Everything that packages 8.6 packages the beta, while our matrices ask setup-php for a nightly. The two
will not line up until 8.6 has releases, or until these legs pin a beta instead of the nightly.

So the turbo family needs either your PPA to publish 8.6, or the legs to stop using nightlies. Neither is
mine to decide, and both are separable from the ten 8.6 legs that already pass. The offer to split them out
stands.

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.

4 participants