diff --git a/.github/workflows/build-phar.yml b/.github/workflows/build-phar.yml new file mode 100644 index 00000000..91209ad1 --- /dev/null +++ b/.github/workflows/build-phar.yml @@ -0,0 +1,63 @@ +# Invoking this pipeline requires additional permissions, so must be invoked +# in a way to pass those permissions on, e.g.: +# +# build-phar: +# permissions: +# contents: read +# id-token: write +# attestations: write +# uses: ./.github/workflows/build-phar.yml + +name: "Build the PIE PHAR" + +on: + workflow_call: + +permissions: + contents: read + +jobs: + build-phar: + runs-on: ${{ matrix.operating-system }} + strategy: + matrix: + operating-system: + - ubuntu-latest + php-versions: + - '8.1' + permissions: + # id-token:write is required for build provenance attestation. + id-token: write + # attestations:write is required for build provenance attestation. + attestations: write + steps: + - name: Setup PHP + uses: shivammathur/setup-php@v2 + with: + coverage: none + tools: composer, box + php-version: "${{ matrix.php-version }}" + - uses: actions/checkout@v4 + with: + fetch-depth: 0 + # Ensure some kind of previous tag exists, otherwise box fails + - run: git describe --tags HEAD || git tag 0.0.0 + - uses: ramsey/composer-install@v3 + - name: Build PHAR + run: box compile + - name: Check the PHAR executes + run: php pie.phar --version + - 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@v1 + with: + subject-path: '${{ github.workspace }}/pie.phar' + - uses: actions/upload-artifact@v4 + with: + name: pie-${{ github.sha }}.phar + path: pie.phar diff --git a/.github/workflows/continuous-integration.yml b/.github/workflows/continuous-integration.yml index d8e1a5c1..9f251c75 100644 --- a/.github/workflows/continuous-integration.yml +++ b/.github/workflows/continuous-integration.yml @@ -109,4 +109,9 @@ jobs: - unit-tests - coding-standards - static-analysis - uses: ./.github/workflows/release-unsigned-phar.yml + # See build-phar.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 diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml index b095dc62..5bde9d5f 100644 --- a/.github/workflows/docs.yml +++ b/.github/workflows/docs.yml @@ -19,10 +19,14 @@ concurrency: jobs: build-phar: - uses: ./.github/workflows/release-unsigned-phar.yml + # See build-phar.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 - # Build job - build: + build-docs-package: runs-on: ubuntu-latest needs: - build-phar @@ -35,6 +39,10 @@ jobs: uses: actions/download-artifact@v4 with: name: pie-${{ github.sha }}.phar + - name: Verify the PHAR + env: + GH_TOKEN: ${{ github.token }} + run: gh attestation verify pie.phar --repo ${{ github.repository }} - name: Copy PHAR into docs run: cp pie.phar docs-package/pie-nightly.phar - name: Upload artifact @@ -42,13 +50,12 @@ jobs: with: path: docs-package - # Deployment job deploy: environment: name: github-pages url: ${{ steps.deployment.outputs.page_url }} runs-on: ubuntu-latest - needs: build + needs: build-docs-package permissions: contents: read # pages:write is required to deploy to GitHub pages. diff --git a/.github/workflows/release-unsigned-phar.yml b/.github/workflows/release-unsigned-phar.yml deleted file mode 100644 index 959d52b5..00000000 --- a/.github/workflows/release-unsigned-phar.yml +++ /dev/null @@ -1,38 +0,0 @@ -name: "Release unsigned PHAR" - -on: - workflow_call: - -permissions: - contents: read - -jobs: - build-phar: - runs-on: ${{ matrix.operating-system }} - strategy: - matrix: - operating-system: - - ubuntu-latest - php-versions: - - '8.1' - steps: - - name: Setup PHP - uses: shivammathur/setup-php@v2 - with: - coverage: none - tools: composer, box - php-version: "${{ matrix.php-version }}" - - uses: actions/checkout@v4 - with: - fetch-depth: 0 - # Ensure some kind of previous tag exists, otherwise box fails - - run: git describe --tags HEAD || git tag 0.0.0 - - uses: ramsey/composer-install@v3 - - name: Build PHAR - run: box compile - - name: Check the PHAR executes - run: php pie.phar --version - - uses: actions/upload-artifact@v4 - with: - name: pie-${{ github.sha }}.phar - path: pie.phar diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 228e584e..e2df36b3 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -1,4 +1,4 @@ -name: "Release" +name: "Publish the PHAR for Releases" on: release: @@ -9,58 +9,32 @@ permissions: contents: read jobs: + build-phar: + # See build-phar.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 + release-phar: - runs-on: ${{ matrix.operating-system }} - strategy: - matrix: - operating-system: - - ubuntu-latest - php-versions: - - '8.1' + runs-on: ubuntu-latest + needs: + - build-phar permissions: # contents:write is required to upload the binaries to the release. contents: write - # id-token:write is required for build provenance attestation. - id-token: write - # attestations:write is required for build provenance attestation. - attestations: write steps: - - name: Setup PHP - uses: shivammathur/setup-php@v2 - with: - coverage: none - tools: composer, box - php-version: "${{ matrix.php-version }}" - - uses: actions/checkout@v4 - with: - fetch-depth: 0 - - uses: ramsey/composer-install@v3 - - name: Build PHAR - run: box compile - - name: Check the PHAR executes - run: php pie.phar --version - - name: Import GPG key - uses: crazy-max/ghaction-import-gpg@v6 - with: - gpg_private_key: ${{ secrets.GPG_SIGNING_KEY }} - passphrase: ${{ secrets.GPG_SIGNING_KEY_PASSPHRASE }} - - name: Sign the PHAR - run: | - gpg --local-user asgrim+pie-releases@php.net \ - --batch \ - --yes \ - --passphrase="${{ secrets.GPG_SIGNING_KEY_PASSPHRASE }}" \ - --detach-sign \ - --output pie.phar.asc \ - pie.phar - - name: Generate build provenance attestation - uses: actions/attest-build-provenance@v1 + - name: Fetch built PHAR from artifacts + uses: actions/download-artifact@v4 with: - subject-path: '${{ github.workspace }}/pie.phar' + name: pie-${{ github.sha }}.phar + - name: Verify the PHAR + env: + GH_TOKEN: ${{ github.token }} + run: gh attestation verify pie.phar --repo ${{ github.repository }} - name: Upload binaries to release uses: softprops/action-gh-release@v2 if: ${{startsWith(github.ref, 'refs/tags/') }} with: - files: | - pie.phar - pie.phar.asc + files: pie.phar diff --git a/README.md b/README.md index 799553ba..eb3688cd 100644 --- a/README.md +++ b/README.md @@ -13,7 +13,7 @@ please read [extension-maintainers](./docs/extension-maintainers.md). - Download `pie.phar` either: - [latest stable release](https://github.com/php/pie/releases) - [latest unstable nightly](https://php.github.io/pie/pie-nightly.phar) -- Validate the signature in `pie.phar.asc` +- Verify the PHAR's source with `gh attestation verify pie.phar --repo php/pie` - You may then invoke PIE with `php pie.phar ` Further installation details can be found in the [usage](./docs/usage.md) docs. diff --git a/docs/usage.md b/docs/usage.md index 68235944..764a9b12 100644 --- a/docs/usage.md +++ b/docs/usage.md @@ -9,9 +9,7 @@ order: 2 ### Manual installation - Download `pie.phar` from the [latest releases](https://github.com/php/pie/releases) -- Validate the signature in `pie.phar.asc` - - You can fetch the public key with `gpg --recv-key 343F8427AD6B48FF` - - Then you can verify the release with `gpg --verify pie.phar.asc pie.phar` +- Verify the PHAR's source with `gh attestation verify pie.phar --repo php/pie` - You may then invoke PIE with `php pie.phar ` - Optionally, copy `pie.phar` into your `$PATH`, e.g. `cp pie.phar /usr/local/bin/pie` - If you copy PIE into your `$PATH`, you may then invoke PIE with `pie `