From d98e5b9b7fdf4ed885444532f9e15c99e46d7172 Mon Sep 17 00:00:00 2001 From: James Titcumb Date: Tue, 25 Nov 2025 17:32:54 +0000 Subject: [PATCH 01/12] Added barebones structure of building with Static PHP --- spc/.gitignore | 8 ++++++++ spc/build.sh | 22 ++++++++++++++++++++++ spc/craft.yml | 5 +++++ spc/spc.Dockerfile | 11 +++++++++++ 4 files changed, 46 insertions(+) create mode 100644 spc/.gitignore create mode 100755 spc/build.sh create mode 100644 spc/craft.yml create mode 100644 spc/spc.Dockerfile diff --git a/spc/.gitignore b/spc/.gitignore new file mode 100644 index 0000000..3dde06b --- /dev/null +++ b/spc/.gitignore @@ -0,0 +1,8 @@ +buildroot +downloads +log +pkgroot +source +pie.elf +pie.phar +spc diff --git a/spc/build.sh b/spc/build.sh new file mode 100755 index 0000000..d2be4ef --- /dev/null +++ b/spc/build.sh @@ -0,0 +1,22 @@ +#!/usr/bin/env bash + +set -xeuo pipefail + +SPC_ROOT=$(dirname "$0") + +# First up, build the regular pie.phar +cd "$SPC_ROOT/.." +php box.phar compile +mv pie.phar "$SPC_ROOT/pie.phar" + +cd $SPC_ROOT + +# Build the static PHP micro.sfx +./spc craft + +# Combine pie.phar with the micro.sfx +./spc micro:combine pie.phar --output=pie.elf + +# Docker build & run the test with it +docker build --file spc.Dockerfile --tag pie-spc-test . +docker run --rm -ti pie-spc-test diff --git a/spc/craft.yml b/spc/craft.yml new file mode 100644 index 0000000..0d4d8a1 --- /dev/null +++ b/spc/craft.yml @@ -0,0 +1,5 @@ +php-version: 8.4 +extensions: "curl,filter,iconv,openssl,phar,zlib" +sapi: micro +download-options: + prefer-pre-built: true diff --git a/spc/spc.Dockerfile b/spc/spc.Dockerfile new file mode 100644 index 0000000..cbde648 --- /dev/null +++ b/spc/spc.Dockerfile @@ -0,0 +1,11 @@ +# docker build --file spc.Dockerfile --tag pie-spc-test . +# docker run --rm -ti pie-spc-test +FROM php:7.4-cli + +# need +RUN apt-get update && \ + apt-get install -y git + +COPY pie.elf /usr/bin/pie + +CMD ["pie", "install", "asgrim/example-pie-extension"] From 2f283866be5718ef07169b9ac5385647f4ac97c4 Mon Sep 17 00:00:00 2001 From: James Titcumb Date: Tue, 25 Nov 2025 17:59:31 +0000 Subject: [PATCH 02/12] Use PHP 8.5 and PHP_BUILD_PROVIDER to identify if we are running under Static PHP --- spc/craft.yml | 2 +- src/Command/CommandHelper.php | 10 +++++++++- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/spc/craft.yml b/spc/craft.yml index 0d4d8a1..10e8293 100644 --- a/spc/craft.yml +++ b/spc/craft.yml @@ -1,4 +1,4 @@ -php-version: 8.4 +php-version: 8.5 extensions: "curl,filter,iconv,openssl,phar,zlib" sapi: micro download-options: diff --git a/src/Command/CommandHelper.php b/src/Command/CommandHelper.php index c43ff07..2f6c54b 100644 --- a/src/Command/CommandHelper.php +++ b/src/Command/CommandHelper.php @@ -37,15 +37,18 @@ use function array_key_exists; use function array_map; use function count; +use function defined; use function is_array; use function is_string; use function reset; use function sprintf; +use function str_contains; use function str_starts_with; use function strtolower; use function substr; use function trim; +use const PHP_BUILD_PROVIDER; use const PHP_VERSION; /** @internal This is not public API for PIE, so should not be depended upon unless you accept the risk of BC breaks */ @@ -197,7 +200,12 @@ public static function determineTargetPlatformFromInputs(InputInterface $input, $targetPlatform = TargetPlatform::fromPhpBinaryPath($phpBinaryPath, $makeParallelJobs); - $io->write(sprintf('You are running PHP %s', PHP_VERSION)); + if (defined('PHP_BUILD_PROVIDER') && str_contains(PHP_BUILD_PROVIDER, 'static-php-cli')) { + $io->write(sprintf('You are running a PIE Static PHP %s build', PHP_VERSION)); + } else { + $io->write(sprintf('You are running PHP %s', PHP_VERSION)); + } + $io->write(sprintf( 'Target PHP installation: %s %s%s, on %s %s (from %s)', $phpBinaryPath->version(), From ab2a90b326976109484c4a5905c8779d4140f604 Mon Sep 17 00:00:00 2001 From: James Titcumb Date: Thu, 27 Nov 2025 08:23:13 +0000 Subject: [PATCH 03/12] Add self contained PIE executable CI step --- .github/workflows/build-phar.yml | 73 +++++++++++++++++++++++++++ {spc => resources/spc}/.gitignore | 1 + {spc => resources/spc}/build.sh | 10 +++- {spc => resources/spc}/craft.yml | 0 {spc => resources/spc}/spc.Dockerfile | 0 5 files changed, 82 insertions(+), 2 deletions(-) rename {spc => resources/spc}/.gitignore (88%) rename {spc => resources/spc}/build.sh (58%) rename {spc => resources/spc}/craft.yml (100%) rename {spc => resources/spc}/spc.Dockerfile (100%) diff --git a/.github/workflows/build-phar.yml b/.github/workflows/build-phar.yml index b0b5aad..c1e803e 100644 --- a/.github/workflows/build-phar.yml +++ b/.github/workflows/build-phar.yml @@ -63,3 +63,76 @@ jobs: with: name: pie-${{ github.sha }}.phar path: pie.phar + + build-executable: + needs: + - build-phar + runs-on: ${{ matrix.operating-system }} + strategy: + fail-fast: false + matrix: + operating-system: + - ubuntu-24.04 + - ubuntu-24.04-arm + - macos-15-intel + - macos-26 + #- windows-2025 ## @todo bash script isn't going to work here + steps: + - uses: actions/checkout@v6 + - name: Download SPC + run: | + # @todo find a better way to do this :/ + # Source URL: https://static-php.dev/en/guide/manual-build.html#build-locally-using-spc-binary-recommended + case "${{ matrix.operating-system }}" in + ubuntu-24.04) + curl -fsSL -o spc https://dl.static-php.dev/static-php-cli/spc-bin/nightly/spc-linux-x86_64 + ;; + + ubuntu-24.04-arm) + curl -fsSL -o spc https://dl.static-php.dev/static-php-cli/spc-bin/nightly/spc-linux-aarch64 + ;; + + macos-15-intel) + curl -fsSL -o spc https://dl.static-php.dev/static-php-cli/spc-bin/nightly/spc-macos-x86_64 + ;; + + macos-26) + curl -fsSL -o spc https://dl.static-php.dev/static-php-cli/spc-bin/nightly/spc-macos-aarch64 + ;; + + windows-2025) + curl.exe -fsSL -o spc.exe https://dl.static-php.dev/static-php-cli/spc-bin/nightly/spc-windows-x64.exe + ;; + + *) + echo "unsupported operating system: ${{ matrix.operating-system }}" + exit 1 + ;; + esac + chmod +x spc + - name: Grab built pie.phar + uses: actions/download-artifact@v5 + with: + name: pie-${{ github.sha }}.phar + - run: cp resources/spc/craft.yml craft.yml + - run: ls -l + - run: echo "building for ${{ runner.os }}-${{ runner.arch }} on ${{ matrix.operating-system }}" + - run: ./spc craft + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + # @todo call it `pie` or `pie.exe` depending on os + - run: ./spc micro:combine pie.phar --output=pie.bin + - run: ./pie.bin --version + - uses: actions/upload-artifact@v5 + with: + name: pie-${{ github.sha }}-${{ runner.os }}-${{ runner.arch }}.bin + # @todo call it `pie` or `pie.exe` depending on os + path: pie.bin + + - name: Setup PHP + uses: shivammathur/setup-php@v2 + with: + coverage: none + tools: composer + php-version: "7.4" + - run: ./pie.bin show --all diff --git a/spc/.gitignore b/resources/spc/.gitignore similarity index 88% rename from spc/.gitignore rename to resources/spc/.gitignore index 3dde06b..8c9ae3a 100644 --- a/spc/.gitignore +++ b/resources/spc/.gitignore @@ -6,3 +6,4 @@ source pie.elf pie.phar spc +spc.exe diff --git a/spc/build.sh b/resources/spc/build.sh similarity index 58% rename from spc/build.sh rename to resources/spc/build.sh index d2be4ef..ad43f59 100755 --- a/spc/build.sh +++ b/resources/spc/build.sh @@ -1,15 +1,21 @@ #!/usr/bin/env bash +# A little test build script for manually building a self-contained PIE executable +# Note; needs `spc` pre-installed: +# curl -fsSL -o spc https://dl.static-php.dev/static-php-cli/spc-bin/nightly/spc-linux-x86_64 +# chmod +x spc + set -xeuo pipefail SPC_ROOT=$(dirname "$0") +PIE_PROJECT_ROOT="$SPC_ROOT/../.." # First up, build the regular pie.phar -cd "$SPC_ROOT/.." +cd "$PIE_PROJECT_ROOT" php box.phar compile mv pie.phar "$SPC_ROOT/pie.phar" -cd $SPC_ROOT +cd "$SPC_ROOT" # Build the static PHP micro.sfx ./spc craft diff --git a/spc/craft.yml b/resources/spc/craft.yml similarity index 100% rename from spc/craft.yml rename to resources/spc/craft.yml diff --git a/spc/spc.Dockerfile b/resources/spc/spc.Dockerfile similarity index 100% rename from spc/spc.Dockerfile rename to resources/spc/spc.Dockerfile From 1dc43c3a8a6d7a238b1082fbe0e036c06d1254b5 Mon Sep 17 00:00:00 2001 From: James Titcumb Date: Fri, 28 Nov 2025 13:24:12 +0000 Subject: [PATCH 04/12] Add Windows into SPC build matrix --- .github/workflows/build-phar.yml | 31 +++++++++++++++++-------------- 1 file changed, 17 insertions(+), 14 deletions(-) diff --git a/.github/workflows/build-phar.yml b/.github/workflows/build-phar.yml index c1e803e..b603ed9 100644 --- a/.github/workflows/build-phar.yml +++ b/.github/workflows/build-phar.yml @@ -76,10 +76,11 @@ jobs: - ubuntu-24.04-arm - macos-15-intel - macos-26 - #- windows-2025 ## @todo bash script isn't going to work here + - windows-2025 steps: - uses: actions/checkout@v6 - - name: Download SPC + - name: Download SPC (non-Windows) + if: runner.os != 'Windows' run: | # @todo find a better way to do this :/ # Source URL: https://static-php.dev/en/guide/manual-build.html#build-locally-using-spc-binary-recommended @@ -100,34 +101,36 @@ jobs: curl -fsSL -o spc https://dl.static-php.dev/static-php-cli/spc-bin/nightly/spc-macos-aarch64 ;; - windows-2025) - curl.exe -fsSL -o spc.exe https://dl.static-php.dev/static-php-cli/spc-bin/nightly/spc-windows-x64.exe - ;; - *) echo "unsupported operating system: ${{ matrix.operating-system }}" exit 1 ;; esac chmod +x spc + echo "SPC_BINARY=./spc" >> $GITHUB_ENV + echo "PIE_BINARY_OUTPUT=pie" >> $GITHUB_ENV + - name: Download SPC (Windows) + if: runner.os == 'Windows' + run: | + curl.exe -fsSL -o spc.exe https://dl.static-php.dev/static-php-cli/spc-bin/nightly/spc-windows-x64.exe + chmod +x spc.exe + echo "SPC_BINARY=.\spc.exe" >> $env:GITHUB_ENV + echo "PIE_BINARY_OUTPUT=pie.exe" >> $env:GITHUB_ENV - name: Grab built pie.phar uses: actions/download-artifact@v5 with: name: pie-${{ github.sha }}.phar - run: cp resources/spc/craft.yml craft.yml - - run: ls -l - run: echo "building for ${{ runner.os }}-${{ runner.arch }} on ${{ matrix.operating-system }}" - - run: ./spc craft + - run: ${{ env.SPC_BINARY }} craft env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - # @todo call it `pie` or `pie.exe` depending on os - - run: ./spc micro:combine pie.phar --output=pie.bin - - run: ./pie.bin --version + - run: ${{ env.SPC_BINARY }} micro:combine pie.phar --output=${{ env.PIE_BINARY_OUTPUT }} + - run: ./${{ env.PIE_BINARY_OUTPUT }} --version - uses: actions/upload-artifact@v5 with: name: pie-${{ github.sha }}-${{ runner.os }}-${{ runner.arch }}.bin - # @todo call it `pie` or `pie.exe` depending on os - path: pie.bin + path: ${{ env.PIE_BINARY_OUTPUT }} - name: Setup PHP uses: shivammathur/setup-php@v2 @@ -135,4 +138,4 @@ jobs: coverage: none tools: composer php-version: "7.4" - - run: ./pie.bin show --all + - run: ./${{ env.PIE_BINARY_OUTPUT }} show --all From b1b35575fc2af3e848f081842d6e65cff980df63 Mon Sep 17 00:00:00 2001 From: James Titcumb Date: Fri, 28 Nov 2025 16:55:24 +0000 Subject: [PATCH 05/12] Tidying up PIE binary build pipeline a bit --- .github/workflows/build-phar.yml | 46 +++++++++++++++++++++++--------- 1 file changed, 33 insertions(+), 13 deletions(-) diff --git a/.github/workflows/build-phar.yml b/.github/workflows/build-phar.yml index b603ed9..e31c1f3 100644 --- a/.github/workflows/build-phar.yml +++ b/.github/workflows/build-phar.yml @@ -77,8 +77,14 @@ jobs: - macos-15-intel - macos-26 - windows-2025 + permissions: + # id-token:write is required for build provenance attestation. + id-token: write + # attestations:write is required for build provenance attestation. + attestations: write steps: - uses: actions/checkout@v6 + - name: Download SPC (non-Windows) if: runner.os != 'Windows' run: | @@ -108,29 +114,26 @@ jobs: esac chmod +x spc echo "SPC_BINARY=./spc" >> $GITHUB_ENV - echo "PIE_BINARY_OUTPUT=pie" >> $GITHUB_ENV + echo "PIE_BINARY_OUTPUT=pie-${{ runner.os }}-${{ runner.arch }}" >> $GITHUB_ENV - name: Download SPC (Windows) if: runner.os == 'Windows' run: | curl.exe -fsSL -o spc.exe https://dl.static-php.dev/static-php-cli/spc-bin/nightly/spc-windows-x64.exe chmod +x spc.exe echo "SPC_BINARY=.\spc.exe" >> $env:GITHUB_ENV - echo "PIE_BINARY_OUTPUT=pie.exe" >> $env:GITHUB_ENV - - name: Grab built pie.phar + echo "PIE_BINARY_OUTPUT=pie-${{ runner.os }}-${{ runner.arch }}.exe" >> $env:GITHUB_ENV + + - name: Grab the pie.phar from artifacts uses: actions/download-artifact@v5 with: name: pie-${{ github.sha }}.phar - - run: cp resources/spc/craft.yml craft.yml - - run: echo "building for ${{ runner.os }}-${{ runner.arch }} on ${{ matrix.operating-system }}" - - run: ${{ env.SPC_BINARY }} craft + + - name: Build for ${{ runner.os }} ${{ runner.arch }} on ${{ matrix.operating-system }} + run: ${{ env.SPC_BINARY }} craft resources/spc/craft.yml env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - - run: ${{ env.SPC_BINARY }} micro:combine pie.phar --output=${{ env.PIE_BINARY_OUTPUT }} - - run: ./${{ env.PIE_BINARY_OUTPUT }} --version - - uses: actions/upload-artifact@v5 - with: - name: pie-${{ github.sha }}-${{ runner.os }}-${{ runner.arch }}.bin - path: ${{ env.PIE_BINARY_OUTPUT }} + - name: Bundle pie.phar into executable PIE binary + run: ${{ env.SPC_BINARY }} micro:combine pie.phar --output=${{ env.PIE_BINARY_OUTPUT }} - name: Setup PHP uses: shivammathur/setup-php@v2 @@ -138,4 +141,21 @@ jobs: coverage: none tools: composer php-version: "7.4" - - run: ./${{ env.PIE_BINARY_OUTPUT }} show --all + - name: Quick validation that the binary runs + run: ./${{ env.PIE_BINARY_OUTPUT }} show --all + + - name: Generate build provenance attestation + # It does not make sense to do this for PR builds, nor do contributors + # have permission to do. We can't write attestations to `php/pie` in an + # unprivileged context, otherwise anyone could send a PR with malicious + # code, which would store attestation that `php/pie` built the PHAR, and + # it would look genuine. So this should NOT run for PR builds. + if: github.event_name != 'pull_request' + uses: actions/attest-build-provenance@v3 + with: + subject-path: '${{ github.workspace }}/${{ env.PIE_BINARY_OUTPUT }}' + + - uses: actions/upload-artifact@v5 + with: + name: pie-${{ github.sha }}-${{ runner.os }}-${{ runner.arch }}.bin + path: ${{ env.PIE_BINARY_OUTPUT }} From 17c33e85cb9a61975a608901ce5665fdccb229fa Mon Sep 17 00:00:00 2001 From: James Titcumb Date: Fri, 28 Nov 2025 17:05:50 +0000 Subject: [PATCH 06/12] Add all the binaries to the PIE release too --- .github/workflows/release.yml | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 625fd05..ab1dd87 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -52,19 +52,29 @@ jobs: uses: actions/download-artifact@v6 with: name: pie-${{ github.sha }}.phar - - name: Verify the PHAR + - name: Fetch the executable PIEs from artifacts + uses: actions/download-artifact@v5 + with: + path: executable-pie-binaries + pattern: pie-${{ github.sha }}-*.bin + merge-multiple: true + - name: Verify the PHAR and binaries env: GH_TOKEN: ${{ github.token }} - run: gh attestation verify pie.phar --repo ${{ github.repository }} + run: | + gh attestation verify pie.phar --repo ${{ github.repository }} ; + find executable-pie-binaries -type f -exec gh attestation verify {} --repo ${{ github.repository }} \; # Once the PHAR has been attached to the release, it is ready for review # before publishing it. Note that if immutable releases are enabled, # the tag, pre-release/latest release flag, and all assets become # immutable, so checking this over is a manual exercise. # More info: https://docs.github.com/en/code-security/supply-chain-security/understanding-your-software-supply-chain/immutable-releases - - name: Attach an asset to the draft release + - name: Attach the assets to the draft release env: GH_TOKEN: ${{ github.token }} - run: gh release upload "${{ github.ref_name }}" "pie.phar" --clobber + run: | + gh release upload "${{ github.ref_name }}" "pie.phar" --clobber ; + find executable-pie-binaries -type f -exec gh release upload "${{ github.ref_name }}" {} --clobber \; build-and-push-docker-image: if: ${{ startsWith(github.ref, 'refs/tags/') }} From 51929b0ed290a39f1bbdfbe29a793ce6d1aae8e2 Mon Sep 17 00:00:00 2001 From: James Titcumb Date: Mon, 1 Dec 2025 14:28:37 +0000 Subject: [PATCH 07/12] Rename various jobs and steps for the addition of static binaries --- .../workflows/build-and-push-docker-image.yml | 2 +- .../{build-phar.yml => build-assets.yml} | 10 ++++---- .github/workflows/continuous-integration.yml | 6 ++--- .../workflows/docker-nightly-image-push.yml | 8 +++---- .github/workflows/docs.yml | 8 +++---- .github/workflows/release.yml | 23 ++++++++++--------- 6 files changed, 29 insertions(+), 28 deletions(-) rename .github/workflows/{build-phar.yml => build-assets.yml} (96%) diff --git a/.github/workflows/build-and-push-docker-image.yml b/.github/workflows/build-and-push-docker-image.yml index 6bbd28b..10b125a 100644 --- a/.github/workflows/build-and-push-docker-image.yml +++ b/.github/workflows/build-and-push-docker-image.yml @@ -2,7 +2,7 @@ # in a way to pass those permissions on, e.g.: # # build-and-push-docker-image: -# needs: build-phar +# needs: build-assets # permissions: # contents: read # id-token: write diff --git a/.github/workflows/build-phar.yml b/.github/workflows/build-assets.yml similarity index 96% rename from .github/workflows/build-phar.yml rename to .github/workflows/build-assets.yml index e31c1f3..f0ef767 100644 --- a/.github/workflows/build-phar.yml +++ b/.github/workflows/build-assets.yml @@ -1,14 +1,14 @@ # Invoking this pipeline requires additional permissions, so must be invoked # in a way to pass those permissions on, e.g.: # -# build-phar: +# build-assets: # permissions: # contents: read # id-token: write # attestations: write -# uses: ./.github/workflows/build-phar.yml +# uses: ./.github/workflows/build-assets.yml -name: "Build the PIE PHAR" +name: "Build the PIE assets" on: workflow_call: @@ -148,8 +148,8 @@ jobs: # It does not make sense to do this for PR builds, nor do contributors # have permission to do. We can't write attestations to `php/pie` in an # unprivileged context, otherwise anyone could send a PR with malicious - # code, which would store attestation that `php/pie` built the PHAR, and - # it would look genuine. So this should NOT run for PR builds. + # code, which would store attestation that `php/pie` built the binaries, + # and it would look genuine. So this should NOT run for PR builds. if: github.event_name != 'pull_request' uses: actions/attest-build-provenance@v3 with: diff --git a/.github/workflows/continuous-integration.yml b/.github/workflows/continuous-integration.yml index 8bdacbb..cffed08 100644 --- a/.github/workflows/continuous-integration.yml +++ b/.github/workflows/continuous-integration.yml @@ -187,14 +187,14 @@ jobs: - name: Run phpstan run: vendor/bin/phpstan - build-phar: + build-assets: needs: - unit-tests - coding-standards - static-analysis - # See build-phar.yml for a list of the permissions and why they are needed + # See build-assets.yml for a list of the permissions and why they are needed permissions: contents: read id-token: write attestations: write - uses: ./.github/workflows/build-phar.yml + uses: ./.github/workflows/build-assets.yml diff --git a/.github/workflows/docker-nightly-image-push.yml b/.github/workflows/docker-nightly-image-push.yml index 43d5219..064a96b 100644 --- a/.github/workflows/docker-nightly-image-push.yml +++ b/.github/workflows/docker-nightly-image-push.yml @@ -11,18 +11,18 @@ permissions: contents: read jobs: - build-phar: + build-assets: if: github.ref_name == github.event.repository.default_branch - # See build-phar.yml for a list of the permissions and why they are needed + # See build-assets.yml for a list of the permissions and why they are needed permissions: contents: read id-token: write attestations: write - uses: ./.github/workflows/build-phar.yml + uses: ./.github/workflows/build-assets.yml build-and-push-docker-image: if: github.ref_name == github.event.repository.default_branch - needs: build-phar + needs: build-assets # See build-and-push-docker-image.yml for a list of the permissions and why they are needed permissions: contents: read diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml index 6710df8..95c16cb 100644 --- a/.github/workflows/docs.yml +++ b/.github/workflows/docs.yml @@ -17,20 +17,20 @@ concurrency: cancel-in-progress: false jobs: - build-phar: + build-assets: if: github.ref_name == github.event.repository.default_branch - # See build-phar.yml for a list of the permissions and why they are needed + # See build-assets.yml for a list of the permissions and why they are needed permissions: contents: read id-token: write attestations: write - uses: ./.github/workflows/build-phar.yml + uses: ./.github/workflows/build-assets.yml build-docs-package: if: github.ref_name == github.event.repository.default_branch runs-on: ubuntu-latest needs: - - build-phar + - build-assets steps: - name: Checkout uses: actions/checkout@v6 diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index ab1dd87..ee5de12 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -1,4 +1,4 @@ -name: "Publish a draft release with PHAR attached" +name: "Publish a draft release with assets attached" on: push: @@ -9,18 +9,18 @@ permissions: contents: read jobs: - build-phar: - # See build-phar.yml for a list of the permissions and why they are needed + build-assets: + # See build-assets.yml for a list of the permissions and why they are needed permissions: contents: read id-token: write attestations: write - uses: ./.github/workflows/build-phar.yml + uses: ./.github/workflows/build-assets.yml create-draft-release: runs-on: ubuntu-latest needs: - - build-phar + - build-assets permissions: # contents:write is required to create the draft release contents: write @@ -39,7 +39,7 @@ jobs: GH_TOKEN: ${{ github.token }} run: gh release create "${{ github.ref_name }}" --title "${{ github.ref_name }}" --draft --notes-from-tag - release-phar: + attach-release-assets: runs-on: ubuntu-latest needs: - create-draft-release @@ -64,10 +64,10 @@ jobs: run: | gh attestation verify pie.phar --repo ${{ github.repository }} ; find executable-pie-binaries -type f -exec gh attestation verify {} --repo ${{ github.repository }} \; - # Once the PHAR has been attached to the release, it is ready for review - # before publishing it. Note that if immutable releases are enabled, - # the tag, pre-release/latest release flag, and all assets become - # immutable, so checking this over is a manual exercise. + # Once the PHAR and binaries have been attached to the release, it is + # ready for review before publishing it. Note that if immutable releases + # are enabled, the tag, pre-release/latest release flag, and all assets + # become immutable, so checking this over is a manual exercise. # More info: https://docs.github.com/en/code-security/supply-chain-security/understanding-your-software-supply-chain/immutable-releases - name: Attach the assets to the draft release env: @@ -78,7 +78,8 @@ jobs: build-and-push-docker-image: if: ${{ startsWith(github.ref, 'refs/tags/') }} - needs: build-phar + needs: + - build-assets # See build-and-push-docker-image.yml for a list of the permissions and why they are needed permissions: contents: read From 43ba15d749102b5861e63e139cd01e4b881e3f31 Mon Sep 17 00:00:00 2001 From: James Titcumb Date: Mon, 1 Dec 2025 15:23:52 +0000 Subject: [PATCH 08/12] Extract static PHP check --- src/Command/CommandHelper.php | 5 +---- src/Platform.php | 7 +++++++ 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/src/Command/CommandHelper.php b/src/Command/CommandHelper.php index 2f6c54b..f8ac776 100644 --- a/src/Command/CommandHelper.php +++ b/src/Command/CommandHelper.php @@ -37,18 +37,15 @@ use function array_key_exists; use function array_map; use function count; -use function defined; use function is_array; use function is_string; use function reset; use function sprintf; -use function str_contains; use function str_starts_with; use function strtolower; use function substr; use function trim; -use const PHP_BUILD_PROVIDER; use const PHP_VERSION; /** @internal This is not public API for PIE, so should not be depended upon unless you accept the risk of BC breaks */ @@ -200,7 +197,7 @@ public static function determineTargetPlatformFromInputs(InputInterface $input, $targetPlatform = TargetPlatform::fromPhpBinaryPath($phpBinaryPath, $makeParallelJobs); - if (defined('PHP_BUILD_PROVIDER') && str_contains(PHP_BUILD_PROVIDER, 'static-php-cli')) { + if (PiePlatform::isRunningStaticPhp()) { $io->write(sprintf('You are running a PIE Static PHP %s build', PHP_VERSION)); } else { $io->write(sprintf('You are running PHP %s', PHP_VERSION)); diff --git a/src/Platform.php b/src/Platform.php index 90d50ca..4abeb70 100644 --- a/src/Platform.php +++ b/src/Platform.php @@ -15,10 +15,12 @@ use function implode; use function md5; use function rtrim; +use function str_contains; use function strpos; use function strtr; use const DIRECTORY_SEPARATOR; +use const PHP_BUILD_PROVIDER; use const STDIN; /** @internal This is not public API for PIE, so should not be depended upon unless you accept the risk of BC breaks */ @@ -125,4 +127,9 @@ public static function getPieJsonFilename(TargetPlatform $targetPlatform): strin { return self::getPieWorkingDirectory($targetPlatform) . '/pie.json'; } + + public static function isRunningStaticPhp(): bool + { + return defined('PHP_BUILD_PROVIDER') && str_contains(PHP_BUILD_PROVIDER, 'static-php-cli'); + } } From a284b63d158e97db9fb5c45ea375892b3b5aa01f Mon Sep 17 00:00:00 2001 From: James Titcumb Date: Mon, 1 Dec 2025 15:30:39 +0000 Subject: [PATCH 09/12] Disable self-update for staic PHP build --- src/Command/SelfUpdateCommand.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Command/SelfUpdateCommand.php b/src/Command/SelfUpdateCommand.php index ed3a767..8e37163 100644 --- a/src/Command/SelfUpdateCommand.php +++ b/src/Command/SelfUpdateCommand.php @@ -82,7 +82,7 @@ public function configure(): void public function execute(InputInterface $input, OutputInterface $output): int { - if (! PieVersion::isPharBuild()) { + if (! PieVersion::isPharBuild() || Platform::isRunningStaticPhp()) { $this->io->writeError('Aborting! You are not running a PHAR, cannot self-update.'); return Command::FAILURE; From 866fdc4debf97b288514d0cb455f8df46f2309f0 Mon Sep 17 00:00:00 2001 From: James Titcumb Date: Wed, 17 Dec 2025 17:08:37 +0000 Subject: [PATCH 10/12] Added to usage docs about executable PIE version --- docs/usage.md | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/docs/usage.md b/docs/usage.md index b775a11..da62dde 100644 --- a/docs/usage.md +++ b/docs/usage.md @@ -70,6 +70,24 @@ RUN pie install asgrim/example-pie-extension If the extension you would like to install needs additional libraries or other dependencies, then these must be installed beforehand too. +### Executable PIE (Experimental) + +As of 1.4.0 an **experimental** executable (binary) version of PIE is included. +The PIE is built using [Static PHP](https://static-php.dev/), which builds a +self-contained PHP executable with the extensions that PIE needs to run, and +bundles the PHAR as a single distributable executable. Please keep in mind that +this is **experimental** and we do not recommend this for production use for +the time being. Please also note there are some limitations: + + - [php/pie#459](https://github.com/php/pie/discussions/459) - the OSX version + is not signed with an Apple Developer account, which means (at your own risk) + you would need to tell your system to trust the downloaded executable. + - [php/pie#460](https://github.com/php/pie/discussions/460) - all the binary + versions have the `pie self-update` feature disabled for now. + +If you find the binary releases useful, please leave feedback or upvote on the +relevant discussions, so we can gauge interest in improving this functionality. + ## Prerequisites for PIE Running PIE requires PHP 8.1 or newer. However, you may still use PIE to install From f7f8c570bed31763dbca353ef7b280bee20fb7a2 Mon Sep 17 00:00:00 2001 From: James Titcumb Date: Mon, 22 Dec 2025 14:18:46 +0000 Subject: [PATCH 11/12] Added nightly executables --- .github/workflows/docs.yml | 14 ++++++++++++-- docs/usage.md | 19 +++++++++++++++++++ 2 files changed, 31 insertions(+), 2 deletions(-) diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml index 95c16cb..f5ab386 100644 --- a/.github/workflows/docs.yml +++ b/.github/workflows/docs.yml @@ -40,12 +40,22 @@ jobs: uses: actions/download-artifact@v6 with: name: pie-${{ github.sha }}.phar - - name: Verify the PHAR + - name: Fetch the executable PIEs from artifacts + uses: actions/download-artifact@v5 + with: + path: executable-pie-binaries + pattern: pie-${{ github.sha }}-*.bin + merge-multiple: true + - name: Verify the PHAR and binaries env: GH_TOKEN: ${{ github.token }} - run: gh attestation verify pie.phar --repo ${{ github.repository }} + run: | + gh attestation verify pie.phar --repo ${{ github.repository }} ; + find executable-pie-binaries -type f -exec gh attestation verify {} --repo ${{ github.repository }} \; - name: Copy PHAR into docs run: cp pie.phar docs-package/pie-nightly.phar + - name: Copy executables into docs + run: cp executable-pie-binaries/* docs-package/ - name: Upload artifact uses: actions/upload-pages-artifact@v4 with: diff --git a/docs/usage.md b/docs/usage.md index da62dde..174c2ff 100644 --- a/docs/usage.md +++ b/docs/usage.md @@ -88,6 +88,25 @@ the time being. Please also note there are some limitations: If you find the binary releases useful, please leave feedback or upvote on the relevant discussions, so we can gauge interest in improving this functionality. +The "nightly" versions of these can be found here: + +| Operating System | Architecture | Download URL | +|------------------|------------------|-----------------------------------------------| +| Linux | ARM 64 / aarch64 | https://php.github.io/pie/pie-Linux-ARM64 | +| Linux | amd64 / x86_64 | https://php.github.io/pie/pie-Linux-X64 | +| OS X | ARM 64 / aarch64 | https://php.github.io/pie/pie-macOS-ARM64 | +| OS X | Intel / x86_64 | https://php.github.io/pie/pie-macOS-X64 | +| Windows | x86_64 | https://php.github.io/pie/pie-Windows-X64.exe | + +We *highly* recommend you verify the file came from the PHP GitHub repository +before running it, for example: + +```shell +$ gh attestation verify --owner php pie-Linux-X64 +$ chmod +x pie-Linux-X64 +$ ./pie-Linux-X64 --version +``` + ## Prerequisites for PIE Running PIE requires PHP 8.1 or newer. However, you may still use PIE to install From d8d008f31fa62df7415ad3882c424647714c01df Mon Sep 17 00:00:00 2001 From: James Titcumb Date: Mon, 22 Dec 2025 14:51:32 +0000 Subject: [PATCH 12/12] Use PHP 8.4 for build --- resources/spc/craft.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/resources/spc/craft.yml b/resources/spc/craft.yml index 10e8293..0d4d8a1 100644 --- a/resources/spc/craft.yml +++ b/resources/spc/craft.yml @@ -1,4 +1,4 @@ -php-version: 8.5 +php-version: 8.4 extensions: "curl,filter,iconv,openssl,phar,zlib" sapi: micro download-options: