Skip to content

Commit 6d3e41a

Browse files
authored
Build static macOS PHP CLI binaries (#3297)
## Related issues - Related to RSM-1650 ## How AI was used in this PR AI helped compare the Buildkite and GitHub Actions approaches, simplify the static-php-cli build, and validate the generated artifacts. I reviewed the changes and tested the resulting binaries locally. ## Proposed Changes - Add a manual `Build PHP CLI Binaries` GitHub Actions workflow. - Build PHP CLI binaries with upstream `static-php-cli` instead of custom Buildkite scripts. - Default to PHP `8.4.20` and static-php-cli `2.8.5`, with workflow inputs to override them. - Build the currently working targets: `macos-aarch64`, `macos-x86_64`, and `windows-x86_64`. - Upload packaged archives plus `.sha256` sidecars as GitHub Actions artifacts. - Leave Apps CDN upload and manifest updates for a follow-up PR. ## Testing Instructions - Confirm the `macos-aarch64`, `macos-x86_64`, and `windows-x86_64` jobs pass. - Download the artifacts and verify the inner archive against its `.sha256` file. - Extract the archive and confirm `php -v` reports PHP `8.4.20`. - Move the archive to `.studio` folder - `~/.studio/php-bin/8.4` for example - `npm run cli:build` - `STUDIO_RUNTIME=native-php node apps/cli/dist/cli/main.mjs site create` - Confirm the WordPress site is running ## Pre-merge Checklist - [ ] Have you checked for TypeScript, React or other console errors?
1 parent b0209d8 commit 6d3e41a

2 files changed

Lines changed: 218 additions & 0 deletions

File tree

Lines changed: 190 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,190 @@
1+
name: Build PHP CLI Binaries
2+
3+
on:
4+
workflow_dispatch:
5+
inputs:
6+
php_version:
7+
description: PHP patch version to build
8+
required: true
9+
default: 8.4.20
10+
spc_ref:
11+
description: static-php-cli ref
12+
required: true
13+
default: 2.8.5
14+
prefer_pre_built:
15+
description: Prefer pre-built static-php-cli libraries
16+
required: true
17+
type: boolean
18+
default: true
19+
debug:
20+
description: Enable static-php-cli debug logs
21+
required: true
22+
type: boolean
23+
default: false
24+
25+
permissions:
26+
contents: read
27+
28+
env:
29+
GITHUB_TOKEN: ${{ github.token }}
30+
31+
jobs:
32+
build:
33+
name: Build ${{ matrix.target }}
34+
runs-on: ${{ matrix.runner }}
35+
timeout-minutes: 240
36+
strategy:
37+
fail-fast: false
38+
matrix:
39+
include:
40+
- target: macos-aarch64
41+
runner: macos-15
42+
artifact_platform: macos
43+
artifact_arch: aarch64
44+
archive_extension: tar.gz
45+
binary_name: php
46+
extensions: &macos_php_extensions apcu,bcmath,calendar,ctype,curl,dba,dom,exif,fileinfo,filter,ftp,gd,gettext,iconv,igbinary,imagick,intl,mbregex,mbstring,mysqli,mysqlnd,opcache,openssl,pcntl,pdo,pdo_mysql,pdo_sqlite,phar,posix,readline,redis,session,shmop,simplexml,sockets,sodium,sqlite3,ssh2,tokenizer,xml,xmlreader,xmlwriter,xsl,yaml,zip,zlib
47+
- target: macos-x86_64
48+
runner: macos-15-intel
49+
artifact_platform: macos
50+
artifact_arch: x86_64
51+
archive_extension: tar.gz
52+
binary_name: php
53+
extensions: *macos_php_extensions
54+
- target: windows-x86_64
55+
runner: windows-latest
56+
artifact_platform: windows
57+
artifact_arch: x86_64
58+
archive_extension: zip
59+
binary_name: php.exe
60+
# static-php-cli 2.8.5 has Windows builders for intl and sodium, but not gettext/libxslt.
61+
extensions: apcu,bcmath,calendar,ctype,curl,dba,dom,exif,fileinfo,filter,ftp,gd,iconv,igbinary,intl,mbregex,mbstring,mysqli,mysqlnd,opcache,openssl,pdo,pdo_mysql,pdo_sqlite,phar,redis,session,shmop,simplexml,sockets,sodium,sqlite3,ssh2,tokenizer,xml,xmlreader,xmlwriter,yaml,zip,zlib
62+
env:
63+
PHP_VERSION: ${{ github.event_name == 'workflow_dispatch' && inputs.php_version || '8.4.20' }}
64+
SPC_REF: ${{ github.event_name == 'workflow_dispatch' && inputs.spc_ref || '2.8.5' }}
65+
PHP_CLI_EXTENSIONS: ${{ matrix.extensions }}
66+
PHP_CLI_ARTIFACT_PLATFORM: ${{ matrix.artifact_platform }}
67+
PHP_CLI_ARTIFACT_ARCH: ${{ matrix.artifact_arch }}
68+
PHP_CLI_ARCHIVE_EXTENSION: ${{ matrix.archive_extension }}
69+
PHP_CLI_BINARY_NAME: ${{ matrix.binary_name }}
70+
PREFER_PRE_BUILT: ${{ github.event_name != 'workflow_dispatch' || inputs.prefer_pre_built }}
71+
SPC_DEBUG: ${{ github.event_name == 'workflow_dispatch' && inputs.debug || false }}
72+
73+
steps:
74+
- name: Checkout Studio
75+
uses: actions/checkout@v6
76+
77+
- name: Checkout static-php-cli
78+
uses: actions/checkout@v6
79+
with:
80+
repository: crazywhalecc/static-php-cli
81+
ref: ${{ env.SPC_REF }}
82+
path: .cache/static-php-cli
83+
84+
- name: Setup PHP
85+
uses: shivammathur/setup-php@v2
86+
with:
87+
coverage: none
88+
tools: composer:v2
89+
php-version: 8.4
90+
ini-values: memory_limit=-1
91+
extensions: curl, openssl, mbstring
92+
env:
93+
phpts: nts
94+
95+
- name: Install static-php-cli dependencies
96+
working-directory: .cache/static-php-cli
97+
run: composer install --no-dev --no-interaction --prefer-dist --classmap-authoritative
98+
99+
- name: Build PHP CLI on macOS
100+
if: runner.os == 'macOS'
101+
working-directory: .cache/static-php-cli
102+
shell: bash
103+
run: |
104+
set -euo pipefail
105+
106+
download_args=(--with-php="$PHP_VERSION" --for-extensions="$PHP_CLI_EXTENSIONS" --ignore-cache-sources=php-src)
107+
build_args=("$PHP_CLI_EXTENSIONS" --build-cli)
108+
109+
if [ "$PREFER_PRE_BUILT" = "true" ]; then
110+
download_args+=(--prefer-pre-built)
111+
fi
112+
113+
if [ "$SPC_DEBUG" = "true" ]; then
114+
download_args+=(--debug)
115+
build_args+=(--debug)
116+
fi
117+
118+
php bin/spc doctor --auto-fix
119+
php bin/spc download "${download_args[@]}"
120+
php bin/spc build "${build_args[@]}"
121+
122+
- name: Build PHP CLI on Windows
123+
if: runner.os == 'Windows'
124+
working-directory: .cache/static-php-cli
125+
shell: pwsh
126+
run: |
127+
$downloadArgs = @(
128+
"--with-php=$env:PHP_VERSION",
129+
"--for-extensions=$env:PHP_CLI_EXTENSIONS",
130+
"--ignore-cache-sources=php-src"
131+
)
132+
$buildArgs = @( $env:PHP_CLI_EXTENSIONS, "--build-cli" )
133+
134+
if ( $env:PREFER_PRE_BUILT -eq "true" ) {
135+
$downloadArgs += "--prefer-pre-built"
136+
}
137+
138+
if ( $env:SPC_DEBUG -eq "true" ) {
139+
$downloadArgs += "--debug"
140+
$buildArgs += "--debug"
141+
}
142+
143+
php bin/spc doctor --auto-fix
144+
php bin/spc download @downloadArgs
145+
php bin/spc build @buildArgs
146+
147+
- name: Package macOS artifact
148+
if: runner.os == 'macOS'
149+
shell: bash
150+
run: |
151+
set -euo pipefail
152+
153+
out_dir="$GITHUB_WORKSPACE/out/php-binaries"
154+
artifact="php-${PHP_VERSION}-cli-${PHP_CLI_ARTIFACT_PLATFORM}-${PHP_CLI_ARTIFACT_ARCH}.${PHP_CLI_ARCHIVE_EXTENSION}"
155+
156+
mkdir -p "$out_dir"
157+
cp "$GITHUB_WORKSPACE/.cache/static-php-cli/buildroot/bin/$PHP_CLI_BINARY_NAME" "$RUNNER_TEMP/php"
158+
chmod +x "$RUNNER_TEMP/php"
159+
xattr -cr "$RUNNER_TEMP/php"
160+
tar -czf "$out_dir/$artifact" -C "$RUNNER_TEMP" php
161+
shasum -a 256 "$out_dir/$artifact" | awk '{print $1}' > "$out_dir/$artifact.sha256"
162+
163+
- name: Package Windows artifact
164+
if: runner.os == 'Windows'
165+
shell: pwsh
166+
run: |
167+
$outDir = Join-Path $env:GITHUB_WORKSPACE 'out/php-binaries'
168+
$artifact = "php-$env:PHP_VERSION-cli-$env:PHP_CLI_ARTIFACT_PLATFORM-$env:PHP_CLI_ARTIFACT_ARCH.$env:PHP_CLI_ARCHIVE_EXTENSION"
169+
$source = Join-Path $env:GITHUB_WORKSPACE ".cache/static-php-cli/buildroot/bin/$env:PHP_CLI_BINARY_NAME"
170+
$dest = Join-Path $env:RUNNER_TEMP $env:PHP_CLI_BINARY_NAME
171+
$archive = Join-Path $outDir $artifact
172+
173+
New-Item -ItemType Directory -Force $outDir | Out-Null
174+
Copy-Item -Force $source $dest
175+
Compress-Archive -Force -Path $dest -DestinationPath $archive
176+
(Get-FileHash $archive -Algorithm SHA256).Hash.ToLower() | Set-Content -NoNewline "$archive.sha256"
177+
178+
- name: Upload PHP CLI artifact
179+
uses: actions/upload-artifact@v4
180+
with:
181+
name: php-${{ env.PHP_VERSION }}-cli-${{ matrix.target }}
182+
path: out/php-binaries/*
183+
184+
- name: Upload static-php-cli logs
185+
if: ${{ failure() }}
186+
uses: actions/upload-artifact@v4
187+
with:
188+
name: spc-logs-${{ matrix.target }}
189+
path: .cache/static-php-cli/log/*.log
190+
if-no-files-found: ignore
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
# Native PHP Binaries
2+
3+
Use the manual `Build PHP CLI Binaries` GitHub Actions workflow to build Studio
4+
PHP CLI artifacts. The workflow checks out `crazywhalecc/static-php-cli`, pins
5+
the requested SPC ref, passes Studio's extension list directly to `spc download`
6+
and `spc build`, then uploads archives with `.sha256` sidecars.
7+
8+
The manual workflow currently builds:
9+
10+
- `php-8.4.20-cli-macos-aarch64.tar.gz`
11+
- `php-8.4.20-cli-macos-x86_64.tar.gz`
12+
- `php-8.4.20-cli-windows-x86_64.zip`
13+
14+
Windows ARM64 Studio builds use the Windows x64 PHP binary under Windows 11
15+
emulation. Native Windows ARM64 PHP binaries are not built.
16+
17+
The `.sha256` sidecars are used to verify downloaded artifacts. When these
18+
artifacts are published to the Apps CDN, copy those checksums into
19+
`tools/common/lib/php-binary-metadata.ts`.
20+
Before publishing macOS artifacts, sign and notarize the `php` binary with the
21+
existing Studio Developer ID setup.
22+
23+
Regular Studio app builds upload to the Apps CDN through `fastlane/Fastfile`:
24+
`upload_file_to_apps_cdn` wraps `upload_build_to_apps_cdn` from
25+
`fastlane-plugin-wpmreleasetoolkit`. That path requires `WPCOM_API_TOKEN`, the
26+
Studio Apps CDN site ID, build metadata, and a file path. CDN upload for PHP
27+
binary artifacts should be added separately after the manual GitHub Actions
28+
builds are proven.

0 commit comments

Comments
 (0)