Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 23 additions & 10 deletions .github/scripts/download-php-windows-devel.sh
Original file line number Diff line number Diff line change
Expand Up @@ -3,22 +3,35 @@
# (the short SHA of the last commit touching turbo-ext/src, the Makefile's
# computation) and fetches the php-devel-pack matching the installed PHP
# (MATRIX_TS: nts/zts, MATRIX_VS: its toolset infix) into C:\php-devel and the
# php-sdk-binary-tools at PHP_SDK_COMMIT into C:\php-sdk.
# php-sdk-binary-tools at PHP_SDK_COMMIT into C:\php-sdk. For a prerelease
# (PHP_PRERELEASE, the minor's entry find-php-windows-prereleases.sh resolved
# for this run) the pack and its checksum come from that entry.
set -euo pipefail

SHA=$(git log -1 --format=%H -- turbo-ext/src | cut -c1-7)
echo "extension version: $SHA"
echo "PHPSTANTURBO_VERSION=$SHA" >> "$GITHUB_ENV"

FULL=$(php -r 'echo PHP_VERSION;')
# thread-safe devel packs carry no infix, NTS ones carry -nts
INFIX=$([ "$MATRIX_TS" = "zts" ] && echo "" || echo "-nts")
PACK="php-devel-pack-$FULL$INFIX-Win32-$MATRIX_VS-x64.zip"
echo "devel pack: $PACK"
curl -fsSLo devel-pack.zip "https://windows.php.net/downloads/releases/$PACK" \
|| curl -fsSLo devel-pack.zip "https://windows.php.net/downloads/releases/archives/$PACK" \
|| curl -fsSLo devel-pack.zip "https://downloads.php.net/~windows/qa/$PACK" \
|| curl -fsSLo devel-pack.zip "https://downloads.php.net/~windows/qa/archives/$PACK"
if [ -n "${PHP_PRERELEASE:-}" ] && [ "$PHP_PRERELEASE" != "null" ]; then
# shellcheck disable=SC2016 # PHP code, not shell expansions
read -r PACK SHA256 < <(php -r '
$entry = json_decode(getenv("PHP_PRERELEASE"), true, 512, JSON_THROW_ON_ERROR);
$devel = $entry[getenv("MATRIX_TS") === "zts" ? "ts" : "nts"]["devel"];
echo $devel["path"], " ", $devel["sha256"], "\n";
')
echo "devel pack: $PACK"
curl -fsSLo devel-pack.zip "https://downloads.php.net/~windows/qa/$PACK" \
|| curl -fsSLo devel-pack.zip "https://downloads.php.net/~windows/qa/archives/$PACK"
echo "$SHA256 devel-pack.zip" | sha256sum -c -
else
FULL=$(php -r 'echo PHP_VERSION;')
# thread-safe devel packs carry no infix, NTS ones carry -nts
INFIX=$([ "$MATRIX_TS" = "zts" ] && echo "" || echo "-nts")
PACK="php-devel-pack-$FULL$INFIX-Win32-$MATRIX_VS-x64.zip"
echo "devel pack: $PACK"
curl -fsSLo devel-pack.zip "https://windows.php.net/downloads/releases/$PACK" \
|| curl -fsSLo devel-pack.zip "https://windows.php.net/downloads/releases/archives/$PACK"
fi
unzip -q devel-pack.zip -d /c/php-devel

git clone -q https://github.com/php/php-sdk-binary-tools.git /c/php-sdk
Expand Down
40 changes: 40 additions & 0 deletions .github/scripts/find-php-windows-prereleases.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
#!/usr/bin/env bash
# For an unreleased PHP minor, setup-php installs a nightly build of its
# development branch on Windows, which has no devel pack to compile an
# extension against. The Windows legs of phar.yml then replace that runtime
# with the official prerelease (install-php-windows-prerelease.sh) and build
# against its devel pack (download-php-windows-devel.sh).
#
# For each minor in MINORS that windows.php.net has no stable build of, this
# writes the current prerelease from its QA manifest to the `prereleases`
# step output:
# {"<minor>": {"version": "8.6.0RC3",
# "nts": {"zip": {"path", "sha256"}, "devel": {"path", "sha256"}},
# "ts": {...}}}
# A minor with a stable build is left out: setup-php installs that release,
# whose devel pack is published next to it. It runs once per workflow run,
# so every job installs the same prerelease even when a new one comes out
# in the meantime.
#
# Usage: MINORS="8.3 8.4 8.5 8.6" find-php-windows-prereleases.sh
set -euo pipefail

: "${MINORS:?set MINORS to the PHP minors the Windows legs build for}"
fetch() { curl -fsSL --retry 3 --retry-all-errors "https://downloads.php.net/~windows/$1/releases.json"; }
stable=$(fetch releases)
qa=$(fetch qa)

prereleases=$(jq -cn --argjson stable "$stable" --argjson qa "$qa" --arg minors "$MINORS" '
def files($builds; $ts):
$builds | to_entries
| map(select(.key | test("^" + $ts + "-vs[0-9]+-x64$")))
| if length == 1 then .[0].value | {zip: (.zip | {path, sha256}), devel: (.devel_pack | {path, sha256})}
else error("expected one \($ts) x64 build, found \(length)") end;
reduce ($minors | split(" ") | .[] | select(. != "")) as $minor ({};
if $stable | has($minor) then .
elif $qa | has($minor) | not then error("windows.php.net has neither a stable nor a QA build of PHP \($minor)")
else .[$minor] = {version: $qa[$minor].version, nts: files($qa[$minor]; "nts"), ts: files($qa[$minor]; "ts")}
end)')

jq -r 'if length == 0 then "every minor has a stable build" else to_entries[] | "PHP \(.key): prerelease \(.value.version)" end' <<< "$prereleases"
echo "prereleases=$prereleases" >> "${GITHUB_OUTPUT:-/dev/stdout}"
2 changes: 1 addition & 1 deletion .github/scripts/find-turbo-origins.sh
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ BUILD_INPUT_PATHS=(
.github/scripts/install-alpine-php.sh
.github/scripts/download-composer.sh
.github/scripts/composer-tags.pub
.github/scripts/install-php86-windows.sh
.github/scripts/install-php-windows-prerelease.sh
.github/scripts/download-php-windows-devel.sh
turbo-ext/bin/shared-core
)
Expand Down
33 changes: 33 additions & 0 deletions .github/scripts/install-php-windows-prerelease.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
#!/usr/bin/env bash
set -euo pipefail

# setup-php supplies Composer, php.ini and CA certificates, but for an
# unreleased minor it installs a nightly build, which has no matching
# development pack. Replace the runtime and bundled extensions with the
# official prerelease find-php-windows-prereleases.sh resolved for this run
# (PHP_PRERELEASE, its JSON entry for the minor), preserving that
# configuration.
PHP_DIR="$(cygpath -u "$(php -r 'echo dirname(PHP_BINARY);')")"
case "$MATRIX_TS" in
zts) TS=ts ;;
nts) TS=nts ;;
*) echo "Unknown thread-safety mode: $MATRIX_TS" >&2; exit 1 ;;
esac
# shellcheck disable=SC2016 # PHP code, not shell expansions
read -r VERSION PACK SHA256 < <(php -r '
$entry = json_decode(getenv("PHP_PRERELEASE"), true, 512, JSON_THROW_ON_ERROR);
$zip = $entry[$argv[1]]["zip"];
echo $entry["version"], " ", $zip["path"], " ", $zip["sha256"], "\n";
' "$TS")
ARCHIVE="$RUNNER_TEMP/$PACK"
curl -fsSLo "$ARCHIVE" "https://downloads.php.net/~windows/qa/$PACK" \
|| curl -fsSLo "$ARCHIVE" "https://downloads.php.net/~windows/qa/archives/$PACK"
echo "$SHA256 $ARCHIVE" | sha256sum -c -
unzip -qo "$ARCHIVE" -d "$PHP_DIR"
EXPECTED_VERSION="$VERSION" php -r '
if (PHP_VERSION !== getenv("EXPECTED_VERSION") || (bool) PHP_ZTS !== (getenv("MATRIX_TS") === "zts")) {
fwrite(STDERR, "PHP prerelease version or thread-safety mismatch\n");
exit(1);
}
echo "Using PHP ", PHP_VERSION, PHP_ZTS ? " ZTS\n" : " NTS\n";
'
24 changes: 0 additions & 24 deletions .github/scripts/install-php86-windows.sh

This file was deleted.

69 changes: 57 additions & 12 deletions .github/workflows/phar.yml
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,6 @@
# The php-parser version whose grammar tables and semantic actions the
# native parser engine (turbo-ext/src/parser/) was ported against.
SUPPORTED_PHP_PARSER_VERSION: "v5.9.0"
# setup-php installs an 8.6 nightly, which has no matching Windows devel pack.
PHP86_WINDOWS_VERSION: "8.6.0RC2"

jobs:
compiler-tests:
Expand Down Expand Up @@ -335,6 +333,45 @@
make -C "$RUNNER_TEMP/turbo-ext" install INSTALL_ROOT="$RUNNER_TEMP/install-root"
find "$RUNNER_TEMP/install-root" -name 'phpstan_turbo.so' | grep .

php-windows-prereleases:
name: "Find PHP Prereleases for Windows"
# For an unreleased minor, setup-php installs a nightly build on Windows,
# which has no devel pack to compile against; the Windows legs replace it
# with the official prerelease. This resolves the current one for every
# minor in this workflow's matrices that has no stable Windows build yet
# (.github/scripts/find-php-windows-prereleases.sh), once per run, so all
# legs install the same build even when a new release candidate comes out
# in the meantime.
runs-on: "ubuntu-latest"
timeout-minutes: 5

permissions:
contents: read # actions/checkout of this repository

outputs:
prereleases: ${{ steps.find.outputs.prereleases }}

steps:
- name: Harden the runner (Audit all outbound calls)
uses: step-security/harden-runner@bf7454d06d71f1098171f2acdf0cd4708d7b5920 # v2.20.0
with:
egress-policy: audit

- name: "Checkout"
uses: actions/checkout@d23441a48e516b6c34aea4fa41551a30e30af803 # v6.1.0
with:
persist-credentials: false
sparse-checkout: |
.github/scripts
.github/workflows

- name: "Find the prerelease of every PHP minor without a stable Windows build"
id: find
run: |
MINORS="$(yq -r '[.jobs[].strategy.matrix["php-version"] | select(. != null) | .[]] | unique | .[] | select(test("^[0-9]+\\.[0-9]+$"))' .github/workflows/phar.yml | tr '\n' ' ')"
echo "PHP minors in the matrices: $MINORS"
MINORS="$MINORS" bash .github/scripts/find-php-windows-prereleases.sh

turbo-origins:
name: "Find Reusable Turbo Extension Builds"
# Most pushes and pull requests leave the extension's build inputs
Expand Down Expand Up @@ -1469,7 +1506,9 @@
# is the one that ships VS2022.
# PHP 8.6's vs18 development packs need the VS2026 toolchain.
runs-on: ${{ matrix.php-version == '8.6' && 'windows-2025-vs2026' || 'windows-2022' }}
needs: turbo-compile-core-windows
needs:
- php-windows-prereleases
- turbo-compile-core-windows
# see turbo-compile
if: ${{ !cancelled() }}
timeout-minutes: ${{ matrix.variant == 'pie' && 45 || 30 }}
Expand Down Expand Up @@ -1518,18 +1557,20 @@
coverage: "none"
php-version: "${{ matrix.php-version }}"

- name: "Install the matching PHP 8.6 prerelease runtime"
if: matrix.php-version == '8.6'
- name: "Install the PHP prerelease runtime"
if: fromJSON(needs.php-windows-prereleases.outputs.prereleases)[matrix.php-version]
shell: bash
env:
MATRIX_TS: ${{ matrix.ts }}
run: bash .github/scripts/install-php86-windows.sh
PHP_PRERELEASE: ${{ toJSON(fromJSON(needs.php-windows-prereleases.outputs.prereleases)[matrix.php-version]) }}
run: bash .github/scripts/install-php-windows-prerelease.sh

- name: "Compute the extension version and download the build tools"
shell: bash
env:
MATRIX_TS: ${{ matrix.ts }}
MATRIX_VS: ${{ matrix.vs }}
PHP_PRERELEASE: ${{ toJSON(fromJSON(needs.php-windows-prereleases.outputs.prereleases)[matrix.php-version]) }}
run: bash .github/scripts/download-php-windows-devel.sh

# the DLL and its import library, into the extension directory where
Expand Down Expand Up @@ -1751,6 +1792,7 @@
# it at all; the ZTS legs so as not to depend on setup-php's thread-safe
# Linux builds.
needs:
- php-windows-prereleases
- turbo-compile
- turbo-compile-windows
runs-on: ${{ matrix.runs-on }}
Expand Down Expand Up @@ -1856,11 +1898,12 @@
coverage: "none"
php-version: "${{ matrix.php-version }}"

- name: "Install the matching PHP 8.6 prerelease runtime"
if: matrix.target == 'windows-x86_64' && matrix.php-version == '8.6'
- name: "Install the PHP prerelease runtime"
if: matrix.target == 'windows-x86_64' && fromJSON(needs.php-windows-prereleases.outputs.prereleases)[matrix.php-version]
env:
MATRIX_TS: ${{ matrix.ts }}
run: bash .github/scripts/install-php86-windows.sh
PHP_PRERELEASE: ${{ toJSON(fromJSON(needs.php-windows-prereleases.outputs.prereleases)[matrix.php-version]) }}
run: bash .github/scripts/install-php-windows-prerelease.sh

- uses: "ramsey/composer-install@65e4f84970763564f46a70b8a54b90d033b3bdda" # v4.0.0
if: ${{ !matrix.container }}
Expand Down Expand Up @@ -2038,6 +2081,7 @@
turbo-run:
name: "Run with Turbo Extension"
needs:
- php-windows-prereleases
- turbo-compile
- turbo-compile-windows
runs-on: ${{ matrix.operating-system }}
Expand Down Expand Up @@ -2109,11 +2153,12 @@
coverage: "none"
php-version: "${{ matrix.php-version }}"

- name: "Install the matching PHP 8.6 prerelease runtime"
if: matrix.operating-system == 'windows-latest' && matrix.php-version == '8.6'
- name: "Install the PHP prerelease runtime"
if: matrix.operating-system == 'windows-latest' && fromJSON(needs.php-windows-prereleases.outputs.prereleases)[matrix.php-version]
env:
MATRIX_TS: ${{ matrix.ts }}
run: bash .github/scripts/install-php86-windows.sh
PHP_PRERELEASE: ${{ toJSON(fromJSON(needs.php-windows-prereleases.outputs.prereleases)[matrix.php-version]) }}
run: bash .github/scripts/install-php-windows-prerelease.sh

- name: "Download extension artifact"
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
Expand Down
5 changes: 4 additions & 1 deletion turbo-ext/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -537,7 +537,10 @@ Windows legs' tests are their check.
infix and toolset in `include`) and of the jobs testing them
(`turbo-differential`, `turbo-differential-musl`, `turbo-run`,
`turbo-docker-run`), and give the new version a `gnu-php<minor>` image
for the Linux gnu legs. The cores need no change: they keep compiling
for the Linux gnu legs. Until the version has a stable Windows release,
the Windows legs install its current prerelease by themselves (the
`php-windows-prereleases` job reads windows.php.net's manifests), so
there is no version to pin. The cores need no change: they keep compiling
against the version they are pinned to (`php-version` in
`turbo-compile-core`'s targets, `["8.3"]` with the vs16 toolset in
`turbo-compile-core-windows`). Run the smoke test of every version
Expand Down
Loading