Skip to content

Commit e7cd615

Browse files
ondrejmirtesclaude
andcommitted
Restore the macOS turbo extension build with ad-hoc signing
This reinstates the build removed in f87728f, adapted to the jobs added since (Windows build, turbo-artifact aggregation, the keyed turbo-run matrix). Instead of Developer ID signing + notarization, the universal binary is ad-hoc signed: AMFI only requires some signature to map code on arm64, and quarantine — the notarization trigger — is never set by composer/git/curl installs. Ad-hoc needs no secrets, so signing also covers fork PRs and runs before the load check, which now exercises the exact bytes that ship. The macOS staging in the aggregate and commit jobs comes for free from the generic artifact-name-derived loops; they and turbo-run gain a needs on turbo-macos-universal so their phpstan_turbo-* download patterns cannot race the universal job. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01WzC9uwcKEL4psLGotKnD1u
1 parent 6c8b521 commit e7cd615

1 file changed

Lines changed: 93 additions & 5 deletions

File tree

‎.github/workflows/phar.yml‎

Lines changed: 93 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -249,6 +249,18 @@ jobs:
249249
family: "zts"
250250
artifact: "phpstan_turbo"
251251
suffix: "-zts"
252+
# The macOS slices are merged into one universal binary (and ad-hoc
253+
# signed) by the turbo-macos-universal job below, so their artifacts
254+
# carry the turbo-slice prefix that the phpstan_turbo-* download
255+
# patterns in the aggregate and commit jobs do not match.
256+
- name: "macos-x86_64"
257+
runs-on: "macos-15-intel" # the last x86_64 macOS image, available until August 2027
258+
family: "macos"
259+
artifact: "turbo-slice"
260+
- name: "macos-arm64"
261+
runs-on: "macos-latest"
262+
family: "macos"
263+
artifact: "turbo-slice"
252264

253265
steps:
254266
- name: Harden the runner (Audit all outbound calls)
@@ -395,6 +407,67 @@ jobs:
395407
path: "turbo-ext/phpstan_turbo.so"
396408
if-no-files-found: "error"
397409

410+
turbo-macos-universal:
411+
name: "Turbo macOS Universal Binary"
412+
needs: "turbo-compile"
413+
runs-on: "macos-latest"
414+
timeout-minutes: 30
415+
416+
strategy:
417+
fail-fast: false
418+
matrix:
419+
php-version: ["8.4", "8.5"]
420+
421+
steps:
422+
- name: Harden the runner (Audit all outbound calls)
423+
uses: step-security/harden-runner@9af89fc71515a100421586dfdb3dc9c984fbf411 # v2.19.4
424+
with:
425+
egress-policy: audit
426+
427+
- name: "Download x86_64 slice"
428+
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
429+
with:
430+
name: "turbo-slice-macos-x86_64-php${{ matrix.php-version }}"
431+
path: "slice-x86_64"
432+
433+
- name: "Download arm64 slice"
434+
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
435+
with:
436+
name: "turbo-slice-macos-arm64-php${{ matrix.php-version }}"
437+
path: "slice-arm64"
438+
439+
- name: "Merge the slices into a universal binary"
440+
run: |
441+
lipo -create slice-x86_64/phpstan_turbo.so slice-arm64/phpstan_turbo.so -output phpstan_turbo.so
442+
lipo -info phpstan_turbo.so
443+
444+
# On arm64 AMFI refuses to map unsigned code, so the binary must carry
445+
# at least an ad-hoc signature. lipo preserves the linker's per-slice
446+
# ad-hoc signatures, but re-sign deliberately instead of relying on
447+
# that. Quarantine (and thus Gatekeeper/notarization) only applies to
448+
# browser downloads — composer/git/curl installs never see it — so an
449+
# ad-hoc signature is enough and needs no secrets.
450+
- name: "Ad-hoc sign the universal binary"
451+
run: |
452+
codesign --force --sign - phpstan_turbo.so
453+
codesign --verify --verbose=2 phpstan_turbo.so
454+
455+
- name: "Install PHP"
456+
uses: "shivammathur/setup-php@f3e473d116dcccaddc5834248c87452386958240" # v2.37.2
457+
with:
458+
coverage: "none"
459+
php-version: "${{ matrix.php-version }}"
460+
461+
- name: "Verify the universal binary loads"
462+
run: php -d extension="$PWD/phpstan_turbo.so" -m | grep phpstan_turbo
463+
464+
- name: "Upload universal binary artifact"
465+
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
466+
with:
467+
name: "phpstan_turbo-macos-php${{ matrix.php-version }}"
468+
path: "phpstan_turbo.so"
469+
if-no-files-found: "error"
470+
398471
turbo-compile-windows:
399472
name: "Compile Turbo Extension (Windows)"
400473
# windows-latest and windows-2025 serve the VS2026 image, whose 14.5x
@@ -518,6 +591,7 @@ jobs:
518591
needs:
519592
- turbo-compile
520593
- turbo-compile-windows
594+
- turbo-macos-universal
521595
runs-on: "ubuntu-latest"
522596
timeout-minutes: 5
523597

@@ -562,6 +636,7 @@ jobs:
562636
needs:
563637
- turbo-compile
564638
- turbo-compile-windows
639+
- turbo-macos-universal
565640
runs-on: ${{ matrix.operating-system }}
566641
timeout-minutes: 60
567642

@@ -580,6 +655,17 @@ jobs:
580655
php-version: ["8.4", "8.5"]
581656
ts: ["nts", "zts"]
582657
script: ["make tests", "make phpstan"]
658+
# macOS runs the shipped ad-hoc-signed universal binary; there is no
659+
# macOS zts build, and 8.4 coverage comes from the other legs.
660+
include:
661+
- operating-system: "macos-latest"
662+
php-version: "8.5"
663+
ts: "nts"
664+
script: "make tests"
665+
- operating-system: "macos-latest"
666+
php-version: "8.5"
667+
ts: "nts"
668+
script: "make phpstan"
583669

584670
steps:
585671
- name: Harden the runner (Audit all outbound calls)
@@ -603,7 +689,7 @@ jobs:
603689
- name: "Download extension artifact"
604690
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
605691
with:
606-
name: "phpstan_turbo-${{ matrix.operating-system == 'windows-latest' && 'windows-x86_64' || 'linux-gnu-x86_64' }}-php${{ matrix.php-version }}${{ matrix.ts == 'zts' && '-zts' || '' }}"
692+
name: "phpstan_turbo-${{ matrix.operating-system == 'windows-latest' && 'windows-x86_64' || matrix.operating-system == 'macos-latest' && 'macos' || 'linux-gnu-x86_64' }}-php${{ matrix.php-version }}${{ matrix.ts == 'zts' && '-zts' || '' }}"
607693
path: "turbo-ext"
608694

609695
- name: "Install extension"
@@ -641,11 +727,12 @@ jobs:
641727
'
642728
643729
- name: "Run"
644-
# The memo's per-worker footprint grows with files-per-worker; a
645-
# future few-core leg (macOS runners) needs 1G where these many-worker
646-
# runners stay under the default 450M.
730+
# The memo's per-worker footprint grows with files-per-worker; macOS
731+
# runners have few cores, so each of their few workers analyses enough
732+
# files to tip the default 450M limit that a many-worker runner
733+
# stays under.
647734
env:
648-
PHPSTAN_MEMORY_LIMIT: "450M"
735+
PHPSTAN_MEMORY_LIMIT: ${{ matrix.operating-system == 'macos-latest' && '1G' || '450M' }}
649736
# The Windows runner image ships GNU make only inside its MSYS2
650737
# install, which is not on PATH.
651738
run: |
@@ -836,6 +923,7 @@ jobs:
836923
- turbo-version
837924
- turbo-compile
838925
- turbo-compile-windows
926+
- turbo-macos-universal
839927
runs-on: "ubuntu-latest"
840928
timeout-minutes: 60
841929
steps:

0 commit comments

Comments
 (0)