Skip to content

Commit 691e3de

Browse files
committed
Merge remote-tracking branch 'origin/2.2.x' into 2.3.x
# Conflicts: # .github/workflows/phar.yml
2 parents 74c3942 + 156f1ff commit 691e3de

4 files changed

Lines changed: 110 additions & 31 deletions

File tree

‎.github/turbo-build/Dockerfile‎

Lines changed: 25 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
# Prebuilt image for the turbo-compile gnu legs in phar.yml, published to
22
# ghcr.io/phpstan/turbo-build by turbo-build-image.yml (tags gnu-php8.3,
3-
# gnu-php8.4, gnu-php8.5; each a linux/amd64 + linux/arm64 manifest).
3+
# gnu-php8.4, gnu-php8.5, gnu-php8.6; each a linux/amd64 + linux/arm64
4+
# manifest).
45
#
56
# Baking the PHP toolchain in keeps apt and the ondrej/php PPA out of the
67
# compile jobs entirely: ports.ubuntu.com (the only Ubuntu arm64 mirror,
@@ -15,10 +16,23 @@ FROM ubuntu:22.04
1516
ARG PHP_MINOR
1617
ENV DEBIAN_FRONTEND=noninteractive
1718

19+
# PHP 8.6 is a prerelease, and ondrej/php trails its tags by weeks: on
20+
# 2026-09-25 it still served 8.6.0beta3, whose module API (20250926) the
21+
# 8.6.0RC2 that the php:8.6-rc images ship had already replaced
22+
# (20260924) — an extension built against one refuses to load into the
23+
# other. The 8.6 image therefore builds the official release tarball on
24+
# the same base. Drop these and the source branch below once ondrej/php
25+
# ships 8.6.0.
26+
ARG PHP86_VERSION=8.6.0RC2
27+
ARG PHP86_URL=https://downloads.php.net/~mbeccati/php-8.6.0RC2.tar.xz
28+
ARG PHP86_SHA256=ef3fba21c311e9bbace0e2102702446d322c275b8a10e6b33b28f2561299671c
29+
1830
# The source label links the GHCR package to this repository.
1931
LABEL org.opencontainers.image.source="https://github.com/phpstan/phpstan-src"
2032
LABEL org.opencontainers.image.description="PHP and build toolchain for compiling the phpstan_turbo extension (glibc floor 2.34)"
2133

34+
COPY build-php.sh /tmp/build-php.sh
35+
2236
# apt mirrors 404 mid-sync (the fetched index can reference a superseded
2337
# .deb already pruned from the pool); only a fresh index fixes that, so
2438
# update+install retries as a unit
@@ -34,8 +48,13 @@ RUN test -n "$PHP_MINOR"; \
3448
return 1; \
3549
}; \
3650
apt_install software-properties-common gnupg ca-certificates curl git make g++ patch unzip zstd \
37-
&& add-apt-repository -y ppa:ondrej/php \
38-
&& apt_install "php$PHP_MINOR-cli" "php$PHP_MINOR-dev" "php$PHP_MINOR-curl" "php$PHP_MINOR-mbstring" "php$PHP_MINOR-xml" \
39-
&& rm -rf /var/lib/apt/lists/* \
40-
&& ln -sf "/usr/bin/php$PHP_MINOR" /usr/local/bin/php \
41-
&& ln -sf "/usr/bin/php-config$PHP_MINOR" /usr/local/bin/php-config
51+
&& if [ "$PHP_MINOR" = "8.6" ]; then \
52+
apt_install pkg-config xz-utils libxml2-dev libonig-dev libcurl4-openssl-dev libssl-dev zlib1g-dev \
53+
&& PHP_VERSION="$PHP86_VERSION" PHP_URL="$PHP86_URL" PHP_SHA256="$PHP86_SHA256" sh /tmp/build-php.sh; \
54+
else \
55+
add-apt-repository -y ppa:ondrej/php \
56+
&& apt_install "php$PHP_MINOR-cli" "php$PHP_MINOR-dev" "php$PHP_MINOR-curl" "php$PHP_MINOR-mbstring" "php$PHP_MINOR-xml" \
57+
&& ln -sf "/usr/bin/php$PHP_MINOR" /usr/local/bin/php \
58+
&& ln -sf "/usr/bin/php-config$PHP_MINOR" /usr/local/bin/php-config; \
59+
fi \
60+
&& rm -rf /var/lib/apt/lists/* /tmp/build-php.sh

‎.github/turbo-build/build-php.sh‎

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
#!/bin/sh
2+
# Builds and installs PHP $PHP_VERSION into /usr/local from the official
3+
# release tarball at $PHP_URL, verified against $PHP_SHA256. Used by the
4+
# Dockerfile for the PHP minors ondrej/php does not ship yet.
5+
#
6+
# The extensions match what the turbo-compile legs use from the PPA
7+
# images: tokenizer for the parser tests, pcntl + posix for the fork
8+
# tests, opcache (always built in since 8.5) for the trusted-types test,
9+
# and curl, mbstring, openssl, xml and zlib for Composer.
10+
set -eu
11+
12+
cd /tmp
13+
curl -fsSLo php.tar.xz "$PHP_URL"
14+
echo "$PHP_SHA256 php.tar.xz" | sha256sum -c -
15+
mkdir php-src
16+
tar -xJf php.tar.xz -C php-src --strip-components=1
17+
rm php.tar.xz
18+
19+
cd php-src
20+
./configure \
21+
--prefix=/usr/local \
22+
--disable-cgi \
23+
--disable-phpdbg \
24+
--without-sqlite3 \
25+
--without-pdo-sqlite \
26+
--enable-mbstring \
27+
--enable-pcntl \
28+
--with-curl \
29+
--with-openssl \
30+
--with-zlib
31+
make -j"$(nproc)"
32+
make install
33+
34+
# The distro CLI packages the other images use ship a production php.ini
35+
# with no memory limit; match it.
36+
INI_DIR="$(php -r 'echo PHP_CONFIG_FILE_PATH;')"
37+
mkdir -p "$INI_DIR"
38+
sed 's/^memory_limit = .*/memory_limit = -1/' php.ini-production > "$INI_DIR/php.ini"
39+
40+
cd /tmp
41+
rm -rf php-src
42+
43+
php -r 'if (PHP_VERSION !== getenv("PHP_VERSION")) { fwrite(STDERR, "built PHP " . PHP_VERSION . ", expected " . getenv("PHP_VERSION") . "\n"); exit(1); }'
44+
php -m

‎.github/workflows/phar.yml‎

Lines changed: 38 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ env:
3535
COMPOSER_VERSION: "2.9.2"
3636
COMPOSER_PHAR_SHA256: "471f2d857abf0ec18af7b055e61472214d91adb24f9bdbbb864c1c64faad7dd6"
3737
# setup-php installs an 8.6 nightly, which has no matching Windows devel pack.
38-
PHP86_WINDOWS_VERSION: "8.6.0beta3"
38+
PHP86_WINDOWS_VERSION: "8.6.0RC2"
3939

4040
jobs:
4141
compiler-tests:
@@ -397,9 +397,9 @@ jobs:
397397
# of ORIGIN_RUN_ID repeated in both). The tests of every binary, reused
398398
# or compiled, run in the turbo-differential jobs, so the commit job,
399399
# which needs the binaries, does not wait for them.
400-
runs-on: ${{ fromJSON(needs.turbo-origins.outputs.origins || '{}')[format('{0}-{1}-php{2}', matrix.target.artifact, matrix.target.name, matrix.php-version)] && 'ubuntu-latest' || (matrix.php-version == '8.6' && matrix.target.family == 'gnu' && (matrix.target.name == 'linux-gnu-arm64' && 'ubuntu-22.04-arm' || 'ubuntu-22.04') || matrix.target.runs-on) }}
400+
runs-on: ${{ fromJSON(needs.turbo-origins.outputs.origins || '{}')[format('{0}-{1}-php{2}', matrix.target.artifact, matrix.target.name, matrix.php-version)] && 'ubuntu-latest' || matrix.target.runs-on }}
401401
# Container legs pin the built binaries' userland floor independently of
402-
# the runner image. The 8.3–8.5 gnu legs run in a prebuilt ubuntu:22.04-based
402+
# the runner image. The gnu legs run in a prebuilt ubuntu:22.04-based
403403
# image (.github/turbo-build/Dockerfile, published to GHCR by
404404
# turbo-build-image.yml) with the PHP toolchain baked in: the glibc
405405
# symbol floor stays at 2.34 (RHEL 9, Ubuntu 22.04+, Debian 12+) and the
@@ -418,10 +418,9 @@ jobs:
418418
# not worth two binaries per PHP minor. Their binaries are deleted from
419419
# phpstan/phpstan by the commit job (TURBO_RETIRED_BINARIES). Windows
420420
# keeps its ZTS leg: XAMPP, WampServer and Scoop default to TS PHP.
421-
# PHP 8.6 has no ondrej/php packages or prebuilt GNU image yet. Use
422-
# setup-php on Jammy runners, preserving the shipped binary's glibc floor.
423-
# Alpine's php86 packages are currently only in edge/testing.
424-
container: ${{ !(fromJSON(needs.turbo-origins.outputs.origins || '{}')[format('{0}-{1}-php{2}', matrix.target.artifact, matrix.target.name, matrix.php-version)]) && (matrix.target.family == 'gnu' && matrix.php-version != '8.6' && format('ghcr.io/phpstan/turbo-build:gnu-php{0}', matrix.php-version) || matrix.target.family == 'musl' && matrix.php-version == '8.6' && 'alpine:edge' || matrix.target.container) || '' }}
421+
# The gnu-php8.6 image builds the official 8.6 prerelease tarball (see the
422+
# Dockerfile). Alpine's php86 packages are currently only in edge/testing.
423+
container: ${{ !(fromJSON(needs.turbo-origins.outputs.origins || '{}')[format('{0}-{1}-php{2}', matrix.target.artifact, matrix.target.name, matrix.php-version)]) && (matrix.target.family == 'gnu' && format('ghcr.io/phpstan/turbo-build:gnu-php{0}', matrix.php-version) || matrix.target.family == 'musl' && matrix.php-version == '8.6' && 'alpine:edge' || matrix.target.container) || '' }}
425424
needs: turbo-origins
426425
timeout-minutes: 30
427426

@@ -485,7 +484,7 @@ jobs:
485484
# The Alpine leg installs PHP and tooling before checkout:
486485
# actions/checkout needs git inside the container, and the build needs
487486
# php/php-config symlinks pointing at the matrix PHP version. The GNU
488-
# container legs have the toolchain baked in; 8.6 uses setup-php below.
487+
# container legs have the toolchain baked in.
489488
- name: "Install PHP and build tools (Alpine container)"
490489
if: env.ORIGIN_RUN_ID == '' && matrix.target.family == 'musl'
491490
run: |
@@ -526,13 +525,6 @@ jobs:
526525
coverage: "none"
527526
php-version: "${{ matrix.php-version }}"
528527

529-
- name: "Install PHP (GNU runners)"
530-
if: env.ORIGIN_RUN_ID == '' && matrix.target.family == 'gnu' && matrix.php-version == '8.6'
531-
uses: "shivammathur/setup-php@f3e473d116dcccaddc5834248c87452386958240" # v2.37.2
532-
with:
533-
coverage: "none"
534-
php-version: "${{ matrix.php-version }}"
535-
536528
# The training run of `make pgo` (bin/pgo-train.sh) runs bin/phpstan on
537529
# the checkout, so the dependencies must be in place before the build.
538530
- uses: "ramsey/composer-install@65e4f84970763564f46a70b8a54b90d033b3bdda" # v4.0.0
@@ -544,15 +536,11 @@ jobs:
544536
if: env.ORIGIN_RUN_ID == '' && matrix.target.family != 'macos'
545537
# checksum-pinned composer, run under the matrix PHP so platform
546538
# requirements are validated against the interpreter the build
547-
# trains on. COMPOSER_HOME is isolated: on the runner (PHP 8.6) legs,
548-
# setup-php seeds ~/.composer/auth.json with the workflow's GitHub
549-
# token, which this pinned composer rejects at startup ("github oauth
550-
# token contains invalid characters") — everything here comes from
551-
# packagist dists, no auth needed.
539+
# trains on
552540
run: |
553541
curl -fsSLo composer.phar "https://getcomposer.org/download/$COMPOSER_VERSION/composer.phar"
554542
echo "$COMPOSER_PHAR_SHA256 composer.phar" | sha256sum -c -
555-
COMPOSER_HOME="$(mktemp -d)" php composer.phar install --no-interaction --no-progress
543+
php composer.phar install --no-interaction --no-progress
556544
rm composer.phar
557545
558546
- name: "Compile phpstan_turbo with strict warnings (profile-guided)"
@@ -1142,11 +1130,15 @@ jobs:
11421130
# reused, under the runtime setup-php installs on the platform the
11431131
# binary is built for. Kept out of the compile jobs so the commit job,
11441132
# which only needs the binaries, does not wait for them (see there).
1145-
# The musl binaries are tested in turbo-differential-musl.
1133+
# The musl binaries are tested in turbo-differential-musl. The linux-gnu
1134+
# 8.6 legs run in the image the binary is compiled in instead: setup-php's
1135+
# Linux 8.6 is a nightly snapshot that can predate the release the binary
1136+
# targets, and a module API mismatch refuses to load it at all.
11461137
needs:
11471138
- turbo-compile
11481139
- turbo-compile-windows
11491140
runs-on: ${{ matrix.runs-on }}
1141+
container: ${{ matrix.container || '' }}
11501142
timeout-minutes: 30
11511143

11521144
defaults:
@@ -1180,9 +1172,16 @@ jobs:
11801172
# see turbo-run for why windows-latest loads the DLL
11811173
- target: "windows-x86_64"
11821174
runs-on: "windows-latest"
1175+
- target: "linux-gnu-x86_64"
1176+
php-version: "8.6"
1177+
container: "ghcr.io/phpstan/turbo-build:gnu-php8.6"
1178+
- target: "linux-gnu-arm64"
1179+
php-version: "8.6"
1180+
container: "ghcr.io/phpstan/turbo-build:gnu-php8.6"
11831181

11841182
steps:
11851183
- name: Harden the runner (Audit all outbound calls)
1184+
if: ${{ !matrix.container }}
11861185
uses: step-security/harden-runner@bf7454d06d71f1098171f2acdf0cd4708d7b5920 # v2.20.0
11871186
with:
11881187
egress-policy: audit
@@ -1193,6 +1192,7 @@ jobs:
11931192
persist-credentials: false
11941193

11951194
- name: "Install PHP"
1195+
if: ${{ !matrix.container }}
11961196
uses: "shivammathur/setup-php@f3e473d116dcccaddc5834248c87452386958240" # v2.37.2
11971197
env:
11981198
phpts: "${{ matrix.ts == 'zts' && 'ts' || 'nts' }}"
@@ -1207,9 +1207,18 @@ jobs:
12071207
run: bash .github/scripts/install-php86-windows.sh
12081208

12091209
- uses: "ramsey/composer-install@65e4f84970763564f46a70b8a54b90d033b3bdda" # v4.0.0
1210+
if: ${{ !matrix.container }}
12101211
with:
12111212
ignore-cache: true
12121213

1214+
- name: "Install Composer dependencies (pinned composer)"
1215+
if: ${{ matrix.container }}
1216+
run: |
1217+
curl -fsSLo composer.phar "https://getcomposer.org/download/$COMPOSER_VERSION/composer.phar"
1218+
echo "$COMPOSER_PHAR_SHA256 composer.phar" | sha256sum -c -
1219+
php composer.phar install --no-interaction --no-progress
1220+
rm composer.phar
1221+
12131222
- name: "Download extension artifact"
12141223
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
12151224
with:
@@ -1407,6 +1416,13 @@ jobs:
14071416
exclude:
14081417
- operating-system: "ubuntu-latest"
14091418
ts: "zts"
1419+
# setup-php's Linux 8.6 is a nightly snapshot that can predate the
1420+
# release the binary is compiled against (on 2026-09-25 it still
1421+
# had the module API 8.6.0RC2 replaced), and a module API mismatch
1422+
# refuses to load the extension at all. turbo-docker-run runs the
1423+
# same checks with this binary in the official 8.6 prerelease image.
1424+
- operating-system: "ubuntu-latest"
1425+
php-version: "8.6"
14101426
# macOS runs the shipped ad-hoc-signed arm64 binary; there is no
14111427
# macOS zts build, and 8.3/8.4 coverage comes from the other legs.
14121428
include:

‎.github/workflows/turbo-build-image.yml‎

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
name: "Build Turbo compile images"
44

55
# Builds .github/turbo-build/Dockerfile natively on x86_64 and arm64
6-
# runners and publishes ghcr.io/phpstan/turbo-build:gnu-php{8.3,8.4,8.5}
6+
# runners and publishes ghcr.io/phpstan/turbo-build:gnu-php{8.3,8.4,8.5,8.6}
77
# as multi-arch manifests. The turbo-compile gnu legs in phar.yml run in
88
# these images, so their only network dependency is a GHCR pull — no apt,
99
# no ports.ubuntu.com, no PPA at compile time.
@@ -45,7 +45,7 @@ jobs:
4545
strategy:
4646
fail-fast: false
4747
matrix:
48-
php-version: ["8.3", "8.4", "8.5"]
48+
php-version: ["8.3", "8.4", "8.5", "8.6"]
4949
platform:
5050
- arch: "amd64"
5151
runs-on: "ubuntu-latest"
@@ -97,7 +97,7 @@ jobs:
9797

9898
strategy:
9999
matrix:
100-
php-version: ["8.3", "8.4", "8.5"]
100+
php-version: ["8.3", "8.4", "8.5", "8.6"]
101101

102102
env:
103103
TAG: "ghcr.io/phpstan/turbo-build:gnu-php${{ matrix.php-version }}"

0 commit comments

Comments
 (0)